English mirror
This English page is generated from the current Chinese documentation so every route, anchor, code sample, and language switch stays available on agently.tech. Human-edited English copy can replace this generated body page by page.
知识库
知识库适合处理这类问题:材料很多,不可能每次都塞进 prompt;用户每次问的问题又只需要其中一小部分事实。它的工作方式是先把材料切成片段并向量化,提问时检索相关片段,再把这些片段作为本次请求的上下文交给模型。
Agently 的知识库路径由三部分组成:
- embedding agent:把文本变成向量。
- 向量集合:保存文档片段和 metadata。
- 请求上下文:把检索结果挂到本次 Agent 请求里。
Agently 内置 Chroma 适配器作为参考实现,包路径是 agently.integrations.chromadb。如果团队已经有 Milvus、pgvector、Elasticsearch 或内部检索服务,也可以把检索结果整理成同样的上下文形态再交给 Agent。
先判断是不是知识库问题
| 场景 | 更合适的能力 |
|---|---|
| 每次请求都要带一小份固定事实 | agent.info(..., always=True) |
| 每次从大量文档里找相关片段 | Knowledge Base |
| 记住用户连续对话里的上下文 | Session |
| 存放跨 execution 的业务状态 | 外部数据库或 TriggerFlow runtime_resources |
| 把 live client 缓存在 flow 里 | TriggerFlow runtime_resources |
知识库解决的是“从大语料里找本次相关事实”。它不是会话记忆,也不是业务数据库。
一条请求链路长什么样
文档片段
|
v
embedding agent -> 向量集合
|
用户问题 -> embedding agent -> 相似度检索 -> 相关片段
|
v
agent.info(..., always=False)
|
v
本次请求always=False 很关键。检索片段只属于这一次问题,不应该污染 Agent 后续请求的固定上下文。
最小用法
from agently import Agently
from agently.integrations.chromadb import ChromaCollection
embedding_agent = Agently.create_agent().set_settings("OpenAICompatible", {
"base_url": "https://api.openai.com/v1",
"api_key": "${ENV.OPENAI_API_KEY}",
"model": "${ENV.EMBEDDING_MODEL}",
})
collection = ChromaCollection(
collection_name="agently-docs",
embedding_agent=embedding_agent,
)
collection.add([
{
"id": "triggerflow-lifecycle",
"document": "TriggerFlow execution 有 open、sealed、closed 三个状态。",
"metadata": {"section": "triggerflow"},
},
{
"id": "model-plugins",
"document": "Agently 内置 OpenAICompatible、OpenAIResponsesCompatible 和 AnthropicCompatible。",
"metadata": {"section": "models"},
},
])
question = "TriggerFlow 有哪些生命周期状态?"
chunks = collection.query(question, top_n=3)
agent = Agently.create_agent()
result = (
agent
.info({"retrieved": chunks}, always=False)
.input(question)
.output({"answer": (str, "基于检索片段回答", True)})
.get_result()
)
answer = await result.async_get_data(ensure_keys=["answer"])这段代码有两个边界:
- 索引阶段把文档片段写入集合。
- 请求阶段只把本问检索出的片段放进
info(..., always=False)。
文档片段怎么设计
知识库质量主要卡在切片和 metadata,而不只是 embedding 模型。
| 设计点 | 建议 |
|---|---|
| 片段大小 | 一段能独立解释一个事实或步骤,不要整篇塞进去 |
id | 稳定、可追溯,最好能回到原文位置 |
metadata | 放 tenant、source、version、section、权限标签 |
| 更新 | 原文变更后重新索引对应片段,不要只追加新版 |
| 返回给模型 | 带上片段正文,也带上 source/id,便于回答引用和排错 |
如果检索片段本身质量差,后面的 prompt 很难补回来。先让片段可读、可追溯,再调相似度参数。
按 metadata 过滤
多租户、权限、文档类型这些边界,应该在检索阶段先过滤。
chunks = collection.query(
user_question,
top_n=5,
where={
"tenant_id": current_user.tenant_id,
"doc_type": "policy",
},
)不要把不该看的片段先检出来,再指望模型“不要使用”。权限边界应在模型前处理。
在 TriggerFlow 里使用
知识库检索经常是工作流中的一个 chunk。
async def retrieve(data):
collection = data.require_resource("collection")
chunks = collection.query(data.input["question"], top_n=5)
await data.async_set_state("retrieved_chunks", chunks)
return {"question": data.input["question"], "chunks": chunks}
async def answer(data):
agent = data.require_resource("agent")
payload = data.input
result = (
agent
.info({"retrieved": payload["chunks"]}, always=False)
.input(payload["question"])
.output({"answer": (str, "回答", True)})
.get_result()
)
final = await result.async_get_data(ensure_keys=["answer"])
await data.async_set_state("answer", final)
return final
flow.to(retrieve).to(answer)
execution = flow.create_execution(
runtime_resources={"collection": collection, "agent": agent},
)
snapshot = await execution.async_start({"question": "报销额度怎么算?"})collection 和 agent 是 live 对象,放进 runtime_resources。检索出的片段和最终回答是业务数据,放进 state。
自动回写要谨慎
有些系统会把 Agent 的答案再写回知识库,用来形成自更新上下文:
collection.add([{
"id": new_id(),
"document": answer["answer"],
"metadata": {"source": "agent_answer"},
}])这条路要有审核或置信边界。未经审核的模型输出直接进入知识库,会把错误答案变成未来检索事实。更稳妥的做法是:先写入待审核集合,人工或规则通过后再进入正式集合。
常见误用
| 写法 | 后果 |
|---|---|
| 把整篇文档当一个 chunk | 检索命中后上下文太大,模型抓不住具体事实 |
检索片段用 always=True 挂到 Agent | 后续请求继续携带旧片段 |
| 用知识库保存会话历史 | 历史没有轮次结构,也难以清理 |
| 把 collection client 放进 TriggerFlow state | save/load 不可靠,snapshot 也不该暴露 live 对象 |
| 自动 ingest 模型答案 | 容易自我污染 |
另见
- Context Engineering - 固定上下文、检索上下文、会话上下文怎么分
- 会话记忆 - 多轮对话记忆
- TriggerFlow State 与 Resources - flow 中 live client 放哪
- 知识库对话案例 - 把检索放进多轮问答