📘 **TELUS Agriculture & Consumer Goods** 如何通过 **Haystack Agents** 转变促销交易

利用说话人分离功能,全面提升您的 RAG 应用

利用 AssemblyAI 和 Haystack 的说话人标签

LLM 在处理文本数据方面效果惊人。使用 LLM,您无需阅读文档,甚至无需进行 CTRL+F 搜索,即可获得对长文档的复杂问题的答案。但如果您处理的是音频或视频录音呢?

最简单的方法是为 LLM 提供录音的转录文本。这样您就可以捕获音频或视频中说的所有内容。但对于未说出的信息呢?

在有多位说话人的音频或视频录音中,仅转录录音无法向 LLM 提供所有信息。关于有多少人在说话、他们各自说了什么的数据在书面格式中丢失了。

那么,使用 LLM 处理多说话人录音是否就无法发挥其全部潜力了?当然可以,通过 **说话人分离**!

说话人分离简介

通过 AssemblyAI 的 assemblyai-haystack Python 包,您只需 10 分钟即可构建。说话人分离模型可让您检测音频文件中的多个说话人以及他们各自所说的话。得益于内置的说话人分离功能,您可以获得普通格式的音频或视频录音转录文本,以及说话人注释格式,其中录音中的每一句话都归属于一位说话人。效果如下

说话人 B早上好。

说话人 A那么,目前是什么情况导致这一轮野火影响到如此多远方的民众?

说话人 B嗯,有几个原因。这个季节已经相当干燥了,然后我们在美国受到影响。是因为有几个天气系统基本上将加拿大野火产生的烟雾输送到宾夕法尼亚州,进入中大西洋和东北部地区,并将烟雾滞留在那里。

说话人 A那么,这种雾霾中有哪些成分使其有害?我猜是有的。

让我们先通过示例了解一下将说话人注释的转录文本传递给 LLM 的好处。稍后,我们将介绍可用于构建带有说话人标签转录文本的代码。

为了进行比较,我们运行了两个 RAG 应用,一个使用了录音的转录文本,另一个使用了说话人标签转录文本,以比较它们的响应。从现在起,我们将它们称为转录应用和说话人应用。

以下是示例中使用的 YouTube 视频

#1:利用说话人标签,我们可以分别获取每个人的观点

在这次小组讨论中,各位发言人讨论了 AI 技术以及他们如何在各自的组织中利用 AI。在讨论的中间部分,他们回答了主持人关于如何看待内部构建 AI 与使用第三方供应商的问题。

转录应用只能评论小组讨论中传达的总体想法。它无法区分不同说话人的观点。而说话人应用则报告每个说话人的观点。

音频文件:小组讨论 👇

问题:“各位发言人对内部构建还是使用第三方有什么看法?”

转录应用 说话人应用
“发言人认为,内部构建或使用第三方没有放之四海而皆准的方法。他们采取混合方法,考虑核心知识产权、可行性和价值等因素。他们强调了明确如何使用时间和资源以及合作和伙伴关系的重要性。他们还承认不同团队之间可能存在摩擦,但这可以通过变更管理来缓解。” “说话人 A 有兴趣了解公司如何决定是在内部构建解决方案还是使用第三方。说话人 C 认为,决定取决于该组件是否属于公司核心知识产权,并且通常会结合使用市场标准和内部解决方案。说话人 D 采取混合方法,使用开源并进行合作,并强调将 AI 嵌入业务的重要性。说话人 C 认为,决定应基于可行性和价值。”

在另一段录音中,就关于在家办公与返回办公室的问题,快速交换了意见。演播室里的主持人认为在家办公和在办公室一样高效,但电话线上的嘉宾不同意他们的观点。

转录应用能够识别对立的观点,但只有当录音中明确提到姓名时,才能识别持有观点的人。通过使用说话人标签,您可以清楚地识别讨论中的所有观点以及发表观点的说话人。

音频文件:在家办公辩论 👇

问题:“两个对立的观点是什么?每边有多少人?”

