基于Ernie-Bot打造语音对话功能

大模型场景实战培训,提示词效果调优,大模型应用定制开发,点击咨询
咨询热线:400-920-8999转2

GPT-4的语音对话功能前段时间在网上火了一把,许多人被其强大的自然语言处理能力和流畅的语音交互所吸引。现在,让我们来看看如何使用类似的技术,即基于百度的ERNIE-Bot,来打造自己的语音对话功能。ERNIE-Bot是一种先进的语言理解模型,可以处理复杂的语言任务,包括语音到文本的转换和自然语言理解。

视频演示:
shequ.mov

涉及技术:

依赖:

  • ffmpeg

langchain调用Ernie-bot并实现记忆

值得一提的是,在langchain构建ernie-bot多轮对话能力上,社区中已有成员对此进行了深入研究和实践: https://cloud.baidu.com/qianfandev/topic/267682

from langchain.chat_models import ErnieBotChat
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
from langchain.memory import ConversationBufferMemory
# 定义一个大语言模型对象
llm = ErnieBotChat(ernie_client_id="xxxxx", 
            ernie_client_secret="xxxxxx",
            model_name='ERNIE-Bot',
            temperature=0.01
    ) 
    
# 定义prompt template    
template = """You are a chatbot having a conversation with a human. Please answer as briefly as possible.

{chat_history}
Human: {human_input}
Chatbot:
"""

prompt = PromptTemplate(
    input_variables=["chat_history", "human_input"], template=template
)
# memory
memory = ConversationBufferMemory(llm=llm,memory_key="chat_history",return_messages=True)
# chain
conversation = LLMChain(llm=llm, memory=memory,prompt=prompt)
# 推理
response = conversation.predict(human_input=input)

语音识别部分

目前,百度语音识别服务支持固定的采样率:16000Hz 和 8000Hz。为了确保您的音频文件与这些标准兼容,可能需要对原始音频的采样率进行适当调整。这意味着,如果您的音频文件采样率与上述两个固定值不符,您将需要通过音频处理软件或编程方法,将其转换为这两种支持的采样率之一。这个步骤是确保音频识别准确性的关键,可以显著提高语音识别的效果和准确度。
详情参考: https://ai.baidu.com/ai-doc/SPEECH/0lbxfnc9b

from aip import AipSpeech
import tempfile
import os, uuid
from pydub import AudioSegment

APP_ID = 'xxx'
API_KEY = 'xxxxx'
SECRET_KEY = 'xxxxxxxxx'

client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)

def transcribe(audio):
    with tempfile.TemporaryDirectory() as tempdir:
        print(f"Temporary directory created at {tempdir}")
        audio = AudioSegment.from_file(audio)

        new_frame_rate = 16000
        new_audio = audio.set_frame_rate(new_frame_rate)

        random_code = uuid.uuid4()
        temp_audio_path = f"{tempdir}/output_audio_16000_{random_code}.wav"
        new_audio.export(temp_audio_path, format="wav")

                
        def get_file_content(filePath):
            with open(filePath, 'rb') as fp:
                return fp.read()

        ret = client.asr(get_file_content(temp_audio_path), 'wav', 16000, {'dev_pid': 1537})
     
    # 注意:退出 with 块后,tempdir 及其内容会被自动删除
    return ret.get('result')[0]

语音合成部分

将大型语言模型生成的文本内容转换成语音输出是一个引人入胜的过程。通过这种转换,我们可以将模型的文字回应转化为更加生动、直观的语音形式。这不仅提升了用户体验,还增加了交互的可访问性和便利性。无论是为视觉受限用户提供更加友好的界面,还是为智能助理增添自然的交流方式,这一过程都显得至关重要。
参考语音合成SDK: https://ai.baidu.com/ai-doc/SPEECH/plbxhh4be

from pydub import AudioSegment
from pydub.playback import play

def play_voice(text):
    result = client.synthesis(text, 'zh', 1, {'vol': 5})
    # 识别正确返回语音二进制 错误则返回dict 参照下面错误码
    if not isinstance(result, dict):
        with tempfile.NamedTemporaryFile(delete=True, suffix='.mp3', mode='wb') as temp_audio_file:
            temp_audio_file.write(result)
            temp_audio_file.seek(0)  # 回到文件开头
            # print(temp_audio_file.name)
            # 使用 pydub 播放音频
            audio = AudioSegment.from_file(temp_audio_file.name, format="mp3")
            play(audio)

gradio交互逻辑

gradio的核心代码框架如下:

def clear_history():
    # 返回一个空列表来清空聊天记录
    return [], []

with gr.Blocks(css="#chatbot{height:800px} .overflow-y-auto{height:800px}") as demo:
    chatbot = gr.Chatbot(elem_id="chatbot")
    state = gr.State([])
 
    with gr.Row():
        txt = gr.Textbox(show_label=False, placeholder="Enter text and press enter")
    # 录音功能
    with gr.Row(): 
        # 得到音频文件地址
        audio = gr.Audio(sources="microphone", type="filepath")
    with gr.Row():        
        clear_button = gr.Button("清空聊天记录")
    # 重要逻辑  
    txt.submit(predict, [txt, state], [chatbot, txt, state])    
    audio.change(process_audio, [audio, state], [chatbot, audio, state])

    clear_button.click(clear_history, [], [chatbot, state])            
# 启动gradio
demo.launch(share=False)

