diff --git a/src/main/java/guru/springframework/springaiimage/controllers/QuestionController.java b/src/main/java/guru/springframework/springaiimage/controllers/QuestionController.java index ca8382e..f551315 100644 --- a/src/main/java/guru/springframework/springaiimage/controllers/QuestionController.java +++ b/src/main/java/guru/springframework/springaiimage/controllers/QuestionController.java @@ -1,8 +1,18 @@ package guru.springframework.springaiimage.controllers; +import guru.springframework.springaiimage.model.Question; import guru.springframework.springaiimage.services.OpenAIService; import lombok.RequiredArgsConstructor; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; /** * Created by jt, Spring Framework Guru. @@ -13,5 +23,17 @@ public class QuestionController { private final OpenAIService openAIService; - //todo impl + @PostMapping(value = "/vision", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}, produces = {MediaType.APPLICATION_JSON_VALUE}) + public ResponseEntity upload( + @Validated @RequestParam("file") MultipartFile file, + @RequestParam("name") String name + ) throws IOException { + + return ResponseEntity.ok(openAIService.getDescription(file)); + } + + @PostMapping(value = "/image", produces = MediaType.IMAGE_PNG_VALUE) + public byte[] getImage(@RequestBody Question question) { + return openAIService.getImage(question); + } } diff --git a/src/main/java/guru/springframework/springaiimage/services/OpenAIService.java b/src/main/java/guru/springframework/springaiimage/services/OpenAIService.java index f7d8a2c..e114c18 100644 --- a/src/main/java/guru/springframework/springaiimage/services/OpenAIService.java +++ b/src/main/java/guru/springframework/springaiimage/services/OpenAIService.java @@ -2,6 +2,9 @@ import guru.springframework.springaiimage.model.Question; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; /** @@ -9,5 +12,7 @@ */ public interface OpenAIService { - Object getImage(Question question); + byte[] getImage(Question question); + + String getDescription(MultipartFile file) throws IOException; } diff --git a/src/main/java/guru/springframework/springaiimage/services/OpenAIServiceImpl.java b/src/main/java/guru/springframework/springaiimage/services/OpenAIServiceImpl.java index 31bf717..66446f1 100644 --- a/src/main/java/guru/springframework/springaiimage/services/OpenAIServiceImpl.java +++ b/src/main/java/guru/springframework/springaiimage/services/OpenAIServiceImpl.java @@ -2,7 +2,22 @@ import guru.springframework.springaiimage.model.Question; import lombok.RequiredArgsConstructor; +import org.springframework.ai.chat.messages.UserMessage; +import org.springframework.ai.chat.model.ChatModel; +import org.springframework.ai.chat.model.ChatResponse; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.image.ImageModel; +import org.springframework.ai.image.ImagePrompt; +import org.springframework.ai.model.Media; +import org.springframework.ai.openai.OpenAiChatOptions; +import org.springframework.ai.openai.OpenAiImageOptions; +import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.stereotype.Service; +import org.springframework.util.MimeTypeUtils; +import org.springframework.web.multipart.MultipartFile; + +import java.util.Base64; +import java.util.List; /** * Created by jt, Spring Framework Guru. @@ -11,9 +26,58 @@ @Service public class OpenAIServiceImpl implements OpenAIService { + private final ImageModel imageModel; + + private final ChatModel chatModel; + + @Override + public String getDescription(MultipartFile file) { + + OpenAiChatOptions options = OpenAiChatOptions.builder() + .withModel(OpenAiApi.ChatModel.GPT_4_O.getValue()) + .build(); + + var userMessage = new UserMessage("Explain what do you see in this picture?", + List.of(new Media(MimeTypeUtils.IMAGE_JPEG, file.getResource()))); + + ChatResponse response = chatModel.call(new Prompt(List.of(userMessage), options)); + + return response.getResult().getOutput().toString(); + } + @Override - public Object getImage(Question question) { + public byte[] getImage(Question question) { + + var options = OpenAiImageOptions.builder() + .withHeight(1024).withWidth(1792) + .withResponseFormat("b64_json") + .withModel("dall-e-3") + .withQuality("hd") //default standard + //.withStyle("natural") //default vivid + .build(); + + ImagePrompt imagePrompt = new ImagePrompt(question.question(), options); - return new Object(); + var imageResponse = imageModel.call(imagePrompt); + + return Base64.getDecoder().decode(imageResponse.getResult().getOutput().getB64Json()); } } + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 954dd00..4f58c98 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -1,7 +1,7 @@ spring: application: name: spring-ai-functions -#Pass API key as environment variable, e.g. -DOPENAI_API_KEY=your-api-key + #Pass API key as environment variable, e.g. -DOPENAI_API_KEY=your-api-key ai: openai: - api-key: ${OPENAI_API_KEY} + api-key: ${BEARER_TOKEN_OPENAI_API_KEY}