RAG生產級完全指南:2026年檢索增強生成從原理到實戰,建構企業知識庫AI

技术架构

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快取 相似查詢複用檢索結果,降低延遲和成本

總結

  1. 分塊是RAG的地基 — 語意分塊 > 結構分塊 > 固定分塊
  2. 混合檢索是2026年標配 — 向量70% + 關鍵詞30% + 重排序
  3. 引用是RAG的靈魂 — 每個答案必須可追溯到原始文件
  4. 評估是持續最佳化的前提 — 檢索命中率、答案準確率、引用準確率

RAG不是「檢索+生成」這麼簡單,而是一個需要精心設計每個環節的系統工程。分塊策略、檢索方法、重排序、查詢改寫——每個環節都決定了最終答案的品質。

本站提供瀏覽器本地工具,免註冊即可試用 →

#RAG#检索增强生成#向量数据库#Embedding#大模型#知识库#LangChain#LlamaIndex