From 596374d657c9b5140b5fc737cff24f1ed2cf5446 Mon Sep 17 00:00:00 2001 From: Renato Date: Mon, 13 Mar 2023 10:07:43 -0300 Subject: [PATCH] feat: iOS sample integration --- sample/ios/EnvConfig.xcconfig | 2 +- .../Features/Completion/CompletionView.swift | 34 +++++++++++++++++-- .../Completion/Model/ChatMessage.swift | 1 + .../ViewModel/CompletionViewModel.swift | 26 ++++++++++++-- .../ychat/jvm/controller/YChatController.java | 8 +++++ .../yml/ychat/jvm/services/YChatService.java | 9 +++++ 6 files changed, 73 insertions(+), 7 deletions(-) diff --git a/sample/ios/EnvConfig.xcconfig b/sample/ios/EnvConfig.xcconfig index 4d3ddd0..3df9919 100644 --- a/sample/ios/EnvConfig.xcconfig +++ b/sample/ios/EnvConfig.xcconfig @@ -10,4 +10,4 @@ // https://help.apple.com/xcode/#/dev745c5c974 -API_KEY = // YOUR API KEY +API_KEY = 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 diff --git a/sample/ios/YChatApp/Features/Completion/CompletionView.swift b/sample/ios/YChatApp/Features/Completion/CompletionView.swift index a4d44d0..c506beb 100644 --- a/sample/ios/YChatApp/Features/Completion/CompletionView.swift +++ b/sample/ios/YChatApp/Features/Completion/CompletionView.swift @@ -72,9 +72,15 @@ private extension CompletionView { } case .bot: HStack { - botChatBubble(message: chatMessage.message) - Spacer().frame(width: 60) - Spacer() + if let imageUrl = chatMessage.url { + botImageBubble(imageUrl) + Spacer().frame(width: 60) + Spacer() + } else { + botChatBubble(message: chatMessage.message) + Spacer().frame(width: 60) + Spacer() + } } case .loading: HStack { @@ -120,6 +126,28 @@ private extension CompletionView { .cornerRadius(16, corners: [.bottomLeft, .bottomLeft, .topRight]) } } + + @ViewBuilder + private func botImageBubble(_ url: String) -> some View { + HStack(alignment: .top, spacing: 4) { + Circle() + .fill(.green) + .frame(width: 40, height: 40) + .overlay { + Image(uiImage: Icon.bot.uiImage) + .renderingMode(.template) + .foregroundColor(.white) + } + ZStack { + AsyncImage(url: URL(string: url)) + .foregroundColor(.grayDark) + } + .padding(.horizontal, 16) + .padding(.vertical, 8) + .background(Color.grayLight) + .cornerRadius(16, corners: [.bottomLeft, .bottomLeft, .topRight]) + } + } @ViewBuilder private func sendMessageSection() -> some View { diff --git a/sample/ios/YChatApp/Features/Completion/Model/ChatMessage.swift b/sample/ios/YChatApp/Features/Completion/Model/ChatMessage.swift index 04306aa..1219bb2 100644 --- a/sample/ios/YChatApp/Features/Completion/Model/ChatMessage.swift +++ b/sample/ios/YChatApp/Features/Completion/Model/ChatMessage.swift @@ -12,6 +12,7 @@ struct ChatMessage: Identifiable, Equatable { let id: String var message: String = "" var type: MessageType = .human(error: false) + var url: String? enum MessageType: Equatable { case human(error: Bool), bot, loading diff --git a/sample/ios/YChatApp/Features/Completion/ViewModel/CompletionViewModel.swift b/sample/ios/YChatApp/Features/Completion/ViewModel/CompletionViewModel.swift index f13f22f..05be4bb 100644 --- a/sample/ios/YChatApp/Features/Completion/ViewModel/CompletionViewModel.swift +++ b/sample/ios/YChatApp/Features/Completion/ViewModel/CompletionViewModel.swift @@ -19,6 +19,11 @@ internal final class CompletionViewModel: ObservableObject { content: "You are a helpful assistant." ) + private var imageGenerations: ImageGenerations = + YChatCompanion.shared.create(apiKey: Config.apiKey) + .imageGenerations() + .setResults(results: 2) + @Published var message: String = "" @@ -37,9 +42,15 @@ internal final class CompletionViewModel: ObservableObject { cleanLastMessage() addLoading() do { - let result = try await chatCompletions.execute(content: input)[0].content - removeLoading() - addAIMessage(message: result) + if input.contains("/image ") { + let result = try await imageGenerations.execute(prompt: input)[0].url + removeLoading() + addAIImage(url: result) + } else { + let result = try await chatCompletions.execute(content: input)[0].content + removeLoading() + addAIMessage(message: result) + } } catch { removeLoading() setError() @@ -64,6 +75,15 @@ internal final class CompletionViewModel: ObservableObject { ) chatMessageList.append(chatMessage) } + + private func addAIImage(url: String) { + let chatMessage = ChatMessage( + id: UUID().uuidString, + type: .bot, + url: url + ) + chatMessageList.append(chatMessage) + } private func addLoading() { let chatMessage = ChatMessage( diff --git a/sample/jvm/src/main/java/co/yml/ychat/jvm/controller/YChatController.java b/sample/jvm/src/main/java/co/yml/ychat/jvm/controller/YChatController.java index 4e1b1ac..dbb8660 100644 --- a/sample/jvm/src/main/java/co/yml/ychat/jvm/controller/YChatController.java +++ b/sample/jvm/src/main/java/co/yml/ychat/jvm/controller/YChatController.java @@ -32,6 +32,14 @@ public ResponseEntity chatCompletions( return ResponseEntity.ok(result); } + @GetMapping("image-generations") + public ResponseEntity imageGenerations( + @RequestParam(value = "prompt", defaultValue = Defaults.CHAT_COMPLETION_INPUT) String input + ) throws Exception { + String result = YChatService.getImageGenerationsAnswer(input); + return ResponseEntity.ok(result); + } + private static class Defaults { static final String COMPLETION_INPUT = "Say this is a test."; static final String CHAT_COMPLETION_INPUT = "Tell me one strength exercise"; diff --git a/sample/jvm/src/main/java/co/yml/ychat/jvm/services/YChatService.java b/sample/jvm/src/main/java/co/yml/ychat/jvm/services/YChatService.java index a6aaa34..76f871e 100644 --- a/sample/jvm/src/main/java/co/yml/ychat/jvm/services/YChatService.java +++ b/sample/jvm/src/main/java/co/yml/ychat/jvm/services/YChatService.java @@ -7,6 +7,7 @@ import org.springframework.stereotype.Service; import java.util.concurrent.CompletableFuture; import co.yml.ychat.YChat; +import co.yml.ychat.domain.model.ImageGenerated; @Service public class YChatService { @@ -35,6 +36,14 @@ public String getChatCompletionsAnswer(String input, String topic) throws Except return future.get().get(0).getContent(); } + public String getImageGenerationsAnswer(String prompt) throws Exception { + final CompletableFuture> future = new CompletableFuture<>(); + ychat.imageGenerations() + .setResults(2) + .execute(prompt, new CompletionCallbackResult<>(future)); + return future.get().get(0); + } + private static class CompletionCallbackResult implements YChat.Callback { private final CompletableFuture future;