批作业这件事,谁干谁知道——它不累,但极其磨人。尤其到了期中、期末这种节点,左手一摞卷子,右手一个答案本,机械性地打勾画叉,一小时批完一个班,眼睛都快看花。我今年在华为云智能体平台上搭了一套“辅助批改作业工作流”,把大部分重复性批改工作交给智能体去处理,自己只做最后的复核和反馈补充分。这篇就完整梳理一下我当时从0到1搭建这套工作流的操作流程、踩坑过程,以及一些可复用的设计经验。
这套方案面向的主要人群是:日常需要处理大量作业/试卷批改的教师、教育机构的教务人员,以及在做AI教育应用开发的开发者。它不追求“完全替代老师”,而是把“批改-统计-反馈”这条链路上的机械环节自动化,让老师把省下来的时间投入到更重要的面批和个性化辅导上。如果你有类似需求,可以直接照着下面的流程在华为云智能体平台上复现一套。
1. 项目背景与整体设计思路
1.1 为什么选“辅助批改作业”这个场景
我在学校做过一段信息化的技术支持,接触过不少老师的批改场景。看起来批改就是对着答案打勾叉,但实际上它包含好几个隐性环节:判断正误、圈出错点、标注原因、计算得分、登记成绩、统计班级整体掌握情况。这些环节全串起来,一位老师批一个班五十份作业,光数学卷子就得两小时起步,语文作文这类主观题更久。
AI能不能做?能,但要拆解清楚。批改的本质是“比对”:学生的作答内容和参考答案、评分标准做比对。这种结构化比对任务,恰好是大语言模型和规则引擎的强项。输入是作业图像或文字,经过OCR识别、内容归一化、模型判断、结果结构化输出,最后再汇总成一份可读的批改报告。这整个链路,用智能体平台的工作流编排能力来做,比写一套独立后端服务要灵活得多,改动节点不需要重新发版。
我选择华为云智能体平台,核心原因有三点:一是它原生集成了盘古大模型和各类华为云服务,OCR、语音转写这种基础AI能力不用单独搭;二是工作流编排支持可视化的“积木式”设计,后期调整批改规则、增加节点非常方便,不用改代码;三是它的运行日志和监控很全,跑批的时候追问题很方便。当时我也对比过dify、coze这类社区热度高的智能体平台,dify的工作流自由度确实不错,但要从零接OCR等云服务还得自己配连接器,coze则默认面向C端功能,教育场景的私有化部署和数据合规做法比较绕。如果你们学校有自己的云资源或华为云资源,智能体平台基本是开箱即用。
1.2 工作流的整体架构与节点规划
开始搭之前,我先把“一次完整的作业批改”拆成了下面几个阶段:
- 作业提交:学生作业以拍照图片或PDF文件形式上传,这是工作流的输入端。
- 内容识别:对图片做OCR识别,转成可编辑的文本;如果是PDF,先按页拆分再逐页识别。
- 试卷归一化:把OCR出来的杂散文本按题号、小问切分成结构化的题目列表,去掉页码、页眉等噪声。
- 批改引擎:把每道题的题干、学生作答、参考答案、评分标准一起提交给大模型,让模型输出每道题的对错判断、得分、错误原因、知识点标签。
- 结果汇总:把所有题目的批改结果聚合成一份完整反馈,统计出总分、正确率、错题分布、薄弱知识点。
- 反馈生成:生成适合学生阅读的批改报告(含评语、错题解析),同时给老师生成一份班级学情摘要。
对应到华为云智能体平台的工作流设计上,我把后面几个阶段落成了具体的节点:识别节点、切分节点、批改节点、统计节点、报告节点。工作流整体是线性的,但“批改节点”内部会有并行分支,不同题型走不同的提示词策略。这个设计思路很关键,你不能让一个大模型提示词处理所有题型——数学计算题和语文阅读理解题的评判逻辑完全不同,硬放一起会互相干扰。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心细节解析:批改工作流的节点设计与模型选型
2.1 五个核心节点的功能与配置要点
工作流里最核心的五个节点,我从头讲一遍配置思路。
输入节点。这个负责接收作业数据。当时我支持了两种方式:手动上传和API回调。手动上传适合老师小批量测试,API回调适合跟学校的作业系统打通。输入的数据格式我统一定义为JSON:包含学生ID、作业ID、作业类型(数学/语文/英语)、题目列表,以及每道题的题干、参考答案、学生作答内容。如果你走的是图片识别链路,这个节点就先把原始文件传给OCR服务。
OCR识别节点。我用的是华为云通用文字识别接口。这里有个配置要点:一定要开“手写体识别”选项,而且把识别语言设为“中英文混合”。学生作业多数是手写的,很多人把OCR识别失败归因于模型不行,其实大概率是参数没调对。另外,图片分辨率也对识别率影响很大,我建议从源头控制,上传规范统一为“整页A4纸平铺拍摄、光线充足、分辨率不低于200dpi”,并在输入节点的说明文档里写清楚。
题目切分节点。这是最容易被忽视但最影响效果的一个环节。OCR识别出来的文本是一整页的文字流,没有结构化信息。我的做法是用规则加正则,按“1.”“(1)”等题号模式做切分,再结合模型对切分结果做二次修正。如果你处理的作业题型比较固定,规则切分就够了;如果跨科目,建议在切分节点后面加一个低成本的分类模型,把文本片段先分到对应题型再切。
批改节点。这是核心节点,本质是一个大模型调用节点。我单独针对不同科目配置了不同的提示词模板,模板里会注入评分标准。比如数学题,评分标准可能包含“解题步骤占60%,计算结果占40%”;语文阅读理解,则更侧重“要点覆盖率”。工作流平台支持变量引用,所以我在每个分支节点里把提示词和输入的字段动态拼接。具体提示词模板的设计,下一节单独展开。
报告生成节点。批改节点输出的是每道题的结果,报告节点负责把它们聚合成两份内容:一份给学生,一份给老师。学生端的重点在错题解析和鼓励性评语;老师端的重点是统计数据和学情预警,比如“第7题全班错误率高达80%”“第3题学生普遍在哪个步骤丢分”。这一步我直接用平台内置的文本生成能力,把JSON结果喂给模型,让它按模板生成自然语言报告。
2.2 模型选型:盘古大模型还是第三方模型
工作流平台一般允许你配置不同的模型,当时我优先试了平台默认集成的盘古大模型。批改任务有个特点:规则性强、需要稳定可控的输出。盘古大模型在处理中文教育语料时表现不错,尤其是在识别学生“解题思路对了但过程不规范”这类情况时,比某些通用英文模型要灵光。不过某些数学证明题、理科推导题的逻辑判断,它也偶有误判,我实际用下来准确率大约在90%-95%之间。
另外我也对比过接入第三方开源模型,比如通过Ollama部署的Qwen系列,效果接近,但运维成本和响应速度不占优势。对于批改这种对延迟有要求的场景,我更推荐用平台托管的模型服务,省心。有一点必须注意:任何模型都不能完全替代老师做最终判定,尤其涉及主观题和分数评定,工作流里必须保留“人工复核”环节,不能让AI给学生的作业批改结果直接推送出去,否则出了纠纷很难处理。
2.3 批改提示词模板的两条核心设计原则
提示词是批改效果的灵魂。我调试了无数版后,总结出两条核心原则。
第一条:给模型清晰的角色和输出格式,最好用JSON约束。我见过太多人写“请批改下面这道题”,这种提示词10秒就能生成一段“看起来很有道理”的批改结果,但完全不结构化,没法接入下游统计。我最终的模板格式固定是:
text复制你是一名有20年教学经验的中小学数学老师,现在要批改一道[科目][题型]题。
题干:
{{question}}
标准答案:
{{answer}}
评分标准:
1. 正确列式得2分
2. 计算过程正确得3分
3. 最终答案正确得2分
4. 书写不规范酌情扣1分
学生作答:
{{student_answer}}
请严格按照以下JSON格式输出批改结果,不要输出其他内容:
{
"judge": "对/错/部分对",
"score": 7,
"full_score": 7,
"error_points": ["学生漏掉了...", "计算第一步...出错"],
"knowledge_points": ["一元二次方程求解", "因式分解"],
"comment": "写给学生的简短评语"
}
第二条:“让模型当老师,而不是当判官”。这个有意思,同样是判断对错,你让模型“挑刺”它就只找错处,你让它“以批改促进步”它就会连正确答案之外的其他合理解法也认。我后期把所有提示词里的“判断对错”都改成了“评估解题过程是否合理,指出进步点和待改进点”,这样批改反馈的友好度提升很明显,家长看到也不容易焦虑。
3. 实操过程:在华为云智能体平台上搭建工作流
3.1 准备工作与环境开通
先要有华为云账号,这个不多说。进入控制台后,搜索“智能体平台”或从AI服务大类下进入。首次使用会要求开通一些依赖服务,我这边主要开通了三项:对象存储服务(用来存作业图片)、OCR服务(文字识别)、以及对话模型服务。如果你的作业文件不大,可以直接用平台自带的对象存储,不用单独去配复杂权限。
开通之后第一件事不是创建工作流,而是建一个“应用空间”。这个空间相当于一个隔离的工程目录,把工作流、知识库、模型配置都归类管理。我当时建了两个空间:一个“dev”用来测试调优,一个“prod”跑正式批改任务。强烈建议你这么分,因为工作流迭代很频繁,直接在正式环境改容易把历史数据弄脏。
3.2 创建工作流:从空白画布到可运行任务
进入工作流编排界面,选择“从空白创建”,然后按下面的顺序拖节点连线。这里我把每个节点的配置参数也一并提供了,你可以直接照着填。
第一步,拖一个“HTTP触发”节点作为工作流的入口,请求方法选POST,数据格式选JSON。这个节点用来接收作业数据,我把请求体Schema设计为:
json复制{
"student_id": "string",
"homework_id": "string",
"subject": "math",
"images": ["url1", "url2"],
"answers": [
{
"question_id": "Q1",
"question": "已知x^2-5x+6=0,求x的值",
"standard_answer": "x=2或x=3",
"student_answer": "x=2, x=3"
}
]
}
第二步,加一个“条件分支”节点,按subject字段区分数学、语文、英语三种批改策略。这里要注意分支条件的写法,我当时用平台内置的表达式,类似{{subject}} == "math",返回true就走数学分支。不同分支后面接的提示词模板不同,但节点结构一致。
第三步,配置“OCR识别”节点。把输入节点里传进来的图片URL批量传给OCR连接器,输出存成变量ocr_results。这里有个平台细节:OCR连接器的输出默认是数组,但工作流后面的大模型调用节点只接受单条文本,所以我在OCR节点后面加了一个“数组转文本”的脚本节点,把识别出的所有行拼成纯文本。这个拼接操作别用空格,用换行符\n,不然切分节点会把题目粘连在一起。
第四步,配置“题目切分”节点。我用的是一个Python脚本节点,在里面写了一个简单的正则切分函数:
python复制import re
def split_questions(text):
pattern = re.compile(r'(?m)^(\d+)[\.、.](?=\s*\S)')
matches = list(pattern.finditer(text))
questions = []
for i, m in enumerate(matches):
start = m.start()
end = matches[i+1].start() if i+1 < len(matches) else len(text)
questions.append(text[start:end].strip())
return {"questions": questions}
切分出来的题目列表存为questions变量,供后续批改节点循环处理。
第五步,也是最关键的一步——配置“批改节点”。这是一个“循环”结构,遍历questions数组,把每道题和对应的参考答案传给大模型节点。循环体内的处理逻辑是:先从questions里取当前题目,再根据subject字段选对应的提示词模板,组装好后调用大模型API,输出结果追加到一个叫batch_results的数组里。大模型节点的参数我建议用temperature=0.2、top_p=0.5,因为批改要的是稳定一致的输出,也不是创意生成,温度调太高容易“发挥不稳定”,同一个答案两次批改分数不一致,就麻烦了。
第六步,配置“统计汇总”节点。等循环跑完,把batch_results里的分数、知识点做统计,算总分、正确率、错误知识点分布。这个节点依然用Python脚本实现,逻辑不复杂。统计结果生成两份输出:student_report和teacher_report,分别调用两次文本生成节点写报告。
最后是“输出节点”。把报告和统计数据封装成一个JSON返回给调用方。整个工作流保存后,先点“测试运行”,用一份假数据验证各节点连通,确认无报错后再发布成正式版本。
3.3 知识库:让批改更贴合自己的教学大纲
如果你只是通用批改,可以跳过知识库;但如果要批改的内容有特定教材版本、特定评分细则,强烈建议建一个知识库。我当时在平台的知识库模块上传了一份“本校数学校本作业答案册”PDF,按章节做了分段切片。然后在批改节点的提示词里,把“标准答案”字段替换成“从知识库检索到的相关参考答案片段”。
这样做带来的好处很明显:模型不再只凭自己训练时的“标准解题步骤”判题,而是能对照你们学校的答案体系和阅卷习惯。尤其是在批改开放性题目和“一题多解”题时,知识库里的参考答案不一定覆盖所有解法,所以提示词里我会额外加一句:“如果学生使用了与答案不同的解题方法,请根据数学逻辑判断其正确性,不要机械比对答案。”这句很重要,不然很多合理的创新解法会被盲判为错。
4. 批改效果实测:三类题型的真实表现
4.1 数学计算题、语文阅读理解、英语选择题的对比
工作流跑通之后,我拿一个40人的班级作业做了实测,分数学、语文、英语三组,每组随机抽10份作业,由工作流先批,再由老师人工复批一遍,结果汇总如下:
| 题型 | 批改份数 | 与人工批改完全一致比例 | 平均单份批改耗时 | 主要差异点 |
|---|---|---|---|---|
| 数学计算题 | 10 | 90% | 约3分钟/份 | 步骤分判定略有出入 |
| 语文阅读理解 | 10 | 70% | 约5分钟/份 | 主观题采分点判断偏严 |
| 英语选择题 | 10 | 100% | 约1分钟/份 | 无差异 |
英语选择题这类有标准答案的客观题,工作流基本能做到零误差,前提是OCR识别没把A认成D。数学计算题的差异主要出现在“解题步骤部分正确但结果算错”这类题目上,模型有时会在步骤分上少给,这在提示词里把步骤分标准写得更细之后有改善。语文阅读理解的开放性题是最难做到完全一致的,它本身存在主观判断,同一位老师两次批改都可能给不同的分,所以工作流做到“给出参考分数+采分点评析”就够用了,最后由老师来确认最终分数。
4.2 实测中的效率数据与隐藏收益
时间方面,原来一位老师批改40份数学作业大约需要80分钟,用工作流辅助后,老师只需要花15到20分钟复核机器批改结果、处理少数争议题,整体效率大概提升了75%。而且因为OCR识别和模型批改是异步跑的,老师完全可以上午提交作业,下午看汇总好的批改报告。
还有一个设计之初没想到的收益:知识点统计数据对教学的指导价值。有一次实测数据显示班上有17个学生都在同一道“分式方程应用”题上丢分,老师在第二天的课上专门重新讲了这个知识点。手动批改时代,老师知道“这道题错得多”,但很难快速量化到具体知识点维度,工作流统计节点把这些数据自动生成了,对教研活动非常有帮助。
5. 常见问题与排查技巧实录
5.1 问题速查表与定位思路
搭建和运行过程中,我遇到不少问题,整理成一张速查表,遇到类似情况的直接对照查:
| 症状 | 根本原因 | 解决办法 |
|---|---|---|
| OCR识别结果乱码 | 图片分辨率过低、手写行重叠 | 统一上传规范,要求平铺拍摄;必要时先做图片预处理 |
| 批改结果对判断题全部判错 | 学生作答文本带了题号前缀,大模型误把“答案: A”当成内容本身 | 在切分节点里清洗掉“答案:”“答:”等前缀 |
| 大模型输出不是合法JSON | 提示词里没有严格限制输出格式,或temperature设太高 | 提示词里明确“不要输出任何解释”,temperature调到0.2 |
| 循环批改节点响应超时 | 单份作业题目数太多,串行调用大模型耗时过长 | 减少循环粒度,改成每5题一个批次批量提交;或升级模型服务的并发配额 |
| 统计节点计算结果为0 | 批改节点输出的是字符串,不是数值,统计脚本没做类型转换 | 在统计脚本里用float()强转,或在大模型提示词里强制score字段输出数字 |
| 工作流测试正常但正式运行偶发失败 | 上游接口偶发限流,没有重试机制 | 在调用节点配置里开启“失败重试”,最多重试3次,间隔2秒 |
定位问题最大的技巧:善用平台的工作流日志和节点输出预览。每一个节点的输入输出都能展开看详情,哪个环节数据不对,一眼就能锁定。我第一次遇到批改结果不准时,就是逐个节点看输出,最后在切分节点发现正则表达式把“第1题”这种中文序号漏掉了,导致多道题被合并成一大段文本,后续批改自然全乱。
5.2 三条独家避坑经验
第一,不要一上来就追求“全自动批改”,先跑通“人机协同”模式。我的做法是工作流跑完后生成一个供老师快速复核的网页,每条批改结果旁边都有“确认/修改”按钮,老师一键确认就能归档。等积累一段时间、确认机器批改准确率足够高后,再对客观题开放自动归档权限。
第二,工作流的“版本管理”一定要用起来。每次调完提示词或节点逻辑,别在旧版本上直接覆盖,先创建新版本跑一跑,用同样的测试数据对比新旧版本输出,确认没退化再切正式流量。批改任务的稳定性优先级高于一切,你今天手滑改了一个参数,可能明天整个班的作业批改结果就全乱了。
第三,Prompt和脚本里的字段命名要有全局一致性。我踩过一个大坑:OCR节点输出的字段叫text,切分节点里读的是ocr_result,两边对不上,运行时报错提示还不明显。后来我养成了一个习惯,画完工作流先做一个“字段清单”,把每个节点的输入输出字段名都列出来核对一遍,再开始接逻辑。这个习惯省了我后期大量调试时间。
6. 从辅助批改到一个可扩展的教学助手
工作流稳定运行之后,我开始思考怎么把它扩展成更大的教学工具集。批改只是教学闭环中的一个环节,把整套链路延伸开:作业批改完后,统计分析节点输出的“班级知识点薄弱项”,直接可以触发一个“练习试卷推荐”节点,自动从题库里挑出对应知识点的配套练习题,生成一份新的个性化作业。再往后走,还能在期中考前根据每位学生的历史错题,生成“个人复习清单”。这些都是在已有工作流基础上,增加几个节点就能实现的事。
这套方案的另一个价值在于复用。换个场景,输入从“作业图片”变成“简历文本”,批改节点换成“简历筛选提示词”,统计节点换成“候选人排序”,它就变成了一套招聘场景的简历筛选工作流。工作流编排这种“积木式”架构,优势就在于此:核心的识别、切分、调模型、汇总逻辑都是通用的,要变动的只是提示词和评分标准。
如果你也想搭一套类似的教育类工作流,我的建议是:先找一道最典型的题型跑通最小闭环,比如先只处理数学计算题,把输入到输出的整条链路跑顺,再逐步扩展题型。一开始就想着覆盖所有科目、所有题型,只会把自己陷在提示词调试的无底洞里。把“一个点”做到足够好用,再复制到其他场景,这是我这几个月实践下来最深刻的体会。
