우선 신규 테이블 생성이 필요합니다.
https://cwbeany.com/blog_diary/39 에서 말한 것 처럼 요약 테이블을 1:N 관계로 생성하고, 아래와 같은 필드들을 포함할 것입니다
chatgpt.consts.py
class ProcessStatus(StrValueLabel):
PROCESSING = ('PROCESSING', '처리중')
DONE = ('DONE', '처리완료')
FAIL = ('FAIL', '실패')
chatgpt.models .py
class PostSummary(models.Model):
body = models.TextField(help_text='본문', null=True, blank=True)
post = models.ForeignKey('board.Post', on_delete=models.CASCADE, related_name='post_summary')
status = models.CharField(
choices=ProcessStatus.choices(),
max_length=45,
default=ProcessStatus.PROCESSING.value,
help_text='처리상태',
)
created_at = models.DateTimeField(auto_now_add=True, db_index=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = '게시글 요약'
verbose_name_plural = '게시글 요약'
def __str__(self):
return f'id: {self.id} post_id: {self.post_id}'
status
는 기본값을 PROCESSING
으로 설정했습니다. 시작 후, 바로 요약본 정보가 오지 않을 것이기 때문입니다.
created_at
에는 db_index
를 설정했습니다. 이유는 한 게시판에 가장 마지막에 생성된 요약본을 보여줄 것이기 때문입니다. 불필요한 인덱스라고 생각할 수도 있지만, id
기준이 아닌 created_at
기준으로 처리하겠습니다.
수동으로 요약본을 수정해야 할 수도 있기 때문에 Admin에 등록합니다.
chatgpt.admin.py
@admin.register(PostSummary)
class PostSummaryAdmin(admin.ModelAdmin):
list_display = (
'id',
'body',
'post',
'status',
'created_at',
'updated_at',
)
이제 Celery Task를 구현해 봅시다. 게시글을 생성할 때, 생성이 완료되면 아래 task를 실행할 예정입니다.
혹시 문제가 발생할 수 있으니 모니터링을 위해 이메일을 보낼 예정입니다.
@app.task(time_limit=30)
def update_post_summary(body: str, post_summary_id: int) -> None:
try:
response = get_chatgpt_response(POST_SUMMARY_SYSTEM_PROMPT, body, [])
post_summary = PostSummary.objects.get(id=post_summary_id)
post_summary.body = response
post_summary.status = ProcessStatus.DONE.value
post_summary.save()
except PostSummary.DoesNotExist:
send_email(
f'[Beany 블로그] Update Post Summary Issue Raised - PostSummary id: {post_summary_id}',
EMAIL_TEMPLATE_MAPPER[POST_SUMMARY_ISSUE],
{},
settings.NOTICE_EMAILS,
)
except SoftTimeLimitExceeded:
post_summary = PostSummary.objects.get(id=post_summary_id)
post_summary.status = ProcessStatus.FAIL.value
post_summary.save()
send_email(
f'[Beany 블로그] Task Timeout - PostSummary id: {post_summary_id}',
EMAIL_TEMPLATE_MAPPER[POST_SUMMARY_ISSUE],
{},
settings.NOTICE_EMAILS,
)
board.admin.py
def save_related(self, request, form, formsets, change):
super().save_related(request, form, formsets, change)
instance = form.instance
if instance.def_tag:
instance.tag_save()
if instance.is_active:
post_summary = PostSummary.objects.create(post_id=instance.id)
request_n8n_webhook(instance.board.url, instance.id)
update_post_summary.apply_async((instance.body, post_summary.id))
게시글이 생성 및 수정되는 경우, PostSummary
데이터를 생성합니다.
Celery 실행
celery -A config worker -l INFO -P solo
[2024-09-21 16:15:23,342: INFO/MainProcess] Connected to redis://localhost:6379/1
[2024-09-21 16:15:23,343: INFO/MainProcess] mingle: searching for neighbors
[2024-09-21 16:15:24,351: INFO/MainProcess] mingle: all alone
[2024-09-21 16:15:24,375: INFO/MainProcess] celery@A202205037M2406 ready.
[2024-09-21 16:15:44,858: INFO/MainProcess] Task chatgpt.task.update_post_summary[bde5387c-cd4c-4233-8359-4e5c51dbabba] received
[2024-09-21 16:15:45,376: INFO/MainProcess] Task chatgpt.task.update_post_summary[bde5387c-cd4c-4233-8359-4e5c51dbabba] succeeded in 0.5178740829999988s: None
[2024-09-21 16:16:18,947: INFO/MainProcess] Task chatgpt.task.update_post_summary[cf7421b2-1bea-49bc-b074-b106d35015ef] received
[2024-09-21 16:16:20,803: INFO/MainProcess] Task chatgpt.task.update_post_summary[cf7421b2-1bea-49bc-b074-b106d35015ef] succeeded in 1.8557699999999997s: None
아주 잘 작동합니다!
다음 장에서는 요약 내용을 조회할 수 있도록 작업을 하자!