Phi3+RAG+TTS=将钢铁侠の贾维斯带进现实

项目名称:AI-AGENT夏季训练营 — RAG智能对话机器人

报告日期:2024年8月18日

项目负责人:[JadeFrost]

一、项目概述:

        本项目是基于NVIDIA NIM (NVIDIA AI Foundation Models)的RAG (Retrieval-Augmented Generation) 智能问答语音系统。为了解决传统大模型的参数量巨大,难以在边缘设备上部署,以及知识库不能及时更新的缺点,本项目使用轻量级的模型Phi3-Vision,与RAG和TTS结合,实现了具有视、听、说输入和输出功能的小语言模型,使得模型不仅轻量级,还能具有高性能。成本低和性能高,使得钢铁侠的贾维斯能够走进每个人的生活。

        通过RAG技术,模型可以检索相关资料,实现在自身参数量及其有限的情况下,依然能够表现高性能。接下来,我们一起通过一步步搭建,实现这激动人心的时刻。

二、技术方案与实施步骤

1.环境搭建

此处请移步到这位大佬的主页:

2024 NVIDIA开发者社区夏令营环境配置指南(Win & Mac)_csdn 2024nvidia开发者-CSDN博客

2.模型选择

Try NVIDIA NIM APIs

进入NVIDIA官网,可以看到有很多热门模型,例如前不久发布的Llama3.1 405B大模型,但是我们此次项目是在小模型上做文章,所以大模型就先按下不表。

我们搜索Phi,可以看到Phi系列的所有模型

Phi总的来说归结为3个版本:Phi-3-small(3.8亿参数)、Phi-3-medium(14亿参数)和Phi-3-large(70亿参数),我们此次选用的是最下面的phi-3-vision-128k-instruct,此款模型别看只有4.2B的参数量,但是其具有的CV能力,就已经比很多的硬堆参数的无视觉能力的大模型强太多了。点击这款模型之后,点击右上角输入邮箱,即可获取1000 credits

之所以选择这一款模型,是因为我们前面提到,我们需要一款轻量级,与RAG结合,具有视、听、说说功能的模型,而这一款模型就具备了轻量级,视觉的特点,所以为我们后面工作的开展会减少一些困难。

RAG的优势就在于,

a. 能够利用外部知识,减少"幻觉"。
b. 回答更加准确和相关。
c. 可以处理开放域的问题。
d. 知识可以实时更新。

所以此种结合方式,得到的模型必然是性价比极高的。

3.数据构建

首先我们探究一下RAG的实现

1. 初始化设置:

   - 使用NVIDIA API密钥初始化环境

   - 初始化OpenAI客户端,连接到NVIDIA的推理平台

import getpass
import os

if os.environ.get("NVIDIA_API_KEY", "").startswith("nvapi-"):
    print("Valid NVIDIA_API_KEY already in environment. Delete to reset")
else:
    nvapi_key = getpass.getpass("NVAPI Key (starts with nvapi-): ")
    assert nvapi_key.startswith("nvapi-"), f"{nvapi_key[:5]}... is not a valid key"
    os.environ["NVIDIA_API_KEY"] = nvapi_key

2. 模型准备:

   - 使用NVIDIA的phi-3-vision-128k-instruct模型作为语言模型

   - 使用ai-embed-qa-4模型进行文本嵌入

from langchain_nvidia_ai_endpoints import ChatNVIDIA
llm = ChatNVIDIA(model="ai-phi-3-vision-128k-instruct", nvidia_api_key=nvapi_key, max_tokens=512)
result = llm.invoke("NVIDIA的CEO是谁?")
print(result.content)
from langchain_nvidia_ai_endpoints import NVIDIAEmbeddings

embedder = NVIDIAEmbeddings(model="ai-embed-qa-4")

3. 数据处理:

   - 从本地文件读取文本数据

   - 对文本进行基本清理和分割

import os
from tqdm import tqdm
from pathlib import Path

# Here we read in the text data and prepare them into vectorstore
ps = os.listdir("./zh_data/")
data = []
sources = []
for p in ps:
    if p.endswith('.txt'):
        path2file="./zh_data/"+p
        with open(path2file,encoding="utf-8") as f:
            lines=f.readlines()
            for line in lines:
                if len(line)>=1:
                    data.append(line)
                    sources.append(path2file)
documents=[d for d in data if d != '\n']
len(data), len(documents), data[0]

4. 向量存储:

   - 使用FAISS创建向量存储

   - 将处理后的文档嵌入到向量空间

   - 保存向量存储到本地,以便后续重用

# Load the vectorestore back.
store = FAISS.load_local("./zh_data/nv_embedding", embedder,allow_dangerous_deserialization=True)

