当前位置:首页 > 技术分析 > 正文内容

如何控制 LLM 的输出格式和解析其输出结果?

ruisui883个月前 (01-23)技术分析15

深入了解我们如何使用生成式 Al 模型进行创新实验,从而拓宽 GitHub Copilot 在开发者整个生命周期中的应用。

本文经授权转载宝玉老师的个人博客(微博@宝玉xp ),链 接https://baoyu.io/blog/prompt-engineering/how-to-parse-the-output-from-llm


责编 | 夏萌
出处 | baoyu.io

现在很多人对于如何使用像 ChatGPT 这样的 LLM 已经比较有经验了,可以使用各种不同的 Prompt 得到自己想要的结果。但有时候我们的使用场景不局限于手动操作,而是需要结合程序去调用 API,并且解析 API 的返回结果,从而实现一些自动化的功能。但是 LLM 的输出不确定性很大,所以我们需要想办法去控制 LLM 的输出格式,从而让程序得到稳定的输出,并且进一步对输出结果进行解析。

方法一:使用 Function Calling

Function Calling 是 OpenAI 不久前退出的针对 GPT API 的一个功能,可以让 LLM 决定在输出最终结果前,是否需要调用某个特定函数。比如说有用户问今天天气是什么,那么 LLM 在输出结果前,会先输出一个中间结果,告诉你需要调用天气相关的函数,并且传入这个函数的参数是“今天”。这样你就可以去调用天气函数,拿到结果后告诉 LLM,再输出最终结果给用户。

这个功能本意不是用来控制格式输出的,但是它在告诉我们该调用什么函数时,为了方便解析,给我们输出的是一个标准 JSON 格式,即使是 GPT-3.5,也能得到比较稳定的 JSON 格式。所以我们可以利用这个特性,来控制 LLM 的输出格式。

我们可以把要 ChatGPT 输出的内容定义成一个函数,但我们实际上不需要执行这个函数,只要 LLM 给我们的输出结果。

举例来说,我希望 ChatGPT 给我输出的格式是一个 Object:

{ "name": "John", "age": 30, "city": "New York"}
我们可以在调用 GPT 的时候定义一个函数,将函数的参数格式和要输出的 JSON 格式对应起来:
{ "name": "getUserInfo", "description": "Get user information", "parameters": { "type": "object", "properties": { "name": { "type": "string", "description": "User's fullname" }, "age": { "type": "number", "description": "User's age" }, "name": { "type": "string", "description": "User's city" }, }, "required": ["name", "age", "city"] }}

然后在调用 GPT 的时候,我们可以这样写:

messages = [{"role": "user", "content": "My name is John, I'm 30 years old, and I live in New York."}]functions = [{ "name": "getUserInfo", "description": "Get user information", "parameters": { "type": "object", "properties": { "name": { "type": "string", "description": "User's fullname" }, "age": { "type": "number", "description": "User's age" }, "name": { "type": "string", "description": "User's city" }, }, "required": ["name", "age", "city"] }}]openai.ChatCompletion.create( model="gpt-3.5-turbo-0613", messages=messages, functions=functions, function_call={ name: "getUserInfo" }, # 强制指定调用 getUserInfo 函数)

这样我们就可以得到一个稳定的 JSON 格式的输出结果。这种方法的局限在于必须 API 支持 Function Calling。

Function Calling 的具体用法可以参考 OpenAI 的文档:https://platform.openai.com/docs/guides/gpt/function-calling

方法二:使用 few-shot,给出输出格式样例

如果 API 不支持 Function Calling,那么我们可以使用 few-shot 的方式,给出一个甚至多个输出格式的样例,让 LLM 按照这个样例去输出结果。

比如我在翻译时,会让 LLM 翻译两次,一次直译一次意译,然后采用意译的结果。这种情况下我不需要用 JSON 格式,只需要简单的用特殊字符将两次结果隔开,然后按照特殊字符一分割,就可以得到意译的结果。

You are a friendly translation assistant. You'll help me translate English text into Chinese in two simple steps, ensuring the translation is easy to understand and free from any filler words like "you know", "so", and "eme". Here's how you will assist:
Literal translation focuses on preserving the original text's literal meaning, while free translation adjusts the expression based on the target language's habits while maintaining the original meaning.
1. You will provide a Literal Translation, preserving the original line breaks and paragraph format.2. You will then provide a free translation based on the literal translation, again preserving the format.
Please ensure that your output only contains the Literal Translation and the free translation, separated by "----" and new lines.
Output:[Literal Translation]
----
[free translation]

如果是 JSON 格式,也可以用 few-shot 说明,但是对于 GPT-3.5,稳定性不够好,有时候会出现不符合格式的情况。

Ensure that your response can be parsed by Python json, use the following format as an example:{ "name": "John", "age": 30, "city": "New York"}

方法三:使用 TypeScript 类型声明

这个方法仅适用于 GPT-4,你可以在 Prompt 中,将要输出的格式,用 TypeScript 的类型定义出来,甚至你还可以写上注释对部分字段进行详细的说明。这样 GPT-4 就会按照你的类型定义,输出符合格式的结果。

Your output should resemble a VALID JSON Object with the type TranslatedResult as illustrated below:type TranslatedResult = { // The comprehensive translated content from step 1 fullTranslatedContent: string; // All individual translated sentences. translatedSentences: Array<{ // A distinct translated sentence. translated: string; // Related input items, 1 translated sentence corresponds to 1 or more input items related: Array<{ // The timestamp of the input item timestamp: number; // The initial word of the related input item. firstWord: string; }> }>;};

输出结果参考

ChatGPT 的输出结果控制

如果是 ChatGPT,由于是网页直接操作,并且它支持 Markdown 格式,通常我会把我想要的结果放在 Markdown 的代码块中,这样就可以直接复制粘贴出来,但有时候也不是很稳定。

参考 Prompt:

请按照上面的规则和下面的格式打印翻译结果,返回格式如下,"{xxx}"表示占位符:### 直译{直译结果}####### 意译\`\`\`{意译结果}\`\`\`

容错处理

由于生成式 AI 现阶段的特点,我们很难保证输出结果的稳定性,所以我们需要对输出结果进行容错处理,以防止程序出错。这是我的一些经验总结:

1. 降低 temprature 参数的值会让结果更稳定。

temprature 越低,输出结果越稳定,当然温度低会影响输出结果的多样性,你可以灵活运用,比如出错后降低 temprature 值。

2. 对 JSON 结果进行容错处理

即使是 GPT-4,输出 JSON 时也不够稳定,经常会错误输出多余的逗号或者引号,但是老是重试也废 token,所以最好是用日志把出错的结果都记录下来,找出其中的规律,然后做一些字符串预处理,降低出错概率。

比如这里是我针对我的程序写的一个处理 JSON 错误的函数:

export const parseJson = (text: string) => { try { return JSON.parse(text); } catch (e) { let fixedContent = text .replace(/"},"\n/g, '"},\n') .replace(/"}"\n/g, '"}\n') .replace(/}"$/g, "}") .replace(/}]}]"/g, "}]}]") .replace(/]"\n?$/g, "]") .replace(/}]},"/g, "}]},") .replace(/}]}"/g, "}]}"); return JSON.parse(fixedContent); }};

