實戰(zhàn):從零搭建并用Deepseek驅動)
在業(yè)務中接入大模型時很多同學都會走到同一步希望大模型能回答自己企業(yè)內部文檔里的問題。但直接提問會發(fā)現模型既不了解你的業(yè)務也容易一本正經地編造答案。要解決這個問題RAG 是目前最實用、成本最低的方案。本文將基于一套完整可運行的代碼帶你從零搭建一個RAG知識庫問答系統(tǒng)并把 Deepseek 作為最終生成模型接入其中從原理到落地一次性講透。先說一下本文適合誰對大模型感興趣但還沒系統(tǒng)接觸過 RAG 的開發(fā)者、正在做企業(yè)知識庫需求的后端工程師、想在自己電腦上跑通一套完整問答系統(tǒng)的學習者。讀完本文你會理解 RAG 的完整處理鏈路掌握文檔加載、文本切分、向量化、向量檢索、Prompt 組裝、大模型生成這幾個關鍵環(huán)節(jié)并拿到一套可以擴展成真實項目的基礎源碼。1. RAG 到底是什么為什么大模型需要它1.1 從大模型的“知識缺陷”說起大模型雖然能寫文章、寫代碼、做翻譯但有一個天然缺陷它的知識來自訓練數據存在明顯的“知識截止時間”。如果你的問題涉及企業(yè)最新制度、某個產品的使用手冊、某個系統(tǒng)的內部操作說明大模型很可能會回答一個看似合理、實則錯誤的內容這就是常說的“幻覺”問題。舉個例子你問“公司請休假制度是什么”模型可能會編造一套看似標準的制度而它根本沒有見過你公司的文檔。此時你不可能為了這個問題重新訓練一個大模型成本太高也不現實。RAG 的解決思路很直接與其讓模型“背”下所有知識不如在它回答問題之前先幫它找到相關資料。這就好比考試時允許翻書模型不用死記硬背只需要根據“查到的那幾頁”來組織答案。1.2 RAG 的完整定義與核心流程RAG全稱 Retrieval-Augmented Generation檢索增強生成。它是一種將信息檢索與文本生成相結合的架構先從外部知識庫中檢索出與用戶問題相關的文檔片段再將片段與問題一起交給大模型讓模型基于這些片段生成回答。標準 RAG 的處理流程可以拆成八個環(huán)節(jié)文檔加載讀取內部文檔支持 txt、PDF、Word、Markdown 等格式。文本切分長文檔不能整體向量化需要按一定策略切分成 chunk文本塊。向量化使用 embedding 模型將每個 chunk 轉換為向量向量可以理解為一段文本的語義坐標。向量存儲將向量和原文一起存入向量數據庫例如 Chroma、FAISS、Milvus。問題向量化用戶提問時將問題也轉換為向量。相似度檢索計算問題向量與知識庫向量的相似度返回最相關的 Top K 個片段。Prompt 組裝將系統(tǒng)提示詞、檢索到的片段、用戶問題拼接成一個完整的 Prompt。生成回答將 Prompt 發(fā)送給大模型模型基于片段內容生成最終答案。1.3 RAG 與模型微調的區(qū)別很多初學者會把 RAG 和微調搞混。簡單來說微調是修改模型的“記憶”RAG 是給模型“查資料”。兩者各有適用場景對比維度RAG微調成本較低無需訓練顯卡較高需要訓練資源和數據準備知識更新替換文檔即可實時生效需要重新訓練周期長可解釋性回答可溯源到具體文檔片段相對難以解釋模型參考了什么幻覺控制通過限定參考片段效果明顯降低有限模型仍可能生成非訓練知識適用場景企業(yè)知識庫、文檔問答、實時信息改變模型語氣風格、專業(yè)術語理解、特定格式輸出真實項目中RAG 和微調也經常配合使用。如果模型本身對你所在行業(yè)的術語理解較弱可以先用部分數據微調模型再疊加 RAG 讓模型獲取最新知識。但對大多數知識庫問答需求來說RAG 是首選中低成本方案。2. 系統(tǒng)方案設計與技術選型2.1 方案目標我們要搭建的這套系統(tǒng)需要滿足以下需求支持把本地文檔導入知識庫。文檔必須支持持續(xù)追加和更新不需要重訓練模型。用戶提問后系統(tǒng)能檢索到相關文檔片段并在回答中給出依據。最終生成模型使用 Deepseek API保證中文效果且調用簡單。整個系統(tǒng)可以本地運行不依賴大型 GPU 環(huán)境。2.2 總體架構根據需求系統(tǒng)的整體架構可以這樣設計用戶提問Web界面 / 命令行 ↓ 中文問題向量化本地Embedding模型 ↓ Chroma向量庫相似度檢索 ↓ 返回 Top-K 相關文檔片段 ↓ 組裝 Prompt系統(tǒng)提示詞 參考片段 用戶問題 ↓ 調用 Deepseek Chat API ↓ 生成最終回答并返回給用戶在這個架構中文檔離線處理鏈路把原始知識庫轉換為向量索引在線問答鏈路負責檢索與生成。兩條鏈路合起來就是一套完整的 RAG 系統(tǒng)。2.3 技術棧說明本方案涉及的主要技術組件如下模塊技術選型選擇原因文檔加載Python 內置文件讀取輕量零依賴適合 txt 文檔入門文本切分LangChain Text Splitters成熟的切分策略支持重疊窗口向量化模型sentence-transformers bge-small-zh-v1.5中文效果好本地運行免費向量數據庫Chroma輕量級無需獨立服務適合快速開發(fā)生成模型Deepseek Chat API中文能力強兼容 OpenAI 協(xié)議接入成本低Web 展示層Streamlit用 Python 快速搭建交互界面為什么使用 Deepseek 作為生成模型這是很多讀者關心的問題。Deepseek 的 API 調用方式與 OpenAI 協(xié)議兼容只需要安裝 openai SDK 并修改 base_url 和 api_key 就能完成接入非常省事。同時Deepseek 在中文理解與生成上的表現足夠優(yōu)秀適合中文知識庫問答場景。相比本地部署一個十幾B或幾十B的大模型API 方式對電腦性能要求極低個人開發(fā)者和中小規(guī)模應用都能低成本使用。為什么 embedding 模型選用本地部署原因也很實際。如果每次寫文檔和提問都調用外部 embedding 接口會產生持續(xù)費用同時還會把文檔內容送到第三方服務。使用本地 bge-small-zh-v1.5 模型只需要首次運行下載模型文件之后便可以在完全離線的狀態(tài)下完成向量化成本低、隱私性也更好。3. 環(huán)境準備與項目結構3.1 安裝 Python 與依賴本文示例以 Python 3.9 及以上版本為例。老規(guī)矩先創(chuàng)建一個獨立的虛擬環(huán)境避免依賴污染系統(tǒng)環(huán)境python -m venv rag-demo-env source rag-demo-env/bin/activate # Windows 下為 rag-demo-env\Scripts\activate然后安裝依賴包pip install openai sentence-transformers chromadb langchain-text-splitters streamlit python-dotenv如果你的環(huán)境安裝速度較慢可以更換為國內 pip 鏡像源pip install -i https://pypi.tuna.tsinghua.edu.cn/simple openai sentence-transformers chromadb langchain-text-splitters streamlit python-dotenv這里不鎖定具體版本號因為這些庫的迭代速度較快建議使用當前最新穩(wěn)定版即可。如果后續(xù)遇到某個庫升級導致接口變動可以回到對應官方文檔確認最新用法。3.2 項目目錄結構完整源碼建議按照下面的目錄結構保存rag-demo/ ├── .env # API Key 等敏感配置不提交到倉庫 ├── requirements.txt # 依賴清單 ├── config.py # 全局配置 ├── ingest.py # 文檔加載與向量庫構建 ├── retriever.py # 檢索模塊 ├── rag.py # RAG 問答主流程 ├── app.py # Streamlit Web 界面 └── data/ # 存放私有文檔 ├── 公司介紹.txt └── product_faq.txtrequirements.txt 文件內容如下openai1.0.0 sentence-transformers2.2.0 chromadb0.4.0 langchain-text-splitters0.0.1 streamlit1.30.0 python-dotenv1.0.04. 核心代碼實現從文檔到知識庫4.1 全局配置 config.py代碼的第一步是寫一個配置模塊把路徑、模型名稱、檢索參數等集中管理起來。這樣后續(xù)修改參數時不需要翻遍每個文件。# 文件路徑rag-demo/config.py import os from dotenv import load_dotenv # 加載 .env 文件中的環(huán)境變量 load_dotenv() # 知識庫文檔目錄 KNOWLEDGE_BASE_DIR data # Chroma 向量庫持久化目錄 CHROMA_DIR ./chroma_db # 向量庫集合名稱 COLLECTION_NAME rag_demo # 本地 Embedding 模型名稱 EMBEDDING_MODEL_NAME BAAI/bge-small-zh-v1.5 # 檢索返回的片段數量 TOP_K 3 # 文檔切分參數 CHUNK_SIZE 500 CHUNK_OVERLAP 50 # Deepseek API 配置 DEEPSEEK_API_KEY os.getenv(DEEPSEEK_API_KEY, ) DEEPSEEK_BASE_URL os.getenv(DEEPSEEK_BASE_URL, https://api.deepseek.com) DEEPSEEK_MODEL os.getenv(DEEPSEEK_MODEL, deepseek-chat)有一處要重點說明DEEPSEEK_API_KEY 不建議硬編碼在代碼文件中應該寫在項目根目錄的 .env 文件里并確保 .env 被加入 .gitignore。這樣可以避免 API Key 意外提交到公開倉庫造成安全風險。.env 文件的格式如下DEEPSEEK_API_KEY你的Deepseek_API_Key關于 Deepseek API 的使用請前往 Deepseek 官方開放平臺注冊并創(chuàng)建 API Key。使用 API 會產生少量費用具體計費標準以官方頁面為準建議先小額充值并查看接口文檔中的價格說明。4.2 文檔加載與向量化入庫 ingest.pyingest.py 的作用是讀取 data 目錄下的文檔進行切分、向量化然后寫入向量數據庫。這是整個 RAG 系統(tǒng)的離線構建階段。# 文件路徑rag-demo/ingest.py import os from typing import List from langchain_text_splitters import CharacterTextSplitter from sentence_transformers import SentenceTransformer import chromadb import config def load_documents(data_dir: str) - List[str]: 讀取 data 目錄下的所有 txt 文件返回文檔內容列表。 docs [] for filename in os.listdir(data_dir): if filename.endswith(.txt): filepath os.path.join(data_dir, filename) with open(filepath, r, encodingutf-8) as f: content f.read() if content.strip(): docs.append(content) print(f已加載文檔: {filename}) return docs def split_text(documents: List[str]) - List[str]: 將長文檔切分成指定大小的文本塊 chunk。 splitter CharacterTextSplitter( separator\n, chunk_sizeconfig.CHUNK_SIZE, chunk_overlapconfig.CHUNK_OVERLAP, length_functionlen, ) chunks [] for doc in documents: chunks.extend(splitter.split_text(doc)) return chunks def build_vector_store(chunks: List[str]): 將文本塊向量化并寫入 Chroma 向量庫。 # 加載本地 embedding 模型首次運行會自動下載 print(正在加載 embedding 模型...) embedder SentenceTransformer(config.EMBEDDING_MODEL_NAME) # 生成向量 print(正在生成向量...) embeddings embedder.encode(chunks, show_progress_barTrue).tolist() # 創(chuàng)建 Chroma 客戶端持久化到本地目錄 client chromadb.PersistentClient(pathconfig.CHROMA_DIR) # 如果集合已存在先刪除避免重復插入 existing_collections client.list_collections() for col in existing_collections: if col.name config.COLLECTION_NAME: client.delete_collection(config.COLLECTION_NAME) print(已刪除舊的向量庫集合) collection client.create_collection( nameconfig.COLLECTION_NAME, metadata{hnsw:space: cosine}, # 使用余弦相似度 ) # 寫入向量庫id 使用序號方便管理 ids [str(i) for i in range(len(chunks))] # 這里直接把原始文本和向量一起存入 collection.add( idsids, embeddingsembeddings, documentschunks, ) print(f向量庫構建完成共寫入 {len(chunks)} 個文本塊) if __name__ __main__: all_docs load_documents(config.KNOWLEDGE_BASE_DIR) if not all_docs: raise ValueError(fdata 目錄下沒有找到可用文檔請檢查目錄: {config.KNOWLEDGE_BASE_DIR}) all_chunks split_text(all_docs) print(f文檔切分完成共得到 {len(all_chunks)} 個文本塊) build_vector_store(all_chunks)這段代碼的重點有幾個。文本切分參數值得專門調試。CHUNK_SIZE 表示每個文本塊的最大字符數CHUNK_OVERLAP 表示相鄰塊之間重疊的字符數。重疊的部分可以讓切塊邊界處的語義不丟失尤其是當問題和答案分別跨越兩個塊邊界時重疊能明顯提升召回效果。實際項目中500 到 800 字是比較常見的塊大小過小會導致檢索上下文不足過大則會讓單塊包含太多無關信息降低檢索精度。Chroma 的持久化方式在代碼中使用了 PersistentClient向量庫數據會保存到 ./chroma_db 目錄。這樣下次啟動系統(tǒng)時不需要重新構建向量庫直接讀取即可。如果知識庫文檔發(fā)生了更新重新運行一次 ingest.py 即可不必重啟任何服務。4.3 檢索模塊 retriever.pyretriever.py 負責接收用戶問題將其向量化后在 Chroma 中檢索最相關的 Top K 個片段。# 文件路徑rag-demo/retriever.py import chromadb from sentence_transformers import SentenceTransformer import config def get_embedder(): 獲取共享的 embedding 模型實例避免多次重復加載。 return SentenceTransformer(config.EMBEDDING_MODEL_NAME) def search(query: str, top_k: int None): 根據用戶問題檢索知識庫返回相關片段列表。 if top_k is None: top_k config.TOP_K # 加載向量庫 client chromadb.PersistentClient(pathconfig.CHROMA_DIR) collection client.get_collection(config.COLLECTION_NAME) # 對用戶問題進行向量化 embedder get_embedder() query_embedding embedder.encode([query]).tolist() # 執(zhí)行相似度檢索 results collection.query( query_embeddingsquery_embedding, n_resultstop_k, ) documents results.get(documents, [[]])[0] distances results.get(distances, [[]])[0] return documents, distances這里需要留意一個問題每次調用 get_embedder 都會重新加載一次模型。在 Streamlit 這種 Web 服務中頻繁加載模型會拖慢速度。實際開發(fā)時可以把 embedder 設計成全局單例或者放到內存緩存中。我在這里保留簡單寫法是為了讓流程更清晰后面工程優(yōu)化部分再討論如何改進。Chroma 的 query 接口返回結果中documents 是對應的原始文本內容distances 是余弦距離。距離越小表示相似度越高后續(xù)可以把距離信息一并展示幫助用戶判斷答案的可信度。4.4 RAG 問答主流程 rag.pyrag.py 是系統(tǒng)的核心負責把檢索結果和用戶問題組裝成 Prompt然后調用 Deepseek 生成回答。# 文件路徑rag-demo/rag.py from openai import OpenAI import config from retriever import search # 初始化 Deepseek 客戶端兼容 OpenAI SDK client OpenAI( api_keyconfig.DEEPSEEK_API_KEY, base_urlconfig.DEEPSEEK_BASE_URL, ) def build_prompt(query: str, context_docs: list) - str: 組裝發(fā)送給大模型的 Prompt。 system_prompt ( 你是一個專業(yè)的知識庫問答助手。 請根據提供的參考資料回答用戶問題。 必須優(yōu)先參考參考資料中的內容不要臆造答案。 如果參考資料無法回答該問題請直接說明知識庫中暫未找到相關信息。 ) context \n\n.join(context_docs) user_prompt f請根據以下參考資料回答用戶問題。 【參考資料】 {context} 【用戶問題】 {query} 請用中文回答如果引用了參考資料可以說明信息來源于哪個部分。 return system_prompt, user_prompt def ask(query: str) - dict: Retrieve Generate 完整流程。 # 檢索相關片段 docs, distances search(query) # 組裝 Prompt system_prompt, user_prompt build_prompt(query, docs) # 調用 Deepseek 生成回答 response client.chat.completions.create( modelconfig.DEEPSEEK_MODEL, temperature0.3, messages[ {role: system, content: system_prompt}, {role: user, content: user_prompt}, ], ) answer response.choices[0].message.content return { answer: answer, source_documents: docs, distances: distances, } if __name__ __main__: question input(請輸入你的問題) result ask(question) print(\n 回答 ) print(result[answer]) print(\n 引用片段 ) for i, doc in enumerate(result[source_documents]): print(f\n[{i 1}] {doc[:200]})Deepseek 的接入方式與 OpenAI 幾乎一致核心代碼只有這么幾行。這里給出的 model 名稱是 deepseek-chat對應 Deepseek 的對話模型。temperature 設置為 0.3會讓回答更加穩(wěn)定、更貼近參考資料內容。如果你想獲得更有創(chuàng)造性的回答可以調高到 0.7 左右但在知識庫問答場景下推薦保持低 temperature以減少胡說八道的概率。Prompt 的設計值得仔細思考。系統(tǒng)提示詞明確要求“必須優(yōu)先參考參考資料中的內容不要臆造答案”這一步是抑制幻覺的關鍵。如果直接把問題和檢索片段丟給模型而不加任何約束模型仍然可能傾向使用自己的知識回答。所以在 RAG 系統(tǒng)中Prompt 不是隨便拼一段文字而是需要反復打磨的工程質量項。4.5 Streamlit Web 界面 app.py最后寫一個簡單的 Web 界面讓系統(tǒng)可以被同事或用戶直接使用。# 文件路徑rag-demo/app.py import streamlit as st import config from rag import ask st.set_page_config(page_titleRAG 知識庫問答系統(tǒng), page_icon, layoutwide) st.title( RAG 知識庫問答系統(tǒng)) st.caption(基于 Deepseek Chroma 構建的私有知識庫問答系統(tǒng)) query st.text_area(請輸入你的問題, height100) if st.button(獲取答案, typeprimary): if not query.strip(): st.warning(請輸入問題內容) elif not config.DEEPSEEK_API_KEY: st.error(未檢測到 DEEPSEEK_API_KEY請檢查 .env 文件配置) else: with st.spinner(正在檢索并生成回答...): result ask(query.strip()) st.subheader(回答) st.write(result[answer]) with st.expander(查看參考文檔片段): for i, (doc, dist) in enumerate(zip(result[source_documents], result[distances])): st.markdown(f**片段 {i 1}**距離{dist:.4f}) st.text(doc[:500])這個界面就是典型的“輸入框 按鈕 結果展示”結構沒有復雜的前端依賴。st.expander 折疊展示參考片段讓用戶既能看答案也能核對答案的出處符合 RAG 可溯源的優(yōu)勢。5. 運行系統(tǒng)與效果驗證5.1 準備示例文檔在 data 目錄下創(chuàng)建兩個測試文檔這里以一個虛構的公司場景為例# 文件路徑rag-demo/data/公司介紹.txt 某某科技有限公司成立于2018年總部位于上海主營業(yè)務是企業(yè)級人工智能解決方案定制服務。 公司核心技術團隊來自國內一線互聯(lián)網公司與高校實驗室在自然語言處理、知識圖譜、大模型應用方向有豐富經驗。 公司的主要產品包括智能客服系統(tǒng)、知識庫問答平臺、數據中臺建設服務。 截至2025年公司已服務超過200家中小企業(yè)客戶覆蓋零售、金融、教育等行業(yè)。# 文件路徑rag-demo/data/product_faq.txt 問知識庫問答平臺支持哪些文檔格式 答平臺支持 txt、PDF、Word、Markdown 等常見格式推薦使用 Markdown 或 txt 以獲得最佳解析效果。 問平臺的數據是否安全 答平臺支持私有化部署文檔向量化和檢索過程可以在企業(yè)內部網絡獨立完成只有最終生成回答時會調用大模型 API。 問知識庫更新需要重新訓練模型嗎 答不需要。知識庫問答系統(tǒng)采用 RAG 架構只需要更新向量庫即可讓模型基于最新文檔回答問題。5.2 初始化知識庫在項目根目錄執(zhí)行python ingest.py正常情況下會看到類似輸出已加載文檔: 公司介紹.txt 已加載文檔: product_faq.txt 文檔切分完成共得到 6 個文本塊 正在加載 embedding 模型... 正在生成向量... 向量庫構建完成共寫入 6 個文本塊首次運行會下載 bge-small-zh-v1.5 模型文件大小在 100MB 左右需要保持網絡暢通。下載完成后模型會緩存在本地之后運行不會再重復下載。5.3 啟動 Web 界面streamlit run app.py瀏覽器會自動打開 Streamlit 提供的本地地址默認是 http://localhost:8501??梢钥吹揭粋€簡潔的問答界面輸入問題后點擊“獲取答案”。嘗試提問“公司知識庫平臺支持哪些文檔格式”預期回答會參考 product_faq.txt 中的內容并明確指出支持 txt、PDF、Word、Markdown 等格式。如果提問“公司成立于哪一年”系統(tǒng)應該從公司介紹文檔中檢索到對應信息并給出答案。在“查看參考文檔片段”區(qū)域你會看到檢索到的原始片段和對應的相似度距離這能幫助你判斷系統(tǒng)是否真正用上了知識庫內容。6. 常見問題與排查思路在實際運行中很多問題其實是共通的。下面把高頻問題整理成表格再逐個展開。問題現象常見原因解決思路首次運行下載模型失敗網絡不穩(wěn)定或 HuggingFace 地址無法訪問使用鏡像地址或手動下載模型到本地向量庫查詢報錯 Collection not found未執(zhí)行 ingest.py 或目錄不一致執(zhí)行 ingest.py 構建向量庫檢查 CHROMA_DIR檢索結果與問題無關chunk 過大、top_k 過小、文檔格式混亂調整 CHUNK_SIZE、增大 TOP_K清洗文檔Deepseek API 返回 401 錯誤API Key 不正確或未加載成功檢查 .env 文件確認 load_dotenv 生效回答沒有引用知識庫內容Prompt 約束不夠或檢索片段為空加強 system prompt檢查檢索結果Chroma old database version 報錯向量庫版本升級不兼容刪除 chroma_db 目錄后重新 ingest6.1 首次運行模型下載失敗bge-small-zh-v1.5 模型默認從 HuggingFace 下載。如果你的網絡環(huán)境無法穩(wěn)定訪問可以設置鏡像環(huán)境變量export HF_ENDPOINThttps://hf-mirror.com然后在終端重新運行 ingest.py。設置鏡像環(huán)境變量的目的是解決下載通道問題屬于開發(fā)過程中的常規(guī)操作。模型下載完成后可以不再依賴外網。另一種方式是從其他方式下載模型文件后把模型目錄放到本地然后在 config.py 中將 EMBEDDING_MODEL_NAME 改為模型所在的本地路徑。例如EMBEDDING_MODEL_NAME ./models/bge-small-zh-v1.56.2 檢索結果不理想檢索結果差通常不是單一原因造成的需要按照順序排查幾個關鍵參數。先檢查 TOP_K。如果設置為 1結果可能只覆蓋一個片段信息量不足如果設置為 5又可能混入大量不相關內容。對于短文檔3 是合理的起點。再檢查 CHUNK_SIZE。如果文檔本身是 FAQ 格式每條問答很短那么把 CHUNK_SIZE 設置成 500會把多個問答切進同一個塊導致檢索時指向內容不準確。對這種結構化文檔建議將 chunk_size 調小比如 200 到 300并去掉過大的 overlap。最重要的還是文檔清洗。如果原始文檔包含大量頁眉頁腳、特殊符號、亂碼向量化效果會明顯變差。在真實項目中文檔預處理往往占用整個 RAG 項目一半以上的工作量這是很正常的現象。6.3 Deepseek API 接入問題如果調用時報 401最直接的排查方式是打印 config.DEEPSEEK_API_KEY確認 .env 是否被正確加載。.env 文件必須和運行命令所在目錄一致也就是項目根目錄。如果報連接超時先確認網絡環(huán)境能夠訪問 Deepseek API。同時可以在代碼中打印 DEEPSEEK_BASE_URL確認沒有因為之前的項目設置而覆蓋成了其他地址。6.4 向量庫版本兼容問題Chroma 版本迭代較快不同版本生成的數據庫文件可能不兼容出現類似“old database version”的報錯時最簡單的處理是備份并刪除 chroma_db 目錄然后重新運行 ingest.py。這只是開發(fā)階段的做法生產環(huán)境中應該提前規(guī)劃向量庫的升級策略例如使用獨立的向量數據庫服務。7. 最佳實踐與工程化建議文章到這里整套代碼已經能跑通了。但如果你想把這個 Demo 變成真正可用的系統(tǒng)還需要注意下面幾個工程問題。7.1 把 Prompt 單獨管理不要把 Prompt 字符串散落在業(yè)務代碼里。隨著項目迭代Prompt 的調整頻率很高應該單獨提取為一個配置文件或 Prompt 管理模塊。某些團隊還會為不同場景編寫多套 Prompt比如“摘要模式”“對比模式”“嚴格引用模式”然后用模版變量動態(tài)切換。7.2 增加檢索結果的引用溯源RAG 的核心優(yōu)勢之一就是可解釋性。在 Web 界面和 API 返回中都應該保留 source_documents 字段最好把文檔名、頁碼、片段位置一起返回。這樣用戶能夠點擊查看原文運營人員也能快速發(fā)現錯誤片段并及時修正知識庫。7.3 完善文檔更新機制目前 ingest.py 每次都會刪除舊集合重新寫入。當知識庫規(guī)模變大后應該改成增量更新根據文檔的 hash 值或更新時間只處理變更部分。向量庫中也要增加元數據字段比如來源文件名、更新時間、部門標簽方便按條件過濾。7.4 引入重排Rerank提升精度向量檢索拿到的 Top K 片段里可能順序并不完全符合語義相關度。更成熟的方案是在向量檢索之后增加一個 rerank 模型對候選片段重新打分。比如本地部署 bge-reranker-base 模型先用向量召回 20 個候選再重排取前 3 個送給大模型。實踐表明加一層 rerank 后回答準確率往往會有明顯提升。7.5 從 RAG 走向 Agentic RAG目前實現的是標準 RAG每次提問只做一次檢索。當問題復雜時例如“對比公司產品 A 和產品 B 的區(qū)別”或者“找出去年所有投訴工單中的高頻問題”單次檢索可能不夠。Agentic RAG 的核心思想是讓大模型具備“工具調用”能力它可以決定先搜索什么、搜索幾次、是否改寫問題、是否需要查看多個文檔后再綜合回答。這個方向可以作為下一步的進階學習目標。本質上是把 RAG 的“搜索鏈路”從固定流程升級成由模型驅動的動態(tài)流程對 Prompt 設計和工具調用的工程質量要求更高。7.6 安全與合規(guī)注意事項涉及到 API 調用、內部文檔時有幾個安全底線需要堅持。第一API Key 絕不硬編碼在源碼中.env 文件必須加入 .gitignore第二生產環(huán)境建議通過獨立的密鑰管理服務接收 API Key由后端服務統(tǒng)一調用不要把密鑰直接暴露給前端第三企業(yè)內部敏感文檔如果涉及數據保密要求需要確認是否允許調用外部大模型 API。如果嚴格禁止外部傳輸則應該采用本地部署的模型替換 Deepseek API把整個鏈路都收斂在內網環(huán)境中完成。8. 從入門到落地下一步可以做什么至此你已經親手搭完了一套完整的 RAG 知識庫問答系統(tǒng)從文檔加載、切分、向量化、檢索到 Prompt 組裝和 Deepseek 生成回答所有環(huán)節(jié)都是可運行、可擴展的。相比直接調用大模型接口“硬問”這套方案讓模型真正學會利用你的私有資料來回答問題。如果你打算繼續(xù)深入有兩條推薦路線。一條是優(yōu)化檢索質量嘗試引入 rerank、多路召回、元數據過濾讓召回結果更精準另一條是走向 Agentic RAG讓模型能自主規(guī)劃檢索步驟處理更復雜的多跳問答任務。兩條路線都不需要重新訓練模型完全符合 RAG 低成本的核心理念。構建知識庫本身也是一門細活。文檔清洗、文本切分、領域詞表、Prompt 調優(yōu)每一個環(huán)節(jié)都會影響最終回答質量。不要指望運行一遍代碼就得到完美效果真正的項目落地就是在這些細節(jié)里不斷打磨的過程。希望這份手把手教程能幫你邁出扎實的第一步也歡迎把你在搭建過程中遇到的問題留在評論區(qū)大家互相交流排錯經驗。