Flexibles KI Prompt System #48

Merged
Lars merged 56 commits from develop into main 2026-03-26 14:49:48 +01:00
2 changed files with 78 additions and 15 deletions
Showing only changes of commit 15bd6cddeb - Show all commits

View File

@ -814,7 +814,7 @@ async def execute_unified_prompt(
content = json.dumps(content, ensure_ascii=False) content = json.dumps(content, ensure_ascii=False)
# Prepare metadata with resolved placeholders and descriptions # Prepare metadata with resolved placeholders and descriptions
from placeholder_resolver import get_placeholder_catalog from placeholder_resolver import get_placeholder_catalog, get_placeholder_example_values
metadata = { metadata = {
'prompt_type': result['type'], 'prompt_type': result['type'],
@ -825,10 +825,21 @@ async def execute_unified_prompt(
if result.get('debug'): if result.get('debug'):
catalog = get_placeholder_catalog(profile_id) catalog = get_placeholder_catalog(profile_id)
# Get full untruncated values from placeholder resolver
full_values = get_placeholder_example_values(profile_id)
# Remove {{ }} wrappers
cleaned_values = {
key.replace('{{', '').replace('}}', ''): value
for key, value in full_values.items()
}
if result['type'] == 'base': if result['type'] == 'base':
# Base prompt: single set of placeholders # Base prompt: single set of placeholders
resolved = result['debug'].get('resolved_placeholders', {}) resolved_keys = result['debug'].get('resolved_placeholders', {}).keys()
for key, value in resolved.items(): for key in resolved_keys:
# Get full untruncated value
value = cleaned_values.get(key, result['debug']['resolved_placeholders'].get(key, ''))
# Find description in catalog # Find description in catalog
desc = None desc = None
for cat_items in catalog.values(): for cat_items in catalog.values():
@ -847,15 +858,18 @@ async def execute_unified_prompt(
stages_debug = result['debug'].get('stages', []) stages_debug = result['debug'].get('stages', [])
for stage_debug in stages_debug: for stage_debug in stages_debug:
for prompt_debug in stage_debug.get('prompts', []): for prompt_debug in stage_debug.get('prompts', []):
resolved = {} resolved_keys = []
# Check both direct and ref_debug # Check both direct and ref_debug
if 'resolved_placeholders' in prompt_debug: if 'resolved_placeholders' in prompt_debug:
resolved = prompt_debug['resolved_placeholders'] resolved_keys = prompt_debug['resolved_placeholders'].keys()
elif 'ref_debug' in prompt_debug and 'resolved_placeholders' in prompt_debug['ref_debug']: elif 'ref_debug' in prompt_debug and 'resolved_placeholders' in prompt_debug['ref_debug']:
resolved = prompt_debug['ref_debug']['resolved_placeholders'] resolved_keys = prompt_debug['ref_debug']['resolved_placeholders'].keys()
for key, value in resolved.items(): for key in resolved_keys:
if key not in metadata['placeholders']: # Avoid duplicates if key not in metadata['placeholders']: # Avoid duplicates
# Get full untruncated value
value = cleaned_values.get(key, '')
# Find description in catalog # Find description in catalog
desc = None desc = None
for cat_items in catalog.values(): for cat_items in catalog.values():

View File

@ -15,15 +15,23 @@ const SLUG_LABELS = {
function InsightCard({ ins, onDelete, defaultOpen=false, prompts=[] }) { function InsightCard({ ins, onDelete, defaultOpen=false, prompts=[] }) {
const [open, setOpen] = useState(defaultOpen) const [open, setOpen] = useState(defaultOpen)
const [showValues, setShowValues] = useState(false)
// Parse metadata early to determine showOnlyValues
const metadataRaw = ins.metadata ? (typeof ins.metadata === 'string' ? JSON.parse(ins.metadata) : ins.metadata) : null
const isBasePrompt = metadataRaw?.prompt_type === 'base'
const isJsonOutput = ins.content && (ins.content.trim().startsWith('{') || ins.content.trim().startsWith('['))
const placeholdersRaw = metadataRaw?.placeholders || {}
const showOnlyValues = isBasePrompt && isJsonOutput && Object.keys(placeholdersRaw).length > 0
const [showValues, setShowValues] = useState(showOnlyValues) // Auto-expand for base prompts with JSON
// Find matching prompt to get display_name // Find matching prompt to get display_name
const prompt = prompts.find(p => p.slug === ins.scope) const prompt = prompts.find(p => p.slug === ins.scope)
const displayName = prompt?.display_name || SLUG_LABELS[ins.scope] || ins.scope const displayName = prompt?.display_name || SLUG_LABELS[ins.scope] || ins.scope
// Parse metadata if available // Use already-parsed metadata
const metadata = ins.metadata ? (typeof ins.metadata === 'string' ? JSON.parse(ins.metadata) : ins.metadata) : null const metadata = metadataRaw
const placeholders = metadata?.placeholders || {} const placeholders = placeholdersRaw
const placeholderCount = Object.keys(placeholders).length const placeholderCount = Object.keys(placeholders).length
return ( return (
@ -46,7 +54,31 @@ function InsightCard({ ins, onDelete, defaultOpen=false, prompts=[] }) {
</div> </div>
{open && ( {open && (
<> <>
<Markdown text={ins.content}/> {/* For base prompts with JSON: Only show value table */}
{showOnlyValues && (
<div style={{ padding: '12px 16px', background: 'var(--surface)', borderRadius: 8, marginBottom: 12 }}>
<div style={{ fontSize: 11, color: 'var(--text3)', marginBottom: 8 }}>
Basis-Prompt Rohdaten (JSON-Struktur für technische Nutzung)
</div>
<details style={{ fontSize: 11, color: 'var(--text3)' }}>
<summary style={{ cursor: 'pointer' }}>Technische Daten anzeigen</summary>
<pre style={{
marginTop: 8,
padding: 8,
background: 'var(--bg)',
borderRadius: 4,
overflow: 'auto',
fontSize: 10,
fontFamily: 'monospace'
}}>
{ins.content}
</pre>
</details>
</div>
)}
{/* For other prompts: Show full content */}
{!showOnlyValues && <Markdown text={ins.content}/>}
{/* Value Table */} {/* Value Table */}
{placeholderCount > 0 && ( {placeholderCount > 0 && (
@ -80,13 +112,30 @@ function InsightCard({ ins, onDelete, defaultOpen=false, prompts=[] }) {
<tbody> <tbody>
{Object.entries(placeholders).map(([key, data]) => ( {Object.entries(placeholders).map(([key, data]) => (
<tr key={key} style={{ borderBottom: '1px solid var(--border)' }}> <tr key={key} style={{ borderBottom: '1px solid var(--border)' }}>
<td style={{ padding: '6px 8px', fontFamily: 'monospace', color: 'var(--accent)' }}> <td style={{
padding: '6px 8px',
fontFamily: 'monospace',
color: 'var(--accent)',
whiteSpace: 'nowrap',
verticalAlign: 'top'
}}>
{key} {key}
</td> </td>
<td style={{ padding: '6px 8px', fontFamily: 'monospace' }}> <td style={{
padding: '6px 8px',
fontFamily: 'monospace',
wordBreak: 'break-word',
maxWidth: '400px',
verticalAlign: 'top'
}}>
{data.value} {data.value}
</td> </td>
<td style={{ padding: '6px 8px', color: 'var(--text3)', fontSize: 10 }}> <td style={{
padding: '6px 8px',
color: 'var(--text3)',
fontSize: 10,
verticalAlign: 'top'
}}>
{data.description || '—'} {data.description || '—'}
</td> </td>
</tr> </tr>