Skip to content

Commit

Permalink
Integrated react app with viteJs and Django backend
Browse files Browse the repository at this point in the history
  • Loading branch information
shivaam committed Jan 28, 2024
1 parent 069bceb commit c3696c8
Show file tree
Hide file tree
Showing 33 changed files with 2,668 additions and 90 deletions.
Empty file added babblebox/__init__.py
Empty file.
Empty file.
3 changes: 3 additions & 0 deletions babblebox/babblebox/api/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.contrib import admin

# Register your models here.
6 changes: 6 additions & 0 deletions babblebox/babblebox/api/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class ApiConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'babblebox.api'
Empty file.
32 changes: 32 additions & 0 deletions babblebox/babblebox/api/clients/consumer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import pulsar
import io
from avro.io import DatumReader, BinaryDecoder
from avro.schema import Parse, Schema

topic = 'persistent://babblebox/audio_processing/test'

client = pulsar.Client('pulsar://10.2.115.98:6650')
print("Pulsar Python client version:", pulsar.__version__)

consumer = client.subscribe(topic, subscription_name='my-sub')

# Define your Avro schema
schema_path = '../schemas/chat_message_schema.avsc'
with open(schema_path, 'r') as file:
schema = Parse(file.read())


def deserialize_from_avro(data, avro_schema):
bytes_reader = io.BytesIO(data)
decoder = BinaryDecoder(bytes_reader)
reader = DatumReader(avro_schema)
return reader.read(decoder)


while True:
msg = consumer.receive()
#print(deserialize_from_avro(msg.data(), schema))
print("Received message: '%s'" % msg.data())
consumer.acknowledge(msg)

client.close()
21 changes: 21 additions & 0 deletions babblebox/babblebox/api/clients/pulsar_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import random
from time import sleep

import pulsar

client = pulsar.Client("pulsar://10.2.115.98:6650")
print("Pulsar Python client version:", pulsar.__version__)

# Create a producer on the topic with tenant and namespace
topic = 'persistent://babblebox/audio_processing/test'
producer = client.create_producer(topic)

# Now you can send messages
for i in range(100, 500):
# random_num = random.randint(1, 3)
# sleep(random_num)
producer.send(('hello-pulsar-%d' % i).encode('utf-8'))
print("Message sent: ", i)
# Close the producer and client after done
producer.close()
client.close()
30 changes: 30 additions & 0 deletions babblebox/babblebox/api/clients/pulsar_client_avro.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import pulsar
from avro.io import DatumWriter, BinaryEncoder
import io

from pulsar.schema import BytesSchema

topic = 'persistent://babblebox/audio_processing/new_message'
client = pulsar.Client("pulsar://10.2.115.98:6650")
try:
print("No client created")
# producer = client.create_producer(topic, schema=BytesSchema())
except Exception as e:
print("Exception raised" + str(e))

class PulsarClient:
@classmethod
# Function to serialize Django model to Avro
def serialize_to_avro(cls, data, avro_schema):
writer = DatumWriter(avro_schema)
bytes_writer = io.BytesIO()
encoder = BinaryEncoder(bytes_writer)
writer.write(data, encoder)

return bytes_writer.getvalue()

@classmethod
def send_message(cls, data, schema):
serialized_data = PulsarClient.serialize_to_avro(data, schema)
#producer.send(serialized_data)
print("Message sent to pulsar for new transcription")
38 changes: 38 additions & 0 deletions babblebox/babblebox/api/logging_mixin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import logging


