Skip to content

Commit

Permalink
Merge branch 'main' into feat/pdf-highlight
Browse files Browse the repository at this point in the history
  • Loading branch information
vishnuszipstack authored Jul 18, 2024
2 parents 1445f06 + 64861dc commit 0e19028
Show file tree
Hide file tree
Showing 19 changed files with 334 additions and 152 deletions.
13 changes: 0 additions & 13 deletions backend/prompt_studio/prompt_profile_manager/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from adapter_processor.adapter_processor import AdapterProcessor
from prompt_studio.prompt_profile_manager.constants import ProfileManagerKeys
from prompt_studio.prompt_studio_core.exceptions import MaxProfilesReachedError

from backend.serializers import AuditSerializer

Expand Down Expand Up @@ -39,15 +38,3 @@ def to_representation(self, instance): # type: ignore
AdapterProcessor.get_adapter_instance_by_id(x2text)
)
return rep

def validate(self, data):
prompt_studio_tool = data.get(ProfileManagerKeys.PROMPT_STUDIO_TOOL)

profile_count = ProfileManager.objects.filter(
prompt_studio_tool=prompt_studio_tool
).count()

if profile_count >= ProfileManagerKeys.MAX_PROFILE_COUNT:
raise MaxProfilesReachedError()

return data
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,11 @@ def _execute_prompts_in_single_pass(
doc_path, tool_id, org_id, user_id, document_id, run_id
):
prompts = PromptStudioHelper.fetch_prompt_from_tool(tool_id)
prompts = [prompt for prompt in prompts if prompt.prompt_type != TSPKeys.NOTES]
prompts = [
prompt
for prompt in prompts
if prompt.prompt_type != TSPKeys.NOTES and prompt.active
]
if not prompts:
logger.error(f"[{tool_id or 'NA'}] No prompts found for id: {id}")
raise NoPromptsFound()
Expand Down
16 changes: 15 additions & 1 deletion backend/prompt_studio/prompt_studio_core/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
from file_management.file_management_helper import FileManagerHelper
from permissions.permission import IsOwner, IsOwnerOrSharedUser
from prompt_studio.processor_loader import ProcessorConfig, load_plugins
from prompt_studio.prompt_profile_manager.constants import ProfileManagerErrors
from prompt_studio.prompt_profile_manager.constants import (
ProfileManagerErrors,
ProfileManagerKeys,
)
from prompt_studio.prompt_profile_manager.models import ProfileManager
from prompt_studio.prompt_profile_manager.serializers import ProfileManagerSerializer
from prompt_studio.prompt_studio.constants import ToolStudioPromptErrors
Expand All @@ -26,6 +29,7 @@
)
from prompt_studio.prompt_studio_core.exceptions import (
IndexingAPIError,
MaxProfilesReachedError,
ToolDeleteError,
)
from prompt_studio.prompt_studio_core.prompt_studio_helper import PromptStudioHelper
Expand Down Expand Up @@ -345,6 +349,16 @@ def create_profile_manager(self, request: HttpRequest, pk: Any = None) -> Respon
serializer = ProfileManagerSerializer(data=request.data, context=context)

serializer.is_valid(raise_exception=True)
# Check for the maximum number of profiles constraint
prompt_studio_tool = serializer.validated_data[
ProfileManagerKeys.PROMPT_STUDIO_TOOL
]
profile_count = ProfileManager.objects.filter(
prompt_studio_tool=prompt_studio_tool
).count()

if profile_count >= ProfileManagerKeys.MAX_PROFILE_COUNT:
raise MaxProfilesReachedError()
try:
self.perform_create(serializer)
except IntegrityError:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,8 @@ class PromptStudioOutputManagerKeys:
DOCUMENT_MANAGER = "document_manager"
IS_SINGLE_PASS_EXTRACT = "is_single_pass_extract"
NOTES = "NOTES"


class PromptOutputManagerErrorMessage:
TOOL_VALIDATION = "tool_id parameter is required"
TOOL_NOT_FOUND = "Tool not found"
8 changes: 8 additions & 0 deletions backend/prompt_studio/prompt_studio_output_manager/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,17 @@
from .views import PromptStudioOutputView

prompt_doc_list = PromptStudioOutputView.as_view({"get": "list"})
get_output_for_tool_default = PromptStudioOutputView.as_view(
{"get": "get_output_for_tool_default"}
)

