在人工智能领域飞速发展的今天,大模型(LLMs)如GPT-4o展现了令人惊叹的理解和生成人类语言的能力。然而,这些模型的知识受限于训练的时间点,它们对公司最新的内部政策、特定产品的用户手册或实时数据一无所知。这就是检索增强生成(RAG)技术发挥作用的地方,它赋予大模型访问和利用外部私有知识库的能力。本文将深入探讨如何从零开始构建一个复杂的、实时的RAG语音助手,使其能够基于自定义知识库进行自然对话和回答特定问题。
大模型与知识局限性
大模型的出现无疑是AI领域的一座里程碑,它们在文本生成、语言理解和内容创作等方面表现出色。例如,GPT-3能够生成各种类型的文本,从诗歌到代码,但它无法回答关于2021年之后发生的事件,因为它的训练数据只到那个时间点。即使是最新发布的GPT-4o,虽然拥有更强大的多模态能力,但依然无法理解你公司内部的专有文档,或者你个人的最新动态。这种固有的知识局限性,限制了大模型在实际应用中的价值,尤其是在需要特定领域知识或实时信息的场景中。
RAG:赋予大模型实时知识
为了弥补大模型的知识盲区,检索增强生成(RAG)技术应运而生。RAG的核心思想是,当用户提出问题时,首先从外部知识库中检索相关信息,然后将这些信息与问题一起输入到大模型中,让大模型基于检索到的上下文生成答案。 就像给大模型提供了一本“开卷考试”的参考书。 这种方法使得大模型的回答更加准确、可验证,并且能够基于特定的数据。例如,一个客服机器人如果采用了RAG技术,就能够查询公司内部的FAQ文档,从而准确地回答用户关于退款政策、产品使用等问题。
LiveKit Agents:实时语音交互的基石
仅仅拥有知识是不够的,用户需要通过自然的方式与大模型进行交互。LiveKit Agents 框架为构建实时语音(和视频)助手提供了强大的支持。LiveKit是一个开源的实时WebRTC平台,而 LiveKit Agents 框架构建于其之上,专门用于创建 AI 驱动的语音代理。它处理了实时通信的复杂底层细节,使开发人员能够专注于代理的逻辑。它提供了一个基于插件的架构,可以轻松集成各种服务:语音活动检测 (VAD)、语音转文本 (STT)、大模型 (LLM) 和文本转语音 (TTS)。例如,LiveKit可以轻松地与Whisper集成,实现语音转文本的功能,从而让用户可以通过语音与大模型进行对话。
LlamaIndex:RAG流程的简化器
构建一个RAG系统并非易事,需要处理数据摄取、索引、检索等多个环节。LlamaIndex是一个专门用于简化 RAG 应用程序创建的数据框架。它提供高级 API 来处理整个管道:连接到数据源、索引数据和查询数据。它充当我们的自定义数据和 大模型之间的桥梁。例如,你可以使用LlamaIndex连接到你的Confluence文档,然后将这些文档索引成向量数据库,从而让大模型能够回答关于你的公司知识库的问题。LlamaIndex极大地简化了RAG流程,使得开发者能够更专注于业务逻辑的实现。
项目架构:构建RAG语音助手的蓝图
一个典型的RAG语音助手的架构如下:
- 用户语音输入: 用户通过麦克风与助手进行对话。
- VAD -> STT: 语音活动检测(VAD)判断用户何时开始和停止说话,语音转文本(STT)引擎将语音转录为文本。例如,用户说:“你好,我想知道如何申请退款?”Whisper会将这段语音转换为文本。
- 大模型意图识别: 转录的文本被发送到大模型。大模型根据系统提示,判断用户是否需要查询知识库。例如,大模型识别出用户的问题涉及到退款政策。
- 工具调用(RAG检索): 大模型识别出用户的提问需要访问知识库。它调用自定义的
query_info
函数,并将用户的问题作为参数传递。这个query_info就是一个函数工具(Function Calling)。 - LlamaIndex查询:
query_info
函数使用 LlamaIndex 查询引擎在向量存储中搜索来自原始 CSV 文件的相关信息。 例如,LlamaIndex 检索到 CSV 文件中包含退款申请流程的段落。 - 上下文返回: 最相关的文本块从查询引擎返回到 大模型。
- 答案合成: 大模型接收到检索到的上下文,并使用它来生成一个自然、人性化的用户原始问题的答案。 例如,大模型生成回复:“您好,退款申请流程如下:…”。
- TTS -> 音频播放: 最终的文本响应被发送到文本转语音(TTS)引擎,该引擎将其转换为音频。然后将此音频流回 LiveKit 房间供用户收听。
实战:构建Saudia Wallet语音助手
为了更好地理解RAG语音助手的构建过程,我们以构建一个Saudia Wallet的语音助手为例进行说明。该助手能够回答关于Saudia Wallet服务的常见问题。
1. 环境搭建
首先,需要安装必要的软件和库,包括Python 3.11+、LiveKit项目、OpenAI API Key、Cartesia API Key等。 然后,配置环境变量,包括OpenAI API Key、Cartesia API Key、LiveKit URL、LiveKit API Key、LiveKit API Secret。
2. 准备知识库
将Saudia Wallet的FAQ整理成CSV文件,并放置在 docs/
目录下。确保 CSV 文件包含包含问题和答案的列。修改app.py
文件中的TEXT_COLUMN_NAME
变量,使其与包含FAQ答案的列名匹配。
3. 代码详解
app.py
脚本包含了RAG语音助手的核心逻辑。
- 导入和初始化: 导入必要的库,包括
pathlib
、os
、pandas
、dotenv
、llama_index
、livekit
等。 - RAG Pipeline构建: 使用 LlamaIndex 构建 RAG Pipeline。首先,定义常量,包括向量索引的存储目录
PERSIST_DIR
、文档目录DOCS_DIR
、包含文本内容的列名TEXT_COLUMN_NAME
等。显式配置 LlamaIndex 的模型,包括 LLM 和 embedding 模型。如果索引不存在,则从 CSV 文件创建新的索引。否则,从磁盘加载索引。使用index.as_query_engine(use_async=True)
创建查询引擎。 - Function Tool: 定义一个名为
query_info
的函数工具,用于查询知识库。使用@llm.function_tool
装饰器将该函数注册为 大模型 可以调用的工具。该函数的 docstring 描述了工具的功能,并指导 大模型 何时使用该工具。Annotated
类型提示告诉 大模型 如何格式化工具的输入。 - Agent的Entrypoint: 定义
entrypoint
函数,该函数是 agent 启动时运行的主要逻辑。使用ctx.connect(auto_subscribe=AutoSubscribe.AUDIO_ONLY)
连接到 LiveKit 房间。使用Agent(...)
创建 agent,并配置系统提示、VAD、STT、LLM、TTS 和工具。使用session.start()
启动会话。使用session.say(...)
让 agent 说出初始问候语。 - 启动应用: 使用
cli.run_app(WorkerOptions(entrypoint_fnc=entrypoint))
启动应用。
4. 运行项目
在终端中执行 python app.py start
命令,启动 RAG语音助手。
核心代码片段分析
以下是一些关键代码片段的分析:
@llm.function_tool
async def query_info(
query: Annotated[
str,
"The specific question to ask the knowledge base. This should be a clear, "
"concise, and fully formed question, extracted from the user's conversational input. "
"For example, if the user says 'Hey, can you tell me how to get a refund?', "
"the query should be 'How to get a refund?'"
]) -> str:
"""
Use this tool to find information and answer Frequently Asked Questions (FAQs)
specifically about Saudia Wallet and GovClick services. This is your primary
source of knowledge.
Example topics include: fees, ticket issuance, voucher management (loss, usage),
refunds, wallet activation, credit limits, supported currencies, and troubleshooting.
"""
print(f"\nExecuting RAG query: {query}\n")
res = await query_engine.aquery(query)
print(f"\nQuery result: {res}\n")
return str(res)
这段代码定义了一个名为 query_info
的函数工具。@llm.function_tool
装饰器将其注册为 大模型 可以调用的工具。Annotated
类型提示告诉 大模型 如何格式化输入,即从用户的对话输入中提取清晰、简洁、完整的问句。docstring 描述了该工具的功能,即查找关于 Saudia Wallet 和 GovClick 服务的常见问题解答,并给出了示例主题。
agent = Agent(
instructions=(
"You are a specialized voice assistant and expert on Saudia Wallet and GovClick services. "
"Your primary purpose is to answer user questions based on a dedicated knowledge base of FAQs. "
"When a user asks a question about fees, tickets, vouchers, refunds, account management, or other related topics, "
"you MUST use the 'query_info' tool to find the official answer. "
"If a question is outside this scope, politely state that you can only provide information about Saudia Wallet and GovClick. "
"Always provide clear, concise, and voice-friendly answers based on the information retrieved."
),
vad=silero.VAD.load(),
stt=openai.STT(),
llm=openai.LLM(model='gpt-4o'),
tts=cartesia.TTS(
model="sonic-2",
voice="bf0a246a-8642-498a-9950-80c35e9276b5",
),
tools=[query_info],
)
这段代码创建了一个 Agent
对象,并配置了系统提示、VAD、STT、LLM、TTS 和工具。系统提示定义了 agent 的角色和目标,并明确指示 agent 在回答相关问题时必须使用 query_info
工具。 tools=[query_info]
明确赋予了大模型调用之前定义的query_info
工具的权限。
扩展与展望
本文介绍的RAG语音助手只是一个起点。未来,可以从以下几个方面进行扩展:
- 更复杂的数据源: 使用 LlamaIndex 的各种数据加载器,替换 CSV 文件,接入更复杂的数据源,例如 PDF、Word 文档,甚至数据库。
- 会话记忆: 实现一种机制,使 agent 能够记住对话中之前的轮次,从而实现更自然的后续问题。
- 添加更多工具: 赋予 agent 更多功能,例如从 API 查找实时数据或执行创建支持票证等操作。
- 流式TTS: 为了获得更低的延迟,实现流式 TTS,使 agent 在生成第一段音频时就开始说话,而不是等待完整的响应。
- 优化RAG流程: 探索不同的chunking策略,选择合适的embedding模型,优化检索算法,提升RAG的效果。
结论:大模型与RAG的未来
实时交互框架和 RAG 的融合正在解锁新一代 AI 应用程序,这些应用程序不仅智能,而且实用、可靠,并与专有数据深度集成。 借助 LiveKit Agents 框架的实时通信能力,以及 LlamaIndex 驱动的 RAG Pipeline 的数据支持能力,我们创建了一个可以超越其预训练知识的 agent,从而可以从自定义数据源提供准确、具体且有用的答案。 随着大模型技术的不断发展,RAG技术将扮演越来越重要的角色。它不仅可以弥补大模型的知识盲区,还可以提升大模型的安全性、可信度和可解释性。在未来,我们可以期待看到更多基于RAG的创新应用,例如智能客服、知识管理、内容创作等。 现在,就开始尝试构建你自己的基于RAG的大模型应用吧!