Skip to content

[MISC] Auto-create default LLM profile in Prompt Studio with clearer upload tooltip#2005

Merged
chandrasekharan-zipstack merged 7 commits into
mainfrom
feat/default-llm-profile
Jun 2, 2026
Merged

[MISC] Auto-create default LLM profile in Prompt Studio with clearer upload tooltip#2005
chandrasekharan-zipstack merged 7 commits into
mainfrom
feat/default-llm-profile

Conversation

@chandrasekharan-zipstack
Copy link
Copy Markdown
Contributor

What

  • Auto-create and link a default LLM profile ("Default Profile") when a Prompt Studio project is created, whenever the creator has a usable default adapter set for all four types (LLM, Embedding, Vector DB, X2Text).
  • Improve the "Manage Documents" upload empty-state: the disabled upload control now shows a tooltip that guides the user to add an LLM profile (when none exists) or set a default profile (when profiles exist but none is default).

Why

  • A freshly created Prompt Studio project previously started with no profile in OSS/on-prem (the old logic only auto-created a profile from cloud-only "frictionless" adapters), forcing users to manually create a profile before they could do anything.
  • The upload button was disabled with only a mute "not-allowed" cursor — the existing tooltip never rendered because antd disabled buttons swallow hover events — so users had no indication of what was blocking them.

How

  • prompt_studio_helper.py::create_default_profile_manager now builds the profile from the creator's default-set adapters (UserDefaultAdapter) instead of is_friction_less adapters. It creates the profile only when a usable default exists for every adapter type, and skips silently otherwise (so project creation never breaks before adapters are configured). One code path serves cloud (frictionless adapters are the triad defaults, seeded at onboarding) and OSS/on-prem (defaults auto-set as the user adds the first adapter of each type).
  • Profile name uses the shared DefaultValues.DEFAULT_PROFILE_NAME constant ("Default Profile"), matching what the tool-import flow already defaults to.
  • Removed now-unused AdapterKeys / BaseManager imports.
  • ManageDocsModal.jsx: wrapped the disabled upload button in a <span> so the tooltip fires, and branched the tooltip message. Added a .manage-docs-upload-tooltip-wrap CSS class (no inline CSS).

Can this PR break any existing features. If yes, please list possible items. If no, please explain why. (PS: Admins do not merge the PR without this section filled)

  • Low risk. Cloud behavior is preserved: frictionless adapters are written into UserDefaultAdapter at onboarding/invite, so they remain the source for the auto-created profile. The profile-name uniqueness constraint is scoped per project (prompt_studio_tool, profile_name); the auto-created profile is the only profile in a fresh project, so no collision. The frontend change is additive (tooltip wrapper + message branch) and does not alter the disabled condition.

Database Migrations

  • None.

Env Config

  • None.

Relevant Docs

Related Issues or PRs

Dependencies Versions

Notes on Testing

  • OSS/on-prem with all 4 adapter types configured: create a new Prompt Studio project → it opens with a "Default Profile" already set and document upload enabled.
  • Account with no adapters: create a project → upload stays disabled, and hovering the upload control now shows "Add an LLM profile before uploading a document".
  • Profiles exist but none marked default: tooltip shows "Set the default LLM profile before uploading a document".
  • Cloud: regression check that new projects still auto-get a profile from frictionless adapters.

Screenshots

Checklist

I have read and understood the Contribution Guidelines.

🤖 Generated with Claude Code

chandrasekharan-zipstack and others added 2 commits June 1, 2026 15:19
…oad tooltip

Drive default profile creation from the creator's default-set adapters
(UserDefaultAdapter) instead of frictionless-only adapters, so OSS/on-prem
projects also get a profile once each of the 4 adapter types is configured.
Skips silently when a usable default is missing for any type.

Frontend: wrap the disabled upload button in a span so the antd tooltip
fires, and branch the message to prompt adding an LLM profile when none
exists vs setting a default when profiles exist.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reuse DefaultValues.DEFAULT_PROFILE_NAME instead of "sample profile" so the
auto-created profile matches the name the import flow already defaults to.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 1, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 502069a0-ff98-4f69-8143-e959cc679090

📥 Commits

Reviewing files that changed from the base of the PR and between 34b941b and 88e1317.

