본문 바로가기
AI 웹개발반/AI

[AI] Chatgpt-3.5 와 DRF로 챗봇 만들기 - 2 -

by 째깍단 2023. 7. 5.

JSONfield에 관해서는 이전 글 참고 :

https://diane073.tistory.com/150

 

 

 

 

 

 

 

JSONfield를 list형태로 만들기 위해서는 처음 입력할때 list형태로 저장해 줄 것임을 명확히 알려주어야한다.

 

!! request data를 그냥 넣으면 string 값이 들어가고,

첫 자료가 만들어진 후에는 입력 형태가 일치하지 않는 오류가 발생하니 매우 주의!! 밑줄 쫙쫙!

 

 

 

field의 default option에 넣으면 자꾸 warning이 떠서

처음 생성할 때 리스트 형태의 옵션을 넣어주고, 이후에 새로운 데이터를 list에 append 해주는 방식으로 사용하였다.

 

 

 

 

 

 

 

► 챗 데이터 저장을 위한 model 예시

 

# meetai/models.py
from django.db import models
from django.conf import settings

class AiChatBot(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    user_text = models.JSONField(encoder=None, default=dict) # default속성은 이후 저장하는 데이터 형식에 따라 무시되기도 하는듯하다
    ai_text = models.JSONField(encoder=None, default=dict)

 

 

 

 

► 챗 데이터 저장을 위한 serializer 예시

 

user 정보는 email로 가져오고 있어 id값을 주도록 변경,

프론트에서 사용할 것을 고려해 user name을 넣어주었다

 

from rest_framework import serializers
from .models import AiChatBot


class AiChatBotSerailizer(serializers.ModelSerializer):
    user = serializers.SerializerMethodField()
    username = serializers.SerializerMethodField()

    class Meta:
        model=AiChatBot
        fields= '__all__'
    
    def get_user(self,obj):
        return obj.user.id

    def get_username(self, obj):
        return obj.user.name

 

 

 

 


 

 

 

 

기본 모델과 serializer를 작성한 후 유저 요청과 ai 응답에 대한 내용을 저장해줄 수 있도록 view에 기능을 추가하였다!

 

 

 

 

이전에 user_chat을 이용해본적이 있을 경우, 없을 경우를 나누어주었다

 

class SendTextView(APIView):
    def post(self, request):
        ...
        user_chat = AiChatBot.objects.filter(user=request.user).last()
        if not user_chat :
            hello_text = "안녕! 만나서 반가워:D"
            response = send_text(request, user_input, hello_text)
        else:
            # print(user_chat.ai_text[0], "⭐️")
            response = send_text(request, user_input, user_chat.ai_text[0])

 

 

 

 

 

 

그리고 채팅 데이터를 db에 저장해주기 위해

list 형태로 유저의 챗 [user_input] 과  ai의 응답값 [response] 를 넣어주었다.

 

 

 

user_chat  그러니까 이전 데이터가 없는 경우 새로운 테이블을 생성하고,

데이터가 있는 경우에는 append해주는 형식을 사용하였다.

 

insert는 (특정 인덱스값, 넣고자하는 요소)  를 인자로 받아 원하는 곳에 넣어줄 수 있게 해준다.

위의 코드 부분에서도 보이지만 assistant에 입력해주기위해 이전 text를 불러오는 기능을 추가해준 것!

 

 

 

if not user_chat:
    chat = AiChatBot.objects.create(user=request.user, user_text=[user_input], ai_text=[response, hello_text])
    ...
else:
    user_chat.user_text.insert(0, user_input)
    user_chat.ai_text.insert(0, response)
    new_data_set = {'user_text':user_chat.user_text[:10], 'ai_text':user_chat.ai_text[:10]}
    ...

 

 

 

그리고 저장되는 값을 제한하기 위해 범위 연산자를 넣어보았다.

작동하는 지 확인해봐야지!

 

 

 

 


 

 

 

저장되는 채팅 데이터를 제한하기 위해 collections 모듈에 있는 deque를 활용해보려했지만

이미 있는 리스트에 적용할 방법을 찾지 못해 아쉽게도 코드를 삭제했다.

 

 

이후에 활용에 대해 좀더 익혀보는 시간을 가져야겠다..

 

from collections import deque

def text_assistant(text_input):
    deq = deque(maxlen=5)
    deq.appendleft(text_input)
    print(deq, "👀")
    return deq

 

[참고]: https://codetorial.net/python/collections_deque.html

 

 

 

 

 


 

 

 

Today's Error🐛

 

 

 

첫 index를 list 형태로 넣어주고 새로운 아이디를 생성해보았더니

postman에 이미 있던 이전 데이터가 입력되면서 애매하게 [] 빈 리스트가 들어간 테이블이 생성되었다.

 

 

 

+++

print : ⭐️⭐️ {'user_text': [], 'ai_text': []}

시간이 지나고 요청하자 저장되어있던 text 정보가 사라졌다! 왜지... db에 저장된건데

 

 

 

 

 

list가 있으니 else문으로 들어가게되고 0번 index를 찾을 수 없다는 에러가 발생했다.

 

아무것도 없는 상태의 list에대한 조건을 추가했다.

 

 

class SendTextView(APIView):
    def post(self, request):
		user_input = request.data["user_input"]
        user_chat = AiChatBot.objects.filter(user=request.user).last()
        
        if not user_chat :
            # 데이터가 없는 경우
        elif not user_chat.ai_text:
            hello_text = "안녕! 다시 만나서 반가워:D"
            response = send_text(user_input, hello_text)
        else:
            #list 데이터가 있는 경우
            response = send_text(user_input, user_chat.ai_text[0])

 

 

 

아마 범위연산자 문제였던 것 같다 ^^;

이왕 추가한 코드, 나중에 일정 시간이 지나면 대화 데이터를 소거해주는 방식도 괜찮을 것 같다!

 

 

 

 

 

 


 

 

 

+++

 

이것저것 실험해보다보니 유저마다 field가 여러개 생성되는 문제가 있어 모델에 unique=True 속성을 추가하였다.

그랬더니 onetoone 쓰라고 난리남ㅋㅋ unique=True보다는 onetoonefield로 바꾸어주자

 

 

class AiChatBot(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, unique=True)

알았어 알았다구;;

 

 

 

class AiChatBot(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)