Files
lcbp3/specs/200-fullstacks/237-unified-prompt-management-ux-ui/data-model.md
T
admin 67da186672
CI / CD Pipeline / build (push) Failing after 3m23s
CI / CD Pipeline / deploy (push) Has been skipped
feat(ai): implement unified prompt management UX/UI (ADR-037)
- Add context config endpoints (GET/PUT /api/ai/prompts/:type/:version/context-config)
- Add execution profile endpoints (CRUD /api/ai/execution-profiles)
- Add sandbox RAG Prep endpoint (POST /api/ai/admin/sandbox/rag-prep)
- Create Prompt Management UI with multi-type support
- Add ContextConfigEditor, PromptEditor, RuntimeParametersPanel components
- Add SandboxTabs for 3-step workflow (OCR, Extract, RAG Prep)
- Add database deltas for ai_execution_profiles and additional prompt types
- Update quickstart.md with production backend URLs
- Add comprehensive test coverage for new features
2026-06-14 19:55:43 +07:00

8.0 KiB

Data Model: Unified Prompt Management UX/UI

Feature: 237-unified-prompt-management-ux-ui
Date: 2026-06-14
Purpose: Define data entities, relationships, and validation rules

Entities

AiPrompt

Represents a prompt version with template, context config, and activation status.

Table: ai_prompts (extends existing ADR-029 schema)

Column Type Constraints Description
id INT AUTO_INCREMENT PRIMARY KEY Internal ID (not exposed)
public_id UUID UNIQUE, NOT NULL Public identifier (ADR-019)
prompt_type VARCHAR(50) NOT NULL, INDEX Prompt type: ocr_extraction, rag_query_prompt, rag_prep_prompt, classification_prompt
version_number INT NOT NULL, INDEX Version number (per prompt_type)
template TEXT NOT NULL Prompt template with placeholders
context_config JSON NULL Context configuration (filter, pageSize, language)
is_active TINYINT(1) NOT NULL, DEFAULT 0 Active flag (1 = active)
manual_note VARCHAR(500) NULL Manual annotation
created_by INT NOT NULL, FK → users.id Creator user ID
created_at TIMESTAMP NOT NULL, DEFAULT CURRENT_TIMESTAMP Creation timestamp
updated_at TIMESTAMP NOT NULL, DEFAULT CURRENT_TIMESTAMP ON UPDATE Update timestamp

Unique Constraint: (prompt_type, version_number) - ensures version numbers are unique per type

Validation Rules:

  • prompt_type must be one of: ocr_extraction, rag_query_prompt, rag_prep_prompt, classification_prompt
  • template must contain required placeholders based on prompt_type:
    • ocr_extraction: {{ocr_text}}, {{master_data_context}}
    • rag_query_prompt: {{query}}, {{context}}
    • rag_prep_prompt: {{text}}
    • classification_prompt: {{document_text}}
  • context_config JSON structure:
    {
      "filter": {
        "projectId": "uuid|null",
        "contractId": "uuid|null"
      },
      "pageSize": 3,
      "language": "th",
      "outputLanguage": "th"
    }
    
  • is_active can only be true for one version per prompt_type at a time

Relationships:

  • created_byusers.id (many-to-one)

AiExecutionProfile

Represents runtime parameters for AI model behavior (global per profile, not per prompt version).

Table: ai_execution_profiles (new table per ADR-036)

Column Type Constraints Description
id INT AUTO_INCREMENT PRIMARY KEY Internal ID (not exposed)
public_id UUID UNIQUE, NOT NULL Public identifier (ADR-019)
profile_name VARCHAR(100) NOT NULL, UNIQUE Profile name (e.g., "default", "fast", "accurate")
temperature DECIMAL(3,2) NOT NULL, DEFAULT 0.7 Temperature (0.0 - 1.0)
top_p DECIMAL(3,2) NOT NULL, DEFAULT 0.9 Top-P (0.0 - 1.0)
repeat_penalty DECIMAL(3,2) NOT NULL, DEFAULT 1.0 Repeat penalty (1.0 - 2.0)
max_tokens INT NOT NULL, DEFAULT 2048 Max tokens (1 - 8192)
ctx_size INT NOT NULL, DEFAULT 4096 Context size (1 - 16384)
keep_alive INT NOT NULL, DEFAULT 300 Keep-alive seconds (0 - 3600)
is_default TINYINT(1) NOT NULL, DEFAULT 0 Default profile flag
created_by INT NOT NULL, FK → users.id Creator user ID
created_at TIMESTAMP NOT NULL, DEFAULT CURRENT_TIMESTAMP Creation timestamp
updated_at TIMESTAMP NOT NULL, DEFAULT CURRENT_TIMESTAMP ON UPDATE Update timestamp

Validation Rules:

  • temperature must be between 0.0 and 1.0
  • top_p must be between 0.0 and 1.0
  • repeat_penalty must be between 1.0 and 2.0
  • max_tokens must be between 1 and 8192
  • ctx_size must be between 1 and 16384
  • keep_alive must be between 0 and 3600
  • is_default can only be true for one profile at a time

