Java结合大模型文生图实战

Java结合大模型文生图实战

导读:随着AIGC技术的快速发展,文生图已成为软件开发中的热门功能。本文将带你从零开始,使用Java结合OpenAI的DALL-E模型,构建一个完整的文生图系统。

一、技术背景与选型

2023年全球AIGC市场规模达到150亿美元,预计2025年将突破500亿美元。Java作为企业级开发的主力语言,与AI大模型的结合正成为开发者关注的焦点。

为什么选择OpenAI DALL-E?

复制代码
✅ 技术成熟:API稳定,文档完善
✅ 效果优质:生成图片质量高
✅ 集成便捷:提供官方Java SDK
✅ 商业友好:清晰的定价模型

二、系统架构设计

六层架构体系

复制代码
1️⃣ 表现层:React/Vue前端
2️⃣ API网关层:认证授权、流量管理
3️⃣ 应用服务层:业务逻辑编排
4️⃣ 业务逻辑层:核心算法处理
5️⃣ 数据层:MySQL/Redis/MongoDB
6️⃣ AI服务层:OpenAI DALL-E调用

三、核心代码实现

核心依赖配置

xml 复制代码
<dependencies>
    <!-- Spring Boot Webflux -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>

    <!-- OpenAI Client -->
    <dependency>
        <groupId>com.theokanning.openai-gpt3-java</groupId>
        <artifactId>service</artifactId>
        <version>0.17.0</version>
    </dependency>

    <!-- Caffeine缓存 -->
    <dependency>
        <groupId>com.github.ben-manes.caffeine</groupId>
        <artifactId>caffeine</artifactId>
    </dependency>
</dependencies>

核心类图

五个核心类

复制代码
🔹 ImageController:处理HTTP请求
🔹 OpenAiImageService:调用OpenAI API
🔹 ImageRequest:请求参数封装
🔹 ImageResponse:响应结果封装
🔹 CacheService:缓存管理

核心代码示例

ImageRequest - 请求模型

arduino 复制代码
package com.example.textToImage.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.validation.constraints.*;

/**
 * 文生图请求参数
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ImageRequest {

    /**
     * 提示词
     */
    @NotBlank(message = "提示词不能为空")
    @Size(max = 1000, message = "提示词长度不能超过1000字符")
    private String prompt;

    /**
     * 图片尺寸
     */
    @NotNull(message = "图片尺寸不能为空")
    private ImageSize size = ImageSize.S1024X1024;

    /**
     * 图片数量
     */
    @Min(value = 1, message = "图片数量至少为1")
    @Max(value = 10, message = "图片数量最多为10")
    private Integer n = 1;

    /**
     * 图片风格
     */
    private ImageStyle style = ImageStyle.VIVID;

    /**
     * 用户ID(用于缓存)
     */
    private String userId;

    /**
     * 图片尺寸枚举
     */
    public enum ImageSize {
        S256X256("256x256"),
        S512X512("512x512"),
        S1024X1024("1024x1024");

        private final String value;

        ImageSize(String value) {
            this.value = value;
        }

        public String getValue() {
            return value;
        }
    }

    /**
     * 图片风格枚举
     */
    public enum ImageStyle {
        NATURAL("natural"),
        VIVID("vivid");

        private final String value;

        ImageStyle(String value) {
            this.value = value;
        }

        public String getValue() {
            return value;
        }
    }
}

ImageController - REST接口

less 复制代码
package com.example.textToImage.controller;

import com.example.textToImage.model.ImageRequest;
import com.example.textToImage.model.ImageResponse;
import com.example.textToImage.service.OpenAiImageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * 文生图控制器
 *
 * 提供RESTful API接口
 */
@Slf4j
@RestController
@RequestMapping("/api/images")
@CrossOrigin(origins = "*")
public class ImageController {

    @Autowired
    private OpenAiImageService imageService;

    /**
     * 生成图片 - 同步接口
     */
    @PostMapping
    public ResponseEntity<ImageResponse> generateImage(@Valid @RequestBody ImageRequest request) {
        log.info("收到图片生成请求: prompt={}, size={}", request.getPrompt(), request.getSize());

        try {
            ImageResponse response = imageService.generateImage(request);

            if (response.getSuccess()) {
                return ResponseEntity.ok(response);
            } else {
                return ResponseEntity.internalServerError().body(response);
            }
        } catch (Exception e) {
            log.error("图片生成请求处理失败", e);
            return ResponseEntity.internalServerError()
                    .body(ImageResponse.builder()
                            .error(e.getMessage())
                            .success(false)
                            .build());
        }
    }