5. 执行问答:

   - 提出问题"NVIDIA的CEO是谁?"

   - 系统根据检索到的相关信息生成答案

retriever = store.as_retriever()

prompt = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            "Answer solely based on the following context:\n<Documents>\n{context}\n</Documents>",
        ),
        ("user", "{question}"),
    ]
)

chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)

chain.invoke("NVIDIA的CEO是谁?")

答案是:

 
 

4.功能整合

而除了RAG之外,就是视听说功能的视觉功能了,因为vision版本自带视觉,所以处理起来就方便很多;CV功能的实现主要分为以下几部分:

1.LangChain NVIDIA AI Endpoints:用于与 NVIDIA AI 模型交互
2.Base64:用于图像编码
3.Subprocess:用于动态执行生成的 Python 代码
4.IPython:用于在 Jupyter 环境中显示图像
5.Matplotlib(在生成的代码中):用于图像处理和保存

听和说的功能与Microsof TTS结合实现,核心原理是如下部分:

1.提问过程:根据用户输入的语音或音频文件,自动转化为文字作为prompt

2.回答过程:使用Microsof TTS将输出的结果转换为音频

三、实施步骤:

1.环境搭建

基础环境请移步到这位大佬的主页:    ​​​​​​

2024 NVIDIA开发者社区夏令营环境配置指南(Win & Mac)_csdn 2024nvidia开发者-CSDN博客

下面是针对不同功能对应的环境

这些库用于创建、管理和使用向量存储,处理文本数据

# Here we create a vector store from the documents and save it to disk.
from operator import itemgetter
from langchain.vectorstores import FAISS
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain.text_splitter import CharacterTextSplitter
from langchain_nvidia_ai_endpoints import ChatNVIDIA
import faiss

这些库是用于构建基于LangChain和NVIDIA AI工具的对话检索系统的组件:

1. ChatNVIDIA: 集成NVIDIA的AI模型用于聊天功能。
2. NVIDIAEmbeddings: 使用NVIDIA模型生成文本嵌入。
3. ConversationalRetrievalChain: 创建能够基于用户查询检索相关文档的对话系统。
4. LLMChain: 使用语言模型生成响应的链。
5. CONDENSE_QUESTION_PROMPT: 用于压缩用户问题的提示模板。
6. load_qa_chain: 加载问答链以处理针对知识库的查询。
7. ConversationBufferMemory: 管理对话历史以维持上下文。
8. FAISS: 基于FAISS实现的向量存储,用于高效存储和检索文档嵌入。
9. RecursiveCharacterTextSplitter: 将长文本分割成更小的可处理块。

这些组件共同构建一个能够理解用户查询、检索相关信息并生成回答的智能对话系统。

from langchain_nvidia_ai_endpoints import ChatNVIDIA
from langchain_nvidia_ai_endpoints import NVIDIAEmbeddings
from langchain.chains import ConversationalRetrievalChain, LLMChain
from langchain.chains.conversational_retrieval.prompts import CONDENSE_QUESTION_PROMPT, QA_PROMPT
from langchain.chains.question_answering import load_qa_chain
from langchain.memory import ConversationBufferMemory
from langchain.vectorstores import FAISS
from langchain.text_splitter import RecursiveCharacterTextSplitter

2.代码实现

1.关键代码展示:

视觉功能:
1.相关库
from langchain_nvidia_ai_endpoints import ChatNVIDIA
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain.schema.runnable import RunnableLambda
from langchain.schema.runnable.passthrough import RunnableAssign
from langchain_core.runnables import RunnableBranch
from langchain_core.runnables import RunnablePassthrough
 
from langchain.chains import ConversationChain
from langchain.memory import ConversationBufferMemory

import os
import base64
import matplotlib.pyplot as plt
import numpy as np
2.对输入图像编码
def image2b64(image_file):
    with open(image_file, "rb") as f:
        image_b64 = base64.b64encode(f.read()).decode()
        return image_b64

image_b64 = image2b64("economic-assistance-chart.png")
# image_b64 = image2b64("eco-good-bad-chart.png")
​​​​​​​3.将数据发送给Phi 3 vision , 利用其强大能力解析图片中的数据
chart_reading = ChatNVIDIA(model="microsoft/phi-3-vision-128k-instruct")
result = chart_reading.invoke(f'Generate underlying data table of the figure below, : <img src="data:image/png;base64,{image_b64}" />')
print(result.content)
4.使用 LangChain 构建多模态智能体

def chart_agent(image_b64, user_input, table):
    # Chart reading Runnable
    chart_reading = ChatNVIDIA(model="microsoft/phi-3-vision-128k-instruct")
    chart_reading_prompt = ChatPromptTemplate.from_template(
        'Generate underlying data table of the figure below, : <img src="data:image/png;base64,{image_b64}" />'
    )
    chart_chain = chart_reading_prompt | chart_reading
