引言

在RAG(检索增强生成)框架的赛道上,Haystack 2.0是一个容易被忽视但值得认真对待的选择。由deepset开发的Haystack没有LangChain那样的营销声量,但在生产环境的稳定性和架构设计上有着独特的优势。2026年的Haystack 2.0版本经过完全重构,已经成为构建生产级RAG系统的强力选择。

架构设计哲学

Haystack 2.0的核心设计理念是管道即代码(Pipeline as Code)——每个RAG系统都是一个由组件构成的DAG(有向无环图),组件之间通过类型化的连接传递数据。

文档输入 → 文档分割 → 嵌入生成 → 向量存储
用户查询 → 查询嵌入 → 向量检索 → 重排序 → Prompt组装 → LLM生成 → 答案输出

与LangChain的Chain抽象不同,Haystack的Pipeline是真正有向图,支持分支、合并、循环等复杂拓扑。

核心组件解析

1. Document Store

Haystack 2.0将文档存储抽象为统一接口,支持多种后端:

from haystack.document_stores import (
    ChromaDocumentStore,
    QdrantDocumentStore,
    ElasticsearchDocumentStore,
    PgVectorDocumentStore,
)

# 使用Qdrant作为向量数据库
document_store = QdrantDocumentStore(
    host="localhost",
    port=6333,
    index="documents",
    embedding_dim=1024,
    recreate_index=False,
    metadata_indexed_fields=["source", "date", "category"],
    # Qdrant特有的payload过滤
    on_disk_payload=True,
    optimizers_config={"indexing_threshold": 20000},
)

2. Retriever

检索器是RAG系统的核心,Haystack支持多种检索策略的即插即用:

from haystack.components.retrievers import (
    QdrantEmbeddingRetriever,
    QdrantHybridRetriever,
    BM25Retriever,
)

# 纯向量检索
embedding_retriever = QdrantEmbeddingRetriever(
    document_store=document_store,
    top_k=20,
    filters={"field": "category", "operator": "==", "value": "technical"},
)

# 混合检索(向量+关键词)
hybrid_retriever = QdrantHybridRetriever(
    document_store=document_store,
    top_k=20,
    # Dense和Sparse检索结果融合
    fusion_algorithm="reciprocal_rank_fusion",
    rrf_k=60,
)

3. Ranker

重排序是提升RAG精度的关键步骤:

from haystack.components.rankers import (
    SentenceTransformersRanker,
    CohereRanker,
    CrossEncoderRanker,
)

ranker = SentenceTransformersRanker(
    model="BAAI/bge-reranker-v2-m3",
    top_k=5,  # 从20条重排到5条
    device="cuda",
)

# Cohere Reranker(API调用,无需GPU)
cohere_ranker = CohereRanker(
    api_key="YOUR_API_KEY",
    model="rerank-multilingual-v3.0",
    top_k=5,
)

构建生产级RAG管道

完整管道示例

from haystack import Pipeline
from haystack.components.embedders import (
    SentenceTransformersTextEmbedder,
    SentenceTransformersDocumentEmbedder,
)
from haystack.components.writers import DocumentWriter
from haystack.components.generators import OpenAIGenerator
from haystack.components.builders import PromptBuilder
from haystack.components.preprocessors import DocumentSplitter, DocumentCleaner
from haystack.dataclasses import Document

# ===== 索引管道 =====
indexing_pipeline = Pipeline()
indexing_pipeline.add_component("cleaner", DocumentCleaner(
    remove_empty_lines=True,
    remove_extra_whitespaces=True,
    remove_repeated_substrings=True,  # 自动检测并移除重复的页眉页脚
))
indexing_pipeline.add_component("splitter", DocumentSplitter(
    split_by="word",
    split_length=300,
    split_overlap=50,
    split_threshold=100,  # 小于100词的块不分割
))
indexing_pipeline.add_component("embedder", SentenceTransformersDocumentEmbedder(
    model="BAAI/bge-m3",
    device="cuda",
    batch_size=64,
    normalize_embeddings=True,
))
indexing_pipeline.add_component("writer", DocumentWriter(document_store=document_store))

indexing_pipeline.connect("cleaner", "splitter")
indexing_pipeline.connect("splitter", "embedder")
indexing_pipeline.connect("embedder", "writer")

# ===== 查询管道 =====
query_pipeline = Pipeline()
query_pipeline.add_component("text_embedder", SentenceTransformersTextEmbedder(
    model="BAAI/bge-m3",
    device="cuda",
    normalize_embeddings=True,
))
query_pipeline.add_component("retriever", QdrantHybridRetriever(
    document_store=document_store,
    top_k=20,
))
query_pipeline.add_component("ranker", SentenceTransformersRanker(
    model="BAAI/bge-reranker-v2-m3",
    top_k=5,
    device="cuda",
))

