论文写作器 本节摘要:LaTeX 骨架是研究者与排版器之间的契约。契约破则文档不编译,失败很响。先建骨架,再填。把研究论文当结构化工件——有已知节图,非自由文档。生成 LaTeX 骨架,在写任何散文前声明其摘要、节、图位、参考文献键。通过确定性槽机制从实验输出(路径与标题)注入图。接一个 mock 散文生成器从结构化大纲填每节,使框架无需模型即可测。发单一 加 加列每个引用图与所用引用的清单。从散文起的草稿累积结构债:引言长出三段该在相关工作的、图在定义前被引、参考文献一篇论文三个键;到作者注意时,重写成本高于写作成本。骨架反转此——结构作数据先声明。 对应原课程:Phase 19 · Lesson 54 · (原英文 )。本节属「AI Scientist」赛道第五节。
本节摘要:LaTeX 骨架是研究者与排版器之间的契约。契约破则文档不编译,失败很响。先建骨架,再填。把研究论文当结构化工件——有已知节图,非自由文档。生成 LaTeX 骨架,在写任何散文前声明其摘要、节、图位、参考文献键。通过确定性槽机制从实验输出(路径与标题)注入图。接一个 mock 散文生成器从结构化大纲填每节,使框架无需模型即可测。发单一
paper.tex加references.bib加列每个引用图与所用引用的清单。从散文起的草稿累积结构债:引言长出三段该在相关工作的、图在定义前被引、参考文献一篇论文三个键;到作者注意时,重写成本高于写作成本。骨架反转此——结构作数据先声明。
对应原课程:Phase 19 · Lesson 54 ·
paper-writer(原英文phases/19-capstone-projects/54-paper-writer/docs/en.md)。本节属「AI Scientist」赛道第五节。
阅读完本节,你应当能够:
paper.tex 加 references.bib 加列每个引用图与所用引用的清单。从散文起的草稿累积结构债。引言长出三段该在相关工作的;图在定义前被引;参考文献一篇论文三个键。到作者注意时,重写成本高于写作成本。骨架反转此:结构作数据先声明。节是带名与序的槽,图是带 id 与标题的槽,参考文献键在顶声明指向其条目。散文一次填一槽。框架能在写任何散文前校验:每图有槽、每引有条目、每节在目录出现。
每字段是纯 Python 数据。渲染器是从 Paper 到 LaTeX 串的纯函数。框架能在渲染前内省论文:数节、列缺失图文件、查每 \cite{key} 有匹配 BibEntry。
渲染器保三性质。一,骨架每图槽发 \begin{figure} 块带形如 fig:<id> 的稳定标签。二,每节发 \section{} 带形如 sec:<id> 的稳定标签使交叉引用工作。三,参考文献发 \bibliography 块,其 references.bib 恰含论文声明的条目,不多不少。违任一是渲染错误非警告——骨架是契约,静默丢图的渲染是违约。
注入是确定性的。图 id 从实验名加单调计数器派生。标题来自清单。路径相对论文输出目录归一化,使实验输出在别处时 LaTeX 仍编译。
本节不调模型。MockProseGenerator 读大纲形状确定性发散文。大纲形状每节一短串,生成器把串扩成两短段,把节标题织入。生成的散文名提图与引用恰在声明时。这够测写作器每行为。真实实现换生成器为模型调用,框架不变。把散文生成器声明为可调用对象的价值:测试替确定性,生产替模型,流水线其余相同。
写作器发三文件到输出目录:
清单是下游评估器或批判循环读的。它不解析 LaTeX,读清单。下一节批判循环取此清单为输入,产反馈列表——这是清单是契约一部分、LaTeX 不是的原因。
写作器在写任何文件前跑四门:每图 id 论文内唯一;每节 cites 字段引用论文声明的参考文献键;摘要非空;标题非空。失败门抛 PaperValidationError 带精确原因,无部分写——要么三文件都发要么都不。
code/main.py 定义 Paper、Section、Figure、BibEntry、PaperValidationError、MockProseGenerator、PaperWriter、render_latex。write 取输出目录发 paper.tex/references.bib/manifest.json。read_experiment_manifest 把实验清单列转 Figure 记录。
@dataclass class Paper: title: str; abstract: str; authors: list[str] sections: list[Section]; figures: list[Figure]; bibliography: list[BibEntry] def write(self, out_dir): self._validate(paper) # 四门先跑 prose = {s.id: self.gen.generate(s) for s in paper.sections} tex = render_latex(paper, prose) # 纯函数 Paper -> str bib = render_bibtex(paper.bibliography) manifest = {"figures": [f.id for f in paper.figures], "citations": collect_cites(paper), "sections": [s.id for s in paper.sections]} atomic_write(out_dir/"paper.tex", tex) atomic_write(out_dir/"references.bib", bib) atomic_write_json(out_dir/"manifest.json", manifest)
设计要点:骨架是赌注——节/图/引用声明作数据,散文填槽,清单伴 LaTeX 发,其他改进叠在上面。渲染器是
Paper -> str纯函数使多格式渲染(Markdown 博文、HTML 预览)成Paper上的策略。校验门在写前跑,无部分写,失败精确。清单是下游契约(批判循环读它不解析 LaTeX),这是它必发的理由。
真实学术写作辅助工具(Scite、Elicit、Writefull)用 LLM 生成散文,但骨架契约同:节结构、图槽、引用键声明在前。Overleaf/ShareLaTeX 是协作排版,不生成结构。本节的 Paper 数据类与 render_latex 纯函数是它们的共同抽象。LaTeX 是学术排版的 lingua franca(1978,TeX),Markdown/HTML 是替代渲染目标。本节 mock 散文生成器的价值是确定性测试——真 LLM 随机,无法断言骨架契约,先在 mock 上把写作器跑通再换真模型。引用管理(Zotero/JabRef)产 BibTeX,与 references.bib 同格式。
code/main.py + code/tests/test_paper_writer.py(覆盖无节骨架渲染、两节两图全渲染、缺引用门、重复图 id 门、清单内容、LaTeX 串契约)。PaperWriter.write(out_dir) 是编排器入口,发三文件供第 53 节批判循环消费。read_experiment_manifest 把第 50 节实验输出转图记录。换真散文生成器(真 LLM 调用),写作器与渲染器不动。
Paper -> str 策略),产博文版。cites 含未声明键,确认 PaperValidationError。MockProseGenerator 换成真 LLM,从大纲生成节散文,人工审连贯性。references.bib。\ref{fig:id} 与 \ref{sec:id} 交叉引用,确认标签稳定。\begin{figure} 带 fig:<id>、节发 \section{} 带 sec:<id>、参考文献恰含声明条目。下一节,我们做「批判循环」——五维打分(clear/novel/evidence/method/related-work)+ 结构化修订,检测收敛在 plateau/target/budget。