自动化提效:用 AI 批量生成技术文档

一、技术文档的痛点

1.1 现实情况

文档类型 平均耗时 痛点
API 文档 4-8 小时 接口多、参数复杂、易过时
代码注释 2-4 小时 重复劳动、容易遗漏
README 2-3 小时 结构难设计、内容难组织
技术方案 8-16 小时 调研耗时、画图费时
测试文档 4-6 小时 用例繁琐、覆盖难全

总计: 一个项目文档时间 ≈ 开发时间的 30-50%

1.2 AI 能做什么

  • API 文档 - 从代码自动生成
  • 代码注释 - 理解逻辑后生成
  • README - 根据项目结构生成
  • 技术方案 - 提供框架和初稿
  • 测试用例 - 根据功能生成边界场景

二、API 文档自动生成

2.1 从代码生成 OpenAPI 规范

工具: Swagger + AI 增强

// scripts/generate-openapi.js
const fs = require('fs');
const path = require('path');
const { OpenAI } = require('openai');

class ApiDocGenerator {
  constructor() {
    this.openai = new OpenAI({
      apiKey: process.env.OPENAI_API_KEY,
    });
  }

  /**
   * 扫描路由文件
   */
  async scanRoutes(routeDir) {
    const routes = [];
    const files = fs.readdirSync(routeDir);
    
    for (const file of files) {
      const filePath = path.join(routeDir, file);
      const stat = fs.statSync(filePath);
      
      if (stat.isDirectory()) {
        routes.push(...await this.scanRoutes(filePath));
      } else if (file.endsWith('.ts') || file.endsWith('.js')) {
        const content = fs.readFileSync(filePath, 'utf8');
        const routeInfo = this.extractRoutes(content, file);
        routes.push(...routeInfo);
      }
    }
    
    return routes;
  }

