rig/providers/anthropic/
client.rs1use super::completion::{CompletionModel, ANTHROPIC_VERSION_LATEST};
4use crate::client::{impl_conversion_traits, CompletionClient, ProviderClient};
5
6const ANTHROPIC_API_BASE_URL: &str = "https://api.anthropic.com";
10
11#[derive(Clone, Debug)]
12pub struct ClientBuilder<'a> {
13 api_key: &'a str,
14 base_url: &'a str,
15 anthropic_version: &'a str,
16 anthropic_betas: Option<Vec<&'a str>>,
17}
18
19impl<'a> ClientBuilder<'a> {
32 pub fn new(api_key: &'a str) -> Self {
33 Self {
34 api_key,
35 base_url: ANTHROPIC_API_BASE_URL,
36 anthropic_version: ANTHROPIC_VERSION_LATEST,
37 anthropic_betas: None,
38 }
39 }
40
41 pub fn base_url(mut self, base_url: &'a str) -> Self {
42 self.base_url = base_url;
43 self
44 }
45
46 pub fn anthropic_version(mut self, anthropic_version: &'a str) -> Self {
47 self.anthropic_version = anthropic_version;
48 self
49 }
50
51 pub fn anthropic_beta(mut self, anthropic_beta: &'a str) -> Self {
52 if let Some(mut betas) = self.anthropic_betas {
53 betas.push(anthropic_beta);
54 self.anthropic_betas = Some(betas);
55 } else {
56 self.anthropic_betas = Some(vec![anthropic_beta]);
57 }
58 self
59 }
60
61 pub fn build(self) -> Client {
62 Client::new(
63 self.api_key,
64 self.base_url,
65 self.anthropic_betas,
66 self.anthropic_version,
67 )
68 }
69}
70
71#[derive(Clone, Debug)]
72pub struct Client {
73 base_url: String,
74 http_client: reqwest::Client,
75}
76
77impl Client {
78 pub fn new(api_key: &str, base_url: &str, betas: Option<Vec<&str>>, version: &str) -> Self {
86 Self {
87 base_url: base_url.to_string(),
88 http_client: reqwest::Client::builder()
89 .default_headers({
90 let mut headers = reqwest::header::HeaderMap::new();
91 headers.insert("x-api-key", api_key.parse().expect("API key should parse"));
92 headers.insert(
93 "anthropic-version",
94 version.parse().expect("Anthropic version should parse"),
95 );
96 if let Some(betas) = betas {
97 headers.insert(
98 "anthropic-beta",
99 betas
100 .join(",")
101 .parse()
102 .expect("Anthropic betas should parse"),
103 );
104 }
105 headers
106 })
107 .build()
108 .expect("Anthropic reqwest client should build"),
109 }
110 }
111
112 pub fn post(&self, path: &str) -> reqwest::RequestBuilder {
113 let url = format!("{}/{}", self.base_url, path).replace("//", "/");
114 self.http_client.post(url)
115 }
116}
117
118impl ProviderClient for Client {
119 fn from_env() -> Self {
122 let api_key = std::env::var("ANTHROPIC_API_KEY").expect("ANTHROPIC_API_KEY not set");
123 ClientBuilder::new(&api_key).build()
124 }
125}
126
127impl CompletionClient for Client {
128 type CompletionModel = CompletionModel;
129 fn completion_model(&self, model: &str) -> CompletionModel {
130 CompletionModel::new(self.clone(), model)
131 }
132}
133
134impl_conversion_traits!(
135 AsTranscription,
136 AsEmbeddings,
137 AsImageGeneration,
138 AsAudioGeneration for Client
139);