📌 内容摘要

  • 技术文档是开发中最容易被忽视、最耗时的工作——用 Claude API 可以把这部分工作自动化 80% 以上。
  • 本文覆盖5类文档的自动生成:API 接口文档、代码注释、README、更新日志(CHANGELOG)、错误码说明。
  • 所有代码示例均可直接运行,含 Git 提交自动触发、GitHub Actions 集成两种 CI/CD 方案。
  • 附文档质量评估提示词:让 Claude 检查自己生成的文档是否合格。

一、为什么要用 AI 自动生成技术文档?

技术文档的现实处境很尴尬:写的人嫌烦,读的人嫌少,更新的人更是凤毛麟角。调查显示,超过 60% 的开发者承认自己项目的文档已经过时超过3个月。

Claude API 在这个场景里有天然优势:它能读懂代码的意图,理解参数含义,识别边界条件,并用清晰的自然语言表达出来。配合 Git hooks 或 CI/CD 流水线,每次代码提交都可以自动触发文档更新——让文档和代码真正同步。

文档类型 手动耗时 自动化后 节省
API 接口文档 30-60分钟/接口 10-30秒/接口 ~98%
代码注释 10-20分钟/函数 5-15秒/函数 ~95%
README 2-4小时 1-2分钟 ~95%
CHANGELOG 20-40分钟/版本 30秒/版本 ~95%

二、环境准备

pip install anthropic python-dotenv gitpython ast
# .env
ANTHROPIC_API_KEY=sk-ant-api03-你的key

三、场景一:自动生成 API 接口文档

把 Python 函数、TypeScript 接口或 OpenAPI 路由传给 Claude,自动生成结构化的接口文档:

import anthropic
import ast
import inspect
from pathlib import Path

client = anthropic.Anthropic()

API_DOC_SYSTEM = """你是一名技术文档工程师,专门为 API 接口编写清晰的文档。
文档规范:
- 使用 Markdown 格式
- 包含:功能描述、参数说明(类型/是否必填/默认值)、返回值、异常情况、代码示例
- 语言简洁专业,面向使用该 API 的开发者
- 代码示例使用实际可运行的代码,不用伪代码"""

def generate_function_doc(func_source: str, context: str = "") -> str:
    """为单个函数生成文档"""
    prompt = f"""请为以下函数生成完整的 API 文档:
```python
{func_source}
```

{f'项目背景:{context}' if context else ''}

按以下结构输出:
## 函数名

**功能描述**:一句话说明

**参数**

| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|

**返回值**

**异常**

**示例**
```python
# 使用示例
```
"""
    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=2048,
        system=API_DOC_SYSTEM,
        messages=[{"role": "user", "content": prompt}]
    )
    return response.content[0].text


def generate_module_docs(file_path: str, output_path: str = None) -> str:
    """为整个 Python 模块生成文档"""
    source = Path(file_path).read_text(encoding="utf-8")

    # 解析 AST 提取函数和类
    tree = ast.parse(source)
    functions = [n for n in ast.walk(tree) if isinstance(n, (ast.FunctionDef, ast.AsyncFunctionDef))]
    classes = [n for n in ast.walk(tree) if isinstance(n, ast.ClassDef)]

    print(f"发现 {len(functions)} 个函数,{len(classes)} 个类")

    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=8192,
        system=API_DOC_SYSTEM,
        messages=[{
            "role": "user",
            "content": f"""为以下 Python 模块生成完整的 API 文档:

文件:{file_path}
```python
{source}
```

请按模块→类→方法→函数的层次结构组织文档,每个公开接口都要有完整说明。
在文档开头加上模块概述和快速上手示例。"""
        }]
    )

    doc = response.content[0].text

    if output_path:
        Path(output_path).write_text(doc, encoding="utf-8")
        print(f"文档已保存到:{output_path}")

    return doc


# 使用示例
doc = generate_module_docs("src/payment.py", "docs/payment_api.md")

四、场景二:自动添加代码注释

import re

