feta:优化AI回复
This commit is contained in:
@@ -828,6 +828,31 @@ class AIChat(PluginBase):
|
|||||||
if strip_thinking:
|
if strip_thinking:
|
||||||
cleaned = self._strip_thinking_content(cleaned)
|
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,或在剥离标签后才露出标记
|
# 再跑一轮:部分模型会把“思考/最终”标记写成 Markdown,或在剥离标签后才露出标记
|
||||||
if strip_markdown:
|
if strip_markdown:
|
||||||
cleaned = self._strip_markdown_syntax(cleaned)
|
cleaned = self._strip_markdown_syntax(cleaned)
|
||||||
@@ -855,6 +880,16 @@ class AIChat(PluginBase):
|
|||||||
if strip_thinking and cleaned and self._contains_thinking_markers(cleaned):
|
if strip_thinking and cleaned and self._contains_thinking_markers(cleaned):
|
||||||
return ""
|
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:
|
if cleaned:
|
||||||
return 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 []
|
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)}")
|
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 []
|
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:
|
if tool_calls_data:
|
||||||
# 提示已在流式处理中发送,直接启动异步工具执行
|
# 提示已在流式处理中发送,直接启动异步工具执行
|
||||||
logger.info(f"[图片] 启动异步工具执行,共 {len(tool_calls_data)} 个工具")
|
logger.info(f"[图片] 启动异步工具执行,共 {len(tool_calls_data)} 个工具")
|
||||||
|
|||||||
@@ -43,8 +43,6 @@ Gentle expression
|
|||||||
绘图规则:
|
绘图规则:
|
||||||
仅当用户明确要求绘图,或提出“看看腿/看看白丝/画一张”等明确绘图诉求时,才调用绘图函数绘制对应画面。
|
仅当用户明确要求绘图,或提出“看看腿/看看白丝/画一张”等明确绘图诉求时,才调用绘图函数绘制对应画面。
|
||||||
在绘制以<瑞依>为主角的图像时,务必保持她的基本特征。
|
在绘制以<瑞依>为主角的图像时,务必保持她的基本特征。
|
||||||
也属于明确绘图诉求的常见说法: “生成一张/出一张/来一张/发一张/给我一张……图/图片/照片”、“来张……的图”、“文生图/图生图”。
|
|
||||||
如果用户只说“来张图/发张图”但没有说明要随机图还是要你生成/绘制,先追问一句确认,再决定调用哪个工具。
|
|
||||||
|
|
||||||
重要:工具调用方式
|
重要:工具调用方式
|
||||||
你拥有 Function Calling 能力,可以直接调用工具函数。
|
你拥有 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,直接用文字回应即可。
|
|
||||||
如果用户说“整活/发疯”但没有明确要发病文学,先追问一句确认,不要直接调用工具。
|
|
||||||
|
|||||||
Reference in New Issue
Block a user