fix(chat): AI 回覆截斷問題 — 強制 persona + Markdown 清理 + 600字上限
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 14m39s

問題: OpenClaw/NemoClaw 回覆 Markdown 語法 + 超長,Telegram 顯示截斷
修正:
1. chat_manager: _call_openclaw/_call_nemotron 強制前置 persona (含不超過300字規範)
2. telegram_gateway: _clean_ai_reply() 移除 **bold** *italic* # header 語法
   移除 deepseek-r1 <think> 標籤,截斷 > 600 字並在段落邊界截

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
OG T
2026-04-10 21:26:15 +08:00
parent 5d45499d12
commit 100e4d9b89
2 changed files with 32 additions and 4 deletions

View File

@@ -85,7 +85,11 @@ class ChatManager:
2026-04-03 ogt: 老闆指示改用 Gemini費用控管月上限 $10 USD
每次回覆附帶 token 用量與費用統計
2026-04-10 Claude Code: 強制合併 OPENCLAW_PERSONA確保字數限制與格式規範
"""
# 強制在 system_prompt 前置 persona確保 LLM 遵守字數與格式
system_prompt = f"{OPENCLAW_PERSONA}\n{system_prompt}"
import httpx
from src.core.config import get_settings
settings = get_settings()
@@ -153,7 +157,12 @@ class ChatManager:
2026-04-09 ogt: 改接 192.168.0.111 Ollama deepseek-r1:14bSRE 推理能力最強
deepseek-r1 含 <think> 標籤,需過濾後才回傳
2026-04-10 Claude Code: 強制合併 NEMOCLAW_PERSONA確保字數限制與格式規範
"""
# 強制在 system_prompt 前置 persona
system_prompt = f"{NEMOCLAW_PERSONA}\n{system_prompt}"
import httpx
import re

View File

@@ -3683,14 +3683,32 @@ class TelegramGateway:
context = await chat_mgr.get_system_context()
def _clean_ai_reply(text: str, max_chars: int = 600) -> str:
"""清理 AI 回覆:移除 Markdown 語法,截斷超長內容"""
import re
# 移除 Markdown bold/italic (**text**, *text*, __text__, _text_)
text = re.sub(r'\*\*(.+?)\*\*', r'\1', text)
text = re.sub(r'\*(.+?)\*', r'\1', text)
text = re.sub(r'__(.+?)__', r'\1', text)
text = re.sub(r'_(.+?)_', r'\1', text)
# 移除 Markdown header (#, ##, ###)
text = re.sub(r'^#{1,3}\s+', '', text, flags=re.MULTILINE)
# 移除 <think> 標籤deepseek-r1
text = re.sub(r'<think>.*?</think>', '', text, flags=re.DOTALL).strip()
# 截斷
if len(text) > max_chars:
text = text[:max_chars].rsplit('\n', 1)[0] + ''
return text.strip()
if mention_openclaw and not mention_nemo:
# 只 OpenClaw 回應
result = await chat_mgr._call_openclaw(
f"{context}\n用戶 {username} 在 SRE 戰情室問你:",
clean_text,
)
body = _clean_ai_reply(result) if result else '🔴 無響應'
await self.send_as_openclaw(
text=f"🦞 <b>OpenClaw</b>\n\n{result or '🔴 無響應'}",
text=f"🦞 <b>OpenClaw</b>\n\n{body}",
reply_to_message_id=message_id,
)
@@ -3700,8 +3718,9 @@ class TelegramGateway:
f"{context}\n用戶 {username} 在 SRE 戰情室問你:",
clean_text,
)
body = _clean_ai_reply(result) if result else '🔴 無響應 (NIM 超時)'
await self.send_as_nemotron(
text=f"🤖 <b>NemoClaw</b>\n\n{result or '🔴 無響應 (NIM 超時)'}",
text=f"🤖 <b>NemoClaw</b>\n\n{body}",
reply_to_message_id=message_id,
)
@@ -3717,13 +3736,13 @@ class TelegramGateway:
if oc_result and not isinstance(oc_result, Exception):
await self.send_as_openclaw(
text=f"🦞 <b>OpenClaw</b>\n\n{oc_result}",
text=f"🦞 <b>OpenClaw</b>\n\n{_clean_ai_reply(oc_result)}",
reply_to_message_id=message_id,
)
if nemo_result and not isinstance(nemo_result, Exception):
await self.send_as_nemotron(
text=f"🤖 <b>NemoClaw</b>\n\n{nemo_result}",
text=f"🤖 <b>NemoClaw</b>\n\n{_clean_ai_reply(nemo_result)}",
reply_to_message_id=message_id,
)