提交
This commit is contained in:
parent
05778d8082
commit
d1d1075f3d
@ -1734,7 +1734,7 @@ class XianyuLive:
|
||||
# user_id=f"{self.cookie_id}_{int(time.time() * 1000)}", # 使用唯一ID避免冲突
|
||||
user_id=f"{self.cookie_id}", # 使用唯一ID避免冲突
|
||||
enable_learning=True, # 启用学习功能
|
||||
headless=True # 使用有头模式(可视化浏览器)
|
||||
headless=False # 使用有头模式(可视化浏览器)
|
||||
)
|
||||
|
||||
# 在线程池中执行滑块验证
|
||||
|
||||
@ -221,13 +221,22 @@ class AIReplyEngine:
|
||||
|
||||
def _call_openai_api(self, client: OpenAI, settings: dict, messages: list, max_tokens: int = 100, temperature: float = 0.7) -> str:
|
||||
"""调用OpenAI兼容API"""
|
||||
response = client.chat.completions.create(
|
||||
model=settings['model_name'],
|
||||
messages=messages,
|
||||
max_tokens=max_tokens,
|
||||
temperature=temperature
|
||||
)
|
||||
return response.choices[0].message.content.strip()
|
||||
try:
|
||||
logger.info(f"调用OpenAI API: model={settings['model_name']}, base_url={settings.get('base_url', 'default')}")
|
||||
response = client.chat.completions.create(
|
||||
model=settings['model_name'],
|
||||
messages=messages,
|
||||
max_tokens=max_tokens,
|
||||
temperature=temperature
|
||||
)
|
||||
return response.choices[0].message.content.strip()
|
||||
except Exception as e:
|
||||
logger.error(f"OpenAI API调用失败: {e}")
|
||||
# 如果有详细的错误信息,打印出来
|
||||
if hasattr(e, 'response'):
|
||||
logger.error(f"响应状态码: {getattr(e.response, 'status_code', 'unknown')}")
|
||||
logger.error(f"响应内容: {getattr(e.response, 'text', 'unknown')}")
|
||||
raise
|
||||
|
||||
def is_ai_enabled(self, cookie_id: str) -> bool:
|
||||
"""检查指定账号是否启用AI回复"""
|
||||
|
||||
@ -1795,7 +1795,11 @@ class DBManager:
|
||||
return False
|
||||
|
||||
def get_ai_reply_settings(self, cookie_id: str) -> dict:
|
||||
"""获取AI回复设置"""
|
||||
"""获取AI回复设置
|
||||
|
||||
优先使用账号级别的设置,如果账号没有配置api_key/base_url/model_name,
|
||||
则从系统设置中读取全局AI配置作为默认值
|
||||
"""
|
||||
with self.lock:
|
||||
try:
|
||||
cursor = self.conn.cursor()
|
||||
@ -1807,24 +1811,31 @@ class DBManager:
|
||||
''', (cookie_id,))
|
||||
|
||||
result = cursor.fetchone()
|
||||
|
||||
# 获取系统级别的AI设置作为默认值
|
||||
system_api_key = self.get_system_setting('ai_api_key') or ''
|
||||
system_base_url = self.get_system_setting('ai_api_url') or 'https://dashscope.aliyuncs.com/compatible-mode/v1'
|
||||
system_model = self.get_system_setting('ai_model') or 'qwen-plus'
|
||||
|
||||
if result:
|
||||
# 账号有设置,但如果api_key/base_url/model_name为空,使用系统设置
|
||||
return {
|
||||
'ai_enabled': bool(result[0]),
|
||||
'model_name': result[1],
|
||||
'api_key': result[2],
|
||||
'base_url': result[3],
|
||||
'model_name': result[1] if result[1] else system_model,
|
||||
'api_key': result[2] if result[2] else system_api_key,
|
||||
'base_url': result[3] if result[3] else system_base_url,
|
||||
'max_discount_percent': result[4],
|
||||
'max_discount_amount': result[5],
|
||||
'max_bargain_rounds': result[6],
|
||||
'custom_prompts': result[7]
|
||||
}
|
||||
else:
|
||||
# 返回默认设置
|
||||
# 账号没有设置,使用系统设置作为默认值
|
||||
return {
|
||||
'ai_enabled': False,
|
||||
'model_name': 'qwen-plus',
|
||||
'api_key': '',
|
||||
'base_url': 'https://dashscope.aliyuncs.com/compatible-mode/v1',
|
||||
'model_name': system_model,
|
||||
'api_key': system_api_key,
|
||||
'base_url': system_base_url,
|
||||
'max_discount_percent': 10,
|
||||
'max_discount_amount': 100,
|
||||
'max_bargain_rounds': 3,
|
||||
|
||||
@ -323,9 +323,8 @@ export function Settings() {
|
||||
<label className="input-label">API 地址</label>
|
||||
<input
|
||||
type="text"
|
||||
value={settings?.ai_api_url || ''}
|
||||
value={settings?.ai_api_url || 'https://dashscope.aliyuncs.com/compatible-mode/v1'}
|
||||
onChange={(e) => setSettings(s => s ? { ...s, ai_api_url: e.target.value } : null)}
|
||||
placeholder="https://api.openai.com/v1"
|
||||
className="input-ios"
|
||||
/>
|
||||
<p className="text-xs text-slate-400 mt-1">无需补全 /chat/completions</p>
|
||||
@ -344,12 +343,11 @@ export function Settings() {
|
||||
<label className="input-label">模型</label>
|
||||
<input
|
||||
type="text"
|
||||
value={settings?.ai_model || ''}
|
||||
value={settings?.ai_model || 'qwen-plus'}
|
||||
onChange={(e) => setSettings(s => s ? { ...s, ai_model: e.target.value } : null)}
|
||||
placeholder="gpt-3.5-turbo"
|
||||
className="input-ios"
|
||||
/>
|
||||
<p className="text-xs text-slate-400 mt-1">如: gpt-3.5-turbo、gpt-4、claude-3-sonnet</p>
|
||||
<p className="text-xs text-slate-400 mt-1">如: qwen-plus、qwen-turbo、gpt-3.5-turbo、gpt-4</p>
|
||||
</div>
|
||||
<div className="flex items-end gap-2">
|
||||
<div className="flex-1">
|
||||
@ -372,8 +370,8 @@ export function Settings() {
|
||||
<div className="bg-slate-50 dark:bg-slate-800/50 rounded-lg p-3 text-xs text-slate-500 dark:text-slate-400">
|
||||
<p className="font-medium mb-1">常见 AI 服务配置:</p>
|
||||
<ul className="space-y-0.5 list-disc list-inside">
|
||||
<li>阿里云通义千问: https://dashscope.aliyuncs.com/compatible-mode/v1</li>
|
||||
<li>OpenAI: https://api.openai.com/v1</li>
|
||||
|
||||
<li>国内中转: 使用服务商提供的 API 地址</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@ -2410,6 +2410,33 @@ def clear_default_reply_records(cid: str, current_user: Dict[str, Any] = Depends
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
# ------------------------- 默认回复管理接口(单数形式兼容路由) -------------------------
|
||||
# 兼容前端使用 /default-reply/ 单数形式的请求
|
||||
|
||||
@app.get('/default-reply/{cid}')
|
||||
def get_default_reply_compat(cid: str, current_user: Dict[str, Any] = Depends(get_current_user)):
|
||||
"""获取指定账号的默认回复设置(兼容路由)"""
|
||||
return get_default_reply(cid, current_user)
|
||||
|
||||
|
||||
@app.put('/default-reply/{cid}')
|
||||
def update_default_reply_compat(cid: str, reply_data: DefaultReplyIn, current_user: Dict[str, Any] = Depends(get_current_user)):
|
||||
"""更新指定账号的默认回复设置(兼容路由)"""
|
||||
return update_default_reply(cid, reply_data, current_user)
|
||||
|
||||
|
||||
@app.delete('/default-reply/{cid}')
|
||||
def delete_default_reply_compat(cid: str, current_user: Dict[str, Any] = Depends(get_current_user)):
|
||||
"""删除指定账号的默认回复设置(兼容路由)"""
|
||||
return delete_default_reply(cid, current_user)
|
||||
|
||||
|
||||
@app.post('/default-reply/{cid}/clear-records')
|
||||
def clear_default_reply_records_compat(cid: str, current_user: Dict[str, Any] = Depends(get_current_user)):
|
||||
"""清空指定账号的默认回复记录(兼容路由)"""
|
||||
return clear_default_reply_records(cid, current_user)
|
||||
|
||||
|
||||
# ------------------------- 通知渠道管理接口 -------------------------
|
||||
|
||||
@app.get('/notification-channels')
|
||||
@ -4321,6 +4348,13 @@ def test_ai_reply(cookie_id: str, test_data: dict, _: None = Depends(require_aut
|
||||
if not ai_reply_engine.is_ai_enabled(cookie_id):
|
||||
raise HTTPException(status_code=400, detail='该账号未启用AI回复')
|
||||
|
||||
# 检查AI设置是否完整
|
||||
settings = db_manager.get_ai_reply_settings(cookie_id)
|
||||
if not settings.get('api_key'):
|
||||
raise HTTPException(status_code=400, detail='未配置API Key,请先在AI设置中配置API Key')
|
||||
if not settings.get('base_url'):
|
||||
raise HTTPException(status_code=400, detail='未配置API地址,请先在AI设置中配置API地址')
|
||||
|
||||
# 构造测试数据
|
||||
test_message = test_data.get('message', '你好')
|
||||
test_item_info = {
|
||||
@ -4329,25 +4363,28 @@ def test_ai_reply(cookie_id: str, test_data: dict, _: None = Depends(require_aut
|
||||
'desc': test_data.get('item_desc', '这是一个测试商品')
|
||||
}
|
||||
|
||||
# 生成测试回复
|
||||
# 生成测试回复(跳过等待时间)
|
||||
reply = ai_reply_engine.generate_reply(
|
||||
message=test_message,
|
||||
item_info=test_item_info,
|
||||
chat_id=f"test_{int(time.time())}",
|
||||
cookie_id=cookie_id,
|
||||
user_id="test_user",
|
||||
item_id="test_item"
|
||||
item_id="test_item",
|
||||
skip_wait=True # 测试时跳过10秒等待
|
||||
)
|
||||
|
||||
if reply:
|
||||
return {"message": "测试成功", "reply": reply}
|
||||
else:
|
||||
raise HTTPException(status_code=400, detail="AI回复生成失败")
|
||||
raise HTTPException(status_code=400, detail="AI回复生成失败,请检查API Key是否正确、API地址是否可访问")
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"测试AI回复异常: {e}")
|
||||
import traceback
|
||||
logger.error(f"详细错误: {traceback.format_exc()}")
|
||||
raise HTTPException(status_code=500, detail=f"服务器错误: {str(e)}")
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user