知识目录 / Agent 开发

实战案例:用 Agent4J 构建全栈项目

通过一个完整的实战案例,看看 Agent4J 如何自动生成 Chrome 扩展和 Spring Boot 后端。

实战案例:用 Agent4J 构建全栈项目

前言

理论讲得再多,不如一个真实的案例有说服力。

今天,我要带你看看 Agent4J 是如何帮我自动生成一个完整的全栈项目:一个 Chrome 扩展 + Spring Boot 后端。

这个案例来自 Agent4J 的 MainTest 类,是一个真实的演示程序。

项目需求

假设你有这样一个需求:

  1. Chrome 扩展:用户选中网页上的文字,点击扩展图标,发送到后端
  2. Spring Boot 后端:接收前端请求,调用 LLM 生成回答,返回给前端
  3. 参考数据:后端使用 da.md 文件作为参考数据

这个需求涉及到:

  • Chrome 扩展开发(manifest.json、content.js、content.css)
  • Spring Boot 后端开发(pom.xml、Controller、Service)
  • 文件读写操作
  • 项目结构组织

如果手动开发,至少需要几个小时。但用 Agent4J,只需要几分钟。

完整代码

java
import ink.icoding.llm.agent.AgentClient;
import ink.icoding.llm.agent.AgentResultHandler;
import ink.icoding.llm.agent.builtin.skill.BuiltInSkills;
import ink.icoding.llm.core.entity.ModelType;
import ink.icoding.llm.core.model.LLMModel;

public class MainTest {
    public static void main(String[] args) {
        // 从环境变量读取模型配置
        String baseURL = System.getenv("BASE_URL");   // e.g. https://token-plan-cn.xiaomimimo.com
        String apiKey  = System.getenv("API_KEY");
        String model   = System.getenv("MODEL");       // e.g. mimo-v2.5-pro
        
        // 创建 LLM 模型
        LLMModel llm = LLMModel.create(ModelType.OpenAI, baseURL, model, apiKey);
        
        // 创建 Agent
        AgentClient agent = new AgentClient();
        agent.setName("CodeAgent");
        agent.setDescription("一个专业的全栈工程师,擅长 Chrome 扩展和 Spring Boot 开发");
        agent.setModel(llm);
        agent.getSkills().addAll(BuiltInSkills.all());
        
        // 创建会话并发送任务
        agent.createSession()
            .command("""
                请在 /Users/dev/plugin 目录下创建一个 Chrome 扩展和 Spring Boot 后端项目。
                
                需求:
                1. Chrome 扩展:用户选中文字后,点击扩展图标,发送到后端的 /answer 接口
                2. Spring Boot 后端:接收请求,使用 da.md 作为参考数据,调用 LLM 生成回答
                3. da.md 文件在当前目录下,包含约 860 行的医药数据
                
                要求:
                - Chrome 扩展要有美观的 UI
                - 后端要有完善的错误处理
                - 代码要有中文注释
                """)
            .then(new AgentResultHandler() {
                public void onMessage(String msg) { 
                    System.out.print(msg); 
                }
                
                public void onTool(ToolDescriptor tool, ToolStatus status) {
                    System.out.println("[" + status + "] " + tool.getName());
                }
                
                public void onPlanCreated(Plan plan) {
                    System.out.println("\n========== 创建执行计划 ==========");
                    System.out.println("计划包含 " + plan.getSteps().size() + " 个步骤");
                }
                
                public void onPlanStepStart(Plan plan, int current, int total, String step) {
                    System.out.println("\n--- 步骤 " + current + "/" + total + " ---");
                    System.out.println("任务:" + step);
                }
                
                public void onPlanStepComplete(Plan plan, int current, int total, String step, String result) {
                    System.out.println("步骤 " + current + " 完成");
                }
            })
            .error(e -> e.printStackTrace());
    }
}

执行过程

让我们看看 Agent 是如何完成这个任务的。

第一步:分析需求

Agent 首先会读取 da.md 文件,了解参考数据的结构:

