2026年,RAG已成為AI應用的標配
沒有RAG的大模型就像沒有圖書館的學者——知識停留在訓練資料截止日。RAG讓AI擁有即時、可更新的知識庫,是2026年企業AI應用的核心基礎設施。
一個資料:2026年企業AI應用中,87%使用了RAG,比2024年的31%增長了近3倍。
RAG解決了什麼問題
| 問題 |
沒有RAG |
有RAG |
| 知識過時 |
模型訓練資料截止 |
即時檢索最新文件 |
| 幻覺(Hallucination) |
捏造不存在的事實 |
基於檢索結果回答 |
| 領域知識缺失 |
通用知識,不懂專業 |
注入企業私有知識 |
| 資料隱私 |
資料上傳到模型廠商 |
知識庫本地/私有雲 |
| 可追溯性 |
不知道答案來源 |
每個答案附帶引用來源 |
RAG核心架構
基礎架構:索引 + 檢索 + 生成
┌──────────────────────────────────────────────────────┐
│ 使用者提問 │
│ "公司2025年Q4的營收是多少?" │
├──────────────────────────────────────────────────────┤
│ 查詢處理層 │
│ 查詢改寫 │ 查詢擴展 │ 意圖識別 │ HyDE │
├──────────────────────────────────────────────────────┤
│ 檢索層(雙路召回) │
│ 向量檢索(語意相似) │ 關鍵詞檢索(精確匹配) │
│ ↕ 融合排序(RRF/Cross-Encoder重排) │
├──────────────────────────────────────────────────────┤
│ 生成層 │
│ 上下文注入 → LLM推理 → 答案 + 引用來源 │
└──────────────────────────────────────────────────────┘
第一步:文件處理與分塊
分塊策略對比
| 策略 |
原理 |
優點 |
缺點 |
適用場景 |
| 固定長度 |
按token數切割 |
簡單 |
切斷語意 |
日誌、表格 |
| 遞迴字元 |
按分隔符遞迴切 |
保留段落結構 |
長度不均 |
通用文件 |
| 語意分塊 |
Embedding相似度斷點 |
語意完整 |
計算量大 |
技術文件 |
| 文件結構 |
按標題/章節切 |
結構完整 |
需解析器 |
Markdown/HTML |
生產級分塊實作
import { RecursiveCharacterTextSplitter } from "langchain/text_splitter";
import { MarkdownTextSplitter } from "langchain/text_splitter";
// 通用文件分塊
const splitter = new RecursiveCharacterTextSplitter({
chunkSize: 512,
chunkOverlap: 64,
separators: ["\n\n", "\n", "。", ".", " ", ""],
});
// Markdown結構化分塊
const mdSplitter = new MarkdownTextSplitter({
chunkSize: 1024,
chunkOverlap: 128,
});
// 帶元資料的分塊
interface ChunkMetadata {
source: string;
page?: number;
section?: string;
chunkIndex: number;
totalChunks: number;
}
async function chunkDocument(doc: Document): Promise<Chunk[]> {
const chunks = await splitter.splitText(doc.content);
return chunks.map((text, index) => ({
content: text,
metadata: {
source: doc.source,
section: extractSection(text),
chunkIndex: index,
totalChunks: chunks.length,
},
}));
}
語意分塊(2026年最佳實踐)
import OpenAI from "openai";
const openai = new OpenAI();
async function semanticChunk(text: string, threshold = 0.85): Promise<string[]> {
const sentences = text.match(/[^。.!!??]+[。.!!??]/g) || [];
const embeddings = await openai.embeddings.create({
model: "text-embedding-3-small",
input: sentences,
});
const chunks: string[] = [];
let currentChunk = sentences[0];
for (let i = 1; i < sentences.length; i++) {
const similarity = cosineSimilarity(
embeddings.data[i - 1].embedding,
embeddings.data[i].embedding
);
if (similarity > threshold) {
currentChunk += sentences[i];
} else {
chunks.push(currentChunk);
currentChunk = sentences[i];
}
}
chunks.push(currentChunk);
return chunks;
}
第二步:Embedding與向量資料庫
Embedding模型選型(2026年6月)
| 模型 |
維度 |
效能(MTEB) |
價格/1M tokens |
中文支援 |
| text-embedding-3-large |
3072 |
68.4 |
$0.13 |
✅ |
| text-embedding-3-small |
1536 |
62.3 |
$0.02 |
✅ |
| bge-m3(開源) |
1024 |
65.8 |
免費 |
✅✅ |
| gte-Qwen2-1.5B(開源) |
1536 |
67.2 |
免費 |
✅✅ |
| Cohere embed-v4 |
1024 |
66.1 |
$0.10 |
✅ |
向量資料庫選型
| 資料庫 |
類型 |
延遲(1M向量) |
特點 |
適用場景 |
| Pinecone |
託管 |
15ms |
零維運 |
快速上線 |
| Weaviate |
開源/託管 |
20ms |
混合檢索 |
通用 |
| Qdrant |
開源/託管 |
12ms |
Rust高效能 |
高併發 |
| Milvus |
開源/託管 |
18ms |
十億級規模 |
大規模 |
| pgvector |
PostgreSQL擴充 |
25ms |
複用PG |
已有PG |
| Chroma |
開源 |
30ms |
輕量級 |
原型開發 |
Qdrant生產級設定
import { QdrantClient } from "@qdrant/js-client-rest";
const client = new QdrantClient({ url: "http://localhost:6333" });
// 建立集合
await client.createCollection("knowledge_base", {
vectors: {
size: 1536,
distance: "Cosine",
},
optimizers_config: {
indexing_threshold: 20000,
},
hnsw_config: {
m: 16,
ef_construct: 100,
},
});
// 索引文件
async function indexDocuments(chunks: Chunk[]) {
const embeddings = await openai.embeddings.create({
model: "text-embedding-3-small",
input: chunks.map((c) => c.content),
});
const points = chunks.map((chunk, i) => ({
id: crypto.randomUUID(),
vector: embeddings.data[i].embedding,
payload: {
content: chunk.content,
...chunk.metadata,
},
}));
await client.upsert("knowledge_base", { points, wait: true });
}
// 向量檢索
async function vectorSearch(query: string, topK = 5) {
const queryEmbedding = await openai.embeddings.create({
model: "text-embedding-3-small",
input: query,
});
const results = await client.search("knowledge_base", {
vector: queryEmbedding.data[0].embedding,
limit: topK,
with_payload: true,
});
return results.map((r) => ({
content: r.payload?.content as string,
score: r.score,
metadata: r.payload,
}));
}
第三步:混合檢索(2026年標配)
向量檢索 + 關鍵詞檢索 + 重排序
import { BM25Retriever } from "langchain/retrievers/bm25";
async function hybridSearch(query: string, topK = 10) {
// 1. 向量檢索(語意相似)
const vectorResults = await vectorSearch(query, topK * 2);
// 2. 關鍵詞檢索(精確匹配)
const bm25Results = await bm25Search(query, topK * 2);
// 3. 倒數排名融合(Reciprocal Rank Fusion)
const fused = reciprocalRankFusion(
[vectorResults, bm25Results],
[0.7, 0.3] // 權重:向量70%,關鍵詞30%
);
// 4. Cross-Encoder重排序
const reranked = await crossEncoderRerank(query, fused, topK);
return reranked;
}
function reciprocalRankFusion(
resultSets: SearchResult[][],
weights: number[]
): SearchResult[] {
const scores = new Map<string, number>();
resultSets.forEach((results, setIndex) => {
results.forEach((result, rank) => {
const key = result.content;
const score = weights[setIndex] / (rank + 1 + 60); // k=60
scores.set(key, (scores.get(key) || 0) + score);
});
});
return Array.from(scores.entries())
.sort((a, b) => b[1] - a[1])
.map(([content, score]) => ({ content, score }));
}
async function crossEncoderRerank(
query: string,
candidates: SearchResult[],
topK: number
): Promise<SearchResult[]> {
const pairs = candidates.map((c) => [query, c.content]);
const results = await openai.chat.completions.create({
model: "gpt-4o-mini",
messages: pairs.map(([q, c]) => ({
role: "user",
content: `判斷以下文件與查詢的相關性(0-10分):\n查詢:${q}\n文件:${c}\n評分:`,
})),
});
return candidates
.map((c, i) => ({
...c,
rerankScore: parseFloat(results.choices[i]?.message?.content || "0"),
}))
.sort((a, b) => b.rerankScore - a.rerankScore)
.slice(0, topK);
}
第四步:生成與引用
帶引用的RAG生成
async function ragGenerate(query: string) {
// 1. 檢索相關文件
const documents = await hybridSearch(query, 5);
// 2. 建構上下文
const context = documents
.map((doc, i) => `[${i + 1}] 來源:${doc.metadata.source}\n${doc.content}`)
.join("\n\n");
// 3. 生成答案
const response = await openai.chat.completions.create({
model: "gpt-4o",
messages: [
{
role: "system",
content: `你是知識庫問答助手。基於以下檢索到的文件回答使用者問題。
規則:
1. 只基於檢索到的文件回答,不捏造資訊
2. 每個陳述必須標註引用來源 [1][2]...
3. 如果檢索結果不足以回答,明確說明
4. 優先使用最新、最相關的資訊
檢索文件:
${context}`,
},
{ role: "user", content: query },
],
temperature: 0.1,
});
return {
answer: response.choices[0].message.content,
sources: documents.map((d) => ({
source: d.metadata.source,
score: d.score,
snippet: d.content.slice(0, 100),
})),
};
}
進階最佳化:查詢改寫與HyDE
// 查詢改寫:將模糊查詢轉為精確查詢
async function queryRewrite(query: string): Promise<string[]> {
const response = await openai.chat.completions.create({
model: "gpt-4o-mini",
messages: [
{
role: "system",
content: "將使用者查詢改寫為3個不同角度的搜尋查詢,提高檢索召回率。輸出JSON陣列。",
},
{ role: "user", content: query },
],
response_format: { type: "json_object" },
});
return JSON.parse(response.choices[0].message.content).queries;
}
// HyDE:假設性文件嵌入
async function hydeEmbedding(query: string): Promise<number[]> {
const hypotheticalAnswer = await openai.chat.completions.create({
model: "gpt-4o-mini",
messages: [
{ role: "system", content: "給出這個問題的詳細答案(即使你不確定)。" },
{ role: "user", content: query },
],
});
const embedding = await openai.embeddings.create({
model: "text-embedding-3-small",
input: hypotheticalAnswer.choices[0].message.content,
});
return embedding.data[0].embedding;
}
生產級部署架構
┌──────────────────────────────────────────────────────┐
│ API Gateway │
│ 認證 │ 限流 │ 快取 │ 日誌 │
├──────────────────────────────────────────────────────┤
│ RAG Pipeline │
│ 查詢改寫 → 混合檢索 → 重排序 → 生成 → 引用 │
├───────────────┬──────────────────────────────────────┤
│ Embedding │ 向量資料庫 │ 關鍵詞索引 │
│ API/本地模型 │ Qdrant/Pinecone │ Elasticsearch │
├───────────────┴──────────────────────────────────────┤
│ 文件擷取Pipeline │
│ 解析 → 分塊 → Embedding → 索引 → 元資料儲存 │
├──────────────────────────────────────────────────────┤
│ 監控與評估 │
│ 檢索命中率 │ 答案準確率 │ 延遲 │ 成本 │
└──────────────────────────────────────────────────────┘
RAG評估指標
| 指標 |
說明 |
目標值 |
| 檢索命中率 |
查詢相關文件被召回的比例 |
> 90% |
| MRR |
首個相關文件的平均排名倒數 |
> 0.8 |
| 答案準確率 |
答案與ground truth一致的比例 |
> 85% |
| 引用準確率 |
引用來源與答案內容匹配的比例 |
> 95% |
| 端到端延遲 |
從查詢到答案的總時間 |
< 2s |
| 拒答率 |
正確拒絕無法回答的問題的比例 |
> 80% |
2026下半年趨勢
| 趨勢 |
說明 |
| GraphRAG |
知識圖譜+向量檢索,處理多跳推理 |
| ColBERT晚期互動 |
更精細的token級匹配,檢索精度提升20% |
| 多模態RAG |
圖表、圖片、影片也能檢索和引用 |
| 自適應分塊 |
根據查詢動態調整分塊策略 |
| RAG快取 |
相似查詢複用檢索結果,降低延遲和成本 |
總結
- 分塊是RAG的地基 — 語意分塊 > 結構分塊 > 固定分塊
- 混合檢索是2026年標配 — 向量70% + 關鍵詞30% + 重排序
- 引用是RAG的靈魂 — 每個答案必須可追溯到原始文件
- 評估是持續最佳化的前提 — 檢索命中率、答案準確率、引用準確率
RAG不是「檢索+生成」這麼簡單,而是一個需要精心設計每個環節的系統工程。分塊策略、檢索方法、重排序、查詢改寫——每個環節都決定了最終答案的品質。