项目名称: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.模型选择
进入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