微调数据集太难搞?我直接手搓一个开源项目!

883 阅读31分钟

如何将领域文献转换为可供模型微调的数据集?

大家好,我是 ConardLi

本文为:想微调特定领域的 DeepSeek,数据集究竟要怎么搞? 对应的第一个实战章节,通过今天的文章,将带大家学习:

  • 学会怎么找:了解一些获取公开数据集的途径和注意事项
  • 学会怎么用:使用 Easy DataSet 工具批量构造领域数据集
  • 学会怎么做:了解 Easy DataSet 的核心设计原理,你可以自己实现此类工具

一、获取公开数据集

很多情况下,如果你只是需要通过微调来提升模型某一方面的能力,在没有特殊的内部数据要求的情况下,是没必要自己去构造数据集的,因为目前互联网上存在着大量的公开且免费使用的数据集,下面就带大家来了解一下,常见的获取公开数据集的途径有哪些,以及对应的使用方法。

2.1 HuggingFace(🪜)

HuggingFace 是一个专注于自然语言处理和机器学习的社区平台,提供了大量高质量的数据集和预训练模型,也是目前 AI 领域最活跃的社区型平台。其数据集涵盖多种语言和任务,如文本分类、情感分析、机器翻译等。

  • 专注NLP/语音/多模态领域数据集
  • 提供Python库直接加载(datasets库)
  • 支持数据集版本控制与增量更新
  • 附带数据预处理脚本和评估指标

https://huggingface.co/datasets

HuggingFace 的 datasets 库也是一个非常方便的工具,可以轻松加载和处理数据集。

from datasets import load_dataset
dataset = load_dataset("glue", "mrpc")  # 示例:加载GLUE基准数据集

在平台上,也直接提供了可以直接在不同场景下使用数据集的代码示例:

2.2 Kaggle(🪜)

Kaggle 是一个数据科学平台,不仅提供大量的公开数据集,还举办各种数据科学竞赛。其数据集涵盖了计算机视觉、自然语言处理、数据可视化等多个领域。

  • 全球最大的数据科学社区驱动平台
  • 包含竞赛数据集、教程和工具
  • 支持在线内核(Kaggle Kernels)进行数据分析
  • 支持通过 API 批量下载

https://www.kaggle.com/datasets

在数据集详情页,直接提供了下载 zip 包的方式,也可以通过 Pythonkaggle datasets download -d <dataset-name> 进行下载。

2.3 Google DataSet Search(🪜)

Google Dataset Search 是一个专门用于搜索数据集的搜索引擎,能够帮助用户找到互联网上公开的数据集。

https://datasetsearch.research.google.com/

它支持跨多个存储库的搜索,包括 Kaggle、GitHub、HuggingFace 等。

2.4 awesome-public-datasets

GitHub 上的 awesome-public-datasets 是一个开源项目,汇集了各种主题的高质量公共数据集(不过已经有段时间没更新了)。这些数据集按照主题分类,如农业、生物、气候、计算机网络、教育、金融等。

https://github.com/awesomedata/awesome-public-datasets

2.5 openDataLab

openDataLab 是一个专注于中文数据集的平台,也是中国本土最大的开源数据集平台,提供了丰富的中文数据集资源。

https://opendatalab.com/

openDataLab 支持通过 CLI 和 Python SDK 下载,打开数据集详情后可以看到具体代码示例:

2.6 ModelScope

ModelScope 是阿里巴巴推出的 AI 模型与数据集中心,除了提供预训练模型外,还包含与模型相关的数据集。其实有点类似于中国版的 HuggingFace

https://modelscope.cn/datasets

ModelScope 同样也提供了用于拉取数据集的 SDK:

2.7 几个平台对比

平台适合领域数据量级语言侧重特色功能
HuggingFaceNLP/多模态英文即装即用
Kaggle通用型超大多语言竞赛生态
Google Dataset Search跨平台搜索全域多语言元数据聚合
Awesome-public-datasets学术研究英文领域细分
OpenDataLab中文场景中文本土化支持
ModelScope中文AI应用中文模型-数据协同

2.8 数据协议

大家在使用开源数据集的时候,有一点一定注意,就是数据集的协议。数据使用协议(License),直接影响数据能否合法使用,特别是关注能不能商用。

比如下面这个 Facebook 提供的推理数据集,协议为 cc-by-nc-4.0

如果大家不明白这些协议什么意思,直接问 AI 就可以:

如果是非商用数据集,大家一定不能用于公司内部业务的训练,自己学习使用是没问题的。

二、基于特定领域文献合成数据集

相信目前很多同学都在尝试用 AI 来构造数据集,大概就是用这样的方式:

比如这是一个回答效果:

第一个面临问题是回复长度的限制,结果被截断,然后生成的每条数据集中的问题和答案都比较简单,如果你用同一个文档重复问的话,模型给的回答大概率是会重复的,因为之前的上下文已经丢失了。

另外还有一个问题,目前很多 AI 平台支持的上传文件来进行问答的功能,并不一定都是利用模型本身的长上下文来做的,而是也结合了 RAG 来做,所以在上面这种场景,没有明确的问题,让 QA 自己来检索和回答,其实也会产生很大的幻觉,其中产出的很多内容都并不一定是你给定的文献里了,不信大家可以自己尝试检查一下。所以这种直接将整个问题丢给 AI 构造出来的数据集,质量肯定也是没法保障的。

所以这种方法大家就别考虑了。

2.1 构造领域数据集需要解决的核心问题

因为上一期视频里关于数据集构造的问题特别多,但也不是很明确,在开始做这个教程之前,我在交流群收集了一下,大家在构造数据集时究竟的面临的问题有哪些:

其中大部分都是从已有的领域文献来构造数据集的问题,我整理了一下,大概有这么几类:

  • 完全不知道怎么做,目前就在纯人工去做,想提高效率
  • 直接将文档丢给 AI ,但是 AI 对于大文件生成的 QA 对效果比较差
  • AI 本身有上下文的限制,一次不能生成太多的问题,分批生成后面又会生成重复的问题
  • 已经有整理出来的数据集了,想有一个批量管理数据集的地方,可以进行标注和验证
  • 对于数据集有细分领域的需求,不知道如何去构建领域标签
  • 想要微调推理模型,但是不知道推理微调数据集中的 COT 怎么构造
  • 想从一个格式的数据集转换成另一个格式的数据集,不知道怎么转换

于是我去检索了一下,目前没有任何一个项目能同时满足这些需求,这也是为什么大家对于构造数据集有这么多问题的原因。

那没办法了,只能我自己造一个工具来满足大家的需求了,这个工具得解决下面这些问题:

  • 能够做到基于 AI 辅助生成数据集,而且不丢失准确性
  • 能够解决由于模型上下文限制导致的截断问题
  • 能够批量构造数据集,能生成 COT,而且不生成重复的数据集,
  • 能够构建领域标签,并且按照领域树组织数据集
  • 能够合理的管理数据集,方便对数据集进行质量校验等操作
  • 能够方便的对生成的数据集进行格式转换,比如 Alpaca 和 ShareGPT 格式

于是就有了 Easy DataSet 这个开源项目,这个项目是我真正为解决以上问题,完全从大家需求的角度出发,从零编写的一个项目,希望能够满足大家对于数据集构造的各种场景。

https://github.com/ConardLi/easy-dataset

也是这期教程花费这么长的时间的原因,因为我是真的想做点实际能帮助到大家的东西,而不是用一些网上通用的套路来糊弄大家,这个项目也耗费了我比较大的心血,如果能帮助到大家,可以点个 Star ,我后面也会根据这个项目 Star 的数量来决定是否继续维护。

github.com/ConardLi/ea…

下面我们先来看看这个项目的基本使用方式。

2.2 Easy DataSet 使用方法

2.2.1 本地启动方法

Easy DataSet 目前还没有发布线上版本,只支持本地部署。

首先我们到 github.com/ConardLi/ea… ,可以看到项目提供了两种本地启动方式。

第一个是通过 NPM 启动(适合有代码基础的同学,可以直接改本地代码):

成功启动服务效果如下,本地默认监听 3000 端口

如果通过 NPM 启动,你的项目数据将存储到项目的相对目录,不用担心数据丢失。

启动必备环境:Git、Node.js,如果你是代码小白,不知道这两个环境怎么搭建,直接去问 AI 就可以,这里不做特殊讲解。

第二个使用过 Docker 启动(无法直接更改代码):

我会定期将最新代码打包成 Docker 镜像,并且推送到 DockerHub,所以本地有 Docker 环境的同学可以直接拉取启动(同样的,不会搭建 Docker 环境就问 AI)。

注意这里的 YOUR_LOCAL_DB_PATH 需要替换为大家的本地电脑的一个绝对路径,用于存放项目数据,避免 Docker 容器销毁后,本地的数据丢失。

成功启动项目后,访问 http://localhost:3000/ ,大家应该能看到这样的页面:

2.2.2 数据集广场

这里先说一下这个搜索数据集模块:

上面我们提到的各种检索公开数据集的途径,我直接聚合在这个模块里了,大家只需要在这个搜索里输入关键字,就可以快速在多个平台进行检索:

另外,在下面的里表里也集合了多个公开的获取数据集的平台:

2.2.3 项目

项目是 Easy DataSet 中的一个最小工作单元,一个项目下有一份独立的配置,可以处理一个文献并且管理基于这个文献生成的所有问题和数据集。

创建新项目,只需要输入项目名称和描述,名称和描述只用于记录和查看,不会影响后续的数据集生成任务。

2.2.4 模型配置

创建新项目后,默认会进入「项目设置 - 模型配置」页:

在这里我们可以配置后续用于处理文献和生成数据集的模型,比如选择 Ollama ,平台将自动获取你已经通过 Ollama 下载到的模型:

或者编辑其他模型提供商,输入 API 密钥,以及模型名称即可:

注意:你的所有配置信息都会保存到本地,不会被上传至远端服务器,无需担心数据泄露。

或者你也可以添加任意的三方 API ,只需要填写:模型名称、接口地址、API 密钥即可,所有兼容 OPEN AI 格式的 API ,平台都是支持配置的。

配置完成后,可以将无需关注的模型配置删除:

2.2.5 模型测试

为了测试模型配置的准确性,平台实现了一个在线的 Playground,选择模型后,如果这里能够输出成功,则配置正常:

另外,这里还支持同时选择多个模型(最多三个)进行模型回答效果的对比,可以方便大家测试在不同的任务场景下,哪个模型的效果更好:

模型测试完没问题后,我们可以直接到文献处理模块。

另外有一点需要特殊提醒一下,在后续的任务上,强烈建议大家不要选择本地 Ollama 部署的小参数模型,比如 7B、14B 左右的模型,在生成结构化数据的效果上非常差,会导致最终任务报错,或者影响数据集的准确性,建议大家选择上下文比较长的模型来保障最终效果。

2.2.6 文献处理

因为是第一个版本(作者只花了大概三个晚上的时间做出来的),只实现了一些核心功能,所以这里上传文件的格式只支持 Markdown

Markdown 在结构化方面,可通过标题、列表等清晰构建文档层次结构,使内容逻辑一目了然。语法方面,简洁直观,符号表意明确,无需复杂代码,能轻松实现文本格式设置。

目前业界有很多成熟的工具可以将其他格式(如 PDF、Word)转换为 Markdown 语法,后续平台也会支持默认转换,这里我们可以先借助一些第三方平台来转。

比如:MinerU

这是我输入的一个 PDF 转换示例,效果非常不错:

我们直接把转换好的文件上传上去,然后点击「上传并处理文件」:

注意在点击处理前,一定要先在右上角选择好模型,否则会导致处理失败,注意,这一步大家没必要选推理模型(比如 DeepSeek-R1),选择一个普通的问答模型比如豆包、千问都可以,在这一步推理模型并不会起到优势,而且会拖慢处理速度。

这一步的处理主要有两个,第一个就是将传入的文献进行了智能的文本分割,我们可以在分割列表里看到被拆分好的文本块,以及每个文本块的字数:

点击可以查看文本块的详情,包括对文本块的摘要提取,以及文本块的正文:

大家可以看到,分割后的文本块非常整齐,基本上都是按照章节划分的,而且比较少会出现在一个章节分成两个文本块的情况,这样可以充分保障后面生成问题、以及生成数据集的质量,具体方法呢,我们在后面实现原理的部分再讲。

如果大家觉的文本块分割的太大或者太小,可以到「项目设置 - 任务配置」里,设置文本分割的最小长度,以及最大长度:

然后我们发现右侧还有一个领域分析的 TAB:

在这里,我们可以看到基于 AI 智能分析出的这个文献的领域树,后面在生成问题以及数据集的时候,我们都会基于这个领域树去构建,并且把生成的问题和数据集映射到每个领域标签上。领域树可以让每条3数据集具备全局理解的能力,并且减少生成重复数据集的可能性。

如果大家觉得 AI 生成的领域树,有哪些不准确或者不完善的地方,也可以直接手动添加或者更改和删除标签,建议大家把领域树的划分确认的更准确后,再去生成问题。

另外,我们也可以在这里看到基于文献提取出的原始目录结构:

然后,回到智能分割 TAB,我们可以点击每个文本块上的问题图标,为这个文本块创建问题:

任务完成后我们可以看到创建好的问题:

每个文本块生成多少问题,是由「项目设置 - 任务设置」里的生成问题的最大长度决定的,默认设置是每 240 个字符生成一个问题,所以上面 2000 字符左右的文本块生成了 8 个问题,大家可以根据自己文献的信息密度来灵活调整。

我们也可以批量或者全选文本块,然后点击批量创建问题:

注意创建问题的过程中,不要关闭页面,否则将中断任务,或者如果你想主动中断任务,刷新页面即可:

2.2.7 问题管理

问题生成任务完成后,我们可以到问题管理模块,详细查看刚刚生成的所有问题,包括问题的领域标签、问题所属的文本块:

转存失败,建议直接上传图片文件

另外,问题管理模块还提供了领域树视图,我们可以以领域树的维度来呈现问题,更方便的帮助我们展示生成问题的全貌

我们可以在这个模块删除觉得质量较低的问题(比如跟文献的作者、标注等不相关的问题),避免后续构造出一些质量较低的数据集。

然后我们可以点击问题上的魔法棒图标,来生成对应的答案:

然后我们可以看到已经生成了答案的问题,一个问题可以生成多个答案:

Easy DataSet 会根据问题+问题对应的文本块来一起生成答案,来保障答案和文献本身的相关性。

同样的,我们可以批量或者全选问题,来批量生成答案:

注意创建答案的过程中,不要关闭页面,否则将中断任务,或者如果你想主动中断任务,刷新页面即可:

如果你想生成带思维链的答案,可以选择推理模型(推荐 DeepSeek-R1)来生成数据集:

后续我们也将支持在非推理模型上直接生成 COT,大家敬请期待!

2.2.8 数据集管理

然后,我们可以到数据集管理模块,看到(搜索)所有已经生成好的数据集:

点击数据集,我们可以查看数据集的详情,包括原始问题、问题的回答、思维链(如果有的话),以及生成此数据集所用的模型、此数据集的领域标签以及创建时间。

如果大家对答案,或者数据集生产的结果不满意,可以删除数据集,如果觉得效果比较好,可以确认保留(这里只是方便在数据集数量比较大的时候进行记录,不影响导出),另外也提供了快速向前向后翻页的功能:

如果觉得答案和思维链有些稍微需要调整的地方,可以手动编辑:

如果想让 AI 帮忙优化,可以点击魔法棒图标,输入优化思路:

AI 优化后的效果:

2.2.9 数据集导出

数据集确认完成后,我们可以点击右上角的导出数据集:

在导出选项中,目前支持以下配置:

  • 选择文件格式:支持 JSON、JSONL 两种格式
  • 选择数据集风格:支持 Alpaca、ShareGPT ,以及自定义风格(在自定义风格中,可以配置问题、回答对应的字段格式以及是否包含领域标签)

  • 系统提示词:会分别在 Alpaca 和 ShareGPT 中增加 System 字段
  • 仅导出已确认数据(默认勾选)
  • 包含思维链(默认勾选):将思维链回答拼接到 Thing 标签内,和回答合并

一个导出的数据集案例:

这里是一个内部测试用户用平台生成的医疗行业数据集:

后续这里也会支持一键上传 HuggingFace 平台,以及其他更多格式。

2.3 Easy DataSet 核心原理

下面我也来大家了解一下 Easy DataSet 项目的核心原理,第一个是希望大家也能学习了解此类工具的构建思路,后续也能做到自己搭建类似的产品,第二个是希望能够深入了解的小伙伴可以一起参与到 Easy DataSet 项目的建设,想要做好一个开源产品,一个人的精力肯定不够,我这里还有很多想法没有实现,希望感兴趣的小伙伴一起来参与,把它完善成一个成熟的产品。

相信走完上面的流程,大家已经对这个工具的核心设计思路有了基本的了解了,其实核心就是下面这三个部分:

  • 模型管理:一个通用的大模型管理模块,负责对用户配置的 LLM API 进行统一封装和调用;
  • 文献处理:对用户输入的文献进行统一处理,包括格式转换,对文本进行智能分块,目录大纲提取;
  • 数据集构建:当文献以及文本分块处理完成后,需要调用 LLM API分别对文本块进行处理,生产标签、问题、数据集等。

下面我们分别来看看这三个模块的核心构建原理。

2.3.1 模型封装

大家可能都用过像 Chatbox、Cherry Studio 这样的本地模型调用工具,这些工具的底层核心,其实就是封装了各种模型或者三方模型提供商提供的开放 API,你只需要填几个关键参数就可以直接在本地调用了。

大家可能觉得,要支持这么多的模型以及三方平台的 API 调用,肯定需要做很多适配工作。

其实不然,目前大部分主流的模型提供商支持的 LLM API 都是符合标准的 OPEN AI 格式的。

我们只要掌握了这个 API 的封装方法,那大家完全可以自己在实现这些工具,比如下面几个平台:

很明显,API 的调用格式都是完全一样的,封装 API 的核心替换就是以下几个内容:

  • API 的前缀:可以看到 API 的Path 都是以 /chat/completions 结尾,所以只需要替换前缀,就可以区分不同的模型提供商。

  • APIKey: 这个就是用来做鉴权的,所有的 API 都是通过标准的 Bearer Token 认证方式。

Bearer Token 是一种基于令牌的认证方式。客户端在请求中携带一个令牌(通常是 JWT 或 API 密钥),服务器通过验证令牌的有效性来确认请求的合法性。

简单理解,就是每个用户可以生成一个密钥 ,用这个密钥来给你做鉴权,表示是你在调用,所以这里的密钥一定不能泄漏。

  • 模型名称:这个很好理解,用于标识你要调用的具体模型。

需要注意的是,同一个模型在不同平台上,模型的唯一标识可能是不一样的,比如你通过 DeepSeek 官方 API ,调用 R1 需要传入 deepseek-reasoner

而在硅基流动上需要传入 deepseek-ai/DeepSeek-R1

做一个模型的配置调用的配置,其实加好这三个关键参数就好了,回顾下我们平台的模型配置模块,其实只需要让用户支持输入 模型名称、接口地址、API 密钥,就可以实现任意符合 OPEN AI 格式的 API 调用了(提供商只是个标识,不起实际作用):

然后在列表里已经内置的模型,其实就是默认把这个模型提供商的 API 前缀、支持的常用模型内置下来了,你只需要填自己的 API 密钥就可以。

我们再来看一些接口里的其他参数,比如传入的消息上下文:

是不是看着很眼熟,其实这就是我们上个教程里提到的标准的 OPEN AI 格式的数据集的格式,大家只需要按照这个消息格式来进行组织就可以实现多轮对话。

另外还有几个可选的参数,比如:

  • stream:是否采用流式输出
  • temperature:控制生成文本的随机性,较高的值(如 0.8)会使输出更随机,而较低的值(如 0.2)会使输出更确定。
  • max_tokens:限制模型生成的最大 Token 数。

了解完这个,你也可以自己封装一个通用的模型调用中心了。

2.3.2 文本分块

下面一个核心内容就是文本分块了,把一个长文献,合理的分割出多个文本块,对于后续基于文本块生成问题和数据集是非常重要的,如果随意分割,可能会导致一些关键信息丢失。

  1. 超出上下文长度:大模型处理文本有长度限制,不分块可能导致部分文本无法被完整处理,信息丢失。
  2. 处理效率低下:不分块直接处理会导致模型需要处理大量文本,增加计算负担,处理速度慢。
  3. 语义理解困难:不分块的文本信息混杂,模型难以准确提取关键内容,导致生成的回答不够精准。

在 RAG 架构中,对数据进行向量化之前,第一步就是对数据进行分块,分块的合理性其实也会直接影响知识库最终检索的准确性:

最简单的分块策略就是完全按照字符数分块:

这种方式非常粗暴,优点是产出的块很统一,字符数都一样,缺点就很有可能会破坏原有的文本结构,可能切断重要的上下文。

另外一种常见的策略就是递归分块。

递归分块就是把文本一层一层地切开,先用大的分隔符(比如句号)把文本切成大块,然后再检查这些块的大小,如果太大,就用更小的分隔符(比如逗号)继续切,直到每个块都符合要求。这个过程就像切蛋糕,先用大刀切出几大块,如果某一块太大,就换小刀继续切,直到每一块都合适。

在切块的时候,还会用到一个叫 chunkOverlap 的技巧。简单来说,就是相邻的两个块之间会有一些重复的内容,就像两块拼图之间有部分重叠一样。比如,假设我们设置 chunkOverlap 为 50 个字符,那么在分块时,相邻的两个块之间会有 50 个字符的重叠。这样做的好处是,即使某个重要的信息恰好位于块的边界上,也能被完整地保留下来,确保模型在生成回答时能够参考到这些关键信息。

递归分块的好处是它很灵活,可以根据文本的长度和结构动态调整分块方式,确保每个块都有意义。而且它能处理各种类型的文本,无论是新闻、论文还是小说,都能通过递归分块得到有效处理。这种方法在RAG架构中能显著提高文本检索和生成的质量,让回答更准确、更有用。

比如在 langchain 里提供了 RecursiveCharacterTextSplitter ,就是用来对文本做递归分块的。通过测试这个方法,我发现分割之后的效果没有达到我的理想效果。

比如在对一个文件分割完成后,第 16、17 个文本块,我发现同一个章节被分割到了两个不同块里,因为这里的最小分割单元是一句话,不会考虑整个章节的问题:

这无论是在知识库检索、还是我们的微调数据集生成时,都不会起到很好的效果。

为了解决这个问题,我决定自己实现一套加强版的递归分块的算法,也就是代码里的 lib/split-mardown 模块:

具体的代码我就不讲解了,我的核心思路是这样的:

  • 首先需要设定文本块的最小、最大分割长度;
  • 然后自动对章节(比如 Markdown 里的 #、##、###)进行识别;
  • 对已识别到的章节字数进行计数,在恰好位于 > 最小分割长度 同时 < 最大分割长度的前提下进行分段;
  • 当遇到超长段落(超出最大分割长度)的时候,在执行递归分段算法,确保语义的完整性。

在大部分情况下,可以达到这样的效果,一个文本块不会出现截断章节的情况,同时分割字符数处于最小和最大分割数的区间:

同时,这个模块还实现了文献大纲的提取、单个文本块的摘要提取等功能,目前我测试的效果还是非常不错的:

看到这,你也可以自己去实现文本分块啦!

2.3.3 提示词

调用大模型进行分析,最终的效果其实很大程度上取决于提示词的质量,目前 Easy Dataset 项目里的提示词就是下面这几个(根据用户选择的中、英环境会选择不同语言的提示词):

  • label:为文献构建整体的领域树;
  • question:基于指定文本块生成问题;
  • addLabel:基于领域树为问题打上对应的领域标签;
  • answer:基于问题、文本块,生成指定答案;
  • newAnswer:基于用户的优化思路,为问题重新生成答案;

这里我们挑其中一个来讲解:


module.exports = function getAddLabelPrompt(label, question) {
  return `
# Role: 标签匹配专家
- Description: 你是一名标签匹配专家,擅长根据给定的标签数组和问题数组,将问题打上最合适的领域标签。你熟悉标签的层级结构,并能根据问题的内容优先匹配二级标签,若无法匹配则匹配一级标签,最后打上“其他”标签。

### Skill:
1. 熟悉标签层级结构,能够准确识别一级和二级标签。
2. 能够根据问题的内容,智能匹配最合适的标签。
3. 能够处理复杂的标签匹配逻辑,确保每个问题都能被打上正确的标签。
4. 能够按照规定的输出格式生成结果,确保不改变原有数据结构。
5. 能够处理大规模数据,确保高效准确的标签匹配。

## Goals:
1. 将问题数组中的每个问题打上最合适的领域标签。
2. 优先匹配二级标签,若无法匹配则匹配一级标签,最后打上“其他”标签。
3. 确保输出格式符合要求,不改变原有数据结构。
4. 提供高效的标签匹配算法,确保处理大规模数据时的性能。
5. 确保标签匹配的准确性和一致性。

## OutputFormat:
1. 输出结果必须是一个数组,每个元素包含 question、和 label 字段。
2. label 字段必须是根据标签数组匹配到的标签,若无法匹配则打上“其他”标签。
3. 不改变原有数据结构,只新增 label 字段。

## 标签数组:

${label}

## 问题数组:

${question}


## Workflow:
1. Take a deep breath and work on this problem step-by-step.
2. 首先,读取标签数组和问题数组。
3. 然后,遍历问题数组中的每个问题,根据问题的内容匹配标签数组中的标签。
4. 优先匹配二级标签,若无法匹配则匹配一级标签,最后打上“其他”标签。
5. 将匹配到的标签添加到问题对象中,确保不改变原有数据结构。
6. 最后,输出结果数组,确保格式符合要求。

## Output Example:
   \`\`\`json
   [
     {
       "question": "XSS为什么会在2003年后引起人们更多关注并被OWASP列为威胁榜首?",
       "label": "2.2 XSS攻击"
     }
   ]
   \`\`\`

    `;
}

整体使用 LangGPT 的风格来编写的提示词:

  1. Role(角色) 定义模型身份与任务边界,明确“你是谁”“要做什么”,比如“标签专家”,约束模型行为的专业领域

  2. Skill(技能) 列举模型完成任务所需的核心能力,如“熟悉层级结构”“处理复杂逻辑”,强化模型对自身能力的认知,避免越界输出。

  3. Goals(目标) 用结果导向的语言,明确任务要达成的具体效果(如“优先匹配二级标签”),对齐人机双方对“成功”的定义

  4. OutputFormat(输出格式) 强制规定输出的结构(如JSON数组、字段名),消除歧义,确保结果可被系统解析,常用于API或自动化流程。

  5. Variables(变量区) 预留动态填充的输入位(如${label} ${question}),分离固定逻辑与可变数据,实现提示词模板的复用。

  6. Workflow(工作流) 拆解任务为可执行的步骤(如“遍历→匹配→添加标签”),降低模型思考成本,尤其适合新手或复杂任务。

  7. Constrains(约束) 用“必须/禁止”类规则限制输出(如“不改变原有数据”“标签必须存在”),防止模型发散,确保结果一致性

  8. Examples(示例) 提供格式正确的输出样例,通过具象化案例强化模型对规则的理解,尤其适用于格式敏感型任务(如JSON)。

通过这样的编写方式,可以极大提升模型最终输出的稳定性,当然仅限于具备长上下文理解能力的模型,所以在这个项目里强烈不建议大家使用本地蒸馏过的小模型来跑,不管提示词如何,最终输出的稳定性都得不到保障。

其他的提示词都是基于这个思路来写,大家可以自己去阅读。

2.4 Easy DataSet 后续计划

目前 Easy DataSet 项目刚刚发布了第一个版本,还有很多需要完善的地方,而且我自己的很多构想还没有实现,如果本期教程发出后,大家觉得还可以,并且有一定的 Star 的数量,我就会继续维护,直到把它打造成一个完善的数据集产品,后续大概的迭代方向如下:

  • 支持多种文件格式的处理(包括 PDF、Excel、Txt、Word 等);
  • 支持强化学习偏好数据集的质量标注,完善数据集评估能力;
  • 支持不基于领域文献,直接基于大模型生成用于模型蒸馏的数据集;
  • 支持将数据集一键上传 HuggingFace 等平台;
  • 支持从 HuggingFace 等平台一键拉取数据集,进行二次评估;
  • 上线 Online 版本,支持不想要本地部署的部分用户;

大家最想要哪些功能,可以在评论区留言,另外大家有想参与共建的也可以直接来 PR,欢迎共建,觉得不错的话,一定要留个 Star 呀!

github.com/ConardLi/ea…

最后

大家有任何问题,欢迎在评论区留言。

为了方便大家交流学习,我准备组建一个 AI 交流群,本文中微调案例中使用到的完整代码,我也会发到群里,想要在群里和大家一起讨论 AI 技术的小伙伴可以添加我的个人微信 ConardLi(备注 AI),拉你进群。

点赞评论关注 是最大的支持 ⬇️❤️⬇️