新增功能

This commit is contained in:
Your Name
2026-07-28 09:46:53 +08:00
parent 45b3bc0852
commit 980795b4da
57 changed files with 18421 additions and 1051 deletions
+59 -24
View File
@@ -9,6 +9,7 @@ import requests
import base64
import json
import re
import secrets
from urllib.parse import urlparse
import ai_config
@@ -240,28 +241,34 @@ def _user_turn(chat_text: str) -> dict:
}
def call_ai_text(chat_text: str, history: list = None) -> str:
def call_ai_text(
chat_text: str,
history: list = None,
session_id: str | None = None,
) -> str:
"""
文本模式:将聊天记录文字发给文本 AI,返回回复
若开启 AI_MCP_ENABLED,会连接外部 MCP Server,让模型按需调用工具后再回复。
若 AI_API_BASE 为 Dify chat-messages,走 Dify 协议(不支持 OpenAI tools)。
企业微信客服文本入口
回复由 Grok Build Agent 生成;Agent 按需调度当前项目的受控本地客服
MCP。这里不再调用 Chat 项目网址,也不会把客服回复直接发给 Dify 或
OpenAI 兼容 HTTP 接口。``history`` 参数仅为旧调用方兼容保留;同一
客户的真实历史由受控 MCP 按 session_id 从本地档案读取。
"""
if _is_dify_endpoint():
print(" [AI] 检测到 Dify 接口,使用 chat-messages 协议")
return _humanize(_strip_thinking(_call_dify(_dify_query_from_chat(chat_text, history))))
if not getattr(ai_config, "GROK_CUSTOMER_SERVICE_ENABLED", True):
raise RuntimeError("Grok Agent 客服调度已关闭")
from grok_customer_agent import generate_customer_reply
if getattr(ai_config, "AI_MCP_ENABLED", False):
try:
from mcp_bridge import run_coro
return _humanize(run_coro(_call_ai_text_with_mcp(chat_text, history)))
except Exception as e:
print(f" [MCP] ⚠ 工具增强失败,回退普通回复: {e}")
messages = [{"role": "system", "content": _system_prompt()}]
messages += _history_messages(history)
messages.append(_user_turn(chat_text))
msg = _chat_completion(messages)
return _humanize(_strip_thinking(msg.get("content") or ""))
stable_session_id = (session_id or "").strip()
if not re.fullmatch(r"(?:[0-9a-f]{16}|[0-9a-f]{32})", stable_session_id):
# 临时草稿也必须使用隔离的合法作用域,绝不复用其他客户的档案。
stable_session_id = secrets.token_hex(16)
print(" [AI] 使用本地 Grok Build Agent 调度客服能力")
return _humanize(
generate_customer_reply(
chat_text,
session_id=stable_session_id,
)
)
async def _call_ai_text_with_mcp(chat_text: str, history: list = None) -> str:
@@ -367,13 +374,28 @@ def call_ai_vision(image_bytes: bytes, history: list = None) -> str:
return _humanize(_strip_thinking(content))
def get_ai_reply(chat_text: str = None, image_bytes: bytes = None, history: list = None) -> str:
def get_ai_reply(
chat_text: str = None,
image_bytes: bytes = None,
history: list = None,
session_id: str | None = None,
) -> str:
"""
统一入口:根据 AI_USE_VISION 配置自动选择模式。
history 为该会话的历史上下文(多轮记忆),可为 None。
返回 AI 生成的回复文本。
"""
try:
if (
getattr(ai_config, "GROK_CUSTOMER_SERVICE_ENABLED", True)
and ai_config.AI_USE_VISION
and image_bytes
):
print(
" [AI] [WARN] Grok Agent 客服当前只接收已提取的聊天文字;"
"本轮不会绕过 Agent 调用图片模型"
)
return ""
if ai_config.AI_USE_VISION and image_bytes:
print(" [AI] 使用视觉模式分析聊天截图...")
return call_ai_vision(image_bytes, history=history)
@@ -382,15 +404,28 @@ def get_ai_reply(chat_text: str = None, image_bytes: bytes = None, history: list
print(" [AI] 文本模式 + MCP 工具增强...")
else:
print(" [AI] 使用文本模式分析聊天记录...")
return call_ai_text(chat_text, history=history)
return call_ai_text(
chat_text,
history=history,
session_id=session_id,
)
else:
return ""
except requests.exceptions.Timeout:
print(" [AI] API 请求超时")
print(" [AI] [WARN] API 请求超时")
return ""
except requests.exceptions.RequestException as e:
print(f" [AI] API 请求失败: {e}")
print(f" [AI] [WARN] API 请求失败: {e}")
return ""
except (KeyError, IndexError, json.JSONDecodeError) as e:
print(f" [AI] 解析响应失败: {e}")
print(f" [AI] [WARN] 解析响应失败: {e}")
return ""
except Exception as e:
try:
from grok_customer_agent import GrokCustomerAgentError
except ImportError:
GrokCustomerAgentError = RuntimeError
if isinstance(e, GrokCustomerAgentError):
print(f" [AI] [WARN] Grok Agent 调度失败: {e}")
return ""
raise