1.개발 진행 및 완료상황
현재 db도 어느정도 정규화가 진행되었다.
각자 역할을 나누어 어느부분 파트를 코딩할지 역할 분배가 완료되었다.
2. OPEN AI API사용
자기소개서를 ai로 피드백해주는 기능이 있다면 사용자들이 보다 편하게 입사지원을 할 수 있지 않을까? 하는 생각에서 고안된 아이디어이다. 그런데 찾아보니 이미 각종 사이트에서 사용되고있는 기능이어서 좀 아쉬웠다. 이거 말고도 다른 아이디어들도 몇개있었는데 타 사이트에서 찾아보기 힘든 아이디어였지만 그만큼 실용도도 떨어져서 굳이 채택하진 않았다.
writeValueAsString
이 메소드는 JAVA객체를 JSON문자열로 변환하기 위해 사용아였는데 클라이언트에 사용자가 입력한 정보를 담아오고 컨트롤러(서버)에서 model과 token값을 지정해주었다.
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> requestBodyMap = new HashMap<>();
requestBodyMap.put("model", "gpt-3.5-turbo");
requestBodyMap.put("messages", request.getMessages());
requestBodyMap.put("max_tokens", 1000);
String requestBody;
try {
requestBody = objectMapper.writeValueAsString(requestBodyMap);
} catch (JsonProcessingException e) {
logger.error("JSON 변환 오류: {}", e.getMessage());
return ResponseEntity.badRequest().body(Map.of("message", "JSON 변환 오류"));
}
Rest Template
이 템플릿을 사용하여 OPEN AI API를 불러올때 호출시간과 응답시간을 조절하였다.
String url = "https://api.openai.com/v1/chat/completions";
HttpEntity<String> entity = new HttpEntity<>(requestBody, headers);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder
.setConnectTimeout(Duration.ofSeconds(10)) // 연결 타임아웃
.setReadTimeout(Duration.ofSeconds(60)) // 읽기 타임아웃
.build();
}
- url : 요청을 보낼 URL
- HttpMethod.POST : HTTP 메서드 (POST)
- entity : 요청 본문 및 헤더를 포함한 HttpEntity
- String.class : 응답 본문 타입
is2xxSuccessful
HTTP 응답의 상태 코드가 200번대(즉, 성공적인 응답)인지 확인하는 데 사용하였다. 요청이 성공적이면 true를 반환하게 된다.
JsonNode
readTree: 주어진 JSON 문자열을 JsonNode 객체로 변환
JsonNode: JSON 데이터를 트리 구조로 표현하는 클래스.
JsonNode 객체로 변환하는 이유
- 구조 탐색: JSON 데이터를 트리 형태로 표현하여, 각 필드에 쉽게 접근할 수 있다. 예를 들어, jsonNode.get("choices")로 "choices" 배열을 쉽게 가져올 수 있다.
- 타입 변환: JSON 값의 타입을 쉽게 변환할 수 있어, 필요한 형태로 데이터를 사용할 수 있다. 예를 들어, .asText()로 문자열로 변환할 수 있다.
- 에러 처리: JSON 문자열을 파싱할 때 발생할 수 있는 오류를 catch 블록에서 쉽게 관리할 수 있어, 안정적인 코드 작성이 가능하다.
if (response.getStatusCode().is2xxSuccessful()) {
String responseBody = response.getBody();
try {
JsonNode jsonNode = objectMapper.readTree(responseBody);
String improvedCoverLetter = jsonNode.get("choices").get(0).get("message").get("content").asText();
Map<String, String> result = new HashMap<>();
result.put("improvedCoverLetter", improvedCoverLetter);
return ResponseEntity.ok(result);
이때, OpenAI API에서 choies객체의 0번째 배열의 메세지의 content를 불러와 문자열로 변환한다.
curl https://api.openai.com/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-d '{
"model": "gpt-3.5-turbo",
"messages": [
{
"role": "system",
"content": "You are a helpful assistant."
},
{
"role": "user",
"content": "Hello!"
}
]
}'
호출예시
{
"id": "chatcmpl-123",
"object": "chat.completion",
"created": 1677652288,
"model": "gpt-3.5-turbo",
"system_fingerprint": "fp_44709d6fcb",
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": "\n\nHello there, how may I assist you today?",
},
"logprobs": null,
"finish_reason": "stop"
}],
"usage": {
"prompt_tokens": 9,
"completion_tokens": 12,
"total_tokens": 21,
"completion_tokens_details": {
"reasoning_tokens": 0,
"accepted_prediction_tokens": 0,
"rejected_prediction_tokens": 0
}
}
}
API응답예시
이를 토대로 json객체를 전달하였고 서버에서 호출처리를 구현하였다.
🦠문제상황
fetch('http://localhost:9090/coverletter/improve', {
method: 'POST',
headers: {
분명히 이렇게 POST방식으로 전송해주었지만 네트워크에서 자꾸 GET요청이 들어왔다는 오류가 나타났다. 그래서 Talend API Tester를 이용하여 먼저 테스트 해보았다. 처음엔
이렇게 api인증키 없이 전송요청을 했더니
이렇게만 나왔다. OPEN AI사이트를 들어가서 확인해보니
이렇게 권한 만료가 되있어서 새로 결제를 해야했다. 그런데 결제를 하고나서도 여전히 " 요청이 너무 많다" 는 오류가 발생하였다. 또한
🪄해결
뭐가문제인지 고민하다 설마 URI가 잘못되었나 싶어 https://api.openai.com/v1/chat/completions 이 URI를 넣었더니 정상적으로 작동하였다.
{
"model": "gpt-3.5-turbo",
"messages": [
{
"role": "system",
"content": "이 이력서를 업그레이드 시켜줘"
},
{
"role": "user",
"content": "안녕하세요, 저는 홍길동이며 현재 서울대학교에서 컴퓨터공학을 전공하고 있습니다. 대학 생활 동안 다양한 팀 프로젝트에 참여하여 문제 해결 능력과 협업 능력을 키웠고, 특히 최근에는 인공지능 관련 연구 프로젝트에 참여하여 데이터 분석 및 프로그래밍 기술을 향상시켰습니다. 앞으로 IT 분야에서 혁신적인 솔루션을 개발하며 성장할 수 있는 기회를 찾고 있습니다.!"
}
]
}
요청
{
"id": "chatcmpl-AX5wzqjUkNP8De1ur3eYnE9hILe9b",
"object": "chat.completion",
"created": 1732451061,
"model": "gpt-3.5-turbo-0125",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "안녕하세요, 홍길동님!\n\n홍길동님의 경력과 학습 경험을 종합하여 이력서를 업그레이드해보겠습니다.\n\n---\n\n# 홍길동\n## 컴퓨터공학 전공 학생\n\n### 학력\n- 서울대학교 컴퓨터공학과 재학 중\n- GPA: x.x / 4.5\n\n### 핵심 역량\n- 문제 해결능력과 협업 능력 보유\n- 데이터 분석 및 프로그래밍 기술 보유\n- 인공지능 관련 연구 프로젝트 참여 경험\n- 다양한 팀 프로젝트 경험\n\n### 경력\n- 인공지능 관련 연구 프로젝트 참여 (날짜)\n - 데이터 분석 및 프로그래밍 역할 수행\n - 팀원들과의 협업을 통해 문제 해결\n- 팀 프로젝트 경험 (날짜)\n - XXX 프로젝트: (간단한 설명)\n - YYY 프로젝트: (간단한 설명)\n\n### 기술 스킬\n- 프로그래밍 언어: Python, Java, C++\n- 데이터 분석 도구: Pandas, NumPy, Scikit-learn\n- 웹 개발: HTML, CSS, JavaScript\n\n### 희망 직무\n- IT 분야에서 혁신적인 솔루션 개발에 관심\n- 성장 가능한 환경에서 능력 발전 및 경험 쌓기 희망\n\n---\n\n홍길동님의 이력서를 좀 더 간결하고 전문적으로 업그레이드해 보았습니다. 특히, 학력, 경력, 기술 스킬, 희망 직무 등을 명확히 구분하여 정보를 제공하였습니다. 이 내용을 참고하여 더욱 강조하고 싶은 부분이 있거나 추가할 내용이 있다면 자유롭게 말씀해주세요.",
"refusal": null
},
"logprobs": null,
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 221,
"completion_tokens": 599,
"total_tokens": 820,
"prompt_tokens_details": {
"cached_tokens": 0,
"audio_tokens": 0
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"audio_tokens": 0,
"accepted_prediction_tokens": 0,
"rejected_prediction_tokens": 0
}
},
"system_fingerprint": null
}
응답
이때, 로컬에서 개발한 API가 아닌, 외부 API의 기능을 활용하는 것이기 때문에 OpenAI의 엔드포인트를 지정해 OpenAI의 AI모델에 직접 요청을 보내고 응답을 받아야한다. 두 주소의 사용목적이 엄연히 다른 것을... 간과하였다.
풀 소스는 https://github.com/verynahce/TeamProject2 여기서 확인가능하다.
3. 참고 사이트
org.springframework.web.client (Spring Framework 6.2.0 API)
Client to perform HTTP requests, exposing a fluent, synchronous API over underlying HTTP client libraries such as the JDK HttpClient, Apache HttpComponents, and others. Synchronous client to perform HTTP requests, exposing a simple, template method API ove
docs.spring.io
https://platform.openai.com/docs/api-reference/chat/object?lang=curl
4. 회고
처음에는 아이디어만 가지고 어떻게 구현할지 막막했지만, 여러 사이트를 참고하며 완성해 나가다 보니 어느새 내가 원하던 그림이 완성되었다. 아쉬운 점은 파일로 업로드된 포트폴리오를 반영하여 자기소개서를 보완해주는 프로그램을 완성하고 싶었으나, 다른 작업들이 많아 사용자가 입력한 정보에 기반해 피드백을 제공하는 정도로 그치게 되었다. 프로젝트가 끝난 후에는 개인적으로 이 기능을 보완하고 싶다.
그동안 ChatGPT를 자료 참고에만 활용했었지만, 이번 프로젝트를 통해 이를 응용할 수 있는 기회를 얻어 진취감을 얻었다. 이러한 경험은 앞으로의 작업에 큰 도움이 될 것이라 확신한다.
'개발일지 > GreenMiniProject2' 카테고리의 다른 글
6일차 (0) | 2024.12.02 |
---|---|
5일차 (0) | 2024.11.28 |
4일차 (0) | 2024.11.26 |
3일차 (0) | 2024.11.26 |
[project2]1일차 (0) | 2024.11.20 |