跳到主要内容

文本推断

在这节课中,你将从产品评论和新闻文章中推断情感和主题。

这些任务可以看作是模型接收文本作为输入并执行某种分析的过程。这可能涉及提取标签、提取实体、理解文本情感等等。如果你想要从一段文本中提取正面或负面情感,在传统的机器学习工作流程中,需要收集标签数据集、训练模型、确定如何在云端部署模型并进行推断。这样做可能效果还不错,但是这个过程需要很多工作。而且对于每个任务,如情感分析、提取实体等等,都需要训练和部署单独的模型。

大型语言模型的一个非常好的特点是,对于许多这样的任务,你只需要编写一个 prompt 即可开始产生结果,而不需要进行大量的工作。这极大地加快了应用程序开发的速度。你还可以只使用一个模型和一个 API 来执行许多不同的任务,而不需要弄清楚如何训练和部署许多不同的模型。

依赖引入

同上一章节,我们需要导入 OpenAI 第三方库,并加载 API 密钥,定义 getCompletion 函数。

import openai
import os

# 读取环境变量中的 api_key
openai.api_key = os.environ.get("OPENAI_API_KEY")
# 直接写 api_key
#openai.api_key = 'API_KEY'

def get_completion(prompt, model="gpt-3.5-turbo"):
messages = [{"role": "user", "content": prompt}]
response = openai.ChatCompletion.create(
model=model,
messages=messages,
temperature=0, # 值越低则输出文本随机性越低
)
return response.choices[0].message["content"]

商品评论

通过商品评论来推断其情感、提取实体及相关信息。

文本:

lamp_review_zh = """
我需要一盏漂亮的卧室灯,这款灯具有额外的储物功能,价格也不算太高。\
我很快就收到了它。在运输过程中,我们的灯绳断了,但是公司很乐意寄送了一个新的。\
几天后就收到了。这款灯很容易组装。我发现少了一个零件,于是联系了他们的客服,他们很快就给我寄来了缺失的零件!\
在我看来,Lumina 是一家非常关心顾客和产品的优秀公司!
"""

情感(正向/负向)

现在让我们来编写一个 prompt 来分类这个评论的情感。如果我想让系统告诉我这个评论的情感是什么,只需要编写 “以下产品评论的情感是什么” 这个 prompt,加上通常的分隔符和评论文本等等。

然后让我们运行一下。结果显示这个产品评论的情感是积极的,这似乎是非常正确的。虽然这盏台灯不完美,但这个客户似乎非常满意。这似乎是一家关心客户和产品的伟大公司,可以认为积极的情感似乎是正确的答案。

输入:

prompt = f"""
以下用三个反引号分隔的产品评论的情感是什么?

评论文本: ```{lamp_review_zh}```
"""
response = get_completion(prompt)
print(response)

输出:

情感是积极的/正面的。

如果你想要给出更简洁的答案,以便更容易进行后处理,可以使用上面的 prompt 并添加另一个指令,以一个单词 “正面” 或 “负面” 的形式给出答案。这样就只会打印出 “正面” 这个单词,这使得文本更容易接受这个输出并进行处理。

输入:

prompt = f"""
以下用三个反引号分隔的产品评论的情感是什么?

用一个单词回答:「正面」或「负面」。

评论文本: ```{lamp_review_zh}```
"""
response = get_completion(prompt)
print(response)

输出:

正面

识别情感类型

让我们看看另一个 prompt,仍然使用台灯评论。这次我要让它识别出以下评论作者所表达的情感列表,不超过五个。

输入:

# 中文
prompt = f"""
识别以下评论的作者表达的情感。包含不超过五个项目。将答案格式化为以逗号分隔的单词列表。

评论文本: ```{lamp_review_zh}```
"""
response = get_completion(prompt)
print(response)

输出:

满意,感激,信任,赞扬,愉快

大型语言模型非常擅长从一段文本中提取特定的东西。在上面的例子中,评论正在表达情感,这可能有助于了解客户如何看待特定的产品。

识别愤怒

对于很多企业来说,了解某个顾客是否非常生气很重要。所以你可能有一个类似这样的分类问题:以下评论的作者是否表达了愤怒情绪?因为如果有人真的很生气,那么可能值得额外关注,让客户支持或客户成功团队联系客户以了解情况,并为客户解决问题。

输入:

# 中文
prompt = f"""
以下评论的作者是否表达了愤怒?评论用三个反引号分隔。给出是或否的答案。

评论文本: ```{lamp_review_zh}```
"""
response = get_completion(prompt)
print(response)

输出:


上面这个例子中,客户并没有生气。注意,如果使用常规的监督学习,如果想要建立所有这些分类器,不可能在几分钟内就做到这一点。我们鼓励大家尝试更改一些这样的 prompt,也许询问客户是否表达了喜悦,或者询问是否有任何遗漏的部分,并看看是否可以让 prompt 对这个灯具评论做出不同的推论。

从客户评论中提取产品和公司名称

接下来,让我们从客户评论中提取更丰富的信息。信息提取是自然语言处理(NLP)的一部分,与从文本中提取你想要知道的某些事物相关。因此,在这个 prompt 中,我要求它识别以下内容:购买物品和制造物品的公司名称。

同样,如果你试图总结在线购物电子商务网站的许多评论,对于这些评论来说,弄清楚是什么物品,谁制造了该物品,弄清楚积极和消极的情感,以跟踪特定物品或特定制造商的积极或消极情感趋势,可能会很有用。

在下面这个示例中,我们要求它将响应格式化为一个 JSON 对象,其中物品和品牌是键。

输入:

