diff --git a/api/app/controllers/model_controller.py b/api/app/controllers/model_controller.py index 509f7cad..e5a1cec3 100644 --- a/api/app/controllers/model_controller.py +++ b/api/app/controllers/model_controller.py @@ -7,7 +7,7 @@ from app.core.error_codes import BizCode from app.core.exceptions import BusinessException from app.db import get_db from app.dependencies import get_current_user -from app.models.models_model import ModelProvider, ModelType +from app.models.models_model import ModelProvider, ModelType, LoadBalanceStrategy from app.models.user_model import User from app.repositories.model_repository import ModelConfigRepository from app.schemas import model_schema @@ -33,6 +33,10 @@ def get_model_types(): def get_model_providers(): return success(msg="获取模型提供商成功", data=list(ModelProvider)) +@router.get("/strategy", response_model=ApiResponse) +def get_model_strategies(): + return success(msg="获取模型策略成功", data=list(LoadBalanceStrategy)) + @router.get("", response_model=ApiResponse) def get_model_list( @@ -91,7 +95,7 @@ def get_model_list( @router.get("/new", response_model=ApiResponse) -def get_model_list( +def get_model_list_new( type: Optional[list[str]] = Query(None, description="模型类型筛选(支持多个,如 ?type=LLM 或 ?type=LLM,EMBEDDING)"), provider: Optional[model_schema.ModelProvider] = Query(None, description="提供商筛选(基于ModelConfig)"), is_active: Optional[bool] = Query(None, description="激活状态筛选"), @@ -198,6 +202,10 @@ def update_model_base( ): """更新基础模型""" + # 不允许更改type类型 + if data.type is not None or data.provider is not None: + raise BusinessException("不允许更改模型类型和供应商", BizCode.INVALID_PARAMETER) + result = ModelBaseService.update_model_base(db=db, model_base_id=model_base_id, data=data) return success(data=model_schema.ModelBase.model_validate(result), msg="基础模型更新成功") @@ -460,8 +468,8 @@ async def create_model_api_key_by_provider( created_keys = await ModelApiKeyService.create_api_key_by_provider(db=db, data=create_data) api_logger.info(f"API Key创建成功: 关联{len(created_keys)}个模型") - result_list = [model_schema.ModelApiKey.model_validate(key) for key in created_keys] - return success(data=result_list, msg=f"成功为 {len(created_keys)} 个模型创建API Key") + # result_list = [model_schema.ModelApiKey.model_validate(key) for key in created_keys] + return success(data=f"成功为 {len(created_keys)} 个模型创建API Key", msg=f"成功为 {len(created_keys)} 个模型创建API Key") except Exception as e: api_logger.error(f"创建API Key失败: {str(e)}") raise diff --git a/api/app/core/models/scripts/__init__.py b/api/app/core/models/scripts/__init__.py new file mode 100644 index 00000000..657b12fd --- /dev/null +++ b/api/app/core/models/scripts/__init__.py @@ -0,0 +1 @@ +"""模型配置脚本模块""" diff --git a/api/app/core/models/scripts/bedrock_models.yaml b/api/app/core/models/scripts/bedrock_models.yaml new file mode 100644 index 00000000..e561310d --- /dev/null +++ b/api/app/core/models/scripts/bedrock_models.yaml @@ -0,0 +1,174 @@ +provider: bedrock +enabled: true +models: +- name: ai21 + type: llm + provider: bedrock + description: AI21 Labs大语言模型,completion生成模式,256000上下文窗口 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + logo: bedrock +- name: amazon nova + type: llm + provider: bedrock + description: Amazon Nova大语言模型,支持智能体思考、工具调用、流式工具调用、视觉能力,300000上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - agent-thought + - tool-call + - stream-tool-call + - vision + logo: bedrock +- name: anthropic claude + type: llm + provider: bedrock + description: Anthropic Claude大语言模型,支持智能体思考、视觉能力、工具调用、流式工具调用、文档处理,200000上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - agent-thought + - vision + - tool-call + - stream-tool-call + - document + logo: bedrock +- name: cohere + type: llm + provider: bedrock + description: Cohere大语言模型,支持智能体思考、工具调用、流式工具调用,128000上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - agent-thought + - tool-call + - stream-tool-call + logo: bedrock +- name: deepseek + type: llm + provider: bedrock + description: DeepSeek大语言模型,支持智能体思考、视觉能力、工具调用、流式工具调用,32768上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - agent-thought + - vision + - tool-call + - stream-tool-call + logo: bedrock +- name: meta + type: llm + provider: bedrock + description: Meta Llama大语言模型,支持智能体思考、工具调用,128000上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - agent-thought + - tool-call + logo: bedrock +- name: mistral + type: llm + provider: bedrock + description: Mistral AI大语言模型,支持智能体思考、工具调用,32000上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - agent-thought + - tool-call + logo: bedrock +- name: openai + type: llm + provider: bedrock + description: OpenAI大语言模型,支持智能体思考、工具调用、流式工具调用,32768上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - agent-thought + - tool-call + - stream-tool-call + logo: bedrock +- name: qwen + type: llm + provider: bedrock + description: Qwen大语言模型,支持智能体思考、工具调用、流式工具调用,32768上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - agent-thought + - tool-call + - stream-tool-call + logo: bedrock +- name: amazon.rerank-v1:0 + type: rerank + provider: bedrock + description: amazon.rerank-v1:0重排序模型,5120上下文窗口 + is_deprecated: false + is_official: true + tags: + - 重排序模型 + logo: bedrock +- name: cohere.rerank-v3-5:0 + type: rerank + provider: bedrock + description: cohere.rerank-v3-5:0重排序模型,5120上下文窗口 + is_deprecated: false + is_official: true + tags: + - 重排序模型 + logo: bedrock +- name: amazon.nova-2-multimodal-embeddings-v1:0 + type: embedding + provider: bedrock + description: amazon.nova-2-multimodal-embeddings-v1:0文本嵌入模型,支持视觉能力,8192上下文窗口 + is_deprecated: false + is_official: true + tags: + - 文本嵌入模型 + - vision + logo: bedrock +- name: amazon.titan-embed-text-v1 + type: embedding + provider: bedrock + description: amazon.titan-embed-text-v1文本嵌入模型,8192上下文窗口 + is_deprecated: false + is_official: true + tags: + - 文本嵌入模型 + logo: bedrock +- name: amazon.titan-embed-text-v2:0 + type: embedding + provider: bedrock + description: amazon.titan-embed-text-v2:0文本嵌入模型,8192上下文窗口 + is_deprecated: false + is_official: true + tags: + - 文本嵌入模型 + logo: bedrock +- name: cohere.embed-english-v3 + type: embedding + provider: bedrock + description: Cohere Embed 3 English文本嵌入模型,512上下文窗口 + is_deprecated: false + is_official: true + tags: + - 文本嵌入模型 + logo: bedrock +- name: cohere.embed-multilingual-v3 + type: embedding + provider: bedrock + description: Cohere Embed 3 Multilingual文本嵌入模型,512上下文窗口 + is_deprecated: false + is_official: true + tags: + - 文本嵌入模型 + logo: bedrock diff --git a/api/app/core/models/scripts/dashscope_models.yaml b/api/app/core/models/scripts/dashscope_models.yaml new file mode 100644 index 00000000..24997728 --- /dev/null +++ b/api/app/core/models/scripts/dashscope_models.yaml @@ -0,0 +1,850 @@ +provider: dashscope +enabled: true +models: +- name: deepseek-r1-distill-qwen-14b + type: llm + provider: dashscope + description: DeepSeek-R1-Distill-Qwen-14B大语言模型,支持智能体思考,32000上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - agent-thought + logo: dashscope +- name: deepseek-r1-distill-qwen-32b + type: llm + provider: dashscope + description: DeepSeek-R1-Distill-Qwen-32B大语言模型,支持智能体思考,32000上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - agent-thought + logo: dashscope +- name: deepseek-r1 + type: llm + provider: dashscope + description: DeepSeek-R1大语言模型,支持智能体思考,131072超大上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - agent-thought + logo: dashscope +- name: deepseek-v3.1 + type: llm + provider: dashscope + description: DeepSeek-V3.1大语言模型,支持智能体思考,131072超大上下文窗口,对话模式,支持丰富生成参数调节 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - agent-thought + logo: dashscope +- name: deepseek-v3.2-exp + type: llm + provider: dashscope + description: DeepSeek-V3.2-exp实验版大语言模型,支持智能体思考,131072超大上下文窗口,对话模式,支持丰富生成参数调节 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - agent-thought + logo: dashscope +- name: deepseek-v3.2 + type: llm + provider: dashscope + description: DeepSeek-V3.2大语言模型,支持智能体思考,131072超大上下文窗口,对话模式,支持丰富生成参数调节 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - agent-thought + logo: dashscope +- name: deepseek-v3 + type: llm + provider: dashscope + description: DeepSeek-V3大语言模型,支持智能体思考,64000上下文窗口,对话模式,支持文本与JSON格式输出 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - agent-thought + logo: dashscope +- name: farui-plus + type: llm + provider: dashscope + description: farui-plus大语言模型,支持多工具调用、智能体思考、流式工具调用,12288上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: dashscope +- name: glm-4.7 + type: llm + provider: dashscope + description: GLM-4.7大语言模型,支持多工具调用、智能体思考、流式工具调用,202752超大上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: dashscope +- name: qvq-max-latest + type: llm + provider: dashscope + description: qvq-max-latest大语言模型,支持视觉、智能体思考、流式工具调用,131072上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - vision + - agent-thought + - stream-tool-call + logo: dashscope +- name: qvq-max + type: llm + provider: dashscope + description: qvq-max大语言模型,支持视觉、智能体思考、流式工具调用,131072上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - vision + - agent-thought + - stream-tool-call + logo: dashscope +- name: qwen-coder-turbo-0919 + type: llm + provider: dashscope + description: qwen-coder-turbo-0919代码专用大语言模型,支持智能体思考,131072上下文窗口,对话模式,已废弃 + is_deprecated: true + is_official: true + tags: + - 大语言模型 + - 代码模型 + - agent-thought + logo: dashscope +- name: qwen-max-latest + type: llm + provider: dashscope + description: qwen-max-latest大语言模型,支持多工具调用、智能体思考、流式工具调用,131072上下文窗口,对话模式,支持联网搜索 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: dashscope +- name: qwen-max-longcontext + type: llm + provider: dashscope + description: qwen-max-longcontext长上下文大语言模型,支持多工具调用、智能体思考、流式工具调用,32000上下文窗口,对话模式,已废弃 + is_deprecated: true + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: dashscope +- name: qwen-max + type: llm + provider: dashscope + description: qwen-max大语言模型,支持多工具调用、智能体思考、流式工具调用,32768上下文窗口,对话模式,支持联网搜索 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: dashscope +- name: qwen-mt-plus + type: llm + provider: dashscope + description: qwen-mt-plus多语言翻译大语言模型,支持智能体思考,16384上下文窗口,对话模式,支持多语种互译与领域翻译适配 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - 翻译模型 + - agent-thought + logo: dashscope +- name: qwen-mt-turbo + type: llm + provider: dashscope + description: qwen-mt-turbo轻量化多语言翻译大语言模型,支持智能体思考,16384上下文窗口,对话模式,支持多语种互译与领域翻译适配 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - 翻译模型 + - agent-thought + logo: dashscope +- name: qwen-plus-0112 + type: llm + provider: dashscope + description: qwen-plus-0112大语言模型,支持多工具调用、智能体思考、流式工具调用,131072上下文窗口,对话模式,支持联网搜索,已废弃 + is_deprecated: true + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: dashscope +- name: qwen-plus-0125 + type: llm + provider: dashscope + description: qwen-plus-0125大语言模型,支持多工具调用、智能体思考、流式工具调用,131072上下文窗口,对话模式,支持联网搜索,已废弃 + is_deprecated: true + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: dashscope +- name: qwen-plus-0723 + type: llm + provider: dashscope + description: qwen-plus-0723大语言模型,支持多工具调用、智能体思考、流式工具调用,32000上下文窗口,对话模式,支持联网搜索,已废弃 + is_deprecated: true + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: dashscope +- name: qwen-plus-0806 + type: llm + provider: dashscope + description: qwen-plus-0806大语言模型,支持多工具调用、智能体思考、流式工具调用,131072上下文窗口,对话模式,支持联网搜索,已废弃 + is_deprecated: true + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: dashscope +- name: qwen-plus-0919 + type: llm + provider: dashscope + description: qwen-plus-0919大语言模型,支持多工具调用、智能体思考、流式工具调用,131072上下文窗口,对话模式,支持联网搜索,已废弃 + is_deprecated: true + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: dashscope +- name: qwen-plus-1125 + type: llm + provider: dashscope + description: qwen-plus-1125大语言模型,支持多工具调用、智能体思考、流式工具调用,131072上下文窗口,对话模式,支持联网搜索,已废弃 + is_deprecated: true + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: dashscope +- name: qwen-plus-1127 + type: llm + provider: dashscope + description: qwen-plus-1127大语言模型,支持多工具调用、智能体思考、流式工具调用,131072上下文窗口,对话模式,支持联网搜索,已废弃 + is_deprecated: true + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: dashscope +- name: qwen-plus-1220 + type: llm + provider: dashscope + description: qwen-plus-1220大语言模型,支持多工具调用、智能体思考、流式工具调用,131072上下文窗口,对话模式,已废弃 + is_deprecated: true + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: dashscope +- name: qwen-vl-max + type: llm + provider: dashscope + description: qwen-vl-max多模态大模型,支持视觉理解、智能体思考、视频理解,131072上下文窗口,对话模式,未废弃 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - 多模态模型 + - vision + - agent-thought + - video + logo: dashscope +- name: qwen-vl-plus-0809 + type: llm + provider: dashscope + description: qwen-vl-plus-0809多模态大模型,支持视觉理解、智能体思考、视频理解,32768上下文窗口,对话模式,已废弃 + is_deprecated: true + is_official: true + tags: + - 大语言模型 + - 多模态模型 + - vision + - agent-thought + - video + logo: dashscope +- name: qwen-vl-plus-2025-01-02 + type: llm + provider: dashscope + description: qwen-vl-plus-2025-01-02多模态大模型,支持视觉理解、智能体思考、视频理解,32768上下文窗口,对话模式,未废弃 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - 多模态模型 + - vision + - agent-thought + - video + logo: dashscope +- name: qwen-vl-plus-2025-01-25 + type: llm + provider: dashscope + description: qwen-vl-plus-2025-01-25多模态大模型,支持视觉理解、智能体思考、视频理解,131072上下文窗口,对话模式,未废弃 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - 多模态模型 + - vision + - agent-thought + - video + logo: dashscope +- name: qwen-vl-plus-latest + type: llm + provider: dashscope + description: qwen-vl-plus-latest多模态大模型,支持视觉理解、智能体思考、视频理解,131072上下文窗口,对话模式,未废弃 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - 多模态模型 + - vision + - agent-thought + - video + logo: dashscope +- name: qwen-vl-plus + type: llm + provider: dashscope + description: qwen-vl-plus多模态大模型,支持视觉理解、智能体思考、视频理解,131072上下文窗口,对话模式,未废弃 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - 多模态模型 + - vision + - agent-thought + - video + logo: dashscope +- name: qwen2.5-0.5b-instruct + type: llm + provider: dashscope + description: qwen2.5-0.5b-instruct大语言模型,支持多工具调用、智能体思考、流式工具调用,32768上下文窗口,对话模式,未废弃 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: dashscope +- name: qwen3-14b + type: llm + provider: dashscope + description: qwen3-14b大语言模型,支持多工具调用、智能体思考、流式工具调用,131072上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: dashscope +- name: qwen3-235b-a22b-instruct-2507 + type: llm + provider: dashscope + description: qwen3-235b-a22b-instruct-2507大语言模型,支持多工具调用、智能体思考、流式工具调用,131072上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: dashscope +- name: qwen3-235b-a22b-thinking-2507 + type: llm + provider: dashscope + description: qwen3-235b-a22b-thinking-2507大语言模型,支持多工具调用、智能体思考、流式工具调用,131072上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: dashscope +- name: qwen3-235b-a22b + type: llm + provider: dashscope + description: qwen3-235b-a22b大语言模型,支持多工具调用、智能体思考、流式工具调用,131072上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: dashscope +- name: qwen3-30b-a3b-instruct-2507 + type: llm + provider: dashscope + description: qwen3-30b-a3b-instruct-2507大语言模型,支持多工具调用、智能体思考、流式工具调用,131072上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: dashscope +- name: qwen3-30b-a3b + type: llm + provider: dashscope + description: qwen3-30b-a3b大语言模型,支持多工具调用、智能体思考、流式工具调用,131072上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: dashscope +- name: qwen3-32b + type: llm + provider: dashscope + description: qwen3-32b大语言模型,支持多工具调用、智能体思考、流式工具调用,131072上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: dashscope +- name: qwen3-4b + type: llm + provider: dashscope + description: qwen3-4b大语言模型,支持多工具调用、智能体思考、流式工具调用,131072上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: dashscope +- name: qwen3-8b + type: llm + provider: dashscope + description: qwen3-8b大语言模型,支持多工具调用、智能体思考、流式工具调用,131072上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: dashscope +- name: qwen3-coder-30b-a3b-instruct + type: llm + provider: dashscope + description: qwen3-coder-30b-a3b-instruct大语言模型,支持智能体思考,262144上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - 代码模型 + - agent-thought + logo: dashscope +- name: qwen3-coder-480b-a35b-instruct + type: llm + provider: dashscope + description: qwen3-coder-480b-a35b-instruct大语言模型,支持智能体思考,262144上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - 代码模型 + - agent-thought + logo: dashscope +- name: qwen3-coder-plus-2025-09-23 + type: llm + provider: dashscope + description: qwen3-coder-plus-2025-09-23大语言模型,支持智能体思考,1000000上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - 代码模型 + - agent-thought + logo: dashscope +- name: qwen3-coder-plus + type: llm + provider: dashscope + description: qwen3-coder-plus大语言模型,支持智能体思考,1000000上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - 代码模型 + - agent-thought + logo: dashscope +- name: qwen3-max-2025-09-23 + type: llm + provider: dashscope + description: qwen3-max-2025-09-23大语言模型,支持多工具调用、智能体思考、流式工具调用,262144上下文窗口,对话模式,支持联网搜索 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + - 联网搜索 + logo: dashscope +- name: qwen3-max-2026-01-23 + type: llm + provider: dashscope + description: qwen3-max-2026-01-23大语言模型,支持多工具调用、智能体思考、流式工具调用,262144上下文窗口,对话模式,支持联网搜索 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + - 联网搜索 + logo: dashscope +- name: qwen3-max-preview + type: llm + provider: dashscope + description: qwen3-max-preview大语言模型,支持多工具调用、智能体思考、流式工具调用,262144上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: dashscope +- name: qwen3-max + type: llm + provider: dashscope + description: qwen3-max大语言模型,支持多工具调用、智能体思考、流式工具调用,262144上下文窗口,对话模式,支持联网搜索 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + - 联网搜索 + logo: dashscope +- name: qwen3-next-80b-a3b-instruct + type: llm + provider: dashscope + description: qwen3-next-80b-a3b-instruct大语言模型,支持多工具调用、智能体思考、流式工具调用,131072上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: dashscope +- name: qwen3-next-80b-a3b-thinking + type: llm + provider: dashscope + description: qwen3-next-80b-a3b-thinking大语言模型,支持多工具调用、智能体思考、流式工具调用,131072上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: dashscope +- name: qwen3-omni-flash-2025-12-01 + type: llm + provider: dashscope + description: qwen3-omni-flash-2025-12-01多模态大语言模型,支持视觉、智能体思考、视频、音频能力,65536上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - 多模态模型 + - vision + - agent-thought + - video + - audio + logo: dashscope +- name: qwen3-vl-235b-a22b-instruct + type: llm + provider: dashscope + description: qwen3-vl-235b-a22b-instruct多模态大语言模型,支持多工具调用、智能体思考、流式工具调用、视觉、视频能力,131072上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - 多模态模型 + - multi-tool-call + - agent-thought + - stream-tool-call + - vision + - video + logo: dashscope +- name: qwen3-vl-235b-a22b-thinking + type: llm + provider: dashscope + description: qwen3-vl-235b-a22b-thinking多模态大语言模型,支持多工具调用、智能体思考、流式工具调用、视觉、视频能力,131072上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - 多模态模型 + - multi-tool-call + - agent-thought + - stream-tool-call + - vision + - video + logo: dashscope +- name: qwen3-vl-30b-a3b-instruct + type: llm + provider: dashscope + description: qwen3-vl-30b-a3b-instruct多模态大语言模型,支持多工具调用、智能体思考、流式工具调用、视觉、视频能力,131072上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - 多模态模型 + - multi-tool-call + - agent-thought + - stream-tool-call + - vision + - video + logo: dashscope +- name: qwen3-vl-30b-a3b-thinking + type: llm + provider: dashscope + description: qwen3-vl-30b-a3b-thinking多模态大语言模型,支持多工具调用、智能体思考、流式工具调用、视觉、视频能力,131072上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - 多模态模型 + - multi-tool-call + - agent-thought + - stream-tool-call + - vision + - video + logo: dashscope +- name: qwen3-vl-flash + type: llm + provider: dashscope + description: qwen3-vl-flash多模态大语言模型,支持多工具调用、智能体思考、流式工具调用、视觉、视频能力,131072上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - 多模态模型 + - multi-tool-call + - agent-thought + - stream-tool-call + - vision + - video + logo: dashscope +- name: qwen3-vl-plus-2025-09-23 + type: llm + provider: dashscope + description: qwen3-vl-plus-2025-09-23多模态大语言模型,支持视觉、智能体思考、视频能力,262144上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - 多模态模型 + - vision + - agent-thought + - video + logo: dashscope +- name: qwen3-vl-plus + type: llm + provider: dashscope + description: qwen3-vl-plus多模态大语言模型,支持视觉、智能体思考、视频能力,262144上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - 多模态模型 + - vision + - agent-thought + - video + logo: dashscope +- name: qwq-32b + type: llm + provider: dashscope + description: qwq-32b大语言模型,支持智能体思考、流式工具调用,131072上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - agent-thought + - stream-tool-call + logo: dashscope +- name: qwq-plus-0305 + type: llm + provider: dashscope + description: qwq-plus-0305大语言模型,支持智能体思考、流式工具调用,131072上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - agent-thought + - stream-tool-call + logo: dashscope +- name: qwq-plus + type: llm + provider: dashscope + description: qwq-plus大语言模型,支持智能体思考、流式工具调用,131072上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - agent-thought + - stream-tool-call + logo: dashscope +- name: gte-rerank-v2 + type: rerank + provider: dashscope + description: gte-rerank-v2重排序模型,4000上下文窗口 + is_deprecated: false + is_official: true + tags: + - 重排序模型 + logo: dashscope +- name: gte-rerank + type: rerank + provider: dashscope + description: gte-rerank重排序模型,4000上下文窗口 + is_deprecated: false + is_official: true + tags: + - 重排序模型 + logo: dashscope +- name: paraformer-realtime-v1 + type: speech2text + provider: dashscope + description: paraformer-realtime-v1语音转文字模型,支持多格式音频/视频文件,文件上传限制100MB + is_deprecated: false + is_official: true + tags: + - 语音识别 + - 语音转文字 + logo: dashscope +- name: paraformer-realtime-v2 + type: speech2text + provider: dashscope + description: paraformer-realtime-v2语音转文字模型,支持多格式音频/视频文件,文件上传限制100MB + is_deprecated: false + is_official: true + tags: + - 语音识别 + - 语音转文字 + logo: dashscope +- name: multimodal-embedding-v1 + type: embedding + provider: dashscope + description: multimodal-embedding-v1多模态嵌入模型,支持视觉能力,8192上下文窗口,最大分块数10 + is_deprecated: false + is_official: true + tags: + - 嵌入模型 + - 多模态模型 + - vision + logo: dashscope +- name: text-embedding-v1 + type: embedding + provider: dashscope + description: text-embedding-v1文本嵌入模型,2048上下文窗口,最大分块数25 + is_deprecated: false + is_official: true + tags: + - 嵌入模型 + - 文本嵌入 + logo: dashscope +- name: text-embedding-v2 + type: embedding + provider: dashscope + description: text-embedding-v2文本嵌入模型,2048上下文窗口,最大分块数25 + is_deprecated: false + is_official: true + tags: + - 嵌入模型 + - 文本嵌入 + logo: dashscope +- name: text-embedding-v3 + type: embedding + provider: dashscope + description: text-embedding-v3文本嵌入模型,8192上下文窗口,最大分块数10 + is_deprecated: false + is_official: true + tags: + - 嵌入模型 + - 文本嵌入 + logo: dashscope +- name: text-embedding-v4 + type: embedding + provider: dashscope + description: text-embedding-v4文本嵌入模型,8192上下文窗口,最大分块数10 + is_deprecated: false + is_official: true + tags: + - 嵌入模型 + - 文本嵌入 + logo: dashscope +- name: tts-1 + type: tts + provider: dashscope + description: tts-1语音合成模型,默认音色知茹(新闻女声),支持多语言多音色,最大文本长度7000字,输出MP3格式 + is_deprecated: false + is_official: true + tags: + - 语音合成 + - 文字转语音 + logo: dashscope diff --git a/api/app/core/models/scripts/loader.py b/api/app/core/models/scripts/loader.py new file mode 100644 index 00000000..6469656c --- /dev/null +++ b/api/app/core/models/scripts/loader.py @@ -0,0 +1,143 @@ +"""模型配置加载器 - 用于将预定义模型批量导入到数据库""" + +import os +from pathlib import Path +from typing import Callable + +import yaml +from sqlalchemy.orm import Session +from app.models.models_model import ModelBase, ModelProvider + + +def _load_yaml_config(provider: ModelProvider) -> list[dict]: + """从YAML文件加载指定供应商的模型配置""" + config_dir = Path(__file__).parent + config_file = config_dir / f"{provider.value}_models.yaml" + + if not config_file.exists(): + return [] + + with open(config_file, 'r', encoding='utf-8') as f: + data = yaml.safe_load(f) + + # 检查是否需要加载(默认为 true) + if not data.get('enabled', True): + return [] + + return data.get('models', []) + + +def _disable_yaml_config(provider: ModelProvider) -> None: + """将YAML文件的enabled标志设置为false""" + config_dir = Path(__file__).parent + config_file = config_dir / f"{provider.value}_models.yaml" + + if not config_file.exists(): + return + + with open(config_file, 'r', encoding='utf-8') as f: + data = yaml.safe_load(f) + + data['enabled'] = False + + with open(config_file, 'w', encoding='utf-8') as f: + yaml.dump(data, f, allow_unicode=True, sort_keys=False) + + +def load_models(db: Session, providers: list[str] = None, silent: bool = False) -> dict: + """ + 加载模型配置到数据库 + + Args: + db: 数据库会话 + providers: 要加载的供应商列表,None表示加载所有 + silent: 是否静默模式(不输出详细日志) + + Returns: + dict: 加载结果统计 {"success": int, "skipped": int, "failed": int} + """ + result = {"success": 0, "skipped": 0, "failed": 0} + + # 确定要加载的供应商 + if providers: + target_providers = [ModelProvider(p) if isinstance(p, str) else p for p in providers] + else: + target_providers = [p for p in ModelProvider if p != ModelProvider.COMPOSITE] + + for provider in target_providers: + # 从YAML文件加载模型配置 + models = _load_yaml_config(provider) + + if not models: + if not silent: + print(f"警告: 供应商 '{provider.value}' 暂无预定义模型") + continue + + if not silent: + print(f"\n正在加载 {provider.value} 的 {len(models)} 个模型...") + + # provider_success = 0 + for model_data in models: + try: + # 检查模型是否已存在 + existing = db.query(ModelBase).filter( + ModelBase.name == model_data["name"], + ModelBase.provider == model_data["provider"] + ).first() + + if existing: + # 更新现有模型配置 + for key, value in model_data.items(): + setattr(existing, key, value) + db.commit() + if not silent: + print(f"更新成功: {model_data['name']}") + result["success"] += 1 + # provider_success += 1 + else: + # 创建新模型 + model = ModelBase(**model_data) + db.add(model) + db.commit() + if not silent: + print(f"添加成功: {model_data['name']}") + result["success"] += 1 + # provider_success += 1 + + except Exception as e: + db.rollback() + if not silent: + print(f"添加失败: {model_data['name']} - {str(e)}") + result["failed"] += 1 + + # 如果该供应商的模型全部加载成功,将enabled设置为false + # if provider_success == len(models): + _disable_yaml_config(provider) + + return result + + +def load_models_by_provider(db: Session, provider: str) -> dict: + """ + 加载指定供应商的模型配置 + + Args: + db: 数据库会话 + provider: 供应商名称(字符串或ModelProvider枚举) + + Returns: + dict: 加载结果统计 + """ + provider_enum = ModelProvider(provider) if isinstance(provider, str) else provider + return load_models(db, providers=[provider_enum]) + + +def get_available_providers() -> list[Callable[[], str]]: + """获取所有可用的供应商列表(从ModelProvider枚举获取,排除COMPOSITE)""" + return [p.value for p in ModelProvider if p != ModelProvider.COMPOSITE] + + +def get_models_by_provider(provider: str) -> list[dict]: + """获取指定供应商的模型配置列表""" + provider_enum = ModelProvider(provider) if isinstance(provider, str) else provider + return _load_yaml_config(provider_enum) diff --git a/api/app/core/models/scripts/openai_models.yaml b/api/app/core/models/scripts/openai_models.yaml new file mode 100644 index 00000000..7ae2cfce --- /dev/null +++ b/api/app/core/models/scripts/openai_models.yaml @@ -0,0 +1,348 @@ +provider: openai +enabled: true +models: +- name: chatgpt-4o-latest + type: llm + provider: openai + description: chatgpt-4o-latest大语言模型,支持多工具调用、智能体思考、流式工具调用、视觉能力,128000上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + - vision + logo: openai +- name: gpt-3.5-turbo-0125 + type: llm + provider: openai + description: gpt-3.5-turbo-0125大语言模型,支持多工具调用、智能体思考、流式工具调用,16385上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: openai +- name: gpt-3.5-turbo-1106 + type: llm + provider: openai + description: gpt-3.5-turbo-1106大语言模型,支持多工具调用、智能体思考、流式工具调用,16385上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: openai +- name: gpt-3.5-turbo-16k + type: llm + provider: openai + description: gpt-3.5-turbo-16k大语言模型,支持多工具调用、智能体思考、流式工具调用,16385上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: openai +- name: gpt-3.5-turbo-instruct + type: llm + provider: openai + description: gpt-3.5-turbo-instruct大语言模型,4096上下文窗口,文本补全模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + logo: openai +- name: gpt-3.5-turbo + type: llm + provider: openai + description: gpt-3.5-turbo大语言模型,支持多工具调用、智能体思考、流式工具调用,16385上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: openai +- name: gpt-4-0125-preview + type: llm + provider: openai + description: gpt-4-0125-preview大语言模型,支持多工具调用、智能体思考、流式工具调用,128000上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: openai +- name: gpt-4-1106-preview + type: llm + provider: openai + description: gpt-4-1106-preview大语言模型,支持多工具调用、智能体思考、流式工具调用,128000上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: openai +- name: gpt-4-turbo-2024-04-09 + type: llm + provider: openai + description: gpt-4-turbo-2024-04-09大语言模型,支持多工具调用、智能体思考、流式工具调用、视觉能力,128000上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + - vision + logo: openai +- name: gpt-4-turbo-preview + type: llm + provider: openai + description: gpt-4-turbo-preview大语言模型,支持多工具调用、智能体思考、流式工具调用,128000上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + logo: openai +- name: gpt-4-turbo + type: llm + provider: openai + description: gpt-4-turbo大语言模型,支持多工具调用、智能体思考、流式工具调用、视觉能力,128000上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + - vision + logo: openai +- name: o1-preview + type: llm + provider: openai + description: o1-preview大语言模型,支持智能体思考,128000上下文窗口,对话模式,已废弃 + is_deprecated: true + is_official: true + tags: + - 大语言模型 + - agent-thought + logo: openai +- name: o1 + type: llm + provider: openai + description: o1大语言模型,支持多工具调用、智能体思考、流式工具调用、视觉能力、结构化输出,200000上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - multi-tool-call + - agent-thought + - stream-tool-call + - vision + - structured-output + logo: openai +- name: o3-2025-04-16 + type: llm + provider: openai + description: o3-2025-04-16大语言模型,支持智能体思考、工具调用、视觉能力、流式工具调用、结构化输出,200000上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - agent-thought + - tool-call + - vision + - stream-tool-call + - structured-output + logo: openai +- name: o3-mini-2025-01-31 + type: llm + provider: openai + description: o3-mini-2025-01-31大语言模型,支持智能体思考、工具调用、流式工具调用、结构化输出,200000上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - agent-thought + - tool-call + - stream-tool-call + - structured-output + logo: openai +- name: o3-mini + type: llm + provider: openai + description: o3-mini大语言模型,支持智能体思考、工具调用、流式工具调用、结构化输出,200000上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - agent-thought + - tool-call + - stream-tool-call + - structured-output + logo: openai +- name: o3-pro-2025-06-10 + type: llm + provider: openai + description: o3-pro-2025-06-10大语言模型,支持智能体思考、工具调用、视觉能力、结构化输出,200000上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - agent-thought + - tool-call + - vision + - structured-output + logo: openai +- name: o3-pro + type: llm + provider: openai + description: o3-pro大语言模型,支持智能体思考、工具调用、视觉能力、结构化输出,200000上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - agent-thought + - tool-call + - vision + - structured-output + logo: openai +- name: o3 + type: llm + provider: openai + description: o3大语言模型,支持智能体思考、视觉能力、工具调用、流式工具调用、结构化输出,200000上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - agent-thought + - vision + - tool-call + - stream-tool-call + - structured-output + logo: openai +- name: o4-mini-2025-04-16 + type: llm + provider: openai + description: o4-mini-2025-04-16大语言模型,支持智能体思考、工具调用、视觉能力、流式工具调用、结构化输出,200000上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - agent-thought + - tool-call + - vision + - stream-tool-call + - structured-output + logo: openai +- name: o4-mini + type: llm + provider: openai + description: o4-mini大语言模型,支持智能体思考、工具调用、视觉能力、流式工具调用、结构化输出,200000上下文窗口,对话模式 + is_deprecated: false + is_official: true + tags: + - 大语言模型 + - agent-thought + - tool-call + - vision + - stream-tool-call + - structured-output + logo: openai +- name: gpt-4o-mini-transcribe + type: speech2text + provider: openai + description: gpt-4o-mini-transcribe语音转文本模型,文件上传限制25MB,支持flac,mp3,mp4,mpeg,mpga,m4a,ogg,wav,webm格式 + is_deprecated: false + is_official: true + tags: + - 语音转文本模型 + logo: openai +- name: gpt-4o-transcribe + type: speech2text + provider: openai + description: gpt-4o-transcribe语音转文本模型,文件上传限制25MB,支持flac,mp3,mp4,mpeg,mpga,m4a,ogg,wav,webm格式 + is_deprecated: false + is_official: true + tags: + - 语音转文本模型 + logo: openai +- name: whisper-1 + type: speech2text + provider: openai + description: whisper-1语音转文本模型,文件上传限制25MB,支持flac,mp3,mp4,mpeg,mpga,m4a,ogg,wav,webm格式 + is_deprecated: false + is_official: true + tags: + - 语音转文本模型 + logo: openai +- name: text-embedding-3-large + type: embedding + provider: openai + description: text-embedding-3-large文本向量模型,8191上下文窗口,最大分块数32 + is_deprecated: false + is_official: true + tags: + - 文本向量模型 + logo: openai +- name: text-embedding-3-small + type: embedding + provider: openai + description: text-embedding-3-small文本向量模型,8191上下文窗口,最大分块数32 + is_deprecated: false + is_official: true + tags: + - 文本向量模型 + logo: openai +- name: text-embedding-ada-002 + type: embedding + provider: openai + description: text-embedding-ada-002文本向量模型,8097上下文窗口,最大分块数32 + is_deprecated: false + is_official: true + tags: + - 文本向量模型 + logo: openai +- name: gpt-4o-mini-tts + type: tts + provider: openai + description: gpt-4o-mini-tts文本转语音模型,输出音频格式mp3,支持多语种语音,字数限制3500 + is_deprecated: false + is_official: true + tags: + - 文本转语音模型 + logo: openai +- name: tts-1-hd + type: tts + provider: openai + description: tts-1-hd高清文本转语音模型,输出音频格式mp3,支持多语种语音,字数限制3500 + is_deprecated: false + is_official: true + tags: + - 文本转语音模型 + logo: openai +- name: tts-1 + type: tts + provider: openai + description: tts-1文本转语音模型,输出音频格式mp3,支持多语种语音,字数限制3500 + is_deprecated: false + is_official: true + tags: + - 文本转语音模型 + logo: openai diff --git a/api/app/main.py b/api/app/main.py index 87bfecf8..7e16d2c0 100644 --- a/api/app/main.py +++ b/api/app/main.py @@ -16,6 +16,8 @@ from app.core.error_codes import BizCode, HTTP_MAPPING from app.core.exceptions import BusinessException from app.core.logging_config import LoggingConfig, get_logger from app.core.response_utils import fail +from app.core.models.scripts.loader import load_models +from app.db import get_db_context # Initialize logging system LoggingConfig.setup_logging() @@ -47,6 +49,15 @@ async def lifespan(app: FastAPI): else: logger.info("自动数据库升级已禁用 (DB_AUTO_UPGRADE=false)") + # 加载预定义模型 + logger.info("开始加载预定义模型...") + try: + with get_db_context() as db: + result = load_models(db, silent=True) + logger.info(f"预定义模型加载完成: 成功{result['success']}个, 跳过{result['skipped']}个, 失败{result['failed']}个") + except Exception as e: + logger.warning(f"加载预定义模型时出错: {str(e)}") + logger.info("应用程序启动完成") yield # 应用关闭事件 diff --git a/api/app/models/models_model.py b/api/app/models/models_model.py index a8918c7c..11a869a6 100644 --- a/api/app/models/models_model.py +++ b/api/app/models/models_model.py @@ -5,6 +5,7 @@ from enum import StrEnum from sqlalchemy import Column, String, Boolean, DateTime, Text, ForeignKey, Enum as SQLEnum, UniqueConstraint, Integer, ARRAY, Table from sqlalchemy.dialects.postgresql import UUID, JSON from sqlalchemy.orm import relationship +from sqlalchemy.sql import func from app.db import Base @@ -23,6 +24,8 @@ class ModelType(StrEnum): CHAT = "chat" EMBEDDING = "embedding" RERANK = "rerank" + TTS = "tts" + SPEECH2TEXT = "speech2text" # IMAGE = "image" # AUDIO = "audio" # VISION = "vision" @@ -48,8 +51,7 @@ class ModelProvider(StrEnum): class LoadBalanceStrategy(StrEnum): """API Key负载均衡策略枚举""" ROUND_ROBIN = "round_robin" # 轮询 - WEIGHTED_ROUND_ROBIN = "weighted_round_robin" # 加权轮询 - RANDOM = "random" # 随机 + NONE = "none" # 无 # 多对多关联表 @@ -90,7 +92,8 @@ class ModelConfig(BaseModel): # 状态管理 is_public = Column(Boolean, default=False, nullable=False, comment="是否公开") - load_balance_strategy = Column(String, nullable=True, comment="负载均衡策略") + load_balance_strategy = Column(String, nullable=True, comment="负载均衡策略", default=LoadBalanceStrategy.NONE, + server_default=LoadBalanceStrategy.NONE) # 关联关系 model_base = relationship("ModelBase", back_populates="configs") @@ -151,6 +154,7 @@ class ModelBase(Base): is_official = Column(Boolean, default=True, comment="是否供应商官方模型(区分自定义)") tags = Column(ARRAY(String), default=list, nullable=False, comment="模型标签(如['聊天', '创作'])") add_count = Column(Integer, default=0, nullable=False, comment="模型被用户添加的次数") + created_at = Column(DateTime, default=datetime.datetime.now, comment="创建时间", server_default=func.now()) # 关联关系 configs = relationship("ModelConfig", back_populates="model_base", cascade="all, delete-orphan") diff --git a/api/app/repositories/model_repository.py b/api/app/repositories/model_repository.py index 8e4632cc..36f7062f 100644 --- a/api/app/repositories/model_repository.py +++ b/api/app/repositories/model_repository.py @@ -165,7 +165,7 @@ class ModelConfigRepository: total = base_query.count() # 分页查询 - models = base_query.order_by(desc(ModelConfig.updated_at)).offset( + models = base_query.order_by(desc(ModelConfig.created_at)).offset( (query.page - 1) * query.pagesize ).limit(query.pagesize).all() @@ -234,7 +234,7 @@ class ModelConfigRepository: # 获取总数 total = base_query.count() - query_results = base_query.order_by(desc(ModelConfig.updated_at)).all() + query_results = base_query.order_by(desc(ModelConfig.created_at)).all() provider_groups: Dict[str, List[ModelConfig]] = {} for model_config in query_results: @@ -433,6 +433,7 @@ class ModelConfigRepository: ModelConfig.is_public ), ModelBase.provider == provider, + ModelConfig.is_active, ~ModelConfig.is_composite ) ).distinct().all() @@ -621,7 +622,7 @@ class ModelBaseRepository: if filters: q = q.filter(and_(*filters)) - return q.order_by(ModelBase.add_count.desc()).all() + return q.order_by(ModelBase.add_count.desc(), ModelBase.created_at.desc()).all() @staticmethod def create(db: Session, data: dict) -> 'ModelBase': @@ -636,6 +637,17 @@ class ModelBaseRepository: return None for key, value in data.items(): setattr(model_base, key, value) + + # 同步更新绑定的非组合模型配置 + if any(k in data for k in ['name', 'description', 'logo']): + db.query(ModelConfig).filter( + ModelConfig.model_id == model_base_id, + ModelConfig.is_composite == False + ).update({ + k: v for k, v in data.items() + if k in ['name', 'description', 'logo'] + }, synchronize_session=False) + return model_base @staticmethod diff --git a/api/app/schemas/model_schema.py b/api/app/schemas/model_schema.py index ce1b36bb..73f60936 100644 --- a/api/app/schemas/model_schema.py +++ b/api/app/schemas/model_schema.py @@ -3,14 +3,12 @@ from typing import Optional, List, Dict, Any import datetime import uuid -from app.models.models_model import ModelProvider, ModelType +from app.models.models_model import ModelProvider, ModelType, LoadBalanceStrategy from app.core.logging_config import get_business_logger schema_logger = get_business_logger() - - # ModelConfig Schemas class ModelConfigBase(BaseModel): """模型配置基础Schema""" @@ -22,6 +20,7 @@ class ModelConfigBase(BaseModel): config: Optional[Dict[str, Any]] = Field({}, description="模型配置参数") is_active: bool = Field(True, description="是否激活") is_public: bool = Field(False, description="是否公开") + load_balance_strategy: Optional[str] = Field(LoadBalanceStrategy.NONE.value, description="负载均衡策略") class ApiKeyCreateNested(BaseModel): @@ -51,6 +50,7 @@ class CompositeModelCreate(BaseModel): is_active: bool = Field(True, description="是否激活") is_public: bool = Field(False, description="是否公开") api_key_ids: List[uuid.UUID] = Field(..., description="绑定的API Key ID列表") + load_balance_strategy: Optional[str] = Field(default=LoadBalanceStrategy.NONE.value, description="负载均衡策略") class ModelConfigUpdate(BaseModel): diff --git a/api/app/services/model_service.py b/api/app/services/model_service.py index 5b2ab7e6..729fc192 100644 --- a/api/app/services/model_service.py +++ b/api/app/services/model_service.py @@ -347,7 +347,9 @@ class ModelConfigService: "is_public": model_data.is_public, "is_composite": True } - + if "load_balance_strategy" in model_data.model_fields_set: + model_config_data["load_balance_strategy"] = model_data.load_balance_strategy + model = ModelConfigRepository.create(db, model_config_data) db.flush() @@ -397,6 +399,8 @@ class ModelConfigService: existing_model.config = model_data.config existing_model.is_active = model_data.is_active existing_model.is_public = model_data.is_public + if "load_balance_strategy" in model_data.model_fields_set: + existing_model.load_balance_strategy = model_data.load_balance_strategy # 更新 API Keys 关联 existing_model.api_keys.clear() diff --git a/api/migrations/versions/5ca246ee7dd4_202601291352.py b/api/migrations/versions/5ca246ee7dd4_202601291352.py new file mode 100644 index 00000000..74931287 --- /dev/null +++ b/api/migrations/versions/5ca246ee7dd4_202601291352.py @@ -0,0 +1,30 @@ +"""202601291352 + +Revision ID: 5ca246ee7dd4 +Revises: 915bed077f8d +Create Date: 2026-01-29 13:52:47.647306 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision: str = '5ca246ee7dd4' +down_revision: Union[str, None] = '915bed077f8d' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('model_bases', sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=True, comment='创建时间')) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('model_bases', 'created_at') + # ### end Alembic commands ### diff --git a/api_key_mcp_server.py b/api_key_mcp_server.py deleted file mode 100644 index f611dc59..00000000 --- a/api_key_mcp_server.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python3 -"""API Key认证MCP服务器""" - -from fastapi import FastAPI, HTTPException, Depends, Header -from typing import Optional -import uvicorn -from mcp_base import MCPRequest, handle_mcp_request, TOOLS - -app = FastAPI(title="API Key MCP Server", version="1.0.0") - -# API Key配置 -API_KEYS = {"test-api-key", "demo-key-123"} - -def verify_api_key(x_api_key: Optional[str] = Header(None)): - """验证API Key""" - if x_api_key and x_api_key in API_KEYS: - return True - raise HTTPException(status_code=401, detail="Invalid API Key") - -@app.get("/") -async def root(): - return {"name": "API Key MCP Server", "version": "1.0.0", "auth_type": "api_key"} - -@app.get("/health") -async def health(): - return {"status": "healthy", "tools": len(TOOLS), "auth_type": "api_key"} - -@app.post("/mcp") -async def mcp_handler(request: MCPRequest, _: bool = Depends(verify_api_key)): - return await handle_mcp_request(request, "API Key MCP Server") - -if __name__ == "__main__": - print("启动API Key认证MCP服务器...") - print("访问 http://localhost:8004 查看服务状态") - print("MCP端点: http://localhost:8004/mcp") - print("认证方式: API Key (Header: X-API-Key)") - print("测试API Keys: test-api-key, demo-key-123") - uvicorn.run(app, host="0.0.0.0", port=8004) \ No newline at end of file diff --git a/basic_auth_mcp_server.py b/basic_auth_mcp_server.py deleted file mode 100644 index 11bb5595..00000000 --- a/basic_auth_mcp_server.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env python3 -"""Basic Auth认证MCP服务器""" - -from fastapi import FastAPI, HTTPException, Depends, Header -from typing import Optional -import uvicorn -import base64 -from mcp_base import MCPRequest, handle_mcp_request, TOOLS - -app = FastAPI(title="Basic Auth MCP Server", version="1.0.0") - -# Basic Auth配置 -BASIC_AUTH_USERS = {"admin": "password", "user": "secret"} - -def verify_basic_auth(authorization: Optional[str] = Header(None)): - """验证Basic Auth""" - if authorization and authorization.startswith("Basic "): - try: - credentials = base64.b64decode(authorization.split(" ")[1]).decode() - username, password = credentials.split(":", 1) - if username in BASIC_AUTH_USERS and BASIC_AUTH_USERS[username] == password: - return True - except: - pass - raise HTTPException(status_code=401, detail="Invalid Basic Auth") - -@app.get("/") -async def root(): - return {"name": "Basic Auth MCP Server", "version": "1.0.0", "auth_type": "basic_auth"} - -@app.get("/health") -async def health(): - return {"status": "healthy", "tools": len(TOOLS), "auth_type": "basic_auth"} - -@app.post("/mcp") -async def mcp_handler(request: MCPRequest, _: bool = Depends(verify_basic_auth)): - return await handle_mcp_request(request, "Basic Auth MCP Server") - -if __name__ == "__main__": - print("启动Basic Auth认证MCP服务器...") - print("访问 http://localhost:8006 查看服务状态") - print("MCP端点: http://localhost:8006/mcp") - print("认证方式: Basic Auth (Header: Authorization: Basic )") - print("测试用户: admin:password, user:secret") - uvicorn.run(app, host="0.0.0.0", port=8006) \ No newline at end of file diff --git a/bearer_token_mcp_server.py b/bearer_token_mcp_server.py deleted file mode 100644 index 57d27f2f..00000000 --- a/bearer_token_mcp_server.py +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env python3 -"""Bearer Token认证MCP服务器""" - -from fastapi import FastAPI, HTTPException, Depends, Header -from typing import Optional -import uvicorn -from mcp_base import MCPRequest, handle_mcp_request, TOOLS - -app = FastAPI(title="Bearer Token MCP Server", version="1.0.0") - -# Bearer Token配置 -BEARER_TOKENS = {"bearer-token-123", "demo-bearer-token"} - -def verify_bearer_token(authorization: Optional[str] = Header(None)): - """验证Bearer Token""" - if authorization and authorization.startswith("Bearer "): - token = authorization.split(" ")[1] - if token in BEARER_TOKENS: - return True - raise HTTPException(status_code=401, detail="Invalid Bearer Token") - -@app.get("/") -async def root(): - return {"name": "Bearer Token MCP Server", "version": "1.0.0", "auth_type": "bearer_token"} - -@app.get("/health") -async def health(): - return {"status": "healthy", "tools": len(TOOLS), "auth_type": "bearer_token"} - -@app.post("/mcp") -async def mcp_handler(request: MCPRequest, _: bool = Depends(verify_bearer_token)): - return await handle_mcp_request(request, "Bearer Token MCP Server") - -if __name__ == "__main__": - print("启动Bearer Token认证MCP服务器...") - print("访问 http://localhost:8005 查看服务状态") - print("MCP端点: http://localhost:8005/mcp") - print("认证方式: Bearer Token (Header: Authorization: Bearer )") - print("测试Bearer Tokens: bearer-token-123, demo-bearer-token") - uvicorn.run(app, host="0.0.0.0", port=8005) \ No newline at end of file diff --git a/mcp_base.py b/mcp_base.py deleted file mode 100644 index f571e2fa..00000000 --- a/mcp_base.py +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/env python3 -"""MCP服务器基础模块 - 共享的模型和处理逻辑""" - -from pydantic import BaseModel -from typing import Dict, Any - -class MCPRequest(BaseModel): - jsonrpc: str = "2.0" - id: str - method: str - params: Dict[str, Any] = {} - -class MCPResponse(BaseModel): - jsonrpc: str = "2.0" - id: str - result: Any = None - error: Dict[str, Any] = None - -# 工具定义 -TOOLS = [ - { - "name": "calculator", - "description": "简单计算器", - "inputSchema": { - "type": "object", - "properties": { - "expression": {"type": "string", "description": "数学表达式"} - }, - "required": ["expression"] - } - }, - { - "name": "echo", - "description": "回显工具", - "inputSchema": { - "type": "object", - "properties": { - "message": {"type": "string", "description": "要回显的消息"} - }, - "required": ["message"] - } - } -] - -async def handle_mcp_request(request: MCPRequest, server_name: str = "MCP Server"): - """处理MCP请求""" - try: - if request.method == "initialize": - return MCPResponse( - id=request.id, - result={ - "protocolVersion": "2024-11-05", - "capabilities": {"tools": {"listChanged": True}}, - "serverInfo": {"name": server_name, "version": "1.0.0"} - } - ) - - elif request.method == "tools/list": - return MCPResponse( - id=request.id, - result={"tools": TOOLS} - ) - - elif request.method == "tools/call": - tool_name = request.params.get("name") - arguments = request.params.get("arguments", {}) - - if tool_name == "calculator": - try: - expression = arguments.get("expression", "") - result = eval(expression) - return MCPResponse( - id=request.id, - result={"content": [{"type": "text", "text": f"结果: {result}"}]} - ) - except Exception as e: - return MCPResponse( - id=request.id, - error={"code": -1, "message": f"计算错误: {str(e)}"} - ) - - elif tool_name == "echo": - message = arguments.get("message", "") - return MCPResponse( - id=request.id, - result={"content": [{"type": "text", "text": f"Echo: {message}"}]} - ) - - else: - return MCPResponse( - id=request.id, - error={"code": -1, "message": f"未知工具: {tool_name}"} - ) - - elif request.method == "ping": - return MCPResponse( - id=request.id, - result={"status": "pong"} - ) - - else: - return MCPResponse( - id=request.id, - error={"code": -1, "message": f"未知方法: {request.method}"} - ) - - except Exception as e: - return MCPResponse( - id=request.id, - error={"code": -1, "message": str(e)} - ) \ No newline at end of file diff --git a/simple_mcp_server.py b/simple_mcp_server.py deleted file mode 100644 index fa299e37..00000000 --- a/simple_mcp_server.py +++ /dev/null @@ -1,130 +0,0 @@ -#!/usr/bin/env python3 -"""简化的MCP服务器 - 用于测试MCP工具集成""" - -from fastapi import FastAPI, HTTPException -from pydantic import BaseModel -from typing import Dict, Any, List -import uvicorn - -app = FastAPI(title="Simple MCP Server", version="1.0.0") - -class MCPRequest(BaseModel): - jsonrpc: str = "2.0" - id: str - method: str - params: Dict[str, Any] = {} - -class MCPResponse(BaseModel): - jsonrpc: str = "2.0" - id: str - result: Any = None - error: Dict[str, Any] = None - -# 可用工具定义 -TOOLS = [ - { - "name": "calculator", - "description": "简单计算器", - "inputSchema": { - "type": "object", - "properties": { - "expression": {"type": "string", "description": "数学表达式"} - }, - "required": ["expression"] - } - }, - { - "name": "echo", - "description": "回显工具", - "inputSchema": { - "type": "object", - "properties": { - "message": {"type": "string", "description": "要回显的消息"} - }, - "required": ["message"] - } - } -] - -@app.get("/") -async def root(): - return {"name": "Simple MCP Server", "version": "1.0.0"} - -@app.get("/health") -async def health(): - return {"status": "healthy", "tools": len(TOOLS)} - -@app.post("/mcp") -async def mcp_handler(request: MCPRequest): - """处理MCP请求""" - try: - if request.method == "initialize": - return MCPResponse( - id=request.id, - result={ - "protocolVersion": "2024-11-05", - "capabilities": {"tools": {"listChanged": True}}, - "serverInfo": {"name": "Simple MCP Server", "version": "1.0.0"} - } - ) - - elif request.method == "tools/list": - return MCPResponse( - id=request.id, - result={"tools": TOOLS} - ) - - elif request.method == "tools/call": - tool_name = request.params.get("name") - arguments = request.params.get("arguments", {}) - - if tool_name == "calculator": - try: - expression = arguments.get("expression", "") - result = eval(expression) # 注意:生产环境不要用eval - return MCPResponse( - id=request.id, - result={"content": [{"type": "text", "text": f"结果: {result}"}]} - ) - except Exception as e: - return MCPResponse( - id=request.id, - error={"code": -1, "message": f"计算错误: {str(e)}"} - ) - - elif tool_name == "echo": - message = arguments.get("message", "") - return MCPResponse( - id=request.id, - result={"content": [{"type": "text", "text": f"Echo: {message}"}]} - ) - - else: - return MCPResponse( - id=request.id, - error={"code": -1, "message": f"未知工具: {tool_name}"} - ) - - elif request.method == "ping": - return MCPResponse( - id=request.id, - result={"status": "pong"} - ) - - else: - return MCPResponse( - id=request.id, - error={"code": -1, "message": f"未知方法: {request.method}"} - ) - - except Exception as e: - return MCPResponse( - id=request.id, - error={"code": -1, "message": str(e)} - ) - -if __name__ == "__main__": - print("启动简化MCP服务器...") - print("访问 http://localhost:8002 查看服务状态") - print("MCP端点: http://localhost:8002/mcp") - uvicorn.run(app, host="0.0.0.0", port=8002) \ No newline at end of file diff --git a/web/src/i18n/en.ts b/web/src/i18n/en.ts index ea45ea6d..45305113 100644 --- a/web/src/i18n/en.ts +++ b/web/src/i18n/en.ts @@ -546,7 +546,10 @@ export const en = { tags: 'Tags', createCustomModel: 'Add Custom Model', edit: 'Edit', - selectOneTip: 'Model API KEY not configured, please configure in Model Plaza first', + selectOneTip: 'Model API KEY not configured, please configure it in the model list first', + load_balance_strategy: 'Concurrency Strategy', + round_robin: 'Sequential Execution - Call each model in order', + none: 'None', api_key: 'API KEY', api_base: 'API Base URL', diff --git a/web/src/i18n/zh.ts b/web/src/i18n/zh.ts index 0e5c9288..7a83b784 100644 --- a/web/src/i18n/zh.ts +++ b/web/src/i18n/zh.ts @@ -1118,7 +1118,10 @@ export const zh = { tags: '标签', createCustomModel: '添加自定义模型', edit: '编辑', - selectOneTip: '模型未配置API KEY,请先在模型广场配置', + selectOneTip: '模型未配置API KEY,请先在模型列表配置', + load_balance_strategy: '并发策略', + round_robin: '顺序执行 - 按顺序依次调用每个模型', + none: '无', api_key: 'API KEY', api_base: 'API Base URL', diff --git a/web/src/views/ModelManagement/List.tsx b/web/src/views/ModelManagement/List.tsx index 4f8fb665..bb799752 100644 --- a/web/src/views/ModelManagement/List.tsx +++ b/web/src/views/ModelManagement/List.tsx @@ -23,7 +23,6 @@ const ModelList: FC<{ query: any }> = ({ query }) => { getModelNewList({ ...query, is_composite: false, - is_active: true, }) .then(res => { setList((res || []) as ProviderModelItem[]) diff --git a/web/src/views/ModelManagement/components/CustomModelModal.tsx b/web/src/views/ModelManagement/components/CustomModelModal.tsx index d22fbcdd..47928d87 100644 --- a/web/src/views/ModelManagement/components/CustomModelModal.tsx +++ b/web/src/views/ModelManagement/components/CustomModelModal.tsx @@ -129,6 +129,7 @@ const CustomModelModal = forwardRef( items.map((item) => ({ label: t(`modelNew.${item}`), value: String(item) }))} /> @@ -141,6 +142,7 @@ const CustomModelModal = forwardRef( items.map((item) => ({ label: t(`modelNew.${item}`), value: String(item) }))} /> diff --git a/web/src/views/ModelManagement/components/GroupModelModal.tsx b/web/src/views/ModelManagement/components/GroupModelModal.tsx index 6ae54d4c..c66288e5 100644 --- a/web/src/views/ModelManagement/components/GroupModelModal.tsx +++ b/web/src/views/ModelManagement/components/GroupModelModal.tsx @@ -1,5 +1,5 @@ import { forwardRef, useImperativeHandle, useState } from 'react'; -import { Form, Input, App } from 'antd'; +import { Form, Input, App, Select } from 'antd'; import { useTranslation } from 'react-i18next'; import type { ModelListItem, CompositeModelForm, GroupModelModalRef, GroupModelModalProps, ModelApiKey } from '../types'; @@ -106,6 +106,7 @@ const GroupModelModal = forwardRef(({
(({ + +