以编程方式使用文档

概述

嵌入模型将原始文本(如句子、段落或推文)转换为固定长度的数字向量,捕捉其 **语义含义**。这些向量使机器能够基于含义而非精确词汇来比较和搜索文本。

在实践中,这意味着具有相似想法的文本在向量空间中彼此靠近放置。例如,不仅匹配短语 *"机器学习"*,嵌入可以呈现讨论相关概念的文件,即使使用了不同的措辞。

工作原理

  1. **向量化** — 模型将每个输入字符串编码为高维向量。
  2. **相似度评分** — 使用数学度量比较向量,以衡量底层文本之间的相关程度。

相似度度量

几种常见的度量用于比较嵌入:

  • * **余弦相似度** — 测量两个向量之间的角度。
  • * **欧几里得距离** — 测量点之间的直线距离。
  • * **点积** — 测量一个向量在另一个向量上的投影量。

以下是计算两个向量之间余弦相似度的示例:

def cosine_similarity(vec1, vec2):
    dot = np.dot(vec1, vec2)
    return dot / (np.linalg.norm(vec1) * np.linalg.norm(vec2))

similarity = cosine_similarity(query_embedding, document_embedding)
print("Cosine Similarity:", similarity)

接口

LangChain 通过 Embeddings 接口为文本嵌入模型(如 OpenAI、Cohere、Hugging Face)提供标准接口。

两个主要方法可用:

  • * embed_documents(texts: List[str]) → List[List[float]]:嵌入文档列表。
  • * embed_query(text: str) → List[float]:嵌入单个查询。

热门集成

模型
OpenAIEmbeddingslangchain-openai
AzureOpenAIEmbeddingslangchain-openai
GoogleGenerativeAIEmbeddingslangchain-google-genai
HuggingFaceEmbeddingslangchain-huggingface
OllamaEmbeddingslangchain-ollama
TogetherEmbeddingslangchain-together
MistralAIEmbeddingslangchain-mistralai
CohereEmbeddingslangchain-cohere
NomicEmbeddingslangchain-nomic
DatabricksEmbeddingsdatabricks-langchain
NVIDIAEmbeddingslangchain-nvidia
AIMLAPIEmbeddingslangchain-aimlapi
PerplexityEmbeddingslangchain-perplexity

常见部署模式

在实践中,大多数团队收敛于四种模式之一:

  1. 托管、旗舰:OpenAI text-embedding-3-large、Cohere embed-english-v3、Google gemini-embedding-001、Voyage voyage-3。一次 API 调用,开箱即用的最佳质量,无需本地基础设施。每次调用成本和数据出口依赖。
  2. 本地、开源: BAAI/bge-*, mixedbread-ai/mxbai-embed-*, Qwen/Qwen3-Embedding-*, nomic-ai/modernbert-embed-*, sentence-transformers/all-*一次下载,随处运行。无按调用计费成本,数据永不离开您的环境。在小规模下可能比托管API慢;如果有GPU,则速度相当或更快。
  3. 本地、开源、专业化:一个针对您的特定领域、语言或任务进行微调的模型。以强大的开源基础模型为起点(例如 BAAI/bge-m3) and fine-tuning on even a few thousand in-domain query/document pairs often beats hosted flagships on retrieval accuracy for that domain.
  4. 在生产规模上自托管:通过 Text Embeddings Inference (TEI) 或Ollama提供相同的开源模型(基础版或微调版)。让您享有本地推理的经济效益,同时具备托管服务商的水平扩展能力和API易用性。

LangChain对四种方式一视同仁:您实例化一个 Embeddings 子类并将其交给向量存储或检索器。模式(2)和(3)使用 HuggingFaceEmbeddings;模式(4)使用 HuggingFaceEndpointEmbeddings or OllamaEmbeddings.

需要权衡的因素

质量

MTEB 排行榜开始。MTEB 在检索、聚类、分类和重排序任务上对嵌入模型进行基准测试,是事实上的行业参考标准。按您的语言和任务类型进行筛选(检索是RAG最常见的场景)。

排行榜数据并非总能直接迁移,因此在做决定之前请在您自己的数据上进行小规模评估。LangSmith 提供了相关工具;请参阅 评估指南.

成本

