Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feat] Highlight support in prompt studio #887

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Generated by Django 4.2.1 on 2024-12-05 10:21

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("prompt_studio_output_manager_v2", "0001_initial"),
]

operations = [
migrations.AddField(
model_name="promptstudiooutputmanager",
name="highlight_data",
field=models.JSONField(
blank=True, db_comment="Field to store highlight data", null=True
),
),
]
vishnuszipstack marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ class PromptStudioOutputManager(BaseModel):
challenge_data = models.JSONField(
db_comment="Field to store challenge data", editable=True, null=True, blank=True
)
highlight_data = models.JSONField(
db_comment="Field to store highlight data", editable=True, null=True, blank=True
)
eval_metrics = models.JSONField(
db_column="eval_metrics",
null=False,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ def update_or_create_prompt_output(
tool: CustomTool,
context: str,
challenge_data: Optional[dict[str, Any]],
highlight_data: Optional[dict[str, Any]],
) -> PromptStudioOutputManager:
"""Handles creating or updating a single prompt output and returns
the instance."""
Expand All @@ -76,6 +77,7 @@ def update_or_create_prompt_output(
"eval_metrics": eval_metrics,
"context": context,
"challenge_data": challenge_data,
"highlight_data": highlight_data,
},
)
)
Expand All @@ -97,6 +99,7 @@ def update_or_create_prompt_output(
"eval_metrics": eval_metrics,
"context": context,
"challenge_data": challenge_data,
"highlight_data": highlight_data,
}
PromptStudioOutputManager.objects.filter(
document_manager=document_manager,
Expand All @@ -118,6 +121,7 @@ def update_or_create_prompt_output(
serialized_data: list[dict[str, Any]] = []
context = metadata.get("context")
challenge_data = metadata.get("challenge_data")
highlight_data = metadata.get("highlight_data")

if not prompts:
return serialized_data
Expand All @@ -134,6 +138,8 @@ def update_or_create_prompt_output(

if not is_single_pass_extract:
context = context.get(prompt.prompt_key)
if highlight_data:
highlight_data = highlight_data.get(prompt.prompt_key)
if challenge_data:
challenge_data = challenge_data.get(prompt.prompt_key)

Expand All @@ -156,6 +162,7 @@ def update_or_create_prompt_output(
tool=tool,
context=json.dumps(context),
challenge_data=challenge_data,
highlight_data=highlight_data,
)

# Serialize the instance
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,13 @@ function DocumentManager({ generateIndex, handleUpdateTool, handleDocChange }) {
isSimplePromptStudio,
isPublicSource,
refreshRawView,
selectedHighlight,
} = useCustomToolStore();
const { sessionDetails } = useSessionStore();
const axiosPrivate = useAxiosPrivate();
const { setPostHogCustomEvent } = usePostHogEvents();
const { id } = useParams();
const highlightData = selectedHighlight?.highlight || [];

useEffect(() => {
if (isSimplePromptStudio) {
Expand Down Expand Up @@ -386,7 +388,7 @@ function DocumentManager({ generateIndex, handleUpdateTool, handleDocChange }) {
setOpenManageDocsModal={setOpenManageDocsModal}
errMsg={fileErrMsg}
>
<PdfViewer fileUrl={fileUrl} />
<PdfViewer fileUrl={fileUrl} highlightData={highlightData} />
</DocumentViewer>
)}
{activeKey === "2" && (
Expand Down
50 changes: 32 additions & 18 deletions frontend/src/components/custom-tools/pdf-viewer/PdfViewer.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useRef } from "react";
import { useEffect, useRef, useMemo } from "react";
import { Viewer, Worker } from "@react-pdf-viewer/core";
import { defaultLayoutPlugin } from "@react-pdf-viewer/default-layout";
import { pageNavigationPlugin } from "@react-pdf-viewer/page-navigation";
Expand All @@ -20,32 +20,46 @@ function PdfViewer({ fileUrl, highlightData }) {
const pageNavigationPluginInstance = pageNavigationPlugin();
const { jumpToPage } = pageNavigationPluginInstance;
const parentRef = useRef(null);
function removeZerosAndDeleteIfAllZero(highlightData) {
return highlightData.filter((innerArray) =>

const removeZerosAndDeleteIfAllZero = (data) => {
return data?.filter((innerArray) =>
innerArray.some((value) => value !== 0)
); // Keep arrays that contain at least one non-zero value
}
let highlightPluginInstance = "";
if (RenderHighlights && highlightData) {
highlightPluginInstance = highlightPlugin({
renderHighlights: (props) => (
<RenderHighlights {...props} highlightData={highlightData} />
),
});
}
);
};

const processHighlightData = highlightData
? removeZerosAndDeleteIfAllZero(highlightData)
: [];

const processedHighlightData =
processHighlightData?.length > 0 ? processHighlightData : [[0, 0, 0, 0]];

const highlightPluginInstance = useMemo(() => {
if (
RenderHighlights &&
Array.isArray(processedHighlightData) &&
processedHighlightData?.length > 0
) {
return highlightPlugin({
renderHighlights: (props) => (
<RenderHighlights {...props} highlightData={processedHighlightData} />
),
});
}
return "";
}, [RenderHighlights, processedHighlightData]);

// Jump to page when highlightData changes
useEffect(() => {
if (highlightData && highlightData.length > 0) {
highlightData = removeZerosAndDeleteIfAllZero(highlightData);
const pageNumber = highlightData[0][0]; // Assume highlightData[0][0] is the page number
if (processedHighlightData && processedHighlightData?.length > 0) {
const pageNumber = processedHighlightData[0][0]; // Assume highlightData[0][0] is the page number
if (pageNumber !== null && jumpToPage) {
setTimeout(() => {
jumpToPage(pageNumber); // jumpToPage is 0-indexed, so subtract 1
jumpToPage(pageNumber); // jumpToPage is 0-indexed, so subtract 1 if necessary
}, 100); // Add a slight delay to ensure proper page rendering
}
}
}, [highlightData, jumpToPage]);
}, [processedHighlightData, jumpToPage]);

return (
<div ref={parentRef} className="doc-manager-body">
Expand Down
13 changes: 13 additions & 0 deletions frontend/src/components/custom-tools/prompt-card/PromptCard.css
Original file line number Diff line number Diff line change
Expand Up @@ -299,3 +299,16 @@
.info-circle-colored {
color: #f0ad4e;
}

.highlighted-prompt {
border-width: 1.2px;
border-style: solid;
border-color: #4096ff;
box-shadow: 4px 4px 12.5px 0px rgba(0, 0, 0, 0.08);
}

.highlighted-prompt-cell {
border-width: 1.2px;
border-style: solid;
border-color: #ffb400;
}
26 changes: 24 additions & 2 deletions frontend/src/components/custom-tools/prompt-card/PromptCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,13 @@ const PromptCard = memo(
const [openOutputForDoc, setOpenOutputForDoc] = useState(false);
const [progressMsg, setProgressMsg] = useState({});
const [spsLoading, setSpsLoading] = useState({});
const { llmProfiles, selectedDoc, details, summarizeIndexStatus } =
useCustomToolStore();
const {
llmProfiles,
selectedDoc,
details,
summarizeIndexStatus,
updateCustomTool,
} = useCustomToolStore();
const { messages } = useSocketCustomToolStore();
const { setAlertDetails } = useAlertStore();
const { setPostHogCustomEvent } = usePostHogEvents();
Expand Down Expand Up @@ -161,6 +166,22 @@ const PromptCard = memo(
);
};

const handleSelectHighlight = (
highlightData,
highlightedPrompt,
highlightedProfile
) => {
if (details?.enable_highlight) {
updateCustomTool({
selectedHighlight: {
highlight: highlightData,
highlightedPrompt: highlightedPrompt,
highlightedProfile: highlightedProfile,
},
});
}
};
tahierhussain marked this conversation as resolved.
Show resolved Hide resolved

const handleTypeChange = (value) => {
handleChange(value, promptDetailsState?.prompt_id, "enforce_type", true);
};
Expand Down Expand Up @@ -261,6 +282,7 @@ const PromptCard = memo(
promptRunStatus={promptRunStatus}
coverageCountData={coverageCountData}
isChallenge={isChallenge}
handleSelectHighlight={handleSelectHighlight}
/>
<OutputForDocModal
open={openOutputForDoc}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ function PromptCardItems({
promptRunStatus,
coverageCountData,
isChallenge,
handleSelectHighlight,
}) {
const {
llmProfiles,
Expand All @@ -64,6 +65,8 @@ function PromptCardItems({
isPublicSource,
adapters,
defaultLlmProfile,
selectedHighlight,
details,
} = useCustomToolStore();
const [isEditingPrompt, setIsEditingPrompt] = useState(false);
const [isEditingTitle, setIsEditingTitle] = useState(false);
Expand Down Expand Up @@ -148,7 +151,13 @@ function PromptCardItems({
}, [llmProfiles, selectedLlmProfileId, enabledProfiles]);

return (
<Card className="prompt-card">
<Card
className={`prompt-card ${
details?.enable_highlight &&
selectedHighlight?.highlightedPrompt === promptDetails?.prompt_id &&
"highlighted-prompt"
}`}
>
<div className="prompt-card-div prompt-card-bg-col1 prompt-card-rad">
<Space direction="vertical" className="width-100" ref={divRef}>
<Header
Expand Down Expand Up @@ -265,6 +274,7 @@ function PromptCardItems({
promptOutputs={promptOutputs}
promptRunStatus={promptRunStatus}
isChallenge={isChallenge}
handleSelectHighlight={handleSelectHighlight}
/>
</Row>
</Collapse.Panel>
Expand Down Expand Up @@ -302,6 +312,7 @@ PromptCardItems.propTypes = {
promptRunStatus: PropTypes.object.isRequired,
coverageCountData: PropTypes.object.isRequired,
isChallenge: PropTypes.bool.isRequired,
handleSelectHighlight: PropTypes.func.isRequired,
};

export { PromptCardItems };
Loading
Loading