<!-- Spring AI OpenAI -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
<!-- JTokkit -->
<dependency>
<groupId>com.knuddels</groupId>
<artifactId>jtokkit</artifactId>
<version>1.1.0</version>
</dependency>
package com.ejemplo.productos;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.ai.tokenizer.JTokkitTokenCountEstimator;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/productos")
public class CategorizadorDeProductosController {
private final ChatClient chatClient;
private final JTokkitTokenCountEstimator tokenCountEstimator;
public CategorizadorDeProductosController(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
this.tokenCountEstimator = new JTokkitTokenCountEstimator();
}
@GetMapping("/categorizar")
public String categorizarProducto(
@RequestParam String descripcion,
@RequestParam(defaultValue = "gpt-4o-mini") String modelo) {
String prompt = """
Eres un asistente especializado en categorización de productos para e-commerce.
Tu tarea es analizar la descripción del producto y devolver únicamente una categoría válida.
Categorías permitidas:
- Electrónica
- Ropa
- Hogar
- Deportes
- Belleza
- Juguetes
- Alimentos
- Libros
- Mascotas
- Otros
Reglas:
1. Responde solo con una categoría.
2. No expliques tu respuesta.
3. No agregues texto adicional.
4. Si la descripción es ambigua, responde: Otros.
Ejemplos:
Descripción: "Smartphone con pantalla OLED y 256 GB"
Categoría: Electrónica
Descripción: "Camiseta deportiva de algodón"
Categoría: Ropa
Ahora categoriza este producto:
Descripción: "%s"
Categoría:
""".formatted(descripcion);
return this.chatClient.prompt()
.user(prompt)
.options(OpenAiChatOptions.builder()
.model(modelo)
.temperature(0.2)
.build())
.call()
.content();
}
@GetMapping("/contar-tokens")
public String contarTokens(@RequestParam String texto) {
int totalTokens = this.tokenCountEstimator.estimate(texto);
return "Cantidad de tokens estimados: " + totalTokens;
}
@GetMapping("/categorizar-con-tokens")
public String categorizarProductoConTokens(
@RequestParam String descripcion,
@RequestParam(defaultValue = "gpt-4o-mini") String modelo) {
String prompt = """
Eres un asistente especializado en categorización de productos para e-commerce.
Devuelve únicamente una categoría válida.
Categorías permitidas:
- Electrónica
- Ropa
- Hogar
- Deportes
- Belleza
- Juguetes
- Alimentos
- Libros
- Mascotas
- Otros
Reglas:
1. Responde solo con una categoría.
2. Si no estás seguro, responde: Otros.
Descripción: "%s"
Categoría:
""".formatted(descripcion);
int tokensPrompt = this.tokenCountEstimator.estimate(prompt);
String categoria = this.chatClient.prompt()
.user(prompt)
.options(OpenAiChatOptions.builder()
.model(modelo)
.temperature(0.2)
.build())
.call()
.content();
return """
Modelo usado: %s
Tokens estimados del prompt: %d
Categoría generada: %s
""".formatted(modelo, tokensPrompt, categoria);
}
}
.options(OpenAiChatOptions.builder()
.model(modelo)
.temperature(0.2)
.build())
this.tokenCountEstimator = new JTokkitTokenCountEstimator();