深入解析 Continue 的 @continuedev/llm-info:模型元数据、能力声明与两步新增模型机制
【免费下载链接】continueopen-source coding agent项目地址: https://gitcode.com/GitHub_Trending/co/continue
导读
@continuedev/llm-info是 Continue(open-source coding agent)中负责"描述大语言模型"的轻量级核心包:它统一承载了模型模板(Templates)、能力声明(Capabilities,如工具调用、图片输入、流式输出、预测输出等)以及模型别名(Model aliases)三部分信息,与负责"API 类型翻译"的@continuedev/openai-adapters形成明确分工。读完本文,你将掌握LlmInfo与ModelProvider两大核心数据结构的字段语义、findLlmInfo与getAllRecommendedFor的底层匹配逻辑、当前 16 个内置 Provider 的组织方式,并理解"编辑一个 LlmInfo 对象 + 挂入 ModelProvider"两步新增模型的设计目标与真实落地现状。
一、包定位:llm-info 与 openai-adapters 的职责边界
@continuedev/llm-info在 README.md 中自我定位为:提供各类大语言模型(LLM)的信息,包括 embedding(嵌入)、reranking(重排)以及其他模型。它与同为 Continue 生态的@continuedev/openai-adapters的关系被明确区分:
| 关注点 | openai-adapters | llm-info |
|---|---|---|
| API 类型翻译 | 负责在不同 API 协议之间做转换 | 不涉及 |
| 模板(Templates) | — | 负责 |
| 能力(Capabilities) | — | 负责(工具调用、图片、流式、预测输出等) |
| 模型别名(Model aliases) | — | 负责 |
README 同时点明两者存在依赖方向:openai-adapters在部分场景下可能会依赖llm-info提供的信息。因此,llm-info 本质上是一份"模型事实数据库"——它不关心请求如何发出,只关心"某个模型是什么、能做什么、怎么配置"。
从包配置看(package.json),该包当前版本为1.0.10,采用 ESM 模块("type": "module"),通过tsc构建为dist/index.js并导出dist/index.d.ts类型声明,以@continuedev/llm-info的形式被核心模块引用。
二、核心类型体系:LlmInfo 与 ModelProvider
2.1 LlmInfo:单个模型的信息单元
LlmInfo在 src/types.ts 中定义,是描述"一个模型长什么样"的基础结构:
export interface LlmInfo { model: string; // providers: string[]; // TODO: uncomment and deal with the consequences displayName?: string; description?: string; contextLength?: number; maxCompletionTokens?: number; regex?: RegExp; chatTemplate?: ChatTemplate; /** If not set, assumes "text" only */ mediaTypes?: MediaType[]; recommendedFor?: UseCase[]; /** Any additional parameters required to configure the model */ extraParameters?: Parameter[]; }各字段语义如下:
model:必填,模型的规范标识符,例如gpt-4o、claude-sonnet-4-6。displayName:展示给用户的名字,例如GPT-4o、Claude Sonnet 4.6。description:模型的自然语言描述,常用于 UI 展示。例如 Anthropic 的claude-sonnet-4-6描述为 "Anthropic's latest and most capable Sonnet model with exceptional coding, reasoning, and multilingual performance."(见 anthropic.ts)。contextLength:上下文窗口长度(token 数),是 Continue 计算 prompt 预算的关键依据(见后文 BaseLLM 用法)。maxCompletionTokens:单次生成的最大补全 token 数。regex:模型别名匹配正则。当用户输入的模型名与model字段不完全一致时,通过正则进行模糊匹配(详见 2.4 节匹配逻辑)。chatTemplate:聊天模板枚举,当前在 types.ts 中仅有None = "none"一个取值,其余模板待实现(源码中留有// TODO)。mediaTypes:模型支持的媒体类型。不设置时默认仅支持文本。枚举定义见 types.ts:Text、Image、Audio、Video;并提供了便捷常量AllMediaTypes(四者全含)。Gemini 系列模型普遍设置mediaTypes: AllMediaTypes(见 gemini.ts)。recommendedFor:推荐使用场景,取值为UseCase联合类型:"chat" | "autocomplete" | "rerank" | "embed"(见 types.ts)。例如 embedding 模型models/text-embedding-004标记为recommendedFor: ["embed"],多数对话模型标记为["chat"]。extraParameters:配置该模型所需的附加参数,类型为Parameter[]。
其中Parameter结构(types.ts)定义了附加配置项的形态:
export interface Parameter { key: string; required: boolean; valueType: ParameterType; // "string" | "number" | "boolean" displayName?: string; description?: string; defaultValue?: any; }此外还有一个派生类型LlmInfoWithProvider = LlmInfo & { provider: string },用于在模型信息上再附加所属 Provider 标识(types.ts)。
2.2 ModelProvider:一组模型的容器
ModelProvider(types.ts)描述"某个 Provider 支持哪些模型":
export interface ModelProvider { id: string; displayName: string; // capabilities: ModelProviderCapability[]; // TODO: uncomment and deal with the consequences models: Omit<LlmInfo, "provider">[]; extraParameters?: Parameter[]; }id:Provider 的唯一标识,如openai、anthropic、gemini、ollama。displayName:展示名,如OpenAI、Anthropic。models:该 Provider 支持的全部模型列表。由于LlmInfo的provider字段仍处于注释状态(源码// providers: string[]; // TODO),模型通过挂在 Provider 的models数组上实现与 Provider 的绑定。extraParameters:Provider 级别的附加配置参数。README 特别说明:apiKey、apiBase以及model、provider被视为恒常存在,不重复声明。
类型中同样保留了未启用的ModelProviderCapability联合类型("stream" | "fim" | "image" | "template_chat" | "tools",见 types.ts),指向未来按 Provider 声明能力的演进方向,当前代码中以 TODO 注释挂起。
2.3 为什么模型必须绑定 Provider
README 强调了一个关键设计点:模型必须与 Provider 绑定,因为同一个模型在不同 Provider 下可能有不同的属性(例如上下文长度)。README 给出的实践原则是:
Define as much as possible in the base object, and then spread to update for the specific providers as needed.
即"在基础对象中尽可能多定义通用属性,然后针对具体 Provider 通过展开(spread)覆盖差异项"。
这一原则在仓库中有实例佐证:gpt-4o在 openai.ts 中声明contextLength: 128000并标记recommendedFor: ["chat"];而在 azure.ts 中,gpt-4o被重新声明为contextLength: 128_000(使用数字分隔符的等价写法),gpt-4o-mini亦然。两个 Provider 对同一模型的上下文长度认知保持一致,但未来若出现差异,即可通过 Provider 内的覆盖实现。
2.4 匹配逻辑:findLlmInfo 的别名解析机制
模型别名解析的核心实现在 src/index.ts 的findLlmInfo函数:
export function findLlmInfo( model: string, preferProviderId?: string, ): LlmInfoWithProvider | undefined { if (preferProviderId) { const provider = allModelProviders.find((p) => p.id === preferProviderId); const info = provider?.models.find((llm) => llm.regex ? llm.regex.test(model) : llm.model === model, ); if (info) { return { ...info, provider: preferProviderId, }; } } return allLlms.find((llm) => llm.regex ? llm.regex.test(model) : llm.model === model, ); }其匹配策略包含三个要点:
- 优先 Provider 限定:若传入
preferProviderId,先在对应 Provider 的模型列表中查找;命中则返回带该 Provider 标识的LlmInfoWithProvider。 - regex 优先于精确匹配:对每个模型,若定义了
regex则用正则测试模型名,否则回退到llm.model === model的精确比较。这实现了模型别名能力——例如 Anthropic 的claude-sonnet-4-6定义regex: /claude-(?:4[.-]6-sonnet|sonnet-4[.-]6).*/i,因此claude-4-6-sonnet、claude-sonnet-4-6等书写形式都能命中同一条信息。 - 全量兜底:未指定 Provider 或 Provider 内未命中时,遍历
allLlms(所有 Provider 模型扁平化后的全集)再次匹配。
值得注意的细节是 regex 与匹配顺序的耦合:在 anthropic.ts 中有一行注释// order matters for regex conflicts,并刻意将claude-opus-4.1的条目放在claude-opus-4之前——因为claude-opus-4的正则/claude-(?:4-opus|opus-4).*/i可能误吞claude-opus-4.1,数组顺序保证了更具体的正则先被命中。这是维护模型条目时必须遵守的隐性规则。
2.5 聚合导出:allModelProviders 与 allLlms
src/index.ts 提供两个聚合导出:
allModelProviders:当前全部 16 个 Provider 的数组,包括OpenAi、Gemini、Anthropic、Mistral、Voyage、Azure、Ollama、Vllm、Bedrock、Cohere、CometAPI、Inception、MiniMax、xAI、zAI(另有os.ts中的本地模型集合被 Ollama 复用)。新增 Provider 时需在此登记。allLlms:通过flatMap将所有 Provider 的模型展开并附加provider字段,形成LlmInfoWithProvider[]全量扁平列表。
另有getAllRecommendedFor(useCase)(src/index.ts)按UseCase过滤出推荐模型,例如getAllRecommendedFor("embed")会返回所有标记了recommendedFor: ["embed"]的 embedding 模型。
三、内置 Provider 与模型数据的组织方式
3.1 目录组织现状
README 描述的目标结构是"模型定义在models目录、Provider 定义在providers目录",但从当前仓库的实际布局看,模型定义已直接内联在各 Provider 文件中(位于 packages/llm-info/src/providers 目录),每个文件导出一个ModelProvider常量,例如:
- openai.ts:GPT-3.5/GPT-4/GPT-4o/GPT-4.1/GPT-5/o 系列与
text-embedding-*系列,覆盖 chat 与 embed 两类 UseCase。 - anthropic.ts:从
claude-instant-1.2到claude-sonnet-4-6/claude-opus-4-6的完整 Claude 谱系。 - gemini.ts:Gemini 3.1 / 3 / 2.5 / 2.0 系列,普遍声明
mediaTypes: AllMediaTypes,并附注官方文档中的弃用时间线(如 "Gemini 2.5 series (deprecating June 17, 2026)")。 - azure.ts:声明
extraParameters: [],展示 Provider 级附加参数的写法。 - ollama.ts:直接复用 os.ts 导出的
OsLlms(当前仅含starcoder2:3b,contextLength: 8192),演示了模型数组跨 Provider 复用的模式。
3.2 一个完整的 Provider 定义示例
以 OpenAI 为例(openai.ts),一条模型条目通常包含:
{ model: "gpt-5.1", displayName: "GPT-5.1", contextLength: 400000, maxCompletionTokens: 128000, regex: /^gpt-5\.1$/, recommendedFor: ["chat"], }可以看到,模型条目充分利用了regex做精确别名锚定(/^gpt-5\.1$/不会误匹配gpt-5.1-mini之类的变体),同时为不同模型族(gpt-4.1 系列、gpt-5 系列、o 系列、codex 系列)标注了各自独立的上下文与最大输出长度。这印证了 README 中"模型分组可依据语义自由组织"的说明——同一 Provider 内部按系列分组排列,便于维护。
四、llm-info 在 Continue 中的实际消费点
README 的 "Where to use llm-info" 章节列出了三个消费方向,其中部分已在当前仓库落地:
4.1 BaseLLM 构造函数:运行时自动检测模型参数(已落地)
在 core/llm/index.ts 中,BaseLLM构造函数通过findLlmInfo实现参数自动检测:
// Use @continuedev/llm-info package to autodetect certain parameters const llmInfo = findLlmInfo(this.model, this.underlyingProviderName); // ... this._contextLength = options.contextLength ?? llmInfo?.contextLength; this.completionOptions = { ...options.completionOptions, model: options.model || "gpt-4", maxTokens: options.completionOptions?.maxTokens ?? (llmInfo?.maxCompletionTokens ? Math.min( llmInfo.maxCompletionTokens, // Even if the model has a large maxTokens, we don't want to use that every time, // because it takes away from the context length this.contextLength / 4, ) : DEFAULT_MAX_TOKENS), };这一实现揭示了 llm-info 的运行时价值:
- 上下文长度兜底:用户未显式配置
contextLength时,直接采用 llm-info 中登记的llmInfo.contextLength。 - 最大输出 token 的防御性钳制:即使模型支持很大的
maxCompletionTokens(如 128000),也取min(maxCompletionTokens, contextLength / 4)作为默认值——代码注释明确解释原因:过大的 maxTokens 会挤占上下文预算。 - Provider 感知:
findLlmInfo的第二参传入this.underlyingProviderName,让检测优先在当前 Provider 范围内进行。
4.2 测试与工具代码中的消费(已落地)
- core/llm/index.test.ts 直接导入
allModelProviders,对全部 Provider 执行遍历式测试,说明 llm-info 聚合数据是核心层单元测试的输入源。 - core/llm/llms/CometAPI.ts 通过
allModelProviders.find((p) => p.id === "cometapi")按 id 精确取回 Provider 数据,演示了"按 id 索引 Provider"的典型用法。
4.3 尚未完全落地的两个方向
README 还列出了两个演进方向,从仓库现状看仍未完全替换:
- 替换
core/llm/autodetect.ts:该文件(autodetect.ts)仍保留独立的模型能力检测逻辑(如modelSupportsImages、modelSupportsReasoning等基于字符串/正则的推断函数),说明 llm-info 尚未全面接管 autodetect 职责。 - 替换
gui/pages/AddNewModel/configs/[providers/models].ts:经检索 GUI 目录未发现该路径下的对应文件,表明 GUI 侧"添加新模型"配置页的数据源迁移也未完成。
因此,"用 llm-info 替换 autodetect、并在所有相关位置统一使用 llm-info"仍是 README 标注的进行中工作。
五、设计目标:两步新增一个模型
README 用一句话定义了 llm-info 的完成标准(Done criteria):
We know we are done when the steps required to add support for a new model in Continue are exactly
- editing a single LlmInfo object, and
- adding it to the supporting ModelProviders.
即:在 Continue 中为某个新模型添加支持,只需(1)编辑一个 LlmInfo 对象,(2)将其加入支持的 ModelProvider——仅此两步。
对照当前仓库,这套流程的操作形态如下:
- 在对应 Provider 文件(如 openai.ts 或 anthropic.ts)中新增/编辑一个
LlmInfo对象,填充model、displayName、contextLength、maxCompletionTokens、recommendedFor等字段;若模型存在命名变体,补一个regex字段即可获得别名匹配能力。 - 将该对象加入目标 Provider 的
models数组;若是一个全新厂商,还需新建 Provider 文件并在 src/index.ts 的allModelProviders数组中登记(注意第 3.2 节提到的 regex 冲突时的顺序规则)。
从"模型必须挂在 Provider 下、且可针对 Provider 覆盖属性"的设计来看,两步走的目标是让模型元数据成为单一事实来源:运行时通过findLlmInfo自动推导上下文长度与最大输出 token,UI 通过displayName/recommendedFor/extraParameters渲染配置表单,测试通过allModelProviders覆盖全部条目——而这一切都源自集中式的 LlmInfo 数据,这正是该包存在的意义。
六、小结
@continuedev/llm-info用两个核心接口(LlmInfo+ModelProvider)外加三个查询函数(findLlmInfo、getAllRecommendedFor、allLlms聚合),把 Continue 的模型事实层从"各处硬编码的字符串判断"收敛为"可枚举、可测试、可自动检测的数据表"。对使用者而言:查询模型能力看findLlmInfo,扩展模型看 Provider 文件与allModelProviders登记表,理解模型差异看regex与按 Provider 覆盖的contextLength。其"两步新增模型"的设计目标与 BaseLLM 中的自动检测实现,共同构成了 Continue 模型接入层"配置驱动、数据优先"的底层范式。
【免费下载链接】continueopen-source coding agent项目地址: https://gitcode.com/GitHub_Trending/co/continue
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考