feat(ai): clean reasoning content from replies

This commit is contained in:
liuwei
2026-04-07 09:23:48 +08:00
parent 496463c442
commit 51fe971cda
4 changed files with 73 additions and 10 deletions

View File

@@ -6,7 +6,10 @@ enabled = true
[api]
api_key = "app-McGLzBhBjeBCSEi7n83MtuTo"
api_url = "http://192.168.2.240/v1/chat-messages"
response_mode = "streaming"
response_mode = "blocking"
connect_timeout_seconds = 10
request_timeout_seconds = 180
retry_delays_seconds = [10, 20]
[output]
output_dir = "output"

View File

@@ -21,7 +21,7 @@ from utils.decorator.rate_limit_decorator import group_feature_rate_limit
from utils.markdown_to_image import convert_md_str_to_image
from utils.revoke.message_auto_revoke import MessageAutoRevoke
from utils.robot_cmd.robot_command import GroupBotManager, PermissionStatus
from utils.string_utils import remove_trailing_content
from utils.string_utils import remove_reasoning_content, remove_trailing_content
from utils.wechat.contact_manager import ContactManager
from utils.wechat.message_to_db import MessageStorage
from wechat_ipad import WechatAPIClient
@@ -84,7 +84,10 @@ class MessageSummaryPlugin(MessagePluginInterface):
api_config = self._config.get("api", {})
self._api_key = api_config.get("api_key", "app-McGLzBhBjeBCSEi7n83MtuTo")
self._api_url = api_config.get("api_url", "http://192.168.2.240/v1/chat-messages")
self._response_mode = api_config.get("response_mode", "streaming")
self._response_mode = api_config.get("response_mode", "blocking")
self._connect_timeout_seconds = int(api_config.get("connect_timeout_seconds", 10))
self._request_timeout_seconds = int(api_config.get("request_timeout_seconds", 180))
self._retry_delays_seconds = api_config.get("retry_delays_seconds", [10, 20])
self.message_storage = MessageStorage()
db_manager = context.get("db_manager")
if db_manager:
@@ -275,6 +278,16 @@ class MessageSummaryPlugin(MessagePluginInterface):
tokens_info = f"\n\n【tokens】输入: {prompt_tokens} 生成: {completion_tokens} 总: {total_tokens}"
return answer + tokens_info
def _clean_summary_output(self, answer: str) -> str:
"""清理总结输出中的思考内容和无关尾部内容"""
if not answer:
return answer
cleaned = remove_reasoning_content(answer)
cleaned = remove_trailing_content(cleaned)
cleaned = re.sub(r'\n{3,}', '\n\n', cleaned).strip()
return cleaned
def _get_revoke_manager(self) -> Optional[MessageAutoRevoke]:
"""优先使用消息上下文中的撤回器,定时任务场景则懒初始化一个"""
if self.revoke:
@@ -357,12 +370,15 @@ class MessageSummaryPlugin(MessagePluginInterface):
"Accept": "text/event-stream" if self._response_mode == "streaming" else "application/json"
}
max_retries = 3
retry_delays = [2, 4]
max_retries = len(self._retry_delays_seconds) + 1
for attempt in range(1, max_retries + 1):
try:
custom_timeout = ClientTimeout(total=None, connect=10, sock_read=300)
custom_timeout = ClientTimeout(
total=None,
connect=self._connect_timeout_seconds,
sock_read=self._request_timeout_seconds
)
conn = aiohttp.TCPConnector(keepalive_timeout=60) # 保持连接活跃
async with aiohttp.ClientSession(connector=conn, timeout=custom_timeout) as session:
async with session.post(self._api_url, headers=headers, json=data) as response:
@@ -381,8 +397,7 @@ class MessageSummaryPlugin(MessagePluginInterface):
# 提取回答内容
answer = response_data.get("answer", "")
# 去除广告内容pollinations.ai 的广告
# answer = remove_trailing_content(answer)
answer = self._clean_summary_output(answer)
spath = ""
# 提取token使用情况
metadata = response_data.get("metadata", {})
@@ -420,7 +435,7 @@ class MessageSummaryPlugin(MessagePluginInterface):
self.LOG.error(f"处理总结时出现未知错误: attempt={attempt}/{max_retries}, error={e}")
if attempt < max_retries:
delay = retry_delays[attempt - 1] if attempt - 1 < len(retry_delays) else retry_delays[-1]
delay = self._retry_delays_seconds[attempt - 1]
self.LOG.warning(f"群总结生成失败,准备重试: attempt={attempt}/{max_retries}, delay={delay}s")
await asyncio.sleep(delay)