diff --git a/astrbot/core/config/astrbot_config.py b/astrbot/core/config/astrbot_config.py index 23699c9b7..bc3fd97eb 100644 --- a/astrbot/core/config/astrbot_config.py +++ b/astrbot/core/config/astrbot_config.py @@ -54,8 +54,10 @@ class ModelConfig: max_tokens: int = 6000 temperature: float = 0.9 top_p: float = 1 - frequency_penalty: float = 0 - presence_penalty: float = 0 + + def __init__(self, **kwargs): + for key, value in kwargs.items(): + setattr(self, key, value) @dataclass class ImageGenerationModelConfig: @@ -122,7 +124,6 @@ class AstrBotConfig(): llm_settings: LLMSettings = field(default_factory=LLMSettings) content_safety: ContentSafetyConfig = field(default_factory=ContentSafetyConfig) t2i: bool = True - dump_history_interval: int = 10 admins_id: List[str] = field(default_factory=list) https_proxy: str = "" http_proxy: str = "" @@ -180,7 +181,6 @@ class AstrBotConfig(): self.llm_settings=LLMSettings(**data.get("llm_settings", {})) self.content_safety=ContentSafetyConfig(**data.get("content_safety", {})) self.t2i=data.get("t2i", True) - self.dump_history_interval=data.get("dump_history_interval", 10) self.admins_id=data.get("admins_id", []) self.https_proxy=data.get("https_proxy", "") self.http_proxy=data.get("http_proxy", "") diff --git a/astrbot/core/config/default.py b/astrbot/core/config/default.py index 6e8ac6052..007e98c45 100644 --- a/astrbot/core/config/default.py +++ b/astrbot/core/config/default.py @@ -1,6 +1,86 @@ +''' +这里定义了一些默认配置文件,请不要修改这个文件。如需修改配置,请在 `data/cmd_config.json` 中修改或者在管理面板中可视化修改。 +''' + VERSION = '3.4.0' DB_PATH = 'data/data_v2.db' +# LLM 提供商配置模板 +PROVIDER_CONFIG_TEMPLATE = { + "openai": { + "id": "default", + "name": "openai", + "enable": True, + "key": [], + "api_base": "", + "prompt_prefix": "", + "default_personality": "", + "model_config": { + "model": "gpt-4o", + "max_tokens": 6000, + "temperature": 0.9, + "top_p": 1, + }, + "image_generation_model_config": { + "enable": False, + "model": "dall-e-3", + "size": "1024x1024", + "style": "vivid", + "quality": "standard", + } + }, + "ollama": { + "id": "ollama_default", + "name": "ollama", + "enable": True, + "key": ["ollama"], # ollama 的 key 默认是 ollama + "api_base": "http://localhost:11434", + "prompt_prefix": "", + "default_personality": "", + "model_config": { + "model": "llama3.1-8b", + "temperature": 0.9, + "top_p": 1, + } + }, + "gemini": { + "id": "gemini_default", + "name": "gemini", + "enable": True, + "key": [], + "api_base": "https://generativelanguage.googleapis.com/v1beta/openai/", + "prompt_prefix": "", + "default_personality": "", + "model_config": { + "model": "gemini-1.5-flash", + } + }, + "deepseek": { + "id": "deepseek_default", + "name": "deepseek", + "enable": True, + "key": [], + "api_base": "https://api.deepseek.com/v1", + "prompt_prefix": "", + "default_personality": "", + "model_config": { + "model": "deepseek-chat", + } + }, + "zhipu": { + "id": "zhipu_default", + "name": "zhipu(glm)", + "enable": True, + "key": [], + "api_base": "https://open.bigmodel.cn/api/paas/v4/", + "prompt_prefix": "", + "default_personality": "", + "model_config": { + "model": "glm-4-flash", + } + }, +} + # 新版本配置文件,摈弃旧版本令人困惑的配置项 :D DEFAULT_CONFIG_VERSION_2 = { "config_version": 2, @@ -37,33 +117,10 @@ DEFAULT_CONFIG_VERSION_2 = { "count": 30, }, "reply_prefix": "", - "forward_threshold": 200, # 转发消息的阈值 + "forward_threshold": 200, # 转发消息的阈值 }, "llm": [ - { - "id": "default", - "name": "openai", - "enable": True, - "key": [], - "api_base": "", - "prompt_prefix": "", - "default_personality": "", - "model_config": { - "model": "gpt-4o", - "max_tokens": 6000, - "temperature": 0.9, - "top_p": 1, - "frequency_penalty": 0, - "presence_penalty": 0, - }, - "image_generation_model_config": { - "enable": True, - "model": "dall-e-3", - "size": "1024x1024", - "style": "vivid", - "quality": "standard", - } - }, + PROVIDER_CONFIG_TEMPLATE["openai"] ], "llm_settings": { "wake_prefix": "", @@ -78,7 +135,6 @@ DEFAULT_CONFIG_VERSION_2 = { }, "wake_prefix": ["/"], "t2i": True, - "dump_history_interval": 10, "admins_id": [], "https_proxy": "", "http_proxy": "", @@ -101,7 +157,7 @@ CONFIG_METADATA_2 = { "type": "list", "items": { "id": {"description": "ID", "type": "string", "hint": "提供商 ID 名,用于在多实例下方便管理和识别。自定义,ID 不能重复。"}, - "name": {"description": "适配器类型", "type": "string", "hint": "当前版本下,内置支持 `qq_official`(QQ 官方机器人), `aiocqhttp`(Onebot 适用) 适配器类型。", "options": ["qq_official", "aiocqhttp"]}, + "name": {"description": "适配器类型", "type": "string", "hint": "当前版本下,内置支持 `qq_official`(QQ 官方机器人), `aiocqhttp`(Onebot 适用) 适配器类型。", "options": ["qq_official", "aiocqhttp", "wechat"], "readonly": True}, "enable": {"description": "启用", "type": "bool", "hint": "是否启用该适配器。未启用的适配器对应的消息平台将不会接收到消息。"}, "appid": {"description": "appid", "type": "string", "hint": "必填项。QQ 官方机器人平台的 appid。如何获取请参考文档。"}, "secret": {"description": "secret", "type": "string", "hint": "必填项。QQ 官方机器人平台的 secret。如何获取请参考文档。"}, @@ -137,7 +193,7 @@ CONFIG_METADATA_2 = { "type": "list", "items": { "id": {"description": "ID", "type": "string", "hint": "提供商 ID 名,用于在多实例下方便管理和识别。自定义,ID 不能重复。"}, - "name": {"description": "模型提供商类型", "type": "string", "hint": "当前版本下,支持 `openai` 一个模型提供商。", "options": ["openai"]}, + "name": {"description": "模型提供商类型", "type": "string", "hint": "如需变更模型提供商,请点击上面的 + 新建一个。如果没有找到你想要接入的提供商,可以前往你的提供商的官网查看是否兼容 OpenAI API,如兼容,可以选择 `openai`。大多数提供商都是兼容的。", "options": list(PROVIDER_CONFIG_TEMPLATE.keys()), "obvious_hint": True, "readonly": True}, "enable": {"description": "启用", "type": "bool", "hint": "是否启用该模型。未启用的模型将不会被使用。"}, "key": {"description": "API Key", "type": "list", "items": {"type": "string"}, "hint": "API Key 列表。填写好后输入回车即可添加 API Key。支持多个 API Key。"}, "api_base": {"description": "API Base URL", "type": "string", "hint": "API Base URL 请在在模型提供商处获得。支持 Ollama 开放的 API 地址。如果您确认填写正确但是使用时出现了 404 异常,可以尝试在地址末尾加上 `/v1`。"}, @@ -151,8 +207,6 @@ CONFIG_METADATA_2 = { "max_tokens": {"description": "最大令牌数", "type": "int"}, "temperature": {"description": "温度", "type": "float"}, "top_p": {"description": "Top P值", "type": "float"}, - "frequency_penalty": {"description": "频率惩罚", "type": "float"}, - "presence_penalty": {"description": "存在惩罚", "type": "float"}, } }, "image_generation_model_config": { @@ -203,7 +257,6 @@ CONFIG_METADATA_2 = { }, "wake_prefix": {"description": "机器人唤醒前缀", "type": "list", "items": {"type": "string"}, "hint": "在不 @ 机器人的情况下,可以通过外加消息前缀来唤醒机器人。"}, "t2i": {"description": "文本转图像", "type": "bool", "hint": "启用后,超出一定长度的文本将会通过 AstrBot API 渲染成 Markdown 图片发送。可以缓解审核和消息过长刷屏的问题,并提高 Markdown 文本的可读性。"}, - "dump_history_interval": {"description": "历史记录保存间隔", "type": "int", "hint": "每隔多少分钟将 LLM 聊天的历史记录转储到数据库。"}, "admins_id": {"description": "管理员 ID", "type": "list", "items": {"type": "int"}, "hint": "管理员 ID 列表,管理员可以使用一些特权命令,如 `update`, `plugin` 等。ID 可以通过 `/myid` 指令获得。回车添加,可添加多个。"}, "https_proxy": {"description": "HTTPS 代理", "type": "string", "hint": "启用后,会以添加环境变量的方式设置代理。格式为 `http://ip:port`"}, "http_proxy": {"description": "HTTP 代理", "type": "string", "hint": "启用后,会以添加环境变量的方式设置代理。格式为 `http://ip:port`"}, @@ -221,7 +274,7 @@ CONFIG_METADATA_2 = { "pip_install_arg": {"description": "pip 安装参数", "type": "string", "hint": "安装插件依赖时,会使用 Python 的 pip 工具。这里可以填写额外的参数,如 `--break-system-package` 等。"}, "plugin_repo_mirror": {"description": "插件仓库镜像", "type": "string", "hint": "插件仓库的镜像地址,用于加速插件的下载。", "options": ["default", "https://ghp.ci/", "https://github-mirror.us.kg/"]}, } - + DEFAULT_VALUE_MAP = { "int": 0, "float": 0.0, @@ -230,4 +283,4 @@ DEFAULT_VALUE_MAP = { "text": "", "list": [], "object": {}, -} \ No newline at end of file +} diff --git a/astrbot/dashboard/routes/config.py b/astrbot/dashboard/routes/config.py index b8c245b68..63cd0c17a 100644 --- a/astrbot/dashboard/routes/config.py +++ b/astrbot/dashboard/routes/config.py @@ -1,7 +1,7 @@ import os, json from .route import Route, Response from quart import Quart, request -from core.config.default import CONFIG_METADATA_2, DEFAULT_VALUE_MAP +from core.config.default import CONFIG_METADATA_2, DEFAULT_VALUE_MAP, PROVIDER_CONFIG_TEMPLATE from core.config.astrbot_config import AstrBotConfig from core.plugin.config import update_config from core.core_lifecycle import AstrBotCoreLifecycle @@ -130,6 +130,7 @@ class ConfigRoute(Route): return { "metadata": CONFIG_METADATA_2, "config": config, + "provider_config_tmpl": PROVIDER_CONFIG_TEMPLATE } async def _get_extension_config(self, namespace: str): diff --git a/packages/astrbot_plugin_openai/main.py b/packages/astrbot_plugin_openai/main.py index 5a36b9777..875b8ee67 100644 --- a/packages/astrbot_plugin_openai/main.py +++ b/packages/astrbot_plugin_openai/main.py @@ -1,5 +1,5 @@ import json, traceback -from typing import List +from typing import List, Dict from astrbot.api import Context, AstrMessageEvent, MessageEventResult from .openai_adapter import ProviderOpenAIOfficial from .commands import OpenAIAdapterCommand @@ -11,31 +11,38 @@ from openai.types.chat.chat_completion_message_tool_call import Function from astrbot.api import command_parser from .web_searcher import search_from_bing, fetch_website_content from astrbot.core.utils.metrics import Metric +from astrbot.core.config.astrbot_config import LLMConfig class Main: def __init__(self, context: Context) -> None: + supported_provider_names = ["openai", "ollama", "gemini", "deepseek", "zhipu"] + self.context = context self.provider_insts: List[ProviderOpenAIOfficial] = [] + self.provider_llm_configs: List[LLMConfig] = [] self.provider = None + self.provider_config = None llms_config = self.context.get_config().llm loaded = False for llm in llms_config: if llm.enable: - if llm.name == "openai": + if llm.name in supported_provider_names: if not llm.key or not llm.enable: logger.warning("没有开启 LLM Provider 或 API Key 未填写。") continue self.provider_insts.append(ProviderOpenAIOfficial(llm, self.context.get_db())) + self.provider_llm_configs.append(llm) loaded = True - logger.info(f"已启用 LLM Provider(OpenAI API): {llm.id}({llm.name})。") + logger.info(f"已启用 LLM Provider(OpenAI API 适配器): {llm.id}({llm.name})。") if loaded: self.command_handler = OpenAIAdapterCommand(self.context) self.command_handler.set_provider(self.provider_insts[0]) self.context.register_listener(PLUGIN_NAME, "openai_adapter_chat", self.chat, "OpenAI Adapter LLM 调用监听器", after_commands=True) self.provider = self.command_handler.provider + self.provider_config = self.provider_llm_configs[0] self.context.register_commands(PLUGIN_NAME, "provider", "查看当前 LLM Provider", 10, self.provider_info) self.context.register_commands(PLUGIN_NAME, "websearch", "启用/关闭网页搜索", 10, self.web_search) @@ -88,6 +95,7 @@ class Main: if idx >= len(self.provider_insts): event.set_result(MessageEventResult().message("无效的序号。")) self.provider = self.provider_insts[idx] + self.provider_config = self.provider_llm_configs[idx] self.command_handler.set_provider(self.provider) event.set_result(MessageEventResult().message(f"已经成功切换到 LLM 接入源 {self.provider.llm_config.id}。")) return @@ -114,6 +122,10 @@ class Main: if not event.is_wake_up(): return + # prompt 前缀 + if self.provider_config.prompt_prefix: + event.message_str = self.provider_config.prompt_prefix + event.message_str + image_url = None for comp in event.message_obj.message: if isinstance(comp, Image):