Merge branch 'Mai-with-u:dev' into dev
This commit is contained in:
@@ -240,7 +240,7 @@ class MaisakaExpressionSelector:
|
||||
if candidate.get("id") in selected_ids
|
||||
]
|
||||
self._update_last_active_time(selected_ids)
|
||||
logger.info(
|
||||
logger.debug(
|
||||
f"表达方式直接注入:session_id={session_id} 已选数={len(selected_ids)} "
|
||||
f"selected_ids={selected_ids!r} 已选预览={self._format_candidate_preview(selected_expressions)}"
|
||||
)
|
||||
|
||||
@@ -93,12 +93,14 @@ class BaseMaisakaReplyGenerator:
|
||||
alias_names = global_config.bot.alias_names
|
||||
bot_aliases = f",也有人叫你{','.join(alias_names)}" if alias_names else ""
|
||||
|
||||
prompt_personality = global_config.personality.personality
|
||||
prompt_personality = global_config.personality.personality.strip()
|
||||
if not prompt_personality:
|
||||
prompt_personality = "是人类。"
|
||||
|
||||
return f"你的名字是{bot_name}{bot_aliases},你{prompt_personality};"
|
||||
return f"你的名字是{bot_name}{bot_aliases}。\n{prompt_personality}"
|
||||
except Exception as exc:
|
||||
logger.warning(f"构建 Maisaka 人设提示词失败: {exc}")
|
||||
return "你的名字是麦麦,你是一个活泼可爱的 AI 助手。"
|
||||
return "你的名字是麦麦。\n是人类。"
|
||||
|
||||
@staticmethod
|
||||
def _normalize_content(content: str, limit: int = 500) -> str:
|
||||
|
||||
@@ -36,7 +36,6 @@ class ReplyerManager:
|
||||
generator_type = self._get_maisaka_generator_type() if replyer_type == "maisaka" else ""
|
||||
cache_key = f"{replyer_type}:{generator_type}:{stream_id}"
|
||||
if cache_key in self._repliers:
|
||||
logger.info(f"[ReplyerManager] 命中缓存 replyer: cache_key={cache_key}")
|
||||
return self._repliers[cache_key]
|
||||
|
||||
target_stream = chat_stream or _chat_manager.get_session_by_session_id(stream_id)
|
||||
|
||||
@@ -56,7 +56,7 @@ BOT_CONFIG_PATH: Path = (CONFIG_DIR / "bot_config.toml").resolve().absolute()
|
||||
MODEL_CONFIG_PATH: Path = (CONFIG_DIR / "model_config.toml").resolve().absolute()
|
||||
LEGACY_ENV_PATH: Path = (PROJECT_ROOT / ".env").resolve().absolute()
|
||||
MMC_VERSION: str = "1.0.0"
|
||||
CONFIG_VERSION: str = "8.9.18"
|
||||
CONFIG_VERSION: str = "8.9.19"
|
||||
MODEL_CONFIG_VERSION: str = "1.14.3"
|
||||
|
||||
logger = get_logger("config")
|
||||
|
||||
@@ -75,13 +75,13 @@ class PersonalityConfig(ConfigBase):
|
||||
__ui_icon__ = "user-circle"
|
||||
|
||||
personality: str = Field(
|
||||
default="是一个大二女大学生,现在正在上网和群友聊天。",
|
||||
default="你是一个大二女大学生,现在正在上网和群友聊天。",
|
||||
json_schema_extra={
|
||||
"x-widget": "textarea",
|
||||
"x-icon": "user-circle",
|
||||
},
|
||||
)
|
||||
"""人格,建议100字以内,描述人格特质和身份特征"""
|
||||
"""人格,建议200字以内,描述人格特质和身份特征;可以写完整设定。要求第二人称"""
|
||||
|
||||
reply_style: str = Field(
|
||||
default="你的风格平淡简短。可以参考贴吧,知乎和微博的回复风格。不浮夸不长篇大论,不要过分修辞和复杂句。尽量回复的简短一些,平淡一些",
|
||||
@@ -1262,7 +1262,7 @@ class DebugConfig(ConfigBase):
|
||||
__ui_icon__ = "more-horizontal"
|
||||
|
||||
enable_maisaka_stage_board: bool = Field(
|
||||
default=True,
|
||||
default=False,
|
||||
json_schema_extra={
|
||||
"x-widget": "switch",
|
||||
"x-icon": "layout-dashboard",
|
||||
|
||||
@@ -939,7 +939,7 @@ class LLMOrchestrator:
|
||||
audio_base64=audio_base64,
|
||||
)
|
||||
if self.request_type.startswith("maisaka_"):
|
||||
logger.info(
|
||||
logger.debug(
|
||||
f"LLMOrchestrator[{self.request_type}] 正在向模型 model={model_info.name} 发送请求 "
|
||||
f"(tool_options={len(tool_options or [])})"
|
||||
)
|
||||
@@ -949,7 +949,7 @@ class LLMOrchestrator:
|
||||
request=request,
|
||||
)
|
||||
if self.request_type.startswith("maisaka_"):
|
||||
logger.info(
|
||||
logger.debug(
|
||||
f"LLMOrchestrator[{self.request_type}] 模型 model={model_info.name} 已返回 API 响应"
|
||||
)
|
||||
total_tokens, penalty, usage_penalty = self.model_usage[model_info.name]
|
||||
@@ -962,7 +962,7 @@ class LLMOrchestrator:
|
||||
total_tokens, penalty, usage_penalty = self.model_usage[model_info.name]
|
||||
self.model_usage[model_info.name] = (total_tokens, penalty, usage_penalty - 1)
|
||||
if self.request_type.startswith("maisaka_"):
|
||||
logger.info(
|
||||
logger.debug(
|
||||
f"LLMOrchestrator[{self.request_type}] 模型 model={model_info.name} 的请求已被外部信号中断"
|
||||
)
|
||||
raise e
|
||||
|
||||
@@ -282,15 +282,17 @@ class MaisakaChatLoopService:
|
||||
try:
|
||||
bot_name = global_config.bot.nickname
|
||||
if global_config.bot.alias_names:
|
||||
bot_nickname = f", also known as {','.join(global_config.bot.alias_names)}"
|
||||
bot_nickname = f",也有人叫你{','.join(global_config.bot.alias_names)}"
|
||||
else:
|
||||
bot_nickname = ""
|
||||
|
||||
prompt_personality = global_config.personality.personality
|
||||
prompt_personality = global_config.personality.personality.strip()
|
||||
if not prompt_personality:
|
||||
prompt_personality = "是人类。"
|
||||
|
||||
return f"Your name is {bot_name}{bot_nickname}; persona: {prompt_personality};"
|
||||
return f"你的名字是{bot_name}{bot_nickname}。\n{prompt_personality}"
|
||||
except Exception:
|
||||
return "Your name is MaiMai; persona: lively and cute AI assistant."
|
||||
return "你的名字是麦麦。\n是人类。"
|
||||
|
||||
async def ensure_chat_prompt_loaded(self, tools_section: str = "") -> None:
|
||||
"""确保主聊天提示词已经加载完成。
|
||||
|
||||
@@ -54,6 +54,7 @@ logger = get_logger("maisaka_reasoning_engine")
|
||||
|
||||
TIMING_GATE_CONTEXT_LIMIT = 24
|
||||
TIMING_GATE_MAX_TOKENS = 384
|
||||
TIMING_GATE_MAX_ATTEMPTS = 3
|
||||
TIMING_GATE_TOOL_NAMES = {"continue", "no_reply", "wait"}
|
||||
HISTORY_SILENT_TOOL_NAMES = {"finish"}
|
||||
|
||||
@@ -247,36 +248,69 @@ class MaisakaReasoningEngine:
|
||||
if self._runtime._force_next_timing_continue:
|
||||
return self._build_forced_continue_timing_result()
|
||||
|
||||
response = await self._run_timing_gate_sub_agent(
|
||||
context_message_limit=TIMING_GATE_CONTEXT_LIMIT,
|
||||
system_prompt=self._build_timing_gate_system_prompt(),
|
||||
tool_definitions=get_timing_tools(),
|
||||
)
|
||||
tool_result_summaries: list[str] = []
|
||||
tool_monitor_results: list[dict[str, Any]] = []
|
||||
response: Any = None
|
||||
selected_tool_call: Optional[ToolCall] = None
|
||||
for tool_call in response.tool_calls:
|
||||
if tool_call.func_name in TIMING_GATE_TOOL_NAMES:
|
||||
selected_tool_call = tool_call
|
||||
invalid_tool_text = ""
|
||||
for attempt_index in range(TIMING_GATE_MAX_ATTEMPTS):
|
||||
response = await self._run_timing_gate_sub_agent(
|
||||
context_message_limit=TIMING_GATE_CONTEXT_LIMIT,
|
||||
system_prompt=self._build_timing_gate_system_prompt(),
|
||||
tool_definitions=get_timing_tools(),
|
||||
)
|
||||
selected_tool_call = None
|
||||
for tool_call in response.tool_calls:
|
||||
if tool_call.func_name in TIMING_GATE_TOOL_NAMES:
|
||||
selected_tool_call = tool_call
|
||||
break
|
||||
|
||||
if selected_tool_call is not None:
|
||||
break
|
||||
|
||||
if selected_tool_call is None:
|
||||
invalid_tool_names = [
|
||||
str(tool_call.func_name).strip()
|
||||
for tool_call in response.tool_calls
|
||||
if str(tool_call.func_name).strip()
|
||||
]
|
||||
invalid_tool_text = "、".join(invalid_tool_names) if invalid_tool_names else "无工具"
|
||||
logger.warning(
|
||||
f"{self._runtime.log_prefix} Timing Gate 未返回有效控制工具:{invalid_tool_text},将按 no_reply 处理"
|
||||
)
|
||||
self._append_timing_gate_invalid_tool_hint(invalid_tool_text)
|
||||
remaining_attempts = TIMING_GATE_MAX_ATTEMPTS - attempt_index - 1
|
||||
if remaining_attempts > 0:
|
||||
logger.warning(
|
||||
f"{self._runtime.log_prefix} Timing Gate 未返回有效控制工具:{invalid_tool_text},"
|
||||
f"将重试 ({attempt_index + 1}/{TIMING_GATE_MAX_ATTEMPTS})"
|
||||
)
|
||||
tool_result_summaries.append(
|
||||
f"- retry [非法 Timing 工具]: 返回了 {invalid_tool_text},将重试 "
|
||||
f"({attempt_index + 1}/{TIMING_GATE_MAX_ATTEMPTS})"
|
||||
)
|
||||
continue
|
||||
|
||||
logger.warning(
|
||||
f"{self._runtime.log_prefix} Timing Gate 连续 {TIMING_GATE_MAX_ATTEMPTS} 次未返回有效控制工具:"
|
||||
f"{invalid_tool_text},将按 no_reply 处理"
|
||||
)
|
||||
self._runtime._enter_stop_state()
|
||||
tool_result_summaries.append(
|
||||
f"- no_reply [非法 Timing 工具]: 返回了 {invalid_tool_text},已停止本轮并等待新消息"
|
||||
)
|
||||
return "no_reply", response, tool_result_summaries, tool_monitor_results
|
||||
|
||||
if selected_tool_call is None:
|
||||
self._runtime._enter_stop_state()
|
||||
tool_result_summaries.append(
|
||||
"- no_reply [非法 Timing 工具]: 已停止本轮并等待新消息"
|
||||
)
|
||||
return "no_reply", response, tool_result_summaries, tool_monitor_results
|
||||
|
||||
if invalid_tool_text:
|
||||
self._runtime._chat_history = [
|
||||
message
|
||||
for message in self._runtime._chat_history
|
||||
if message.source != TIMING_GATE_INVALID_TOOL_HINT_SOURCE
|
||||
]
|
||||
|
||||
append_history = False
|
||||
store_record = selected_tool_call.func_name != "continue"
|
||||
invocation, result, tool_spec = await self._invoke_tool_call(
|
||||
|
||||
@@ -429,7 +429,7 @@ class MaisakaHeartFlowChatting:
|
||||
self._reply_latency_measurement_started_at = None
|
||||
self._recent_reply_latencies.append((time.time(), reply_duration))
|
||||
self._prune_recent_reply_latencies()
|
||||
logger.info(
|
||||
logger.debug(
|
||||
f"{self.log_prefix} 已记录消息回复时长: {reply_duration:.2f} 秒 "
|
||||
f"最近10分钟样本数={len(self._recent_reply_latencies)}"
|
||||
)
|
||||
@@ -943,7 +943,7 @@ class MaisakaHeartFlowChatting:
|
||||
if self._pending_wait_tool_call_id != tool_call_id:
|
||||
return
|
||||
|
||||
logger.info(f"{self.log_prefix} Maisaka 等待已超时")
|
||||
logger.debug(f"{self.log_prefix} Maisaka 等待已超时")
|
||||
self._agent_state = self._STATE_RUNNING
|
||||
await self._internal_turn_queue.put("timeout")
|
||||
except asyncio.CancelledError:
|
||||
@@ -1645,7 +1645,7 @@ class MaisakaHeartFlowChatting:
|
||||
return panels
|
||||
|
||||
def _log_cycle_started(self, cycle_detail: CycleDetail, round_index: int) -> None:
|
||||
logger.info(
|
||||
logger.debug(
|
||||
f"{self.log_prefix} MaiSaka 轮次开始: 循环编号={cycle_detail.cycle_id} "
|
||||
f"回合={round_index + 1}/{self._max_internal_rounds} "
|
||||
f"上下文消息数={len(self._chat_history)}"
|
||||
@@ -1653,14 +1653,14 @@ class MaisakaHeartFlowChatting:
|
||||
|
||||
def _log_cycle_completed(self, cycle_detail: CycleDetail, timer_strings: list[str]) -> None:
|
||||
end_time = cycle_detail.end_time if cycle_detail.end_time is not None else cycle_detail.start_time
|
||||
logger.info(
|
||||
logger.debug(
|
||||
f"{self.log_prefix} MaiSaka 轮次结束: 循环编号={cycle_detail.cycle_id} "
|
||||
f"总耗时={end_time - cycle_detail.start_time:.2f} 秒; "
|
||||
f"阶段耗时={', '.join(timer_strings) if timer_strings else '无'}"
|
||||
)
|
||||
|
||||
def _log_history_trimmed(self, removed_count: int, user_message_count: int) -> None:
|
||||
logger.info(
|
||||
logger.debug(
|
||||
f"{self.log_prefix} 已裁剪 {removed_count} 条历史消息; "
|
||||
# f"剩余计入上下文的消息数={user_message_count}"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user