모각코/석드류

[석드류] 4회차

카르노도 2024. 7. 19. 00:50

목표

gpt stream 공부

공부

이전 글에 이어서, 캐릭터의 대사를 뽑아주는 경우에는
"조금 더 생동감을 높이기 위해 GPT가 응답을 주는대로 받아오는 것이 좋지 않을까"
해서 고민하게 되었다.

찾아보니 GPT에는 스트리밍이 기본적으로 가능하더라.

    openai.ChatCompletion.create(
     model=GPT_MODEL_ENGINE,
     messages=messages,
     stream=True,
    )

단순하게 맨 밑에 stream=True만 해주면 스트리밍이 가능한데,
이렇게 하면 GPT의 응답이 generator 형태로 제공되어, 반복해서 값을 넘겨줘야 한다.
여기에 웹 소켓으로 실시간 전송을 해준다면, 내가 원하는대로 GPT의 응답이 올 때마다 값을 받아서, 클라이언트가 아무 화면도 못 보는 채로 대기하는 일이 없다.

여기까지는 굉장히 쉽게 했는데, 이 값들을 반복자를 이용해서 어떻게 넘겨줘야할지 감이 오지 않았다.

response 값을 어떻게 받아서 선택해야할지 몰라서,
우선 response = next(stream)을 통해 response에 다음 객체를 담아주고,
print문으로 response값을 확인해보았다.

{
  "id": "",
  "object": "",
  "created": ,
  "model": "",
  "system_fingerprint": "",
  "choices": 
      [
         {
            "index": ,
            "delta": {
            "role": "",
            "content": ""
            },
             "logprobs": ,
             "finish_reason": 
         }
      ]
}

음 뭐 대충 이런 형태가 나오더라
그러면 어떻게 뽑아내야 result 값으로 넘겨줄 수 있을까?

    response = next(stream)
    result = response.choices[0]['delta']['content'].strip()

    channel_layer = get_channel_layer()
    async_to_sync(channel_layer.group_send)(
        'group_name',
        {
            'type': '',
            'message': result,
        }
    )

대충 이렇게 넣어봤다. 과연 될까?

전송은됐다.
근데 진짜 전송만 됐다.. 가장 큰 문제는 한 번만 보내지는 현상이다. 매우 당연하다.

아까 말했든 반복자를 통해 계속해서 보내줘야하는데 한 번만 보내고 있으니 그냥 빈 값만 들어가고 끝난다.

수정해서 반복을 통해 연속적으로 보내보자.

    for response in stream:
        if 'delta' in response.choices[0] and 'content' in response.choices[0]['delta']:
            result = response.choices[0]['delta']['content'].strip()

            channel_layer = get_channel_layer()
            async_to_sync(channel_layer.group_send)(
                'group_name',
                {
                    'type': '',
                    'message': result,
                }
            )

이렇게 하니 성공했다.
여기서 살짝 삽질한 부분은, 어쨌든 계속 next 값을 찾기 때문에, 종료 조건을 주지 않으면 안되더라.

if 'delta' in response.choices[0] and 'content' in response.choices[0]['delta']:

해당 코드 없이 진행하니, 마지막에 delta가 빈 값이 생겨서, content가 없다며 오류가 발생했다.
꼭 체크하길 바란다.

마치며

아무튼 이런식으로 해서 얼추 스트리밍까지 구현한 것 같다.

정말 많은 삽질이 있었지만, 그만큼 많이 찾아보고 공부가 됐다는 것에 의의를 두기로 했다.
앞으로 주 개발은 spring boot로 할 것이지만, 참여하고 있는 프로젝트에서 장고를 쓰는 만큼 다른 언어도 좀 공부하면서 시야를 넓혀야겠다.