From 64bf6d7af034cf711279e82edacdaf36d29491ea Mon Sep 17 00:00:00 2001 From: zk Date: Thu, 9 Jul 2026 15:47:19 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=8E=A2=E9=92=88=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/services/ai_tool.py | 54 +++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/app/services/ai_tool.py b/app/services/ai_tool.py index 9c6a68d..1ce0c97 100644 --- a/app/services/ai_tool.py +++ b/app/services/ai_tool.py @@ -72,38 +72,44 @@ async def ai_chat(llm: BaseChatModel, system_prompt: str, user_message: str, sce if not _gate_probing: # 当前协程成为探针,负责退避重试直到成功 _gate_probing = True - result = await _probe_until_recover(llm, system_prompt, user_message) - # 记录 AI 调用日志 - if scene: - await _save_call_log(scene, system_prompt, user_message, result) - # 探针成功,直接返回结果(不用再调一次) - return result + await _probe_until_recover(llm, system_prompt, user_message) + # 探针恢复后,回到 while 循环顶部用业务数据重新调用 + continue # 已有探针在工作,回到 while 顶部 await _gate_event.wait() 等待唤醒 async def _probe_until_recover(llm: BaseChatModel, system_prompt: str, user_message: str) -> str: - """探针:固定间隔重试直到接口恢复,返回成功的响应内容,并打开门闸唤醒所有等待协程""" + """探针:用轻量 hello 消息探测接口是否恢复,成功后打开门闸,原协程重新走正常流程""" global _gate_probing - delay = 0.5 # 固定间隔 500ms + delay = 0.2 # 探测间隔 200ms attempt = 0 - while True: - await asyncio.sleep(delay) - attempt += 1 - try: - messages = [ - SystemMessage(content=system_prompt), - HumanMessage(content=user_message), - ] - response = await llm.ainvoke(messages) - # 成功 → 打开门闸,唤醒所有等待协程 - _gate_probing = False - _gate_event.set() - log.info("AI 接口恢复,门闸打开,第{}次探测成功", attempt) - return response.content - except Exception as e: - log.warning("AI 接口仍不可用,第{}次探测失败(间隔{}ms): {}", attempt, int(delay * 1000), e) + try: + while True: + await asyncio.sleep(delay) + attempt += 1 + try: + log.info("探针第{}次探测开始...", attempt) + messages = [ + SystemMessage(content="You are a helpful assistant."), + HumanMessage(content="hello"), + ] + await llm.ainvoke(messages) + # 成功 → 打开门闸,唤醒所有等待协程 + _gate_probing = False + _gate_event.set() + log.info("探针第{}次探测成功,AI 接口恢复,门闸打开", attempt) + break + except Exception as e: + log.warning("探针第{}次探测失败: {}", attempt, e) + except (asyncio.CancelledError, Exception) as e: + # 探针意外死亡 → 必须恢复门闸状态,否则所有 worker 永远阻塞 + _gate_probing = False + _gate_event.set() + log.error("探针协程意外退出,强制打开门闸: {}", e) + + return "" async def ai_chat_json(llm: BaseChatModel, system_prompt: str, user_message: str, scene: Optional[str] = None) -> Any: