Skip to content

Commit

Permalink
Stability Enhancements and Bug Fixes (#510)
Browse files Browse the repository at this point in the history
* Stability Enhancements and Bug Fixes

* Fix ai name removal
  • Loading branch information
Ashesh3 authored Apr 22, 2024
1 parent ee6d681 commit 1323bfc
Show file tree
Hide file tree
Showing 11 changed files with 134 additions and 22 deletions.
17 changes: 17 additions & 0 deletions ayushma/migrations/0052_document_failed.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 4.2.6 on 2024-04-17 13:56

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("ayushma", "0051_project_tts_engine"),
]

operations = [
migrations.AddField(
model_name="document",
name="failed",
field=models.BooleanField(default=False),
),
]
1 change: 1 addition & 0 deletions ayushma/models/document.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class Document(BaseModel):
"TestQuestion", on_delete=models.PROTECT, null=True, blank=True
)
uploading = models.BooleanField(default=True)
failed = models.BooleanField(default=False)

def __str__(self) -> str:
return f"{self.title} in {self.project.title}"
3 changes: 3 additions & 0 deletions ayushma/serializers/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class Meta:
"allow_key",
"is_staff",
"is_reviewer",
"date_joined",
)


Expand Down Expand Up @@ -56,6 +57,7 @@ class Meta:
"is_staff",
"is_reviewer",
"password",
"date_joined",
)
read_only_fields = (
"external_id",
Expand All @@ -64,6 +66,7 @@ class Meta:
"allow_key",
"is_staff",
"is_reviewer",
"date_joined",
)

def update(self, instance, validated_data):
Expand Down
18 changes: 18 additions & 0 deletions ayushma/tasks/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from celery import current_app
from celery.schedules import crontab

from ayushma.tasks.stale_cleanup import clean_stale_test_runs, clean_stale_upsert_doc


@current_app.on_after_finalize.connect
def setup_periodic_tasks(sender, **kwargs):
sender.add_periodic_task(
crontab(minute="*/30"), # Every 30 minutes
clean_stale_test_runs.s(),
name="clean_stale_test_runs",
)
sender.add_periodic_task(
crontab(minute="*/30"), # Every 30 minutes
clean_stale_upsert_doc.s(),
name="clean_stale_upsert_doc",
)
52 changes: 52 additions & 0 deletions ayushma/tasks/stale_cleanup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from datetime import timedelta

from celery import shared_task
from django.utils.timezone import now

from ayushma.models.document import Document
from ayushma.models.enums import StatusChoices
from ayushma.models.testsuite import TestRun


@shared_task(bind=True)
def clean_stale_test_runs(self):
try:
# Get testRuns that are created over 6 hours ago and are still in RUNNING state
test_runs = TestRun.objects.filter(
created_at__lt=now() - timedelta(hours=6),
status=StatusChoices.RUNNING,
)

# Cancel the testRuns
for test_run in test_runs:
print(
f"Cleaning stale test run: {test_run.id}; Created at: {test_run.created_at}"
)
test_run.status = StatusChoices.FAILED
test_run.save()
except Exception as e:
print(f"Error occurred while cleaning stale test runs: {e}")
raise e


@shared_task(bind=True)
def clean_stale_upsert_doc(self):
try:
# Get stale Document objects that are still in UPLOADING state after 6 hours
documents = Document.objects.filter(
created_at__lt=now() - timedelta(hours=6),
uploading=True,
)

# Set the documents to failed state
for document in documents:
print(
f"Cleaning stale document: {document.id}; Created at: {document.created_at}"
)
document.failed = True
document.uploading = False
document.save()

except Exception as e:
print(f"Error occurred while cleaning stale test runs: {e}")
raise e
2 changes: 1 addition & 1 deletion ayushma/utils/converse.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def converse_api(
if not open_ai_key:
open_ai_key = (
request.headers.get("OpenAI-Key")
or (chat.project and chat.project.openai_key)
or (chat.project and chat.project.open_ai_key)
or (user.allow_key and settings.OPENAI_API_KEY)
)
noonce = request.data.get("noonce")
Expand Down
9 changes: 3 additions & 6 deletions ayushma/utils/openaiapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ def converse(
response = lang_chain_helper.get_response(
english_text, reference, chat_history, documents
)
chat_response = response.replace("Ayushma: ", "")
chat_response = response.replace(f"{AI_NAME}:", "").lstrip()
stats["response_end_time"] = time.time()
translated_chat_response, url, chat_message = handle_post_response(
chat_response,
Expand Down Expand Up @@ -391,8 +391,6 @@ def converse(
documents,
)
chat_response = ""
skip_token = len(f"{AI_NAME}: ")

while True:
if token_queue.empty():
continue
Expand Down Expand Up @@ -427,10 +425,9 @@ def converse(
ayushma_voice=url,
)
break
if skip_token > 0:
skip_token -= 1
continue

chat_response += next_token[0]
chat_response = chat_response.replace(f"{AI_NAME}:", "").lstrip()
yield create_json_response(
local_translated_text,
chat.external_id,
Expand Down
9 changes: 5 additions & 4 deletions ayushma/utils/speech_to_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def recognize(self, audio):
return ""
response = response.json()
return response["data"]["transcription"].strip()
except Exception as e:
except Exception:
raise ValueError(
"[Speech to Text] Failed to recognize speech with Self Hosted engine"
)
Expand All @@ -99,16 +99,17 @@ def speech_to_text(engine_id, audio, language_code):
engine_class = engines.get(engine_name)

if not engine_class:
raise ValueError(f"[Speech to Text] Engine with ID {engine_id} not found")
print(f"Invalid Speech to Text engine: {engine_name}")
raise ValueError("The selected Speech to Text engine is not valid")

try:
engine = engine_class(api_key, language_code)
recognized_text = engine.recognize(audio)
if not recognized_text:
raise ValueError("[Speech to Text] No text recognized")
raise ValueError("No text recognized in the audio")
return recognized_text
except Exception as e:
print(f"Failed to transcribe speech with {engine_name} engine: {e}")
raise ValueError(
f"[Speech to Text] Failed to transcribe speech with {engine_name} engine"
f"[Speech to Text] Failed to transcribe speech with {engine_name} engine: {e}"
)
24 changes: 20 additions & 4 deletions ayushma/views/chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
from rest_framework.response import Response

from ayushma.models import Chat, ChatFeedback, Project
from ayushma.models.chat import ChatMessage
from ayushma.models.enums import ChatMessageType
from ayushma.permissions import IsTempTokenOrAuthenticated
from ayushma.serializers import (
ChatDetailSerializer,
Expand Down Expand Up @@ -131,11 +133,25 @@ def speech_to_text(self, *args, **kwarg):
stats["transcript_end_time"] = time.time()
translated_text = transcript
except Exception as e:
print(f"Failed to transcribe speech with {stt_engine} engine: {e}")
print(f"Failed to transcribe speech with {stt_engine} engine:\n{e}")

error_msg = (
f"[Transcribing] Something went wrong in getting transcription.\n{e}"
)
chat = Chat.objects.get(external_id=kwarg["external_id"])
chat.title = "Transcription Error"
chat.save()
ChatMessage.objects.create(
message=error_msg,
original_message=error_msg,
chat=chat,
messageType=ChatMessageType.SYSTEM,
language=language,
meta={},
)

return Response(
{
"error": "[Transcribing] Something went wrong in getting transcription, please try again later"
},
{"error": error_msg},
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
)

Expand Down
10 changes: 7 additions & 3 deletions ayushma/views/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,12 @@ class ProjectViewSet(
CreateModelMixin,
DestroyModelMixin,
):
queryset = Project.objects.all()
filter_backends = (filters.SearchFilter, DjangoFilterBackend)
queryset = Project.objects.all().order_by("-is_default")
filter_backends = (
filters.SearchFilter,
DjangoFilterBackend,
filters.OrderingFilter,
)
search_fields = ("title",)
filterset_fields = ("archived",)
serializer_class = ProjectSerializer
Expand Down Expand Up @@ -56,7 +60,7 @@ def get_queryset(self):
if self.action == "list":
if not self.request.user.is_staff:
queryset = self.queryset.filter(is_default=True)
return queryset
return queryset.order_by("-is_default")

def perform_create(self, serializer):
serializer.save(creator=self.request.user)
Expand Down
11 changes: 7 additions & 4 deletions ayushma/views/users.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from django_filters.rest_framework import DjangoFilterBackend
from drf_spectacular.utils import extend_schema
from rest_framework import permissions
from rest_framework import filters, permissions
from rest_framework.decorators import action
from rest_framework.filters import SearchFilter

from ayushma.models import User
from ayushma.serializers.users import (
Expand All @@ -15,7 +14,12 @@


class UserViewSet(FullBaseModelViewSet):
queryset = User.objects.all()
queryset = User.objects.all().order_by("-date_joined")
filter_backends = (
filters.SearchFilter,
DjangoFilterBackend,
filters.OrderingFilter,
)
serializer_class = UserDetailSerializer
permission_classes = (permissions.IsAdminUser,)
serializer_action_classes = {
Expand All @@ -29,7 +33,6 @@ class UserViewSet(FullBaseModelViewSet):
"partial_update_me": (permissions.IsAuthenticated(),),
}
lookup_field = "username"
filter_backends = [SearchFilter, DjangoFilterBackend]
search_fields = ["full_name"]
filterset_fields = ["is_staff", "is_reviewer", "allow_key"]

Expand Down

0 comments on commit 1323bfc

Please sign in to comment.