【Spring AI实战】第11章 多媒体AI能力实战
·
1. 图像识别、图文问答实战
我来分享一个完整的Spring AI图像识别与图文问答实战指南,包含代码示例和最佳实践。
项目环境搭建
1.1 依赖配置
<!-- pom.xml -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
# application.yml
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
chat:
options:
model: gpt-4-vision-preview
temperature: 0.7
基础图像识别
2.1 图像描述生成
@Service
public class ImageDescriptionService {
@Autowired
private OpenAiChatClient chatClient;
public String describeImage(String imageUrl) {
UserMessage userMessage = new UserMessage(
"请详细描述这张图片的内容",
List.of(new Media(MimeTypeUtils.IMAGE_PNG, imageUrl))
);
ChatResponse response = chatClient.call(
new Prompt(List.of(userMessage))
);
return response.getResult().getOutput().getContent();
}
public String describeImage(MultipartFile imageFile) throws IOException {
String base64Image = Base64.getEncoder()
.encodeToString(imageFile.getBytes());
UserMessage userMessage = new UserMessage(
"描述这张图片",
List.of(new Media(MimeTypeUtils.IMAGE_PNG,
"data:image/png;base64," + base64Image))
);
ChatResponse response = chatClient.call(
new Prompt(List.of(userMessage))
);
return response.getResult().getOutput().getContent();
}
}
2.2 图像分类服务
@Service
public class ImageClassificationService {
private static final Map<String, String> CATEGORY_PROMPTS = Map.of(
"SCENE", "这是一张什么场景的照片?",
"OBJECT", "图片中的主要物体是什么?",
"EMOTION", "这张图片传达了什么情感?",
"ACTION", "图片中正在发生什么动作?"
);
public Map<String, String> classifyImage(String imageUrl) {
Map<String, String> results = new HashMap<>();
for (Map.Entry<String, String> entry : CATEGORY_PROMPTS.entrySet()) {
UserMessage userMessage = new UserMessage(
entry.getValue(),
List.of(new Media(MimeTypeUtils.IMAGE_PNG, imageUrl))
);
ChatResponse response = chatClient.call(
new Prompt(List.of(userMessage))
);
results.put(entry.getKey(),
response.getResult().getOutput().getContent());
}
return results;
}
}
图文问答系统
3.1 问答服务实现
@Service
public class VisualQAService {
@Autowired
private OpenAiChatClient chatClient;
public String answerQuestion(String imageUrl, String question) {
// 构建包含图像和问题的消息
UserMessage userMessage = new UserMessage(
question,
List.of(new Media(MimeTypeUtils.IMAGE_PNG, imageUrl))
);
ChatResponse response = chatClient.call(
new Prompt(List.of(userMessage))
);
return response.getResult().getOutput().getContent();
}
public VisualQAResponse analyzeWithContext(String imageUrl,
String question,
String context) {
String systemPrompt = """
你是一个视觉问答助手。请基于提供的图像和上下文信息回答问题。
上下文:%s
如果图像内容与上下文矛盾,以图像为准。
""".formatted(context);
SystemPrompt systemMessage = new SystemPrompt(systemPrompt);
UserMessage userMessage = new UserMessage(
question,
List.of(new Media(MimeTypeUtils.IMAGE_PNG, imageUrl))
);
ChatResponse response = chatClient.call(
new Prompt(List.of(systemMessage, userMessage))
);
return VisualQAResponse.builder()
.question(question)
.answer(response.getResult().getOutput().getContent())
.confidence(extractConfidence(response))
.build();
}
private double extractConfidence(ChatResponse response) {
// 从响应中提取置信度(示例逻辑)
String content = response.getResult().getOutput().getContent();
if (content.contains("确定") || content.contains("肯定")) {
return 0.9;
} else if (content.contains("可能") || content.contains("大概")) {
return 0.7;
} else {
return 0.5;
}
}
@Data
@Builder
public static class VisualQAResponse {
private String question;
private String answer;
private double confidence;
private LocalDateTime timestamp;
}
}
3.2 多轮对话支持
@Service
public class MultiTurnVisualChatService {
private final Map<String, List<Message>> conversationHistory =
new ConcurrentHashMap<>();
public String chat(String sessionId, String imageUrl, String userMessage) {
List<Message> history = conversationHistory
.computeIfAbsent(sessionId, k -> new ArrayList<>());
// 如果是第一次消息,添加图像
if (history.isEmpty() && imageUrl != null) {
history.add(new UserMessage(
"这是我们要讨论的图片",
List.of(new Media(MimeTypeUtils.IMAGE_PNG, imageUrl))
));
}
// 添加用户问题
history.add(new UserMessage(userMessage));
// 限制历史记录长度
if (history.size() > 10) {
history = history.subList(history.size() - 10, history.size());
}
ChatResponse response = chatClient.call(new Prompt(history));
String assistantResponse = response.getResult()
.getOutput().getContent();
// 保存助手回复
history.add(new AssistantMessage(assistantResponse));
conversationHistory.put(sessionId, history);
return assistantResponse;
}
public void clearHistory(String sessionId) {
conversationHistory.remove(sessionId);
}
}
REST API 控制器
@RestController
@RequestMapping("/api/vision")
public class VisionController {
@Autowired
private ImageDescriptionService descriptionService;
@Autowired
private VisualQAService qaService;
@Autowired
private MultiTurnVisualChatService chatService;
@PostMapping("/describe")
public ResponseEntity<String> describeImage(
@RequestParam("imageUrl") String imageUrl) {
return ResponseEntity.ok(
descriptionService.describeImage(imageUrl)
);
}
@PostMapping("/describe/upload")
public ResponseEntity<String> describeUploadedImage(
@RequestParam("file") MultipartFile file) throws IOException {
return ResponseEntity.ok(
descriptionService.describeImage(file)
);
}
@PostMapping("/qa")
public ResponseEntity<VisualQAResponse> visualQA(
@RequestBody VisualQARequest request) {
return ResponseEntity.ok(
qaService.answerQuestion(
request.getImageUrl(),
request.getQuestion()
)
);
}
@PostMapping("/chat")
public ResponseEntity<String> visualChat(
@RequestBody VisualChatRequest request) {
return ResponseEntity.ok(
chatService.chat(
request.getSessionId(),
request.getImageUrl(),
request.getMessage()
)
);
}
@Data
public static class VisualQARequest {
private String imageUrl;
private String question;
}
@Data
public static class VisualChatRequest {
private String sessionId;
private String imageUrl;
private String message;
}
}
高级功能:图像分析报告
@Service
public class ImageAnalysisReportService {
public AnalysisReport generateReport(String imageUrl) {
String description = describeImage(imageUrl);
Map<String, String> classifications = classifyImage(imageUrl);
List<String> tags = extractTags(imageUrl);
String summary = generateSummary(description, classifications);
return AnalysisReport.builder()
.description(description)
.classifications(classifications)
.tags(tags)
.summary(summary)
.analysisTime(LocalDateTime.now())
.build();
}
private List<String> extractTags(String imageUrl) {
UserMessage userMessage = new UserMessage(
"提取这张图片的关键标签,用逗号分隔",
List.of(new Media(MimeTypeUtils.IMAGE_PNG, imageUrl))
);
ChatResponse response = chatClient.call(
new Prompt(List.of(userMessage))
);
String tagsStr = response.getResult().getOutput().getContent();
return Arrays.stream(tagsStr.split(","))
.map(String::trim)
.collect(Collectors.toList());
}
private String generateSummary(String description,
Map<String, String> classifications) {
String prompt = """
基于以下信息生成图片分析摘要:
描述:%s
分类:%s
请生成一段简洁的总结,不超过100字。
""".formatted(description, classifications);
ChatResponse response = chatClient.call(
new Prompt(prompt)
);
return response.getResult().getOutput().getContent();
}
@Data
@Builder
public static class AnalysisReport {
private String description;
private Map<String, String> classifications;
private List<String> tags;
private String summary;
private LocalDateTime analysisTime;
}
}
性能优化与缓存
@Service
public class CachedVisionService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final long CACHE_TTL = 3600; // 1小时
public String describeImageWithCache(String imageUrl) {
String cacheKey = "image:desc:" + hashImageUrl(imageUrl);
// 尝试从缓存获取
String cached = (String) redisTemplate.opsForValue().get(cacheKey);
if (cached != null) {
return cached;
}
// 调用API
String description = descriptionService.describeImage(imageUrl);
// 存入缓存
redisTemplate.opsForValue().set(
cacheKey,
description,
CACHE_TTL,
TimeUnit.SECONDS
);
return description;
}
private String hashImageUrl(String url) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(url.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(hash);
} catch (NoSuchAlgorithmException e) {
return String.valueOf(url.hashCode());
}
}
}
错误处理与监控
@ControllerAdvice
public class VisionExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleVisionException(Exception ex) {
ErrorResponse error = ErrorResponse.builder()
.timestamp(LocalDateTime.now())
.status(HttpStatus.INTERNAL_SERVER_ERROR.value())
.error("Vision Processing Error")
.message(ex.getMessage())
.path(getRequestPath())
.build();
// 记录监控指标
Metrics.counter("vision.api.errors").increment();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(error);
}
@Data
@Builder
public static class ErrorResponse {
private LocalDateTime timestamp;
private int status;
private String error;
private String message;
private String path;
}
}
测试用例
@SpringBootTest
class VisionServiceTest {
@Autowired
private VisualQAService qaService;
@Test
void testImageDescription() {
String imageUrl = "https://example.com/image.jpg";
String description = qaService.answerQuestion(
imageUrl,
"描述这张图片"
);
assertNotNull(description);
assertTrue(description.length() > 10);
}
@Test
void testComplexQuestion() {
String imageUrl = "https://example.com/chart.png";
String answer = qaService.answerQuestion(
imageUrl,
"这张图表展示了什么趋势?最大值和最小值分别是多少?"
);
assertNotNull(answer);
assertTrue(answer.contains("趋势") ||
answer.contains("增长") ||
answer.contains("下降"));
}
}
部署配置
# application-prod.yml
spring:
ai:
openai:
base-url: https://api.openai.com/v1
chat:
options:
model: gpt-4-vision-preview
max-tokens: 1000
management:
endpoints:
web:
exposure:
include: health,metrics,prometheus
metrics:
export:
prometheus:
enabled: true
resilience4j:
ratelimiter:
instances:
vision-api:
limit-for-period: 10
limit-refresh-period: 1s
timeout-duration: 0
最佳实践建议
- 图像预处理 :压缩大图像,限制分辨率
- 速率限制 :实现API调用频率控制
- 成本控制 :监控token使用量
- 异步处理 :对耗时操作使用异步调用
- 结果缓存 :缓存常见图像的识别结果
- 错误重试 :实现指数退避重试机制
- 内容审核 :添加敏感内容检测
这个实战指南提供了从基础到高级的完整实现,你可以根据具体需求进行调整和扩展。
2. 文档解析、表格提取、智能总结
我来为你详细介绍 Spring AI 在文档解析、表格提取和智能总结方面的功能。
1. 文档解析
Spring AI 提供了多种文档解析器,支持多种格式:
支持的文档格式:
// 常见解析器
- PdfDocumentReader // PDF 文件
- TikaDocumentReader // 多种格式(docx, pptx, xlsx, html等)
- TextDocumentReader // 纯文本文件
- MarkdownDocumentReader // Markdown 文件
- JsonDocumentReader // JSON 文件
使用示例:
@Bean
public VectorStore vectorStore(EmbeddingModel embeddingModel) {
// 解析 PDF 文档
DocumentReader pdfReader = new PdfDocumentReader("path/to/document.pdf");
List<Document> documents = pdfReader.read();
// 解析多种格式文档
TikaDocumentReader tikaReader = new TikaDocumentReader(
ResourceUtils.getFile("classpath:documents/")
);
return new SimpleVectorStore(embeddingModel);
}
2. 表格提取
使用 Tika 提取表格:
import org.springframework.ai.reader.tika.TikaDocumentReader;
import org.springframework.ai.document.Document;
public class TableExtractor {
public List<TableData> extractTables(String filePath) {
TikaDocumentReader reader = new TikaDocumentReader(filePath);
List<Document> documents = reader.read();
// 使用正则表达式或自定义逻辑提取表格
return extractTableData(documents);
}
private List<TableData> extractTableData(List<Document> docs) {
List<TableData> tables = new ArrayList<>();
for (Document doc : docs) {
String content = doc.getContent();
// 提取表格内容(示例:简单的 CSV 格式表格)
Pattern tablePattern = Pattern.compile("\\|.*?\\|", Pattern.DOTALL);
Matcher matcher = tablePattern.matcher(content);
while (matcher.find()) {
tables.add(parseTable(matcher.group()));
}
}
return tables;
}
}
使用 DocumentTransformers 处理表格:
@Bean
public DocumentTransformer tableExtractorTransformer() {
return documents -> {
return documents.stream()
.map(doc -> {
String content = doc.getContent();
// 提取并格式化表格数据
String extractedTables = extractAndFormatTables(content);
return new Document(
doc.getContent() + "\n\n提取的表格数据:\n" + extractedTables,
doc.getMetadata()
);
})
.collect(Collectors.toList());
};
}
3. 智能总结
使用 ChatClient 进行文档总结:
@Service
public class DocumentSummaryService {
private final ChatClient chatClient;
public DocumentSummaryService(ChatClient chatClient) {
this.chatClient = chatClient;
}
public String summarizeDocument(String documentContent) {
String prompt = """
请对以下文档内容进行智能总结:
要求:
1. 提取核心要点
2. 保持关键数据
3. 总结主要结论
4. 限制在300字以内
文档内容:
%s
""".formatted(documentContent);
return chatClient.call(prompt);
}
public Map<String, String> structuredSummary(Document document) {
String prompt = """
请以结构化格式总结以下文档:
要求返回JSON格式:
{
"title": "文档标题",
"keyPoints": ["要点1", "要点2", ...],
"summary": "详细总结",
"keywords": ["关键词1", "关键词2", ...],
"actionItems": ["行动项1", "行动项2", ...]
}
文档内容:
%s
""".formatted(document.getContent());
String jsonResponse = chatClient.call(prompt);
return parseJsonResponse(jsonResponse);
}
}
批量文档处理管道:
@Configuration
public class DocumentProcessingPipeline {
@Bean
public Function<List<Document>, List<Document>> documentProcessingPipeline() {
return documents -> {
// 1. 文档解析和清理
DocumentTransformer cleaner = new ContentFormattingTransformer();
// 2. 表格提取
DocumentTransformer tableExtractor = new TableExtractionTransformer();
// 3. 文本分割(用于向量化)
DocumentTransformer splitter = new TokenTextSplitter(
1000, // 最大token数
200 // 重叠token数
);
// 4. 应用转换链
return documents.stream()
.map(cleaner::apply)
.map(tableExtractor::apply)
.flatMap(doc -> splitter.apply(doc).stream())
.collect(Collectors.toList());
};
}
}
4. 完整示例:端到端文档处理
@Service
public class CompleteDocumentProcessor {
private final ChatClient chatClient;
private final VectorStore vectorStore;
private final EmbeddingModel embeddingModel;
public CompleteDocumentProcessor(ChatClient chatClient,
VectorStore vectorStore,
EmbeddingModel embeddingModel) {
this.chatClient = chatClient;
this.vectorStore = vectorStore;
this.embeddingModel = embeddingModel;
}
public ProcessingResult processDocument(String filePath) {
// 1. 解析文档
DocumentReader reader = new TikaDocumentReader(filePath);
List<Document> documents = reader.read();
// 2. 提取表格
List<TableData> tables = extractTables(documents);
// 3. 生成智能总结
String fullText = documents.stream()
.map(Document::getContent)
.collect(Collectors.joining("\n"));
String summary = generateSummary(fullText);
// 4. 向量化存储
List<Document> processedDocs = new TokenTextSplitter(1000, 200)
.apply(documents);
vectorStore.add(processedDocs);
// 5. 返回结果
return new ProcessingResult(
documents,
tables,
summary,
processedDocs.size()
);
}
private String generateSummary(String text) {
String prompt = """
你是一个专业的文档分析助手。请完成以下任务:
1. 文档总结(不超过200字)
2. 提取3-5个关键点
3. 识别重要数据/数字
4. 如果有表格,总结表格主要内容
文档内容:
%s
""".formatted(text.substring(0, Math.min(text.length(), 4000)));
return chatClient.call(prompt);
}
public String queryDocument(String question) {
// 使用向量搜索找到相关文档片段
List<Document> relevantDocs = vectorStore.similaritySearch(
SearchRequest.query(question).withTopK(3)
);
String context = relevantDocs.stream()
.map(Document::getContent)
.collect(Collectors.joining("\n\n"));
String prompt = """
基于以下文档内容回答问题:
文档内容:
%s
问题:%s
要求:如果文档中有表格数据,请引用表格内容。
""".formatted(context, question);
return chatClient.call(prompt);
}
}
5. 配置建议
# application.yml
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
chat:
options:
model: gpt-4
temperature: 0.1 # 降低创造性,提高准确性
vectorstore:
pgvector:
enabled: true
initialize-schema: true
document:
splitter:
chunk-size: 1000
chunk-overlap: 200
6. 最佳实践
- 分块策略 :根据文档类型调整分块大小
- 技术文档:500-800 tokens
- 法律文档:200-400 tokens
- 普通文章:1000 tokens
- 表格处理 :
- 将表格转换为Markdown格式存储
- 为表格添加描述性元数据
- 考虑使用专门的表格识别库(如Tabula for PDF)
- 总结优化 :
- 使用few-shot提示提高总结质量
- 为不同文档类型定制总结模板
- 实现增量总结(用于长文档)
- 性能考虑 :
- 对大文档实现流式处理
- 缓存处理结果
- 并行处理多个文档
Spring AI 的这些功能可以很好地集成到企业文档处理流程中,实现自动化的文档解析、信息提取和智能分析。
3. 文本翻译、内容润色、代码优化AI工具开发
我来帮你设计一个基于Spring AI的AI工具开发方案,包含文本翻译、内容润色和代码优化三大功能。
项目架构设计
# Maven依赖
dependencies:
- Spring Boot 3.x
- Spring AI (支持OpenAI/Azure OpenAI/本地模型)
- Spring Web
- Spring Validation
核心功能实现
2.1 统一AI服务接口
@Service
public class AIService {
@Autowired
private ChatClient chatClient;
// 文本翻译
public String translate(String text, String sourceLang, String targetLang) {
String prompt = String.format("""
请将以下%s文本翻译成%s:
原文:%s
要求:
1. 保持原意准确
2. 符合目标语言表达习惯
3. 专业术语准确
""", sourceLang, targetLang, text);
return chatClient.call(prompt);
}
// 内容润色
public String polishContent(String text, PolishStyle style) {
String stylePrompt = switch(style) {
case FORMAL -> "正式、专业的语气";
case CASUAL -> "轻松、口语化的语气";
case ACADEMIC -> "学术、严谨的语气";
case CONCISE -> "简洁、精炼的表达";
};
String prompt = String.format("""
请润色以下文本,要求:
1. 保持原意不变
2. 使用%s
3. 优化语法和表达
4. 提升可读性
原文:%s
""", stylePrompt, text);
return chatClient.call(prompt);
}
// 代码优化
public String optimizeCode(String code, String language, OptimizationGoal goal) {
String goalPrompt = switch(goal) {
case PERFORMANCE -> "提升性能,优化算法复杂度";
case READABILITY -> "提高代码可读性和可维护性";
case SECURITY -> "增强安全性,修复潜在漏洞";
case BEST_PRACTICE -> "遵循最佳实践和设计模式";
};
String prompt = String.format("""
请优化以下%s代码:
%s
优化目标:%s
要求:
1. 提供优化后的完整代码
2. 说明优化点和原因
3. 保持原有功能不变
4. 添加必要的注释
""", language, code, goalPrompt);
return chatClient.call(prompt);
}
}
2.2 RESTful API接口
@RestController
@RequestMapping("/api/ai")
public class AIController {
@PostMapping("/translate")
public ResponseEntity<TranslationResponse> translate(
@Valid @RequestBody TranslationRequest request) {
String result = aiService.translate(
request.getText(),
request.getSourceLang(),
request.getTargetLang()
);
return ResponseEntity.ok(new TranslationResponse(result));
}
@PostMapping("/polish")
public ResponseEntity<PolishResponse> polish(
@Valid @RequestBody PolishRequest request) {
String result = aiService.polishContent(
request.getText(),
request.getStyle()
);
return ResponseEntity.ok(new PolishResponse(result));
}
@PostMapping("/optimize-code")
public ResponseEntity<CodeOptimizationResponse> optimizeCode(
@Valid @RequestBody CodeOptimizationRequest request) {
String result = aiService.optimizeCode(
request.getCode(),
request.getLanguage(),
request.getGoal()
);
return ResponseEntity.ok(new CodeOptimizationResponse(result));
}
}
2.3 配置类
@Configuration
public class AIConfig {
@Value("${spring.ai.openai.api-key}")
private String apiKey;
@Value("${spring.ai.openai.model}")
private String model;
@Bean
public OpenAiChatClient openAiChatClient() {
OpenAiApi openAiApi = new OpenAiApi("https://api.openai.com/v1", apiKey);
return new OpenAiChatClient(openAiApi, model);
}
}
高级功能扩展
3.1 批量处理服务
@Service
public class BatchAIService {
public List<TranslationResult> batchTranslate(
List<String> texts,
String sourceLang,
String targetLang) {
return texts.parallelStream()
.map(text -> {
try {
String translated = aiService.translate(text, sourceLang, targetLang);
return TranslationResult.success(text, translated);
} catch (Exception e) {
return TranslationResult.failure(text, e.getMessage());
}
})
.collect(Collectors.toList());
}
}
3.2 历史记录与缓存
@Entity
@Table(name = "ai_operations")
public class AIOperation {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String operationType; // TRANSLATE, POLISH, OPTIMIZE
private String input;
private String output;
private String modelUsed;
private LocalDateTime createdAt;
@PrePersist
protected void onCreate() {
createdAt = LocalDateTime.now();
}
}
3.3 流式响应(SSE)
@GetMapping(value = "/stream/translate", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamTranslate(
@RequestParam String text,
@RequestParam String targetLang) {
return Flux.create(sink -> {
// 模拟流式输出
String[] words = text.split(" ");
for (int i = 0; i < words.length; i++) {
sink.next("翻译进度: " + (i + 1) + "/" + words.length);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
sink.error(e);
}
}
sink.complete();
});
}
应用配置文件
# application.yml
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
model: gpt-4
temperature: 0.7
max-tokens: 2000
datasource:
url: jdbc:mysql://localhost:3306/ai_tools
username: root
password: password
jpa:
hibernate:
ddl-auto: update
server:
port: 8080
# 自定义配置
ai:
tools:
max-input-length: 5000
enable-cache: true
default-language: zh-CN
rate-limit:
requests-per-minute: 60
前端示例(Vue.js)
<template>
<div class="ai-tools">
<!-- 翻译功能 -->
<div class="tool-card">
<h3>文本翻译</h3>
<select v-model="sourceLang">
<option value="zh">中文</option>
<option value="en">英文</option>
<option value="ja">日文</option>
</select>
<select v-model="targetLang">
<option value="en">英文</option>
<option value="zh">中文</option>
<option value="ja">日文</option>
</select>
<textarea v-model="textToTranslate" placeholder="输入要翻译的文本"></textarea>
<button @click="translate">翻译</button>
<div class="result">{{ translationResult }}</div>
</div>
<!-- 代码优化 -->
<div class="tool-card">
<h3>代码优化</h3>
<select v-model="codeLanguage">
<option value="java">Java</option>
<option value="python">Python</option>
<option value="javascript">JavaScript</option>
</select>
<textarea v-model="codeToOptimize" placeholder="输入代码"></textarea>
<button @click="optimizeCode">优化代码</button>
<pre class="code-result">{{ optimizedCode }}</pre>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import axios from 'axios'
const textToTranslate = ref('')
const translationResult = ref('')
const codeToOptimize = ref('')
const optimizedCode = ref('')
const translate = async () => {
const response = await axios.post('/api/ai/translate', {
text: textToTranslate.value,
sourceLang: 'zh',
targetLang: 'en'
})
translationResult.value = response.data.result
}
const optimizeCode = async () => {
const response = await axios.post('/api/ai/optimize-code', {
code: codeToOptimize.value,
language: 'java',
goal: 'PERFORMANCE'
})
optimizedCode.value = response.data.result
}
</script>
部署与监控
# Dockerfile
FROM openjdk:17-jdk-slim
WORKDIR /app
COPY target/ai-tools.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
# docker-compose.yml
version: '3.8'
services:
ai-tools:
build: .
ports:
- "8080:8080"
environment:
- OPENAI_API_KEY=${OPENAI_API_KEY}
- SPRING_PROFILES_ACTIVE=prod
depends_on:
- mysql
- redis
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: ai_tools
redis:
image: redis:alpine
增强功能建议
- 多模型支持 :集成多个AI提供商(OpenAI、Claude、本地模型)
- 自定义提示词模板 :允许用户保存和重用提示词
- API密钥管理 :多用户API密钥轮询使用
- 质量评估 :对AI输出进行评分和反馈收集
- 插件系统 :支持自定义功能扩展
- 团队协作 :共享历史记录和模板
这个方案提供了完整的Spring AI工具开发框架,你可以根据具体需求进行调整和扩展。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)