第一部分 环境配置
1.1 安装 Anaconda
- 官网:Anaconda
- 清华源镜像:Anaconda
- 推荐安装版本:Anaconda Python 3.11
1.2 创建虚拟环境
- 打开:
anaconda prompt
- 创建名为
env_name
的虚拟环境:conda create -n env_name python=3.11.5
- 激活虚拟环境:
activate env_name
其中,env_name
是虚拟环境的名字,可以根据自己的虚拟环境名称进行更改。
1.3 安装 openai
bash
pip install openai
1.4 获取并配置 OpenAI API key
- 注册 OpenAI 账号:OpenAI
- 注册 Google 账号,使用 Google 账号登录:gmail.com
- 获取 OpenAI key:
- 方式一:前往 OpenAI Platform:openai platform,自己有 Google 账号的情况下推荐。
- 方式二:免费获取 GPT_API_free,会有使用限制,本教程使用足够。
1.5 调用 OpenAI API key
python
from openai import OpenAI
# 免费key,这里是通过方式二获取的 key,需要添加 base_url
client = OpenAI(
base_url='https://api.chatanywhere.com.cn/v1',
api_key='your_openai_api_key',
)
# 一个封装 OpenAI 接口的函数,参数为 Prompt,返回对应结果
def get_completion(prompt , model="gpt-3.5-turbo"):
'''
prompt: 对应的提示词
model: 调用的模型,默认为 gpt-3.5-turbo(ChatGPT)。你也可以选择其他模型。
https://platform.openai.com/docs/models/overview
'''
messages = [{"role": "user", "content": prompt}]
# 调用 OpenAI 的 ChatCompletion 接口
response = client.chat.completions.create(
model=model,
messages=messages,
temperature=0
)
return response.choices[0].message.content
prompt = '你好,你是谁?'
res = get_completion(prompt)
print(res)
output
你好,我是一个人工智能助手。有什么可以帮助你的吗?
第二部分 如何去使用 Prompt,以充分发挥 LLM 的性能?
设计高效 Prompt 的两个关键原则:
- 编写清晰、具体的指令
- 使用分隔符清晰地表示输入的不同部分
- 寻求结构化的输出
- 要求模型检查是否满足条件
- 提供少量示例
- 给予模型充足思考时间
- 指定完成任务所需的步骤
- 指导模型在下结论之前找出一个自己的解法
2.1 提示原则:编写清晰、具体的指令
2.1.1 使用分隔符清晰地表示输入的不同部分
在编写 Prompt 时,我们可以使用各种标点符号作为"分隔符",将不同的文本部分区分开来。分隔符就像是 Prompt 中的墙,将不同的指令、上下文、输入隔开,避免意外的混淆。你可以选择用 ```````,""",< >,<tag> </tag>,:```` 等做分隔符,只要能明确起到隔断作用即可。
使用分隔符尤其重要的是可以防止 提示词注入(Prompt Rejection)。什么是提示词注入?就是用户输入的文本可能包含与你的预设 Prompt 相冲突的内容,如果不加分隔,这些输入就可能"注入"并操纵语言模型,导致模型产生毫无关联的乱七八糟的输出。
在以下的例子中,我们给出一段话并要求 GPT 进行总结,在该示例中我们使用 ```来作为分隔符。
python
text = f"""
您应该提供尽可能清晰、具体的指示,以表达您希望模型执行的任务。\
这将引导模型朝向所需的输出,并降低收到无关或不正确响应的可能性。\
不要将写清晰的提示词与写简短的提示词混淆。\
在许多情况下,更长的提示词可以为模型提供更多的清晰度和上下文信息,从而导致更详细和相关的输出。
"""
# 需要总结的文本内容
prompt = f"""
把用三个反引号括起来的文本总结成一句话。
```{text}```
"""
# 指令内容,使用 ```来分隔指令和待总结的内容
response = get_completion(prompt)
print(response)
output
提供清晰、具体的指示可以引导模型朝向所需的输出,避免收到无关或不正确响应。
2.1.2 寻求结构化的输出
有时候我们需要语言模型给我们一些结构化的输出,而不仅仅是连续的文本。
什么是结构化输出呢?就是按照某种格式组织的内容,例如JSON、HTML等。这种输出非常适合在代码中进一步解析和处理。例如,您可以在 Python 中将其读入字典或列表中。
在以下示例中,我们要求 LLM 生成三本书的标题、作者和类别,并要求 LLM 以 JSON 的格式返回给我们,为便于解析,我们指定了 Json 的键。
python
prompt = f"""
请生成包括书名、作者和类别的三本虚构的、非真实存在的中文书籍清单,\
并以 JSON 格式提供,其中包含以下键:book_id、title、author、genre。
"""
response = get_completion(prompt)
print(response)
json
[
{
"book_id": 1,
"title": "幻境之门",
"author": "王小明",
"genre": "奇幻"
},
{
"book_id": 2,
"title": "星际之旅",
"author": "张小红",
"genre": "科幻"
},
{
"book_id": 3,
"title": "梦境之城",
"author": "李大伟",
"genre": "悬疑"
}
]
2.1.3 要求模型检查是否满足条件
如果任务包含不一定能满足的假设(条件),我们可以告诉模型先检查这些假设,如果不满足,则会指出并停止执行后续的完整流程。您还可以考虑可能出现的边缘情况及模型的应对,以避免意外的结果或错误发生。
在如下示例中,我们将分别给模型两段文本,分别是制作茶的步骤以及一段没有明确步骤的文本。我们将要求模型判断其是否包含一系列指令,如果包含则按照给定格式重新编写指令,不包含则回答"未提供步骤"。
python
# 满足条件的输入(text中提供了步骤)
text_1 = f"""
泡一杯茶很容易。首先,需要把水烧开。\
在等待期间,拿一个杯子并把茶包放进去。\
一旦水足够热,就把它倒在茶包上。\
等待一会儿,让茶叶浸泡。几分钟后,取出茶包。\
如果您愿意,可以加一些糖或牛奶调味。\
就这样,您可以享受一杯美味的茶了。
"""
prompt = f"""
您将获得由三个引号括起来的文本。\
如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:
第一步 - ...
第二步 - ...
...
第N步 - ...
如果文本中不包含一系列的指令,则直接写"未提供步骤"。"
\"\"\"{text_1}\"\"\"
"""
response = get_completion(prompt)
print("Text 1 的总结:")
print(response)
output
Text 1 的总结:
第一步 - 把水烧开。
第二步 - 拿一个杯子并把茶包放进去。
第三步 - 把烧开的水倒在茶包上。
第四步 - 等待几分钟,让茶叶浸泡。
第五步 - 取出茶包。
第六步 - 如果愿意,可以加一些糖或牛奶调味。
上述示例中,模型可以很好地识别一系列的指令并进行输出。在接下来一个示例中,我们将提供给模型没有预期指令的输入,模型将判断未提供步骤。
python
# 不满足条件的输入(text中未提供预期指令)
text_2 = f"""
今天阳光明媚,鸟儿在歌唱。\
这是一个去公园散步的美好日子。\
鲜花盛开,树枝在微风中轻轻摇曳。\
人们外出享受着这美好的天气,有些人在野餐,有些人在玩游戏或者在草地上放松。\
这是一个完美的日子,可以在户外度过并欣赏大自然的美景。
"""
prompt = f"""
您将获得由三个引号括起来的文本。\
如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:
第一步 - ...
第二步 - ...
...
第N步 - ...
如果文本中不包含一系列的指令,则直接写"未提供步骤"。"
\"\"\"{text_2}\"\"\"
"""
response = get_completion(prompt)
print("Text 2 的总结:")
print(response)
output
Text 2 的总结:
未提供步骤。
2.1.4 提供少量示例
"Few-shot" prompting,即在要求模型执行实际任务之前,给模型一两个已完成的样例,让模型了解我们的要求和期望的输出样式。
例如,在以下的样例中,我们先给了一个祖孙对话样例,然后要求模型用同样的隐喻风格回答关于"韧性"的问题。这就是一个少样本样例,它能帮助模型快速抓住我们要的语调和风格。
利用少样本样例,我们可以轻松"预热"语言模型,让它为新的任务做好准备。这是一个让模型快速上手新任务的有效策略。
python
prompt = f"""
您的任务是以一致的风格回答问题。
<孩子>: 请教我何为耐心。
<祖父母>: 挖出最深峡谷的河流源于一处不起眼的泉眼;最宏伟的交响乐从单一的音符开始;最复杂的挂毯以一根孤独的线开始编织。
<孩子>: 请教我何为韧性。
"""
response = get_completion(prompt)
print(response)
output
<祖父母>: 韧性就像是一棵顽强的树,无论遭受多少风雨摧残,依然能够顽强地生长;就像是一块坚固的石头,经历了无数次的磨砺,依然能够保持坚硬不变。韧性是一种坚定不移的品质,让人能够在逆境中坚持不懈,永不放弃。
2.2 提示原则:给予模型充足思考时间
在设计 Prompt 时,给予语言模型充足的推理时间非常重要。语言模型与人类一样,需要时间来思考并解决复杂问题。如果让语言模型匆忙给出结论,其结果很可能不准确。例如,若要语言模型推断一本书的主题,仅提供简单的书名和一句简介是不足够的。这就像让一个人在极短时间内解决困难的数学题,错误在所难免。
相反,我们应通过 Prompt 指引语言模型进行深入思考。可以要求其先列出对问题的各种看法,说明推理依据,然后再得出最终结论。在 Prompt 中添加逐步推理的要求,能让语言模型投入更多时间逻辑思维,输出结果也将更可靠准确。
综上所述,给予语言模型充足的推理时间,是 Prompt Engineering 中一个非常重要的设计原则。这将大大提高语言模型处理复杂问题的效果,也是构建高质量 Prompt 的关键之处。开发者应注意给模型留出思考空间,以发挥语言模型的最大潜力。
指定完成任务所需的步骤
接下来我们将通过给定一个复杂任务,给出完成该任务的一系列步骤,来展示这一策略的效果。
首先我们描述了杰克和吉尔的故事,并给出提示词执行以下操作:首先,用一句话概括三个反引号限定的文本。第二,将摘要翻译成英语。第三,在英语摘要中列出每个名称。第四,输出包含以下键的 JSON 对象:英语摘要和人名个数。要求输出以换行符分隔。
python
text = f"""
在一个迷人的村庄里,兄妹杰克和吉尔出发去一个山顶井里打水。\
他们一边唱着欢乐的歌,一边往上爬,\
然而不幸降临------杰克绊了一块石头,从山上滚了下来,吉尔紧随其后。\
虽然略有些摔伤,但他们还是回到了温馨的家中。\
尽管出了这样的意外,他们的冒险精神依然没有减弱,继续充满愉悦地探索。
"""
# example 1
prompt_1 = f"""
执行以下操作:
1-用一句话概括下面用三个反引号括起来的文本。
2-将摘要翻译成英语。
3-在英语摘要中列出每个人名。
4-输出一个 JSON 对象,其中包含以下键:english_summary,num_names。
请用换行符分隔您的答案。
Text:
```{text}```
"""
response = get_completion(prompt_1)
print("prompt 1:")
print(response)
python
prompt 1:
1- 兄妹在山顶井里打水时发生意外,但他们的冒险精神依然不减。
2- Siblings Jack and Jill set off to fetch water from a well on a hilltop in a charming village. As they sang joyfully and climbed up, Jack stumbled on a rock and tumbled down the hill, with Jill following closely behind. Despite some minor injuries, they made it back home safely. Despite the mishap, their adventurous spirit remained undiminished as they continued to explore with joy.
3- Jack, Jill.
4-
{
"english_summary": "Siblings Jack and Jill set off to fetch water from a well on a hilltop in a charming village. As they sang joyfully and climbed up, Jack stumbled on a rock and tumbled down the hill, with Jill following closely behind. Despite some minor injuries, they made it back home safely. Despite the mishap, their adventurous spirit remained undiminished as they continued to explore with joy.",
"num_names": 2
}
指导模型在下结论之前找出一个自己的解法
在设计 Prompt 时,我们还可以通过明确指导语言模型进行自主思考,来获得更好的效果。
举个例子,假设我们要语言模型判断一个数学问题的解答是否正确。仅仅提供问题和解答是不够的,语言模型可能会匆忙做出错误判断。
相反,我们可以在 Prompt 中先要求语言模型自己尝试解决这个问题,思考出自己的解法,然后再与提供的解答进行对比,判断正确性。这种先让语言模型自主思考的方式,能帮助它更深入理解问题,做出更准确的判断。
接下来我们会给出一个问题和一份来自学生的解答,要求模型判断解答是否正确:
python
prompt = f"""
判断学生的解决方案是否正确。
问题:
我正在建造一个太阳能发电站,需要帮助计算财务。
土地费用为 100美元/平方英尺
我可以以 250美元/平方英尺的价格购买太阳能电池板
我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元
作为平方英尺数的函数,首年运营的总费用是多少。
学生的解决方案:
设x为发电站的大小,单位为平方英尺。
费用:
土地费用:100x
太阳能电池板费用:250x
维护费用:100,000美元+100x
总费用:100x+250x+100,000美元+100x=450x+100,000美元
"""
response = get_completion(prompt)
print(response)
output
学生的解决方案是正确的。总费用的计算是正确的,即总费用为450x+100,000美元。
但是注意,学生的解决方案实际上是错误的。(维护费用项100x应为10x,总费用450x应为360x)
我们可以通过指导模型先自行找出一个解法来解决这个问题。
在接下来这个 Prompt 中,我们要求模型先自行解决这个问题,再根据自己的解法与学生的解法进行对比,从而判断学生的解法是否正确。同时,我们给定了输出的格式要求。通过拆分任务、明确步骤,让模型有更多时间思考,有时可以获得更准确的结果。在这个例子中,学生的答案是错误的,但如果我们没有先让模型自己计算,那么可能会被误导以为学生是正确的。
python
prompt = f"""
请判断学生的解决方案是否正确,请通过如下步骤解决这个问题:
步骤:
首先,自己解决问题。
然后将您的解决方案与学生的解决方案进行比较,对比计算得到的总费用与学生计算的总费用是否一致,并评估学生的解决方案是否正确。
在自己完成问题之前,请勿决定学生的解决方案是否正确。
使用以下格式:
问题:问题文本
学生的解决方案:学生的解决方案文本
实际解决方案和步骤:实际解决方案和步骤文本
学生计算的总费用:学生计算得到的总费用
实际计算的总费用:实际计算出的总费用
学生计算的费用和实际计算的费用是否相同:是或否
学生的解决方案和实际解决方案是否相同:是或否
学生的成绩:正确或不正确
问题:
我正在建造一个太阳能发电站,需要帮助计算财务。
- 土地费用为每平方英尺100美元
- 我可以以每平方英尺250美元的价格购买太阳能电池板
- 我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元;
作为平方英尺数的函数,首年运营的总费用是多少。
学生的解决方案:
设x为发电站的大小,单位为平方英尺。
费用:
1. 土地费用:100x美元
2. 太阳能电池板费用:250x美元
3. 维护费用:100,000+100x=10万美元+10x美元
总费用:100x美元+250x美元+10万美元+100x美元=450x+10万美元
实际解决方案和步骤:
"""
response = get_completion(prompt)
print(response)
output
首先,计算土地费用:100美元/平方英尺 * x平方英尺 = 100x美元
然后,计算太阳能电池板费用:250美元/平方英尺 * x平方英尺 = 250x美元
接着,计算维护费用:10万美元 + 10美元/平方英尺 * x平方英尺 = 10万 + 10x美元
最后,计算总费用:100x美元 + 250x美元 + 10万美元 + 10x美元 = 360x + 10万美元
学生计算的总费用:450x + 10万美元
实际计算的总费用:360x + 10万美元
学生计算的费用和实际计算的费用是否相同:否
学生的解决方案和实际解决方案是否相同:否
学生的成绩:不正确
2.3 多次提问,迭代优化
在开发大语言模型应用时,很难通过第一次尝试就得到完美适用的 Prompt。但关键是要有一个良好的迭代优化过程,以不断改进 Prompt。相比训练机器学习模型,Prompt 的一次成功率可能更高,但仍需要通过多次迭代找到最适合应用的形式。
2.3.1 初始提示
python
# 示例:产品说明书
fact_sheet_chair = """
概述
美丽的中世纪风格办公家具系列的一部分,包括文件柜、办公桌、书柜、会议桌等。
多种外壳颜色和底座涂层可选。
可选塑料前后靠背装饰(SWC-100)或10种面料和6种皮革的全面装饰(SWC-110)。
底座涂层选项为:不锈钢、哑光黑色、光泽白色或铬。
椅子可带或不带扶手。
适用于家庭或商业场所。
符合合同使用资格。
结构
五个轮子的塑料涂层铝底座。
气动椅子调节,方便升降。
尺寸
宽度53厘米|20.87英寸
深度51厘米|20.08英寸
高度80厘米|31.50英寸
座椅高度44厘米|17.32英寸
座椅深度41厘米|16.14英寸
选项
软地板或硬地板滚轮选项。
两种座椅泡沫密度可选:中等(1.8磅/立方英尺)或高(2.8磅/立方英尺)。
无扶手或8个位置PU扶手。
材料
外壳底座滑动件
改性尼龙PA6/PA66涂层的铸铝。
外壳厚度:10毫米。
座椅
HD36泡沫
原产国
意大利
"""
python
# Prompt :基于说明书创建营销描述
prompt = f"""
您的任务是帮助营销团队基于技术说明书创建一个产品的营销描述。
根据```标记的技术说明书中提供的信息,编写一个产品描述。
技术说明: ```{fact_sheet_chair}```
"""
response = get_completion(prompt)
print(response)
output
产品描述:
我们自豪地推出美丽的中世纪风格办公家具系列,包括文件柜、办公桌、书柜、会议桌等。这款家具系列提供多种外壳颜色和底座涂层选择,让您可以根据个人喜好和装饰风格进行搭配。您可以选择塑料前后靠背装饰或全面装饰,以及底座涂层选项为不锈钢、哑光黑色、光泽白色或铬。椅子可选择带或不带扶手,适用于家庭或商业场所,并符合合同使用资格。
这款办公家具系列的椅子采用五个轮子的塑料涂层铝底座,配有气动椅子调节功能,方便您进行高度调节。尺寸适中,宽度53厘米,深度51厘米,高度80厘米,座椅高度44厘米,座椅深度41厘米。
我们提供多种选项,包括软地板或硬地板滚轮、两种座椅泡沫密度可选、以及无扶手或8个位置PU扶手。材料方面,外壳底座滑动件采用改性尼龙PA6/PA66涂层的铸铝,外壳厚度为10毫米,座椅采用HD36泡沫。这款产品原产国为意大利。
无论您是在家办公还是在商业场所使用,我们的中世纪风格办公家具系列将为您的空间增添优雅和舒适感。选择我们的产品,让您的办公环境更加完美!
2.3.2 提示优化1: 解决生成文本太长
它似乎很好地完成了要求,即从技术说明书开始编写产品描述,介绍了一个精致的中世纪风格办公椅。但是当我看到这个生成的内容时,我会觉得它太长了。
在看到语言模型根据产品说明生成的第一个版本营销文案后,我们注意到文本长度过长,不太适合用作简明的电商广告语。所以这时候就需要对 Prompt 进行优化改进。具体来说,第一版结果满足了从技术说明转换为营销文案的要求,描写了中世纪风格办公椅的细节。但是过于冗长的文本不太适合电商场景。这时我们就可以在 Prompt 中添加长度限制,要求生成更简洁的文案。
python
# 优化后的 Prompt,要求生成描述不多于 50 词
prompt = f"""
您的任务是帮助营销团队基于技术说明书创建一个产品的零售网站描述。
根据```标记的技术说明书中提供的信息,编写一个产品描述。
使用最多50个词。
技术规格:```{fact_sheet_chair}```
"""
response = get_completion(prompt)
print(response)
output
体验中世纪风格的办公家具系列,包括文件柜、办公桌和书柜。多种颜色和底座涂层选择,可选装饰和扶手。适用于家庭和商业场所,符合合同使用资格。铝底座,气动调节,可选软硬地板滚轮。意大利制造。
当在 Prompt 中设置长度限制要求时,语言模型生成的输出长度不总能精确符合要求,但基本能控制在可接受的误差范围内。比如要求生成50词的文本,语言模型有时会生成60词左右的输出,但总体接近预定长度。
这是因为语言模型在计算和判断文本长度时依赖于分词器,而分词器在字符统计方面不具备完美精度。目前存在多种方法可以尝试控制语言模型生成输出的长度,比如指定语句数、词数、汉字数等。
虽然语言模型对长度约束的遵循不是百分之百精确,但通过迭代测试可以找到最佳的长度提示表达式,使生成文本基本符合长度要求。这需要开发者对语言模型的长度判断机制有一定理解,并且愿意进行多次试验来确定最靠谱的长度设置方法。
2.3.3 提示优化2: 处理抓错文本细节
在迭代优化 Prompt 的过程中,我们还需要注意语言模型生成文本的细节是否符合预期。
比如在这个案例中,进一步分析会发现,该椅子面向的其实是家具零售商,而不是终端消费者。所以生成的文案中过多强调风格、氛围等方面,而较少涉及产品技术细节,与目标受众的关注点不太吻合。这时候我们就可以继续调整 Prompt,明确要求语言模型生成面向家具零售商的描述,更多关注材质、工艺、结构等技术方面的表述。
通过迭代地分析结果,检查是否捕捉到正确的细节,我们可以逐步优化 Prompt,使语言模型生成的文本更加符合预期的样式和内容要求。细节的精准控制是语言生成任务中非常重要的一点。我们需要训练语言模型根据不同目标受众关注不同的方面,输出风格和内容上都适合的文本。
python
# 优化后的 Prompt,说明面向对象,应具有什么性质且侧重于什么方面
prompt = f"""
您的任务是帮助营销团队基于技术说明书创建一个产品的零售网站描述。
根据```标记的技术说明书中提供的信息,编写一个产品描述。
该描述面向家具零售商,因此应具有技术性质,并侧重于产品的材料构造。
使用最多50个单词。
技术规格: ```{fact_sheet_chair}```
"""
response = get_completion(prompt)
print(response)
output
我们很高兴向您介绍我们的中世纪风格办公家具系列。这些家具包括文件柜、办公桌、书柜和会议桌,适用于家庭或商业场所。产品具有多种外壳颜色和底座涂层可选,座椅可选择带或不带扶手。结构坚固,座椅舒适,符合合同使用资格。来自意大利,采用高质量材料制造。
可见,通过修改 Prompt ,模型的关注点倾向了具体特征与技术细节。
我可能进一步想要在描述的结尾展示出产品 ID。因此,我可以进一步改进这个 Prompt ,要求在描述的结尾,展示出说明书中的7位产品 ID。
python
# 更进一步
prompt = f"""
您的任务是帮助营销团队基于技术说明书创建一个产品的零售网站描述。
根据```标记的技术说明书中提供的信息,编写一个产品描述。
该描述面向家具零售商,因此应具有技术性质,并侧重于产品的材料构造。
在描述末尾,包括技术规格中每个7个字符的产品ID。
使用最多50个单词。
技术规格: ```{fact_sheet_chair}```
"""
response = get_completion(prompt)
print(response)
output
这款中世纪风格办公家具系列包括文件柜、办公桌、书柜和会议桌,适用于家庭或商业场所。可选多种外壳颜色和底座涂层,座椅可带或不带扶手。结构坚固,座椅高度可调,座椅深度适中。材料优质,外壳底座采用改性尼龙PA6/PA66涂层的铸铝,座椅采用HD36泡沫。产品ID:SWC-100。
通过上面的示例,我们可以看到 Prompt 迭代优化的一般过程。与训练机器学习模型类似,设计高效 Prompt 也需要多个版本的试错调整。
具体来说,第一版 Prompt 应该满足明确和给模型思考时间两个原则。在此基础上,一般的迭代流程是:首先尝试一个初版,分析结果,然后继续改进 Prompt,逐步逼近最优。许多成功的Prompt 都是通过这种多轮调整得出的。
后面我会展示一个更复杂的 Prompt 案例,让大家更深入地了解语言模型的强大能力。但在此之前,我想强调 Prompt 设计是一个循序渐进的过程。开发者需要做好多次尝试和错误的心理准备,通过不断调整和优化,才能找到最符合具体场景需求的 Prompt 形式。这需要智慧和毅力,但结果往往是值得的。
让我们继续探索提示工程的奥秘,开发出令人惊叹的大语言模型应用吧!
2.3.4 提示优化3: 添加表格描述
继续添加指引,要求提取产品尺寸信息并组织成表格,并指定表格的列、表名和格式;再将所有内容格式化为可以在网页使用的 HTML。
python
# 要求它抽取信息并组织成表格,并指定表格的列、表名和格式
prompt = f"""
您的任务是帮助营销团队基于技术说明书创建一个产品的零售网站描述。
根据```标记的技术说明书中提供的信息,编写一个产品描述。
该描述面向家具零售商,因此应具有技术性质,并侧重于产品的材料构造。
在描述末尾,包括技术规格中每个7个字符的产品ID。
在描述之后,包括一个表格,提供产品的尺寸。表格应该有两列。第一列包括尺寸的名称。第二列只包括英寸的测量值。
给表格命名为"产品尺寸"。
将所有内容格式化为可用于网站的HTML格式。将描述放在<div>元素中。
技术规格:```{fact_sheet_chair}```
"""
response = get_completion(prompt)
print(response)
html
<div>
<p>这款中世纪风格办公家具系列的椅子是您家具店的理想选择。它包括文件柜、办公桌、书柜、会议桌等,适用于家庭或商业场所。您可以选择多种外壳颜色和底座涂层,以及可选的装饰和扶手选项。</p>
<p>这款椅子具有五个轮子的塑料涂层铝底座,配有气动椅子调节功能,方便升降。座椅采用HD36泡沫,提供舒适的坐感。您还可以选择软地板或硬地板滚轮,以及不同座椅泡沫密度和扶手选项。</p>
<p>这款椅子的尺寸为:宽度53厘米(20.87英寸)、深度51厘米(20.08英寸)、高度80厘米(31.50英寸)、座椅高度44厘米(17.32英寸)、座椅深度41厘米(16.14英寸)。</p>
<p>材料方面,外壳底座滑动件采用改性尼龙PA6/PA66涂层的铸铝,外壳厚度为10毫米。这款椅子的原产国是意大利。</p>
<p>产品ID:SWC-100</p>
</div>
<table>
<caption>产品尺寸</caption>
<tr>
<th>尺寸名称</th>
<th>英寸</th>
</tr>
<tr>
<td>宽度</td>
<td>20.87</td>
</tr>
<tr>
<td>深度</td>
<td>20.08</td>
</tr>
<tr>
<td>高度</td>
<td>31.50</td>
</tr>
<tr>
<td>座椅高度</td>
<td>17.32</td>
</tr>
<tr>
<td>座椅深度</td>
<td>16.14</td>
</tr>
</table>
2.4 文本概括
在繁忙的信息时代,小明是一名热心的开发者,面临着海量的文本信息处理的挑战。他需要通过研究无数的文献资料来为他的项目找到关键的信息,但是时间却远远不够。在他焦头烂额之际,他发现了大型语言模型(LLM)的文本摘要功能。
这个功能对小明来说如同灯塔一样,照亮了他处理信息海洋的道路。LLM 的强大能力在于它可以将复杂的文本信息简化,提炼出关键的观点,这对于他来说无疑是巨大的帮助。他不再需要花费大量的时间去阅读所有的文档,只需要用 LLM 将它们概括,就可以快速获取到他所需要的信息。
通过编程调用 AP I接口,小明成功实现了这个文本摘要的功能。他感叹道:"这简直就像一道魔法,将无尽的信息海洋变成了清晰的信息源泉。"小明的经历,展现了LLM文本摘要功能的巨大优势:节省时间,提高效率,以及精准获取信息。这就是我们本章要介绍的内容,让我们一起来探索如何利用编程和调用API接口,掌握这个强大的工具。
2.4.1 单一文本概括
以商品评论的总结任务为例:对于电商平台来说,网站上往往存在着海量的商品评论,这些评论反映了所有客户的想法。如果我们拥有一个工具去概括这些海量、冗长的评论,便能够快速地浏览更多评论,洞悉客户的偏好,从而指导平台与商家提供更优质的服务。
接下来我们提供一段在线商品评价作为示例,可能来自于一个在线购物平台,例如亚马逊、淘宝、京东等。评价者为一款熊猫公仔进行了点评,评价内容包括商品的质量、大小、价格和物流速度等因素,以及他的女儿对该商品的喜爱程度。
python
prod_review = """
这个熊猫公仔是我给女儿的生日礼物,她很喜欢,去哪都带着。
公仔很软,超级可爱,面部表情也很和善。但是相比于价钱来说,
它有点小,我感觉在别的地方用同样的价钱能买到更大的。
快递比预期提前了一天到货,所以在送给女儿之前,我自己玩了会。
"""
prompt = f"""
您的任务是从电子商务网站上生成一个产品评论的简短摘要。
请对三个反引号之间的评论文本进行概括,最多30个字。
评论: ```{prod_review}```
"""
response = get_completion(prompt)
print(response)
output
熊猫公仔软可爱,面部表情和善,但有点小,快递提前到货。
2.4.2 设置关键角度侧重
在某些情况下,我们会针对不同的业务场景对文本的侧重会有所不同。例如,在商品评论文本中,物流部门可能更专注于运输的时效性,商家则更关注价格和商品质量,而平台则更看重整体的用户体验。
我们可以通过增强输入提示(Prompt),来强调我们对某一特定视角的重视。
python
prompt = f"""
您的任务是从电子商务网站上生成一个产品评论的简短摘要。
请对三个反引号之间的评论文本进行概括,最多30个字,并且侧重在快递服务上。
评论: ```{prod_review}```
"""
response = get_completion(prompt)
print(response)
output
快递提前送达,公仔可爱软绵,但稍小。
侧重于价格和质量
python
prompt = f"""
您的任务是从电子商务网站上生成一个产品评论的简短摘要。
请对三个反引号之间的评论文本进行概括,最多30个词汇,并且侧重在产品价格和质量上。
评论: ```{prod_review}```
"""
response = get_completion(prompt)
print(response)
output
可爱软熊猫公仔,质量好,面部表情和善。价格略小贵,但快递提前到货。适合作为礼物。
2.4.3 关键信息提取
虽然我们通过添加关键角度侧重的 Prompt ,确实让文本摘要更侧重于某一特定方面,然而,我们可以发现,在结果中也会保留一些其他信息,比如偏重价格与质量角度的概括中仍保留了"快递提前到货"的信息。如果我们只想要提取某一角度的信息,并过滤掉其他所有信息,则可以要求 LLM 进行 文本提取(Extract) 而非概括( Summarize )。
下面让我们来一起来对文本进行提取信息吧!
python
prompt = f"""
您的任务是从电子商务网站上的产品评论中提取相关信息。
请从以下三个反引号之间的评论文本中提取产品运输相关的信息,最多30个词汇。
评论: ```{prod_review}```
"""
response = get_completion(prompt)
print(response)
output
产品运输相关信息:快递比预期提前了一天到货。
2.4.4 同时概括多条文本
在实际的工作流中,我们往往要处理大量的评论文本,下面的示例将多条用户评价集合在一个列表中,并利用 for 循环和文本概括(Summarize)提示词,将评价概括至小于 20 个词以下,并按顺序打印。当然,在实际生产中,对于不同规模的评论文本,除了使用 for 循环以外,还可能需要考虑整合评论、分布式等方法提升运算效率。您可以搭建主控面板,来总结大量用户评论,以及方便您或他人快速浏览,还可以点击查看原评论。这样,您就能高效掌握顾客的所有想法。
python
review_1 = prod_review
# 一盏落地灯的评论
review_2 = """
我需要一盏漂亮的卧室灯,这款灯不仅具备额外的储物功能,价格也并不算太高。
收货速度非常快,仅用了两天的时间就送到了。
不过,在运输过程中,灯的拉线出了问题,幸好,公司很乐意寄送了一根全新的灯线。
新的灯线也很快就送到手了,只用了几天的时间。
装配非常容易。然而,之后我发现有一个零件丢失了,于是我联系了客服,他们迅速地给我寄来了缺失的零件!
对我来说,这是一家非常关心客户和产品的优秀公司。
"""
# 一把电动牙刷的评论
review_3 = """
我的牙科卫生员推荐了电动牙刷,所以我就买了这款。
到目前为止,电池续航表现相当不错。
初次充电后,我在第一周一直将充电器插着,为的是对电池进行条件养护。
过去的3周里,我每天早晚都使用它刷牙,但电池依然维持着原来的充电状态。
不过,牙刷头太小了。我见过比这个牙刷头还大的婴儿牙刷。
我希望牙刷头更大一些,带有不同长度的刷毛,
这样可以更好地清洁牙齿间的空隙,但这款牙刷做不到。
总的来说,如果你能以50美元左右的价格购买到这款牙刷,那是一个不错的交易。
制造商的替换刷头相当昂贵,但你可以购买价格更为合理的通用刷头。
这款牙刷让我感觉就像每天都去了一次牙医,我的牙齿感觉非常干净!
"""
# 一台搅拌机的评论
review_4 = """
在11月份期间,这个17件套装还在季节性促销中,售价约为49美元,打了五折左右。
可是由于某种原因(我们可以称之为价格上涨),到了12月的第二周,所有的价格都上涨了,
同样的套装价格涨到了70-89美元不等。而11件套装的价格也从之前的29美元上涨了约10美元。
看起来还算不错,但是如果你仔细看底座,刀片锁定的部分看起来没有前几年版本的那么漂亮。
然而,我打算非常小心地使用它
(例如,我会先在搅拌机中研磨豆类、冰块、大米等坚硬的食物,然后再将它们研磨成所需的粒度,
接着切换到打蛋器刀片以获得更细的面粉,如果我需要制作更细腻/少果肉的食物)。
在制作冰沙时,我会将要使用的水果和蔬菜切成细小块并冷冻
(如果使用菠菜,我会先轻微煮熟菠菜,然后冷冻,直到使用时准备食用。
如果要制作冰糕,我会使用一个小到中号的食物加工器),这样你就可以避免添加过多的冰块。
大约一年后,电机开始发出奇怪的声音。我打电话给客户服务,但保修期已经过期了,
所以我只好购买了另一台。值得注意的是,这类产品的整体质量在过去几年里有所下降
,所以他们在一定程度上依靠品牌认知和消费者忠诚来维持销售。在大约两天内,我收到了新的搅拌机。
"""
reviews = [review_1, review_2, review_3, review_4]
for i in range(len(reviews)):
prompt = f"""
你的任务是从电子商务网站上的产品评论中提取相关信息。
请对三个反引号之间的评论文本进行概括,最多20个词汇。
评论文本: ```{reviews[i]}```
"""
response = get_completion(prompt)
print(f"评论{i+1}: ", response, "\n")
output
评论1: 熊猫公仔生日礼物,女儿喜欢,软可爱,面部表情和善,价钱小,快递提前到货。
评论2: 评论概括:漂亮的卧室灯,具备储物功能,价格适中。快速送达,售后服务好,客户关怀。
评论3: 评论概括:电动牙刷续航好,但牙刷头太小,价格合理,清洁效果好,替换刷头贵。
评论4: 11月份17件套装季节性促销,价格约49美元,12月上涨至70-89美元。使用小心,电机质量下降。
2.5 推断
让我们先想象一下,你是一名初创公司的数据分析师,你的任务是从各种产品评论和新闻文章中提取出关键的情感和主题。这些任务包括了标签提取、实体提取、以及理解文本的情感等等。在传统的机器学习流程中,你需要收集标签化的数据集、训练模型、确定如何在云端部署模型并进行推断。尽管这种方式可能会产生不错的效果,但完成这一全流程需要耗费大量的时间和精力。而且,每一个任务,比如情感分析、实体提取等等,都需要训练和部署单独的模型。
然而,就在你准备投入繁重工作的时候,你发现了大型语言模型(LLM)。LLM 的一个明显优点是,对于许多这样的任务,你只需要编写一个 Prompt,就可以开始生成结果,大大减轻了你的工作负担。这个发现像是找到了一把神奇的钥匙,让应用程序开发的速度加快了许多。最令你兴奋的是,你可以仅仅使用一个模型和一个 API 来执行许多不同的任务,无需再纠结如何训练和部署许多不同的模型。
2.5.1 情感推断
让我们以一则电商平台上的台灯评论为例,通过此例,我们将学习如何对评论进行情感二分类(正面/负面)。
python
lamp_review = """
我需要一盏漂亮的卧室灯,这款灯具有额外的储物功能,价格也不算太高。\
我很快就收到了它。在运输过程中,我们的灯绳断了,但是公司很乐意寄送了一个新的。\
几天后就收到了。这款灯很容易组装。我发现少了一个零件,于是联系了他们的客服,他们很快就给我寄来了缺失的零件!\
在我看来,Lumina 是一家非常关心顾客和产品的优秀公司!
"""
接下来,我们将尝试编写一个 Prompt ,用以分类这条商品评论的情感。如果我们想让系统解析这条评论的情感倾向,只需编写"以下商品评论的情感倾向是什么?"这样的 Prompt ,再加上一些标准的分隔符和评论文本等。
然后,我们将这个程序运行一遍。结果表明,这条商品评论的情感倾向是正面的,这似乎非常准确。尽管这款台灯并非完美无缺,但是这位顾客对它似乎相当满意。这个公司看起来非常重视客户体验和产品质量,因此,认定评论的情感倾向为正面似乎是正确的判断。
python
prompt = f"""
以下用三个反引号分隔的产品评论的情感是什么?
评论文本: ```{lamp_review}```
"""
response = get_completion(prompt)
print(response)
output
积极的情感。
如果你想要给出更简洁的答案,以便更容易进行后期处理,可以在上述 Prompt 基础上添加另一个指令:用一个单词回答:「正面」或「负面」。这样就只会打印出 "正面" 这个单词,这使得输出更加统一,方便后续处理。
python
prompt = f"""
以下用三个反引号分隔的产品评论的情感是什么?
用一个单词回答:「正面」或「负面」。
评论文本: ```{lamp_review}```
"""
response = get_completion(prompt)
print(response)
output
正面
识别感情类型
接下来,我们将继续使用之前的台灯评论,但这次我们会试用一个新的 Prompt 。我们希望模型能够识别出评论作者所表达的情感,并且将这些情感整理为一个不超过五项的列表。
python
# 中文
prompt = f"""
识别以下评论的作者表达的情感。包含不超过五个项目。将答案格式化为以逗号分隔的单词列表。
评论文本: ```{lamp_review}```
"""
response = get_completion(prompt)
print(response)
output
满意,感激,快速,优秀,关心
大型语言模型非常擅长从一段文本中提取特定的东西。在上面的例子中,评论所表达的情感有助于了解客户如何看待特定的产品。
识别愤怒 对于许多企业来说,洞察到顾客的愤怒情绪是至关重要的。这就引出了一个分类问题:下述的评论作者是否流露出了愤怒?因为如果有人真的情绪激动,那可能就意味着需要给予额外的关注,因为每一个愤怒的顾客都是一个改进服务的机会,也是一个提升公司口碑的机会。这时,客户支持或者客服团队就应该介入,与客户接触,了解具体情况,然后解决他们的问题。
python
# 中文
prompt = f"""
以下评论的作者是否表达了愤怒?评论用三个反引号分隔。给出是或否的答案。
评论文本: ```{lamp_review}```
"""
response = get_completion(prompt)
print(response)
output
否
上面这个例子中,客户并没有生气。注意,如果使用常规的监督学习,如果想要建立所有这些分类器,不可能在几分钟内就做到这一点。我们鼓励大家尝试更改一些这样的 Prompt ,也许询问客户是否表达了喜悦,或者询问是否有任何遗漏的部分,并看看是否可以让 Prompt 对这个灯具评论做出不同的推论。
2.5.2 信息提取
信息提取是自然语言处理(NLP)的重要组成部分,它帮助我们从文本中抽取特定的、我们关心的信息。我们将深入挖掘客户评论中的丰富信息。在接下来的示例中,我们将要求模型识别两个关键元素:购买的商品和商品的制造商。
想象一下,如果你正在尝试分析一个在线电商网站上的众多评论,了解评论中提到的商品是什么、由谁制造,以及相关的积极或消极情绪,将极大地帮助你追踪特定商品或制造商在用户心中的情感趋势。
在接下来的示例中,我们会要求模型将回应以一个 JSON 对象的形式呈现,其中的 key 就是商品和品牌。
python
# 中文
prompt = f"""
从评论文本中识别以下项目:
- 评论者购买的物品
- 制造该物品的公司
评论文本用三个反引号分隔。将你的响应格式化为以 "物品" 和 "品牌" 为键的 JSON 对象。
如果信息不存在,请使用 "未知" 作为值。
让你的回应尽可能简短。
评论文本: ```{lamp_review}```
"""
response = get_completion(prompt)
print(response)
json
{
"物品": "卧室灯",
"品牌": "Lumina"
}
在上面小节中,我们采用了三至四个 Prompt 来提取评论中的"情绪倾向"、"是否生气"、"物品类型"和"品牌"等信息。然而,事实上,我们可以设计一个单一的 Prompt ,来同时提取所有这些信息。
python
# 中文
prompt = f"""
从评论文本中识别以下项目:
- 情绪(正面或负面)
- 审稿人是否表达了愤怒?(是或否)
- 评论者购买的物品
- 制造该物品的公司
评论用三个反引号分隔。将你的响应格式化为 JSON 对象,以 "情感倾向"、"是否生气"、"物品类型" 和 "品牌" 作为键。
如果信息不存在,请使用 "未知" 作为值。
让你的回应尽可能简短。
将 "是否生气" 值格式化为布尔值。
评论文本: ```{lamp_review}```
"""
response = get_completion(prompt)
print(response)
json
{
"情感倾向": "正面",
"是否生气": false,
"物品类型": "卧室灯",
"品牌": "Lumina"
}
这个例子中,我们指导 LLM 将"是否生气"的情况格式化为布尔值,并输出 JSON 格式。你可以尝试对格式化模式进行各种变化,或者使用完全不同的评论来试验,看看 LLM 是否仍然可以准确地提取这些内容。
2.5.3 主题推断
大型语言模型的另一个很酷的应用是推断主题。假设我们有一段长文本,我们如何判断这段文本的主旨是什么?它涉及了哪些主题?让我们通过以下一段虚构的报纸报道来具体了解一下。
python
# 中文
story = """
在政府最近进行的一项调查中,要求公共部门的员工对他们所在部门的满意度进行评分。
调查结果显示,NASA 是最受欢迎的部门,满意度为 95%。
一位 NASA 员工 John Smith 对这一发现发表了评论,他表示:
"我对 NASA 排名第一并不感到惊讶。这是一个与了不起的人们和令人难以置信的机会共事的好地方。我为成为这样一个创新组织的一员感到自豪。"
NASA 的管理团队也对这一结果表示欢迎,主管 Tom Johnson 表示:
"我们很高兴听到我们的员工对 NASA 的工作感到满意。
我们拥有一支才华横溢、忠诚敬业的团队,他们为实现我们的目标不懈努力,看到他们的辛勤工作得到回报是太棒了。"
调查还显示,社会保障管理局的满意度最低,只有 45%的员工表示他们对工作满意。
政府承诺解决调查中员工提出的问题,并努力提高所有部门的工作满意度。
"""
以上是一篇关于政府员工对其工作单位感受的虚构报纸文章。我们可以要求大语言模型确定其中讨论的五个主题,并用一两个词语概括每个主题。输出结果将会以逗号分隔的Python列表形式呈现。
python
# 中文
prompt = f"""
确定以下给定文本中讨论的五个主题。
每个主题用1-2个词概括。
请输出一个可解析的 Python 列表,每个元素是一个字符串,展示了一个主题。
给定文本: ```{story}```
"""
response = get_completion(prompt)
print(response)
output
- NASA
- 员工满意度
- 社会保障管理局
- 政府调查
- 管理团队
假设我们有一个新闻网站或类似的平台,这是我们感兴趣的主题:美国航空航天局、当地政府、工程、员工满意度、联邦政府等。我们想要分析一篇新闻文章,理解其包含了哪些主题。可以使用这样的 Prompt:确定以下主题列表中的每个项目是否是以下文本中的主题。以 0 或 1 的形式给出答案列表。
python
# 中文
prompt = f"""
判断主题列表中的每一项是否是给定文本中的一个话题,
以列表的形式给出答案,每个元素是一个Json对象,键为对应主题,值为对应的 0 或 1。
主题列表:美国航空航天局、当地政府、工程、员工满意度、联邦政府
给定文本: ```{story}```
"""
response = get_completion(prompt)
print(response)
output
[
{"美国航空航天局": 1},
{"当地政府": 1},
{"工程": 0},
{"员工满意度": 1},
{"联邦政府": 1}
]
从输出结果来看,这个 story 与关于"美国航空航天局"、"员工满意度"、"联邦政府"、"当地政府"有关,而与"工程"无关。这种能力在机器学习领域被称为零样本(Zero-Shot)学习。这是因为我们并没有提供任何带标签的训练数据,仅凭 Prompt ,它便能判定哪些主题在新闻文章中被包含。
如果我们希望制定一个新闻提醒,我们同样可以运用这种处理新闻的流程。假设我对"美国航空航天局"的工作深感兴趣,那么你就可以构建一个如此的系统:每当出现与'美国宇航局'相关的新闻,系统就会输出提醒。
python
result_lst = eval(response)
topic_dict = {list(i.keys())[0] : list(i.values())[0] for i in result_lst}
print(topic_dict)
if topic_dict['美国航空航天局'] == 1:
print("提醒: 关于美国航空航天局的新消息")
output
{'美国航空航天局': 1, '当地政府': 1, '工程': 0, '员工满意度': 1, '联邦政府': 1}
提醒: 关于美国航空航天局的新消息
这就是我们关于推断的全面介绍。在短短几分钟内,我们已经能够建立多个用于文本推理的系统,这是以前需要机器学习专家数天甚至数周时间才能完成的任务。这一变化无疑是令人兴奋的,因为无论你是经验丰富的机器学习开发者,还是刚入门的新手,都能利用输入 Prompt 快速开始复杂的自然语言处理任务。
参考学习:
《吴恩达-面向开发者的LLM入门课程》