    /**
     * 生成图片 - 异步接口
     */
    @PostMapping("/async")
    public CompletableFuture<ResponseEntity<ImageResponse>> generateImageAsync(@Valid @RequestBody ImageRequest request) {
        log.info("收到异步图片生成请求: prompt={}", request.getPrompt());

        return CompletableFuture.supplyAsync(() -> {
            try {
                ImageResponse response = imageService.generateImage(request);

                if (response.getSuccess()) {
                    return ResponseEntity.ok(response);
                } else {
                    return ResponseEntity.internalServerError().body(response);
                }
            } catch (Exception e) {
                log.error("异步图片生成请求处理失败", e);
                return ResponseEntity.internalServerError()
                        .body(ImageResponse.builder()
                                .error(e.getMessage())
                                .success(false)
                                .build());
            }
        });
    }

    /**
     * 批量生成图片
     */
    @PostMapping("/batch")
    public CompletableFuture<ResponseEntity<List<ImageResponse>>> generateImages(
            @Valid @RequestBody List<ImageRequest> requests) {

        return CompletableFuture.supplyAsync(() -> {
            try {
                List<ImageResponse> responses = requests.stream()
                        .map(imageService::generateImage)
                        .collect(Collectors.toList());

                boolean allSuccess = responses.stream().allMatch(ImageResponse::getSuccess);

                if (allSuccess) {
                    return ResponseEntity.ok(responses);
                } else {
                    return ResponseEntity.internalServerError().body(responses);
                }
            } catch (Exception e) {
                log.error("批量图片生成请求处理失败", e);
                return ResponseEntity.internalServerError()
                        .body(Arrays.asList(ImageResponse.builder()
                                .error(e.getMessage())
                                .success(false)
                                .build()));
            }
        });
    }

    /**
     * 生成示例图片
     */
    @GetMapping("/examples")
    public ResponseEntity<List<ImageRequest>> getExampleRequests() {
        List<ImageRequest> examples = Arrays.asList(
                createExampleRequest("一只可爱的卡通猫,坐在花园里,阳光明媚", ImageRequest.ImageSize.S1024X1024, 1, ImageRequest.ImageStyle.VIVID),
                createExampleRequest("现代城市天际线,夜晚,霓虹灯", ImageRequest.ImageSize.S1024X1024, 1, ImageRequest.ImageStyle.NATURAL),
                createExampleRequest("抽象艺术,彩色几何形状", ImageRequest.ImageSize.S512X512, 2, ImageRequest.ImageStyle.VIVID)
        );

        return ResponseEntity.ok(examples);
    }

    /**
     * 检查服务状态
     */
    @GetMapping("/health")
    public ResponseEntity<String> healthCheck() {
        return ResponseEntity.ok("Image Generation Service is running");
    }

    /**
     * 创建请求
     */
    private ImageRequest createExampleRequest(String prompt, ImageRequest.ImageSize size, int n, ImageRequest.ImageStyle style) {
        ImageRequest request = new ImageRequest();
        request.setPrompt(prompt);
        request.setSize(size);
        request.setN(n);
        request.setStyle(style);
        return request;
    }
}

OpenAiImageService

scss 复制代码
package com.example.textToImage.service;

import com.example.textToImage.model.ApiKeyConfig;
import com.example.textToImage.model.ImageRequest;
import com.example.textToImage.model.ImageResponse;
import com.theokanning.openai.image.CreateImageRequest;
import com.theokanning.openai.image.ImageResult;
import com.theokanning.openai.service.OpenAiService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * OpenAI文生图服务实现
 *
 * 使用DALL-E 3/2模型生成图片
 * 支持多种参数配置
 */
@Slf4j
@Service
public class OpenAiImageService {

    @Autowired
    private ApiKeyConfig apiKeyConfig;

    /**
     * 生成图片
     */
    @Cacheable(value = "images", key = "#request.prompt + '_' + #request.size + '_' + #request.style")
    public ImageResponse generateImage(ImageRequest request) {
        long startTime = System.currentTimeMillis();
        String requestId = UUID.randomUUID().toString();

        try {
            // 创建OpenAI服务
            OpenAiService service = createOpenAiService();

            // 构建请求参数
            CreateImageRequest imageRequest = buildCreateImageRequest(request);

            // 调用API生成图片
            ImageResult result = service.createImage(imageRequest);

            // 构建响应
            ImageResponse response = buildResponse(request, requestId, result, startTime);

            log.info("图片生成成功: requestId={}, prompt={}", requestId, request.getPrompt());
            return response;

        } catch (Exception e) {
            log.error("图片生成失败: requestId={}, prompt={}", requestId, request.getPrompt(), e);
            return buildErrorResponse(requestId, e.getMessage(), startTime);
        }
    }