prompt = f"""
从评论文本中识别以下项目:
- 评论者购买的物品
- 制造该物品的公司

评论文本用三个反引号分隔。将你的响应格式化为以 “物品” 和 “品牌” 为键的 JSON 对象。
如果信息不存在,请使用 “未知” 作为值。
让你的回应尽可能简短。

评论文本: ```{lamp_review_zh}```
"""
response = get_completion(prompt)
print(response)

输出:

{
"物品": "卧室灯",
"品牌": "Lumina"
}

如上所示,它会说这个物品是一个卧室灯,品牌是 Luminar,你可以轻松地将其加载到 Python 字典中,然后对此输出进行其他处理。

一次完成多项任务

提取上面所有这些信息使用了 3 或 4 个 prompt,但实际上可以编写单个 prompt 来同时提取所有这些信息。

输入:

prompt = f"""
从评论文本中识别以下项目:
- 情绪(正面或负面)
- 审稿人是否表达了愤怒?(是或否)
- 评论者购买的物品
- 制造该物品的公司

评论用三个反引号分隔。将您的响应格式化为 JSON 对象,以 “Sentiment”、“Anger”、“Item” 和 “Brand” 作为键。
如果信息不存在,请使用 “未知” 作为值。
让你的回应尽可能简短。
将 Anger 值格式化为布尔值。

评论文本: ```{lamp_review_zh}```
"""
response = get_completion(prompt)
print(response)

输出:

{
"Sentiment": "正面",
"Anger": false,
"Item": "卧室灯",
"Brand": "Lumina"
}

这个例子中,我们告诉它将愤怒值格式化为布尔值,然后输出一个 JSON。大家可以自己尝试不同的变化,或者甚至尝试完全不同的评论,看看是否仍然可以准确地提取这些内容。

推断主题

大型语言模型的一个很酷的应用是推断主题。给定一段长文本,这段文本是关于什么的?有什么话题?

文本:

story_zh = """
在政府最近进行的一项调查中,要求公共部门的员工对他们所在部门的满意度进行评分。
调查结果显示,NASA 是最受欢迎的部门,满意度为 95%。

一位 NASA 员工 John Smith 对这一发现发表了评论,他表示:
“我对 NASA 排名第一并不感到惊讶。这是一个与了不起的人们和令人难以置信的机会共事的好地方。我为成为这样一个创新组织的一员感到自豪。”

NASA 的管理团队也对这一结果表示欢迎,主管 Tom Johnson 表示:
“我们很高兴听到我们的员工对 NASA 的工作感到满意。
我们拥有一支才华横溢、忠诚敬业的团队,他们为实现我们的目标不懈努力,看到他们的辛勤工作得到回报是太棒了。”

调查还显示,社会保障管理局的满意度最低,只有 45%的员工表示他们对工作满意。
政府承诺解决调查中员工提出的问题,并努力提高所有部门的工作满意度。
"""

推断5个主题

上面是一篇虚构的关于政府工作人员对他们工作机构感受的报纸文章。我们可以让它确定五个正在讨论的主题,用一两个字描述每个主题,并将输出格式化为逗号分隔的列表。

输入:

prompt = f"""
确定以下给定文本中讨论的五个主题。

每个主题用1-2个单词概括。

输出时用逗号分割每个主题。

给定文本: ```{story_zh}```
"""
response = get_completion(prompt)
print(response)
调查结果, NASA, 社会保障管理局, 员工满意度, 政府承诺

为特定主题制作新闻提醒

假设我们有一个新闻网站或类似的东西,这是我们感兴趣的主题:NASA、地方政府、工程、员工满意度、联邦政府等。假设我们想弄清楚,针对一篇新闻文章,其中涵盖了哪些主题。可以使用这样的 prompt:确定以下主题列表中的每个项目是否是以下文本中的主题。以 0 或 1 的形式给出答案列表。

输入:

prompt = f"""
判断主题列表中的每一项是否是给定文本中的一个话题,

以列表的形式给出答案,每个主题用 0 或 1。

主题列表:美国航空航天局、地方政府、工程、员工满意度、联邦政府

给定文本: ```{story_zh}```
"""
response = get_completion(prompt)
print(response)

输出:

美国航空航天局:1
地方政府:1
工程:0
员工满意度:1
联邦政府:1

所以,这个故事是关于 NASA 的。它不是关于地方政府的,不是关于工程的。它是关于员工满意度的,它是关于联邦政府的。这在机器学习中有时被称为 Zero-Shot 学习算法,因为我们没有给它任何标记的训练数据。仅凭 prompt,它就能确定哪些主题在新闻文章中涵盖了。

如果我们想生成一个新闻提醒,也可以使用这个处理新闻的过程。假设我非常喜欢 NASA 所做的工作,就可以构建一个这样的系统,每当 NASA 新闻出现时,输出提醒。

输入:

prompt = f"""
判断主题列表中的每一项是否是给定文本中的一个话题,

以列表的形式给出答案,每个主题用 0 或 1。

主题列表:美国航空航天局、地方政府、工程、员工满意度、联邦政府

给定文本: ```{story_zh}```
"""

response = get_completion(prompt)
topic_dict = {i.split(':')[0]: int(i.split(':')[1]) for i in response.split(sep='\n')}
if topic_dict['美国航空航天局'] == 1:
print("提醒: 关于美国航空航天局的新消息")
else:
print(response)

输出为:

提醒: 关于美国航空航天局的新消息

这就是关于推断的全部内容了,仅用几分钟时间,我们就可以构建多个用于对文本进行推理的系统,而以前则需要熟练的机器学习开发人员数天甚至数周的时间。这非常令人兴奋,无论是对于熟练的机器学习开发人员还是对于新手来说,都可以使用 prompt 来非常快速地构建和开始相当复杂的自然语言处理任务。