总览
v1.0:
用户提出Query:产品的优点是什么。
AI 回答Answer:
过程:
- 收集原始数据 rawData (txt,doc,ppt,excel…)
- 将原始数据切割成 若干trunk,得到知识库。(为了解决原始文档过大,不能直接放入到 prompt 上下文里,以及清洗数据)
- 寻找和 query 相关性较大的 trunk
- trunk 和 对应的向量
- 计算相关性(Q 的向量和trunk 的向量)
- 从而找到相关性较高的文本
- 将 Q 的string 和 trunk 的 string(不是向量)放入到 prompt
- 让大模型回复。
所以问题的关键是,如何进行相似性计算。
Q:可以直接比较token 重合度吗?
A:不行。因为很表面。要考虑到近义词,语境之类的,比如 手机,电话,两者是相似的,但是单词都不一样。所以要比较的是 Query 和 trunk 之间的真正含义。
Q:如何表达真正的意思?
A:向量。
难点 1:一个 string 计算 vector
计算vector 的方法,对结果的影响是很大的。(什么样的向量 语义化
难点 2:vector1 和 vector2 计算相似度
难点 3:Q 的 vector 和 所有trunk 的 vector 比较计算相似性时,计算复杂度太高:O(n),所以需要向量数据库快速查询。
步骤细节
如何从文本——→trunk?
- 根据句子来切分。
- 每个句子切分。
- nltk sent_tokenize
- 根据字符数来切分
- 每 100 个字符切割一次。
- nltk
- 按固定字符数,但结合 overlapping window
- 每 100 个字符切割一次
- eg 每 5 个字符,2 的 overlapping:(1,2,3,4,5)(4,5,6,7,8)(7,8,9,10,11)
- 递归方法:RecursiveCharacterTextSplitter(来自 langChain)
- 常用,首选
- 根据语义切割
- 难度大,要跑很多机器学习的算法。
eg:
常用工具
英文:
- nltk
文本向量化(trunk—>向量)
常用的方法:
- openai 的 embedding model(调接口)
- 同理 Claude,gemini,等等
向量间的相似度计算
最常用的:余弦相似度(-1,1)
这是最常用的方法之一。它测量两个向量之间的夹角的余弦值。余弦相似度的值范围在-1到1之间,1表示方向相同,0表示正交,-1表示方向相反。
计算方法:
cosine_similarity = (A · B) / (||A|| * ||B||)
其中A·B是向量的点积,||A||和||B||分别是向量A和B的欧几里得范数。
向量点积的计算:
向量点积(Dot Product):
- 向量点积(Dot Product):
向量点积,也称为标量积或内积,是两个向量的对应元素相乘后求和的结果。对于两个n维向量 A = (a1, a2, ..., an) 和 B = (b1, b2, ..., bn),它们的点积计算如下:
A · B = a1b1 + a2b2 + ... + anbn
def dot_product(A, B): return sum(a * b for a, b in zip(A, B)) # 使用NumPy库可以更简洁地计算: import numpy as np A = np.array([a1, a2, ..., an]) B = np.array([b1, b2, ..., bn]) dot_product = np.dot(A, B)
欧几里得范数(Euclidean Norm):
欧几里得范数,也称为L2范数,是向量的长度或大小的度量。它是向量各元素平方和的平方根。
对于向量 A = (a1, a2, ..., an),其欧几里得范数计算如下:
||A|| = √(a1^2 + a2^2 + ... + an^2)
import math def euclidean_norm(A): return math.sqrt(sum(a**2 for a in A)) #numpy import numpy as np A = np.array([a1, a2, ..., an]) norm = np.linalg.norm(A)
# 余弦相似度计算 import numpy as np def cosine_similarity(A, B): dot_product = np.dot(A, B) norm_A = np.linalg.norm(A) norm_B = np.linalg.norm(B) return dot_product / (norm_A * norm_B)