构建并填充知识库
创建知识库,添加文本和文件,并在挂载之前验证检索功能——通过 MCP。
create_knowledge_baseadd_knowledge_textadd_knowledge_filesearch_knowledge_baseupdate_agentbuild_knowledge_indexget_knowledge_indexpatch_knowledge_index原则——先确立,再验证。 知识库是必须遵循的权威来源,而非参考建议。在
instructions中明确其覆盖范围,并始终在依赖它之前确认实际检索到了内容——如果检索结果为空,智能体将回答“未涵盖”。更多信息请参阅 设计原则。
挂载的知识库会在每一轮对话中自动检索——模型不会决定是否进行检索;相关性由向量距离决定。这是有意为之:知识库是必须遵循的权威来源,而非可选工具。
1. 创建它
create_knowledge_base(
name="Company policy",
description="Mortgage policy and rates, effective 2026 — not car or personal loans", # routes questions here
instructions="Authoritative current mortgage policy; overrides any industry norm. "
"Covers home mortgages only; for car or personal loans, say so and hand off.", # for the model
)名称在创建时会被规范化为 url-safe slug——"Company policy" 会返回为 company-policy。请使用返回的名称进行后续所有操作:add_knowledge_text(kb_name=…)、search_knowledge_base(kb_name=…) 以及将其附加到智能体上。稍后输入原始带空格的名称只会导致 404 错误。
2. 编写 description——它是将问题路由到此知识库的依据
description 不是标题。在每次回答之前,平台会读取每个已附加知识库的描述,并决定此问题需要哪一个——如果都不需要,则根本不进行检索。否则,拥有三个知识库的智能体在每一轮对话中都会执行三次向量检索,并将三组摘录内容注入提示词中,即使访客只是说了“你好”。
因此,描述模糊或为空的知识库会在不应被检索时被检索,而——更糟糕的是——在应该被检索时被遗漏。这两种失败都不会报错:第一种表现为带有无关引用的缓慢回答,第二种表现为“我没有关于那方面的信息”。
用访客会使用的词语,写一行描述主题:
✅ "Country-by-country medical device registration requirements"
✅ "Regulatory change news by country and authority, 2022–2026 — what changed and when"
✅ "Selpercatinib — for lung and thyroid cancer"
❌ "Knowledge base" ← routes nothing
❌ "Imported from the website" ← says where it came from, not what is in it
❌ "Sandbox test, safe to delete" ← says why it exists, not what is in it关键在于与其他知识库具有区分度,而非篇幅长短。 拥有九个知识库的租户——八个药物和一个公司简介,每行一句话,均不超过十二个词——能正确路由 10 个中的 10 个问题,因为“针对肺癌和甲状腺癌”和“针对 IgA 肾病”绝不会混淆。这是经过测量的,而非假设的。
仅在两个知识库重叠时才添加边界。 如果你的产品页面和新闻档案都谈论同一主题,请说明哪一个是什么——“……不包括定价或公司信息”可以阻止档案库回答定价问题。如果知识库之间已经明显不同,添加边界条款毫无益处。
这一行也是控制台列表显示的内容,但这只是次要功能。
3. 从预期用途编写 instructions——在创建时,而非“稍后”
instructions 不影响召回率——召回率由向量搜索和 max_distance 决定。它在回答时与此知识库的摘录一起注入,因此它控制模型如何使用检索到的内容。如果留空,知识库仍会检索,但回答会失去所有知识库特定规则:权威性、边界、引用约定。仅当通用参考资料没有特殊规则时,留空才是可接受的。
根据知识库的实际使用方式推导它——每个问题一行:
| 问题 | 示例行 |
|---|---|
| 范围——包含什么、排除什么、超出范围时该怎么做? | "Covers residential mortgages only; for car or personal loans, say so and hand off." |
| 权威性——它排在什么位置? | "Current company policy; overrides industry norms and the model's prior knowledge." |
| 使用规则——引用时是否有任何约定? | "Any quoted rate must state its effective date." |
按知识库类型划分的知识库指令示例:
# Website-content KB (products, services, team, blog)
instructions="Company website content: products, services, team and blog posts. Authoritative
for what we offer and who we are. Marketing copy is not a contractual promise — for prices,
terms or eligibility prefer the policy KB; if only this KB answers, attribute it to the website."
# Policy / regulation KB
instructions="Current company policy, effective 2026; overrides industry norms and prior
knowledge. Covers home mortgages only — for car or personal loans, say so and hand off.
Any quoted rate or fee must state its effective date."
# Product-docs KB
instructions="Official product documentation for the current release. State the version when a
feature is version-dependent. If the docs don't cover something, say so — never fill the gap
from general knowledge."4. 添加内容
add_knowledge_text(kb_name="Company policy", title="2026 late-fee rule",
content="From 1 July 2026 the daily late fee is 0.019% …")二进制文件(pdf/docx)和整个文件夹(zip 压缩包)通过 add_knowledge_file 进行添加——子文件夹会被遍历,每个 md/txt/pdf/html/docx 文件都会按其存档内的路径导入。
4b. 编写你希望被检索到的句子
检索匹配的是含义,而单独的值几乎没有任何意义。这是你所能控制的杠杆率最高的事情,而且很容易出错,因为不会报错——搜索仍会返回某些内容,只是不是正确的内容。
一个真实的客户目录在 1,500 条记录中的 1,480 条包含以下行:
Reading level: 1 · Age: 5 · Words: 1951而“哪些书适合刚开始独立阅读的孩子”返回了一本关于音乐神童的书。事实就在文本中,但仍然无法触及:1 与 beginner reader(初学者读者)毫无相似之处,就像单词与单词之间的相似性一样。
在值旁边添加一句话即可修复——在该记录上进行了测量:
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 包含相同的正文。这看起来很浪费,而且直觉认为它“消耗”了向量空间是错误的:我们进行了测量,删除重复项使检索距离在 60 条记录上仅变化了 +0.002——即毫无影响。嵌入是一个方向,而非预算;说同样的事情两次主要指向同一个方向两次。
就这样吧。把精力花在上面那句话上。
4c. 如果文档共享标头,构建结构化索引
向量搜索无法计数、按数字过滤或分组。“你有多少”、“哪些少于 200 词”、“每类有多少”回答得不好——它们是结构上无法回答的,智能体要么拒绝回答,要么报告它碰巧检索到的那几条记录。
build_knowledge_index(name="books", roles=["identity", "link", "image"])仅在文档共享机器可读标头时才值得调用——元数据表、YAML front matter、Field: value 行。产品导出、目录、传单和课程列表通常符合条件;正文不符合,且调用会拒绝构建值各不相同的表。拒绝是正确的结果,而非需要规避的错误。
roles 命名必须精确提取且绝不 paraphrase 的字段:
| 角色 | 含义 |
|---|---|
identity | 项目的名称——书名、药物名称、产品名称 |
link | 将用户发送到的位置 |
image | 向用户展示的内容 |
code | 他们向你引用的标识符 |
询问用户这些字段是什么;不要推断它们。 三个 URL 中哪一个是发送给客户的,这是一个数据未陈述的业务事实。如果声明的角色无法找到,它会作为 roles.unresolved 带有候选字段名返回——将这些提供给用户,而不是选择一个。
读取 dropped,并告知用户
{"built": true, "documents": 4523,
"columns": ["title", "age", "word_count", "genre", "read_url", "cover_url"],
"dropped": [["isbn", "not_found", "no anchor 'ISBN: ' in the sample"]]}被丢弃的列在其他地方不可见:后续回答只是绕过它,因此此报告是唯一提及它的地方。get_knowledge_index 也是如此,其警告通常揭示客户不知道的数据问题——在一个真实的目录中,十分之一的记录页数为 0,这不是短书,而是缺失值记录为零,这会拉低基于它构建的所有平均值。
用客户自己的术语报告这些内容。平台中没有任何其他内容会这样做。
稍后更改它
patch_knowledge_index(name="books", request="also track the author", apply=false)先使用 apply=false 运行,向用户展示将发生的变化,批量进行几次编辑,然后一次性应用。应用从存储的文本中重新读取字段;它不会重新嵌入任何内容,因此成本很低。
请求文档中不存在的字段会返回带有原因的 refused 条目——将该原因原样传递给用户,而不是发明变通方案。
5. ★ 验证检索——不要跳过 ★
search_knowledge_base(kb_name="Company policy", query="how is the late fee calculated")
# hits → the agent can answer this
# empty → the agent will treat it as "not covered" and say so6. 挂载它
update_agent(name="Support", add_knowledge_bases=["company-policy"]) # incremental — keeps existing mounts不要在 instructions 中写“始终引用段落”——这种行为是内置的。只写此库特有的内容:权威性排序、覆盖范围边界、特殊用法(例如,“引用利率必须说明其生效日期”)。
反馈——不要止步于“已导入”。 告诉用户有多少块落地,并提供可点击的链接以打开知识库及其知识星图(已摄取内容的 3D 视图):
https://console.agent4.io/#/knowledge-bases/Company%20policy——然后确认它已附加到智能体上。