ChatGPT 把 JSON 当成普通文本读,而不是结构化数据

ChatGPT 把你的 JSON 当一大段文字读,靠字符串匹配回答,而不是跑 pandas。本文讲怎么逼它用代码沙箱、拿到真正算出来的聚合结果。

你传一份有 5,000 条记录的 orders.json,问”加州客户的订单金额中位数是多少”。ChatGPT 不写 pandas 代码,扫一眼前几千个字符就回”根据数据样本,中位数大约 80 美元左右”。这答案是凭感觉,不是算出来的。模型把 JSON 当成 prose 读,没去触发 Python 沙箱真正解析和聚合。结果听着自信、带数字,是错的。

最快的修复: 重新问一遍,带上明确的代码指令——Load orders.json into a pandas DataFrame and compute the median of total grouped by state. Show me the code.。措辞里点名 pandas、要求把代码给你看,ChatGPT 几乎一定会跑沙箱而不是瞎猜。下面这些都是这一招还不够时才用的。

根本原因是 ChatGPT 每一轮自己决定:把你的文件丢进 Python 沙箱跑,还是只当文本上下文读。这个沙箱功能现在叫 Code Interpreter & Data Analysis(老文档里你还会看到旧名 “Advanced Data Analysis” 和 “Code Interpreter”——同一个工具)。JSON 经常被路由到”上下文阅读”——尤其是文件够小能塞进 prompt,或者你的问题听起来像在请求总结。截至 2026 年 6 月,默认模型是 GPT-5.5,触发启发式在不同模型、不同选择器模式(Instant / Thinking / Pro)之间还会变,所以上周能触发代码的 prompt 这周可能就不行了。这篇讲怎么每次都把它逼到正确路径上。

你属于哪一类

症状大概率原因跳到
没有 “Analyzing” 步骤,也没有可展开的代码块模型压根没跑 Python原因 1、2
回答夹着”该数据集结构有差异”这类含糊话schema 不规整 / 嵌套原因 3
它跑的代码里报 json.load() parse errorNDJSON 用了 .json 扩展名原因 4
文件是建 Project / GPT 时传的,不是在消息里传的走了 vector embedding,不是沙箱原因 5
语音模式,或没启用代码能力的 Custom GPT当前界面没有沙箱原因 6
记录总数回来是个可疑的整数,还对不上内联进 prompt 后被 token 上限截断原因 7

常见原因

按命中率从高到低:

1. 文件够小塞得下,模型干脆不调沙箱

JSON 大致 200 KB 以下,模型常直接把整份内容内联进 prompt,当文本推理。没有 Python 跑过。中位数、百分位、group-by 这些聚合都是用眼睛估的。

如何判断:ChatGPT 没显示 “Analyzing” 步骤,也没有可展开的代码块。回答数字不精确。问”把你用的 Python 给我看”,它回”我从数据里估的”而不是给真代码。代码真跑过时,你会看到一个折叠的 “Analyzed” 小标签,点开能读到它执行的 pandas——没有这个标签就是没跑。

2. 问题写得像”总结”,不是”计算”

“告诉我这份数据的情况""主要规律是什么”——听起来像总结。模型走便宜路径,扫开头然后描述。量化措辞会触发代码,定性措辞不会。

如何判断:换成”用 Python 计算中位数并把代码给我看”会触发沙箱;原来的”大致是多少”不会。

3. JSON 结构不规整,模型放弃结构化处理

记录的 key 不一致、深度嵌套带可选字段、根层 array 和 object 混着。模型一看没法简单映射到表,干脆回退到文本阅读。

如何判断:本地检查 schema 会发现确实有可选 / 嵌套 / 不一致字段。ChatGPT 回答夹着”该数据集结构有差异”再做定性陈述。

4. NDJSON / JSON Lines 用了 .json 扩展名

文件每行一个 JSON 对象(NDJSON),扩展名却是 .jsonjson.load() 会失败。Code Interpreter 真被调起来也会抛 parse error,模型回退到读原始字节当文本。

如何判断:第一个字符是 { 第二行也是 { 开头 = NDJSON 不是 JSON。json.load() 会挂;pd.read_json(..., lines=True) 才行。

5. JSON 是 Project / Custom GPT 的 knowledge 文件

Projects 和 Custom GPT 的 knowledge 文件走的是检索式索引(file_search)——切块、embedding、按语义相似度搜,不是读进 DataFrame。聚合类问题返回的是检索到的片段,永远不会作为合计或分组结果被算出来。有个不完全的例外:如果这个 GPT 启用了 Code Interpreter & Data Analysis,模型有时能把 knowledge 文件复制进沙箱跑代码,但对大数据文件不可靠,模型往往还是默认走检索。稳妥的做法是改成每条消息附件(见下面修复 Step 5)。

如何判断:这份 JSON 是当初建 Project 或 GPT 时上传的(Configure → Knowledge,上限 20 个文件 / 每个 512 MB),不是对话里的每条消息附件。聚合类问题返回的是检索到的片段,不是合计。

6. 当前界面没启用代码沙箱

语音模式、某些移动端流程,以及任何没勾选 Code Interpreter & Data Analysis 的 Custom GPT,都不带 Python 沙箱。在这些界面里对数据文件做数值回答永远是估的。

如何判断:在 Custom GPT 里打开 Configure → Capabilities,如果 Code Interpreter & Data Analysis 没勾选,就没法跑代码。普通对话里,沙箱在 Plus / Pro / Team / Enterprise 上可用——如果你在限额很紧的 Free 档,复杂分析可能被限流或不可用。

7. token 预算到顶,文件被静默截断

大 JSON 内联进 prompt:只有头 N 个 token 进得来,之后的记录对模型来说不存在。聚合只在可见部分算出来。

如何判断:问”这份文件总共多少条记录?“如果回答是一个可疑的整数(比如”大约 1,000”)且实际数对不上 = 被截断了。

最短修复路径

Step 1: 显式要求用 Python

把”订单金额中位数是多少”换成:

用代码沙箱把 orders.json 读进 pandas DataFrame。按 state 分组算 total 字段的中位数。把代码和结果表都给我看。

这种措辞强制 tool-call。沙箱可用时,模型极少拒绝明确的”跑 pandas 并把代码给我看”请求。点名 pandas、要求看到代码,正是翻转路由的关键——光说”算个中位数”往往不行。

Step 2: 如果是 NDJSON 直接告诉它

这份文件是 NDJSON(每行一个 JSON 对象)。用
pd.read_json('orders.json', lines=True) 读。

把解析那一行喂到它嘴边,parse 失败分支整条消失。

Step 3: 先验证行数

每次都问:

先打印 len(df)df.dtypes。确认你读到了所有行再答。

行数和你预期对不上 = 截断 / NDJSON 误读 / 重复解析这类问题立刻暴露。

Step 4: 嵌套 JSON 先扁平化再聚合

import json, pandas as pd
with open('orders.json') as f:
    data = json.load(f)
df = pd.json_normalize(data, sep='_')

json_normalize 把嵌套键压成扁平列。之后 group-by 和聚合就和普通 CSV 一样。

Step 5: Project / Custom GPT knowledge 改成每条消息附件

需要聚合答案的话,别把 JSON 放进 Knowledge。改成在沙箱可用的对话里每条消息上传。Knowledge 是检索用的,不是算术用的。

Step 6: Knowledge 留给参考文字,不放数据

schema 规范、分类法、品牌文案——这类放 Project Knowledge。需要计数 / 过滤 / 求和的表格数据——这类做每条消息附件。

Step 7: 用一个你已知的数字交叉验证

挑一个你能对得上的值(记录总数、某一小列的 sum、某条具体记录)。让 ChatGPT 算这个值再对照。对得上 = 聚合结果可信;对不上 = 回去查哪一步偏了。

怎么确认真修好了

下面三条全满足,才说明你拿到的是代码算出来的真结果(不是估的):

  1. 回答里有一个可展开的 Analyzed 小标签,点开能读到它跑的 pandas——而不只是一段文字。
  2. 之前打印的 len(df) 和你从源文件预期的记录数对得上。
  3. 一个你已知的交叉验证值(一个计数、或某条记录的某个字段)回来完全正确。

任何一条没满足,模型就还在做字符串匹配。重发 Step 1 的 prompt,再加一句 Do not estimate — run the code and print the result.

不是你的锅的部分

是否跑沙箱这个决策完全不透明。OpenAI 调触发启发式,不同模型、不同选择器模式(Instant / Thinking / Pro)之间还会变。上个月能触发的 prompt 这个月可能不行了。唯一稳定的防御是显式要求”写代码”。

vector-embedded 的 Knowledge 仓在本质上就不是算术引擎。如果产品把你的文件路由到了检索,你没法靠 prompt 后期可靠地补上聚合能力——改成每条消息附件才行。

容易误诊为

  • “ChatGPT 数学不行”——Python 跑起来时它数学很好。读 prose 时才不行。
  • “文件太大”——几 MB 以内对沙箱完全没压力。问题是触发不触发,不是大小。
  • “JSON 写坏了”——多半没坏。先 jq . orders.json > /dev/null 验证一下,jq 退出码 0 就说明文件没事。
  • “Custom GPT 指令没生效”——指令不能可靠强制 tool-call,模型仍然会根据问题的措辞自己路由。

预防

  • 凡是对文件的量化问题,默认用”用代码沙箱算 X 并把代码给我”这种措辞。
  • 留一句固定的开场白:“先打印行数、列名、dtype 再答。”
  • 任何”需要聚合”的数据不要放进 Project Knowledge。Knowledge 是搜索索引,不是数据库。
  • 行分隔 JSON 用 .ndjson 扩展名,格式无歧义。
  • 复杂 schema 本地用 jq 或 pandas 先压平成 CSV,上传扁的 CSV。给模型留的功课越少越稳。

FAQ

  • 为什么 CSV 行 JSON 不行? CSV 几乎一定触发沙箱——扁、表格化、一眼能看出。JSON 有歧义;小 JSON 尤其常被路由到”读 prose”路径,因为它塞得进 prompt 窗口。
  • 能不能让 Custom GPT 永远走沙箱? 在 Configure → Capabilities 里勾选 Code Interpreter & Data Analysis,再把 instructions 写成:任何分析类问题都要写代码。即便如此,模型偶尔在边缘情况下还是会跳过,所以你的 prompt 里始终留着”跑代码、把代码给我看”这种措辞。
  • 怎么知道它真跑了 Python 而不是假装的? 点开回答里的 Analyzed 小标签读代码。没有标签、没有代码块 = 它在估。具体运行态长什么样,见 OpenAI 的数据分析指南
  • 嵌套 JSON 跑了 json_normalize 还是聚合不了,为啥? 记录里嵌套的 list 不会被扁平成标量列;json_normalize 会把它们变成”列值是个 list”的单元格。让模型用 record_path 定位到内层 list,或在分组前用 df.explode('items') 把它炸开。
  • Free 档有沙箱吗? Free(截至 2026 年 6 月是 GPT-5.5)能跑数据分析,但限额很紧;重活或反复跑可能被限流。Plus($20/月)及以上 headroom 大得多。
  • 是不是干脆转成 CSV 算了? 扁数据的话,是的——本地用 jq 或 pandas 导成 CSV,路由歧义全消,是最稳的上传方式。JSON 上传留给真正有嵌套的数据。

标签: #ChatGPT #ChatGPT 文件 #排查 #排查 #json #数据分析 #code-interpreter