📒 Files selected for processing (1)
  • backend/prompt_studio/prompt_studio_core_v2/prompt_studio_helper.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • backend/prompt_studio/prompt_studio_core_v2/prompt_studio_helper.py

Summary by CodeRabbit

  • New Features

    • Enhanced guidance for LLM profile setup with contextual messages prompting users to set a default profile or create one based on availability.
  • Improvements

    • Tooltip accessibility improved for the document upload area, enabling hover interactions over a disabled upload control.
  • Changes

    • Default profile creation now follows user-specific defaults, which may change how automatic profiles are provisioned.

Walkthrough

Refactors default profile creation to use organization-scoped UserDefaultAdapter defaults and updates the manage-docs upload tooltip/wrapper to show contextual guidance when a default LLM profile is missing.

Changes

Default Profile Setup and Upload Modal UX

Layer / File(s) Summary
Default profile manager refactoring
backend/prompt_studio/prompt_studio_core_v2/prompt_studio_helper.py
Imports updated to use UserDefaultAdapter and Django transaction; create_default_profile_manager now fetches the user's organization_member, reads scoped UserDefaultAdapter defaults, validates required adapter defaults (llm, embedding_model, vector_store, x2text), and attempts to create a ProfileManager inside transaction.atomic() with DefaultValues.DEFAULT_PROFILE_NAME, setting prompt_studio_tool via CustomTool.objects.get(pk=tool_id). Previous global frictionless adapter selection and "sample profile" path removed.
Upload modal tooltip + wrapper
frontend/src/components/custom-tools/manage-docs-modal/ManageDocsModal.css, frontend/src/components/custom-tools/manage-docs-modal/ManageDocsModal.jsx
Adds .manage-docs-upload-tooltip-wrap CSS wrapper (inline-block, 100% width) to allow tooltip hover over a disabled upload button; JSX changes the upload dragger tooltip title to conditionally show: when no defaultLlmProfile — if llmProfiles exist prompt "Set the default LLM profile", otherwise prompt "Add an LLM profile"; upload button wrapped in an extra span for tooltip interaction.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main changes: auto-creating a default LLM profile and improving the upload tooltip guidance in Prompt Studio.
Description check ✅ Passed The description is comprehensive and well-structured, covering all required sections with detailed information about changes, rationale, impact assessment, and testing guidance.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/default-llm-profile

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@chandrasekharan-zipstack chandrasekharan-zipstack marked this pull request as ready for review June 1, 2026 10:55
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Jun 1, 2026

Greptile Summary

