fix:降低quote的概率
This commit is contained in:
@@ -22,8 +22,7 @@ def get_tool_spec() -> ToolSpec:
|
||||
detailed_description=(
|
||||
"参数说明:\n"
|
||||
"- msg_id:string,必填。要回复的目标用户消息编号。\n"
|
||||
"- quote:boolean,可选。当有非常明确的回复目标时,以引用回复的方式发送,默认 true。\n"
|
||||
"- unknown_words:array,可选。回复前可能需要查询的黑话或词条列表。"
|
||||
"- set_quote:boolean,可选。以引用回复的方式发送,默认 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,
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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} "
|
||||
|
||||
Reference in New Issue
Block a user