From 42bed6aecad51c23ab013575137ed3ebadbe31d9 Mon Sep 17 00:00:00 2001 From: Asankilp Date: Fri, 31 Jan 2025 18:23:41 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20=E6=B7=BB=E5=8A=A0=E6=8F=90?= =?UTF-8?q?=E5=8F=96=E6=80=9D=E7=BB=B4=E9=93=BE=EF=BC=8C=E5=A4=84=E7=90=86?= =?UTF-8?q?=E6=B6=88=E6=81=AF=E5=AF=B9=E8=B1=A1=E7=9A=84=E5=87=BD=E6=95=B0?= =?UTF-8?q?=EF=BC=8C=E6=94=B9=E5=96=84=E5=85=BC=E5=AE=B9=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nonebot_plugin_marshoai/marsho.py | 30 +++++++++---------- nonebot_plugin_marshoai/util.py | 48 ++++++++++++++++++++++++++++--- 2 files changed, 58 insertions(+), 20 deletions(-) diff --git a/nonebot_plugin_marshoai/marsho.py b/nonebot_plugin_marshoai/marsho.py index 698dd0e..cb323c6 100644 --- a/nonebot_plugin_marshoai/marsho.py +++ b/nonebot_plugin_marshoai/marsho.py @@ -6,7 +6,6 @@ import openai from arclet.alconna import Alconna, AllParam, Args from azure.ai.inference.models import ( AssistantMessage, - ChatCompletionsToolCall, CompletionsFinishReason, ImageContentItem, ImageUrl, @@ -22,7 +21,6 @@ from nonebot.permission import SUPERUSER from nonebot.rule import Rule, to_me from nonebot.typing import T_State from nonebot_plugin_alconna import MsgTarget, UniMessage, UniMsg, on_alconna -from openai import AsyncOpenAI from .hooks import * from .instances import * @@ -287,7 +285,7 @@ async def marsho( tools_lists = tools.tools_list + list( map(lambda v: v.data(), get_function_calls().values()) ) - logger.debug(f"正在获取回答,模型:{model_name}") + logger.info(f"正在获取回答,模型:{model_name}") response = await make_chat_openai( client=client, model_name=model_name, @@ -306,25 +304,26 @@ async def marsho( context.append( UserMessage(content=usermsg).as_dict(), target.id, target.private # type: ignore ) - choice_msg_dict = choice.message.to_dict() - if "reasoning_content" in choice_msg_dict: - if config.marshoai_send_thinking: - await UniMessage( - "思维链:\n" + choice_msg_dict["reasoning_content"] - ).send() - del choice_msg_dict["reasoning_content"] - context.append(choice_msg_dict, target.id, target.private) + ##### DeepSeek-R1 兼容部分 ##### + choice_msg_content, choice_msg_thinking, choice_msg_after = ( + extract_content_and_think(choice.message) + ) + if choice_msg_thinking and config.marshoai_send_thinking: + await UniMessage("思维链:\n" + choice_msg_thinking).send() + ##### 兼容部分结束 ##### + + context.append(choice_msg_after.to_dict(), target.id, target.private) if [target.id, target.private] not in target_list: target_list.append([target.id, target.private]) # 对话成功发送消息 if config.marshoai_enable_richtext_parse: - await (await parse_richtext(str(choice.message.content))).send( + await (await parse_richtext(str(choice_msg_content))).send( reply_to=True ) else: - await UniMessage(str(choice.message.content)).send(reply_to=True) + await UniMessage(str(choice_msg_content)).send(reply_to=True) elif choice.finish_reason == CompletionsFinishReason.CONTENT_FILTERED: # 对话失败,消息过滤 @@ -467,9 +466,8 @@ with contextlib.suppress(ImportError): # 优化先不做() ) choice = response.choices[0] if choice.finish_reason == CompletionsFinishReason.STOPPED: - await UniMessage(" " + str(choice.message.content)).send( - at_sender=True - ) + content = extract_content_and_think(choice.message)[0] + await UniMessage(" " + str(content)).send(at_sender=True) except Exception as e: await UniMessage(str(e) + suggest_solution(str(e))).send() traceback.print_exc() diff --git a/nonebot_plugin_marshoai/util.py b/nonebot_plugin_marshoai/util.py index 35789d2..fb76874 100755 --- a/nonebot_plugin_marshoai/util.py +++ b/nonebot_plugin_marshoai/util.py @@ -1,6 +1,7 @@ import base64 import json import mimetypes +import re import uuid from typing import Any, Optional @@ -15,6 +16,7 @@ from nonebot_plugin_alconna import Image as ImageMsg from nonebot_plugin_alconna import Text as TextMsg from nonebot_plugin_alconna import UniMessage from openai import AsyncOpenAI, NotGiven +from openai.types.chat import ChatCompletionMessage from zhDateTime import DateTime from .config import config @@ -34,7 +36,7 @@ if config.marshoai_enable_time_prompt: # noinspection LongLine -_chromium_headers = { +_browser_headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:134.0) Gecko/20100101 Firefox/134.0" } """ @@ -47,7 +49,7 @@ _praises_init_data = { "like": [ { "name": "Asankilp", - "advantages": "赋予了Marsho猫娘人格,使用手机,在vim与vscode的加持下为Marsho写了许多代码,使Marsho更加可爱", + "advantages": "赋予了Marsho猫娘人格,在vim与vscode的加持下为Marsho写了许多代码,使Marsho更加可爱", } ] } @@ -71,7 +73,7 @@ async def get_image_raw_and_type( """ async with httpx.AsyncClient() as client: - response = await client.get(url, headers=_chromium_headers, timeout=timeout) + response = await client.get(url, headers=_browser_headers, timeout=timeout) if response.status_code == 200: # 获取图片数据 content_type = response.headers.get("Content-Type") @@ -180,7 +182,7 @@ async def refresh_praises_json(): praises_json = data -def build_praises(): +def build_praises() -> str: praises = get_praises() result = ["你喜欢以下几个人物,他们有各自的优点:"] for item in praises["like"]: @@ -461,3 +463,41 @@ if config.marshoai_enable_richtext_parse: """ Mulan PSL v2 协议授权部分结束 """ + + +def extract_content_and_think( + message: ChatCompletionMessage, +) -> tuple[str, str | None, ChatCompletionMessage]: + """ + 处理 API 返回的消息对象,提取其中的内容和思维链,并返回处理后的消息,思维链,消息对象。 + + Args: + message (ChatCompletionMessage): API 返回的消息对象。 + Returns: + + - content (str): 提取出的消息内容。 + + - thinking (str | None): 提取出的思维链,如果没有则为 None。 + + - message (ChatCompletionMessage): 移除了思维链的消息对象。 + + 本函数参考自 [nonebot-plugin-deepseek](https://github.com/KomoriDev/nonebot-plugin-deepseek) + """ + try: + thinking = message.reasoning_content # type: ignore + except AttributeError: + thinking = None + if thinking: + delattr(message, "reasoning_content") + else: + think_blocks = re.findall( + r"(.*?)", message.content or "", flags=re.DOTALL + ) + thinking = "\n".join([block.strip() for block in think_blocks if block.strip()]) + + content = re.sub( + r".*?", "", message.content or "", flags=re.DOTALL + ).strip() + message.content = content + + return content, thinking, message