Relationships:

  • created_byusers.id (many-to-one)

SandboxJob

Represents a sandbox test execution (transient, stored in Redis, not in database).

Redis Key: sandbox:job:{jobId} (TTL: 1 hour)

Structure:

{
  "jobId": "uuid",
  "jobType": "ocr|ai-extract|rag-prep",
  "status": "pending|processing|completed|failed",
  "result": {
    "ocrText": "string|null",
    "extractedMetadata": "object|null",
    "ragChunks": "array|null",
    "ragVectors": "array|null",
    "error": "string|null"
  },
  "createdAt": "timestamp",
  "completedAt": "timestamp|null"
}

Validation Rules:

  • jobType must be one of: ocr, ai-extract, rag-prep
  • status transitions: pending → processing → completed/failed
  • result structure depends on jobType:
    • ocr: { ocrText, error }
    • ai-extract: { extractedMetadata, error }
    • rag-prep: { ragChunks, ragVectors, error }

Relationships: None (transient data)


Entity Relationships

users (1) ──────── (∞) ai_prompts
  │
  └── (1) ──────── (∞) ai_execution_profiles

ai_prompts (independent from ai_execution_profiles)
  - Runtime parameters are global (ai_execution_profiles)
  - Context config is per version (ai_prompts.context_config)

Indexes

ai_prompts

  • idx_prompt_type_version: (prompt_type, version_number) - UNIQUE
  • idx_prompt_type_active: (prompt_type, is_active) - for finding active version
  • idx_public_id: (public_id) - UNIQUE

ai_execution_profiles

  • idx_profile_name: (profile_name) - UNIQUE
  • idx_is_default: (is_default) - for finding default profile
  • idx_public_id: (public_id) - UNIQUE

Database Schema Changes (ADR-009)

New Table: ai_execution_profiles

CREATE TABLE ai_execution_profiles (
  id INT AUTO_INCREMENT PRIMARY KEY,
  public_id UUID NOT NULL,
  profile_name VARCHAR(100) NOT NULL UNIQUE,
  temperature DECIMAL(3,2) NOT NULL DEFAULT 0.7,
  top_p DECIMAL(3,2) NOT NULL DEFAULT 0.9,
  repeat_penalty DECIMAL(3,2) NOT NULL DEFAULT 1.0,
  max_tokens INT NOT NULL DEFAULT 2048,
  ctx_size INT NOT NULL DEFAULT 4096,
  keep_alive INT NOT NULL DEFAULT 300,
  is_default TINYINT(1) NOT NULL DEFAULT 0,
  created_by INT NOT NULL,
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE,
  UNIQUE KEY uk_public_id (public_id),
  KEY idx_is_default (is_default),
  CONSTRAINT fk_execution_profile_user FOREIGN KEY (created_by) REFERENCES users(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

Seed Data: ai_execution_profiles

INSERT INTO ai_execution_profiles (public_id, profile_name, temperature, top_p, repeat_penalty, max_tokens, ctx_size, keep_alive, is_default, created_by)
VALUES 
  (UUID(), 'default', 0.7, 0.9, 1.0, 2048, 4096, 300, 1, 1),
  (UUID(), 'fast', 0.5, 0.8, 1.0, 1024, 2048, 0, 0, 1),
  (UUID(), 'accurate', 0.8, 0.95, 1.1, 4096, 8192, 600, 0, 1);

Seed Data: ai_prompts (additional types)

-- RAG Query Prompt
INSERT INTO ai_prompts (public_id, prompt_type, version_number, template, context_config, is_active, created_by)
VALUES (
  UUID(),
  'rag_query_prompt',
  1,
  'Answer the following question based on the provided context:\n\nQuestion: {{query}}\n\nContext: {{context}}\n\nAnswer:',
  '{"filter": null, "language": "th"}',
  1,
  1
);

-- RAG Prep Prompt
INSERT INTO ai_prompts (public_id, prompt_type, version_number, template, context_config, is_active, created_by)
VALUES (
  UUID(),
  'rag_prep_prompt',
  1,
  'Split the following text into semantic chunks for RAG indexing:\n\nText: {{text}}\n\nOutput JSON array of chunks with "text" and "summary" fields.',
  '{"filter": null, "language": "th"}',
  1,
  1
);

-- Classification Prompt
INSERT INTO ai_prompts (public_id, prompt_type, version_number, template, context_config, is_active, created_by)
VALUES (
  UUID(),
  'classification_prompt',
  1,
  'Classify the following document into one of these categories: Correspondence, RFA, Transmittal, Circulation, Shop Drawing, Contract Drawing\n\nDocument: {{document_text}}\n\nOutput JSON with "category" and "confidence" fields.',
  '{"filter": null, "language": "th"}',
  1,
  1
);