简介:这份压缩包提供了一套基于LLM的高中语文作文自动批改应用源码与工程配置,面向高中语文教师、教育技术研究者及具备Python基础的开发者,用于解决作文评分、语病识别和个性化反馈等教学痛点。压缩包共18个文件,主体为5个Python脚本(涵盖主程序、LLM调用与工具函数)、4个XML工程配置、4个编译缓存pyc文件,并附依赖清单、说明文档及Git忽略规则,整体仅21KB,轻量易部署。已有93人学习下载。应用覆盖自动评分、错误标注、内容建议、数据分析和个性化反馈等功能,展示了如何利用大模型在中文语境下完成语义理解与写作指导;对于想快速搭建作文批改原型或学习LLM教育落地方案的读者,具有直接参考价值。 我第一次把学生作文丢给大模型的时候,它给了一篇五百字的夸夸其谈:"情感真挚、结构清晰、语言流畅、主题深刻"——几乎把所有能想到的褒义词都堆了一遍。第二天我把同一篇文章换个说法再丢进去,它又改口说"立意不够鲜明、论证不够充分"。那一刻我意识到,用LLM批改高中语文作文,真正的难点根本不在模型会不会"评价",而在于怎么让它别瞎评价。
后来我把这套东西做成了一个能实际跑起来的应用:基于LLM的高中语文作文自动批改应用。输入一篇学生作文,几十秒后返回分项评分、逐段批注、总评和修改示范,整个项目打包成了一个zip,部署起来不复杂。过程中踩了无数坑,也摸出了一些经验。这篇博文把从设计、Prompt调优到落地实测的全过程记录下来,给正在做教育类LLM应用、或者自己就是语文老师想拿AI当助手的你做个参考。
1. 为什么作文批改这种"主观题"反而是LLM的用武之地
1.1 先算一笔时间账:语文老师批作文有多累
高中语文老师一般带两个班,一百多号人。一篇800字作文,精批细改需要十分钟以上:要逐段看逻辑,标出错别字,写旁批,结尾还要写一段总评。一晚上改六十篇,基本意味着从八点坐到凌晨两点。这种情况下,大部分老师只能"提速":重点看标题、开头、结尾和每段首句,中间扫一眼,给个总分,再写一句"论证不够充分"之类的通用评语。批改质量下降,学生拿到手也没有可执行的改进方向。
LLM最擅长的事情恰恰是"快速读完一篇长文本并给出结构化反馈"。它不会累,不会因为改到第三十篇就失去耐心,对每篇作文都能保持同样的注意力。这个特性决定了它在作文批改场景里有不可替代的价值——前提是你把它设计对。
1.2 难点:主观评价不是"给个分",而是"给依据"
作文批改难,难在它不是客观题。同样一篇作文,教师A可能给52分,教师B可能给48分,两人都能说出道理。这种主观性让很多团队一开始就放弃做语文作文批改,转头去做英语作文或者数学题。但我认为恰恰相反:LLM在处理主观评价时,只要能给出"依据",它的参考价值就远大于一个冷冰冰的分数。
我定义的"好批改"包含四个方面:第一,分项评分要对应明确标准,不能拍脑袋;第二,每个扣分点要对应到作文里的具体段落或句子;第三,总评要指出核心问题和改进方向;第四,最好能给出局部的改写示范。这四个方面,指向的不是让AI"替代老师打分",而是让AI"帮老师把活干完",老师只需审核和微调。
1.3 定位想清楚:是"教练",不是"裁判"
这是整个项目最关键的定位决定。如果目标是"自动评分系统",要求LLM的分数和阅卷组完全一致,那基本是给自己挖坑。但如果目标是"教练",那情况完全不同——学生需要的不是一句"你有很大提升空间",而是"你第二段的论据和观点脱节,换一个关于坚持的史例会更有说服力"。
所以这个应用的设计初衷是:把LLM当作一个读过大量高分范文、精通高考评分标准的助教,它的批改报告是初稿,老师在此基础上做最终裁决。想通这一点之后,整个系统的技术选型和Prompt设计都变得顺理成章。
2. 应用设计:从一篇作文到一份批改报告的完整链路
2.1 先看zip包里有什么
我把项目打包成zip分享出去的时候,特别注重"拿过去就能跑"。整个目录结构长这样:
grading_app/ ├── app.py # FastAPI 入口,提供Web接口 ├── core/ │ ├── models.py # 作文数据模型与输出Schema │ ├── scorer.py # LLM调用与Prompt编排 │ └── rules.py # 本地规则引擎(错别字、字数、段落统计) ├── prompts/ │ ├── system.md # 系统提示词 │ └── fewshots.jsonl # few-shot 示例 ├── utils/ │ ├── chunker.py # 长文本分段处理 │ └── formatter.py # 结果格式化为批改报告 ├── frontend/ # 极简Web页面 └── output/ # 批改报告导出目录结构上我把"规则引擎"和"LLM引擎"分开,这是故意的。作文批改中有大量确定性工作不适合交给LLM:字数统计、段落数检测、明显的错别字、标点异常。这些用规则引擎做,又快又准。LLM只负责它真正擅长的事:理解语义、判断逻辑、评估文采、给出建议。
2.2 技术选型:为什么是Python + FastAPI
选型上我基本没犹豫:Python + FastAPI + httpx + pydantic。FastAPI的优势在异步处理和自动生成的接口文档,批改一篇作文要调用模型接口,网络IO是主要耗时,异步能把并发顶起来。更重要的是pydantic,它对模型输出的JSON做强校验,格式不对就能立刻捕获并触发重试,这对LLM应用来说是刚需。
模型接入层我做成了适配器模式:底层支持两种方式,一种是直接调用国内主流大模型的API,另一种是通过Ollama这类工具加载本地开源模型(比如Qwen2.5系列)。两种方式通过一个配置项切换,方便不同场景使用——个人测试用本地模型省钱,正式使用用云端API效果好。
2.3 核心调用流程:谁先谁后很讲究
整个批改流程我调了很多版,最后稳定为五步:
- 接收作文原文,规则引擎先跑一遍,统计字数、段落数、标题、明显的错别字和标点问题。
- 将作文和规则引擎的输出一起交给LLM,要求它先"通读全文,提炼中心论点"。
- LLM逐段批注,输出每个段落在扣题、论证、语言上的问题。
- LLM按评分标准分项打分,并输出总评和修改建议。
- 后处理:解析JSON,用pydantic校验,汇入模板形成批改报告。
这里特别值得说的是第一步和第二步的衔接。一开始我没让规则引擎参与LLM调用,结果模型总把错别字漏掉。后来把规则引擎的错别字结果一并塞进Prompt,让模型"复核",漏检率明显下降。这个"规则先行、LLM复核"的思路,在做任何垂直领域LLM应用时都值得借鉴。
3. Prompt工程:这是整个应用最花功夫的地方
3.1 第一版翻车实录:跑题作文拿了56分
第一版Prompt非常简单:
你是语文老师,请批改下面这篇作文,给出评分和评语。结果惨不忍睹。一篇明显跑题的作文,写的是"坚持就是胜利"但通篇在讲"科技改变生活",模型给了56分(满分60),评语是"文章充分论证了坚持的重要性,结构清晰,语言优美"。为什么会这样?我仔细看了几篇输出,发现问题出在模型缺少两样东西:一是缺少对"题意扣合度"的强制检查,二是在没有参照系的情况下,模型默认给出偏高的分数——这大概是因为训练数据里"学生作文"普遍对应着鼓励性评价。
也就是说,让LLM裸评作文,它的默认行为是"和气生财",这不符合阅卷逻辑。
3.2 角色设定与评分锚点:把高考评分标准"塞进"提示词
第二版Prompt做了大幅调整。我先给模型一个明确身份,再把评分标准做成了可操作的检查清单。系统提示词的核心部分长这样:
你是一位有20年阅卷经验的高考语文阅卷组组长。请严格依据《高考作文评分标准》批改作文,满分60分:基础等级·内容20分(题意、中心、内容、思想),基础等级·表达20分(语言、文体、结构、书写),发展等级20分(深刻、丰富、有文采、有创新)。 批改流程: 1. 先用自己的话复述本文的中心论点,判断是否切题。 2. 逐段检查:该段是否扣题?论据是否支撑观点?段与段之间是否有逻辑递进? 3. 分项评分,每一项都要写出扣分依据,引用原文原句。 4. 最终给总分、总评和三条最可执行的修改建议。关键改动有两个:一是把"题意"检查放在最前面,强制模型先复述中心论点,复述得出来且切题,才是高分的前提;二是要求"引用原文原句"作为扣分依据,这一步能极大抑制模型胡说。实测对比下来,有了这个锚点,跑题作文的分数降到了45分以下,靠谱多了。
3.3 结构化输出:让模型返回能直接入库的JSON
Prompt调优的另一半,是输出结构。我要求模型返回固定格式的JSON:
{ "central_idea": "本文的中心论点是……", "is_relevant": true, "sub_scores": { "content": 17, "expression": 16, "development": 19 }, "paragraph_comments": [ { "range": "第2段", "issue": "论据与观点脱节", "quote": "原文原句", "suggestion": "建议补充……" } ], "overall_comment": "总评,150字以内", "modification_example": "对某一句话的改写示范" }直接让模型输出JSON,一开始出现了不少格式问题:字段名漂移、尾逗号、里层引号转义错误。我的解法是配合few-shot示例,同时在代码里做容错:第一次解析失败就自动让模型"修正JSON",最多重试两次;如果还失败,就把整段原始输出丢给正则表达式提取关键字段。这一套兜底逻辑,在实际运行中把格式成功率从八成提到了差不多满分。
3.4 few-shot示例与版本迭代效果对比
few-shot示例我精选了三篇:一篇52分的中等偏上作文、一篇46分的中等作文、一篇40分以下的偏题作文。每篇都带完整的批改示例,相当于给模型做了"手把手"示范。这里有个细节:few-shot示例里的评语也用"引用原文+具体建议"的格式,让模型去模仿这种批改习惯,而不是模仿内容。
我把几个版本的Prompt在同一个30篇测试集上做了对比:
| 版本 | 与教师评分相关系数 | 完全同分比例 | 平均绝对误差 |
|---|---|---|---|
| v1 裸评 | 0.31 | 7% | 7.8分 |
| v2 角色+标准 | 0.58 | 17% | 5.2分 |
| v3 +JSON结构化 | 0.61 | 23% | 4.5分 |
| v4 +few-shot | 0.66 | 31% | 3.9分 |
这个数据说明了调优方向是对的:角色设定解决"立场"问题,评分标准解决"尺度"问题,结构化输出解决"可用性"问题,few-shot解决"风格模仿"问题。每一步都在原有的基础上往前推进了一点。
4. 分数可靠性:让LLM从"拍脑袋"变成"有依据"
4.1 多次采样与分数聚合:减少随机波动
同一个Prompt在同一篇作文上跑两次,分数可能相差3到5分,这是LLM的温度参数带来的随机性。为了压住这种波动,我采用了多次采样策略:temperature设置为0.3(不要降到0,否则输出会变得呆板),同一篇作文调用3次,取三次分数的中位数作为最终分数,同时把三次评语去重后合并。这样做的代价是耗时和成本变成原来的3倍,但换来的是稳定性的显著提升。实测中,单次评分的平均绝对误差是4.5分,三次取中位数后降到3.2分左右。
如果你在并发量高的生产环境用,不建议对所有请求都做三次采样。可以先跑一次,如果模型的置信度字段(我在Prompt里要求它输出self_eval,即"本次批改把握程度")低于某个阈值再补采,能省不少成本。
4.2 规则引擎兜底:不让模型处理它不擅长的事
错别字、字数不足、段落混乱这些"硬伤",让LLM检查既慢又不可靠。我在规则引擎里维护了一个常见错别字词库("的地得"混用、形近字等),配合正则表达式做初筛,再把初筛结果写进Prompt让模型复核确认。这样做的准确率远高于让模型从零开始找错。
字数统计也用规则引擎。高考作文一般要求不少于800字,如果文字量不足,规则引擎直接在报告中置顶提示,这比等模型发现靠谱得多。我的经验是:凡是能用确定性算法解决的问题,就不要交给LLM。LLM的价值在于处理那些"没有标准答案"的部分,比如论证逻辑、立意深度、文采风格。
4.3 用真实教师评分做回归校准
即使做了这么多约束,模型的分数和教师真实阅卷之间仍然存在系统性偏差。我的做法是拿一批有教师评分的真实作文做"校准集",跑完LLM评分后做一个一元线性回归,找到从LLM分数到教师分数的映射关系。公式很简单:最终分 = a × LLM分 + b,其中a和b由校准集拟合得出。
我在一个60篇样本的小数据集上做过实验,LLM确实存在"高分容易偏低、低分容易偏高"的收敛倾向,也就是给分区间偏窄。通过线性校准,把52分以上的"优秀段"和40分以下的"待努力段"重新拉开,最终报告就更接近教师的实际分布。这个校准过程必须定期重跑,因为换模型或者改Prompt之后,偏差模式会完全变化。
5. 实测效果、翻车案例与落地建议
5.1 小规模测试的效果数据
项目做完之后,我请三位在职高中语文老师帮忙,拿30篇真实学生作文(议论文为主,兼有少量记叙文)做了盲测。LLM批改的分数与教师平均分的相关系数在0.6到0.7之间(不同模型差异较大,更强的商用模型能达到0.75以上),完全同分的约三成,浮动在正负5分以内的约八成。
这个数据说明什么?说明LLM目前做不到"精确判卷",但完全做得到"把作文分成大致层次"。放在辅助定位下,这个准确率是够用的:它能把明显的好作文和明显需要重写的作文快速分拣出来,让老师的精力集中在那批"可上可下"的中间作文上。
5.2 三个典型的翻车场景
第一类翻车:文笔华丽但内容空洞的作文,容易拿高分。模型特别容易被漂亮的排比句、名言警句带偏,忽视论点是否扎实。对策是在Prompt里加重"中心是否突出、论证是否充分"的权重,并且要求每个分项都必须引用原文证据。
第二类翻车:对"剑走偏锋"的作文评价过于保守。有一篇用书信体写家乡变化的作文,教师认为很有创意,给了高分,但模型只给了中等分,原因是"文体不够标准"。后来我在Prompt里加了一句"议论文之外,允许并认可记叙文、书信体、散文等其他文体的合理表达",情况才好转。
第三类翻车:长作文后半段失忆。超过1200字的作文,模型经常对开头记忆深刻、对结尾关注不足,批注集中在前面几个段落。我用chunker把作文按段落分组,先让模型对每个分段做批注,再汇总成分段批注列表,最后整体给分,有效缓解了这个失忆问题。
5.3 批改报告怎么呈现,老师才愿意用
一个容易被技术人忽略的点:老师对"AI味"很敏感。如果总评全是"通过您的文字,我感受到了……"这种空话,老师会觉得不如自己写。我把输出模板改成了"先点出一个最核心的问题,再给一条具体的修改路径",比如:"本文最大的问题是第二段论据(方仲永的故事)与论点'坚持'无关,建议换为'左思写《三都赋》'的典故,并在分析句指明'坚持十年'与论点的关联。"
修改示范也很有用。我让模型挑出正文中的一到两句"典型病句",给出改写版本,并附上改写理由。这种"看到具体变化"的反馈,学生最容易接受。我们后台统计过,带修改示范的批改报告,被学生查看和转发的次数远高于纯评语报告。
5.4 落地成本与使用建议
成本方面我粗略算过:一篇800字作文输入约1500到2000个token,批改输出约800到1200个token,单次调用约3000个token。即使三次采样,一篇总消耗约1万个token。按当前市面上主流模型API的价格,一个50人的班级,批量批改一次作文的成本在几块钱到十几块钱之间,完全在可接受范围内。
使用流程上,我的建议是"LLM先批改,教师再审核":老师拿到批改报告后,调整分数和评语,确认没有问题,再发布给学生。这样做既保证质量,又帮老师省掉八成以上的机械劳动。运行时间上,如果配置了并发,60篇作文大概能在10分钟到20分钟内全部批完,老师冲杯咖啡的工夫就出来了。
最后说一个我自己的体会。做这个项目的过程中,我最深刻的感受是:LLM应用的价值不取决于模型多聪明,而取决于你把任务拆得多清楚、把标准定得多具体。给模型一个清晰的评分锚点、一套可执行的输出结构、几条真实可信的示例,它交出来的东西就能从"正确的废话"变成"可用的初稿"。这个项目打包成zip分享出去之后,有不少老师找我要使用说明,我说不用什么说明,把作文粘进去,它给你的批改报告基本能直接改改用。你放心,AI不会替你教书,但它能让你从凌晨两点的批改桌上解放出来,把时间留给真正需要你指导的学生。
本文还有配套的精品资源,点击获取