复旦大学-intel实践项目
小组成员:叶、张、范、朱
使用intel-extension-for-transformers结合modelscope-agent实现健康助手agent
前言
大模型时代,多领域结合是大势所趋,本项目项目是一个基于LLM技术开发健康小助手。
通过大模型,解答用户的健康问题。利用大模型对用户进行营养指导(私人营养师),指导用户通过饮食改善健康状况;为用户制定运动计划,帮助用户达成运动指标;提供心理健康支持,帮助缓解压力和焦虑;指导用户对于常见疾病和药物的预防和使用;提高用户的健康意识并根据用户需求提供相关的推荐。
一、简介
intel-extension-for-transformers
Intel® Extension for Transformers 是一款创新工具套件,旨在在各种 Intel 平台(包括 Intel Gaudi2、Intel CPU 和 Intel GPU)上实现基于 Transformer 的模型的最佳性能,从而在任何地方加速 GenAI/LLM。
github地址 https://github.com/intel/intel-extension-for-transformers
modelscope-agent
Modelscope-Agent是一个可定制的、可扩展的Agent代码框架。单Agent具有角色扮演、LLM调用、工具使用、规划、记忆等能力。
github地址https://github.com/modelscope/modelscope-agent/
二、实践步骤
选取qwen1.5-4b-chat模型,硬件环境必须是intel的cpu 且至少32G内存,显存有没有没关系(本次项目主要结合对cpu进行加速)
本次项目主要分两大部分:
- 模型微调
- agent构建
1. 模型微调
数据集选取
现有的关于医疗领域大模型已经很多了,直接从开源的模型那获取相关数据集,这里放上链接:
https://github.com/CMKRG/QiZhenGPT/tree/main/data
https://github.com/shibing624/MedicalGPT/tree/main/data/finetune
拉取intel-extension-for-transformers项目
直接拉取上面链接,git clone https://github.com/intel/intel-extension-for-transformers,然后按照intel提供文档安装依赖
调用QLora进行微调
直接使用官方文档提供的方法进行调用
2. Health-Agent构建
部署大模型
部署大模型方法很多,这里采用了fastapi + uvicorn 进行部署
核心是写一个openai_api的后端服务,实现如下所示接口:
@app.post('/v1/chat/completions', response_model=ChatCompletionResponse)
async def create_chat_completion(request: ChatCompletionRequest):
global model, tokenizer
然后利用intel的neural speed的模对大模型进行加速,使其在cpu环境下也能取得较好的推理效果。
核心代码如下:
model = AutoModelForCausalLM.from_pretrained(args.checkpoint_path, load_in_4bit=True, model_hub="modelscope",device_map=device_map)
调用这段代码会对模型文件进行量化,我这里设置为4bit会量化成int4类型,再利用model.generate进行推理,加快推理速度。
本地知识库构建
先在网上找到有关健康生活的pdf、word数据集。
利用model-agent构建本地数据库,构建方法很简单,将文件放入config目录下,并配置一下数据的config
model-agent会自动调用去解析文件
@register_tool('doc_parser')
class DocParser(BaseTool):
name = 'doc_parser'
description = '解析文件'
parameters = [{
'name': 'url',
'type': 'string',
'description': '待解析的文件的路径'
}]
后续使用该本地知识库时,agent调用相似搜索,检索出最近的文件。
@register_tool('similarity_search')
class SimilaritySearch(BaseTool):
name = 'similarity_search'
description = '从文档中检索和问题相关的部分,从而辅助回答问题'
parameters = [{
'name': 'query',
'type': 'string',
'description': '待回答的问题',
'required': True
}]
ps: agent调用本地知识库时候,需要修改modelscope-agent源码里面对于知识库大小的设定,可以根据模型最大上下文token数进行选取。
RAG实现
进行rag,首先要确定用啥搜索引擎了,本次项目里面用的是bing进行搜索(提供免费的api),申请bing api key的可以参考网上教程去官网申请一下就行。
bing的搜索代码也很简单,核心代码如下所示:
response = requests.get(
self.endpoint,
headers=headers,
params=params,
timeout=self.timeout)
raw_result = json.loads(response.text)
if raw_result.get('error', None):
print(f'Call Bing web search api failed: {raw_result}')
except Exception as ex:
raise ex('Call Bing web search api failed.')
results = []
res_list = raw_result.get('webPages', {}).get('value', [])
for item in res_list:
title = item.get('name', None)
link = item.get('url', None)
sniper = item.get('snippet', None)
if not link and not sniper:
continue
results.append(
SearchResult(title=title, link=link,
sniper=sniper).model_dump())
解决完搜索的问题,考虑怎么和大模型融合,很简单的思路,让大模型判断是否要进行web search。
主要思路是prompt里面设定好对应的返回词,如果大模型认为需要进行web search,从返回的resposne中解析到对应的生成文本,然后再调用tools进行web search,拿到返回的结果再调用大模型,让大模型自己判断接下来是否要进行search。
## 从返回结果中解析对应的提示词
text = message
func_name, func_args = None, None
i = text.rfind(ACTION_TOKEN)
j = text.rfind(ARGS_TOKEN)
k = text.rfind(OBSERVATION_TOKEN)
ps:模型支持函数式调用,需要修改一下流式调用方式,改为非流式调用
评估
没用intel加速,可以看到用了18分钟,amazing,这个速度完全无法接受,生成的结果虽然更长,但是这个速度基本已经被pass了。
用上intel加速后,这里跑了个英文自我介绍问题,可以看到耗时1分20秒。结果更短,但是至少时间在可接受范围。
在我这里cpu都是跑满了,但是用上intel加速后,可以看到cpu上还是可以进行大模型推理的。
效果
启动
安装完依赖后,先启动后台服务(前文部署大模型提到的服务),在本项目里面是启动qwen文件夹下面的openai_api.py,启动后模型会自动初始化,然后启动项目文件夹下面的appBot.py。根据配置的网址,可以进入到可视化页面展示。