使用 Terraform 管理 Onyx 部署级默认 LLM 模型:onyx_llm_provider_default 资源完全指南
2026/9/10 3:06:43 网站建设 项目流程

使用 Terraform 管理 Onyx 部署级默认 LLM 模型:onyx_llm_provider_default 资源完全指南

【免费下载链接】danswerOpen Source AI Platform - AI Chat with advanced features that works with every LLM项目地址: https://gitcode.com/GitHub_Trending/da/danswer

本篇指南基于开源仓库 terraform-provider-onyx 中的官方文档 llm_provider_default.md 编写,并结合后端 API 与 Provider 源码进行纵深剖析。它适用于所有希望通过 Infrastructure as Code 方式统一管理 Onyx(开源 AI 平台)部署默认文本模型、默认视觉模型与聊天自动命名模型的平台工程师。

为什么需要一个"默认模型"资源

Onyx 是一个开源 AI 平台,其 LLM 供应商(Provider)体系允许管理员注册多个 Provider,每个 Provider 下再配置若干 Model Configuration。整个部署需要指定一个"部署级默认 LLM 模型"——它决定用户发起聊天时默认使用哪个 Provider 的哪个模型。

在 terraform-provider-onyx 中,这个默认值被建模为一个独立资源onyx_llm_provider_default,而不是 Provider 资源上的一个字段。官方文档(terraform-provider-onyx/docs/resources/llm_provider_default.md)给出的定位是:

The deployment-wide default LLM model — a singleton pointer at one provider + model pair (plus optional vision and chat auto-naming defaults).

即:它是一个单例指针,指向"一个 Provider + 一个模型"的组合,并可选附带默认视觉模型(vision)和聊天自动命名模型(chat auto-naming)的配置。

将其独立建模的核心价值在于依赖排序(depends_on ordering)

  • 当某个 Provider 需要被删除或缩减(shrunk)时,Terraform 需要先把"默认"指针重定向(repoint)到别的 Provider,再执行删除;
  • 由于onyx_llm_provider_default通过provider_id = onyx_llm_provider.xxx.id引用 Provider 的 id,Terraform 的依赖图会自动保证:先更新/重定向默认指针,再删除持有该默认的 Provider;
  • 这避免了删除默认 Provider 时后端报错或默认被意外清空的局面(后端 API 对持有 chat 默认的 Provider 删除有保护逻辑,详见下文)。

资源 Schema 详解

onyx_llm_provider_default的 Schema 由 llm_provider_default_resource.go 定义,共 7 个属性,分为三类:

Required(必填)

属性类型说明
provider_idString持有默认模型的onyx_llm_provider资源的 id。
model_nameString该 Provider 内的模型名称,例如gpt-5-mini。必须命中该 Provider 下可见的model_configurations之一(即必须与onyx_llm_provider中声明的model_configurations里的name对应)。

Optional(可选)

属性类型说明
vision_provider_idString默认视觉模型所在的 Provider id。
vision_model_nameString默认视觉模型名称。
chat_naming_provider_idString聊天自动命名专用模型的 Provider id。不设置时,自动命名使用当前会话(session)的模型;删除该对配置会清除服务器端值。
chat_naming_model_nameString聊天自动命名专用模型名称。

配对校验规则:源码中对这四个可选属性都配置了stringvalidator.AlsoRequires验证器,即:

  • vision_provider_idvision_model_name必须成对出现(不能只填其中一个);
  • chat_naming_provider_idchat_naming_model_name必须成对出现。

Read-Only(只读)

属性类型说明
idString恒为"default"。因为该资源是单例,id 固定不变。

完整示例配置

官方文档 Example Usage 与示例文件 resource.tf 给出了最小可用配置:

# The deployment-wide default model. Referencing the provider's id also # orders destroys correctly: the default is repointed/released before the # provider holding it is deleted. resource "onyx_llm_provider_default" "this" { provider_id = onyx_llm_provider.openai.id model_name = "gpt-5" vision_provider_id = onyx_llm_provider.openai.id vision_model_name = "gpt-5" }

下面是一个更贴近生产实践的组合示例:先创建两个 Provider,再分别把文本默认、视觉默认、聊天命名默认指向不同的模型组合。

