14
0
0

AI 自动整理周报并生成 Word:自研周报总结 skill 拆解

2026-10-27
2026-10-30
文章摘要
|

背景与目标

每周写周报是很多团队的固定动作,但它非常机械:收集每个人/每个项目做了什么(常是零散的几条),把它们整理成简洁客观的条目,再按规格排好序、附上总结,最后导成一份带格式的 Word 文档。重复劳动,枯燥,还容易因为格式不一致被退回。

我把它做成了一个 skill(可复用的能力封装,见 GLOSSARY.md),让 AI 完成"整理→排序→总结→排版→出文档"的整条流水线。阅读本文后你会得到:

  • 一套从零搭一个"整理类" skill 的通用套路:输入怎么定、规则怎么列、脚本怎么接、踩过哪些坑。

  • 一个可以复制改造成任意"条目整理成文档"场景的方法论骨架(会议纪要、日报、需求清单、验收记录……换汤不换药)。

这不是一个"开箱即用"的成品 skill,而是"如何设计一个这样的 skill"的思路拆解。核心价值在方法论,不在某一份具体配置。

步骤

一个整理类 skill 通常由四块组成,按这个顺序设计基本不会漏:

1. 定输入结构:让"人"的活最轻松

最重要的是输入格式要贴近人怎么说话,而不是贴近程序怎么解析。我用的输入长这样:

项目名-姓名
1. 完成事项描述
2. 完成事项描述
工作总结:(可选)一段话汇总核心成果

三条约定保证了机器可解析、人易书写:

  • 每条以 项目名-姓名 开头作为块标题。块是一个最小组织单元。

  • 标题下是数字列表,至少一条。数字列表让 AI 容易识别"这是条目而不是废话"。

  • 末尾可选一段 工作总结:。人是可以偷懒不写的,缺了让 AI 自动补。

注意一个关键决策:同一人可出现在多个项目下,每个 项目名-姓名 视为独立块,不合并。这跟"按人汇总"的直觉相反,但它更接近真实输入——人本来就是按"在哪个项目里做了什么"来打字的,中途改回按人合并反而逼用户多做事。

2. 列处理规则:把"隐性规则"讲明白

AI 的难点不在生成,而在你不知道它有没有遵守你的隐性要求。所以规则要一条条写明。以周报为例,最要命的是两类规则:

语言规则(所有条目通用):

  • 以动词开头,简洁客观(上线XX功能、修复XX的Bug)。

  • 每条 1-2 句,突出"做了什么→结果如何"。

  • 去除冗余、重复,按重要性排序。

结构规则(本场景特有,也是最容易踩坑的一类):

  • 块按固定的板块顺序排列(如:主产品 → 子产品 → 其他 → 运维支持)。这个顺序写在规则里,AI 才可能遵守。

  • "禁止主动添加":分类标题(如 【功能开发】)只在用户输入里明确给了才保留,用户没给就纯数字列表。规则里专门加了一句"禁止主动归类捏造标题"——没有这句,AI 会自作主张给空白条目编分类,这是实际踩出来的教训,详见踩坑第 3 条。

  • 特例板块(如 【运维支持】)要合并、每条约负责人、且不要工作总结——凡是"特殊处理",都要显式写清楚范围。

3. 总结生成:三分靠模板,七分靠"不编造"

工作总结是周报里最需要"AI 味"的地方,但要防止它编造没做过的事。所以规则分两种情况:

  • 用户给了 工作总结: → 保留并优化语言,突出核心价值。

  • 用户没给 → AI 根据该块条目自动生成,且规则要求"概括准确、不编造内容",只能从已有条目归纳,不能凭空加成果。

给 AI 一条生成句式参考(如 完成X,对接Y,实现Z 的动宾结构)能显著稳定输出质量。"可参考例子"是让 AI 稳定的一等公民手段——一个正确的例子比十句话都管用。

4. 生成 Word:把排版交给脚本,而不是让 AI 手写

不要让 AI 直接吐 docx,它做不到稳定格式。正确分工是:

  • AI 负责内容:把输入整理成一段结构化 JSON(blocks 数组:标题、分类、条目、总结)。

  • 脚本负责排版:用一个 python-docx 脚本读这份 JSON,产出格式统一的 .docx。

这就是"AI 纠内容、脚本管格式"的边界,也是整套系统可持续的关键——改格式只改脚本,改规则只改 prompt,互不污染。

