11from typing import Optional , List , Dict
2- from openai import OpenAI
2+ from openai import AsyncOpenAI
33from .base import BaseAIProvider
44import os
55import logging
66
77logger = logging .getLogger (__name__ )
88
99class OpenAIBaseProvider (BaseAIProvider ):
10- def __init__ (self , env_prefix : str , default_model : str , default_api_base : str ):
10+ def __init__ (self , env_prefix : str = 'OPENAI' , default_model : str = 'gpt-4o-mini' ,
11+ default_api_base : str = 'https://api.openai.com/v1' ):
1112 """
1213 初始化基础OpenAI格式提供者
13-
14+
1415 Args:
1516 env_prefix: 环境变量前缀,如 'OPENAI', 'GROK', 'DEEPSEEK', 'QWEN'
1617 default_model: 默认模型名称
1718 default_api_base: 默认API基础URL
1819 """
19- self .client = None
20- self .model = None
20+ super ().__init__ ()
2121 self .env_prefix = env_prefix
2222 self .default_model = default_model
23-
24- # 获取环境变量中的 API_BASE,如果为空或只有空格则使用默认值
25- api_base = os .getenv (f'{ env_prefix } _API_BASE' , '' ).strip ()
26- self .api_base = api_base if api_base else default_api_base
27-
28- async def initialize (self , ** kwargs ):
23+ self .default_api_base = default_api_base
24+ self .client = None
25+ self .model = None
26+
27+ async def initialize (self , ** kwargs ) -> None :
2928 """初始化OpenAI客户端"""
30- api_key = os .getenv (f'{ self .env_prefix } _API_KEY' )
31- if not api_key :
32- raise ValueError (f"未设置{ self .env_prefix } _API_KEY环境变量" )
33-
34- self .client = OpenAI (
35- api_key = api_key ,
36- base_url = self .api_base
37- )
38- logger .info (f"初始化OpenAI模型: { kwargs .get ('model' )} " )
39-
40- self .model = kwargs .get ('model' , self .default_model )
41-
42- async def process_message (self ,
43- message : str ,
29+ try :
30+ api_key = os .getenv (f'{ self .env_prefix } _API_KEY' )
31+ if not api_key :
32+ raise ValueError (f"未设置 { self .env_prefix } _API_KEY 环境变量" )
33+
34+ api_base = os .getenv (f'{ self .env_prefix } _API_BASE' , '' ).strip () or self .default_api_base
35+
36+ self .client = AsyncOpenAI (
37+ api_key = api_key ,
38+ base_url = api_base
39+ )
40+
41+ self .model = kwargs .get ('model' , self .default_model )
42+ logger .info (f"初始化OpenAI模型: { self .model } " )
43+
44+ except Exception as e :
45+ error_msg = f"初始化 { self .env_prefix } 客户端时出错: { str (e )} "
46+ logger .error (error_msg , exc_info = True )
47+ raise
48+
49+ async def process_message (self ,
50+ message : str ,
4451 prompt : Optional [str ] = None ,
4552 images : Optional [List [Dict [str , str ]]] = None ,
4653 ** kwargs ) -> str :
4754 """处理消息"""
4855 try :
4956 if not self .client :
5057 await self .initialize (** kwargs )
51-
58+
5259 messages = []
5360 if prompt :
5461 messages .append ({"role" : "system" , "content" : prompt })
55-
62+
5663 # 如果有图片,需要添加到消息中
5764 if images and len (images ) > 0 :
5865 # 创建包含文本和图片的内容数组
5966 content = []
60-
67+
6168 # 添加文本
6269 content .append ({
6370 "type" : "text" ,
6471 "text" : message
6572 })
66-
73+
6774 # 添加每张图片
6875 for img in images :
6976 content .append ({
@@ -73,46 +80,46 @@ async def process_message(self,
7380 }
7481 })
7582 logger .info (f"已添加一张类型为 { img ['mime_type' ]} 的图片,大小约 { len (img ['data' ]) // 1000 } KB" )
76-
83+
7784 messages .append ({"role" : "user" , "content" : content })
7885 else :
7986 # 没有图片,只添加文本
8087 messages .append ({"role" : "user" , "content" : message })
8188
8289 logger .info (f"实际使用的OpenAI模型: { self .model } " )
83-
90+
8491 # 所有模型统一使用流式调用
85- completion = self .client .chat .completions .create (
92+ completion = await self .client .chat .completions .create (
8693 model = self .model ,
8794 messages = messages ,
8895 stream = True
8996 )
90-
97+
9198 # 收集所有内容
9299 collected_content = ""
93100 collected_reasoning = ""
94-
95- for chunk in completion :
101+
102+ async for chunk in completion :
96103 if not chunk .choices :
97104 continue
98-
105+
99106 delta = chunk .choices [0 ].delta
100-
107+
101108 # 处理思考内容(如果存在)
102109 if hasattr (delta , 'reasoning_content' ) and delta .reasoning_content is not None :
103110 collected_reasoning += delta .reasoning_content
104-
111+
105112 # 处理回答内容
106113 if hasattr (delta , 'content' ) and delta .content is not None :
107114 collected_content += delta .content
108-
115+
109116 # 如果没有内容但有思考过程,可能是思考模型只返回了思考过程
110117 if not collected_content and collected_reasoning :
111118 logger .warning ("模型只返回了思考过程,没有最终回答" )
112119 return "模型未能生成有效回答"
113-
120+
114121 return collected_content
115-
122+
116123 except Exception as e :
117- logger .error (f"{ self .env_prefix } API 调用失败: { str (e )} " )
118- return f"AI处理失败: { str (e )} "
124+ logger .error (f"{ self .env_prefix } API 调用失败: { str (e )} " , exc_info = True )
125+ return f"AI处理失败: { str (e )} "
0 commit comments