当前位置: 首页 > 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.gsyq.cn/news/1611059.html

相关文章:

  • Java开发者实战指南:Spring Boot集成AI大模型与Agent开发
  • Domain3-2 安全模型
  • Mac与Android无缝连接:HoRNDIS USB网络共享驱动深度解析
  • 2026年6月零代码网站搭建与企业无代码建站工具测评:谁更适合你
  • 解决音频格式兼容性难题:FlicFlac轻量级音频转换工具深度解析
  • 餐饮老板必看:扫码点餐小程序3步搞定,别再让顾客干等了!
  • 抖音内容监控助手:告别手动刷新,让优质内容主动找你
  • 移动端游戏功耗测试实战:电流、功率、亮度和场景对比
  • 足球口袋教练 HarmonyOS 离线应用实战(03/20):ArkUI 首页仪表盘搭建
  • [C++]内存管理:串顺序存储的内存回收
  • 计算机毕业设计之沧州师范学院学生旅游攻略分享平台的设计与实现
  • 学长真实分享|点餐平台网站全套源码+论文,餐饮类课设毕设稳妥选题!
  • 3步实现Photoshop与AI绘图的无缝融合:SD-PPP插件完全指南
  • 【共创季稿事节】鸿蒙原生 ArkTS 布局实现 Column + List + Navigation 协作导航 — 从列表渲染到页面切换的完整实践
  • day4:复合函数与分段函数
  • 如何5分钟搞定B站抢票:告别手速焦虑的自动化神器指南
  • 2026年全球范围内最佳高端品牌网站建设公司服务商排行榜,测评零代码、低代码、定制工具
  • 学长走心分享|在线动漫信息平台全套源码+论文,二次元特色毕设课设亮眼选题!
  • 面向AI ASIC上全同态加密NTT加速的低成本多精度脉动阵列
  • Kafka-UI安全加固:如何解决生产环境权限失控问题
  • [QT]重载qdbug
  • 2026年7月零代码网站搭建与企业无代码建站工具测评:谁更适合你,
  • 速来薅羊毛!8元免费得
  • Claude Code(15):CodeGraph - 给 AI 装上代码地图,少读文件、少烧 Token
  • 管人这件事:三流领导靠罚,二流靠制度,一流靠方法
  • SPI机制:服务扩展的核心技术
  • 用WSL(Windows Subsystem for Linux :适用于Linux的windows子系统) 在 Windows 系统上运行你最喜爱的linux工具、使用工具,应用工具和工作流
  • openeuler/skills用户指南:从安装到优化的10个实用技巧
  • 别再凭感觉选RC了!用这个比率设计法,5分钟搞定Sallen-Key低通滤波器
  • 时钟控制器和TIM、DMA、ADC、UART控制器