结构化推理
通过让语言模型将它们的推理输出为结构化的 Markdown 表格,我们可以提高它们的推理能力和输出质量。这被称为表格化思维链 (Tabular Chain Of Thought, Tab-CoT) 1。
我们可以使用 instructor
作为响应对象来实现这一点,如下所示,以确保我们获得 بالضبط 需要的数据。表格中的每一行在这里表示为一个 ReasoningStep
对象。
import instructor
from openai import OpenAI
from pydantic import BaseModel, Field
from textwrap import dedent
client = instructor.from_openai(OpenAI())
class ReasoningStep(BaseModel):
step: int = Field(description="The step number")
subquestion: str = Field(description="Subquestion to solve")
procedure: str = Field(
description="""Any intermediate computation
that was done in the reasoning process. Leave
empty if no computation is needed""",
)
result: str
class Response(BaseModel):
reasoning: list[ReasoningStep] = Field(
description="reasoning steps to derive answer",
)
correct_answer: int
def generate_structured_reasoning_response(query: str, context: str):
response = client.chat.completions.create(
model="gpt-4o",
response_model=Response,
messages=[
{
"role": "system",
"content": dedent(
f"""
<system>
<role>expert Question Answering system</role>
<instruction>Make sure to output your reasoning in structured reasoning steps before generating a response to the user's query.</instruction>
</system>
<context>
{context}
</context>
<query>
{query}
</query>
"""
),
},
],
)
return response
if __name__ == "__main__":
query = "How many loaves of bread did they have left?"
context = """
The bakers at the Beverly Hills Bakery baked
200 loaves of bread on Monday morning. They
sold 93 loaves in the morning and 39 loaves
in the afternoon. A grocery store returned 6
unsold loaves.
"""
response = generate_structured_reasoning_response(query, context)
print(response.model_dump_json(indent=2))
"""
{
"reasoning": [
{
"step": 1,
"subquestion": "How many loaves of bread were sold in the morning
and afternoon?",
"procedure": "93 (morning) + 39 (afternoon)",
"result": "132"
},
{
"step": 2,
"subquestion": "How many loaves of bread were originally baked?",
"procedure": "",
"result": "200"
},
{
"step": 3,
"subquestion": "How many loaves of bread were returned by the
grocery store?",
"procedure": "",
"result": "6"
},
{
"step": 4,
"subquestion": "How many loaves of bread were left after accounting
for sales and returns?",
"procedure": "200 (originally baked) - 132 (sold) + 6 (returned)",
"result": "74"
}
],
"correct_answer": 74
}
"""
这会生成以下推理步骤和正确的响应 74。
步骤 | 子问题 | 过程 | 结果 |
---|---|---|---|
1 | 上午和下午总共卖出了多少面包? | 93(上午)+ 39(下午) | 132 |
2 | 最初烘烤了多少面包? | 200 | |
3 | 杂货店退回了多少面包? | 6 | |
4 | 扣除销售和退货后,还剩下多少面包? | 200(最初烘烤)- 132(卖出)+ 6(退回) | 74 |