skip to content
tlj 的工程笔记
← 项目

AI 论文排版助手

个人

写本科毕设时被字体格式折磨出来的工具。用 LLM 把自然语言排版指令转成 Word 样式,核心技巧是直接写 Word XML 的 w:eastAsia 槽位让中文字体生效。也如实记一段宣传大于实现的复盘。

时间
2026-01
角色
独立完成
成果
把字体映射表整张塞进 prompt 让 LLM 查表;直接操作 Word XML 的 w:eastAsia 正确渲染中文字体

这个工具的起点很真实:写本科毕业论文时,我花了大量时间手动调字体、字号、标题层级。当时 Manus 这类 AI Agent 正火,但实测它们满足不了高校论文格式的硬性要求。所以我没指望通用 Agent,自己做了个轻量工具,只解决”能用代码确定性实现”的那部分——格式这种东西要的是精确,不是模型即兴发挥。

我重写这篇时回去把代码通读了一遍,发现当年 README 写的有些功能其实代码里并没真正做到。下面只讲代码真实做了什么,也把那几处”宣传大于实现”如实记下来——这本身是个值得复盘的教训。

真正硬核的一招:直接写 Word XML 的 w:eastAsia

普通 python-docx 设字体时,中文常常不生效——因为 Word 的字体分槽:西文走 w:ascii/w:hAnsi,中文字符走 w:eastAsia 槽位,而高层 API 只设了前者。我的渲染器直接操作底层 XML:

run.font.name = style.family
run._element.rPr.rFonts.set(qn('w:eastAsia'), style.family)

qn('w:eastAsia') 把命名空间前缀展开成全限定名,直接给中文槽位赋值,这样中文字体才真正生效、且在任何设备打开都标准统一。这是这个项目唯一真正硬核、且确实正确的技巧。

但要诚实说明:当年 README 宣传”中文宋体、英文 Times 双通道独立 + 衬线无衬线智能回退”,回看代码,w:asciiw:eastAsia 其实被设成了同一个字体名,样式数据结构里也只有一个 family 字段——物理上承载不了中英文两种字体。所以它做到的是”正确设置中文字体”,不是”中英文用不同字体”。那个智能回退在代码里并不存在。这是我当年把”想做的”写成了”做到的”。

一个有意思(也有争议)的架构决策:让 LLM 查表

口语化字号字体(“楷体""小四”)要映射成系统码(KaiTi12.0pt)。我的做法不是在 Python 里查表,而是把整张字体映射表 json.dumps 后塞进 prompt,让 LLM 在 prompt 里查

好处是灵活——加一个字体改 JSON 配置就行、不用动代码;代价是把一个本该确定性的映射交给了概率模型,靠 temperature=0.1 赌稳定。这个选择见仁见智,但它是这个项目的核心架构,我把它如实摆出来。配套有兜底:配置文件找不到时用一份硬编码的保底映射(注释原话是”为了防止变回宋体”)。

真正的金矿:6 个 fix 脚本背后的调试史

仓库里有 6 个 fix_*.py 一次性补丁脚本,是我当年”改完线上文件”的痕迹。把它们串起来,正好是 LLM 工程的三类经典坑:

  1. LangChain 花括号转义:prompt 里的字面 JSON 花括号 {} 被 LangChain 当成变量插值符,必须双写 {{}}
  2. 过度修复误伤代码:上一步把 Python 代码里本不该转义的 {"type":"json_object"} 也误转成了 {{}},又得写个脚本还原——典型的”修 prompt 误伤代码”。
  3. LLM 输出的 JSON 不合法:模型文本里的裸双引号撑爆 json.loads(往 prompt 注入转义指令)、输出小写 align 撑爆 Enum 校验(merge 时强制 .upper())、偶尔包 ```json 围栏(代码里剥离)。
  4. Windows GBK 编码:在 Windows 上默认 GBK 存盘,传到 Linux 按 UTF-8 读就乱码,得遍历文件 gbk 读 → utf-8 写回

这些坑没法编,是真接了 LLM、跨了 Windows/Linux 才会撞上的。整个工程贯穿一个”LLM 不可靠”的防御式假设:配置找不到→硬编码兜底、LLM 挂了→原文当单个段落、JSON 不合法→剥围栏/补大小写。这是我觉得这个小项目里最实在的部分。

技术栈与诚实的边界

FastAPI 后端、Streamlit 前端、LangChain 管 prompt、智谱 GLM-4 出 JSON、python-docx 生成文档。要补一句诚实的:仓库里的 RAG(Chroma 向量库)在提交状态下是空的,所以语义检索那条链路当时没真正跑通,实际走兜底默认样式。

后来补的(AI 协作完成,诚实标注)

回头给它做了一轮加固,几处值得记(这些是后来补的、AI 辅助完成,不是当年手搓):

小结

这是个典型的”自己痛点驱动”的本科小工具。它有一个真正正确的硬核技巧(w:eastAsia ),一个有争议但自洽的架构(prompt 查表),和一段编不出来的真实调试史(6 个 fix 脚本)。我也借这次重写把当年”宣传大于实现”的几处如实更正了——回到代码看真相,比照着 README 复述,要靠谱得多。