WebSocket 智能语义分析服务 - 长期记忆增强版

项目概述

这是一个基于 WebSocket 和 Agent-to-Agent (A2A) 架构的智能语音识别服务,具备说话人识别和长期记忆功能。系统能够在同一场会议中,通过学习每个说话人的发言特征,持续提高说话人识别的准确率。

核心特性

1. 实时语音识别处理

  • 接收前端音频流,转发到 ASR 引擎
  • 支持双通道模式2pass和 PCM 音频格式
  • 实时推送识别结果到前端

2. 多 Agent 协作架构

  • AuditorAgent: 判断说话人是否完成发言
  • ProfilerAgent: 识别说话人身份(支持长期记忆)

3. 长期记忆功能

  • 为每个说话人建立特征档案
  • 持续学习说话人的发言风格和用词习惯
  • 利用会议历史上下文提高识别准确率

4. 完善的日志系统 📝

  • 自动创建日志目录,分级记录运行信息
  • 控制台输出INFO 级别(运行状态)
  • 完整日志文件DEBUG 级别(详细调试信息)
  • 错误日志文件ERROR 级别(错误和异常)
  • 所有日志包含时间戳和上下文信息

日志系统说明

日志文件位置

程序运行时会在项目根目录下创建 logs 文件夹,包含以下日志文件:

logs/
├── a2a_wss.log          # 完整日志DEBUG 级别)
└── a2a_wss_error.log   # 错误日志ERROR 级别)

日志级别说明

级别 说明 使用场景 输出位置
DEBUG 调试信息 详细的程序执行流程、变量值等 仅日志文件
INFO 一般信息 关键业务流程、状态变更 控制台 + 日志文件
ERROR 错误信息 异常、错误堆栈 控制台 + 日志文件 + 错误日志

日志内容示例

2025-01-07 14:30:15 - root - INFO - 启动 WebSocket 智能语义分析服务: ws://0.0.0.0:10095
2025-01-07 14:30:15 - root - INFO - Agent 模型: Qwen3-32B
2025-01-07 14:30:15 - root - INFO - ASR 服务地址: ws://localhost:59805/ws/asr
2025-01-07 14:30:15 - root - INFO - Redis 地址: redis://localhost:6379/0
2025-01-07 14:30:20 - root - INFO - 客户端已连接
2025-01-07 14:30:20 - root - INFO - 已连接到 ASR 服务: ws://localhost:59805/ws/asr
2025-01-07 14:30:22 - root - DEBUG - 收到 ASR 识别结果: 各位好,今天我们召开月度工作总结会议...
2025-01-07 14:30:23 - root - INFO - [Auditor] 发言完成检测通过 - 会话ID: room_101
2025-01-07 14:30:23 - root - DEBUG - 获取说话人特征库 - 会话ID: room_101, 说话人数量: 0
2025-01-07 14:30:24 - root - INFO - [Profiler] 识别说话人: 主持人 - 会话ID: room_101

日志配置

日志系统在代码中自动配置(无需手动配置),包含:

  1. 日志格式时间 - 记录器名称 - 级别 - 消息
  2. 编码UTF-8支持中文
  3. 自动创建目录:首次运行时自动创建 logs 文件夹
  4. 错误追踪ERROR 级别日志包含完整的异常堆栈信息

日志查看建议

  • 实时监控tail -f logs/a2a_wss.log
  • 查看错误cat logs/a2a_wss_error.log
  • 搜索关键词grep "识别说话人" logs/a2a_wss.log
  • 统计分析grep "ERROR" logs/a2a_wss_error.log | wc -l

长期记忆功能详解

功能说明

长期记忆功能使得系统能够在同一场会议中,记住每个说话人的发言特征,并利用这些历史信息来辅助后续的说话人识别。

工作流程

┌─────────────┐
│ 开始会议    │
└──────┬──────┘
       │
       ▼
┌─────────────────────┐
│ 接收语音片段        │
└──────┬──────────────┘
       │
       ▼
┌─────────────────────┐
│ 累积到缓冲区        │
└──────┬──────────────┘
       │
       ▼
┌─────────────────────┐
│ Auditor: 判断发言   │
│ 是否完成            │
└──────┬──────────────┘
       │
       ▼ (发言完成)
