上一篇文章,我們討論了 LLM 的知識來源、Token 與 Context,也確定 RAG 不是把整個知識庫塞進 Prompt,而是先找到與問題相關的內容,再交給模型產生回答。今天就要開始處理這個「知識庫」本身,決定文件要如何保存,才能讓後續的清理、切分、搜尋與來源引用都有一致的基礎。
知識庫聽起來像是一個很大的系統,但在這個系列的第一版中,它可以從一批整理良好的 Markdown 文件開始。Markdown 同時保留人類容易閱讀的文章結構,也能用程式解析標題、段落、清單與程式碼區塊。這些文件還可以直接放在專案中版本控制,當內容變更時,能夠追蹤是哪一份文件、哪一個版本發生變化。
在建立資料夾之前,必須先決定一份文件代表什麼。若一個檔案同時包含 Spring Security、JPA、資料庫索引與部署設定,未來搜尋某個問題時,很可能取得一大段互不相關的內容。相反地,如果每個檔案只記錄一個主要概念或一個彼此緊密相關的主題,後續的文件切分與搜尋就比較容易控制。
因此,本系列會把一份 Markdown 文件視為一個可以被追蹤的知識單位。它不一定只能有一個段落,但應該有清楚的主題與邊界。例如「SecurityFilterChain 的角色與設定方式」可以是一份文件,而「Java 後端開發所有相關知識」就太過寬廣。文件太大會增加切分與引用的難度,文件太小則可能失去必要的上下文。
今天先處理原始文件的組織方式,還不急著把內容切成搜尋片段。原始文件需要保持可讀、可修改與可追溯,搜尋用的 Chunk 則是之後根據系統需求產生的資料,會在 Day 6 再詳細討論。
如果只保存正文,未來雖然可以做關鍵字搜尋,卻很難回答「這段內容從哪裡來」或「它適用於哪個版本」。因此,每份文件除了正文之外,也需要保存一些 Metadata,也就是描述文件的資料,例如文件識別碼、標題、主題、來源、語言、版本與更新時間。
這些欄位會直接參與後續流程。文件識別碼可以讓搜尋結果和原始檔案建立穩定關係;來源網址可以支援回答引用;主題與標籤可以協助過濾搜尋範圍;版本欄位則能避免把不同版本的設定混在一起。
本系列會使用 Markdown 常見的 YAML Front Matter 保存 Metadata,並讓正文維持一般 Markdown 格式。以下是一份技術文件的概念:
---
id: spring-security-filter-chain
title: SecurityFilterChain 的角色與設定方式
source_type: self_written
source_url: null
language: zh-TW
topic: spring-security
version: "6.x"
tags:
- spring
- spring-security
- java
status: published
updated_at: 2026-07-29
---
# SecurityFilterChain 的角色與設定方式
SecurityFilterChain 負責定義請求通過 Spring Security 時會經過哪些安全性處理。
Front Matter 和正文之間用分隔線區隔。人類閱讀時,可以直接看到文章內容;程式讀取時,則能先解析上方欄位,再取得下方正文。未來即使換成資料庫或向量資料庫,也能把這些欄位轉換成 Payload 或 API 回應中的來源資訊。
id 是文件的穩定識別碼,應該避免因為檔名或標題變更而跟著改變。搜尋結果與引用資料都可以使用它,讓系統知道目前顯示的段落屬於哪一份原始文件。title 則是給人閱讀的名稱,回答引用來源時通常會直接使用。
source_type 和 source_url 用來說明資料來源。資料可以是自己撰寫的筆記,也可以是具有適當使用條件的公開文件;如果內容是根據官方文件整理而來,保留原始連結仍然有助於日後查證。引用機制要可信,前提是每份文件都先交代清楚自己的出處。
language、topic、version 與 tags 則描述文件適用的範圍。未來可以用它們過濾搜尋條件,例如只搜尋繁體中文內容、只搜尋 Spring Security,或只取適用於特定版本的文件。status 與 updated_at 則能協助管理草稿、正式與過期資料。
除了文件內容,檔案位置同樣會影響維護方式。第一版可以採用以主題分類的簡單結構:
knowledge-base/
├── spring-security/
│ ├── security-filter-chain.md
│ └── authentication.md
├── natural-language-processing/
│ ├── token.md
│ └── text-cleaning.md
└── rag/
├── retrieval-augmented-generation.md
└── chunking.md
資料夾分類主要提供人類瀏覽與管理使用,不能把它當成唯一的分類依據。文件可能同時屬於多個主題,也可能因為內容調整而需要移動位置,因此系統真正使用的分類資訊仍然應該放在 Metadata 中,檔案路徑則保持簡單。原始資料要方便修改,衍生資料才交給程式產生。
建立格式之後,還不能代表知識庫已經準備完成。文件如果有重複段落、缺少版本、混用不同主題,或把過時設定和目前設定放在一起,搜尋系統仍然可能找到錯誤內容。RAG 能夠讓模型參考文件,但不能自動保證文件本身正確。
因此,每份文件至少要能回答幾個問題:這篇內容在說什麼?適用哪個主題或版本?資料來自哪裡?最後一次確認或更新是什麼時候?如果這些問題都無法回答,之後即使搜尋與 Embedding 做得很好,也很難建立可信的引用。
今天先不處理空白、標點、重複內容與特殊格式,因為那是下一篇「繁體中文文件清理」的工作。這一篇的重點,是先建立一個穩定的資料契約,讓程式知道每份文件應該包含什麼。
知識庫不是把檔案隨意放進資料夾,而是替文件建立一致的結構與可追溯的來源。這次我們選擇 Markdown 作為原始格式,使用 YAML Front Matter 保存識別碼、標題、來源、主題、版本與更新時間,再用簡單的資料夾結構協助人類管理內容。
有了這個基礎,後續的資料清理、文件切分、關鍵字搜尋與向量索引才有可靠的起點。下一篇,我們會正式處理繁體中文文件中的換行、編碼、空白與全形字等格式雜訊,並確保程式碼區塊在清理過程中完整保留,看看一份適合人閱讀的 Markdown 文件,如何變成適合搜尋系統處理的文字資料。