项目名称:AI-AGENT夏季训练 —— Who is KevinYu?
报告日期:2024年8月18日
项目负责人:WenniLiu
项目概述:
“Who is Kevin?” 是一个致力于通过构建一个基于RAG(Retrieval-Augmented Generation)智能对话机器人来帮助大家了解Kevin是谁的项目。该项目的核心目的是通过AI技术展现Kevin的个性特点、兴趣爱好,以及他在我生活中的重要地位,使用户通过互动了解Kevin和我们之间的关系。
我们可以从以下示例中发现:传统的生成式模型依赖于预训练过程中的内部知识来生成回答,因此无法回答出本人所希望让大家知道“KevinYu是谁”的正确答案(此处调用的传统模型为meta/llama-3.1-405b-instruct):
from openai import OpenAI
#初始化OpenAI客户端
client = OpenAI(
base_url = "https://integrate.api.nvidia.com/v1",
api_key = "此处应填入您在NVIDIA Nim平台申请到的API Key"
)
#创建对话请求
completion = client.chat.completions.create(
model="meta/llama-3.1-405b-instruct",
messages=[{"role":"user","content":"KevinYu是谁"}],
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="")
输出:
技术方案
技术方案:
- OpenAI GPT-3 模型:对话生成和自然语言处理
- NVIDIA API:模型部署和优化
- NVIDIA LangChain库:文本处理和嵌入
- FAISS:文本相似度搜索
- LangChain Core库:文本流水线构建
RAG模型优势分析:
1. 结合检索与生成的强大能力:
通过从大量文本中检索相关信息,将检索的文本片段与生成模型结合,使生成的内容更加贴近实际情况和用户的问题,从而提升对话的上下文一致性。
2.减少幻觉:
传统生成模型有时会生成与事实不符的内容,而RAG模型通过引用实际的检索结果,使得生成的回答更具真实性,且能够应对包含动态或更新内容的问题,确保用户得到的答案是最新且准确的。
3. 可定制性:
可以根据具体需求对检索和生成的过程进行优化,以满足项目特定目标——让大家知道KevinYu是我的男朋友。
5. 模型训练的高效性:
相较于纯生成模型,RAG模型可以在更少的训练数据下产生较好的结果,在面对新问题时的适应能力更强,因为它无需完全依赖于预先训练的数据。
数据构建的过程、向量化处理方式及其优势:
数据构建过程包括读取文本数据、数据预处理、文本向量化和向量存储。其中,向量化处理方法使用了NVIDIAEmbeddings模型,将文本转换为向量表示。
这种向量化处理方法的优势在于能够捕捉文本的语义信息,实现语义表示;同时,它能够进行高效的向量计算,提高处理效率;另外,它还具有可扩展性,适用于处理大规模的文本数据集。
实施步骤:
环境搭建:
- 配置Python 3.8环境
- 安装.NET 8
- 安装Visual Studio Code及插件(.NET Extension Pack)
- 安装Jupyter。
必要库文件:
! pip install gradio
! pip install openai-whisper==20231117
! pip install ffmpeg==1.4
! conda install ffmpeg -y
! pip install edge-tts
! pip install transformers
! pip install openai
代码实现:
Step 1 - 使用NVIDIA_API_KEY
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
# 输出所有可用模型
from langchain_nvidia_ai_endpoints import ChatNVIDIA
ChatNVIDIA.get_available_models()
Step 2 - 初始化SLM
为稀疏线性模型的训练做好准备工作,包括模型参数的初始化、模型结构的定义以及正则化参数的配置。这里我们使用phi-3-small-128k-instruct
llm = ChatNVIDIA(model="ai-phi-3-small-128k-instruct", nvidia_api_key=nvapi_key, max_tokens=512)
result = llm.invoke("KevinYu是谁")
print(result.content)
输出:
Step 3 - 初始化ai-embed-qa-4向量模型
为了确保模型能够正常加载预训练权重,并配置模型的参数和数据处理流程。
from langchain_nvidia_ai_endpoints import NVIDIAEmbeddings
embedder = NVIDIAEmbeddings(model="ai-embed-qa-4")
Step 4 - 获取文本数据集
在相对路径./zh_data/中添加介绍KevinYu的txt数据库
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)
Step 5 - 进行一些基本的清理并删除空行
documents=[d for d in data if d != '\n']
len(data), len(documents), data[0]
Step 6 - 将文档处理到 faiss vectorstore 并将其保存到磁盘
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
# 只需要执行一次,后面可以重读已经保存的向量存储
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))
store = FAISS.from_texts(docs, embedder , metadatas=metadatas)
store.save_local('./zh_data/nv_embedding')
输出:
Step 7- 重读之前处理并保存的 Faiss Vectore 存储
# Load the vectorestore back.
store = FAISS.load_local("./zh_data/nv_embedding", embedder,allow_dangerous_deserialization=True)
Step 8- 提出问题并基于phi-3-small-128k-instruct模型进行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()
)
chain.invoke("KevinYu是谁")
输出:
Step 9-使用gradio作为UI界面展示结果
import gradio as gr
def chat_agent(text):
response = chain.invoke(text)
return response
chat_interface = gr.Interface(fn = chat_agent,
inputs = "text",
outputs = "text",
title = "KevinYu观察日记",
allow_flagging = "never")
chat_interface.launch()
输出:
项目总结与展望:
- 项目评估:对照项目最初设定的目标,项目达成了预期的结果,即让用户了解Kevin的个人信息和我们的关系。
- 未来方向:考虑系统的扩展和升级,确保项目能够适应未来的需求和技术变化。并将系统优化成能够支持语音输入及输出的RAG模型。
附件与参考资料
https://blog.csdn.net/Ma132001/article/details/141278547?spm=1001.2014.3001.5502