:用 YAML 声明式管理 LLM 供应商与模型能力)
DocsGPT 模型目录Model Catalogs用 YAML 声明式管理 LLM 供应商与模型能力【免费下载链接】DocsGPTPrivate AI platform for agents, assistants and enterprise search. Built-in Agent Builder, Deep research, Document analysis, Multi-model support, and API connectivity for agents.项目地址: https://gitcode.com/GitHub_Trending/do/DocsGPT本篇基于 DocsGPT 仓库中 模型目录 README 展开讲解如何用application/core/models/下的 YAML 文件声明式地管理各家 LLM 供应商的模型目录如何为已有供应商追加模型、零 Python 代码接入任意 OpenAI 兼容端点、编写独立 SDK 的供应商插件以及通过MODELS_CONFIG_DIR以运维侧 YAML 扩展现有目录。读完本文你可以独立完成 DocsGPT 中所有模型上下架、能力声明、多端点共存的接入工作并理解其背后 YAML 加载器 与 模型注册表 的合并、校验与失效机制。核心设计目录YAML与行为Provider 插件解耦DocsGPT 的模型注册采用分层设计这是理解整套 YAML 体系的前提每个application/core/models/下的*.yaml文件声明一个供应商的静态模型目录模型清单及其能力参数注册表在启动时加载所有 YAML再将其与application/llm/providers/下同名的 Provider 插件拼接join by provider nameProvider 插件负责行为——如何解析 API key、实例化哪个 LLM 类YAML 只负责数据——有哪些模型、什么能力。这一分工由插件基类 Provider 的文档字符串明确表述Concrete providers declare their name, the LLM class to instantiate, and how to resolve credentials from settings. Static model catalogs live in YAML underapplication/core/models/and are joined to the provider by name at registry load time. 因此在绝大多数场景下——增删模型、改能力参数——只需要改 YAML不碰 Python 代码。模型注册表 ModelRegistry 是进程级单例它在__init__中调用_load_models()将 BUILTIN_MODELS_DIR即application/core/models/与可选的运维目录一并加载最终形成self.models字典供/api/models与 模型校验 等调用方使用。为已有供应商追加模型只改两行 YAML以内置的 anthropic.yaml 为例供应商级defaults:块声明了该供应商所有模型共享的能力基线工具调用、附件类型、上下文窗口provider: anthropic defaults: supports_tools: true attachments: [image, pdf] context_window: 200000 models: - id: claude-opus-4-7 display_name: Claude Opus 4.7 description: Most capable Claude model for complex reasoning and agentic coding context_window: 1000000 supports_structured_output: true追加一个新模型只需在models:下追加两行models: - id: claude-3-7-sonnet display_name: Claude 3.7 Sonnet模型能力默认继承供应商的defaults:块仅在需要时才按模型覆盖例如单独放大上下文窗口- id: claude-3-7-sonnet display_name: Claude 3.7 Sonnet context_window: 500000改完重启应用新模型即出现在/api/models。这个defaults per-model override的合并逻辑在源码中由 _build_model 实现它内部用pick(field_name, fallback)依次取模型级覆盖值 → 供应商 defaults 值 → 内置兜底值内置兜底值与文档一致——supports_tools/supports_structured_output默认False、supports_streaming默认True、context_window默认128000、api_flavor默认chat_completions。注意模型id是持久化的引用键。模型id会被写入 agent / workflow 记录。一旦用户开始选用该模型不要重命名它的id——agent 与 workflow 行以自由字符串形式引用它若id消失系统会静默回退到默认模型而不是报错。仓库中 0015_token_usage_model_id 迁移 等 alembic 版本文件也印证了 token 用量按模型id归因的数据链路。零 Python 接入 OpenAI 兼容供应商一个 YAML 就是一个逻辑端点对于讲 OpenAI 线协议的端点Mistral、Together、Fireworks、Ollama 等接入完全不需要写 Python在该目录或你的MODELS_CONFIG_DIR放入一个使用openai_compatible插件的 YAML设置api_key_env指定的环境变量即可——不改settings.py不改 LLMCreator# mistral.yaml provider: openai_compatible display_provider: mistral # shown in /api/models response api_key_env: MISTRAL_API_KEY # env var the plugin reads at boot base_url: https://api.mistral.ai/v1 defaults: supports_tools: true context_window: 128000 models: - id: mistral-large-latest display_name: Mistral Large - id: mistral-small-latest display_name: Mistral Small设置MISTRAL_API_KEYsk-...并重启后Mistral 模型即以provider: mistral出现在/api/models。请求走 OpenAI 线协议底层就是OpenAILLM但端点与密钥用的是 Mistral 的。仓库内置的可运行示例是 examples/mistral.yaml.example含三个模型及description字段。几个从源码可直接印证的关键行为一个文件 一个逻辑端点。与普通供应商不同openai_compatible允许多个 YAML 文件共存每个文件携带自己的api_key_env与base_url。OpenAICompatibleProvider 重写了get_models()对每个 catalog 独立执行_materialize_yaml_catalog()把该文件的base_url和从环境变量读到的api_key预配置到每个模型对象上_with_endpoint中per-modelbase_url优先于 catalog 级base_url。环境变量未设置时静默跳过。插件读取os.environ.get(catalog.api_key_env)为空则整个目录被跳过并记录 INFO 级日志不报错——这是有意设计运维可能一次性投多份供应商 YAML 模板只给实际使用的那几个配密钥。base_url与api_key_env为必填。对openai_compatible缺失这两者会在启动时抛ValueErroropenai_compatible.py#L75-L84因为一个没有端点的兼容供应商目录毫无意义。旧式OPENAI_BASE_URLLLM_NAME本地端点模式仍受支持。若设置了OPENAI_BASE_URL与LLM_NAME插件会按逗号切分LLM_NAME动态生成模型_materialize_legacy_local_endpointdisplay_provider显示为openai用于 Ollama、LM Studio 等本地部署。需要独立 SDK 的供应商写一个 Provider 插件对不讲 OpenAI 线协议的供应商需在application/llm/providers/name.py增加一个 Python 文件from application.llm.providers.base import Provider from application.llm.my_provider import MyLLM class MyProvider(Provider): name my_provider llm_class MyLLM def get_api_key(self, settings): return settings.MY_PROVIDER_API_KEY完整步骤与文档一致注册插件在 application/llm/providers/init.py 的ALL_PROVIDERS中加一行该列表同时决定/api/models的展示顺序在 settings.py 中新增MY_PROVIDER_API_KEY配置项在application/core/models/下创建my_provider.yaml模型目录provider:值必须与插件name一致。插件的启用与否由基类 is_enabled 决定默认实现是bool(self.get_api_key(settings))——取不到 API key 的供应商不会向注册表贡献任何模型。此外filter_yaml_models()和extra_models()是两个可选钩子分别用于过滤 YAML 模型和追加 YAML 未声明的动态模型。YAML 完整字段参考以下 Schema 与 model_yaml.py 中 Pydantic 模型_ProviderFile/_ModelEntry/_CapabilityFields一一对应provider: string, required # matches the Provider plugins name # openai_compatible only — required for that provider, ignored for others display_provider: string # label shown in /api/models response api_key_env: string # name of the env var carrying the key base_url: string # endpoint URL defaults: # optional, applied to every model below supports_tools: bool # default false supports_structured_output: bool # default false supports_streaming: bool # default true attachments: [alias-or-mime, ...] # default [] context_window: int # default 128000 input_cost_per_token: float # default null output_cost_per_token: float # default null reasoning_effort: string # default null; none|minimal|low|medium|high|xhigh (subset is model-dependent) api_flavor: string # chat_completions (default) or responses models: # required - id: string, required # unique registry key; persisted in agent records display_name: string # default: id description: string # default: enabled: bool # default true; false hides from /api/models base_url: string # optional custom endpoint for this model upstream_model_id: string # default: id; the name actually sent to the provider # All defaults: fields above can be overridden here per-model.所有 Schema 模型都设置了extraforbidmodel_yaml.py#L61这意味着拼错的字段名不会静默忽略而是直接让启动失败——这是有意的防御性设计。reasoning_effort 与同一模型多种推理强度reasoning_effort会转发给 OpenAI 推理模型。合法取值是none、minimal、low、medium、high、xhigh但每个模型实际接受的是其中子集老 o 系列只接受low/medium/highGPT-5.5 增加xhigh。该字段在 YAML 加载时即被 validator 校验拼写错误会在启动时炸掉而不是在调用时变成上游 400- id: gpt-5.4-mini display_name: GPT-5.4 Mini reasoning_effort: medium若要把同一个上游模型以两种推理强度同时暴露为每个条目分配不同的id并指向同一个upstream_model_idid是注册表唯一键也是存入 agent 记录的键upstream_model_id才是真正发给上游的名字缺省等于id- id: gpt-5.4-mini-low display_name: GPT-5.4 Mini (Low Reasoning) upstream_model_id: gpt-5.4-mini reasoning_effort: low - id: gpt-5.4-mini-high display_name: GPT-5.4 Mini (High Reasoning) upstream_model_id: gpt-5.4-mini reasoning_effort: high两条在网络上都调用gpt-5.4-minitoken 用量归因到各自不同的id上成本看板因此能按推理强度拆分。这也是为什么upstream_model_id字段对一个上游模型、多个逻辑条目的模式至关重要。附件别名attachment aliasesattachments:列表可以混合人类可读的别名与原始 MIME 类型。别名在 _defaults.yaml 中定义别名展开为imageimage/png,image/jpeg,image/jpg,image/webp,image/gifpdfapplication/pdfaudioaudio/mpeg,audio/wav,audio/ogg展开规则在 _expand_attachments 中含/的条目视为原始 MIME 类型直接透传其余条目查别名表未定义的别名抛ModelYAMLError。需要精细控制时直接用原始 MIMEattachments: [image/png, image/webp] # only these two运维侧 YAMLMODELS_CONFIG_DIR 扩展与覆盖将MODELS_CONFIG_DIR环境变量或.env条目对应 settings.py#L74 的MODELS_CONFIG_DIR: Optional[str]指向一个目录。该目录下每个*.yaml都会在内置目录application/core/models/之后被加载。运维用途有三类新增openai_compatible供应商Mistral、Together、Fireworks、Ollama…无需 fork 仓库扩展现有供应商目录——在provider: anthropic下追加模型与内置模型并列展示覆盖内置模型能力——声明相同id、不同字段如更大的context_window后加载者获胜later wins且覆盖动作会记录WARNING日志便于审计。源码中对应两处证据ModelRegistry._load_models 将[BUILTIN_MODELS_DIR]与运维目录按序传入load_model_yamlsload_model_yamls 在遍历中维护seen_ids字典同一id跨文件重复定义时打出Model id %r redefined: %s overrides %s (later wins)的 WARNING。而后加载者获胜的合并最终由 Provider.get_models 完成重复id时新模型替换旧模型在原位置。MODELS_CONFIG_DIR做不到的事不能凭空添加非 OpenAI 线协议的新供应商——那需要application/llm/providers/下的 Python 插件见上一节。运维 YAML 只能指向一个已注册的provider:值指向未知插件会在启动时抛错错误信息会列出所有合法插件名model_registry.py#L166-L173。部署示例Docker 与 KubernetesDocker 场景——把模型 YAML 挂载进容器并指向挂载路径# docker-compose.yml services: app: image: arc53/docsgpt environment: MODELS_CONFIG_DIR: /etc/docsgpt/models MISTRAL_API_KEY: ${MISTRAL_API_KEY} volumes: - ./my-models:/etc/docsgpt/models:ro随后./my-models/mistral.yaml即 examples/mistral.yaml.example 的内容在启动时被加载。Kubernetes 场景——把包含 YAML 的ConfigMap挂载到固定路径在 Deployment 上设置MODELS_CONFIG_DIR同一份mistral.yaml.example成为 ConfigMap 中的一个 key。仓库提供了现成的部署清单可参考包括 deployment/k8s 下的 deployments 与 deployment/docker-compose.yaml。配置错误的容错行为若MODELS_CONFIG_DIR被设置但路径不存在或不是目录应用只会在启动时记录WARNING并继续以纯内置目录运行model_registry.py#L146-L157。应用不会因配置漂移而启动失败——运维可以安全地推送配置变更——但该 WARNING 足够响亮能在任何合理的日志聚合系统里浮出。启动期校验失败快、报错清YAML 在启动时经 Pydantic 解析model_yaml.py#L259-L291 的_load_one_yaml先yaml.safe_load再_ProviderFile.model_validate任何异常都包装成携带文件路径的ModelYAMLError。以下情况都会让应用带着清晰的错误信息启动失败顶层键未知extraforbid拦截拼写错误模型缺少idid校验器要求非空字符串附件别名未定义ModelYAMLError会列出所有合法别名并提示可用原始 MIME 类型provider:值没有对应注册的插件。文档对此明确表态这是有意设计——静默回退意味着用户在模型选择悄悄失效时毫无察觉直到真正调用 API 才暴露问题。相关行为可由 tests/core/test_models_config_dir.py 与 test_model_registry_yaml.py 复现验证。保留字段aliases尚未生效模型条目目前接受aliases:字段model_yaml.py#L103语义为解析到本模型的旧 ID 列表为未来重命名预留当前 Schema 接受该字段但尚无任何运行时逻辑处理它。如果你在做模型重命名迁移现阶段仍应避免直接改id可用新增id 保留旧条目的过渡方案。小结DocsGPT 的模型目录体系把模型数据与供应商行为清晰拆开日常模型上下架只碰application/core/models/下的 YAML接入 OpenAI 兼容端点连 Python 都不需要只有私有 SDK 供应商才落到application/llm/providers/插件层。配合MODELS_CONFIG_DIR的后加载覆盖机制与启动期 Pydantic 严格校验运维团队可以在不 fork、不重启代码的前提下扩展模型能力声明同时保证任何配置错误都在启动时快速暴露。相关延伸阅读YAML 加载器、分层注册表、插件注册表 与 Mistral 示例。【免费下载链接】DocsGPTPrivate AI platform for agents, assistants and enterprise search. Built-in Agent Builder, Deep research, Document analysis, Multi-model support, and API connectivity for agents.项目地址: https://gitcode.com/GitHub_Trending/do/DocsGPT创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考