如何开发双语语音助手

如何开发双语语音助手

原文:towardsdatascience.com/developing-a-bilingual-voice-assistant/

谷歌 Nest、亚马逊 Alexa和 Siri 是普遍使用的语音助手,它们服务于今天大多数互联网连接的群体。就大部分而言,英语是这些语音助手使用的占主导地位的语言。然而,为了使语音助手真正有用,它必须能够理解用户自然说话的方式。在世界的许多地方,尤其是在像印度这样的多元文化国家,人们通常会说多种语言,并在一次对话中切换到多种语言。一个真正智能的助手应该能够处理这种情况。

谷歌助手提供了添加第二种语言的能力;但它的功能仅限于某些设备,并且仅对一组主要语言提供此功能。例如,谷歌的 Nest Hub 目前还不支持泰米尔语的双语能力,泰米尔语是一种由超过 8000 万人使用的语言。只要内部语言对得到支持,亚马逊 Alexa 就支持双语方法;但同样,这也仅限于一组主要语言。Siri 没有双语能力,并且一次只能支持一种语言。

在这篇文章中,我将讨论实现我的语音助手具有双语能力(英语和泰米尔语)所采取的方法。使用这种方法,语音助手将能够通过直接分析音频自动检测说话者使用的语言。通过使用基于“置信度分数”的算法,系统将确定是英语还是泰米尔语被说出,并以相应的语言进行回应。

双语能力的方法

为了使助手理解英语和泰米尔语,有几种可能的解决方案。第一种方法是从头开始训练一个定制的机器学习模型,专门针对泰米尔语数据,然后将该模型集成到 Raspberry Pi 中。虽然这将提供高度定制化,但这是一个耗时且资源密集的过程。训练模型需要一个庞大的数据集和显著的计算能力。此外,运行一个重量级的自定义模型可能会减慢 Raspberry Pi 的速度,导致用户体验不佳。

fastText 方法

一个更实际的解决方案是使用已经针对特定任务优化过的现有、预训练模型。对于语言识别,一个很好的选择是 fastText。

fastText 是由 Facebook AI Research 开发的一个开源库,用于高效的文本分类和词表示。它附带预训练模型,可以快速准确地从大量语言中识别给定文本的语言。因为它轻量级且高度优化,非常适合在资源受限的设备上运行,如 Raspberry Pi,而不会引起重大的性能问题。因此,计划是使用fastText来对用户的说话语言进行分类。

要使用 fastText,你需要下载相应的模型(lid.176.bin)并将其存储在你的项目文件夹中。指定这个路径为 MODEL_PATH 并加载模型。

import fastText
import speech_recognition as sr
import fasttext

# --- Configuration ---
MODEL_PATH = "./lid.176.bin" # This is the model file you downloaded and unzipped

# --- Main Application Logic ---
print("Loading fastText language identification model...")
try:
    # Load the pre-trained model
    model = fasttext.load_model(MODEL_PATH)
except Exception as e:
    print(f"FATAL ERROR: Could not load the fastText model. Error: {e}")
    exit()

下一步是将语音命令作为录音传递给模型,并获取预测结果。这可以通过一个专用函数实现。

def identify_language(text, model):
    # The model.predict() function returns a tuple of labels and probabilities
    predictions = model.predict(text, k=1)
    language_code = predictions[0][0] # e.g., '__label__en'
    return language_code

try:
    with microphone as source:
        recognizer.adjust_for_ambient_noise(source, duration=1)
        print("\nPlease speak now...")
        audio = recognizer.listen(source, phrase_time_limit=8)

    print("Transcribing audio...")
    # Get a rough transcription without specifying a language
    transcription = recognizer.recognize_google(audio)
    print(f"Heard: \"{transcription}\"")

    # Identify the language from the transcribed text
    language = identify_language(transcription, model)

    if language == '__label__en':
        print("\n---> Result: The detected language is English. <---")
    elif language == '__label__ta':
        print("\n---> Result: The detected language is Tamil. <---")
    else:
        print(f"\n---> Result: Detected a different language: {language}")

except sr.UnknownValueError:
    print("Could not understand the audio.")
except sr.RequestError as e:
    print(f"Speech recognition service error; {e}")
except Exception as e:
    print(f"An unexpected error occurred: {e}")

上面的代码块遵循一个简单的路径。它使用*recognizer.recognize_google(audio)*函数来转录语音命令,然后将这个转录文本传递给 fastText 模型以获取语言预测。如果预测结果是“__label__en”,则检测到英语;如果预测结果是“__label_ta”,则检测到泰米尔语。

这种方法虽然导致了预测效果不佳。问题在于speech_recognition库默认为英语。所以当我用泰米尔语说话时,它会找到最接近(且不正确)的英语发音相似的单词,并将其传递给 fastText。

