Merge pull request #730 from RockChinQ/feat/customized-model

Feat: 允许自定义模型信息
This commit is contained in:
Junyan Qin 2024-03-16 22:19:27 +08:00 committed by GitHub
commit 9c32420a95
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 178 additions and 179 deletions

View File

@ -0,0 +1,47 @@
from __future__ import annotations
from .. import migration
@migration.migration_class("openai-config-migration", 2)
class OpenAIConfigMigration(migration.Migration):
"""OpenAI配置迁移
"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移
"""
return 'openai-config' in self.ap.provider_cfg.data
async def run(self):
"""执行迁移
"""
old_openai_config = self.ap.provider_cfg.data['openai-config'].copy()
if 'keys' not in self.ap.provider_cfg.data:
self.ap.provider_cfg.data['keys'] = {}
if 'openai' not in self.ap.provider_cfg.data['keys']:
self.ap.provider_cfg.data['keys']['openai'] = []
self.ap.provider_cfg.data['keys']['openai'] = old_openai_config['api-keys']
self.ap.provider_cfg.data['model'] = old_openai_config['chat-completions-params']['model']
del old_openai_config['chat-completions-params']['model']
if 'requester' not in self.ap.provider_cfg.data:
self.ap.provider_cfg.data['requester'] = {}
if 'openai-chat-completions' not in self.ap.provider_cfg.data['requester']:
self.ap.provider_cfg.data['requester']['openai-chat-completions'] = {}
self.ap.provider_cfg.data['requester']['openai-chat-completions'] = {
'base-url': old_openai_config['base_url'],
'args': old_openai_config['chat-completions-params'],
'timeout': old_openai_config['request-timeout'],
}
del self.ap.provider_cfg.data['openai-config']
await self.ap.provider_cfg.dump_config()

View File

@ -53,6 +53,8 @@ class Application:
plugin_setting_meta: config_mgr.ConfigManager = None
llm_models_meta: config_mgr.ConfigManager = None
# =========================
ctr_mgr: center_mgr.V2CenterAPI = None

View File

@ -18,7 +18,6 @@ class LoadConfigStage(stage.BootingStage):
ap.provider_cfg = await config.load_json_config("data/config/provider.json", "templates/provider.json")
ap.system_cfg = await config.load_json_config("data/config/system.json", "templates/system.json")
ap.plugin_setting_meta = await config.load_json_config("plugins/plugins.json", "templates/plugin-settings.json")
await ap.plugin_setting_meta.dump_config()
@ -27,3 +26,6 @@ class LoadConfigStage(stage.BootingStage):
ap.adapter_qq_botpy_meta = await config.load_json_config("data/metadata/adapter-qq-botpy.json", "templates/metadata/adapter-qq-botpy.json")
await ap.adapter_qq_botpy_meta.dump_config()
ap.llm_models_meta = await config.load_json_config("data/metadata/llm-models.json", "templates/metadata/llm-models.json")
await ap.llm_models_meta.dump_config()

View File

@ -4,7 +4,7 @@ import importlib
from .. import stage, app
from ...config import migration
from ...config.migrations import m1_sensitive_word_migration
from ...config.migrations import m1_sensitive_word_migration, m2_openai_config_migration
@stage.stage_class("MigrationStage")

View File

@ -17,8 +17,8 @@ from ... import entities as llm_entities
from ...tools import entities as tools_entities
@api.requester_class("openai-chat-completion")
class OpenAIChatCompletion(api.LLMAPIRequester):
@api.requester_class("openai-chat-completions")
class OpenAIChatCompletions(api.LLMAPIRequester):
"""OpenAI ChatCompletion API 请求器"""
client: openai.AsyncClient
@ -26,8 +26,8 @@ class OpenAIChatCompletion(api.LLMAPIRequester):
async def initialize(self):
self.client = openai.AsyncClient(
api_key="",
base_url=self.ap.provider_cfg.data['openai-config']['base_url'],
timeout=self.ap.provider_cfg.data['openai-config']['request-timeout'],
base_url=self.ap.provider_cfg.data['requester']['openai-chat-completions']['base-url'],
timeout=self.ap.provider_cfg.data['requester']['openai-chat-completions']['timeout'],
http_client=httpx.AsyncClient(
proxies=self.ap.proxy_mgr.get_forward_proxies()
)
@ -58,7 +58,7 @@ class OpenAIChatCompletion(api.LLMAPIRequester):
) -> llm_entities.Message:
self.client.api_key = use_model.token_mgr.get_token()
args = self.ap.provider_cfg.data['openai-config']['chat-completions-params'].copy()
args = self.ap.provider_cfg.data['requester']['openai-chat-completions']['args'].copy()
args["model"] = use_model.name if use_model.model_name is None else use_model.model_name
if use_model.tool_call_supported:

View File