转录应用 说话人应用
转录中的对立观点在于:一方认为为了协作和提高生产力而必须完全返回办公室,另一方则认为远程工作同样有效且提供更大的灵活性。第一方(由 Jim 代表)对完全返回办公室持怀疑态度,并担心通勤对环境的影响。第二方(由说话人代表)承认协作的重要性,但认为远程和办公室工作相结合的混合方法是有益的。 对立的观点在于返回办公室的必要性以及员工和管理者之间的权力平衡。说话人 A 和说话人 C 似乎支持灵活性和远程工作,而说话人 B 则更倾向于返回办公室,但承认需要灵活性。

#2:利用说话人标签,我们可以从文件中提取实用信息

在分析包含多位说话人的录音时,您可能想要分析的一个重要方面是说话人的数量或他们在录音中的角色。

除非在录音中明确提及,否则转录应用无法告知说话人的数量。最多只能识别出录音中有多人。

音频文件:小组讨论 👇

问题:“此录音中有多少人在说话?”

转录应用 说话人应用
此录音中有多人说话,但转录文本未提供确切数字。 此录音中有三个人在说话:说话人 A、说话人 B 和说话人 D。

音频文件:Netflix 👇

问题:“这次电话会议中有多少位发言人和主持人?”

转录应用 说话人应用
这次电话会议中有四位发言人和一位主持人。 这次通话中有三位发言人:Ted Sorandos、Greg Peters 和 Spence Newman。Spencer Wong 是主持人。

音频文件:在家办公辩论 👇

问题:“此录音中有多少人在说话?”

转录应用 说话人应用
转录文本未提供足够信息来确定此录音中说话的确切人数。 此录音中有三个人在说话。

代码解释

现在让我们看看如何使用 Haystack 和 AssemblyAI 构建一个带有说话人标签的应用。在此 Colab notebook 中,您可以找到快速入门的代码。

Haystack 是一个用于构建生产级 LLM 应用的开源 Python 框架。它提供了实现端到端应用所需的工具,并附带 AssemblyAI 集成,可将音频数据的转录、摘要和说话人标签纳入您的管道。更多信息,请参阅 Haystack 文档

我们将在此应用中使用 haystack 以及 assemblyai-haystack 包。使用 pip 安装所有必需的软件包。

pip install haystack
pip install assemblyai-haystack
pip install "sentence-transformers>=2.2.0"

接下来,我们将设置管道,使用 AssemblyAITranscriber 来生成任何输入音频文件的说话人标签转录文本。

查看 文档,了解有关 assemblyai-haystack Python 包的更多信息。

要使用这段代码,请确保您创建一个 AssemblyAI 账户 并获取您的免费 API 密钥。您还需要 Hugging Face 的访问令牌 才能访问免费的推理 API。

首先,初始化所需的 Haystack 组件以索引带有嵌入的文档

创建完所有这些组件后,初始化一个 Pipeline 对象,将这些组件添加到您的管道中,并通过指示下一个组件应连接到哪个组件来connect()这些组件。

from haystack.components.writers import DocumentWriter
from haystack.components.preprocessors import DocumentSplitter
from haystack.components.embedders import SentenceTransformersDocumentEmbedder
from haystack import Pipeline
from haystack.document_stores.in_memory import InMemoryDocumentStore
from assemblyai_haystack.transcriber import AssemblyAITranscriber
from haystack.document_stores.types import DuplicatePolicy
from haystack.utils import ComponentDevice

speaker_document_store = InMemoryDocumentStore()
transcriber = AssemblyAITranscriber(api_key=ASSEMBLYAI_API_KEY)
speaker_splitter = DocumentSplitter(
    split_by = "sentence",
    split_length = 10,
    split_overlap = 1
)
speaker_embedder = SentenceTransformersDocumentEmbedder(device=ComponentDevice.from_str("cuda:0"))
speaker_writer = DocumentWriter(speaker_document_store, policy=DuplicatePolicy.SKIP)

indexing_pipeline = Pipeline()
indexing_pipeline.add_component(instance=transcriber, name="transcriber")
indexing_pipeline.add_component(instance=speaker_splitter, name="speaker_splitter")
indexing_pipeline.add_component(instance=speaker_embedder, name="speaker_embedder")
indexing_pipeline.add_component(instance=speaker_writer, name="speaker_writer")

