對於您的文件的回答,其品質僅與所建構的文本相當;當您在聊天中貼上整個檔案時,無法判斷模型實際使用了哪一部分。GroupDocs.Search.Mcp 在本機 Docker 中執行,為 Claude Desktop、Cursor 或 Copilot 提供了一個不同的原語:get_text_fragments 只返回與查詢匹配的段落,並附帶少量上下文文字與來源檔案名稱,因而代理會以引用的方式作答:

我的合約中關於罰金的規定是什麼?請引用相關段落,並提供足夠的上下文以理解每一段。

包含設定與故障排除的逐步說明位於文件中:如何取得匹配的段落而非讀取整個檔案.

為何答案會偏離文件內容?

因為上下文窗口是一種預算,而整篇文件會浪費這個預算。關於罰金的問題可能只需要五十頁中的三句話。貼上整個五十頁後,模型必須自行在所有內容中找出那三句,並在寫作時保持它們。長篇上下文會被摘要,較早的內容會失去權重,答案便會依賴模型對合約通常說法的一般認知,而非您實際的合約內容。業界將此管理方式稱為 context engineering(上下文工程);最簡單的做法就是不載入不需要的文字。

片段長什麼樣子?

索引已經保存了每份文件的文字,因此伺服器可以切出每個匹配周圍的段落。以下是我們對五份合成合約測試得到的真實回應。預設值為每側八個詞,會給出一個短語:

-> get_text_fragments {"query":"penalty","indexName":"contracts"}
<- === contracts/acme-master-services-agreement.pdf (1 occurrence(s)) ===
     [content] …before the end of the Term, a termination penalty of
   three monthly fees applies, payable within 30…

每側二十個詞則會給出整個條款:

-> get_text_fragments {"query":"penalty","indexName":"contracts",
     "termsBefore":20,"termsAfter":20,"maxFragmentsPerDocument":1}
<- === contracts/acme-master-services-agreement.pdf (1 occurrence(s)) ===
     …convenience on 90 days written notice.
   12.3 If the Client terminates before the end of the Term, a termination
   penalty of three monthly fees applies, payable within 30 days of the
   termination date.
   14.2 Force majeure: neither party is…

termsBefore 與 termsAfter 如同旋鈕:設定較小時適用於「哪些檔案以及大概位置」,設定較大時則是「引用整條條款」。maxFragmentsPerDocument 與 maxDocuments 限制答案的大小,避免出現出現兩百次的詞彙淹沒上下文。

預算比較

Reading the files                        Searching the index
-------------------------------------    -------------------------------------
agent opens every document               search: which files match (JSON)
  context grows with the corpus          get_text_fragments: the passages
  long files crowd out the question        (~8 words either side, per file)
  repeated for every question            answer cites file + passage
                                         the index is reused next time

隨著語料庫的增大,差異會變得更明顯。對於三個短檔案幾乎沒有影響。對於包含長合約、報告與郵件的資料夾,一個問題的片段可能有數百字,而每個候選文件的完整文本則更長。

當詞彙不同時

全文搜尋匹配詞彙,這是用於落實(每個命中都有說明)的特性,同時也是召回率的限制(同義詞會被錯過)。代理的工作是嘗試變體,且它能看到每個變體實際匹配了什麼:

-> search {"query":"renewal OR renews","indexName":"contracts"}
<- umbrella-office-lease.pdf, terms ["renewal", "renews"]

-> search {"query":"renewl","indexName":"contracts","fuzzy":true}
<- umbrella-office-lease.pdf, terms ["renewal", "renews", "rent"]

模糊匹配救回了拼寫錯誤,同時也把 rent 拉了進來。由於回應列出了匹配的詞彙,代理或您都能看到過度匹配的情況,而不是盲目信任。這種透明度正是「落實」的意義:不僅是「答案引用來源」,更是「您可以看到來源是如何被找到的」。

落實答案的樣子

要求引用時,答案會以一目了然的形式呈現,方便您驗證:

兩份合約包含終止罰金。Acme MSA,第12.3條:「終止罰金為三個月費用,於終止日期起30天內支付。」 Globex 顧問協議,第9節:「客戶支付當前階段剩餘費用的50%。」 Initech NDA 提及終止與罰金,但聲明沒有罰金。

如果摘要誤讀了引用,誤讀會緊貼在引用旁邊。

誠實的限制

  • 在評估模式下,索引最多容納 100 份文件,搜尋最多返回 10 筆。評估模式還會在某些格式的索引文字中加入「Evaluation only…」行,可能會出現在片段中;請為伺服器授權並重新建立索引以移除該行。請先呼叫 get_license_status。
  • 片段的上下文以字數計算,而非句子數,因此段落可能從句中間開始;在需要時提升 termsBefore。
  • 不支援 OCR:沒有文字層的掃描檔無法返回任何段落。
  • 僅支援 Docker;在 Linux 上請加入 --user "$(id -u):$(id -g)"。

常見問題

如何讓 Claude 引用我的文件來源?
提供一個能返回來源文字與檔名的工具。get_text_fragments 正好具備此功能,且給予「引用段落及其檔案」之指示即可養成習慣。

這會減少 token 使用量嗎?
它避免載入整份文件來回答問題:代理只會閱讀匹配的段落。節省多少取決於您的檔案大小。

代理在需要時仍能閱讀整個檔案嗎?
可以,使用其內建的檔案工具。片段用於尋找與引用;當段落不足時則閱讀整個檔案。

深入了解