项目名称:AI-AGENT夏季训练营 —医疗专家智能机器人
一、项目概述
总所周知,当前大模型面临幻觉问题、知识更新滞后和计算资源消耗大的痛点。RAG(检索增强生成)通过结合检索机制和生成模型,有效提升了信息生成的准确性和可靠性,同时弥补了私有化知识不足问题,广泛应用于问答系统、客户支持、医疗咨询、法律咨询等场景。
本项目介绍基于RAG的实现医疗专家智能机器人,使用NVDIA提供的LLM + LangChain框架 + faiss向量数据库 + streamlit前端展示,整体上简单易懂,小白也可以很轻松实现自己RAG系统。
二、技术方案与实施步骤
2.1 技术方案
2.1.1 RAG工作流程
2.1.2 模型选择
nvidia_ai_endpoints提供了众多模型,下面代码可以查看支持的模型
from langchain_nvidia_ai_endpoints import ChatNVIDIA
ChatNVIDIA.get_available_models()
模型选择可以根据特定的业务场景来选择,通常模型越大(LLM),准确度越高,当然依赖的计算资源越大,费用也越贵,速度越慢。当前,小模型(SLM)越来越受到关注,在一般的GPU,甚至手机嵌入式设备上可以跑起来,经过微调SLM,效果也不错。所以本项目采用SLM模型:phi-3-small-8k-instruct。
2.1.3 数据的构建
- 数据准备和预处理
从网上收集了关于疾病症状对应的数据,并进行预处理,删除噪点
- 数据分段
由于向量化模型的上下文长度有限,需要对数据进行分段后向量模型才能处理,分段长度一般在200~500。
- 数据向量化&存储
通过向量模型,可以把特定的文本数据转成多维的向量数据,并存储在向量数据库中,供后续查询。
向量化检索和传统字符检索,向量化充分考虑了句子语义,情感,上下语句关联等,匹配结果更优。
2.2 实施步骤
2.2.1 环境安装
- 安装miniconda
大家可以根据自己的网络情况从下面的地址下载安装,比较简单,这里忽略
- 创建python虚拟环境(python >= 3.8)
conda create --name ai-robot python=3.8
conda activate ai-robot
2.2.2 安装python依赖包
pip install langchain-nvidia-ai-endpoints jupyterlab langchain_core langchain faiss-cpu==1.7.2 openai numpy langchain-community streamlit -i https://pypi.tuna.tsinghua.edu.cn/simple/
2.2.3 代码实现
- 设置NVIDIA KEY
import getpass
import os
# 设置 NVIDIA API ke
nvapi_key = getpass.getpass("Enter your NVIDIA API key: ")
os.environ["NVIDIA_API_KEY"] = nvapi_key
- 加载SLM
from langchain_nvidia_ai_endpoints import ChatNVIDIA
# 加载SLM
llm = ChatNVIDIA(model="ai-phi-3-small-8k-instruct", nvidia_api_key=nvapi_key, max_tokens=512)
- 加载数据和预处理
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("./rag_data/")
data = []
sources = []
for p in ps:
if p.endswith('.txt'):
path2file="./rag_data/"+p
with open(path2file,encoding="utf-8") as f:
for line in f.readlines():
if line:
data.append(line)
sources.append(path2file)
documents=[d for d in data if d != '\n']
documents就是预处理完的数据
- 数据分段
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))
docs就是分段后的数据,metadatas对应元数据
- 数据向量化&存储
from langchain_nvidia_ai_endpoints import NVIDIAEmbeddings
embedder = NVIDIAEmbeddings(model="ai-embed-qa-4")
store = FAISS.from_texts(docs, embedder , metadatas=metadatas)
store.save_local('./rag_data/nv_embedding')
加载向量化模型ai-embed-qa-4,并存储在faiss向量化数据库中
- 问答
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("我头晕,没有食欲,怕冷,可能是什么疾病?")
RAG回答:
' 根据提供的文档,您的症状可能与甲状腺功能减退有关。然而,建议您及时就医进行诊断和适当的治疗。'
- 前端交互页面设计
使用steamlit作为前端页面设计框架
import streamlit as st
st.set_page_config(
page_title="医疗专家智能机器人演示",
page_icon=":robot:",
layout='wide'
)
st.title("医疗专家智能机器人")
if 'history' not in st.session_state:
st.session_state.history = []
if 'past_key_values' not in st.session_state:
st.session_state.past_key_values = None
for i, (query, response) in enumerate(st.session_state.history):
with st.chat_message(name="user", avatar="user"):
st.markdown(query)
with st.chat_message(name="assistant", avatar="assistant"):
st.markdown(response)
with st.chat_message(name="user", avatar="user"):
input_placeholder = st.empty()
with st.chat_message(name="assistant", avatar="assistant"):
message_placeholder = st.empty()
prompt_text = st.text_area(label="用户输入",
height=100,
placeholder="请在这儿输入您的咨询的症状描述")
button = st.button("发送", key="predict")
if button:
input_placeholder.markdown(prompt_text)
history, past_key_values = st.session_state.history, st.session_state.past_key_values
message_placeholder.markdown(chain.invoke(question))
st.session_state.history = history
st.session_state.past_key_values = past_key_values
运行
streamlit run robot.py
至此,医疗专家智能机器人搭建完成!
三、项目成果与展示
医疗专家智能机器人应用于网络医疗就诊,帮助广大用户初步排查疾病以及医疗建议。
用户输入对应症状,医疗专家智能机器人输出对应可能的疾病。
四、项目总结与展望
本项目的实现比较简单,主要针对初学者,旨在快速了解RAG大模型应用,在实际产品中需要考虑很多因素,如如何提高RAG索引精度,多模态RAG,RAG多跳问题处理等等。