urlpatterns = format_suffix_patterns(
[
path("prompt-output/", prompt_doc_list, name="prompt-doc-list"),
path(
"prompt-output/prompt-default-profile/",
get_output_for_tool_default,
name="prompt-default-profile-outputs",
),
]
)
58 changes: 56 additions & 2 deletions backend/prompt_studio/prompt_studio_output_manager/views.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import logging
from typing import Optional
from typing import Any, Optional

from django.core.exceptions import ObjectDoesNotExist
from django.db.models import QuerySet
from django.http import HttpRequest
from prompt_studio.prompt_studio.models import ToolStudioPrompt
from prompt_studio.prompt_studio_output_manager.constants import (
PromptOutputManagerErrorMessage,
PromptStudioOutputManagerKeys,
)
from prompt_studio.prompt_studio_output_manager.serializers import (
PromptStudioOutputSerializer,
)
from rest_framework import viewsets
from rest_framework import status, viewsets
from rest_framework.exceptions import APIException
from rest_framework.response import Response
from rest_framework.versioning import URLPathVersioning
from utils.common_utils import CommonUtils
from utils.filtering import FilterHelper
Expand Down Expand Up @@ -49,3 +55,51 @@ def get_queryset(self) -> Optional[QuerySet]:
queryset = PromptStudioOutputManager.objects.filter(**filter_args)

return queryset

def get_output_for_tool_default(self, request: HttpRequest) -> Response:
# Get the tool_id from request parameters
# Get the tool_id from request parameters
tool_id = request.GET.get("tool_id")
document_manager_id = request.GET.get("document_manager")
tool_validation_message = PromptOutputManagerErrorMessage.TOOL_VALIDATION
tool_not_found = PromptOutputManagerErrorMessage.TOOL_NOT_FOUND
if not tool_id:
raise APIException(detail=tool_validation_message, code=400)

try:
# Fetch ToolStudioPrompt records based on tool_id
tool_studio_prompts = ToolStudioPrompt.objects.filter(tool_id=tool_id)
except ObjectDoesNotExist:
raise APIException(detail=tool_not_found, code=400)

# Initialize the result dictionary
result: dict[str, Any] = {}

# Iterate over ToolStudioPrompt records
for tool_prompt in tool_studio_prompts:
prompt_id = str(tool_prompt.prompt_id)
profile_manager_id = str(tool_prompt.profile_manager.profile_id)

# If profile_manager is not set, skip this record
if not profile_manager_id:
result[tool_prompt.prompt_key] = ""
continue

try:
queryset = PromptStudioOutputManager.objects.filter(
prompt_id=prompt_id,
profile_manager=profile_manager_id,
is_single_pass_extract=False,
document_manager_id=document_manager_id,
)

if not queryset.exists():
result[tool_prompt.prompt_key] = ""
continue

for output in queryset:
result[tool_prompt.prompt_key] = output.output
except ObjectDoesNotExist:
result[tool_prompt.prompt_key] = ""