托管嵌入服务的定价通常在每百万token几美分到约0.15美元之间。对于仅嵌入一次但每天查询数千次的语料库,成本通常由查询端主导。

本地推理无按调用计费成本,但需要CPU(速度慢)或GPU(硬件或云服务成本)。盈亏平衡点取决于工作负载:低流量的个人项目在CPU上基本免费;对于中等规模的生产环境,通过TEI使用单块GPU运行本地模型在单位经济效益上通常优于托管服务。

延迟

托管嵌入API每次请求会增加约50-200毫秒的网络延迟。本地模型在CPU上处理短查询,小型模型需要10-100毫秒(all-MiniLM-L6-v2级),大型模型需要50-500毫秒。在GPU上,本地推理通常比往返托管API更快。

对于批量索引,每请求延迟不如吞吐量重要。TEI和多进程本地推理会进行大批量处理。在GPU上运行时,请考虑例如 encode_kwargs={"batch_size": 64} 或更高。 HuggingFaceEmbeddings 当在GPU上运行时。

维度

嵌入维度会影响向量存储的存储和查询计算。典型尺寸:

  • - 384(小型Sentence Transformer模型, all-MiniLM-L6-v2)
  • - 768(中型ST模型, all-mpnet-base-v2, bge-base)
  • - 1024 (bge-large、Cohere v3、Voyage)
  • - 1536(OpenAI text-embedding-3-small、Qwen3-Embedding-0.6B)
  • - 3072+(OpenAI text-embedding-3-large, Qwen3-Embedding-4B/8B)

较大的向量通常更准确,但会消耗更多存储空间和查询计算资源。多个现代模型(OpenAI text-embedding-3-*, mixedbread-ai/mxbai-embed-large-v1、Matryoshka训练的ST模型、Qwen3-Embedding)支持 **截断**:将向量截取至更小维度,同时保持优雅的质量降级。可用于将更多向量适配到更小的索引中。

上下文长度

大多数经典嵌入模型的上下文上限为512个token(all-mpnet-base-v2、经典BGE)。较新的模型支持更长的上下文:

  • - nomic-ai/modernbert-embed-base:8192个token
  • - Alibaba-NLP/gte-multilingual-base: 8192 tokens
  • - BAAI/bge-m3: 8192 tokens
  • - OpenAI text-embedding-3-*: 8191 tokens

如果您的文本块较长(全页技术文档、法律段落),请优先选择长上下文模型。对于较短的文本块,512个token的限制很少会构成约束。

多语言支持

对于多语言检索,请选择针对您的语言进行训练的模型。推荐默认值:

  • - Open: BAAI/bge-m3, intfloat/multilingual-e5-*, Alibaba-NLP/gte-multilingual-*, Qwen/Qwen3-Embedding-* (通过 HuggingFaceEmbeddings)
  • - 托管版:Cohere embed-multilingual-v3、OpenAI text-embedding-3-*

查询和文档提示词

多个现代开源模型(如E5、BGE、Qwen3-Embedding、GTE)针对查询和文档使用不同的文本前缀进行训练。在查询时使用错误的前缀是常见的质量下降原因。当使用 HuggingFaceEmbeddings时,请显式传递提示词:

from langchain_huggingface import HuggingFaceEmbeddings

embeddings = HuggingFaceEmbeddings(
    model_name="intfloat/e5-large-v2",
    encode_kwargs={"prompt": "passage: "},
    query_encode_kwargs={"prompt": "query: "},
)

请查阅Hugging Face上各模型的模型卡,获取推荐的提示词字符串。

许可协议

大多数流行的开源嵌入模型采用宽松的许可协议(Apache 2.0、MIT)。部分最新的专业模型在生产环境中使用需要商业许可。在发布前,请检查每个模型的许可协议。

超越单向量密集嵌入

每个块使用单个密集向量是默认设置,但并非唯一选择。

稀疏检索与混合检索

密集嵌入在处理精确匹配查询(产品代码、命名实体、代码标识符)方面不如基于关键词的索引。混合检索将密集索引与BM25或稀疏神经索引(SPLADE、 BAAI/bge-m3的稀疏输出)相结合,以覆盖两种情况。

晚期交互与多向量

