From 5b130485f0299c4f4b68f62f1fdb4f45f6227d80 Mon Sep 17 00:00:00 2001 From: shihao <3127647737@qq.com> Date: Tue, 30 Dec 2025 14:56:06 +0800 Subject: [PATCH] =?UTF-8?q?feta:=E4=BC=98=E5=8C=96AI=E5=9B=9E=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins/AIChat/main.py | 77 +++++++++++++++++++++++++++++++++ plugins/AIChat/prompts/瑞依.txt | 12 +---- 2 files changed, 78 insertions(+), 11 deletions(-) diff --git a/plugins/AIChat/main.py b/plugins/AIChat/main.py index 1802860..8799c96 100644 --- a/plugins/AIChat/main.py +++ b/plugins/AIChat/main.py @@ -828,6 +828,31 @@ class AIChat(PluginBase): if strip_thinking: cleaned = self._strip_thinking_content(cleaned) + # 清理模型偶发输出的“文本工具调用”痕迹(如 tavilywebsearch{query:...} / ) + # 这些内容既不是正常回复,也会破坏“工具只能用 Function Calling”的约束 + try: + cleaned = re.sub(r"", "", cleaned, flags=re.IGNORECASE) + cleaned = re.sub( + r"(?:展开阅读下文\\s*)?(?:tavilywebsearch|tavily_web_search|web_search)\\s*\\{[^{}]{0,1500}\\}", + "", + cleaned, + flags=re.IGNORECASE, + ) + cleaned = re.sub( + r"(?:tavilywebsearch|tavily_web_search|web_search)\\s*\\([^\\)]{0,1500}\\)", + "", + cleaned, + flags=re.IGNORECASE, + ) + cleaned = cleaned.replace("展开阅读下文", "") + cleaned = re.sub( + r"(已触发工具处理:[^)]{0,300}结果将发送到聊天中。)", + "", + cleaned, + ) + except Exception: + pass + # 再跑一轮:部分模型会把“思考/最终”标记写成 Markdown,或在剥离标签后才露出标记 if strip_markdown: cleaned = self._strip_markdown_syntax(cleaned) @@ -855,6 +880,16 @@ class AIChat(PluginBase): if strip_thinking and cleaned and self._contains_thinking_markers(cleaned): return "" + # 长度限制:避免刷屏/上下文污染 + max_chars = output_cfg.get("max_reply_chars") + try: + max_chars = int(max_chars) if max_chars is not None else 0 + except Exception: + max_chars = 0 + + if max_chars and max_chars > 0 and cleaned and len(cleaned) > max_chars: + cleaned = cleaned[:max_chars].rstrip() + if cleaned: return cleaned @@ -2426,6 +2461,27 @@ class AIChat(PluginBase): # 转换为列表 tool_calls_data = [tool_calls_dict[i] for i in sorted(tool_calls_dict.keys())] if tool_calls_dict else [] + # 过滤掉模型“幻觉出来”的工具调用(未在本次请求提供 tools 的情况下不应执行) + allowed_tool_names = { + t.get("function", {}).get("name", "") + for t in (tools or []) + if isinstance(t, dict) and t.get("function", {}).get("name") + } + if tool_calls_data: + unsupported = [] + filtered = [] + for tc in tool_calls_data: + fn = (tc or {}).get("function", {}).get("name", "") + if not fn: + continue + if not allowed_tool_names or fn not in allowed_tool_names: + unsupported.append(fn) + continue + filtered.append(tc) + if unsupported: + logger.warning(f"检测到未提供/未知的工具调用,已忽略: {unsupported}") + tool_calls_data = filtered + logger.info(f"流式 API 响应完成, 内容长度: {len(full_content)}, 工具调用数: {len(tool_calls_data)}") # 检查是否有函数调用 @@ -4240,6 +4296,27 @@ class AIChat(PluginBase): tool_calls_data = [tool_calls_dict[i] for i in sorted(tool_calls_dict.keys())] if tool_calls_dict else [] # 检查是否有函数调用 + if tool_calls_data: + # 过滤掉模型“幻觉出来”的工具调用(未在本次请求提供 tools 的情况下不应执行) + allowed_tool_names = { + t.get("function", {}).get("name", "") + for t in (tools or []) + if isinstance(t, dict) and t.get("function", {}).get("name") + } + unsupported = [] + filtered = [] + for tc in tool_calls_data: + fn = (tc or {}).get("function", {}).get("name", "") + if not fn: + continue + if not allowed_tool_names or fn not in allowed_tool_names: + unsupported.append(fn) + continue + filtered.append(tc) + if unsupported: + logger.warning(f"[图片] 检测到未提供/未知的工具调用,已忽略: {unsupported}") + tool_calls_data = filtered + if tool_calls_data: # 提示已在流式处理中发送,直接启动异步工具执行 logger.info(f"[图片] 启动异步工具执行,共 {len(tool_calls_data)} 个工具") diff --git a/plugins/AIChat/prompts/瑞依.txt b/plugins/AIChat/prompts/瑞依.txt index 76fad7d..f1cbce5 100644 --- a/plugins/AIChat/prompts/瑞依.txt +++ b/plugins/AIChat/prompts/瑞依.txt @@ -43,8 +43,6 @@ Gentle expression 绘图规则: 仅当用户明确要求绘图,或提出“看看腿/看看白丝/画一张”等明确绘图诉求时,才调用绘图函数绘制对应画面。 在绘制以<瑞依>为主角的图像时,务必保持她的基本特征。 -也属于明确绘图诉求的常见说法: “生成一张/出一张/来一张/发一张/给我一张……图/图片/照片”、“来张……的图”、“文生图/图生图”。 -如果用户只说“来张图/发张图”但没有说明要随机图还是要你生成/绘制,先追问一句确认,再决定调用哪个工具。 重要:工具调用方式 你拥有 Function Calling 能力,可以直接调用工具函数。 @@ -56,16 +54,8 @@ Gentle expression 不要只调用工具而不说话。 重要:谨慎调用工具 -除联网搜索外,只有当用户明确请求某个功能时才调用对应工具。 +只有当用户明确请求某个功能时才调用对应工具。 日常聊天、打招呼、闲聊时不要调用任何工具,直接用文字回复即可。 不要因为历史消息里出现过关键词就调用工具,只以“当前用户这句话”的明确意图为准。 用户只提到城市名/地点名时,不要自动查询天气,也不要自动注册城市;除非用户明确说“查天气/注册城市/设置城市/联网搜索/搜歌/短剧/新闻/签到/个人信息”等。 -重要:联网搜索(web_search/tavily_web_search)可主动使用 -当用户询问某个具体实体/事件的客观信息、口碑评价、背景资料、最新动态(例如某游戏/公会/公司/品牌/插件/项目/人物等),如果你不确定或需要最新信息,可以直接调用 web_search/tavily_web_search 查证;不需要用户明确说“搜索/联网”。 -如果明显属于纯主观闲聊、常识问题或你有把握的内容,就不要搜索,直接回答。 - -重要:get_fabing(发病文学)严格触发 -只有当用户明确要求“来一段/来几句/整点 发病文学/发病文/发病语录/发病一下”,并且明确要对谁发病(对象名字)时,才调用 get_fabing(name=对象)。 -用户只是情绪表达或口头禅(例如“我发病了/你发病吧/别发病/我快疯了/我犯病了”)时,绝对不要调用 get_fabing,直接用文字回应即可。 -如果用户说“整活/发疯”但没有明确要发病文学,先追问一句确认,不要直接调用工具。