Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Redis for message log context #339

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
9 changes: 9 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ jobs:
--health-timeout 5s
--health-retries 5

redis:
image: redis:latest

options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5

steps:
- name: Check out repository code
uses: actions/checkout@v2
Expand Down
1 change: 1 addition & 0 deletions contrib/gen_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ def generate_env():
"ALLOWED_HOSTS": "*",
"SECRET_KEY": get_random_secret_key(),
"DEFAULT_DATABASE": "postgres://nexus:nexus@postgres:5432/nexus",
"CELERY_BROKER_URL": "redis://redis:6379/1",
"WENIGPT_FLOWS_CLASSIFY_TOKEN": "",
"WENIGPT_FLOWS_SEARCH_TOKEN": "",
"SENTENX_BASE_URL": "",
Expand Down
14 changes: 13 additions & 1 deletion nexus/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,22 @@

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

# Celery config
# Redis Config

week_duration = 60 * 60 * 24 * 7
REDIS_MESSAGE_CACHE_KEY_DURATION = env.int("REDIS_MESSAGE_CACHE_KEY_DURATION", default=week_duration)
REDIS_URL = env.str("CELERY_BROKER_URL", default="redis://localhost:6379/1")

CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": REDIS_URL,
"OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient"},
}
}

# Celery config

CELERY_RESULT_BACKEND = "django-db"
CELERY_BROKER_URL = REDIS_URL
CELERY_ACCEPT_CONTENT = ["application/json"]
Expand Down
37 changes: 37 additions & 0 deletions nexus/usecases/logs/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,44 @@
MessageLog,
)

from django.core.cache import cache
from django.conf import settings


# TODO refactor this class methods to recieve MessageLog object as parameter not using class attributes
class CreateLogUsecase:

def _create_redis_cache(
self,
message_log: MessageLog,
project_uuid: str
):
message = message_log.message

contact_urn = message.contact_urn
cache_key = f"last_5_messages_{project_uuid}_{contact_urn}"
last_5_messages = cache.get(cache_key, [])
last_5_messages.insert(
0,
{
"text": message.text,
"contact_urn": message.contact_urn,
"llm_respose": message_log.llm_response,
"project_uuid": project_uuid,
"content_base_uuid": str(message_log.content_base.uuid),
"created_at": message.created_at.isoformat(),
"uuid": str(message.uuid),
"log_id": message_log.id
}
)

if len(last_5_messages) > 5:
last_5_messages.pop()

key_expiration = settings.REDIS_MESSAGE_CACHE_KEY_DURATION

cache.set(cache_key, last_5_messages, key_expiration)

def create_message(self, text: str, contact_urn: str, status: str = "P") -> Message:
self.message = Message.objects.create(
text=text,
Expand Down Expand Up @@ -50,3 +85,5 @@ def update_log_field(self, **kwargs):
setattr(log, key, kwargs.get(key))

log.save()
if log.project.uuid:
self._create_redis_cache(log, log.project.uuid)
60 changes: 60 additions & 0 deletions nexus/usecases/logs/tests/test_create.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
from nexus.usecases.logs.tests.logs_factory import MessageLogFactory
from nexus.usecases.logs.create import CreateLogUsecase
from nexus.logs.models import MessageLog

from django.test import TestCase
from django.core.cache import cache


class TestCreateLogUsecase(TestCase):

def setUp(self) -> None:
self.msg_log: MessageLog = MessageLogFactory()

self.msg_log1: MessageLog = MessageLogFactory()
self.msg_log2: MessageLog = MessageLogFactory()
self.project_uuid1 = self.msg_log1.project.uuid
self.project_uuid2 = self.msg_log2.project.uuid

def test_redis_cache(self):
project_uuid = self.msg_log.project.uuid

usecase = CreateLogUsecase()
usecase._create_redis_cache(self.msg_log, project_uuid)

cache_key = f"last_5_messages_{project_uuid}_{self.msg_log.message.contact_urn}"
cache_data = cache.get(cache_key)
cache_data = cache_data[0]

self.assertEqual(cache_data['text'], self.msg_log.message.text)

def test_redis_cache_multiple_conversations(self):
usecase = CreateLogUsecase()

for i in range(6):
msg_log = MessageLogFactory(
project=self.msg_log1.project,
message__contact_urn=self.msg_log1.message.contact_urn,
message__text=f'Text {i}'
)
usecase._create_redis_cache(msg_log, self.project_uuid1)

for i in range(6):
msg_log = MessageLogFactory(
project=self.msg_log2.project,
message__contact_urn=self.msg_log2.message.contact_urn,
message__text=f'Text {i}'
)
usecase._create_redis_cache(msg_log, self.project_uuid2)

cache_key1 = f"last_5_messages_{self.project_uuid1}_{self.msg_log1.message.contact_urn}"
cache_data1 = cache.get(cache_key1)
self.assertEqual(len(cache_data1), 5)
self.assertEqual(cache_data1[0]['text'], 'Text 5')

cache_key2 = f"last_5_messages_{self.project_uuid2}_{self.msg_log2.message.contact_urn}"
cache_data2 = cache.get(cache_key2)
self.assertEqual(len(cache_data2), 5)
self.assertEqual(cache_data2[0]['text'], 'Text 5')

self.assertNotEqual(cache_data1, cache_data2)
Loading