过滤器功能
示例代码: examples/knowledge/features/metadata-filter 以及 examples/knowledge/features/agentic-filter
Knowledge 系统提供了强大的过滤器功能,允许基于文档元数据进行精准搜索。这包括静态过滤器和智能过滤器(由 LLM 根据文档元数据信息自动生成过滤条件)两种模式。
配置元数据源
为了使过滤器功能正常工作,需要在创建文档源时添加元数据:
| import (
"trpc.group/trpc-go/trpc-agent-go/knowledge/source"
filesource "trpc.group/trpc-go/trpc-agent-go/knowledge/source/file"
dirsource "trpc.group/trpc-go/trpc-agent-go/knowledge/source/dir"
urlsource "trpc.group/trpc-go/trpc-agent-go/knowledge/source/url"
)
sources := []source.Source{
// 文件源配置元数据
filesource.New(
[]string{"./docs/api.md"},
filesource.WithName("API Documentation"),
filesource.WithMetadataValue("category", "documentation"),
filesource.WithMetadataValue("topic", "api"),
filesource.WithMetadataValue("service_type", "gateway"),
filesource.WithMetadataValue("protocol", "trpc-go"),
filesource.WithMetadataValue("version", "v1.0"),
),
// 目录源配置元数据
dirsource.New(
[]string{"./tutorials"},
dirsource.WithName("Tutorials"),
dirsource.WithMetadataValue("category", "tutorial"),
...
),
// URL 源配置元数据
urlsource.New(
[]string{"https://example.com/wiki/rpc"},
urlsource.WithName("RPC Wiki"),
urlsource.WithMetadataValue("category", "encyclopedia"),
...
),
}
|
提示:更多文档源配置详见 文档源配置。
过滤器字段设置要求
在使用过滤器时,元数据字段需要使用 metadata. 前缀:
metadata. 前缀用于区分元数据字段和系统字段(如 id、name、content 等)
- 无论是基础过滤器的条件设置,还是智能过滤器生成的条件,元数据字段名都必须包含此前缀
- 基础过滤器:例如
searchfilter.Equal("metadata.category", "docs")
- 智能过滤器:LLM 生成的 JSON 字段名也需包含前缀,例如
{"metadata.topic": "api"}(系统会自动处理)
- 例外:通过
WithDocBuilder 自定义的表字段(如 status、priority 等额外列,需向量数据库支持)直接使用字段名,无需前缀
过滤器层级
Knowledge 系统支持多层过滤器,所有过滤器统一使用 FilterCondition 实现,通过 AND 逻辑组合。系统不区分优先级,所有层级的过滤器平等合并。
过滤器层级:
-
Tool 级过滤器 / Agent 级过滤器:
- 手动创建工具(通过
llmagent.WithTools(自定义searchTool) 注入):通过 knowledgetool.WithConditionedFilter() 设置。
- 自动创建工具(通过
llmagent.WithKnowledge 注入):通过 llmagent.WithKnowledgeConditionedFilter() 设置。
- 注:两者本质相同,都是作用于 Tool 实例的静态过滤器。
-
Runner 级过滤器:
- 通过
agent.WithKnowledgeConditionedFilter() 在 runner.Run() 时传递条件过滤器
-
LLM 智能过滤器:
重要说明:
- 所有过滤器通过 AND 逻辑组合,即必须同时满足所有层级的过滤条件
基础过滤器
基础过滤器支持两种设置方式:Tool/Agent 级别的固定过滤器和 Runner 级别的运行时过滤器。
方式一:自动创建 Tool 时的 Agent 级过滤器
在创建 Agent 并通过 WithKnowledge 自动注入 Knowledge Tool 时,可以使用 WithKnowledgeConditionedFilter 预设固定的搜索过滤条件:
| import (
"trpc.group/trpc-go/trpc-agent-go/agent/llmagent"
"trpc.group/trpc-go/trpc-agent-go/knowledge/searchfilter"
)
// 创建带有固定过滤器的 Agent
llmAgent := llmagent.New(
"knowledge-assistant",
llmagent.WithModel(modelInstance),
llmagent.WithKnowledge(kb),
llmagent.WithKnowledgeConditionedFilter(
searchfilter.And(
searchfilter.Equal("metadata.category", "documentation"),
searchfilter.Equal("metadata.topic", "api"),
),
),
)
|
方式二:手动创建 Tool 时的 Tool 级过滤器
手动创建 Knowledge Search Tool 时,可以使用 WithConditionedFilter 注入过滤器:
| import (
"trpc.group/trpc-go/trpc-agent-go/agent/llmagent"
"trpc.group/trpc-go/trpc-agent-go/knowledge/searchfilter"
knowledgetool "trpc.group/trpc-go/trpc-agent-go/knowledge/tool"
)
// 手动创建 Tool 并设置过滤器
searchTool := knowledgetool.NewKnowledgeSearchTool(
kb,
knowledgetool.WithConditionedFilter(
searchfilter.Equal("metadata.language", "en"),
),
)
// 将 Tool 注入到 Agent
llmAgent := llmagent.New(
"knowledge-assistant",
llmagent.WithModel(modelInstance),
llmagent.WithTools(searchTool),
)
|
Runner 级过滤器
在调用 runner.Run() 时动态传递过滤器,适用于需要根据不同请求上下文进行过滤的场景:
| import (
"trpc.group/trpc-go/trpc-agent-go/agent"
"trpc.group/trpc-go/trpc-agent-go/knowledge/searchfilter"
"trpc.group/trpc-go/trpc-agent-go/runner"
)
// 创建 Runner
appRunner := runner.NewRunner("knowledge-chat", llmAgent)
// 在运行时传递过滤器
eventCh, err := appRunner.Run(
ctx,
userID,
sessionID,
message,
agent.WithKnowledgeConditionedFilter(
searchfilter.And(
searchfilter.Equal("metadata.category", "tutorial"),
searchfilter.Equal("metadata.difficulty", "beginner"),
searchfilter.Equal("metadata.language", "zh"),
),
),
)
|
过滤器合并规则
Tool/Agent 级过滤器和 Runner 级过滤器通过 AND 逻辑组合:
| import (
"trpc.group/trpc-go/trpc-agent-go/agent"
"trpc.group/trpc-go/trpc-agent-go/agent/llmagent"
"trpc.group/trpc-go/trpc-agent-go/knowledge/searchfilter"
"trpc.group/trpc-go/trpc-agent-go/runner"
)
// Tool/Agent 级过滤器 (metadata.category = "documentation")
llmAgent := llmagent.New(
"assistant",
llmagent.WithKnowledge(kb),
llmagent.WithKnowledgeConditionedFilter(
searchfilter.And(
searchfilter.Equal("metadata.category", "documentation"),
searchfilter.Equal("metadata.source_type", "web"),
),
),
)
// 创建 Runner
appRunner := runner.NewRunner("knowledge-chat", llmAgent)
// Runner 级过滤器 (metadata.topic = "api")
eventCh, err := appRunner.Run(
ctx, userID, sessionID, message,
agent.WithKnowledgeConditionedFilter(
searchfilter.Equal("metadata.topic", "api"),
),
)
// 最终生效的过滤器(AND 组合):
// metadata.category = "documentation" AND
// metadata.source_type = "web" AND
// metadata.topic = "api"
|
智能过滤器 (Agentic Filter)
智能过滤器是 Knowledge 系统的高级功能,允许 LLM Agent 根据用户查询动态选择合适的过滤条件。
启用智能过滤器
启用智能过滤器时,需要通过 WithKnowledgeAgenticFilterInfo 提供可用于过滤的元数据字段信息。这些信息将作为提示词的一部分,引导 LLM 生成正确的过滤条件。
支持以下三种配置方式:
方式一:自动提取(推荐)
从配置的文档源中自动提取元数据信息:
- 提取字段和值:使用
source.GetAllMetadata(sources),LLM 将在提取的枚举值范围内进行选择(适合有限枚举值)。
- 仅提取字段:使用
source.GetAllMetadataWithoutValues(sources),LLM 将根据用户查询自由推断值(适合开放域值)。
| import (
"trpc.group/trpc-go/trpc-agent-go/agent/llmagent"
"trpc.group/trpc-go/trpc-agent-go/knowledge/source"
)
// 1. 提取所有元数据信息(包括字段名和所有出现过的值)
// 例如:{"metadata.category": ["doc", "tutorial"], "metadata.topic": ["api", "rpc"]}
sourcesMetadata := source.GetAllMetadata(sources)
// 2. 或者仅提取字段名(不限制取值范围,由 LLM 推断)
// 例如:{"metadata.category": [], "metadata.topic": []}
// sourcesMetadata := source.GetAllMetadataWithoutValues(sources)
llmAgent := llmagent.New(
// ...
llmagent.WithEnableKnowledgeAgenticFilter(true),
llmagent.WithKnowledgeAgenticFilterInfo(sourcesMetadata),
)
|
方式二:手动配置(指定字段和值)
手动指定允许过滤的字段及其允许值枚举,适合枚举值有限的场景(如状态、分类):
| // 手动指定字段和可选值
customMetadata := map[string][]string{
"category": {"documentation", "tutorial", "blog"},
"language": {"en", "zh"},
}
llmAgent := llmagent.New(
// ...
llmagent.WithEnableKnowledgeAgenticFilter(true),
llmagent.WithKnowledgeAgenticFilterInfo(customMetadata),
)
|
方式三:手动配置(指定字段,由 LLM 推断值)
仅指定允许过滤的字段,值列表留空(nil 或空切片),让 LLM 根据用户查询自由推断值(适合 ID、名称等枚举值过多的开放域字段):
| // 仅指定字段,不限制取值范围
customMetadata := map[string][]string{
"author_id": nil, // LLM 自动提取 author_id
"publish_year": nil, // LLM 自动提取年份
"category": {"news"}, // 混合使用:category 限制为 "news"
}
llmAgent := llmagent.New(
// ...
llmagent.WithEnableKnowledgeAgenticFilter(true),
llmagent.WithKnowledgeAgenticFilterInfo(customMetadata),
)
|
过滤器组合示例
| import (
"trpc.group/trpc-go/trpc-agent-go/agent"
"trpc.group/trpc-go/trpc-agent-go/knowledge/searchfilter"
"trpc.group/trpc-go/trpc-agent-go/runner"
)
// 创建 Runner
appRunner := runner.NewRunner("knowledge-chat", llmAgent)
// 2. Runner 级过滤器
eventCh, err := appRunner.Run(
ctx, userID, sessionID, message,
agent.WithKnowledgeConditionedFilter(
searchfilter.And(
searchfilter.Equal("metadata.language", "zh"),
searchfilter.Equal("metadata.version", "v1.0"),
),
),
)
// 3. LLM 智能过滤器(由 LLM 动态生成)
// 例如:用户问 "查找 API 相关文档",LLM 可能生成 {"field": "metadata.topic", "value": "api"}
// 最终生效的过滤条件(所有条件通过 AND 组合):
// metadata.source_type = "web" AND
// metadata.category = "documentation" AND
// metadata.protocol = "trpc-go" AND
// metadata.language = "zh" AND
// metadata.version = "v1.0" AND
// metadata.topic = "api"
//
// 即:必须同时满足所有层级的所有条件
|
复杂条件过滤器
| import (
"trpc.group/trpc-go/trpc-agent-go/agent/llmagent"
"trpc.group/trpc-go/trpc-agent-go/knowledge/searchfilter"
knowledgetool "trpc.group/trpc-go/trpc-agent-go/knowledge/tool"
)
// 手动创建带有条件过滤器的 Tool
searchTool := knowledgetool.NewKnowledgeSearchTool(
kb,
knowledgetool.WithConditionedFilter(
searchfilter.And(
searchfilter.Equal("metadata.source_type", "web"),
searchfilter.Or(
searchfilter.Equal("metadata.topic", "programming"),
searchfilter.Equal("metadata.topic", "api"),
),
),
),
)
llmAgent := llmagent.New(
"knowledge-assistant",
llmagent.WithModel(modelInstance),
llmagent.WithTools(searchTool), // 手动传递 Tool
)
// 最终过滤条件:
// metadata.source_type = "web" AND (metadata.topic = "programming" OR metadata.topic = "api")
// 即:必须是 web 来源,且主题是编程或 API
|
常用过滤器辅助函数
| import "trpc.group/trpc-go/trpc-agent-go/knowledge/searchfilter"
// 比较操作符(注意:元数据字段需要 metadata. 前缀)
searchfilter.Equal("metadata.topic", value) // metadata.topic = value
searchfilter.NotEqual("metadata.category", value) // metadata.category != value
searchfilter.GreaterThan("metadata.version", value) // metadata.version > value
searchfilter.GreaterThanOrEqual("metadata.version", value) // metadata.version >= value
searchfilter.LessThan("metadata.version", value) // metadata.version < value
searchfilter.LessThanOrEqual("metadata.version", value) // metadata.version <= value
searchfilter.In("metadata.category", values...) // metadata.category IN (...)
searchfilter.NotIn("metadata.topic", values...) // metadata.topic NOT IN (...)
searchfilter.Like("metadata.protocol", pattern) // metadata.protocol LIKE pattern
searchfilter.Between("metadata.version", min, max) // metadata.version BETWEEN min AND max
// 自定义表字段(通过 WithDocBuilder 添加的额外列)不需要前缀
searchfilter.NotEqual("status", "deleted") // status != "deleted"
searchfilter.GreaterThanOrEqual("priority", 3) // priority >= 3
// 逻辑操作符
searchfilter.And(conditions...) // AND 组合
searchfilter.Or(conditions...) // OR 组合
// 嵌套示例:(metadata.category = 'documentation') AND (metadata.topic = 'api' OR metadata.topic = 'rpc')
searchfilter.And(
searchfilter.Equal("metadata.category", "documentation"),
searchfilter.Or(
searchfilter.Equal("metadata.topic", "api"),
searchfilter.Equal("metadata.topic", "rpc"),
),
)
|