郭禹 · AI数据采购Owner实战学习包

返回课程入口

Python零基础到批量验收

AI数据采购Owner实战课 · 第一册 · 2026-09-28

目标:把你已经掌握的JSON知识变成批量检查能力。你将亲手读取20条记录,定位类型、重复、路径、音频属性和质检声明问题,生成可追溯的问题报告。你不需要先学算法、模型训练或网站开发。

01 你要学到什么程度

采购Owner的核心是把需求、质量口径和交付责任说清楚。Python帮助你验证交付,而不是替你决定验收标准。

完成本课后,你应能独立做五件事:打开并运行脚本;读懂输入、规则和输出;修改一个已有检查条件;定位坏数据和运行错误;解释报告覆盖范围。

能力本课要达到现在不用追求
数据读取JSON、JSONL和本地文件路径大规模数据平台
基础语法变量、字典、列表、循环、条件、函数、异常复杂面向对象设计
检查缺失、类型、重复、文件存在、WAV属性全模态自动质量判断
报告行号、编号、规则、证据、分母与未检项漂亮但无法复核的仪表盘
协作向工程师提出可验证的规则需求从零重写所有工具

你的毕业标准不是背语法,而是能拿着报告告诉供应商:哪条有问题,违反哪一版规格,证据在哪里,如何回源修复,以及复验什么。

02 第一次准备:文件夹、Python和终端

1. 解压完整学习包到一个自己找得到的位置,例如文档目录。暂时保留所有文件名和目录结构。

2. 双击“开始学习.html”阅读课程。HTML是教材,不会替你执行Python。

3. 在解压后的文件夹空白处右键,选择“在终端中打开”;也可以在资源管理器地址栏输入powershell并按回车。打开后应在课程根目录,能看到data、lessons、tools等文件夹。

4. 输入下面一行,回车:

python --version

如果出现Python 3.x,确认版本至少3.10;建议用当前受支持版本。如果无法识别,再试:

py --version

如果只有py有效,后续示例中的python统一换成py。如果两个都不可用,到Python官方下载页按Windows安装提示安装,关闭并重新打开终端,再检查。Windows安装方式可能变化,以官方Windows说明为准。不必为了这套课程卸载电脑已有的Python。

“终端”是输入运行命令的地方;“.py文件”是保存代码的地方。不要把python tools/validate_batch.py写进.py文件。看到>>>表示进入了Python交互窗口,输入exit()并回车,回到终端后再运行本课命令。

编辑代码可以使用已有的代码编辑器。没有编辑器时,记事本也能完成最初练习;保存为UTF-8,确认后缀确实是.py,不是.py.txt。编辑原始练习前先保存副本。

03 第一段程序:先运行,再改一行

在课程根目录的终端输入:

python lessons/01_hello.py

预期看到欢迎语、总数20、问题记录占比0.85。这个占比是练习中17÷20,不是模型错误率,也不是合格语音比例。

print("开始你的第一次批量验收练习。")
total = 20
bad = 17
print("总数:", total)
print("问题记录占比:", bad / total)

print负责显示。引号里的内容是文字;20是数字;total是变量名,表示给数字起个方便引用的名字;=是赋值。#后面的文字是注释,不会执行。

动手:把副本中的total改成100、bad改成3,再运行。应得到0.03。显示成3%可以写print(f"问题记录占比:{bad / total:.1%}")。f字符串用花括号嵌入计算结果;:.1%表示百分比保留一位小数。

采购思考:一条样本有三处问题,坏样本数仍是1,缺陷数是3。必须说明分子、分母及统计单位。

检查点:你能找到运行中的脚本、改一行、保存并重新运行,而不是只看截图。

04 把JSON翻译成Python

你熟悉的JSONPython中的常见对应注意
对象 {...}字典dict用字段名取值
数组 [...]列表list可按顺序循环
字符串 "th"字符串strPython单引号也合法,JSON字段仍用双引号
数字 3、1.5int、float"3"是文字
true / falseTrue / False大小写不同
nullNone不等于空字符串或0
record = {"sample_id": "A001", "duration_seconds": 1.0}
print(record["sample_id"])
print(record.get("language"))

