kalosm_language_model/claude/
mod.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use std::sync::OnceLock;

use thiserror::Error;

mod chat;
pub use chat::*;

/// A client for making requests to an OpenAI compatible API.
#[derive(Debug, Clone)]
pub struct AnthropicCompatibleClient {
    reqwest_client: reqwest::Client,
    base_url: String,
    api_key: Option<String>,
    resolved_api_key: OnceLock<String>,
    version: String,
}

impl Default for AnthropicCompatibleClient {
    fn default() -> Self {
        Self::new()
    }
}

impl AnthropicCompatibleClient {
    /// Create a new client.
    pub fn new() -> Self {
        Self {
            reqwest_client: reqwest::Client::new(),
            base_url: "https://api.anthropic.com/v1/".to_string(),
            resolved_api_key: OnceLock::new(),
            api_key: None,
            version: "2023-06-01".to_string(),
        }
    }

    /// Sets the API key for the builder. (defaults to the environment variable `ANTHROPIC_API_KEY`)
    ///
    /// The API key can be accessed from the Anthropic dashboard [here](https://console.anthropic.com/settings/keys).
    pub fn with_api_key(mut self, api_key: impl ToString) -> Self {
        self.api_key = Some(api_key.to_string());
        self
    }

    /// Set the base URL of the API. (defaults to `https://api.anthropic.com/v1/`)
    pub fn with_base_url(mut self, base_url: impl ToString) -> Self {
        self.base_url = base_url.to_string();
        self
    }

    /// Set the anthropic [version](https://docs.anthropic.com/en/api/versioning) you are using.
    ///
    /// Defaults to `2023-06-01``
    pub fn with_anthropic_version(mut self, version: impl ToString) -> Self {
        self.version = version.to_string();
        self
    }

    /// Set the reqwest client for the builder.
    pub fn with_reqwest_client(mut self, client: reqwest::Client) -> Self {
        self.reqwest_client = client;
        self
    }

    /// Resolve the anthropic API key from the environment variable `ANTHROPIC_API_KEY` or the provided api key.
    pub fn resolve_api_key(&self) -> Result<String, NoAnthropicAPIKeyError> {
        if let Some(api_key) = self.resolved_api_key.get() {
            return Ok(api_key.clone());
        }

        let anthropic_api_key = match self.api_key.clone() {
            Some(api_key) => api_key,
            None => std::env::var("ANTHROPIC_API_KEY").map_err(|_| NoAnthropicAPIKeyError)?,
        };

        self.resolved_api_key
            .set(anthropic_api_key.clone())
            .unwrap();

        Ok(anthropic_api_key)
    }

    /// Get the base URL for the Anthropic API.
    pub(crate) fn base_url(&self) -> &str {
        self.base_url.trim_end_matches('/')
    }

    /// Get the version of the Anthropic API.
    pub(crate) fn version(&self) -> &str {
        &self.version
    }
}

/// An error that can occur when building a remote Anthropic model without an API key.
#[derive(Debug, Error)]
#[error("No API key was provided in the [AnthropicCompatibleClient] builder or the environment variable `ANTHROPIC_API_KEY` was not set")]
pub struct NoAnthropicAPIKeyError;