┌──────────────────────────────┐
│ 获取长期记忆                 │
│ (所有说话人的历史特征)       │
└──────┬───────────────────────┘
       │
       ▼
┌──────────────────────────────┐
│ Profiler: 识别说话人         │
│ - 分析会议历史记录           │
│ - 对比说话人特征库           │
│ - 判断对话流程和上下文       │
└──────┬───────────────────────┘
       │
       ▼
┌──────────────────────────────┐
│ 更新长期记忆                 │
│ (保存当前发言到特征库)       │
└──────┬───────────────────────┘
       │
       ▼
┌─────────────────────┐
│ 推送结果到前端       │
└─────────────────────┘

核心改进

1. Redis 存储扩展

新增方法

  • save_speaker_profile(sid, speaker, text, features): 保存说话人特征到长期记忆

    • 保留每个说话人最近 10 条发言记录
    • 存储发言文本片段(前 200 字符)
    • 记录时间戳和可选的特征向量
  • get_speaker_profiles(sid): 获取所有说话人的历史特征

    • 返回字典格式:{说话人: [历史记录列表]}
    • 用于 Agent 分析时参考

2. ProfilerAgent 增强

改进的识别逻辑

  • 历史记录分析:查看最近 15 条对话,理解会议上下文
  • 对话流程分析:判断当前发言是对之前谁的话题的回应
  • 说话风格匹配:对比每个角色的用词习惯、句式结构、语气
  • 角色职责判断:根据发言内容是否符合角色职责范围
  • 话题连贯性:当前发言与该角色历史话题的连贯性

提示词优化

# 增强版系统提示词包含4个分析维度
1. 对话流程分析
2. 说话风格匹配
3. 角色职责判断
4. 话题连贯性

3. A2AOrchestrator 集成

process_asr_fragment() 方法中集成长期记忆:

# 1. 获取长期记忆(说话人特征库)
speaker_profiles = await self.redis.get_speaker_profiles(session_id)

# 2. 使用长期记忆识别说话人
speaker = await self.profiler.identify(buf, history, speaker_profiles)

# 3. 保存到长期记忆(持续学习)
await self.redis.save_speaker_profile(session_id, speaker, buf)

配置说明

环境变量

变量名 说明 默认值
TARGET_WS_URL ASR 服务的 WebSocket 地址 ws://localhost:59805/ws/asr
REDIS_URL Redis 连接地址 redis://localhost:6379/0
LLM_API_KEY 大语言模型 API Key sk-xxxx
LLM_BASE_URL 大语言模型服务地址 http://172.18.127.124:9997/v1
LLM_MODEL 使用的模型名称 Qwen3-32B

候选说话人列表

