项目名称:AI-AGENT夏季训练营 — RAG智能对话机器人
报告日期:2024年8月18日
项目负责人:Petter Lee
一、项目概述
1 引言
现在的大模型遍地都是,如何搭建一个自己的大模型,并且可以和你对话?参考这个文档就对了。你只需要按步骤操作,就能无误完成。这个教程不需要GPU也可完成,老爷们请进!
2 动机
目前的大模型会产生一定的"幻觉",我们如果不仔细查看,可能会出现较大的问题。
3 RAG的优势分析
RAG模型能有效利用外部知识库,提高生成文本的可靠性。具备检索库的更新机制,无需重新训练模型即可实现知识的即时更新。另外,其可以提供与最新信息相关的回答,高度适配需要及时性的应用。
4 工具
NVIDIA NIM 微服务是NVIDIA提供基于NVIDIA推理软件的预构建容器,包括 Triton 推理服务器和 TensorRT-LLM,使开发者能够将部署时间从几周缩短至几分钟。这里我们直接使用他们的服务,免费额度1000token,官网:https://build.nvidia.com/。
二、技术方案与实施步骤
1 步骤
A. 从NVIDIA-NIM中挑选一个你心仪的大模型
-
登录网址:https://build.nvidia.com/,并完成注册(这里就省略了),下面是主界面
-
选择一个模型,这里选择一个比较轻量且好用的模型Phi-3-small-128K-instrust,如下图
-
点击之后会出现使用说明,如下,这里以Python为例
-
记得获取一下自己的API-Key,参考上述图片
-
至此你就完成了模型选择
B. 环境
既然我们是以Python代码展示,自然少不了python环境了,这里用anaconda创建了一个Python=3.8的环境,参考:https://blog.csdn.net/kunhe0512/article/details/140910139
按照下面的步骤执行即可搭建完成(缺啥装啥)
conda create --name ai_endpoint python=3.8
conda activate ai_endpoint
pip install langchain-nvidia-ai-endpoints jupyterlab langchain_core langchain matplotlib faiss-cpu==1.7.2 openai
C. 简单对话
1)把复制的代码粘贴到py文件里,这里放在jupyter里,记得切换自己的api-key到指定的位置,图中第4行,提问在messages的content中即可
from openai import OpenAI
client = OpenAI(
base_url = "https://integrate.api.nvidia.com/v1",
api_key = "api-key"
)
completion = client.chat.completions.create(
model="microsoft/phi-3-mini-4k-instruct",
messages=[{"role":"user","content":"你好!"}],
temperature=0.2,
top_p=0.7,
max_tokens=1024,
stream=True
)
for chunk in completion:
if chunk.choices[0].delta.content is not None:
print(chunk.choices[0].delta.content, end="")
2) 但是这样还是太麻烦了不是吗?这么多代码,下面有简单的操作,且看
import os
from langchain_nvidia_ai_endpoints import ChatNVIDIA
if not os.getenv("NVIDIA_API_KEY"):
# 保护好自己的key
os.environ['NVIDIA_API_KEY'] = ''
model = 'microsoft/phi-3-mini-4k-instruct'
llm = ChatNVIDIA(model=model, max_tokens=512)
result = llm.invoke("hello!")
print(result.content)
3) 好了,现在的大模型可以给你答复了,但是,效果可能不尽人意(如上)。如果你需要将其部署到你自己的工作领域中,比如小说,这个效果肯定不行。不过,你可以使用RAG将你的数据喂给他,将其增强,我这里最终RAG后的结果如下:
D. RAG增强
从1)到4), 从上到下复制粘贴,你就可以完成对模型的RAG增强
- 模型构建
import os
from langchain_nvidia_ai_endpoints import ChatNVIDIA
if not os.getenv("NVIDIA_API_KEY"):
# 保护好自己的key
os.environ['NVIDIA_API_KEY'] = ''
model = 'microsoft/phi-3-mini-4k-instruct'
llm = ChatNVIDIA(model=model, max_tokens=512)
- 获取文本数据集
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(r"文本数据路径")
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']
- 将文本数据编码保存
# 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
# 只需要执行一次,后面可以重读已经保存的向量存储
# # 分词分块器,对文档分批做embedding,可以一定程度提升RAG的准确度
text_splitter = CharacterTextSplitter(chunk_size=400, separator=" ")
docs = []
metadatas = []
# 遍历清洗的数据
for i, d in enumerate(documents):
splits = text_splitter.split_text(d) # 分快
print(len(splits))
docs.extend(splits) # 拼接
metadatas.extend([{"source": sources[i]}] * len(splits)) # 每个document元素分了多少块
print(metadatas)
# embedding
store = FAISS.from_texts(docs, embedder , metadatas=metadatas)
# 保存到文件
store.save_local('保存的文本数据编码的路径')
- 执行RAG,并输出
# 将文档内容的编码向量作为检索对象
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()
)
# 执行链条
result = chain.invoke("老猪的小说《紫川》讲了什么故事!")
print(result)
E. 语音播报
这个其实更简单,只需要借助一个第三方库pyttsx3即可完成
- 安装pyttsx3第三方库
conda activate ai_endpoint
pip install pyttsx3
- 定义这样的一个保存文本到mp3文件的函数
import pyttsx3
def play_content(text):
engine = pyttsx3.init()
engine.save_to_file(text, r'./last.mp3')
engine.runAndWait()
print("save sussful to './last.mp3'")
- 将model执行的结果作为参数传给play_content函数即可, 效果如下:
play_content(result)
4) 可以播放查看内容,但是这样太不美观,我们借用IPython.display.Audio完成一个美观的MP3播放器, 效果如下:
from IPython.display import Audio
play_content(text)
Audio('last.mp3', autoplay=True)
三、问题与解决方案
问题:对于大模型型的RAG任务,其实核心的内容就是自己的数据,本文展示的内容是以文本.txt内容进行的,需要自己通过一定手段将数据进行读取。
解决方案:数据的准备不仅限于.txt,还可以通过HTML网页、PDF、语音等形式准备数据,不同格式的数据需要自己去处理,本项目只提供了一个最基本的案例,还有很大的提升空间。
四、项目总结与展望
项目评估:项目虽然一定程度上解决了对话Agent的核心问题,但值得一提的是,在应用层面方面还有提升空间。
未来方向: 为角色训练专属声音和live2d,结合语言大模型使其更加还原,唯美主义可以通过这个功能,将其部署到网页端,使用对话模式完成。。