Skip to content
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
6217946
Intial commit
johnyrahul Apr 3, 2024
756137a
Updated the admin page
johnyrahul Apr 9, 2024
cf4e3ae
Fritcionless onbaodring changes
johnyrahul Apr 17, 2024
8dc9306
Merge branch 'main' into feat/friction_less_onboarding
johnyrahul Apr 18, 2024
0b7f6aa
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 18, 2024
c76a7ee
Updated the authenication helper
johnyrahul Apr 19, 2024
998f6a6
Merge branch 'main' into feat/friction_less_onboarding
johnyrahul Apr 19, 2024
e9ea57f
Historical model fix in migration
johnyrahul Apr 19, 2024
9ee64b0
added adapter identfiers
johnyrahul Apr 19, 2024
4bf71ad
Merge branch 'main' into feat/friction_less_onboarding
Deepak-Kesavan Apr 21, 2024
c151be8
Made token_usage table tenant specific
Deepak-Kesavan Apr 22, 2024
201c518
Updated the migrations
johnyrahul Apr 23, 2024
dfeade0
Validating adapter state in prompt and workflow run
johnyrahul Apr 23, 2024
64c4c06
Validating adapter state in prompt and workflow run
johnyrahul Apr 23, 2024
65a3cd8
Added method for usage in pusbsub helper
johnyrahul Apr 23, 2024
0df2a34
Removed organization_id field from token_usage table
Deepak-Kesavan Apr 24, 2024
00ecc16
Made admin page as plugin
Deepak-Kesavan Apr 24, 2024
2282a5e
usage table changes
Deepak-Kesavan Apr 24, 2024
7f9e368
Pass adapter_instance_id to run_completion function
Deepak-Kesavan Apr 24, 2024
b5629ea
Updated field model_type -> model_name
Deepak-Kesavan Apr 24, 2024
9ccbda2
Merge branch 'main' into feat/friction_less_onboarding
johnyrahul Apr 24, 2024
19e1154
added description for adapters
johnyrahul Apr 24, 2024
b91f791
Added the error messages
johnyrahul Apr 24, 2024
5be3a17
Updated serilizer to display description
johnyrahul Apr 24, 2024
b9b5db8
Updated organziation with token limit
johnyrahul Apr 25, 2024
50a76a3
Support description for adapters
Deepak-Kesavan Apr 25, 2024
2bc37c8
Save total token usage
Deepak-Kesavan Apr 25, 2024
d4c3578
Merge branch 'main' into feat/friction_less_onboarding
johnyrahul Apr 25, 2024
5497982
resolved conflict
johnyrahul Apr 25, 2024
d6bf555
Implemented the SocketMessages component globally
tahierhussain Apr 25, 2024
f04e632
Minor fix
Deepak-Kesavan Apr 25, 2024
8615e6f
Merge remote-tracking branch 'origin/feat/friction_less_onboarding' i…
Deepak-Kesavan Apr 25, 2024
c796aa0
Merge remote-tracking branch 'origin/global-websocket-component' into…
Deepak-Kesavan Apr 25, 2024
aad8318
Merge branch 'main' into feat/friction_less_onboarding
johnyrahul Apr 26, 2024
25fa9e2
Rverted the git ignore
johnyrahul Apr 26, 2024
d2b22e9
Reverted the git ignore
johnyrahul Apr 26, 2024
2a86ee8
Correct the error message
johnyrahul Apr 26, 2024
107cf7f
Make token usage 0 if negative
Deepak-Kesavan Apr 26, 2024
3f79e26
Merge remote-tracking branch 'origin/feat/friction_less_onboarding' i…
Deepak-Kesavan Apr 26, 2024
ff8f03a
SDk version bump
johnyrahul Apr 26, 2024
97e9f63
Review comment fixes
Deepak-Kesavan Apr 26, 2024
3af46f9
Merge branch 'main' into feat/friction_less_onboarding
Deepak-Kesavan Apr 26, 2024
13b9fb5
Merge branch 'main' into feat/friction_less_onboarding
nehabagdia Apr 27, 2024
5dffc24
Update backend/adapter_processor/models.py
johnyrahul Apr 29, 2024
40f5ce2
Addressed the review comments
johnyrahul Apr 29, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion backend/account/authentication_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@
ErrorMessage,
OrganizationMemberModel,
)
from account.custom_exceptions import DuplicateData, Forbidden, UserNotExistError
from account.custom_exceptions import (
DuplicateData,
Forbidden,
MethodNotImplemented,
UserNotExistError,
)
from account.dto import (
MemberInvitation,
OrganizationData,
Expand Down Expand Up @@ -173,6 +178,15 @@ def set_user_organization(self, request: Request, organization_id: str) -> Respo
{ErrorMessage.DUPLICATE_API}"
)
self.create_tenant_user(organization=organization, user=user)

if new_organization:
try:
self.auth_service.frictionless_onboarding(
organization=organization, user=user
)
except MethodNotImplemented:
Logger.info("Method not implemented")
Comment thread
johnyrahul marked this conversation as resolved.
Outdated

if new_organization:
self.authentication_helper.create_initial_platform_key(
user=user, organization=organization
Expand Down
2 changes: 2 additions & 0 deletions backend/account/authentication_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ def get_or_create_user_by_email(user_id: str, email: str) -> User:
"""
user_service = UserService()
user = user_service.get_user_by_email(email)
if user and not user.user_id:
user = user_service.update_user(user, user_id)
Comment thread
chandrasekharan-zipstack marked this conversation as resolved.
if not user:
user = user_service.create_user(email, user_id)
return user
Expand Down
3 changes: 3 additions & 0 deletions backend/account/authentication_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,9 @@ def get_roles(self) -> list[UserRoleData]:
def get_invitations(self, organization_id: str) -> list[MemberInvitation]:
raise MethodNotImplemented()

def frictionless_onboarding(self, organization: Organization, user: User) -> None:
raise MethodNotImplemented()

def delete_invitation(self, organization_id: str, invitation_id: str) -> bool:
raise MethodNotImplemented()

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Generated by Django 4.2.1 on 2024-04-25 07:55

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("account", "0006_delete_encryptionsecret"),
]

operations = [
migrations.AddField(
model_name="organization",
name="allowed_token_limit",
field=models.IntegerField(
db_comment="token limit set in case of frition less onbaoarded org",
default=-1,
),
),
]
4 changes: 4 additions & 0 deletions backend/account/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ class Organization(TenantMixin):
)
modified_at = models.DateTimeField(auto_now=True)
created_at = models.DateTimeField(auto_now=True)
allowed_token_limit = models.IntegerField(
default=-1,
db_comment="token limit set in case of frition less onbaoarded org",
)

auto_create_schema = True

Expand Down
5 changes: 5 additions & 0 deletions backend/account/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ def create_user(self, email: str, user_id: str) -> User:
raise error
return user

def update_user(self, user: User, user_id: str) -> User:
user.user_id = user_id
user.save()
Comment thread
chandrasekharan-zipstack marked this conversation as resolved.
return user

def get_user_by_email(self, email: str) -> Optional[User]:
try:
user: User = User.objects.get(email=email)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import json
from typing import Any

from adapter_processor.models import AdapterInstance
from cryptography.fernet import Fernet
from django.conf import settings
from django.db import migrations, models
Expand All @@ -17,6 +16,7 @@ class Migration(migrations.Migration):
def EncryptCredentials(apps: Any, schema_editor: Any) -> None:
encryption_secret: str = settings.ENCRYPTION_KEY
f: Fernet = Fernet(encryption_secret.encode("utf-8"))
AdapterInstance = apps.get_model("adapter_processor", "AdapterInstance")
queryset = AdapterInstance.objects.all()

for obj in queryset: # type: ignore
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Generated by Django 4.2.1 on 2024-04-24 11:01

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
(
"adapter_processor",
"0007_remove_adapterinstance_is_default_userdefaultadapter",
),
]

operations = [
migrations.AddField(
model_name="adapterinstance",
name="description",
field=models.TextField(blank=True, default=None, null=True),
),
migrations.AddField(
model_name="adapterinstance",
name="is_friction_less",
field=models.BooleanField(
db_comment="Does the adapter created through frictionless onboarding",
default=False,
),
),
migrations.AddField(
model_name="adapterinstance",
name="is_usable",
field=models.BooleanField(db_comment="Is the Adpater Usable", default=True),
),
migrations.AddField(
model_name="adapterinstance",
name="shared_to_org",
field=models.BooleanField(
db_comment="Is the adapter shared to entire org", default=False
),
),
]
33 changes: 32 additions & 1 deletion backend/adapter_processor/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,12 @@ def get_queryset(self) -> QuerySet[Any]:
def for_user(self, user: User) -> QuerySet[Any]:
return (
self.get_queryset()
.filter(models.Q(created_by=user) | models.Q(shared_users=user))
.filter(
models.Q(created_by=user)
| models.Q(shared_users=user)
| models.Q(shared_to_org=True)
| models.Q(is_friction_less=True)
)
.distinct("id")
)

Expand Down Expand Up @@ -80,10 +85,24 @@ class AdapterInstance(BaseModel):
default=False,
db_comment="Is the adapter instance currently being used",
)
shared_to_org = models.BooleanField(
default=False,
db_comment="Is the adapter shared to entire org",
)

is_friction_less = models.BooleanField(
default=False,
db_comment="Does the adapter created through frictionless onboarding",
Comment thread
johnyrahul marked this conversation as resolved.
Outdated
)
is_usable = models.BooleanField(
default=True,
db_comment="Is the Adpater Usable",
)
Comment thread
chandrasekharan-zipstack marked this conversation as resolved.

# Introduced field to establish M2M relation between users and adapters.
# This will introduce intermediary table which relates both the models.
shared_users = models.ManyToManyField(User, related_name="shared_adapters")
description = models.TextField(blank=True, null=True, default=None)

objects = AdapterInstanceModelManager()

Expand All @@ -98,6 +117,18 @@ class Meta:
),
]

def create_adapter(self) -> None:

encryption_secret: str = settings.ENCRYPTION_KEY
f: Fernet = Fernet(encryption_secret.encode("utf-8"))

self.adapter_metadata_b = f.encrypt(
json.dumps(self.adapter_metadata).encode("utf-8")
)
self.adapter_metadata = {}

self.save()

def get_adapter_meta_data(self) -> Any:
encryption_secret: str = settings.ENCRYPTION_KEY
f: Fernet = Fernet(encryption_secret.encode("utf-8"))
Expand Down
7 changes: 6 additions & 1 deletion backend/adapter_processor/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,19 @@ class Meta(BaseAdapterSerializer.Meta):
"adapter_name",
"adapter_type",
"created_by",
"description",
) # type: ignore

def to_representation(self, instance: AdapterInstance) -> dict[str, str]:
rep: dict[str, str] = super().to_representation(instance)
rep[common.ICON] = AdapterProcessor.get_adapter_data_with_key(
instance.adapter_id, common.ICON
)
rep["created_by_email"] = instance.created_by.email

if instance.is_friction_less:
rep["created_by_email"] = "Unstract"
else:
rep["created_by_email"] = instance.created_by.email

return rep

Expand Down
70 changes: 48 additions & 22 deletions backend/adapter_processor/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,12 @@
from django.db.models import ProtectedError, QuerySet
from django.http import HttpRequest
from django.http.response import HttpResponse
from permissions.permission import IsOwner, IsOwnerOrSharedUser
from permissions.permission import (
IsFrictionLessAdapter,
IsFrictionLessAdapterDelete,
IsOwner,
IsOwnerOrSharedUser,
)
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.request import Request
Expand Down Expand Up @@ -124,9 +129,21 @@ def test(self, request: Request) -> Response:


class AdapterInstanceViewSet(ModelViewSet):
permission_classes: list[type[IsOwner]] = [IsOwner]

serializer_class = AdapterInstanceSerializer

def get_permissions(self) -> list[Any]:

if self.action in ["update", "retrieve"]:
return [IsFrictionLessAdapter()]

elif self.action == "destroy":
return [IsFrictionLessAdapterDelete()]

# Hack for friction-less onboarding
# User cant view/update metadata but can delete/share etc
return [IsOwner()]

def get_queryset(self) -> Optional[QuerySet]:
if filter_args := FilterHelper.build_filter_args(
self.request,
Expand Down Expand Up @@ -195,27 +212,36 @@ def destroy(
) -> Response:
adapter_instance: AdapterInstance = self.get_object()
adapter_type = adapter_instance.adapter_type
user_default_adapter = UserDefaultAdapter.objects.get(user=request.user)
if (
(
adapter_type == AdapterKeys.LLM
and adapter_instance == user_default_adapter.default_llm_adapter
)
or (
adapter_type == AdapterKeys.EMBEDDING
and adapter_instance == user_default_adapter.default_embedding_adapter
)
or (
adapter_type == AdapterKeys.VECTOR_DB
and adapter_instance == user_default_adapter.default_vector_db_adapter
)
or (
adapter_type == AdapterKeys.X2TEXT
and adapter_instance == user_default_adapter.default_x2text_adapter
try:
user_default_adapter: UserDefaultAdapter = UserDefaultAdapter.objects.get(
user=request.user
)
):
logger.error("Cannot delete a default adapter")
raise CannotDeleteDefaultAdapter()

if (
(
adapter_type == AdapterKeys.LLM
and adapter_instance == user_default_adapter.default_llm_adapter
)
or (
adapter_type == AdapterKeys.EMBEDDING
and adapter_instance
== user_default_adapter.default_embedding_adapter
)
or (
adapter_type == AdapterKeys.VECTOR_DB
and adapter_instance
== user_default_adapter.default_vector_db_adapter
)
or (
adapter_type == AdapterKeys.X2TEXT
and adapter_instance == user_default_adapter.default_x2text_adapter
)
):
logger.error("Cannot delete a default adapter")
raise CannotDeleteDefaultAdapter()
except UserDefaultAdapter.DoesNotExist:
# We can go head and remove adapter here
logger.info("User default adpater doesnt not exist")

try:
super().perform_destroy(adapter_instance)
Expand Down
10 changes: 10 additions & 0 deletions backend/backend/public_urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,13 @@
),
]
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)


try:
import pluggable_apps.platform_admin.urls # noqa: F401

urlpatterns += [
path(f"{path_prefix}/", include("pluggable_apps.platform_admin.urls")),
]
except ImportError:
pass
1 change: 1 addition & 0 deletions backend/backend/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ def get_required_setting(
"prompt_studio.prompt_studio_output_manager",
"prompt_studio.prompt_studio_document_manager",
"prompt_studio.prompt_studio_index_manager",
"usage",
)

INSTALLED_APPS = list(SHARED_APPS) + [
Expand Down
Loading