如何使用输出解析器将LLM响应解析为结构化格式
语言模型输出的是文本。但在某些情况下,您可能希望获得比纯文本更结构化的信息。尽管某些模型提供商支持返回结构化输出的内置方法,但并非全部都支持。对于这些提供商,您必须使用提示来引导模型以期望的格式返回结构化数据。
LangChain 提供了输出解析器,可帮助将模型输出解析为可用的对象。我们将在下面介绍几个示例。
开始之前
用于处理模型响应中结构化数据的主要输出解析器类型是
StructuredOutputParser。在下面的示例中,我们将使用
zod 定义我们期望模型输出类型的模式:
首先,让我们看一下将插入提示中的默认格式说明:
Pick your chat model:
- Groq
- OpenAI
- Anthropic
- Google Gemini
- FireworksAI
- MistralAI
- VertexAI
Install dependencies
- npm
- yarn
- pnpm
npm i @langchain/groq
yarn add @langchain/groq
pnpm add @langchain/groq
Add environment variables
GROQ_API_KEY=your-api-key
Instantiate the model
import { ChatGroq } from "@langchain/groq";
const model = new ChatGroq({
model: "llama-3.3-70b-versatile",
temperature: 0
});
Install dependencies
- npm
- yarn
- pnpm
npm i @langchain/openai
yarn add @langchain/openai
pnpm add @langchain/openai
Add environment variables
OPENAI_API_KEY=your-api-key
Instantiate the model
import { ChatOpenAI } from "@langchain/openai";
const model = new ChatOpenAI({
model: "gpt-4o-mini",
temperature: 0
});
Install dependencies
- npm
- yarn
- pnpm
npm i @langchain/anthropic
yarn add @langchain/anthropic
pnpm add @langchain/anthropic
Add environment variables
ANTHROPIC_API_KEY=your-api-key
Instantiate the model
import { ChatAnthropic } from "@langchain/anthropic";
const model = new ChatAnthropic({
model: "claude-3-5-sonnet-20240620",
temperature: 0
});
Install dependencies
- npm
- yarn
- pnpm
npm i @langchain/google-genai
yarn add @langchain/google-genai
pnpm add @langchain/google-genai
Add environment variables
GOOGLE_API_KEY=your-api-key
Instantiate the model
import { ChatGoogleGenerativeAI } from "@langchain/google-genai";
const model = new ChatGoogleGenerativeAI({
model: "gemini-2.0-flash",
temperature: 0
});
Install dependencies
- npm
- yarn
- pnpm
npm i @langchain/community
yarn add @langchain/community
pnpm add @langchain/community
Add environment variables
FIREWORKS_API_KEY=your-api-key
Instantiate the model
import { ChatFireworks } from "@langchain/community/chat_models/fireworks";
const model = new ChatFireworks({
model: "accounts/fireworks/models/llama-v3p1-70b-instruct",
temperature: 0
});
Install dependencies
- npm
- yarn
- pnpm
npm i @langchain/mistralai
yarn add @langchain/mistralai
pnpm add @langchain/mistralai
Add environment variables
MISTRAL_API_KEY=your-api-key
Instantiate the model
import { ChatMistralAI } from "@langchain/mistralai";
const model = new ChatMistralAI({
model: "mistral-large-latest",
temperature: 0
});
Install dependencies
- npm
- yarn
- pnpm
npm i @langchain/google-vertexai
yarn add @langchain/google-vertexai
pnpm add @langchain/google-vertexai
Add environment variables
GOOGLE_APPLICATION_CREDENTIALS=credentials.json
Instantiate the model
import { ChatVertexAI } from "@langchain/google-vertexai";
const model = new ChatVertexAI({
model: "gemini-1.5-flash",
temperature: 0
});
import { z } from "zod";
import { RunnableSequence } from "@langchain/core/runnables";
import { StructuredOutputParser } from "@langchain/core/output_parsers";
import { ChatPromptTemplate } from "@langchain/core/prompts";
const zodSchema = z.object({
answer: z.string().describe("answer to the user's question"),
source: z
.string()
.describe(
"source used to answer the user's question, should be a website."
),
});
const parser = StructuredOutputParser.fromZodSchema(zodSchema);
const chain = RunnableSequence.from([
ChatPromptTemplate.fromTemplate(
"Answer the users question as best as possible.\n{format_instructions}\n{question}"
),
model,
parser,
]);
console.log(parser.getFormatInstructions());
You must format your output as a JSON value that adheres to a given "JSON Schema" instance.
"JSON Schema" is a declarative language that allows you to annotate and validate JSON documents.
For example, the example "JSON Schema" instance {{"properties": {{"foo": {{"description": "a list of test words", "type": "array", "items": {{"type": "string"}}}}}}, "required": ["foo"]}}}}
would match an object with one required property, "foo". The "type" property specifies "foo" must be an "array", and the "description" property semantically describes it as "a list of test words". The items within "foo" must be strings.
Thus, the object {{"foo": ["bar", "baz"]}} is a well-formatted instance of this example "JSON Schema". The object {{"properties": {{"foo": ["bar", "baz"]}}}} is not well-formatted.
Your output will be parsed and type-checked according to the provided schema instance, so make sure all fields in your output match the schema exactly and there are no trailing commas!
Here is the JSON Schema instance your output must adhere to. Include the enclosing markdown codeblock:
```json
{"type":"object","properties":{"answer":{"type":"string","description":"answer to the user's question"},"source":{"type":"string","description":"source used to answer the user's question, should be a website."}},"required":["answer","source"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}
```
接下来,让我们调用这个链:
const response = await chain.invoke({
question: "What is the capital of France?",
format_instructions: parser.getFormatInstructions(),
});
console.log(response);
{
answer: "The capital of France is Paris.",
source: "https://en.wikipedia.org/wiki/Paris"
}
输出解析器实现了Runnable 接口,这是LangChain 表达式语言(LCEL)的基本构建块。这意味着它们支持invoke、stream、batch和streamLog调用。
验证
StructuredOutputParser的一个特性是它支持更严格的 Zod 验证。例如,如果你传递了一个不符合模式的模拟模型输出,我们将得到一个详细的类型错误:
import { AIMessage } from "@langchain/core/messages";
await parser.invoke(new AIMessage(`{"badfield": "foo"}`));
Error: Failed to parse. Text: "{"badfield": "foo"}". Error: [
{
"code": "invalid_type",
"expected": "string",
"received": "undefined",
"path": [
"answer"
],
"message": "Required"
},
{
"code": "invalid_type",
"expected": "string",
"received": "undefined",
"path": [
"source"
],
"message": "Required"
}
]
相较于:
await parser.invoke(
new AIMessage(`{"answer": "Paris", "source": "I made it up"}`)
);
{ answer: "Paris", source: "I made it up" }
更高级的 Zod 验证也受支持。要了解更多信息,请查看 Zod 文档。
流式处理
虽然所有解析器都是可运行的并支持流式接口,但只有某些解析器能够通过部分解析的对象进行流式传输,因为这高度依赖于输出类型。StructuredOutputParser
不支持部分流式传输,因为它会在每个步骤验证输出。如果你尝试使用带有此输出解析器的链进行流式传输,该链将仅生成完全解析后的输出:
const stream = await chain.stream({
question: "What is the capital of France?",
format_instructions: parser.getFormatInstructions(),
});
for await (const s of stream) {
console.log(s);
}
{
answer: "The capital of France is Paris.",
source: "https://en.wikipedia.org/wiki/Paris"
}
不过,更简单的
JsonOutputParser
支持通过部分输出进行流式传输:
import { JsonOutputParser } from "@langchain/core/output_parsers";
const template = `Return a JSON object with a single key named "answer" that answers the following question: {question}.
Do not wrap the JSON output in markdown blocks.`;
const jsonPrompt = ChatPromptTemplate.fromTemplate(template);
const jsonParser = new JsonOutputParser();
const jsonChain = jsonPrompt.pipe(model).pipe(jsonParser);
const stream = await jsonChain.stream({
question: "Who invented the microscope?",
});
for await (const s of stream) {
console.log(s);
}
{}
{ answer: "" }
{ answer: "The" }
{ answer: "The invention" }
{ answer: "The invention of" }
{ answer: "The invention of the" }
{ answer: "The invention of the microscope" }
{ answer: "The invention of the microscope is" }
{ answer: "The invention of the microscope is attributed" }
{ answer: "The invention of the microscope is attributed to" }
{ answer: "The invention of the microscope is attributed to Hans" }
{ answer: "The invention of the microscope is attributed to Hans L" }
{
answer: "The invention of the microscope is attributed to Hans Lippers"
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey"
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey,"
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zach"
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias"
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Jans"
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen"
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen,"
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and"
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Anton"
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie"
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 4 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 8 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 12 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 13 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 18 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 20 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 26 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 29 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 33 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 38 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 43 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 48 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 51 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 52 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 57 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 63 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 73 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 80 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 81 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 85 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 94 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 99 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 108 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 112 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 118 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 127 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 138 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 145 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 149 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 150 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 151 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 157 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 159 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 163 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 167 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 171 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 175 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 176 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 181 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 186 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 190 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 202 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 203 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 209 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 214 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 226 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 239 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 242 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 246 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 253 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 257 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 262 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 265 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 268 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 273 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 288 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 300 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 303 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 311 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 316 more characters
}
{
answer: "The invention of the microscope is attributed to Hans Lippershey, Zacharias Janssen, and Antonie van"... 317 more characters
}
下一步
你已经了解了如何使用输出解析器来解析模型输出中的结构化内容。
接下来,可以查看工具调用指南,这是某些模型提供商支持的一种更内置的获取结构化输出的方式;或者进一步阅读关于其他类型结构化数据(如XML)的输出解析器相关内容。