Skip to content

LV010-向量与文本表示

在 RAG(Retrieval-Augmented Generation,检索增强生成)中,Embedding(向量)是实现语义检索的核心。理解 Embedding 的原理和工程实践,是构建高质量智能检索系统的基础。

一、Embedding

1. Embedding 到底是什么?

Embedding(嵌入向量) 是一种把文本、图片、音频等数据转换为 计算机能理解的数字向量 的技术。通过这种方式,计算机可以使用数学运算来比较它们的相似度,进行分类、聚类、搜索等任务。

Embedding(向量)本质上是将文本映射到一个高维空间中的数学坐标。这样,模型就能通过距离来衡量文本间的语义相似度。下方的流程图直观展示了文本如何被映射为向量,并通过距离体现语义关系:

2025-11-17-2138

在这个空间中,意思相近的文本距离更近,意思相反或无关的文本距离更远。

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-small1536
bge-base-zh768
bge-large-zh1024
Cohere Embed v3 large4096
Mistral embedding1024
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

shell
ollama pull qwen3-embedding:0.6b

2. demo.py

直接看这个:01_quick_start/20_Embedding/01_embedding_demo.py · master · sumu.k/ai-llm-demo

python
# -*- 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. 测试结果

我们运行看一下:

shell
=== 文本向量化和相似度计算 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 检索的核心原理。

参考资料:

Attention Is All You Need

第六讲 - 向量语义与嵌入

Embedding(向量)与文本表示 | Jimmy Song