于是流程闭合为:用户给草稿 → AI 整理成 JSON → 脚本转 Word。人只需要在最开始打字,最末尾核对。

附:完整 skill 内容

下面给出我实际用的 skill 完整内容,便于你把方法论落到自己的版本。公司内部的项目名、板块名、团队署名已用占位符替换。

A. SKILL.md(规则主体)

---
name: weekly-summary
description: 团队周报工作总结 - 调整优化已有周报内容,或根据输入生成周报总结,按项目维度汇总,最终生成 Word 文档。
---
​
# 周报工作总结 Skill
​
## 功能概述
- **内容整理**:用户提供按人/项目整理的周报草稿,自动优化语言、统一格式、生成工作总结
- **输出 Word 文档**:自动生成格式规范的 `.docx` 文件
​
## 工作流程
​
### 1. 收集输入
​
用户自行整理本周团队工作内容,输入格式如下:
​
项目名-姓名
1. 完成事项描述
工作总结:(可选)一段话汇总核心成果
​
- 每条以 `项目名-姓名`(无括号)开头作为标题
- 标题下列数字列表条目(至少 1 条)
- 末尾可选 `工作总结:` 段落
- **同一人可出现在多个项目下**,每个 `项目名-姓名` 视为独立块
​
### 2. 处理内容
​
#### 2.1 保留块结构
保持每个 `项目名-姓名` 为独立块,**不合并同人不同项目**的条目。
​
**例外:`【运维支持】` 板块** — 将所有涉及运维支持的条目合并为一个板块,标题为 `【运维支持】`,且**不需要工作总结**。每条条目末尾标注负责人及状态,格式如 `(XX-已完成)`、`(XX-进行中)`。
​
#### 2.2 整理条目
- 检查语言表达是否简洁明了
- 统一句式:以动词开头,简洁客观
- 去除冗余、重复内容
- 保持每条 1-2 句话,突出成果
- 按重要性排序
- **分类标题(如 `【功能开发】`)仅在用户输入中已明确提供时原样保留,禁止主动添加**。用户未提供分类标题时,直接使用数字列表列出条目,不得自行归类捏造标题
​
#### 2.3 处理工作总结
- **用户已提供** `工作总结:` → 保留并优化语言表达,使其精炼、突出核心价值
- **用户未提供** → AI 根据该块条目自动生成一段工作总结,以 `工作总结:` 开头
​
### 3. 输出格式
​
参考示例 docx,将输入转换为以下结构:
​
YYYYMMDD工作情况
​
【项目名】-姓名
【分类标题】(可选:仅当用户输入中已提供时保留,不主动添加)
1. 完成事项描述(以动词开头,简洁客观)
...
工作总结:用一段话汇总该人本周核心成果,突出价值
​
​
- **板块排序**:按固定顺序排列,`【运维支持】` 固定在最后(具体项目名已打码):
  1. 【主产品 A】 2. 【主产品 B】 3. 【子产品 C】 4. 【子产品 D】 5. 【智能体 E】 6. 【应用服务 F】 7. 其他未在上述列表中的板块(按原顺序) 8. 【运维支持】(始终最后)
- **条目语言风格**:简洁客观,以「动词 + 事项 + 结果/状态」结构为主
- **不含「下周计划」板块**
​
### 4. 生成 Word 文档
​
运行 `script/generate_weekly_report.py` 使用 `python-docx` 生成 `.docx` 文件,保存到项目 `output/` 文件夹下,文件命名格式:`周报_YYYY-MM-DD.docx`。
​
## 输出规则
1. 每条条目控制在 1-2 句话,以动词开头,突出做了什么、结果如何
2. 按人/项目维度组织(`【项目名】-姓名`),项目内按重要性排序
3. 语言简洁、客观,避免主观评价
4. 每人板块内先列详细条目(数字列表),再附一段工作总结
5. **工作总结处理规则**:用户已提供 → 保留并优化;用户未提供 → AI 自动生成,确保概括准确、不编造内容。**例外:`【运维支持】` 板块不需要工作总结**
6. **`【运维支持】` 板块合并规则**:所有涉及运维支持的条目合并为一个板块,标题为 `【运维支持】`,不需要工作总结。每条条目末尾标注负责人及状态

B. generate_weekly_report.py(Word 生成脚本)

"""Generate a weekly summary Word document matching SKILL.md format."""
​
import sys
import json
from pathlib import Path
from docx import Document
from docx.shared import Pt, Cm, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
​
​
def generate_report(data: dict, output_path: str):
    doc = Document()