仅供参考,最好还是你根据自己的 JSON 格式,记录日志,然后针对你的错误情况去写容错函数。

以上就是我对于我在日常使用 LLM 中,如何控制输出结果格式,以及如何对输出结果进行解析的一些经验总结,希望对你有帮助。也欢迎分享你的经验,一起进步。

扫描二维码推送至手机访问。

版权声明:本文由ruisui88发布,如需转载请注明出处。

本文链接:http://www.ruisui88.com/post/490.html

分享给朋友:

“如何控制 LLM 的输出格式和解析其输出结果?” 的相关文章

最古老的Linux发行版刚刚进行了重大更新

Slackware 15.0 带来了全新的 KDE Plasma 5 桌面体验。Slackware Linux(仍然维护的最古老的Linux发行版)的制造商刚刚发布了Linux发行版的15.0版本。Slackware Linux于1993年出现,创始人Patrick Volderding今天继续维护...

30 个纯 HTML5 实现的游戏

浏览器和 JavaScript 的功能逐年不断的变强变大。曾几何时,任何类型的游戏都需要Flash。但随着 HTML5 发展,HTML5 + WebGL 游戏式就慢慢占领着这个舞台。以下是30款流行的游戏,它们可以在所有现代浏览器中运行,并且只使用web技术构建。1. HexGL地址:http://...

Solid State Logic 发布低保真数字失真插件 Digicrush

Solid State Logic 宣布推出低保真数字失真插件 Digicrush ,他们最新的创意工具具有经典数字失真的粗糙、低保真特性,完美模拟早期数字音频的衰减和伪影。Digicrush 充满怀旧气息,深受经典数字采样器和效果器的影响,具有内置抖动、可调比特深度和采样率降低功能,是为音轨添加复...

vue3使用vue-router路由(路由懒加载、路由传参)

vue-router 是 vue的一个插件库1. 专门用来实现一个SPA单页面应用2 .基于vue的项目基本都会用到此库SPA的理解1) 单页Web应用(single page web application,SPA)2) 整个应用只有一个完整的页面3) 点击页面中的链接不会刷新页面, 本身也不会向...

22《Vue 入门教程》VueRouter 路由嵌套

1. 前言本小节我们介绍如何嵌套使用 VueRouter。嵌套路由在日常的开发中非常常见,如何定义和使用嵌套路由是本节的重点。同学们在学完本节课程之后需要自己多尝试配置路由。2. 配置嵌套路由实际项目中的应用界面,通常由多层嵌套的组件组合而成。同样地,URL 中各段动态路径也按某种结构对应嵌套的各层...

VUE3+JAVA商城源码小程序APP商城

三勾小程序商城基于springboot+element-ui+uniapp打造的面向开发的小程序商城,方便二次开发或直接使用,可发布到多端,包括微信小程序、微信公众号、QQ小程序、支付宝小程序、字节跳动小程序、百度小程序、android端、ios端。软件架构后端: springboot2.3.12管...