Agent Note: 读取协议特定的模型列表
Status: implemented Archived: 2026-09-04
English | 中文
问题
提供方草稿询问决策最初只读取 OpenAI 兼容的 data 数组。一些兼容网关改为公布富信息 models 对象,而 Anthropic 公布了具有不同认证与 URL 规则的原生模型列表路由。把任一情况视为不受支持,都会迫使用户手工复制模型 id 和容量,即使端点已经公布这些信息。
向一个网关发送 OpenAI SDK User-Agent 可以使其返回 OpenAI 风格数组。该行为没有文档,改变了请求归属,并使回答取决于客户端身份而非受支持的响应解析器。
决策
dsh-llm-pi-ai 按所选协议格式读取模型列表。openai-completions 与 openai-responses 以 bearer 认证使用 GET \{baseURL\}/models。anthropic-messages 以 x-api-key 和 anthropic-version: 2023-06-01 使用 GET /v1/models?limit=1000。Anthropic 页大小采用文档规定的最大值;模型发现不会继续跟随 has_more,因此公布超过 1,000 个模型的端点只会暴露第一页。
Anthropic SDK 资源方法会自行追加 /v1,而网关文档会同时发布带与不带该后缀的 API 根地址。因此列表 URL 会把末尾为 /v1 的 Anthropic baseURL 草稿视为与不带该后缀的地址相同的 API 根地址,并且只有它会归一化这一段:模型请求收到的仍是配置原样的 baseURL,与 pi-ai 的处理完全一致。部署路径前缀会保留:https://gateway.example/tenant/v1 与 https://gateway.example/tenant 都在 /tenant/v1/models 列表。
解析器接受 data 数组或富信息 models 对象,并在数组存在时优先使用它。数组条目使用自身的 id;对象条目使用属性键,因为嵌套 id 可能指向规范模型,而不是请求所接受的路由别名。只有值为对象的映射条目才视为模型,因此原始类型的目录元数据不会意外成为候选。空属性键才会回退到嵌套 id。
解析器会把受支持的名称与容量拼写归一化为 LlmDiscoveredModel。缺失的显示名会变成请求 id,使采纳操作填入完整的可编辑行。请求保留 Harness 归属标头;网关兼容性由响应解析提供,而非冒充客户端身份。
考虑过的替代方案
跟随 Anthropic 的所有页面。 游标遍历可以返回超过 1,000 个条目的列表,但会给配置操作增加多请求失败、取消、游标推进与总大小处理。实现请求 Anthropic 的最大页面,并记录剩余截断限制。
同时归一化推理地址。 在模型路由前截掉同一段 /v1 可以让 /v1 地址既能列表也能服务,但这会把请求 URL 规则从 pi-ai 挪进本包,且只为一种协议。模型请求保持 pi-ai 自身对 baseURL 的处理;列表请求是本包构造的唯一 URL。
拒绝末尾的 /v1。 在加载或探测时拒绝可以尽早点出错误,但网关文档发布的就是 /v1 写法,照文档粘贴地址的用户会被一个本能工作的列表拒之门外。
为模型发现发送 OpenAI SDK User-Agent。 这会让一个网关返回 data,但会错误标记 Harness 流量,并依赖未记录的客户端名称分支。读取两种已知响应格式可以保持归属准确。
采纳 models 对象的每个属性。 原始类型属性不能证明其键是模型 id,也可能是数量或状态等目录元数据。把条目限制为记录可避免虚构模型候选。
后果
Models 页面无需改变请求身份,即可询问 OpenAI 兼容网关与 Anthropic Messages 端点。发现的候选会在端点提供时携带路由 id、名称、上下文窗口与最大输出 token 数,只有 id 的列表也会通过 id 回退获得可编辑标签。Anthropic 地址以根地址或 /v1 形式都能列表;模型请求使用 pi-ai 收到的配置地址。
受支持格式仍是显式兼容集合,而不是任意 JSON 推断。可见模型超过 1,000 个的 Anthropic 账户需要手工录入第一页之外的条目,原始类型的 models 属性会被忽略。
测试
本地 HTTP 服务器测试钉住两种受支持响应格式、字段归一化、名称回退、忽略畸形条目、Anthropic 标头、最大页查询,以及 Anthropic 根地址的两种写法。2026-09-02 从 OpenRouter、models.dev 与 DeepSeek 录得的回复,连同 Anthropic List Models 参考文档给出的示例回复,存放在 packages/llm/llm-pi-ai/tests/fixtures/model-listings/ 下并经解析器回放,因此受支持的字段拼写钉在真实端点与公开参考文档上,而不是手写样例上。