前言
在端到端全双工实时语音对话场景,通话会话拥有完整生命周期:会话启动、每一轮问答交互、会话结束。很多业务需要在对话的各个节点植入横切逻辑:通话敏感词过滤、会话日志埋点、风险检测、自定义变量改写、对话内容审计、会话结束后业务回调。
如果直接修改通话主业务代码实现上述逻辑,会大量侵入核心会话逻辑,版本升级时产生大量代码冲突,不利于维护扩展。
该机制的核心价值在于:把"会话生命周期中的横切关注点"从主业务流程中剥离出来,通过"钩子 + Spring Bean 自动发现"的方式,让开发者以极低侵入性扩展通话能力,无需改动核心编排代码。
基于Spring Bean自动发现机制,零侵入业务主流程 ,开发者新增业务逻辑,只需要实现拦截器接口并标注@Component,框架自动加载执行,无需修改原有通话编排代码,完美遵循开闭原则。
一、端到端会话整体执行链路回顾
端到端实时对话完整流程:
- 来电/外呼接通,AgiHandler 检测
agentId,进入ProcessServiceImpl.realtime()实时会话编排 - 加载智能体配置,解析变量占位符,通过适配器工厂创建模型会话
- 建立AudioSocket全双工音频流,初始化
RealtimeCallSession通话会话 - 会话启动,执行拦截器
onSessionStart - 用户说话→模型应答,每一轮问答前后执行拦截器
beforeTurn、afterTurn - 会话结束、挂机,执行拦截器
onSessionEnd - 释放音频、WebSocket、线程全部资源
拦截器就是嵌入在会话生命周期各个钩子点的扩展插槽,不改变原有通话、媒体流、打断、挂机核心逻辑。
二、RealtimeTurnInterceptor核心接口定义
RealtimeTurnInterceptor为顶层拦截器接口,提供四个生命周期钩子,同时支持order()指定执行顺序,数字越小优先级越高。
java
public interface RealtimeTurnInterceptor {
/**
* 会话开始回调:模型连接就绪,会话正式启动
* @param turnContext 通话上下文对象,携带会话全部信息
*/
default void onSessionStart(TurnContext turnContext) {}
/**
* 每一轮大模型应答生成【之前】执行
* @param turnContext 通话上下文
*/
default void beforeTurn(TurnContext turnContext) {}
/**
* 每一轮大模型应答生成【结束之后】执行
* @param turnContext 通话上下文
*/
default void afterTurn(TurnContext turnContext) {}
/**
* 整个通话会话完全结束,准备释放资源
* @param turnContext 通话上下文
*/
default void onSessionEnd(TurnContext turnContext) {}
/**
* 拦截器执行顺序,数值越小越优先执行
* @return 排序order
*/
default int order() {
return 0;
}
}
TurnContext 通话上下文
TurnContext是拦截器最重要的入参,承载单次会话全部运行时信息:
- 智能体基础配置、通话通道ID、来电/去电号码
- 当前轮次:用户转写文本、模型输出应答文本
- 会话变量集合,可以读取、修改会话内业务变量
- 通话状态、会话ID、相关工具调用信息
业务开发可以从
TurnContext拿到通话全量上下文,完成日志、过滤、改写变量等操作。
三、框架如何自动加载、执行拦截器
1. Bean自动收集
RealtimeCallSession初始化阶段,直接从Spring上下文获取全部实现RealtimeTurnInterceptor接口的Bean,根据order()进行升序排序,形成拦截器调用链。
开发者自定义拦截器,只需要加上
@Component,不需要手动注册,框架自动扫描识别。
2. 调用链执行时机
- onSessionStart:模型WebSocket会话连接建立完成,对话会话刚刚启动时执行全部拦截器;
- beforeTurn :每一轮AI生成回答之前执行,适合做提示词改写、敏感词前置校验;
- afterTurn:一轮AI应答完整结束后执行,适合做应答内容审计、保存对话业务记录;
- onSessionEnd:会话即将销毁,通话准备挂机释放资源,适合会话结束回调、业务数据上报。
注意:拦截器运行在通话业务线程,禁止长时间阻塞,耗时IO操作需要丢到异步线程池,否则会阻塞实时对话。
执行顺序规则
多个拦截器共存:order()值越小越先执行。
- beforeTurn / onSessionStart:按order从小到大执行
- afterTurn / onSessionEnd:按order从大到小执行(类似过滤器的责任链回滚)
四、自定义拦截器开发示例
示例1:会话全链路日志审计拦截器
实现RealtimeTurnInterceptor,添加@Component,即可自动生效。
java
@Component
@Slf4j
public class CallAuditInterceptor implements RealtimeTurnInterceptor {
@Override
public int order() {
return 1;
}
@Override
public void onSessionStart(TurnContext turnContext) {
log.info("实时会话启动,通话ID:{},来电号码:{}",
turnContext.getChannelId(),
turnContext.getPhone());
}
@Override
public void beforeTurn(TurnContext turnContext) {
// 每一轮模型生成应答前
String userText = turnContext.getUserTranscript();
log.info("用户输入内容:{}", userText);
}
@Override
public void afterTurn(TurnContext turnContext) {
// AI应答结束,执行审计逻辑
String botAnswer = turnContext.getBotTranscript();
log.info("模型应答内容:{}", botAnswer);
// 可以在这里做敏感词检测,命中后设置会话结束,转接人工
}
@Override
public void onSessionEnd(TurnContext turnContext) {
log.info("会话结束,通话ID:{}", turnContext.getChannelId());
// 异步上报通话业务记录到外部CRM、工单系统
}
}
示例2:会话变量动态修改拦截器
会话启动时,从外部接口拉取用户业务数据,写入会话上下文,后续智能体提示词可以直接读取变量。
java
@Component
public class CustomerInfoInterceptor implements RealtimeTurnInterceptor {
@Override
public void onSessionStart(TurnContext turnContext) {
String phone = turnContext.getPhone();
// 异步调用外部CRM接口获取客户信息
CustomerDTO customer = remoteCrmApi.getCustomerByPhone(phone);
// 写入会话上下文,智能体提示词${customerName}即可直接读取
turnContext.setVariable("customerName", customer.getName());
turnContext.setVariable("customerLevel", customer.getLevel());
}
}
五、拦截器典型业务落地场景
-
通话安全审计、敏感词过滤 会话每轮应答前后抓取用户和AI输出文本,做敏感词、风险内容检测,命中风险可以触发转人工、结束通话。
-
会话生命周期日志埋点 记录会话启动、每轮对话、会话结束全流程日志,用于问题排查、通话复盘。
-
动态注入会话业务变量 会话启动时拉取CRM、工单系统数据,注入会话上下文,提示词直接使用变量,实现千人千面话术。
-
会话结束业务回调上报 通话挂机之后,自动把对话结果、通话摘要推送给业务系统,不需要修改底层通话代码。
-
业务规则控制 例如:同一个号码最多对话轮次限制,达到轮次自动引导转人工。
⚠️开发注意事项
- 拦截器所有钩子方法禁止同步阻塞IO,数据库、HTTP远程调用,必须切换异步线程池,否则直接影响实时对话时延;
- 不要在拦截器内直接操作底层音频、模型连接,所有会话操作通过
TurnContext提供的API;- 异常务必捕获,拦截器内部异常不能导致整个通话会话崩溃;
- order()合理设置,控制多个拦截器执行先后顺序。
六、拦截器和FunctionCallHandler区别
很多开发者容易混淆RealtimeTurnInterceptor轮次拦截器和FunctionCallHandler工具调用处理器:
| 组件 | 作用 | 触发时机 |
|---|---|---|
| RealtimeTurnInterceptor | 会话生命周期钩子,会话启动、每轮问答、会话结束横切扩展 | 会话完整生命周期,不管是否调用工具都会执行 |
| FunctionCallHandler | 专门处理模型下发function‑call工具调用请求 | 只有模型发起工具调用的时候才触发,执行业务接口并返回结果给大模型 |
二者可以搭配使用:工具调用完成后,拦截器afterTurn可以拿到工具调用结果做日志审计。
七、资源地址
📘官方开发文档:qidiangk.com/docs/develo...
⭐ Gitee开源仓库:gitee.com/gdzWork/Sma...
🌐官网地址:qidiangk.com
小结:
RealtimeTurnInterceptor拦截器机制,是SmartCall端到端实时对话重要的扩展点。通过钩子+Spring Bean自动发现,以极低侵入性,实现通话会话横切业务逻辑,开发者不用修改核心通话、媒体流、打断挂机代码,就可以实现审计、变量注入、风险检测等丰富业务,这也是开源呼叫中心可扩展架构设计的典型实践。