资讯动态

基于RAG与大模型的医疗问答系统毕设源码实战指南

发布时间:2026/10/8 16:48:52 来源:尧图企业网站定制
简介这份资源是面向计算机相关专业学生与项目实战学习者的高分毕业设计资料主题为基于RAG与大模型技术的Python医疗问答系统评审分达99分代码完整可运行适合作为毕业设计、课程设计或期末大作业参考。压缩包共75个文件约84.66MB包含10个py源码、7个ipynb实验笔记、7个json数据配置、3个yaml与3个md说明文档以及19个txt语料、18个png与4个jpg界面截图覆盖模型微调、知识图谱构建、命名实体识别与Web交互等模块。资源围绕医疗问答场景提供从数据预处理、图谱搭建到LoRA微调与推理部署的完整链路并附有运行说明与结果记录便于读者理解RAG检索增强与大模型结合的工程实现。目前已有120人学习适合希望快速上手医疗问答项目、积累实战经验的学习者。1. 从一份能跑通的医疗问答毕设说起RAG 到底解决了什么如果你正在找一份能直接跑起来、代码结构清晰、还带文档说明的 Python 毕业设计那这套基于 RAG 与大模型技术的医疗问答系统源码大概率能省掉你从零搭架子的一大半时间。医疗问答这个场景有个天然矛盾通用大模型什么都懂一点但一被问到具体药品剂量、疾病症状、诊疗建议就容易一本正经地胡说。RAG检索增强生成就是冲着这个矛盾来的——先从本地知识库里把相关医学资料捞出来再让大模型基于这些资料组织答案相当于给模型配了一本随时能翻的参考书。这套源码的价值不在于它用了多前沿的模型而在于它把「文档入库 → 向量检索 → 上下文拼接 → 大模型生成」这条链路完整地串了起来并且配了文档说明适合拿来改、拿来交、拿来当 rag 实战的入门样本。适合谁一是毕设选题卡在「大模型 垂直领域」方向的同学二是想搞懂 rag 知识库到底怎么落地、但不想一上来就啃框架源码的开发者。下面我按「先跑通、再拆解、最后避坑」的顺序把这份资源拆开讲。2. 环境搭建与依赖安装把 Python 环境和大模型接口先理顺2.1 为什么这类项目最容易死在环境上医疗问答系统看着是算法项目实际上手第一步全是环境问题。这套源码依赖 Python 运行环境、向量库、大模型调用 SDK 和一堆文本处理库任何一个版本对不上报错信息都能让你怀疑人生。我一般建议用 conda 单独开一个环境别跟系统 Python 混着用因为 rag 相关的库更新快依赖冲突是常态。先确认 Python 版本源码通常要求 3.9 以上3.10 或 3.11 兼容性最好。低于 3.9 的话部分向量库和异步调用会直接装不上。装完 Python 后pip 源建议换成国内镜像不然装依赖的时间够你喝两杯咖啡。# 创建独立环境避免污染系统 Python conda create -n med_rag python3.11 -y conda activate med_rag # 升级 pip 并配置国内镜像加速依赖安装 python -m pip install --upgrade pip pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple这里conda create的-n指定环境名python3.11是版本约束-y跳过确认。镜像配置只影响当前用户不会动系统级设置卸载环境时一起删掉就行。2.2 依赖清单与安装顺序这类项目的依赖大致分四类Web 框架Flask 或 FastAPI、向量检索库、大模型 SDK、文档解析库。安装顺序有讲究先装底层数值库再装上层框架能减少编译报错。常见做法是先装 numpy、pandas 这类基础包再装向量库最后装 Web 框架。# 基础数值与文本处理 pip install numpy pandas jieba # 文档解析PDF、Word、TXT 都要能读 pip install pypdf python-docx # 向量检索轻量场景常用 FAISS 或 Chroma pip install faiss-cpu chromadb # Web 服务与前端交互 pip install flask fastapi uvicorn # 大模型调用 SDK按源码实际使用的平台装 pip install openai requestsfaiss-cpu是 CPU 版本适合毕设这种数据量不大的场景GPU 版本装起来麻烦且没必要。chromadb自带持久化适合不想自己管向量文件的情况。openai这个包现在很多兼容接口的平台都用它具体调哪家看源码里的 base_url 配置。提示如果源码里用的是本地大模型比如通过 Ollama 部署那openai包依然能用只要把 base_url 指向本地服务地址即可不用额外装模型权重。2.3 配置文件与密钥管理源码里通常会有一个 config 文件或 .env 文件存放模型 API Key、向量库路径、知识库目录这些参数。这一步是新手最容易翻车的地方——直接把 Key 写死在代码里交上去查重或者公开仓库就泄露了。正确做法是用环境变量读取。# config.py 示例从环境变量读取敏感配置 import os from dotenv import load_dotenv load_dotenv() # 加载 .env 文件 class Config: # 大模型接口配置 LLM_API_KEY os.getenv(LLM_API_KEY, ) LLM_BASE_URL os.getenv(LLM_BASE_URL, https://api.example.com/v1) LLM_MODEL os.getenv(LLM_MODEL, gpt-3.5-turbo) # 向量库与知识库路径 VECTOR_STORE_PATH os.getenv(VECTOR_STORE_PATH, ./data/vector_store) KNOWLEDGE_BASE_DIR os.getenv(KNOWLEDGE_BASE_DIR, ./data/medical_docs) # 检索参数 TOP_K int(os.getenv(TOP_K, 3)) # 召回文档数 CHUNK_SIZE int(os.getenv(CHUNK_SIZE, 500)) # 文本切块大小 CHUNK_OVERLAP int(os.getenv(CHUNK_OVERLAP, 50)) # 块间重叠load_dotenv()会自动读取同目录下的 .env 文件把里面的键值对加载进环境变量。os.getenv的第二个参数是默认值这样即使 .env 没配全程序也能用兜底值跑起来不至于一启动就崩。TOP_K控制每次检索返回几段资料太大容易超出模型上下文长度太小又可能漏掉关键信息3 到 5 是比较稳的范围。3. 知识库构建与向量检索RAG 的核心链路拆解3.1 医疗文档怎么切块才不丢信息RAG 的效果七成取决于知识库建得好不好。医疗文档有个特点一段话里可能同时包含症状、药品名、剂量、禁忌切得太碎会丢上下文切得太大会引入噪声。常见做法是按语义段落切同时保留一定的重叠区让相邻块之间有信息衔接。# document_processor.py文档加载与切块 from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain.document_loaders import PyPDFLoader, TextLoader import os def load_documents(kb_dir): 遍历知识库目录加载所有支持的文档 docs [] for filename in os.listdir(kb_dir): filepath os.path.join(kb_dir, filename) if filename.endswith(.pdf): loader PyPDFLoader(filepath) elif filename.endswith(.txt): loader TextLoader(filepath, encodingutf-8) else: continue # 跳过不支持格式 docs.extend(loader.load()) return docs def split_documents(docs, chunk_size500, chunk_overlap50): 按语义递归切块保留重叠区 splitter RecursiveCharacterTextSplitter( chunk_sizechunk_size, chunk_overlapchunk_overlap, separators[\n\n, \n, 。, , , , ] ) return splitter.split_documents(docs)RecursiveCharacterTextSplitter会按 separators 列表的顺序依次尝试切分优先在段落处断开实在不行才在句子、逗号处断。中文场景下把「。」「」加进去很关键否则容易把一句话拦腰截断。chunk_size500是字符数医疗文本信息密度高500 字左右通常能覆盖一个完整知识点。chunk_overlap50让相邻块有 50 字重叠防止关键信息正好卡在切分点上被割裂。3.2 向量化与入库embedding 模型怎么选切完块就要把文本转成向量存进向量库。embedding 模型的选择直接影响检索准确率。通用场景下开源的 text2vec、bge 系列中文效果都不错如果源码调的是在线 embedding 接口那就按配置走。这里要注意embedding 模型和检索时的查询向量必须用同一个模型否则向量空间对不上检索结果全是乱的。# vector_store.py向量化并写入向量库 from langchain.embeddings import HuggingFaceEmbeddings from langchain.vectorstores import FAISS def build_vector_store(chunks, persist_path): 将文本块向量化并持久化到本地 # 中文场景推荐 bge-small-zh体积小、速度快 embeddings HuggingFaceEmbeddings( model_nameBAAI/bge-small-zh-v1.5, model_kwargs{device: cpu}, encode_kwargs{normalize_embeddings: True} # 归一化提升余弦相似度稳定性 ) vector_store FAISS.from_documents(chunks, embeddings) vector_store.save_local(persist_path) # 持久化下次直接加载 return vector_storenormalize_embeddingsTrue会把向量归一化到单位长度这样用内积算相似度等价于余弦相似度检索更稳定。save_local会在指定目录生成 index 文件和 metadata 文件下次启动直接FAISS.load_local加载不用重新算一遍省时间。3.3 检索与上下文拼接把资料喂给大模型检索环节的核心是「用问题去找资料」。用户问「高血压吃什么药」系统先把这句话向量化然后在向量库里找最相似的 TOP_K 个块再把这几块拼成上下文连同问题一起发给大模型。# qa_engine.py检索 生成 def answer_question(query, vector_store, llm_client, top_k3): 检索相关文档并生成回答 # 1. 相似度检索 docs vector_store.similarity_search(query, ktop_k) # 2. 拼接上下文加分隔符便于模型区分 context \n\n---\n\n.join([d.page_content for d in docs]) # 3. 构造提示词明确要求基于资料回答 prompt f你是一个医疗问答助手。请严格根据以下参考资料回答问题。 如果资料中没有相关信息请直接说明「资料中未提及」不要编造。 参考资料 {context} 用户问题{query} 回答 # 4. 调用大模型 response llm_client.chat.completions.create( modelgpt-3.5-turbo, messages[{role: user, content: prompt}], temperature0.3 # 医疗场景降低随机性 ) return response.choices[0].message.contentsimilarity_search返回的是 Document 对象列表page_content才是正文。提示词里那句「资料中未提及就不要编造」是医疗场景的保命条款能显著降低幻觉。temperature0.3让输出更保守医疗问答不需要创意需要的是准确和稳定。注意如果检索回来的资料本身质量差再好的提示词也救不回来。知识库文档要提前清洗去掉页眉页脚、乱码和无关广告。4. 避坑与常见问题排查这些报错我替你踩过了4.1 检索结果答非所问现象用户问感冒症状系统却返回一堆糖尿病资料。原因通常是 embedding 模型对中文医疗术语区分度不够或者 chunk_size 太大导致单个块里混了多个主题。解决办法是换用医疗领域微调过的 embedding 模型或者把 chunk_size 降到 300 左右让每个块聚焦一个知识点。另外检查一下查询语句有没有做预处理口语化的问题最好先转成规范表述再检索。4.2 大模型接口超时或返回空现象程序卡在调用大模型那一步等半天报 timeout或者返回内容为空。原因一般是网络不稳定、API Key 额度用完、或者 base_url 配错。先确认 Key 有没有余额再用 curl 直接测一下接口通不通。如果用的是兼容接口注意路径是/v1/chat/completions还是别的少一段都调不通。超时参数建议设 30 秒以上医疗回答生成本来就慢。4.3 向量库加载报维度不匹配现象重新加载向量库时报「dimension mismatch」。原因是建库时用的 embedding 模型和加载时用的不是同一个向量维度对不上。解决方法是把建库和检索的 embedding 配置统一写在一个地方别一处用 bge、一处用 text2vec。如果换了模型必须删掉旧向量库重新建不能直接覆盖。4.4 中文乱码与编码问题现象读取 TXT 文档时出现乱码或者写入日志时中文变问号。原因是文件编码不是 UTF-8而 Python 默认按系统编码读。解决方法是加载文档时显式指定encodingutf-8如果文件本身是 GBK先用工具转成 UTF-8 再入库。Windows 环境下尤其要注意默认编码经常是 GBK。4.5 依赖版本冲突导致启动失败现象装完依赖后 import 报错提示某个库版本不兼容。rag 生态更新快langchain 和向量库之间经常有版本约束。解决办法是不要盲目装最新版按源码文档里给的版本号装或者用pip install langchain0.1.0这种锁定版本的方式。实在搞不定就重建环境从零按顺序装。5. 进阶技巧让医疗问答更稳的几个实操习惯5.1 用重排序提升检索精度基础向量检索召回的资料相关性排序不一定最优。加一个重排序rerank环节用交叉编码器对召回的块重新打分能明显提升 top 结果的质量。常见做法是先用向量检索召回 10 条再用 rerank 模型挑出最相关的 3 条喂给大模型。这样既控制了上下文长度又保证了资料质量。# rerank.py对召回结果重排序 from sentence_transformers import CrossEncoder def rerank_docs(query, docs, top_n3): 用交叉编码器对文档重新打分排序 model CrossEncoder(BAAI/bge-reranker-base) pairs [[query, d.page_content] for d in docs] scores model.predict(pairs) # 按分数降序取前 top_n ranked sorted(zip(docs, scores), keylambda x: x[1], reverseTrue) return [doc for doc, _ in ranked[:top_n]]CrossEncoder会把 query 和文档拼在一起算相关性比单纯向量相似度准但速度慢所以只对召回结果做重排不对全库做。bge-reranker-base中文效果不错模型也不大CPU 跑得动。5.2 多轮对话的上下文管理医疗问答经常是多轮的用户会追问「那这个药有什么副作用」。如果每轮都独立检索会丢失前文信息。常见做法是把最近几轮对话拼进查询里再检索或者维护一个对话历史让大模型结合历史回答。但要注意上下文长度限制历史不能无限堆一般保留最近 3 到 5 轮就够了。5.3 知识库更新与增量入库医疗知识会更新知识库不能建一次就不管了。FAISS 支持增量添加新文档切块后直接add_documents就行不用重建整个库。但要注意去重同一份文档重复入库会导致检索结果里出现大量重复内容。我一般会在入库前算一下文档哈希已经存在的就跳过。参数建议值说明chunk_size300-500医疗文本信息密度高不宜过大chunk_overlap50-80保证切分点信息不丢失top_k 召回5-10召回阶段宁多勿少rerank top_n3最终喂给模型的资料数temperature0.2-0.4医疗场景降低随机性从那以后我每次搭 RAG 项目都强制先把知识库文档清洗一遍再入库因为血泪经验告诉我检索效果差十有八九是资料本身脏而不是模型不行。希望这份拆解能帮你少走点弯路把这份源码真正跑起来、改起来。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