COMMENT_SYSTEM = """你是一名代码注释专家。
注释规范:
- Python 函数使用 Google Style Docstring
- 注释解释"为什么"而不仅仅是"是什么"
- 复杂逻辑需要行内注释
- 不要注释显而易见的代码
- 保持原有代码格式不变,只添加注释"""

def add_docstrings_to_file(file_path: str, backup: bool = True) -> str:
    """为 Python 文件中所有缺少 docstring 的函数添加注释"""

    source = Path(file_path).read_text(encoding="utf-8")

    # 备份原文件
    if backup:
        backup_path = file_path + ".backup"
        Path(backup_path).write_text(source, encoding="utf-8")
        print(f"原文件已备份到:{backup_path}")

    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=8192,
        system=COMMENT_SYSTEM,
        messages=[{
            "role": "user",
            "content": f"""为以下 Python 代码补充完整的 docstring 和必要的行内注释。
要求:
1. 只为缺少 docstring 的函数/方法/类添加注释
2. 已有注释的保持不变
3. 返回完整的修改后代码,不要省略任何部分
4. 不要修改任何逻辑代码
```python
{source}
```

直接返回修改后的完整代码,不要加 markdown 代码块标记。"""
        }]
    )

    annotated_source = response.content[0].text

    # 去除可能的 markdown 标记
    if annotated_source.startswith("```"):
        lines = annotated_source.split("\n")
        annotated_source = "\n".join(lines[1:-1])

    Path(file_path).write_text(annotated_source, encoding="utf-8")
    print(f"注释已添加到:{file_path}")
    return annotated_source


def add_comments_to_complex_functions(
    file_path: str,
    min_lines: int = 20
) -> str:
    """只为超过指定行数的复杂函数添加详细注释"""

    source = Path(file_path).read_text(encoding="utf-8")
    tree = ast.parse(source)
    source_lines = source.splitlines()

    complex_functions = []
    for node in ast.walk(tree):
        if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
            func_lines = node.end_lineno - node.lineno
            if func_lines >= min_lines:
                func_source = "\n".join(
                    source_lines[node.lineno - 1:node.end_lineno]
                )
                complex_functions.append({
                    "name": node.name,
                    "source": func_source,
                    "lines": func_lines
                })

    print(f"发现 {len(complex_functions)} 个复杂函数(≥{min_lines}行)")

    for func in complex_functions:
        print(f"\n正在为 {func['name']} ({func['lines']}行) 生成注释...")
        response = client.messages.create(
            model="claude-sonnet-4-6",
            max_tokens=2048,
            system=COMMENT_SYSTEM,
            messages=[{
                "role": "user",
                "content": f"为这个复杂函数添加详细的行内注释,解释关键逻辑步骤:\n\n{func['source']}"
            }]
        )
        print(response.content[0].text)

五、场景三:自动生成 README

import json

README_SYSTEM = """你是一名开源项目维护者,擅长编写吸引开发者的 README 文档。
README 规范:
- 开头用一句话说明项目是什么
- 包含徽章(badges)占位符
- 快速上手示例放在前面,详细配置放后面
- 语言简洁,减少废话,让开发者30秒内看懂项目价值"""