prompt_template = """
基于以下检索到的上下文,回答用户问题。
如果上下文中没有足够信息,明确说明"根据现有资料无法回答",不要编造。

上下文:
{% for doc in documents %}
[{{ loop.index }}] (来源: {{ doc.meta.source }}, 置信度: {{ doc.score | round(3) }})
{{ doc.content }}
{% endfor %}

问题:{{ question }}

回答要求:
1. 回答必须引用对应的上下文编号,如 [1] [2]
2. 区分事实陈述和推断
3. 如有多个来源冲突,指出差异
"""
query_pipeline.add_component("prompt_builder", PromptBuilder(template=prompt_template))
query_pipeline.add_component("generator", OpenAIGenerator(
    model="gpt-5",
    generation_kwargs={
        "temperature": 0.1,
        "max_tokens": 1024,
        "seed": 42,
    },
))

query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding")
query_pipeline.connect("retriever.documents", "ranker.documents")
query_pipeline.connect("ranker.documents", "prompt_builder.documents")
query_pipeline.connect("prompt_builder.prompt", "generator.prompt")

# 运行查询
result = query_pipeline.run({
    "text_embedder": {"text": "vLLM的PagedAttention原理是什么?"},
    "prompt_builder": {"question": "vLLM的PagedAttention原理是什么?"},
})

管道可视化与调试

# 导出管道结构图
query_pipeline.draw("rag_pipeline.png")

# 查看管道拓扑
print(query_pipeline.dumps())

# 逐步调试
from haystack.components.joiners import DocumentJoiner

# 在任何节点插入调试组件
debug_pipeline = Pipeline()
# ... 前置组件 ...
debug_pipeline.add_component("debug_joiner", DocumentJoiner())
# ... 后续组件 ...

# 查看中间结果
intermediate = debug_pipeline.run(
    {"text_embedder": {"text": "测试查询"}},
    include_outputs_from=["retriever", "ranker"]
)
print(f"检索阶段返回: {len(intermediate['retriever']['documents'])} 篇文档")
print(f"重排后保留: {len(intermediate['ranker']['documents'])} 篇文档")

高级特性

1. 动态路由

from haystack.components.routers import ConditionalRouter

router = ConditionalRouter(routes=[
    {
        "condition": "{{ question|length < 100 }}",
        "output": "{{ question }}",
        "output_name": "simple_query",
        "output_type": "str",
    },
    {
        "condition": "{{ question|length >= 100 }}",
        "output": "{{ question }}",
        "output_name": "complex_query",
        "output_type": "str",
    },
])

# 短查询走快速路径(直接检索)
# 长查询走深度路径(先分解再检索)

2. 查询扩展

from haystack.components.generators import OpenAIGenerator
from haystack.components.builders import PromptBuilder

# 用LLM将用户查询扩展为多个子查询
query_expander = Pipeline()
query_expander.add_component("expander_prompt", PromptBuilder(
    template="将以下问题分解为3个不同的搜索查询,以获取更全面的信息:\n{{ question }}\n\n只输出查询,每行一个。"
))
query_expander.add_component("expander_llm", OpenAIGenerator(model="gpt-5-mini"))

# 多查询并行检索后合并结果

3. 增量更新

# Haystack 2.0支持文档的增量更新,无需重建索引
from haystack.components.updaters import DocumentUpdater

updater = DocumentUpdater(document_store=document_store)
updater.run(documents=[
    Document(content="更新后的内容", id="doc_001", meta={"version": "2"})
])

性能基准

在100万文档的语料库上,Haystack 2.0的性能表现:

组件 吞吐量 延迟(P95) 备注
文档索引 2000 docs/s - 批量嵌入
向量检索 500 queries/s 45ms top_k=20
重排序 100 queries/s 120ms top_k=5
端到端RAG 80 queries/s 850ms 含LLM生成

与LangChain对比

维度 Haystack 2.0 LangChain
架构清晰度 高(显式管道) 中(隐式Chain)
类型安全 强(Pydantic类型)
管道可视化 原生支持 需第三方
生产稳定性
社区规模 较小
集成数量 60+ 300+
文档质量

总结

Haystack 2.0不会在社交媒体上引发热烈讨论,但它是那种真正用来构建生产系统的框架。显式的管道设计、严格的类型系统、完善的调试工具,这些"无聊但重要"的工程品质让它在严肃项目中脱颖而出。

如果你的RAG系统需要上线服务真实用户,Haystack 2.0值得列入技术选型的候选名单。它可能不是最酷的选择,但很可能是最稳妥的。