跳到主要内容
Python AI 应用开发:Embedding 向量表征与相似度计算 | 极客日志
Python AI 算法
Python AI 应用开发:Embedding 向量表征与相似度计算 介绍 Python 中 Embedding 向量表征的概念与应用,涵盖向量语义空间理解、相似度计算方法(余弦与欧氏距离)及向量数据库 Chroma 的使用。通过代码示例演示文本向量化过程,对比不同句子间的相似度,并讲解向量数据库与传统数据库的区别及核心功能,为 AI 应用开发提供基础技术支撑。
DataScient 发布于 2026/3/28 更新于 2026/6/6 36 浏览
1. 向量表征 (Vector Representation)
向量表征(Vector Representation)是核心概念之一。通过将文本、图像、声音、行为甚至复杂关系转化为高维向量(Embedding),AI 系统能够以数学方式理解和处理现实世界中的复杂信息。这种表征方式为机器学习模型提供了统一的'语言'。
1.1 通俗理解:AI 的'语义坐标系'
想象一下,我们有一个巨大的'语义空间',每个词或句子都被表示为一个点(向量)。语义越接近的词,在空间中的距离就越近。
例如:
'猫'和'狗'的向量距离很近(都是宠物)
'飞机'和'火车'距离较近(都是交通工具)
'猫'和'飞机'距离很远
这种将文本转化为数字向量的过程,就叫嵌入(Embedding) 。
1.2 数学/几何中的向量
在最简单的层面上,一个向量 就是一个具有大小 和方向 的量。物理学科上叫做矢量。
例子 :速度就是一个向量。如果你说'一辆车以 60 公里/小时的速度行驶',这只是一个标量(只有大小)。但如果你说'一辆车以 60 公里/小时的速度向北 行驶',这就是一个向量(大小是 60,方向是北)。
可视化 :在几何中,向量通常被画成一条带箭头的线段。线段的长度表示大小,箭头的指向表示方向。
坐标表示 :在二维平面中,一个向量可以用一对数字 (x, y) 来表示,比如 (3, 4)。这表示从原点 (0,0) 出发,指向点 (3,4) 的箭头。在三维空间,就是 (x, y, z)。
1.3 计算机科学中的向量
在计算机科学中,向量 的含义被泛化了。它本质上就是一个一维数组 ,即一列有序的数字 。
例子 :[1.5, -0.2, 3.14, 42.0] 就是一个包含 4 个数字的向量。
维度的含义 :这个向量的维度 就是它包含的数字个数。上面的例子是 4 维向量。在机器学习和 AI 中,我们经常会处理几百、几千甚至更高维度的向量。
在计算机的世界里,我们可以用这样一个数字列表(向量)来表示任何东西 。每个数字可以被看作是描述该事物的一个特征 或属性 。
用向量表示一杯饮料:
特征 1:甜度 (0 不甜,10 非常甜) -> 7
特征 2:酸度 (0 不酸,10 非常酸) -> 2
特征 3:温度 (0 冰,10 烫) -> 1
特征 4:咖啡因含量 (毫克) -> 90
那么,这杯饮料就可以表示为一个 4 维向量:[7, 2, 1, 90]。这杯饮料很可能是一杯冰甜咖啡。
1.4 向量 Embedding
向量嵌入 是'向量'概念的一个非常强大和重要的应用。它是一种 ,专门用于在计算机中 (如词语、图片、声音、用户、商品等),并捕捉其 或 。
特殊类型的向量
表示复杂对象
内在含义
语义
你可以把向量嵌入理解为一个对象的**'数字指纹'或 'DNA 序列'**。
向量嵌入的强大之处在于,它不仅仅是随机的一堆数字,而是通过复杂的机器学习模型(如 Word2Vec, Transformer 等)学习得到的。这些数字的排列方式具有以下关键特性:
语义相似性
含义相近的对象,它们的向量在空间中的距离会很近 。
例子 :'猫'和'狗'都是宠物,它们的向量距离会很近;而'猫'和'电脑'的向量距离会很远。
关系类比
向量空间中可以捕捉到类比关系。最著名的例子是:
'国王'的向量 - '男人'的向量 + '女人'的向量 ≈ '女王'的向量
这意味着词语之间的语义关系(如'性别关系')被编码在了向量的数学运算中。
1.5 向量嵌入是如何工作的?(以词嵌入为例) 想象一下,我们要把词语映射到一个 3 维空间(实际中维度更高,如 300 维、768 维),以便可视化:
初始状态 :一开始,计算机随机给每个词分配一个位置(一个向量)。
学习过程 :模型阅读海量文本(如维基百科)。它学习一个原则:'出现在相似上下文中的词语,具有相似的含义' 。
例如,'苹果'和'香蕉'经常出现在'吃'、'水果'、'甜'等词语附近。
而'苹果'和'微软'可能出现在'公司'、'技术'等词语附近。
最终结果 :经过学习,模型会调整每个词的向量位置。
'苹果'(水果)和'香蕉'、'橘子'的向量会聚集在一起。
'苹果'(公司)和'微软'、'谷歌'的向量会聚集在另一处。
'水果'这个大类会和'蔬菜'等大类在更高层级上靠近。
最终,我们得到了一个'语义地图',每个词都是这张地图上的一个点(即一个高维向量)。
1.6 Embedding 的核心价值 作用 说明 语义搜索 搜索'轻便的户外背包'也能匹配'登山用小容量背包' 自然语言处理 搜索引擎(理解你的查询意图)、机器翻译、智能客服、情感分析。 图像识别 将图片转换为向量,然后寻找相似的图片。 推荐系统 根据用户兴趣向量推荐相似内容 RAG 基础 检索最相关的知识片段,供大模型参考生成答案
2. 向量间相似度计算 余弦相似度是通过计算两个向量夹角的余弦值来衡量相似性,等于两个向量的点积除以两个向量长度的乘积。
2.1 实验环境准备 通过代码实验需要用到 Embedding 模型,这里接入的是兼容 OpenAI 协议的 API 服务。配置好环境变量后,即可使用。
这里我注册的环境变量名称为:EMBEDDING_API_KEY
numpy 用于做数值计算,它扩展了很多数据类型
openai 它提供了与 openai 兼容的 API 库,可以用来访问各种 AI 平台提供的模型服务。
pip install --upgrade numpy openai
2.2 Embedding Model 嵌入模型(Embedding Model)是一种将离散数据(如文本、图像)映射到连续向量空间的技术。通过高维向量表示(如 768 维或 3072 维),模型可捕捉数据的语义信息,使得语义相似的文本在向量空间中距离更近。例如,'忘记密码'和'账号锁定'会被编码为相近的向量,从而支持语义检索而非仅关键词匹配。
语义编码 :将文本、图像等转换为向量,保留上下文信息(如 BERT 的 CLS Token 或均值池化)。
相似度计算 :通过余弦相似度、欧氏距离等度量向量关联性,支撑检索增强生成(RAG)、推荐系统等应用。
信息降维 :压缩复杂数据为低维稠密向量,提升存储与计算效率。
2.2.1 主流嵌入模型分类 Embedding 模型将文本转换为数值向量,捕捉语义信息,使计算机能够理解和比较内容的'意义'。选择 Embedding 模型的考虑因素:
因素 说明 任务性质 匹配任务需求 (问答、搜索、聚类等) 领域特性 通用 vs 专业领域 (医学、法律等) 多语言支持 需处理多语言内容时考虑 维度 权衡信息丰富度与计算成本 许可条款 开源 vs 专有服务 最大 Tokens 适合的上下文窗口大小
BGE-M3 :北京智源研究院开发,支持多语言、混合检索(稠密 + 稀疏向量),处理 8K 上下文,适合企业级知识库。
NV-Embed-v2 :基于 Mistral-7B,检索精度高(MTEB 得分 62.65),但需较高计算资源。
中文场景 :BGE-large-zh-v1.5(合同/政策文件)、M3E-base(社交媒体分析)。
多模态场景 :BGE-VL(图文跨模态检索),联合编码 OCR 文本与图像特征。
nomic-embed-text :768 维向量,推理速度比 OpenAI 快 3 倍,适合边缘设备。
gte-qwen2-1.5b-instruct :1.5B 参数,16GB 显存即可运行,适合初创团队原型验证。
中文为主 → BGE 系列 > M3E;多语言需求 → BGE-M3 > multilingual-e5;预算有限 → 开源模型(如 Nomic Embed)
2.3 通用包 代码中创建一个通用包 common,这个包下提供两个通用函数:
创建 openai 客户端
获取 embedding 模型
import os
from openai import OpenAI
def _get_client ():
api_key = os.getenv("EMBEDDING_API_KEY" )
base_url = "https://dashscope.aliyuncs.com/compatible-mode/v1"
return OpenAI(api_key=api_key, base_url=base_url)
def get_embedding (text, model="text-embedding-v4" ):
"""获取 embedding 向量,默认使用 text-embedding-v4"""
client = _get_client()
if isinstance (text, list ):
return client.embeddings.create(input =text, model=model)
text = text.replace("\n" , " " )
return client.embeddings.create(input =[text], model=model)
2.4 文本转向量 在 main 函数中我们输入一小段文字,使用模型进行向量化:
from common import model_utils
if __name__ == "__main__" :
text = "今天天气不错"
response = model_utils.get_embedding(text)
print (response.model_dump_json())
result = response.data[0 ].embedding
print (result[:3 ])
print (len (result))
打印出来的数组元素为 1024 个,即默认是 1024 个维度。
2.5 距离计算 现在在 common/model_utils.py 中继续添加两个函数,分别用于计算余弦距离和欧式距离。
在这之前,我们先要熟悉一个 numpy 中的两个函数 dot 和 norm。
2.5.1 点积 (dot) dot 函数主要用于计算两个数组的点积(Dot Product) 。对于一维向量 :它计算的是对应元素的乘积之和。
import numpy as np
from numpy import dot
a = np.array([1 , 2 , 3 ])
b = np.array([4 , 5 , 6 ])
result = dot(a, b)
print (result)
对于二维矩阵 :它执行的是标准的矩阵乘法。('行乘列 '的运算规则。)
2.5.2 范数/长度 (norm) norm 函数用于计算向量或矩阵的范数 。在处理向量时,默认计算的是 L2 范数(欧几里得长度) ,即向量在空间中的物理长度。
from numpy.linalg import norm
a = np.array([3 , 4 ])
dist = norm(a)
print (dist)
2.5.3 余弦相似度计算 import numpy as np
from numpy import dot
from numpy.linalg import norm
def cosine_similarity (v1, v2 ):
return dot(v1, v2) / (norm(v1) * norm(v2))
vec1 = np.array([1 , 1 , 0 ])
vec2 = np.array([1 , 0 , 1 ])
similarity = cosine_similarity(vec1, vec2)
print (f"相似度:{similarity:.4 f} " )
2.5.4 欧式距离 def l2 (a, b ):
'''欧氏距离 -- 越小越相似'''
x = np.asarray(a) - np.asarray(b)
return norm(x)
2.6 相似度对比 下面我们将三句话进行向量化,然后对比它们之间的相似度:
text1 = "Spring AI 帮助开发者快速集成人工智能功能"
text2 = "Spring AI 是一个用于构建 AI 应用的框架"
text3 = "Java 是一种跨平台的编程语言"
text_list = [text1, text2, text3]
response_data = model_utils.get_embedding(text_list).data
embedding_list = [data.embedding for data in response_data]
print (f"text1 与 text2 余弦距离:{model_utils.cosine_similarity(embedding_list[0 ], embedding_list[1 ])} " )
print (f"text1 与 text3 余弦距离:{model_utils.cosine_similarity(embedding_list[0 ], embedding_list[2 ])} " )
print (f"text2 与 text3 余弦距离:{model_utils.cosine_similarity(embedding_list[1 ], embedding_list[2 ])} " )
print ("=" * 50 )
print (f"text1 与 text2 欧式距离:{model_utils.l2(embedding_list[0 ], embedding_list[1 ])} " )
print (f"text1 与 text3 欧式距离:{model_utils.l2(embedding_list[0 ], embedding_list[2 ])} " )
print (f"text2 与 text3 欧式距离:{model_utils.l2(embedding_list[1 ], embedding_list[2 ])} " )
text1 与 text2 余弦距离:0.8747069083399994
text1 与 text3 余弦距离:0.31450617230698164
text2 与 text3 余弦距离:0.373276450524592
==========================================
text1 与 text2 欧式距离:0.5005858686858007
text1 与 text3 欧式距离:1.1708918177413983
text2 与 text3 欧式距离:1.1195745555537098
余弦值越大,说明夹角越小,则越相似 (cos(0) = 1),很明显 text1 与 text2 是最相似的。
距离越小,说明两个向量相聚越小,则越相似,显然 text1 与 text2 之间的距离比较小。
3. 向量数据库 向量数据库,是专门为向量检索设计的中间件!高效存储、快速检索和管理高纬度向量数据的系统称为向量数据库 。
向量数据库的核心作用是实现相似性搜索,即通过计算向量之间的距离(如欧几里得距离、余弦相似度等)来找到与目标向量最相似的其他向量。它特别适合处理非结构化数据,支持语义搜索、内容推荐等场景。
注意 text Embedding model 只能对文本向量化,对于 image 和 audio 则需要其它多模态模型。
3.1 向量数据库与传统数据库
数据类型
传统数据库:存储结构化数据(如表格、行、列)。
向量数据库:存储高维向量数据,适合非结构化数据。
查询方式
传统数据库:依赖精确匹配(如=、<、>)。
向量数据库:基于相似度或距离度量(如欧几里得距离、余弦相似度)。
应用场景
传统数据库:适合事务记录和结构化信息管理。
向量数据库:适合语义搜索、内容推荐等需要相似性计算的场景。
注意:向量数据库的意义是快速的检索;向量数据库本身不生成向量,向量是由 Embedding 模型产生的;向量数据库与传统的关系型数据库是互补的,不是替代关系,在实际应用中根据实际需求经常同时使用。
数据库 类型 核心特点 Milvus 开源 + 云 功能全面、支持多种索引和分布式部署,适合大规模生产环境。 Pinecone 商业 SaaS 全托管、API 简单易用,适合快速开发,但不开源、需联网。 Weaviate 开源 + 企业版 内置语义搜索与知识图谱能力,支持 GraphQL,上手容易。 Qdrant 开源 + 云 性能优秀、支持过滤和集群,Rust 编写,部署简单。 Chroma 开源 轻量级,专为 LLM 应用设计,与 LangChain 深度集成,适合原型或小项目。 FAISS 开源库(非数据库) Meta 出品,高效向量检索,但无持久化或服务功能,常用于研究或嵌入其他系统。 Vespa 开源 Yahoo 出品,支持实时搜索、排序和向量混合查询,适合复杂业务逻辑。 Redis (带向量模块)开源 + 商业 在 Redis 中添加向量搜索能力,适合已有 Redis 架构、要求低延迟的场景。
3.2 Chroma 向量数据库 Chroma 是一款开源的向量数据库,专为高效存储和检索高维向量数据设计。其核心能力在于语义相似性搜索,支持文本、图像等嵌入向量的快速匹配,广泛应用于大模型上下文增强(RAG)、推荐系统、多模态检索等场景。与传统数据库不同,Chroma 基于向量距离(如余弦相似度、欧氏距离)衡量数据关联性,而非关键词匹配。
轻量易用:以 Python/JS 包形式嵌入代码,无需独立部署,适合快速原型开发。
灵活集成:支持自定义嵌入模型(如 OpenAI、HuggingFace),兼容 LangChain 等框架。
高性能检索:采用 HNSW 算法优化索引,支持百万级向量毫秒级响应。
多模式存储:内存模式用于开发调试,持久化模式支持生产环境数据落地。
3.2.1 安装 Chroma
3.2.2 内存运行模式 import chromadb
client = chromadb.EphemeralClient()
3.2.3 持久化运行模式 import chromadb
client = chromadb.PersistentClient(path="/path/to/save/to" )
3.2.4 Chroma 操作流程 集合是 Chroma 中管理数据的基本单元,类似关系数据库的表。
import chromadb
from chromadb.utils import embedding_functions
if __name__ == "__main__" :
client = chromadb.PersistentClient(path="./chroma" )
default_ef = embedding_functions.DefaultEmbeddingFunction()
collection = client.create_collection(
name="my_collection" ,
configuration={
"hnsw" : {
"space" : "cosine" ,
"ef_search" : 100 ,
"ef_construction" : 100 ,
"max_neighbors" : 16 ,
"num_threads" : 4
},
"embedding_function" : default_ef
}
)
方法执行后,发现本地创建了一个文件 chroma/chroma.sqlite3,数据将会被持久化到这个文件中。
client.create_collection 方法其实只需要给定一个 name 参数即可,其它参数都有默认值。上面代码中给定的就是默认值。
collection = client.get_collection(name="my_collection" )
if collection is None :
collection = client.create_collection(name="my_collection" )
collection = client.get_collection(name="my_collection" )
print (collection.peek())
print (collection.count())
client.delete_collection(name="my_collection" )
collection.add(
documents=["RAG 是一种检索增强生成技术" , "向量数据库存储文档的嵌入表示" , "在机器学习领域,智能体(Agent)通常指能够感知环境、做出决策并采取行动以实现特定目标的实体" ],
metadatas=[{"source" : "RAG" }, {"source" : "向量数据库" }, {"source" : "Agent" }],
ids=["id1" , "id2" , "id3" ]
)
collection.update(ids=["id1" ], documents=["RAG 是一种检索增强生成技术,在智能客服系统中大量使用" ])
collection.delete(ids=["id3" ])
results = collection.query(
query_texts=["RAG 是什么?" ],
n_results=3 ,
)
print (results)
相关免费在线工具 加密/解密文本 使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
RSA密钥对生成器 生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
Mermaid 预览与可视化编辑 基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
随机西班牙地址生成器 随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online
Gemini 图片去水印 基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online
curl 转代码 解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online