def generate_readme(project_dir: str) -> str:
    """扫描项目目录,自动生成 README"""

    project_path = Path(project_dir)

    # 收集项目信息
    info = {
        "name": project_path.name,
        "files": [],
        "main_code": "",
        "dependencies": "",
        "existing_readme": ""
    }

    # 读取主要代码文件(最多3个)
    code_files = list(project_path.glob("*.py"))[:3]
    code_snippets = []
    for f in code_files:
        content = f.read_text(encoding="utf-8", errors="ignore")
        code_snippets.append(f"### {f.name}\n```python\n{content[:2000]}\n```")
    info["main_code"] = "\n\n".join(code_snippets)

    # 读取依赖文件
    for dep_file in ["requirements.txt", "pyproject.toml", "package.json"]:
        dep_path = project_path / dep_file
        if dep_path.exists():
            info["dependencies"] = dep_path.read_text(encoding="utf-8")
            break

    # 读取现有 README(如果有)
    for readme_name in ["README.md", "README.txt", "readme.md"]:
        readme_path = project_path / readme_name
        if readme_path.exists():
            info["existing_readme"] = readme_path.read_text(encoding="utf-8")
            break

    # 获取目录结构
    info["files"] = [
        str(f.relative_to(project_path))
        for f in project_path.rglob("*")
        if f.is_file()
        and not any(p in f.parts for p in [".git", "__pycache__", "node_modules", ".venv"])
    ][:30]  # 最多显示30个文件

    prompt = f"""根据以下项目信息,生成一份专业的 README.md:

**项目名称**:{info['name']}

**项目文件结构**:
{chr(10).join(info['files'])}

**主要代码**:
{info['main_code']}

**依赖配置**:
{info['dependencies'] or '未找到依赖文件'}

{f"**现有 README(供参考)**:{info['existing_readme']}" if info['existing_readme'] else ''}

README 结构要求:
# 项目名 + 一句话描述
[徽章占位符]
## ✨ 特性
## 🚀 快速开始(安装 + 最简示例)
## 📖 使用说明
## ⚙️ 配置项
## 🤝 贡献指南
## 📄 许可证"""

    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=4096,
        system=README_SYSTEM,
        messages=[{"role": "user", "content": prompt}]
    )

    readme_content = response.content[0].text
    output_path = project_path / "README.md"
    output_path.write_text(readme_content, encoding="utf-8")
    print(f"README 已生成:{output_path}")
    return readme_content

六、场景四:从 Git 提交记录生成 CHANGELOG

import git
from datetime import datetime

CHANGELOG_SYSTEM = """你是一名技术写作专家,专门将 Git 提交记录整理成用户友好的更新日志。
CHANGELOG 规范(遵循 Keep a Changelog 格式):
- 按版本号倒序排列
- 每个版本分类:Added / Changed / Fixed / Removed / Security
- 面向用户而非开发者,避免内部术语
- 合并相关的小提交,突出重要变更"""

def generate_changelog(
    repo_path: str = ".",
    version: str = None,
    since_tag: str = None,
    max_commits: int = 50
) -> str:
    """从 Git 历史生成 CHANGELOG"""

    repo = git.Repo(repo_path)
    version = version or f"v{datetime.now().strftime('%Y.%m.%d')}"

    # 获取提交记录
    if since_tag:
        commits = list(repo.iter_commits(f"{since_tag}..HEAD", max_count=max_commits))
    else:
        commits = list(repo.iter_commits("HEAD", max_count=max_commits))

    if not commits:
        print("没有找到新的提交记录")
        return ""

    # 格式化提交记录
    commit_log = []
    for commit in commits:
        commit_log.append(
            f"- [{commit.hexsha[:7]}] {commit.message.strip()} "
            f"({commit.author.name}, {datetime.fromtimestamp(commit.committed_date).strftime('%Y-%m-%d')})"
        )

    commits_text = "\n".join(commit_log)
    print(f"处理 {len(commits)} 条提交记录...")

    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=2048,
        system=CHANGELOG_SYSTEM,
        messages=[{
            "role": "user",
            "content": f"""将以下 Git 提交记录整理为 {version} 版本的 CHANGELOG:

提交记录:
{commits_text}

输出格式:
## [{version}] - {datetime.now().strftime('%Y-%m-%d')}

### Added
- ...

### Changed
- ...

### Fixed
- ...

只输出本次版本的 CHANGELOG 内容,不需要其他说明。"""
        }]
    )

    changelog_entry = response.content[0].text

    # 追加到现有 CHANGELOG.md
    changelog_path = Path(repo_path) / "CHANGELOG.md"
    if changelog_path.exists():
        existing = changelog_path.read_text(encoding="utf-8")
        # 在文件开头插入新版本
        if "# Changelog" in existing:
            new_content = existing.replace(
                "# Changelog\n",
                f"# Changelog\n\n{changelog_entry}\n"
            )
        else:
            new_content = f"# Changelog\n\n{changelog_entry}\n\n{existing}"
    else:
        new_content = f"# Changelog\n\n{changelog_entry}\n"

    changelog_path.write_text(new_content, encoding="utf-8")
    print(f"CHANGELOG 已更新:{changelog_path}")
    return changelog_entry