ColBERT风格的模型为每个token生成一个向量,而不是为每个块生成一个向量,然后通过晚期交互对查询和文档进行评分。这通常比单向量密集检索在复杂查询上更准确,但代价是更高的存储需求和更复杂的索引。当前该领域的开源模型包括 jinaai/jina-colbert-v2, answerdotai/answerai-colbert-small-v1,以及更新的晚期交互变体,例如 lightonai/LateOn。LangChain的内置检索器针对单向量嵌入;晚期交互通常需要专门的索引(Vespa、Qdrant的多向量支持或PyLate)。

起点

如果您只需要一个可用的起点:

  • - 快速原型,托管版: OpenAIEmbeddings(model="text-embedding-3-small")
  • - 快速原型,本地版,无需API密钥: HuggingFaceEmbeddings(model_name="sentence-transformers/all-mpnet-base-v2", encode_kwargs={"normalize_embeddings": True})
  • - 生产环境,托管版,质量优先: VoyageAIEmbeddings(model="voyage-3") or OpenAIEmbeddings(model="text-embedding-3-large")
  • - 生产环境,开源版,质量优先: HuggingFaceEmbeddings(model_name="BAAI/bge-m3", encode_kwargs={"normalize_embeddings": True}) 通过TEI服务
  • - 多语言,开源版: HuggingFaceEmbeddings(model_name="intfloat/multilingual-e5-large") 已配置查询和文档提示词

在您自己的数据上衡量检索质量,然后进行迭代。

缓存

可以存储或临时缓存嵌入向量,以避免重新计算。

可以使用 CacheBackedEmbeddings。此包装器将嵌入向量存储在键值存储中,其中文本被哈希处理,哈希值用作缓存中的键。

初始化 CacheBackedEmbeddings is from_bytes_store的主要支持方式是:它接受以下参数:

  • - **underlying_embedder**:用于嵌入的嵌入器。
  • - **document_embedding_cache**:任意 ByteStore 用于缓存文档嵌入
  • - **batch_size**:(可选,默认为 None)存储更新之间要嵌入的文档数量
  • - **namespace**:(可选,默认为 "")文档缓存要使用的命名空间。有助于避免冲突(例如,将其设置为嵌入模型名称)
  • - **query_embedding_cache**:(可选,默认为 None) A ByteStore 用于缓存查询嵌入,或 True 来重用与 document_embedding_cache.
  • - 始终设置 namespace 参数以避免使用不同嵌入模型时发生冲突
  • - CacheBackedEmbeddings 默认不缓存查询嵌入。要启用此功能,请指定一个 query_embedding_cache.
from langchain_classic.embeddings import CacheBackedEmbeddings  # [!code highlight]
from langchain_classic.storage import LocalFileStore # [!code highlight]
from langchain_core.vectorstores import InMemoryVectorStore

# Create your underlying embeddings model
underlying_embeddings = ... # e.g., OpenAIEmbeddings(), HuggingFaceEmbeddings(), etc.

# Store persists embeddings to the local filesystem
# This isn't for production use, but is useful for local
store = LocalFileStore("./cache/") # [!code highlight]

cached_embedder = CacheBackedEmbeddings.from_bytes_store(
    underlying_embeddings,
    store,
    namespace=underlying_embeddings.model
)

# Example: caching a query embedding
tic = time.time()
print(cached_embedder.embed_query("Hello, world!"))
print(f"First call took: {time.time() - tic:.2f} seconds")

# Subsequent calls use the cache
tic = time.time()
print(cached_embedder.embed_query("Hello, world!"))
print(f"Second call took: {time.time() - tic:.2f} seconds")

在生产环境中,通常会使用更强大的持久存储,如数据库或云存储。请参阅 存储集成 了解选项

所有嵌入模型

AI/ML API

AzureOpenAI

Baseten

Bedrock

BGE on Hugging Face

Cloudflare Workers AI

Cohere

Databricks

Elasticsearch

Google Gemini

Google Vertex AI

GreenNode

Hugging Face

IBM watsonx.ai

Instruct Embeddings

Isaacus

Lindorm

LocalAI

MistralAI

ModelScope

Naver

Nebius

Netmind

Nomic

NVIDIA NIMs

Oracle Cloud Infrastructure

Ollama

OpenAI

Oracle AI Database

Pinecone Embeddings

PredictionGuard

Perplexity

SambaNova

Sentence Transformers

Text Embeddings Inference

Together AI

Upstage