03. Service를 구현해보자!

2024. 1. 20. 22:37·Web/GPT 응답 API 서버

이제 컨트롤러에서 요청 Dto로 서비스에게 넘겨주었으니 이제 비즈니스 로직을 구현할 차례입니다.

사실 지금 구현하고 있는 API 서버의 비스니스 로직은 매우 간단합니다.

그저 OpenAI API가 요구하는 형태로 Curl 요청만 보내면 되는 것이기 때문입니다.

Java 에서 Http 요청을 하는 방법을 여러가지가 있습니다. Http Client를 사용하던지, HttpURLConnection을 사용하던지 등의 방법이 있습니다.

하지만 저는 Spring Cloud에서 사용하는 Rest Http 요청을 아주아주 쉽게 사용하게 해주는 OpenFeign이라는 라이브러리를 사용하여 처리를 해볼 예정입니다!

먼저, OpenFeign 라이브러리를 추가하기 위해 build.gradle에 spring cloud를 추가하여줍니다.

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.2.1'
    id 'io.spring.dependency-management' version '1.1.4'
}

ext {
    set('springCloudVersion', "2023.0.0")
}

 

스프링 클라우드 공식 홈페이지 (https://spring.io/projects/spring-cloud/) 에서 확인햇을 때 spring boot 버전이 3.2.x 버전이면 2023.0.x 버전을 세팅하라고 명시되어 있었고 저는 그 중 가장 최신 버전인 '2023.0.0'을 셋팅하여 주었습니다.

 

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    }
}

 

그리고, dependencyManagement를 추가해주었고 마지막으로 OpenFeign 라이브러리와 Json 형태의 응답을 처리하기 위한 Gson을 추가하여 주었습니다.

 

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'

    // feign
    implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'

    // json
    implementation 'com.google.code.gson:gson:2.10.1'

}

 

여기까지 하였으면 50%이상은 완료하였습니다!

다음으로, OpenAI API 서버에 Http 요청을 하기위한 OpenFeign Interface를 하나 생성합니다.

 

@FeignClient(name = "chat-gpt-open-feign", url = "${gpt.url}")
public interface ChatGptOpenFeign {
    @PostMapping(value = "/v1/chat/completions", consumes = "application/json")
    String requestAnswerToOpenAiApiByText(
            @RequestHeader("Authorization") String authorizationHeader,
            @RequestBody GptApiTextReq req
            );
}

 

그 후, 텍스트 처리를 해주는 End Point로 요청을 보내줄 requestAnswerToOpenAiApiByText 메서드를 하나 생성하였습니다.

이 메서드는 Post 형태로 요청을 보내며, response data type은 'application/json', 그리고 헤더에 Authorization을 추가하고, 바디에 Text 요청에서 요구하는 데이터 형식으로 만들어진 GptApiTextReq를 추가하여 보내도록 설정하였습니다.

OpenFeign 사용법은 도큐먼트나, 여러 포스팅을 참고하면 아주 쉽게 확인할 수 있습니다!

 

그 다음으로 OpenAI api에 Text 요청을 할 GptApiTextReq Dto 입니다.

@Data
@Builder
public class GptApiTextReq {

    private String model;
    private List<Message> messages;

    @Data
    @Builder
    public static class Message {
        private String role;
        private String content;
    }

}

 

예제의 바디 데이터를 보면

{
    "model": "gpt-3.5-turbo",
    "messages": [
      {
        "role": "system",
        "content": "You are a poetic assistant, skilled in explaining complex programming concepts with creative flair."
      },
      {
        "role": "user",
        "content": "Compose a poem that explains the concept of recursion in programming."
      }
    ]
  }'

 

이런식으로 되어있는 것을 확인 할 수 있습니다. 똑같은 형태로 Dto를 생성하였습니다.

 

이런 부수적인 것을 모두 생성하였으면, 이제 비즈니스 로직을 작성합니다.

@Service
@Slf4j
@RequiredArgsConstructor
public class GptApiService {

    private final ChatGptOpenFeign chatGptOpenFeign;
    private final Gson gson;

    @Value("${gpt.token}")
    private String token;
    @Value("${gpt.model}")
    private String model;

    public List<JsonObject> getAnswerForQuestion(TextReq req) {

        String resp = chatGptOpenFeign.requestAnswerToOpenAiApiByText(token,
                GptApiTextReq.builder()
                        .model(model)
                        .messages(Arrays.asList(
                                GptApiTextReq.Message.builder()
                                        .role("user")
                                        .content(req.getQuestion())
                                        .build()
                        ))
                        .build());


        JsonObject result = gson.fromJson(resp, JsonObject.class);
        JsonArray choicesArray = result.getAsJsonArray("choices");
        Type type = new TypeToken<List<JsonObject>>() {}.getType();

        return gson.fromJson(choicesArray.toString(), type);
    }
}

 

