简介这是一套面向AI应用开发者和算法工程师的实战课程PPT围绕Dify平台讲解大模型微调语料的自动化构建方法。内容针对传统人工标注成本高、技术门槛高、格式不统一等痛点给出从文档输入到标准JSONL语料输出的全流程方案并拆解了各环节常见问题与解决思路。包体为单个pptx文件大小15.21MB聚焦Dify工作流五个核心节点开始、文档提取器、代码执行、LLM、结束详细说明节点配置参数、提示词设计、SiliconCloud Qwen2.5-72B-Instruct-128K模型调用以及语料质量评估方法。目前已有109人浏览学习。通过本课程可掌握低代码可视化搭建语料流水线的方法理解文档自动提取、智能问答对生成、JSONL格式规范等关键环节还包含《少年歌行》小说文本的测试案例与17条合规语料产出演示适合希望利用Dify快速定制垂直领域AI模型的开发者参考。1. 大模型微调的成本不在训练而在语料生产微调模型的训练脚本其实很成熟真正让一个微调项目延期的是语料。手工标注的耗时占比常在70%以上JSONL格式、Python脚本处理和字段转义又把门槛抬高了一截文档一多格式不统一带来的返工几乎不可避免。Dify把这条链路压缩成五个可视化节点文档提取、代码截断、LLM生成、标准输出从TXT到可训练的对话语料不再经过任何手工编辑。这篇内容适合两类人一类是准备做领域微调但还没摸清语料从哪来的工程师另一类是已有标注流程、想换成自动化流水线的团队。2. 传统语料构建的三个断层与Dify作为自动化流水线的选型逻辑2.1 高成本的人工标注与技术门槛传统语料构建的第一个断层是人工标注的结构性成本。以客服领域的意图识别微调为例一次完整标注要经历四步通读业务文档、提炼候选问题、撰写标准答复、再由业务人员复核一致性。前面两步可以交给外包标注员后面两步必须由懂业务的专家把关四步全部依赖人力且无法通过简单增加人手来并行压缩工期。Dify教学材料里给出的数据标注工作耗时占比超过70%一点也不夸张这是语料工程里最难绕开的现实。第二个断层是技术门槛。微调数据集不是把问答对堆进Excel就能用标准做法是用Python脚本把文本转成JSONL再处理特殊字符转义、role字段一致性、上下文窗口内的文本截断。对业务团队来说这一整套知识足以劝退对工程师来说每接一个新文档都要重写一遍解析和清洗逻辑属于典型的低水平重复劳动。Dify官方对这套痛点的描述是格式不统一、数据转换流程繁琐极易出错在工作中确实是最高发的返工原因。第三个断层发生在工具链之间。不同团队可能分别用脚本、在线标注平台、Excel维护语料导出格式彼此不兼容合并时最常见的问题是字段名对不上、role顺序错乱、多轮对话被拆坏。这些问题在数据量小的时候不会暴露一旦跑到几千条清洗成本会突然吃掉整个微调预算。所以语料构建不只是生成内容的问题更是统一格式的问题。2.2 Dify在语料场景的核心能力映射Dify适合做语料构建不是因为它是通用工作流平台而是它的四个原生能力恰好对着上面三个断层文档自动提取解决读文档代码执行节点解决文本预处理和截断LLM节点解决生成问答对变量管理和结束节点解决格式标准化。Dify 能力对应痛点在语料流水线中的角色文档提取器人工通读文档成本高自动解析TXT、PDF等文件输出文本数组代码执行节点需要Python脚本而团队不会写在画布内完成文本合并、截断、清洗LLM节点问答对撰写依赖业务专家用大模型按提示词批量生成对话语料结束节点文件输出格式不统一导致返工统一输出标准JSONL文件供下载Dify对多模型的支持也很关键。同一个工作流里SiliconCloud的Qwen2.5-72B-Instruct-128K负责生成语料后续如果换了更强的模型只需在LLM节点替换模型供应商整个流程不用动。这一点比自研脚本更适合长期维护也是我倾向把语料流水线放在Dify而不是单独写一套调度服务的原因。2.3 用Dify社区版搭流水线的部署前提Dify社区版支持Docker Compose一键部署这是目前最常见的方式。部署前建议先确认三件事模型供应商的API Key能正常鉴权工作流涉及的外部模型会单独计费批量跑前先估算token消耗Docker镜像版本要固定避免自动升级导致工作流节点的字段行为变化。社区版从1.10开始引入多租户能力1.17.1对工作流引用、变量管理和知识库流水线都有更新如果团队多人协同先确认成员间的工作流导入导出兼容性再动手。有一个高频坑Docker镜像拉取失败。这种情况问题通常出在Docker的registry-mirrors配置上优先检查镜像仓库配置是否可用而不是去改Dify的安装脚本。镜像就绪后用docker compose up -d拉起服务浏览器打开控制台在模型供应商页面配置SiliconCloud并填入模型名称就可以开始搭工作流了。3. 五节点工作流从零配置开始、文档提取器、代码执行、LLM与结束节点3.1 开始节点attachments与trigger的变量约定示例工作流是一条开始 → 文档提取器 → 代码执行 → LLM → 结束的五节点闭环。开始节点暴露两个参数给调用方attachments是文件列表必填调用时直接上传文档trigger是触发词字符串用来定义这份语料面向的角色或指令。把trigger设计成独立参数而不是写死在提示词里是因为语料工程中的角色定义经常要换。同一份技术文档trigger设成你是数据库运维专家和你是新入职的实习生生成的问答风格完全不同微调出来的模型行为也会跟着变。参数外置后测试不同trigger只需要改一个值不需要动整个提示词结构。3.2 文档提取器多格式文本解析与text数组文档提取器接在开始节点后面输入变量绑定attachments数组输出是text数组数组里的每个元素对应一个文档或一个内容块。这个节点会自动解析TXT、PDF等常见格式也支持多文件同时输入省掉了传统方案里先转格式再抽取文本的步骤。多文件输入时需要留意输出顺序。文档提取器对多文件输出并不承诺严格的业务顺序如果后续要按章节或按页截取建议在代码执行节点里先给每个文件打上文件名标记再在合并阶段按标记恢复顺序。语料构建对顺序不敏感时可以省略这一步但连载小说、长报告这类强依赖上下文顺序的文档排序问题会直接影响生成语料的质量。3.3 代码执行节点文本合并与80000字符截断逻辑文档提取器输出的是字符串数组而LLM节点需要一份连续文本。代码执行节点在这里做两件事把数组元素按段落合并并把合并结果截断到80000字符以内。def main(articleSections: list) - dict: # articleSections 对应文档提取器输出的 text 数组 merged \n\n.join([s.strip() for s in articleSections if s.strip()]) # 中文场景下 1 个字符约 0.8 - 1 个 token80000 字符约 7 万 token # Qwen2.5-72B-Instruct-128K 上下文 128K token需给模型输出留出空间 truncated_text merged[:80000] return {truncated_text: truncated_text}为什么截断到80000字符而不是把全文传进去Qwen2.5-72B-Instruct-128K的128K指token上限中文一个字符约等于0.8到1个token80000字符消耗约7到8万token剩余空间要留给系统提示、触发词以及模型生成语料时的输出。如果一次灌满128K模型很容易在输出中途触达上限产出的JSONL会带一个截断的半行JSON对象后续解析直接失败。函数签名里的articleSections必须与文档提取器输出变量名称一致否则Dify代码执行节点找不到入参。返回dict的key名truncated_text要和下一个LLM节点的输入变量绑定对齐这是工作流里最容易因为大小写差异而断链的地方。3.4 LLM节点SiliconCloud Qwen2.5-72B-Instruct-128K的参数设定LLM节点是整个工作流的生成引擎。模型选择SiliconCloud Qwen2.5-72B-Instruct-128K超长上下文、中文生成质量稳定适合整段文档传入。节点输入用变量引用代码执行节点的truncated_text和开始节点的trigger提示词模板在下一章展开。参数推荐值说明模型qwen2.5-72b-instruct-128k超长上下文适合整段文档传入temperature0.2 ~ 0.4语料生成要求格式稳定温度过高会出现字段错乱max_tokens4096 或更大影响单次生成条数太小会截断输出response_formatjson_object若平台支持强制JSON输出显著降低解析失败率temperature是最值得调的参数。语料生成不是创意写作需要模型严格遵循JSONL schematemperature超过0.7时常见表现是字段名被改成小写、assistant内容里混入解释性文字这些都要靠后续清洗兜底。把temperature控制在0.3附近配合严格的系统提示词基本能做到开箱即用。3.5 结束节点标准JSONL文件输出与下载验证结束节点把LLM输出的原始文本直接作为结果返回节点配置里输入变量选LLM节点的输出text类型设为文件。运行工作流后从运行结果中直接下载JSONL文件。下载后不要直接入库先做一个最基础的检查确认文件可解析# 统计行数确认每条数据是独立的一行 wc -l output.jsonl # 逐行解析能跑通说明格式没有大问题 python -c import json,sys for i,line in enumerate(open(output.jsonl)): json.loads(line) print(parse ok, i1)如果python逐行解析报错优先看文件末尾是否有半行JSON这通常对应上一节说的上下文窗口不够或max_tokens太小调整代码执行节点的截断字符数或增大max_tokens即可解决。4. 提示词工程与语料质量评估从17条《少年歌行》样本看怎么验收4.1 system/user/assistant三段式提示词模板LLM节点引入的提示词分系统层和用户层。系统层定义输出格式与角色行为用户层注入文档文本和trigger。下面的模板可以直接复制你是微调语料生成助手。我会提供一段文档文本和一个触发词请基于文档内容生成JSONL格式的对话语料。 输出要求 1. 每行一个JSON对象结构为 {messages: [{role: system, content: 触发词}, {role: user, content: 问题}, {role: assistant, content: 解答}]} 2. system消息的content必须是触发词本身不要改写 3. 问题必须能从文档中找到依据答案忠实原文不补充编造细节 4. 问题表述要口语化、无歧义避免依赖背景知识 5. 只输出JSON行不要输出解释、标题或Markdown代码块标记用户消息里把truncated_text和trigger传入Dify变量。第5条不要输出Markdown代码块标记很关键模型在长文档输入下经常习惯性用json包住输出多包一层会让结束节点拿到的整个文件无法解析。4.2 JSONL格式规范与常见解析错误每条数据的标准结构是三层system角色放触发词user角色放问题assistant角色放解答。JSONL要求每一行都是完整独立的JSON对象行与行之间没有逗号字段顺序固定为role和content。实际运行中最高频的三个错误是assistant内容里出现未转义的双引号或换行、模型在数据前后输出解释性文字、字段名被改成其他写法。第三类错误最隐蔽因为json.loads能解析成功但训练框架读入时会因缺少标准字段直接报错。所以提示词里要明确字段名与结构禁止改动仅靠一个示例约束不够还要在系统提示里重复强调。4.3 质量评估三维度通俗性、准确性、格式规范性Dify把验证环节拆成三个维度问题通俗性、解答准确性、格式规范性三者缺一不可。评估维度检查方式常见失败模式问题通俗性逐条阅读user内容确认无歧义问题隐含只有原文才能回答的缩写与专名解答准确性对照原文定位答案出处assistant包含原文没有的推断或日期格式规范性json.loads批量解析加字段校验字段名被改写、多余解释、行尾缺失通俗性经常被忽略但它直接影响微调后的模型在真实用户提问下的表现。真实用户不会说请解释BGP与ECS的耦合关系他们更可能问为什么服务器外网经常断。语料里的问题如果太书面化调出来的模型在线上对话里会显得呆板。4.4 小样本验证后如何扩展到全量文档教学案例用的是《少年歌行》小说TXTtrigger设为你是少年歌行小说专家一次运行生成17条JSONL。这个体量做流程验证完全够直接拿去微调远远不够还需要把体量扩到几百上千条。常见做法是让文档提取器按章节拆分小说在代码执行节点里把章节编号写进去LLM节点按章节逐段生成每次控制在10到20条最后把多次运行的JSONL文件合并。合并时检查章节之间是否有重复问题最简单的方法是对user内容做MD5索引重复条目直接丢弃。先跑小样本验证三个质量维度再批量扩展是这条流水线上性价比最高的推进方式。5. 把语料流水线接入微调链路格式映射与LLaMA-Factory/LoRA衔接5.1 从Dify JSONL到训练框架的字段映射Dify结束节点输出的JSONL在自己的生态里直接可用但主流微调框架不会原样接受这套结构。社区里使用最广的LLaMA-Factory要求sharegpt格式外层字段从messages变成conversations用户与助手的角色名从user/assistant换成human/gpt。直接拿Dify的文件跑会报字段缺失这一步被很多教程跳过实际卡住最多。import json def dify_to_sharegpt(src: str, dst: str): with open(src, encodingutf-8) as f, open(dst, w, encodingutf-8) as out: for line in f: obj json.loads(line) msgs obj[messages] # Dify输出固定为 system/user/assistant 三段 conversations [ {from: system, value: msgs[0][content]}, {from: human, value: msgs[1][content]}, {from: gpt, value: msgs[2][content]}, ] out.write(json.dumps({conversations: conversations}, ensure_asciiFalse) \n)转换脚本把每条messages的三条内容按固定顺序重写字段后逐行写出。如果语料是多轮对话而非固定三段式后续轮次的user/assistant要按顺序追加到conversations数组末尾不能只取前三条。字段映射完成后文件交给LLaMA-Factory或直接做LoRA微调语料流水线才算真正闭环。5.2 批量生成时的运行约束批量跑整份文档时控制节奏比控制提示词更重要。SiliconCloud API有并发和速率限制工作流串行调用时跑几百条数据要留意单次运行耗时并行跑多个分支又要注意同一文档的多个分片之间不要互相踩重。现在一般会让代码执行节点输出章节编号LLM节点把章节编号写进user消息后续筛查时能知道每条数据来自哪段文档定位错误语料的成本会低很多。5.3 工作流与知识库流水线的边界Dify里除了工作流还有知识库流水线。两者都能处理文档但定位完全不同知识库流水线侧重文档切分、向量化和RAG检索输出的是检索片段本文讲的工作流侧重把文档转化为训练语料输出的是对话样本。1.17.1版本里知识库流水线有更新容易让人误以为它能直接生成微调语料。实际做语料构建时工作流加代码执行加LLM节点这套组合仍是正确选择要做微调语料构建就走工作流这条DSL要做RAG检索再切知识库流水线两个引擎不要混用。本文还有配套的精品资源点击获取