利用ChatGPT,自己动手写lite-ChatPDF-1

之前看到了网友的分享,讲解了 chatpdf 的原理,但是并没有看懂,不明白embedingcompletion 是什么意思,于是想着利用 chatgpt 学习一下,学习完之后一不做二不休,不如直接利用 chatgpt 写一个玩具版的 chatpdf。

1. 需求

首先我们有一个 pdf,文章内容 article_text,即背景信息文本为:

"这篇文章是关于运动的好处。锻炼已被证明可以改善身体健康、心理健康和整体福祉。经常锻炼的人不太可能患上慢性疾病,如肥胖症、糖尿病和心脏病。锻炼还可以改善情绪,降低压力水平。"

其次我们有一个问题文本 question_text,内容为:

"这篇文章的主题是什么?"

问题是背景信息太冗长,所以我们要找到文章中与问题最相关的那部分内容,然后将这部分内容与问题发送给chatgpt,让 chatgpt 根据这段内容,对问题进行回答。

在我们的例子中,文章中与问题"这篇文章的主题是什么?"最相关的内容,明显是"这篇文章是关于运动的好处。"这句话。

最后我们发送请求询问chatgpt:这篇文章是关于运动的好处。请根据以上信息回答问题,这篇文章的主题是什么?

2. 原理

