LiteLLM Terraform Provider 数据源litellm_models实战:从/v1/model/info读取代理上的全部模型部署
【免费下载链接】litellmThe fastest, litest AI Gateway. Rust core with Python SDK. Call 100+ LLM APIs in OpenAI (or native) format with cost tracking, guardrails, load balancing, and logging [Bedrock, Azure, OpenAI, Anthropic, OpenAI, VertexAI, vLLM, Nvidia NIM]项目地址: https://gitcode.com/GitHub_Trending/li/litellm
LiteLLM是一个以 Rust 核心 + Python SDK 构建的 AI 网关,能够以 OpenAI 兼容或各厂商原生格式调用 100+ 家大模型 API,并统一提供成本追踪、护栏、负载均衡与日志能力;其仓库内随源码一起维护了一个官方 Terraform Provider(源码位于 terraform/provider),让用户能用 IaC(基础设施即代码)方式管理 LiteLLM Proxy 上的模型、Team、Key、Budget 等资源。litellm_models正是该 Provider 中面向"批量读取模型部署信息"的只读数据源:本文以 terraform/provider/docs/data-sources/models.md 为骨架,结合同目录单条数据源文档 docs/data-sources/model.md 与 Go 实现源码,完整讲解它的作用、参数、导出属性、安全设计与底层调用链,并给出可直接运行的 HCL 示例。读完你将掌握如何用一条data "litellm_models"列出代理的全部模型、按 Team 过滤,并把模型名与 ID 喂给 Output、资源引用或下游编排。
一、数据源定位:清单(List)形态的模型读取器
在 LiteLLM Terraform Provider 中,围绕"模型部署"存在两个互补的只读数据源(Data Source,读取代理上已存在的对象、不创建不修改):
| 数据源 | 职责 | 对应代理 API |
|---|---|---|
litellm_model | 按model_id读取单个模型部署的完整路由元数据 | GET /v1/model/info?litellm_model_id=<id> |
litellm_models | 列出全部模型部署(可按team_id过滤) | GET /v1/model/info/GET /v1/model/info?teamId=<id> |
litellm_models的核心文档描述非常明确(见 docs/data-sources/models.md):
Lists all model deployments via
/v1/model/info. Sensitivelitellm_paramsfields (API keys and other credentials) are never exposed.
它通过 LiteLLM Proxy 的模型信息管理端点/v1/model/info拉取代理上注册的全部模型部署,并且出于安全考虑,绝不导出任何敏感凭据字段——例如api_key、aws_secret_access_key、vertex_credentials这类只存在于litellm_params中的密钥信息,永远不会进入 Terraform State。这正是设计上把该数据源定位为"安全路由元数据"读取器的直接证据:源码中定义请求体解析结构时,注释明确写着modelInfoParams intentionally maps only the non-sensitive litellm_params fields(见 litellm/data_source_model.go),该结构体只声明了model、custom_llm_provider、api_base、api_version、tpm、rpm六个非敏感字段。
二、Example Usage:最小可用示例
原文档给出的示例非常精简(docs/data-sources/models.md),一行data块即可拉取全部模型,配合 Terraform 的for表达式把"模型列表"投影成"模型名列表":
data "litellm_models" "all" {} output "model_names" { value = [for m in data.litellm_models.all.models : m.model_name] }要真正跑通这段代码,还需补齐 Provider 声明与鉴权配置。根据 Provider 主 README 中的用法(README.md),litellm_models依赖连接 LiteLLM Proxy 的api_base与虚拟 Key(Virtual Key):
terraform { required_providers { litellm = { source = "BerriAI/litellm" version = "~> 1.99.0" # Provider 版本与 LiteLLM Proxy 版本严格对齐 } } } provider "litellm" { api_base = var.litellm_api_base # 例如 http://localhost:4000 api_key = var.litellm_api_key # 具备 /v1/model/info 读取权限的 Key } data "litellm_models" "all" {} output "model_names" { value = [for m in data.litellm_models.all.models : m.model_name] } output "model_ids" { value = data.litellm_models.all.ids }版本注意事项:README 明确指出"Provider 版本就是 LiteLLM 版本"(README.md)。每个 LiteLLM 发布(dev、rc、stable)都会以与 Proxy 相同的版本号发布 Provider,并在 CI 中用代理自动生成的 OpenAPI 规格审计 Provider 调用的每一个端点。因此建议始终把 Provider 固定在与你所运行 Proxy 相同的大版本线上,例如
~> 1.99.0。
2.1 按 Team 过滤的进阶用法
把文档中的team_id参数(见 docs/data-sources/models.md)与模型名输出结合,就可以实现"只看某个团队能访问的模型":
data "litellm_team" "infra" { # 此处假设已有一个 litellm_team 数据源/资源提供 team_id } data "litellm_models" "infra_models" { team_id = data.litellm_team.infra.team_id } output "infra_model_providers" { value = { for m in data.litellm_models.infra_models.models : m.model_name => m.custom_llm_provider } }三、Argument Reference:入参说明
litellm_models只接受一个可选入参:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
team_id | string | 否 | 按"该 Team 可访问"过滤模型。传参后,Provider 会在请求/v1/model/info时追加?teamId=<team_id>查询串;不传则返回全部模型 |
该语义在 Go Schema 中定义得十分清晰(litellm/data_source_model.go):team_id的类型为TypeString、Optional: true,Description 为 "Filter models to those accessible by this team"。
从源码看,team_id不仅影响请求,还直接决定数据源 State 的 ID。读取逻辑(dataSourceLiteLLMModelsRead)在拿到team_id后首先改写端点,随后在收尾阶段执行:
d.SetId(GetStringValue(d.Get("team_id").(string), "all"))即:传了team_id时数据源 ID 等于该 Team ID,否则为常量字符串"all"(litellm/data_source_model.go)。这也是单元测试TestDataSourceModelsRead中断言d.Id()应为"team-1"的原因。
四、Attributes Reference:导出属性详解
除了全部入参外,litellm_models还会导出两个计算属性(Computed,由代理返回,不可由用户设置):
4.1ids:模型 ID 列表
类型为 string 列表,按model_info.id汇总本次返回的所有模型的 LiteLLM 模型 ID。在源码中对应 Schema 的"ids"字段(litellm/data_source_model.go),其值来源于响应的entry.ModelInfo.ID。
这些 ID 有一个非常实用的下游用途:它们是单条数据源litellm_model的model_id入参。按照单条数据源文档,model_id即为 LiteLLM 模型 ID,也就是代理在响应头x-litellm-model-id中返回的值(docs/data-sources/model.md)。也就是说litellm_models.ids天然可以循环喂给litellm_model,实现"先批量发现、再逐条获取完整细节"的两段式读取。
4.2models:模型对象列表
models是核心属性,为对象列表(List of Object),每一项导出的字段与语义如下(字段定义见 docs/data-sources/models.md):
| 字段 | 类型 | 说明 |
|---|---|---|
id | string | LiteLLM 模型 ID,即model_info.id |
model_name | string | 对外公开、用于路由的模型名(客户端实际请求时使用的名字) |
model | string | 底层litellm_params.model,即真正指向厂商的具体模型串,形如openai/gpt-4o、anthropic/claude-opus-4 |
custom_llm_provider | string | 该模型使用的 Provider,如openai、anthropic、bedrock、vertex_ai |
model_api_base | string | 配置了才有的 API Base URL,即litellm_params.api_base |
base_model | string | 用于定价(cost)与能力推断的基础模型名,如gpt-4o、claude-3-5-sonnet-20241022 |
tier | string | 模型层级,取值为free或paid |
mode | string | 模型模式,如chat(对话)、embedding(向量)、image_generation(图像生成)等 |
team_id | string | 若该部署被限定到某个 Team,则为对应 Team ID;否则为空 |
db_model | bool | 该部署是否存储在数据库中(DB 路径),而非来自 YAML 配置文件(Config 路径) |
Schema 中对上述每个字段的声明位于 litellm/data_source_model.go:除db_model为TypeBool外,其余全部为只读的Computed: true字符串。数据组装逻辑(litellm/data_source_model.go)展示了每个导出值与代理响应 JSON 的映射关系——例如model_name取自顶层entry.ModelName,而model、custom_llm_provider、model_api_base取自litellm_params,base_model、tier、mode、team_id、db_model取自model_info。
4.3 与单条数据源litellm_model的属性差异
值得注意:清单形态的litellm_models为了保持列表轻量,并未导出api_version、tpm(每分钟 Token 上限)、rpm(每分钟请求上限)这三个在单条litellm_model中提供的字段(对比 docs/data-sources/model.md)。因此当你需要某个具体部署的限流配额或 API 版本时,正确的姿势是用litellm_models先发现 ID,再通过litellm_model按 ID 精确读取完整信息。
五、安全设计:敏感凭据永不进入 Terraform State
这是该数据源最重要的设计约束,值得单独强调。官方文档与源码从三个层面共同保障:
- 白名单式解析结构:请求解析使用的
modelInfoParams只声明了六个非敏感字段,源码注释明示 "credentials (api_key,aws_secret_access_key, ...) must never reach state"(litellm/data_source_model.go)。 - 安全提示成文:单条数据源文档末尾专门设有 Security Note 一节(docs/data-sources/model.md),说明
litellm_params中的凭据材料(如api_key、aws_secret_access_key、vertex_credentials)绝不会被导出。 - State 落盘即隔离:由于 Provider 结构体层面就没有定义敏感字段,Terraform 根本不会把它们写入
.tfstate,更不会出现在terraform show/terraform output或计划差异中。
这也意味着litellm_models与管理资源的litellm_model的分工不同:创建/更新模型部署(需要提交model_api_key等敏感参数)属于 Resource 的职责(示例见 README.md),而读取侧的数据源负责在"可发现性"与"不泄露密钥"之间取得平衡。
六、源码级原理:从 HCL 到 HTTP 的完整调用链
把数据源接入 Provider 的注册点位于 terraform/provider/litellm/provider.go,注册名为字符串"litellm_models",值为工厂函数dataSourceLiteLLMModels()。随后 Terraform 在terraform plan/apply时触发其Read回调,完整流程如下(对应 litellm/data_source_model.go):
- 拼端点:默认端点为常量
endpointModelInfoV1 = "/v1/model/info"(同文件 L12)。若配置了team_id,则拼接?teamId=<url.QueryEscape(team_id)>,并对 Team ID 做 URL 转义。 - 发请求:调用
MakeRequest(client, "GET", endpoint, nil)发起 GET;失败时错误信息包装为"failed to list models: %w";随后handleResponse(resp, "listing models")统一处理非 2xx 状态码。 - 解析响应:响应按信封结构
modelInfoEnvelope{ Data json.RawMessage }反序列化,得到data字段的原始 JSON。 - 兼容两种返回形态:
modelDecodeInfoEntries先尝试把data当作单个对象解,失败再当作对象列表解(litellm/data_source_model.go)。源码注释解释了原因:/v1/model/info在DB 存储路径下返回单个对象,在Config 配置路径下返回单元素列表,两种形状都必须兼容。 - 组装 State:遍历 entries,并行填充
ids与models,db_model等布尔值按model_info.db_model原样映射;最后d.SetId(...)并写日志"[INFO] Successfully listed %d models"。
代理侧对应的管理端点实现位于 litellm/proxy/management_endpoints/model_management_endpoints.py,对 Proxy 上/v1/model/info返回内容与db_model(区分 DB 与 Config 部署)语义的进一步确认可深入该文件。
七、测试佐证:行为是被单测钉死的
Provider 对数据源行为的验证并不依赖真实代理,而是用 Go 标准库的httptest起假服务端,因此能精确断言请求与解析行为。TestDataSourceModelsRead(litellm/data_source_model_test.go)验证了四条关键约定:
- 请求必须是
GET /v1/model/info; - 配置
team_id后,URL 查询串必须携带teamId=team-1; - 解析后
ids的长度与顺序符合响应中的两条记录(id-1、id-2); models首项字段正确,包括model_name、custom_llm_provider与布尔类型的db_model。
测试中构造的响应{"model_name": "b", "litellm_params": {"model": "anthropic/b", "custom_llm_provider": "anthropic"}, ...}也反向印证了第三节属性映射表——model与custom_llm_provider正是从litellm_params中白名单提取的。
八、典型应用场景与最佳实践
基于上述能力与约束,litellm_models在真实 IaC 工作流中适合以下用途:
- 模型清单观测:将代理上全部已注册模型的
model_name、mode、tier投影为terraform output或写入外部系统的下游消费,便于审计"这台代理到底暴露了哪些模型"。 - 模型 ID 驱动的二次读取:把
data.litellm_models.all.ids与for_each结合,逐个交给litellm_model获取tpm/rpm/api_version等清单中不包含的字段,形成"清单 + 明细"的两层结构。 - Team 级模型可用性核对:借助
team_id过滤,核对某个 Team 实际可路由的模型集合,用于验证权限/模型绑定配置是否按预期生效。 - 配置与 DB 双来源梳理:利用导出的
db_model布尔值区分"来自 YAML 配置"与"来自数据库"的部署,帮助判断修改时该走 Config 热加载还是 DB 管理 API。
实践要点可归纳为三点:
- 版本对齐:把 Provider 版本固定在所运行 Proxy 的版本线(如
~> 1.99.0),避免 OpenAPI 审计覆盖之外的 API 漂移。 - 敏感信息走 Resource 而非 Data Source:读取侧永远拿不到密钥——这是特性而非限制;凡需提交
model_api_key等凭据的变更,一律走litellm_modelResource(参考 README.md 中声明 API Key 的方式)。 - 善用
ids与for表达式:清单数据源返回的是models对象列表与平行的ids字符串列表,HCL 中优先用for m in data.litellm_models.all.models : m.<字段>这类投影访问,语义更清晰。
如需继续深入,建议阅读同目录的姊妹数据源文档 docs/data-sources/model.md(单条读取、含tpm/rpm/api_version等字段)以及 Provider 主说明 README.md(版本策略、安装要求、全部资源/数据源能力总览),并在 litellm/data_source_model_test.go 中观察更多可被断言的边界行为。
【免费下载链接】litellmThe fastest, litest AI Gateway. Rust core with Python SDK. Call 100+ LLM APIs in OpenAI (or native) format with cost tracking, guardrails, load balancing, and logging [Bedrock, Azure, OpenAI, Anthropic, OpenAI, VertexAI, vLLM, Nvidia NIM]项目地址: https://gitcode.com/GitHub_Trending/li/litellm
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考