让 LLM 稳定输出 JSON

Posted by Yezhiwei on March 19, 2024

LLMs 是如何工作的

非常高层级的 GPT 模型,包括 ChatGPT、GPT-4、GPT-3.5-turbo,它们接受过庞大的数据集的训练,包括互联网、维基百科、公共 GitHub 代码和其他授权材料。它们被称为自回归,因为它们所做的只是综合所有这些信息。它们接受一个 prompt,或者我们可以称之为上下文。它们查看 prompt。然后它们基本上只是决定,给定这个 prompt,给定这个输入,下一个单词应该是什么?它实际上只是在预测下一个单词

例如,如果给定 GPT 的输入是,“the largest city in the United States is“(美国最大的城市是),那么答案就是 New York City(纽约市)。LLMs 会一个字一个字地思考,LLMs 会返回 “New”、“York”,然后是“City”。同样,在更具对话性的环境中,如果我们问它地球和太阳之间的距离是多少。GPT 已经从互联网上学过这个,它将输出 9400 万英里。它是根据输入逐个单词逐个单词思考的。

在底层,LLMs 真正做的是每次输出单词时,都会查看一堆候选单词并为它们分配概率。例如,在最初的例子中,“美国最大的城市是”,它可能有很多候选城市,New 代表“纽约”(New York),或者“新泽西”(New Jersey),或者其他什么,Los 代表“洛杉矶”(Los Angeles),然后还有其他一些可能的例子。你可以看到,它确实认为“New York City”(纽约市)可能是正确的答案,因为 New 的概率为 95%。在这种情况下,它通常会选择最有可能的结果,所以它会选择 New,然后继续前进。这个单词出现后,我们现在就知道 New 是第一个单词,所以它对下一个单词是什么就有了更多的限制。

我们可以看到,现在它认为 New York(纽约)的可能性要高得多,但它也在考虑 New Brunswick(新不伦瑞克)、New Mexico(新墨西哥)和 New Delhi(新德里)等。直到完成第二个单词,这基本上是模型的叠加。它基本上知道答案是 New York City,概率几乎是 100%。但它仍在考虑其他一些剩余概率很低的选项,比如 County(县)、New York Metro(纽约地铁)、New York Times(纽约时报),但最终它选择了 City 并给出答案。

对于更专业的 LLM 人士来说,这在技术上过于简单化了。LLMs 并不是真正在预测单词,而是在预测 token,比如单词片段,这实际上是一种更有效的表达英语的方式,主要是因为单词片段会在一堆不同的单词中重复,而不是单词本身会重复。但概念仍然是一样的。LLM 在这种上下文中,很可能会连续输出一堆不同的 token。就是这样,这就是这些语言模型的真正含义。

详细内容请关注:

ReAct 是如何工作的

ReAct Prompt 模版

TOOL_DESC = """{name_for_model}: Call this tool to interact with the {name_for_human} API. What is the {name_for_human} API useful for? {description_for_model} Parameters: {parameters} Format the arguments as a JSON object."""

REACT_PROMPT = """Answer the following questions as best you can. You have access to the following tools:

{tool_descs}

Use the following format:

Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [{tool_names}]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can be repeated zero or more times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question

Begin!

Question: {query}"""

分析

在实践过程中发现:

  • ReAct 按照 Prompt 的步骤一步步执行。
  • 通过设置停止词,当生成与停止词一样的输出时,模型停止生成。
  • 进行工具和参数解析(即处理 Action 和 Action Input),并调用工具。
  • 将工具调用结果进行 ReAct 格式进行拼装,调用模型继续进行续写生成。
  • 直到遇见 Final Answer: ,获得最终答案。

通过这现象,结合 LLMs 的工作原理,给定这个 prompt,给定这个输入,模型能预测下一个单词应该是什么。

实践

COND_DATA_PROMPT = """根据提供 json_data 数据和用户问题生成 JSON 格式,其中 key 分别为 'on' 和 'how'。

要求:
- 'on' 的取值规则为两个数据集合对象中相同的key,'how' 的取值只能 outer、inner、left、right 之一,需要根据数据和用户问题进行分析选择其中一个,不能随便编造。
- 请生成包括 'on' 和 'how' 的 JSON。
- 不要输出 JSON 内容以外的其它文本。

按以下格式输出:

用户问题:
近三年东方财富、贵州茅台、中国平安的净利润、经营活动现金流入分别是多少

json_data 数据:
[报告期,\
报告期,\
报告期]
[报告期,\
报告期]

\```json
on  
\```

Begin!

用户问题:
{question}

json_data 数据:
{json_data}"""

经过多次验证总能得到符合预期的 JSON 结构

Pasted image 20240314224135

小结

核心思想是利用了大模型的续写能力,按照 Prompt 中的步骤进行续写。即:给定这个 prompt,给定这个输入,模型能预测下一个单词应该是什么。

推荐阅读

参考资料:

Question answering using a search API and re-ranking | OpenAI Cookbook

ReAct: Synergizing Reasoning and Acting in Language Models

欢迎关注公众号,更及时的接收消息,后续会继续写一些相关 ChatGPT 的文章。