在代码中配置(CANDIDATE_SPEAKERS

CANDIDATE_SPEAKERS = [
    "局长",
    "主持人",
    "商务专员",
    "市场专员",
    "控制要素席",
    "空中侦察席"
]

Redis 数据结构

键命名规范

meeting:buffer:{session_id}           # 会话文本缓冲
meeting:history:{session_id}          # 会话历史记录
meeting:speaker_profile:{session_id}:{speaker}  # 说话人特征库

数据类型

  • 缓冲区: String (累积的未完成发言)
  • 历史记录: List (最多 20 条)
  • 说话人特征: List (每个说话人最多 10 条)

使用示例

安装依赖

首先确保已安装 Python 3.8+,然后安装所需依赖:

# 在项目根目录下执行
pip install -r requirements.txt

启动服务

# 在 src 目录下执行
python a2a_wss.py

服务将监听 ws://0.0.0.0:10095

连接和消息格式

前端发送配置

{
  "mode": "2pass",
  "chunk_size": [10, 10, 10],
  "wav_format": "pcm"
}

前端发送音频: 二进制 PCM 数据

后端返回结果

{
  "mode": "offline-speaker",
  "type": "asr_with_speaker",
  "segments": [{
    "id": 0,
    "speaker": "局长",
    "embedding": null,
    "seek": 0,
    "full_text": "今天我们讨论一下市场推广方案"
  }],
  "speaker": "局长"
}

长期记忆的工作示例

会议初期(无记忆)

历史记录: [暂无]
说话人特征库: [暂无]

当前发言: "各位好,今天我们召开月度工作总结会议"

识别结果: 主持人 (基于内容特征)

会议中期(有部分记忆)

历史记录:
[1] 主持人: 各位好,今天我们召开月度工作总结会议
[2] 局长: 本月工作总体进展顺利
[3] 商务专员: 我们完成了三个重要合同的签署
[4] 市场专员: 市场推广活动覆盖了五个新城市

说话人特征库:
- 【主持人】(发言1次): 各位好,今天我们召开月度工作总结会议
- 【局长】(发言1次): 本月工作总体进展顺利
- 【商务专员】(发言1次): 我们完成了三个重要合同的签署
- 【市场专员】(发言1次): 市场推广活动覆盖了五个新城市

当前发言: "关于下个月的计划,我们需要重点关注客户反馈"

识别结果: 市场专员
分析:
- 延续了市场专员之前的话题(市场推广)
- 符合市场专员的职责范围(客户反馈)
- 用词风格与历史记录匹配

会议后期(丰富记忆)

历史记录: [15条完整对话记录]

说话人特征库:
- 【局长】(发言4次): 本月工作总体进展顺利; 很好,各部门配合默契;
  这次会议很有成效; 最后强调一下安全问题
- 【主持人】(发言3次): 各位好,今天我们召开月度工作总结会议;
  下面请商务专员汇报; 时间关系,今天的会议就到这里
- 【商务专员】(发言5次): 我们完成了三个重要合同的签署;
  这三个合同总金额达500万; 客户对我们的方案很满意;
  下季度重点跟进大客户; 需要技术部门的支持
...

当前发言: "技术部门会全力支持商务工作,确保项目交付质量"

识别结果: (未出现在候选列表中,或需要进一步判断)
分析:
- 提到了"技术部门",可能是技术相关角色
- 对之前商务专员的话题做出回应
- 风式偏向技术人员的特点(强调"质量"、"交付"

性能优化

1. 数据限制

  • 历史记录:最多保留 20 条
  • 每个说话人特征:最多保留 10 条
  • LLM 上下文:使用最近 15 条历史记录

2. 异步处理

  • Agent 处理使用后台任务,不阻塞主循环
  • 连接关闭时等待任务完成(最多 5 秒)

3. Redis 连接池

  • 使用连接池提高并发性能
  • 自动编码/解码 JSON 数据

技术栈

  • Python 3.8+
  • websockets: WebSocket 通信
  • redis: 会话状态和长期记忆存储
  • openai: 大语言模型调用
  • logging: 日志记录和系统监控
  • asyncio: 异步编程

代码结构

a2a_wss.py
├── 基础配置 (1-48行)
├── RedisManager 类 (52-199行)
│   ├── 会话缓冲管理
│   ├── 历史记录管理
│   └── 说话人特征库管理 ⭐新增
├── Agent 基类 (154-208行)
├── AuditorAgent 类 (211-235行)
├── ProfilerAgent 类 (238-369行) ⭐增强
│   ├── 长期记忆提示词
│   ├── 会议历史分析
│   └── 说话人特征匹配
├── A2AOrchestrator 类 (372-343行) ⭐集成
│   └── process_asr_fragment() 方法
└── WebSocket 处理 (352-450行)

注意事项

  1. Redis 依赖: 确保 Redis 服务正常运行
  2. LLM 可用性: 确保大语言模型服务可访问
  3. 内存管理: 长时间运行的会议会累积数据,建议定期清理
  4. 识别准确率: 长期记忆随时间累积,会议初期识别准确率可能较低

未来改进方向

  1. 跨会议记忆: 支持多场会议之间的说话人特征迁移
  2. 特征工程: 提取更多说话人特征(语速、停顿模式等)
  3. 置信度评分: 为每次识别添加置信度分数
  4. 自适应学习: 根据识别准确率动态调整特征权重
  5. 多模态融合: 结合声学特征提高识别准确率

作者和许可

本项目为智能语音识别系统的核心组件,采用 Agent-to-Agent 编排模式。

最后更新: 2025-01-07