    /**
     * 创建OpenAI服务
     */
    private OpenAiService createOpenAiService() {
        if (apiKeyConfig.getUseProxy() && apiKeyConfig.getProxy() != null) {
            // 代理配置(示例)
            return new OpenAiService(apiKeyConfig.getOpenaiKey(), Duration.ofSeconds(apiKeyConfig.getTimeout()));
        } else {
            // 直接连接
            return new OpenAiService(apiKeyConfig.getOpenaiKey(), Duration.ofSeconds(apiKeyConfig.getTimeout()));
        }
    }

    /**
     * 构建图片请求
     */
    private CreateImageRequest buildCreateImageRequest(ImageRequest request) {
        return CreateImageRequest.builder()
                .prompt(request.getPrompt())
                .n(request.getN())
                .size(request.getSize().getValue())
                .responseFormat("url")
                .user(request.getUserId() != null ? request.getUserId() : "anonymous")
                .build();
    }

    /**
     * 构建成功响应
     */
    private ImageResponse buildResponse(ImageRequest request, String requestId,
                                       ImageResult result, long startTime) {
        List<String> urls = Arrays.asList(result.getData().stream()
                .map(image -> image.getUrl())
                .toArray(String[]::new));

        List<String> imageIds = Collections.emptyList(); // 暂时使用空列表

        return ImageResponse.builder()
                .requestId(requestId)
                .prompt(request.getPrompt())
                .createdAt(java.time.LocalDateTime.now())
                .urls(urls)
                .imageIds(imageIds)
                .duration(System.currentTimeMillis() - startTime)
                .success(true)
                .build();
    }

    /**
     * 构建错误响应
     */
    private ImageResponse buildErrorResponse(String requestId, String errorMessage, long startTime) {
        return ImageResponse.builder()
                .requestId(requestId)
                .error(errorMessage)
                .createdAt(java.time.LocalDateTime.now())
                .duration(System.currentTimeMillis() - startTime)
                .success(false)
                .build();
    }
}

四、业务流程详解

8步完整流程

复制代码
1️⃣ 用户输入文本:前端提交文本描述
2️⃣ 参数验证:校验参数格式和内容
3️⃣ 缓存查询:检查是否已生成过
4️⃣ 构建API请求:组装OpenAI请求
5️⃣ 调用OpenAI:发送图片生成请求
6️⃣ 接收响应:获取图片URL
7️⃣ 处理结果:保存到数据库
8️⃣ 返回图片:响应给用户

时序图

关键交互流程

前端→控制器:POST请求

控制器→服务:参数验证

服务→缓存:查询缓存

服务→OpenAI:API调用

OpenAI→服务:返回图片URL

服务→缓存:更新缓存

服务→控制器:返回响应

五、缓存机制优化

多级缓存策略

L1 - Caffeine本地缓存

读写速度快,适合热点数据

减少网络调用

L2 - Redis分布式缓存

支持集群,容量大

集群环境数据共享

L3 - OpenAI API缓存

第三方服务自带缓存

降低API成本

Caffeine

csharp 复制代码
package com.example.textToImage.demo;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.Expiry;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * Caffeine缓存演示类
 *
 * Caffeine缓存的基本用法和高级特性
 */
@Component
public class CaffeineDemo {

    /**
     * 创建基础缓存
     */
    public Cache<String, String> createBasicCache() {
        return Caffeine.newBuilder()
                .maximumSize(1000) // 最大缓存数量
                .expireAfterWrite(1, TimeUnit.HOURS) // 写入后1小时过期
                .build();
    }

    /**
     * 带有自定义过期策略的缓存
     */
    public Cache<String, Object> createCustomExpiryCache() {
        return Caffeine.newBuilder()
                .expireAfter(new Expiry<String, Object>() {
                    @Override
                    public long expireAfterCreate(String key, Object value, long currentTime) {
                        return TimeUnit.MINUTES.toNanos(30); // 创建后30分钟过期
                    }

                    @Override
                    public long expireAfterUpdate(String key, Object value, long currentTime, long currentDuration) {
                        return currentDuration; // 更新时不重置过期时间
                    }

                    @Override
                    public long expireAfterRead(String key, Object value, long currentTime, long currentDuration) {
                        return currentDuration; // 读取时不重置过期时间
                    }
                })
                .maximumSize(500)
                .build();
    }

    /**
     * 带有统计信息的缓存
     */
    public Cache<String, String> createStatsCache() {
        return Caffeine.newBuilder()
                .maximumSize(1000)
                .recordStats() // 开启统计功能
                .expireAfterWrite(1, TimeUnit.HOURS)
                .build();
    }

