mirror of
https://github.com/LiteyukiStudio/nonebot-plugin-marshoai.git
synced 2025-02-16 01:59:57 +08:00
系统提示词相关兼容性改进 (#12)
* 更新OpenAI模型列表,重构获取系统提示词逻辑,添加开发者消息类型,兼容 OpenAI o1 以上模型的系统提示词 * 添加 System-As-User 提示词配置,更新相关文档 * 更新使用文档,添加 DeepSeek-R1 模型的 System-As-User Prompt 配置说明
This commit is contained in:
parent
0c57ace798
commit
57c09df1fe
@ -117,7 +117,8 @@ Add options in the `.env` file from the diagram below in nonebot2 project.
|
||||
| -------------------------------- | ------- | --------------------------------------- | --------------------------------------------------------------------------------------------- |
|
||||
| MARSHOAI_TOKEN | `str` | | The token needed to call AI API |
|
||||
| MARSHOAI_DEFAULT_MODEL | `str` | `gpt-4o-mini` | The default model of Marsho |
|
||||
| MARSHOAI_PROMPT | `str` | Catgirl Marsho's character prompt | Marsho's basic system prompt **※Some models(o1 and so on) don't support it** |
|
||||
| MARSHOAI_PROMPT | `str` | Catgirl Marsho's character prompt | Marsho's basic system prompt |
|
||||
| MARSHOAI_SYSASUSER_PROMPT | `str` | `好的喵~` | Marsho 的 System-As-User 启用时,使用的 Assistant 消息 |
|
||||
| MARSHOAI_ADDITIONAL_PROMPT | `str` | | Marsho's external system prompt |
|
||||
| MARSHOAI_ENFORCE_NICKNAME | `bool` | `true` | Enforce user to set nickname or not |
|
||||
| MARSHOAI_POKE_SUFFIX | `str` | `揉了揉你的猫耳` | When double click Marsho who connected to OneBot adapter, the chat content. When it's empty string, double click function is off. Such as, the default content is `*[昵称]揉了揉你的猫耳。` |
|
||||
@ -135,6 +136,7 @@ Add options in the `.env` file from the diagram below in nonebot2 project.
|
||||
| MARSHOAI_ENABLE_SUPPORT_IMAGE_TIP | `bool` | `true` | When on, if user send request with photo and model don't support that, remind the user |
|
||||
| MARSHOAI_ENABLE_NICKNAME_TIP | `bool` | `true` | When on, if user haven't set username, remind user to set |
|
||||
| MARSHOAI_ENABLE_PRAISES | `bool` | `true` | Turn on Praise list or not |
|
||||
| MARSHOAI_ENABLE_SYSASUSER_PROMPT | `bool` | `false` | 是否启用 System-As-User 提示词 |
|
||||
| MARSHOAI_ENABLE_TIME_PROMPT | `bool` | `true` | Turn on real-time date and time (accurate to seconds) and lunar date system prompt |
|
||||
| MARSHOAI_ENABLE_TOOLS | `bool` | `false` | Turn on Marsho Tools or not |
|
||||
| MARSHOAI_ENABLE_PLUGINS | `bool` | `true` | Turn on Marsho Plugins or not
|
||||
|
@ -119,7 +119,8 @@ GitHub Models API 的限制较多,不建议使用,建议通过修改`MARSHOA
|
||||
| -------------------------------- | ------- | --------------------------------------- | --------------------------------------------------------------------------------------------- |
|
||||
| MARSHOAI_TOKEN | `str` | | 调用 AI API 所需的 token |
|
||||
| MARSHOAI_DEFAULT_MODEL | `str` | `gpt-4o-mini` | Marsho 默认调用的模型 |
|
||||
| MARSHOAI_PROMPT | `str` | 猫娘 Marsho 人设提示词 | Marsho 的基本系统提示词 **※部分模型(o1等)不支持系统提示词。** |
|
||||
| MARSHOAI_PROMPT | `str` | 猫娘 Marsho 人设提示词 | Marsho 的基本系统提示词 |
|
||||
| MARSHOAI_SYSASUSER_PROMPT | `str` | `好的喵~` | Marsho 的 System-As-User 启用时,使用的 Assistant 消息 |
|
||||
| MARSHOAI_ADDITIONAL_PROMPT | `str` | | Marsho 的扩展系统提示词 |
|
||||
| MARSHOAI_ENFORCE_NICKNAME | `bool` | `true` | 是否强制用户设置昵称 |
|
||||
| MARSHOAI_POKE_SUFFIX | `str` | `揉了揉你的猫耳` | 对 Marsho 所连接的 OneBot 用户进行双击戳一戳时,构建的聊天内容。此配置项为空字符串时,戳一戳响应功能会被禁用。例如,默认值构建的聊天内容将为`*[昵称]揉了揉你的猫耳。` |
|
||||
@ -135,6 +136,7 @@ GitHub Models API 的限制较多,不建议使用,建议通过修改`MARSHOA
|
||||
| MARSHOAI_ENABLE_SUPPORT_IMAGE_TIP | `bool` | `true` | 启用后用户发送带图请求时若模型不支持图片,则提示用户 |
|
||||
| MARSHOAI_ENABLE_NICKNAME_TIP | `bool` | `true` | 启用后用户未设置昵称时提示用户设置 |
|
||||
| MARSHOAI_ENABLE_PRAISES | `bool` | `true` | 是否启用夸赞名单功能 |
|
||||
| MARSHOAI_ENABLE_SYSASUSER_PROMPT | `bool` | `false` | 是否启用 System-As-User 提示词 |
|
||||
| MARSHOAI_ENABLE_TIME_PROMPT | `bool` | `true` | 是否启用实时更新的日期与时间(精确到秒)与农历日期系统提示词 |
|
||||
| MARSHOAI_ENABLE_TOOLS | `bool` | `false` | 是否启用小棉工具 |
|
||||
| MARSHOAI_ENABLE_PLUGINS | `bool` | `true` | 是否启用小棉插件 |
|
||||
|
@ -23,7 +23,15 @@ title: 使用
|
||||
```dotenv
|
||||
MARSHOAI_ADDITIONAL_IMAGE_MODELS=["hunyuan-vision"]
|
||||
```
|
||||
|
||||
- 对于本地部署的 DeepSeek-R1 模型:
|
||||
:::tip
|
||||
MarshoAI 默认使用 System Prompt 进行人设等的调整,但 DeepSeek-R1 官方推荐**避免**使用 System Prompt(但可以正常使用)。
|
||||
为解决此问题,引入了 System-As-User Prompt 配置,可将 System Prompt 作为用户传入的消息。
|
||||
:::
|
||||
```dotenv
|
||||
MARSHOAI_ENABLE_SYSASUSER_PROMPT=true
|
||||
MARSHOAI_SYSASUSER_PROMPT="好的喵~" # 假装是模型收到消息后的回答
|
||||
```
|
||||
### 使用 DeepSeek-R1 模型
|
||||
MarshoAI 兼容 DeepSeek-R1 模型,你可通过以下步骤来使用:
|
||||
1. 获取 API Key
|
||||
|
33
nonebot_plugin_marshoai/_types.py
Normal file
33
nonebot_plugin_marshoai/_types.py
Normal file
@ -0,0 +1,33 @@
|
||||
# source: https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/ai/azure-ai-inference/azure/ai/inference/models/_models.py
|
||||
from typing import Any, Literal, Mapping, Optional, overload
|
||||
|
||||
from azure.ai.inference._model_base import rest_discriminator, rest_field
|
||||
from azure.ai.inference.models import ChatRequestMessage
|
||||
|
||||
|
||||
class DeveloperMessage(ChatRequestMessage, discriminator="developer"):
|
||||
|
||||
role: Literal["developer"] = rest_discriminator(name="role") # type: ignore
|
||||
"""The chat role associated with this message, which is always 'developer' for developer messages.
|
||||
Required."""
|
||||
content: Optional[str] = rest_field()
|
||||
"""The content of the message."""
|
||||
|
||||
@overload
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
content: Optional[str] = None,
|
||||
): ...
|
||||
|
||||
@overload
|
||||
def __init__(self, mapping: Mapping[str, Any]):
|
||||
"""
|
||||
:param mapping: raw JSON to initialize the model.
|
||||
:type mapping: Mapping[str, Any]
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, *args: Any, **kwargs: Any
|
||||
) -> None: # pylint: disable=useless-super-delegation
|
||||
super().__init__(*args, role="developer", **kwargs)
|
@ -28,6 +28,8 @@ class ConfigModel(BaseModel):
|
||||
"当主人给你图片作为问题,并且你确实可以处理图片时,你必须以猫娘的说话方式进行回答,"
|
||||
"当主人想要你回复一些有关 LaTeX 公式的时候,你切记一定不可以在公式中包含非 ASCII 字符。"
|
||||
)
|
||||
marshoai_sysasuser_prompt: str = "好的喵~"
|
||||
marshoai_enable_sysasuser_prompt: bool = False
|
||||
marshoai_additional_prompt: str = ""
|
||||
marshoai_poke_suffix: str = "揉了揉你的猫耳"
|
||||
marshoai_enable_richtext_parse: bool = True
|
||||
@ -146,6 +148,7 @@ if config.marshoai_use_yaml_config:
|
||||
|
||||
config = ConfigModel(**yaml_config)
|
||||
else:
|
||||
logger.info(
|
||||
"MarshoAI 支持新的 YAML 配置系统,若要使用,请将 MARSHOAI_USE_YAML_CONFIG 配置项设置为 true。"
|
||||
)
|
||||
# logger.info(
|
||||
# "MarshoAI 支持新的 YAML 配置系统,若要使用,请将 MARSHOAI_USE_YAML_CONFIG 配置项设置为 true。"
|
||||
# )
|
||||
pass
|
||||
|
@ -26,7 +26,14 @@ SUPPORT_IMAGE_MODELS: list = [
|
||||
"llama-3.2-11b-vision-instruct",
|
||||
"gemini-2.0-flash-exp",
|
||||
]
|
||||
NO_SYSPROMPT_MODELS: list = ["o1", "o1-preview", "o1-mini"]
|
||||
OPENAI_NEW_MODELS: list = [
|
||||
"o1",
|
||||
"o1-preview",
|
||||
"o1-mini",
|
||||
"o3",
|
||||
"o3-mini",
|
||||
"o3-mini-large",
|
||||
]
|
||||
INTRODUCTION: str = f"""MarshoAI-NoneBot by LiteyukiStudio
|
||||
你好喵~我是一只可爱的猫娘AI,名叫小棉~🐾!
|
||||
我的主页在这里哦~↓↓↓
|
||||
|
@ -257,7 +257,7 @@ async def marsho(
|
||||
model_name.lower()
|
||||
in SUPPORT_IMAGE_MODELS + config.marshoai_additional_image_models
|
||||
)
|
||||
is_reasoning_model = model_name.lower() in NO_SYSPROMPT_MODELS
|
||||
is_openai_new_model = model_name.lower() in OPENAI_NEW_MODELS
|
||||
usermsg = [] if is_support_image_model else ""
|
||||
for i in text: # type: ignore
|
||||
if i.type == "text":
|
||||
@ -285,14 +285,13 @@ async def marsho(
|
||||
backup_context, target.id, target.private
|
||||
) # 加载历史记录
|
||||
logger.info(f"已恢复会话 {target.id} 的上下文备份~")
|
||||
context_msg = context.build(target.id, target.private)
|
||||
if not is_reasoning_model:
|
||||
context_msg = [get_prompt()] + context_msg
|
||||
# o1等推理模型不支持系统提示词, 故不添加
|
||||
context_msg = get_prompt(model_name) + context.build(target.id, target.private)
|
||||
|
||||
tools_lists = tools.tools_list + list(
|
||||
map(lambda v: v.data(), get_function_calls().values())
|
||||
)
|
||||
logger.info(f"正在获取回答,模型:{model_name}")
|
||||
# logger.info(f"上下文:{context_msg}")
|
||||
response = await make_chat_openai(
|
||||
client=client,
|
||||
model_name=model_name,
|
||||
@ -304,7 +303,7 @@ async def marsho(
|
||||
# Sprint(choice)
|
||||
# 当tool_calls非空时,将finish_reason设置为TOOL_CALLS
|
||||
if choice.message.tool_calls != None and config.marshoai_fix_toolcalls:
|
||||
choice.finish_reason = CompletionsFinishReason.TOOL_CALLS
|
||||
choice.finish_reason = "tool_calls"
|
||||
logger.info(f"完成原因:{choice.finish_reason}")
|
||||
if choice.finish_reason == CompletionsFinishReason.STOPPED:
|
||||
# 当对话成功时,将dict的上下文添加到上下文类中
|
||||
@ -460,12 +459,8 @@ with contextlib.suppress(ImportError): # 优化先不做()
|
||||
response = await make_chat_openai(
|
||||
client=client,
|
||||
model_name=model_name,
|
||||
msg=[
|
||||
(
|
||||
get_prompt()
|
||||
if model_name.lower() not in NO_SYSPROMPT_MODELS
|
||||
else None
|
||||
),
|
||||
msg=get_prompt(model_name)
|
||||
+ [
|
||||
UserMessage(
|
||||
content=f"*{user_nickname}{config.marshoai_poke_suffix}"
|
||||
),
|
||||
|
@ -3,22 +3,23 @@ import json
|
||||
import mimetypes
|
||||
import re
|
||||
import uuid
|
||||
from typing import Any, Optional
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
import aiofiles # type: ignore
|
||||
import httpx
|
||||
import nonebot_plugin_localstore as store
|
||||
from azure.ai.inference.aio import ChatCompletionsClient
|
||||
from azure.ai.inference.models import SystemMessage
|
||||
from azure.ai.inference.models import AssistantMessage, SystemMessage, UserMessage
|
||||
from nonebot import get_driver
|
||||
from nonebot.log import logger
|
||||
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 openai.types.chat import ChatCompletion, ChatCompletionMessage
|
||||
from zhDateTime import DateTime
|
||||
|
||||
from ._types import DeveloperMessage
|
||||
from .config import config
|
||||
from .constants import *
|
||||
from .deal_latex import ConvertLatex
|
||||
@ -135,7 +136,7 @@ async def make_chat_openai(
|
||||
msg: list,
|
||||
model_name: str,
|
||||
tools: Optional[list] = None,
|
||||
):
|
||||
) -> ChatCompletion:
|
||||
"""
|
||||
使用 Openai SDK 调用ai获取回复
|
||||
|
||||
@ -252,7 +253,7 @@ async def refresh_nickname_json():
|
||||
logger.error("刷新 nickname_json 表错误:无法载入 nickname.json 文件")
|
||||
|
||||
|
||||
def get_prompt():
|
||||
def get_prompt(model: str) -> List[Dict[str, Any]]:
|
||||
"""获取系统提示词"""
|
||||
prompts = config.marshoai_additional_prompt
|
||||
if config.marshoai_enable_praises:
|
||||
@ -271,8 +272,19 @@ def get_prompt():
|
||||
)
|
||||
|
||||
marsho_prompt = config.marshoai_prompt
|
||||
spell = SystemMessage(content=marsho_prompt + prompts).as_dict()
|
||||
return spell
|
||||
sysprompt_content = marsho_prompt + prompts
|
||||
prompt_list: List[Dict[str, Any]] = []
|
||||
if not config.marshoai_enable_sysasuser_prompt:
|
||||
if model not in OPENAI_NEW_MODELS:
|
||||
prompt_list += [SystemMessage(content=sysprompt_content).as_dict()]
|
||||
else:
|
||||
prompt_list += [DeveloperMessage(content=sysprompt_content).as_dict()]
|
||||
else:
|
||||
prompt_list += [UserMessage(content=sysprompt_content).as_dict()]
|
||||
prompt_list += [
|
||||
AssistantMessage(content=config.marshoai_sysasuser_prompt).as_dict()
|
||||
]
|
||||
return prompt_list
|
||||
|
||||
|
||||
def suggest_solution(errinfo: str) -> str:
|
||||
|
Loading…
x
Reference in New Issue
Block a user