text
[COMPLETED] view_file

Agent 发现 da.md 包含约 860 行的医药数据,需要特殊处理。

第二步:创建执行计划

Agent 创建了一个包含 5 个步骤的计划:

text
========== 创建执行计划 ==========
计划包含 5 个步骤

步骤 1:验证 da.md 文件存在且可读
步骤 2:创建 Chrome 扩展(manifest.json、content.js、content.css)
步骤 3:创建 Spring Boot 后端(pom.xml、Controller、Service)
步骤 4:创建配置文件(application.properties)
步骤 5:验证项目完整性

第三步:执行计划

步骤 1:验证 da.md

text
--- 步骤 1/5 ---
任务:验证 da.md 文件存在且可读
[COMPLETED] view_file
步骤 1 完成

Agent 读取了 da.md,确认文件存在且包含有效数据。

步骤 2:创建 Chrome 扩展

text
--- 步骤 2/5 ---
任务:创建 Chrome 扩展
[COMPLETED] create_file  // manifest.json
[COMPLETED] create_file  // content.js
[COMPLETED] create_file  // content.css
[COMPLETED] create_file  // popup.html
[COMPLETED] create_file  // popup.js
步骤 2 完成

Agent 创建了完整的 Chrome 扩展,包括:

  • manifest.json:扩展配置文件
  • content.js:内容脚本,处理选中文字
  • content.css:样式文件,美化 UI
  • popup.html:弹出窗口
  • popup.js:弹出窗口逻辑

步骤 3:创建 Spring Boot 后端

text
--- 步骤 3/5 ---
任务:创建 Spring Boot 后端
[COMPLETED] create_file  // pom.xml
[COMPLETED] create_file  // Application.java
[COMPLETED] create_file  // AnswerController.java
[COMPLETED] create_file  // AnswerService.java
步骤 3 完成

Agent 创建了完整的 Spring Boot 后端,包括:

  • pom.xml:Maven 配置文件
  • Application.java:应用入口
  • AnswerController.java:REST 控制器
  • AnswerService.java:业务逻辑

步骤 4:创建配置文件

text
--- 步骤 4/5 ---
任务:创建配置文件
[COMPLETED] create_file  // application.properties
步骤 4 完成

步骤 5:验证项目完整性

text
--- 步骤 5/5 ---
任务:验证项目完整性
[COMPLETED] list_directory_tree
步骤 5 完成

Agent 浏览了整个项目结构,确认所有文件都已创建。

自动修复

在执行过程中,Agent 还会自动修复一些问题:

text
[COMPLETED] edit_file  // 修复 pom.xml 中的依赖问题
[COMPLETED] delete_file  // 清理重复的包结构

生成的项目结构

text
/Users/dev/plugin/
├── chrome-extension/
│   ├── manifest.json
│   ├── content.js
│   ├── content.css
│   ├── popup.html
│   └── popup.js
├── backend/
│   ├── pom.xml
│   └── src/
│       └── main/
│           ├── java/
│           │   └── com/example/
│           │       ├── Application.java
│           │       ├── controller/
│           │       │   └── AnswerController.java
│           │       └── service/
│           │           └── AnswerService.java
│           └── resources/
│               └── application.properties
└── da.md

代码解析

Chrome 扩展

manifest.json

json
{
    "manifest_version": 3,
    "name": "AI Answer Assistant",
    "version": "1.0",
    "description": "选中文字,获取 AI 回答",
    "permissions": ["activeTab", "selection"],
    "action": {
        "default_popup": "popup.html"
    },
    "content_scripts": [{
        "matches": ["<all_urls>"],
        "js": ["content.js"],
        "css": ["content.css"]
    }]
}

content.js

javascript
// 监听选中文字事件
document.addEventListener('mouseup', function() {
    const selectedText = window.getSelection().toString().trim();
    if (selectedText.length > 0) {
        // 显示浮动按钮
        showFloatingButton(selectedText);
    }
});

