在 AI 超级智能体项目中,你为什么要使用动态 RAG Advisor 工厂?
- 标签:后端、编程导航
🏛 业务架构师
我用动态 RAG Advisor 工厂的核心动机:不同业务域的知识库,检索策略参数天然不同,一套配置打天下必然次优。
真实场景:我的项目里同时有"公司制度库"(结构化强、术语精确、关键词过滤价值大)和"行业资讯库"(时效敏感、语义多样、多查询扩展收益高)——固定 Advisor 链在 A 库好用的参数(如激进的重写、强元数据过滤)到 B 库就是灾难(漏召回)。知识特征差异 → 检索策略差异,这是业务规律。
实现方式:工厂按"知识库标识/场景码"运行时组装 Advisor 链——每个知识库有自己的策略配置(是否多查询扩展、重写模板、topK、相似度阈值、元数据过滤规则、重排开关),配置驱动、热更新。
业务架构的三个收益:
- 新知识库接入成本降到"写配置":运营配置策略参数即可上线,不写代码不发包——AI 能力的运营化;
- 策略可独立调优:每个库用自己的评测集验证参数调整——不然 A 库调优把 B 库调坏,互相污染;
- 灰度与回滚:策略配置化后可按用户百分比灰度、出问题秒回滚——AI 检索策略也是生产变更,要有变更纪律。
一句话总结:动态工厂体现的架构思想是——把"策略"从代码里剥离成配置资产。RAG 的效果一半靠语料,一半靠策略运营;策略不能运营(写死在代码里)的 RAG 系统,上线之日就是效果冻结之时。
🏗 系统架构师
动态 RAG Advisor 工厂解决的问题是:不同知识库/不同会话需要不同的检索策略,而调用链不能写死。
遇到的具体痛点:我有多套知识库(产品文档库、内部规章库、各租户私有库),策略各不相同——向量库不同(租户隔离)、TopK 与阈值不同、是否开启多查询/重写不同、元数据过滤条件不同(租户/密级)。如果 RAG 增强 Advisor 硬编码单例配置,每加一个库就要改代码发版。
我的实现(工厂 + 运行时装配):
java
public class RagAdvisorFactory {
public Advisor create(RagConfig cfg) {
var builder = QuestionAnswerAdvisor.builder(cfg.getVectorStore())
.searchRequest(cfg.toSearchRequest()) // TopK/阈值/过滤表达式
.promptTemplate(cfg.getPromptTemplate());
if (cfg.isMultiQuery()) builder.advisors(multiQueryAdvisor);
if (cfg.isRewrite()) builder.advisors(rewriteAdvisor);
if (cfg.getContextEnhance()) builder.advisors(contextAdvisor);
return builder.build();
}
}配置存数据库/配置中心(按知识库/租户维度),会话初始化时工厂按配置动态装配 Advisor 链(带本地缓存避免重复构建)。
架构价值:
- 策略与配置分离:检索策略调优(K 值、开关)不用发版,运营可调;
- 租户隔离:每个租户的 VectorStore 指向与过滤条件随配置注入,数据边界由工厂保证;
- 开闭原则落地:新检索优化(重排序、混合检索)做成 Advisor 注册进工厂即可组合。
一句话:把 RAG 从"写死的增强"变成"可配置组合的能力链",这是智能体层多租户化的基础设计。
💻 全栈开发专家
背景:项目里有多个知识库(产品手册、制度文档、技术 wiki),不同用户/场景能用的知识库、检索参数(topK、相似度阈值)、advisor 组合都不一样。最初写死一个 RAG Advisor,每加一种场景就改代码发版——所以做成工厂 + 配置驱动。
实现:运行时按配置组装 Advisor 链:
java
@Component
public class RagAdvisorFactory {
private final Map<String, VectorStore> stores; // 多个知识库
public QuestionAnswerAdvisor create(RagConfig cfg) {
SearchRequest search = SearchRequest.builder()
.topK(cfg.getTopK()) // 场景化参数
.similarityThreshold(cfg.getThreshold()) // 相似度阈值
.filterExpression(cfg.getFilter()) // 元数据过滤(权限/分类)
.build();
return new QuestionAnswerAdvisor(
stores.get(cfg.getVectorStore()), search, promptTemplate);
}
}
// 业务侧:按请求动态构建(配置来自 DB/配置中心,可热更)
ChatClient client = baseClient.mutate()
.defaultAdvisors(memoryAdvisor, ragFactory.create(cfg))
.build();收益(它解决了什么):
- 新增知识库零代码:运营在后台配 vectorStore/filter/参数即可上线;
- A/B 与调参不重启:topK、阈值在线调整,配合评估集快速迭代;
- 权限隔离:filter 按用户部门动态生成,知识库级别的越权访问被结构性挡住;
- 职责收敛:RAG 相关的所有变化点收口在一个工厂,排查链路清晰。
踩坑:Advisor 实例非线程安全的部分要每次新建(工厂每次 create 而不是缓存单例);配置变更要刷新缓存并留痕(谁改的、改了什么)。