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

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

报告日期:2024819

项目负责人:Sophia

项目概述:

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

      项目基于NVIDIANIM平台+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

代码实现: 

# 使用NVIDIANIM平台 使用NVIDIA_API_KEY

# 使用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)

# 初始化向量模型

# 初始化向量模型
from langchain_nvidia_ai_endpoints import NVIDIAEmbeddings
embedder = NVIDIAEmbeddings(model="nvidia/nv-embed-v1")

# 获取专家库的数据

# 获取专家库的数据
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/"+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

# 将文档处理到 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=" ")
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架构的模型

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值