diff --git a/build.gradle b/build.gradle index 2b2b7299..55ef8461 100644 --- a/build.gradle +++ b/build.gradle @@ -36,6 +36,16 @@ sourceSets { } } +ext { + set('springCloudVersion', "2023.0.1") +} + +dependencyManagement { + imports { + mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" + } +} + dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-validation' @@ -45,15 +55,20 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' implementation 'org.springframework.boot:spring-boot-starter-mail' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' + implementation 'io.jsonwebtoken:jjwt-api:0.12.3' implementation 'io.jsonwebtoken:jjwt-impl:0.12.3' implementation 'io.jsonwebtoken:jjwt-jackson:0.12.3' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.4.0' + compileOnly 'org.projectlombok:lombok' + runtimeOnly 'org.postgresql:postgresql' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' implementation 'com.googlecode.json-simple:json-simple:1.1.1' implementation 'org.springframework.boot:spring-boot-starter-aop' + implementation 'org.springframework.cloud:spring-cloud-starter-openfeign' } diff --git a/src/main/java/com/space/server/common/config/OpenAiFeignConfig.java b/src/main/java/com/space/server/common/config/OpenAiFeignConfig.java new file mode 100644 index 00000000..14aecffa --- /dev/null +++ b/src/main/java/com/space/server/common/config/OpenAiFeignConfig.java @@ -0,0 +1,23 @@ +package com.space.server.common.config; + +import feign.RequestInterceptor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableFeignClients +public class OpenAiFeignConfig { + @Value("${gpt.api.key}") + private String apiKey; + + @Bean + public RequestInterceptor requestInterceptor() { + return requestTemplate -> { + requestTemplate.header("Content-Type", "application/json"); + requestTemplate.header("Authorization", "Bearer " + apiKey); + requestTemplate.header("OpenAI-Beta", "assistants=v2"); + }; + } +} diff --git a/src/main/java/com/space/server/domain/ai/infra/feign/OpenAiFeignClient.java b/src/main/java/com/space/server/domain/ai/infra/feign/OpenAiFeignClient.java new file mode 100644 index 00000000..f0d821b6 --- /dev/null +++ b/src/main/java/com/space/server/domain/ai/infra/feign/OpenAiFeignClient.java @@ -0,0 +1,44 @@ +package com.space.server.domain.ai.infra.feign; + +import com.space.server.common.config.OpenAiFeignConfig; +import com.space.server.domain.ai.service.dto.request.internal.AiChat; +import com.space.server.domain.ai.service.dto.request.internal.AiRunsRequest; +import com.space.server.domain.ai.service.dto.response.internal.AiAllMessagesResponse; +import com.space.server.domain.ai.service.dto.response.internal.AiMessagesResponse; +import com.space.server.domain.ai.service.dto.response.internal.AiRunsResponse; +import com.space.server.domain.ai.service.dto.response.internal.AiThreadResponse; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +@FeignClient( + name = "OpenAiFeign", + url = "https://api.openai.com/v1/threads", + configuration = OpenAiFeignConfig.class +) +public interface OpenAiFeignClient { + + @PostMapping + AiThreadResponse createThread(); + + @PostMapping("/{threadId}/messages") + AiMessagesResponse createMessage(@PathVariable("threadId") String threadId, + @RequestBody AiChat aiChat); + + @GetMapping("/{threadId}/messages") + AiAllMessagesResponse getAllMessages(@PathVariable("threadId") String threadId); + + @GetMapping("/{threadId}/messages/{messageId}") + AiMessagesResponse getMessage(@PathVariable("threadId") String threadId, + @PathVariable("messageId") String messageId); + + @PostMapping("/{threadId}/runs") + AiRunsResponse createRun(@PathVariable("threadId") String threadId, + @RequestBody AiRunsRequest request); + + @GetMapping("/{threadId}/runs/{runId}") + AiRunsResponse getRun(@PathVariable("threadId") String threadId, + @PathVariable("runId") String runId); +} \ No newline at end of file diff --git a/src/main/java/com/space/server/domain/ai/service/dto/request/gpt/AiAssistantsRequest.java b/src/main/java/com/space/server/domain/ai/service/dto/request/gpt/AiAssistantsRequest.java deleted file mode 100644 index d77d7b9c..00000000 --- a/src/main/java/com/space/server/domain/ai/service/dto/request/gpt/AiAssistantsRequest.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.space.server.domain.ai.service.dto.request.gpt; - -import java.util.List; -import java.util.Map; - -public record AiAssistantsRequest( - String instructions, - String name, - List> tools, - String model -) { - public AiAssistantsRequest toEntity(String instructions, String name, List> tools, String model) { - return new AiAssistantsRequest(instructions, name, tools, model); - } -} diff --git a/src/main/java/com/space/server/domain/ai/service/dto/request/gpt/AiRunsRequest.java b/src/main/java/com/space/server/domain/ai/service/dto/request/gpt/AiRunsRequest.java deleted file mode 100644 index 1e98532b..00000000 --- a/src/main/java/com/space/server/domain/ai/service/dto/request/gpt/AiRunsRequest.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.space.server.domain.ai.service.dto.request.gpt; - -public record AiRunsRequest( - String assistant_id -) {} diff --git a/src/main/java/com/space/server/domain/ai/service/dto/request/gpt/AiChat.java b/src/main/java/com/space/server/domain/ai/service/dto/request/internal/AiChat.java similarity index 50% rename from src/main/java/com/space/server/domain/ai/service/dto/request/gpt/AiChat.java rename to src/main/java/com/space/server/domain/ai/service/dto/request/internal/AiChat.java index db7573f2..65ea79a4 100644 --- a/src/main/java/com/space/server/domain/ai/service/dto/request/gpt/AiChat.java +++ b/src/main/java/com/space/server/domain/ai/service/dto/request/internal/AiChat.java @@ -1,4 +1,4 @@ -package com.space.server.domain.ai.service.dto.request.gpt; +package com.space.server.domain.ai.service.dto.request.internal; public record AiChat ( String role, diff --git a/src/main/java/com/space/server/domain/ai/service/dto/request/internal/AiRunsRequest.java b/src/main/java/com/space/server/domain/ai/service/dto/request/internal/AiRunsRequest.java new file mode 100644 index 00000000..6dda4bfe --- /dev/null +++ b/src/main/java/com/space/server/domain/ai/service/dto/request/internal/AiRunsRequest.java @@ -0,0 +1,5 @@ +package com.space.server.domain.ai.service.dto.request.internal; + +public record AiRunsRequest( + String assistant_id +) {} diff --git a/src/main/java/com/space/server/domain/ai/service/dto/request/gpt/AiThreadRequest.java b/src/main/java/com/space/server/domain/ai/service/dto/request/internal/AiThreadRequest.java similarity index 57% rename from src/main/java/com/space/server/domain/ai/service/dto/request/gpt/AiThreadRequest.java rename to src/main/java/com/space/server/domain/ai/service/dto/request/internal/AiThreadRequest.java index f9366534..39555875 100644 --- a/src/main/java/com/space/server/domain/ai/service/dto/request/gpt/AiThreadRequest.java +++ b/src/main/java/com/space/server/domain/ai/service/dto/request/internal/AiThreadRequest.java @@ -1,4 +1,4 @@ -package com.space.server.domain.ai.service.dto.request.gpt; +package com.space.server.domain.ai.service.dto.request.internal; import java.util.List; diff --git a/src/main/java/com/space/server/domain/ai/service/dto/response/AiResponse.java b/src/main/java/com/space/server/domain/ai/service/dto/response/AiResponse.java index 2f121c1a..9462fb1a 100644 --- a/src/main/java/com/space/server/domain/ai/service/dto/response/AiResponse.java +++ b/src/main/java/com/space/server/domain/ai/service/dto/response/AiResponse.java @@ -1,6 +1,5 @@ package com.space.server.domain.ai.service.dto.response; -import java.util.Map; public record AiResponse ( Boolean isSuccess, diff --git a/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/AiAllMessagesResponse.java b/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/AiAllMessagesResponse.java deleted file mode 100644 index aca28bf0..00000000 --- a/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/AiAllMessagesResponse.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.space.server.domain.ai.service.dto.response.gpt; - -import java.util.List; - -public record AiAllMessagesResponse( - String object, - List data, - String first_id, - String last_id, - Boolean has_more -) {} diff --git a/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/AiMessagesResponse.java b/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/AiMessagesResponse.java deleted file mode 100644 index 710f9352..00000000 --- a/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/AiMessagesResponse.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.space.server.domain.ai.service.dto.response.gpt; - -import java.util.List; -import java.util.Map; - -public record AiMessagesResponse( - String id, - String object, - Long created_at, - String assistant_id, - String thread_id, - String run_id, - String role, - List content, - List attachments, - Map metadata -) {} diff --git a/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/AiRunsResponse.java b/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/AiRunsResponse.java deleted file mode 100644 index 39e5c5a4..00000000 --- a/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/AiRunsResponse.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.space.server.domain.ai.service.dto.response.gpt; - -import com.space.server.domain.ai.service.dto.response.gpt.tools.FileSearchTool; - -import java.util.List; -import java.util.Map; - -public record AiRunsResponse( - String id, - String object, - Long created_at, - String assistant_id, - String thread_id, - String status, - Map>> required_action, - Long started_at, - Long expires_at, - Long cancelled_at, - Long failed_at, - Long completed_at, - Map last_error, - String model, - String instructions, - List incomplete_details, - List tools, - ToolResources tool_resources, - Map metadata, - Map usage, - Double temperature, - Double top_p, - Long max_prompt_tokens, - Long max_completion_tokens, - TruncationStrategy truncation_strategy, - String response_format, - String tool_choice, - Boolean parallel_tool_calls -) {} diff --git a/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/AiThreadResponse.java b/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/AiThreadResponse.java deleted file mode 100644 index cee2b014..00000000 --- a/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/AiThreadResponse.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.space.server.domain.ai.service.dto.response.gpt; - -import java.util.Map; - -public record AiThreadResponse( - String id, - String object, - Long created_at, - Map metadata, - ToolResources tool_resources -) {} diff --git a/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/MessagesContent.java b/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/MessagesContent.java deleted file mode 100644 index 4443e99b..00000000 --- a/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/MessagesContent.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.space.server.domain.ai.service.dto.response.gpt; - -public record MessagesContent( - String type, - MessagesText text -) {} diff --git a/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/MessagesText.java b/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/MessagesText.java deleted file mode 100644 index 8e732d1c..00000000 --- a/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/MessagesText.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.space.server.domain.ai.service.dto.response.gpt; - -import java.util.List; - -public record MessagesText( - String value, - List annotations -) {} diff --git a/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/ToolResources.java b/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/ToolResources.java deleted file mode 100644 index dbf638a4..00000000 --- a/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/ToolResources.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.space.server.domain.ai.service.dto.response.gpt; - -import java.util.List; -import java.util.Map; - -public record ToolResources( - Map code_interpreter, - Map file_search -) {} diff --git a/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/TruncationStrategy.java b/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/TruncationStrategy.java deleted file mode 100644 index 31786ba9..00000000 --- a/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/TruncationStrategy.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.space.server.domain.ai.service.dto.response.gpt; - -public record TruncationStrategy( - String type, - String last_messages -) {} diff --git a/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/tools/FileSearch.java b/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/tools/FileSearch.java deleted file mode 100644 index 6c014064..00000000 --- a/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/tools/FileSearch.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.space.server.domain.ai.service.dto.response.gpt.tools; - -import java.util.Map; - -public record FileSearch( - Long max_num_results, - Map ranking_options -) {} diff --git a/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/tools/FileSearchTool.java b/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/tools/FileSearchTool.java deleted file mode 100644 index 20ca1f18..00000000 --- a/src/main/java/com/space/server/domain/ai/service/dto/response/gpt/tools/FileSearchTool.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.space.server.domain.ai.service.dto.response.gpt.tools; - -public record FileSearchTool( - String type, - FileSearch file_search -) {} diff --git a/src/main/java/com/space/server/domain/ai/service/dto/response/internal/AiAllMessagesResponse.java b/src/main/java/com/space/server/domain/ai/service/dto/response/internal/AiAllMessagesResponse.java new file mode 100644 index 00000000..3d833d1b --- /dev/null +++ b/src/main/java/com/space/server/domain/ai/service/dto/response/internal/AiAllMessagesResponse.java @@ -0,0 +1,8 @@ +package com.space.server.domain.ai.service.dto.response.internal; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public record AiAllMessagesResponse( + String first_id +) {} diff --git a/src/main/java/com/space/server/domain/ai/service/dto/response/internal/AiMessagesResponse.java b/src/main/java/com/space/server/domain/ai/service/dto/response/internal/AiMessagesResponse.java new file mode 100644 index 00000000..379739c3 --- /dev/null +++ b/src/main/java/com/space/server/domain/ai/service/dto/response/internal/AiMessagesResponse.java @@ -0,0 +1,10 @@ +package com.space.server.domain.ai.service.dto.response.internal; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public record AiMessagesResponse( + List content +) {} diff --git a/src/main/java/com/space/server/domain/ai/service/dto/response/internal/AiRunsResponse.java b/src/main/java/com/space/server/domain/ai/service/dto/response/internal/AiRunsResponse.java new file mode 100644 index 00000000..d5331242 --- /dev/null +++ b/src/main/java/com/space/server/domain/ai/service/dto/response/internal/AiRunsResponse.java @@ -0,0 +1,9 @@ +package com.space.server.domain.ai.service.dto.response.internal; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public record AiRunsResponse( + String id, + String status +) {} diff --git a/src/main/java/com/space/server/domain/ai/service/dto/response/internal/AiThreadResponse.java b/src/main/java/com/space/server/domain/ai/service/dto/response/internal/AiThreadResponse.java new file mode 100644 index 00000000..29e5b1ce --- /dev/null +++ b/src/main/java/com/space/server/domain/ai/service/dto/response/internal/AiThreadResponse.java @@ -0,0 +1,8 @@ +package com.space.server.domain.ai.service.dto.response.internal; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public record AiThreadResponse( + String id +) {} diff --git a/src/main/java/com/space/server/domain/ai/service/dto/response/internal/MessagesContent.java b/src/main/java/com/space/server/domain/ai/service/dto/response/internal/MessagesContent.java new file mode 100644 index 00000000..ed8cb0f8 --- /dev/null +++ b/src/main/java/com/space/server/domain/ai/service/dto/response/internal/MessagesContent.java @@ -0,0 +1,8 @@ +package com.space.server.domain.ai.service.dto.response.internal; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public record MessagesContent( + MessagesText text +) {} diff --git a/src/main/java/com/space/server/domain/ai/service/dto/response/internal/MessagesText.java b/src/main/java/com/space/server/domain/ai/service/dto/response/internal/MessagesText.java new file mode 100644 index 00000000..5cb54695 --- /dev/null +++ b/src/main/java/com/space/server/domain/ai/service/dto/response/internal/MessagesText.java @@ -0,0 +1,8 @@ +package com.space.server.domain.ai.service.dto.response.internal; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public record MessagesText( + String value +) {} diff --git a/src/main/java/com/space/server/domain/ai/service/implementation/ChatCompleter.java b/src/main/java/com/space/server/domain/ai/service/implementation/ChatCompleter.java index d369aa0a..d138653f 100644 --- a/src/main/java/com/space/server/domain/ai/service/implementation/ChatCompleter.java +++ b/src/main/java/com/space/server/domain/ai/service/implementation/ChatCompleter.java @@ -1,13 +1,13 @@ package com.space.server.domain.ai.service.implementation; import com.fasterxml.jackson.databind.ObjectMapper; -import com.space.server.domain.ai.service.dto.request.gpt.AiChat; -import com.space.server.domain.ai.service.dto.request.gpt.AiRunsRequest; -import com.space.server.domain.ai.service.dto.request.gpt.AiThreadRequest; -import com.space.server.domain.ai.service.dto.response.gpt.AiAllMessagesResponse; -import com.space.server.domain.ai.service.dto.response.gpt.AiMessagesResponse; -import com.space.server.domain.ai.service.dto.response.gpt.AiRunsResponse; -import com.space.server.domain.ai.service.dto.response.gpt.AiThreadResponse; +import com.space.server.domain.ai.service.dto.request.internal.AiChat; +import com.space.server.domain.ai.service.dto.request.internal.AiRunsRequest; +import com.space.server.domain.ai.service.dto.request.internal.AiThreadRequest; +import com.space.server.domain.ai.service.dto.response.internal.AiAllMessagesResponse; +import com.space.server.domain.ai.service.dto.response.internal.AiMessagesResponse; +import com.space.server.domain.ai.service.dto.response.internal.AiRunsResponse; +import com.space.server.domain.ai.service.dto.response.internal.AiThreadResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpEntity; diff --git a/src/main/java/com/space/server/domain/ai/service/implementation/MessageCreator.java b/src/main/java/com/space/server/domain/ai/service/implementation/MessageCreator.java new file mode 100644 index 00000000..934bab4c --- /dev/null +++ b/src/main/java/com/space/server/domain/ai/service/implementation/MessageCreator.java @@ -0,0 +1,4 @@ +package com.space.server.domain.ai.service.implementation; + +public class MessageCreator { +} diff --git a/src/main/java/com/space/server/domain/ai/service/implementation/MessageReader.java b/src/main/java/com/space/server/domain/ai/service/implementation/MessageReader.java new file mode 100644 index 00000000..d3dc9c1d --- /dev/null +++ b/src/main/java/com/space/server/domain/ai/service/implementation/MessageReader.java @@ -0,0 +1,4 @@ +package com.space.server.domain.ai.service.implementation; + +public class MessageReader { +} diff --git a/src/main/java/com/space/server/domain/ai/service/implementation/RunsCreator.java b/src/main/java/com/space/server/domain/ai/service/implementation/RunsCreator.java new file mode 100644 index 00000000..242880c5 --- /dev/null +++ b/src/main/java/com/space/server/domain/ai/service/implementation/RunsCreator.java @@ -0,0 +1,4 @@ +package com.space.server.domain.ai.service.implementation; + +public class RunsCreator { +} diff --git a/src/main/java/com/space/server/domain/ai/service/implementation/RunsReader.java b/src/main/java/com/space/server/domain/ai/service/implementation/RunsReader.java new file mode 100644 index 00000000..4b9691bf --- /dev/null +++ b/src/main/java/com/space/server/domain/ai/service/implementation/RunsReader.java @@ -0,0 +1,4 @@ +package com.space.server.domain.ai.service.implementation; + +public class RunsReader { +} diff --git a/src/main/java/com/space/server/domain/ai/service/implementation/ThreadCreator.java b/src/main/java/com/space/server/domain/ai/service/implementation/ThreadCreator.java new file mode 100644 index 00000000..a13fde16 --- /dev/null +++ b/src/main/java/com/space/server/domain/ai/service/implementation/ThreadCreator.java @@ -0,0 +1,4 @@ +package com.space.server.domain.ai.service.implementation; + +public class ThreadCreator { +} diff --git a/src/main/java/com/space/server/domain/chat/service/CommandChatService.java b/src/main/java/com/space/server/domain/chat/service/CommandChatService.java index 91268c39..a13817db 100644 --- a/src/main/java/com/space/server/domain/chat/service/CommandChatService.java +++ b/src/main/java/com/space/server/domain/chat/service/CommandChatService.java @@ -1,11 +1,11 @@ package com.space.server.domain.chat.service; -import com.space.server.domain.ai.service.dto.request.gpt.AiChat; +import com.space.server.domain.ai.service.dto.request.internal.AiChat; import com.space.server.domain.ai.service.dto.response.AiResponse; -import com.space.server.domain.ai.service.dto.response.gpt.AiAllMessagesResponse; -import com.space.server.domain.ai.service.dto.response.gpt.AiMessagesResponse; -import com.space.server.domain.ai.service.dto.response.gpt.AiRunsResponse; -import com.space.server.domain.ai.service.dto.response.gpt.AiThreadResponse; +import com.space.server.domain.ai.service.dto.response.internal.AiAllMessagesResponse; +import com.space.server.domain.ai.service.dto.response.internal.AiMessagesResponse; +import com.space.server.domain.ai.service.dto.response.internal.AiRunsResponse; +import com.space.server.domain.ai.service.dto.response.internal.AiThreadResponse; import com.space.server.domain.ai.service.implementation.ChatCompleter; import com.space.server.domain.ai.service.implementation.PromptCreator; import com.space.server.domain.chat.domain.Chat;