当前位置: 首页 > news >正文

【AI大模型应用开发】【项目实战】9.基于GPT2搭建医疗问诊机器人

1. 项目简介

1.1 项目背景

  • 目标:聊天机器人是一种基于自然语言处理技术的智能对话系统,能够模拟人类的自然语言交流,与用户进行对话和互动。聊天机器人能够理解用户的问题或指令,并给出相应的回答或建议,其目标是提供友好、智能、 自然的对  话体验
  • 应用:当前,聊天机器人在多个领域得到广泛应用,首先,它们常用于在线客服系统,能够快速、   准确地回答用户的常见问题,解决疑问;其次,聊天机器人可以作为个人助手,提供个性化的推荐、建议和日程安排等服务,提升用户体验;此外,聊天机器人还被应用于社交娱乐、语言学习、旅游指南等领域,为用户提供有趣、便捷的对话体验

常见的相关聊天机器人产品:

本项目基于医疗领域数据构建了智能医疗问答系统, 目的是为用户提供准确、高效、优质的医疗问答服务

1.2 环境准备

  • python>=3.8
  • transformers>=4.2.0
  • pytorch>=1.7.0

1.3 项目整体结构

2. 数据介绍

data文件夹里面包含2个文件:

  • medical_train.txt  训练数据
  • medical_valid.txt 验证数据

medical_train.txt, medical_valid.txt文件的内容均为对话文本,原始train文档中中—共包含91487条数据, valid文档中包含1244条数据, 每两行数据为—段对话内容,注意:如果想要实现多轮对话,那么不同对话间实现多条对话语句对即可

数据举例:

帕金森叠加综合征的辅助治疗有些什么? 综合治疗;康复训练;生活护理指导;低频重复经颅磁刺激治疗 卵巢癌肉瘤的影像学检查有些什么? 超声漏诊;声像图;MR检查;肿物超声;术前超声;CT检查

数据格式:每段医患对话之间用\n隔开,一共约3w对聊天记录

3. 数据处理

3.1 数据处理简介

目的:将中文文本数据处理成模型能够识别的张量(数字)形式,基本流程如下:

实现过程:

        运行preprocess.py,data/medical_train.txt对话语料进行tokenize然后进行序列化保存到data/medical_train.txt.pkl medical_train.pkl中序列化的对象的类型为List[List],记录对话列表中,每个对话包含的token

注意:这里省略的了数据格式的转换, 目的: 将非txt的文档转换为txt的形式,并符合上述数据格式要求

3.2 代码实现

(1).数据张量转换

