fix:降低quote的概率

This commit is contained in:
SengokuCola
2026-04-03 18:33:51 +08:00
parent fc753f7e9f
commit 5cdca2bbd4
4 changed files with 84 additions and 53 deletions

View File

@@ -22,8 +22,7 @@ def get_tool_spec() -> ToolSpec:
detailed_description=(
"参数说明:\n"
"- msg_idstring必填。要回复的目标用户消息编号。\n"
"- quoteboolean可选。当有非常明确的回复目标时,以引用回复的方式发送,默认 true。\n"
"- unknown_wordsarray可选。回复前可能需要查询的黑话或词条列表。"
"- set_quoteboolean可选。以引用回复的方式发送默认 true。"
),
parameters_schema={
"type": "object",
@@ -32,16 +31,11 @@ def get_tool_spec() -> ToolSpec:
"type": "string",
"description": "要回复的目标用户消息编号。",
},
"quote": {
"set_quote": {
"type": "boolean",
"description": "当有非常明确的回复目标时,以引用回复的方式发送。",
"description": "以引用回复的方式发送这条回复,不用每句都引用",
"default": True,
},
"unknown_words": {
"type": "array",
"description": "回复前可能需要查询的黑话或词条列表。",
"items": {"type": "string"},
},
},
"required": ["msg_id"],
},
@@ -59,9 +53,7 @@ async def handle_tool(
latest_thought = context.reasoning if context is not None else invocation.reasoning
target_message_id = str(invocation.arguments.get("msg_id") or "").strip()
quote_reply = bool(invocation.arguments.get("quote", True))
raw_unknown_words = invocation.arguments.get("unknown_words")
unknown_words = raw_unknown_words if isinstance(raw_unknown_words, list) else None
set_quote = bool(invocation.arguments.get("set_quote", True))
if not target_message_id:
return tool_ctx.build_failure_result(
@@ -77,8 +69,8 @@ async def handle_tool(
)
logger.info(
f"{tool_ctx.runtime.log_prefix} 已触发回复工具 "
f"目标消息编号={target_message_id} 引用回复={quote_reply} 最新思考={latest_thought!r}"
f"{tool_ctx.runtime.log_prefix} 已触发回复工具"
f"目标消息编号={target_message_id} 引用回复={set_quote} 最新思考={latest_thought!r}"
)
try:
replyer = replyer_manager.get_replyer(
@@ -108,7 +100,6 @@ async def handle_tool(
stream_id=tool_ctx.runtime.session_id,
reply_message=target_message,
chat_history=tool_ctx.runtime._chat_history,
unknown_words=unknown_words,
log_reply=False,
)
except Exception as exc:
@@ -144,8 +135,8 @@ async def handle_tool(
sent = await send_service.text_to_stream(
text=segment,
stream_id=tool_ctx.runtime.session_id,
set_reply=quote_reply if index == 0 else False,
reply_message=target_message if quote_reply and index == 0 else None,
set_reply=set_quote if index == 0 else False,
reply_message=target_message if set_quote and index == 0 else None,
selected_expressions=reply_result.selected_expression_ids or None,
typing=index > 0,
)
@@ -166,7 +157,7 @@ async def handle_tool(
"可见回复生成成功,但发送失败。",
structured_content={
"msg_id": target_message_id,
"quote": quote_reply,
"set_quote": set_quote,
"reply_segments": reply_segments,
},
)
@@ -180,7 +171,7 @@ async def handle_tool(
"回复已生成并发送。",
structured_content={
"msg_id": target_message_id,
"quote": quote_reply,
"set_quote": set_quote,
"reply_text": combined_reply_text,
"reply_segments": reply_segments,
"target_user_name": target_user_name,

View File

@@ -821,19 +821,6 @@ class MaisakaChatLoopService:
)
total_tokens = self._coerce_int(after_response_kwargs.get("total_tokens"), generation_result.total_tokens)
tool_call_summaries = [
{
"调用编号": getattr(tool_call, "call_id", getattr(tool_call, "id", None)),
"工具名": getattr(tool_call, "func_name", getattr(tool_call, "name", None)),
"参数": getattr(tool_call, "args", getattr(tool_call, "arguments", None)),
}
for tool_call in final_tool_calls
]
logger.info(
f"Maisaka 规划器返回结果: 内容={final_response!r} "
f"工具调用={tool_call_summaries}"
)
raw_message = AssistantMessage(
content=final_response,
timestamp=datetime.now(),

View File

@@ -125,24 +125,33 @@ class MaisakaReasoningEngine:
logger.info(f"{self._runtime.log_prefix} 当前思考与上一轮过于相似,已替换为重新思考提示")
self._last_reasoning_content = reasoning_content
self._runtime._render_context_usage_panel(
selected_history_count=response.selected_history_count,
prompt_tokens=response.prompt_tokens,
)
self._runtime._chat_history.append(response.raw_message)
tool_result_summaries: list[str] = []
if response.tool_calls:
tool_started_at = time.time()
should_pause = await self._handle_tool_calls(
should_pause, tool_result_summaries = await self._handle_tool_calls(
response.tool_calls,
response.content or "",
anchor_message,
)
cycle_detail.time_records["tool_calls"] = time.time() - tool_started_at
self._runtime._render_context_usage_panel(
selected_history_count=response.selected_history_count,
prompt_tokens=response.prompt_tokens,
planner_response=response.content or "",
tool_calls=response.tool_calls,
tool_results=tool_result_summaries,
)
if should_pause:
break
continue
self._runtime._render_context_usage_panel(
selected_history_count=response.selected_history_count,
prompt_tokens=response.prompt_tokens,
planner_response=response.content or "",
)
if response.content:
continue
@@ -701,12 +710,25 @@ class MaisakaReasoningEngine:
)
)
def _build_tool_result_summary(self, tool_call: ToolCall, result: ToolExecutionResult) -> str:
"""构建用于终端展示的工具结果摘要。"""
history_content = result.get_history_content().strip()
if not history_content:
history_content = result.error_message.strip()
if not history_content:
history_content = "执行成功" if result.success else "执行失败"
summary_prefix = "[成功]" if result.success else "[失败]"
normalized_content = self._truncate_tool_record_text(history_content, max_length=200)
return f"- {tool_call.func_name} {summary_prefix}: {normalized_content}"
async def _handle_tool_calls(
self,
tool_calls: list[ToolCall],
latest_thought: str,
anchor_message: SessionMessage,
) -> bool:
) -> tuple[bool, list[str]]:
"""执行一批统一工具调用。
Args:
@@ -715,9 +737,11 @@ class MaisakaReasoningEngine:
anchor_message: 当前轮的锚点消息。
Returns:
bool: 是否需要暂停当前思考循环。
tuple[bool, list[str]]: 是否需要暂停当前思考循环,以及工具结果摘要列表
"""
tool_result_summaries: list[str] = []
if self._runtime._tool_registry is None:
for tool_call in tool_calls:
invocation = self._build_tool_invocation(tool_call, latest_thought)
@@ -728,7 +752,8 @@ class MaisakaReasoningEngine:
)
await self._store_tool_execution_record(invocation, result, None)
self._append_tool_execution_result(tool_call, result)
return False
tool_result_summaries.append(self._build_tool_result_summary(tool_call, result))
return False, tool_result_summaries
execution_context = self._build_tool_execution_context(latest_thought, anchor_message)
tool_spec_map = {
@@ -744,12 +769,13 @@ class MaisakaReasoningEngine:
tool_spec_map.get(invocation.tool_name),
)
self._append_tool_execution_result(tool_call, result)
tool_result_summaries.append(self._build_tool_result_summary(tool_call, result))
if not result.success and tool_call.func_name == "reply":
logger.warning(f"{self._runtime.log_prefix} 回复工具未生成可见消息,将继续下一轮循环")
if bool(result.metadata.get("pause_execution", False)):
return True
return True, tool_result_summaries
return False
return False, tool_result_summaries

View File

@@ -1,6 +1,6 @@
"""Maisaka 非 CLI 运行时。"""
from typing import Literal, Optional
from typing import Any, Literal, Optional
import asyncio
import time
@@ -450,28 +450,55 @@ class MaisakaHeartFlowChatting:
*,
selected_history_count: int,
prompt_tokens: int,
planner_response: str = "",
tool_calls: Optional[list[Any]] = None,
tool_results: Optional[list[str]] = None,
) -> None:
"""在终端展示当前聊天流的上下文占用情况"""
"""在终端展示当前聊天流的上下文占用、规划结果与工具摘要"""
if not global_config.maisaka.show_thinking:
return
session_name = chat_manager.get_session_name(self.session_id) or self.session_id
body = "\n".join(
[
f"聊天流: {session_name}",
f"Chat ID: {self.session_id}",
f"上下文占用: {selected_history_count}条 / {self._format_token_count(prompt_tokens)}",
]
)
body_lines = [
f"聊天流: {session_name}",
f"Chat ID: {self.session_id}",
f"上下文占用: {selected_history_count}条 / {self._format_token_count(prompt_tokens)}",
]
normalized_response = planner_response.strip()
if normalized_response:
body_lines.extend(["", "Maisaka 返回:", normalized_response])
normalized_tool_calls = self._build_tool_call_summary_lines(tool_calls or [])
if normalized_tool_calls:
body_lines.extend(["", "工具调用:", *normalized_tool_calls])
normalized_tool_results = [result.strip() for result in tool_results or [] if isinstance(result, str) and result.strip()]
if normalized_tool_results:
body_lines.extend(["", "工具结果:", *normalized_tool_results])
console.print(
Panel(
Text(body),
title="MaiSaka 上下文占用",
Text("\n".join(body_lines)),
title="MaiSaka 上下文与结果",
border_style="bright_blue",
padding=(0, 1),
)
)
@staticmethod
def _build_tool_call_summary_lines(tool_calls: list[Any]) -> list[str]:
"""构建工具调用摘要文本。"""
summary_lines: list[str] = []
for tool_call in tool_calls:
tool_name = str(getattr(tool_call, "func_name", getattr(tool_call, "name", "")) or "").strip() or "unknown"
tool_args = getattr(tool_call, "args", getattr(tool_call, "arguments", None))
if isinstance(tool_args, dict) and tool_args:
summary_lines.append(f"- {tool_name}: {tool_args}")
else:
summary_lines.append(f"- {tool_name}")
return summary_lines
def _log_cycle_started(self, cycle_detail: CycleDetail, round_index: int) -> None:
logger.info(
f"{self.log_prefix} MaiSaka 轮次开始: 循环编号={cycle_detail.cycle_id} "