This commit is contained in:
zhinianboke 2025-12-14 20:17:03 +08:00
parent 05778d8082
commit d1d1075f3d
5 changed files with 80 additions and 25 deletions

View File

@ -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 # 使用有头模式(可视化浏览器)
)
# 在线程池中执行滑块验证

View File

@ -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回复"""

View File

@ -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,

View File

@ -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-turbogpt-4claude-3-sonnet</p>
<p className="text-xs text-slate-400 mt-1">: qwen-plusqwen-turbogpt-3.5-turbogpt-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>

View File

@ -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)}")