前言:API key 這件事,遲早讓你半夜醒來
用 OpenAI API 跑 RAG 的時候,你是否曾經盯著用量報表,心裡想:「這個月又要多少錢?」
或者更糟——半夜收到 rate limit 通知,系統直接斷線,知識庫變啞巴。
這篇文章不是另一篇「什麼是 RAG」的理論文。 這是一篇實戰手冊,專門寫給:想自己架知識庫、但不想每個月被 API 帳單追著跑的人。
目標很明確:用 Ollama 在本地跑一套完整的 RAG 搜尋引擎,不需要任何外部 API,不需要網路,連機密文件都不用傳到別人的伺服器。
為什麼選 Ollama?
Ollama 近期做到以下幾件事:
- 模型下載超簡單:
ollama pull llama3搞定,不需要折騰 CUDA、docker compose、HF token - Embedding 內建:0.6 版之後自帶
nomic-embed-text,不需要再串 OpenAI 或 Cohere - 跟 Docker 說再見:直接二進位執行,macOS / Linux / Windows 都能跑
- OpenAI 相容 API:
/api/chat和/api/embeddings完全比照 OpenAI 格式,現有套件無痛替換
簡單說:Ollama 把「架本地 LLM」這件事,從工程師專屬變成了普通開發者兩行指令能搞定的事。
安裝 Ollama——10 分鐘以內從零到可以跑模型
macOS / Linux
### 一行指令搞定
curl -fsSL https://ollama.com/install.sh | sh
Windows
直接去 ollama.com/download 下載安裝程式,點兩下即可。
確認版本
ollama --version
### 預期輸出:ollama version 0.6.x 以上(建議 0.13 以上)
拉模型
### LLM 本體(推薦一開始先用 8B 參數的模型,省 RAM)
ollama pull llama3.2
### Embedding 模型(用 nomic-embed-text,專為搜尋優化)
ollama pull nomic-embed-text
硬體需求參考:
- 8B 模型:至少 8GB RAM(建議 16GB 以上)
- Embedding 模型:通常 1-2GB RAM,負擔不大
- ChromaDB:100MB 級別,磁碟空間看你的文件量
架設向量資料庫——ChromaDB 的本地部署
RAG 的核心是「先把文件切塊、向量化、存進資料庫,搜尋時找出最相似的幾塊,再送進 LLM 回答」。底層原理與檢索優化還有更多眉角,想深入了解可以看 RAG 檢索優化指南:為什麼別人的知識庫回答比你的精準?(2026)。
ChromaDB 是目前最流行的本地向量資料庫:
pip install chromadb
或著用 Docker:
docker pull chromadb/chroma:latest
docker run -d -p 8000:8000 chromadb/chroma
為什麼選 ChromaDB?
- 純 Python,生態系完整(langchain、llamaindex 都支援)
- 預設就會把資料存在本地磁碟,重啟不消失
- 查詢延遲低,embedded mode 不需要另外架服務
想了解檢索品質如何再上一階,可以看 RAG 檢索優化指南:為什麼別人的知識庫回答比你的精準?(2026)。
文件向量化——Chunking 策略決定搜尋品質
文件要怎麼「切」直接影響搜尋品質。這裡有三種常見策略,但底層原理與檢索優化還有更多眉角,想知道更多可以看 RAG 檢索優化指南:為什麼別人的知識庫回答比你的精準?(2026)。
固定長度(最簡單,但品質一般)
def chunk_text(text, chunk_size=500, overlap=50):
chunks = []
start = 0
while start < len(text):
chunks.append(text[start:start + chunk_size])
start += chunk_size - overlap
return chunks
問題:可能把一句話切成兩半,語意不完整。
依段落切(推薦)
def chunk_by_paragraph(text):
paragraphs = text.split('\n\n')
chunks = []
current = ""
for p in paragraphs:
if len(current) + len(p) < 500:
current += "\n\n" + p
else:
if current:
chunks.append(current.strip())
current = p
if current:
chunks.append(current.strip())
return chunks
使用 langchain 的 RecursiveCharacterTextSplitter
from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50,
separators=["\n\n", "\n", "。", ",", " "]
)
chunks = splitter.split_text(text)
原則:
- 技術文件(API 文件、程式碼):chunk_size 200-400
- 長文章、報告:chunk_size 500-800
- Overlap 設 10-20%,讓邊界資訊不要遺失
存入 ChromaDB 與 Embedding——完整的 RAG 資料庫建立流程
import ollama
import chromadb
### 1. 初始化 ChromaDB client
client = chromadb.Client()
### 2. 建立 collection
collection = client.create_collection(
name="my-knowledge-base",
metadata={"hnsw:space": "cosine"}
)
### 4. 把每個 chunk 做 embedding
embeddings = []
for chunk in documents:
response = ollama.embeddings(
model="nomic-embed-text",
prompt=chunk
)
embeddings.append(response["embedding"])
### 5. 存入 ChromaDB
collection.add(
documents=documents,
embeddings=embeddings,
ids=[f"chunk-{i}" for i in range(len(documents))]
)
print(f"已存入 {len(documents)} 個 chunks")
搜尋與生成答案——把本地 RAG 跑起來的最終一步
### 1. 使用者的問題做 embedding
query = "公司的年假政策是什麼?"
query_embedding = ollama.embeddings(
model="nomic-embed-text",
prompt=query
)["embedding"]
### 2. 在 ChromaDB 裡找出最相似的 3 個 chunks
results = collection.query(
query_embeddings=[query_embedding],
n_results=3
)
### 3. 把找到的 chunks 組進 prompt
context = "\n\n".join(results["documents"][0])
prompt = f"""你是公司的內部助理。以下是公司文件中的相關資訊:
{context}
根據以上資訊回答問題。如果找不到答案,請如實說不知道。
問題:{query}
回答:"""
### 4. 送進 LLM 生成答案
response = ollama.chat(
model="llama3.2",
messages=[{"role": "user", "content": prompt}]
)
print(response["message"]["content"])
這就是完整的 RAG 流程:Embedding 存檔 → Query 找相關內容 → LLM 生成回答。
串接 OpenClaw——把本地 RAG 變成真正的企業知識庫
把上面的流程封裝成一個 function,就是 OpenClaw 的 RAG tool 可以呼叫的格式:
def local_rag_search(query: str, top_k: int = 3) -> str:
"""OpenClaw 本地 RAG 搜尋"""
# 1. Embed 問題
query_emb = ollama.embeddings(
model="nomic-embed-text",
prompt=query
)["embedding"]
# 2. 向量搜尋
results = collection.query(
query_embeddings=[query_emb],
n_results=top_k
)
# 3. 組 prompt
context = "\n\n".join(results["documents"][0])
# 4. LLM 生成
response = ollama.chat(
model="llama3.2",
messages=[{
"role": "user",
"content": f"根據以下文件回答:\n\n{context}\n\n問題:{query}"
}]
)
return response["message"]["content"]
在 OpenClaw 的 workflow 裡,這個 function 就是你的「本地知識庫查詢節點」,不需要任何外部 API call。
本地 RAG vs 雲端 RAG——我的實際選擇建議
| 維度 | 本地 RAG(Ollama) | 雲端 RAG(OpenAI + Pinecone) |
|---|---|---|
| 成本 | 極低(只要電費) | API call + 向量資料庫費用 |
| 隱私 | 最強(資料不離開本機) | 需要上傳文件到第三方 |
| 速度 | 取決於本機硬體(可能慢) | 速度快(雲端 GPU) |
| 維護 | 自己管,簡單 | 有平台幫你管,省事 |
| 規模 | 單機為主 | 可擴充到大規模文件庫 |
我的建議:
- 個人或小型工作室 → 本地 RAG,省錢又安心
- 中大型企業、文件量大、需要的回應延遲低 → 考慮雲端方案
- 最佳實踐:平常用本地開發測試,需要擴充時遷移到雲端
結語
本地 RAG 這條路,門檻已經比兩年前低太多了。
Ollama 把複雜的模型下載、硬體優化、API 相容性全部封裝成一個乾淨的介面。你不再需要懂 CUDA、不需要折騰 docker compose、不需要申請十個 API key。只要十行 Python code,就能架出一個完全私有、不知道 GPT 長怎樣的知識庫系統。
重點不是「不用雲端」,而是「你有選擇的權利」。
哪天 Ollama 的模型不夠用了,API 規格完全相容,搬上去只是五分鐘的事。但在那之前,你的資料一直在你自己的機器上——這件事本身就值了。
🔨 如果你想把這套系統實際架在網站上,讓訪客也能用自然語言查詢你的文件,歡迎找鍛碼匠聊聊。我們專門幫企業把 AI 系統落地,不是只停留在「聊天」的層次。








