AI修仙之:救人一命胜造七级浮屠,NIM+RAG+SLM急救知识智能对话机器人

Sophia.Chen 小灰灰 2024-08-31 09:01:01 阅读 74

项目名称:AI修仙之:救人一命胜造七级浮屠,NIM+RAG+SLM急救知识智能对话机器人

报告日期:2024年8月19日

项目负责人:Sophia

项目概述:

       业余做民间救援志愿者多年,虽然民间救援队一直在做急救普及工作,但是如果有一个智能对话机器人,在当突发事件发生时可以及时提供知识协助,也许能否挽救不少生命。本项目就是基于这样一个朴素的想法,进行的一点探索。

      项目基于NVIDIA的NIM平台+RAG+phi-3小模型进行实现,NIM平台提供了各种大模型和小模型的方便的API接口,使用RAG技术提升模型在某一领域的回答精准度,phi-3小模型可部署于边缘硬件如车载端、手机端,降低对设备性能的要求,提升项目对于硬件的兼容性。

技术方案与实施步骤

模型选择:

Embeding模型选择nvidia/nv-embed-v1  效果表现还不错;

RAG采用FAISS向量库,基于FAISS的高性能、易于集成、内存使用效率高等优势;

SLM选择microsoft/phi-3-small-128k-instruct,轻量级,高效速度快、低延迟,对于资源使用来说性价比优势大,尤其适用于边缘计算,低成本,面向资源有限且任务简单的场景。

数据的构建:

使用相应领域的知识数据构建知识库文档,数据读取之后需要进行数据清理,并对数据进行分块,使用FAISS进行向量化储存。

实施步骤:

环境搭建: 

Python 3.8 或3.8+

pip install langchain-nvidia-ai-endpoints

pip install langchain_core

pip install langchain

pip install faiss-cpu==1.7.2

pip install openai

pip install gradio

代码实现: 

# 使用NVIDIA的NIM平台 使用NVIDIA_API_KEY

<code># 使用NVIDIA的NIM平台 使用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

# 初始化SLM phi-3

# 初始化SLM phi-3

from langchain_nvidia_ai_endpoints import ChatNVIDIA

llm = ChatNVIDIA(model="microsoft/phi-3-small-128k-instruct", nvidia_api_key=nvapi_key, max_tokens=512)code>

# 初始化向量模型

# 初始化向量模型

from langchain_nvidia_ai_endpoints import NVIDIAEmbeddings

embedder = NVIDIAEmbeddings(model="nvidia/nv-embed-v1")code>

# 获取专家库的数据

# 获取专家库的数据

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("./data/")

data = []

sources = []

for p in ps:

if p.endswith('.txt'):

path2file="./data/"+pcode>

with open(path2file,encoding="utf-8") as f:code>

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

# 将文档处理到 faiss vectorstore 并将其保存到磁盘

# 将文档处理到 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=" ")code>

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('./data/nv_embedding')

# 读取之前处理并保存的 Faiss Vectore 存储

# 读取之前处理并保存的 Faiss Vectore 存储

store = FAISS.load_local("./data/nv_embedding", embedder,allow_dangerous_deserialization=True)

#提出问题并基于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()

)

# 智能机器人对话界面展示

# 读取之前处理并保存的 Faiss Vectore 存储

store = FAISS.load_local("./data/nv_embedding", embedder,allow_dangerous_deserialization=True)

#提出问题并基于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()

)

测试与调优:

调整专家知识库更好的匹配对话问题,比如知识库内容是【判断是否需要进行心肺复苏包括以下3个步骤,1……,2……,3……】;在RAG匹配的时候效果并不好,不能读到需要的3个步骤,但是将知识库内容改为【判断是否需要进行心肺复苏包括以下3个步骤,1判断是否需要进行心肺复苏首先应该……,2判断是否需要进行心肺复苏其次应该……,3判断是否需要进行心肺复苏还应该……】,再进行小模型加RAG去对话的时候可以完美匹配知识库内容。

这一点只是在调试过程中发现的一个小技巧,路过的小伙伴欢迎多多探讨。

项目成果与展示:

应用场景展示: 

本项目基于智能对话机器人在急救领域的应用做了一个小小的尝试

功能演示: 

问题与解决方案:

问题分析: 

回答问题时与知识库内容匹配不好

解决措施: 

调整知识库内容与问题的联系紧密度;

进一步可以尝试调整token以及chunk的参数设置。

项目总结与展望:

项目评估: 

成功点:项目在调整知识库内容之后对话表现回答精准度有大幅提高;

不足点:对于上下文关联的内容从知识库的读取和匹配不太好;

未来方向: 

可以更换模型做更多的尝试,比如Mamba架构的模型



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。