第一行建立字典。record["sample_id"]取已有字段;字段不存在时会报KeyError。get取不到字段会返回None,让你继续判断。正式检查中,“缺字段”和“字段明确为null”可能需要分开记录;可用"language" in record判断是否存在。

records = [{"sample_id": "A"}, {"sample_id": "B"}]
print(records[0]["sample_id"])

结果为A。Python从0计数,所以records[0]是第一条。给供应商的报告用真实文件行号,从1开始,别混淆。

动手:新建一个字典,加入language="th"和quality_checked=False,打印这两个字段。False只是一个声明值,不能据此知道真实审核过程。

05 条件和循环:让电脑重复检查

运行:

python lessons/02_records.py

预期:A通过此项,B与C有问题。查看脚本:

for record in records:
    value = record.get("duration_seconds")
    if type(value) in (int, float) and value > 0:
        print(record["sample_id"], "时长类型和正数检查通过")
    else:
        print(record["sample_id"], "时长有问题:", repr(value))

for表示逐条处理;if表示如果;else表示否则;and表示两个条件都要满足。冒号后面缩进四个空格,表示哪些动作属于这个循环或判断。不要混用Tab和空格。

type看真实类型。这里不用简单的isinstance(value, int),因为Python里True也属于int的子类;在项目时长中把True当1秒会造成漏检。repr让字符串周围显示引号,便于看出"1.0"与1.0的区别。

动手:把条件补成“数字且大于0且不超过30秒”,加入一条31秒样本。预期31秒被拦截。真实项目的上限必须来自规格,不能照搬30秒。

06 路径和文件:为什么电脑说找不到

from pathlib import Path
root = Path(__file__).resolve().parents[1]
path = root / "data" / "broken.jsonl"

from...import引入现成能力。Path处理文件路径;__file__是当前脚本;resolve得到完整位置;parents[1]从lessons里的脚本回到课程根目录。这里的/用于拼接路径,不是数学除法。

运行命令时,python lessons/03_read_jsonl.py中的路径仍相对于终端当前目录。因此请先在课程根目录打开终端。脚本内部则通过自身位置寻找data,减少切换目录造成的错误。

Windows完整路径有空格时,在命令中用双引号包住路径。不要随意把客户给的路径直接用于读写:需要限制在本批次目录内。../表示上一级目录,本课会拦截逃出audio目录的路径。

动手:找到data/broken.jsonl,用记事本打开。你应该看到三行;第二行故意多了逗号。

07 读取JSONL:坏一行,不能丢掉证据

运行:

python lessons/03_read_jsonl.py

预期第1、3行读取成功,第2行解析失败,汇总成功2、失败1。必须继续看到第三行,且失败行不能从报告里消失。

with path.open(encoding="utf-8") as file:
    for line_number, line in enumerate(file, start=1):
        try:
            record = json.loads(line)
        except json.JSONDecodeError as error:
            print("第", line_number, "行解析失败:", error.msg)
            continue

with负责读完后关闭文件;encoding指定文字编码;enumerate同时给你行号和内容;json.loads把一行文字解析成Python对象;try尝试执行;except处理预期错误;continue转到下一行。

不要写“except: pass”把所有失败藏起来。它会让交付数量悄悄减少,也让采购Owner失去追责证据。解析成功也不代表字段、业务或内容正确。

动手:复制broken.jsonl为broken_fixed.jsonl,去掉第二行末尾多余逗号,把脚本副本的输入文件名改为新名字。预期成功3、失败0。保留原始错误文件作为练习证据。

08 函数:把一条规则写清楚

运行:

python lessons/04_function.py

预期A通过;空字符串与缺失编号都提示错误。函数是一段可重复调用的检查。

def check_id(record):
    value = record.get("sample_id")
    if not isinstance(value, str) or not value.strip():
        return "sample_id必须是非空字符串"
    return None

def声明函数;record是输入;return是输出;strip去掉两端空白;or表示任一条件成立就进入错误分支。此函数只判断编号是否非空,不判断是否重复,也不判断编号对应的真实身份。

动手:加一条只包含三个空格的编号,应被拦截。再思考“A001”和“a001”是否重复:这是项目编号大小写规则,必须先约定,不能临时猜。

09 第一张规格表:先写规则,再运行工具

本课数据是合成测试音,不是ASR。音频目录有19个.wav扩展名文件:18个可读PCM WAV和1个损坏文件。第8个音频故意没有交付。其他文件即使没有被引用,也不代表已经完整检查;本课没有实现全量孤立文件盘点。

字段或属性本课约定自动检查范围
sample_id非空字符串且批内唯一两条重复记录都列出
languagezxx,无语言内容仅检查声明是否符合合成音题设
duration_seconds数字,0<时长≤30秒排除字符串、布尔值及非有限值
audio_pathaudio目录内的.wav存在、目录边界、扩展名
quality_checked布尔值false暂缓;true仍需证据
media_originsynthetic_tone防止将合成音标成真实语音
文件属性16000Hz、单声道、16-bit PCM标准库wave读取PCM WAV
时长一致性声明与实际差≤0.02秒这是教学容差,不是行业统一标准

规则文件位于data/policy.json。修改规则会改变判定,所以报告必须保留规则版本。此课程没有把所有检查都做成可配置项:例如30秒上限写在脚本中。真实项目应审查并版本化完整脚本与配置,不只保存一个版本名字。

10 实战:运行20条批次检查

先预测会有哪些问题,再在课程根目录执行:

python tools/validate_batch.py

预期统计:total_lines=20、parsed_objects=20、error_lines=17、hold_only_lines=1、no_configured_issue_lines=2、issue_count=18。

对应中文:共20行,20个对象解析成功;17行有错误;1行仅因未完成质检声明暂缓;2行未发现已配置规则问题;共18条问题记录,其中包含1条暂缓事项。

打开reports/my_run/report.html查看问题清单。report.json是机器可继续处理的版本。参考报告在reports/reference,避免与你的运行结果混淆。

终端命令运行结束,不等于批次通过。这个教学脚本即使发现数据缺陷也会正常结束;判定要读取报告中的统计和结论。将来接入自动流水线时,可请工程师约定错误退出码。

报告记录输入文件的SHA-256:它像文件内容的指纹,可帮助确认你复查的是不是同一版本;它不能证明数据授权、内容真实或采集人身份。

动手:找到第5行重复问题、第9行采样率问题、第11行暂缓问题,分别写出不同的处理动作。不能统一用“改成合格”解决。

11 读懂完整脚本,而不是背完它

按这个顺序阅读tools/validate_batch.py:

1. ROOT和main:输入从哪里来,报告写到哪里。--batch、--policy、--out是允许你指定的选项。

2. validate:主检查流程。rows保存解析成功的对象,issues保存发现的问题,ids记录同一编号出现的行号。

3. add:统一记录行号、样本编号、规则代码、说明和等级。统一结构让反馈能被复查。

4. number与no_duplicate_keys:拒绝布尔值伪装数字、NaN/Infinity以及同一对象重复字段名等歧义。

5. wave读取:观察真实文件属性,与policy比较。只适用于本课PCM WAV;不支持的格式应换工具,不要立刻指控供应商文件损坏。

6. errors和holds:使用集合set按行去重;先统计错误,再把同时有错误的行从“仅暂缓”中剔除,避免重复计数。

7. not_checked:明确没有检查的部分。这个列表不是免责话术,而是下一步工作清单。

本脚本面向20条的小批次,整文件读取并计算哈希;不是你们每月上万小时数据的生产平台。放大到生产时还要做流式读取、并发限流、日志、权限、版本、去重、抽样与人工复核流程。

12 学会改一条规则,并证明修改有效

练习A:复制policy.json为policy_strict.json,把duration_tolerance_seconds由0.02改成0.005,并把rule_version改成tone-training-v2-exercise。不要覆盖原文件。

练习B:复制batch.jsonl为batch_trial.jsonl,只把第19行duration_seconds改成1.01。按旧规则运行应无新增时长问题,按新规则运行应多出第19行问题。

python tools/validate_batch.py --batch data/batch_trial.jsonl --policy data/policy.json --out reports/trial_old
python tools/validate_batch.py --batch data/batch_trial.jsonl --policy data/policy_strict.json --out reports/trial_strict

预期旧规则仍17个错误行、2个无配置问题行;新规则18个错误行、1个无配置问题行。第11行仍仅暂缓。修改时应先说明为何需要更严格的容差,再改变规则;这里仅为练习。

练习C:运行坏语法文件,检查第2行是否明确报告JSON_PARSE:

python tools/validate_batch.py --batch data/broken.jsonl --out reports/broken

其他两行虽可解析,但缺少完整项目字段,因此也有规则错误。不能把“解析成功2条”说成“合格2条”。

13 遇到错误怎样处理

看到的提示常见原因你先做什么
python无法识别未安装或终端未更新试py,检查安装后重开终端
can't open file命令路径错或不在根目录确认能看到lessons与tools
FileNotFoundError数据路径或解压结构有误核对输入位置,不创建空文件凑数
SyntaxError代码标点、引号或括号有错查报错行及上一行,和原版比较
IndentationError缩进层级不一致使用四个空格,保留代码块结构
JSONDecodeError输入JSON语法有错看真实行号,回数据修复
KeyError取不存在的字段确认规格,必要时先判断存在性
ModuleNotFoundError当前环境未安装所需包核对使用哪个Python,再按第二册安装
UnicodeDecodeError文件编码不匹配核实编码,不用忽略错误掩盖损失

求助时提供:运行的命令、完整错误文字、输入的脱敏片段、Python版本、你希望得到的结果。不要只发“报错了”,也不要把客户原始数据和凭证上传到不被允许的服务。

14 七次练习安排与毕业作业

次数建议任务可检查产出
1第1—3节成功运行并修改欢迎语和比例
2第4—5节类型、布尔值和31秒边界练习
3第6—7节保留行号的坏JSONL报告
4第8—9节写清本批规格及不适用范围
5第10—11节自己生成的20条报告
6第12—13节新旧容差对比与故障说明
7毕业作业一页采购验收说明

每天可安排45—90分钟;卡住就围绕该检查点复练,不必赶进度。

毕业作业:不看讲师答案,写一份批次反馈,必须包括输入数量和版本、检查范围、17条错误与1条暂缓的统计口径、至少三条证据、供应商整改要求、未检内容、复验步骤和当前结论。

自评:能运行属于入门;能解释误判/漏判属于理解;能改规则并验证边界属于可协作;能结合合同和人工证据完成闭环才接近项目Owner工作。

15 向Coding、API、Agent迁移

你刚学的套路可以迁移:数据读取→规格检查→执行或观察→证据记录→人工判定。

Coding样本:检查题目、代码、测试和授权字段;在隔离环境运行测试;看测试是否覆盖边界。通过几条测试不等于代码完全正确。

API样本:检查工具名、参数名、参数类型、返回结构以及错误分支。JSON合法不等于工具调用正确。

Agent样本:检查动作是否被允许、调用顺序、工具结果、最终状态以及额外副作用。最终回答“已取消”不代表订单真的取消。

第二册附有本地模拟练习。你现在不必成为高级开发者,但应该能把“请帮我验一下”变成可测试的规则说明。

官方参考:Python入门教程、json模块、pathlib模块、wave模块。

一分钟自测

脚本显示“无配置规则问题”,能否直接通知客户全部合格?