代码路径: /data_preprocess/preprocess.py

        代码实现了一个针对医疗对话语料的预处理脚本。它的核心功能是将原始的文本对话数据(txt格式),通过BERT 的分词器(Tokenizer)转化为模型可理解的Token ID 序列,并遵循 BERT 处理多轮对话的标准格式([CLS] seq1 [SEP] seq2 [SEP] ...,最后将处理好的数据保存为二进制文件(pkl格式)以供后续训练直接读取        

# 导入依赖模块 # 导入分词器 # BertTokenizerFast, BertTokenizer:从 Hugging Face 的 transformers 库导入 BERT 分词器。 # Fast 版本基于 Rust 实现,处理速度比标准版快很多 from transformers import BertTokenizerFast, BertTokenizer import pickle # # 将数据保存为pkl文件,方便下次读取 from tqdm import tqdm # 加在进度条 import os def data_preprocess(train_txt_path, train_pkl_path): """ 对原始语料进行tokenizer,将每段对话处理成如下形式:"[CLS]sentence1[SEP]sentence2[SEP]sentence3[SEP]" :param train_txt_path: 原始文本路径 :param train_pkl_path: 输出 pkl 文件路径 :return: """ # 初始化分词器与特殊字符 # 初始化tokenizer,使用BertTokenizerFast从预训练的中文Bert模型(bert-base-chinese)创建一个tokenizer对象 # tokenizer = BertTokenizerFast.from_pretrained('/Users/ligang/PycharmProjects/llm/prompt_tasks/bert-base-chinese', # 使用 BertTokenizerFast 加载自定义的词汇表文件 ../vocab/vocab.txt,并显式指定了 BERT 的三个特殊 Token: # [SEP]:分隔符,用于区分不同的句子或对话轮次。 # [PAD]:填充符,用于将不同长度的序列对齐到相同长度。 # [CLS]:起始符,通常放在序列开头,其最终隐藏状态可作为整个序列的聚合表示 ) tokenizer = BertTokenizerFast('../vocab/vocab.txt', sep_token="[SEP]", pad_token="[PAD]", cls_token="[CLS]") # 打印词表大小 print(f'tokenizer.vocab_size-->{tokenizer.vocab_size}') sep_id = tokenizer.sep_token_id # 获取分隔符[SEP]的token ID cls_id = tokenizer.cls_token_id # 获取起始符[CLS]的token ID # [SEP] 和 [CLS] 对应的数字 ID print(f'sep_id-->{sep_id}') print(f'cls_id-->{cls_id}') # # # # # 读取训练数据集, 读取与切分原始语料 with open(train_txt_path, 'rb') as f: data = f.read().decode("utf-8") # 以UTF-8编码读取文件内容 # print(data) # 根据换行符区分不同的对话段落,需要区分Windows和Linux\mac环境下的换行符 # 兼容跨平台换行符:通过判断文本中是否包含 \r\n(Windows换行符)来决定按 \r\n\r\n 还是 \n\n 进行切分。 # 这里以双换行符作为不同对话段落(样本)的分界线 if "\r\n" in data: train_data = data.split("\r\n\r\n") else: train_data = data.split("\n\n") # # print(len(train_data)) # 打印对话段落数量 print(train_data[:2]) # 核心 Tokenize 逻辑 # 开始进行tokenize # 保存所有的对话数据,每条数据的格式为:"[CLS]seq1[SEP]seq2[SEP]seq3[SEP]" dialogue_len = [] # 记录所有对话tokenize分词之后的长度,用于统计中位数与均值 dialogue_list = [] # 记录所有对话: 记录处理后的数据 # # # # # for index, dialogue in enumerate(tqdm(train_data)): # print(f'dialogue-->{dialogue}') # 同样兼容单换行符,将一段对话按行切分成多个独立的句子(sequences) if "\r\n" in dialogue: sequences = dialogue.split("\r\n") else: sequences = dialogue.split("\n") # print(f'sequences--》{sequences}') # 初始化 input_ids 列表,并将 [CLS] 的 ID 作为序列的开头 input_ids = [cls_id] # 每个dialogue以[CLS]seq1[sep]seq2[sep] for sequence in sequences: # 调用 tokenizer.encode(sequence, add_special_tokens=False) 将文本转为 ID 列表。 # 关键点:这里必须设置 add_special_tokens=False,因为代码需要手动控制 [SEP] 的插入位置, # 防止 BERT 自动在句首句尾添加额外的 [CLS] 或 [SEP] input_ids += tokenizer.encode(sequence, add_special_tokens=False) # 将每个对话句子进行tokenize,并将结果拼接到input_ids列表中 # input_ids += tokenizer.encode(sequence) # 将每个对话句子进行tokenize,并将结果拼接到input_ids列表中 input_ids.append(sep_id) # 每个seq之后添加[SEP],表示seqs会话结束 # 记录当前对话的总长度,并将完整的 input_ids 存入 dialogue_list dialogue_len.append(len(input_ids)) # 将对话的tokenize后的长度添加到对话长度列表中 dialogue_list.append(input_ids) # 将tokenize后的对话添加到对话列表中 #保存数据 with open(train_pkl_path, "wb") as f: pickle.dump(dialogue_list, f) if __name__ == '__main__': train_txt_path = '../data/medical_valid.txt' train_pkl_path = '../data/medical_valid.pkl' data_preprocess(train_txt_path, train_pkl_path)
tokenizer.vocab_size-->13317 sep_id-->102 cls_id-->101 413 ['小孩五岁,脐周淋巴结肿大,小孩五岁,脐周淋巴结肿大,输液后不痛也不烧了,就是淋巴大了,原来9.3mm*3.4mm现在10mm*5mm又吃了半月克拉霉素和猴头菌提取物颗粒查了一下,变成10mm*6mm更大了,怎么办呀?请医生帮助,谢谢\n你好,考虑肠系膜淋巴结炎,本病常与上呼吸道感染有联系。临床表现为发热、腹痛、呕吐,或发生腹泻或便秘。腹痛有时象绞痛在右下腹部,也可在其他部位,本病多属病毒感染,一般自然痊愈,及时的对症治疗即可', '断指再植血管危象的手术治疗有些什么?\n断指再植;静脉皮瓣游离移植'] 100%|██████████| 413/413 [00:00<00:00, 965.28it/s]
http://www.cnnetsun.cn/news/3074538.html

相关文章:

  • 版本兼容设计事件类预留版本字段:
  • C++ STL之互斥锁与条件变量详解
  • C++ STL 之随机数生成详解
  • GPIO详细介绍
  • 汽车软件测试,难点到底在哪?
  • 2026年7月零代码网站搭建与企业无代码建站工具测评:谁更适合你,
  • 手机AI Agent系统级集成实战:从架构到代码的完整指南
  • 告别信息过载:利用聚合平台的 Grok 模型快速提炼长文章核心观点
  • 英伟达“技术没有秘密“合理吗:研发总监拆解护城河的真相
  • Dify实战教程:从零搭建企业级AI应用,掌握低代码开发与工作流设计
  • TEE-TA学习轨迹第八篇:optee_os源码下TA分析之-app_secrets
  • Unsloth量化实战:消费级显卡(12GB)跑通8B大模型
  • 解决方案|腾讯安全天御金融反电诈产品解决方案
  • 09505黄大年茶思屋榜文95期 第5题 三方 CaaS下 CloudOS存储 Bypass关键技术
  • GPU PRO 5 - 4.2 Deferred Rendering Techniques on Mobile Devices 笔记
  • 【Java踩坑笔记】14_Collections.singletonList的坑:不能add也不能set
  • 2026年6月GESP真题及题解(C++一级):去旅行
  • pthread_create通过加锁设置线程启动竞争条件
  • 如何高效使用Diablo Edit2:暗黑破坏神2存档编辑器的完整指南
  • 查新报告分为哪几种?科技查新、查收查引与专利查新区别
  • Advanced XRay技术深度解析:如何通过方块渲染优化实现高效矿石定位
  • 5分钟免费让Windows拥有macOS优雅鼠标指针的完整指南
  • 用Backtrader回测DMI指标:一个Python量化新手的实战踩坑记录(附完整代码)
  • 基于sigrity的TDR/TDT仿真设计
  • 数据安全检查,这3个API盲区最容易被问穿
  • 如何用中文工作流轻松玩转AI绘画?这份完整指南让你从入门到精通
  • 第018章:ComfyUI文生图Z-Image模型创建数字人模特(二)
  • 01 静态分析(Static Analysis)
  • PKMS+AppOps 双权限体系:隐私管控、特权白名单全流程源码剖析
  • 2026年桌面风扇类型选购要点:从四个核心部件看懂一台风