概述

开源地址:HumanAIGC-Engineering/OpenAvatarChathttps://github.com/HumanAIGC-Engineering/OpenAvatarChat

本文档详细说明了OpenAvatarChat项目中TTS(文本转语音)和LLM(大语言模型)处理器的工作原理、输入输出要求以及处理流程。

LLM处理器详细说明

1. 基本信息

文件位置: src/handlers/llm/openai_compatible/llm_handler_openai_compatible.py

主要类: HandlerLLM

2. 配置参数 (LLMConfig)

class LLMConfig(HandlerBaseConfigModel, BaseModel):
    model_name: str = Field(default="qwen-plus")  # 模型名称
    system_prompt: str = Field(default="请你扮演一个 AI 助手,用简短的对话来回答用户的问题,并在对话内容中加入合适的标点符号,不需要加入标点符号相关的内容")
    api_key: str = Field(default=os.getenv("DASHSCOPE_API_KEY"))  # API密钥
    api_url: str = Field(default=None)  # API地址
    enable_video_input: bool = Field(default=False)  # 是否启用视频输入

3. 输入要求

3.1 支持的输入类型
  • HUMAN_TEXT: 用户输入的文本数据
  • CAMERA_VIDEO: 摄像头视频数据(当enable_video_input=True时)
3.2 输入文本要求
  • 格式: 纯文本字符串
  • 编码: UTF-8
  • 长度限制: 无特定限制,但会受到API提供商的限制
  • 特殊标记: 支持 <|.*|> 格式的特殊标记(会被自动过滤)

4. 输出格式

4.1 输出类型
  • AVATAR_TEXT: AI助手回复的文本
4.2 输出特性
  • 流式输出: 支持实时流式文本生成
  • 元数据: 包含 avatar_text_endspeech_id 元数据
  • 文本结束标记: 通过 avatar_text_end=True 标记文本生成结束

5. 文本处理流程

5.1 输入处理
  1. 文本累积: 将多个输入文本片段累积到 context.input_texts
  2. 结束检测: 等待 human_text_end=True 标记
  3. 文本清理: 使用正则表达式 r"<\|.*?\|>" 移除特殊标记
  4. 长度验证: 检查处理后文本长度是否大于1
5.2 API调用
completion = context.client.chat.completions.create(
    model=context.model_name,
    messages=[
        context.system_prompt,
    ] + current_content,
    stream=True,
    stream_options={"include_usage": True}
)
5.3 响应处理
  1. 流式处理: 逐块处理API响应
  2. 文本输出: 每个文本块立即输出
  3. 历史记录: 完整响应添加到对话历史
  4. 结束标记: 发送结束标记

6. 对话历史管理

文件位置: src/handlers/llm/openai_compatible/chat_history_manager.py

6.1 历史记录特性
  • 最大长度: 20条消息
  • 自动清理: 超出长度时自动删除最早的消息
  • 角色映射: avatar → assistant, human → user
  • 多模态支持: 支持文本和图像输入
6.2 文本过滤规则
def filter_text(text):
    pattern = r"[^a-zA-Z0-9\u4e00-\u9fff,.\~!?,。!? ]"  # 保留字母、数字、中文、基本标点
    filtered_text = re.sub(pattern, "", text)
    return filtered_text

TTS处理器详细说明

1. 基本信息

文件位置: src/handlers/tts/bailian_tts/tts_handler_cosyvoice_bailian.py

主要类: HandlerTTS

API提供商: 阿里云百炼CosyVoice

2. 配置参数 (TTSConfig)

class TTSConfig(HandlerBaseConfigModel, BaseModel):
    ref_audio_path: str = Field(default=None)  # 参考音频路径
    ref_audio_text: str = Field(default=None)  # 参考音频文本
    voice: str = Field(default=None)  # 语音类型
    sample_rate: int = Field(default=24000)  # 采样率
    api_key: str = Field(default=os.getenv("DASHSCOPE_API_KEY"))  # API密钥
    model_name: str = Field(default="cosyvoice-1")  # 模型名称

3. 输入要求

3.1 支持的输入类型
  • AVATAR_TEXT: 来自LLM的文本数据
3.2 输入文本要求
3.2.1 字符过滤规则
def filter_text(self, text):
    pattern = r"[^a-zA-Z0-9\u4e00-\u9fff,.\~!?,。!? ]"  # 匹配不在范围内的字符
    filtered_text = re.sub(pattern, "", text)
    return filtered_text

允许的字符类型:

  • 英文字母 (a-z, A-Z)
  • 数字 (0-9)
  • 中文字符 (\u4e00-\u9fff)
  • 基本标点符号: ,, ., ~, !, ?, , , ,
  • 空格