@ -1,11 +1,15 @@
from __future__ import annotations
import aiohttp
from . import entities
from ...core import app
from . import token
from . import token, api
from .apis import chatcmpl
FETCH_MODEL_LIST_URL = "https://api.qchatgpt.rockchin.top/api/v2/fetch/model_list"
class ModelManager:
"""模型管理器"""
@ -13,10 +17,16 @@ class ModelManager:
ap: app.Application
model_list: list[entities.LLMModelInfo]
requesters: dict[str, api.LLMAPIRequester]
token_mgrs: dict[str, token.TokenManager]
def __init__(self, ap: app.Application):
self.ap = ap
self.model_list = []
self.requesters = {}
self.token_mgrs = {}
async def get_model_by_name(self, name: str) -> entities.LLMModelInfo:
"""通过名称获取模型
@ -24,171 +34,72 @@ class ModelManager:
for model in self.model_list:
if model.name == name:
return model
raise ValueError(f"不支持模型: {name} , 请检查配置文件")
raise ValueError(f"无法确定模型 {name} 的信息,请在元数据中配置")
async def initialize(self):
openai_chat_completion = chatcmpl.OpenAIChatCompletion(self.ap)
await openai_chat_completion.initialize()
openai_token_mgr = token.TokenManager("openai", list(self.ap.provider_cfg.data['openai-config']['api-keys']))
# 初始化token_mgr, requester
for k, v in self.ap.provider_cfg.data['keys'].items():
self.token_mgrs[k] = token.TokenManager(k, v)
model_list = [
entities.LLMModelInfo(
name="gpt-3.5-turbo",
token_mgr=openai_token_mgr,
requester=openai_chat_completion,
tool_call_supported=True,
),
entities.LLMModelInfo(
name="gpt-3.5-turbo-1106",
token_mgr=openai_token_mgr,
requester=openai_chat_completion,
tool_call_supported=True,
),
entities.LLMModelInfo(
name="gpt-3.5-turbo-16k",
token_mgr=openai_token_mgr,
requester=openai_chat_completion,
tool_call_supported=True,
),
entities.LLMModelInfo(
name="gpt-3.5-turbo-0613",
token_mgr=openai_token_mgr,
requester=openai_chat_completion,
tool_call_supported=True,
),
entities.LLMModelInfo(
name="gpt-3.5-turbo-16k-0613",
token_mgr=openai_token_mgr,
requester=openai_chat_completion,
tool_call_supported=True,
),
entities.LLMModelInfo(
name="gpt-3.5-turbo-0301",
token_mgr=openai_token_mgr,
requester=openai_chat_completion,
tool_call_supported=True,
)
]
for api_cls in api.preregistered_requesters:
api_inst = api_cls(self.ap)
await api_inst.initialize()
self.requesters[api_inst.name] = api_inst
self.model_list.extend(model_list)
# 尝试从api获取最新的模型信息
try:
async with aiohttp.ClientSession() as session:
async with session.request(
method="GET",
url=FETCH_MODEL_LIST_URL,
) as resp:
model_list = (await resp.json())['data']['list']
gpt4_model_list = [
entities.LLMModelInfo(
name="gpt-4-0125-preview",
token_mgr=openai_token_mgr,
requester=openai_chat_completion,
tool_call_supported=True,
),
entities.LLMModelInfo(
name="gpt-4-turbo-preview",
token_mgr=openai_token_mgr,
requester=openai_chat_completion,
tool_call_supported=True,
),
entities.LLMModelInfo(
name="gpt-4-1106-preview",
token_mgr=openai_token_mgr,
requester=openai_chat_completion,
tool_call_supported=True,
),
entities.LLMModelInfo(
name="gpt-4-vision-preview",
token_mgr=openai_token_mgr,
requester=openai_chat_completion,
tool_call_supported=True,
),
entities.LLMModelInfo(
name="gpt-4",
token_mgr=openai_token_mgr,
requester=openai_chat_completion,
tool_call_supported=True,
),
entities.LLMModelInfo(
name="gpt-4-0613",
token_mgr=openai_token_mgr,
requester=openai_chat_completion,
tool_call_supported=True,
),
entities.LLMModelInfo(
name="gpt-4-32k",
token_mgr=openai_token_mgr,
requester=openai_chat_completion,
tool_call_supported=True,
),
entities.LLMModelInfo(
name="gpt-4-32k-0613",
token_mgr=openai_token_mgr,
requester=openai_chat_completion,
tool_call_supported=True,
)
]
for model in model_list:
self.model_list.extend(gpt4_model_list)
for index, local_model in enumerate(self.ap.llm_models_meta.data['list']):
if model['name'] == local_model['name']:
self.ap.llm_models_meta.data['list'][index] = model
break
else:
self.ap.llm_models_meta.data['list'].append(model)
one_api_model_list = [
entities.LLMModelInfo(
name="OneAPI/SparkDesk",
model_name='SparkDesk',
token_mgr=openai_token_mgr,
requester=openai_chat_completion,
tool_call_supported=False,
),
entities.LLMModelInfo(
name="OneAPI/chatglm_pro",
model_name='chatglm_pro',
token_mgr=openai_token_mgr,
requester=openai_chat_completion,
tool_call_supported=False,
),
entities.LLMModelInfo(
name="OneAPI/chatglm_std",
model_name='chatglm_std',
token_mgr=openai_token_mgr,
requester=openai_chat_completion,
tool_call_supported=False,
),
entities.LLMModelInfo(
name="OneAPI/chatglm_lite",
model_name='chatglm_lite',
token_mgr=openai_token_mgr,
requester=openai_chat_completion,
tool_call_supported=False,
),
entities.LLMModelInfo(
name="OneAPI/qwen-v1",
model_name='qwen-v1',
token_mgr=openai_token_mgr,
requester=openai_chat_completion,
tool_call_supported=False,
),
entities.LLMModelInfo(
name="OneAPI/qwen-plus-v1",
model_name='qwen-plus-v1',
token_mgr=openai_token_mgr,
requester=openai_chat_completion,
tool_call_supported=False,
),
entities.LLMModelInfo(
name="OneAPI/ERNIE-Bot",
model_name='ERNIE-Bot',
token_mgr=openai_token_mgr,
requester=openai_chat_completion,
tool_call_supported=False,
),
entities.LLMModelInfo(
name="OneAPI/ERNIE-Bot-turbo",
model_name='ERNIE-Bot-turbo',
token_mgr=openai_token_mgr,
requester=openai_chat_completion,
tool_call_supported=False,
),
entities.LLMModelInfo(
name="OneAPI/gemini-pro",
model_name='gemini-pro',
token_mgr=openai_token_mgr,
requester=openai_chat_completion,
tool_call_supported=False,
),
]
await self.ap.llm_models_meta.dump_config()
self.model_list.extend(one_api_model_list)
except Exception as e:
self.ap.logger.debug(f'获取最新模型列表失败: {e}')
default_model_info: entities.LLMModelInfo = None
for model in self.ap.llm_models_meta.data['list']:
if model['name'] == 'default':
default_model_info = entities.LLMModelInfo(
name=model['name'],
model_name=None,
token_mgr=self.token_mgrs[model['token_mgr']],
requester=self.requesters[model['requester']],
tool_call_supported=model['tool_call_supported']
)
break
for model in self.ap.llm_models_meta.data['list']:
try:
model_name = model.get('model_name', default_model_info.model_name)
token_mgr = self.token_mgrs[model['token_mgr']] if 'token_mgr' in model else default_model_info.token_mgr
requester = self.requesters[model['requester']] if 'requester' in model else default_model_info.requester
tool_call_supported = model.get('tool_call_supported', default_model_info.tool_call_supported)
model_info = entities.LLMModelInfo(
name=model['name'],
model_name=model_name,
token_mgr=token_mgr,
requester=requester,
tool_call_supported=tool_call_supported
)
self.model_list.append(model_info)
except Exception as e:
self.ap.logger.error(f"初始化模型 {model['name']} 失败: {e} ,请检查配置文件")

View File

@ -50,7 +50,7 @@ class SessionManager:
conversation = core_entities.Conversation(
prompt=await self.ap.prompt_mgr.get_prompt(session.use_prompt_name),
messages=[],
use_model=await self.ap.model_mgr.get_model_by_name(self.ap.provider_cfg.data['openai-config']['chat-completions-params']['model']),
use_model=await self.ap.model_mgr.get_model_by_name(self.ap.provider_cfg.data['model']),
use_funcs=await self.ap.tool_mgr.get_all_functions(),
)
session.conversations.append(conversation)

View File

@ -0,0 +1,34 @@
{
"list": [
{
"name": "default",
"requester": "openai-chat-completions",
"token_mgr": "openai",
"tool_call_supported": false
},
{
"name": "gpt-3.5-turbo",
"tool_call_supported": true
},
{
"name": "gpt-4",
"tool_call_supported": true
},
{
"name": "gpt-4-turbo-preview",
"tool_call_supported": true
},
{
"name": "gpt-4-32k",
"tool_call_supported": true
},
{
"model_name": "SparkDesk",
"name": "OneAPI/SparkDesk"
},
{
"model_name": "gemini-pro",
"name": "OneAPI/gemini-pro"
}
]
}

View File

@ -1,17 +1,20 @@
{
"enable-chat": true,
"openai-config": {
"api-keys": [
"keys": {
"openai": [
"sk-1234567890"
],
"base_url": "https://api.openai.com/v1",
"chat-completions-params": {
"model": "gpt-3.5-turbo"
},
"request-timeout": 120
]
},
"requester": {
"openai-chat-completions": {
"base-url": "https://api.openai.com/v1",
"args": {},
"timeout": 120
}
},
"model": "gpt-3.5-turbo",
"prompt-mode": "normal",
"prompt": {
"default": "如果用户之后想获取帮助,请你说”输入!help获取帮助“。"
"default": ""
}
}