class LoggingMixin:
"""
Provides full logging of requests and responses
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.logger = logging.getLogger('django.request')

def initial(self, request, *args, **kwargs):
try:
self.logger.debug(request.META)
self.logger.debug({
"request": request.data,
"method": request.method,
"endpoint": request.path,
"user": request.user.username,
"ip_address": request.META.get('REMOTE_ADDR'),
"user_agent": request.META.get('HTTP_USER_AGENT')
})
except Exception:
self.logger.exception("Error logging request data")
super().initial(request, *args, **kwargs)

def finalize_response(self, request, response, *args, **kwargs):
try:
self.logger.debug({
"response": response.data,
"status_code": response.status_code,
"user": request.user.username,
"ip_address": request.META.get('REMOTE_ADDR'),
"user_agent": request.META.get('HTTP_USER_AGENT')
})
except Exception:
self.logger.exception("Error logging response data")
return super().finalize_response(request, response, *args, **kwargs)
72 changes: 72 additions & 0 deletions babblebox/babblebox/api/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Generated by Django 4.2.9 on 2024-01-27 21:56

from django.db import migrations, models
import django.db.models.deletion
import uuid


class Migration(migrations.Migration):
initial = True

dependencies = []

operations = [
migrations.CreateModel(
name="AudioFile",
fields=[
(
"id",
models.CharField(editable=False, max_length=100, primary_key=True, serialize=False, unique=True),
),
("audio", models.FileField(upload_to="audios")),
("transcription_en", models.TextField(blank=True)),
("transcription_original", models.TextField(blank=True)),
("file_location", models.CharField(editable=False, max_length=255)),
("upload_timestamp", models.DateTimeField(auto_now=True)),
],
),
migrations.CreateModel(
name="Chat",
fields=[
("id", models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
("topic", models.CharField(max_length=255)),
],
),
migrations.CreateModel(
name="ImageFile",
fields=[
(
"id",
models.CharField(editable=False, max_length=100, primary_key=True, serialize=False, unique=True),
),
("image", models.ImageField(blank=True, null=True, upload_to="images")),
("file_location", models.CharField(blank=True, editable=False, max_length=255)),
("upload_timestamp", models.DateTimeField(auto_now=True)),
],
),
migrations.CreateModel(
name="ChatMessage",
fields=[
("id", models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
("timestamp", models.DateTimeField(auto_now_add=True)),
(
"audio_message_id",
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to="api.audiofile"),
),
("chat_id", models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to="api.chat")),
(
"image_id",
models.ForeignKey(
blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to="api.imagefile"
),
),
],
options={
"indexes": [
models.Index(fields=["chat_id"], name="chat_id_idx"),
models.Index(fields=["timestamp"], name="timestamp_idx"),
models.Index(fields=["chat_id", "timestamp"], name="chat_id_timestamp_idx"),
],
},
),
]
Empty file.
91 changes: 91 additions & 0 deletions babblebox/babblebox/api/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import os
import uuid

from avro.schema import parse
from django.db import models
from django.db.models import Index
from django.conf import settings

from config.settings.base import BASE_DIR
from babblebox.api.whisper.whisper import get_transcription


class AudioFile(models.Model):
id = models.CharField(max_length=100, unique=True, editable=False, primary_key=True)
audio = models.FileField(upload_to='audios')
transcription_en = models.TextField(blank=True)
transcription_original = models.TextField(blank=True)
file_location = models.CharField(max_length=255, editable=False)
upload_timestamp = models.DateTimeField(auto_now=True)

def save(self, *args, **kwargs):
if not self.id:
# Generate a unique ID
self.id = str(uuid.uuid4())
super(AudioFile, self).save(*args, **kwargs)
print(self.audio)
# Generate transcription after the file is saved
# Update the transcription fields
self.file_location = settings.MEDIA_ROOT + "/" + str(self.audio)
# Save the model again to store the transcription
super(AudioFile, self).save(update_fields=['transcription_en', 'file_location'])


class ImageFile(models.Model):
id = models.CharField(max_length=100, unique=True, editable=False, primary_key=True)
image = models.ImageField(upload_to='images', null=True, blank=True)
file_location = models.CharField(max_length=255, editable=False, null=False, blank=True)
upload_timestamp = models.DateTimeField(auto_now=True)

def save(self, *args, **kwargs):
if not self.id:
# Generate a unique ID
self.id = str(uuid.uuid4())
super(ImageFile, self).save(*args, **kwargs)
if self.image:
self.file_location = settings.MEDIA_ROOT + "/" + str(self.image)
super(ImageFile, self).save(update_fields=['file_location'])


class Chat(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
topic = models.CharField(max_length=255, editable=True)

def save(self, *args, **kwargs):
if not self.id:
# Generate a unique ID
self.id = str(uuid.uuid4())
super(Chat, self).save(*args, **kwargs)


class ChatMessage(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
chat_id = models.ForeignKey(Chat, on_delete=models.CASCADE)
audio_message_id = models.ForeignKey(AudioFile, on_delete=models.CASCADE)
timestamp = models.DateTimeField(auto_now_add=True)
image_id = models.ForeignKey(ImageFile, on_delete=models.CASCADE, null=True, blank=True)

class Meta:
indexes = [
Index(fields=['chat_id'], name='chat_id_idx'),
Index(fields=['timestamp'], name='timestamp_idx'),
# Assuming you want to be able to filter by chat_id and then within a time range
Index(fields=['chat_id', 'timestamp'], name='chat_id_timestamp_idx'),
]

@classmethod
def get_messages_for_chat(cls, chat_id):
return cls.objects.filter(chat_id=chat_id).order_by('timestamp')

@classmethod
def get_avro_schema(cls):
schema_file = os.path.join(BASE_DIR, 'babblebox/api/schemas/chat_message_schema.avsc')
print(BASE_DIR)
print(schema_file)
with open(schema_file, 'r') as file:
schema = parse(file.read())
print(schema)
return schema


print(ChatMessage.get_avro_schema())
26 changes: 26 additions & 0 deletions babblebox/babblebox/api/schemas/chat_message_schema.avsc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"type": "record",
"name": "ChatMessage",
"fields": [
{
"name": "id",
"type": "string"
},
{
"name": "chat_id",
"type": "string"
},
{
"name": "audio_message_id",
"type": "string"
},
{
"name": "image_id",
"type": "string"
},
{
"name": "timestamp",
"type": "string"
}
]
}
40 changes: 40 additions & 0 deletions babblebox/babblebox/api/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from rest_framework import serializers
from .models import AudioFile, ChatMessage, Chat, ImageFile


class AudioFileSerializer(serializers.ModelSerializer):
class Meta:
model = AudioFile
fields = ['id', 'audio', 'transcription_en', 'file_location']


class ImageFileSerializer(serializers.ModelSerializer):
class Meta:
model = ImageFile
fields = ['id', 'image', 'file_location']


class ChatSerializer(serializers.ModelSerializer):
class Meta:
model = Chat
fields = ['id', 'topic']


class ChatMessageSerializer(serializers.ModelSerializer):
audio_file = AudioFileSerializer(write_only=True)
id = serializers.CharField(read_only=True)

class Meta:
model = ChatMessage
fields = ['id', 'chat_id', 'audio_message_id', 'timestamp', 'audio_file', 'image_id']
read_only_fields = ('audio_message_id', 'timestamp', 'id')

def create(self, validated_data):
# No need to use the serializer as we can directly create the audioFile
audio_file_data = validated_data.pop('audio_file')
audio_file = AudioFile.objects.create(**audio_file_data)
validated_data.pop('image_id')

image_file = ImageFile.objects.create()
chat_message = ChatMessage.objects.create(audio_message_id=audio_file, image_id=image_file, **validated_data)
return chat_message
3 changes: 3 additions & 0 deletions babblebox/babblebox/api/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.test import TestCase

# Create your tests here.
14 changes: 14 additions & 0 deletions babblebox/babblebox/api/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from django.urls import path, include
from rest_framework.routers import DefaultRouter

from .views import AudioFileViewSet, ChatViewSet, ChatMessageViewSet, ImageFileViewSet

router = DefaultRouter()
router.register(r'AudioFile', AudioFileViewSet)
router.register(r'ImageFile', ImageFileViewSet)
router.register(r'Chat', ChatViewSet)
router.register(r'ChatMessage', ChatMessageViewSet)

urlpatterns = [
path('', include(router.urls)),
]
Loading

0 comments on commit c3696c8

Please sign in to comment.