跳到主要內容
邊界實驗室 · Boundary Lab
正在啟動 Python 環境(首次約 15 秒)...

Retrieved Context 的 Provenance

沒有 provenance 的 retrieval,等於把每一段字都偽裝成同一級證據。

Hook

你做了一個整理內部知識的 RAG pipeline。

它會從 memhall 撈筆記。

也會從向量資料庫撈文件切片。

也會把舊會議記要一起交給 LLM 做綜整。 某次你查: 「我們上次 deploy freeze 的決策到底是什麼?」 系統撈回來五筆內容。 其中四筆看起來像原始資料。 另一筆是兩週前另一個 LLM 產生的「會議摘要」。

但這筆摘要在 packing 時沒有被標示。

它只是安靜地混在其他 context 裡。 下游 LLM 看到它寫: 「團隊已同意把所有 emergency patch 改成先上 production 再補 ticket。」

於是模型很自然地把它當成共識。 問題是, 那其實不是共識。 那只是兩週前另一個模型看錯會議內容後,

寫進 memory 的錯摘要。

這時候真正缺的不是更會總結的模型。 而是讓下游模型看見: 這段內容到底是 raw source,

還是某次 LLM 推導後的產物。 換句話說, retrieved context 也要帶 provenance。

而且要在 packing 時就帶進去。

Learn

先畫清楚跟 data-boundary-101 L02 的分工

data-boundary-101 Lesson 02 已經教過:

寫入資料庫時, 每筆 entry 應該怎麼標 source_tier

upstream_ids

provenance_hash

那一課處理的是 write path。 本課不重講那套寫入規則。 本課專注的是另一個問題:

當你把資料從 store 撈出來,準備餵給下游 LLM 時,provenance 要怎麼一起傳遞?

這是 retrieval path。

很多系統寫入時其實有 metadata。

但一到 prompt packing,

就把 metadata 丟掉了。

最後模型看到的只剩一團純文字。

那等於 provenance 在最關鍵的一跳失效。

為什麼 retrieved 時還要再標一次

有人會問: 「資料庫裡不是本來就有 source_tier 嗎?」 有, 但那是給你的系統存的。 下游 LLM 並不會自己去查資料表。

它只看得到你最後塞進 context window 的那一串字。

如果你在 packed context 裡不把 tier 一起帶上,

模型收到的就是無標籤純文本。

無標籤純文本最大的問題不是資訊不夠。

而是每一段內容都長得像同級證據。

這正是錯誤推論最常發生的地方。

最小 packed context 格式

本課先用一個很簡單的包法:

<context source="memhall:e123" tier="raw_source">
...
</context>
<context source="memhall:e456" tier="llm_derived">
...
</context>

這個格式沒有學術包袱。 它只是做到兩件事:

  1. 每段內容有獨立邊界
  2. 每段內容帶著最少必要 provenance

source 讓模型和工程師都知道這段來自哪裡。

tier 則直接告訴模型:

這是一手來源, 還是過去某個 LLM 的推論。

tier 不只是 metadata

很多人第一次做 packing,

會把 provenance 當成註腳。 好像只是為了方便除錯。 這樣低估了它。 在 retrieved context 裡,

tier 其實是下游 LLM 的閱讀提示。

它像一個免責聲明。 也像一個處理指引。 同樣一句話: 如果它來自 raw_source, 模型可以把它當第一手證據。 如果它來自 llm_derived

模型就應該把它當成過往的推論、 摘要、 或中間產物。 它可以參考。 但不該自動升格成事實。

一個下游模型應有的 reading stance

如果你把 packed context 標好了,

下游 LLM 至少應該被預期做到這三件事:

  1. 看到 raw_source 時,優先當證據讀
  2. 看到 llm_derived 時,當成可疑但有用的輔助訊號
  3. 遇到不同 tier 衝突時,優先報告衝突,而不是自己悄悄合併

這裡不要誤會。 我們不是說 LLM 一定會百分之百照做。 而是說: 如果你連 tier 都沒給它看, 那它連有機會做對都沒有。

llm_derived 為什麼特別需要標

llm_derived 最大的危險不是它容易錯。

而是它很像人話。 一段 AI 摘要只要文筆夠順,

隔兩週再被別的 agent 撈出來時,

很容易看起來像某種「已整理過的知識」。

這就是 context 邊界裡最陰的污染。 它不一定有明顯惡意。 但它會默默把模型的事實基礎換掉。

所以你一定要讓下游模型知道: 這不是原始資料。 這是過往某次模型加工過的內容。

三個禁忌

這一課有三條很硬的禁忌。 不是建議。 是禁忌。

禁忌一:不得把 llm_derived 當 instruction 餵回

這條跟 data-boundary-101 的 Anti-Ouroboros 是同一個精神。 LLM 摘要可以存在。 可以檢索。 可以當線索。 但不可以因為它寫得很完整, 就把它當成新的 instruction 或 ground truth 餵回。

