feta:优化AI回复

This commit is contained in:
2025-12-30 14:56:06 +08:00
parent 58f17e4497
commit 5b130485f0
2 changed files with 78 additions and 11 deletions

View File

@@ -828,6 +828,31 @@ class AIChat(PluginBase):
if strip_thinking:
cleaned = self._strip_thinking_content(cleaned)
# 清理模型偶发输出的“文本工具调用”痕迹(如 tavilywebsearch{query:...} / <ctrl46>
# 这些内容既不是正常回复,也会破坏“工具只能用 Function Calling”的约束
try:
cleaned = re.sub(r"<ctrl\\d+>", "", 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)} 个工具")

View File

@@ -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直接用文字回应即可。
如果用户说“整活/发疯”但没有明确要发病文学,先追问一句确认,不要直接调用工具。