向量化思维:使用 Elasticsearch 构建生产就绪的 RAG 流水线
Source: Dev.to
Abstract
虽然传统的基于关键词的搜索已经为我们服务了数十年,但在生成式 AI 时代,它常常无法捕捉人类意图的细微差别。在本指南中,我们将探讨向 Vectorized Thinking 的转变。我们将使用 Elasticsearch Relevance Engine (ESRE) 和 OpenAI embeddings 实现完整的检索增强生成(RAG)流水线,演示如何弥合词汇匹配与语义理解之间的鸿沟。阅读完本文后,您将了解如何构建、优化和部署一个既准确又可扩展的 RAG 系统。
1. 关键字搜索中的“语义鸿沟”
传统搜索引擎依赖词汇匹配,通常使用 BM25 算法。虽然 BM25 在查找精确词语方面表现出色,但它本质上对意义 盲目。这就产生了我们所说的 语义鸿沟。
问题 – 想象一下用户向支持机器人询问:“我该如何恢复我的账户?”。如果你的知识库中仅包含短语 “使用忘记密码选项 重置密码”,标准的关键字搜索可能会失败。为什么?因为词语 恢复 和 账户 并未出现在目标文档中。
这种鸿沟会导致 LLM(大语言模型) 出现 幻觉,因为在缺乏正确上下文的情况下,模型被迫猜测。向量搜索通过将意图表示为高维空间中的数学坐标来解决此问题,使系统能够“理解”在此上下文中 恢复 与 重置 在语义上是相同的。
2. 什么是向量搜索?
向量搜索将非结构化文本转换为称为 embeddings 的密集数值表示。这些 embeddings 将词语、句子或整个文档映射到高维空间,在该空间中 “Account Recovery” 与 “Password Reset” 在地理位置上非常接近。
Elastic Stack 的关键概念
| Concept | Description |
|---|---|
| Dense Vector Embeddings | 固定长度数组(例如 OpenAI 的 text‑embedding‑3‑small 为 1536 维),充当意义的数字指纹。 |
| Cosine Similarity | 衡量两个向量之间的夹角;夹角越小,语义相似度越高。 |
| HNSW (Hierarchical Navigable Small World) | Elasticsearch 使用的高性能索引算法。它构建多层图结构,在毫秒级找到 最近邻,跳过数十亿无关文档。可将其视为多维空间的 “跳表”。 |
3. 系统架构
生产级别的 RAG 流水线不仅仅是一个脚本;它是由两个不同循环组成的生命周期。理解这一流程对于构建可靠的生成式 AI 应用至关重要。
[Diagram: The RAG Lifecycle]
摄取循环(离线)
Raw Documents → Chunking Service → OpenAI Embedder → Elasticsearch Index (Vector Store)
在此阶段,我们通过将文本转换为可搜索的向量来准备知识库。
推理循环(在线)
User Query → OpenAI Embedder → kNN Vector Search in Elastic → Context Injection → LLM Response
在此阶段,我们使用用户的查询在向量库中寻找最佳上下文,然后向 LLM 提出问题以获取答案。
Source: …
4. 使用 Elastic Cloud 的实现指南
要按照本指南操作,您需要一个 Elastic Cloud 实例(托管环境,包含 Elasticsearch Relevance Engine (ESRE),可简化对 OpenAI 等外部模型提供商的集成)。
步骤 1:定义向量模式
PUT /rag-index
{
"mappings": {
"properties": {
"text": {
"type": "text"
},
"metadata": {
"type": "keyword"
},
"embedding": {
"type": "dense_vector",
"dims": 1536,
"index": true,
"similarity": "cosine",
"index_options": {
"type": "hnsw",
"m": 16,
"ef_construction": 100
}
}
}
}
}
技术说明: m 定义每个新元素的双向链接数量(数值越大准确度越高,但索引时间会增加)。ef_construction 控制图构建过程中使用的动态列表大小。
步骤 2:智能分块与写入
对整篇文章进行嵌入会导致 语义稀释。最佳的 “Goldilocks” 区间是每块 500‑800 个 token,并保持 10 % 的重叠,以在块边界之间保留上下文。
def chunk_text(text, limit=500, overlap=50):
"""
Split `text` into overlapping chunks.
- `limit` : maximum number of tokens per chunk
- `overlap`: number of tokens to overlap between consecutive chunks
"""
words = text.split()
chunks = []
for i in range(0, len(words), limit - overlap):
chunks.append(" ".join(words[i:i + limit]))
return chunks
写入循环示例
for chunk in chunk_text(raw_document):
# Generate embedding via OpenAI
response = client.embeddings.create(
model="text-embedding-3-small",
input=chunk
)
vector = response.data[0].embedding
# Index into Elasticsearch
es.index(
index="rag-index",
document={
"text": chunk,
"embedding": vector,
"metadata": {"source": "kb"} # optional metadata
}
)
步骤 3:语义检索(kNN)
我们检索的是 用户意图的向量,而不是原始文本。num_candidates 参数告诉 Elasticsearch 在 HNSW 图层中要考虑多少候选结果。
search_response = es.search(
index="rag-index",
knn={
"field": "embedding",
"query_vector": user_query_vector,
"k": 3, # top‑k results to return
"num_candidates": 100 # candidates examined in the graph
}
)
Source: …
5. 高级优化:混合搜索与倒数排名融合 (RRF)
虽然纯向量搜索功能强大,但将其与传统词项搜索相结合往往能够兼顾两者的优势。
- 混合搜索 – 同时对 BM25(或其他词项评分器)和向量字段进行查询,然后合并得分。
- 倒数排名融合 (RRF) – 一种简单、与得分无关的方法,通过奖励在两个排序列表中都排名靠前的条目来合并两份排名。
POST /rag-index/_search
{
"size": 5,
"query": {
"bool": {
"should": [
{
"knn": {
"embedding": {
"vector": user_query_vector,
"k": 5
}
}
},
{
"match": {
"text": {
"query": user_query_text,
"boost": 2.0
}
}
}
]
}
}
}
在获取混合搜索结果后,在应用层使用 RRF 进行处理,以生成最终排名。
6. 部署 RAG 服务
- 容器化 数据摄取和推理脚本(Docker)。
- 暴露 一个轻量级 HTTP 接口(FastAPI / Flask),其功能包括:
- 接收用户查询。
- 调用 OpenAI 对查询进行嵌入。
- 执行 kNN 检索。
- 将 top‑k 片段格式化为上下文。
- 将上下文 + 查询发送给 LLM(例如
gpt‑4o)。
- 扩展 服务,使用 Kubernetes 或 Elastic Cloud 的内置自动伸缩。
7. 监控与维护
| 指标 | 为什么重要 |
|---|---|
| 索引延迟 | 确保摄取能够跟上源数据的更新。 |
| kNN 查询延迟 | 保证用户体验响应迅速(典型 < 200 ms)。 |
| 嵌入成本 | 跟踪 OpenAI token 使用量以控制费用。 |
| LLM 幻觉率 | 定期审计回复;高幻觉率表明上下文不足。 |
在 Elastic Observability(APM、日志、指标)中设置警报,以提前发现回归。
8. 弱点:精确术语匹配
如果用户搜索特定零件号,例如 “SKU‑9904‑X”,纯向量搜索可能返回“相似”零件,而不是准确的那一个。
解决方案 – 使用 Reciprocal Rank Fusion (RRF) 的混合搜索
RRF 让你将 BM25 关键字搜索 与 k‑NN 向量搜索 的结果合并为一个统一的排序。
GET /rag-index/_search
{
"query": {
"match": {
"text": "SKU-9904-X"
}
},
"knn": {
"field": "embedding",
"query_vector": [0.12, 0.45, ...],
"k": 10,
"num_candidates": 100
},
"rank": {
"rrf": {}
}
}
通过合并这两种方法,你可以获得 “两全其美”——关键字匹配的精确度和语义搜索的直觉性。
Source: …
9. 生产考虑因素:“战壕中的经验教训”
在生产环境中构建检索增强生成(RAG)流水线不仅需要逻辑,还需要对基础设施有充分的认识。
量化(标量量化)
- 向量存储非常占用 RAM。
- Elasticsearch 支持 int8 量化,将向量从 32 位浮点压缩到 8 位整数。
- 实际上,这可以 节省约 75 % 的内存,而检索准确率下降 不到 1 %。
熔断器
- 你的嵌入提供商(OpenAI、Anthropic 等)是第三方依赖。
- 实现 指数退避 和 熔断器。
- 当嵌入服务宕机时,优雅地降级为 仅关键字搜索,而不是直接崩溃。
重排序器模式
- 对于高风险应用,使用两阶段检索流程:
- Elasticsearch 返回 前 50 条文档。
- 交叉编码器 模型(例如 Cohere Rerank)挑选出最终的 前 3 条。
- 这可以显著提升精确度。
10. Observations & Performance
在 50 000 篇技术文档 的数据集上测试此架构,得到:
| 指标 | 结果 |
|---|---|
| 准确率 | LLM “幻觉” 减少了 40%。将模型基于检索到的事实进行 grounding,使答案更具事实性且更简洁。 |
| 延迟 | “语义跳跃”(调用嵌入 API)每次查询会额外增加 ≈150 ms。对于对延迟敏感的应用,请对常用查询缓存嵌入。 |
结论
向量化思维将关注点从关键词转向意图。通过利用 Elasticsearch Relevance Engine,开发者可以构建真正理解用户的搜索体验。无论是构建客服机器人还是复杂的研究工具,HNSW indexing、Hybrid Search 和 LLM augmentation 的组合为下一代 AI 驱动的应用提供了坚实的基础。