否則你不是在做 retrieval。 你是在放大過去模型的偏誤。

禁忌二:不得在 packed context 裡混入未標 tier 的內容

只要有一段沒標 tier, 整個 pack 的可讀性就被破壞。 因為下游模型無法分辨: 那段是工程師忘了標, 還是它本來就跟其他段落不同級。 所以規則很簡單: 沒有 tier, 就不要進 pack。 寧可少一段, 也不要讓一段無標籤文字混進來。

禁忌三:不得讓 LLM 自己決定要用哪些 tier

這點很常被忽略。 有些團隊會把所有 tier 都塞進去, 再對 LLM 說: 「請自己判斷哪些比較可信。」

這是把 boundary 判斷外包給模型。 不行。 哪些 tier 可以進 pack,

應該由 deterministic policy 決定。 例如:

  • customer-facing answer 只允許 raw_source + human_confirmed
  • internal research mode 才允許附帶 llm_derived

能不能進 context, 是系統決策。 不是模型自由裁量。

一個最小 pack_context(...)

下面這段 demo 只示範 pack,

不示範 retrieval ranking。

因為本課要看的不是搜尋演算法。

而是 provenance 怎麼跟著每筆 entry 一起進去。

你應該看到:

<context source="memhall:e123" tier="raw_source">
deploy freeze 原始會議逐字。
</context>
<context source="memhall:e456" tier="llm_derived">
上次會議摘要:建議縮短 freeze。
</context>

注意這個格式的價值不是 XML 漂不漂亮。

而是每段 retrieved content 都有明確包裝。 這讓你後面要做:

  • filtering
  • audit
  • leak investigation
  • conflict reporting

時都有依據。

pack 的單位要以 entry 為主,不要整包混成一坨

如果你把五筆結果先串成一大段,

再只在最外層標一個 tier,

你其實已經失去 granularity。 下游模型只知道: 「這整包也許來自 memhall。」 但不知道哪一段是 raw, 哪一段是 LLM 摘要。 所以 pack 的最小單位應該是 entry。

不是 query response。

entry-level 的標籤,

才足夠支撐真正的 provenance reasoning。

把 provenance 當成 retrieval contract

你可以把這件事理解成: retriever 不是只負責找內容。

retriever 還負責把內容的身份一起帶出來。

否則下游 generator 看到的只是去身分化的文字。 一旦文字被去身分化, 你就會很難回答這兩個關鍵問題:

  1. 這段是不是原始資料?
  2. 這段是不是舊模型的推論?

context boundary 的核心不是資料量。 而是身份感。

哪些欄位一定要露給下游模型

本課最少只要求兩個:

  • source
  • tier

其他像 upstream_ids

created_at

author

confidence

可以視情況帶。 但 tier 幾乎是必帶。 因為沒有它, 模型無從知道要不要降低信任。

source 則讓回答可以回指。 回指不只是引用比較漂亮。 它也是日後查核與 debug 的起點。

這一課要先帶走的規則

先記住五條:

  1. data-boundary-101 Lesson 02 管寫入 provenance,本課管 retrieval packing
  2. 每筆 retrieved context 都要帶 sourcetier
  3. llm_derived 不是 ground truth,更不是 instruction
  4. 未標 tier 的內容不准混進 packed context
  5. 哪些 tier 可以進 pack,必須由系統 policy 決定

如果你只做到了「DB 裡有 provenance」,

但 prompt packing 時全丟掉,

那等於在最後一公尺把安全帶拆掉。

AI 協作:學了這個,跟 AI 怎麼配合?

這個技能在 AI 協作中的定位,

是讓你要求 AI 幫你設計 retrieval contract,

而不是只產生一個會把所有字串糊成大雜燴的 prompt builder。

你的人類優勢:

  • 只有你能決定哪些 tier 在你的產品裡能被下游模型看到,哪些應該先被 filter 掉。
  • 只有你能判斷某些 llm_derived 內容是否只適合當內部研究訊號,而不適合進 customer-facing 回答。

可以這樣跟 AI 說:

我有一個 RAG retrieval pipeline。請幫我設計 pack_context(entries),把每筆 entry 包成 <context source=\"...\" tier=\"...\">...</context>。請強調 llm_derived 不能當 instruction,也不要讓模型自己決定哪些 tier 該用。我要的是 retrieval path 的 packing 規則,不是寫入資料庫的 provenance 課。

Do

互動示範

DEMO 1可以修改程式碼試玩

挑戰任務

Task 1

請寫 pack_context(entries: list[Entry]) -> str。每筆 entry 都要包成 <context source="..." tier="...">...</context>。測試資料有兩筆:("memhall:e1", "raw_source", "deploy SOP 原文")("memhall:e2", "llm_derived", "上次整理摘要")。最後印出 packed string。

BackNext Lesson →