大模型技术:LLM 支持的元数据提取算法
介绍
来源:作者利用人工智能(Flux AI)生成的图像
您是否知道企业每天都会收到数千条客户评论,每条评论都包含宝贵的见解?然而,理解这些数据并对其进行处理是一项艰巨的任务。非结构化数据的数量不断增长——社交媒体帖子、客户评论、文章等。处理这些数据并提取有意义的见解对于企业了解客户反馈至关重要。
非结构化数据的数量不断增长——社交媒体帖子、客户评论、文章等。人们创建了许多技术来处理这些非结构化数据,例如情绪分析、关键字提取、命名实体识别、解析等。但这些方法往往无法完成更复杂的任务。大型语言模型 (LLM) 的发展使人们能够对传统 NLP 算法难以理解的信息进行更高层次的理解和提取。
用例
假设您拥有一家企业,想了解客户对您的产品的感受,并找出改进产品的可能方法。虽然评论中的数字评分可以大致了解对产品的满意度,但它们在具体功能方面可能更有意义。要真正了解对产品的反馈,您必须处理大量评论:了解优缺点、可以改进的地方、产品的平均使用时间等。需要对文本进行人类级别的理解,以提取这些基本特征以供进一步分析。这就是 LLM 发挥作用的地方,它们能够解释客户反馈并以易于分析的结构化方式呈现它。
本文将重点介绍 LLM 从产品评论中提取有意义的元数据的功能,具体来说是使用 OpenAI API。
数据
我们决定使用亚马逊评论数据集。以下是所选数据集自述文件中的引用:
Amazon 评论数据集由来自 Amazon 的评论组成。数据跨越 18 年,截至 2013 年 3 月,共包含约 3500 万条评论。评论包括产品和用户信息、评分和纯文本评论。它在以下论文中用作文本分类基准:Xiang Zhang、Junbo Zhao、Yann LeCun。用于文本分类的字符级卷积网络。神经信息处理系统进展 28(NIPS 2015)。
Amazon 评论全分数据集是通过针对从 1 到 5 的每个评论评分随机抽取 600,000 个训练样本和 130,000 个测试样本构建的。总共有 3,000,000 个训练样本和 650,000 个测试样本。
train.csv 和 test.csv 文件包含所有训练样本,以逗号分隔的值形式显示。其中有 3 列,分别对应类别索引(1 至 5)、评论标题和评论文本。
数据处理
由于我们的主要兴趣领域是从评论中提取元数据,因此我们必须选择评论子集并使用选定的感兴趣字段手动标记它。我们选择从评论中提取以下结构:
class ProductReview(BaseModel):
pros: list[str]
cons: list[str]
product_features: list[str]
use_case: str
experience: str
usage_duration: str
improvements: list[str]
stars_of_review: int
support_quality: int
refund: bool
以下是字段的细分:
- Pros:对客户体验产生积极影响的事件或功能列表
- Cons:损害客户体验的事件或功能列表
- Product features:评论中提到的功能列表
- Use case:评论中提到的产品用例
- Experience:基于评论语义的客户整体体验。体验可以是正面的、负面的或混合的
- Usage duration:如果提到,客户在撰写评论时使用了该产品多长时间。
- Improvements:客户在评论中提到的功能或修复列表
- Stars of review:LLM 根据评审文本预测评审星级
我们选择了 62 条评论作为测试数据集,然后标记了它们的元数据。
一些有价值的字段(支持质量和客户是否要求退款)不在我们的子集中,但我们将它们保留在管道中。以防万一它们出现在您的数据集中。
Pipeline
我们利用 OpenAI 的 LLM(特别是 GPT-4o)的零样本提示方法。它允许解释评论和提取数据,而无需大量标记数据集。它减少了训练和管道设置时间,同时实现了快速设置和结果计算。零样本技术有助于根据带有当前任务描述的提示执行 LLM 未明确训练的任务。
一个有效的提示可以向 LLM 解释如何处理数据以及我们期望的结果,这是成功的关键。以下是我们用于任务的提示(Medium 端的 Markdown 渲染不正确):
You are an intelligent assistant designed to analyze product reviews and extract specific information to populate a structured data model. Your task is to process a given product review text and extract the following fields:
1. **pros** (`List[str]`). Empty list if no pros.
- **Description**: A list of positive aspects or advantages mentioned in the review.
2. **cons** (`List[str]`). Empty list if no cons.
- **Description**: A list of negative aspects or disadvantages mentioned in the review.
3. **product_features** (`List[str]`). Empty list if no features.
- **Description**: Specific features or components of the product discussed in the review.
4. **use_case** (`str`). Empty string if no use case mentioned.
- **Description**: The intended or actual use case of the product (e.g., daily usage, gaming, professional use, present).
5. **experience** (`str`)
- **Description**: A summary of the reviewer's overall experience with the product. Positive or negative
6. **usage_duration** (`str`). Empty string if not specified in review.
- **Description**: Duration of product usage mentioned in the review (e.g., "6 months", "1 year").
7. **improvements** (`List[str]`). Empty list if not specified in review.
- **Description**: Suggested improvements or enhancements for the product.
8. **stars_of_review** (`int`, between 1 and 5).
- **Description**: Star rating of the review, ranging from 1 to 5.
9. **support_quality** (`int`, default -1):
- **Description**: Rating or feedback on customer support, if mentioned. Use a scale (e.g., 1-5). If not mentioned, set to -1.
10. **refund** (`bool`, default False):
- **Description**: Indicates whether the reviewer mentions receiving a refund (`True`) or not (`False`).
**Instructions:**
- **Input**: You will be provided with a single product review text.
- **Output**: Extract the specified fields and present them in a well-formatted JSON object that matches the `ProductReview` schema.
- **Formatting Requirements**:
- Use JSON syntax.
- Use appropriate data types for each field.
- If a field is not mentioned in the review, use the default value as specified.
- For the `stars_of_review` field process the review and convert it into an integer scale ranging from 1 to 5
- For the `support` field, if feedback on customer support is mentioned, extract the rating or qualitative feedback and convert it to an integer scale (e.g., 1-5). If not mentioned, set it to -1.
- For the `refund` field, set it to `True` if the review mentions receiving a refund, otherwise `False`.
其中一个重大挑战是处理 LLM 的输出。模型的响应可能并不总是您所期望的,因为它可能会产生幻觉、截断输出等。我们利用了 OpenAI 的新功能——结构化输出来解决这个问题。它确保与您提供的 JSON 模式 100% 一致。结构化输出允许输入 JSON 模式:
{
"type": "json_schema",
"json_schema": {
"name": "product_review",
"schema": {
"type": "object",
"properties": {
"pros": {
"type": "array",
"items": {
"type": "string"
}
},
"cons": {
"type": "array",
"items": {
"type": "string"
}
},
"product_features": {
"type": "array",
"items": {
"type": "string"
}
},
"use_case": {
"type": "string"
},
"experience": {
"type": "string"
},
"usage_duration": {
"type": "string"
},
"improvements": {
"type": "array",
"items": {
"type": "string"
}
},
"stars_of_review": {
"type": "integer"
},
"support_quality": {
"type": "integer"
},
"refund": {
"type": "boolean"
}
},
"required": [
"pros",
"cons",
"product_features",
"use_case",
"experience",
"usage_duration",
"improvements",
"stars_of_review",
"support_quality",
"refund"
],
"additionalProperties": False
},
"strict": True
}
}
或者,类似地,一个 pydantic 模型:
from pydantic import BaseModel
class ProductReview(BaseModel):
pros: list[str]
cons: list[str]
product_features: list[str]
use_case: str
experience: str
usage_duration: str
improvements: list[str]
stars_of_review: int
support_quality: int
refund: bool
在我们的实施中,我们使用了 LangChain 框架,该框架有助于处理不同的 LLM,并允许在各种模型之间轻松切换。为了降低成本,我们使用了批处理 API,该 API 为 OpenAI API 请求提供了 50% 的折扣。
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
import os
import config
os.environ['OPENAI_API_KEY'] = config.OPENAI_API_KEY
MODEL = 'gpt-4o-2024-08-06'
llm = ChatOpenAI(
model=MODEL,
temperature=0,
max_tokens=None,
timeout=None,
max_retries=2,
)
structured_llm = llm.with_structured_output(ProductReview)
response = structured_llm.batch(batch)
指标
我们计算了两个关键领域的指标来评估模型的准确性:星级评分预测和元数据提取。对于星级评分,我们将模型的预测与初始数据集中可用的实际评分进行了比较。至于元数据提取,我们设计了一个自定义的基于嵌入的指标来将预测与标签进行比较。
标星准确度
对于星级,我们只选择了 100 条评论(比我们的标记数据集多一点)。为了评估我们模型的星级预测的准确性,我们采用了均方根误差 (RMSE) 指标。RMSE 测量预测误差和实际误差之间的误差,显着误差对指标的影响很大,因为它会平方值之间的差异。
来源:图片取自来源
使用零样本技术(未事先对模型进行微调)计算 LLM 预测的 RMSE 为 0.76。您可能认为它并不接近 0,但对于评论来说,由于个人估计偏差,+- 1 星是可以接受的。
我们对所得结果的混淆度指标进行了可视化,以了解误差的性质。它显示了对分配的不同星级的预测频率以及它们与标签中的星级之间的关联。
来源:作者创作的图片
该矩阵显示,模型的预测通常与数据集中的实际评分相差 1 星。深入研究这个问题后,我们发现了以下评论:
这部充满了动物的电影确实让我的孙子在我照看孩子时很忙碌。他喜欢一遍又一遍地看。在他厌倦之前,我可以完成很多事情。所以,这很值得!事实上,我要为他家、他 3 岁表弟家和我家买一台。我们要和 Netflix 说再见了!亚马逊加油!!Gammy
令人惊讶的是,这篇评论只有 3 颗星,考虑到这篇评论的语气,这很奇怪。考虑到它的写作方式,模型给这篇评论打了 5 颗星,这似乎是合适的。
这本书是我图书馆的家谱部分,家谱书籍不允许带出图书馆。但我很喜欢它,以至于坐在图书馆里分两次读完它。这本书读起来很快,因为里面有很多图片:贫民窟及其居民的照片,还有配给卡、工作证、黄色星星等文物的照片。它更像是博物馆展品,而不是一本简单的书。由于格式的原因,我认为年轻人也能从这本书中得到一些东西,尽管它显然是为成年人写的。当然,它可能包含了关于科夫诺/考纳斯贫民窟的最多信息,而且都集中在一个地方。研究人员和对大屠杀感兴趣的普通人都会喜欢这本书。额外福利:这本书中印有伊利亚·格伯的日记页面;你可以在亚历山德拉·扎普鲁德的《挽救的页面:年轻作家的大屠杀日记》中阅读日记摘录。
这篇评论的评分为4星,而模型给出了5星。
有史以来最好的球拍。我已经使用这款球拍大约 15 年了,它仍然是 Prince 有史以来最好的球拍之一。Prince Graphite Mid Plus 仍然是您能买到的最硬的球拍之一,而且重量和平衡性也非常出色。这款球拍更适合更高水平的球员。它提供了出色的控制力,尤其是在截击时。我有 62-64 磅重的球拍,用于硬地和草地比赛。如果有一天这些球拍不再可用,那将是令人悲伤的一天。
鉴于这篇过于激动人心的文章,模型给它打了 5 颗星。然而,出于某种原因,这篇评论只有 4 颗星。
这项分析表明,有时,评论的星级并不总是与评论的实际文本完全对应,而且非常主观。LLM 对星级的预测基于评论的语义及其解释;因此,其星级预测可能更好地概括了评论背景。
注意:LLM 有自己的偏见,有时它们可能在模型预测中发挥关键作用。因此,在使用 LLM 时,请务必牢记这一点。不要将所有输出视为理所当然。
提取的元数据
RMSE 不适用于衡量元数据提取的质量,因为所有字段都是字符串或字符串列表。因此,我们必须将这些字符串表示为向量并计算它们的相似度。
为了正确测量字符串值之间的相似度,我们必须考虑底层上下文和语义。我们可以通过将字符串转换为捕获语义细节的高维嵌入表示来计算两个向量之间的角度。这是 NLP 中的一种常见做法,称为余弦相似度。它通常用于测量文本之间的相似度。为此,我们使用 OpenAI 文本嵌入模型 ( text-embedding-3-large ) 从字符串中获取嵌入并计算它们之间的余弦相似度。余弦相似度的计算方法如下:
来源:图片取自来源
其中 A · B 是向量 A 和 B 的点积,||A|| 是向量的欧几里得范数。
此外,我们在某些字段中有一个字符串列表。因此,可能会出现列表中的字符串多于预测中的字符串,反之亦然的情况。为了计算指标,我们获取了列表中所有字符串的嵌入,并得到了一个矩阵,其中 (i, j) 项是预测中的第 i 个条目和标签中的第 j 个条目之间的余弦相似度。
取矩阵中每行的最大值可得到预测向量的最佳标签对应关系。同样,每列的最大值可得到预测中标签向量的最佳对应关系。当列表中的条目不匹配(条目较多或较少)时,将标签与预测分开并反之亦然很有用。通过向量之间的最佳对应关系,我们可以计算平均余弦相似度值、精度、召回率和 f1 分数。
下面是上面定义的算法的实现:
def compute_bidirectional_similarity(true_embeddings, pred_embeddings):
if not pred_embeddings and not true_embeddings:
return {"precision": 1.0, "recall": 1.0, "f1": 1.0}
if not pred_embeddings or not true_embeddings:
return {"precision": 0.0, "recall": 0.0, "f1": 0.0}
pred_matrix = np.array(pred_embeddings)
true_matrix = np.array(true_embeddings)
sim_pred_to_true = cosine_similarity(pred_matrix, true_matrix)
max_sim_pred = sim_pred_to_true.max(axis=1)
precision = max_sim_pred.mean()
max_sim_true = sim_pred_to_true.max(axis=0)
recall = max_sim_true.mean()
f1_score = 2 * (precision * recall) / (precision + recall) if precision + recall else 0
return {
"precision": round(precision, 4),
"recall": round(recall, 4),
"f1": round(f1_score, 4)
}
以下是针对所选标记评论子集获得的结果。
来源:作者创作的图片
结论
我们采用 OpenAI 的 GPT-4o 数据提取算法展示了我们可以多么轻松地从非结构化数据中收集重要元数据以供进一步分析,而大多数传统算法都难以完成这项任务。
从结果来看,LLM 在预测星级评分和从评论中提取关键特征方面表现良好。此外,该模型对用户反馈评分的预测可能具有更好的合理性,并且缺乏个人主观性。谁知道呢,也许很快我们会有 2 个产品评级(第一个基于用户评分,第二个基于 LLM 评分),或者某个对最终消费者更有利的平均值。
总体而言,LLM 是帮助企业更好地了解客户需求、促进分析、增强产品和更快地处理大量非结构化数据的强大工具。
参考:
https://pub.towardsai.net/llm-powered-metadata-extraction-algorithm-14267f053d53