接地答案
文件如何成為代理可回答的內容——分塊、上下文標頭、查詢重寫與相關性門檻。
「來自您文件的回答」很容易宣稱,卻難以做好。本頁說明平台在檔案上傳與有根據的回答之間實際上做了什麼,包含通常未被提及的部分。
從檔案到片段
擷取:每份文件一次
檔案被解析為文字 — 對於包含圖形的文件,也會讀取圖形(見下文)。此階段進行格式特定的提取;所有後續步驟看到的都是純文字。
分割為以 token 為單位的片段 — 但文字是依字元分割的,因此兩者之間的比率是從文件本身的腳本估算而來。若將拉丁語系的比率套用於中文,會產生比預期大數倍的片段。
每個片段的前綴為其文件標題(以及可選的生成註記),僅供嵌入使用。儲存的文字不變;標頭的存在是為了讓向量反映該段落屬於何物。
將片段及其標頭嵌入向量。
加密儲存並限制於該空間內。從這裡可以檢索 — 但僅限於該空間內。
在文件上傳時執行。下方的查詢路徑在每次提問時執行。
查詢:每次提問一次
客戶提出問題 — 往往是只有在語境中才有意義的後續問題:「那一個的費率是多少?」
如果問題取決於之前的對話輪次,它會被重寫為一個獨立的問題,僅供檢索向量使用。模型仍會收到客戶的原始措辭,任何失敗都會回退到原始措辭。
使用與片段相同的模型嵌入(可能已重寫的)問題。
餘弦最近鄰演算法,依距離排序,在資料庫層級限制於該最終使用者的空間,而非透過應用程式過濾器。
超過最大距離的匹配結果會被捨棄。返回的段落少於請求的數量是正確的結果 — 填充至固定數量是檢索系統產生流暢但錯誤答案的方式。
倖存的所有內容被解密並送給模型。如果沒有任何倖存內容,代理程式會表示它沒有答案。
門檻是決定代理程式是否回答的步驟。
上傳的文件被解析為文字,分割為片段,嵌入並加密儲存。分割過程中的兩個細節比它們看起來更重要。
片段大小以 token 為單位測量,但文字是依字元分割的 — 因此平台必須在兩者之間轉換,且轉換取決於語言。大約每 token 4 個字元的拉丁語系比率對於中文、日文和韓文來說完全錯誤,因為在這些語言中,單一字元更接近一個完整的 token。使用單一全域常數意味著 CJK 文件會獲得比預期大數倍的片段:片段超出其大小設定的上下文,且檢索會返回大段文字。
因此,分割器會從文件本身的內容中估算比率,根據文本中 CJK 的比例在 CJK 和拉丁語系比率之間進行插值。一份混合中文/英文的合約會落在兩者之間,而不是任一極端。
段落會盡可能保持完整。 片段以段落為單位累積,直到達到目標大小;只有本身過大的段落才會被硬性分割。連續片段之間的重疊量是可配置的,將前一個片段的尾部帶向前方,以便跨越邊界的事實仍可從兩側檢索。
預設值為平台設定中的 chunk_target_tokens 和 chunk_overlap_tokens。它們是可針對租戶調整的,而非固定保證 — 正確的大小取決於您的文件。
圖形,而不僅是文字層
大多數文件提取僅止於文字層。上傳數據表、安裝手冊或報告,典型的管線會提取文章,並靜默地丟棄所有繪製而非鍵入的內容 — 接線圖、電路板佈局、頁面中間的圖表。檔案被「處理」了;它說的一半內容從未讀取過。詢問「CPU 風扇在哪個標頭上」,答案不在索引中,因為它只存在於圖片中。
此平台也會讀取這些內容。
- 掃描或僅含圖片的 PDF — 完全沒有文字層 — 會逐頁渲染並由視覺模型轉錄,因此拍攝的合約或掃描的表格會變成可搜尋的文字。
- 混合文件 — 文字層 加上 圖形 — 是其他系統遺漏的情況。帶有實際圖形的頁面會由視覺模型渲染並描述,描述內容會合併到文件的文字中,以便與文章一起分塊、嵌入並可檢索。電路板佈頁會返回連接器名稱及其位置;圖表會返回趨勢和數字。
- Word 檔案中的嵌入圖片 會從文件中提取,並以相同方式進行描述。
困難之處不在於呼叫視覺模型 — 而在於不在同一裝飾性側邊欄上呼叫四十次。手冊在每一頁重複標誌和頁面邊框;描述這些內容將純粹是成本與純粹的雜訊。因此,圖形檢測區分真正的圖表(許多向量路徑、大照片、圖片拼貼)與模板裝飾(相同內容的圖片,在頁面間重複出現),僅發送帶有資訊的頁面。
描述圖形使用視覺模型,因此成本比純文字提取更高。兩個防護措施:圖形密集的文件在產生高昂費用前會要求確認,且圖片描述支出會顯示為其自己的行 — vision_image — 在用量中,因此您總能看見錢花在哪裡。
上下文標頭
單獨嵌入的片段會遺失它來自特定文件的事實。「當借款人違約時,第 7.2 條適用」在查詢為「如果我錯過橋接產品的付款會發生什麼事」時檢索效果不佳 — 該片段從未說明它屬於哪個產品。
在嵌入之前,每個片段的前綴為上下文標頭 — 文件標題,以及可選的 LLM 生成情境註記 — 以便向量反映段落及其所屬內容。儲存的文字不變;僅嵌入輸入攜帶標頭。
查詢重寫:大多數系統跳過的部分
檢索品質通常被討論為排序問題。通常並非如此 — 通常查詢根本沒有包含任何資訊。
客戶詢問「那一個的費率是多少?」。代名詞指的是兩輪之前提到的內容。嵌入該句子會產生一個與任何特定內容都無關的向量,且該輪次的檢索接近隨機。沒有任何重排序能修復它,因為信號從未存在。
因此,在嵌入之前,取決於先前語境的後續問題會被重寫為一個獨立的問題。三個刻意選擇:
- 它偏向過度觸發。 參考表達式的正則表達式決定是否嘗試重寫。不必要地觸發僅耗費一次廉價呼叫,且重寫後的獨立問題會原樣返回;未能觸發則會完全損失該輪次的檢索。
- 它重寫為更完整的句子,而非關鍵字。 嵌入模型是針對句子訓練的。簡化為關鍵字會遺失關係(「借款人的責任」與「貸款人的責任」收斂為同一個向量)和否定(「哪些案例不需要擔保」)。
- 它僅影響檢索向量。 送給模型的訊息始終是客戶的原始措辭。重寫永不進入提示、對話歷史或儲存 — 且任何失敗都會回退到原始句子,因此最壞情況與舊行為完全相同。
搜尋,以及相關性門檻
查詢向量與限制於該最終使用者空間的片段進行餘弦距離比較。此空間限制不是可能被遺忘的應用程式層級過濾器 — 它是在資料庫層級強制執行的。
然後依最大距離過濾頂部匹配結果。這是區分有用代理程式與自信代理程式的部分:
接待處週一至週五 9:00 至 17:00 有人值班。
預約至少提前一個工作日進行。
24 小時內取消將收取一半費用。
由兩位合夥人於 1998 年創立,現為九人團隊。
Illustrative. 虛構診所的範例距離。實際值取決於您的文件和嵌入模型 — 這裡沒有任何測量值,且門檻可由租戶設定。
返回少於請求數量的片段是正確的結果,而非不足。 如果您的知識庫中沒有任何相關內容,代理程式將得不到任何內容並如此表示,而不是被交付最不相關的段落並在其間編造橋樑。將結果填充至固定數量是檢索系統產生流暢、看似有來源但錯誤的答案的方式。
過濾器是在排名獲取後應用,而非在 SQL 謂詞中 — 結果已經按距離排序,因此結果相同,但這保持了清晰的索引掃描,而非退化為全表後過濾器。
當檢索成功但仍失敗時
相關性門檻捕捉了沒有任何內容足夠接近的情況。有一個更難的情況它無法看見:所有段落都通過了門檻,主題正確,且問題所關於的那個事實不在任何段落中。
在該站點自身的售前代理程式上進行測量。詢問*「如果我處於 Starter 方案且我的用量每月增長 30%,六個月後我會付多少?」*,檢索返回了三段內容:Starter 方案頁面、token 使用指南和服務條款。所有都相關。但沒有任何一段說明價格 — 方案頁面是一個關於該方案適合誰的頁面。給定一個標題為「Starter」且其中沒有數字的文件,模型提供了一個數字。在五次運行中,它產生了 $5、$250、$99、$0 和 $29,每個都附帶引用標記。實際數字是 $49。
沒有任何失敗以可檢測的方式發生。距離很好,因此沒有檢索遺漏可報告。引用指向的段落確實被檢索了。只有答案是錯誤的。
第二次傳遞,在程式碼中決定
因此,在第一次搜尋之後,對返回的內容提出兩個問題 — 兩者均可透過字串比較回答,均未委託給模型:
被詢問的事物甚至被提及了嗎? 問題中的專有名詞,加上從您知識庫中文件的標題中提取的術語 — 一個由某人策劃的詞彙,而非我們猜測的詞彙。如果某個術語出現在問題中,但未出現在任何檢索段落中,則單獨搜尋該術語。
被詢問的那一面存在嗎? 這是第一次檢查遺漏的一半,也是上述測量所落在的一半:Starter 確實 在檢索文本中;價格則沒有。因此,每個問題也會與它詢問的內容進行匹配。其中一些具有硬性格式 — 價格帶有貨幣符號,持續時間帶有時間單位,聯絡資訊看起來像電子郵件或 URL — 且真正涵蓋該側面的內容幾乎從不遺失格式。其他(退款、合規、試用、整合)沒有格式,因此信號是主題詞本身,以每種語言寫出,而非留給向量相似性來橋接。
當任一檢查未達標時,派生術語會被再次搜尋,結果會合併。僅一次,永不迴圈。誤報僅耗費一次向量查詢 — 無額外模型呼叫,無額外往返 — 而遺漏則會導致帶有引用標記的虛構數字。
- Starter — 適合誰一個小型、定義明確的業務 — 幾十個客戶。無價格
- Token 使用 — 什麼算數您的儀表板將使用情況顯示為兩種顏色,提示和完成。無價格
- 服務條款您可以按公布費率提前購買額外 token。無價格
兩件值得坦誠相告的事。這是防止虛構的門檻,而非正確性的證明 — 它注意到問題的一面未被代表,而非答案正確。且它並不需要知識庫實際包含該事實:使上述範例在生產環境中修復的修復措施也是給予每個方案一份簡短文件以說明其價格,因為關於增長和超額費用的長問題每次都會擊敗單一合併定價表。
當問句點名了條號
語意相似度是核對引證時用錯了的工具。「第 18 條」「Part 9」「ISO 9408」——它們不表達意思,它們指認對象。一張標準表裡相差一個數字的兩行,在向量看來是同一句話。
所以問句裡的標識會被抽出來當作文字去查,而帶著被點名那個標識的片段會被釘在語意排序之前,並且語意排序不許把它挪走。最後這半句才是重點,值得直說,因為這裡曾經不是這樣:那層保護寫在註解裡、從來沒有在程式碼裡實現,於是重排把釘住的片段又排了下去。在一張相鄰行只差一個數字的標準表上實測:唯一寫著被問那一部分的那行,關掉重排排第 1,開著重排連前 20 都進不去—— 而回答用的是相鄰那一行。
把標識當身份而不是意思,會帶來兩個後果:
當這個標識出現的地方多到上下文裝不下時,引證不再被整組丟棄。 以前是丟的:如果「第 18 條」命中的片段超過能放下的數量,整組就按「樣本不是答案」的理由扔掉。這句話對「按檔案順序取前幾個」成立,對「取離問題最近的幾個」不成立。實測的一例裡按後一種取法排完,能回答它的兩片餘弦距離是 0.27 和 0.31,雜訊從 0.51 開始——那道坎自己說明了該在哪裡停,不必預先猜一個閾值。而當距離是一道平滑的斜坡而不是一級台階時,一片都不救:分布均勻說明這些片段彼此沒有分別,那才真的是樣本。
向量距離最近的那一片一定會被帶進上下文。 重排可以重新排序,但不許把最接近的那一片丟掉。實測中重排把它擠出上下文的比例是七次裡有一次,而在人工核對的樣本裡,被擠掉的那一片有時是 唯一能回答這個問題的。它是補進去的,不是替換——不會為了給它騰位置而擠掉別的片段。
當模型自己要更多材料
有時候擺在模型面前的片段定不了這道題,於是它不作答,而是自己去查知識庫。這個動作就是訊號。 它讀完了手上的材料並且伸手要更多,所以它需要的是下一批,而不是同一批——後者正是樸素實作會回傳的東西,而那等於什麼也沒告訴它。
下一批本來就在手上。檢索取回的候選池比它交出去的更寬,排一次序,只交出最前面的一段,剩下的就留在這一刻用。把它交出去不需要第二次檢索、第二次排序,也不需要第二次相關性評估——只多一次它本來就要打的模型呼叫。第一版實作確實重跑了檢索,在一道題上把 22 秒變成了 71 秒;一次「再看一眼」的代價是這樣量出來的,不是估出來的。
每一輪只發一次。之後重查恢復原樣,因為「再查還是這些」本身也是一個訊號,拿掉它模型就會一直挖下去。
解密發生在最後
片段內容以每空間加密儲存。僅實際匹配的片段會被解密,並載入該租戶和用戶的密碼 — 檢索在向量上操作,且純文字僅出現在即將使用的段落中。
數字不是意義
上述一切都是機械裝置。本節是您控制的內容,它比本頁上的任何設定更能推動結果。
檢索匹配意義。單獨的值攜帶的意義非常少,因此事實可以坐在您的文字中卻仍不可達 — 靜默地,因為搜尋會繼續返回某些內容。
這行文字出現在真實客戶目錄的 1,500 個片段中的 1,480 個中:
Reading level: 1 · Age: 5 · Words: 1951而「哪些書適合剛開始獨立閱讀的孩子」返回了一本關於音樂神童的書。1 與 beginner reader(初學者讀者)的 resemblance 不像一個詞與另一個詞的 resemblance。
在該記錄旁添加一句話修復了它,在該記錄上進行測量:
Reading level: 1 · Age: 5
Suitable for around age 5, for children just starting to read on their own.| 查詢 | 之前 | 之後 |
|---|---|---|
| which books suit a child just starting to read on their own | 0.625 | 0.540 |
| 什么书适合刚开始自己读的孩子 | 0.626 | 0.552 |
| beginner reader age 5 | 0.598 | 0.498 |
越低越接近,且 — 見下文 — 兩個無關的段落在此模型上位於約 0.61。因此最後一行從「僅比隨機稍好」變為真實匹配,且增益跨語言保持。
一般規則:如果問題會由屬性而非文章回答 — 價格、日期、等級、可用性、庫存 — 請以文字形式以及欄位形式將其放入。 結構化值用於過濾;檢索尋找寫下的內容。
一件不值得努力的事,因為我們測量過:匯出經常重複自身(summary 和 description 攜帶相同的文章)。移除重複將檢索距離改變了 +0.002 across 60 records — nothing。嵌入是一個方向,而非預算,重複文字不會耗盡它。
距離不是分數,且無法跨模型比較
在閱讀任何距離數字之前,還有一件值得知道的事。嵌入模型將文字壓縮到一個狹窄的錐體中,且錐體的寬度因模型而異。在此平台今天運行的模型上,兩個完全無關的段落相距約 0.61 — 因此 0.52 的命中是強匹配,而非弱匹配,且 0.5 在任何地方都不是有意義的截止值。
兩個實際後果:
- 將距離與無關基準進行比較,切勿與您從某處記憶的數字進行比較。控制台中的知識星圖在其刻度上標記該基準,正是出於這個原因。
- 較長的問題比關鍵字檢索效果更好。 單一字詞與 900 字元段落的對比是一個弱信號,即使該段落 literally 關於該字詞;完整問題是一個更接近的匹配。真實用戶撰寫句子,這是好情況 — 但如果您使用一字詞查詢進行測試,預期數字會比系統實際表現更差。
檢索無法做到的事,以及回答這些問題的其他方法
上述所有内容都是關於尋找回答問題的文段。三種類型的問題根本不是關於文段,且沒有任何調校能使相似性搜尋回答它們:
- 計數 — 「你們有多少」、「多少是非小說類」
- 數值過濾 — 「哪些少於 200 字」、「介於 1000 和 2000 之間」
- 分組 — 「每類有多少」、「哪位作者出現最多」
這些以容易遺漏的方式失敗。詢問「有大約 500 字的嗎」,僅有向量搜尋的代理程式將報告其前幾個中碰巧出現的記錄 — 關於四份文件的真實陳述,被呈現為關於整個集合的陳述。
結構化索引
因此,知識庫可以攜帶第二個小表格,與向量並列:每份文件一行,由文件已包含的欄位構建。值被逐字元複製 — 沒有生成,沒有重寫。
有了它,代理程式選擇適合問題的 tool:
| 問題 | 由...回答 |
|---|---|
| 「關於恐龍的任何事?」 | 向量搜尋 |
| 「你們有多少?」 | 表格 |
| 「關於恐龍,適合五歲兒童」 | 表格過濾,向量搜尋排名 |
| 「連結是什麼?」 | 表格,精確引用 |
欄位是通過閱讀幾份您的文件提出的,然後與整個集合進行驗證:僅在五分之一文件中找到的欄位會被捨棄並報告,因為在其上過濾會靜默地省略其餘部分。建立或更改索引不會重新嵌入任何內容 — 值從已儲存的文字中讀出 — 因此它不會干擾已經運作的檢索。
共享無機器可讀標頭的文件不會獲得索引,平台會如此表示,而非建立一個值各不相同的表格。這不是需要繞過的限制:這樣的表格無法有意義地計數或分組,擁有它只會引發它回答不佳的問題。
為什麼答案中的連結過去屬於錯誤的項目
同一個表格修復了第二個更安靜的失敗。
檢索返回片段,但標題、產品代碼、連結和圖片位於文件標頭中 — 即,在片段 1 中,而回答問題的段落可能是片段 7。因此,模型收到來自三到四個文件的四到五個片段,並必須弄清楚哪個連結屬於哪個標題。
當它弄錯時,看起來沒有錯誤。連結是真實的,它會開啟,圖片會渲染 — 但它屬於不同的項目。在 4,500 份文件的目錄中,20 個測試答案中有 11 個將標題與另一份文件的連結配對。
您標記為精確的欄位 — 連結、圖片、標識符 — 現在完全不會顯示給模型。它收到一個佔位符,寫下佔位符,平台在輸出時替換儲存的值。模型無法誤打它從未見過的地址。相同的 20 個問題返回 20 次正確。
哪個連結是要發送給客戶的連結是一個您的數據未陳述的事實,因此您自行命名這些欄位;其餘由為您提出。更多內容請見 結構化索引。
當您的材料確實沒有答案時
有時誠實的答案是「這不在您的材料中」,有時這是有用對話的終點。公共來源後備是一個可選的、每個代理程式的替代方案:當檢索為空時,代理程式可以搜尋網路,閱讀它找到的一頁,並從中回答。
除非您開啟它,否則它處於關閉狀態,且當它開啟時,有三件事是真實的。
閱讀頁面是其中的一部分,而非額外步驟。 搜尋結果是一個標題和兩行摘要,且重要的數字 — 有效期、費用、截止日期 — 通常僅在正文中。我們評估集中的一頁在摘要中陳述「有效期五年」,而*「續期前:9 個月」*僅在頁面本身中。僅給摘要,模型有提示但沒有事實,並從記憶中填補空白。因此一個開關同時啟用搜尋和閱讀;僅啟用搜尋是可測量的最差配置,而非更保守的配置。
搜尋而不閱讀不是允許的結果。 如果代理程式搜尋然後在未開啟頁面的情況下回答,平台會要求它在交付答案之前回去閱讀一頁。這不僅是學術上的區別:詢問誰目前運行日本的 PMDA,僅摘要產生了自信的錯誤名稱;閱讀頁面後同一問題產生了正確名稱。
來自公共頁面的任何內容都會被標記,且您可以看到它搜尋了什麼。 引用標記是不同顏色,面板顯示網域並明確陳述這是公共來源而非您的材料,且此區別由平台應用 — 而非要求模型,它會在恰好需要時遺忘。
代理程式閱讀的頁面和它僅找到的結果都列出,以不同方式繪製(實線 versus 虛線)並以不同方式標記,因為它們是不同級別的證據。早期版本僅顯示它閱讀的頁面,效果與意圖相反:在獲取失敗的一輪中,答案來自摘要且沒有任何來源標記 — 視覺上與來自您自己材料的答案相同。隱藏較弱的證據隱藏了證據薄弱的事實。
每個此類答案都會進入審查佇列,在控制台的 知識審查 下。問題、答案、來源 URL、它閱讀時頁面的快照,以及出站事實檢查無法追蹤到來源的任何數字。
當您批准時寫入的是一個新條目,從問題和材料中重寫 — 而非訪客收到的答案。該答案針對一個人並由該對話塑造:它以他們的名字開頭,提及「您的產品線」,並以行動呼籲結束。逐字存檔,一個訪客的私人上下文成為每個人的答案。因此,條目在不包含任何這些內容的情況下重新生成,標題從材料而非從問題中寫入 — 措辭為*「...關於我的產品」*的問題是一個標題,會靜默地將某人的上下文帶入標題在檢索中權重很高的地方。電子郵件地址和電話號碼在儲存前會被遮罩。您可以看到重寫後的條目,如果需要進行編輯,並批准它。
拒絕會保留記錄,因此同一頁面不會在下個月重新審查。
我們更希望您知道的數字
在 24 個知識庫確實無法回答的問題上進行測量,運行三次:可追蹤到真實來源的答案從 8% 增加到 33%,且我們無法追蹤到任何來源的數字從 13 下降到 6。第二個數字不是零。大約每十二個答案中就有一個仍攜帶我們無法說明來源的數字,這就是為什麼事實檢查隨功能一起提供,而非在其後提供,以及為什麼審查佇列存在的原因。
這在實踐中的意義
- 多語言文件集不會靜默退化 — 分割器適應腳本。
- 文件內的圖表或圖表是可回答的,不會與其餘圖片一起靜默丟棄。
- 後續問題的檢索效果與開啟問題一樣好。
- 代理程式誠實的「我沒有那個」是相關性門檻的設計結果。
檢索品質更多地取決於您上傳的內容,而非此處的任何參數。請參閱 Spaces & knowledge 了解如何組織知識庫,如果您希望有人與您一起完成,請參閱 Partners。