例如,当我说了“En Peyar enna” (What is my Name in Tamil)时,speech_recognition将其理解为了“Empire NA”,因此 fastText 预测语言为英语。为了克服这个问题,我可以将speech_recognition函数硬编码以仅检测泰米尔语。但这样就会违背了真正“智能”和“双语”的理念。助手应该能够根据所说话语来检测语言,而不是基于硬编码的内容。

图片

照片由Siora PhotographyUnsplash提供

“置信度分数”方法

我们需要的是一个更直接且数据驱动的解决方案。这个解决方案在 speech_recognition 库的一个特性中。***recognizer.recognize_google()***函数是 Google 语音识别 API,它可以转录多种语言的音频,包括英语和泰米尔语。这个 API 的一个关键特性是,对于它提供的每一份转录,它还可以返回一个置信度分数——一个介于 0 和 1 之间的数值,表示其转录正确性的确定性。

这个特性允许我们采用更加优雅和动态的语言识别方法。让我们看看代码。

def recognize_with_confidence(recognizer, audio_data):

    tamil_text = None
    tamil_confidence = 0.0
    english_text = None
    english_confidence = 0.0

    # 1\. Attempt to recognize as Tamil and get confidence
    try:
        print("Attempting to transcribe as Tamil...")
        # show_all=True returns a dictionary with transcription alternatives
        response_tamil = recognizer.recognize_google(audio_data, language='ta-IN', show_all=True)
        # We only look at the top alternative
        if response_tamil and 'alternative' in response_tamil:
            top_alternative = response_tamil['alternative'][0]
            tamil_text = top_alternative['transcript']
            if 'confidence' in top_alternative:
                tamil_confidence = top_alternative['confidence']
            else:
                tamil_confidence = 0.8 # Assign a default high confidence if not provided
    except sr.UnknownValueError:
        print("Could not understand audio as Tamil.")
    except sr.RequestError as e:
        print(f"Tamil recognition service error; {e}")

    # 2\. Attempt to recognize as English and get confidence
    try:
        print("Attempting to transcribe as English...")
        response_english = recognizer.recognize_google(audio_data, language='en-US', show_all=True)
        if response_english and 'alternative' in response_english:
            top_alternative = response_english['alternative'][0]
            english_text = top_alternative['transcript']
            if 'confidence' in top_alternative:
                english_confidence = top_alternative['confidence']
            else:
                english_confidence = 0.8 # Assign a default high confidence
    except sr.UnknownValueError:
        print("Could not understand audio as English.")
    except sr.RequestError as e:
        print(f"English recognition service error; {e}")

    # 3\. Compare confidence scores and return the winner
    print(f"\nConfidence Scores -> Tamil: {tamil_confidence:.2f}, English: {english_confidence:.2f}")
    if tamil_confidence > english_confidence:
        return tamil_text, "Tamil"
    elif english_confidence > tamil_confidence:
        return english_text, "English"
    else:
        # If scores are equal (or both zero), return neither
        return None, None

这个代码块中的逻辑很简单。我们将音频传递给 *recognize_google() *函数,并获取所有替代方案及其分数。首先,我们尝试使用泰米尔语,并获取相应的置信度分数。然后,我们尝试用英语播放相同的音频,并从 API 获取相应的置信度分数。一旦我们有了这两个分数,我们就比较置信度分数,并选择分数更高的作为系统检测到的语言。

下面是当我用英语和泰米尔语说话时函数的输出。

以下是 Visual Studio 输出的截图(泰米尔语)。图片归作者所有。

以下是 Visual Studio 输出的截图(英语)。图片归作者所有。

上述结果显示了代码如何根据置信度分数动态理解所说话的语言。

将所有这些放在一起——双语助手

最后一步是将这种方法集成到基于 Raspberry Pi 的语音助手代码中。完整的代码可以在我的GitHub上找到。一旦集成,下一步将是通过用英语和泰米尔语说话来测试语音助手的性能,并查看它对每种语言的响应。下面的录音展示了双语语音助手在用英语和泰米尔语提问时的功能。

结论

在这篇文章中,我们看到了如何成功地将一个简单的语音助手升级为一个真正的双语工具。通过实现“置信度分数”算法,系统可以确定一个命令是用英语还是泰米尔语说的,允许它以用户选择的特定查询语言理解和回复。这创造了一个更自然和无缝的对话体验。

这种方法的关键优势是其可靠性和可扩展性。虽然这个项目只关注了两种语言,但相同的置信度分数逻辑可以很容易地通过为每种新语言添加一个 API 调用并比较所有结果来扩展到支持三种、四种或更多语言。这里探索的技术为创建更高级和直观的个人 AI 工具提供了一个稳健的基础。

参考文献:

[1] A. Joulin, E. Grave, P. Bojanowski, T. Mikolov, Bag of Tricks for Efficient Text Classification

[2] A. Joulin, E. Grave, P. Bojanowski, M. Douze, H. Jégou, T. Mikolov, FastText.zip: Compressing text classification models

posted @ 2026-03-28 09:27  绝不原创的飞龙  阅读(0)  评论(0)    收藏  举报