【学习笔记3】AI 工程实战

项目一:内部文档知识库问答(最推荐入手)

这是覆盖 RAG 完整链路、业务价值最直接的项目。两周内可以出一个 Demo。

复制代码
【完整架构】

上传阶段(离线):
PDF/Word 上传 → Apache POI/PDFBox 提取文本
→ 按段落切片(每片 500 字,50 字重叠)
→ 调 Embedding API 转向量
→ 存入 PostgreSQL + pgvector

查询阶段(在线):
用户提问 → 转向量 → pgvector 检索 Top5 相似片段
→ 拼装 Prompt(问题 + 5段原文)→ Claude 生成答案
→ 附带引用来源(哪个文档第几页)

// Spring AI 实现,核心代码极简
@Service
public class KnowledgeService {

    @Autowired
    private VectorStore vectorStore;       // pgvector
    @Autowired
    private ChatClient chatClient;         // Claude
    @Autowired
    private EmbeddingModel embeddingModel; // Embedding

    // 上传文档
    public void ingest(MultipartFile file) {
        // Spring AI 自动完成:提取文本 → 切片 → 向量化 → 存储
        List<Document> docs = new TikaDocumentReader(file.getResource()).get();
        var splitter = new TokenTextSplitter(500, 50, 5, 10000, true);
        vectorStore.add(splitter.apply(docs));
    }

    // 问答
    public String ask(String question) {
        // 1. 检索相关文档
        List<Document> relevant = vectorStore.similaritySearch(
            SearchRequest.query(question).withTopK(5)
        );

        // 2. 拼 Prompt
        String context = relevant.stream()
            .map(Document::getContent)
            .collect(Collectors.joining("\n\n---\n\n"));

        String prompt = """
            根据以下文档内容回答问题,如果文档中没有相关信息,
            请说"文档中未找到相关内容",不要凭空回答。

            文档内容:
            %s

            问题:%s
            """.formatted(context, question);

        // 3. 调 Claude
        return chatClient.prompt(prompt).call().content();
    }
}

关键难点只有两个:切片策略(切太短语义不完整,切太长 Token 费用高,500 字 + 50 字重叠是经验值);以及引用溯源(要在 Document 的 metadata 里存文件名和页码,回答时带上来源)。


项目二:AI 自动生成单元测试

程序员自己用,开发体验提升立竿见影,也是向团队展示 AI 价值最容易的方式。

复制代码
@Service
public class TestGenerator {

    private static final String SYSTEM = """
        你是 Java 单元测试专家。
        给定一个 Java 方法,生成完整的 JUnit 5 测试类,要求:
        1. 覆盖正常流程、边界值、异常情况
        2. 使用 Mockito mock 依赖
        3. 测试方法命名:should_预期结果_when_场景
        只输出代码,不要任何解释。
        """;

    public String generate(String javaSourceCode, String methodName) {
        // 用 JavaParser 精确提取目标方法,避免浪费 Token
        CompilationUnit cu = StaticJavaParser.parse(javaSourceCode);
        MethodDeclaration method = cu.findAll(MethodDeclaration.class)
            .stream()
            .filter(m -> m.getNameAsString().equals(methodName))
            .findFirst()
            .orElseThrow();

        // 同时提取类结构(依赖注入字段等),给 AI 更多上下文
        String classContext = extractClassContext(cu);

        String prompt = """
            类结构:
```java
            %s
```

            需要测试的方法:
```java
            %s
```

            请生成完整的测试类。
            """.formatted(classContext, method.toString());

        return claude.chat("claude-sonnet-4-6", 2048, 0.2, SYSTEM, prompt);
    }
}

进阶做法:把这个功能做成 IntelliJ IDEA 插件,右键点击方法名就能生成测试,用起来和原生功能一样顺滑。


项目三:AI 代码 Review 工具(团队基础设施)

接入 GitLab Webhook,每次提 MR 自动触发 AI Review,评论直接显示在代码行上。

复制代码
@RestController
public class GitLabWebhookController {

    @PostMapping("/webhook/gitlab")
    public void handleMR(@RequestBody GitLabEvent event) {
        if (!"merge_request".equals(event.getObjectKind())) return;
        if (!"open".equals(event.getObjectAttributes().getState())) return;

        // 异步处理,不阻塞 GitLab
        executor.submit(() -> reviewMR(event));
    }

