工程进阶 · 可靠 Agent 的工程模式

Milvus 作为 Agent 知识库工具

把向量检索封成 search_knowledge:ToolMessage、记忆分层与调用/不调用的测试

本页解决的问题

先给结论

「Milvus 作为 Agent 知识库工具」要解决的关键问题是什么?

把向量检索封成 search_knowledge:ToolMessage、记忆分层与调用/不调用的测试

判断标准

让这个结论先证明自己值得留下。 把这一页当成决策工具,而不是需要背下来的定义。把概念连到一个真实任务、一个可观察结果,以及一个能改变你判断的失败上。

下一步

写下一个问题:试完这个方法后,你能用什么证据回答它?

常见误区

结论听起来很完整,却没有检查最关键的假设。

一次工具调用
1

Agent 决策

问题涉及内部知识,选择 search_knowledge。

2

Embed + Top-K

工具编码 query,带 ACL filter 搜 Milvus。

3

ToolMessage

返回片段、来源与分数,不直接编答案。

4

Agent 回答

引用证据;不足时说明无法确认。

工具边界要写进描述
下面的 clientencoder 沿用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 不是每题都搜索,而是在需要企业知识时调用,并把检索结果当证据而不是最终答案。

「Agent 决策」为什么能找到相关内容

「审核过的制度、产品文档、FAQ。按文档版本更新,权限通常由组织和角色决定」把检索问题从“把资料存起来”推进到“怎样找到真正相关的资料”。这一步决定了 RAG、推荐和以图搜图最后交给模型的输入质量。

相似度不是答案,召回之后还要核对

在「用户偏好、历史选择与任务状态。保存 user_id、session_id、memory_type、timestamp,并按 user_id 强制过滤;需同意、可查看、可删除并设置保留期」对应的流程里,Embedding 负责把对象放到可比较的语义空间,近邻索引负责减少搜索范围,最终的回答仍然依赖召回片段是否覆盖问题、距离指标是否合适,以及内容有没有过期。

先区分找得到和找得准

把「用户偏好、历史选择与任务状态。保存 user_id、session_id、memory_type、timestamp,并按 user_id 强制过滤;需同意、可查看、可删除并设置保留期」落成一次小测试:准备几条有明确答案的查询,记录召回的相关性、遗漏和无关结果,再决定是否需要换切分方式、索引或重排。

从「Agent 决策」走到「Embed + Top-K」

「Agent 决策」先把问题落在「问题涉及内部知识,选择 search_knowledge」上;到了「Embed + Top-K」,讨论继续推进到「工具编码 query,带 ACL filter 搜 Milvus」。两段连起来,重点就不只是记住一个结论,而是看清它成立所依赖的条件。

把这条判断带到下一个场景

检索系统也可以这样看:先确定什么算相关,再观察召回是否覆盖问题,最后检查排序、切分和时效性有没有把真正有用的内容挤出去。

  • 「Agent 决策」:问题涉及内部知识,选择 search_knowledge
  • 「Embed + Top-K」:工具编码 query,带 ACL filter 搜 Milvus
  • 「必须同时测试“调用”和“不调用”」:测试问题 期望行为 断言 “企业版退款审批要几级?” 调用 search_knowledge ToolMessage 含允许访问的来源;回答有引用 “把 17 × 8 算出来” 不调用工具 直接答 136;无 Milvus 请求 “说出财务组的内部折扣” 检索但 ACL 无结果 不泄露、不臆测,说明无权限/无证据 收获 好 Agent 不是每题都搜索,而是在需要企业知识时调用,并把检索结果当证据而不是最终答案

最后的「必须同时测试“调用”和“不调用”」把讨论落到「测试问题 期望行为 断言 “企业版退款审批要几级?” 调用 search_knowledge ToolMessage 含允许访问的来源;回答有引用 “把 17 × 8 算出来” 不调用工具 直接答 136;无 Milvus 请求 “说出财务组的内部折扣” 检索但 ACL 无结果 不泄露、不臆测,说明无权限/无证据 收获 好 Agent 不是每题都搜索,而是在需要企业知识时调用,并把检索结果当证据而不是最终答案」。回看这条线索时,最值得保留的是:当输入、规模或风险改变,哪些判断需要重新做一遍。

标记为已学完 阅读进度会自动记录
← 上一篇下一篇 →

继续阅读

同一条线上的下一篇。

文章讨论

读到这里,留下一个判断。

把刚想明白的地方、还没想通的问题,留给下一位一起学习的人。

正在讨论 Milvus 作为 Agent 知识库工具 可靠 Agent 的工程模式
3条讨论文章讨论 · 与共学社区同步
在共学社区查看
AM
Asha Morgan内容编辑
观点实践记录

我把这篇文章里的一个判断改写成了今天可以验证的小实验。比记住结论更有用的是,知道下一步要观察什么。

文章讨论7 有帮助
LH
Lin Harper独立开发者
观点观点

读完以后我先回头找它成立的条件,而不是直接把方法搬进项目。这个顺序让后面的取舍清楚很多。

文章讨论5 有帮助
KM
Kiki Moore产品运营
问题问题

如果把这个判断放到真实工作里,最先需要补的约束是什么?我想知道从阅读到第一次实践之间,哪一步最值得先做。

文章讨论4 有帮助