一位Java开发者的AI之旅:从AI Coding到AI工程化应用
目录
- [1. 引言:AI时代,Java开发者的新机遇](#1. 引言:AI时代,Java开发者的新机遇 "#1-%E5%BC%95%E8%A8%80ai%E6%97%B6%E4%BB%A3java%E5%BC%80%E5%8F%91%E8%80%85%E7%9A%84%E6%96%B0%E6%9C%BA%E9%81%87")
- [2. AI发展历程:从理论到实践的演进](#2. AI发展历程:从理论到实践的演进 "#2-ai%E5%8F%91%E5%B1%95%E5%8E%86%E7%A8%8B%E4%BB%8E%E7%90%86%E8%AE%BA%E5%88%B0%E5%AE%9E%E8%B7%B5%E7%9A%84%E6%BC%94%E8%BF%9B")
- [3. AI知识体系:构建完整的认知地图](#3. AI知识体系:构建完整的认知地图 "#3-ai%E7%9F%A5%E8%AF%86%E4%BD%93%E7%B3%BB%E6%9E%84%E5%BB%BA%E5%AE%8C%E6%95%B4%E7%9A%84%E8%AE%A4%E7%9F%A5%E5%9C%B0%E5%9B%BE")
- [4. AI Coding工具:开发者的智能助手](#4. AI Coding工具:开发者的智能助手 "#4-ai-coding%E5%B7%A5%E5%85%B7%E5%BC%80%E5%8F%91%E8%80%85%E7%9A%84%E6%99%BA%E8%83%BD%E5%8A%A9%E6%89%8B")
- [5. AI工程化实践:从概念到落地](#5. AI工程化实践:从概念到落地 "#5-ai%E5%B7%A5%E7%A8%8B%E5%8C%96%E5%AE%9E%E8%B7%B5%E4%BB%8E%E6%A6%82%E5%BF%B5%E5%88%B0%E8%90%BD%E5%9C%B0")
1. 引言:AI时代,Java开发者的新机遇
1.1 为什么是现在?
2022年11月,ChatGPT的发布标志着我们进入了大模型时代。作为Java开发者,我们正处于一个历史性的转折点:
- 开发方式的革命:AI Coding工具正在改变我们写代码的方式
- 应用形态的创新:AI能力正在被集成到各类应用中
- 技术栈的扩展:Java生态正在快速拥抱AI技术
1.2 Java开发者的优势
作为Java开发者,我们在AI工程化落地方面有天然优势:
2. AI发展历程:从理论to实践的演进
2.1 AI发展时间线
2.2 三个重要阶段
阶段一:传统AI时代(1956-2010)
特征:
- 基于规则和专家系统
- 符号主义和逻辑推理
- 应用场景有限
典型代表:
- 专家系统(MYCIN、DENDRAL)
- 搜索算法(A*、博弈树)
- 早期自然语言处理
阶段二:深度学习革命(2012-2020)
特征:
- 数据驱动的学习方式
- 神经网络的复兴
- 在特定领域超越人类
关键技术:
阶段三:大模型时代(2020至今)
特征:
- 规模化预训练模型
- 涌现能力(Emergent Abilities)
- 通用人工智能的雏形
核心理念:
- Scale Law:模型越大,能力越强
- Few-shot Learning:少样本甚至零样本学习
- Instruction Following:理解并执行复杂指令
3. AI知识体系:构建完整的认知地图
3.1 整体知识架构
3.2 核心概念详解
3.2.1 大语言模型(LLM)
什么是LLM?
大语言模型是通过在海量文本数据上进行预训练,学习语言模式和知识的深度学习模型。
核心特征:
| 特征 | 说明 | 示例 |
|---|---|---|
| 大规模参数 | 数十亿到数千亿参数 | GPT-4: ~1.7T, Claude 3.5: 未公开 |
| 预训练 | 在大规模语料上自监督学习 | 互联网文本、书籍、代码等 |
| 涌现能力 | 模型规模达到临界点后出现的能力 | 推理、代码生成、多语言理解 |
| 上下文学习 | 从提示词中学习任务 | Few-shot、Zero-shot学习 |
工作原理简化理解:
arduino
用户输入 → Token化 → Embedding → Transformer处理 → 概率预测 → 生成输出
↓ ↓ ↓ ↓ ↓ ↓
"你好" → [101,203] → 向量化 → 多层注意力计算 → 下一个Token → "您好"
3.2.2 Prompt Engineering(提示词工程)
定义: 设计和优化输入提示词,以获得更好的模型输出。
核心技巧:
-
明确角色和任务
你是一位资深的Java架构师,擅长Spring Boot和微服务设计。
请帮我设计一个订单系统的数据库表结构。 -
提供上下文和约束
diff
背景:电商系统,日订单量10万
要求:
- 支持订单拆分
- 需要记录完整的状态流转
- 考虑分库分表
- 使用示例引导
diff
参考以下格式输出:
表名:t_order
字段:
- id: bigint, 主键
- user_id: bigint, 用户ID
...
- 分步骤思考(Chain of Thought)
markdown
请按以下步骤分析:
1. 识别核心实体
2. 确定表关系
3. 设计字段
4. 添加索引
5. 考虑扩展性
Prompt模式总结:

3.2.3 RAG(检索增强生成)
为什么需要RAG?
大模型虽然强大,但存在局限:
- ❌ 知识截止日期限制
- ❌ 无法访问私有数据
- ❌ 可能产生幻觉(Hallucination)
- ❌ 缺乏特定领域知识
RAG如何解决?
文档2: 同比增长25%
文档3: 净利润15亿 S->>L: 构建Prompt(问题+检索文档) Note over L: Prompt:
基于以下信息回答...
[相关文档]
问题: 公司Q3财报如何? L-->>S: 生成答案 S-->>U: "Q3营收100亿,同比增长25%..."
RAG技术架构:
关键技术点:
| 环节 | 技术选择 | 说明 |
|---|---|---|
| 文档切分 | 固定长度、语义切分、递归切分 | 平衡上下文完整性和检索精度 |
| Embedding模型 | OpenAI、BGE、M3E | 中文推荐BGE或M3E |
| 向量数据库 | Milvus、Qdrant、Pinecone | 考虑性能和部署方式 |
| 检索策略 | 密集检索、稀疏检索、混合检索 | 提升召回率和准确率 |
| 重排序 | Rerank模型 | 优化Top-K结果质量 |
3.2.4 Agent(智能体)
什么是AI Agent?
具备自主决策和工具使用能力的AI系统,能够理解任务、制定计划、执行动作、并根据反馈调整策略。
Agent核心组件:
Agent工作流程:
典型Agent模式:
- ReAct模式(Reasoning + Acting)
vbnet
Thought: 用户想查询订单状态,我需要先获取订单ID
Action: 调用getUserOrders工具
Observation: 返回订单列表[#12345, #12346]
Thought: 用户最近的订单是#12346,查询其状态
Action: 调用getOrderStatus(#12346)
Observation: 订单状态为"已发货"
Thought: 我已经得到答案
Answer: 您的订单#12346已发货
- Plan-and-Execute模式
ini
Plan:
1. 搜索Spring AI Alibaba官方文档
2. 提取核心特性信息
3. 对比LangChain4j的差异
4. 生成对比表格
Execute:
[执行步骤1] → [执行步骤2] → [执行步骤3] → [执行步骤4]
3.2.5 Function Calling(函数调用)
定义: 让LLM能够主动调用外部函数/API来完成任务。
工作原理:
"function": "getWeather",
"parameters": {
"city": "北京",
"date": "明天"
}
} S->>API: 调用天气API API-->>S: 返回天气数据 S->>L: 将结果返回给LLM L->>U: "北京明天晴,15-25℃"
Java实现示例(LangChain4j):
java
// 定义工具函数
@Tool("查询订单状态")
public String getOrderStatus(@P("订单ID") String orderId) {
// 实际业务逻辑
return orderService.queryStatus(orderId);
}
// 配置Agent
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(apiKey)
.modelName("gpt-4")
.build();
Assistant assistant = AiServices.builder(Assistant.class)
.chatLanguageModel(model)
.tools(new OrderTools())
.build();
// 调用
String response = assistant.chat("帮我查询订单12345的状态");
3.2.6 Fine-tuning(微调)
什么是微调?
在预训练模型基础上,使用特定领域数据进行进一步训练,使模型适应特定任务。
微调 vs RAG vs Prompt Engineering:
快速迭代| C[Prompt Engineering] B -->|中等数据
知识增强| D[RAG] B -->|大量数据
行为定制| E[Fine-tuning] C --> C1[优点: 零成本快速验证] C --> C2[缺点: 受限于模型能力] D --> D1[优点: 动态知识更新] D --> D2[缺点: 需要维护检索系统] E --> E1[优点: 深度定制] E --> E2[缺点: 成本高周期长] style C fill:#e1ffe1 style D fill:#fff4e1 style E fill:#ffe1e1
选择决策树:
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 格式化输出 | Prompt | 简单有效 |
| 企业知识问答 | RAG | 知识可更新 |
| 特定领域对话风格 | Fine-tuning | 深度定制 |
| 多轮对话 | Prompt + RAG | 组合使用 |
| 专业术语翻译 | Fine-tuning | 专业性强 |
3.3 技术栈全景图
4. AI Coding工具:开发者的智能助手
4.1 AI Coding的本质
AI Coding不是替代程序员,而是:
- ✅ 提升开发效率(2-5倍)
- ✅ 减少重复性工作
- ✅ 辅助学习新技术
- ✅ 改善代码质量
4.2 主流工具全景对比

4.3 重点工具详解
4.3.1 Claude Code
定位: 官方CLI工具,深度集成Claude 3.5 Sonnet,专注于代码生成和工程实践。
核心特性:
| 特性 | 说明 | 优势 |
|---|---|---|
| 长上下文 | 支持200K tokens | 可以理解整个代码库 |
| Artifacts | 独立的代码预览 | 所见即所得 |
| 工具集成 | Bash、文件操作、搜索 | 完整的开发环境 |
| 思维链 | 可见的推理过程 | 理解AI的决策逻辑 |
典型使用场景:
bash
# 1. 代码重构
claude "将这个Controller改造为RESTful风格,并添加参数校验"
# 2. 单元测试生成
claude "为UserService生成完整的单元测试,覆盖率达到80%"
# 3. 代码审查
claude "审查这段代码的安全性和性能问题"
# 4. 架构设计
claude "设计一个支持百万级用户的秒杀系统架构"
最佳实践:
4.3.2 Cursor
定位: AI-first的IDE,基于VS Code深度定制。
核心特性:
-
Cmd+K:内联编辑
- 选中代码,描述需求
- AI直接修改代码
- 支持多处同时编辑
-
Composer:多文件编辑
- 跨文件重构
- 一次性修改多个相关文件
- 保持代码一致性
-
Chat:对话式编程
@Codebase搜索整个代码库@Web搜索网络资料@Docs查询文档
-
Tab:代码补全
- 上下文感知补全
- 学习个人编码风格
Cursor vs Claude Code:
| 维度 | Cursor | Claude Code |
|---|---|---|
| 界面 | 图形化IDE | 命令行CLI |
| 集成度 | 深度集成VS Code | 独立工具 |
| 学习曲线 | 平缓 | 稍陡峭 |
| 灵活性 | 中等 | 高 |
| 适用场景 | 日常开发 | 复杂任务、自动化 |
| 价格 | $20/月 | 按API计费 |
组合使用建议:
css
日常开发:Cursor(快速迭代)
复杂重构:Claude Code(深度思考)
学习探索:两者结合使用
4.3.3 GitHub Copilot
定位: GitHub官方,集成度最高。
优势:
- ✅ 无缝集成GitHub生态
- ✅ 支持几乎所有IDE
- ✅ 企业版安全合规
- ✅ Chat功能增强
适合:
- 使用VS Code/JetBrains的团队
- 需要企业级安全的公司
- GitHub深度用户
4.3.4 其他工具简介
| 工具 | 特点 | 适用场景 |
|---|---|---|
| Codeium | 免费、隐私保护 | 个人开发者、初学者 |
| Tabnine | 本地运行、企业级 | 对数据安全要求高的企业 |
| Amazon Q | AWS生态集成 | 使用AWS服务的团队 |
| Windsurf | 新兴工具,流式体验 | 尝鲜用户 |
4.4 工具选择决策树
4.5 AI Coding最佳实践
4.5.1 提示词技巧
1. 提供足够的上下文
❌ 不好的提示:
帮我写个用户服务
✅ 好的提示:
markdown
项目:Spring Boot 3.2 + MyBatis Plus
需求:创建UserService,包含CRUD操作
要求:
1. 使用@Service注解
2. 集成Redis缓存
3. 添加事务管理
4. 参数校验使用JSR-303
5. 统一异常处理
2. 明确技术栈和约束
diff
技术栈:
- JDK 17
- Spring Boot 3.2
- MySQL 8.0
- Redis 7.0
约束:
- 遵循阿里巴巴Java开发规范
- 使用Lombok减少样板代码
- 日志使用SLF4J
- 返回统一的Result对象
3. 使用示例驱动
less
参考以下代码风格:
@Service
@Slf4j
public class OrderService {
@Resource
private OrderMapper orderMapper;
@Cacheable(value = "order", key = "#id")
public OrderDTO getById(Long id) {
// ...
}
}
请按相同风格实现UserService
4.5.2 代码审查检查清单
AI生成代码后,必须检查:
4.5.3 迭代式开发流程
5. AI工程化实践:从概念到落地
5.1 AI应用架构设计
5.1.1 整体架构
5.1.2 分层设计原则
1. 控制层(Controller)
java
@RestController
@RequestMapping("/ai/chat")
@Slf4j
public class ChatController {
@Resource
private ChatService chatService;
@PostMapping("/stream")
public SseEmitter chatStream(@RequestBody ChatRequest request) {
// 处理流式响应
return chatService.streamChat(request);
}
@PostMapping("/sync")
public Result<ChatResponse> chat(@RequestBody ChatRequest request) {
// 同步响应
return Result.success(chatService.chat(request));
}
}
2. 服务层(Service)
java
@Service
@Slf4j
public class ChatService {
@Resource
private ChatClient chatClient; // Spring AI
@Resource
private ConversationService conversationService;
@Resource
private RagService ragService;
public ChatResponse chat(ChatRequest request) {
// 1. 加载历史对话
List<Message> history = conversationService.getHistory(request.getSessionId());
// 2. RAG检索
String context = ragService.retrieve(request.getQuestion());
// 3. 构建Prompt
String prompt = buildPrompt(request.getQuestion(), context);
// 4. 调用大模型
String response = chatClient.call(prompt);
// 5. 保存对话
conversationService.save(request.getSessionId(), request.getQuestion(), response);
return ChatResponse.builder()
.answer(response)
.sessionId(request.getSessionId())
.build();
}
}
5.2 Java生态AI框架深度对比
5.2.1 Spring AI Alibaba详解
定位: 阿里云官方AI框架,深度集成阿里云百炼平台,也支持OpenAI等。
核心特性:
快速开始:
xml
<!-- Maven依赖 -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-cloud-starter-alibaba-ai</artifactId>
<version>1.0.0-M2</version>
</dependency>
yaml
# application.yml
spring:
ai:
dashscope:
api-key: ${DASHSCOPE_API_KEY}
chat:
options:
model: qwen-max
temperature: 0.7
java
// 使用示例
@Service
public class AiService {
@Resource
private ChatClient chatClient;
public String chat(String message) {
return chatClient.call(message);
}
// 流式响应
public Flux<String> streamChat(String message) {
return chatClient.stream(message)
.map(ChatResponse::getResult)
.map(result -> result.getOutput().getContent());
}
}
RAG实现:
java
@Configuration
public class RagConfig {
@Bean
public VectorStore vectorStore(EmbeddingClient embeddingClient) {
return new SimpleVectorStore(embeddingClient);
}
@Bean
public DocumentReader pdfReader() {
return new PagePdfDocumentReader("classpath:docs/manual.pdf");
}
}
@Service
public class RagService {
@Resource
private VectorStore vectorStore;
@Resource
private ChatClient chatClient;
public String ragChat(String question) {
// 1. 检索相关文档
List<Document> docs = vectorStore.similaritySearch(
SearchRequest.query(question).withTopK(3)
);
// 2. 构建Prompt
String context = docs.stream()
.map(Document::getContent)
.collect(Collectors.joining("\n"));
String prompt = """
基于以下信息回答问题:
%s
问题:%s
""".formatted(context, question);
// 3. 调用大模型
return chatClient.call(prompt);
}
}
5.2.2 LangChain4j详解
定位: Java版LangChain,功能最全面的Java AI框架。
核心特性:
快速开始:
xml
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-spring-boot-starter</artifactId>
<version>0.35.0</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>0.35.0</version>
</dependency>
java
// AI Services - 接口式编程
interface Assistant {
@SystemMessage("你是一个Java专家,帮助开发者解决技术问题")
String chat(String userMessage);
@UserMessage("""
分析以下代码的问题:
```java
{{code}}
```
""")
String analyzeCode(@V("code") String code);
}
@Configuration
public class LangChain4jConfig {
@Bean
public Assistant assistant(@Value("${openai.api.key}") String apiKey) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(apiKey)
.modelName(GPT_4_O)
.temperature(0.7)
.build();
return AiServices.create(Assistant.class, model);
}
}
@Service
public class CodeReviewService {
@Resource
private Assistant assistant;
public String reviewCode(String code) {
return assistant.analyzeCode(code);
}
}
Tools(函数调用):
java
// 定义工具
public class DatabaseTools {
@Tool("查询用户信息")
public String getUserInfo(@P("用户ID") Long userId) {
// 实际数据库查询
User user = userMapper.selectById(userId);
return JSON.toJSONString(user);
}
@Tool("更新用户状态")
public String updateUserStatus(
@P("用户ID") Long userId,
@P("状态") String status) {
userMapper.updateStatus(userId, status);
return "更新成功";
}
}
// 配置Agent
@Bean
public Assistant agentAssistant() {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(apiKey)
.modelName(GPT_4_O)
.build();
return AiServices.builder(Assistant.class)
.chatLanguageModel(model)
.tools(new DatabaseTools()) // 注册工具
.chatMemory(MessageWindowChatMemory.withMaxMessages(10))
.build();
}
RAG完整实现:
java
@Service
public class DocumentRagService {
private final EmbeddingStore<TextSegment> embeddingStore;
private final EmbeddingModel embeddingModel;
private final ChatLanguageModel chatModel;
public DocumentRagService() {
// 1. 初始化Embedding模型
this.embeddingModel = OpenAiEmbeddingModel.builder()
.apiKey(apiKey)
.modelName("text-embedding-3-small")
.build();
// 2. 初始化向量数据库
this.embeddingStore = new InMemoryEmbeddingStore<>();
// 3. 初始化Chat模型
this.chatModel = OpenAiChatModel.builder()
.apiKey(apiKey)
.modelName(GPT_4_O)
.build();
// 4. 加载文档
loadDocuments();
}
private void loadDocuments() {
// 读取文档
Document document = FileSystemDocumentLoader.loadDocument(
"docs/knowledge.pdf",
new ApachePdfBoxDocumentParser()
);
// 文档分块
DocumentSplitter splitter = DocumentSplitters.recursive(
500, // chunk size
50 // overlap
);
List<TextSegment> segments = splitter.split(document);
// 向量化并存储
List<Embedding> embeddings = embeddingModel.embedAll(segments).content();
embeddingStore.addAll(embeddings, segments);
}
public String ragQuery(String question) {
// 1. 检索相关文档
Embedding questionEmbedding = embeddingModel.embed(question).content();
List<EmbeddingMatch<TextSegment>> matches = embeddingStore.findRelevant(
questionEmbedding,
3, // top-k
0.7 // 最小相似度
);
// 2. 构建上下文
String context = matches.stream()
.map(match -> match.embedded().text())
.collect(Collectors.joining("\n\n"));
// 3. 构建Prompt
String prompt = PromptTemplate.from("""
基于以下信息回答问题:
{{context}}
问题:{{question}}
要求:
1. 只基于提供的信息回答
2. 如果信息不足,明确说明
3. 给出信息来源
""")
.apply(Map.of(
"context", context,
"question", question
))
.text();
// 4. 生成答案
return chatModel.generate(prompt);
}
}
5.2.3 框架对比总结
| 维度 | Spring AI Alibaba | LangChain4j |
|---|---|---|
| 定位 | Spring生态集成,国内优化 | 功能全面,社区活跃 |
| 上手难度 | 简单(Spring开发者) | 中等 |
| 文档 | 中文文档完善 | 英文为主,示例丰富 |
| 模型支持 | 侧重阿里云、OpenAI兼容 | 20+主流模型 |
| 功能丰富度 | 核心功能 | 非常全面(Tools、Agent等) |
| 生态集成 | Spring Boot深度集成 | 多框架支持 |
| 企业特性 | 可观测性、限流等 | 需自行集成 |
| 适用场景 | 使用阿里云、Spring项目 | 复杂AI应用、多模型切换 |
| 开源活跃度 | 较新,快速迭代 | 非常活跃 |
选择建议:
5.3 AI工程化最佳实践
5.3.1 项目结构设计
bash
my-ai-application/
├── src/main/java/
│ ├── config/ # 配置类
│ │ ├── AiConfig.java # AI框架配置
│ │ ├── VectorStoreConfig.java
│ │ └── PromptConfig.java
│ ├── controller/ # 控制器
│ │ ├── ChatController.java
│ │ └── RagController.java
│ ├── service/ # 业务服务
│ │ ├── ChatService.java
│ │ ├── RagService.java
│ │ └── AgentService.java
│ ├── ai/ # AI核心
│ │ ├── prompt/ # Prompt管理
│ │ │ ├── PromptTemplate.java
│ │ │ └── templates/
│ │ │ ├── chat.txt
│ │ │ └── rag.txt
│ │ ├── tools/ # AI工具
│ │ │ ├── DatabaseTool.java
│ │ │ └── ApiTool.java
│ │ ├── chain/ # 执行链
│ │ │ ├── RagChain.java
│ │ │ └── AgentChain.java
│ │ └── memory/ # 记忆管理
│ │ └── ConversationMemory.java
│ ├── domain/ # 领域模型
│ ├── repository/ # 数据访问
│ └── utils/ # 工具类
├── src/main/resources/
│ ├── prompts/ # Prompt模板
│ │ ├── system.txt
│ │ ├── user.txt
│ │ └── rag.txt
│ ├── documents/ # 知识库文档
│ └── application.yml
└── src/test/
5.3.2 Prompt管理
1. 模板化管理
java
@Component
public class PromptTemplateManager {
private final Map<String, String> templates = new HashMap<>();
@PostConstruct
public void loadTemplates() {
// 从文件加载
templates.put("chat", loadFromFile("prompts/chat.txt"));
templates.put("rag", loadFromFile("prompts/rag.txt"));
templates.put("code_review", loadFromFile("prompts/code_review.txt"));
}
public String getPrompt(String templateName, Map<String, String> variables) {
String template = templates.get(templateName);
return replaceVariables(template, variables);
}
}
2. Prompt版本控制
rust
prompts/
├── v1/
│ ├── chat.txt
│ └── rag.txt
├── v2/
│ ├── chat.txt
│ └── rag.txt
└── current -> v2/
3. A/B测试框架
java
@Service
public class PromptExperimentService {
public String chatWithExperiment(String message, String userId) {
// 根据用户分组选择不同Prompt
String promptVersion = getUserGroup(userId);
String prompt = promptManager.getPrompt(promptVersion, Map.of("message", message));
// 记录实验数据
experimentTracker.track(userId, promptVersion, message);
return chatClient.call(prompt);
}
}
5.3.3 模型管理
1. 多模型策略
java
@Service
public class ModelRouter {
@Resource
private ChatClient gpt4Client; // 复杂任务
@Resource
private ChatClient gpt35Client; // 简单任务
@Resource
private ChatClient qwenClient; // 备用模型
public String chat(String message) {
// 根据复杂度路由
if (isComplexQuery(message)) {
return gpt4Client.call(message);
} else {
return gpt35Client.call(message);
}
}
private boolean isComplexQuery(String message) {
// 简单判断逻辑
return message.length() > 200 ||
message.contains("分析") ||
message.contains("设计");
}
}
2. 降级策略
java
@Service
public class FallbackService {
@Resource
private ModelRouter modelRouter;
@Resource
private CacheManager cacheManager;
public String chatWithFallback(String message) {
try {
// 主模型
return modelRouter.chat(message);
} catch (RateLimitException e) {
// 降级到备用模型
log.warn("主模型限流,切换备用模型");
return qwenClient.call(message);
} catch (Exception e) {
// 返回缓存结果
return cacheManager.getCachedResponse(message)
.orElse("服务暂时不可用,请稍后重试");
}
}
}
5.3.4 监控与可观测
1. 指标监控
java
@Aspect
@Component
public class AiMetricsAspect {
@Resource
private MeterRegistry meterRegistry;
@Around("@annotation(AiMonitored)")
public Object monitor(ProceedingJoinPoint pjp) throws Throwable {
Timer.Sample sample = Timer.start(meterRegistry);
try {
Object result = pjp.proceed();
// 记录成功
sample.stop(Timer.builder("ai.call")
.tag("method", pjp.getSignature().getName())
.tag("status", "success")
.register(meterRegistry));
return result;
} catch (Exception e) {
// 记录失败
sample.stop(Timer.builder("ai.call")
.tag("method", pjp.getSignature().getName())
.tag("status", "error")
.tag("error", e.getClass().getSimpleName())
.register(meterRegistry));
throw e;
}
}
}
2. 日志记录
java
@Component
public class AiLogger {
@Resource
private AiLogRepository logRepository;
public void logInteraction(String sessionId, String input, String output,
long latency, int tokens) {
AiLog log = AiLog.builder()
.sessionId(sessionId)
.input(input)
.output(output)
.latency(latency)
.tokens(tokens)
.cost(calculateCost(tokens))
.timestamp(LocalDateTime.now())
.build();
logRepository.save(log);
}
private BigDecimal calculateCost(int tokens) {
// 根据Token数计算成本
return BigDecimal.valueOf(tokens)
.multiply(BigDecimal.valueOf(0.00001));
}
}
3. 链路追踪
java
@Service
public class TracedChatService {
@NewSpan("ai.chat")
public String chat(@SpanTag("session.id") String sessionId,
@SpanTag("input") String message) {
Span currentSpan = tracer.currentSpan();
// 检索阶段
currentSpan.tag("stage", "retrieve");
String context = ragService.retrieve(message);
currentSpan.tag("retrieved.docs", String.valueOf(context.split("\n").length));
// 生成阶段
currentSpan.tag("stage", "generate");
String response = chatClient.call(buildPrompt(message, context));
currentSpan.tag("response.length", String.valueOf(response.length()));
return response;
}
}
5.3.5 测试策略
1. 单元测试
java
@SpringBootTest
class ChatServiceTest {
@MockBean
private ChatClient chatClient;
@Resource
private ChatService chatService;
@Test
void testChat() {
// Mock
when(chatClient.call(anyString()))
.thenReturn("这是测试回复");
// 执行
String response = chatService.chat("测试问题");
// 验证
assertThat(response).isEqualTo("这是测试回复");
verify(chatClient).call(anyString());
}
}
2. Prompt测试
java
@Test
void testPromptQuality() {
List<TestCase> testCases = loadTestCases();
for (TestCase testCase : testCases) {
String response = chatService.chat(testCase.getInput());
// 评估回复质量
double score = evaluateResponse(response, testCase.getExpectedKeywords());
assertThat(score).isGreaterThan(0.8);
}
}
private double evaluateResponse(String response, List<String> keywords) {
long matchCount = keywords.stream()
.filter(response::contains)
.count();
return (double) matchCount / keywords.size();
}
3. 集成测试
java
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class ChatControllerIntegrationTest {
@Resource
private TestRestTemplate restTemplate;
@Test
void testChatEndpoint() {
ChatRequest request = new ChatRequest();
request.setMessage("测试问题");
request.setSessionId("test-session");
ResponseEntity<ChatResponse> response = restTemplate.postForEntity(
"/ai/chat",
request,
ChatResponse.class
);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getAnswer()).isNotEmpty();
}
}
5.4 典型应用场景实战
5.4.1 场景一:智能客服系统
架构设计:
核心代码:
java
@Service
public class CustomerServiceAI {
@Resource
private ChatClient chatClient;
@Resource
private KnowledgeBaseService knowledgeBase;
@Resource
private IntentClassifier intentClassifier;
public CustomerServiceResponse handle(String userMessage, String sessionId) {
// 1. 意图识别
Intent intent = intentClassifier.classify(userMessage);
// 2. 根据意图路由
return switch (intent) {
case FAQ -> handleFAQ(userMessage);
case COMPLAINT -> handleComplaint(userMessage, sessionId);
case ORDER_QUERY -> handleOrderQuery(userMessage);
default -> handleGeneral(userMessage);
};
}
private CustomerServiceResponse handleFAQ(String question) {
// RAG检索知识库
String answer = knowledgeBase.search(question);
if (answer != null) {
return CustomerServiceResponse.builder()
.answer(answer)
.source("knowledge_base")
.confidence(0.9)
.build();
}
// 降级到大模型
return handleGeneral(question);
}
private CustomerServiceResponse handleComplaint(String message, String sessionId) {
// 创建工单
Ticket ticket = ticketService.create(message, sessionId);
// AI生成安抚话术
String response = chatClient.call(
"用户投诉:" + message + "\n请生成专业的安抚回复"
);
return CustomerServiceResponse.builder()
.answer(response)
.ticketId(ticket.getId())
.needHumanIntervention(true)
.build();
}
}
5.4.2 场景二:代码助手
功能模块:
实现示例:
java
@Service
public class CodeAssistant {
interface Assistant {
@SystemMessage("""
你是一位资深Java架构师,擅长:
1. 代码审查和优化建议
2. 设计模式应用
3. 性能优化
4. 安全漏洞检测
""")
String reviewCode(@UserMessage String code);
@UserMessage("""
请为以下方法生成单元测试:
```java
{{code}}
```
要求:
- 使用JUnit 5和Mockito
- 覆盖正常和异常情况
- 包含边界条件测试
""")
String generateTest(@V("code") String code);
}
@Resource
private Assistant assistant;
public CodeReviewResult review(String code) {
String review = assistant.reviewCode(code);
return parseReviewResult(review);
}
public String generateUnitTest(String methodCode) {
return assistant.generateTest(methodCode);
}
}
5.4.3 场景三:文档问答系统
系统架构:
完整实现:
java
@Service
public class DocumentQAService {
@Resource
private EmbeddingModel embeddingModel;
@Resource
private VectorStore vectorStore;
@Resource
private ChatClient chatClient;
/**
* 文档导入
*/
public void importDocuments(List<MultipartFile> files) {
files.forEach(file -> {
// 1. 解析文档
Document doc = parseDocument(file);
// 2. 文档分块
List<TextSegment> segments = splitDocument(doc);
// 3. 向量化
List<Embedding> embeddings = embeddingModel.embedAll(segments).content();
// 4. 存储
vectorStore.addAll(embeddings, segments);
});
}
/**
* 问答
*/
public QAResponse query(String question) {
// 1. 检索相关文档
List<Document> relevantDocs = retrieveRelevantDocs(question, 5);
// 2. 重排序
List<Document> rerankedDocs = rerank(question, relevantDocs);
// 3. 构建Prompt
String prompt = buildQAPrompt(question, rerankedDocs);
// 4. 生成答案
String answer = chatClient.call(prompt);
// 5. 提取引用
List<Citation> citations = extractCitations(rerankedDocs);
return QAResponse.builder()
.answer(answer)
.citations(citations)
.confidence(calculateConfidence(rerankedDocs))
.build();
}
private List<Document> retrieveRelevantDocs(String query, int topK) {
Embedding queryEmbedding = embeddingModel.embed(query).content();
return vectorStore.findRelevant(queryEmbedding, topK, 0.7)
.stream()
.map(EmbeddingMatch::embedded)
.map(segment -> new Document(segment.text()))
.collect(Collectors.toList());
}
private String buildQAPrompt(String question, List<Document> docs) {
String context = docs.stream()
.map(Document::text)
.collect(Collectors.joining("\n\n---\n\n"));
return """
# 任务
基于以下文档内容回答用户问题。
# 文档内容
%s
# 用户问题
%s
# 要求
1. 仅基于提供的文档内容回答
2. 如果文档中没有相关信息,明确说明
3. 给出具体的文档引用
4. 回答要准确、简洁
""".formatted(context, question);
}
}