0


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

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

报告日期:2024年8月19日

项目负责人:Sophia

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

代码实现:

使用NVIDIA的NIM平台使用NVIDIA_API_KEY

  1. # 使用NVIDIA的NIM平台 使用NVIDIA_API_KEY
  2. import getpass
  3. import os
  4. if os.environ.get("NVIDIA_API_KEY", "").startswith("nvapi-"):
  5. print("Valid NVIDIA_API_KEY already in environment. Delete to reset")
  6. else:
  7. nvapi_key = getpass.getpass("NVAPI Key (starts with nvapi-): ")
  8. assert nvapi_key.startswith("nvapi-"), f"{nvapi_key[:5]}... is not a valid key"
  9. os.environ["NVIDIA_API_KEY"] = nvapi_key

初始化SLM phi-3

  1. # 初始化SLM phi-3
  2. from langchain_nvidia_ai_endpoints import ChatNVIDIA
  3. llm = ChatNVIDIA(model="microsoft/phi-3-small-128k-instruct", nvidia_api_key=nvapi_key, max_tokens=512)

初始化向量模型

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

获取专家库的数据

  1. # 获取专家库的数据
  2. import os
  3. from tqdm import tqdm
  4. from pathlib import Path
  5. # Here we read in the text data and prepare them into vectorstore
  6. ps = os.listdir("./data/")
  7. data = []
  8. sources = []
  9. for p in ps:
  10. if p.endswith('.txt'):
  11. path2file="./data/"+p
  12. with open(path2file,encoding="utf-8") as f:
  13. lines=f.readlines()
  14. for line in lines:
  15. if len(line)>=1:
  16. data.append(line)
  17. sources.append(path2file)

数据清理及删除空行

  1. # 数据清理及删除空行
  2. documents=[d for d in data if d != '\n']
  3. len(data), len(documents), data

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

  1. # 将文档处理到 faiss vectorstore 并将其保存到磁盘
  2. from operator import itemgetter
  3. from langchain.vectorstores import FAISS
  4. from langchain_core.output_parsers import StrOutputParser
  5. from langchain_core.prompts import ChatPromptTemplate
  6. from langchain_core.runnables import RunnablePassthrough
  7. from langchain.text_splitter import CharacterTextSplitter
  8. from langchain_nvidia_ai_endpoints import ChatNVIDIA
  9. import faiss
  10. # 只需要执行一次,后面可以重读已经保存的向量存储
  11. text_splitter = CharacterTextSplitter(chunk_size=400, separator=" ")
  12. docs = []
  13. metadatas = []
  14. for i, d in enumerate(documents):
  15. splits = text_splitter.split_text(d)
  16. #print(len(splits))
  17. docs.extend(splits)
  18. metadatas.extend([{"source": sources[i]}] * len(splits))
  19. store = FAISS.from_texts(docs, embedder , metadatas=metadatas)
  20. store.save_local('./data/nv_embedding')

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

  1. # 读取之前处理并保存的 Faiss Vectore 存储
  2. store = FAISS.load_local("./data/nv_embedding", embedder,allow_dangerous_deserialization=True)
  3. #提出问题并基于phi-3-small-128k-instruct模型进行RAG检索
  4. retriever = store.as_retriever()
  5. prompt = ChatPromptTemplate.from_messages(
  6. [
  7. (
  8. "system",
  9. "Answer solely based on the following context:\n<Documents>\n{context}\n</Documents>",
  10. ),
  11. ("user", "{question}"),
  12. ]
  13. )
  14. chain = (
  15. {"context": retriever, "question": RunnablePassthrough()}
  16. | prompt
  17. | llm
  18. | StrOutputParser()
  19. )

智能机器人对话界面展示

  1. # 读取之前处理并保存的 Faiss Vectore 存储
  2. store = FAISS.load_local("./data/nv_embedding", embedder,allow_dangerous_deserialization=True)
  3. #提出问题并基于phi-3-small-128k-instruct模型进行RAG检索
  4. retriever = store.as_retriever()
  5. prompt = ChatPromptTemplate.from_messages(
  6. [
  7. (
  8. "system",
  9. "Answer solely based on the following context:\n<Documents>\n{context}\n</Documents>",
  10. ),
  11. ("user", "{question}"),
  12. ]
  13. )
  14. chain = (
  15. {"context": retriever, "question": RunnablePassthrough()}
  16. | prompt
  17. | llm
  18. | StrOutputParser()
  19. )

测试与调优:

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

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

项目成果与展示:

应用场景展示:

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

功能演示:

问题与解决方案:

问题分析:

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

解决措施:

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

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

项目总结与展望:

项目评估:

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

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

未来方向:

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

标签: 人工智能

本文转载自: https://blog.csdn.net/SophiaC2020/article/details/141298614
版权归原作者 Sophia.Chen 小灰灰 所有, 如有侵权,请联系我们删除。

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

还没有评论