5.将多模态智能体封装进Gradio
import gradio as gr
multi_modal_chart_agent = gr.Interface(fn=chart_agent_gr,
                    inputs=[gr.Image(label="Upload image", type="filepath"), 'text'],
                    outputs=['image'],
                    title="Multi Modal chat agent",
                    description="Multi Modal chat agent",
                    allow_flagging="never")

multi_modal_chart_agent.launch(debug=True, share=False, show_api=False, server_port=5000, server_name="0.0.0.0")

​​​​​​​​​​​​​​

就可以得到这样一个UI界面进行对话了

听说功能:

听说功能主要包括两个方便,核心代码是听和说

听力的实现:将语音转为文本作为输入

import speech_recognition as sr

def speech_to_text():
    recognizer = sr.Recognizer()
    with sr.Microphone() as source:
        print("请说话...")
        audio = recognizer.listen(source)

    try:
        text = recognizer.recognize_google(audio, language='zh-CN')
        print("你说的内容是: " + text)
        return text
    except sr.UnknownValueError:
        print("未能理解音频")
    except sr.RequestError as e:
        print(f"无法请求结果; {e}")

语音输出的实现:使用rate和voice.id实现说话速度和音色的调节

import pyttsx3
from IPython.display import Audio

def play_content(text):
    engine = pyttsx3.init()
    
    # Set speech rate
    engine.setProperty('rate', 150)
    
    # Set voice
    voices = engine.getProperty('voices')
    for voice in voices:
        if voice.id == 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices\Tokens\TTS_MS_EN-US_ZIRA_11.0':
            engine.setProperty('voice', voice.id)
            break
    
    engine.save_to_file(text, r'./test.mp3')
    engine.runAndWait()
    print("save successful to './test.mp3'")

with open('./zh_data/NVIDIA.txt', 'r', encoding='utf-8') as file:
    text = file.read()

play_content(text)
Audio('test.mp3', autoplay=True)

四、问题与解决方案

1.这次遇到的问题有,使用文档对模型进行矫正时,模型似乎无法读懂文档的内容,解决方法是清除所有可能的缓存文件,例如embed和checkpoint

2.对于Gradio无法显示完整的情况,可以在命令中加入share=True,inbrowser=True来新开一个标签页,这样就看的舒服多了;

五、项目总结与展望:

1.项目评估: 

成功点:

这次的项目经历使我收获颇丰,基本上初步实现了模型的视听说功能,这也是我之前一直想做但是没有做到的,看到几天来的成果,感觉很累也很充实;

不足点:

存在的不足也是很多,例如RAG的把控还是不够好,有时参考了文献模型依然存在幻觉;

模型的融合还做的不够好,只是基本上每个功能都能实现,但是还没有做到真正意义上视听说结合的程度,没有实现真正的有机结合和衔接;

2.未来方向: 基于项目经验,提出未来可能的改进方向和发展规划。

未来展望:

未来希望能够在此基础上,进一步优化RAG的效果,以及将TTS和CV功能更好的融合,使得模型具有更多的感知能力,同时优化连续对话,长时记忆体的功能,让模型真正的成为一个像贾维斯那样的私人助理。

具体到细节就是:

        在将来,这个智能体将会真正成为像贾维斯那样的私人助理,可以同你对话,询问问题(会主动询问我觉得是AI Agent区别于传统大模型的显著方式。)通过与用户的不断交流,不断完善用户在Agent中的形象,以便提供更好的客制化服务。

        比如,对学生而言,可以将模型集成到手表等便携式穿戴设备上。Agent会主动询问你今天还有课吗,或者是否有其他安排并提前为主人规划好时间,在安排开始前一段时间就会告知主人。到饭点了会提醒是否要提前点外卖,通过定位模块检测到宿舍门口了会提醒记得拿外卖等等;

        除了主动询问,Agent还可以回答用户的问题,比如大一的学生会很关心军训和社团,还有四年规划,将来的考研等等,还有包括竞赛等等,Agent就会在这方面得到强化,对于大二的学生就是专业课了,Agent可能就不是很擅长了,Agent虽然不擅长自我解决问题,但是擅长提出能解决问题的渠道,它会搜索相关的网络视频提供用户参考;对于大三Agent可以询问将来的打算是考研还是考公还是就业还是多手抓,当确定后Agent就可以就可以为用户提供精确的个性化的服务,使得用户的生活更加便利。

        也非常感谢项目期间老师毫无保留的技术指导,让我一个小白也能体验一把科技前沿的成果。

参考文献

https://pan.baidu.com/s/15JTy9CqnesXSlPiwwrUmjA?pwd=1111 
提取码:1111 

  • 24
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaojiezibu6

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值