본문 바로가기
과정/2차 AI프로젝트 서비스 개발

프로젝트 '재움' 개발과정(5)

by 줘요 2023. 11. 7.

 

chatGPT api를 이용하여 GPT에게 정보를 주고 수면 피드백을 받아보겠습니다!

 

먼저 open api key를 이용해 사용하여야 하는데요 gpt 3.5 turbo를 사용하였습니다. 

 

서버에서 전달받은 데이터를 토대로(chatGPT를 이용할 때 직접 쓰는 질문이랑 같습니다.)

 

답변을 해줄겁니다.

 

gpt에게 어떤 데이터를 넘겨줄 것인지 정하겠습니다.

 

start_sleep : 수면 시작 시간

total_sleep : 총 수면 시간

sleep_event : 수면 자세

bad_position_time : 바르지 않은 수면 자세 시간

 

을 넘겨주도록 하겠습니다.

 

 

촬영 종료 버튼을 누르면 바로 피드백을 받을 것이기 때문에 버튼을 눌렀을 때 gpt에게 질문을 던져줘야 합니다.

 

아래 엔드포인트를 통해 닉네임과 수면정보아이디를 넘겨줍니다.

        const sleepInfoId = document.getElementById("sleep_info_id").value;
        const requestData = {
          nickname: nickname,
          sleep_info_id: sleepInfoId,
        };
        return fetch("/record/info_and_event", {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify(requestData),
        });

 

보내준 정보와 받을 정보를 schemas.py에 작성합니다.

# Pydantic 모델을 사용하여 요청의 body에서 데이터를 추출
class RequestData(BaseModel):
    nickname: str
    sleep_info_id: int

class SleepInfoGet(BaseModel):
    total_sleep: str
    start_sleep: str
    end_sleep: str
    sleep_event: List[str] = []
    event_time: List[str] = []

 

닉네임과 수면정보아이디를 통해 수면정보 테이블과 수면이벤트 테이블의 정보를 join 해서 얻을 겁니다.

def get_sleep_info_with_events_by_nickname_and_id(db: Session, nickname: str, sleep_info_id: int):
    return db.query(model.SleepInfo.total_sleep, model.SleepInfo.start_sleep,model.SleepInfo.end_sleep, model.SleepEvent.sleep_event, model.SleepEvent.event_time).\
        join(model.SleepEvent).\
        filter(model.SleepInfo.nickname == nickname).\
        filter(model.SleepInfo.sleep_info_id == sleep_info_id).\
        filter(model.SleepEvent.sleep_info_id == model.SleepInfo.sleep_info_id).\
        all()

 

이제 api_record에서 gpt에게 join 해서 얻은 데이터를 넘겨주고 맨 처음 작성한 generate_sleep_feedback 함수를 통해

 

피드백을 받고 클라이언트에게 보여줍니다.

# 수면 피드백 
@router.post("/record/info_and_event")
async def get_info_and_events(request_data: RequestData, db: Session = Depends(get_db) ):
    db_info_event_data = get_sleep_info_with_events_by_nickname_and_id(
        db, request_data.nickname, request_data.sleep_info_id
    )
    
    results = SleepInfoGet(total_sleep='', start_sleep='',end_sleep='', sleep_event=[], event_time=[])
    sleep_events = []
    event_times = []
    for info in db_info_event_data:
        results.total_sleep = info.total_sleep
        results.start_sleep = info.start_sleep
        results.end_sleep = info.end_sleep
        sleep_events.append(info.sleep_event)
        event_times.append(info.event_time)
    
    results.sleep_event = sleep_events
    results.event_time = event_times

    bad_position_time = calculate_bad_sleep_without_event(sleep_events, event_times, results.end_sleep, "front standard")

     # results 데이터를 JSON 형식으로 변환
    results_json = {
        "total_sleep": results.total_sleep,
        "start_sleep": results.start_sleep,
        "sleep_event": results.sleep_event,
        "bad_position_time": bad_position_time
    }
    json_data = json.dumps(results_json)
    print("gpt한테 보내주는 값: ", type(json_data))
    # generate_sleep_feedback 함수에 results_text를 전달하여 GPT-3.5 모델에 데이터를 제공
    response = generate_sleep_feedback(json_data)
    # 응답 받은 내용 출력 형식 변경
    feedback = response["choices"][0]["message"]["content"].replace("\n", "<br>").replace("{", "").replace("}", "").replace("\"","").replace(",","")
    
    return feedback

 

