Skip to main content

llm_relay/client/
mod.rs

1use std::time::Duration;
2
3use crate::types::common::Provider;
4
5pub mod chat;
6#[cfg(feature = "embeddings")]
7pub mod embeddings;
8pub mod error;
9
10pub use chat::ChatOptions;
11#[cfg(feature = "embeddings")]
12pub use embeddings::{EmbeddingsClient, EmbeddingsConfig};
13pub use error::LlmError;
14
15/// Configuration for the LLM client.
16#[derive(Debug, Clone)]
17pub struct ClientConfig {
18    pub provider: Provider,
19    pub base_url: String,
20    pub api_key: String,
21    pub timeout: Duration,
22    pub model: String,
23    pub max_tokens: u32,
24}
25
26impl ClientConfig {
27    /// Create config for the Anthropic API.
28    pub fn anthropic(api_key: impl Into<String>, model: impl Into<String>) -> Self {
29        Self {
30            provider: Provider::Anthropic,
31            base_url: "https://api.anthropic.com".to_string(),
32            api_key: api_key.into(),
33            timeout: Duration::from_secs(180),
34            model: model.into(),
35            max_tokens: 16384,
36        }
37    }
38
39    /// Create config for an OpenAI-compatible API (OpenRouter, OpenAI, Ollama, etc.).
40    pub fn openai_compatible(
41        base_url: impl Into<String>,
42        api_key: impl Into<String>,
43        model: impl Into<String>,
44    ) -> Self {
45        Self {
46            provider: Provider::OpenAiCompatible,
47            base_url: base_url.into(),
48            api_key: api_key.into(),
49            timeout: Duration::from_secs(60),
50            model: model.into(),
51            max_tokens: 16384,
52        }
53    }
54
55    #[must_use]
56    pub fn timeout(mut self, timeout: Duration) -> Self {
57        self.timeout = timeout;
58        self
59    }
60
61    #[must_use]
62    pub fn max_tokens(mut self, max_tokens: u32) -> Self {
63        self.max_tokens = max_tokens;
64        self
65    }
66
67    #[must_use]
68    pub fn base_url(mut self, base_url: impl Into<String>) -> Self {
69        self.base_url = base_url.into();
70        self
71    }
72}
73
74/// The main LLM client.
75pub struct LlmClient {
76    pub(crate) http: reqwest::Client,
77    pub(crate) config: ClientConfig,
78}
79
80impl LlmClient {
81    pub fn new(config: ClientConfig) -> Result<Self, LlmError> {
82        let http = reqwest::Client::builder()
83            .timeout(config.timeout)
84            .build()
85            .map_err(|e| LlmError::Client(e.to_string()))?;
86        Ok(Self { http, config })
87    }
88
89    /// Get a reference to the client config.
90    pub fn config(&self) -> &ClientConfig {
91        &self.config
92    }
93}