feat: add System Prompts library for Expand Prompt button#9152
Open
Pfannkuchensack wants to merge 8 commits into
Open
feat: add System Prompts library for Expand Prompt button#9152Pfannkuchensack wants to merge 8 commits into
Pfannkuchensack wants to merge 8 commits into
Conversation
- Add system_prompts SQLite table (migration 32) seeded with 6 curated default prompts adapted from FLUX.2, HunyuanImage 3.0, Qwen-Image, Z-Image and HiDream - Add CRUD service layer + REST router at /api/v1/system_prompts - Add RTK Query endpoints, management modal (list/create/edit/delete) and a system-prompt picker in the Expand Prompt popover - Persist last picked system prompt + text-LLM model via Redux
- Migration 32 now adds user_id + is_public columns and seeds the 6 default prompts as user_id='system', is_public=TRUE; - Storage layer gains optional user_id scoping on get_many/update/delete, and create requires user_id + is_public - Router uses CurrentUserOrDefault: list scopes to own+public, GET returns 403 for foreign private prompts, PATCH/DELETE require owner or admin - Frontend adds useCanEditSystemPrompt hook, hides edit/delete on prompts the user does not own, shows System/Shared badges in the list, and exposes a 'Share with everyone' toggle in the form when multiuser is on
- Critical: migration_32.py had a 7-space indent on the second cursor.execute(), raising IndentationError on import and blocking server startup. Re-indent and restore the ALTER TABLE backfill block lost in the previous edit. - Medium: drop the heavy import of invokeai.backend.text_llm_pipeline from the migration (which would pull torch+transformers into the migrator import path). Inline DEFAULT_SYSTEM_PROMPT verbatim and rename the seeded row to "Default"; the value still mirrors text_llm_pipeline.DEFAULT_SYSTEM_PROMPT. - Medium: add 7 storage-layer tests covering own/public/admin scoping and the no-mutate guarantees on non-owner update/delete, plus 9 router tests with JWT auth covering 401/403/404 paths, owner is_public flip, and admin override. - Conftest and the existing workflows-multiuser test fixtures now wire a real SqliteSystemPromptRecordsStorage so InvocationServices construction succeeds with the new required parameter.
…zation fixture The new required InvocationServices parameter broke 122 unrelated tests in tests/app/routers/test_multiuser_authorization.py because that file builds its own InvocationServices. Add SqliteSystemPromptRecordsStorage to its fixture the same way the workflows-multiuser fixture and the global conftest were updated in the previous commit.
…ow node Adds a sibling node to TextLLMInvocation that takes a SystemPromptField (a DB-backed preset reference) instead of a free-text system prompt. Selecting a preset in the workflow editor pulls its content from the System Prompts library at run time. The original TextLLMInvocation is unchanged, so users keep the free-text option and can pick the appropriate node per workflow. - New SystemPromptField primitive in app/invocations/fields.py - Shared _run_text_llm helper extracted from TextLLMInvocation; both nodes use it - Frontend wires SystemPromptField as a new stateful field type analogous to StylePresetField (zod schemas, type guards, builders, slice action, color, Combobox renderer backed by useListSystemPromptsQuery) - Pytest covers both behaviours: DB lookup happens with the configured id and forwards the resolved content; SystemPromptNotFoundError short-circuits the pipeline call so the LLM is not invoked
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
system_promptsSQLite table (migration 32) seeded with 7 curated default prompts: anInvokeAI Default(mirrors the hardcoded fallback intext_llm_pipeline.DEFAULT_SYSTEM_PROMPT) plus 6 prompts adapted from FLUX.2, HunyuanImage 3.0, Qwen-Image (edit + 2512), Z-Image and HiDream/api/v1/system_prompts, with per-user ownership and optional sharing (modeled on the workflow library):user_id+is_publiccolumns,CurrentUserOrDefaultdependency on every endpoint, owner-or-admin checks for PATCH/DELETE, and own+public scoping for LIST in multi-user modeexpandPromptslice)useCanEditSystemPrompthook hides edit/delete on prompts the user does not own, list items show System / Shared badges, and the form exposes a Share with everyone toggle when multi-user is enabledDB-backed preset reference) instead of a free-text system prompt.
Related Issues / Discussions
None.
QA Instructions
Backend — single-user (default)
uv run --extra cuda invokeai-web— migration 32 runs, creates thesystem_promptstable (withuser_id+is_publiccolumns) and seeds 7 default prompts asuser_id='system',is_public=TRUE.GET /api/v1/system_prompts/→ 7 recordsPOST /api/v1/system_prompts/with{"name":"Test","content":"foo"}→ 200; record echoed back withis_public=true(single-user default)PATCH /api/v1/system_prompts/i/{id}with{"name":"Test2"}→ record updatedDELETE /api/v1/system_prompts/i/{id}→ record gone; subsequentGETreturns 404INSERT OR IGNORE).Backend — multi-user
4. Run with multi-user enabled and create two non-admin users (alice, bob) plus an admin.
5. As alice:
POSTa private prompt → it is owned by alice,is_public=false.6. As bob:
GET /api/v1/system_prompts/→ sees the 7 system defaults plus only public prompts; does not see alice's private prompt.7. As bob:
PATCHorDELETEof alice's prompt id → 403 (or 404 if he does not even know the id, depending on path).8. As alice:
PATCH … {"is_public": true}→ flips her prompt to shared; bob's nextGETnow includes it.9. As admin:
GETreturns all prompts (including alice/bob's privates), and PATCH/DELETE on any prompt succeeds.Frontend
10. Install at least one Text-LLM model (e.g. via the Model Manager starter list).
11. In the Generate tab, click the Expand Prompt button (sparkle icon) over a non-empty prompt.
12. The popover now shows a System Prompt combobox above the model picker — pick one of the seeded defaults, pick a model, click Expand. The positive prompt is replaced;
Ctrl+Zrestores the original.13. Click the pencil icon next to the system-prompt combobox → management modal opens.
- Single-user: Create / Edit / Delete buttons appear on every row.
- Multi-user (non-admin): Edit / Delete only appear on prompts you own; system/shared prompts show a badge instead.
- Multi-user: opening the form for an owned prompt shows the Share with everyone checkbox.
14. Reload the browser → the previously picked system prompt and model are still selected (Redux persistence).
15. Lint + test suite:
pnpm lint && pnpm test:no-watchfrominvokeai/frontend/web/(1 pre-existing flaky timer test innavigation-api.test.tsis unrelated).Merge Plan
This PR adds a new SQLite migration (32) and a new persisted Redux slice. Notes for reviewers / mergers:
system_promptstable withuser_id+is_publicalready in the schema and seeds 7 default rows owned bysystem(public). For dev databases that already ran an earlier revision of this migration without the multi-user columns, the migration also runsPRAGMA table_infoandALTER TABLE … ADD COLUMNto backfill the columns — safe and idempotent.expandPromptslice has amigratestep (sets_version: 1if missing) — an old persisted state without this slice simply starts from initial state, no breaking change for users.Checklist
What's Newcopy (if doing a release after this PR)