Nox-Lumen MfgNox-Lumen Mfg

docx

能力

Word 文档(.docx) 提供完整的读写与编辑能力,既覆盖简单段落/表格操作,也覆盖书签、跨文档超链接、修订(tracked changes)、批注、复杂样式等高级需求。

大类支持能力
段落、表格、图像、修订、批注、样式;支持 pandoc / unpack 两种方式
创建从零构造 .docx(docx-js),含标题、列表、表格、图片、TOC、页眉页脚、页面大小
编辑段落文本替换、表格改值、插入/删除段落、插入图片、查找替换
书签与超链接段落级 / run 级书签,内部锚点链接,跨文档超链接
修订与批注<w:ins> / <w:del> 跟踪变更、添加批注(comments)
高亮与格式精准关键字高亮、跨 run 自动拆分
验证docx_validator 后置校验 ZIP 完整性、书签配对、r:id 与 rels 一致性

两条工具链:python-docx 优先、必要时走 XML

原则:能用 python-docx 完成的先用 python-docx,代码简单、易维护;只有 python-docx 做不到的才走 unpack → edit XML → pack。

能力python-docxXML 方案
段落 / 表格 / 插入图片✅ 简单✅ 支持
样式 / 复杂格式⚠️ 部分支持✅ 完全支持
书签 / 超链接✅ 用 docx_link_engine
修订 / 批注✅ 必须 XML

