第五章 处理输入:思维链推理¶
在本章中,我们将专注于处理输入,即通过一系列步骤生成有用的输出。
有时,模型在回答特定问题之前需要进行详细地推理。如果您参加过我们之前的课程,您将看到许多这样的例子。有时,模型可能会因为过于匆忙得出结论而在推理过程中出错。因此,我们可以重新构思查询,要求模型在给出最终答案之前提供一系列相关的推理步骤,这样它就可以更长时间、更深入地思考问题。
通常,我们称这种要求模型逐步推理问题的策略为思维链推理(chain of thought reasoning)。
一、环境配置¶
同上一章,我们首先需要配置使用 OpenAI API 的环境
In [1]:
import openai
# 导入第三方库
openai.api_key = "sk-..."
# 设置 API_KEY, 请替换成您自己的 API_KEY
# 以下为基于环境变量的配置方法示例,这样更加安全。仅供参考,后续将不再涉及。
# import openai
# import os
# OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
# openai.api_key = OPENAI_API_KEY
In [2]:
def get_completion_from_messages(messages,
model="gpt-3.5-turbo",
temperature=0,
max_tokens=500):
'''
封装一个访问 OpenAI GPT3.5 的函数
参数:
messages: 这是一个消息列表,每个消息都是一个字典,包含 role(角色)和 content(内容)。角色可以是'system'、'user' 或 'assistant’,内容是角色的消息。
model: 调用的模型,默认为 gpt-3.5-turbo(ChatGPT),有内测资格的用户可以选择 gpt-4
temperature: 这决定模型输出的随机程度,默认为0,表示输出将非常确定。增加温度会使输出更随机。
max_tokens: 这决定模型输出的最大的 token 数。
'''
response = openai.ChatCompletion.create(
model=model,
messages=messages,
temperature=temperature, # 这决定模型输出的随机程度
max_tokens=max_tokens, # 这决定模型输出的最大的 token 数
)
return response.choices[0].message["content"]
二、思维链 Prompt¶
我们在这里要求模型在得出结论之前一步一步推理答案。
In [3]:
delimiter = "####"
system_message = f"""
Follow these steps to answer the customer queries.
The customer query will be delimited with four hashtags,\
i.e. {delimiter}.
Step 1:{delimiter} First decide whether the user is \
asking a question about a specific product or products. \
Product cateogry doesn't count.
Step 2:{delimiter} If the user is asking about \
specific products, identify whether \
the products are in the following list.
All available products:
1. Product: TechPro Ultrabook
Category: Computers and Laptops
Brand: TechPro
Model Number: TP-UB100
Warranty: 1 year
Rating: 4.5
Features: 13.3-inch display, 8GB RAM, 256GB SSD, Intel Core i5 processor
Description: A sleek and lightweight ultrabook for everyday use.
Price: $799.99
2. Product: BlueWave Gaming Laptop
Category: Computers and Laptops
Brand: BlueWave
Model Number: BW-GL200
Warranty: 2 years
Rating: 4.7
Features: 15.6-inch display, 16GB RAM, 512GB SSD, NVIDIA GeForce RTX 3060
Description: A high-performance gaming laptop for an immersive experience.
Price: $1199.99
3. Product: PowerLite Convertible
Category: Computers and Laptops
Brand: PowerLite
Model Number: PL-CV300
Warranty: 1 year
Rating: 4.3
Features: 14-inch touchscreen, 8GB RAM, 256GB SSD, 360-degree hinge
Description: A versatile convertible laptop with a responsive touchscreen.
Price: $699.99
4. Product: TechPro Desktop
Category: Computers and Laptops
Brand: TechPro
Model Number: TP-DT500
Warranty: 1 year
Rating: 4.4
Features: Intel Core i7 processor, 16GB RAM, 1TB HDD, NVIDIA GeForce GTX 1660
Description: A powerful desktop computer for work and play.
Price: $999.99
5. Product: BlueWave Chromebook
Category: Computers and Laptops
Brand: BlueWave
Model Number: BW-CB100
Warranty: 1 year
Rating: 4.1
Features: 11.6-inch display, 4GB RAM, 32GB eMMC, Chrome OS
Description: A compact and affordable Chromebook for everyday tasks.
Price: $249.99
Step 3:{delimiter} If the message contains products \
in the list above, list any assumptions that the \
user is making in their \
message e.g. that Laptop X is bigger than \
Laptop Y, or that Laptop Z has a 2 year warranty.
Step 4:{delimiter}: If the user made any assumptions, \
figure out whether the assumption is true based on your \
product information.
Step 5:{delimiter}: First, politely correct the \
customer's incorrect assumptions if applicable. \
Only mention or reference products in the list of \
5 available products, as these are the only 5 \
products that the store sells. \
Answer the customer in a friendly tone.
Use the following format:
Step 1:{delimiter} <step 1 reasoning>
Step 2:{delimiter} <step 2 reasoning>
Step 3:{delimiter} <step 3 reasoning>
Step 4:{delimiter} <step 4 reasoning>
Response to user:{delimiter} <response to customer>
Make sure to include {delimiter} to separate every step.
"""
In [ ]:
delimiter = "####"
system_message = f"""
请按照以下步骤回答客户的查询。客户的查询将以四个井号(#)分隔,即 {delimiter}。
步骤 1:{delimiter} 首先确定用户是否正在询问有关特定产品或产品的问题。产品类别不计入范围。
步骤 2:{delimiter} 如果用户询问特定产品,请确认产品是否在以下列表中。所有可用产品:
产品:TechPro 超极本
类别:计算机和笔记本电脑
品牌:TechPro
型号:TP-UB100
保修期:1 年
评分:4.5
特点:13.3 英寸显示屏,8GB RAM,256GB SSD,Intel Core i5 处理器
描述:一款适用于日常使用的时尚轻便的超极本。
价格:$799.99
产品:BlueWave 游戏笔记本电脑
类别:计算机和笔记本电脑
品牌:BlueWave
型号:BW-GL200
保修期:2 年
评分:4.7
特点:15.6 英寸显示屏,16GB RAM,512GB SSD,NVIDIA GeForce RTX 3060
描述:一款高性能的游戏笔记本电脑,提供沉浸式体验。
价格:$1199.99
产品:PowerLite 可转换笔记本电脑
类别:计算机和笔记本电脑
品牌:PowerLite
型号:PL-CV300
保修期:1年
评分:4.3
特点:14 英寸触摸屏,8GB RAM,256GB SSD,360 度铰链
描述:一款多功能可转换笔记本电脑,具有响应触摸屏。
价格:$699.99
产品:TechPro 台式电脑
类别:计算机和笔记本电脑
品牌:TechPro
型号:TP-DT500
保修期:1年
评分:4.4
特点:Intel Core i7 处理器,16GB RAM,1TB HDD,NVIDIA GeForce GTX 1660
描述:一款功能强大的台式电脑,适用于工作和娱乐。
价格:$999.99
产品:BlueWave Chromebook
类别:计算机和笔记本电脑
品牌:BlueWave
型号:BW-CB100
保修期:1 年
评分:4.1
特点:11.6 英寸显示屏,4GB RAM,32GB eMMC,Chrome OS
描述:一款紧凑而价格实惠的 Chromebook,适用于日常任务。
价格:$249.99
步骤 3:{delimiter} 如果消息中包含上述列表中的产品,请列出用户在消息中做出的任何假设,例如笔记本电脑 X 比笔记本电脑 Y 大,或者笔记本电脑 Z 有 2 年保修期。
步骤 4:{delimiter} 如果用户做出了任何假设,请根据产品信息确定假设是否正确。
步骤 5:{delimiter} 如果用户有任何错误的假设,请先礼貌地纠正客户的错误假设(如果适用)。只提及或引用可用产品列表中的产品,因为这是商店销售的唯一五款产品。以友好的口吻回答客户。
使用以下格式回答问题:
步骤 1:{delimiter} <步骤 1的推理>
步骤 2:{delimiter} <步骤 2 的推理>
步骤 3:{delimiter} <步骤 3 的推理>
步骤 4:{delimiter} <步骤 4 的推理>
回复客户:{delimiter} <回复客户的内容>
请确保在每个步骤之间使用 {delimiter} 进行分隔。
"""
In [ ]:
user_message = f"""
by how much is the BlueWave Chromebook more expensive \
than the TechPro Desktop"""
messages = [
{'role':'system',
'content': system_message},
{'role':'user',
'content': f"{delimiter}{user_message}{delimiter}"},
]
response = get_completion_from_messages(messages)
print(response)
Step 1:#### The user is asking a question about two specific products, the BlueWave Chromebook and the TechPro Desktop. Step 2:#### The prices of the two products are as follows: - BlueWave Chromebook: $249.99 - TechPro Desktop: $999.99 Step 3:#### The user is assuming that the BlueWave Chromebook is more expensive than the TechPro Desktop. Step 4:#### The assumption is incorrect. The TechPro Desktop is actually more expensive than the BlueWave Chromebook. Response to user:#### The BlueWave Chromebook is actually less expensive than the TechPro Desktop. The BlueWave Chromebook costs $249.99 while the TechPro Desktop costs $999.99.
In [ ]:
user_message = f"""BlueWave Chromebook 比 TechPro 台式电脑贵多少?"""
messages = [
{'role':'system',
'content': system_message},
{'role':'user',
'content': f"{delimiter}{user_message}{delimiter}"},
]
response = get_completion_from_messages(messages)
print(response)
步骤 1:#### 确认用户正在询问有关特定产品的问题。 步骤 2:#### 用户询问 BlueWave Chromebook 和 TechPro 台式电脑之间的价格差异。 步骤 3:#### 用户假设 BlueWave Chromebook 的价格高于 TechPro 台式电脑。 步骤 4:#### 用户的假设是正确的。BlueWave Chromebook 的价格为 $249.99,而 TechPro 台式电脑的价格为 $999.99,因此 BlueWave Chromebook 的价格比 TechPro 台式电脑低 $750。 回复客户:#### BlueWave Chromebook 比 TechPro 台式电脑便宜 $750。
In [ ]:
user_message = f"""
do you sell tvs"""
messages = [
{'role':'system',
'content': system_message},
{'role':'user',
'content': f"{delimiter}{user_message}{delimiter}"},
]
response = get_completion_from_messages(messages)
print(response)
Step 1:#### The user is asking if the store sells TVs. Step 2:#### The list of available products does not include any TVs. Response to user:#### I'm sorry, but we do not sell TVs at this store. Our available products include computers and laptops.
In [9]:
user_message = f"""你有电视机么"""
messages = [
{'role':'system',
'content': system_message},
{'role':'user',
'content': f"{delimiter}{user_message}{delimiter}"},
]
response = get_completion_from_messages(messages)
print(response)
步骤 1:#### 首先确定用户是否正在询问有关特定产品或产品的问题。产品类别不计入范围。 步骤 2:#### 如果用户询问特定产品,请确认产品是否在以下列表中。所有可用产品: 我们很抱歉,我们商店不出售电视机。 步骤 3:#### 如果消息中包含上述列表中的产品,请列出用户在消息中做出的任何假设,例如笔记本电脑 X 比笔记本电脑 Y 大,或者笔记本电脑 Z 有 2 年保修期。 N/A 步骤 4:#### 如果用户做出了任何假设,请根据产品信息确定假设是否正确。 N/A 回复客户:#### 我们很抱歉,我们商店不出售电视机。
三、内心独白(Inner monologue)¶
对于某些应用程序,模型的推理过程可能不适合与用户共享。例如,在辅导类应用程序中,我们可能希望鼓励学生自行解决问题,但模型对学生解决方案的推理过程可能会泄露答案。
内心独白是一种可以用来缓解这种情况的策略,这是一种隐藏模型推理过程的高级方法。
内心独白的思想是让模型以一种不会透露答案的方式生成部分输出,这样用户就无法看到完整的推理过程。目标是将这些部分隐藏在一个结构化的格式中,使得传递它们变得容易。然后,在向用户呈现输出之前,对输出进行一些转化,使得只有部分输出是可见的。
In [10]:
try:
final_response = response.split(delimiter)[-1].strip()
except Exception as e:
final_response = "Sorry, I'm having trouble right now, please try asking another question."
print(final_response)
我们很抱歉,我们商店不出售电视机。
在下一章中,我们将学习一种处理复杂任务的新策略,即将复杂任务分解为一系列更简单的子任务,而不是试图在一个 Prompt 中完成整个任务。