    /**
     * 缓存操作
     */
    public void demonstrateCacheOperations() {
        System.out.println("=== Caffeine缓存演示 ===");

        // 创建缓存
        Cache<String, String> cache = createBasicCache();

        // 1. 基本操作
        System.out.println("\n1. 基本缓存操作:");

        // 存储
        cache.put("user:1001", "张三");
        cache.put("user:1002", "李四");
        cache.put("user:1003", "王五");

        // 获取
        String user1 = cache.getIfPresent("user:1001");
        System.out.println("获取用户1001: " + user1);

        // 使用computeIfAbsent(原子操作)
        String user4 = cache.get("user:1004", k -> "新用户" + k.substring(k.lastIndexOf(":") + 1));
        System.out.println("获取用户1004: " + user4);

        // 2. 统计信息
        System.out.println("\n2. 缓存统计:");
        Cache<String, String> statsCache = createStatsCache();

        // 模拟一些操作
        for (int i = 0; i < 100; i++) {
            statsCache.put("key:" + i, "value:" + i);
        }

        for (int i = 0; i < 50; i++) {
            statsCache.getIfPresent("key:" + i);
        }

        // 打印统计信息
        com.github.benmanes.caffeine.cache.stats.CacheStats stats = statsCache.stats();
        System.out.println("缓存命中次数: " + stats.hitCount());
        System.out.println("缓存未命中次数: " + stats.missCount());
        System.out.println("缓存命中率: " + stats.hitRate());
        System.out.println("加载时间: " + stats.totalLoadTime() + " ns");

        // 3. 手动失效
        System.out.println("\n3. 缓存失效:");
        cache.invalidate("user:1001"); // 单个key失效
        cache.invalidateAll(); // 全部失效

        System.out.println("缓存演示完成!");
    }

    /**
     * 图片缓存场景
     */
    public void demonstrateImageCache() {
        System.out.println("\n=== 图片缓存演示 ===");

        Cache<String, byte[]> imageCache = Caffeine.newBuilder()
                .maximumSize(100) // 缓存100张图片
                .maximumWeight(10 * 1024 * 1024) // 最大10MB
                .expireAfterWrite(24, TimeUnit.HOURS) // 24小时过期
                .build();

        // 模拟图片数据
        byte[] smallImage = new byte[50 * 1024]; // 50KB
        byte[] largeImage = new byte[2 * 1024 * 1024]; // 2MB

        // 存储图片
        imageCache.put("image:small", smallImage);
        imageCache.put("image:large", largeImage);

        System.out.println("小图片缓存状态: " +
            (imageCache.getIfPresent("image:small") != null ? "已缓存" : "未缓存"));
        System.out.println("大图片缓存状态: " +
            (imageCache.getIfPresent("image:large") != null ? "已缓存" : "未缓存"));

        // 获取缓存统计
        com.github.benmanes.caffeine.cache.stats.CacheStats stats = imageCache.stats();
        System.out.println("图片缓存命中率: " + String.format("%.2f%%", stats.hitRate() * 100));
    }
}

数据流转

智能缓存查询流程

复制代码
1、用户发起请求
2、验证并查询缓存
3、缓存未命中调用API
4、OpenAI生成图片
5、处理结果并缓存
6、返回结果给用户

六、性能优化与部署

JVM参数优化

diff 复制代码
-Xms2g -Xmx4g 
-XX:+UseG1GC 
-XX:MaxGCPauseMillis=200

异步处理配置

less 复制代码
@Configuration
@EnableAsync
public class AsyncConfig {
    @Bean
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = 
            new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(100);
        return executor;
    }
}

七、总结

多模态融合

复制代码
文+图→图
图+图→视频
AR/VR内容生成

本地化部署

复制代码
模型小型化
推理优化
成本可控
相关推荐
DigitalOcean1 小时前
技术解码:Character.ai 如何实现大模型实时推理性能 2 倍提升
性能优化·aigc
Focus_2 小时前
如何借助AI在UE5中将图片批量生成3D模型
前端·aigc·游戏开发
GISer_Jing5 小时前
Claude Skills
人工智能·prompt·aigc
jacky2576 小时前
高保真光学仿真解决方案:基于多物理场耦合与混合数据驱动的产品数字孪生构建
大数据·人工智能·aigc·制造·数据库架构·共识算法
得一录6 小时前
大模型的基本概念及主要功能
人工智能·aigc
GISer_Jing7 小时前
前端Vibe Coding
人工智能·aigc
石云升19 小时前
谁来负责企业落地AI?
aigc·openai·ai编程
墨风如雪19 小时前
语音模型变天!阶跃星辰R1.1开源,96.4%胜率让GPT都沉默
aigc
狼爷19 小时前
【译】Skills 详解:Skills 与 prompts、Projects、MCP 和 subagents 的比较
人工智能·aigc