LangChain.js 如何用 bindTools 与 JsonOutputToolsParser 从文本中抽取结构化实体
2026/9/14 7:57:17 网站建设 项目流程

LangChain.js 如何用 bindTools 与 JsonOutputToolsParser 从文本中抽取结构化实体

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

假设你有一段自由文本,需要把其中的实体(人名、年龄、身高、发色等)抽成结构化的 JSON 对象。LangChain.js 仓库中给出了可直接运行的做法:用ChatOpenAI(或ChatAnthropic)的bindTools把 Zod schema 绑定为"函数",让模型按 schema 返回工具调用,再用JsonOutputToolsParser把这些工具调用解析成普通 JSON 数组。整条链路不需要执行任何工具,工具调用在这里纯粹充当结构化输出的载体。

主要示例代码在 examples/src/extraction/openai_tool_calling_extraction.ts,解析器实现在 json_output_tools_parsers.ts。

准备条件

  1. 一个 Node.js 项目,安装核心包与 OpenAI 集成包(安装方式来自 langchain-openai 包 README):
npm install @langchain/openai @langchain/core
  1. 设置 OpenAI API Key 环境变量:
export OPENAI_API_KEY=your-api-key
  1. 示例代码使用 Zod 3 的子路径导入zod/v3,而 examples 包 的devDependencies中是"zod": "^4.3.6"(peerDependencies 允许^3.25.76 || ^4),所以还需要安装:
npm install zod

另外,仓库约定所有 LangChain 包依赖同一个@langchain/core实例,README 建议在package.json中为pnpm/npm/yarn添加对应的 overrides 字段固定版本。

主路径:用 OpenAI 模型抽取实体

下面是仓库示例文件的完整代码,可直接保存为.ts文件后用tsxts-node运行:

import { z } from "zod/v3"; import { ChatOpenAI } from "@langchain/openai"; import { ChatPromptTemplate } from "@langchain/core/prompts"; import { JsonOutputToolsParser } from "@langchain/core/output_parsers/openai_tools"; const EXTRACTION_TEMPLATE = `Extract and save the relevant entities mentioned \ in the following passage together with their properties. If a property is not present and is not required in the function parameters, do not include it in the output.`; const prompt = ChatPromptTemplate.fromMessages([ ["system", EXTRACTION_TEMPLATE], ["human", "{input}"], ]); const person = z.object({ name: z.string().describe("The person's name"), age: z.string().describe("The person's age"), }); const model = new ChatOpenAI({ model: "gpt-3.5-turbo-1106", temperature: 0, }).bindTools([ { name: "person", description: "A person", schema: person, }, ]); const parser = new JsonOutputToolsParser(); const chain = prompt.pipe(model).pipe(parser); const res = await chain.invoke({ input: "jane is 2 and bob is 3", }); console.log(res);

各环节的作用:

  • Zod schema(person:定义要抽取的实体结构和字段说明。bindTools接收{ name, description, schema }形式的工具定义,name会成为解析结果中的实体类型标识。
  • ChatPromptTemplate:系统消息固定抽取规则(缺失且非必填的属性不要输出),人类消息用{input}占位,运行时传入待抽取的文本。
  • prompt.pipe(model).pipe(parser):标准的 Runnable 管道——提示词渲染后发给绑定工具的模型,模型输出交给解析器。
  • new ChatOpenAI({ model: "gpt-3.5-turbo-1106", temperature: 0 }):示例用低温度保证抽取稳定。模型名可按你的账户可用模型替换。

结果验证

示例文件注释中给出的运行输出(文档示例,实际内容会随模型输出略有差异):

[ { name: 'person', arguments: { name: 'jane', age: '2' } }, { name: 'person', arguments: { name: 'bob', age: '3' } } ]

判断抽取是否完成的依据有两条,都来自仓库文档:

  1. 结果数量:openai_tools.int.test.ts 中有一个 "Extraction" 集成测试,用同样的bindTools+JsonOutputToolsParser链路让模型输出两个笑话,断言expect(res.length).toBe(2)。也就是说,解析结果是数组,其长度对应模型返回的工具调用条数——你可以按待抽取实体的预期数量断言。
  2. 字段结构:按 解析器源码,每个解析结果的字段为{ type, args, id? },其中type是工具名(示例中为"person"),args是按 schema 解析出的对象;仅当构造解析器时传returnId: true时才带上id。Anthropic 变体示例注释中的输出正是这种结构:
[ { "type": "person", "args": { "name": "Alex", "height": 5, "hairColor": "blonde" } }, { "type": "person", "args": { "name": "Claudia", "height": 6, "hairColor": "brunette" } } ]

如果消息里没有tool_callsparsePartialResult返回空数组[];工具参数不是合法 JSON 时,parseToolCall会抛出OutputParserException

可选分支一:用 Anthropic 模型并强制选择工具

同样的模式适用于ChatAnthropic,仓库示例见 anthropic_tools/extraction.ts,需要额外安装@langchain/anthropic。与 OpenAI 主路径相比有两个差异:

import { z } from "zod/v3"; import { ChatAnthropic } from "@langchain/anthropic"; import { PromptTemplate } from "@langchain/core/prompts"; import { JsonOutputToolsParser } from "@langchain/core/output_parsers/openai_tools"; const prompt = PromptTemplate.fromTemplate(EXTRACTION_TEMPLATE); const schema = z.object({ name: z.string().describe("The name of a person"), height: z.number().describe("The person's height"), hairColor: z.optional(z.string()).describe("The person's hair color"), }); const model = new ChatAnthropic({ temperature: 0.1, model: "claude-3-sonnet-20240229", }) .bindTools([ { name: "person", description: "Extracts the relevant people from the passage.", schema, }, ]) .withConfig({ // Can also set to "auto" to let the model choose a tool tool_choice: { type: "tool", name: "person", }, }); const chain = await prompt.pipe(model).pipe(new JsonOutputToolsParser()); const response = await chain.invoke({ input: "Alex is 5 feet tall. Claudia is 1 foot taller than Alex and jumps higher than him. Claudia is a brunette and Alex is blonde.", });
  • z.optional(...)声明可缺失字段,主路径示例里则靠提示词约束"缺失属性不输出"。
  • 通过.withConfig({ tool_choice: { type: "tool", name: "person" } })强制模型调用指定工具;示例注释说明也可以设为"auto"让模型自行选择。chainawait出来的,因为withConfig返回 Promise。

可选分支二:只关心单一工具时用 JsonOutputKeyToolsParser

如果你的场景只绑定了一个抽取工具,解析器源码中还有JsonOutputKeyToolsParser:构造参数为{ keyName, returnSingle?, zodSchema?, serializableSchema?, returnId? }。它会过滤出type === keyName的调用,默认只返回argsreturnSingle: true时返回第一个结果而不是数组;提供zodSchemaserializableSchema时会对结果做 schema 校验,校验失败同样抛出OutputParserException

限制

  • 该链路依赖模型返回工具调用消息:模型没有产生tool_calls时解析结果为空数组,需要按你自己的任务逻辑判断是"文本中确实没有实体"还是"模型未按约定输出"。
  • JsonOutputToolsParser不校验字段内容(如args是否符合 schema),要做 schema 校验应使用带zodSchemaJsonOutputKeyToolsParser,或在拿到args后自行用 Zod 解析。
  • 示例中的模型名(gpt-3.5-turbo-1106claude-3-sonnet-20240229)来自仓库示例文件,实际运行时替换为你账户可访问的模型。

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

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

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

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

立即咨询