七、场景五:自动生成错误码文档

import re

def generate_error_code_docs(source_files: list[str]) -> str:
    """扫描代码中的错误码定义,生成错误码文档"""

    # 收集所有错误码相关代码
    error_patterns = [
        r'raise\s+\w+Error\([^)]+\)',    # raise 语句
        r'ERROR_\w+\s*=\s*["\']?\w+',   # 错误码常量
        r'class\s+\w+Error\(',           # 自定义异常类
        r'status_code\s*=\s*\d{3}',     # HTTP 状态码
    ]

    collected = []
    for file_path in source_files:
        try:
            source = Path(file_path).read_text(encoding="utf-8")
            matches = []
            for pattern in error_patterns:
                matches.extend(re.findall(pattern, source))
            if matches:
                collected.append(f"### {file_path}\n" + "\n".join(matches[:20]))
        except Exception:
            continue

    if not collected:
        print("未找到错误码相关代码")
        return ""

    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=3000,
        system="你是一名技术文档工程师,专门整理 API 错误码文档。",
        messages=[{
            "role": "user",
            "content": f"""根据以下代码中的错误处理逻辑,生成完整的错误码文档:

{chr(10).join(collected)}

文档格式:
## 错误码说明

| 错误码 | HTTP状态码 | 说明 | 常见原因 | 解决方案 |
|--------|-----------|------|----------|----------|

每个错误码都要包含用户友好的说明和具体的解决建议。"""
        }]
    )

    error_doc = response.content[0].text
    Path("docs/error_codes.md").write_text(error_doc, encoding="utf-8")
    print("错误码文档已生成:docs/error_codes.md")
    return error_doc

八、文档质量自动评估

def evaluate_doc_quality(doc_content: str, doc_type: str = "API文档") -> dict:
    """让 Claude 评估生成文档的质量"""

    response = client.messages.create(
        model="claude-haiku-4-5-20251001",  # 评估用 Haiku 省成本
        max_tokens=1024,
        messages=[{
            "role": "user",
            "content": f"""评估以下{doc_type}的质量,以 JSON 格式返回:

文档内容:
{doc_content[:3000]}

评估维度(每项0-10分):
{{
  "completeness": {{
    "score": 分数,
    "issues": ["缺少的内容"]
  }},
  "clarity": {{
    "score": 分数,
    "issues": ["不够清晰的地方"]
  }},
  "examples": {{
    "score": 分数,
    "issues": ["示例的问题"]
  }},
  "accuracy": {{
    "score": 分数,
    "issues": ["可能的准确性问题"]
  }},
  "overall_score": 总分(0-10),
  "priority_improvements": ["最需要改进的3点"]
}}

只返回 JSON,不要其他内容。"""
        }]
    )

    import json
    text = response.content[0].text.strip()
    if text.startswith("```"):
        text = "\n".join(text.split("\n")[1:-1])
    return json.loads(text)


def generate_and_validate(func_source: str) -> str:
    """生成文档并自动验证质量,不合格则重新生成"""

    for attempt in range(3):
        doc = generate_function_doc(func_source)
        quality = evaluate_doc_quality(doc, "函数文档")

        print(f"第{attempt+1}次生成,质量评分:{quality['overall_score']}/10")

        if quality["overall_score"] >= 7:
            print("✅ 文档质量达标")
            return doc

        # 质量不达标,带着改进意见重新生成
        improvements = "\n".join(quality["priority_improvements"])
        print(f"⚠️  需要改进:\n{improvements}")

        func_source = f"""请改进以下函数的文档,重点改进:
{improvements}

函数代码:
{func_source}

上次生成的文档(需要改进):
{doc}"""

    return doc  # 3次后返回最后一次结果

九、CI/CD 集成:GitHub Actions 自动更新文档

