Embedding 和语义相似度入门:把文本变成可比较的向量
聊天接口返回的是文本,而很多 AI 应用首先要解决的是“这两段话是不是在说相近的事情”。例如,用户问“怎么重置密码”,知识库里的“找回账户登录凭证”虽然没有相同的关键词,却应该被检索到。Embedding(嵌入)就是解决这类问题的基础技术:它把文本转换成一串数字,使程序可以用数学方法比较语义接近程度。本文只聚焦这个核心概念,并完成一个可运行的最小实验。
Embedding 到底是什么
Embedding 模型接收一段文本,输出固定长度的浮点数列表,这个列表称为向量。向量中的单个数字通常没有可解释的“词义”,真正有意义的是向量在高维空间中的整体位置。意思相近的文本,经过同一个模型处理后,通常会落在相近的位置;主题不同的文本,距离通常更远。
可以把它想成一张没有坐标轴标签的语义地图。模型在训练时学会了把相关内容放在附近: “退款多久到账”和“退货后什么时候能收到钱”可能相近,而“如何烤面包”则会远一些。Embedding 不是翻译,也不是摘要;它不会直接给你一段人类可读的答案,而是为比较、搜索和聚类提供数值表示。
为什么不用关键词匹配
关键词搜索擅长找字面完全相同的内容,却不擅长处理同义表达、语序变化和概念关联。向量相似度搜索关注的是表示后的距离,因此可以补充关键词搜索的不足。但它也不是万能的:如果文本很短、领域术语很多,或者切分方式不合理,语义表示仍可能不符合业务预期。实际系统经常把关键词检索和向量检索组合起来,而不是把 Embedding 当成唯一答案。
需要注意一个边界:比较必须使用同一个 Embedding 模型。不同模型的向量维度或坐标空间不一定兼容,不能把模型 A 生成的向量直接和模型 B 的向量计算距离。模型升级后,已有向量通常也需要重新生成。
最小可运行示例:生成向量并计算相似度
先在虚拟环境中安装官方 Python SDK 和环境变量加载库:
1 | python -m pip install openai python-dotenv |
在项目目录的 .env 中配置密钥。这里只读取环境变量,不把真实密钥写入源码:
1 | OPENAI_API_KEY=替换为你的真实密钥 |
下面程序使用 OpenAI Python SDK 当前的 Embeddings 接口。input 可以是一段文本;返回对象的 data[0].embedding 是浮点数向量。示例同时请求两段文本,然后计算余弦相似度:
1 | import math |
运行命令是 python embedding_demo.py。程序会实际访问 API,因此需要网络和有效密钥;本文不伪造具体的相似度数值。你应当记录自己运行时的维度和数值,并再把第二句话替换成“今天北京天气如何”做对照。相似度的绝对大小受模型、语言和文本长度影响,不要把某个固定阈值当成通用结论。
余弦相似度如何工作
余弦相似度比较两个向量夹角的余弦值,公式为:
1 | similarity(a, b) = (a · b) / (||a|| × ||b||) |
分子是对应元素相乘后求和,也就是点积;分母是两个向量长度的乘积。它更关注方向而不是长度,所以适合比较“语义方向”。对常见的 Embedding 向量,结果通常落在接近 0 到 1 的范围,但不要在业务代码中武断假设所有模型都严格满足这个范围。若只比较一批向量,先归一化再用点积也可以得到相同的排序结果。
示例中的 zip 会按位置配对元素,因此两个向量必须长度一致。norm_a == 0 的保护不能省略:零向量没有方向,除法没有意义。生产代码还应确认 API 返回了预期的 data 项,并记录模型名称,便于排查向量来源。
常见问题
向量维度越大,效果一定越好吗? 不一定。维度是模型设计的一部分,不能单独代表质量;更大的向量还会占用更多存储和计算资源。应使用目标数据集做检索效果测试。
相似度高就代表答案正确吗? 不代表。相似度只能说明文本表示接近,不能证明事实正确,也不能代替权限判断、业务规则和答案生成。后续做 RAG 时,还要把召回片段交给模型,并保留来源信息。
为什么两次运行的数值不完全符合直觉? Embedding 模型可能对专有名词、否定词、很短的句子表现不同。先用真实业务句子组成小测试集,再观察排序,而不是只凭两个例子下结论。
能不能把整本书一次生成一个向量? 技术上可以,但一个向量会把大量主题压缩在一起,检索定位会变差。长文应先按语义和长度切分;这会在后续的文档切分主题中展开。
小结
Embedding 把文本转换成可计算的向量,余弦相似度则提供了一个简单的语义接近度指标。本文用 client.embeddings.create() 生成两个向量,并在本地完成相似度计算。掌握这个基础后,下一步就是决定如何切分文档、设计元数据,让向量不仅能比较,还能在真实知识库中被有效检索。