diff --git a/astrbot/core/config/default.py b/astrbot/core/config/default.py
index fc304d587..4a75a11bc 100644
--- a/astrbot/core/config/default.py
+++ b/astrbot/core/config/default.py
@@ -54,6 +54,7 @@ DEFAULT_CONFIG = {
"wake_prefix": "",
"web_search": False,
"web_search_link": False,
+ "display_reasoning_text": False,
"identifier": False,
"datetime_system_prompt": True,
"default_personality": "default",
@@ -1652,6 +1653,11 @@ CONFIG_METADATA_2 = {
"obvious_hint": True,
"hint": "开启后,将会传入网页搜索结果的链接给模型,并引导模型输出引用链接。",
},
+ "display_reasoning_text": {
+ "description": "显示思考内容",
+ "type": "bool",
+ "hint": "开启后,将在回复中显示模型的思考过程。",
+ },
"identifier": {
"description": "启动识别群员",
"type": "bool",
diff --git a/packages/thinking_filter/main.py b/packages/thinking_filter/main.py
new file mode 100644
index 000000000..eb36a107f
--- /dev/null
+++ b/packages/thinking_filter/main.py
@@ -0,0 +1,70 @@
+import re
+from astrbot.api.event import filter, AstrMessageEvent
+from astrbot.api.star import Context, Star, register
+from astrbot.api.provider import LLMResponse
+from openai.types.chat.chat_completion import ChatCompletion
+
+
+@register(
+ "thinking_filter",
+ "Soulter",
+ "可选择是否过滤推理模型的思考内容",
+ "1.0.0",
+ "https://astrbot.app",
+)
+class R1Filter(Star):
+ def __init__(self, context: Context):
+ super().__init__(context)
+ self.display_reasoning_text = (
+ self.context.get_config()
+ .get("provider_settings", {})
+ .get("display_reasoning_text", False)
+ )
+
+ @filter.on_llm_response()
+ async def resp(self, event: AstrMessageEvent, response: LLMResponse):
+ if self.display_reasoning_text:
+ if (
+ response
+ and response.raw_completion
+ and isinstance(response.raw_completion, ChatCompletion)
+ ):
+ if (
+ len(response.raw_completion.choices)
+ and response.raw_completion.choices[0].message
+ ):
+ message = response.raw_completion.choices[0].message
+ reasoning_content = "" # 初始化 reasoning_content
+
+ # 检查 Groq deepseek-r1-distill-llama-70b模型的 'reasoning' 属性
+ if hasattr(message, "reasoning") and message.reasoning:
+ reasoning_content = message.reasoning
+ # 检查 DeepSeek deepseek-reasoner模型的 'reasoning_content'
+ elif (
+ hasattr(message, "reasoning_content")
+ and message.reasoning_content
+ ):
+ reasoning_content = message.reasoning_content
+
+ if reasoning_content:
+ response.completion_text = (
+ f"🤔思考:{reasoning_content}\n\n{message.content}"
+ )
+ else:
+ response.completion_text = message.content
+
+ else:
+ # DeepSeek 官方的模型的思考存在了 reason_content 字段因此不需要过滤
+ completion_text = response.completion_text
+ # 适配 ollama deepseek-r1 模型
+ if r"" in completion_text or r"" in completion_text:
+ completion_text = re.sub(
+ r".*?", "", completion_text, flags=re.DOTALL
+ ).strip()
+ # 可能有单标签情况
+ completion_text = (
+ completion_text.replace(r"", "")
+ .replace(r"", "")
+ .strip()
+ )
+ response.completion_text = completion_text