项目名称:从零开始NIM及大模型RAG使用入门
报告日期:2024年8月17日
项目负责人:Lio
项目概述:
大模型在改变很多行业,很多工作方式,虽然还有不足,但是对于很多场景都已经发挥了不同程度的作用,今天对NVIDIA NIM /LLM大模型模型及RAG浅浅使用,NVIDIA不仅提供了GPU加速大模型的计算,还让大模型更加好用易用,让我们离大模型更近,让大模型使用更简单。
什么是大模型:大模型是指参数量非常大的深度学习模型,通常用于处理大规模数据集,并能够学习到数据的复杂特征。大模型的出现,极大地提升了人工智能的能力,并在语音识别、图像处理、自然语言处理等领域取得了显著成果
什么是RAG:RAG 是检索增强生成(Retrieval-Augmented Generation)的简称,是当前最火热的大语言模型应用落地的关键技术,主要用于提高语言模型的效果和准确性。它结合了两种主要的NLP方法:检索(Retrieval)和生成(Generation)。
技术方案与实施步骤
- 模型选择:
基于深度学习的英伟达NIM平台,模型使用了llama-3.1-405b-instruct、llama3-8b-instruct,算是大名鼎鼎,llama开源比较早,接触过大模型的大多数朋友都听过,llama3-8b-instruct还可以下载到本地运行,正好测试以下刚拿到的旗舰专业卡 NVIDIA RTX 5880 Ada 48G。
实施步骤:
环境准备:
#windows环境请参考:https://blog.csdn.net/kunhe0512/article/details/140910139
#Linux平台
#安装conda
mkdir -p ~/miniconda3
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda3/miniconda.sh
bash ~/miniconda3/miniconda.sh -b -u -p ~/miniconda3
alias conda=~/miniconda3/_conda #可以编辑到 .bashrc 等自启动
~/miniconda3/_conda init bash #退出后重新进入终端
#创建python 3.8虚拟环境
conda create --name ai_endpoint python=3.8
alias cin='conda activate ai_endpoint' #方便使用
#进入虚拟环境
#注:本次在Linux下搭建,进入前,需要退出一次终端窗口,重新打开。再次进入
conda activate ai_endpoint
#进入虚拟环境后后,提示符显示如下:
#(ai_endpoint) Lio@Super-Server:~$
安装nvidia_ai_endpoint工具
pip install langchain-nvidia-ai-endpoints
#安装Jupyter Lab
pip install jupyterlab
#安装langchain_core
pip install langchain_core
#安装langchain
pip install langchain
#测试发现,还需要安装
pip install -U langchain-community
#安装matplotlib
pip install matplotlib
#安装Numpy
pip install numpy
#安装faiss, 这里如果没有GPU可以安装CPU版本
pip install faiss-cpu==1.7.0 #或pip install faiss-gpu==1.7.2
#安装OPENAI库
pip install openai
#升级NVIDIA AI Foundation Endpoints
pip install --upgrade --quiet langchain-nvidia-ai-endpoints
#运行jupyter-lab,通过ssh或linux终端
jupyter-lab --ip=0.0.0.0 --port 8888 --allow-root
Linux桌面环境,会自动打开浏览器,进入jupyter页面。
如自己windows电脑,可打开浏览器访问服务器IP+端口8888,并根据提示,输入jupyter运行后输出的token密码信息,即可打开运行web调试环境。
验证NVIDIA NIM模型服务
from openai import OpenAI
client = OpenAI(
base_url = "https://integrate.api.nvidia.com/v1",
api_key = "<api key> "
)
#build.nvidia.com 可以登录生产api key,同时浏览有哪些模型可以使用,可以自行选择修改模型的名字。
completion = client.chat.completions.create(
model="meta/llama-3.1-405b-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="")
输出返回信息如下:
詹姆斯·卡梅隆
meta/llama-3.1-405b-instruct返回数据简洁且准确,回答使用中文。可见模型更大,相对准确性和功能更强。
也可以使用langchain方式调用,代码如下:
from langchain_nvidia_ai_endpoints import ChatNVIDIA
ChatNVIDIA.get_available_models()
llm = ChatNVIDIA(model="meta/llama-3.1-405b-instruct", nvidia_api_key=nvapi_key, max_tokens=512)
result = llm.invoke("泰坦尼克号的导演是谁?")
print(result.content)
Llama 8b模型下载及本地化使用及验证
(docer环境安装部署略,可参考 网络文章)
sudo docker login -u \$oauthtoken -p <api key> nvcr.io
#运行模型,启动命令会自动下周模型,需要等等一会儿,注意下面apikey的输入,和NV官网给的有些区别,实测按下面命令格式通过
export LOCAL_NIM_CACHE=~/.cache/nim
mkdir -p "$LOCAL_NIM_CACHE"
sudo docker run -it --rm \
--gpus all \
--shm-size=16GB \
-e NGC_API_KEY=<api key> \
-v "$LOCAL_NIM_CACHE:/opt/nim/.cache" \
-u $(id -u) \
-p 8000:8000 \
nvcr.io/nim/meta/llama3-8b-instruct:1.0.0
运行后,通过命令行,验证服务是否正常:
curl -X 'POST' \
'http://0.0.0.0:8000/v1/chat/completions' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"model": "meta/llama3-8b-instruct",
"messages": [{"role":"user", "content":"泰坦尼克号的导演是谁?"}],
"max_tokens": 64
}'
正常返回结果如下,llama3-8b模型能识别中文问题,但回答明显有点复杂,而且是英文。
{"id":"cmpl-64e1a9e9bf904fcfb36018e19f1216be","object":"chat.completion","created":1723885676,"model":"meta/llama3-8b-instruct","choices":[{"index":0,"message":{"role":"assistant","content":"A legendary question! \n\nThe director of the 1997 film \"Titanic\" is James Cameron. He is a Canadian film director, producer, screenwriter, and Deepsea explorer. Cameron is known for his visual and technical skill in directing, and \"Titanic\" was a massive commercial success, gross"},"logprobs":null,"finish_reason":"length","stop_reason":null}],"usage":{"prompt_tokens":21,"total_tokens":85,"completion_tokens":64}}
数据构建
RAG能够加强大模型的知识结构,提高大模型的使用价值,数据构建使用NV-Embed-QA的模型对象,建立并重新数据,本次采用文本文件:
from langchain_nvidia_ai_endpoints import NVIDIAEmbeddings
embedder = NVIDIAEmbeddings(model="NV-Embed-QA")
#读取指定路径的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)
#对于读取的文件,进行一些简单处理后,进行分词处理
documents=[d for d in data if d != '\n']
len(data), len(documents), data[0]
# 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
from langchain.vectorstores 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')
# 要利用到新的知识,需要把向量数据加载进retriever,并对回答方式进行配置。
store = FAISS.load_local("./zh_data/nv_embedding", embedder,allow_dangerous_deserialization=True)
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("泰坦尼克号的导演是谁?")
返回输出信息如下:
'泰坦尼克号的导演是Lio·卡梅隆。'
注:
本次为了验证知识是否使用,数据故意喂了错误数据(只是为了验证,其他情况还是要严谨些),
(哈哈哈.....)
项目成果与展示:
项目整个流程,完成了大模型的完整流程,从基础模型,到通过文件建立向量数据,实现RAG。还尝试了大模型本地运行,8b模型显存使用40G,要求确实挺高。
错误知识库导致错误的回答,并不是模型的幻觉,该如何处理?这可能就是大模型和人类本质的区别吧,在相当长的时间里还是能帮助到大模型,我们还是要优于大模型。
问题与解决方案:
- 问题分析: 第一次做过程中,按给会有一些报错处理,比如apikey等,通过分析返回信息、并查阅相关资料进行修改。
#测试中,from langchain.vectorstores import FAISS 无法运行,发现环境还需要安装一些组件,安装命令如下:
pip install -U langchain-community
项目总结与展望:
对于初学者,以上过程可以很快的了解了大模型的一个流程闭环,从搭建到使用,再到知识数据的重建,同时也让我们认识了大模型的一些问题,特别是数据的准确性和真实性,非常非常重要。
对于UI开发能力高的同学,可以将本地下载的大模型,配合自己搭建的UI页面,将大模型输入输出做的更加便捷,希望看到更好的大模型应用。
附件与参考资料
2024 NVIDIA开发者社区夏令营环境配置指南(Win & Mac)_csdn 2024nvidia开发者-CSDN博客