# .github/workflows/auto-docs.yml
name: Auto Generate Docs

on:
  push:
    branches: [main]
    paths:
      - 'src/**/*.py'      # 只在源码变更时触发
      - 'src/**/*.ts'

jobs:
  generate-docs:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0    # 获取完整历史,用于 CHANGELOG

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install dependencies
        run: pip install anthropic gitpython pymupdf

      - name: Generate documentation
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        run: |
          python scripts/generate_docs.py \
            --source src/ \
            --output docs/ \
            --changelog \
            --readme

      - name: Commit and push docs
        run: |
          git config --local user.email "action@github.com"
          git config --local user.name "GitHub Action"
          git add docs/ README.md CHANGELOG.md
          git diff --staged --quiet || git commit -m "docs: auto-update documentation [skip ci]"
          git push

配套的 generate_docs.py 脚本

#!/usr/bin/env python3
"""CI/CD 文档自动生成入口脚本"""

import argparse
from pathlib import Path

def main():
    parser = argparse.ArgumentParser(description="自动生成技术文档")
    parser.add_argument("--source", default="src/", help="源码目录")
    parser.add_argument("--output", default="docs/", help="文档输出目录")
    parser.add_argument("--changelog", action="store_true", help="生成 CHANGELOG")
    parser.add_argument("--readme",    action="store_true", help="更新 README")
    parser.add_argument("--since-tag", help="从指定 tag 开始的提交")
    args = parser.parse_args()

    Path(args.output).mkdir(parents=True, exist_ok=True)
    source_files = list(Path(args.source).rglob("*.py"))
    print(f"找到 {len(source_files)} 个 Python 文件")

    # 生成各模块 API 文档
    for py_file in source_files:
        if py_file.name.startswith("_"):
            continue  # 跳过私有模块
        output_file = Path(args.output) / py_file.with_suffix(".md").name
        generate_module_docs(str(py_file), str(output_file))
        print(f"✅ {py_file.name} → {output_file.name}")

    if args.changelog:
        generate_changelog(since_tag=args.since_tag)
        print("✅ CHANGELOG 已更新")

    if args.readme:
        generate_readme(".")
        print("✅ README 已更新")

if __name__ == "__main__":
    main()

十、成本与效果评估

以一个中型 Python 项目(20个模块,共5000行代码)为例:

任务 预计 token 消耗 费用(Sonnet 4.6) 耗时
20个模块 API 文档 约 60万 token 约 $2.7 约5分钟
全项目代码注释 约 80万 token 约 $3.6 约8分钟
README 生成 约 2万 token 约 $0.09 约30秒
CHANGELOG(50次提交) 约 1万 token 约 $0.045 约15秒

一次性为整个项目补全文档约需 $6-7,之后每次提交触发的增量更新不超过 $0.1——对比工程师手动写文档的时间成本,ROI 极高。

常见问题

Q:生成的文档准确性有保障吗?
Claude 基于代码本身生成文档,准确性很高,但复杂的业务逻辑可能需要人工补充上下文背景。建议用本文的”文档质量评估”功能做自动检查,评分低于7分的文档进入人工审核队列。

Q:如果代码逻辑本身有问题,文档会”美化”它吗?
不会。Claude 会如实描述代码的行为,并在发现潜在问题时主动标注(如果 System Prompt 要求的话)。可以在 System Prompt 中加入”如果发现代码潜在问题,在文档中用⚠️标注”来开启这个能力。

Q:支持哪些编程语言?
Claude 支持所有主流编程语言。本文示例以 Python 为主,换成 TypeScript、Go、Java、Rust 只需修改解析逻辑和代码块语言标记,提示词框架完全通用。

总结

技术文档自动化的核心思路是:用 Claude 读懂代码意图 → 生成结构化文档 → CI/CD 触发保持同步 → 质量评估兜底。五个场景(API 文档、注释、README、CHANGELOG、错误码)覆盖了日常开发文档工作的绝大部分。一次性投入搭建这套流水线,之后每次代码提交都会自动产出高质量文档,技术债不再积累。