如何在不使用函数调用情况下进行提取
先决条件
本指南假设您熟悉以下内容
能够很好地遵循提示指令的 LLM 可以被要求以给定的格式输出信息,而无需使用函数调用。
这种方法依赖于设计良好的提示,然后解析 LLM 的输出以使其能够很好地提取信息,尽管它缺乏函数调用或 JSON 模式提供的一些保证。
在这里,我们将使用 Claude,它非常擅长遵循指令!有关 Anthropic 模型的更多信息,请参阅此处。
首先,我们将安装集成包
提示
有关安装集成包的一般说明,请参阅此部分。
- npm
- yarn
- pnpm
npm i @langchain/anthropic @langchain/core zod zod-to-json-schema
yarn add @langchain/anthropic @langchain/core zod zod-to-json-schema
pnpm add @langchain/anthropic @langchain/core zod zod-to-json-schema
import { ChatAnthropic } from "@langchain/anthropic";
const model = new ChatAnthropic({
model: "claude-3-sonnet-20240229",
temperature: 0,
});
提示
所有与提取质量相关的相同注意事项都适用于解析方法。
本教程旨在简单,但通常应该真正包含参考示例以提高性能!
使用 StructuredOutputParser
以下示例使用内置的StructuredOutputParser
来解析聊天模型的输出。我们使用解析器中包含的内置提示格式化指令。
import { z } from "zod";
import { StructuredOutputParser } from "langchain/output_parsers";
import { ChatPromptTemplate } from "@langchain/core/prompts";
let personSchema = z
.object({
name: z.optional(z.string()).describe("The name of the person"),
hair_color: z
.optional(z.string())
.describe("The color of the person's hair, if known"),
height_in_meters: z
.optional(z.string())
.describe("Height measured in meters"),
})
.describe("Information about a person.");
const parser = StructuredOutputParser.fromZodSchema(personSchema);
const prompt = ChatPromptTemplate.fromMessages([
[
"system",
"Answer the user query. Wrap the output in `json` tags\n{format_instructions}",
],
["human", "{query}"],
]);
const partialedPrompt = await prompt.partial({
format_instructions: parser.getFormatInstructions(),
});
让我们看一下发送到模型的信息
const query = "Anna is 23 years old and she is 6 feet tall";
const promptValue = await partialedPrompt.invoke({ query });
console.log(promptValue.toChatMessages());
[
SystemMessage {
lc_serializable: true,
lc_kwargs: {
content: "Answer the user query. Wrap the output in `json` tags\n" +
"You must format your output as a JSON value th"... 1444 more characters,
additional_kwargs: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: "Answer the user query. Wrap the output in `json` tags\n" +
"You must format your output as a JSON value th"... 1444 more characters,
name: undefined,
additional_kwargs: {}
},
HumanMessage {
lc_serializable: true,
lc_kwargs: {
content: "Anna is 23 years old and she is 6 feet tall",
additional_kwargs: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: "Anna is 23 years old and she is 6 feet tall",
name: undefined,
additional_kwargs: {}
}
]
const chain = partialedPrompt.pipe(model).pipe(parser);
await chain.invoke({ query });
{ name: "Anna", hair_color: "", height_in_meters: "1.83" }
自定义解析
您也可以使用LangChain
和 LCEL
创建自定义提示和解析器。
您可以使用原始函数来解析来自模型的输出。
在以下示例中,我们将以 JSON 架构的形式将架构传递到提示中。为了方便起见,我们将使用 Zod 声明我们的架构,然后使用zod-to-json-schema
实用程序将其转换为 JSON 架构。
import { z } from "zod";
import { zodToJsonSchema } from "zod-to-json-schema";
personSchema = z
.object({
name: z.optional(z.string()).describe("The name of the person"),
hair_color: z
.optional(z.string())
.describe("The color of the person's hair, if known"),
height_in_meters: z
.optional(z.string())
.describe("Height measured in meters"),
})
.describe("Information about a person.");
const peopleSchema = z.object({
people: z.array(personSchema),
});
const SYSTEM_PROMPT_TEMPLATE = [
"Answer the user's query. You must return your answer as JSON that matches the given schema:",
"```json\n{schema}\n```.",
"Make sure to wrap the answer in ```json and ``` tags. Conform to the given schema exactly.",
].join("\n");
const customParsingPrompt = ChatPromptTemplate.fromMessages([
["system", SYSTEM_PROMPT_TEMPLATE],
["human", "{query}"],
]);
const extractJsonFromOutput = (message) => {
const text = message.content;
// Define the regular expression pattern to match JSON blocks
const pattern = /```json\s*((.|\n)*?)\s*```/gs;
// Find all non-overlapping matches of the pattern in the string
const matches = pattern.exec(text);
if (matches && matches[1]) {
try {
return JSON.parse(matches[1].trim());
} catch (error) {
throw new Error(`Failed to parse: ${matches[1]}`);
}
} else {
throw new Error(`No JSON found in: ${message}`);
}
};
const customParsingQuery = "Anna is 23 years old and she is 6 feet tall";
const customParsingPromptValue = await customParsingPrompt.invoke({
schema: zodToJsonSchema(peopleSchema),
customParsingQuery,
});
customParsingPromptValue.toString();
"System: Answer the user's query. You must return your answer as JSON that matches the given schema:\n"... 170 more characters
const customParsingChain = prompt.pipe(model).pipe(extractJsonFromOutput);
await customParsingChain.invoke({
schema: zodToJsonSchema(peopleSchema),
customParsingQuery,
});
{ name: "Anna", age: 23, height: { feet: 6, inches: 0 } }
下一步
您现在已经了解了如何在不使用工具调用情况下执行提取。
接下来,查看本节中的其他一些指南,例如有关如何使用示例提高提取质量的一些提示。