Playbook 是 RustPBX 的核心配置文件,它采用 Markdown 格式,通过 Front Matter (YAML) 定义 AI 引擎参数,通过 Markdown 内容定义业务流程、场景和 AI 提示词(Prompt)。
Playbook 文件由三部分组成:
- Front Matter (
---): YAML 格式的全局配置,包括 ASR/TTS/LLM 引擎参数。 - 全局提示词 (Global Prompt): 定义 AI 的角色身份、行为准则和工具使用规则。
- 场景 (
# Scene: ...): 定义不同的对话阶段及其特定的提示词、按键处理和流程跳转。
asr:
provider: "aliyun" # 或 "openai", "tencent", "deepgram", "sensevoice"
language: "zh-CN"
# extra 参数用于向特定引擎传递额外配置
extra:
silence_threshold: "0.05" # 仅用于 sensevoice: 静音阈值 (默认 0.01),调高可减少噪音误触发
tts:
provider: "aliyun" # 默认值: 中文(zh)默认 aliyun, 英文(en)默认 supertonic
model: "cosyvoice-v2"
speed: 1.0
volume: 50
llm:
provider: "aliyun"
model: "gpt-4o"
#apiKey: "OPENAI_API_KEY"
#baseUrl: "https://api.openai.com/v1"
language: "zh" # 默认: "zh"。用于加载语言特定的工具说明和功能特性
features: ["http_tool", "voice_emotion"] # 启用增强功能
# toolInstructions: "自定义工具使用说明..." # 可选: 覆盖默认的工具使用说明greeting: "您好,我是您的 AI 助手,请问有什么可以帮您?"
denoise: true # 启用语音降噪
agc: {} # 启用 WebRTC AGC2 自动增益控制(默认 5 dB 余量,15 dB 初始增益),需要同时配置 `vad`
interruption:
strategy: "both" # 打断策略: "none", "vad", "asr", "both"
minSpeechMs: 500 # 用户说话超过 500ms 才触发打断
fillerWordFilter: true # 自动过滤 "嗯"、"那个" 等语气词
followup:
timeout: 10000 # 如果用户 10 秒没说话,AI 主动开启跟进
max: 2 # 最多连续跟进 2 次ambiance:
path: "./config/office.wav" # 通话背景音乐
duckLevel: 0.1 # AI 说话时背景音自动降低到的音量系数 (0.1 = 10%)
normalLevel: 0.5 # 默认背景音量
recorder:
recorderFile: "recordings/call_{id}.wav" # 自动开启通话录音
ringbackDetection:
enabled: true # 检测回铃音
confidenceThreshold: 0.8
onStateChangeOnly: false # 每次检测都发送 RingbackState 事件
sip:
extractHeaders:
- "X-Customer-Id" # 提取 SIP 头到模板变量 {{ sip["X-Customer-Id"] }}
- "X-Session-Token"通过 Scene: [ID] 定义对话阶段,AI 会在切换场景时自动更新其 System Prompt。
# Scene: start
## welcome
AI 角色:你现在是欢迎人员。
<dtmf digit="1" action="goto" scene="sale"/>
<dtmf digit="2" action="transfer" target="sip:operator@domain.com"/>
# Scene: sale
## product_info
AI 角色:你现在是销售顾问。请向用户介绍我们的理财产品。Playbook 支持两种方式触发系统动作:
这类指令可以直接写在角色描述或直接被模型输出,支持流式处理:
- 挂断:
<hangup/> - 转接:
<refer to="sip:1001@127.0.0.1"/> - 发送 SIP 元信息正文:
<message body="customer_id=12345" contentType="text/plain;charset=utf-8" refer="false"/> - 音效播放:
<play file="config/media/ding.wav"/> - 场景跳转:
<goto scene="support"/> - 设置变量:
<set_var key="user_name" value="John"/>— 存储为{{ user_name }},可在后续模板中使用 - HTTP 调用:
<http url="https://api.example.com/query" method="POST" body='{"id":"123"}'/>— 结果回传 LLM - DTMF 收集:
<collect type="phone" var="user_phone" prompt="请输入您的手机号"/>— 收集按键存入{{ user_phone }}
用于复杂操作,如 HTTP 调用。结果会自动喂回给 AI 进行下一次推理。
{
"tools": [
{
"name": "http",
"url": "https://api.example.com/query",
"method": "POST",
"body": { "id": "123" }
}
]
}在智能客服场景中,对于电话号码、验证码、身份证号等数字信息,语音识别容易出错。DTMF (按键音) 数字收集功能提供了更可靠的输入方式。
在 Front Matter 中定义可复用的收集器配置:
dtmfCollectors:
phone:
description: "11位手机号"
digits: 11 # 固定位数
finishKey: "#" # 完成键(可选)
timeout: 20 # 总超时(秒)
interDigitTimeout: 5 # 按键间隔超时(秒)
validation:
pattern: "^1[3-9]\\d{9}$" # 正则表达式验证
errorMessage: "请输入有效的11位手机号,以1开头"
retryTimes: 3 # 验证失败最大重试次数
interruptible: false # 收集时是否允许语音打断
code:
description: "6位验证码"
digits: 6
timeout: 30
interDigitTimeout: 5
retryTimes: 2
# 无 finishKey:达到最大位数自动完成
idcard:
description: "身份证号"
minDigits: 15 # 最少位数
maxDigits: 18 # 最多位数
finishKey: "#"
timeout: 30
validation:
pattern: "^\\d{15}(\\d{2}[0-9X])?$"
errorMessage: "请输入15或18位身份证号"配置说明:
digits: 固定位数(digits: 6等同于minDigits: 6, maxDigits: 6)finishKey: 完成键(#或*)。如果不设置且配置了maxDigits,达到最大位数时自动完成timeout: 从开始收集到超时的总时长(秒)interDigitTimeout: 两次按键之间的超时(秒),超时后尝试验证已收集的数字validation: 正则表达式验证规则和错误提示(可选)retryTimes: 验证失败后的最大重试次数(默认 3 次)interruptible: 是否允许用户在收集过程中通过语音打断(默认 false)
定义好收集器后,系统会自动将可用的收集器信息注入到 LLM 的 System Prompt 中。LLM 可以通过输出 XML 标签来启动收集:
你是智能客服。当需要收集用户的手机号时,使用:
<collect type="phone" var="user_phone" prompt="请输入您的11位手机号,输入完成后按井号键" />参数说明:
type: 收集器类型(对应dtmfCollectors中定义的 key)var: 变量名,收集成功后会存储到通话状态的extras中prompt: 语音提示(可选),告诉用户如何输入
- LLM 输出收集命令:
<collect type="phone" var="user_phone" prompt="请输入手机号" /> - 系统播放提示:播放 prompt 中的文字(TTS)
- 进入收集模式:用户只能按键输入,语音输入会被忽略(除非
interruptible: true) - 收集完成:
- 用户按下完成键(如
#),或 - 达到最大位数(如果未配置完成键),或
- 按键间隔超时
- 用户按下完成键(如
- 验证:
- 检查最少位数(
minDigits) - 匹配正则表达式(
validation.pattern)
- 检查最少位数(
- 结果处理:
- 验证成功:存储到
{{ var_name }},通知 LLM 继续对话 - 验证失败:播放错误提示(
errorMessage),重新收集(最多retryTimes次) - 重试超限:通知 LLM 收集失败,由 LLM 引导用户(如转人工或尝试其他方式)
- 验证成功:存储到
收集成功后,LLM 可以在后续对话中使用 Minijinja 模板语法引用变量:
感谢您提供手机号:{{ user_phone }}。我们将向该号码发送验证码。
<collect type="code" var="sms_code" prompt="请输入您收到的6位短信验证码" />调试提示:
- 收集成功/失败时,系统会向 LLM 发送 System 消息,可以在日志中查看
- 如果收集器类型不存在,系统会向 LLM 返回可用类型列表
- 超时时,如果已收集部分数字,系统会尝试验证;如果没有收集到任何数字,会通知 LLM
---
asr:
provider: "aliyun"
tts:
provider: "aliyun"
llm:
provider: "openai"
model: "gpt-4o"
language: "zh"
dtmfCollectors:
phone:
description: "11位手机号"
digits: 11
finishKey: "#"
validation:
pattern: "^1[3-9]\\d{9}$"
errorMessage: "请输入有效的11位手机号"
retryTimes: 3
code:
description: "6位验证码"
digits: 6
retryTimes: 2
---
# 身份验证客服
你是银行客服。需要先验证用户身份:
1. 首先收集手机号:<collect type="phone" var="user_phone" prompt="请输入您的11位手机号,输入完成后按井号键" />
2. 收集验证码:<collect type="code" var="sms_code" prompt="请输入您收到的6位短信验证码" />
3. 验证成功后,为用户办理业务
对于输入错误,请友好引导用户重新输入。如果多次失败,提示转人工服务。如果模型支持 Realtime API (如 OpenAI gpt-4o-realtime),可跳过序列化 pipeline 以获得超低延迟:
realtime:
provider: "openai"
model: "gpt-4o-realtime-preview"
voice: "alloy"
turn_detection:
type: "server_vad"
threshold: 0.5在 llm 配置中启用功能后,AI 可以调用内置的知识库检索逻辑。
默认情况下,系统会根据 language 配置(如 "en" 为英文,"zh" 为中文)在提示词中包含工具使用说明。这些说明告诉 LLM 如何使用 <hangup/>、<refer/> 等命令。
方法1: 使用语言特定的默认说明
在 LLM 配置中设置 language 字段:
llm:
language: "zh" # 将使用 features/tool_instructions.zh.md方法2: 提供自定义说明 完全覆盖默认的工具使用说明:
llm:
toolInstructions: |
针对您特定用例的自定义说明。
您可以在这里定义自己的工具使用格式。方法3: 修改特性文件 直接编辑文件:
features/tool_instructions.zh.md用于中文features/tool_instructions.en.md用于英文- 添加您自己的语言:
features/tool_instructions.ja.md用于日语
这允许您:
- 将工具说明翻译成任何语言
- 添加特定领域的指导
- 自定义说明的格式和风格
通话挂断后,自动生成摘要并推送到业务系统:
posthook:
url: "https://your-crm.com/api/callback"
summary: "detailed" # 摘要精细度: short, detailed, intent, json
method: "POST" # HTTP 方法(默认 POST)
headers:
Authorization: "Bearer ${API_TOKEN}"
include_history: true # 是否包含完整对话历史
timeout: 30 # 请求超时(秒,默认 30)摘要类型说明:
short: 一句话简短摘要detailed: 详细对话摘要intent: 仅提取用户意图json: 结构化 JSON,含主被叫、时长、意图、关键信息等
- 短句原则: 在提示词中要求 AI 使用短句,因为系统会按句子流式合成语音,句子越短响应越快。
- 打断保护: 如果 AI 说话很关键,可以在 Front Matter 中设置
interruption.strategy: "none"临时禁止打断。 - 转接兜底: 在提供转接功能时,务必告知 AI 如果转接失败该如何安抚用户。
- 变量注入: Playbook 支持 Minijinja 模板语法,你可以在启动呼叫时动态注入变量。
- 普通变量:
{{ user_name }} - SIP Headers(包含连字符):
{{ sip["X-Customer-ID"] }}(详见高级特性文档)
- 普通变量: