/poster
从已撰写的论文生成学术 HTML 海报。读取
paper/main.tex、章节文件与图片; 构建 PaperX 兼容的dag.json中间格式;将每个章节提炼为 2–5 句话摘要; 选取代表性配图;渲染为自包含的 HTML 海报(三栏自适应布局)。
Inputs
常用
paper_dir(可选,默认paper/):LaTeX 项目目录,需包含main.tex和sections/--review(可选):调用 Review LLM 对生成的海报内容进行跨模型评审--anonymous(可选):强制将作者写为 "Anonymous",忽略\author{}、paper/.author_display.txt缓存以及--authorsflag--no-figures(可选):所有章节渲染为纯文本(适合文本密集型海报,或配图尚未准备好时)--no-logos(可选):跳过 affiliation / conference logo 询问,header 只显示 venue 文本--no-refine(可选):跳过 Step 5.5 critique-revise(默认会跑 1 轮)
进阶(脚本化使用;交互场景一般用不到)
--authors STR:覆盖海报上的作者文本(例如--authors "Mingtian Yang, Co-Author")。一次性覆盖用;日常需求由 Step 0 Q1 的paper/.author_display.txt缓存自动处理。--anonymous同时传入时仍以--anonymous为准。--venue STR:header 右块的 venue 文本(例如"NeurIPS 2026")。跳过 Step 0 的 venue 询问。--affiliation-logo PATH/--conference-logo PATH:logo 文件路径(PNG/JPG/PDF);各自跳过 Step 0 对应的询问。--layout corners|stacked(默认corners):header 布局。corners= 单位 logo 左上 + 会议 logo 右上;stacked= 两个 logo 都叠在右侧.conf区,venue 文本在最上。--auto-figures:跳过 Step 2.5 的逐章节配图询问,直接为每章选择面积最大的候选图(旧的 "largest wins" 行为)。--refine-iterations N(默认 1,硬上限 2):Step 5.5 的迭代次数。0等同于--no-refine。文字密集且首轮可能无法收敛时,调到 2。
Outputs
poster/dag.json—— PaperX 兼容的中间格式(未来可被/slides、/pr复用)poster/outline.html—— 模板注入前的<section>块拼接结果poster/poster.html—— 最终自包含的 HTML 海报(浏览器打开即可;若需 PDF:Cmd/Ctrl+P → 另存为 PDF,打印设置见 Step 7 报告)poster/poster.png—— 2× CSS 尺寸的渲染截图(默认 2800×1800),见 Step 5bposter/images/—— 从paper/figures/复制/转换(PDF→PNG @ 200 DPI)而来的图片- POSTER_REPORT(输出到终端)
wiki/log.md—— 追加日志条目
Wiki Interaction
Reads
paper/main.tex+paper/sections/*.tex+paper/figures/—— 论文源wiki/outputs/paper-plan-*.md(可选)—— 叙事线、配图计划、证据图wiki/ideas/*.md(可选)—— 假设、新颖性论证,用于海报开头wiki/experiments/*.md(可选)—— 关键数值与结果,用于结果区 callout.claude/skills/shared-references/academic-writing.md—— 去 AI 风格化规则
Writes
poster/目录(完整列于 Outputs)wiki/log.md—— 追加
Graph edges created
- 无(海报是展示产物,不是知识实体)
Workflow
前置:确认 paper/main.tex 存在。否则报错:"先运行 /paper-draft"。
Step 0: 交互式 header 配置
目标:收集 venue 文本与(可选的)两个 logo,用于海报 header 渲染。如果用户已通过 CLI flag 传入对应值,则静默跳过该项。
整个交互流程用 AskUserQuestion 做是/否/布局选择,自由文本(路径与 venue)直接读取下一条用户消息。
-
作者 —— 论文级别的元数据,按下面的优先级解析:
- 传入
--authors STRflag → 用它,不问也不持久化。 - 传入
--anonymousflag → 强制 "Anonymous",不问也不持久化。 paper/.author_display.txt存在 → 用文件内容,不问。这是"问一次,以后复用"的缓存。未来/paper-draft会在写作阶段填这个文件;在那之前,/posterStep 0 维护它(见下)。- dag.json 根节点
content(来自main.tex的\author{...}) 非空且不是字面 "Anonymous" → 用它,不问。 - 否则(匿名稿且没有缓存的 display name):问用户。
询问流程(只在第 5 条触发时进入):
- 用
AskUserQuestion,选项:"Keep 'Anonymous' (double-blind submission)"(Recommended)"Provide author names (I'll ask for the string)"
- 若选 "Provide author names":自由文本询问 "海报上应显示什么作者字符串?例如
Mingtian Yang, Co-Author Name。回复字符串,或回复skip保留 'Anonymous'。" 把下一条用户消息取作 authors 字符串。 - 把答案持久化 到
paper/.author_display.txt(单行,不要末尾换行)。下一次/poster跑时文件已存在 → step 0 Q1 静默跳过。用户想改的话,自己编辑或删除这个文件。 - 两个分支("Keep Anonymous" 或 自定义字符串)都要持久化 —— 目标是 除非用户主动删文件,否则不再被问。
- 传入
-
Venue 文本 —— 若未传入
--venue:- 询问:"海报 header 要显示什么 venue 文本?例如
NeurIPS 2026。回复文本,或回复skip留空。" - 把下一条用户消息原文取作 venue。
skip(不区分大小写)视为空。
- 询问:"海报 header 要显示什么 venue 文本?例如
-
单位/实验室 logo —— 若未传入
--affiliation-logo且未传入--no-logos:- 用
AskUserQuestion询问,选项:"Yes, I have a logo file"/"No, skip the affiliation logo"。 - 若选 yes:询问 "单位 logo 文件路径?(PNG / JPG / PDF;相对路径或绝对路径都可以)"。把下一条用户消息当作路径。校验文件存在;若不存在,提示错误后再询问一次,仍失败则按 skip 处理。
- 用
-
会议/期刊 logo —— 若未传入
--conference-logo且未传入--no-logos:- 流程同上(yes/no 用
AskUserQuestion,路径自由文本)。
- 流程同上(yes/no 用
-
布局 —— 若至少一个 logo 被提供,且未传入
--layout:- 用
AskUserQuestion询问,选项:"corners —— 单位 logo 左上、会议 logo 右上"(Recommended)"stacked —— 两个 logo 叠在右侧 conf 区,venue 文本在上方"
- 若只有 venue 没有 logo:跳过布局询问(默认
corners即可,只用 venue 文本槽)。
- 用
-
配置摘要 —— 打印一行:
Header config: authors='{...}', venue='{...}', affiliation={path|none}, conference={path|none}, layout={...}
作者字符串通过 Step 5 的 python3 tools/poster.py inject-title --authors "..." 应用;venue 与 logo 通过 python3 tools/poster.py inject-header 应用。
Step 1: 构建 dag.json
python3 tools/wiki2dag.py build --paper-dir paper/ --output poster/dag.json
若用户传入 --anonymous,在命令上加 --anonymous。
桥接工具生成三类节点:
- Root(
level: 0):name为论文标题,content为作者,edge为按顺序排列的章节名 - Section(
level: 1):name为章节标题,content为完整正文,visual_node为该章节引用的图片 - Visual(
level: 2):name为 markdown 图片引用,content为 caption,resolution为WxH
wiki2dag.py 保留论文中的:
- 数学公式:
$…$、$$…$$、\(…\)、\[…\]原样进入章节内容,后续由海报 HTML 中的 KaTeX 渲染。math_commands.tex里的宏会被展开,残留的\ensuremath{X}包装会被解包为$X$,让 KaTeX 能识别。 - 引用 —— 默认丢弃:
\citep{key}/\citet{...}标记被剥成空。基于对 CCF-A 海报的调研,实际会场上的海报通常不在正文里渲染[N]内联标注(没地方放参考文献列表)。如果你的海报样式确实需要它们,在wiki2dag.py build上加--citationsflag 可以恢复为[N]/[N, M](按首次出现顺序的bibkey → ordinal)。未来支持参考文献页脚的样式可以默认开启。 - 表格:
\begin{table}…\end{table}envs(包括通过\input{tables/foo}内联的)被转为活的 HTML<table class="poster-table">块,booktabs caption 渲染为<caption>,\multicolumn、\textbf、\emph、\textit、\texttt在 cell 层处理。Step 3 的 LLM 在SECTION_JSON.content中看到这段 HTML,必须原样插入到 summary 段落之后(见 Step 3)。fit() 算法会与正文文字一起缩放表格字号;若表格仍然溢出,Step 5.5 的 DOM 溢出探针会发现并要求修剪。 - TikZ 图:
\begin{figure}envs 中含\begin{tikzpicture}但没有\includegraphics{}的,通过tools/rasterize_latex.py(pdflatex + pdftoppm)自动光栅化到paper/figures/_tikz_<sec>_<label>.png。生成的 PNG 在桥接层眼里就是普通 visual node,Step 3 完全一样处理。若同一个 figure env 里同时有\includegraphics{},现有流水线优先(TikZ 跳过)。光栅化失败时 stderr 告警 + 丢弃该图,其它流程继续。跨次运行缓存 —— 删除 PNG 即强制重建。
Step 2: 编译 WIKI_CONTEXT(可选)
目标:可选地用论文自己的规划产物(假设陈述、新颖性论证、关联 ideas/experiments 的关键数值)为 Step 3 的蒸馏提示词提供锚点。始终告知用户当前发生了什么 —— 不要静默采用。
检测与透明度:
-
不存在 plan 文件:打印一行 ——
Step 2: 在 wiki/outputs/ 未找到 paper-plan-*.md —— Step 3 将在没有 WIKI_CONTEXT 的情况下运行。跳到 Step 2.5。 -
存在 plan 文件:打印一行总结找到了什么,例如
Step 2: 找到 wiki/outputs/paper-plan-2026-05-17.md(3 个 idea,2 个 experiment)。然后用AskUserQuestion:"Yes —— 作为 WIKI_CONTEXT 锚点采用"(推荐)"No —— 仅基于论文源蒸馏"
若用户选 Yes:读取 plan 获取 venue、叙事弧线、关联 idea slug。对每个 idea slug,读取 wiki/ideas/<slug>.md 的假设(hypothesis)与新颖性论证;对每个关联的 wiki/experiments/*.md,读取 outcome 与 key_result 字段。按章节聚合成一个 WIKI_CONTEXT 字符串:
[INTRODUCTION]
hypothesis: <来自 idea 的一句话>
novelty: <来自 idea 的一句话>
[EXPERIMENTS]
key_result: <来自 experiments 的关键数值>
outcome: <一句话总结>
若用户选 No:WIKI_CONTEXT 保持为空。
此字符串通过 Step 3 提示词中的 {WIKI_CONTEXT} 槽位传入。Step 3 提示词显式允许此槽位为空。
Step 2.5: 配图选择
目标:决定每个被选中的章节应配哪张图(或无图)。在 dag.json 构建之后、LLM 提炼之前运行,使配图选择成为 Step 3 的输入,而不是让 LLM 猜。每张图都内联渲染在章节中;manifest 中的 ⚠ wide 标记仅作信息提示 —— 提醒比例极端的图在单列里可能被压扁,用户可以选其它图或跳过。
章节选择(优先级表,硬上限 6 个章节,保持 1400×900 下可读):
- Introduction(摘要或第一节)
- Method(方法/方案章节)
- 主要结果(Experiments / Replication / 主结果章节)
- 次要结果 / 消融(空间允许时)
- 分析 / 讨论(一个核心 insight)
- Conclusion(简短结论)
模式判定:
- 传入
--no-figures→ 模式 =none;所有章节渲染为纯文本,跳过所有询问。 - 传入
--auto-figures→ 模式 =auto;为每章选面积最大的 visual(resolution的 W×H),跳过所有询问。 - 否则 → 模式 =
interactive,执行下面的 manifest + 询问。
打印配图 manifest(任何模式下都打印),示例:
Figure candidates per section:
Abstract — text only
Introduction — text only
Method — text only
Experiments — 2 candidates:
[a] layer_curves.png 2378x618 aspect 3.85 ⚠ wide
[b] bootstrap.png 974x612 aspect 1.59
Discussion — text only
Conclusion — text only
aspect 由 resolution(W×H)计算。⚠ wide 标记来自 dag.json 的 wide 字段(aspect ≥ 2.0 或 ≤ 0.5 时为 true)。
交互流程(仅模式 = interactive):
逐章节,按候选数与 wide 标记决定如何询问:
| 候选数 | Wide? | 行为 |
|---|---|---|
| 0 | — | 无图(不询问,静默) |
| 1 | any | 静默 inline 使用(manifest 已展示;若 wide |