rig_core/providers/together/
client.rs1use crate::{
2 client::{
3 self, BearerAuth, Capabilities, Capable, DebugExt, Nothing, Provider, ProviderBuilder,
4 ProviderClient,
5 },
6 http_client,
7};
8
9const TOGETHER_AI_BASE_URL: &str = "https://api.together.xyz";
13
14#[derive(Debug, Default, Clone, Copy)]
15pub struct TogetherExt;
16#[derive(Debug, Default, Clone, Copy)]
17pub struct TogetherExtBuilder;
18
19type TogetherApiKey = BearerAuth;
20
21pub type Client<H = reqwest::Client> = client::Client<TogetherExt, H>;
22pub type ClientBuilder<H = crate::markers::Missing> =
23 client::ClientBuilder<TogetherExtBuilder, TogetherApiKey, H>;
24
25impl Provider for TogetherExt {
26 type Builder = TogetherExtBuilder;
27
28 const VERIFY_PATH: &'static str = "/models";
29}
30
31impl DebugExt for TogetherExt {}
32
33impl crate::providers::openai::completion::OpenAICompatibleProvider for TogetherExt {
34 const PROVIDER_NAME: &'static str = "together";
35
36 type StreamingUsage = crate::providers::openai::Usage;
37
38 const SUPPORTS_RESPONSE_FORMAT: bool = false;
41
42 type Response = crate::providers::openai::CompletionResponse;
43
44 fn completion_path(&self, _model: &str) -> String {
46 "/v1/chat/completions".to_string()
47 }
48}
49
50impl<H> Capabilities<H> for TogetherExt {
51 type Completion = Capable<super::CompletionModel<H>>;
52 type Embeddings = Capable<super::EmbeddingModel<H>>;
53
54 type Transcription = Nothing;
55 type ModelListing = Nothing;
56 #[cfg(feature = "image")]
57 type ImageGeneration = Nothing;
58 #[cfg(feature = "audio")]
59 type AudioGeneration = Nothing;
60 type Rerank = Nothing;
61}
62
63impl ProviderBuilder for TogetherExtBuilder {
64 type Extension<H>
65 = TogetherExt
66 where
67 H: http_client::HttpClientExt;
68 type ApiKey = TogetherApiKey;
69
70 const BASE_URL: &'static str = TOGETHER_AI_BASE_URL;
71
72 fn build<H>(
73 _builder: &client::ClientBuilder<Self, Self::ApiKey, H>,
74 ) -> http_client::Result<Self::Extension<H>>
75 where
76 H: http_client::HttpClientExt,
77 {
78 Ok(TogetherExt)
79 }
80}
81
82impl ProviderClient for Client {
83 type Input = String;
84 type Error = crate::client::ProviderClientError;
85
86 fn from_env() -> Result<Self, Self::Error> {
88 let api_key = crate::client::required_env_var("TOGETHER_API_KEY")?;
89 Self::new(&api_key).map_err(Into::into)
90 }
91
92 fn from_val(input: Self::Input) -> Result<Self, Self::Error> {
93 Self::new(&input).map_err(Into::into)
94 }
95}
96
97pub mod together_ai_api_types {
98 use serde::Deserialize;
99
100 impl ApiErrorResponse {
101 pub fn message(&self) -> String {
102 format!("Code `{}`: {}", self.code, self.error)
103 }
104 }
105
106 #[derive(Debug, Deserialize)]
107 pub struct ApiErrorResponse {
108 pub error: String,
109 pub code: String,
110 }
111
112 #[derive(Debug, Deserialize)]
113 #[serde(untagged)]
114 pub enum ApiResponse<T> {
115 Ok(T),
116 Error(ApiErrorResponse),
117 }
118}
119#[cfg(test)]
120mod tests {
121 #[test]
122 fn test_client_initialization() {
123 let _client =
124 crate::providers::together::Client::new("dummy-key").expect("Client::new() failed");
125 let _client_from_builder = crate::providers::together::Client::builder()
126 .api_key("dummy-key")
127 .build()
128 .expect("Client::builder() failed");
129 }
130}