news 2026/9/13 5:42:27

langchainjs Model Profiles Generator:基于 models.dev API 自动生成类型安全模型能力画像

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
langchainjs Model Profiles Generator:基于 models.dev API 自动生成类型安全模型能力画像

langchainjs Model Profiles Generator:基于 models.dev API 自动生成类型安全模型能力画像

【免费下载链接】langchainjsThe agent engineering platform项目地址: https://gitcode.com/GitHub_Trending/la/langchainjs

langchainjs 仓库在internal/model-profiles中内置了一个内部 CLI 工具,用于从 models.dev API 拉取模型能力数据、叠加 provider 级与模型级覆盖配置,并基于 TypeScript 编译器 AST 生成与@langchain/coreModelProfile接口严格对齐的 TypeScript 文件。本文以该工具的官方文档 README 为主线,结合 cli.ts、config.ts、generator.ts 等源码,完整讲解其配置格式、字段映射、覆盖机制、AST 生成流程、路径安全校验与测试验证方式,读完后可直接掌握在一个 provider 包中接入并使用该生成器的全部要点。

工具定位与整体架构

模型能力画像(Model Profile)描述了每个模型的能力与约束:上下文窗口、最大输出 token、多模态输入输出、工具调用、结构化输出等。LangChain 的各个 provider 包(如langchain-openai)需要为每个模型维护一份这样的画像,用于运行时查询模型能力。手工维护这些数据既繁琐又容易滞后,而 Model Profiles Generator 将其自动化:

  • 自动数据拉取:从 models.dev API(https://models.dev/api.json)获取各 provider 最新模型数据;
  • Provider 级覆盖:对整个 provider 的所有模型统一施加配置修正;
  • 模型级覆盖:对单个模型做细粒度修正,且优先级高于 provider 级;
  • TypeScript AST 生成:使用 TypeScript Compiler API 构造代码节点,而非字符串拼接,保证生成结果类型安全;
  • 格式化工具集成:自动按项目格式化配置输出代码(README 中描述为 Prettier 集成,而当前源码实现中实际调用的是oxfmt,见下文“格式化与写盘”一节);
  • Monorepo 友好:基于pnpm --filter在 pnpm workspace 中运行,并内置 monorepo 根目录定位与路径安全校验;
  • 类型安全:生成代码匹配@langchain/core中的ModelProfile接口,接口定义见 profile.ts。

工具源码的组织结构如下(摘自 README 的 Architecture 一节,与实际目录一致):

internal/model-profiles/ ├── src/ │ ├── cli.ts # Command-line interface │ ├── config.ts # TOML config parsing and override logic │ ├── generator.ts # TypeScript code generation and API integration │ ├── api-schema.ts # TypeScript types for models.dev API │ └── tests/ # Test suite │ ├── config.test.ts │ └── generator.test.ts ├── package.json # Tool dependencies ├── vitest.config.ts # Test configuration └── README.md # This documentation

该工具是一个内部私有包:package.json 中name@langchain/model-profilesprivate: true,不对外发布。其核心依赖包括@iarna/toml(TOML 解析)、commander(CLI 参数解析)、typescript(AST 生成)、zod(API schema 校验)以及 workspace 内的@langchain/core(仅用于ModelProfile类型引用)。

快速开始:TOML 配置与运行命令

创建配置文件

按 README 的 Basic Usage 一节,在某个 provider 包中创建 TOML 配置文件(例如profiles.toml),最小可用配置只有两项:

provider = "openai" output = "src/chat_models/profiles.ts"
  • provider(必填):models.dev 中的 provider ID,例如openai。cli.ts 中会显式检查该字段,缺失时报错Provider name must be specified in the config file
  • output(必填):生成文件的输出路径,相对于配置文件所在目录解析(见 config.ts 中parseConfigparsed.outputconfigDir为基准的解析逻辑)。

仓库中的真实配置可参考 langchain-openai 的 profiles.toml:

provider = "openai" output = "src/chat_models/profiles.ts" # Overrides applicable to all OpenAI models [overrides] imageUrlInputs = true pdfInputs = true pdfToolMessage = true imageToolMessage = true toolChoice = true structuredOutput = true # Model-specific overrides for gpt-3.5-turbo [overrides."gpt-3.5-turbo"] imageUrlInputs = false pdfInputs = false pdfToolMessage = false imageToolMessage = false structuredOutput = false

运行生成器

按 README 的说明,通过 pnpm workspace 的--filter机制调用:

# From the model-profiles package pnpm --filter @langchain/model-profiles make --config profiles.toml # Or if running from within a provider package pnpm --filter @langchain/model-profiles make --config profiles.toml

这里的make是 package.json 中定义的 npm script,其实际执行命令为tsx src/cli.ts,即直接用 tsx 运行 TypeScript 入口 cli.ts。CLI 使用 commander 定义了一个必填选项--config <path>(指向 TOML 配置文件),执行流程为:parseConfig解析配置 →separateOverrides拆分两级覆盖 →generateModelProfiles拉取数据并生成文件。任何异常都会打印Error: <message>并以退出码 1 结束(见 cli.ts)。

配置文件完整格式

README 中给出的完整 TOML 结构如下,overrides部分可同时包含 provider 级与模型级两类条目:

# Required: Provider ID from models.dev provider = "openai" # Required: Output path for generated TypeScript file (relative to config file) output = "src/chat_models/profiles.ts" # Optional: Provider-level overrides (applied to all models) [overrides] maxInputTokens = 100000 toolCalling = true structuredOutput = true imageUrlInputs = true # Optional: Model-specific overrides (override provider-level settings) [overrides."gpt-4"] maxOutputTokens = 8192 [overrides."gpt-3.5-turbo"] maxInputTokens = 16385 imageUrlInputs = false

其中output是 TypeScript 接口中唯一必填的字段(provider在接口中标注为可选,但 CLI 会强制校验),overrides则是一个扁平的混合结构:顶层的 ModelProfile 字段名视为 provider 级覆盖,以模型名为 key 的嵌套表视为模型级覆盖。该设计在源码类型ConfigFileOverridesConfig中有明确定义(见 config.ts)。

字段映射:models.dev API 数据如何变成 ModelProfile

api-schema.ts用 Zod 定义了 models.dev API 的Model/Provider/ProviderMap结构(文件头注释说明其改编自 SST models.dev 项目的 schema,许可证为 Apache-2.0),每个模型包含limit.context/limit.output(上下文与输出上限)、modalities.input/modalities.output(模态数组,枚举值为textaudioimagevideopdf)、reasoningtool_callstructured_output等字段(见 api-schema.ts)。

generator.ts中的modelToProfile函数完成了 API 模型到ModelProfile的字段映射(见 generator.ts):

models.dev API 字段生成的 ModelProfile 字段说明
limit.contextmaxInputTokens输入上下文窗口(token)
limit.outputmaxOutputTokens最大输出 token 数
modalities.inputimageimageInputs图片输入
modalities.inputaudioaudioInputs音频输入
modalities.inputpdfpdfInputsPDF 输入
modalities.inputvideovideoInputs视频输入
modalities.outputimageimageOutputs图片输出
modalities.outputaudioaudioOutputs音频输出
modalities.outputvideovideoOutputs视频输出
reasoningreasoningOutput推理/思维链输出
tool_calltoolCalling工具调用
structured_outputstructuredOutput结构化输出

需要特别注意:imageUrlInputsimageToolMessagepdfToolMessagetoolChoice这几个ModelProfile字段不会由 API 数据自动产生——modelToProfile中没有对应映射(models.dev schema 中不含这些维度的信息),它们只能来自 TOML 配置中的[overrides]。这也解释了为什么 langchain-openai 的 profiles.toml 把imageUrlInputstoolChoice等写在 provider 级覆盖里。

ModelProfile接口的完整字段说明可参考 profile.ts:maxInputTokens表示输入上下文的总 token 预算(含 prompt、系统消息、对话历史),maxOutputTokens表示单次响应长度上限,imageUrlInputs表示可直接接受图片 URL 而非内嵌数据等,每个字段都附带 JSDoc 语义说明。

覆盖机制:provider 级 + 模型级两层合并

覆盖条目的分离

config.ts维护了一个白名单集合MODEL_PROFILE_FIELDS,包含 16 个合法字段名:maxInputTokensimageInputsimageUrlInputspdfInputsaudioInputsvideoInputsimageToolMessagepdfToolMessagemaxOutputTokensreasoningOutputimageOutputsaudioOutputsvideoOutputstoolCallingtoolChoicestructuredOutput(见 config.ts)。separateOverrides据此区分两类条目(见 config.ts):

  • key 命中白名单 → 归入providerOverrides(provider 级);
  • key 不在白名单且 value 是非数组对象 → 归入modelOverrides[modelName](模型级);
  • 其余条目(如白名单外、且不是嵌套对象的值)直接忽略。

config.test.ts中有对应单测:含invalidField: "should be ignored"的输入被验证不会进入providerOverrides(见 config.test.ts)。

合并优先级

applyOverrides的合并顺序是:基础画像(API 数据)→ provider 级覆盖 → 模型级覆盖,后者覆盖前者的同名字段(见 config.ts):

let result = { ...baseProfile }; if (providerOverrides) { result = { ...result, ...providerOverrides }; } // 模型级覆盖最后应用,优先级最高 if (modelOverrides) { result = { ...result, ...modelOverrides }; }

测试用例覆盖了全部四种场景:仅 provider 覆盖、仅模型覆盖、两者叠加(各自生效)、以及模型覆盖与 provider 覆盖冲突时模型覆盖胜出(如maxInputTokens基础值 1000 → provider 覆盖 2000 → 模型覆盖 3000,最终 3000,见 config.test.ts)。generator.test.ts也在端到端层面验证了 provider 覆盖(toolCalling: true出现在生成文件中)与模型覆盖(maxOutputTokens: 8192出现在生成文件中)各自及同时生效的情形(见 generator.test.ts)。

代码生成实现:TypeScript AST 与格式化写盘

generateModelProfiles是核心入口(见 generator.ts),其流程为:

  1. 拉取数据fetchProviderData通过全局fetch请求https://models.dev/api.json,使用AbortSignal.timeout(30000)设置 30 秒超时;HTTP 非 2xx 时抛出Failed to fetch models.dev API: <statusText>
  2. 定位 provider:从返回的ProviderMap中按 ID 取 provider,未找到时抛出Provider "<id>" not found in models.dev API(测试用例验证了这两个错误路径,见 generator.test.ts);
  3. 逐模型合并:遍历provider.models,对每个模型执行modelToProfile得到基础画像,再经applyOverrides合并两级覆盖;
  4. AST 生成generateTypeScript使用 TypeScript Compiler API 构造源码节点(见 generator.ts)。生成的文件结构固定为三段:
    • 一条带 JSDoc 头注释的 type-only import:import type { ModelProfile } from "@langchain/core/language_models/profile";,注释为 “This file was automatically generated by an automated script. Do not edit manually.”(该合成注释通过ts.addSyntheticLeadingComment添加);
    • 一个const PROFILES: Record<string, ModelProfile> = { ... }声明,每个模型名作为字符串 key,画像对象中值为undefined的字段会被过滤掉不输出;
    • export default PROFILES;
  5. 格式化与写盘:输出路径会再次经过 monorepo 路径校验(防御性检查,虽然parseConfig已校验过一次),输出目录不存在时自动mkdir -p递归创建(generator.test.ts验证了嵌套目录自动创建,见 generator.test.ts)。

格式化细节

README 的功能列表中描述为 “Prettier Integration: Automatically formats generated code using your project's Prettier config”,但当前源码实现(generator.ts顶部import { format } from "oxfmt")实际调用的是oxfmt,并从 monorepo 根目录加载.oxfmtrc.jsonc/.oxfmtrc.json作为格式化配置(loadOxfmtConfig,见 generator.ts)。若格式化失败(含配置不存在),工具仅打印警告并降级写出未格式化的代码,不会中断生成流程。generator.test.ts中通过 mockoxfmt模块验证了格式化确实被调用(见 generator.test.ts)。

生成产物与消费方式

生成产物是各 provider 包中的src/chat_models/profiles.ts。以 langchain-openai 的 profiles.ts 为例,文件头部带有 “automatically generated… Do not edit manually.” 注释,随后是PROFILES常量表,每个模型条目完整列出 14 个能力字段:

import type { ModelProfile } from "@langchain/core/language_models/profile"; const PROFILES: Record<string, ModelProfile> = { "gpt-5-nano": { maxInputTokens: 400000, imageInputs: true, audioInputs: false, pdfInputs: true, videoInputs: false, maxOutputTokens: 128000, reasoningOutput: true, imageOutputs: false, audioOutputs: false, videoOutputs: false, toolCalling: true, structuredOutput: true, imageUrlInputs: true, pdfToolMessage: true, imageToolMessage: true, toolChoice: true, }, // ... 更多模型 }; export default PROFILES;

消费端以 langchain-openai 的 base.ts 为例,通过import PROFILES from "./profiles.js"引入,并在get profile()访问器中按当前模型名查表:return PROFILES[this.model] ?? {}(见 base.ts)。因此生成器产出的静态画像表直接支撑了模型实例在运行时对自身能力的类型安全查询。仓库中langchain-google同样拥有生成产物 profiles.ts。

安全设计:monorepo 边界内的路径校验

由于工具会在文件系统中读写路径,config.ts实现了较完整的路径安全校验逻辑:

  • monorepo 根定位findMonorepoRoot,见 config.ts):以process.cwd()作为可信起点向上逐级查找,优先识别pnpm-workspace.yaml;备选指标是含"private": truepackage.json且同级存在turbo.json
  • INIT_CWD 处理:通过pnpm --filter运行时,pnpm 会把命令发起的原始工作目录写入环境变量INIT_CWDparseConfigINIT_CWD(或回退cwd())作为解析--config相对路径的基准,但会先验证该目录位于 monorepo 根之内,否则抛出路径越界错误(见 config.ts);
  • 双重校验输出路径outputparseConfig中相对配置文件目录解析并校验一次,在generateModelProfiles写盘前再防御性校验一次(validatePathInMonorepo,见 config.ts)。越界路径会抛出形如Path "..." resolves to "..." which is outside the monorepo root "..."的错误;
  • 测试同样遵守该约束:generator.test.ts的临时目录特意创建在 monorepo 根下的.test-temp中以满足路径校验(见 generator.test.ts)。

测试验证

工具的测试基于 vitest(pnpm --filter @langchain/model-profiles test对应 package.json 中的test: vitest run),覆盖三个层面:

  • config.test.ts:单测separateOverrides的白名单过滤、空/未定义输入、以及applyOverrides的四层合并优先级;
  • generator.test.ts:mock 全局fetchoxfmt模块,端到端验证生成文件包含import type { ModelProfile }const PROFILES、具体模型 key 与export default PROFILES,并覆盖 API 失败、provider 不存在等错误分支。

使用小结

  • 为某个 provider 生成画像只需两步:在 provider 包内写好含provider/output/ 可选[overrides]的 TOML,然后执行pnpm --filter @langchain/model-profiles make --config profiles.toml
  • output相对配置文件目录解析,且所有路径(config 基准目录、配置文件、输出文件)必须落在 monorepo 根之内;
  • 字段白名单之外的覆盖项会被静默忽略,模型级覆盖始终优先于 provider 级覆盖,二者都优先于 API 原始数据;
  • imageUrlInputsimageToolMessagepdfToolMessagetoolChoice四类字段无法从 API 自动获得,只能依赖[overrides]补齐;
  • 生成文件带 “Do not edit manually.” 头注释,属于再生成产物,人工修改会在下次生成时丢失;
  • 运行前提:位于 langchainjs 的 pnpm workspace 环境中执行(工具依赖 monorepo 根定位),且需要网络可达 models.dev API(30 秒超时)。

【免费下载链接】langchainjsThe agent engineering platform项目地址: https://gitcode.com/GitHub_Trending/la/langchainjs

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 5:41:43

ADHD生存操作系统:神经多样性适配的工程化实践

1. 项目概述&#xff1a;这不是一句玩笑话&#xff0c;而是一份真实存在的生活操作系统说明书“i-have-adhd”——当它作为一句短语出现在社交平台、评论区、甚至简历备注栏里&#xff0c;很多人第一反应是&#xff1a;“又一个网络梗&#xff1f;”但如果你真把它当成梗来刷&a…

作者头像 李华
网站建设 2026/9/13 5:41:22

SpringBoot乡村养鸭管理平台架构设计与实践

1. 项目背景与核心需求乡村养鸭产业作为传统农业的重要组成部分&#xff0c;长期以来面临着信息孤岛、管理粗放、产销脱节等痛点。基于SpringBoot的乡村养鸭户综合服务管理平台&#xff0c;正是针对这些行业痛点提出的数字化解决方案。这个平台本质上是一个垂直领域的产业互联网…

作者头像 李华
网站建设 2026/9/13 5:34:58

AI代理技能封装:将人脉资源转化为可复用token

1. 项目背景与核心概念 "colleague-skill--将冰冷的前同事变成温暖的token"这个项目名称乍看有些抽象&#xff0c;但结合当前AI代理和技能开发的热潮&#xff0c;其实揭示了一个非常实用的场景&#xff1a;如何将过往职场中积累的人脉资源转化为可复用的数字化资产。…

作者头像 李华