news 2026/8/6 18:06:43

Canguo Science 的学术 Skills 是怎么把模型输出变成规范 Word / PDF 的?(含代码)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Canguo Science 的学术 Skills 是怎么把模型输出变成规范 Word / PDF 的?(含代码)

科研工作流的最后一公里是"成稿"——把一堆分析结果、笔记、引用,拼成一份格式规范的 Word 或 PDF。这一步最磨人的不是写内容,而是排版、对齐引用、统一格式。Canguo Science 把它封装成了"学术 Skills":模型负责产出内容,Skill 负责把内容变成规范文档。

这篇讲讲这条链路在工程上怎么落地,用能跑的 Python:让模型返回结构化输出 → 用 python-docx 生成规范 Word → 处理字体 / 表格 / 引用 → 导出 PDF。模型这一层在 Canguo Science 里统一走 CanguoAI 的 OpenAI 兼容入口,所以下面的代码换任意模型都一样,不影响成稿逻辑。代码为便于阅读做了简化。

一、先让模型给你"结构化"的输出

直接把模型吐的一大段 Markdown 硬塞进文档,格式很难控制。更稳的做法是让模型返回结构化 JSON,成稿逻辑只跟固定的数据结构打交道:

import os, json

from openai import OpenAI

client = OpenAI(

api_key=os.environ["LLM_API_KEY"],

base_url=os.environ["LLM_BASE_URL"], # OpenAI 兼容入口的 /v1,换模型只改 model

)

SCHEMA_HINT = """

只输出 JSON,结构为:

{"title": "标题",

"sections": [{"heading": "小节标题", "body": "正文"}],

"references": ["文献1", "文献2"]}

"""

resp = client.chat.completions.create(

model="gpt-4o-mini",

messages=[

{"role": "system", "content": "你是科研写作助手。" + SCHEMA_HINT},

{"role": "user", "content": "写一份关于扩散模型的简短综述"},

],

response_format={"type": "json_object"}, # 保证输出是合法 JSON

)

data = json.loads(resp.choices[0].message.content)

一个细节:用response_format={"type": "json_object"}时,prompt 里必须出现 "JSON" 字样,否则接口会报错——这是 OpenAI 兼容协议的约定。

二、用 python-docx 把结构化数据变成 Word

拿到规整的data之后,生成文档就是"照着结构填":

from docx import Document

def build_docx(data: dict, out="report.docx"):

doc = Document()

doc.add_heading(data["title"], level=0)

for sec in data["sections"]:

doc.add_heading(sec["heading"], level=1)

doc.add_paragraph(sec["body"])

if data.get("references"):

doc.add_heading("参考文献", level=1)

for i, ref in enumerate(data["references"], 1):

doc.add_paragraph(f"[{i}] {ref}")

doc.save(out)

build_docx(data)

结构化的好处在这一步体现得淋漓尽致:模型输出一变,文档跟着变,中间没有脆弱的字符串解析。

三、中文字体:一个绕不过去的坑

python-docx 设中文字体有个经典陷阱——只设font.name对中文不生效,中文会回退成默认字体。正确做法是额外通过w:eastAsia设一遍

from docx.shared import Pt

from docx.oxml.ns import qn

def set_base_font(doc, latin="Times New Roman", cjk="宋体", size=12):

style = doc.styles["Normal"]

style.font.name = latin

style.font.size = Pt(size)

# 关键:中文字体必须单独通过 w:eastAsia 设置,否则不生效

style.element.rPr.rFonts.set(qn("w:eastAsia"), cjk)

这个坑几乎每个用 python-docx 排中文文档的人都会踩一次,记住qn("w:eastAsia")就行。

四、表格与图表:把实验结果放进去

科研文档少不了表格和图。表格用add_table,图用add_picture

from docx.shared import Inches

from docx.enum.text import WD_ALIGN_PARAGRAPH

def add_table(doc, headers, rows):

table = doc.add_table(rows=1, cols=len(headers))

table.style = "Table Grid" # 带边框的内置样式,最稳

for j, h in enumerate(headers):

table.rows[0].cells[j].text = str(h)

for row in rows:

cells = table.add_row().cells

for j, v in enumerate(row):

cells[j].text = str(v)

def add_figure(doc, img_path, caption=None):

doc.add_picture(img_path, width=Inches(5.5))

if caption:

p = doc.add_paragraph(caption)

p.alignment = WD_ALIGN_PARAGRAPH.CENTER

add_table(doc=Document(), headers=["方法", "准确率"],

rows=[["A", "0.91"], ["B", "0.88"]])

Table Grid是内置样式、任何环境都有,比那些花哨样式名稳;图的宽度用Inches/Cm控制,避免原图过大撑破版面。

五、引用与编号:让正文和参考文献对得上

综述里最容易出错的是引用编号——正文里的[3]得和文末第 3 条对得上。与其手动数,不如维护一个引用登记表,自动分配编号:

