Skip to content
98 changes: 53 additions & 45 deletions backend/prompt_studio/prompt_studio_core_v2/prompt_studio_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@

from account_v2.constants import Common
from account_v2.models import User
from adapter_processor_v2.constants import AdapterKeys
from adapter_processor_v2.models import AdapterInstance
from adapter_processor_v2.models import AdapterInstance, UserDefaultAdapter
from django.conf import settings
from django.db import transaction
from django.db.models.manager import BaseManager
from plugins import get_plugin
from rest_framework.exceptions import APIException
from rest_framework.request import Request
Expand Down Expand Up @@ -96,57 +94,67 @@ class PromptStudioHelper:
def create_default_profile_manager(user: User, tool_id: uuid) -> None:
"""Create a default profile manager for a given user and tool.

Args:
user (User): The user for whom the default profile manager is
created.
tool_id (uuid): The ID of the tool for which the default profile
manager is created.

Raises:
AdapterInstance.DoesNotExist: If no suitable adapter instance is
found for creating the default profile manager.
Builds the profile from the creator's default-set adapters
(UserDefaultAdapter). In cloud these are the frictionless adapters
seeded at onboarding; in OSS/on-prem they are auto-set as the user
adds the first adapter of each type. Skips silently when a usable
default is missing for any of the four types, so a project can still
be created before adapters are configured.

Returns:
None
"""
try:
AdapterInstance.objects.get(
is_friction_less=True,
is_usable=True,
adapter_type=AdapterKeys.LLM,
organization_member = OrganizationMemberService.get_user_by_id(id=user.id)
if not organization_member:
logger.info(
"Skipping default profile creation: user has no organization membership"
)
return

default_adapters: BaseManager[AdapterInstance] = (
AdapterInstance.objects.filter(is_friction_less=True)
)
default_adapter = UserDefaultAdapter.objects.filter(
organization_member=organization_member
).first()
if not default_adapter:
Comment thread
greptile-apps[bot] marked this conversation as resolved.
logger.info("Skipping default profile creation: no default adapters set")
return
Comment thread
chandrasekharan-zipstack marked this conversation as resolved.

profile_manager = ProfileManager(
prompt_studio_tool=CustomTool.objects.get(pk=tool_id),
is_default=True,
created_by=user,
modified_by=user,
chunk_size=0,
profile_name="sample profile",
chunk_overlap=0,
section="Default",
retrieval_strategy="simple",
similarity_top_k=3,
adapters = {
"llm": default_adapter.default_llm_adapter,
"embedding_model": default_adapter.default_embedding_adapter,
"vector_store": default_adapter.default_vector_db_adapter,
"x2text": default_adapter.default_x2text_adapter,
}
# A valid profile needs a usable default for every adapter type
if not all(adapter and adapter.is_usable for adapter in adapters.values()):
logger.info(
"Skipping default profile creation: "
"incomplete or unusable default adapters"
)
return

for adapter in default_adapters:
if adapter.adapter_type == AdapterKeys.LLM:
profile_manager.llm = adapter
elif adapter.adapter_type == AdapterKeys.VECTOR_DB:
profile_manager.vector_store = adapter
elif adapter.adapter_type == AdapterKeys.X2TEXT:
profile_manager.x2text = adapter
elif adapter.adapter_type == AdapterKeys.EMBEDDING:
profile_manager.embedding_model = adapter

profile_manager.save()

except AdapterInstance.DoesNotExist:
logger.info("skipping default profile creation")
# Best-effort: a profile creation hiccup must never break project creation.
# The savepoint keeps a DB error from poisoning the request's outer
# transaction when ATOMIC_REQUESTS is enabled.
try:
with transaction.atomic():
ProfileManager.objects.create(
prompt_studio_tool=CustomTool.objects.get(pk=tool_id),
is_default=True,
created_by=user,
modified_by=user,
profile_name=DefaultValues.DEFAULT_PROFILE_NAME,
chunk_size=0,
chunk_overlap=0,
section="Default",
retrieval_strategy="simple",
similarity_top_k=3,
**adapters,
)
except Exception:
logger.warning(
"Skipping default profile creation: failed to create profile",
exc_info=True,
)

@staticmethod
def validate_adapter_status(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@
margin: 0;
}

/* Span wrapper lets the tooltip fire over the disabled upload button,
which otherwise swallows hover events */
.manage-docs-upload-tooltip-wrap {
display: inline-block;
width: 100%;
}

.summarization-status-circle {
width: 8px;
height: 8px;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -766,22 +766,27 @@
>
<Tooltip
title={
!defaultLlmProfile &&
"Set the default LLM profile before uploading a document"
!defaultLlmProfile

Check warning on line 769 in frontend/src/components/custom-tools/manage-docs-modal/ManageDocsModal.jsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unexpected negated condition.

See more on https://sonarcloud.io/project/issues?id=Zipstack_unstract&issues=AZ6C0zu4OyX_q8ezRrhe&open=AZ6C0zu4OyX_q8ezRrhe&pullRequest=2005
? llmProfiles?.length
? "Set the default LLM profile before uploading a document"
: "Add an LLM profile before uploading a document"

Check warning on line 772 in frontend/src/components/custom-tools/manage-docs-modal/ManageDocsModal.jsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Extract this nested ternary operation into an independent statement.

See more on https://sonarcloud.io/project/issues?id=Zipstack_unstract&issues=AZ6C0zu4OyX_q8ezRrhf&open=AZ6C0zu4OyX_q8ezRrhf&pullRequest=2005
: ""
}
>
<Button
type="text"
loading={isUploading}
disabled={
!defaultLlmProfile ||
isMultiPassExtractLoading ||
isSinglePassExtractLoading ||
isPublicSource
}
>
Click or drag file to this area to upload
</Button>
<span className="manage-docs-upload-tooltip-wrap">
<Button
type="text"
loading={isUploading}
disabled={
!defaultLlmProfile ||
isMultiPassExtractLoading ||
isSinglePassExtractLoading ||
isPublicSource
}
>
Click or drag file to this area to upload
</Button>
</span>
</Tooltip>
</Upload.Dragger>
</div>
Expand Down
Loading