Ssul's Blog

[Django, tailwind] AI가 상담글에 자동으로 댓글 달아주기 #1(signal, threading사용) 본문

dev/기능구현

[Django, tailwind] AI가 상담글에 자동으로 댓글 달아주기 #1(signal, threading사용)

Ssul 2024. 1. 18. 14:20

0. signal은 언제 사용하나?

예전에 구독서비스를 개발할때, 카드결제가 정기적으로 이뤄지는 과정을 개발할때 사용했다.

매번 관리자가 카드결제를 실행할 수 없기에...

카드등록 후, 첫 구독 결제를 실행해서 구독객체가 생성되면,

signal을 활용해서 자동으로 payment 객체생성과 다음 결제를 생성해 놓는 개념이다.

이번에는 질문글에 자동으로 AI가 답변을 남기는 기능을 구현하기 위해서 signal을 활용해 보고자 한다.

 

1. 평소처럼 models.py생성

class CounselingPost(models.Model):
    cp_index = models.AutoField(primary_key=True)
    cp_u_index = models.IntegerField()
    cp_content = models.TextField()
    cp_created_at = models.DateTimeField(auto_now_add=True)
    cp_updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = 'counseling_post'

class CounselingPostComment(models.Model):
    cpc_index = models.AutoField(primary_key=True)
    cpc_u_index = models.IntegerField(default=1)
    cpc_cp_index = models.IntegerField()
    cpc_is_ai = models.BooleanField(default=False)
    cpc_created_at = models.DateTimeField(auto_now_add=True)
    cpc_updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = 'counseling_post_comment'

- 궁금한것 물어보는 글과

- 해당글에 댓글 다는 코멘트 모델 선언

 

2. signal 생성하기

- 따로 views.py구현하지 않고, admin모드에서 객체를 생성해볼 것이기에 바로 signal 만들기

- models.py와 동일한 경로에 receivers.py 생성

from django.db.models.signals import post_save
from django.dispatch import receiver

from community.models import CounselingPost


@receiver(post_save, sender=CounselingPost)
def posting_counseling(instance: CounselingPost, created, **kwargs):
    # 새로운 CounselingPost생성
    if created:
        print('gpt호출')
    else:
        return

- CounselingPost객체가 post_save를 호출할 경우 아래 함수를 실행

- 당연히 새글과 수정 모두 post_save를 호출한다.

- 나는 새로운 글에 대해서만, AI가 답변을 달아줄 것이기 때문에 

if created로 체크, 새로 생성한 글이면 gpt를 호출하면 된다

 

3. signal 나머지 셋팅하기

- 동일한 경로에 apps.py

from django.apps import AppConfig


class CommunityConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'community'

    def ready(self):
        # get receivers
        import community.receivers

 

- 동일한 경로에 __init__.py

default_app_config = "community.apps.CommunityConfig"

 

 

4. 이제 새글을 생성해보자!!!

새글 생성!!
성공적으로 receivers.py에 있는 함수 호출

 

- 물론 수정하면, 아무일도 안 일어난다!!

 

이렇게 객체를 생성하거나, 수정하거나, 삭제하거나 할때마다 조건부로 다양한 액션이 가능하다.

signal잘 사용하면 서비스의 퀄리티가 올라간다!

 

그럼 이제 gpt에 호출하여 댓글을 달아보자!

 

5. gpt에 글 물어보고, 댓글 생성

- gpts.py생성

import os

import openai
from dotenv import load_dotenv

from community.models import CounselingPostComment

load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")

def create_comment_with_gpt_response(cp_index, cp_content):
    # 지역 변수로 messages 초기화
    messages = []

    # 시스템 메세지 사용하려면 이렇게 사용!
    # instructions = GptSystemMessage.objects.get(message_type='first').message_text

    # 시스템 메세지 입력
    instructions = """익명게시판에 올라온 글이야. 글을 보고, 적절한 반응을 부탁해"""
    system_content = {"role": "system", "content": instructions}
    messages.append(system_content)

    # 사용자 글 입력
    messages.append({"role": "user", "content": cp_content})

    # OpenAI API에 요청 보내기
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo-1106",
        messages=messages
    )

    # Assuming the structure contains a 'choices' list
    gpt_response_text = response.choices[0].message['content']

    # Create a new CounselingPostComment with the GPT response
    CounselingPostComment.objects.create(
        cpc_cp_index=cp_index,
        cpc_content=gpt_response_text,
        cpc_is_ai=True
    )

- 시스템 메세지 생성해서 넣어주고

- gpt 호출해서, 답변 얻어오기

- 얻어온 답변으로 comment객체 생성하기

- 이런 함수를 제작

 

그리고 signal에 붙여준다.

근데 여기서 threading이 없으면, 사용자가 익명게시판에 글을 올린 후, gpt댓글이 생성될때까지 기다리게 된다. 그러면, 사용자가 올린글이 gpt가 댓글을 달때까지 올라가지 못하게 된다. 그렇게 때문에 threading을 통해서 비동기로 실행되게 해야 함

receivers.py를 수정하자

import threading

from django.db.models.signals import post_save
from django.dispatch import receiver

from community.models import CounselingPost
from community.gpts import create_comment_with_gpt_response

def threaded_gpt_call(cp_index, cp_content):
    thread = threading.Thread(target=create_comment_with_gpt_response, args=(cp_index, cp_content))
    thread.start()

@receiver(post_save, sender=CounselingPost)
def posting_counseling(instance: CounselingPost, created, **kwargs):
    # 새로운 CounselingPost생성
    if created:
        print('gpt호출')
        threaded_gpt_call(instance.cp_index, instance.cp_content)
    else:
        return

 

이러면...댓글을 아주 잘 생성해 준다!!!

끝!!