class Citations:

def __init__(self):

self._refs = []

self._index = {}

def cite(self, ref: str) -> str:

"""引用一次,返回对应编号(同一文献编号固定)。"""

if ref not in self._index:

self._refs.append(ref)

self._index[ref] = len(self._refs)

return f"[{self._index[ref]}]"

def bibliography(self) -> list[str]:

return [f"[{i}] {r}" for i, r in enumerate(self._refs, 1)]

cite = Citations()

para = f"扩散模型最早由相关工作提出 {cite.cite('Ho et al., 2020')}," \

f"后续被大量改进 {cite.cite('Song et al., 2021')}。"

print(para) # ...提出 [1],后续被大量改进 [2]。

print(cite.bibliography()) # ['[1] Ho et al., 2020', '[2] Song et al., 2021']

正文按出现顺序自动编号,文末一次性生成参考文献列表,两边永远对得上——这类机械又易错的活,正是"学术 Skill"最该替你干的。

六、导出 PDF:别指望纯 Python 完美转换

很多人以为有个库能把 docx 一键完美转 PDF,实际没有那么理想。几条现实路径:

  • docx2pdf:效果好,但依赖本机装了 Word(Windows / macOS);
  • LibreOffice headless:服务器首选,命令行批量转,无需 Word;
  • reportlab:从结构化数据直接另画 PDF,排版完全可控,但样式得自己写。

服务器环境推荐 LibreOffice,一行命令搞定:

import subprocess

def docx_to_pdf(path, outdir="."):

subprocess.run(

["soffice", "--headless", "--convert-to", "pdf", "--outdir", outdir, path],

check=True,

)

选哪条看场景:要还原 Word 版式用前两个,要完全掌控排版、且不怕多写代码就用 reportlab。

七、成稿也要可溯源

最后补一句和前面工作流的衔接:Canguo Science 里每段内容都能挂上生成它的run_id。成稿时把这个信息留在段落或脚注里,读者(或审稿人)就能顺着它回溯到原始运行——引用不是"编"出来的,而是从真实运行档案里回溯出来的。这是把"可溯源"一路贯穿到最终文档的关键一步。

小结

把模型输出变成规范文档,工程上就三件事:

  • 先要结构化输出(JSON),别让脆弱的字符串解析毁掉排版;
  • python-docx 的中文字体要设w:eastAsia,表格用Table Grid最稳;
  • 引用自动编号,正文和文末靠登记表对齐;
  • PDF 转换按场景选,服务器用 LibreOffice headless。

这些拼起来,就是"从模型输出到一份能交付的 Word / PDF"这条链路。它跟你用哪个模型无关——在 Canguo Science 里模型走 CanguoAI 的统一入口接进来,成稿逻辑一行都不用改。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/6 18:04:57

Windows系统终极清理方案:EdgeRemover专业卸载工具完全指南

Windows系统终极清理方案:EdgeRemover专业卸载工具完全指南 【免费下载链接】EdgeRemover A PowerShell script that correctly uninstalls or reinstalls Microsoft Edge on Windows 10 & 11. 项目地址: https://gitcode.com/gh_mirrors/ed/EdgeRemover …

作者头像 李华
网站建设 2026/8/6 18:04:00

5分钟上手draw.io桌面版:完全免费的跨平台图表工具实战指南

5分钟上手draw.io桌面版:完全免费的跨平台图表工具实战指南 【免费下载链接】drawio-desktop Official electron build of draw.io 项目地址: https://gitcode.com/GitHub_Trending/dr/drawio-desktop 还在为寻找一款既专业又免费的图表软件而烦恼吗&#xf…

作者头像 李华
网站建设 2026/8/6 17:55:30

CSS: underline

.mark { text-decoration-line: underline; //下划线text-decoration-style: wavy; //波浪线 text-decoration-color: red; //红色 }text-decoration-line: overrline; //上划线

作者头像 李华
网站建设 2026/8/6 17:53:35

2026最新5款团队编程协作工具深度实测方案

作为一个带3人小团队的Tech Lead,过去这大半年我一直在寻找适合小团队的高效AI编程协作方案。我们团队同时维护着几个面向企业客户的SaaS项目,之前一直在用传统的Git Flow配合老款AI编程插件,但总感觉协作效率上不去——每个人的AI提示词风格…

作者头像 李华
网站建设 2026/8/6 17:51:34

Linux convertquota 命令详解:磁盘配额文件格式转换工具

Linux 学习资料 https://pan.baidu.com/s/1A6qqBk2ViE_Le2cQjSowkQ?pwd7uz8 1. 命令简介 convertquota 是一个用于转换磁盘配额(Disk Quota)数据文件格式的 Linux 系统管理命令。它主要用于将旧版(通常是 v1 版本)的配额数据…

作者头像 李华