​
    for section in doc.sections:
        section.top_margin = Cm(2.5)
        section.bottom_margin = Cm(2.5)
        section.left_margin = Cm(2.5)
        section.right_margin = Cm(2.5)
​
    # Title: YYYYMMDD工作情况
    date_str = data.get('date', '').replace('-', '')
    title_text = f'{date_str}工作情况'
    title = doc.add_heading(title_text, level=0)
    title.alignment = WD_ALIGN_PARAGRAPH.CENTER
​
    doc.add_paragraph()
​
    blocks = data.get('blocks', [])
    for block in blocks:
        # 【项目名】-姓名
        heading = doc.add_heading(block['heading'], level=2)
​
        # Multiple category groups if present
        groups = block.get('groups')
        if groups:
            for group in groups:
                cat = group.get('category')
                if cat:
                    cat_para = doc.add_paragraph()
                    run = cat_para.add_run(cat)
                    run.bold = True
                    run.font.size = Pt(11)
                g_items = group.get('items', [])
                for i, item in enumerate(g_items, 1):
                    p = doc.add_paragraph()
                    p.paragraph_format.left_indent = Cm(0.75)
                    p.paragraph_format.first_line_indent = Cm(-0.75)
                    run = p.add_run(f'{i}. {item}')
                    run.font.size = Pt(11)
        else:
            # Single category if present
            category = block.get('category')
            if category:
                cat_para = doc.add_paragraph()
                run = cat_para.add_run(category)
                run.bold = True
                run.font.size = Pt(11)
​
            # Items (numbered list)
            items = block.get('items', [])
            for i, item in enumerate(items, 1):
                p = doc.add_paragraph()
                p.paragraph_format.left_indent = Cm(0.75)
                p.paragraph_format.first_line_indent = Cm(-0.75)
                run = p.add_run(f'{i}. {item}')
                run.font.size = Pt(11)
​
        # Summary
        summary = block.get('summary', '')
        if summary:
            p = doc.add_paragraph()
            run = p.add_run(f'工作总结:{summary}')
            run.font.size = Pt(11)
            run.italic = True
​
        doc.add_paragraph()
​
    # Footer
    footer_para = doc.add_paragraph()
    footer_para.alignment = WD_ALIGN_PARAGRAPH.RIGHT
    run = footer_para.add_run('— 【某研发团队】 —')
    run.font.size = Pt(9)
    run.font.color.rgb = RGBColor(0x99, 0x99, 0x99)
​
    doc.save(output_path)
    return output_path
​
​
def main():
    if len(sys.argv) < 2:
        print('Usage: generate_weekly_report.py <json_data_or_file> [output_path]')
        sys.exit(1)
​
    input_data = sys.argv[1]
​
    data_path = Path(input_data)
    if data_path.exists():
        raw = data_path.read_bytes()
        if raw.startswith(b'\xef\xbb\xbf'):
            raw = raw[3:]
        data = json.loads(raw.decode('utf-8'))
    else:
        data = json.loads(input_data)
​
    if len(sys.argv) >= 3:
        output_path = sys.argv[2]
    else:
        output_dir = Path(__file__).resolve().parent.parent / 'output'
        output_dir.mkdir(parents=True, exist_ok=True)
        import datetime
        today = datetime.date.today().strftime('%Y-%m-%d')
        output_path = str(output_dir / f'周报_{today}.docx')
​
    result = generate_report(data, output_path)
    print(f'Word 文档已生成:{result}')
​
​
if __name__ == '__main__':
    main()

脚本接收参数:python generate_weekly_report.py <json数据或文件> [输出路径]。不传输出路径时,默认生成到项目 output/周报_YYYY-MM-DD.docx。AI 端把整理好的 blocks(含 heading、category/groups、items、summary 字段)序列化成这份 JSON 喂给脚本即可。

踩坑与解决

1. AI 自作主张给条目编分类标题

  • 问题:输出里凭空出现 【功能开发】、【线上运维】 这类用户没给的分类标题。

  • 复现:用户输入只有 项目-姓名\n1. 上线XX功能,不写任何分类,输出却自动分了类。

  • 根因:规则没说明白"分类标题默认不加"。AI 看到示例文档里有分类标题,就学样添油加醋。

  • 解决:规则里显式写死"分类标题仅在用户输入中已明确提供时原样保留,禁止主动添加;用户未提供时直接用数字列表,不得自行归类捏造标题"。把"禁止项"写进规则。

  • 验证:不提供分类的输入跑一遍,输出里不再有多余标题。给 AI 立边界,防它发挥。