# 供应商 A:负责文本对话 resource "onyx_llm_provider" "primary" { name = "openai-primary" provider_type = "openai" api_key = var.openai_api_key model_configurations = [ { name = "gpt-5" }, { name = "gpt-5-mini" }, { name = "gpt-5-nano" }, ] } # 供应商 B:负责视觉与命名 resource "onyx_llm_provider" "vision" { name = "openai-vision" provider_type = "openai" api_key = var.openai_api_key model_configurations = [ { name = "gpt-5" }, { name = "gpt-5-mini" }, ] } resource "onyx_llm_provider_default" "this" { # 部署级文本默认 provider_id = onyx_llm_provider.primary.id model_name = "gpt-5" # 部署级视觉默认 vision_provider_id = onyx_llm_provider.vision.id vision_model_name = "gpt-5" # 聊天自动命名默认 chat_naming_provider_id = onyx_llm_provider.primary.id chat_naming_model_name = "gpt-5-nano" }

底层原理:一次 apply 最多三次后端写入

onyx_llm_provider_default的 CRUD 实现在 llm_provider_default_resource.go 中,其核心是apply方法——它"最多做三次写入,把每次成功的结果叠加到 base 之上;失败时返回部分结果以及是否写过任何内容,以便调用方精确持久化服务器端已发生的变更"。

三次写入分别对应三个后端端点(client/llm_provider.go):

