feat: 添加多个可视化编辑schema

This commit is contained in:
Junyan Qin 2024-10-16 15:34:30 +08:00
parent 18cce189a4
commit a313ae5f97
No known key found for this signature in database
GPG Key ID: 8AC0BEFE1743A015
14 changed files with 547 additions and 13 deletions

View File

@ -30,11 +30,12 @@ class HTTPController:
while True:
await asyncio.sleep(1)
asyncio.create_task(self.quart_app.run_task(
task = asyncio.create_task(self.quart_app.run_task(
host=self.ap.system_cfg.data['http-api']['host'],
port=self.ap.system_cfg.data['http-api']['port'],
shutdown_trigger=shutdown_trigger_placeholder
))
self.ap.asyncio_tasks.append(task)
async def register_routes(self) -> None:

View File

@ -69,7 +69,11 @@ class APIGroup(metaclass=abc.ABCMeta):
**kwargs
) -> asyncio.Task:
"""执行请求"""
asyncio.create_task(self._do(method, path, data, params, headers, **kwargs))
task = asyncio.create_task(self._do(method, path, data, params, headers, **kwargs))
self.ap.asyncio_tasks.append(task)
return task
def gen_rid(
self

View File

@ -125,9 +125,11 @@ class Application:
import signal
def signal_handler(sig, frame):
for task in tasks:
for task in self.asyncio_tasks:
task.cancel()
self.logger.info("程序退出.")
# 结束当前事件循环
self.event_loop.stop()
exit(0)
signal.signal(signal.SIGINT, signal_handler)
@ -138,4 +140,3 @@ class Application:
except Exception as e:
self.logger.error(f"应用运行致命异常: {e}")
self.logger.debug(f"Traceback: {traceback.format_exc()}")

View File

@ -0,0 +1,22 @@
from __future__ import annotations
from .. import migration
@migration.migration_class("force-delay-config", 14)
class ForceDelayConfigMigration(migration.Migration):
"""迁移"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移"""
return type(self.ap.platform_cfg.data['force-delay']) == list
async def run(self):
"""执行迁移"""
self.ap.platform_cfg.data['force-delay'] = {
"min": self.ap.platform_cfg.data['force-delay'][0],
"max": self.ap.platform_cfg.data['force-delay'][1]
}
await self.ap.platform_cfg.dump_config()

View File

@ -27,7 +27,8 @@ class LoadConfigStage(stage.BootingStage):
ap.settings_mgr.register_manager(
name="command.json",
description="命令配置",
manager=ap.command_cfg
manager=ap.command_cfg,
schema=schema.CONFIG_COMMAND_SCHEMA
)
ap.settings_mgr.register_manager(
@ -40,13 +41,15 @@ class LoadConfigStage(stage.BootingStage):
ap.settings_mgr.register_manager(
name="platform.json",
description="消息平台配置",
manager=ap.platform_cfg
manager=ap.platform_cfg,
schema=schema.CONFIG_PLATFORM_SCHEMA
)
ap.settings_mgr.register_manager(
name="provider.json",
description="大模型能力配置",
manager=ap.provider_cfg
manager=ap.provider_cfg,
schema=schema.CONFIG_PROVIDER_SCHEMA
)
ap.settings_mgr.register_manager(

View File

@ -6,7 +6,7 @@ from .. import stage, app
from .. import migration
from ..migrations import m001_sensitive_word_migration, m002_openai_config_migration, m003_anthropic_requester_cfg_completion, m004_moonshot_cfg_completion
from ..migrations import m005_deepseek_cfg_completion, m006_vision_config, m007_qcg_center_url, m008_ad_fixwin_config_migrate, m009_msg_truncator_cfg
from ..migrations import m010_ollama_requester_config, m011_command_prefix_config, m012_runner_config, m013_http_api_config
from ..migrations import m010_ollama_requester_config, m011_command_prefix_config, m012_runner_config, m013_http_api_config, m014_force_delay_config
@stage.stage_class("MigrationStage")

View File

@ -60,7 +60,9 @@ class Controller:
# 通知其他协程,有新的请求可以处理了
self.ap.query_pool.condition.notify_all()
asyncio.create_task(_process_query(selected_query))
task = asyncio.create_task(_process_query(selected_query))
self.ap.asyncio_tasks.append(task)
except Exception as e:
# traceback.print_exc()
self.ap.logger.error(f"控制器循环出错: {e}")

View File

@ -19,7 +19,10 @@ class SendResponseBackStage(stage.PipelineStage):
async def process(self, query: core_entities.Query, stage_inst_name: str) -> entities.StageProcessResult:
"""处理
"""
random_delay = random.uniform(*self.ap.platform_cfg.data['force-delay'])
random_range = (self.ap.platform_cfg.data['force-delay']['min'], self.ap.platform_cfg.data['force-delay']['max'])
random_delay = random.uniform(*random_range)
self.ap.logger.debug(
"根据规则强制延迟回复: %s s",

View File

@ -184,7 +184,8 @@ class PlatformManager:
tasks.append(exception_wrapper(adapter))
for task in tasks:
asyncio.create_task(task)
async_task = asyncio.create_task(task)
self.ap.asyncio_tasks.append(async_task)
except Exception as e:
self.ap.logger.error('平台适配器运行出错: ' + str(e))

View File

@ -8,4 +8,7 @@ def load_schema(schema_path: str) -> dict:
CONFIG_SYSTEM_SCHEMA = load_schema("templates/schema/system.json")
CONFIG_PIPELINE_SCHEMA = load_schema("templates/schema/pipeline.json")
CONFIG_PIPELINE_SCHEMA = load_schema("templates/schema/pipeline.json")
CONFIG_COMMAND_SCHEMA = load_schema("templates/schema/command.json")
CONFIG_PLATFORM_SCHEMA = load_schema("templates/schema/platform.json")
CONFIG_PROVIDER_SCHEMA = load_schema("templates/schema/provider.json")

View File

@ -37,7 +37,10 @@
"track-function-calls": true,
"quote-origin": false,
"at-sender": false,
"force-delay": [0, 0],
"force-delay": {
"min": 0,
"max": 0
},
"long-text-process": {
"threshold": 256,
"strategy": "forward",

View File

@ -0,0 +1,39 @@
{
"type": "object",
"layout": "expansion-panels",
"properties": {
"command-prefix": {
"type": "array",
"title": "命令前缀",
"description": "以数组形式设置,程序将前缀符合设置的消息视为命令(群内需要符合群响应规则)",
"items": {
"type": "string"
}
},
"privilege": {
"type": "object",
"title": "权限管理",
"layout": {
"props": {
"title": "权限管理"
}
},
"description": "设置每个命令的权限配置。普通用户权限级别为 1管理员system.json中设置的权限级别为 2在这里设置每个命令的最低权限级别若设置为1则用户和管理员均可用若为2则仅管理员可用设置子命令时以点号间隔如\"plugin.on\"",
"properties": {
"placeholder": {
"type": "integer",
"minimum": 1,
"maximum": 2,
"const": 1
}
},
"patternProperties": {
"^[a-zA-Z0-9_.]+$": {
"type": "integer",
"minimum": 1,
"maximum": 2
}
}
}
}
}

View File

@ -0,0 +1,256 @@
{
"type": "object",
"layout": "expansion-panels",
"properties": {
"platform-adapters": {
"type": "array",
"title": "消息平台适配器",
"items": {
"type": "object",
"oneOf": [
{
"title": "YiriMirai 适配器",
"description": "用于接入 Mirai",
"properties": {
"adapter": {
"type": "string",
"const": "yiri-mirai"
},
"enable": {
"type": "boolean",
"default": false,
"description": "是否启用此适配器",
"layout": {
"comp": "switch",
"props": {
"color": "primary"
}
}
},
"host": {
"type": "string",
"default": "127.0.0.1"
},
"port": {
"type": "integer",
"default": 8080
},
"verifyKey": {
"type": "string",
"default": "yirimirai"
},
"qq": {
"type": "integer",
"default": 123456789
}
}
},
{
"title": "Nakuru 适配器",
"description": "用于接入 go-cqhttp",
"properties": {
"adapter": {
"type": "string",
"const": "nakuru"
},
"enable": {
"type": "boolean",
"default": false,
"description": "是否启用此适配器",
"layout": {
"comp": "switch",
"props": {
"color": "primary"
}
}
},
"host": {
"type": "string",
"default": "127.0.0.1"
},
"ws_port": {
"type": "integer",
"default": 8080
},
"http_port": {
"type": "integer",
"default": 5700
},
"token": {
"type": "string",
"default": ""
}
}
},
{
"title": "aiocqhttp 适配器",
"description": "用于接入 Lagrange 等兼容 OneBot v11 协议的机器人框架仅支持反向ws",
"properties": {
"adapter": {
"type": "string",
"const": "aiocqhttp"
},
"enable": {
"type": "boolean",
"default": false,
"description": "是否启用此适配器",
"layout": {
"comp": "switch",
"props": {
"color": "primary"
}
}
},
"host": {
"type": "string",
"default": "0.0.0.0",
"description": "监听的 IP 地址,一般就保持 0.0.0.0 就可以了。使用 aiocqhttp 时QChatGPT 作为服务端被动等待框架连接,请在 Lagrange 等框架中设置被动 ws 地址或者反向 ws 地址(具体视框架而定)为 QChatGPT 监听的地址,且路径为/ws例如ws://127.0.0.1:8080/ws"
},
"port": {
"type": "integer",
"default": 8080,
"description": "设置监听的端口默认8080需在 Lagrange 等框架中设置为与此处一致的端口"
},
"access-token": {
"type": "string",
"default": "",
"description": "设置访问密钥,与 Lagrange 等框架中设置的保持一致"
}
}
},
{
"title": "qq-botpy 适配器",
"description": "用于接入 QQ 官方机器人 API",
"properties": {
"adapter": {
"type": "string",
"const": "qq-botpy"
},
"enable": {
"type": "boolean",
"default": false,
"description": "是否启用此适配器",
"layout": {
"comp": "switch",
"props": {
"color": "primary"
}
}
},
"appid": {
"type": "string",
"default": "",
"description": "申请到的QQ官方机器人的appid"
},
"secret": {
"type": "string",
"default": "",
"description": "申请到的QQ官方机器人的secret"
},
"intents": {
"type": "array",
"description": "控制监听的事件类型需要填写才能接收到对应消息目前支持的事件类型有public_guild_messagesQQ 频道消息、direct_messageQQ 频道私聊消息、public_messagesQQ 群 和 列表私聊消息)",
"default": [
"public_guild_messages",
"direct_message",
"public_messages"
]
}
}
}
]
}
},
"track-function-calls": {
"type": "boolean",
"default": true,
"layout": {
"comp": "switch",
"props": {
"color": "primary"
}
},
"title": "跟踪内容函数调用",
"description": "开启之后,在对话中调用的内容函数记录也会发给用户,关闭后(false)仅会发给用户最终结果"
},
"quote-origin": {
"type": "boolean",
"default": false,
"layout": {
"comp": "switch",
"props": {
"color": "primary"
}
},
"title": "引用原消息",
"description": "在群内回复时是否引用原消息"
},
"at-sender": {
"type": "boolean",
"default": false,
"layout": {
"comp": "switch",
"props": {
"color": "primary"
}
},
"title": "是否 at 原用户",
"description": "在群内回复时是否@发送者"
},
"force-delay": {
"type": "object",
"default": {
"min": 0,
"max": 0
},
"title": "强制消息延迟范围",
"description": "在将响应内容发回给用户前的强制消息随机延迟时间范围,以防风控,单位是秒",
"properties": {
"min": {
"type": "integer",
"default": 0,
"description": "最小值,单位是秒"
},
"max": {
"type": "integer",
"default": 0,
"description": "最大值,单位是秒"
}
}
},
"long-text-process": {
"type": "object",
"title": "长消息处理策略",
"properties": {
"threshold": {
"type": "integer",
"default": 256,
"title": "长消息处理阈值",
"description": "当消息长度超过此阈值时,将启用长消息处理策略"
},
"strategy": {
"type": "string",
"default": "forward",
"title": "长消息处理策略",
"description": "长消息处理策略目前支持forward转发消息组件和image文字转图片。aiocqhttp 和 qq-botpy 不支持 forward 策略"
},
"font-path": {
"type": "string",
"description": "image的渲染字体。未设置时如果在windows下会尝试寻找系统的微软雅黑字体若找不到则转为forward策略。未设置时若不是windows系统则直接转为forward策略"
}
}
},
"hide-exception-info": {
"type": "boolean",
"default": true,
"layout": {
"comp": "switch",
"props": {
"color": "primary"
}
},
"title": "向用户隐藏AI接口的异常信息",
"description": "是否向用户隐藏AI的异常信息如果为true当请求AI接口出现异常时会返回一个错误的提示给用户。而把报错详情输出在控制台。"
}
}
}

View File

@ -0,0 +1,196 @@
{
"type": "object",
"layout": "expansion-panels",
"properties": {
"enable-chat": {
"type": "boolean",
"default": true,
"title": "启用聊天功能",
"description": "是否启用 AI 聊天功能"
},
"enable-vision": {
"type": "boolean",
"default": true,
"title": "启用视觉功能",
"description": "是否开启AI视觉功能。需要使用的模型同时支持视觉功能详情见元数据板块"
},
"keys": {
"type": "object",
"title": "模型接口密钥",
"description": "以字典的形式设置若干个密钥组,每个密钥组的键为密钥组名称,值为密钥列表。模型与密钥组的对应关系,请查看元数据板块",
"properties": {
"openai": {
"type": "array",
"title": "OpenAI API 密钥",
"description": "OpenAI API 密钥",
"items": {
"type": "string"
}
},
"anthropic": {
"type": "array",
"title": "Anthropic API 密钥",
"description": "Anthropic API 密钥",
"items": {
"type": "string"
}
},
"moonshot": {
"type": "array",
"title": "Moonshot API 密钥",
"description": "Moonshot API 密钥",
"items": {
"type": "string"
}
},
"deepseek": {
"type": "array",
"title": "DeepSeek API 密钥",
"description": "DeepSeek API 密钥",
"items": {
"type": "string"
}
}
}
},
"requester": {
"type": "object",
"title": "大模型请求器",
"description": "以字典的形式设置若干个请求器,每个请求器的键为请求器名称,值为请求器配置。模型与请求器的对应关系,请查看元数据板块。实现请求器的方式,请查看插件编写教程",
"properties": {
"openai-chat-completions": {
"type": "object",
"title": "OpenAI API 请求配置",
"description": "仅可编辑 URL 和 超时时间,额外请求参数不支持可视化编辑,请到编辑器编辑",
"properties": {
"base-url": {
"type": "string",
"title": "API URL"
},
"args": {
"type": "object"
},
"timeout": {
"type": "number",
"title": "API 请求超时时间",
"default": 120
}
}
},
"anthropic-messages": {
"type": "object",
"title": "Anthropic API 请求配置",
"description": "仅可编辑 URL 和 超时时间,额外请求参数不支持可视化编辑,请到编辑器编辑",
"properties": {
"base-url": {
"type": "string",
"title": "API URL"
},
"args": {
"type": "object"
},
"timeout": {
"type": "number",
"title": "API 请求超时时间",
"default": 120
}
}
},
"moonshot-chat-completions": {
"type": "object",
"title": "Moonshot API 请求配置",
"description": "仅可编辑 URL 和 超时时间,额外请求参数不支持可视化编辑,请到编辑器编辑",
"properties": {
"base-url": {
"type": "string",
"title": "API URL"
},
"args": {
"type": "object"
},
"timeout": {
"type": "number",
"title": "API 请求超时时间",
"default": 120
}
}
},
"deepseek-chat-completions": {
"type": "object",
"title": "DeepSeek API 请求配置",
"description": "仅可编辑 URL 和 超时时间,额外请求参数不支持可视化编辑,请到编辑器编辑",
"properties": {
"base-url": {
"type": "string",
"title": "API URL"
},
"args": {
"type": "object"
},
"timeout": {
"type": "number",
"title": "API 请求超时时间",
"default": 120
}
}
},
"ollama-chat": {
"type": "object",
"title": "Ollama API 请求配置",
"description": "仅可编辑 URL 和 超时时间,额外请求参数不支持可视化编辑,请到编辑器编辑",
"properties": {
"base-url": {
"type": "string",
"title": "API URL"
},
"args": {
"type": "object"
},
"timeout": {
"type": "number",
"title": "API 请求超时时间",
"default": 600
}
}
}
}
},
"model": {
"type": "string",
"title": "所使用的模型名称",
"description": "设置要使用的模型名称。通常来说直接填写模型名称即可,但如果要使用原生接口不是 ChatCompletion 但以 ChatCompletion 接口格式接入的模型,请在模型名称前方加一个 OneAPI/ 前缀以进行区分。 简单来说可以认为是:现阶段非 OpenAI 的模型接入都需要在模型名称前方加一个 OneAPI/ 前缀。\n\n例如\n\n1. 通过 OneAPI 等中转服务接入了 OpenAI 的 gpt-4 模型,由于 gpt-4 也是使用 ChatCompletion 接口格式进行请求,则可以直接填入 gpt-4\n2. 通过 OneAPI 等中转服务接入了 Google 的 gemini-pro 模型,由于 gemini-pro 原生接口格式并非 ChatCompletion因此需要填入 OneAPI/gemini-pro。\n具体支持的模型列表和各个模型对应的请求器和密钥组请查看元数据板块 llm-models.json "
},
"prompt-mode": {
"type": "string",
"title": "情景预设(人格)模式",
"description": "值为normal单预设模式和full-scenario完整历史对话模式normal模式时使用下方设置的情景预设也支持读取data/prompts目录下的文件内容作为单个 System Prompt文件名即为prompt的名称full-scenario模式时读取 data/scenario/ 下的完整历史对话作为情景预设",
"enum": ["normal", "full-scenario"],
"default": "normal"
},
"prompt": {
"type": "object",
"title": "情景预设(人格)",
"description": "设置情景预设人格。值为空字符串时将不使用情景预设人格。normal模式时使用下方设置的情景预设也支持读取data/prompts目录下的文件内容作为单个 System Prompt文件名即为prompt的名称full-scenario模式时读取 data/scenario/ 下的完整历史对话作为情景预设",
"properties": {
"default": {
"type": "string",
"title": "默认情景预设",
"description": "设置默认情景预设。值为空字符串时,将不使用情景预设(人格)"
}
},
"patternProperties": {
"^.*$": {
"type": "string",
"title": "情景预设",
"description": "设置情景预设。值为空字符串时,将不使用情景预设(人格)"
}
},
"required": ["default"]
},
"runner": {
"type": "string",
"title": "请求运行器",
"description": "设置请求运行器。值为local-agent时使用内置默认运行器支持插件扩展"
}
}
}