LV010-向量与文本表示
在 RAG(Retrieval-Augmented Generation,检索增强生成)中,Embedding(向量)是实现语义检索的核心。理解 Embedding 的原理和工程实践,是构建高质量智能检索系统的基础。
一、Embedding
1. Embedding 到底是什么?
Embedding(嵌入向量) 是一种把文本、图片、音频等数据转换为 计算机能理解的数字向量 的技术。通过这种方式,计算机可以使用数学运算来比较它们的相似度,进行分类、聚类、搜索等任务。
Embedding(向量)本质上是将文本映射到一个高维空间中的数学坐标。这样,模型就能通过距离来衡量文本间的语义相似度。下方的流程图直观展示了文本如何被映射为向量,并通过距离体现语义关系:
在这个空间中,意思相近的文本距离更近,意思相反或无关的文本距离更远。
2. 为什么需要 Embedding
- 计算机只能处理数字,而文本、图片等数据是非结构化的,无法直接计算。
- Embedding 让计算机能够理解数据的 语义信息,相似的内容在“数学空间”中会更接近。
- 通过向量化,计算机可以高效进行 搜索、分类、推荐 等操作。
3. Embedding 代表什么?
- 语义信息:相似的文本或图片,其向量表示在数学空间中更接近。
- 高维度特征:通常是 128、256、512 或更高维度的向量,每个维度代表某种特征。
- 可计算性:可以用向量距离(如 余弦相似度)来衡量相似性。
二、为什么向量能代表“语义”?
Embedding 之所以能表达语义,关键在于其背后的 Transformer(变换器,Transformer)模型通过自注意力机制学习了大规模文本中的语义结构。
常见的 Embedding 模型包括:BERT 类模型、LLaMA / Mistral 的 Embedding 模式、OpenAI text-embedding-3-large、bge-large-zh 等中文模型。这些模型能够捕捉:词与词之间的语义关系、概念之间的映射、上下文逻辑等信息。因此,模型可以理解:
- “K8s”与“Kubernetes”是等价词
- “Service Mesh”与“Istio”强相关
- “云原生”与“容器化”有语义接近性
- “微服务”与“单体架构”语义相反
Embedding 空间可以看作是一个压缩后的“世界知识空间”。
三、Embedding 的关键参数:维度(dimension)
选择合适的向量维度(dimension)对于性能和效果至关重要。下表列举了常见模型的维度参数:
| 模型 | 维度 |
|---|---|
| OpenAI text-embedding-3-small | 1536 |
| bge-base-zh | 768 |
| bge-large-zh | 1024 |
| Cohere Embed v3 large | 4096 |
| Mistral embedding | 1024 |
| qwen3-embedding:8b | 最高4096 |
高维向量表达能力强,但检索成本更高。低维向量存储和检索效率高,但表达能力有限。
- 低维:类似 Prometheus 的 low-cardinality label,存储少、速度快,但表达能力弱。
- 高维:类似高卡标签,表达能力强,但检索成本更高(如 Milvus、Weaviate 需更优索引)。
经验建议:
- 通用 RAG:1024 是最佳平衡
- 中文问答 / 企业文档:bge-large-zh(1024)最优
- 跨语言需求:推荐 OpenAI 的 small/large
- 千万级数据:建议低维(512–768)以提升性能
四、距离度量(similarity metric)
衡量向量间相似度时,通常不直接用欧氏距离,而是采用更适合语义空间的度量方式。常见的相似度计算方法有:
- Cosine 相似度(最常用)
- Dot-product(向量数据库普遍支持)
- L2(欧氏距离,部分旧模型)
Cosine 相似度之所以主流,是因为它关注向量的方向而非长度,更能反映语义一致性。可以类比为:判断两个人兴趣是否相同(方向),而不是兴趣有多强烈(长度)。
五、不同类型的 Embedding
Embedding 不止一种类型,实际工程中需根据场景区分:
- 文本嵌入(Text Embedding):用于文档检索、知识库、RAG。
- 指令嵌入(Instruction Embedding / Query Embedding):优化“问题 → 文档”的相似度,如 bge-large-zh-instruct。
- 多模态嵌入(Image / Audio / Video Embedding):用于多模态检索,如 CLIP、SigLIP。
- Token Embedding:Transformer 输入层权重,非 RAG 检索用。
六、Python 生成向量并搜索
1. 模型准备
这里需要使用预训练模型(如 text-embedding-ada-002、BERT、Word2Vec)生成固定长度的向量(例如 512 维),我的显卡资源有限,这里用了 qwen3-embedding:0.6b:
ollama pull qwen3-embedding:0.6b2. demo.py
直接看这个:01_quick_start/20_Embedding/01_embedding_demo.py · master · sumu.k/ai-llm-demo:
# -*- coding: utf-8 -*-
# https://ollama.com/blog/embedding-models
import numpy as np
from ollama import embed
def get_embedding(text, model_name="qwen3-embedding:0.6b"):
"""
使用 Ollama 获取文本的向量表示
Args:
text (str): 输入文本
model_name (str): 使用的预训练模型名称
Returns:
list: 文本的向量表示
"""
try:
response = embed(model=model_name, input=text)
return response['embeddings'][0]
except Exception as e:
print(f"获取 embedding 时出错: {e}")
return None
def calculate_similarity(embedding1, embedding2):
"""
计算两个向量之间的余弦相似度
Args:
embedding1 (list): 第一个向量
embedding2 (list): 第二个向量
Returns:
float: 余弦相似度值 (0-1之间)
"""
# 将向量转换为 numpy 数组并调整形状
emb1 = np.array(embedding1).reshape(1, -1)
emb2 = np.array(embedding2).reshape(1, -1)
# 计算余弦相似度
similarity = np.dot(emb1, emb2.T) / (np.linalg.norm(emb1) * np.linalg.norm(emb2))
return similarity[0][0]
def main():
# 测试文本
texts = [
"人工智能是现代科技的重要组成部分",
"机器学习是人工智能的一个分支",
"今天天气很好",
"人工智能和机器学习密切相关",
"我叫小明"
]
print("=== 文本向量化和相似度计算 Demo ===\n")
# 获取每个文本的向量表示
embeddings_list = []
for i, text in enumerate(texts):
print(f"正在获取文本 {i+1} 的向量表示...")
print(f"文本内容: {text}")
embedding = get_embedding(text)
if embedding is not None:
embeddings_list.append(embedding)
print(f"向量维度: {len(embedding)}")
print("-" * 50)
else:
print(f"获取文本 '{text}' 的向量表示失败")
embeddings_list.append(None)
# 计算文本之间的相似度
print("\n=== 相似度计算结果 ===")
for i in range(len(embeddings_list)):
for j in range(i+1, len(embeddings_list)):
if embeddings_list[i] is not None and embeddings_list[j] is not None:
similarity = calculate_similarity(embeddings_list[i], embeddings_list[j])
print(f" 文本 {i+1}: {texts[i]}")
print(f" 文本 {j+1}: {texts[j]}")
print(f"文本 {i+1} vs 文本 {j+1} 相似度: {similarity:.4f}")
print("-" * 50)
else:
print(f"无法计算文本 {i+1} 和文本 {j+1} 之间的相似度(向量获取失败)")
if __name__ == "__main__":
main()3. 测试结果
我们运行看一下:
=== 文本向量化和相似度计算 Demo ===
正在获取文本 1 的向量表示...
文本内容: 人工智能是现代科技的重要组成部分
向量维度: 1024
--------------------------------------------------
正在获取文本 2 的向量表示...
文本内容: 机器学习是人工智能的一个分支
向量维度: 1024
--------------------------------------------------
正在获取文本 3 的向量表示...
文本内容: 今天天气很好
向量维度: 1024
--------------------------------------------------
正在获取文本 4 的向量表示...
文本内容: 人工智能和机器学习密切相关
向量维度: 1024
--------------------------------------------------
正在获取文本 5 的向量表示...
文本内容: 我叫小明
向量维度: 1024
--------------------------------------------------
=== 相似度计算结果 ===
文本 1: 人工智能是现代科技的重要组成部分
文本 2: 机器学习是人工智能的一个分支
文本 1 vs 文本 2 相似度: 0.7288
--------------------------------------------------
文本 1: 人工智能是现代科技的重要组成部分
文本 3: 今天天气很好
文本 1 vs 文本 3 相似度: 0.3679
--------------------------------------------------
文本 1: 人工智能是现代科技的重要组成部分
文本 4: 人工智能和机器学习密切相关
文本 1 vs 文本 4 相似度: 0.7456
--------------------------------------------------
文本 1: 人工智能是现代科技的重要组成部分
文本 5: 我叫小明
文本 1 vs 文本 5 相似度: 0.3705
--------------------------------------------------
文本 2: 机器学习是人工智能的一个分支
文本 3: 今天天气很好
文本 2 vs 文本 3 相似度: 0.3032
--------------------------------------------------
文本 2: 机器学习是人工智能的一个分支
文本 4: 人工智能和机器学习密切相关
文本 2 vs 文本 4 相似度: 0.7903
--------------------------------------------------
文本 2: 机器学习是人工智能的一个分支
文本 5: 我叫小明
文本 2 vs 文本 5 相似度: 0.3674
--------------------------------------------------
文本 3: 今天天气很好
文本 4: 人工智能和机器学习密切相关
文本 3 vs 文本 4 相似度: 0.3234
--------------------------------------------------
文本 3: 今天天气很好
文本 5: 我叫小明
文本 3 vs 文本 5 相似度: 0.4656
--------------------------------------------------
文本 4: 人工智能和机器学习密切相关
文本 5: 我叫小明
文本 4 vs 文本 5 相似度: 0.3351
--------------------------------------------------运行后会发现,与查询最相关的文本得分最高。这正是 RAG 检索的核心原理。
参考资料: