Dify复杂数据清洗排行榜:Python脚本转换技巧
微调在Dify上的成败,首先取决于数据质量。直接拿原始Excel或CSV灌进平台,相当于在精密仪器里倒沙砾。Dify本身不提供交互式文本编辑、正则批量替换或语义去重功能,因此脏数据、字段错位、未脱敏的隐私信息都会原封不动进入训练管道。轻则输出不可控,重则直接被系统拦截。
要在Dify完成一次高质量的微调,第一步必须是:用Python脚本完成数据的清洗与结构转换。没有捷径可走。
环境准备:依赖安装不可跳过
新建一个本地Python项目目录,然后执行这条命令:
pip install pandas openpyxl numpy regex
注意openpyxl这个库——它不是可选项。很多人习惯用xlrd读.xlsx文件,但xlrd已经不支持新版Excel格式,直接报Unsupported format。你在本地调试通过的脚本,如果用了xlrd,上传到Dify的数据预览阶段就会看到字段全部错位。这种坑,没必要踩。
清洗核心字段:去除噪声与统一语义
具体该怎么处理?分两步走。
方法一:基础文本清洗,适用于客服对话、用户反馈这类文本。核心思路是写一个clean_text函数,把HTML标签、连续空白、全角标点、非法Unicode字符统统清理掉:
import re
def clean_text(text):
if not isinstance(text, str):
return ""
text = re.sub(r"<[^>]+>", "", text) # 去HTML标签
text = re.sub(r"[^\u4e00-\u9fa5\w\s.,!?;:()-]", "", text) # 保留中英文、数字和常见符号
text = re.sub(r"\s+", " ", text).strip()
return text
方法二:敏感信息脱敏,这一步是必须执行的,不是建议。Dify审核阶段会扫描上传文件中的手机号、邮箱、身份证号,一旦命中就直接拦截上传。所以要用正则把它们全部替换为占位符:
text = re.sub(r"1[3-9]\d{9}", "[PHONE]", text)
text = re.sub(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}", "[EMAIL]", text)
text = re.sub(r"\d{17}[\dXx]", "[IDCARD]", text)
【脱敏必须在清洗早期执行】——道理很简单:如果你先把文本小写化或压缩空格,原始格式的手机号(比如"139 1234 5678"或"139-1234-5678")就可能被正则漏掉。先脱敏,再做其他清洗操作,顺序不能乱。
结构化对齐:将源数据映射为Dify JSONL三元组
清洗完成后,下一步是要把Excel数据转换成Dify能够识别的JSONL格式。Dify要求的每条样本包含三个字段:instruction、input、output。
第一步:读取源文件并校验必需列
假设你的Excel文件名是qa_raw.xlsx,里面至少包含question和answer两列。读取时用dtype=str强制所有字段为字符串格式,避免数字被自动转换为科学计数法:
import pandas as pd
df = pd.read_excel("qa_raw.xlsx", dtype=str)
if not all(col in df.columns for col in ["question", "answer"]):
raise ValueError("缺少question或answer列,Dify微调必须包含输入输出对")
第二步:填充instruction字段
Dify要求每条样本都必须有instruction。如果原始数据里没有这个字段,就需要根据category或其他字段自动补全。举个例子:
df["instruction"] = df["category"].map({
"翻译": "将以下内容翻译成中文",
"解释": "用通俗语言解释以下概念",
"生成": "根据要求生成一段技术文档"
}).fillna("请按要求完成任务")
第三步:生成JSONL行记录并写入文件
逐行构造字典,注意input允许为空字符串但不能缺失,output不能为空值:
import json
with open("dify_ready.jsonl", "w", encoding="utf-8") as f:
for _, row in df.iterrows():
record = {
"instruction": clean_text(str(row.get("instruction", ""))),
"input": clean_text(str(row.get("question", ""))),
"output": clean_text(str(row.get("answer", "")))
}
f.write(json.dumps(record, ensure_ascii=False) + "\n")
验证JSONL格式合法性
这是最后一步,也是最容易被跳过的一步。很多人写完脚本就直接上传,结果Dify报"解析错误",又回过头来逐一排查。
最简单有效的方法是用jq工具验证:
jq -c . dify_ready.jsonl | head -n 3
如果每行输出都是一个独立的JSON对象,且没有逗号结尾、括号不闭合、中文乱码,就算通过。
如果报错parse error: Invalid string: control characters from U+0000 through U+001F must be escaped,说明clean_text函数没有清除ASCII控制字符。追加一条正则即可解决:
text = re.sub(r'[\x00-\x1f]', '', text)
验证通过后,dify_ready.jsonl就可以直接上传到Dify的「数据集」→「新建数据集」→「上传文件」了。整个流程走完,你会发现——好数据是好模型的前提,这句话不是口号。