不允许的字符: 所有其他特殊字符、符号、表情符号等

3.2.2 特殊标记处理
  • 移除标记: 自动移除 <|.*|> 格式的特殊标记
  • 流式处理: 支持流式文本输入,无需等待完整文本

4. 输出格式

4.1 输出类型
  • AVATAR_AUDIO: 合成的音频数据
4.2 音频规格
  • 格式: PCM 16-bit
  • 采样率: 24000 Hz
  • 声道: 单声道 (Mono)
  • 数据类型: numpy.float32 数组
  • 数值范围: [-1.0, 1.0]
4.3 输出特性
  • 流式输出: 实时生成音频片段
  • 缓冲机制: 累积24000字节后输出一个音频片段
  • 元数据: 包含 avatar_speech_endspeech_id

5. 音频处理流程

5.1 初始化阶段
  1. 合成器创建: 创建 SpeechSynthesizer 实例
  2. 回调设置: 设置 CosyvoiceCallBack 处理音频数据
  3. 格式配置: 设置为 PCM_24000HZ_MONO_16BIT 格式
5.2 流式合成
if not text_end:
    if context.synthesizer is None:
        callback = CosyvoiceCallBack(context=context, output_definition=output_definition, speech_id=speech_id)
        context.synthesizer = SpeechSynthesizer(model=self.model_name, voice=self.voice, callback=callback, format=AudioFormat.PCM_24000HZ_MONO_16BIT)
    context.synthesizer.streaming_call(text)
else:
    context.synthesizer.streaming_call(text)
    context.synthesizer.streaming_complete()
    context.synthesizer = None
5.3 音频数据处理

CosyvoiceCallBack类的关键方法:

  1. on_data(): 处理接收到的音频数据

    def on_data(self, data: bytes) -> None:
        self.temp_bytes += data
        if len(self.temp_bytes) > 24000:  # 缓冲阈值
            output_audio = np.array(np.frombuffer(self.temp_bytes, dtype=np.int16)).astype(np.float32)/32767
            output_audio = output_audio[np.newaxis, ...]
            # 输出音频数据
    
  2. on_complete(): 处理合成完成

    • 输出剩余音频数据
    • 发送结束标记 (avatar_speech_end=True)

6. 数据转换详情

6.1 音频格式转换
# 从16-bit PCM转换为float32
output_audio = np.array(np.frombuffer(self.temp_bytes, dtype=np.int16)).astype(np.float32)/32767
# 添加批次维度
output_audio = output_audio[np.newaxis, ...]
6.2 元数据设置
  • avatar_speech_end: 标记音频是否结束
  • speech_id: 语音会话标识符

完整处理流程

1. 数据流向

用户输入 → ASR → HUMAN_TEXT → LLM → AVATAR_TEXT → TTS → AVATAR_AUDIO → Avatar渲染

2. 详细步骤

  1. 用户输入阶段

    • 用户通过麦克风输入语音
    • ASR处理器将语音转换为HUMAN_TEXT
  2. LLM处理阶段

    • 接收HUMAN_TEXT输入
    • 累积文本直到收到结束标记
    • 过滤特殊字符和标记
    • 调用OpenAI兼容API
    • 流式输出AVATAR_TEXT
  3. TTS处理阶段

    • 接收AVATAR_TEXT输入
    • 过滤不支持的字符
    • 调用CosyVoice API进行语音合成
    • 流式输出AVATAR_AUDIO
  4. Avatar渲染阶段

    • 接收AVATAR_AUDIO
    • 驱动数字人口型和表情
    • 实时渲染输出

配置示例

chat_with_gs.yaml中的相关配置

LLM_Bailian:
  module: llm/openai_compatible/llm_handler_openai_compatible
  model_name: "qwen-plus"
  system_prompt: "你是个AI对话数字人,你要用简短的对话来回答我的问题,并在合理的地方插入标点符号"
  api_url: 'https://dashscope.aliyuncs.com/compatible-mode/v1'
  api_key: 'your_api_key'

CosyVoice:
  module: tts/bailian_tts/tts_handler_cosyvoice_bailian
  voice: "longwan"
  model_name: "cosyvoice-1"
  api_key: 'your_api_key'

总结

OpenAvatarChat的TTS和LLM处理器采用了模块化设计,支持流式处理,具有良好的扩展性。LLM处理器负责理解用户输入并生成回复,TTS处理器将文本转换为自然的语音输出。两者协同工作,为用户提供流畅的对话体验。

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