  /**
   * 提取路由信息
   */
  extractRoutes(content, filename) {
    const routes = [];
    
    // 匹配 Express 路由定义
    const routeRegex = /app\.(get|post|put|delete|patch)\(['"`](.*?)['"`]/g;
    let match;
    
    while ((match = routeRegex.exec(content)) !== null) {
      routes.push({
        method: match[1].toUpperCase(),
        path: match[2],
        file: filename,
      });
    }
    
    return routes;
  }

  /**
   * 使用 AI 生成详细文档
   */
  async enrichWithAI(routes) {
    const enriched = [];
    
    for (const route of routes) {
      const response = await this.openai.chat.completions.create({
        model: 'gpt-4',
        messages: [
          {
            role: 'system',
            content: `你是 API 文档专家。根据路由信息生成详细的 API 文档。
            输出 JSON 格式,包含:
            - summary: 接口简介(一句话)
            - description: 详细描述
            - tags: 标签数组
            - parameters: 参数列表(name, in, required, type, description)
            - requestBody: 请求体 schema(如果是 POST/PUT)
            - responses: 响应示例(200, 400, 401, 500)`
          },
          {
            role: 'user',
            content: `路由:${route.method} ${route.path}
            文件:${route.file}`
          }
        ],
        response_format: { type: 'json_object' },
      });
      
      const doc = JSON.parse(response.choices[0].message.content);
      enriched.push({ ...route, ...doc });
    }
    
    return enriched;
  }

  /**
   * 生成 OpenAPI 规范
   */
  generateOpenAPISpec(routes) {
    const spec = {
      openapi: '3.0.0',
      info: {
        title: 'API Documentation',
        version: '1.0.0',
        description: 'Automatically generated API documentation',
      },
      servers: [
        {
          url: 'http://localhost:3000',
          description: 'Development server',
        },
      ],
      paths: {},
    };
    
    for (const route of routes) {
      const pathKey = route.path;
      const method = route.method.toLowerCase();
      
      spec.paths[pathKey] = {
        [method]: {
          summary: route.summary,
          description: route.description,
          tags: route.tags,
          parameters: route.parameters || [],
          requestBody: route.requestBody,
          responses: route.responses,
        },
      };
    }
    
    return spec;
  }

  /**
   * 生成 HTML 文档
   */
  async generateHTML(spec, outputDir) {
    // 使用 Redoc 或 Swagger UI
    const html = `
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>API Documentation</title>
    <script src="https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js"></script>
  </head>
  <body>
    <redoc spec-url='spec.json'></redoc>
    <script>
      const spec = ${JSON.stringify(spec)};
      Redoc.init(spec, {}, document.getElementById('redoc-container'));
    </script>
    <div id="redoc-container"></div>
  </body>
</html>
    `;
    
    fs.writeFileSync(path.join(outputDir, 'index.html'), html);
    fs.writeFileSync(path.join(outputDir, 'spec.json'), JSON.stringify(spec, null, 2));
  }

  /**
   * 主流程
   */
  async generate(routeDir, outputDir) {
    console.log('🔍 扫描路由文件...');
    const routes = await this.scanRoutes(routeDir);
    console.log(`发现 ${routes.length} 个路由`);
    
    console.log('🤖 AI 增强文档...');
    const enriched = await this.enrichWithAI(routes);
    
    console.log('📝 生成 OpenAPI 规范...');
    const spec = this.generateOpenAPISpec(enriched);
    
    console.log('📄 生成 HTML 文档...');
    await this.generateHTML(spec, outputDir);
    
    console.log('✅ 文档生成完成!');
  }
}

// 使用示例
const generator = new ApiDocGenerator();
generator.generate('./src/routes', './docs/api');

2.2 运行脚本

# 安装依赖
npm install openai

# 运行生成
node scripts/generate-openapi.js

# 查看结果
open docs/api/index.html

2.3 集成到 CI/CD

# .github/workflows/api-docs.yml
name: Generate API Docs

on:
  push:
    branches: [main]
    paths: ['src/routes/**']

jobs:
  generate-docs:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
      
      - name: Install dependencies
        run: npm install
      
      - name: Generate API Docs
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
        run: node scripts/generate-openapi.js
      
      - name: Deploy to GitHub Pages
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./docs/api

三、代码注释自动生成

3.1 TypeScript 注释生成

// scripts/generate-comments.js
const fs = require('fs');
const path = require('path');
const ts = require('typescript');
const { OpenAI } = require('openai');

class CommentGenerator {
  constructor() {
    this.openai = new OpenAI({
      apiKey: process.env.OPENAI_API_KEY,
    });
  }

  /**
   * 处理单个文件
   */
  async processFile(filePath) {
    const content = fs.readFileSync(filePath, 'utf8');
    
    // 解析 TypeScript AST
    const sourceFile = ts.createSourceFile(
      filePath,
      content,
      ts.ScriptTarget.Latest,
      true
    );
    
    // 提取函数和类
    const items = this.extractItems(sourceFile);
    
    // 为每个项目生成注释
    for (const item of items) {
      if (!this.hasComment(content, item.pos)) {
        const comment = await this.generateComment(item, content);
        content = this.insertComment(content, item.pos, comment);
      }
    }
    
    return content;
  }

  /**
   * 提取函数和类
   */
  extractItems(sourceFile) {
    const items = [];
    
    const visit = (node) => {
      if (
        ts.isFunctionDeclaration(node) ||
        ts.isMethodDeclaration(node) ||
        ts.isClassDeclaration(node) ||
        ts.isInterfaceDeclaration(node)
      ) {
        items.push({
          kind: ts.SyntaxKind[node.kind],
          name: node.name?.getText(),
          pos: node.pos,
          end: node.end,
          text: node.getText(),
        });
      }
      
      ts.forEachChild(node, visit);
    };
    
    visit(sourceFile);
    return items;
  }

  /**
   * 生成注释
   */
  async generateComment(item, fileContent) {
    const prompt = `请为以下${item.kind}生成 JSDoc 注释:

${item.text}

注释应包含:
- @description 功能描述
- @param 参数说明(如有)
- @returns 返回值说明(如有)
- @throws 异常说明(如有)

只输出注释部分,不包含代码。`;

    const response = await this.openai.chat.completions.create({
      model: 'gpt-4',
      messages: [
        { role: 'system', content: '你是专业的代码注释生成助手。' },
        { role: 'user', content: prompt },
      ],
      max_tokens: 500,
    });
    
    return response.choices[0].message.content;
  }

  /**
   * 检查是否已有注释
   */
  hasComment(content, pos) {
    // 向前查找,看是否有注释
    const before = content.substring(0, pos);
    const lines = before.split('\n');
    const lastLines = lines.slice(-5);
    
    return lastLines.some(line => 
      line.trim().startsWith('/*') || 
      line.trim().startsWith('*') ||
      line.trim().startsWith('//')
    );
  }

  /**
   * 插入注释
   */
  insertComment(content, pos, comment) {
    const before = content.substring(0, pos);
    const after = content.substring(pos);
    
    // 确保注释格式正确
    const formattedComment = comment.trim();
    
    return before + formattedComment + '\n' + after;
  }

  /**
   * 批量处理
   */
  async processDirectory(dir, outputDir) {
    const files = fs.readdirSync(dir);
    
    for (const file of files) {
      const filePath = path.join(dir, file);
      const stat = fs.statSync(filePath);
      
      if (stat.isDirectory()) {
        await this.processDirectory(filePath, outputDir);
      } else if (file.endsWith('.ts') || file.endsWith('.tsx')) {
        console.log(`处理:${file}`);
        const commented = await this.processFile(filePath);
        
        // 保存到输出目录
        const relativePath = path.relative(dir, filePath);
        const outputPath = path.join(outputDir, relativePath);
        
        fs.mkdirSync(path.dirname(outputPath), { recursive: true });
        fs.writeFileSync(outputPath, commented);
      }
    }
  }
}

// 使用示例
const generator = new CommentGenerator();
generator.processDirectory('./src', './src-commented');

3.2 批量运行

# 安装依赖
npm install typescript openai

# 运行
node scripts/generate-comments.js

# 查看差异
diff -r src src-commented

四、README 自动生成

4.1 项目分析 + AI 生成

// scripts/generate-readme.js
const fs = require('fs');
const path = require('path');
const { OpenAI } = require('openai');

class ReadmeGenerator {
  constructor() {
    this.openai = new OpenAI({
      apiKey: process.env.OPENAI_API_KEY,
    });
  }

  /**
   * 分析项目结构
   */
  analyzeProject(rootDir) {
    const info = {
      name: path.basename(rootDir),
      structure: this.getDirectoryTree(rootDir, 3),
      packageJson: this.readPackageJson(rootDir),
      mainFiles: this.findMainFiles(rootDir),
      dependencies: this.getDependencies(rootDir),
    };
    
    return info;
  }

  /**
   * 获取目录树
   */
  getDirectoryTree(dir, maxDepth = 3, currentDepth = 0) {
    if (currentDepth >= maxDepth) return '';
    
    const items = fs.readdirSync(dir);
    let tree = '';
    
    for (const item of items) {
      if (item.startsWith('.') || item === 'node_modules') continue;
      
      const fullPath = path.join(dir, item);
      const stat = fs.statSync(fullPath);
      const indent = '  '.repeat(currentDepth);
      
      if (stat.isDirectory()) {
        tree += `${indent}📁 ${item}/\n`;
        tree += this.getDirectoryTree(fullPath, maxDepth, currentDepth + 1);
      } else {
        tree += `${indent}📄 ${item}\n`;
      }
    }
    
    return tree;
  }

  /**
   * 读取 package.json
   */
  readPackageJson(dir) {
    const pkgPath = path.join(dir, 'package.json');
    if (fs.existsSync(pkgPath)) {
      return JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
    }
    return null;
  }

  /**
   * 查找主要文件
   */
  findMainFiles(dir) {
    const mains = [];
    const targets = ['index.ts', 'index.js', 'main.ts', 'main.js', 'app.ts', 'app.js'];
    
    for (const target of targets) {
      const fullPath = path.join(dir, target);
      if (fs.existsSync(fullPath)) {
        mains.push(target);
      }
    }
    
    return mains;
  }

  /**
   * 获取依赖列表
   */
  getDependencies(dir) {
    const pkg = this.readPackageJson(dir);
    if (!pkg) return [];
    
    return {
      dependencies: Object.keys(pkg.dependencies || {}),
      devDependencies: Object.keys(pkg.devDependencies || {}),
    };
  }

  /**
   * 生成 README
   */
  async generate(projectInfo) {
    const prompt = `请根据以下项目信息生成一个专业的 README.md:

项目名称:${projectInfo.name}

项目结构:
${projectInfo.structure}

主要文件:${projectInfo.mainFiles.join(', ')}

依赖:
- 生产依赖:${projectInfo.dependencies.dependencies.join(', ')}
- 开发依赖:${projectInfo.dependencies.devDependencies.join(', ')}

package.json 信息:
${JSON.stringify(projectInfo.packageJson, null, 2)}

README 应包含以下部分:
1. 项目简介(一句话)
2. 功能特性(bullet points)
3. 安装步骤
4. 快速开始
5. 使用示例
6. API 文档链接(如有)
7. 贡献指南
8. License

使用 Markdown 格式,适当使用 emoji 增加可读性。`;

    const response = await this.openai.chat.completions.create({
      model: 'gpt-4',
      messages: [
        { role: 'system', content: '你是专业的 README 文档撰写专家。' },
        { role: 'user', content: prompt },
      ],
      max_tokens: 2000,
    });
    
    return response.choices[0].message.content;
  }

  /**
   * 主流程
   */
  async generateReadme(dir, outputFile) {
    console.log('🔍 分析项目...');
    const info = this.analyzeProject(dir);
    
    console.log('🤖 生成 README...');
    const readme = await this.generate(info);
    
    console.log('📄 保存文件...');
    fs.writeFileSync(outputFile || path.join(dir, 'README.md'), readme);
    
    console.log('✅ README 生成完成!');
  }
}

// 使用示例
const generator = new ReadmeGenerator();
generator.generateReadme('./');

4.2 运行

node scripts/generate-readme.js
cat README.md

五、技术方案文档生成

5.1 方案框架生成

// scripts/generate-tech-proposal.js
const { OpenAI } = require('openai');

class TechProposalGenerator {
  constructor() {
    this.openai = new OpenAI({
      apiKey: process.env.OPENAI_API_KEY,
    });
  }

  /**
   * 生成技术方案框架
   */
  async generateFramework(requirements) {
    const prompt = `请根据以下需求生成技术方案文档框架:

需求描述:
${requirements}

技术方案文档应包含:
1. 背景和目标
2. 需求分析
3. 系统架构设计
4. 技术选型及理由
5. 核心模块设计
6. 数据库设计
7. 接口设计
8. 安全设计
9. 性能设计
10. 部署方案
11. 风险评估
12. 时间计划

请为每个章节生成详细的大纲和要点。`;

    const response = await this.openai.chat.completions.create({
      model: 'gpt-4',
      messages: [
        { role: 'system', content: '你是资深技术架构师,擅长编写技术方案。' },
        { role: 'user', content: prompt },
      ],
      max_tokens: 3000,
    });
    
    return response.choices[0].message.content;
  }

  /**
   * 生成架构图描述(可用于 Mermaid)
   */
  async generateArchitectureDiagram(components) {
    const prompt = `请根据以下系统组件生成 Mermaid 格式的架构图:

组件列表:
${components}

输出 Mermaid graphviz 或 flowchart 格式。`;

    const response = await this.openai.chat.completions.create({
      model: 'gpt-4',
      messages: [
        { role: 'system', content: '你是架构图设计专家。' },
        { role: 'user', content: prompt },
      ],
    });
    
    return response.choices[0].message.content;
  }

  /**
   * 生成数据库设计
   */
  async generateDatabaseDesign(requirements) {
    const prompt = `请根据以下需求设计数据库 schema:

需求:${requirements}

输出包含:
1. ER 图(Mermaid 格式)
2. 表结构定义(SQL)
3. 索引设计
4. 关键查询示例`;

    const response = await this.openai.chat.completions.create({
      model: 'gpt-4',
      messages: [
        { role: 'system', content: '你是数据库设计专家。' },
        { role: 'user', content: prompt },
      ],
    });
    
    return response.choices[0].message.content;
  }
}

// 使用示例
async function main() {
  const generator = new TechProposalGenerator();
  
  const requirements = `
  需要开发一个发票核验系统,主要功能:
  1. 用户上传发票图片
  2. 系统调用 OCR 识别发票信息
  3. 调用税务局接口核验真伪
  4. 返回核验结果
  5. 保存核验记录
  
  技术要求:
  - 日处理量 10 万 +
  - 响应时间 < 2 秒
  - 99.9% 可用性
  `;
  
  const framework = await generator.generateFramework(requirements);
  console.log(framework);
}

main();

六、测试用例生成

6.1 单元测试生成

// scripts/generate-tests.js
const fs = require('fs');
const { OpenAI } = require('openai');

class TestGenerator {
  constructor() {
    this.openai = new OpenAI({
      apiKey: process.env.OPENAI_API_KEY,
    });
  }

  /**
   * 生成单元测试
   */
  async generateTests(sourceCode, language = 'javascript') {
    const prompt = `请为以下代码生成完整的单元测试:

代码语言:${language}

源代码:
${sourceCode}

测试要求:
1. 使用 Jest 测试框架
2. 覆盖所有公共函数
3. 包含正常场景和边界场景
4. 包含错误处理测试
5. 测试覆盖率目标 80%+

输出完整的测试文件代码。`;

    const response = await this.openai.chat.completions.create({
      model: 'gpt-4',
      messages: [
        { role: 'system', content: '你是专业的测试工程师。' },
        { role: 'user', content: prompt },
      ],
      max_tokens: 3000,
    });
    
    return response.choices[0].message.content;
  }

  /**
   * 批量生成测试
   */
  async generateTestsForDirectory(srcDir, testDir) {
    const files = fs.readdirSync(srcDir);
    
    for (const file of files) {
      if (file.endsWith('.ts') || file.endsWith('.js')) {
        const sourcePath = path.join(srcDir, file);
        const sourceCode = fs.readFileSync(sourcePath, 'utf8');
        
        console.log(`生成测试:${file}`);
        const testCode = await this.generateTests(sourceCode);
        
        // 保存测试文件
        const testFileName = file.replace(/\.(ts|js)$/, '.test.$1');
        const testPath = path.join(testDir, testFileName);
        
        fs.mkdirSync(testDir, { recursive: true });
        fs.writeFileSync(testPath, testCode);
      }
    }
  }
}

// 使用示例
const generator = new TestGenerator();
generator.generateTestsForDirectory('./src', './tests');

七、文档维护自动化

7.1 文档更新检测

// scripts/doc-sync.js
const { execSync } = require('child_process');

class DocSyncChecker {
  /**
   * 检测代码变更是否影响文档
   */
  checkForDocUpdates() {
    // 获取 git 变更
    const changedFiles = execSync('git diff --name-only HEAD~1')
      .toString()
      .split('\n')
      .filter(f => f.trim());
    
    const apiFiles = changedFiles.filter(f => f.includes('/routes/') || f.includes('/controllers/'));
    
    if (apiFiles.length > 0) {
      console.log('⚠️  检测到 API 变更,需要更新文档:');
      console.log(apiFiles.join('\n'));
      console.log('\n运行:npm run generate:api-docs');
    }
    
    const sourceFiles = changedFiles.filter(f => 
      f.endsWith('.ts') && !f.includes('.test.') && !f.includes('node_modules')
    );
    
    if (sourceFiles.length > 0) {
      console.log('\n⚠️  检测到源代码变更,建议更新注释:');
      console.log(sourceFiles.join('\n'));
      console.log('\n运行:npm run generate:comments');
    }
  }
}

// 添加到 git hook
// .git/hooks/post-commit
// node scripts/doc-sync.js

7.2 文档质量检查

// scripts/doc-lint.js
class DocLinter {
  checkReadme(content) {
    const issues = [];
    
    if (!content.includes('# ')) {
      issues.push('缺少主标题');
    }
    
    if (!content.includes('## 安装') && !content.includes('## Installation')) {
      issues.push('缺少安装说明');
    }
    
    if (!content.includes('## 使用') && !content.includes('## Usage')) {
      issues.push('缺少使用说明');
    }
    
    if (content.length < 500) {
      issues.push('README 内容过少(<500 字符)');
    }
    
    return issues;
  }

  checkApiSpec(spec) {
    const issues = [];
    
    if (!spec.openapi) {
      issues.push('缺少 openapi 版本声明');
    }
    
    if (!spec.info?.title) {
      issues.push('缺少 API 标题');
    }
    
    if (!spec.info?.version) {
      issues.push('缺少 API 版本');
    }
    
    const paths = spec.paths || {};
    for (const [path, methods] of Object.entries(paths)) {
      for (const [method, operation] of Object.entries(methods)) {
        if (!operation.summary) {
          issues.push(`${method.toUpperCase()} ${path} 缺少简介`);
        }
        if (!operation.responses) {
          issues.push(`${method.toUpperCase()} ${path} 缺少响应定义`);
        }
      }
    }
    
    return issues;
  }
}

八、集成到开发流程

8.1 package.json 脚本

{
  "scripts": {
    "generate:api-docs": "node scripts/generate-openapi.js",
    "generate:comments": "node scripts/generate-comments.js",
    "generate:readme": "node scripts/generate-readme.js",
    "generate:tests": "node scripts/generate-tests.js",
    "generate:all": "npm run generate:api-docs && npm run generate:comments && npm run generate:readme",
    "doc:lint": "node scripts/doc-lint.js",
    "doc:sync": "node scripts/doc-sync.js"
  }
}

8.2 Git Hook 集成

#!/bin/bash
# .git/hooks/pre-commit

echo "🔍 检查文档..."

# 检查 README
if [ -f README.md ]; then
  node scripts/doc-lint.js README.md
fi

# 检查 API 变更
CHANGED=$(git diff --cached --name-only | grep -E "(routes|controllers)" || true)
if [ ! -z "$CHANGED" ]; then
  echo "⚠️  API 变更检测到,请确保运行了 npm run generate:api-docs"
fi

九、效果对比

文档类型 人工耗时 AI 辅助耗时 效率提升
API 文档(50 接口) 8 小时 30 分钟 16 倍
代码注释(100 函数) 4 小时 20 分钟 12 倍
README 2 小时 10 分钟 12 倍
技术方案 16 小时 2 小时 8 倍
测试用例(50 用例) 6 小时 30 分钟 12 倍

十、总结

AI 生成技术文档的核心价值:

  1. 时间节省 - 文档时间从小时级降到分钟级
  2. 一致性 - 所有文档格式统一
  3. 及时更新 - 代码变更后立即生成
  4. 覆盖全面 - 不会遗漏接口和函数

最佳实践:

  • 初稿用 AI,人工审核和优化
  • 集成到 CI/CD,自动触发
  • 定期回顾生成质量
  • 建立文档模板和规范

注意事项:

  • AI 生成的内容需要人工审核
  • 业务逻辑和特殊说明需补充
  • 保持文档和代码同步
  • 不要过度依赖,理解内容很重要

现在就开始用 AI 自动化你的文档工作流吧!

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