해당 로직은 매우 간단합니다. 

아까 생성한 ChatGptOpenFeign 인터페이스를 가져와서 requestAnswerToOpenAiApiByText 메서드를 통해 OpenAI API 서버에 Post 요청을 보내는데, 요청할 때 설정파일에 있는 Token값과 Rest 요청으로 들어온 TextReq를 OpenAI API 가 요구하는 요청 형태인 GptApiTextReq 로 변환하여 요청을 보낸 후,

해당 String 응답을 Gson을 통해 Json 형태로 변환 후, 아래와 같은 응답에서 choices 부분만 선택하여 반환하도록 작성하였습니다.

 

{
  "object": "chat.completion",
  "created": 1705493878,
  "model": "gpt-3.5-turbo-0613",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "In the realm where code unfolds its mysterious dance,\nThere lies a concept, both elusive and grand,\nRecursion, a melody that programmers adore,\nA symphony of function, time, and more.\n\nImagine a mirror, reflecting our sight,\nAn image appearing, recursive in its flight,\nA function that calls itself, oh the delight,\nUnwinding complexities, taking us to new heights.\n\nLike a Russian doll, layers within layers,\nA nested pattern, weaving a code that never wavers,\nEach invocation, a step deeper into the abyss,\nSolving problems, with elegance and bliss.\n\nA problem divided, like fractal in design,\nRecursive call, each instance intertwined,\nReducing the puzzle, like a mountain to a hill,\nRecursive whisper, revealing the thrill.\n\nYet caution befalls those who wield this might,\nThe infinite loop, lurking in the night,\nAn absent base case, a silent trap,\nBringing upon chaos, like a wild untamed map.\n\nBut fear not, dear programmer, for there is a guide,\nTo traverse recursion's tangled tide,\nThe base case, a lighthouse in the storm,\nEscaping loops, keeping your code warm.\n\nLike Fibonacci's sequence, a waltz in the air,\nNumbers unfolding, Fibonacci is there,\nRepeating the process, till infinity arrives,\nA dance of patterns, where beauty survives.\n\nAnd so dear friend, let recursion inspire,\nIn this world of coding, where we never tire,\nA concept profound, yet gracefully surreal,\nRecursion, a muse, that programmers feel."
      },
      "logprobs": null,
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 39,
    "completion_tokens": 310,
    "total_tokens": 349
  },
  "system_fingerprint": null
}

 

저작자표시 비영리 변경금지 (새창열림)

'Web > GPT 응답 API 서버' 카테고리의 다른 글

04. 마무리!  (0) 2024.01.20
02. Controller와 Dto를 생성해보자!  (0) 2024.01.20
01. API 구조를 설계해보자!  (0) 2024.01.20
00. Chat GPT 응답을 반환해주는 API 서버를 만들어보자!  (0) 2024.01.20
'Web/GPT 응답 API 서버' 카테고리의 다른 글
  • 04. 마무리!
  • 02. Controller와 Dto를 생성해보자!
  • 01. API 구조를 설계해보자!
  • 00. Chat GPT 응답을 반환해주는 API 서버를 만들어보자!
뚝딱뚝딱2
뚝딱뚝딱2
  • 뚝딱뚝딱2
    개발도상국
    뚝딱뚝딱2
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 공부
        • Java
        • Spring Boot
        • LORA
      • Web
        • 인스타 클론 코딩
        • GPT 응답 API 서버
        • Spring Boot 예외 처리
        • 코테 준비용 서비스 만들기
      • DevOps
        • 쿠버네티스
        • 서버 만들기
      • 코딩테스트
        • 알고리즘
      • 교육
        • 스파르타코딩클럽 - 내일배움단
        • 혼자 공부하는 컴퓨터 구조 운영체제
      • 잡다한것
  • 블로그 메뉴

    • 홈
  • 링크

    • GITHUB
  • 공지사항

  • 인기 글

  • 태그

    백준
    react
    spring boot
    오블완
    스프링부트
    리액트
    OpenAI API
    클론코딩
    클러스터
    예외
    스프링 부트
    MSA
    Entity
    인스타그램
    chat GPT
    티스토리챌린지
    mapstruct
    Java
    쿠버네티스
    REST API
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
뚝딱뚝딱2
03. Service를 구현해보자!
상단으로

티스토리툴바