피드백 생성 시까지 시간이 3초 정도 걸리기 때문에 생성 중이라는 로딩을 보여주고 피드백을 보여주겠습니다.

 

record.css

.feedbackcontainer {
  display: flex;
  align-items: center; /* 요소들을 세로 가운데 정렬 */
  justify-content: center;
}

.loader {
  display: none;
  border: 4px solid rgb(250, 248, 248);
  border-top: 4px solid #3498db;
  border-radius: 50%;
  width: 30px;
  height: 30px;
  animation: spin 2s linear infinite;
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

#feedback {
  font-family: "Cafe24Oneprettynight";

  text-align: center;
  color: white;
  margin-right: 10px; /* 로더와 간격을 주기 위한 마진 설정 */
  margin-top: 15px;
}

 

record.html

<div class="feedbackcontainer">
      <p id="feedback"></p>
      <div class="loader"></div>
</div>

 

record.js 종료버튼 눌렀을 때 첫 부분에 보여줄 메시지를 작성해 줍니다.

const feedbackElement = document.getElementById("feedback");
  const loaderElement = document.querySelector(".loader");
  feedbackElement.innerHTML = "오늘의 피드백을 생성중입니다.";
  loaderElement.style.display = "block";

 

이어서 피드백을 받게 되면 있던 메시지와 로딩은 사라집니다.

.then((secondResponse) => {
        if (secondResponse.ok) {
          return secondResponse.json();
        } else {
          throw new Error("두 번째 요청에 문제가 있습니다.");
        }
      })
      .then((secondData) => {
        console.log("두 번째 요청으로 받은 데이터:", secondData);
        // 받은 데이터를 처리하거나 표시
        console.log("두 번째 요청으로 받은 닉네임:", nickname);
        const feedback = secondData;
        feedbackElement.innerHTML = feedback;
        loaderElement.style.display = "none";

        const feedbackData = {
          nickname: nickname,
          sleep_feedback: secondData,
        };

 

아래는 실제 사용 예시입니다

 

 

피드백을 받았으니 바로 수면 정보 테이블을 업데이트시켜주겠습니다.

아래 엔드포인트를 통해 수면정보 테이블에 피드백을 추가할 예정입니다.

	return fetch(`/feedback/${nickname}`, {
          method: "PUT",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify(feedbackData),
        });
      })
      .then((thirdResponse) => {
        if (thirdResponse.ok) {
          return thirdResponse.json();
        } else {
          throw new Error("세 번째 요청에 문제가 있습니다.");
        }
      })
      .then((thirdData) => {
        console.log("세 번째 요청으로 받은 데이터:", thirdData);
        // Handle the data received from the third request
      })
      .catch((error) => {
        console.error("요청에 문제가 있습니다:", error);
      });

 

schemas.py

class SleepInfoFeedback(BaseModel):
    sleep_feedback: str

 

crud.py

def update_info_feedbeck(db: Session, nickname: str, sleep_feedback: str):
    # 가장 마지막 sleep_info_id 가져오기
    latest_sleep_info_id = db.query(func.max(model.SleepInfo.sleep_info_id)).filter(model.SleepInfo.nickname == nickname).scalar()

    if latest_sleep_info_id is not None:
        # 해당 sleep_info_id를 사용하여 업데이트
        db_sleep_info = db.query(model.SleepInfo).filter(model.SleepInfo.sleep_info_id == latest_sleep_info_id).first()
        if db_sleep_info:
            db_sleep_info.sleep_feedback = sleep_feedback
            db.commit()
            db.refresh(db_sleep_info)
            return db_sleep_info

 

api_record.py

# 수면 피드백 업데이트
@router.put("/feedback/{nickname}")
def update_sleep_info_feedback(nickname: str, sleep_info_feedback: SleepInfoFeedback, db: Session = Depends(get_db)):

    update_sleep_feedback = update_info_feedbeck(db, nickname, sleep_info_feedback.sleep_feedback)

    return update_sleep_feedback

 

수면 이벤트 테이블에 추가되는 예시입니다.

 

 

prompt가 아직 원하는 대답을 계속 주지 않기 때문에 계속 손보는 중입니다..

 

사람들이 왜 prompt 할 때 화딱지가 나는지 알 거 같습니다..

 

얼마나 떠먹여 줘야 알아듣는 거니 ㅠㅠ

댓글