文本生成图片

This commit is contained in:
spllzh
2025-10-18 10:48:46 +08:00
parent 8e640e03c8
commit 9b2e08593c
25 changed files with 356 additions and 4 deletions

View File

@@ -4,10 +4,18 @@ import ai.djl.util.JsonUtils;
import com.alibaba.dashscope.aigc.imagesynthesis.ImageSynthesis;
import com.alibaba.dashscope.aigc.imagesynthesis.ImageSynthesisParam;
import com.alibaba.dashscope.aigc.imagesynthesis.ImageSynthesisResult;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversation;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationParam;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationResult;
import com.alibaba.dashscope.common.MultiModalMessage;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.exception.UploadFileException;
import com.alibaba.dashscope.utils.Constants;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rj.controller.TextModelController;
import com.rj.entity.ImageModel;
import com.rj.mapper.ImageModelMapper;
import com.rj.service.IImageModelService;
@@ -20,9 +28,7 @@ import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.*;
/**
* 图像模型服务实现类
@@ -276,7 +282,8 @@ public class ImageModelServiceImpl extends ServiceImpl<ImageModelMapper, ImageMo
} else {
log.warn("AI处理结果为空或无效");
}
imageModel.setImageType("remove_water");
// 6. 保存处理记录
boolean saveResult = this.updateById(imageModel);
if (!saveResult) {
@@ -887,4 +894,195 @@ public class ImageModelServiceImpl extends ServiceImpl<ImageModelMapper, ImageMo
}
}
/**
* 文本生成图像
*
* 根据文本提示词生成图像,包括:
* - 调用AI图像生成服务
* - 处理生成结果
* - 保存生成记录
*
* @param request 文本生成图像请求参数
* @return 生成结果包含图像URL等信息
*/
@Override
public Map<String, Object> generateImageByText(TextModelController.ImageProcessingRequest request) {
try {
log.info("开始文本生成图像,提示词: {},模型: {}", request.getPrompt(), request.getModel());
Map<String, Object> result = new HashMap<>();
// 1. 参数验证
if (request.getPrompt() == null || request.getPrompt().trim().isEmpty()) {
throw new IllegalArgumentException("提示词不能为空");
}
if (request.getModel() == null || request.getModel().trim().isEmpty()) {
throw new IllegalArgumentException("模型名称不能为空");
}
// 2. 调用阿里云图像生成API
String apiKey = System.getenv("DASHSCOPE_API_KEY");
if (apiKey == null || apiKey.trim().isEmpty()) {
throw new RuntimeException("未配置DASHSCOPE_API_KEY环境变量");
}
// 3. 设置API基础URL参考测试类
Constants.baseHttpApiUrl = "https://dashscope.aliyuncs.com/api/v1";
// 4. 构建多模态对话参数(参考测试类)
MultiModalConversation conv = new MultiModalConversation();
MultiModalMessage userMessage = MultiModalMessage.builder()
.role(Role.USER.getValue())
.content(Arrays.asList(
Collections.singletonMap("text", request.getPrompt())
)).build();
// 5. 构建参数(参考测试类)
Map<String, Object> parameters = new HashMap<>();
parameters.put("watermark", true);
parameters.put("prompt_extend", true);
parameters.put("negative_prompt", "");
parameters.put("size", "1328*1328"); // 使用阿里云允许的尺寸
MultiModalConversationParam param = MultiModalConversationParam.builder()
.apiKey(apiKey)
.model("qwen-image-plus") // 使用固定的模型名称
.messages(Collections.singletonList(userMessage))
.parameters(parameters)
.build();
// 6. 调用图像生成服务
MultiModalConversationResult conversationResult = null;
try {
log.info("开始调用阿里云多模态对话API参数: {}", param);
conversationResult = conv.call(param);
log.info("多模态对话API调用完成结果: {}", JsonUtils.toJson(conversationResult));
} catch (ApiException | NoApiKeyException | UploadFileException e) {
log.error("阿里云多模态对话API调用失败", e);
throw new RuntimeException("图像生成API调用失败: " + e.getMessage(), e);
}
// 7. 处理生成结果
if (conversationResult != null && conversationResult.getOutput() != null &&
conversationResult.getOutput().getChoices() != null &&
!conversationResult.getOutput().getChoices().isEmpty()) {
log.info("图像生成成功,开始处理结果");
log.info("完整API返回结果: {}", JsonUtils.toJson(conversationResult));
// 从多模态对话结果中提取图像URL
String generatedImageUrl = null;
try {
// 根据您提供的返回结果格式解析图像URL
// 返回格式:{"output": {"choices": [{"message": {"content": [{"image": "url"}]}}]}}
var choices = conversationResult.getOutput().getChoices();
if (!choices.isEmpty()) {
var message = choices.get(0).getMessage();
var content = message.getContent();
log.info("API返回的content: {}", JsonUtils.toJson(content));
// 解析content数组中的image字段
if (content != null && !content.isEmpty()) {
// content是一个List包含多个内容项
for (Object contentItem : content) {
if (contentItem instanceof Map) {
@SuppressWarnings("unchecked")
Map<String, Object> contentMap = (Map<String, Object>) contentItem;
if (contentMap.containsKey("image")) {
generatedImageUrl = (String) contentMap.get("image");
log.info("提取到图像URL: {}", generatedImageUrl);
break;
}
}
}
}
}
if (generatedImageUrl == null || generatedImageUrl.trim().isEmpty()) {
log.warn("未能从API返回结果中提取图像URL完整结果: {}", JsonUtils.toJson(conversationResult));
throw new RuntimeException("未能从API返回结果中提取图像URL");
}
} catch (Exception e) {
log.error("解析API返回结果失败", e);
throw new RuntimeException("解析API返回结果失败: " + e.getMessage(), e);
}
if (generatedImageUrl != null && !generatedImageUrl.trim().isEmpty()) {
try {
log.info("开始下载生成的图片: {}", generatedImageUrl);
// 下载图片到字节数组
byte[] imageBytes = downloadImageToBytes(generatedImageUrl);
log.info("图片下载成功,大小: {} bytes", imageBytes.length);
// 生成唯一文件名
String resultFileName = generateUniqueFileName("png");
// 上传到MinIO
String resultImageMinIOUrl = minIOService.uploadFile(imageBytes, resultFileName, "image/png");
log.info("图片上传到MinIO成功: {}", resultImageMinIOUrl);
// 生成7天临时访问链接
String resultImageTempUrl = minIOService.generateTempUrl(resultFileName);
log.info("生成7天临时访问链接: {}", resultImageTempUrl);
// 保存图像模型记录到数据库
ImageModel imageModel = new ImageModel();
imageModel.setImageName(request.getImageName() != null ? request.getImageName() : "文本生成图像");
imageModel.setOwnerName(request.getOwnerName());
imageModel.setOwnerPhone(request.getOwnerPhone());
imageModel.setImageType("text_to_image");
imageModel.setPrompt(request.getPrompt());
imageModel.setModelName(request.getModel());
imageModel.setResultImageUrl(resultImageMinIOUrl);
imageModel.setResultImageTempUrl(resultImageTempUrl);
imageModel.setCreateTime(LocalDateTime.now());
imageModel.setUpdateTime(LocalDateTime.now());
// 保存到数据库
boolean saveResult = this.saveImageModel(imageModel);
if (!saveResult) {
log.error("保存文本生成图像记录失败");
throw new RuntimeException("保存文本生成图像记录失败");
}
// 构建返回结果
result.put("success", true);
result.put("message", "文本生成图像处理完成");
result.put("imageCount", 1);
result.put("imageUrl", resultImageTempUrl);
result.put("imageMinIOUrl", resultImageMinIOUrl);
result.put("prompt", request.getPrompt());
result.put("model", request.getModel());
result.put("requestId", imageModel.getUuid());
result.put("timestamp", LocalDateTime.now());
log.info("文本生成图像处理完成图像已保存到数据库ID: {}", imageModel.getUuid());
} catch (Exception e) {
log.error("处理生成的图片失败", e);
throw new RuntimeException("处理生成的图片失败: " + e.getMessage(), e);
}
} else {
log.warn("生成的图片URL为空");
throw new RuntimeException("生成的图片URL为空");
}
} else {
log.warn("图像生成结果为空");
throw new RuntimeException("图像生成结果为空");
}
return result;
} catch (Exception e) {
log.error("文本生成图像异常", e);
throw new RuntimeException("文本生成图像失败: " + e.getMessage(), e);
}
}
}