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#[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 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 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
74pub 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 pub fn config(&self) -> &ClientConfig {
91 &self.config
92 }
93}