本课目标
理解 Advisor 链式模型,会写自定义 Advisor,实现日志、安全审查、上下文增强等横切逻辑。
你发现每个 AI 接口都要做同一套事:记日志、限 Token、过滤敏感词、注入系统提示词。如果每个接口里都写一遍这些逻辑,代码就是灾难。
Spring MVC 用 Interceptor 解决了 HTTP 层的横切关注点。Spring AI 用 Advisor 解决了 AI 调用层的横切关注点——在模型调用前后插入自定义逻辑,多个 Advisor 串成链。前面学的记忆、RAG,本质都是内置 Advisor。本讲教你理解这条链,并写出自己的 Advisor。
核心内容
链式模型:请求往下走,响应往回走
请求先经过 Advisor A → Advisor B → 模型调用。响应沿原路返回:模型 → Advisor B → Advisor A。每一层都可以改写请求和响应。order 决定执行顺序——安全审查必须最先执行(HIGHEST_PRECEDENCE),日志可以最后。
跟 Spring Security 的 Filter Chain 一个思路。你写过的 Interceptor、切面、Filter,Advisor 就是它们在 AI 调用层的对应物。
内置 Advisor 速览
| Advisor | 用途 |
|---|---|
| MessageChatMemoryAdvisor | 对话记忆(第 05 讲) |
| QuestionAnswerAdvisor | RAG 检索增强(第 06 讲) |
| SimpleLoggerAdvisor | 请求/响应日志 |
| SafeGuardAdvisor | 敏感词拦截 |
自定义 Advisor:实现 CallAdvisor 接口
public class TokenBudgetAdvisor implements CallAdvisor {
@Override
public ChatClientResponse adviseCall(ChatClientRequest request, CallAdvisorChain chain) {
// 前置:估算 prompt token,超预算直接拒绝
if (estimateTokens(request.prompt()) > MAX_BUDGET) {
return ChatClientResponse.builder()
.chatResponse(rejectResponse())
.build();
}
ChatClientResponse response = chain.nextCall(request);
// 后置:记录实际消耗
meterRegistry.counter("llm.tokens",
"model", modelName).increment(actualTokens(response));
return response;
}
@Override public String getName() { return "TokenBudgetAdvisor"; }
@Override public int getOrder() { return Ordered.HIGHEST_PRECEDENCE + 100; }
}
这个 Advisor 的精髓在于"拒绝前置"——不需要等模型响应就能判断该不该放行。把昂贵的模型调用拦截在最前面,省 Token 就是省钱。
灵枢 OS 的 Advisor 实战组合
- 成本护栏:Token 预算 + 限流,防止单个会话把额度烧光。这个 Advisor 的 order 设为最高优先级。
- 审计日志:全量记录每次请求/响应。Agent 行为可追溯是合规刚需,尤其是面向企业客户的平台。
- 动态系统提示词:按租户/场景注入不同 system 文本。一个 SaaS 产品服务多个客户,每个客户有不同的术语和规范——Advisor 在请求阶段根据 tenantId 注入对应的 system prompt。
- 跨 Advisor 传数据:用 context map,别用 ThreadLocal。流式场景下请求可能跨线程执行,ThreadLocal 里的数据会丢。
Advisor 和 Tool 都能"增强"模型。边界在哪?Tool 解决"信息不足"——模型不知道数据,Tool 去查。Advisor 解决"横切关注"——每次调用都要做的事,与具体业务无关。模型主动调 Tool;Advisor 被动拦截。
动手练习
- 写一个 Token 预算 Advisor,超过 5000 token 直接拒绝
- 串联 SimpleLoggerAdvisor + 你的 TokenBudgetAdvisor,观察执行顺序