function showFloatingButton(text) {
    // 创建浮动按钮
    const button = document.createElement('div');
    button.className = 'ai-answer-button';
    button.textContent = 'AI 回答';
    button.onclick = function() {
        // 发送消息到后端
        fetch('http://localhost:8080/answer', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ question: text })
        })
        .then(response => response.json())
        .then(data => {
            // 显示回答
            showAnswer(data.answer);
        });
    };
    document.body.appendChild(button);
}

Spring Boot 后端

AnswerController.java

java
@RestController
@CrossOrigin
public class AnswerController {
    
    @Autowired
    private AnswerService answerService;
    
    @PostMapping("/answer")
    public ResponseEntity<Map<String, String>> answer(@RequestBody Map<String, String> request) {
        String question = request.get("question");
        String answer = answerService.generateAnswer(question);
        
        Map<String, String> response = new HashMap<>();
        response.put("answer", answer);
        
        return ResponseEntity.ok(response);
    }
}

AnswerService.java

java
@Service
public class AnswerService {
    
    @Value("${llm.api.url}")
    private String apiUrl;
    
    @Value("${llm.api.key}")
    private String apiKey;
    
    public String generateAnswer(String question) {
        // 读取参考数据
        String referenceData = readReferenceData();
        
        // 构建 prompt
        String prompt = """
                参考数据:
                %s
                
                用户问题:%s
                
                请根据参考数据回答问题。如果参考数据中没有相关信息,请说明。
                """.formatted(referenceData, question);
        
        // 调用 LLM
        return callLLM(prompt);
    }
    
    private String readReferenceData() {
        // 读取 da.md 文件
        try {
            return new String(Files.readAllBytes(Paths.get("da.md")));
        } catch (IOException e) {
            return "";
        }
    }
    
    private String callLLM(String prompt) {
        // 调用 LLM API
        // ... 实现细节
    }
}

运行项目

1. 启动后端

bash
cd backend
mvn spring-boot:run

2. 加载 Chrome 扩展

  1. 打开 Chrome,进入 chrome://extensions/
  2. 开启"开发者模式"
  3. 点击"加载已解压的扩展程序"
  4. 选择 chrome-extension 目录

3. 使用

  1. 打开任意网页
  2. 选中一段文字
  3. 点击出现的"AI 回答"按钮
  4. 等待 AI 生成回答

这个案例的意义

这个案例展示了 Agent4J 的几个强大能力:

1. 理解复杂需求

Agent 能理解"Chrome 扩展 + Spring Boot 后端"这样的复杂需求,并自动拆分成可执行的步骤。

2. 自动生成代码

Agent 能生成完整的、可运行的代码,包括前端、后端、配置文件。

3. 自动修复问题

Agent 能检测并修复一些常见问题,比如依赖缺失、包结构错误。

4. 跨技术栈

Agent 能同时处理前端(JavaScript、HTML、CSS)和后端(Java、Spring Boot)的代码。

扩展思考

这个案例只是一个开始。你可以用 Agent4J 做更多事情:

  1. 代码审查:让 Agent 审查你的代码,找出潜在问题
  2. 自动化测试:让 Agent 生成单元测试、集成测试
  3. 文档生成:让 Agent 根据代码生成 API 文档
  4. 代码重构:让 Agent 重构你的代码,提高可读性
  5. Bug 修复:让 Agent 分析错误日志,自动修复 bug

关键在于:你给 Agent 什么工具,它就能做什么事情。

总结

通过这个实战案例,我们看到了 Agent4J 的强大能力。它能理解复杂需求,自动生成代码,自动修复问题,真正实现了"用自然语言编程"。

当然,Agent 不是万能的。它生成的代码可能需要人工审查和调整。但它已经能帮你节省大量时间,让你专注于更有创造性的工作。

在下一篇文章中,我们将学习 Agent4J 的高级特性:Plan 和 Sub-Agent。


项目地址https://github.com/onlyGuo/agent4j

上一篇自定义工具开发:扩展 Agent 的能力边界

下一篇高级特性:Plan 和 Sub-Agent 的妙用