indexing_pipeline.connect("transcriber.speaker_labels", "speaker_splitter")
indexing_pipeline.connect("speaker_splitter", "speaker_embedder")
indexing_pipeline.connect("speaker_embedder", "speaker_writer")

然后,我们就可以使用此管道运行任意音频文件了。请确保将 speaker_labels 设置为 True。还可以获取音频文件的内容摘要,但在此教程中我们不使用它。可以将其设置为 None 或 False。

indexing_pipeline.run(
    {
        "transcriber": {
            "file_path": "/content/Netflix_Q4_2023_Earnings_Interview.mp3",
            "summarization": None,
            "speaker_labels": True
        },
    }
)

接下来,该设置用于说话人标签的检索增强(RAG)管道了。对于 RAG 管道,我们需要

from haystack.components.builders.prompt_builder import PromptBuilder
from haystack.components.generators import HuggingFaceAPIGenerator
from haystack.components.embedders import SentenceTransformersTextEmbedder
from haystack.components.retrievers.in_memory import InMemoryEmbeddingRetriever
from haystack.utils import ComponentDevice

open_chat_prompt = """
GPT4 Correct User: You will be provided with a transcription of a recording with each sentence or group of sentences attributed to a Speaker by the word "Speaker" followed by a letter representing the person uttering that sentence. Answer the given question based on the given context.
If you think that given transcription is not enough to answer the question, say so.

Transcription:
{% for doc in documents %}
  {% if doc.meta["speaker"] %} Speaker {{doc.meta["speaker"]}}: {% endif %}{{doc.content}}
{% endfor %}
Question: {{ question }}
<|end_of_turn|>
GPT4 Correct Assistant:
"""

retriever = InMemoryEmbeddingRetriever(speaker_document_store)
text_embedder = SentenceTransformersTextEmbedder(device=ComponentDevice.from_str("cuda:0"))
answer_generator = HuggingFaceAPIGenerator(
    api_type="serverless_inference_api",
    api_params={"model": "openchat/openchat-3.5-0106"},
    generation_kwargs={"max_new_tokens":500})
prompt_builder = PromptBuilder(template=open_chat_prompt)

创建完所有这些组件后,就像为第一个管道一样,初始化一个 Pipeline 对象,将这些组件添加到您的管道中,并通过指示下一个组件应连接到哪个组件来connect()这些组件。在创建连接时,有时需要更明确地指定输入和输出名称。将 retriever 的“documents”输出明确连接到 prompt_builder 的“documents”输入,以使连接更清晰,因为 prompt_builder 有两个输入(我们在提示模板中定义的“documents”和“question”变量)。

from haystack import Pipeline

speaker_rag_pipe = Pipeline()
speaker_rag_pipe.add_component("text_embedder", text_embedder)
speaker_rag_pipe.add_component("retriever", retriever)
speaker_rag_pipe.add_component("prompt_builder", prompt_builder)
speaker_rag_pipe.add_component("llm", answer_generator)

speaker_rag_pipe.connect("text_embedder.embedding", "retriever.query_embedding")
speaker_rag_pipe.connect("retriever.documents", "prompt_builder.documents")
speaker_rag_pipe.connect("prompt_builder.prompt", "llm.prompt")

完成后,您可以使用以下代码根据自己的示例测试结果。根据您想提供给 LLM 的相关文档数量来更改 top_k

question = "Who are the speakers in this recording?"

result = speaker_rag_pipe.run({
    "prompt_builder":{"question": question},
    "text_embedder":{"text": question},
    "retriever":{"top_k": 10}
})
result["llm"]["replies"][0]

结论

感谢您的阅读!通过将 AssemblyAI 的转录功能与 Haystack 的强大功能相结合,您可以增强您的 RAG 系统,使其包含说话人标签,从而确保更全面、更准确地理解内容。

如果您想了解 Haystack 的最新动态,可以 订阅我们的时事通讯加入我们的 Discord 社区。别忘了从 AssemblyAI 获取您的免费 API 密钥,并 订阅 AssemblyAI 的 YouTube 频道,获取关于 AI 世界最新发展的每周视频和教程。