-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3233 from digitalfabrik/feature/celery
Set up Celery for Integreat Chat
- Loading branch information
Showing
15 changed files
with
284 additions
and
110 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -68,3 +68,6 @@ integreat_cms/xliff/download | |
|
||
# Postgres folder | ||
.postgres | ||
|
||
# Celery | ||
celerybeat-schedule.db |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,8 +16,8 @@ | |
|
||
from ....cms.models import ABTester, AttachmentMap, Language, Region, UserChat | ||
from ...decorators import json_response | ||
from .chat_bot import ChatBot | ||
from .zammad_api import ZammadChatAPI | ||
from .utils.chat_bot import process_answer, process_user_message | ||
from .utils.zammad_api import ZammadChatAPI | ||
|
||
if TYPE_CHECKING: | ||
from django.http import HttpRequest | ||
|
@@ -231,11 +231,8 @@ def zammad_webhook(request: HttpRequest) -> JsonResponse: | |
) | ||
if not region.integreat_chat_enabled: | ||
return JsonResponse({"status": "Integreat Chat disabled"}) | ||
client = ZammadChatAPI(region) | ||
webhook_message = json.loads(request.body) | ||
message_text = webhook_message["article"]["body"] | ||
zammad_chat = UserChat.objects.get(zammad_id=webhook_message["ticket"]["id"]) | ||
chat_bot = ChatBot() | ||
|
||
actions = [] | ||
if webhook_message["article"]["internal"]: | ||
|
@@ -249,34 +246,14 @@ def zammad_webhook(request: HttpRequest) -> JsonResponse: | |
webhook_message["article"]["created_by"]["login"] | ||
== "[email protected]" | ||
): | ||
actions.append("question translation") | ||
client.send_message( | ||
zammad_chat.zammad_id, | ||
chat_bot.automatic_translation( | ||
message_text, zammad_chat.language.slug, region.default_language.slug | ||
), | ||
True, | ||
True, | ||
actions.append("question translation queued") | ||
process_user_message.apply_async( | ||
args=[message_text, region.slug, webhook_message["ticket"]["id"]] | ||
) | ||
if answer := chat_bot.automatic_answer( | ||
message_text, region, zammad_chat.language.slug | ||
): | ||
actions.append("automatic answer") | ||
client.send_message( | ||
zammad_chat.zammad_id, | ||
answer, | ||
False, | ||
True, | ||
) | ||
else: | ||
actions.append("answer translation") | ||
client.send_message( | ||
zammad_chat.zammad_id, | ||
chat_bot.automatic_translation( | ||
message_text, region.default_language.slug, zammad_chat.language.slug | ||
), | ||
False, | ||
True, | ||
actions.append("answer translation queued") | ||
process_answer.apply_async( | ||
args=[message_text, region.slug, webhook_message["ticket"]["id"]] | ||
) | ||
return JsonResponse( | ||
{ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
""" | ||
Utils for the Integreat Chat | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
""" | ||
Wrapper for the Chat Bot / LLM API | ||
""" | ||
|
||
from __future__ import annotations | ||
|
||
import requests | ||
from celery import shared_task | ||
from django.conf import settings | ||
|
||
from integreat_cms.cms.models import Region, UserChat | ||
from integreat_cms.cms.utils.content_translation_utils import ( | ||
get_public_translation_for_link, | ||
) | ||
|
||
from .zammad_api import ZammadChatAPI | ||
|
||
|
||
def format_message(response: dict) -> str: | ||
""" | ||
Transform JSON into readable message | ||
""" | ||
if "answer" not in response or not response["answer"]: | ||
raise ValueError("Could not format message, no answer attribute in response") | ||
if "sources" not in response or not response["sources"]: | ||
return response["answer"] | ||
sources = "".join( | ||
[ | ||
f"<li><a href='{settings.WEBAPP_URL}{path}'>{title}</a></li>" | ||
for path in response["sources"] | ||
if (title := get_public_translation_for_link(settings.WEBAPP_URL + path)) | ||
] | ||
) | ||
return f"{response['answer']}\n<ul>{sources}</ul>" | ||
|
||
|
||
def automatic_answer(message: str, region: Region, language_slug: str) -> str | None: | ||
""" | ||
Get automatic answer to question | ||
""" | ||
url = ( | ||
f"https://{settings.INTEGREAT_CHAT_BACK_END_DOMAIN}/chatanswers/extract_answer/" | ||
) | ||
body = {"message": message, "language": language_slug, "region": region.slug} | ||
r = requests.post(url, json=body, timeout=120) | ||
return format_message(r.json()) | ||
|
||
|
||
def automatic_translation( | ||
message: str, source_language_slug: str, target_language_slug: str | ||
) -> str: | ||
""" | ||
Use LLM to translate message | ||
""" | ||
url = f"https://{settings.INTEGREAT_CHAT_BACK_END_DOMAIN}/chatanswers/translate_message/" | ||
body = { | ||
"message": message, | ||
"source_language": source_language_slug, | ||
"target_language": target_language_slug, | ||
} | ||
response = requests.post(url, json=body, timeout=120).json() | ||
if "status" in response and response["status"] == "success": | ||
return response["translation"] | ||
raise ValueError("Did not receive success response for translation request.") | ||
|
||
|
||
@shared_task | ||
def process_user_message( | ||
message_text: str, region_slug: str, zammad_ticket_id: int | ||
) -> None: | ||
""" | ||
Process the message from an Integreat App user | ||
""" | ||
zammad_chat = UserChat.objects.get(zammad_id=zammad_ticket_id) | ||
region = Region.objects.get(slug=region_slug) | ||
client = ZammadChatAPI(region) | ||
if translation := automatic_translation( | ||
message_text, zammad_chat.language.slug, region.default_language.slug | ||
): | ||
client.send_message( | ||
zammad_chat.zammad_id, | ||
translation, | ||
True, | ||
True, | ||
) | ||
if answer := automatic_answer(message_text, region, zammad_chat.language.slug): | ||
client.send_message( | ||
zammad_chat.zammad_id, | ||
answer, | ||
False, | ||
True, | ||
) | ||
|
||
|
||
@shared_task | ||
def process_answer(message_text: str, region_slug: str, zammad_ticket_id: int) -> None: | ||
""" | ||
Process automatic or counselor answers | ||
""" | ||
zammad_chat = UserChat.objects.get(zammad_id=zammad_ticket_id) | ||
region = Region.objects.get(slug=region_slug) | ||
client = ZammadChatAPI(region) | ||
if translation := automatic_translation( | ||
message_text, region.default_language.slug, zammad_chat.language.slug | ||
): | ||
client.send_message( | ||
zammad_chat.zammad_id, | ||
translation, | ||
False, | ||
True, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# This will make sure the app is always imported when | ||
# Django starts so that shared_task will use this app. | ||
from .celery import app as celery_app | ||
|
||
__all__ = ("celery_app",) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
""" | ||
Set up celery app | ||
""" | ||
|
||
from django.apps import AppConfig | ||
|
||
|
||
class IntegreatCeleryConfig(AppConfig): | ||
""" | ||
Configuration for Celery | ||
""" | ||
|
||
default_auto_field = "django.db.models.BigAutoField" | ||
name = "integreat_cms.integreat_celery" |
Oops, something went wrong.