核心封装模块(ragbase_skills.docx

模块用途
docx_utils段落遍历(自动跳过 TOC)、安全文本修改、精准高亮、原地插入段落
keyword_locator关键字定位(支持 para_range + 表格 fallback + 消歧)
docx_link_engine书签 / 超链接 / 批量 batch_operations(坐标驱动)
docx_pipeline组合层:定位 + 操作一步完成、双向链接自动四步
docx_validatorDOCX 后置验证
comment标准化批注文本(build_mapping_comment

这些模块在 Agent 的 execute_code 环境中预装可直接 import,禁止手写 XML。

跨文档超链接(汽车/专利场景高频能力)

ASPICE 场景里"需求文档 ↔ 测试文档"的双向追溯、专利场景里"说明书 ↔ 附图列表"的交叉引用,都是跨文档超链接。docx skill 封装了这套能力的四步原语:

Rendering diagram…

用组合层一次搞定:

from ragbase_skills.docx import docx_pipeline as pipeline
 
pipeline.bidirectional_link(
    pairs=[("req.docx", "REQ_001", "test.docx", "TEST_001")],
    output_dir="out/"
)

跨文档链接避坑清单(高频踩坑)

现象原因做法
跳到目标文档首页而非锚点用了 w:anchor(只对内部链接有效)跨文档必须用 r:id + relationship
跳到 TOC 区域而非正文_Toc 书签干扰书签打在正文段落,必要时中和 _Toc
Word 导航静默失败无报错书签名 > 40 字符(中文 sanitize 后易超限)缩短书签名到 ≤ 40 字符,用 bm_ 前缀
域代码链接不可点击fldChar 控制 run 含 rPr控制 run 不能带 rPr,仅显示文本 run 有格式

详细踩坑清单与解决方案见 skill 内置的 references/hyperlinks.md

批量与双向链接

真实项目里的场景不是"打一个书签",而是"一份需求文档上百条条目,每条都要双向关联到测试文档里对应的用例"。docx_link_engine 为批量操作提供了完整封装:

批量加书签(一次 unzip)

from ragbase_skills.docx import docx_link_engine as dle
 
specs = [("REQ_001", "bm_REQ_001"), ("REQ_002", "bm_REQ_002"), ...]
count = dle.batch_insert_bookmarks_on_run("req.docx", specs, "req.docx")

批量跨文档超链接

specs = [
    # (关键字, 目标文档, 目标书签, 显示文本)
    ("REQ_001", "test.docx", "bm_TC_001", "测试用例 TC_001"),
    ("REQ_002", "test.docx", "bm_TC_002", None),  # None 表示不改显示文本
]
count = dle.batch_insert_cross_document_hyperlinks_on_run("req.docx", specs, "req.docx")

一对多分段链接(一条需求关联多个测试)

# 把 "REQ_001" 文字拆成 N 段,每段指向不同的测试用例
links_created, rids = dle.split_run_with_cross_document_hyperlinks(
    "req.docx",
    text="REQ_001",
    targets=[
        ("test.docx", "bm_TC_001_01"),
        ("test.docx", "bm_TC_001_02"),
        ("test.docx", "bm_TC_001_03"),
    ],
    out="req.docx",
    nearby="功能需求",
    para_range=(120, 200),
)

坐标驱动的批量操作(推荐)

当有上百条条目要在文档中定位 + 操作时,先用 keyword_locator.batch_locate() 一次性拿到所有坐标,再喂给 batch_operations

from ragbase_skills.docx import keyword_locator, docx_link_engine as dle
 
# 一次性定位所有关键字
locators = keyword_locator.batch_locate("req.docx", keywords=[...])
 
operations = [
    {"op": "bookmark",       "locator": locators["REQ_001"], "bookmark_name": "bm_REQ_001"},
    {"op": "hyperlink",      "locator": locators["REQ_002"], "target_doc": "test.docx", "bookmark_name": "bm_TC_002"},
    {"op": "split_hyperlink", "locator": locators["REQ_003"], "targets": [("test.docx", "bm_TC_003_01"), ("test.docx", "bm_TC_003_02")]},
]
result = dle.batch_operations("req.docx", operations, "req.docx")
# → {"bookmarks": 1, "hyperlinks": 1, "splits": 1, "failed": 0, "failed_details": []}

N-to-N 双向链接(完整示例)

# 阶段 1:两个文档各自加书签(一次 unzip/zip)
for text_a, bm_a, pr_a, nb_a, text_b, bm_b, pr_b, nb_b in mapping:
    dle.insert_bookmark(local_a, text_a, bm_a, local_a, nearby=nb_a, para_range=pr_a)
    dle.insert_bookmark(local_b, text_b, bm_b, local_b, nearby=nb_b, para_range=pr_b)
 
# 阶段 2:两个文档各自加指向对方的跨文档超链接
for text_a, bm_a, pr_a, nb_a, text_b, bm_b, pr_b, nb_b in mapping:
    dle.insert_cross_document_hyperlink(local_a, text_b, final_b_name, bm_b, local_a, nearby=nb_a, para_range=pr_a)
    dle.insert_cross_document_hyperlink(local_b, text_a, final_a_name, bm_a, local_b, nearby=nb_b, para_range=pr_b)

运行时两大陷阱

陷阱 1:docx ≠ out 循环覆盖

# ❌ 每轮都从 local_original 读,后一轮覆盖前一轮写的书签
for text, bm in pairs:
    dle.insert_bookmark(local_original, text, bm, local_output)
 
# ✅ out = docx,每轮读到上一轮的最新结果
for text, bm, pr in pairs:
    dle.insert_bookmark(local, text, bm, local, nearby=..., para_range=pr)

陷阱 2:doc.save()dle.insert_*() 在同一循环中混用

python-docxdoc.save()内存对象写到磁盘;dle.insert_*()磁盘读 XML 改后再写回。在循环里交替调用会互相覆盖。

# ❌ 每轮 doc.save() 都覆盖掉上一轮 dle 写的超链接
for gac_id in func_ids:
    docx_utils.safe_append_text(para, f" {gac_id}")
    doc.save(local_path)
    dle.insert_cross_document_hyperlink_on_run(local_path, gac_id, ...)
 
# ✅ 两阶段:python-docx 先一次性 save,再批量 dle
for gac_id in func_ids:
    docx_utils.safe_append_text(para_map[gac_id], f" {gac_id}")
doc.save(local_path)
 
specs = [(gac_id, target_doc, gac_id, gac_id) for gac_id in func_ids]
dle.batch_insert_cross_document_hyperlinks_on_run(local_path, specs, local_path)

关键字精确定位

在已有文档里做"把第 3 章 2.1 节的 XX 替换为 YY"这种操作,光靠 str.find() 会误命中 TOC、误命中其他章节。keyword_locator 通过 para_range 范围 + context_before/after 上下文词 做消歧:

from ragbase_skills.docx import keyword_locator
 
result = keyword_locator.locate_keyword(
    "spec.docx",
    keyword="30",
    nearby="违约责任",          # 附近必须出现的词
    para_range=(120, 150),      # ES 检索给出的段落范围
    match_mode="run"            # run/paragraph/fuzzy
)
# → {"found": True, "paragraph_idx": 135, "run_idx": 3, ...}

通常配合 document-editing skill 的 ES 检索一起用:先用 ES 拿粗略 para_range,再用 keyword_locator 精确落位,最后调 docx_link_engine 操作。

适用场景

场景实现思路
从模板生成合同 / 报告 / 备忘录用 docx-js 从零构造,含 TOC、页眉页脚
批量填充模板字段docx_utils.safe_replace_text 保留格式替换
专利说明书章节修订keyword_locator 定位 + docx_utils.insert_paragraphs_after
需求↔测试双向追溯链接docx_pipeline.bidirectional_link 一步搞定
审查意见回写为 tracked changesunpack → XML 插入 <w:ins> / <w:del>
文档审核标注批注comment.build_mapping_comment + XML comments
跨文档自动插入引用pipeline.locate_and_apply(doc, specs)

触发方式

/docx 从这个模板生成合同,填入客户信息

自然语言示例:

  • "生成 Word 文档"
  • "把这份 .docx 第 3 章改成 Q2 数据"
  • "给两份规范加上双向超链接"
  • "在 DOCX 里批量插入批注"
  • "把修订标记全部接受"

与其他技能的分工

技能分工
docx(本技能)DOCX 文件本身的读/写/编辑具体 API(底层)
document-editing跨格式的"定位 + 编辑 + 快照"流程(对 DOCX 会调用本技能)
xlsxExcel 的等价底层能力
html-report生成交互式 HTML 看板
patent-doc-formatter把 markdown 专利文档格式化为符合专利局格式的 DOCX(行业专用)

硬规则(违反会损坏文档)

#规则
R1execute_code必须用 ragbase_skills.docx 预装模块,禁止手写 XML 字符串
R2定位必须用 para_range + keyword,禁止全文 str.find()(会命中 TOC)
R3插入段落用 docx_utils.insert_paragraphs_after()doc.add_paragraph() 只能追加到末尾)
R4临时目录用 tempfile.mkdtemp(prefix="docx_")
R5输出前必须 docx_validator.validate_docx(path) 验证
R6跨文档超链接绝对不能用 w:anchor,必须用 r:id + relationship
R7书签名 ≤ 40 字符,用 bm_ 前缀,打在正文段落上
R8<w:t> 含首尾空格必须加 xml:space="preserve"

相关文档

On this page