從 RAG 到 Agent:Haystack 3.0 如何把 LLM 應用拆成可追蹤的 Pipeline
Haystack 3.0 以 component 與 Pipeline 為核心,將 RAG、Agent、檢索、工具呼叫與生成拆成可組合、可測試的資料流。本文從官方 source code 出發,帶你理解它的設計、最小 RAG 實作與適合的落地場景。
從 RAG 到 Agent:Haystack 3.0 如何把 LLM 應用拆成可追蹤的 Pipeline
如果你曾經把 RAG、工具呼叫、對話記憶和模型供應商整合在同一支程式裡,應該很快會遇到一個問題:Demo 可以跑,系統卻很難改。檢索器換掉要改 prompt,模型換掉要重接流程,Agent 加上一個工具後又很難知道資料到底在哪一個節點被改寫。
Haystack 提供另一種思路:把 LLM 應用拆成明確的元件,再用 Pipeline 將資料流連起來。它不是替你藏起所有細節的黑盒 Agent framework,而是讓檢索、路由、記憶、生成和工具呼叫都保持可組合、可替換、可觀察。這正是它值得 AI 工程團隊重新認識的地方。
本文以官方 repository、目前的 source code 與官方文件為主要依據,整理 Haystack 3.0 的核心設計,並用一個最小的 RAG Pipeline 說明它適合什麼場景、怎麼開始,以及哪些地方仍然需要工程判斷。
先看專案:為什麼現在值得關注?
截至 2026 年 8 月 21 日查證,deepset-ai/haystack 在 GitHub 擁有超過 26,000 顆 stars,最近一次 push 為 2026 年 8 月 20 日,採用 Apache License 2.0,主要語言是 Python。這不是只收集文章或 prompt 的資源清單,而是一個包含 pipeline runtime、components、dataclasses、serialization 與 generator 整合的實作型框架。
官方 README 將 Haystack 定位為「用 Python 建立 production-ready LLM applications 的開源 AI orchestration framework」。目前首頁也特別標示 Haystack 3.0,並把 RAG、multimodal application、semantic search、question answering 和 autonomous agents 放在同一個可組合架構裡。這個定位很適合寫成工程實作文章:重點不只是「可以接模型」,而是如何把一個會持續變動的 AI 系統拆成可測試的資料流。
Haystack 的核心:元件不是函式呼叫,而是資料流節點
Haystack 的基本單位是 component。Prompt builder、retriever、ranker、generator、工具與自訂邏輯,都可以成為 Pipeline 中的節點。每個節點有清楚的輸入與輸出,Pipeline 再負責驗證連線、傳遞資料,以及在需要時執行分支、迴圈與非同步流程。
這個設計帶來三個工程上的好處:
- 替換成本低:可以把模型、retriever 或 prompt builder 換掉,而不必把整個應用改寫成另一種抽象。
- 資料流可讀:讀 Pipeline 宣告,就能知道文件在哪裡被檢索、排序、放進 prompt,再送給模型。
- 測試邊界清楚:可以先測每一個 component,再測元件之間的連線,而不是只對最後的文字答案做黑盒測試。
Haystack README 也列出 native async support、streaming、branches、loops 和 conditional logic。換句話說,Pipeline 並不只適合最直線的「輸入問題 → 呼叫模型」流程;當產品需要加入 guardrail、工具路由或多階段處理時,仍可維持同一套組合方式。
五分鐘理解一個最小 RAG Pipeline
先安裝套件:
pip install haystack-ai下面的程式直接依照 Haystack repository 內 PromptBuilder 的官方用法縮小而成。文件先以兩個 Document 代表檢索結果,接著由 PromptBuilder 把文件與問題渲染成 prompt,最後交給 OpenAIChatGenerator。真正的產品流程只需要把固定的 documents 換成 retriever 的輸出即可。
from haystack import Document, Pipeline
from haystack.components.builders import PromptBuilder
from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.utils import Secret
documents = [
Document(content="Joe lives in Berlin"),
Document(content="Joe is a software engineer"),
]
prompt_template = """
Given these documents, answer the question.
Documents:
{% for doc in documents %}
{{ doc.content }}
{% endfor %}
Question: {{ query }}
Answer:
"""
pipeline = Pipeline()
pipeline.add_component(
instance=PromptBuilder(template=prompt_template),
name="prompt_builder",
)
pipeline.add_component(
instance=OpenAIChatGenerator(
api_key=Secret.from_env_var("OPENAI_API_KEY")
),
name="llm",
)
pipeline.connect("prompt_builder", "llm")
result = pipeline.run({
"prompt_builder": {
"documents": documents,
"query": "Where does Joe live?",
}
})
print(result)這段程式的重點不是答案本身,而是兩個連線邊界。PromptBuilder 輸出的是 prompt,OpenAIChatGenerator 接收這個輸出並回傳 replies。若下一步要換成另一個 generator,只要維持相容的輸入輸出契約;若要把文件來源換成 Elasticsearch、OpenSearch、Qdrant 或自訂資料庫,則把固定文件替換成對應 retriever 的輸出。
另一個值得注意的細節是 PromptBuilder 使用 Jinja2 template。官方 source code 支援在每次 pipeline.run() 時覆寫 template 或 template_variables,因此 prompt engineering 可以被當成輸入變體測試,而不是散落在程式各處的字串拼接。這對做評測很重要:同一條資料流可以換 prompt、換模型參數,再比較輸出。
從 RAG 延伸到 Agent:控制權留在 Pipeline
一般 RAG 的資料流可以畫成:
問題 → Retriever → Ranker/Filter → PromptBuilder → Chat GeneratorAgent 則會多一個「決定下一步」的迴圈:
問題 → Agent
├─ 呼叫搜尋工具 → 取得結果 → 再思考
├─ 呼叫內部 API → 取得資料 → 再思考
└─ 完成回答Haystack README 將 Agent 描述為可搭配 lifecycle hooks 的 production-oriented agent,並提到 before_llm、before_tool、on_exit 等 hook,以及 step_count、token_usage 和 tool calls 等資訊。這些能力的價值,在於 Agent 不再只是「把一串 tools 丟給模型」;團隊可以在模型前後插入驗證、紀錄、成本控制與安全規則。
同一份 README 也提到 SkillToolset,讓 skill description 只在需要時進入 context。這對工具數量會持續增加的系統很實用:不是每次都把所有工具的完整說明塞給模型,而是先以較小的索引做發現,再載入目前任務需要的能力。
但這不代表應該把所有流程都改成 Agent。若步驟固定,明確的 Pipeline 通常更容易測試、除錯與估算成本;只有在下一步真的需要根據中間結果動態決定時,才值得引入 Agent 迴圈。Haystack 的優勢正是讓這兩種模式可以在同一個 component/pipeline 思維下共存。
模型與供應商解耦,並不等於完全沒有差異
Haystack README 列出的整合範圍包含 OpenAI、Mistral、Anthropic、Cohere、Hugging Face、Google、Azure OpenAI、AWS Bedrock 與 local models。這讓應用層不必把供應商 SDK 的呼叫格式直接散落在業務程式裡。
不過,抽象層只能處理共同介面,不能消除模型之間的行為差異。實作時仍要針對下列項目做驗證:
- chat message 與 tool calling 的格式是否一致。
- streaming、token usage 與錯誤資訊是否能被現有 observability 接住。
- context window、結構化輸出和 retry 行為是否符合產品需求。
- 不同模型在相同 retriever 與 prompt 下的答案品質和成本。
因此,Haystack 適合用來降低整合耦合,但不應被當成「換模型後不用重做評測」的保證。Pipeline 讓比較變得容易,評測仍然是團隊自己的責任。
一個適合團隊落地的開發順序
如果要用 Haystack 建立第一個可維護的 RAG 或 Agent 服務,可以採用以下順序:
1. 先固定資料契約
先定義文件、查詢、生成結果和錯誤的形狀,再選 retriever。這能避免一開始就被某一家向量資料庫或模型 SDK 綁住。
2. 先寫直線 Pipeline
先完成「取得資料 → 組 prompt → 生成」的最小閉環,並把每個節點的輸入輸出記錄下來。先確定資料真的有進到 prompt,再討論 Agent。
3. 將 prompt 當成可替換輸入
利用 PromptBuilder 的 template 與 template_variables,為 prompt 建立版本與評測案例。不要把 prompt 變更當成無法追蹤的手動修改。
4. 最後才加入動態工具路由
當固定 Pipeline 已經無法處理需求,再加入 Agent、tools、hooks 和迴圈。每一次工具呼叫都應記錄名稱、參數、耗時、結果大小與失敗原因,否則出問題時只能猜模型做了什麼。
Haystack 適合什麼、不適合什麼?
Haystack 適合以下情境:
- 需要把 RAG、Agent、semantic search 與生成整合在同一個 Python 服務中。
- 團隊希望明確控制 retrieval、routing、memory 和 generation,而不是使用完全封裝的黑盒流程。
- 需要替換模型供應商、資料來源或自訂 component,並保留可測試的邊界。
- 產品流程會從簡單問答逐步演進成包含工具與多步驟決策的應用。
它不一定適合所有人。一次性的 prompt demo 用單純 SDK 可能更快;如果團隊沒有維護 pipeline、評測與觀測的打算,引入框架反而會增加概念負擔。此外,Haystack 的「可組合」也意味著你需要自己做架構選擇:文件切分、embedding、retriever、reranking、prompt、模型與安全策略都不會因為安裝套件就自動正確。
結語:把「模型會回答」改成「系統可演進」
Haystack 最值得關注的地方,不是它又支援了多少模型,而是它把 LLM 應用重新拉回軟體工程熟悉的問題:元件邊界、資料契約、可替換性、測試與觀測。
當 RAG 只是一個 notebook 時,任何框架都能讓它跑起來;當它要變成有權限、有成本限制、會呼叫工具、需要持續評測的產品,透明的 Pipeline 與明確的 component interface 就會變得重要。Haystack 3.0 提供的是一個把這些需求放在同一個架構裡處理的選項。
如果你的團隊正在從「先做一個能回答的 Demo」走向「維護一個會持續改變的 AI 系統」,Haystack 值得拿一個真實的 RAG use case 試跑,而不是只看它的 star 數。
查證來源
- GitHub repository:deepset-ai/haystack
- 官方文件:Haystack Documentation
- 官方 quick start:Get Started Guide
- 官方 source code:PromptBuilder
- 官方 source code:OpenAIChatGenerator
本文的 GitHub stars、最近更新時間與版本相關資訊,以 2026 年 8 月 21 日查詢 GitHub API 與 repository README 的結果為準;專案會持續更新,實際 API 請以官方文件為準。