前言
书接上文 , 学习结构化输出 StruturedOutputParser , 在文末 , 我们提到 , 在规定输出格式的同时 , 我们使用 Zod 库严格要求数据的输出类型 , 可是 ,你有没有想过 , 如果模型突然一时间短路 , 或者我们的 prompt 没有写好 , 即输出之前发生了什么状况 , 导致输出的类型不符合 Zod 定义 , 那怎么办 ?
正文
我们知道Zod 会进行严格的类型验证,当遇到不符合定义类型规范的数据时,它会抛出一个 ZodError 类型的错误对象。
对于异常不处理的话 , 会导致程序中断 ,所以做好异常处理肥肠重要 ~
在 js , java 等语言中处理异常的机制是使用
try{
...
}catch{
...
}
如果发生一些异常 , 我们可以继续处理 , 那么在 Langchian.js 框架中 ,也有类似机制 , 在我前几篇文章中提到的 : Langchain.js | 基础-LCEL(二) ,
里面就提到了 : withFallbacks
LLMs并不完美,有时无法生成与期望格式完美匹配的输出。
在 parser 中 : OutputFixingParser 可以修复上一个模型输出格式 , 之后再投入流水线中继续运行 , 如此增加了程序的健壮性 , 鲁棒性 !
我们主要参考官网示例:
How to : try to fix errors in output parsing
我们造一个错误 : JSON 格式中使用的单引号 (在标准的 JSON 格式中,属性名和字符串值都应该使用双引号包裹, 所以从格式角度来说,它不符合正确的 JSON 语法规范)
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({
name: z.string().describe("name of an actor"),
film_names: z
.array(z.string())
.describe("list of names of films they starred in"),
});
const parser = StructuredOutputParser.fromZodSchema(zodSchema);
const misformatted = "{'name': 'Tom Hanks', 'film_names': ['Forrest Gump']}";
await parser.parse(misformatted);
Stack trace:
Error: Failed to parse. Text: "{'name': 'Tom Hanks', 'film_names': ['Forrest Gump']}". Error: SyntaxError: Expected property name or '}' in JSON at position 1 (line 1 column 2)
at StructuredOutputParser.parse (file:///C:/Users/MyName🤡/AppData/Local/deno/npm/mirrors.cloud.tencent.com/npm/@langchain/core/0.1.63_1/dist/output_parsers/structured.js:86:19)
at <anonymous>:11:14
现在我们可以构建和使用一个 OutputFixingParser 。这个输出解析器接受另一个输出解析器作为参数,还可以接受一个 LLM 来尝试纠正任何格式错误
官网用的是Anthropic 大模型 , 我换成 OpenAI
import {load} from "dotenv";
import { ChatOpenAI } from "langchain/chat_models/openai";
import { OutputFixingParser } from "langchain/output_parsers";
const env = await load();
const process = {env}
const model = new ChatOpenAI({
maxTokens: 512,
temperature: 0.1,
});
const parserWithFix = OutputFixingParser.fromLLM(model, parser);
await parserWithFix.parse(misformatted);
deno +Notebook 环境下 , 输出结果为 :
在上面的这段代码中 ,其实我们是在使用大模型ChatOpenAI , 修正parser , 我们可以假设一个场景 :
一个肥肠烧钱的 LLM , 在处理大量文本的时候 , 输出格式不符合我们的预期 (大量的文本会导致减弱模型的注意力机制) , 这个时候 , 我们就可以使用花钱少 ,甚至开源的大模型进行修正 , 如此省钱 ,岂不妙哉 !
总结
parser 处理输出的方法很多 , 经过几篇文章的输出 ,也只是冰山一角 , 但是我在官方文档上跑了几遍 , 已经对 OutputParser 驾轻就熟 , 所以 , 就此打住 , 运到再说 , 已经输出过度 , 精疲力竭 , 吃饭去了 ~