
1. 项目概述当若依框架遇上AI文档生成如果你是一名后端开发或者正在使用若依RuoYi这类基于Spring Boot的快速开发框架那么对下面这个场景一定不会陌生项目临近交付或者前端同事等着联调你被催着要接口文档。你打开一个又一个Controller类看着满屏的GetMapping、PostMapping和ApiOperation注解心里盘算着要把这些信息一个个复制粘贴到Swagger UI或者更传统一点手动整理成Word或Markdown文档。这个过程枯燥、重复还容易出错一旦接口有改动文档更新又是个麻烦事。“AI 自动生成若依接口文档Controller 进Markdown 出”这个项目瞄准的就是这个痛点。它的核心思路非常直接利用AI这里主要指大语言模型如GPT、文心一言、通义千问等的理解和生成能力自动解析若依框架中的Controller层代码提取出接口的路径、方法、参数、返回值以及注解中的描述信息最终生成一份结构清晰、内容完整的Markdown格式接口文档。这不仅仅是简单的文本提取和拼接而是让AI理解代码语义补全缺失的描述甚至能根据方法名和参数推断出接口的业务含义生成更易读的文档。为什么是若依因为若依在国内的Java开源后台管理框架中占有相当大的市场份额其标准的Spring MVC结构和常用的注解如Swagger的Api、ApiOperation为自动化解析提供了良好的基础。为什么是Markdown因为Markdown轻量、易读、易写可以被轻松地导入到Confluence、语雀等文档平台也能直接用于生成静态站点是技术文档的首选格式之一。这个工具适合所有使用若依框架的开发者、项目负责人以及需要维护项目文档的团队成员。它不仅能将开发者从繁琐的文档工作中解放出来更能保证文档与代码的同步性提升团队协作效率。接下来我将拆解这个项目的完整实现思路、技术细节以及我踩过的一些坑手把手带你实现一个属于自己的“AI文档小助手”。2. 核心思路与技术选型解析2.1 为什么选择“AI解析”而非“注解提取”传统的接口文档生成工具如SwaggerOpenAPI其工作原理是依赖于在代码中编写特定的注解如ApiOperation、ApiParam。工具在编译或运行时通过反射机制读取这些注解信息从而生成文档或UI界面。这种方式强依赖于开发者的规范注释如果注解没写、写得不全或者写错了生成的文档质量就会大打折扣。而“AI解析”走的是另一条路。它不完全依赖于规范的注解。其核心流程是代码读取与解析读取Controller类的源代码文件.java。语义理解与信息提取将代码文本提交给大语言模型LLM利用其强大的代码理解能力识别出类、方法、注解、参数、返回值等元素。结构化信息补全与润色LLM不仅提取显式信息还能根据方法名如getUserById、参数名Long userId、已有的简单注解推断并补全接口的功能描述、参数说明、业务逻辑等。例如即使方法上只有一个GetMapping(“/user/{id}”)AI也能推断出“根据用户ID查询用户信息”。格式化输出将AI提取和补全后的结构化信息按照预定的模板组装成Markdown文档。优势对比降低注释负担开发者无需为了文档而写大量标准化注解只需保持清晰的代码命名AI就能理解个七八成。智能补全能为缺少描述的接口生成合理的说明提升文档可读性。处理复杂逻辑对于注解无法表达的复杂业务逻辑或前置/后置条件可以在方法旁的Java注释中简单说明AI能将其整合进接口说明。当然也有挑战成本与性能调用AI API有成本Token计费且响应速度比本地反射慢。准确性依赖模型生成质量取决于所用AI模型对代码的理解能力。需要Prompt工程如何给AI下达清晰的指令Prompt让它准确提取我们需要的信息是关键所在。2.2 技术栈拆解与选型理由要实现这个项目我们需要一个清晰的技术栈核心语言Python理由在快速原型、文件处理、调用HTTP APIAI服务方面Python的生态和简洁语法有巨大优势。丰富的库如requests、openai官方库能简化开发。虽然若依是Java项目但我们的工具是独立的外部工具用Python来写非常合适。AI服务提供商OpenAI GPT系列 或 国内大模型APIOpenAI GPT-4/GPT-3.5-Turbo代码理解能力强生成质量高是首选。但需要考虑网络访问问题和API成本。国内替代阿里的通义千问、百度的文心一言、智谱AI的GLM等都提供了功能强大的API。选择时需考虑其代码理解专项能力、价格和稳定性。注意严禁讨论任何与克服网络访问限制相关的内容选择国内API是合规且稳定的方案。文件处理与模板引擎os/pathlib用于遍历项目目录寻找Controller文件。Jinja2一个强大的模板引擎。我们将把AI提取的信息存入一个字典或对象中然后通过Jinja2模板渲染成最终的Markdown文本。这比用字符串拼接要清晰、易维护得多。配置管理python-dotenv将AI API的密钥、模型参数、项目路径等配置信息放在.env文件中避免硬编码提升安全性。提示在项目初期建议从单个Controller文件测试开始成功后再扩展为遍历整个src/main/java目录。优先选用提供免费额度或性价比高的国内大模型API进行验证。2.3 项目整体架构设计整个工具的运行时序可以概括为以下几步初始化配置读取API密钥、设定模型参数如gpt-3.5-turbo、定义目标项目路径和输出目录。源代码扫描递归扫描指定目录过滤出所有以*Controller.java命名的文件。逐文件处理 a.读取读取Java文件内容。 b.提纯可选步骤可以简单清理一些不必要的导入语句或空行减少发送给AI的Token数量。 c.构造Prompt将代码片段与精心设计的指令Prompt结合形成发送给AI的完整消息。 d.调用AI API发送请求获取AI返回的结构化数据通常是JSON格式。 e.解析响应将AI返回的JSON解析为Python数据结构列表、字典。数据聚合将所有Controller文件解析出来的接口信息收集到一个总的数据结构中。模板渲染将聚合后的数据传递给Jinja2模板生成完整的Markdown文档。输出文件将渲染后的Markdown内容写入到api_docs.md文件。这个架构清晰地将“代码识别”AI负责和“文档格式化”本地程序负责解耦后续要更换AI模型或输出格式如HTML、Word都会非常方便。3. 实操要点Prompt工程与AI指令设计这是项目的核心灵魂。AI的表现完全取决于你如何给它下达指令。我们的目标是从一段Java代码中提取出结构化的接口信息。3.1 基础Prompt结构一个有效的Prompt通常包含以下几个部分你是一个资深的Java后端开发专家擅长分析Spring Boot控制器代码并生成接口文档。 请分析以下Controller类的代码提取出所有公开的HTTP接口信息。 ## 代码// 这里粘贴完整的Controller类代码## 提取要求 请严格按照以下JSON格式返回数据不要返回任何其他解释性文字。 { controller_name: 控制器的类名, controller_description: 控制器的简要描述来自类注解或根据类名推断, apis: [ { name: 接口名称优先取自ApiOperation的value若无则根据方法名推断, method: HTTP方法如GET, POST, PUT, DELETE, path: 接口路径是类上的RequestMapping与方法上的注解路径的组合, description: 接口详细描述优先取自ApiOperation的notes或方法Java注释若无则由你根据方法名和参数补充一段合理的业务描述, parameters: [ { name: 参数名, type: 参数类型如Long, String, UserDTO, required: 是否必填true/false, description: 参数说明优先取自ApiParam或方法参数前的Java注释若无则由你推断, in: 参数位置path, query, body, header } ], return_type: 返回值类型, return_description: 返回值说明 } ] } ## 规则与示例 1. 路径组合如果类上有RequestMapping(“/api/system”)方法上有GetMapping(“/user”)则完整路径为/api/system/user。 2. 参数推断PathVariable Long id 的 in 为 pathRequestParam String name 的 in 为 queryRequestBody UserDTO user 的 in 为 body。 3. 描述生成如果方法名为getUserById参数为Long id可生成描述为“根据用户ID获取用户详细信息”。3.2 Prompt设计的核心技巧与避坑指南角色设定Role开头明确AI的角色能引导其以更专业的视角处理任务。指令清晰使用“请分析”、“提取出”、“严格按照以下JSON格式返回”等明确动词。提供示例Few-Shot在复杂场景下可以在Prompt中给一两个简短的代码示例和对应的期望输出能极大提升AI输出的格式准确性。上述Prompt中“规则与示例”部分就是干这个的。格式化输出强制要求返回JSON格式这是后续程序自动化处理的基础。强调“不要返回任何其他解释性文字”避免解析失败。处理不确定性对于描述性文字给出明确的优先级如“优先取自...若无则...”并允许AI进行合理推断。这平衡了规范性和灵活性。控制Token如果Controller文件很大可以考虑按方法拆分发送请求或者只发送类中与接口定义相关的部分如类声明、注解、方法定义省略方法体内的具体实现逻辑以节省Token成本。注意不同的大模型对Prompt的敏感度不同。例如GPT-4严格遵守格式的能力更强而一些轻量模型可能需要更详细的格式描述。在实际开发中需要针对选定的模型进行多次调试和优化。3.3 代码实现调用AI API这里以使用OpenAI API或兼容OpenAI API格式的国内服务为例import openai import json from dotenv import load_dotenv import os # 加载环境变量其中.env文件里配置了OPENAI_API_KEY和OPENAI_BASE_URL如果使用国内代理 load_dotenv() client openai.OpenAI( api_keyos.getenv(“OPENAI_API_KEY”), base_urlos.getenv(“OPENAI_BASE_URL”, “https://api.openai.com/v1”) # 默认OpenAI可替换为国内服务商地址 ) def extract_api_info_with_ai(java_code: str) - dict: 调用AI模型提取接口信息 # 构建上文所述的Prompt消息 messages [ {“role”: “system”, “content”: “你是一个资深的Java后端开发专家擅长分析Spring Boot控制器代码并生成接口文档。”}, {“role”: “user”, “content”: f”””请分析以下Controller类的代码提取出所有公开的HTTP接口信息。 ## 代码 java {java_code}提取要求... 此处省略同上文完整的提取要求JSON和规则 ... “””} ]try: response client.chat.completions.create( model“gpt-3.5-turbo”, # 可根据需要和成本选择模型如 “gpt-4”, “qwen-plus” messagesmessages, temperature0.1, # 温度调低使输出更确定、更格式化 response_format{“type”: “json_object”} # 强烈建议使用此参数强制AI返回JSON对象 ) # 解析返回的JSON字符串 result_json response.choices[0].message.content return json.loads(result_json) except json.JSONDecodeError as e: print(f“AI返回的内容不是有效的JSON: {e}”) print(f“原始返回: {result_json}”) return {“controller_name”: “Error”, “apis”: []} except Exception as e: print(f“调用AI API失败: {e}”) return {“controller_name”: “Error”, “apis”: []}**关键参数说明** * temperature控制输出的随机性。设为较低值如0.1使AI的输出更聚焦、更可预测适合这种需要固定格式的任务。 * response_formatOpenAI较新版本API提供的参数能显著提高模型返回合规JSON的概率。务必使用。 ## 4. 工程化实现构建完整的自动化脚本 有了核心的AI调用函数我们需要构建一个完整的脚本来处理整个项目。 ### 4.1 目录扫描与文件过滤 python import os from pathlib import Path def find_controller_files(project_src_path: str) - list: 在项目的src/main/java目录下递归查找所有*Controller.java文件 controller_files [] src_path Path(project_src_path) / “src” / “main” / “java” if not src_path.exists(): raise FileNotFoundError(f“项目源码路径不存在: {src_path}”) # 使用rglob进行递归匹配 for java_file in src_path.rglob(“*Controller.java”): controller_files.append(str(java_file)) return controller_files4.2 数据处理与聚合我们需要一个主函数来串联整个流程def main(): # 配置 project_path “/path/to/your/ruoyi/project” # 你的若依项目根目录 output_md_path “./generated_api_docs.md” all_api_data [] # 用来存放所有Controller解析后的数据 # 1. 找到所有Controller文件 controller_files find_controller_files(project_path) print(f“共找到 {len(controller_files)} 个Controller文件”) for file_path in controller_files: print(f“正在处理: {file_path}”) # 2. 读取文件内容 with open(file_path, ‘r’, encoding‘utf-8’) as f: java_code f.read() # 3. 调用AI提取信息 api_info extract_api_info_with_ai(java_code) if api_info.get(“controller_name”) ! “Error” and api_info.get(“apis”): all_api_data.append(api_info) else: print(f“ - 处理失败或未提取到接口: {file_path}”) # 4. 使用模板渲染Markdown markdown_content render_markdown_template(all_api_data) # 5. 输出到文件 with open(output_md_path, ‘w’, encoding‘utf-8’) as f: f.write(markdown_content) print(f“文档生成完成输出至: {output_md_path}”) if __name__ “__main__”: main()4.3 使用Jinja2模板生成Markdown创建一个名为api_doc_template.md.j2的模板文件# 项目接口文档 本文档由AI辅助工具自动生成基于源码解析。最后更新时间{{ generate_time }} {% for controller in controllers %} ## {{ controller.controller_name }} {% if controller.controller_description %}*{{ controller.controller_description }}*{% endif %} {% for api in controller.apis %} ### {{ api.method }} {{ api.path }} **接口名称**{{ api.name }} **描述**{{ api.description }} {% if api.parameters %} **请求参数** | 参数名 | 类型 | 必填 | 位置 | 说明 | | :--- | :--- | :--- | :--- | :--- | {% for param in api.parameters %}| {{ param.name }} | {{ param.type }} | {{ “是” if param.required else “否” }} | {{ param.in }} | {{ param.description }} | {% endfor %} {% endif %} **返回类型**{{ api.return_type }} **返回说明**{{ api.return_description }} --- {% endfor %} {% endfor %}然后在Python中渲染它from jinja2 import Environment, FileSystemLoader import datetime def render_markdown_template(controllers_data: list) - str: # 设置模板环境假设模板文件放在当前目录的templates文件夹下 env Environment(loaderFileSystemLoader(‘./templates’)) template env.get_template(‘api_doc_template.md.j2’) # 准备模板上下文 context { “controllers”: controllers_data, “generate_time”: datetime.datetime.now().strftime(“%Y-%m-%d %H:%M:%S”) } return template.render(context)这样我们就得到了一个格式统一、内容丰富的Markdown接口文档。模板可以根据团队喜好自定义比如增加接口状态开发中/已上线、负责人等信息。5. 进阶优化与生产级考量上面的基础版本已经可以工作但要用于实际项目还需要考虑更多。5.1 性能与成本优化批量处理如果项目很大逐个文件调用AI API速度慢且成本高。可以考虑将一个包package下的多个Controller代码合并到一个Prompt中发送让AI一次性分析多个类。但要注意合并后的代码长度不能超过模型的上下文窗口限制如GPT-3.5-Turbo通常是16K Token。缓存机制对已经处理过的文件可以将其生成的JSON结果缓存到本地文件或数据库中。下次运行时先检查文件哈希如MD5是否变化若无变化则直接使用缓存避免重复调用AI产生费用。模型选择对于简单的、注解规范的Controller可以使用更便宜、更快的模型如GPT-3.5-Turbo。对于复杂的、需要深度理解的逻辑再使用GPT-4。可以在Prompt中让AI自我评估复杂度或者根据代码行数/结构进行简单分流。5.2 准确性与可靠性提升混合解析策略完全依赖AI存在不确定性。可以采用“本地解析为主AI补全为辅”的混合模式。先用本地库如javalangPython库进行语法解析准确提取出方法签名、注解文本、参数类型等结构化信息。这部分信息是确定的。将提取出的结构化信息如方法名、参数列表、已有的注解文本连同代码片段再发送给AI让其专注于补全描述、推断业务含义等需要“理解”的任务。 这样既能保证路径、方法等核心信息的绝对准确又能利用AI的语义理解优势。人工审核与修正流程生成的文档不应直接视为最终版。工具可以生成一个“待审核”状态的文档并提供一个简单的Web界面或标注系统让开发者在阅读文档时能快速对不准确或缺失的描述进行补充和修正。这些修正可以反馈回系统甚至用于微调AI的Prompt。5.3 集成与自动化Git Hook集成在项目的.git/hooks/pre-commit钩子中集成脚本当开发者提交Controller相关代码时自动触发文档更新确保文档随代码实时变更。CI/CD流水线集成在Jenkins、GitLab CI等持续集成平台中增加一个文档生成步骤。每次代码合并到主分支后自动运行脚本生成最新文档并发布到内部的文档站点如通过GitHub Pages、语雀API更新。生成多种格式除了Markdown可以扩展模板同时生成HTML、PDF甚至直接生成符合OpenAPI 3.0规范的openapi.yaml文件以便导入到Swagger UI、Postman等工具中。6. 常见问题与排查实录在实际开发和测试过程中我遇到了不少典型问题这里记录下来供你参考。6.1 AI返回格式错误或内容不合规问题现象json.loads()解析失败AI返回了非JSON文本。排查与解决检查Prompt首先确认Prompt中是否明确强调了“严格按照JSON格式返回不要其他文字”。response_format{“type”: “json_object”}参数是否加上。检查模型能力有些模型特别是某些小参数模型或早期版本对JSON格式遵循能力较弱。尝试换用更强大的模型如从gpt-3.5-turbo换到gpt-4。添加输出示例在Prompt中不仅给出JSON结构直接给出一个完整的、针对示例代码的输出样例。Few-shot learning效果显著。降级处理在代码中增加异常捕获当解析失败时尝试用正则表达式从AI返回的文本中“抠”出JSON部分或者记录错误并跳过该文件不至于让整个流程中断。6.2 生成的描述过于笼统或存在幻觉问题现象AI生成的接口描述全是“这是一个XXX接口”或者捏造了不存在的业务逻辑。排查与解决提供更多上下文在发送给AI的代码中保留类和方法上的Java注释//或/* */。这些注释是开发者写的最直接的业务说明AI会优先采用。约束生成范围在Prompt中明确要求“描述应基于方法名、参数和现有注释进行合理推断避免创造代码中未体现的信息”。后处理对于某些关键接口可以设计一个简单的关键词检查。如果生成的描述中包含“可能”、“应该”等不确定词汇或过于简短可以标记出来供人工重点审核。6.3 处理大型项目时Token超限或API调用缓慢问题现象代码太长超过模型上下文限制或者文件太多逐个调用耗时太长。排查与解决代码精简在发送前预处理Java文件只保留与接口定义相关的部分包声明、导入的注解类、类声明、类注解、方法签名、方法注解、方法参数注解。移除方法体内的具体实现、日志语句等。这能大幅减少Token消耗。分而治之按物理目录package或逻辑模块拆分每次处理一个模块的多个Controller平衡单次请求的Token数和请求次数。设置超时与重试网络请求务必设置合理的超时时间并实现重试机制如指数退避以提高脚本的健壮性。异步并发如果AI服务商支持且你的账号速率限制允许可以使用asyncio和aiohttp库并发调用API显著提升多文件处理速度。6.4 如何适配不同风格的若依项目或Spring Boot项目问题核心不同项目可能使用不同的注解组合。有的用Swagger的ApiOperation有的用SpringDoc的Operation有的干脆只用Spring MVC的原生注解。解决策略Prompt的泛化能力在Prompt的“规则与示例”部分列举几种常见的注解风格并说明提取优先级。例如“如果存在ApiOperation(value”…”)则以其value作为接口名否则如果存在Operation(summary”…”)则以其summary作为接口名否则根据方法名推断。”可配置的解析规则将不同注解的匹配规则做成配置文件。工具运行时读取配置动态调整AI Prompt中的“提取要求”部分。这样工具就具备了更强的适应性。我个人在几个中型若依项目上实践了这个方案。初期投入了较多时间在Prompt调试和异常处理上但一旦流程跑通后续的维护成本极低。最大的体会是不要追求100%的全自动化接受90%-95%的准确率将工具定位为“强力辅助”为开发者节省80%的机械劳动剩下的20%由人工快速复核和修正这样的人机协作模式效率最高也最可持续。最后一个小建议生成的Markdown文档可以放入项目根目录的docs文件夹并链接到项目的README中让文档真正成为项目资产的一部分。