This PR auto-creates a "Default Profile" when a new Prompt Studio project is created (using the creator's UserDefaultAdapter defaults instead of the cloud-only is_friction_less flag), and fixes the Manage Documents upload tooltip which previously never rendered because disabled Ant Design buttons swallow hover events.

  • Backend: create_default_profile_manager now queries UserDefaultAdapter, validates all four adapter types are present and usable, then creates the profile inside a transaction.atomic() savepoint so any DB error cannot poison the request's outer transaction under ATOMIC_REQUESTS.
  • Frontend: The disabled upload Button is wrapped in a <span className=\"manage-docs-upload-tooltip-wrap\"> so tooltip hover events fire; the tooltip message branches between "Add an LLM profile" (no profiles exist) and "Set the default LLM profile" (profiles exist, none is default).

Confidence Score: 5/5

Safe to merge — both backend and frontend changes are additive and well-guarded, with no existing functionality altered.

The backend refactor correctly maps UserDefaultAdapter fields to ProfileManager fields, guards all early-exit conditions (missing membership, missing row, any adapter null or unusable), and uses a savepoint so a creation failure cannot corrupt the outer request transaction. The frontend change is purely additive: the span wrapper unblocks tooltip hover events without touching disabled logic, and the branched message uses optional chaining safely. No database migrations, no removed code paths that were load-bearing.

No files require special attention.

Important Files Changed

Filename Overview
backend/prompt_studio/prompt_studio_core_v2/prompt_studio_helper.py Rewrites create_default_profile_manager to source adapters from UserDefaultAdapter; adds org-membership guard, all-adapters-usable check, and transaction.atomic() savepoint. Logic and field mappings are correct.
frontend/src/components/custom-tools/manage-docs-modal/ManageDocsModal.jsx Wraps disabled upload Button in a span to enable tooltip hover events, and branches the tooltip message between 'Add' and 'Set default' based on whether any LLM profiles exist.
frontend/src/components/custom-tools/manage-docs-modal/ManageDocsModal.css Adds .manage-docs-upload-tooltip-wrap style (inline-block, full width) to support the new span wrapper.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[create_default_profile_manager called] --> B{OrganizationMember exists?}
    B -- No --> C[Log & return]
    B -- Yes --> D{UserDefaultAdapter row exists?}
    D -- No --> E[Log & return]
    D -- Yes --> F[Load all 4 adapter FKs]
    F --> G{All 4 adapters present & is_usable?}
    G -- No --> H[Log & return]
    G -- Yes --> I[transaction.atomic savepoint]
    I --> J[ProfileManager.objects.create with DEFAULT_PROFILE_NAME]
    J -- Success --> K[Profile created, outer TX intact]
    J -- Exception --> L[Savepoint rolled back, warning logged]
    L --> M[Outer transaction unaffected]
Loading

Reviews (6): Last reviewed commit: "[MISC] Address review: guard missing org..." | Re-trigger Greptile

Comment thread backend/prompt_studio/prompt_studio_core_v2/prompt_studio_helper.py
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/components/custom-tools/manage-docs-modal/ManageDocsModal.jsx (1)

756-789: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Align Upload.Dragger disabled state with inner upload button state
Upload.Dragger is disabled only for isUploading || !defaultLlmProfile, but the inner Button also disables for isMultiPassExtractLoading, isSinglePassExtractLoading, and isPublicSource. beforeUpload/handleUploadChange don’t guard these flags, so drag/click can still initiate uploads while the UI appears disabled.

Proposed fix
               <Upload.Dragger
                 name="file"
                 action={`/api/v1/unstract/${sessionDetails?.orgId}/prompt-studio/file/${details?.tool_id}`}
                 headers={{
                   "X-CSRFToken": sessionDetails.csrfToken,
                 }}
                 onChange={handleUploadChange}
-                disabled={isUploading || !defaultLlmProfile}
+                disabled={
+                  isUploading ||
+                  !defaultLlmProfile ||
+                  isMultiPassExtractLoading ||
+                  isSinglePassExtractLoading ||
+                  isPublicSource
+                }
                 showUploadList={false}
                 beforeUpload={beforeUpload}
               >
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/custom-tools/manage-docs-modal/ManageDocsModal.jsx`
around lines 756 - 789, The Upload.Dragger disabled condition must match the
inner Button and prevent programmatic uploads: update the Upload.Dragger
disabled prop to include isMultiPassExtractLoading, isSinglePassExtractLoading,
and isPublicSource (so it uses isUploading || !defaultLlmProfile ||
isMultiPassExtractLoading || isSinglePassExtractLoading || isPublicSource) and
add guards at the start of beforeUpload and handleUploadChange to return/abort
if any of those flags are true; reference Upload.Dragger, Button, beforeUpload,
and handleUploadChange to locate and change the conditions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/prompt_studio/prompt_studio_core_v2/prompt_studio_helper.py`:
- Around line 107-113: The code calls
OrganizationMemberService.get_user_by_id(...) and then immediately filters
UserDefaultAdapter.objects.filter(organization_member=organization_member), but
get_user_by_id can return None which causes a null-scoped filter to match
unrelated rows; update the logic in the function containing organization_member
(where OrganizationMemberService.get_user_by_id is called) to check if
organization_member is None and if so log a clear message (e.g., "Skipping
default profile creation: organization member not found for user X") and return
early before querying UserDefaultAdapter, ensuring
UserDefaultAdapter.objects.filter is only called with a valid OrganizationMember
instance.

---

Outside diff comments:
In `@frontend/src/components/custom-tools/manage-docs-modal/ManageDocsModal.jsx`:
- Around line 756-789: The Upload.Dragger disabled condition must match the
inner Button and prevent programmatic uploads: update the Upload.Dragger
disabled prop to include isMultiPassExtractLoading, isSinglePassExtractLoading,
and isPublicSource (so it uses isUploading || !defaultLlmProfile ||
isMultiPassExtractLoading || isSinglePassExtractLoading || isPublicSource) and
add guards at the start of beforeUpload and handleUploadChange to return/abort
if any of those flags are true; reference Upload.Dragger, Button, beforeUpload,
and handleUploadChange to locate and change the conditions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9c62b33f-ff2c-4309-bf91-9c33c25f9d7e

📥 Commits

Reviewing files that changed from the base of the PR and between c633db8 and 949a8f5.

📒 Files selected for processing (3)
  • backend/prompt_studio/prompt_studio_core_v2/prompt_studio_helper.py
  • frontend/src/components/custom-tools/manage-docs-modal/ManageDocsModal.css
  • frontend/src/components/custom-tools/manage-docs-modal/ManageDocsModal.jsx

Comment thread backend/prompt_studio/prompt_studio_core_v2/prompt_studio_helper.py
…roject creation

create_default_profile_manager is called outside the create() try/except, so
wrap the ProfileManager insert and swallow/log any error - matching the prior
contract where a missing adapter was silently skipped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread backend/prompt_studio/prompt_studio_core_v2/prompt_studio_helper.py Outdated
…rofile create

- Return early when the user has no OrganizationMember, so the nullable
  UserDefaultAdapter.organization_member can't match an unrelated null-scoped row.
- Wrap ProfileManager.create in transaction.atomic() so a caught DB error
  doesn't poison the request's outer transaction under ATOMIC_REQUESTS.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 2, 2026

Frontend Lint Report (Biome)

All checks passed! No linting or formatting issues found.

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Jun 2, 2026

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 2, 2026

Unstract test results

Per-group results

Status Group Tier Passed Failed Errors Skipped Duration (s)
unit-connectors unit 64 12 0 3 16.8
unit-core unit 0 0 2 0 1.2
unit-platform-service unit 9 0 1 0 1.3
unit-prompt-service unit 15 0 0 0 19.6
unit-rig unit 53 0 0 0 3.3
unit-runner unit 11 0 0 0 3.1
unit-sdk1 unit 354 0 0 0 20.2
unit-tool-registry unit 0 0 1 0 1.3
unit-workers unit 0 0 0 0 17.7
TOTAL 506 12 4 3 84.4

Critical paths

⚠️ Critical paths not yet covered

  • auth-login — User can log in and obtain a session cookie. (entry: POST /api/v1/auth/login; declared coverage: no groups declared)
  • adapter-register-llm — Register and validate an LLM adapter. (entry: POST /api/v1/adapter/; declared coverage: no groups declared)
  • workflow-create-execute — Create a workflow, configure source+destination, execute, poll, fetch result. (entry: POST /api/v1/workflow/{id}/execute/; declared coverage: e2e-workflow)
  • api-deployment-run — Deploy a workflow as an API, POST a document, receive structured JSON. (entry: POST /deployment/api/{org}/{name}/; declared coverage: e2e-api-deployment)
  • prompt-studio-fetch-response — Prompt Studio: create project, add prompt, run single-pass, get response. (entry: POST /api/v1/prompt-studio/prompt-studio-tool/{id}/fetch_response/; declared coverage: e2e-prompt-studio)
  • pipeline-etl-execute — Run an ETL pipeline from source connector to destination. (entry: POST /api/v1/pipeline/{id}/execute/; declared coverage: no groups declared)
  • usage-token-tracking — Per-execution token usage is recorded and retrievable. (entry: GET /api/v1/usage/get_token_usage/; declared coverage: no groups declared)
  • workflow-execution-fan-out — Multi-file workflow execution fans out to file-processing workers and rejoins. (entry: internal: backend → rabbitmq → workers/file_processing; declared coverage: no groups declared)
  • callback-result-delivery — Async results are posted back via the callback worker. (entry: internal: workers/callback → backend /internal endpoints; declared coverage: no groups declared)
✅ Covered critical paths
  • tool-sandbox-exec — covered by unit-runner

@chandrasekharan-zipstack chandrasekharan-zipstack merged commit b883c49 into main Jun 2, 2026
10 checks passed
@chandrasekharan-zipstack chandrasekharan-zipstack deleted the feat/default-llm-profile branch June 2, 2026 04:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants