用AI Skill和python-docx按国标自动生成公文Word文档
1. 公文格式的痛,你我都懂
做行政、写材料、跑项目申报的朋友,估计都有过这种体验:一篇公文写完了,正文改了三轮,最后调格式又搭进去一晚上。字体改成仿宋GB2312,字号得是3号,标题居中加粗,段落首行缩进2字符,行距固定值28磅——这些规矩本身不难,难的是每次都要从头来一遍,而且总有几个细节容易漏:页码格式对不对、红头下面的分隔线是不是实线、发文字号插没插对位置。
说实话,这套格式标准并没有多高深的技术含量,它就是一套规定动作。但规定动作多了,人就容易烦。烦就容易出错,错了就得返工。所以我看到这个开源项目的时候,第一反应是:总算有人把这事系统化了。
这个项目的核心思路很简单:把《党政机关公文格式》里那些条条框框,比如版头、主体、版记的各要素位置、字体字号、行距、页码样式,全部拆成可执行的规则,然后用一个AI Skill的方式让模型按国标去生成Word文档。项目在GitHub上已经积累到700多星,说明需要它的人不少,而它也确实解决了一个很普遍的问题。
先说清楚它的能力边界。它负责的是“格式生成”,也就是你告诉它公文的内容结构,它帮你生成一份排版完全符合国标GB/T 9704-2012的Word文件。你要做的是把内容组织好——标题、主送机关、正文段落、附件说明、发文机关署名、成文日期这些要素给出清楚,它负责把格式做对。这不等于它帮你写公文内容,它更多是那个在排版车间里替你守着国标线的老师傅。
适合谁用?日常需要处理公文的事务性岗位、需要批量出红头文件的企业行政、想省掉重复劳动的个人,都适用。如果你只是偶尔写个通知、转发个要求,学一下也值。因为哪怕你告别了手动调格式,至少你知道了国标里每一行每一列到底是咋规定的。
2. 国标公文格式的核心规则,先给脑子装上这个知识包
要用好这个Skill,得先知道它到底在替我们执行哪些规则。我建议你先花十分钟把国标里那些关键参数过一遍,不然你看到生成的文档,会说“这不对吧,怎么间距这么大”或者“页码位置怎么偏了”,其实很多是国标规定的,你自己没消化而已。
2.1 版面:纸型、页边距、装订线的硬指标
国标要求公文用纸为A4型纸,这个大家都清楚,但页边距很多人记不住。上边距37mm±1mm,下边距35mm±1mm,左边距28mm±1mm,右边距26mm±1mm。你注意一下这个不对称就明白了,左边多出来的2mm其实是给装订留的。还有一些细节,比如排版时要为装订线预留位置,如果公文要双面印刷,页码要放在版心外。
这里有个容易踩的坑:很多人会用Word默认的2.54cm上下边距,也就是25.4mm,跟国标的37mm、35mm差了将近一厘米。一厘米在屏幕上看着不多,打印出来是肉眼可见的天差地别。我见过有人的公文打印出来上边明显比正常的宽了一大截,就是因为页边距没设对,整篇文件的视觉重心往下掉了。
2.2 字体字号:最容易被扣分的重灾区
国标里对字体的规定是明确的:
- 公文标题用2号小标宋体字,也就是华文中宋、方正小标宋这类,排在红色分隔线下空两行位置。
- 正文一般用3号仿宋体字,很多单位统一要求仿宋GB2312。三号仿宋是正文的主基调,这一条基本决定了整篇文件的视觉密度。
- 一级标题用3号黑体字,二级标题用3号楷体字,三级和四级标题用3号仿宋体字加粗。注意,加粗是有讲究的,不是随便把仿宋加个B。
这几个规则说白了就是:标题黑体、层次楷体、正文仿宋,差别不可混用。实际操作里,我见过很多文件把一级标题做成方正小标宋加粗,其实是错的——一级标题必须是黑体。
这里还有个大坑:Font名到底是用“仿宋_GB2312”还是“仿宋”?很多Windows系统默认没有仿宋_GB2312这个字体,只有仿宋。国标里说的是仿宋,但很多单位模板里写的是仿宋_GB2312。你真要用的时候,得先检查系统里装没装这个字体。如果没装,生成的Word会显示一个缺字体的状态,打印出来也可能用系统自动替换的字体顶替,效果就差得多。这一点等你用Skill生成完文档后,一定要肉眼检查一下字体列表。
2.3 段落和行距:行距28磅背后有小讲究
公文的正文排版里,最容易被忽略又最影响观感的就是行距。国标规定的是行数要求:一般每面排22行,每行排28个字。为了保证这个密度,最常见的做法是设成固定值28磅行距,或者用“固定值28.9磅”“29磅”这些数值,具体看你的字体版本和打印机驱动的情况。
但你要注意,这里的“固定值”一旦设置,如果某个段落里出现了超大字号字符、公式、图片,就会被裁切掉一部分,显示不完整。所以很多老手会把行距设成“最小值28磅”加一个段前段后0值,这样既保证整体疏密一致,又不会把大字符砍掉。这个细节你让Skill去做的时候,它可能只管把固定值28磅写上,但真正的行家里手会自己再调一下。
段落的另一个关键参数是首行缩进2字符。这个“2字符”不是两空格,而是相对当前字号的两个汉字宽度。所以三号字的2字符缩进大约等于两个三号汉字的宽度,约等于21磅左右,用厘米算大约是7.4mm。别用空格代替缩进,空格在不同字体下宽度不一致,打印出来会漂。
2.4 版头、主体、版记三件套
一份标准公文,从结构上分三大块:版头、主体、版记。
版头部分包括份号、密级和保密期限、紧急程度、发文机关标志、发文字号、签发人、红色分隔线。这里难点在于红色分隔线——它是版头与主体之间的界线,通常用一条红色的实线,线上方是发文机关标志和发文字号。许多模板里这条红线会带一个五角星,尤其是在党的机关公文里,规定更细。
主体部分从标题开始,包括主送机关、正文、附件说明、发文机关署名、成文日期、印章、附注。这里需要注意发文机关署名和成文日期必须居右空若干字编排,印章加盖要骑车压月。虽然用代码生成Word的时候没法真正盖章,但日期署名的位置可以精确控制。
版记部分包括版记中的分隔线、抄送机关、印发机关和印发日期。版记一定放在公文的最后一面,也就是说哪怕正文结束以后还有空白页,版记也要在那个末页的最下方,不是紧随正文。
这套规则在国标里写得清清楚楚,但手动操作是真的烦。所以你把这个活儿交给Skill,等于把一套“如果遇到X情况,就用Y规则”的判定逻辑给自动化了。
3. Skill的设计思路:把一个排版车间压缩成一个对话
这个项目的核心构成是Skill机制,具体说就是一个“按国标生成Word公文”的AI技能包。它不像传统模板那样只是把格式预设好,然后往里面套文本。它的运作方式更像你今天问一个懂得公文格式的老同事:“帮我按国标写个通知,打印出来就能用”。
3.1 Skill和你以前用的模板插件的本质区别
传统的Word模板或者VBA宏,是死的。它把格式规则固定好,你往里填内容,优点是可预测、稳定,缺点是你每换一种公文类型(通知、请示、函、会议纪要),你得准备不同的模板,而且只要内容要素一变(比如多了附件、多了抄送),模板就得手工调整。
Skill的思路是活的。它由三部分组成:触发词、指令模板、执行逻辑。你说“按国标生成一个关于XX的请示”,它就会根据你对公文要素的描述,动态选定结构模板、填入格式参数、编排段落顺序。当你告诉它“这个请示有附件,两个”,它会自动调整附件说明部分的位置和版记的编排。本质上,它是把“决定用什么格式”这件事交给了模型和一组规则,而不是交给一个固定模板。
这就好比以前你用的是一个固定的印刷电路板,什么功能都焊死了;现在用的是一个带微控制器的开发板,你可以通过代码动态重组它的外设连接。灵活性和维护成本完全不是一个量级。
3.2 谁在背后干活:Skill引擎 + Word文档生成链路
这里要说清楚它的技术底座。这类Skill通常跑在具备工具调用能力的AI平台上,比如Claude Code、Codex这类智能体环境。模型负责理解需求、拆解流程、生成结构化数据,然后把生成任务交付给下游的文档处理工具——在当前生态里,最常用的是python-docx这个Python库。
python-docx的能力边界你要清楚:它可以精确控制节的属性(页面大小、页边距)、段落的样式(字体、字号、对齐、缩进、行距)、表格的样式、图片的插入。这些正好覆盖了公文国标90%以上的格式需求。剩下的红头文件的印章效果、水印之类,它有局限,需要另想办法,但这个项目目前一般也没去碰印章。
Skill的聪明之处在于,它把“国标知识”和“python-docx的API调用”串联起来了。比如“章节标题用22磅方正小标宋”这句话,在人脑里是一句经验,在代码里就是:
from docx.shared import Pt from docx.enum.text import WD_ALIGN_PARAGRAPH def set_title_style(paragraph): run = paragraph.runs[0] run.font.name = '方正小标宋简体' run._element.rPr.rFonts.set(qn('w:eastAsia'), '方正小标宋简体') run.font.size = Pt(22) paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER这里有个细节,很多人用python-docx设置中文字体时只改了font.name,结果发现没用,因为Word里中文字体存在一个独立的"eastAsia"属性里,必须同时设置w:eastAsia字段才能生效。Skill如果你自己写的话,千万别漏了这一步,漏了文生出来所有中文全是宋体默认,你会怀疑人生。
3.3 项目为什么选择“Skill包”而不是“纯脚本”
这个问题我也想过。如果只是要生成国标Word,写一个Python脚本其实也能干——把规则都硬编码进去,每次传参数就行。为什么不这么做?
答案是从维护和扩展的角度看,Skill包的价值大得多。你写一个单一脚本,意味着每次规则一变(比如新的国标出了修订版、单位自己的版面微调)你都要去改代码。但Skill包把“知识”和“执行”分开了:国标规则变成模型可读的指令文件,生成动作变成一组可复用的脚本工具。改规则不需要重写代码,改指令配置文件就行;加新功能(比如生成PDF版、加签章占位)也只需要加对应的执行工具。
这个分层设计,是这类项目能火起来的重要原因。700多星不完全是“它生成了多好看的Word”,而是一群人看到了“以后我可以在这个基础上做自己单位的定制化”的可能性。
3.4 Skill的输入输出是怎么被组织起来的
把过程掰开来看,大概是这样的流水线:
- 输入阶段:你描述需求,说明文种(通知、请示、报告等)、发文机关、正文要点、附件清单、主送机关等核心要素。
- 规划阶段:模型判断此文种对应的国标版式,确定采用哪种页面设置、标题样式、层次结构。
- 生成阶段:模型调用文档生成工具,按“版头—主体—版记”的顺序构建文档结构,逐段设置段落样式。
- 校验阶段:生成后检查关键参数,如页边距是否等于37/35/28/26mm,标题字号是否2号,正文是否3号仿宋,行距是否28磅。这一步非常关键,毕竟模型生成文档的过程中任何一步都可能漏掉。
这个流水线看起来很顺,但真跑起来的时候,问题往往出在最后一步——校验阶段容易被跳过。我实测了几个类似项目,经常出现的情况是:内容完美、段落结构完美,但页边距设成了默认的2.54cm。所以哪怕项目本身没有显式校验步骤,你自己拿到文件后也应该先看一眼页面设置。
4. 从零跑通:安装、调用、验证一篇国标公文
光知道原理不行,得能亲手跑出成品来。下面我按实际操作的顺序来写,每一步我踩过的坑都会标出来。
4.1 环境准备:别在依赖上浪费半小时
你需要在能运行Python和智能体服务(如Claude Code或Codex)的机器上操作。第一步是把python-docx装好:
pip install python-docx这是最基础的依赖。如果你的机器上之前装过旧版,注意升级一下:
pip install --upgrade python-docxpython-docx目前主版本是1.x,接口上跟0.8.x相比有一些调整,老教程里常见的document.sections[0].page_width这类属性依然能用,但建议你以官方文档为准。
第二步是确认Skill文件结构。这类Skill一般以文件夹形式存在,里面包含SKILL.md(技能说明和触发逻辑)、scripts/(执行脚本)和assets/(辅助资源)。你要确保这个Skill文件夹被放进了智能体技能目录里,否则模型根本看不到这个工具。这一步别看简单,真的是最容易卡住的地方——放错目录的话一切都白搭。
4.2 第一个生成请求:让它写一篇通知
环境就绪后,直接发指令,例如:
请使用公文Skill,按国标GB/T 9704-2012生成一篇关于召开安全生产工作会议的通知。发文机关为“XXX公司办公室”,发文字号为“X办发〔2025〕14号”,主送机关为“各部门、各项目部”,正文要点:一、会议时间2025年7月5日上午9:00;二、会议地点公司三楼会议室;三、参会人员各部门负责人及安全员;四、会议要求提前10分钟入场并签到。请生成Word文档。
Skill收到后会做两件事:先确认文种对应的版式规则,再按要素组织内容。你可以观察它生成的代码——正常情况下,它会定义页面尺寸、设置边距、计算标题行数、安排发文字号的位置。
生成完成后,你手上会得到一个.docx文件。我建议你先别急着打开欣赏,先用一个Python脚本做个“体检”,检查关键参数:
from docx import Document from docx.shared import Cm doc = Document("test.docx") sec = doc.sections[0] print("上边距:", sec.top_margin.cm, "cm") print("下边距:", sec.bottom_margin.cm, "cm") print("左边距:", sec.left_margin.cm, "cm") print("右边距:", sec.right_margin.cm, "cm")国标要求是上37mm、下35mm、左28mm、右26mm,换算成厘米就是3.7、3.5、2.8、2.6。如果输出跟这个不一样,那就说明Skill在页面设置这一步没做对,你可以手动改,也可以把它列为这个Skill的已知缺陷,后续在指令里额外加上“页面设置为上3.7cm、下3.5cm、左2.8cm、右2.6cm”。
4.3 样式检查:字体和段落才是真正的试金石
页面设置过了,接下来检查字体和段落。用下面这段代码扫描全文:
from docx import Document doc = Document("test.docx") for i, p in enumerate(doc.paragraphs): if not p.text.strip(): continue runs_info = [] for r in p.runs: fn = r.font.name east = r._element.rPr.rFonts.get('{http://schemas.openxmlformats.org/wordprocessingml/2006/main}eastAsia') if r._element.rPr is not None and r._element.rPr.rFonts is not None else None runs_info.append((r.text[:15], fn, east, r.font.size.pt if r.font.size else None)) print(i, p.text[:20], runs_info[0] if runs_info else "无run")重点检查三处:
- 标题的字体名是否包含“小标宋”或者“方正小标宋”,字号是否22磅(也就是2号)。
- 正文的字体是否为仿宋类,字号是否16磅(3号)。
- 一级标题(“一、二、三”)的字体是否为黑体,字号16磅。
如果发现字体全是“宋体”且字号是12磅,那基本可以断定Skill在设置中文字体时没写eastAsia属性。
字体检查完之后,再看段落格式。公文的正文段落必须是首行缩进2字符,做法是设置paragraph_format.first_line_indent。如果用字符单位,python-docx支持这样写:
from docx.shared import Pt p.paragraph_format.first_line_indent = Pt(32) # 16磅*2字符或者用docx.shared.Length配合Emu,但最简单的做法是直接设置一个固定值。三号字是16磅,2字符缩进就是32磅。这个数值不会有偏差,因为仿宋三号字每个汉字宽度恰好约等于16磅。
4.4 把成品转成PDF验证打印效果
Word里看着没问题,不等于打印没问题。我一直建议生成完的公文最终要转一遍PDF再检查:字体的嵌入情况、页边距是否真的生效、页码位置是否正确。
转PDF有几种方式:如果只是本地验证,可以在Word里另存为PDF;如果想全自动化,可以用LibreOffice的命令行:
soffice --headless --convert-to pdf test.docx转完之后打开PDF看两件事:
- 页码是否在版心下边缘、右侧,用4号半角宋体阿拉伯数字,数字两侧一般有“—”线装饰(国标里这是“一字线”)。
- 红头分隔线是否是一条从左到右的红色实线,位于发文字号下方约4mm处。
说实话,第一次生成的文档大概率能及格,但页面设置和字体这两处小毛病特别常见。这不是说项目不行,而是说任何自动生成工具都需要人工校验这个环节。
5. 实测下来的坑和正确应对方式
跑了几份不同的文种之后,我总结出几个高频问题,你照着避就行。
5.1 页码设置:python-docx默认不会帮你加“— 1 —”
国标要求页码用4号半角宋体阿拉伯数字,数字左右各放一条一字线,比如“— 1 —”,单页码居右空一字,双页码居左空一字。但python-docx默认新建的文档页脚是空的。如果你直接让Skill生成,它很可能生成出来没有页码,或者有页码但没有“一字线”装饰。
正确的做法是在生成脚本里用域的代码来实现动态页码。python-docx操控域比较啰嗦,但核心思路是先往页脚插入一个PAGE域,然后在前后加上“—”字符。你要是嫌麻烦,一个更稳的方案是生成Word之后用宏手工处理一下,或者生成后用一个后处理脚本专门加域。
我自己的习惯是:让Skill先把正文和格式搞定,页码这种细节用后处理脚本统一补。原因是模型生成域的代码容易失误,而后处理脚本是确定性操作,100%可控。
5.2 红头分隔线的“颜色”问题
红头文件的那条红线,很多Skill生成时用的是表格底边框或段落底边框。这个没有错,但要注意颜色值必须精确为红色——在Word的RGB里,标准红头一般用纯红,即RGB(255,0,0)。有些默认样式用的是深红或者暗红,肉眼看着发暗,不符合“红头”的视觉要求。
如果你是做党的机关文件,这条线的中间可能还要加一个红色五角星,这在python-docx里实现起来非常绕。一个变通方案是:线用段落边框画好,五角星用图片方式插入并精确定位。但这个对坐标的计算要求高,我实测过几次,调整起来费时间,不是核心需求就别死磕,除非你是专门做组织部门文件的。
5.3 字体缺失:仿宋GB2312是中国特色
这是所有自动生成Word的项目在中国场景下都会遇到的头号问题:字体。你机器上装了“仿宋”,单位打印的那台机器可能只装了“仿宋_GB2312”。你的代码里写“仿宋”,生成的文档拿到别的机器上打开,Word会静默替换成宋体或者默认字体,整个公文的观感就废了。
解法有两条路:
- 生成时统一用国标字面名称“仿宋”,并依赖目标机器的字体映射规则。
- 生成时直接嵌入字体,python-docx本身不支持字体嵌入,但你可以用Docx2PDF工具链把字体嵌进PDF里,需要提交PDF版本时这个办法很好用。
如果你严格要走Word格式提交,建议先确认收文方的电脑装了哪些字体,按对方的字体生态来命名。这不是技术问题,是沟通问题——但它确实决定了你的自动化流程能不能收尾。
5.4 附件说明排在正文之后,不能乱跳
多附件公文中,附件说明的位置也要符合国标:在正文下空一行、左空二字编排“附件”二字,后面标全角冒号和附件名称。附件名称后不加标点符号。如果有多个附件,用阿拉伯数字标注序号,每个附件名称单独占一行。
这个逻辑在Skill生成时如果模型没理解透,很容易把附件说明排到版记后面去了。我遇到过不止一次。你检查的时候,重点看附件说明和版记的先后顺序——必须先主体后版记,附件说明属于主体部分,它一定在版记之前。
5.5 成文日期的数字格式
成文日期必须是阿拉伯数字,用公元纪年,年份标全称,月日不编虚位。比如“2025年7月5日”,不能写成“二〇二五年七月五日”,更不能写成“2025.7.5”。这个错在人工排版时也经常出现,模型有时会根据训练数据的习惯输出中文数字日期。生成后扫一眼即可发现。
6. 从“一键生成”到“真正可用”:推广前你还得做几件事
很多人拿到Skill后最理想化的期待是:我把所有公文需求都交给它,我啥都不管了。但现实是,公文自动化做到80分容易,做到100分得靠工程化配置。
6.1 建立你自己的术语库和模板库
Skill虽然内置国标知识,但它对你的单位内部习惯一无所知。比如你们的发文机关标志用的是什么字体、版头占多大高度、发文字号在红线下空几行,这些细节国标没有卡死到像素级,需要单位内部定。
建议你先把本单位近两年正式发过的文件找出来,总结几类常用文种的格式特征,做成一个补充说明文档喂给Skill。比如“本单位标题用方正小标宋22磅,版头高约45mm,发文机关标志字距加宽2磅”等等。有了这些补充,生成的文档才能从“符合国标”进化到“符合本单位格式标准”。
6.2 生成后的质检清单,宁可多查也不要少查
我给自己定了一套查收清单,每次生成后按顺序过一遍:
- 页面设置:上3.7cm、下3.5cm、左2.8cm、右2.6cm
- 标题区:标题2号小标宋、居中、红色分隔线下空两行
- 发文字号:3号仿宋、居中排布
- 主送机关:3号仿宋、顶格
- 正文层级:一级黑体、二级楷体、三四级仿宋加粗,均为3号
- 行距:正文固定值28磅或最小值28磅
- 页码:4号宋体,“— 1 —”格式且在正确位置
- 附件说明:正文下空一行,左空二字
- 版记:末页最下方,抄送、印发信息完整
这九条你每次过一遍,前面提的坑基本都能拦住。
6.3 让Skill可复用:把常用参数沉淀为配置
最后一点,也是我觉得“700星”这个数字背后最有价值的地方。当你真正把Skill用顺了,你会发现可以把它升级成一个单位内部的“公文生产小系统”:把常用主送机关、发文机关署名、抄送单位等要素做成一个本地JSON配置,Skill读取这个配置后自动填充,你再也不用每次重复输入“发文机关是XXX、主送是XXX”。
我的做法是维护一个org_config.json:
{ "org_name": "XXX公司办公室", "org_short_name": "XX办", "doc_no_prefix": "X办发", "default_recipients": ["各部门", "各项目部", "各子公司"], "signature": "XXX公司办公室", "cc_list": ["公司领导", "综合管理部"] }然后在指令里写“使用config中的默认值,并追加本次特殊要求”。这样以后发一个通知,你只需要说:“按国标生成一篇关于员工体检的通知,时间下周三至周五。”剩下的一切它都自己填好,你审一遍就行。
7. 这套思路还能扩散到什么场景
做完公文格式的自动化后,我最大的感触是:国标格式自动化这件事,只是文档自动化大棋里的一小步。同样的“技能包+规则库+生成工具”组合,几乎可以平移复制到很多场景。
教育行业可以用它生成标准化的教学计划、试卷头、成绩报告单;科研领域可以用它规范论文投稿前的版面格式;法律行业可以批量生成符合法院格式要求的起诉状要素、证据清单;企业管理上,标准化的会议纪要、采购申请、函件往来,全部能套用。
关键是你要掌握这个“翻译”的思路:把人类领域的格式规范转译成模型能读懂的结构化指令,再用文档生成工具把指令落地成Word。模型负责处理语言、抽取要素、做判断;python-docx负责把判断结果变成精确的排版动作。这两者的边界只要划对,你的自动化程度就能提升一个量级。
别担心自己不是程序员。这类Skill的使用门槛已经压得很低了,安装和配置也就一二十分钟的事情。真正花时间的是你对自己领域的格式细节复盘和整理——这些没人能替你完成,但那恰恰是最值得投入的部分。规则理清楚了,工具只是顺手的事情。
最后分享一个实际操作中的体会:无论这个Skill多好用,你送出去之前一定要用肉眼从头翻到尾一遍。不是不信代码,而是公文代表了单位门面,格式错了损失的是信任成本。把这套流程跑顺之后,一个上午能出三份规范文件,这是以前想都不敢想的速度。