【Bug已解决】Expected file to have JSONL format, where every line is a JSON dictionary. openai…
【Bug已解决】Expected file to have JSONL format, where every line is a JSON dictionary. openai createFile for fine tune 解决方案一、现象长什么样用 OpenAI 做微调时先把训练集上传到平台from openai import OpenAI client OpenAI() client.files.create(fileopen(train.jsonl, rb), purposefine-tune)结果立刻被服务端拒回Invalid file format. Expected file to have JSONL format, where every line is a JSON dictionary.或者更模糊一点openai.BadRequestError: ... expected each line to be a JSON object ...让人困惑的是文件明明是.jsonl后缀用文本编辑器看每行也像 JSON为什么 OpenAI 说不是每行都是 JSON 字典这背后的真正原因往往藏在肉眼看不见的细节里——末尾空行、字段里的真实换行、或是把整个文件写成了一个 JSON 数组。二、背景OpenAI 微调要求训练文件是JSONLJSON Lines即每行一个独立的 JSON 对象行与行之间用换行分隔整个文件不是一个大 JSON。服务端在上传后会逐行json.loads一旦某行解析失败或不是对象dict就抛出上面的错误。典型的合规单行长这样chat 微调格式{messages: [{role: system, content: 你是一个客服}, {role: user, content: 怎么退款}, {role: assistant, content: 请在订单页点击申请退款}]}注意三点整行必须能被json.loads解析成 dict不是一个 list也不是嵌套在数组里。字符串字段里不能出现真实的换行符。JSON 规范中字符串内的换行必须写成转义形式\n。如果你在 Python 里写line1\nline2然后手工拼字符串真实的换行会让这一行变成两行破坏 JSONL 结构。文件不能有末尾空行。很多人用write循环每行加\n最后多出一个空行那一行json.loads()直接失败。这三点是九成 Expected JSONL 报错的根。三、根因根因 A整个文件是 JSON 数组而非 JSONL。有人写出[{...},{...}]然后存成train.jsonl。服务端逐行解析第一行[不是合法 JSON 对象或把整个数组当一行但它是 list 不是 dict直接拒。根因 B某行字段里含有真实换行符。例如content来自一段多行文案里面是真\n0x0A 字符导致该行在物理上被拆成多行其中某一物理行不再是完整 JSON 对象解析失败。根因 C末尾空行 / 中间空行。文件最后多一个\n产生空行或数据里有空行json.loads()抛错。根因 D手动字符串拼接而非json.dumps。用 f-string 拼 JSON{messages: [...]}极易漏转义引号、换行得到非法 JSON。正确做法是用json.dumps它会自动转义换行和引号。根因 E编码 / BOM 问题。UTF-8 BOM 会让第一行开头多\ufeff偶尔干扰解析或文件不是 UTF-8。四、最小可运行复现复现末尾空行导致失败import json, io, tempfile, os # 错误写法每行加 \n最后多一个空行 bad for obj in [{messages: [{role: user, content: hi}]}]: bad json.dumps(obj, ensure_asciiFalse) \n bad \n # 末尾空行 path tempfile.mktemp(suffix.jsonl) with open(path, w, encodingutf-8) as f: f.write(bad) # 模拟服务端逐行校验 with open(path, encodingutf-8) as f: for i, line in enumerate(f, 1): line line.strip() if not line: print(f第 {i} 行是空行 - 触发 Expected JSONL 错误) continue try: json.loads(line) except json.JSONDecodeError as e: print(f第 {i} 行解析失败: {e}) os.remove(path)复现字段含真实换行raw 第一行\n第二行 # 真实换行字符 # 错误手工拼字符串换行未被转义 bad_line {content: raw } print(json.loads(bad_line)) # JSONDecodeError: Invalid control character五、解决方案第一层最小直接修复第一招用json.dumps生成每行绝不手工拼。import json records [ {messages: [ {role: system, content: 你是一个客服助手}, {role: user, content: 怎么退款}, {role: assistant, content: 请在订单页点击申请退款}, ]}, {messages: [ {role: user, content: 营业时间}, {role: assistant, content: 每天 9:00-21:00}, ]}, ] with open(train.jsonl, w, encodingutf-8) as f: for r in records: # json.dumps 会自动把字段里的真实换行转成 \n保证整行合法 f.write(json.dumps(r, ensure_asciiFalse) \n)json.dumps会替你转义所有内部换行和引号这是避免真实换行破坏 JSONL的根本手段。第二招去掉末尾空行。上面的写法每行都以\n结尾但最后没有额外的空行符合要求。如果你用列表writelines注意别多写一个空字符串。第三招上传前本地校验。def validate_jsonl(path): with open(path, encodingutf-8) as f: for i, line in enumerate(f, 1): s line.strip() if not s: raise ValueError(f第 {i} 行是空行) obj json.loads(s) # 解析失败会抛 JSONDecodeError if not isinstance(obj, dict): raise ValueError(f第 {i} 行不是 JSON 对象而是 {type(obj)}) validate_jsonl(train.jsonl) print(校验通过可以上传)第四招上传。from openai import OpenAI client OpenAI() resp client.files.create(fileopen(train.jsonl, rb), purposefine-tune) print(file_id:, resp.id)六、解决方案第二层结构化改进把记录结构、序列化、校验、路径收口成一个配置对象避免每次手工拼 JSON。from dataclasses import dataclass, field from typing import List, Dict, Any dataclass class OpenAIFineTuneFilePolicy: path: str train.jsonl encoding: str utf-8 ensure_ascii: bool False def make_messages(self, system: str, user: str, assistant: str) - Dict[str, Any]: return {messages: [ {role: system, content: system}, {role: user, content: user}, {role: assistant, content: assistant}, ]} def write(self, records: List[Dict[str, Any]]): with open(self.path, w, encodingself.encoding) as f: for r in records: # 唯一序列化入口杜绝手工拼接 f.write(json.dumps(r, ensure_asciiself.ensure_ascii) \n) def validate(self): import json as _json with open(self.path, encodingself.encoding) as f: for i, line in enumerate(f, 1): s line.strip() if not s: raise ValueError(f第 {i} 行空行) obj _json.loads(s) if not isinstance(obj, dict): raise ValueError(f第 {i} 行不是 dict) def upload(self): from openai import OpenAI client OpenAI() return client.files.create(fileopen(self.path, rb), purposefine-tune)用法policy OpenAIFineTuneFilePolicy(pathtrain.jsonl) policy.write([ policy.make_messages(客服, 怎么退款, 订单页点申请退款), policy.make_messages(客服, 营业时间, 9:00-21:00), ]) policy.validate() # 上传前本地把关 policy.upload()write是唯一序列化入口保证每行都经json.dumps转义validate在上传前复刻服务端校验逻辑把错误挡在createFile之前。七、解决方案第三层断言 / CI 守护把JSONL 合法性做成 pytest 断言集成到数据管线 CI提交训练数据前自动拦截。import json import pytest def _load_lines(path): with open(path, encodingutf-8) as f: return [ln.strip() for ln in f if ln.strip()] def test_no_blank_lines(policy): policy.write([policy.make_messages(s, u, a)]) lines _load_lines(policy.path) assert all(ln for ln in lines), 存在空行会触发 Expected JSONL 错误 def test_every_line_is_json_dict(policy): policy.write([policy.make_messages(s, u, a), policy.make_messages(s, u, b)]) for ln in _load_lines(policy.path): obj json.loads(ln) # 解析不出的行会抛错 assert isinstance(obj, dict) def test_inner_newline_escaped(policy): # 含真实换行的文本也必须能安全序列化且每行合法 rec policy.make_messages(s, 多行\n文本, 回复) policy.write([rec]) for ln in _load_lines(policy.path): obj json.loads(ln) # 若未转义这里会 JSONDecodeError assert \n not in ln[:-1] or \\n in ln # 真实换行必须被转义 def test_not_a_json_array(policy, tmp_path): # 反例整文件是数组必须被校验拒绝 bad tmp_path / bad.jsonl bad.write_text(json.dumps([{messages: []}]), encodingutf-8) with pytest.raises(json.JSONDecodeError): # 逐行解析时第一行 [ 不是合法对象 json.loads(bad.read_text(encodingutf-8).splitlines()[0])把这些断言挂到数据生成后的 CI 步骤能在调用client.files.create之前就发现空行、数组格式、未转义换行等问题。八、排查清单遇到 Expected file to have JSONL format, where every line is a JSON dictionary确认是 JSONL 不是 JSON 数组文件应是每行一个对象不要写成[{...},{...}]。用json.dumps写每行别手工 f-string 拼接它会自动转义内部换行和引号。检查末尾/中间空行多出的\n产生空行json.loads()失败删掉即可。字段里的真实换行必须转义多行文案里的\n让物理行数变多破坏 JSONL靠json.dumps解决。上传前本地复刻校验逐行strip()json.loadsisinstance(obj, dict)提前拦截。确认 UTF-8 无 BOMBOM 会污染第一行保存时选 UTF-8。用OpenAIFineTuneFilePolicy统一生成与校验从源头消除格式错误。九、小结OpenAI 微调上传文件报 Expected file to have JSONL format, where every line is a JSON dictionary根因几乎都是格式细节文件是 JSON 数组而非逐行对象、字段里藏了未转义的真实换行、或末尾多了一个空行。json.dumps是银弹——它自动转义换行与引号保证每行都是合法 JSON 对象再配上上传前逐行strip json.loads isinstance dict的本地校验就能在client.files.create之前拦下所有格式问题。用OpenAIFineTuneFilePolicy把序列化和校验收口为唯一入口这类报错从根上消失。至此 1000 篇任务收官。

相关新闻

从Demo到生产:构建可靠自动化流程的IPOO工程化框架

从Demo到生产:构建可靠自动化流程的IPOO工程化框架

最近在折腾一些本地化工具时,发现一个挺有意思的现象:很多开发者,包括我自己,都曾陷入过一个效率陷阱。我们花大力气把一个开源项目部署起来,跑通了官方示例,感觉一切尽在掌握。但当我们试图把它集成到自己…

2026/8/24 4:18:28 阅读更多 →
C语言长字符串换行:反斜杠续行与自动连接详解

C语言长字符串换行:反斜杠续行与自动连接详解

1. 从一行“超长”代码说起:为什么字符串换行是个问题?如果你写过C语言,大概率遇到过这种情况:一个字符串常量长得离谱,比如一段冗长的SQL语句、一个复杂的JSON模板,或者是一段给用户的详细提示信息。它在你…

2026/8/24 4:18:28 阅读更多 →
HarmonyOS 应用 · 校园宿舍拼单我的页深度解析:渐变用户卡与成就徽章的 ArkUI 实战

HarmonyOS 应用 · 校园宿舍拼单我的页深度解析:渐变用户卡与成就徽章的 ArkUI 实战

HarmonyOS 应用 校园宿舍拼单我的页深度解析:渐变用户卡与成就徽章的 ArkUI 实战 本文以 HarmonyOS 6.0(API 23) ArkTS 声明式 UI 为技术底座,逐行拆解「校园宿舍拼单」应用"我的"Tab(ProfileTab&#xff0…

2026/8/24 4:18:28 阅读更多 →

最新新闻

如何使用 effective-go 把 Go 代码评审从黑箱变成可勾选清单:新人快速上手指南

如何使用 effective-go 把 Go 代码评审从黑箱变成可勾选清单:新人快速上手指南

如何使用 effective-go 把 Go 代码评审从黑箱变成可勾选清单:新人快速上手指南 【免费下载链接】effective-go a list of effective go, best practices and go idiomatic 项目地址: https://gitcode.com/gh_mirrors/ef/effective-go effective-go 是一个把 …

2026/8/24 10:46:54 阅读更多 →
硬件性能调优与故障排查:从原理到实战的深度指南

硬件性能调优与故障排查:从原理到实战的深度指南

1. 从“硬件新问答”聊起:我们到底在问什么? 最近在几个技术社区和硬件发烧友群里,发现一个挺有意思的现象:大家讨论硬件问题的“姿势”变了。以前可能更多是“我的电脑蓝屏了怎么办?”、“这个显卡驱动怎么装不上&…

2026/8/24 10:46:54 阅读更多 →
如何让 AI 编程不跑偏:4 个可复制的避坑做法与 CLAUDE.md 配置

如何让 AI 编程不跑偏:4 个可复制的避坑做法与 CLAUDE.md 配置

如何让 AI 编程不跑偏:4 个可复制的避坑做法与 CLAUDE.md 配置 【免费下载链接】andrej-karpathy-skills A single CLAUDE.md file to improve Claude Code behavior, derived from Andrej Karpathys observations on LLM coding pitfalls. 项目地址: https://git…

2026/8/24 10:46:54 阅读更多 →
从零构建周末AI聊天机器人:基于Telegram与GPT的实战指南

从零构建周末AI聊天机器人:基于Telegram与GPT的实战指南

最近在探索AI助手与自动化工具的结合应用时,我发现很多开发者对如何将类似Grok这样的AI能力集成到日常聊天工具(如Telegram、Discord或企业微信)中,并赋予其实际、有趣的用途非常感兴趣。尤其是在周末,我们总希望有些工…

2026/8/24 10:46:54 阅读更多 →
DeepSeek Vision多模态模型在Codex平台的集成与实战应用指南

DeepSeek Vision多模态模型在Codex平台的集成与实战应用指南

DeepSeek Vision 识图模型正式发布,补齐了 DeepSeek 在视觉理解能力上的重要一环。这个多模态模型不仅能看懂图片,还能理解图片中的文字、图表、代码截图,甚至能进行复杂的视觉推理。对于已经习惯使用 Codex 平台的开发者来说,现在…

2026/8/24 10:46:54 阅读更多 →
LLM智能体如何革新RTL设计:从代码分析到PPA联合优化

LLM智能体如何革新RTL设计:从代码分析到PPA联合优化

1. 项目概述:当LLM智能体遇上RTL设计优化最近在数字电路设计圈子里,一个名为“RTLScout”的概念讨论度挺高。它不是一个具体的开源工具,而更像是一个前沿的设计范式或方法论框架。简单来说,RTLScout探讨的核心是:如何将…

2026/8/24 10:45:54 阅读更多 →

日新闻

前端内容安全与依赖审计实践

前端内容安全与依赖审计实践

前端内容安全与依赖审计实践 前端安全依赖分层防护。没有任何单一配置能替代输出编码、权限校验和依赖更新。 把不可信内容当作数据 默认使用框架的转义能力;确需渲染 HTML 时,先在服务端或可信的客户端库中进行白名单过滤。避免把用户输入直接赋给 inne…

2026/8/24 1:08:15 阅读更多 →
Windows登录密码存储机制全解析:从哈希算法到安全加固实战

Windows登录密码存储机制全解析:从哈希算法到安全加固实战

1. 项目概述:Windows登录密码的“黑匣子”每次你按下CtrlAltDel,输入密码,然后看到那个熟悉的桌面,这背后发生了一系列复杂而精密的操作。作为一名长期与Windows系统打交道的从业者,我经常被问到:“我的密码…

2026/8/24 1:08:15 阅读更多 →
AI面试系统安全挑战与解决方案

AI面试系统安全挑战与解决方案

1. 项目概述:AI面试系统的安全挑战去年参与某跨国企业AI面试系统部署时,遇到一个典型案例:候选人在视频面试中无意提到竞争对手产品名称,系统竟自动将该信息关联到企业知识库并生成竞品分析报告。这个看似"智能"的功能&…

2026/8/24 1:08:15 阅读更多 →

周新闻

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/24 0:06:02 阅读更多 →
SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/24 0:20:20 阅读更多 →
Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/24 0:14:11 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/23 18:47:06 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/23 12:10:44 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/22 3:22:48 阅读更多 →