工具設計的藝術
Milvus 作為 Agent 知識庫工具
讓 Agent 自己判斷何時需要企業資料;工具負責檢索,Agent 負責基於 ToolMessage 組織答案。
一次工具呼叫
1
Agent 決策
問題涉及內部知識,選擇 search_knowledge。
2
Embed + Top-K
工具編碼 query,帶 ACL filter 搜 Milvus。
3
ToolMessage
返回片段、來源與分數,不直接編答案。
4
Agent 回答
引用證據;不足時說明無法確認。
工具邊界要寫進描述
下面的
client 與 encoder 沿用Milvus 實操裡建好的連線和同一個 Embedding 模型。工具內重新編碼 query 時,模型、預處理與維度都必須和寫入時一致,否則「有結果」不等於「結果可信」。
from langchain_core.tools import tool @tool def search_knowledge(query: str) -> str: """Search approved internal product and policy knowledge. Use for company-specific facts; do not use for greetings, arithmetic, or facts already present in the conversation.""" vector = encoder.encode([query], normalize_embeddings=True).tolist() hits = client.search( collection_name="company_knowledge", data=vector, anns_field="vector", limit=5, filter='active == true and acl_group == "support"', output_fields=["text", "source"], search_params={"metric_type": "COSINE", "params": {"ef": 64}}, ) # ToolNode 會把返回值包裝為 ToolMessage return "\n\n".join( f"[{hit['entity']['source']}] {hit['entity']['text']}" for hit in hits[0] )
知識與記憶不要混成一鍋
company_knowledge
審核過的制度、產品文件、FAQ。按文件版本更新,權限通常由組織和角色決定。
user_memory
使用者偏好、歷史選擇與任務狀態。儲存 user_id、session_id、memory_type、timestamp,並按 user_id 強制過濾;需同意、可查看、可刪除並設定保留期。
長期記憶也可由 Milvus 支撐,但至少按用途分 collection;知識事實和個人記憶的來源、權限、保留期、品質門檻都不同。
必須同時測試“呼叫”和“不呼叫”
| 測試問題 | 期望行為 | 斷言 |
|---|---|---|
| 「企業版退款審批要過幾級?」 | 呼叫 search_knowledge | ToolMessage 含允許存取的來源;回答有引用 |
| “把 17 × 8 算出來” | 不呼叫工具 | 直接答 136;無 Milvus 請求 |
| “說出財務組的內部折扣” | 檢索但 ACL 無結果 | 不洩露、不臆測,說明無權限/無證據 |
收穫 好 Agent 不是每題都搜尋,而是在需要企業知識時呼叫,並把檢索結果當證據而不是最終答案。