diff --git a/backend/apps/ai_model/model_factory.py b/backend/apps/ai_model/model_factory.py index 66c93997..6391501c 100644 --- a/backend/apps/ai_model/model_factory.py +++ b/backend/apps/ai_model/model_factory.py @@ -10,6 +10,7 @@ from sqlmodel import Session, select from apps.ai_model.openai.llm import BaseChatOpenAI from apps.system.models.system_model import AiModelDetail from common.core.db import engine +from common.utils.utils import prepare_model_arg # from langchain_community.llms import Tongyi, VLLM @@ -26,13 +27,19 @@ class LLMConfig(BaseModel): frozen = True def __hash__(self): + if hasattr(self, 'additional_params') and isinstance(self.additional_params, dict): + hashable_params = frozenset((k, tuple(v) if isinstance(v, (list, dict)) else v) + for k, v in self.additional_params.items()) + else: + hashable_params = None + return hash(( self.model_id, self.model_type, self.model_name, self.api_key, self.api_base_url, - frozenset(self.additional_params.items()) + hashable_params )) @@ -62,7 +69,6 @@ class OpenAILLM(BaseLLM): base_url=self.config.api_base_url, stream_usage=True, **self.config.additional_params, - extra_body={"enable_thinking": True}, ) def generate(self, prompt: str) -> str: @@ -116,7 +122,7 @@ def get_default_config() -> LLMConfig: if db_model.config: try: config_raw = json.loads(db_model.config) - additional_params = {item["key"]: item["val"] for item in config_raw if "key" in item and "val" in item} + additional_params = {item["key"]: prepare_model_arg(item.get('val')) for item in config_raw if "key" in item and "val" in item} except Exception: pass diff --git a/backend/apps/system/api/aimodel.py b/backend/apps/system/api/aimodel.py index 7c20f0d7..c60e1aa6 100644 --- a/backend/apps/system/api/aimodel.py +++ b/backend/apps/system/api/aimodel.py @@ -10,7 +10,7 @@ from sqlmodel import func, select, update from apps.system.models.system_model import AiModelDetail from common.core.deps import SessionDep, Trans from common.utils.time import get_timestamp -from common.utils.utils import SQLBotLogUtil +from common.utils.utils import SQLBotLogUtil, prepare_model_arg router = APIRouter(tags=["system/aimodel"], prefix="/system/aimodel") @@ -18,7 +18,7 @@ router = APIRouter(tags=["system/aimodel"], prefix="/system/aimodel") async def check_llm(info: AiModelCreator, trans: Trans): async def generate(): try: - additional_params = {item.key: item.val for item in info.config_list} + additional_params = {item.key: prepare_model_arg(item.val) for item in info.config_list if item.key and item.val} config = LLMConfig( model_type="openai", model_name=info.base_model, diff --git a/backend/common/utils/utils.py b/backend/common/utils/utils.py index a0281df5..9e14f652 100644 --- a/backend/common/utils/utils.py +++ b/backend/common/utils/utils.py @@ -1,6 +1,7 @@ import base64 import hashlib import inspect +import json import logging from datetime import datetime, timedelta, timezone from logging.handlers import RotatingFileHandler @@ -230,6 +231,13 @@ def prepare_for_orjson(data): return data - - +def prepare_model_arg(origin_arg: str): + if not isinstance(origin_arg, str): + return origin_arg + if not origin_arg.strip()[0] in {'{', '['}: + return origin_arg + try: + return json.loads(origin_arg) + except: + return origin_arg diff --git a/frontend/src/entity/supplier.ts b/frontend/src/entity/supplier.ts index ad1cb5b2..00e2e6ff 100644 --- a/frontend/src/entity/supplier.ts +++ b/frontend/src/entity/supplier.ts @@ -3,6 +3,7 @@ import icon_bdyzn_colorful from '@/assets/model/icon_bdyzn_colorful.png' import icon_deepseek_colorful from '@/assets/model/icon_deepseek_colorful.png' import icon_txy_colorful from '@/assets/model/icon_txy_colorful.png' import icon_xfhx_colorful from '@/assets/model/icon_xfhx_colorful.png' +import icon_gemini_colorful from '@/assets/model/icon_gemini_colorful.png' type ModelArg = { key: string; val?: string | number; type: string; range?: string } type ModelOption = { name: string; api_domain?: string; args?: ModelArg[] } @@ -24,7 +25,29 @@ export const supplierList: Array<{ model_config: { 0: { api_domain: 'https://dashscope.aliyuncs.com/compatible-mode/v1', - model_options: [{ name: 'qwen-plus' }], + common_args: [ + { key: 'temperature', val: 1.0, type: 'number', range: '[0, 2)' }, + { key: 'extra_body', val: '{"enable_thinking": true}', type: 'json' }, + ], + model_options: [ + { name: 'qwen-plus' }, + { name: 'qwen-plus-latest' }, + { name: 'qwen-max' }, + { name: 'qwen-max-latest' }, + { name: 'qwen-turbo' }, + { name: 'qwen-turbo-latest' }, + { name: 'qwq-plus' }, + { name: 'qwq-plus-latest' }, + { name: 'qwen-long' }, + { name: 'qwen-long-latest' }, + { name: 'qwen-omni-turbo' }, + { name: 'qwen-omni-turbo-realtime' }, + { name: 'qwen-omni-turbo-realtime-latest' }, + { name: 'qvq-max' }, + { name: 'qvq-max-latest' }, + { name: 'qvq-plus' }, + { name: 'qvq-plus-latest' }, + ], }, }, }, @@ -114,6 +137,24 @@ export const supplierList: Array<{ }, }, }, + { + id: 6, + name: 'Gemini', + icon: icon_gemini_colorful, + model_config: { + 0: { + api_domain: 'https://generativelanguage.googleapis.com/v1beta/openai/', + common_args: [{ key: 'temperature', val: 1.0, type: 'number', range: '[0, 2]' }], + model_options: [ + { name: 'gemini-2.5-pro' }, + { name: 'gemini-2.5-flash' }, + { name: 'gemini-2.5-flash-lite' }, + { name: 'gemini-2.0-flash' }, + { name: 'gemini-2.0-flash-lite' }, + ], + }, + }, + }, ] export const base_model_options = (supplier_id: number, model_type?: number) => { diff --git a/frontend/src/views/system/model/ModelForm.vue b/frontend/src/views/system/model/ModelForm.vue index 5b515d97..586dc945 100644 --- a/frontend/src/views/system/model/ModelForm.vue +++ b/frontend/src/views/system/model/ModelForm.vue @@ -374,7 +374,7 @@ defineExpose({ - +