@@ -27,7 +27,39 @@ def __init__(self, config: OpenAILLMConfig):
2727 self .client = openai .Client (
2828 api_key = config .api_key , base_url = config .api_base , default_headers = config .default_headers
2929 )
30- logger .info ("OpenAI LLM instance initialized" )
30+ self .use_backup_client = config .backup_client
31+ if self .use_backup_client :
32+ self .backup_client = openai .Client (
33+ api_key = config .backup_api_key ,
34+ base_url = config .backup_api_base ,
35+ default_headers = config .backup_headers ,
36+ )
37+ logger .info (
38+ f"OpenAI LLM instance initialized with backup "
39+ f"(model={ config .backup_model_name_or_path } )"
40+ )
41+ else :
42+ self .backup_client = None
43+ logger .info ("OpenAI LLM instance initialized" )
44+
45+ def _parse_response (self , response ) -> str :
46+ """Extract text content from a chat completion response."""
47+ if not response .choices :
48+ logger .warning ("OpenAI response has no choices" )
49+ return ""
50+
51+ tool_calls = getattr (response .choices [0 ].message , "tool_calls" , None )
52+ if isinstance (tool_calls , list ) and len (tool_calls ) > 0 :
53+ return self .tool_call_parser (tool_calls )
54+ response_content = response .choices [0 ].message .content
55+ reasoning_content = getattr (response .choices [0 ].message , "reasoning_content" , None )
56+ if isinstance (reasoning_content , str ) and reasoning_content :
57+ reasoning_content = f"<think>{ reasoning_content } </think>"
58+ if self .config .remove_think_prefix :
59+ return remove_thinking_tags (response_content )
60+ if reasoning_content :
61+ return reasoning_content + (response_content or "" )
62+ return response_content or ""
3163
3264 @timed_with_status (
3365 log_prefix = "OpenAI LLM" ,
@@ -50,29 +82,32 @@ def generate(self, messages: MessageList, **kwargs) -> str:
5082 start_time = time .perf_counter ()
5183 logger .info (f"OpenAI LLM Request body: { request_body } " )
5284
53- response = self .client .chat .completions .create (** request_body )
54-
55- cost_time = time .perf_counter () - start_time
56- logger .info (
57- f"Request body: { request_body } , Response from OpenAI: { response .model_dump_json ()} , Cost time: { cost_time } "
58- )
59-
60- if not response .choices :
61- logger .warning ("OpenAI response has no choices" )
62- return ""
63-
64- tool_calls = getattr (response .choices [0 ].message , "tool_calls" , None )
65- if isinstance (tool_calls , list ) and len (tool_calls ) > 0 :
66- return self .tool_call_parser (tool_calls )
67- response_content = response .choices [0 ].message .content
68- reasoning_content = getattr (response .choices [0 ].message , "reasoning_content" , None )
69- if isinstance (reasoning_content , str ) and reasoning_content :
70- reasoning_content = f"<think>{ reasoning_content } </think>"
71- if self .config .remove_think_prefix :
72- return remove_thinking_tags (response_content )
73- if reasoning_content :
74- return reasoning_content + (response_content or "" )
75- return response_content or ""
85+ try :
86+ response = self .client .chat .completions .create (** request_body )
87+ cost_time = time .perf_counter () - start_time
88+ logger .info (
89+ f"Request body: { request_body } , Response from OpenAI: "
90+ f"{ response .model_dump_json ()} , Cost time: { cost_time } "
91+ )
92+ return self ._parse_response (response )
93+ except Exception as e :
94+ if not self .use_backup_client :
95+ raise
96+ logger .warning (
97+ f"Primary LLM request failed with { type (e ).__name__ } : { e } , "
98+ f"falling back to backup client"
99+ )
100+ backup_body = {
101+ ** request_body ,
102+ "model" : self .config .backup_model_name_or_path or request_body ["model" ],
103+ }
104+ backup_response = self .backup_client .chat .completions .create (** backup_body )
105+ cost_time = time .perf_counter () - start_time
106+ logger .info (
107+ f"Backup LLM request succeeded, Response: "
108+ f"{ backup_response .model_dump_json ()} , Cost time: { cost_time } "
109+ )
110+ return self ._parse_response (backup_response )
76111
77112 @timed_with_status (
78113 log_prefix = "OpenAI LLM Stream" ,
0 commit comments