代码18/19行重点介绍下

  1. txt.submit(predict, [txt, state], [chatbot, txt, state])

    • txt.submit: 这是Gradio中Textbox组件的一个方法,用于绑定一个函数(在本例中是predict函数)到文本框的输入动作上。当用户在文本框中输入文本并提交(通常是按下回车键)时,绑定的predict函数会被触发。
    • predict: 这是绑定到文本框提交动作的函数。这个函数会在用户提交文本后执行。
    • [txt, state]: 这是传递给predict函数的参数列表。在这里,txt代表文本框的内容,state是一个State组件,用于在Gradio界面中维持状态。
    • [chatbot, txt, state]: 这是predict函数执行后,其输出将被传递的组件列表。在此,函数的输出将被用来更新Chatbot组件(显示对话内容)、清空Textbox组件的文本,以及更新State组件的状态。
  2. audio.change(process_audio, [audio, state], [chatbot, audio, state])

    • audio.change: 这是Gradio中Audio组件的一个方法,用于将一个函数(在这个例子中是process_audio函数)绑定到音频输入的变化上。当用户通过音频组件提供新的音频输入时,绑定的process_audio函数会被触发。
    • process_audio: 这是绑定到音频组件变化的函数。当音频输入改变时,这个函数会执行。
    • [audio, state]: 这是传递给process_audio函数的参数列表。在这里,audio代表音频组件的输入,state仍然是用于维持状态的State组件。
    • [chatbot, audio, state]: 这是process_audio函数执行后,其输出将被传递的组件列表。这意味着函数的输出将用于更新Chatbot组件、重置Audio组件的输入,以及更新State组件的状态。

总的来说,这两行代码将用户界面的交互(文本输入和音频输入)与相应的处理函数(predictprocess_audio)关联起来,并定义了这些函数执行后如何更新界面组件。

两个函数的实现逻辑:

def play_voice(text):
    result = client.synthesis(text, 'zh', 1, {'vol': 5})
    # 识别正确返回语音二进制 错误则返回dict 参照下面错误码
    if not isinstance(result, dict):
        with tempfile.NamedTemporaryFile(delete=True, suffix='.mp3', mode='wb') as temp_audio_file:
            temp_audio_file.write(result)
            temp_audio_file.seek(0)  # 回到文件开头
            # print(temp_audio_file.name)
            # 使用 pydub 播放音频
            audio = AudioSegment.from_file(temp_audio_file.name, format="mp3")
            play(audio)

# 录音文件转文本的过程
def process_audio(audio, history=[]):
    if audio:
        text = transcribe(audio)  
        # print(text)
        if text is None:
            text="你好"
        responses, clear, updated_history = predict(text, history)
        # print(f"====={responses}")
        # print(f"++++{updated_history}")
        # 返回处理结果和 None 来清空音频输入
        return responses, None, updated_history    
    else:       
        # print(f"------{history}")
        return [(u,b) for u,b in zip(history[::2], history[1::2])], None, history
        
    
# 调用ernie-bot对话功能
def predict(input, history=[]):    
    history.append(input)    
    response = conversation.predict(human_input=input)
    history.append(response)
    # history[::2] 切片语法,每隔两个元素提取一个元素,即提取出所有的输入,
    # history[1::2]表示从历史记录中每隔2个元素提取一个元素,即提取出所有的输出
    # zip函数把两个列表元素打包为元组的列表的方式

    play_voice(response)
    responses = [(u,b) for u,b in zip(history[::2], history[1::2])]
    print("==取出输入:",history[::2])
    print("==取出输出:",history[1::2])
    print("组合元组:",responses)
    
    return responses, "", history

通过本文的介绍,我们探索了如何利用ERNIE-Bot来打造一个高效的语音对话功能。从设置开发环境、处理音频文件,到利用ERNIE-Bot进行语言理解和生成语音回应,每一步都是构建这一创新交互体验的关键部分。

  • 11
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
ERNIE-Bot-turbo是一种基于百度AI技术ERNIE(Enhanced Representation through Knowledge Integration)的聊天机器人,它可以进行智能对话和知识问答。ERNIE-Bot-turbo在原有ERNIE-Bot的基础上,通过使用更大的预训练模型ERNIE2.0和更多的训练数据,提高了对话和问答的准确性和流畅性,同时还增加了多轮对话和情感分析等功能。以下是关于ERNIE-Bot-turbo的一些信息: - ERNIE-Bot-turbo的提问方式与普通聊天机器人相同,用户可以直接在对话框中输入问题或语句,ERNIE-Bot-turbo会自动进行分析并给出回答。 - ERNIE-Bot-turbo的知识库涵盖了广泛的领域,包括文化、科技、体育、社会、历史等多个方面,用户可以向ERNIE-Bot-turbo提出不同领域的问题。 - ERNIE-Bot-turbo支持多轮对话,可以针对用户的问题进行追问和回答,实现更加流畅的对话。 - ERNIE-Bot-turbo还具有情感分析功能,可以识别用户的情感状态并根据情感状态给出不同的回答,增强了对话的真实感和情感交互性。 下面是一个样例对话: 用户:你好,请问你叫什么名字? ERNIE-Bot-turbo:你好,我是ERNIE-Bot-turbo,很高兴为您服务。 用户:你会哪些知识领域? ERNIE-Bot-turbo:我的知识库涵盖了广泛的领域,包括文化、科技、体育、社会、历史等多个方面,您可以向我提出不同领域的问题。 用户:你会情感分析吗? ERNIE-Bot-turbo:是的,我能够识别您的情感状态并根据情感状态给出不同的回答,增强了对话的真实感和情感交互性。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值