1. Visión general
En este tutorial, exploraremos cómo extraer datos estructurados de imágenes con el modelo de chat de OpenAI utilizando Spring AI.
El modelo de chat de OpenAI puede analizar una imagen subida y devolver información relevante. También puede devolver una salida estructurada que se puede canalizar fácilmente a otras aplicaciones para operaciones adicionales.
Para ilustrar, crearemos un servicio web que acepte una imagen del cliente y la envíe a OpenAI para contar el número de autos de colores en la imagen. El servicio web devuelve los recuentos de colores en formato JSON.
2. Configuración de Spring Boot
Necesitamos agregar las siguientes dependencias de Spring Boot Starter Web y Spring AI Model OpenAI a nuestro archivo pom.xml de Maven:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<version>1.0.0-M6</version>
</dependency>
En nuestro archivo application.yml de Spring Boot, debemos proporcionar nuestra clave API (spring.ai.openai.api-key) para la autenticación con la API de OpenAI y un modelo de chat (spring.ai.openai.chat.options.model) capaz de realizar análisis de imágenes.
Hay varios modelos que admiten análisis de imágenes, como gpt-4o-mini, gpt-4o y gpt-4.5-preview. Un modelo más grande como gpt-4o tiene un conocimiento más amplio pero con un costo mayor, mientras que un modelo más pequeño como gpt-4o-mini cuesta menos y tiene menor latencia. Podemos elegir el modelo según nuestras necesidades.
Elijamos el modelo de chat gpt-4o en nuestra ilustración:
spring:
ai:
openai:
api-key: "<TU-CLAVE-API>"
chat:
options:
model: "gpt-4o"
Una vez que tengamos este conjunto de configuraciones, Spring Boot carga OpenAiAutoConfiguration automáticamente para registrar beans como ChatClient, que crearemos más adelante durante el inicio de la aplicación.
3. Servicio Web de Muestra
Después de completar todas las configuraciones, crearemos un servicio web para permitir a los usuarios subir sus imágenes y pasarlas a OpenAI para contar el número de autos de colores en la imagen como el siguiente paso.
3.1. Controlador REST
En este controlador REST, simplemente aceptamos un archivo de imagen y los colores que se contarán en la imagen como parámetros de la solicitud:
@RestController
@RequestMapping("/image")
public class ImageController {
@Autowired
private CarCountService carCountService;
@PostMapping("/car-count")
public ResponseEntity<?> getCarCounts(@RequestParam("colors") String colors,
@RequestParam("file") MultipartFile file) {
try (InputStream inputStream = file.getInputStream()) {
var carCount = carCountService.getCarCount(inputStream, file.getContentType(), colors);
return ResponseEntity.ok(carCount);
} catch (IOException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error uploading image");
}
}
}
Para una respuesta exitosa, esperamos que el servicio responda con un ResponseEntity de CarCount.
3.2. POJO
Si queremos que el modelo de chat devuelva una salida estructurada, definimos el formato de salida como un esquema JSON en la solicitud HTTP a OpenAI. En Spring AI, esta definición se simplifica enormemente definiendo clases POJO.
Definamos dos clases POJO que almacenen los colores y su recuento correspondiente. CarCount almacena la lista de recuentos de autos por color y el recuento total, que es la suma de los recuentos en la lista:
public class CarCount {
private List<CarColorCount> carColorCounts;
private int totalCount;
// constructor, getters y setters
}
CarColorCount almacena el nombre del color y el recuento correspondiente:
public class CarColorCount {
private String color;
private int count;
// constructor, getters y setters
}
3.3. Servicio
Ahora, creemos el servicio central de Spring que envía la imagen a la API de OpenAI para su análisis. En este CarCountService, inyectamos un ChatClientBuilder que crea un ChatClient para la comunicación con OpenAI:
@Service
public class CarCountService {
private final ChatClient chatClient;
public CarCountService(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
}
public CarCount getCarCount(InputStream imageInputStream, String contentType, String colors) {
return chatClient.prompt()
.system(systemMessage -> systemMessage
.text("Count the number of cars in different colors from the image")
.text("User will provide the image and specify which colors to count in the user prompt")
.text("Count colors that are specified in the user prompt only")
.text("Ignore anything in the user prompt that is not a color")
.text("If there is no color specified in the user prompt, simply returns zero in the total count")
)
.user(userMessage -> userMessage
.text(colors)
.media(MimeTypeUtils.parseMimeType(contentType), new InputStreamResource(imageInputStream))
)
.call()
.entity(CarCount.class);
}
}
En este servicio, enviamos mensajes del sistema y del usuario a OpenAI.
El mensaje del sistema proporciona pautas para el comportamiento del modelo de chat. Esto contiene un conjunto de instrucciones para evitar comportamientos inesperados, como contar colores que el usuario no especifica para esta instancia. Esto garantiza que el modelo de chat devuelva una respuesta más determinista.
El mensaje del usuario proporciona los datos necesarios al modelo de chat para su procesamiento. En nuestro ejemplo, pasamos dos entradas. La primera es los colores que nos gustaría contar como entrada de texto. La otra es la imagen subida como entrada multimedia. Esto requiere tanto el InputStream del archivo subido como el tipo MIME del medio que podemos derivar del tipo de contenido del archivo.
El punto crucial a notar es que debemos proporcionar la clase POJO que creamos anteriormente en entity(). Esto dispara el BeanOutputConverter de Spring AI para convertir la respuesta JSON de OpenAI en nuestra instancia POJO CarCount.
4. Ejecución de Prueba
Ahora todo está listo. Podemos hacer una prueba para ver cómo se comporta. Hagamos una solicitud a este servicio web usando Postman. Especificamos tres colores diferentes (azul, amarillo y verde) aquí para que el modelo de chat los cuente en nuestra imagen:
En nuestro ejemplo, usaremos la siguiente foto para probar:
Al solicitar, recibiremos una respuesta JSON del servicio web:
{
"carColorCounts": [
{
"color": "blue",
"count": 2
},
{
"color": "yellow",
"count": 1
},
{
"color": "green",
"count": 0
}
],
"totalCount": 3
}
La respuesta muestra el número de autos para cada color que especificamos en la solicitud. Además, proporciona el recuento total de autos para los colores mencionados. El esquema JSON se alinea con la definición de la clase POJO en CarCount y CarColorCount.
5. Conclusión
Aprendimos cómo extraer una salida estructurada del modelo de chat de OpenAI en este artículo. También construimos un servicio web que acepta una imagen subida, la pasa al modelo de chat de OpenAI para el análisis de imágenes y devuelve una salida estructurada con información relevante.
El código que respalda este artículo está disponible en GitHub. Una vez que estés conectado como un Miembro Pro de Baeldung, comienza a aprender y programar en el proyecto.
Newsletter Semanal de Java
Cada viernes recibe lo más nuevo del ecosistema Java: frameworks, herramientas y mejores prácticas.
Sin spam. Cancela cuando quieras.