Terraform 字段HTTP 方法与路径说明
provider_id+model_namePOST /admin/llm/default设置部署级默认文本模型(SetDefaultLLMModel
vision_provider_id+vision_model_namePOST /admin/llm/default-vision设置部署级默认视觉模型(SetDefaultVisionModel
chat_naming_provider_id+chat_naming_model_namePOST /admin/llm/default-chat-naming设置聊天自动命名模型(SetDefaultChatNamingModel
(删除 chat-naming 对)DELETE /admin/llm/default-chat-naming清除聊天自动命名模型(ClearDefaultChatNamingModel

在 Go 客户端中,这些调用通过doJSON完成,例如:

// SetDefaultLLMModel sets the global default text model. func (c *Client) SetDefaultLLMModel(ctx context.Context, req DefaultModel) error { return c.doJSON(ctx, http.MethodPost, "/admin/llm/default", req, nil) }

DefaultModel结构体仅包含两个字段:ProviderID int64ModelName string(llm_provider.go),与文档中"一个 Provider + 一个 Model 的单例指针"定位完全一致。

后端 API 的对应实现

后端 FastAPI 路由定义在 backend/onyx/server/manage/llm/api.py:

  • POST /admin/llm/defaultupdate_default_provider(provider_id, model_name, ...),权限要求Permission.MANAGE_LLMS
  • POST /admin/llm/default-visionupdate_default_vision_provider(...)
  • POST /admin/llm/default-chat-namingupdate_default_chat_naming_provider(...),权限要求Permission.FULL_ADMIN_PANEL_ACCESS
  • DELETE /admin/llm/default-chat-namingupdate_no_default_chat_naming_provider(...),注释明确说明"清除专用命名模型后,自动命名回退到会话的模型"。

这解释了资源文档中的一个关键差异:文本与视觉默认没有 unset API,而聊天命名默认有

生命周期语义:创建、更新、读取、删除、导入

Create(创建)

Create以空 state 为 base 调用apply,把计划中的三个默认逐一写入。即便部分失败(如 vision 写入失败),也会把已成功的部分写入 state,确保 Terraform state 与服务器端实际状态一致(llm_provider_default_resource.go)。

Update(更新)

Update读取新旧 state,计算clearChatNaming:当计划中chat_naming_provider_id为 null 而旧 state 非 null 时,说明用户从配置中删除了 chat-naming 对,此时会调用DELETE /admin/llm/default-chat-naming清除服务器端值(llm_provider_default_resource.go)。

Read(读取)

Read调用GET /admin/llm/provider?include_image_gen=trueListLLMProviders)获取服务器端default_textdefault_visiondefault_chat_naming。值得注意的两个细节(llm_provider_default_resource.go):

  1. 若服务器端default_text为空,资源会直接从 state 中移除(RemoveResource);
  2. vision 与 chat-naming 默认只有在被 Terraform 管理(即 state 中非 null)时才会被刷新;未管理时,即使服务器端配置了,state 中也保持 null——避免 Terraform 接管未声明管理的配置。

Delete(删除)

Delete的行为是文档中特别强调、也是最容易踩坑的一点(llm_provider_default_resource.go):

  • 文本与视觉默认:Onyx 没有 unset API,因此销毁该资源后,服务器端的默认文本/视觉模型依然保留在原 Provider 上。Provider 只会发出一个 Warning:"Default LLM model left unchanged";
  • 聊天命名默认:如果 state 中管理了 chat-naming 对,删除时会调用DELETE /admin/llm/default-chat-naming将其清除。

换句话说:terraform destroy此资源 ≠ 清空部署默认。如果目标是把默认文本模型切回"无默认",该行为不被 API 支持,属于后端能力边界。

Import(导入)

该资源是单例,导入 id 恒为"default"(import.sh):

#!/bin/sh # Singleton: the import id is always "default". terraform import onyx_llm_provider_default.this default

ImportState会对非"default"的导入 id 直接报错(llm_provider_default_resource.go)。导入后的后续Read会自动从服务器端刷新provider_idmodel_name;vision 与 chat-naming 对则保持 null,直到用户在配置中显式声明。

与 onyx_llm_provider 的协同:删除顺序与 force_delete

将默认指针独立成资源的最大收益体现在 Provider 生命周期管理中。后端在删除 Provider 时存在保护逻辑(backend/onyx/server/manage/llm/api.py):

只有 chat 默认会阻止 Provider 删除。删除持有其他流程(文本/视觉)默认的 Provider,会"故意"连带清空该默认——这由测试test_delete_default_vision_provider_clears_vision_default覆盖。

也就是说:持有文本或视觉默认的 Provider 可以删除,但会连带丢失默认配置;而持有 chat 默认的 Provider 不允许删除,除非传force=true。后端逻辑如下:

model = fetch_default_llm_model(db_session) if model and model.llm_provider_id == provider_id: raise OnyxError( OnyxErrorCode.RESOURCE_IN_USE, "Cannot delete this provider: it holds the deployment's chat " "default model. Repoint that default first, or pass force=true.", )

因此,正确做法是让 Terraform 的依赖关系天然保证"先重定向、后删除":onyx_llm_provider_default引用onyx_llm_provider.id,删除 Provider 时 Terraform 会先重算默认指针,再执行 Provider 删除,避免RESOURCE_IN_USE报错。作为兜底,onyx_llm_provider还提供force_delete参数,允许在持有默认的情况下强制删除。

端到端验证:从 AccTest 看资源行为

资源的行为在 llm_provider_default_resource_test.go 的验收测试(AccTest)中被完整验证:

  1. 创建:创建onyx_llm_provider(带gpt-5-minigpt-5-nano两个 model_configurations 与force_delete = true),再创建onyx_llm_provider_default指向gpt-5-mini,断言id == "default"provider_id与 Provider 的id一致,并调用testAccCheckServerDefaultModel验证服务器端默认确实被设置;
  2. 更新:将model_name改为gpt-5-nano,再次断言服务器端默认同步更新;
  3. 导入:以ImportStateId = "default"执行导入并ImportStateVerify

这套测试同时覆盖了 Provider 与默认资源的联动,可以作为你在自己基础设施中编写配置时的参考模板。另外,client 层的单元测试(TestSetDefaultLLMModelTestSetDefaultVisionModelTestSetDefaultChatNamingModelTestClearDefaultChatNamingModel)直接验证了四个端点的请求路径与参数构造。

关键要点速查

  • onyx_llm_provider_default单例资源,id恒为"default",导入 id 也必须是"default"
  • provider_id+model_name是唯一必填组合,其余均为成对出现的可选属性;
  • 引用onyx_llm_provider.xxx.id而非硬编码数字 id,可获得正确的销毁顺序;
  • 销毁资源不会清空服务器端文本/视觉默认(无 unset API),仅会清除被管理的 chat-naming 默认;
  • 后端对"持有 chat 默认的 Provider 删除"有保护(RESOURCE_IN_USE),需要通过重定向默认或force_delete解决;
  • model_name必须命中 Provider 下可见的model_configurations,否则后端写入会失败。

通过将部署级默认 LLM 纳入 Terraform 管理,你可以把"哪个 Provider、哪个模型作为全局默认"这一关键决策版本化、可审计、可回滚,并与 Provider 资源、权限配置一起构成完整的 LLM 基础设施声明。

【免费下载链接】danswerOpen Source AI Platform - AI Chat with advanced features that works with every LLM项目地址: https://gitcode.com/GitHub_Trending/da/danswer

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询