从零跑通大模型全流程:基于Qwen3‑0.6B微调中医模型并Docker部署

文章目录

    • [1. 先给你们看看最终成品](#1. 先给你们看看最终成品)
      • [1.1 四个核心产物](#1.1 四个核心产物)
      • [1.2 先把定位说清楚](#1.2 先把定位说清楚)
    • [2. 我的本地环境家底](#2. 我的本地环境家底)
      • [2.1 硬件软件配置](#2.1 硬件软件配置)
      • [2.2 文件存放思路](#2.2 文件存放思路)
    • [3. 整个流程就是一条流水线](#3. 整个流程就是一条流水线)
      • [3.1 四个核心脚本](#3.1 四个核心脚本)
      • [3.2 完整数据流](#3.2 完整数据流)
    • [4. 数据清洗:先定好模型该学啥](#4. 数据清洗:先定好模型该学啥)
      • [4.1 原始数据啥成色](#4.1 原始数据啥成色)
      • [4.2 我是怎么筛数据的](#4.2 我是怎么筛数据的)
      • [4.3 两个不能省的细节](#4.3 两个不能省的细节)
    • [5. LoRA微调:花小钱办大事](#5. LoRA微调:花小钱办大事)
      • [5.1 LoRA到底是啥逻辑](#5.1 LoRA到底是啥逻辑)
      • [5.2 我的参数配置](#5.2 我的参数配置)
    • [6. 训练参数是怎么琢磨出来的](#6. 训练参数是怎么琢磨出来的)
      • [6.1 核心配置拆解](#6.1 核心配置拆解)
      • [6.2 为啥要这么设](#6.2 为啥要这么设)
      • [6.3 为啥只训不到半个epoch](#6.3 为啥只训不到半个epoch)
    • [7. 训练结果到底咋样](#7. 训练结果到底咋样)
      • [7.1 耗时和指标](#7.1 耗时和指标)
      • [7.2 实际效果啥水平](#7.2 实际效果啥水平)
    • [8. 为啥要把LoRA合并进去](#8. 为啥要把LoRA合并进去)
      • [8.1 LoRA文件不能单独跑](#8.1 LoRA文件不能单独跑)
      • [8.2 合并就是一步到位](#8.2 合并就是一步到位)
    • [9. 转成GGUF格式干啥用](#9. 转成GGUF格式干啥用)
      • [9.1 GGUF有啥好处](#9.1 GGUF有啥好处)
      • [9.2 转换过程很简单](#9.2 转换过程很简单)
    • [10. 怎么塞进Ollama里](#10. 怎么塞进Ollama里)
      • [10.1 先写个Modelfile](#10.1 先写个Modelfile)
      • [10.2 注册模型就完事](#10.2 注册模型就完事)
    • [11. Docker部署是怎么玩的](#11. Docker部署是怎么玩的)
      • [11.1 卷映射是核心技巧](#11.1 卷映射是核心技巧)
      • [11.2 端口和GPU配置](#11.2 端口和GPU配置)
    • [12. Open WebUI怎么接上去](#12. Open WebUI怎么接上去)
      • [12.1 配置有个小坑](#12.1 配置有个小坑)
      • [12.2 完整访问链路](#12.2 完整访问链路)
    • [13. 踩过的那些坑,说多了都是泪](#13. 踩过的那些坑,说多了都是泪)
      • [13.1 Docker路径格式坑](#13.1 Docker路径格式坑)
      • [13.2 上下文Token莫名暴涨](#13.2 上下文Token莫名暴涨)
      • [13.3 上下文长度的隐形坑](#13.3 上下文长度的隐形坑)
      • [13.4 最容易踩的认知坑](#13.4 最容易踩的认知坑)
    • [14. 折腾完这一圈,我真正收获了啥](#14. 折腾完这一圈,我真正收获了啥)
      • [14.1 值钱的不是模型,是链路](#14.1 值钱的不是模型,是链路)
      • [14.2 给新手的真心话建议](#14.2 给新手的真心话建议)
    • [15. 接下来打算咋迭代](#15. 接下来打算咋迭代)
      • [15.1 先把数据质量提上去](#15.1 先把数据质量提上去)
      • [15.2 扩充能力慢慢迭代](#15.2 扩充能力慢慢迭代)


P.S. 无意间发现了一个巨牛的人工智能教程,非常通俗易懂,对AI感兴趣的朋友强烈推荐去看看, 传送门https://blog.csdn.net/qq_34419312

前言

最近手痒,想完整走一遍大模型从训练到部署的全流程。

不是调个API那种过家家,也不是下个模型跑两下就完事,是从数据清洗到Docker部署,一条龙全给它跑通。

选了中医领域试水,拿Qwen3-0.6B搞了个试点模型。先把丑话说在前头:这就是个纯学习用的模型,不能看病开药方,别回头有人拿着输出的方子去药店抓药,再来找我报销医药费,我这显卡钱还没赚回来呢。

1. 先给你们看看最终成品

1.1 四个核心产物

折腾完一圈,手里攥着四个东西,各有各的用处。

第一个是LoRA适配器,就40.4兆,相当于给原模型打了个中医补丁,只存了参数差值,不能脱离底座单独跑。

第二个是合并后的完整Hugging Face模型,1.2G左右,把补丁和底座焊死在了一起。

第三个是BF16格式的GGUF文件,专门给本地推理工具用的,单文件便携得很。

最后一个是注册好的Ollama模型,叫wo-x-tcm:pilot,配个网页界面就能直接聊天。

1.2 先把定位说清楚

这不是从零训出来的基础大模型,说准确点,是基于Qwen3-0.6B的中医领域LoRA指令微调模型。

说白了就是给通用模型补了点中医专业课,不是从头培养个老中医。只能用来学习中医文献,但凡涉及医疗决策,一律靠边站,别拿它当在线问诊用。

2. 我的本地环境家底

2.1 硬件软件配置

操作系统是Windows,靠Docker Desktop跑Linux容器。

显卡是RTX 5070,说不上顶配,但折腾个0.6B的小模型完全够用。总不能为了个试点项目直接上旗舰卡吧,钱包第一个不同意。

Python单独开了个conda环境,PyTorch 2.13.0配CUDA 13.0,Transformers、PEFT、TRL这些常用库都拉到了对应版本,避免版本不兼容踩坑。

2.2 文件存放思路

所有大体积文件全塞D盘,C盘那点空间,装个系统都够呛,再塞模型分分钟红盘给你看。

分了四个文件夹各司其职:数据集放一起,模型文件放一起,项目代码放一起,conda环境单独放。

分门别类省得找文件找半小时,训练还没开始,先给自己整emo了。

3. 整个流程就是一条流水线

3.1 四个核心脚本

整个项目核心就四个Python文件,各司其职,一点不乱。

prepare_data.py管数据清洗整理,train_lora.py负责微调训练,evaluate.py做效果对比,merge_lora.py用来合并权重。

就像工厂流水线,一个环节接一个环节,哪个环节出问题,直接定位到对应脚本,不用到处瞎找。

3.2 完整数据流

整条链路顺下来特别清晰:原始数据洗干净,划分成训练验证测试集,丢给底座模型加LoRA训练,产出适配器,合并成全量模型,转成GGUF格式,最后塞进Ollama,用Docker部署,配个网页交互界面。

跟搭乐高似的,一块一块往上拼,拼完还能拆下来调整,灵活得很。

4. 数据清洗:先定好模型该学啥

4.1 原始数据啥成色

原始数据用的是公开的Baize TCM V3,一共十五万七千多条记录,看着量挺大,其实水分不小。

就跟你买了一大包零食,拆开一看一半都是包装袋,真正能吃的没多少。

4.2 我是怎么筛数据的

第一步先卡长度,太短太长的都直接pass。

第二步筛领域,明显不是中医内容的,直接踢出去,一下就干掉了七万多条。

第三步最关键,但凡涉及开药、处方、剂量、选穴位这种行动性医疗问题,全给过滤掉。我可不想训出个上来就给人开药方的"江湖郎中"模型,第一步先学理论,别上来就想着行医。

最后再去重,十五万多条洗下来,只剩三万九出头的合格数据。

首轮实验我也没贪多,就挑了两千条训练,两百条验证,五十条测试。先跑通流程,比啥都强。

4.3 两个不能省的细节

所有合格数据统一转成聊天格式,系统提示词加用户问题加助手回答,模型就照着这个结构学,知道看到问题该输出啥。

随机种子必须固定死。不然每次训练数据集划分都不一样,结果根本没法对比,就跟考试每次换题库,你根本不知道自己进步没进步一样。

5. LoRA微调:花小钱办大事

5.1 LoRA到底是啥逻辑

要是全量微调,所有参数都要算梯度存状态,大模型直接能把显存干冒烟。

LoRA就聪明多了,原模型参数全冻住不动,只训练两组低秩小矩阵。相当于给模型打补丁,改动小,见效快,显存占用还低,典型的四两拨千斤。

5.2 我的参数配置

秩设了16,lora_alpha设32,dropout0.05,注意力层和前馈网络的全量模块都加上了LoRA。

算下来可训练参数才一千万出头,只占总参数的1.6%左右,这点参数对显卡来说完全没压力。

这次用的是普通BF16精度,没上QLoRA。毕竟模型小,显卡扛得住,没必要搞量化徒增麻烦。

6. 训练参数是怎么琢磨出来的

6.1 核心配置拆解

核心训练参数我给你们列一下,都是踩坑踩出来的经验。

最大训练步数120步,单卡批次大小1,梯度累积步数8,算下来有效批次大小是8。学习率1e-4,用余弦调度,最大序列长度512。

打开了assistant_only_loss,也开了梯度检查点,BF16混合精度也安排上。

6.2 为啥要这么设

批次大小设1纯粹是为了省显存,靠梯度累积凑有效批次,属于是显存不够,步数来凑。

只算助手回答的损失更合理,总不能让模型学着复述用户的问题吧,那不成复读机了。

梯度检查点就是用计算换显存,反正显卡闲着也是闲着,多算点总比显存溢出强。整套配置下来,峰值显存才2.3G,离谱的省。

6.3 为啥只训不到半个epoch

两千条训练数据,有效批次8,完整跑一遍要250步。我就训了120步,算下来才0.48个epoch,连半圈都没跑完。

没办法,这就是个试点版本,先验证整条流程能不能跑通。总不能第一次就训个几天几夜,最后发现部署环节出问题,那可真是竹篮打水一场空。

7. 训练结果到底咋样

7.1 耗时和指标

整个训练跑下来花了不到7分钟,喝杯茶的功夫就完事了,速度比我预想的快多了。

训练损失从最开始的2.38降到了1.96,验证损失也稳步往下走,没出现发散的情况。说明训练没崩,模型确实在学东西。

7.2 实际效果啥水平

拿同一批问题分别测了原始模型和微调后的模型,差别还是挺明显的。

微调后的模型说话确实更有中医那味儿,专业术语用得也到位,风格一下就对齐了。但冷门知识点还是会胡说八道,也就是大家常说的幻觉。

说白了就是,你问它基础理论,它能跟你头头是道唠半天;你要是问个偏门的草药学名,它可能当场就给你现编一个,跟酒桌上吹牛皮的人似的,不懂也能给你说的跟真的一样。

所以说,少量SFT只能改个说话风格,真要知识靠谱,还得靠可靠知识库和专家审核。别以为损失降了就是模型学会了,它可能只是学会了怎么装得像学会了。

8. 为啥要把LoRA合并进去

8.1 LoRA文件不能单独跑

训出来的LoRA适配器就40兆,看着小巧便携,但它不能脱离底座模型自己运行。

就像游戏补丁不能脱离游戏本体玩一样,你总不能拿着个补丁文件到处跑,到哪都得先装个底座模型,太麻烦。

8.2 合并就是一步到位

把LoRA学到的参数变化合并到底座模型里,就生成了一个完整的独立模型。

后续转换格式、部署都方便,不用每次都额外加载适配器。代码也简单,几行调用就搞定,合并完直接保存成标准的Hugging Face格式。

9. 转成GGUF格式干啥用

9.1 GGUF有啥好处

Hugging Face格式是一堆零散文件,权重、配置、分词器分开装,传起来、部署起来都麻烦。

GGUF就不一样了,一个文件把所有东西都装进去了,模型张量、结构元数据、词表、聊天模板,应有尽有。特别适合llama.cpp、Ollama这类本地推理工具,拎包就能用。

9.2 转换过程很简单

用llama.cpp自带的转换脚本,一行命令的事。指定好输入的模型目录和输出文件,精度选BF16就行。

这次没做量化压缩,先保持完整精度,等后续再慢慢对比不同量化级别的速度和效果差异。

10. 怎么塞进Ollama里

10.1 先写个Modelfile

Ollama靠Modelfile来定义模型。里面要写清楚GGUF文件的路径,设置生成参数:温度0.3,top_p 0.8,重复惩罚1.05,上下文长度拉到8192。

最后再写上系统提示词,给模型定好规矩,明确它只能用来学习文献,不能做医疗建议。就跟给模型写个员工手册似的,告诉它该怎么干活,什么不能干。

10.2 注册模型就完事

写好Modelfile,一条ollama create命令就搞定注册,给模型起个名字,绑定好配置。

注意啊,这一步不是重新训练模型,就是给模型登个记上户口,以后调用名字就能直接用。很多新手以为这步会训模型,站那等半天,纯纯浪费时间。

11. Docker部署是怎么玩的

11.1 卷映射是核心技巧

很多人用Docker跑Ollama,上来就想把模型拷进容器里,那多傻啊。

直接用卷映射,把Windows本地的目录映射到容器内部,容器直接读本地文件,不用复制来复制去,省时间还省空间。我一开始差点犯傻,想把1个多G的模型拷进容器,后来才反应过来,白瞎我差点等半天传输进度。

GGUF目录和Ollama模型目录分别映射,只读权限给模型文件,安全得很。

11.2 端口和GPU配置

GPU必须直通给容器,不然纯CPU推理能急死人,说句话等半分钟。

端口也做了映射,本地原生Ollama用11434,Docker版用11435,互不干扰,想用哪个用哪个。

12. Open WebUI怎么接上去

12.1 配置有个小坑

Open WebUI也直接跑在Docker里,不用单独装,特别省事。

配置的时候要注意,环境变量里的Ollama地址,得写Docker内部的服务名,不能写127.0.0.1。不然它找的是自己容器里的地址,根本连不上Ollama。很多人第一次配都栽在这。

12.2 完整访问链路

浏览器访问本地3000端口就能打开界面。请求链路也很清晰:浏览器发请求给Open WebUI,它通过Docker内部网络转发给Ollama,最后交给显卡推理,结果再原路返回。

用起来跟在线大模型没啥区别,但是所有数据全在本地,安全感直接拉满。

13. 踩过的那些坑,说多了都是泪

13.1 Docker路径格式坑

Windows的路径是反斜杠,容器里是Linux的正斜杠,同一个文件,两边的路径写法完全不一样。

我一开始图省事,直接把Windows的路径写进Docker用的Modelfile里,结果死活找不到文件,排查了半天才反应过来。合着俩系统路径格式不一样,白折腾半天。

13.2 上下文Token莫名暴涨

有次我就输了"咽喉痛吃什么"五个字,结果界面显示输入快六千Token。我当时都懵了,难道我输入的是无字天书?

后来才发现,是Open WebUI偷偷给我塞了一堆内置工具的定义,知识库、搜索、日历、笔记啥的,全算进上下文里了。合着我聊个天,后台还带了个工具人团队是吧,我没叫它们啊,自己就跑进来占位置了。

解决办法也简单,给模型建个专属预设,把内置工具关了,瞬间就清净了。

13.3 上下文长度的隐形坑

Qwen3-0.6B本身支持四万多Token的上下文,但Ollama默认只给4096。

一开始我输入长点的内容就报错,还以为模型不行,后来才发现是配置没改。把Modelfile里的num_ctx调到8192,重新注册模型,立马就好了。这个参数藏得深,很多人容易忽略。

13.4 最容易踩的认知坑

很多人觉得训练损失一直降,模型就越来越厉害。大错特错!

损失下降只能说明模型越来越会模仿训练数据里的回答,不代表答案就是对的。训练数据里要是有错的,模型学的比谁都快。

就跟学生背题一样,答案背得滚瓜烂熟,你换个题型他就不会了,甚至错题他也照背不误。所以别光看损失曲线好看就自我感动,真要靠谱,还得专家评测。

14. 折腾完这一圈,我真正收获了啥

14.1 值钱的不是模型,是链路

说实话,这个模型本身没啥大不了的,就是个试点玩具,能力有限。

真正值钱的是,我把从数据处理到模型训练,再到格式转换、容器部署、问题排查的整条工程链路,完完整整跑通了一遍。每个环节是干啥的,会出啥问题,怎么解决,门儿清了。

14.2 给新手的真心话建议

要是你也想从零学本地大模型,别上来就整7B、14B的大模型,纯纯给自己找罪受。

先整个0.5B到1B的小模型,把全流程跑通再说。能跑通、能复现、能评测,比一开始就追求大参数重要多了。不然上来就整个大模型,显存不够报错,部署也不会,最后打击信心,得不偿失。

15. 接下来打算咋迭代

15.1 先把数据质量提上去

现在的数据都是公开的,没经过人工审核,质量参差不齐。下一步打算人工抽检修订样本,再加一些安全相关的内容,比如儿童、孕产妇用药禁忌这些。

安全永远是第一位的,尤其是和医疗沾边的东西,马虎不得。

15.2 扩充能力慢慢迭代

打算建一个完全隔离的专家测试集,再加个中医古籍RAG知识库,弥补模型知识不准的问题。训练数据也打算扩到一万条以上,再试试继续预训练的效果。

后面也会对比下LoRA、QLoRA不同方式,还有不同量化格式的差异,慢慢优化。反正路已经走通了,剩下的就是慢慢填内容了。

最后给想动手的朋友提个醒,整个项目的核心文件顺序就是:数据准备脚本、训练脚本、评测脚本、合并脚本,再加上Modelfile和compose配置文件。顺着这个顺序看,就能把整个流程摸得明明白白。

踩坑不可怕,踩过一次下次就会了,动手试试比看十篇教程都管用。

P.S. 无意间发现了一个巨牛的人工智能教程,非常通俗易懂,对AI感兴趣的朋友强烈推荐去看看,传送门https://blog.csdn.net/qq_34419312

相关推荐
网易云信1 小时前
权威认可!网易智企帝王蟹入选信通院《2026 智能体创新实践汇编》
人工智能·agent
吾鳴1 小时前
用一句话需求,做完一张 9:16 的 Skill 发布海报:我把设计生图交给 Agent 试了一次
人工智能·aigc·agent
yuluo_YX1 小时前
什么是 OpenAI Responses API?
人工智能·chatgpt
云浪1 小时前
从 0 到实战:掌握向量数据库 Milvus,构建 AI 应用的核心能力
javascript·数据库·人工智能
tachibana21 小时前
知识库文档上传接口
数据库·人工智能·大模型·llm
手写码匠1 小时前
华为云Flexus+DeepSeek征文|Agent 记忆系统实战:用 DeepSeek-R1/V3 + Dify 会话变量打造跨会话长期记忆
人工智能·深度学习·算法·aigc
武子康1 小时前
Pi Agent Loop 源码解析:Context、Streaming、Tool Calling、Steering 与停止条件
人工智能·llm·agent
小当家.1051 小时前
MCP 协议深度解析:AI 领域的 USB-C 接口
开发语言·人工智能·agent·tool·mcp
动物园猫1 小时前
无人机灾害场景人体目标检测数据集:10,000张图像 | 目标检测
人工智能·目标检测·无人机