@@ -4,95 +4,122 @@ mod prompt;
44use std:: env;
55
66pub use agent:: { Agent , run_agent} ;
7- use openai_api_rs:: v1:: { api:: OpenAIClient , common:: GPT3_5_TURBO } ;
7+ use openai_api_rs:: v1:: { api:: OpenAIClient , common} ;
88pub use prompt:: { PromptConfig , prompt_with_config} ;
99
1010use serde:: Deserialize ;
1111
12+ // OpenAI
13+ const OPENAI_API_ENDPOINT : & str = "https://api.openai.com/v1" ;
14+ const OPENAI_DEFAULT_MODEL : & str = common:: GPT4 ;
15+
1216// Deepseek
1317const DEEPSEEK_API_ENDPOINT : & str = "https://api.deepseek.com/v1" ;
14- const DEEPSEEK_V3 : & str = "deepseek-chat" ;
18+ const DEEPSEEK_DEFAULT_MODEL : & str = "deepseek-chat" ;
1519
1620// Anthropic
1721const ANTHROPIC_API_ENDPOINT : & str = "https://api.anthropic.com/v1" ;
18- const CLAUDE_3_5_SONNET : & str = "claude-3-5-sonnet-latest" ;
22+ const ANTHROPIC_DEFAULT_MODEL : & str = "claude-3-5-sonnet-latest" ;
1923
2024#[ derive( Debug , Clone , Deserialize ) ]
21- pub enum AiConfig {
22- #[ serde( rename = "openai" ) ]
23- OpenAI ( ModelConfig ) ,
24- #[ serde( rename = "anthropic" ) ]
25- Anthropic ( ModelConfig ) ,
26- #[ serde( rename = "deepseek" ) ]
27- DeepSeek ( ModelConfig ) ,
25+ pub struct AiConfig {
26+ pub openai : Option < ModelConfig > ,
27+ pub anthropic : Option < ModelConfig > ,
28+ pub deepseek : Option < ModelConfig > ,
29+ }
30+
31+ impl Default for AiConfig {
32+ fn default ( ) -> Self {
33+ Self {
34+ openai : env:: var ( "OPENAI_API_KEY" ) . ok ( ) . map ( |key| ModelConfig {
35+ api_key : key,
36+ api_endpoint : Some ( OPENAI_API_ENDPOINT . to_string ( ) ) ,
37+ model : Some ( OPENAI_DEFAULT_MODEL . to_string ( ) ) ,
38+ } ) ,
39+ anthropic : env:: var ( "CLAUDE_API_KEY" ) . ok ( ) . map ( |key| ModelConfig {
40+ api_key : key,
41+ api_endpoint : Some ( ANTHROPIC_API_ENDPOINT . to_string ( ) ) ,
42+ model : Some ( ANTHROPIC_DEFAULT_MODEL . to_string ( ) ) ,
43+ } ) ,
44+ deepseek : env:: var ( "DEEPKSEEK_API_KEY" ) . ok ( ) . map ( |key| ModelConfig {
45+ api_key : key,
46+ api_endpoint : Some ( DEEPSEEK_API_ENDPOINT . to_string ( ) ) ,
47+ model : Some ( DEEPSEEK_DEFAULT_MODEL . to_string ( ) ) ,
48+ } ) ,
49+ }
50+ }
2851}
2952
3053#[ derive( Debug , Clone , Deserialize ) ]
3154pub struct ModelConfig {
3255 pub api_key : String ,
56+ pub api_endpoint : Option < String > ,
3357 pub model : Option < String > ,
3458}
3559
36- impl AiConfig {
37- pub ( crate ) fn take_model ( & mut self ) -> Option < String > {
38- match self {
39- Self :: OpenAI ( ModelConfig { model, .. } ) => model. take ( ) ,
40- Self :: Anthropic ( ModelConfig { model, .. } ) => model. take ( ) ,
41- Self :: DeepSeek ( ModelConfig { model, .. } ) => model. take ( ) ,
60+ impl Default for ModelConfig {
61+ fn default ( ) -> Self {
62+ ModelConfig {
63+ api_key : env:: var ( "OPENAI_API_KEY" )
64+ . expect ( "Expect `OPENAI_API_KEY` environment variable." ) ,
65+ api_endpoint : Some ( OPENAI_API_ENDPOINT . to_string ( ) ) ,
66+ model : Some ( OPENAI_DEFAULT_MODEL . to_string ( ) ) ,
4267 }
4368 }
44-
45- pub ( crate ) fn set_model ( & mut self , m : String ) {
46- match self {
47- Self :: OpenAI ( ModelConfig { model, .. } ) => model. replace ( m) ,
48- Self :: Anthropic ( ModelConfig { model, .. } ) => model. replace ( m) ,
49- Self :: DeepSeek ( ModelConfig { model, .. } ) => model. replace ( m) ,
50- } ;
51- }
5269}
5370
54- #[ allow( unused) ]
55- pub ( crate ) fn openai_client ( config : Option < & AiConfig > ) -> OpenAIClient {
56- match config {
57- None => OpenAIClient :: builder ( )
58- . with_api_key ( env:: var ( "OPENAI_API_KEY" ) . expect ( "OPENAI_API_KEY not set" ) )
59- . build ( )
60- . unwrap ( ) ,
61- Some ( AiConfig :: OpenAI ( model_config) ) => {
62- let api_key = if model_config. api_key . is_empty ( ) {
63- env:: var ( "OPENAI_API_KEY" ) . expect ( "OPENAI_API_KEY not set" )
64- } else {
65- model_config. api_key . clone ( )
66- } ;
67- OpenAIClient :: builder ( )
68- . with_api_key ( api_key)
69- . build ( )
70- . unwrap ( )
71+ impl AiConfig {
72+ pub ( crate ) fn get_model_config (
73+ & self ,
74+ model_name : Option < String > ,
75+ ) -> Result < ModelConfig , String > {
76+ if let Some ( model) = model_name {
77+ match model {
78+ m if m. starts_with ( "gpt" ) => {
79+ if let Some ( openai) = self . openai . as_ref ( ) {
80+ Ok ( openai. clone ( ) )
81+ } else {
82+ Ok ( ModelConfig :: default ( ) )
83+ }
84+ }
85+ m if m. starts_with ( "claude" ) => {
86+ if let Some ( anthropic) = self . openai . as_ref ( ) {
87+ Ok ( anthropic. clone ( ) )
88+ } else {
89+ Ok ( ModelConfig {
90+ api_key : env:: var ( "CLAUDE_API_KEY" )
91+ . expect ( "Expect `CLAUDE_API_KEY` environment variable." ) ,
92+ api_endpoint : Some ( ANTHROPIC_API_ENDPOINT . to_string ( ) ) ,
93+ model : Some ( ANTHROPIC_DEFAULT_MODEL . to_string ( ) ) ,
94+ } )
95+ }
96+ }
97+ m if m. starts_with ( "deepseek" ) => {
98+ if let Some ( deepseek) = self . deepseek . as_ref ( ) {
99+ Ok ( deepseek. clone ( ) )
100+ } else {
101+ Ok ( ModelConfig {
102+ api_key : env:: var ( "DEEPSEEK_API_KEY" )
103+ . expect ( "Expect `DEEPSEEK_API_KEY` environment variable." ) ,
104+ api_endpoint : Some ( DEEPSEEK_API_ENDPOINT . to_string ( ) ) ,
105+ model : Some ( DEEPSEEK_DEFAULT_MODEL . to_string ( ) ) ,
106+ } )
107+ }
108+ }
109+ m => Err ( format ! ( "Unsupported model `{m}`." ) ) ,
110+ }
111+ } else {
112+ // Default is OpenAI model
113+ Ok ( ModelConfig :: default ( ) )
71114 }
72- Some ( AiConfig :: DeepSeek ( ModelConfig { api_key, .. } ) ) => OpenAIClient :: builder ( )
73- . with_endpoint ( DEEPSEEK_API_ENDPOINT )
74- . with_api_key ( api_key)
75- . build ( )
76- . unwrap ( ) ,
77- Some ( AiConfig :: Anthropic ( ModelConfig { api_key, .. } ) ) => OpenAIClient :: builder ( )
78- . with_endpoint ( ANTHROPIC_API_ENDPOINT )
79- . with_api_key ( api_key)
80- . build ( )
81- . unwrap ( ) ,
82115 }
83116}
84117
85- pub ( crate ) fn default_model ( config : Option < & AiConfig > ) -> String {
86- match config {
87- None => GPT3_5_TURBO . to_string ( ) ,
88- Some ( AiConfig :: OpenAI ( ModelConfig { model, .. } ) ) => {
89- model. clone ( ) . unwrap_or ( GPT3_5_TURBO . to_string ( ) )
90- }
91- Some ( AiConfig :: DeepSeek ( ModelConfig { model, .. } ) ) => {
92- model. clone ( ) . unwrap_or ( DEEPSEEK_V3 . to_string ( ) )
93- }
94- Some ( AiConfig :: Anthropic ( ModelConfig { model, .. } ) ) => {
95- model. clone ( ) . unwrap_or ( CLAUDE_3_5_SONNET . to_string ( ) )
96- }
97- }
118+ #[ allow( unused) ]
119+ pub ( crate ) fn openai_client ( config : & ModelConfig ) -> OpenAIClient {
120+ OpenAIClient :: builder ( )
121+ . with_api_key ( & config. api_key )
122+ . with_endpoint ( config. api_endpoint . as_ref ( ) . unwrap ( ) )
123+ . build ( )
124+ . unwrap ( )
98125}
0 commit comments