下面针对和我一样听不懂的小白,讲一下 chatpdf 的实现原理:

  1. 将pdf中的文本读取后并分为N段,则得到一个长度为n的数组subtexts
  2. 求出问题文本对应的向量embedding_question ,至于这个向量是什么,你可以理解为文本的特征。(你不需要懂怎么求这个向量,只需要向 openai 发送请求即可,这个任务由 openai 完成,称为embedding
  3. 遍历前面N段文本即数组subtexts ,依次求出每段文本文本的向量,第 i 段文本对应的向量为embedding_sub
  4. **(重点)**找出N段文本中,与问题文本最相似的那段文本。即求出向量embedding_question 与每个embedding_sub 向量夹角的余弦值,并找出值最大的那段文本subtext[i] 。是不是很懵?为什么余弦值能代表相似度,不要着急,后面会解释
  5. 将文本subtext[i] 作为背景信息,让 chatgpt 根据以上信息,回答问题question_text

举个栗子,如下图所示,x 轴代表最炫民族风,y 轴代表鸡你太美,向量r=(3, 4) ,表示用户 r 对两首歌曲的评分是 3 和 4,用户 g 评分是 4 和 3,用户 b 的评分是 5 和 0。不难理解,用户 r 和用户 g 的品位更加相似,因此可以将g 喜欢的其他歌曲推荐给 r ,但用户 r 和 b 品位相差较大,则不该将小黑子 b 喜欢的歌曲推荐给 r 。

那么问题来了,如何用数学语言来描述两个用户的品位相似程度呢?

从图中可以看到,相似的用户向量夹角总是很小,相差较大的用户向量夹角则很大。那么我们计算夹角的余弦值不就可以表示用户的相似程度了吗?

夹角度数为 90,余弦值为 0,表示二者完全不相关;随着夹角度数的减小,二者越来越相似,直至夹角度数为 0,余弦值为 1,表示二者完全相同;

那么系统就可以通过计算不同用户间的余弦值,发现用户向量 r 与 g 的夹角余弦值较大,因此会将 g 喜欢的其他歌曲推荐给 r 。

下面是求向量a与向量b夹角的余弦值公式①:

同样的道理,我们也可以根据这个原理,找到文章中与问题最相关的那部分内容。至此,我们已经了解了 chatpdf 的工作原理。

3. 实现

我们就可以根据上面的思路,让chatgpt完成编码,最终编码结果如下

第1部分,求出问题文本对应的向量,将文章切分成多个子段

ini 复制代码
import openai

# 设置 OpenAI API 密钥
openai.api_key = "sk-xxxx"

# 定义要查找相似部分的两个文本
question_text = "What is the main topic of this article?"
article_text = "This article is about the benefits of exercise. Exercise has been shown to improve physical health, mental health, and overall well-being. People who exercise regularly are less likely to develop chronic diseases, such as obesity, diabetes, and heart disease. Exercise can also improve mood and reduce stress levels."


# 将问题文本question_text传递给 Embedding API,获取它们的向量表示
response_question = openai.Embedding.create(model="text-embedding-ada-002", input=question_text)
embedding_question = np.array(response_question["data"][0]["embedding"])


# 将文本B划分成多个子段
subtexts = article_text.split(". ")

第2部分,遍历所有子段,找出与问题最相关的子段。这段代码的关键部分就是求问题向量与子段向量夹角的余弦值。将上一节的余弦公式①用代码表示,分子是两个向量点乘,分母是两个向量的模相乘,就可以求出两个向量夹角的余弦值,即相似度。

ini 复制代码
similarity = np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
# 计算文本A与每个子段的相似度,找到相似度最高的子段
max_similarity = -1
max_subtext = ""

# 遍历分段后的子段
for subtext in subtexts:
    # 请求openai,得到子段的特征向量
    response_sub = openai.Embedding.create(model="text-embedding-ada-002", input=subtext)
    embedding_sub = np.array(response_sub["data"][0]["embedding"])

    # (重点)求问题文本与子段的相关度, 即求两个向量的余弦值
    similarity = np.dot(embedding_question, embedding_sub) / (np.linalg.norm(embedding_question) * np.linalg.norm(embedding_sub))

    # 找出与问题文本最相似的子段
    if similarity > max_similarity:
        max_similarity = similarity
        max_subtext = subtext

# 输出相关度最高的子段
print("Most similar subtext:", max_subtext)
print("-------------------------------------")

输出结果如下,可以看到,成功找到了与问题最相关的子段:

markdown 复制代码
Most similar subtext: This article is about the benefits of exercise
-------------------------------------

第3部分,将最相关子段和问题发给chatgpt,让其作出回答:

ini 复制代码
# 提出问题, 根据子段max_subtext, 回答问题question_text
prompt = f"{max_subtext}. According to the information provided above, what is the answer to the following question: {question_text} "
print("Question:", prompt)


# 调用 OpenAI GPT-3 API,根据问题生成回答
response3 = openai.Completion.create(
    model="text-davinci-003",
    prompt=prompt
)

# 输出回答
print("Answer:", response3.choices[0].text.strip())

输出结果如下,可以看到,由于我们将与问题最相关的文本内容,发送给了 chatgpt,所以 chatgpt 正确回答了问题:

kotlin 复制代码
Question: This article is about the benefits of exercise. According to the information provided above, what is the answer to the following question: What is the main topic of this article? 

Answer: The main topic of this article is the benefits of exercise.
相关推荐
柠石榴7 分钟前
《机器学习》(周志华)第二章 模型评估与选择
人工智能·机器学习
试剂界的爱马仕1 小时前
TCA 循环中间体如何改写肝损伤命运【AbMole】
大数据·人工智能·科技·机器学习·ai写作
Y3174291 小时前
python Day46 学习(日志Day15复习)
python·学习·机器学习
殇者知忧9 小时前
【论文笔记】若干矿井粉尘检测算法概述
深度学习·神经网络·算法·随机森林·机器学习·支持向量机·计算机视觉
YunTM10 小时前
贝叶斯优化+LSTM+时序预测=Nature子刊!
人工智能·机器学习
黑鹿02217 小时前
机器学习基础(四) 决策树
人工智能·决策树·机器学习
molunnnn18 小时前
day 18进行聚类,进而推断出每个簇的实际含义
机器学习·数据挖掘·聚类
Humbunklung18 小时前
机器学习算法分类
算法·机器学习·分类
郄堃Deep Traffic20 小时前
机器学习+城市规划第十三期:XGBoost的地理加权改进,利用树模型实现更精准的地理加权回归
人工智能·机器学习·回归·城市规划
databook21 小时前
概率图模型:机器学习的结构化概率之道
python·机器学习·scikit-learn