    private void reviewMR(GitLabEvent event) {
        int projectId = event.getProject().getId();
        int mrIid = event.getObjectAttributes().getIid();

        // 1. 获取 Diff
        List<FileDiff> diffs = gitlabClient.getMRDiffs(projectId, mrIid);

        // 2. 对每个改动文件做 Review(只看改动的行,控制 Token)
        for (FileDiff diff : diffs) {
            if (!diff.getNewPath().endsWith(".java")) continue;
            if (diff.getDiff().length() > 8000) continue; // 太大的跳过

            String review = aiReview(diff);

            // 3. 把评论发回 GitLab(指定到具体行)
            gitlabClient.addMRComment(projectId, mrIid, review,
                diff.getNewPath(), diff.getNewLine());
        }
    }

    private String aiReview(FileDiff diff) {
        String prompt = """
            Review 以下 Java 代码变更,关注:
            - 潜在的 NPE 和线程安全问题 [HIGH]
            - 性能问题(N+1查询、不必要的循环)[MEDIUM]
            - 代码可读性和命名 [LOW]

            只指出真实问题,不要夸奖。每条评论格式:
            [HIGH/MEDIUM/LOW] 问题描述 → 建议改法

            代码变更:
```diff
            %s
```
            """.formatted(diff.getDiff());

        return claude.chat("claude-sonnet-4-6", 1024, 0.0, null, prompt);
    }
}

项目四:AI 数据分析助手(Text-to-SQL)

业务方输入"上个月每个地区的销售额排名",AI 自动生成 SQL 执行,返回图表。

复制代码
// 核心链路:自然语言 → SQL → 执行 → 结构化结果
public AnalysisResult analyze(String question, String dbSchema) {

    // Step 1:生成 SQL(temperature=0,必须确定性)
    String sql = generateSQL(question, dbSchema);

    // Step 2:安全校验(只允许 SELECT,防止注入)
    if (!sql.trim().toUpperCase().startsWith("SELECT")) {
        throw new SecurityException("只允许查询操作");
    }
    // 进一步:用 JSqlParser 做 AST 级别的安全校验
    validateSQL(sql);

    // Step 3:执行查询
    List<Map<String, Object>> data = jdbcTemplate.queryForList(sql);

    // Step 4:让 AI 生成图表配置(ECharts JSON)和文字解读
    String insight = generateInsight(question, data);

    return new AnalysisResult(sql, data, insight);
}

private String generateSQL(String question, String schema) {
    String prompt = """
        数据库表结构:
        %s

        将以下问题转为 SQL(只输出 SQL,不要任何解释):
        %s
        """.formatted(schema, question);

    return claude.chat("claude-sonnet-4-6", 512, 0.0,
        "你是 SQL 专家,只输出合法的 MySQL SELECT 语句", prompt);
}

这个项目的核心难点是安全------绝对不能让 AI 生成 DELETE/UPDATE 语句,要做多层防护:Prompt 约束 + SQL 解析校验 + 数据库只读账号三道防线。

相关推荐
测试_AI_一辰7 小时前
AI 产品输出格式测试实战:为什么模型返回的 JSON 前端解析总报错
人工智能·ai·自动化·状态模式·ai编程
IT_陈寒7 小时前
SpringBoot自动配置坑了我,原来要这样绕过去
前端·人工智能·后端
东方小月7 小时前
Claude Code 完整上手指南:MCP、Skills、第三方模型配置一次搞定
前端·人工智能·后端
Komorebi_99998 小时前
大模型学习day5
学习·大模型
EnCi Zheng8 小时前
01d-前馈神经网络代码实现 [特殊字符]
人工智能·深度学习·神经网络
阿里云大数据AI技术8 小时前
登顶WorldArena榜单!阿里云PAI助力中科院自动化所、中科第五纪打造具身世界模型FlowWAM
人工智能
hixiong1238 小时前
C# TensorRT部署RF-DETR目标检测&分割模型
人工智能·目标检测·计算机视觉·ai·c#
小程故事多_808 小时前
[大模型面试系列] 深度解析ReAct框架,大模型Agent的“思考+行动”底层逻辑
人工智能·react.js·面试·职场和发展·智能体
逍遥德8 小时前
AI时代,计算机专业大学生学习指南
java·javascript·人工智能·学习·ai编程
蝎子莱莱爱打怪8 小时前
Claude Code 省 Token 小妙招:RTK + Caveman 组合拳
前端·人工智能·后端