在开放办公区、展厅、客厅这种地方,旁边人随口一句话就可能被智能体当成指令。用户正说到一半,同事在两米外聊天,智能体转头回答同事去了——这个问题在 Demo 里不存在,一到真实环境就非常明显。
选择性注意力锁定(SAL)就是干这个的:对话初期锁定一位清晰的主讲人,之后抑制其他人声和环境噪声。打开之后,展厅里路人的交谈、开放工位邻座的讨论,都不会再把对话劫持走。识别准确率和对话连贯性都会明显改善,用户也不用再刻意压低声音或者把设备端到脸前。
本文用的是 sal_mode="locking" 无感锁定模式,不用上传声纹样本。它解决的是「优先听谁」,不是身份认证——不能拿它替代登录、支付确认或生物识别鉴权。这条边界要划清楚。
配好之后你会明显感觉到:智能体优先响应主讲人的指令,侧后方其他人说话基本被忽略。
一. 架构与准备工作
主讲人 ──┐
旁人声 ──┼── RTC 音频 → SAL locking → 凤鸣 → DeepSeek → MiniMax
环境声 ──┘ │
保留主讲人
需要开通了对话式 AI 引擎的 App ID、主要证书、DeepSeek 和 MiniMax Key,使用 agora-agents==2.4.1。SAL 目前是 Beta 能力,正式上线前记得确认项目权限、计费,以及在你的目标设备上实际效果如何。
二. 环境变量
AGORA_APP_ID=REPLACE_WITH_SHENGWANG_APP_ID
AGORA_APP_CERTIFICATE=REPLACE_WITH_PRIMARY_CERTIFICATE
DEEPSEEK_API_KEY=REPLACE_WITH_DEEPSEEK_KEY
MINIMAX_API_KEY=REPLACE_WITH_MINIMAX_KEY
三. SAL 配置
def speaker_lock_config() -> dict[str, str]:
return {"sal_mode": "locking"}
无感模式不需要 sample_urls,配置就这两行。
关键在使用方式:会话启动后,让目标用户在相对安静的环境里靠近麦克风,先大声、清晰地说一句完整的话。这一句是给系统建立锁定用的,开头这几秒说得清楚,后面整场对话都受益。
四. 构造智能体
import os
from agora_agent import Area, AsyncAgora
from agora_agent.agentkit import Agent
from agora_agent.cn import DeepSeekLLM, FengmingSTT, MiniMaxTTS
client = AsyncAgora(
area=Area.CN,
app_id=os.environ["AGORA_APP_ID"],
app_certificate=os.environ["AGORA_APP_CERTIFICATE"],
)
llm = DeepSeekLLM(
api_key=os.environ["DEEPSEEK_API_KEY"],
base_url="https://api.deepseek.com/chat/completions",
model="deepseek-v4-flash",
system_messages=[{"role": "system", "content":
"你是专注、简洁的中文语音助手。只处理主讲人的请求,"
"回答控制在一至两句话;不确定时明确说明。"}],
greeting_message=(
"你好,请在安静环境下清晰说一句话,我会优先锁定你的声音。"
),
failure_message="抱歉,我暂时没有听清,请靠近麦克风再说一次。",
max_history=20,
max_tokens=512,
temperature=0.3,
params={"thinking": {"type": "disabled"}},
)
tts = MiniMaxTTS(
key=os.environ["MINIMAX_API_KEY"],
model="speech-01-turbo",
voice_id="female-shaonv",
sample_rate=16000,
language_boost="Chinese",
)
agent = (
Agent(
client=client,
sal=speaker_lock_config(),
turn_detection={"language": "zh-CN"},
advanced_features={
"enable_rtm": True,
"enable_sal": True,
},
parameters={
"audio_scenario": "chorus",
"data_channel": "rtm",
"enable_metrics": True,
"enable_error_message": True,
},
)
.with_stt(FengmingSTT())
.with_llm(llm)
.with_tts(tts)
.with_labels({"recipe": "speaker-lock", "sal_mode": "locking"})
)
advanced_features.enable_sal 和 sal.sal_mode 必须同时配,少一个都不生效。这里同样显式关闭了 DeepSeek thinking,避免推理文本混进字幕和播报。
五. 启动与停止
from typing import Any
sessions: dict[str, Any] = {}
async def start_agent(
channel: str,
agent_uid: int,
user_uid: int,
) -> str:
session = agent.create_async_session(
channel=channel,
agent_uid=str(agent_uid),
remote_uids=[str(user_uid)],
enable_string_uid=False,
idle_timeout=120,
expires_in=3600,
)
agent_id = await session.start()
sessions[agent_id] = session
return agent_id
async def stop_agent(agent_id: str) -> None:
session = sessions.pop(agent_id, None)
if session is not None:
await session.stop()
完整的三段式 FastAPI 接口在交付目录 code/speaker-lock 里。
六. 运行与验证
cd code/speaker-lock
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env.local
uvicorn app:app --host 0.0.0.0 --port 8000
这个功能没法一个人测,得找两位声音差异明显的同事:
- A 靠近麦克风,清晰地说「请记住主讲人是我」。
- A 连问两轮,确认识别、字幕、回答都正常。
- B 在侧后方说别的指令,确认智能体不会频繁转向 B。
- A 再说新指令,确认自己还能正常触发。
- 换设备、换距离、加噪声重复一遍,记录误接受和误拒绝的次数。
合理的预期是:主讲人的指令明显优先,背景人声大部分被抑制。但别指望在所有麦克风、所有混响条件、声线相似的两个人之间做到百分之百隔离——这是信号处理问题,不是开关问题。
七. 故障排查
- 智能体还在响应旁人:可能是开头锁错人了。停止会话,调整好距离,让目标用户先说一句完整的话再开始。
- 主讲人自己也触发不了:检查麦克风增益、距离和回声消除,并确保开场时不要多人同时说话。
- 创建智能体返回 SAL 相关错误:确认项目已开通对应的 Beta 能力,并且
enable_sal和sal两处都传了。 - 再说一遍:涉及支付、隐私数据、账号变更时,仍然要走服务端身份验证和二次确认。主讲人锁定不是鉴权手段。
八. 下一步
锁定了听谁说,接下来是决定什么时候该让它闭嘴。
《语音智能体打断实战:VAD、关键词与不可打断》