務流程:從Embedding到向量檢索與LLM生成)
這次不聊花哨的框架對比直接看 RAG檢索增強生成的完整業(yè)務流程。很多同學學 RAG 的時候總被一堆名詞繞暈Embedding、向量檢索、切塊、Rerank、知識庫、召回率……概念好像都見過真到自己搭一個能問答的項目又不知道從哪一步開始。這篇文章會把 RAG 的核心鏈路拆開講文本怎么變成向量、向量怎么被檢索、檢索結果怎么交給大模型生成答案。同時給出本地部署的通用流程、接口調(diào)用示例、批量任務設計思路和常見坑點。不管是剛入門大模型開發(fā)還是想給現(xiàn)有系統(tǒng)接入知識庫問答這篇都值得收藏。1. RAG 核心能力速覽先給一張速覽表把 RAG 技術方案的關鍵信息放在前面方便快速判斷。能力項說明項目類型大模型應用開發(fā)技術方案 / 檢索增強生成核心能力文檔解析、文本切塊、Embedding、向量檢索、大模型生成常用模型Embedding 模型BGE-M3、BGE-large-zh、m3e生成模型Qwen、DeepSeek、ChatGLM 等支持硬件CPU 可運行GPU 加速檢索與推理具體顯存取決于 Embedding 模型和 LLM 大小啟動方式命令行啟動 / Docker 啟動 / API 服務啟動 / WebUI 或管理端接入是否支持 API支持可通過 FastAPI / Flask 封裝檢索和問答接口是否支持批量任務支持可批量處理文檔入庫、批量問題和批量生成答案常用向量庫Chroma、Milvus、FAISS、Qdrant、pgvector核心流程文檔加載 → 切塊 → Embedding → 存儲 → 查詢 → 向量檢索 → LLM 生成適合讀者大模型應用開發(fā)者、知識庫系統(tǒng)開發(fā)者、RAG 項目入門者這套流程的優(yōu)勢在于不需要微調(diào)大模型也能讓模型回答出私有知識內(nèi)容。因為 RAG 的核心思路是“先檢索再生成”讓模型基于檢索到的資料來回答問題而不是憑空編造。2. RAG 適用場景與使用邊界2.1 適合哪些場景RAG 最適合的場景可以總結為“文檔多、知識更新快、不能隨便微調(diào)”的企業(yè)內(nèi)部知識庫問答。企業(yè)文檔問答把操作手冊、規(guī)章制度、產(chǎn)品文檔切片入庫員工可以直接提問??头职殉R妴栴}庫、售后政策、產(chǎn)品參數(shù)接入問答系統(tǒng)。課程資料與學習助手基于教材或講義做學習問答。代碼庫問答把項目文檔和代碼片段切塊后可以按語義查找相關實現(xiàn)。輿情分析與報告輔助先檢索相關新聞再讓模型總結減少幻覺。RAG 的核心價值是給大模型提供“外部知識”。它不需要重新訓練模型也不需要維護模型權重只需要維護知識庫數(shù)據(jù)因此知識更新成本遠低于微調(diào)。2.2 不適合什么場景RAG 不適合所有問答場景以下幾個場景需要謹慎評估。需要強推理、多步計算的數(shù)學或邏輯題RAG 檢索到的資料往往只是背景模型本身推理能力不夠時仍然容易出錯。知識庫內(nèi)容很差、錯別字多、排版混亂的文檔切塊和 Embedding 效果都會受影響檢索質(zhì)量很難保證。高頻實時交易類查詢?nèi)绻麛?shù)據(jù)延遲要求毫秒級而知識庫更新又慢RAG 不是最優(yōu)解。需要完全確定性的規(guī)則系統(tǒng)RAG 本質(zhì)是概率檢索加概率生成不適合對輸出格式和答案準確性要求極高的場景。2.3 使用邊界與合規(guī)提醒RAG 涉及文檔處理和私有大模型應用需要特別注意以下幾點。文檔授權上傳到知識庫的文檔必須是已獲得授權的資料不能把內(nèi)部保密文件隨意送入外部 API 或云服務。隱私保護如果要求數(shù)據(jù)不出內(nèi)網(wǎng)建議使用本地部署的 Embedding 模型和 LLM比如 Ollama 部署本地模型。輸出審核RAG 生成的結果仍然可能出現(xiàn)幻覺尤其是檢索到的資料與問題不相關時。商用前需要人工抽查或增加答案置信度判斷。版權合規(guī)生成內(nèi)容不能侵犯第三方版權特別是在內(nèi)容發(fā)布場景中需要對生成結果做復核。3. Embedding 嵌入模型運行機制要理解 RAG必須先理解 Embedding。3.1 什么是 EmbeddingEmbedding 是把文本轉換成向量一串浮點數(shù)的過程。簡單說就是把“自然語言文本”映射到一個高維向量空間中讓語義相近的文本在向量空間中的位置更接近。例如“今天天氣怎么樣” → [0.12, 0.34, -0.56, 0.78, ...]“明天會不會下雨” → [0.14, 0.31, -0.51, 0.80, ...]這兩個句子的向量距離會比較近因為它們語義相近。而“今晚吃什么”的向量會離上面的句子更遠。這就是 Embedding 模型做的事情把文本變成向量用向量的空間距離表示語義距離。3.2 Embedding 模型怎么選擇目前常見的 Embedding 模型有模型特點適用語言BGE-M3多語言、支持稠密檢索和稀疏檢索、長文本支持好中英文BGE-large-zh中文效果較好資源占用適中中文m3e-base / m3e-large輕量級中文 Embedding 模型中文text-embedding-ada-002老牌閉源模型調(diào)用 API 更方便多語言gte-large / gte-base開源可選多種語言支持中英文選擇 Embedding 模型時主要看三個維度語義表征能力在檢索評測集上的準確率。支持的語言中文場景優(yōu)先選中文語料訓練充分的模型。輸入長度限制如 512 token、8192 token 等決定文本切塊的粒度。推理資源大模型參數(shù)量大占用的顯存和內(nèi)存也大。從實際項目看BGE-M3 是很流行的選擇因為它同時支持稠密檢索和稀疏檢索還能做長文本編碼方便做混合檢索。3.3 文本切塊策略文本切片是 RAG 流程中最容易被忽略但又很重要的環(huán)節(jié)。同一篇文章切塊方式不同Embedding 檢索效果會有明顯差異。常見的切塊策略包括固定長度切塊按字符數(shù)或 token 數(shù)切分簡單粗暴。段落切塊按文檔換行、段落分割保留語義完整性。重疊切塊相鄰塊保留一定重疊部分避免上下文被切斷。結構化切塊按 Markdown 標題、代碼塊、表格等結構切分適合技術文檔。智能切塊基于語義邊界切分比如根據(jù)句子向量變化來確定邊界。切塊大小需要根據(jù)文檔類型和 Embedding 模型能力調(diào)整。一般來說問答類文檔每塊 200 到 500 字左右比較合適。技術文檔按章節(jié)或小節(jié)切保留標題層級。長文本如果 Embedding 模型支持長文本可以適當加大切塊但檢索精度可能下降。切塊太大會導致檢索到的內(nèi)容包含太多無關信息回答不聚焦切塊太小又可能丟失上下文導致語義不完整。建議在項目里多做幾組切塊實驗驗證問答質(zhì)量再定方案。4. RAG 本地部署環(huán)境準備4.1 通用環(huán)境要求RAG 項目一般由四個部分組成文檔處理層負責加載 PDF、Word、Markdown、HTML 等格式文檔。Embedding 服務可以把自定義文檔轉成向量。向量數(shù)據(jù)庫存儲和檢索向量。LLM 服務負責根據(jù)檢索結果生成答案。最省事的部署方式是使用 Ollama 本地部署 Embedding 模型和生成模型再配合 Python 做流程編排。環(huán)境準備清單操作系統(tǒng)推薦 Linux 或 Windows WSL2macOS 也可運行。Python建議 3.10 以上。CUDA如果用 N 卡 GPU 加速需要安裝對應版本的 CUDA 和顯卡驅(qū)動。Ollama支持一鍵安裝可以拉取 Embedding 模型和 LLM。向量數(shù)據(jù)庫Chroma 適合快速學習Milvus 適合生產(chǎn)環(huán)境。磁盤空間10GB 以上比較穩(wěn)妥具體取決于模型文件大小。4.2 安裝 Python 依賴以 Python 環(huán)境為例核心依賴包括pip install langchain langchain-community langchain-ollama pip install chromadb pip install fastapi uvicorn pip install pymilvus # 如果使用 Milvus pip install pypdf # 解析 PDF4.3 通過 Ollama 拉取模型Ollama 是目前比較方便的本地模型管理工具支持命令行一鍵拉取模型。# 安裝 OllamaWindows / macOS / Linux 官網(wǎng)下載即可 # 拉取中文 Embedding 模型 ollama pull bge-m3 # 拉取生成模型 ollama pull qwen2.5:7b如果機器沒有 GPU也可以用 CPU 運行只是推理速度會慢一些。如果顯存不夠可以換小一點的模型比如qwen2.5:3b。4.4 初始化向量數(shù)據(jù)庫使用 Chroma 作為本地向量庫時代碼如下from chromadb import PersistentClient client PersistentClient(path./data/chroma_db) collection client.get_or_create_collection( nameknowledge_base, embedding_functionNone # 我們用外部 Embedding不依賴 Chroma 內(nèi)置 )如果有大量文檔且需要分布式擴展可以考慮 Milvus。Milvus 屬于更重的方案適合生產(chǎn)環(huán)境。5. RAG 功能測試與效果驗證5.1 測試目標一個標準的 RAG 項目要驗證以下能力文檔能正常加載并切塊。Embedding 能正確生成向量。向量庫能正確存儲和檢索。檢索結果與問題語義相關。大模型能基于檢索結果生成回答?;卮饍?nèi)容與文檔事實一致。5.2 構建知識庫流程先用一段測試文檔走通流程。from langchain_community.document_loaders import PyPDFLoader from langchain_text_splitters import RecursiveCharacterTextSplitter from langchain_ollama import OllamaEmbeddings from chromadb import PersistentClient # 1. 加載文檔 loader PyPDFLoader(test_docs/product_manual.pdf) documents loader.load() # 2. 切塊 splitter RecursiveCharacterTextSplitter( chunk_size500, chunk_overlap50 ) chunks splitter.split_documents(documents) # 3. 加載 Embedding 模型 embeddings OllamaEmbeddings(modelbge-m3) # 4. 寫入向量庫 client PersistentClient(path./data/chroma_db) collection client.get_or_create_collection(nameknowledge_base) for i, chunk in enumerate(chunks): vector embeddings.embed_query(chunk.page_content) collection.add( ids[fchunk_{i}], embeddings[vector], documents[chunk.page_content], metadatas[{source: chunk.metadata.get(source, )}] ) print(f入庫完成共 {len(chunks)} 個文本塊)5.3 向量檢索測試檢索時需要把用戶問題也轉換為向量然后在向量庫中查找最近鄰。question 這個產(chǎn)品的保修期是多久 question_vector embeddings.embed_query(question) results collection.query( query_embeddings[question_vector], n_results5 ) for idx, doc in enumerate(results[documents][0]): print(f第 {idx 1} 個結果) print(doc) print(---)判斷檢索效果的標準是返回的前幾個文本塊是否與問題相關。如果檢索結果不相關可能是切塊太粗、模型語義能力弱或者文檔格式解析有問題。5.4 完整 RAG 問答測試把檢索結果拼進 Prompt再讓大模型生成答案。from langchain_ollama import OllamaLLM llm OllamaLLM(modelqwen2.5:7b, temperature0.3) def rag_answer(question, context): prompt f請基于以下資料回答問題。如果資料中找不到答案請直接說“資料中未找到相關信息”。 資料 {context} 問題{question} 回答 return llm.invoke(prompt) context \n.join(results[documents][0]) answer rag_answer(question, context) print(answer)這個流程是 RAG 最核心的 Mini 實現(xiàn)。實際項目中你還會加入 Rerank、混合檢索、引用來源標注、對話歷史等功能。6. 接口 API 與批量任務6.1 封裝 FastAPI 接口當本地流程跑通后可以把 RAG 封裝成 HTTP 接口方便上層應用調(diào)用。from fastapi import FastAPI from pydantic import BaseModel app FastAPI() class QueryRequest(BaseModel): question: str top_k: int 5 class QueryResponse(BaseModel): answer: str sources: list[str] app.post(/query, response_modelQueryResponse) async def query(request: QueryRequest): # 這里復用上面的檢索 生成邏輯 question_vector embeddings.embed_query(request.question) results collection.query( query_embeddings[question_vector], n_resultsrequest.top_k ) context \n.join(results[documents][0]) answer rag_answer(request.question, context) return QueryResponse(answeranswer, sourcesresults[documents][0]) if __name__ __main__: import uvicorn uvicorn.run(app, host127.0.0.1, port8000)啟動接口服務python api_server.py調(diào)用接口curl -X POST http://127.0.0.1:8000/query \ -H Content-Type: application/json \ -d {question: 這個產(chǎn)品的保修期是多久, top_k: 3}也可以用 Python 調(diào)用import requests response requests.post( http://127.0.0.1:8000/query, json{question: 這個產(chǎn)品的保修期是多久, top_k: 3}, timeout120 ) print(response.json())6.2 批量任務設計生產(chǎn)環(huán)境中的 RAG 項目通常需要批量處理兩類任務批量文檔入庫任務。批量問答生成任務。批量文檔入庫的任務隊列可以這樣設計任務輸入input_docs/ 目錄下多個文檔 任務處理 1. 解析文檔 2. 文本切塊 3. 生成 Embedding 4. 寫入向量庫 任務輸出入庫日志、成功列表、失敗列表批量問答生成則要特別注意每個問題單獨記錄日志。增加超時和失敗重試機制??刂撇l(fā)數(shù)避免把 LLM 服務打爆。輸出結果保存為 JSONL 或 CSV方便后續(xù)分析。批量任務建議使用消息隊列如 Redis Queue、Celery來管理而不是簡單寫一個 for 循環(huán)。因為 LLM 推理時間不穩(wěn)定一旦中途失敗沒有任務隊列就很難恢復。7. 向量檢索性能優(yōu)化與資源觀察7.1 混合檢索與 Rerank基礎向量檢索是稠密檢索通過語義相似度找到相關文本。但在一些場景下關鍵詞精確匹配更加可靠比如檢索型號、編號、專有名詞。這時就可以使用混合檢索。混合檢索的思路是把向量檢索和關鍵詞檢索如 BM25結合再進行歸一化融合。很多 RAG 框架已經(jīng)內(nèi)置了這種能力例如LangChain 中的 EnsembleRetriever。Milvus 的 Hybrid Search。BGE-M3 本身支持同時生成稠密向量和稀疏向量。Rerank 則是另一層優(yōu)化先粗召回一批候選文本再用重排模型對候選結果重新打分把最相關的文本排到最前面。7.2 顯存與內(nèi)存觀察本地部署 RAG 時主要資源消耗來自兩部分Embedding 模型推理BGE-M3 這類模型在 CPU 上也可以跑但批量處理時 GPU 加速更明顯。LLM 推理7B 級別模型需要至少 6GB 到 8GB 顯存14B 及以上需要更多。實際占用取決于模型量化版本、上下文長度和并發(fā)數(shù)。觀察顯存占用的常用命令# 查看 GPU 顯存占用 nvidia-smi # 查看內(nèi)存占用 free -h如果是 CPU 推理建議把模型量化為 4bit 或 8bit能明顯降低內(nèi)存需求速度也有改善。7.3 如何降低資源占用使用量化模型GGUF 格式的 4bit 量化模型資源占用更少??刂粕舷挛拈L度Prompt 不要無限拼接檢索結果。限制向量庫返回條數(shù)默認 top_k 設置為 3 到 5不要一次性返回 20 條。批量處理時限制并發(fā)一次處理 1 到 2 個請求避免顯存溢出。使用輕量 Embedding 模型檢索場景不一定非用最大的模型。8. RAG 常見問題與排查方法下面這張表總結了 RAG 項目中最常見的幾類問題。問題現(xiàn)象可能原因排查方式解決方案啟動時報模型不存在Ollama 模型未拉取或模型名拼寫錯誤執(zhí)行ollama list查看模型列表用ollama pull 模型名拉取正確模型PDF 解析亂碼PDF 是掃描件或字體編碼異常查看加載后的文檔內(nèi)容改用 OCR 解析工具或先用圖片轉文字檢索結果不相關切塊過大或過小、Embedding 模型不適合打印切塊結果人工檢查相關性調(diào)整切塊策略更換 Embedding 模型回答內(nèi)容與資料無關LLM 忽略上下文或 Prompt 設計不清檢查輸入給 LLM 的 Prompt 內(nèi)容強化 Prompt 約束添加“資料中未找到”處理接口調(diào)用超時LLM 推理太慢或請求排隊觀察服務日志和 GPU 占用減小模型規(guī)模、限制并發(fā)、開啟流式輸出批量任務中斷單條任務異常導致進程退出查看日志定位失敗項使用任務隊列增加超時和失敗重試顯存不足模型太大或并發(fā)太高運行nvidia-smi查看顯存使用小模型、量化版本或降低并發(fā)向量庫數(shù)據(jù)文件損壞寫入中斷或版本不兼容檢查數(shù)據(jù)庫日志重新導入數(shù)據(jù)定期備份向量庫目錄9. RAG 項目最佳實踐與合規(guī)建議9.1 先用最小數(shù)據(jù)集跑通鏈路第一次做 RAG不要直接上一整本幾百頁的 PDF。先準備 3 到 5 個文檔切塊后手動檢查每塊的內(nèi)容質(zhì)量再驗證檢索效果。這樣能快速定位是文檔解析的問題還是切塊、檢索的問題。9.2 記錄每次實驗的關鍵參數(shù)RAG 項目的效果和參數(shù)強相關建議每次實驗都記錄切塊大小與 overlap。Embedding 模型名稱。向量庫類型。Rerank 是否開啟。LLM 模型與溫度參數(shù)。檢索 top_k。測試問題集和人工打分結果。這樣后續(xù)優(yōu)化時才知道是哪個環(huán)節(jié)發(fā)生了變化。9.3 知識庫更新策略知識庫不是一次性建完就不管了。生產(chǎn)環(huán)境中要考慮增量更新給每個文本塊記錄來源文檔和更新時間。文檔更新時刪除對應向量重新入庫。定期清理無效文本塊。版本化知識庫方便回滾。9.4 合規(guī)使用建議這里再強調(diào)一遍涉及本地部署和知識庫問答時務必遵守以下原則只處理已獲得授權的文檔。內(nèi)網(wǎng)數(shù)據(jù)優(yōu)先選擇本地部署模型不傳外部 API。人臉、聲紋、身份證號等敏感信息不得進入測試系統(tǒng)。商用發(fā)布前對生成答案做內(nèi)容審核。10. 總結與下一步RAG 技術棧的核心鏈路并不復雜文檔切塊、Embedding、向量檢索、LLM 生成四個環(huán)節(jié)打通就能做出一個可用的知識庫問答系統(tǒng)。最難的不是跑通 Demo而是讓檢索結果穩(wěn)定可靠。建議下一步做這幾件事用 Ollama 部署 BGE-M3 和一個小參數(shù) LLM跑通本地 RAG。準備一組真實業(yè)務文檔測試不同切塊策略下的檢索質(zhì)量。封裝 FastAPI 接口把單獨的知識庫能力接到現(xiàn)有系統(tǒng)中。逐步引入混合檢索和 Rerank觀察回答準確率的變化。批量任務加上日志、重試和監(jiān)控再考慮生產(chǎn)部署。RAG 項目入門不難但做好需要不斷調(diào)試。建議收藏這篇文章做項目時對著流程一步步推進。