-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Feat/#64 : GPT 요청 방식을 수정합니다.
- Loading branch information
Showing
6 changed files
with
174 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -45,3 +45,4 @@ foodData.csv | |
Untitled-1.py | ||
/src/main/resources/secret.yml | ||
/menu-data | ||
*.txt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
91 changes: 91 additions & 0 deletions
91
src/main/java/com/mju/capstone/recommend/config/AzureConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
package com.mju.capstone.recommend.config; | ||
|
||
|
||
import com.azure.ai.openai.assistants.AssistantsClient; | ||
import com.azure.ai.openai.assistants.AssistantsClientBuilder; | ||
import com.azure.ai.openai.assistants.AssistantsServiceVersion; | ||
import com.azure.ai.openai.assistants.models.Assistant; | ||
import com.azure.ai.openai.assistants.models.AssistantCreationOptions; | ||
import com.azure.ai.openai.assistants.models.CreateFileSearchToolResourceOptions; | ||
import com.azure.ai.openai.assistants.models.CreateFileSearchToolResourceVectorStoreOptions; | ||
import com.azure.ai.openai.assistants.models.CreateFileSearchToolResourceVectorStoreOptionsList; | ||
import com.azure.ai.openai.assistants.models.CreateToolResourcesOptions; | ||
import com.azure.ai.openai.assistants.models.FileDetails; | ||
import com.azure.ai.openai.assistants.models.FilePurpose; | ||
import com.azure.ai.openai.assistants.models.FileSearchToolDefinition; | ||
import com.azure.ai.openai.assistants.models.OpenAIFile; | ||
import com.azure.core.credential.AzureKeyCredential; | ||
import com.azure.core.util.BinaryData; | ||
import java.io.BufferedReader; | ||
import java.io.IOException; | ||
import java.io.InputStreamReader; | ||
import java.nio.charset.StandardCharsets; | ||
import java.nio.file.Path; | ||
import java.nio.file.Paths; | ||
import java.util.Arrays; | ||
import java.util.Objects; | ||
import java.util.stream.Collectors; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
|
||
@Configuration | ||
@RequiredArgsConstructor | ||
@Slf4j | ||
public class AzureConfig { | ||
|
||
@Value("${azure.credential}") | ||
private String credentialKey; | ||
@Value("${azure.endpoint}") | ||
private String endpoint; | ||
@Value("${azure.key}") | ||
private String key; | ||
@Value("${azure.model}") | ||
private String model; | ||
|
||
@Bean | ||
AssistantsClient assistantsClient() { | ||
return new AssistantsClientBuilder() | ||
.credential(new AzureKeyCredential(key)) | ||
.serviceVersion(AssistantsServiceVersion.getLatest()) | ||
.endpoint(endpoint) | ||
.buildClient(); | ||
} | ||
|
||
@Bean | ||
public Assistant customAssistant(AssistantsClient client) throws IOException { | ||
|
||
Path filePath = Paths.get("src/main/resources/menu_final.txt"); | ||
BinaryData fileData = BinaryData.fromFile(filePath); | ||
FileDetails fileDetails = new FileDetails(fileData, "menu_final.txt"); | ||
|
||
|
||
OpenAIFile openAIFile = client.uploadFile(fileDetails, FilePurpose.ASSISTANTS); | ||
|
||
String instructions = loadInstructionsFromFile("instruction2.txt"); | ||
log.info("Application Started with Instructions: {}", instructions); | ||
|
||
CreateToolResourcesOptions createToolResourcesOptions = new CreateToolResourcesOptions(); | ||
createToolResourcesOptions.setFileSearch( | ||
new CreateFileSearchToolResourceOptions( | ||
new CreateFileSearchToolResourceVectorStoreOptionsList( | ||
Arrays.asList(new CreateFileSearchToolResourceVectorStoreOptions(Arrays.asList(openAIFile.getId())))))); | ||
|
||
return client.createAssistant( | ||
new AssistantCreationOptions(model) | ||
.setName("영양사") | ||
.setInstructions(instructions) | ||
.setTools(Arrays.asList(new FileSearchToolDefinition())) | ||
.setToolResources(createToolResourcesOptions) | ||
); | ||
} | ||
|
||
private String loadInstructionsFromFile(String filePath) throws IOException { | ||
try (BufferedReader reader = new BufferedReader(new InputStreamReader( | ||
Objects.requireNonNull(this.getClass().getClassLoader().getResourceAsStream(filePath)), StandardCharsets.UTF_8))) { | ||
return reader.lines().collect(Collectors.joining("\n")); | ||
} | ||
} | ||
} |
99 changes: 65 additions & 34 deletions
99
src/main/java/com/mju/capstone/recommend/repository/GptManagerImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,61 +1,92 @@ | ||
package com.mju.capstone.recommend.repository; | ||
|
||
import static org.springframework.http.MediaType.APPLICATION_JSON; | ||
import static com.azure.ai.openai.assistants.models.MessageRole.USER; | ||
|
||
import com.mju.capstone.global.exception.BusinessException; | ||
import com.mju.capstone.global.response.message.ErrorMessage; | ||
import com.azure.ai.openai.assistants.AssistantsClient; | ||
import com.azure.ai.openai.assistants.models.Assistant; | ||
import com.azure.ai.openai.assistants.models.AssistantThread; | ||
import com.azure.ai.openai.assistants.models.AssistantThreadCreationOptions; | ||
import com.azure.ai.openai.assistants.models.CreateRunOptions; | ||
import com.azure.ai.openai.assistants.models.MessageContent; | ||
import com.azure.ai.openai.assistants.models.MessageTextContent; | ||
import com.azure.ai.openai.assistants.models.PageableList; | ||
import com.azure.ai.openai.assistants.models.RunStatus; | ||
import com.azure.ai.openai.assistants.models.ThreadMessage; | ||
import com.azure.ai.openai.assistants.models.ThreadMessageOptions; | ||
import com.azure.ai.openai.assistants.models.ThreadRun; | ||
import com.fasterxml.jackson.core.type.TypeReference; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.mju.capstone.recommend.domain.GptManager; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
import com.mju.capstone.recommend.dto.response.Menu; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.context.annotation.PropertySource; | ||
import org.springframework.core.ParameterizedTypeReference; | ||
import org.springframework.http.HttpEntity; | ||
import org.springframework.http.HttpHeaders; | ||
import org.springframework.http.HttpMethod; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.stereotype.Repository; | ||
import org.springframework.web.client.RestTemplate; | ||
|
||
@Repository | ||
@PropertySource("classpath:application.yml") | ||
@RequiredArgsConstructor | ||
@Slf4j | ||
public class GptManagerImpl implements GptManager { | ||
|
||
private final RestTemplate restTemplate; | ||
private final AssistantsClient client; | ||
private final Assistant assistant; | ||
|
||
public List<Menu> sendOpenAIRequest(String messageContent) { | ||
log.info("Processing message: {}", messageContent); | ||
|
||
AssistantThread thread = createAssistantThread(); | ||
sendMessageToThread(thread.getId(), messageContent); | ||
|
||
@Value("${python-server.url}") | ||
private String server_url; | ||
List<Menu> result; | ||
|
||
public GptManagerImpl(RestTemplate restTemplate) { | ||
this.restTemplate = restTemplate; | ||
try { | ||
result = getGptResponse(thread.getId()); | ||
} catch (InterruptedException e) { | ||
throw new RuntimeException(e); | ||
} | ||
return result; | ||
} | ||
|
||
public List<Menu> sendOpenAIRequest(String request) { | ||
private AssistantThread createAssistantThread() { | ||
return client.createThread(new AssistantThreadCreationOptions()); | ||
} | ||
|
||
String url = server_url; | ||
Map<String, String> requestBody = new HashMap<>(); | ||
requestBody.put("content", request); | ||
HttpHeaders headers = new HttpHeaders(); | ||
headers.setContentType(APPLICATION_JSON); | ||
private void sendMessageToThread(String threadId, String messageContent) { | ||
client.createMessage(threadId, new ThreadMessageOptions(USER, messageContent)); | ||
} | ||
|
||
HttpEntity<Map<String, String>> requestHttpEntity = new HttpEntity<>(requestBody, headers); | ||
private List<Menu> getGptResponse(String threadId) throws InterruptedException { | ||
ThreadRun run = client.createRun(threadId, new CreateRunOptions(assistant.getId())); | ||
|
||
// ResponseModel response= restTemplate.postForObject(url, requestHttpEntity, ResponseModel.class); | ||
do { | ||
run = client.getRun(run.getThreadId(), run.getId()); | ||
Thread.sleep(500); | ||
} while (run.getStatus() == RunStatus.QUEUED || run.getStatus() == RunStatus.IN_PROGRESS); | ||
|
||
ResponseEntity<List<Menu>> responseEntity = | ||
restTemplate.exchange(url,HttpMethod.POST,requestHttpEntity,new ParameterizedTypeReference<List<Menu>>() {}); | ||
return extractMessagesFromResponse(client.listMessages(run.getThreadId())); | ||
} | ||
|
||
log.info(responseEntity.getBody().toString()); | ||
List<Menu> recommendResponse = responseEntity.getBody(); | ||
private List<Menu> extractMessagesFromResponse(PageableList<ThreadMessage> messages) { | ||
List<Menu> result = new ArrayList<>(); | ||
ObjectMapper objectMapper = new ObjectMapper(); | ||
ThreadMessage threadMessage = messages.getData().getFirst(); | ||
|
||
if (recommendResponse.isEmpty() || recommendResponse == null) { | ||
throw new BusinessException(ErrorMessage.RECOMMEND_NOT_FOUND); | ||
for (MessageContent messageContent : threadMessage.getContent()) { | ||
String jsonResponse = ((MessageTextContent) messageContent).getText().getValue(); | ||
log.info("Message content: {}", jsonResponse); | ||
try { | ||
jsonResponse = jsonResponse.replaceAll("```json", "").trim(); | ||
List<Menu> menu = objectMapper.readValue(jsonResponse, new TypeReference<>() { | ||
}); | ||
result.addAll(menu); | ||
} catch (Exception e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
return recommendResponse; | ||
log.info("result: {}" ,result.toString()); | ||
return result; | ||
} | ||
} |