前言
在 Day 4 我們建立了結構化的個人知識庫,Day 5 則實作了資訊的自動化抓取。隨著筆記與文件累積得越來越多,「如何快速找到需要的知識」便成了新的挑戰。
傳統的關鍵字搜尋(Keyword Search)往往只能精準比對字詞,無法理解語意。今天我們將介紹 RAG(Retrieval-Augmented Generation,檢索增強生成) 技術,帶你用 Python 與 LangChain 打造一個能根據你的本地 Markdown 筆記進行回答的「專屬 AI 智庫」!
一、什麼是 RAG?為什麼你需要它?
RAG 的核心概念很簡單:在將問題送給 LLM 之前,先從你的知識庫中找出相關的資料片段,並把這些片段當作參考背景(Context)一起交給 AI。
這帶 glass 般的優點:
解決 AI 幻覺(Hallucination): AI 只能依據你提供的真實筆記內容回答。
資訊隱私與客製化: 不用把個人筆記上傳給外面的模型進行微調(Fine-tuning),即插即用。
語意搜尋(Semantic Search): 即使輸入「如何處理 Python 記憶體洩漏」,也能檢索出標題為「Python Garbage Collection 機制」的筆記。
二、RAG 架構四部曲
一個基礎的 RAG 系統包含以下步驟:
載入與切分 (Load & Split): 讀取本地 Markdown 檔案,將長文本切分成較小的 Chunk(區塊)。
向量化 (Embedding): 使用 Embedding 模型將文字轉換成多維向量,代表文字的語意。
向量儲存 (Vector Store): 將向量與對應文本存入向量資料庫(如 Chroma, FAISS)。
檢索與生成 (Retrieve & Generate): 當使用者提問時,比對問題向量與資料庫中最相似的內文片段,再由 LLM 整合輸出答案。
三、實戰範例:用 LangChain + Chroma 建立本地問答系統
以下為使用 Python 建立簡單 RAG 管道的實作程式碼:
Python
from langchain_community.document_loaders import DirectoryLoader, MarkdownLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain_google_genai import GoogleGenerativeAIEmbeddings, ChatGoogleGenerativeAI
from langchain.chains import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_core.prompts import ChatPromptTemplate
loader = DirectoryLoader('./notes', glob="**/*.md", loader_cls=MarkdownLoader)
docs = loader.load()
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
splits = text_splitter.split_documents(docs)
embeddings = GoogleGenerativeAIEmbeddings(model="models/embedding-001")
vectorstore = Chroma.from_documents(documents=splits, embedding=embeddings)
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
llm = ChatGoogleGenerativeAI(model="gemini-1.5-flash")
system_prompt = (
"你是一個嚴謹的 IT 筆記助理。請僅根據以下提供之上下文內容回答問題。"
"如果上下文不包含答案,請回答『我的筆記中沒有相關資訊』。\n\n"
"{context}"
)
prompt = ChatPromptTemplate.from_messages([
("system", system_prompt),
("human", "{input}"),
])
question_answer_chain = create_stuff_documents_chain(llm, prompt)
rag_chain = create_retrieval_chain(retriever, question_answer_chain)
if name == "main":
query = "我之前整理的 Docker 網路配置重點是什麼?"
response = rag_chain.invoke({"input": query})
print("AI 導師回答:\n", response["answer"])
四、打造高精準度 RAG 的注意事項
Chunk 大小設定: Chunk 過大容易帶入雜訊,過小則會遺失前後文。通常建議設定在 300~800 字之間,並搭配 10%~20% 的重複重疊(Overlap)。
筆記結構化: Markdown 善用標題(#, ##),能幫助切分器更完整地保留段落邏輯。
附帶引用來源 (Citations): 在輸出答案時要求 AI 列出參考的筆記檔名,方便點擊回溯原始文件。
結語
透過 RAG,我們正式將原本靜態的 Markdown 筆記庫昇華為可對話的「第二大腦」。隨時隨地詢問「我上個月學過的那個指令是什麼?」,AI 都能秒級找到並解答!
明天(Day 7),我們將劃下第一週的句點,進行「第一週階段性總結:從 0 到 1 打造自學工作流的關鍵心法」,並安排後續實戰主題,敬請期待!