2. 运维板块的性质从一开始就没说清

  • 问题:【运维支持】 板块时而被合并、时而没合并,有时还带工作总结。

  • 复现:多次生成同一份周报,运维板块的处理不稳定。

  • 根因:这类"特例板块"的特殊性(要合并、每条约负责人、不要总结)散落在规则各处,没有集中表述,AI 记不全。

  • 解决:把特例板块的所有特殊处理集中成一条规则(所有涉及运维支持的条目合并为一个板块,标题固定为X,不写工作总结,每条末尾标注负责人及状态),并放到"输出规则"小节里单独列一条,不再分散。

  • 验证:特例板块的处理在多次生成中保持一致。规则要内聚,一条规则管一件事。

3. 同人在多个项目,被 AI 自作主张"按人并块"

  • 问题:同一个人在不同项目下的条目被 AI 合并成一个板块。

  • 复现:输入按 项目-人 分了四块,输出却按"人"归并成两块。

  • 根因:AI 默认"按人汇总"更合理,但项目方的需求恰恰是"按项目块";没有成文约定,AI 按自己的直觉来。

  • 解决:明写"每个 项目名-姓名 视为独立块,不合并同人不同项目的条目"。

  • 验证:确认输出块数 = 输入块数。你的排序逻辑要写进规则,AI 才不会自作聪明。

4. 格式稳定但内容漂移:只靠 prompt 不够

  • 问题:AI 每次生成的措辞差异大,交付要求严格的场景(如对外周报)难以接受。

  • 复现:同一份输入连跑三次,条目句式、详略不一致。

  • 根因:prompt 只约束了"结构",没有约束"语言模板";且没有给足"参考例句"。

  • 解决:在规则里给出明确的语言模板(动词 + 事项 + 结果/状态),并放 1-2 条示例条目供对照;同时用示例 Word 文档作为"目标产物"让 AI 对齐。

  • 验证:多次生成的句式、结构趋于一致。稳定输出靠两样:语言模板 + 目标样例。

5. Word 生成脚本跟内容"两层皮"

  • 问题:AI 改规则后,脚本读不懂新结构,或脚本字段变了 AI 不认。

  • 复现:给 block 增加了一个 category 分组字段,脚本没跟上,分类标题打印不出来。

  • 根因:AI 端(prompt 里的 JSON 约定)和脚本端(字段解析)没有统一契约,两边各自演进。

  • 解决:把 JSON 结构定义成 AI 和脚本共同遵守的契约,脚本对这契约做宽容解析(block.get('groups')、block.get('category') 这类"缺省即空"的写法),并给脚本留默认输出路径。

  • 验证:新增可选字段后,旧输入仍能正常出文档。接口层做宽容,缺字段不崩,是两边解耦的关键。

小结与参考

  • 一个"整理类" skill 的四件套:输入结构(贴近人)→ 处理规则(显式化)→ 总结模板(不编造)→ 脚本排版(管格式)。

  • 三个最容易踩的坑,本质都是同一条:AI 有它自己的"合理直觉",你不显式下边界,它就会自作主张。所以规则里要写"禁止项"、把特例集中、用语言模板和参考样例给它稳定输出。

  • AI 与脚本的分工边界:AI 管内容成结构,脚本管格式成文档。两边用一份 JSON 契约沟通,缺字段宽容处理。

  • 这套骨架可以迁移到任何"零散条目 → 规范文档"的场景:日报、会议纪要、需求验收清单、实验记录。换掉输入字段和规则,换掉目标文档模板,方法不变。

参考:

  • 需求管理方法:先把"输入/规则/模板/脚本"四个格子填满,再动手写 prompt

本文拆解的 skill 为团队内部定制。上面的 rules 与脚本已按"原文贴入 + 敏感信息打码"处理:具体项目名、板块名、姓名与团队署名均已替换为占位符;骨架与实现细节保留。请结合你自己的业务约束改造。

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或者给予支持!

AI 自动整理周报并生成 Word:自研周报总结 skill 拆解
/archives/ai-zi-dong-zheng-li-zhou-bao-bing-sheng-cheng-word-zi-yan-zhou-bao-zong-jie-skill-chai-jie
作者
隔壁老陈
发布于
2026-10-27
许可协议
CC BY-NC-SA 4.0

评论