return Response(result, status=status.HTTP_200_OK)
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,8 @@ def frame_export_json(
tool_settings[JsonSchemaKey.ENABLE_HIGHLIGHT] = tool.enable_highlight

for prompt in prompts:
if prompt.prompt_type == JsonSchemaKey.NOTES or not prompt.active:
continue

if not prompt.prompt:
invalidated_prompts.append(prompt.prompt_key)
Expand All @@ -283,8 +285,6 @@ def frame_export_json(
invalidated_outputs.append(prompt.prompt_key)
continue

if prompt.prompt_type == JsonSchemaKey.NOTES:
continue
if not prompt.profile_manager:
prompt.profile_manager = default_llm_profile

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Col, Modal, Row, Tabs, Typography } from "antd";
import PropTypes from "prop-types";
import { useState } from "react";
import { useEffect, useState } from "react";

import { ListOfConnectors } from "../list-of-connectors/ListOfConnectors";
import "./ConfigureConnectorModal.css";
Expand Down Expand Up @@ -28,6 +28,13 @@ function ConfigureConnectorModal({
setSelectedItemName,
}) {
const [activeKey, setActiveKey] = useState("1");
useEffect(() => {
if (connectorMetadata) {
setActiveKey("2"); // If connector is already configured
} else {
setActiveKey("1"); // default value
}
}, [open, connectorMetadata]);
const { setPostHogCustomEvent, posthogConnectorEventText } =
usePostHogEvents();
const tabItems = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ function ConfigureFormsLayout({
connDetails={connDetails}
connType={connType}
selectedSourceName={selectedItemName}
formDataConfig={formDataConfig}
/>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,17 +76,24 @@ function CombinedOutput({ docId, setFilledFields }) {
.then((res) => {
const data = res?.data || [];
const prompts = details?.prompts;
if (activeKey === "0") {
const output = {};
for (const key in data) {
if (Object.hasOwn(data, key)) {
output[key] = displayPromptResult(data[key], false);
}
}
setCombinedOutput(output);
return;
}
const output = {};
prompts.forEach((item) => {
if (item?.prompt_type === promptType.notes) {
return;
}
output[item?.prompt_key] = "";

let profileManager = selectedProfile || item?.profile_manager;
if (singlePassExtractMode) {
profileManager = defaultLlmProfile;
}
const profileManager = selectedProfile || item?.profile_manager;
const outputDetails = data.find(
(outputValue) =>
outputValue?.prompt_id === item?.prompt_id &&
Expand Down Expand Up @@ -147,6 +154,9 @@ function CombinedOutput({ docId, setFilledFields }) {
}&document_manager=${docId}&is_single_pass_extract=${singlePassExtractMode}&profile_manager=${
selectedProfile || defaultLlmProfile
}`;
if (activeKey === "0") {
url = `/api/v1/unstract/${sessionDetails?.orgId}/prompt-studio/prompt-output/prompt-default-profile/?tool_id=${details?.tool_id}&document_manager=${docId}`;
}
}
const requestOptions = {
method: "GET",
Expand Down Expand Up @@ -198,6 +208,7 @@ function CombinedOutput({ docId, setFilledFields }) {
llmProfiles={llmProfiles}
activeKey={activeKey}
adapterData={adapterData}
isSinglePass={singlePassExtractMode}
/>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ function JsonView({
activeKey,
selectedProfile,
llmProfiles,
isSinglePass,
}) {
useEffect(() => {
Prism.highlightAll();
Expand All @@ -21,8 +22,10 @@ function JsonView({
<div className="combined-op-layout">
<div className="combined-op-header">
<Tabs activeKey={activeKey} onChange={handleTabChange} moreIcon={<></>}>
<TabPane tab={<span>Default</span>} key={"0"}></TabPane>
{[...(adapterData || [])].map((adapter, index) => (
{!isSinglePass && (
<TabPane tab={<span>Default</span>} key={"0"}></TabPane>
)}
{adapterData.map((adapter, index) => (
<TabPane
tab={<span>{adapter.llm_model}</span>}
key={(index + 1)?.toString()}
Expand Down Expand Up @@ -54,6 +57,7 @@ JsonView.propTypes = {
selectedProfile: PropTypes.string,
llmProfiles: PropTypes.array,
activeKey: PropTypes.string,
isSinglePass: PropTypes.bool,
};

export { JsonView };
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { DeleteOutlined, EditOutlined } from "@ant-design/icons";
import { Button, Radio, Table, Typography } from "antd";
import { Button, Radio, Table, Tooltip, Typography } from "antd";
import { useEffect, useState } from "react";

import { useAxiosPrivate } from "../../../hooks/useAxiosPrivate";
Expand Down Expand Up @@ -75,6 +75,8 @@ function ManageLlmProfiles() {
const { setAlertDetails } = useAlertStore();
const handleException = useExceptionHandler();
const { setPostHogCustomEvent } = usePostHogEvents();
const MAX_PROFILE_COUNT = 4;
const isMaxProfile = llmProfiles.length >= MAX_PROFILE_COUNT;

const handleDefaultLlm = (profileId) => {
try {
Expand Down Expand Up @@ -239,13 +241,21 @@ function ManageLlmProfiles() {
</div>
</SpaceWrapper>
<div className="display-flex-right">
<CustomButton
type="primary"
disabled={isPublicSource}
onClick={handleAddNewLlmProfileBtnClick}
<Tooltip
title={
isMaxProfile
? `Max profile count(${MAX_PROFILE_COUNT})`
: "Add New LLM Profile"
}
>
Add New LLM Profile
</CustomButton>
<CustomButton
type="primary"
onClick={handleAddNewLlmProfileBtnClick}
disabled={isMaxProfile}
>
Add New LLM Profile
</CustomButton>
</Tooltip>
</div>
</div>
);
Expand Down
Loading

0 comments on commit 0e19028

Please sign in to comment.