Impulse AI Docs
Intern dokumentasjon
Hopp til innhold

AI Prompt DSL

Teknisk referanse for prompt-arkitekturen som styrer all AI-generert tekst i Impulse AI. Denne DSL-en sikrer konsistent kvalitet pa tvers av alle dataprodukter.

For workload-oversikt, modellvalg og kostnader, se AI Pipeline.

Arkitekturoversikt

heading.anchorLabel
apps/api/src/ai/shared/
├── conventions.ts # Lag 1: Globale regler (tone, grammatikk, skrivestil)
├── prompt-builder.ts # Lag 2: PromptStructure DSL + buildPrompt()
├── concept-types.ts # Lag 3: Formula/Bottling field definitions
├── person-context.ts # Personalisering (opt-in)
└── schemas/ # Zod-skjemaer for strukturert output

Tre lag med tydelig ansvar og endringsrisiko:

LagFilAnsvarEndringsrisiko
Conventionsconventions.tsProduktregler som gjelder alle workloadsHoy — endring treffer ALT
Prompt Builderprompt-builder.tsStrukturert XML-format og convention-injeksjonMedium — endrer prompt-struktur
Field Definitionsconcept-types.tsPer-felt Formula/Bottling-spesifikasjonerVarierer — Formula er kritisk, Style er trygt

Lag 1: Conventions

heading.anchorLabel

Globale regler definert i conventions.ts. Noen injiseres alltid, andre er opt-in.

Alltid injisert

heading.anchorLabel

GRAMMAR_RULES injiseres automatisk i alle prompts via buildPrompt(), uavhengig av opt-in:

  • Native-sprak (ikke oversatt engelsk)
  • Pronomen-agreement (singular/plural)
  • Grammatisk korrekthet (kjonn, bøyning)
  • Naturlig setningskonstruksjon
  • Perspektivkonsistens — alltid andreperson (“du”/“you”), aldri tredjeperson om brukeren

Opt-in konvensjoner

heading.anchorLabel
KonvensjonFlagg i PromptStructureHva den injiserer
ToneuseStandardTone: truePersona (varm venn), stemme, do/avoid
VocabularyvocabularyContext: 'clearing' | 'realization' | 'general'Godkjente verb, banned ord
SafetyuseSafety: trueKrise-keyword-deteksjon, eskaleringsregler
AcknowledgmentuseStandardAcknowledgment: trueBanned fraser, variasjonskrav
Writing StyleAuto nar opt-in er aktivAnti-AI-speak (banned: “delve”, “tapestry”, “landscape” etc.)

Workload-dekning

heading.anchorLabel

Alle brukervendte workloads bor ha useStandardTone + vocabularyContext. Workloads med ra brukerinput bor ha useSafety:

WorkloadToneVocabularySafetyBegrunnelse
Classification (enrichment)xxxRa brukerinput
Classification (analytical)Intern analyse, ikke brukervennlig tekst
Check-inxxxRa brukerinput
Step GuidancexxAI-generert input, ikke ra tekst
Session SummaryxxAI-generert input
NarrativexxAnalytisk, ikke ra tekst
PulsexxAnalytisk
DistillationxxAnalytisk

Lag 2: Prompt Builder

heading.anchorLabel

buildPrompt() tar en PromptStructure og produserer ferdig system-prompt i XML-format.

PromptStructure

heading.anchorLabel
interface PromptStructure {
// Pakrevd
role: PromptRole; // Hvem AI-en ER
objective: string; // Hva som skal genereres
// Valgfritt
personContext?: PersonContext; // Hvem den snakker TIL (navn, kjonn, alder)
context?: string; // Bakgrunn + FieldDefinitions + NEVER-blokk
instructions?: string[]; // Steg-for-steg
examples?: PromptExample[]; // Few-shot laering
constraints?: PromptConstraints; // Lengde, sprak, format
// Convention opt-in
useStandardTone?: boolean;
useStandardAcknowledgment?: boolean;
vocabularyContext?: 'clearing' | 'realization' | 'general';
useSafety?: boolean;
useNaturalWritingStyle?: boolean;
}

Seksjonrekkefølge i generert prompt

heading.anchorLabel

buildPrompt() produserer seksjoner i denne rekkefølgen (optimalisert for Anthropic):

<role>Hvem AI-en er</role>
<person>Hvem den snakker til (opt-in personalisering)</person>
<context>Bakgrunn + FieldDefinitions + NEVER-blokk</context>
<objective>Klar malbeskrivelse</objective>
<instructions>Steg-for-steg</instructions>
<examples>Few-shot laering</examples>
<constraints>Lengde, sprak, format</constraints>
<conventions>
<tone_standard>...</tone_standard> <!-- opt-in -->
<vocabulary_standard>...</vocabulary_standard> <!-- opt-in -->
<writing_style>...</writing_style> <!-- auto -->
<grammar_quality>...</grammar_quality> <!-- ALLTID -->
</conventions>

PersonContext

heading.anchorLabel

Injiseres mellom <role> og <context> for a prime modellen med mottakeren. Kun tilgjengelig nar ai_personalization_enabled = true pa profilen.

<person>
<name>Jan Fredrik</name>
<gender>male</gender>
<age>30s</age>
<name-usage>Use their name naturally and sparingly</name-usage>
</person>

Hentet via fetchPersonContext() i person-context.ts — eneste sted som leser profildata for AI.

Lag 3: Field Definitions (Formula/Bottling)

heading.anchorLabel

Definert i concept-types.ts. Brukes for a spesifisere hvert output-felt i en workload.

FieldDefinition-struktur

heading.anchorLabel
interface FieldDefinition {
name: string; // Feltnavn (brukes i prompt)
concept: Concept; // Formula -- LAST, forretningskritisk
style?: Style; // Bottling -- fritt tunable
variation?: Variation; // Freshness -- for gjentatte sesjoner
languageRequired?: boolean; // Default: true
}

Tre lag med ulik endringsrisiko

heading.anchorLabel
LagInterfaceEndringsrisikoFormaal
FormulaConceptHoy — forretningskritisk moatHva feltet betyr
BottlingStyleLavt — trygt a iterereHvordan det leveres
VariationVariationLavt — dynamiskFreshness pa tvers av sesjoner

Concept (Formula)

heading.anchorLabel
interface Concept {
essence: string; // En-setnings formaal
requiredElements: string[]; // MA vaere med i output
forbiddenDrift: string[]; // AI-en far IKKE ga hit
}

forbiddenDrift er der workload-spesifikke perspektivregler horer hjemme. Eksempel fra narrative.ts:

forbiddenDrift: [
// Generiske drifter
'Generic motivational text',
// Produktavgrensning
'Situational language -- that is the Pulse product\'s job',
// Perspektivregel (forsterker global GRAMMAR_RULES)
'Third-person language about the user -- always use "you"/"du"',
]

Style (Bottling)

heading.anchorLabel
interface Style {
delivery: string[]; // Leveringsinstruksjoner
}

Variation (Freshness)

heading.anchorLabel

Brukes av workloads der brukeren ser samme steg-type flere ganger (f.eks. sesjonsveiledning):

interface Variation {
openingApproaches: string[]; // 4 roterende apninger
deduplicationInstruction: string; // "Aldri apne likt to ganger"
}

Block builders

heading.anchorLabel

Hjelpefunksjoner som kompilerer FieldDefinitions til prompt-tekst:

FunksjonBrukTokens
buildCompactFieldBlock(field)Standard — kompakt format~40% faerre
buildFullFieldBlock(field)Concept + Style + VariationFull rendering
buildMultiFieldContext(fields[])Flere felt, separertVanligst
buildNeverBlock(items[])Delt forbidden-listeFor cross-field regler
buildLanguageFieldsDirective(fields, target)SprakhaandhevelsePer-felt

NEVER-blokker

heading.anchorLabel

Hver workload definerer en NEVER-array med forbudte monstre som gjelder alle output-felt. Disse injiseres i <context> via buildNeverBlock().

Noen regler er universelle (gjentar seg i flere workloads):

RegelNarrativePulseDistillSummaryClassif
No generic motivationxxx
No therapy-speakxxxx
No corporate wellnessxxx
No advice/“you should”xxx
No metrics/countingxxx
No passive framingxxx

Produktspesifikke regler er unike per workload og avgrenser ansvarsomrader:

  • Narrative: “No situational language — that is the Pulse product’s job”
  • Pulse: “No trajectory language — that is the Narrative product’s job”
  • Distillation: “No trajectory language — the Narrative product handles trajectories”

Legge til ny workload

heading.anchorLabel

1. Definer Zod-schema

heading.anchorLabel
// I schemas/index.ts eller egen fil
const MyOutputSchema = z.object({
title: z.string(),
body: z.string(),
});

2. Definer FieldDefinitions

heading.anchorLabel
const MY_CONCEPTS: Record<string, FieldDefinition> = {
title: {
name: 'TITLE',
languageRequired: true,
concept: {
essence: 'Kort beskrivelse av feltets formaal',
requiredElements: ['Element som MA vaere med'],
forbiddenDrift: ['Ting AI-en IKKE far gjore'],
},
style: {
delivery: ['Hvordan AI-en bor levere dette'],
},
},
};

3. Bygg PromptStructure

heading.anchorLabel
function getMyPromptConfig(
languageCode?: LanguageCode,
personContext?: PersonContext,
): PromptStructure {
return {
role: {
identity: 'You are...',
expertise: ['...'],
tone: ['Warm', 'Direct'],
},
personContext,
objective: 'Generate...',
context: `${buildMultiFieldContext(Object.values(MY_CONCEPTS))}
${buildNeverBlock(MY_NEVER)}`,
instructions: [
buildLanguageFieldsDirective(Object.values(MY_CONCEPTS), 'detected_language'),
],
constraints: {
output: { maxLength: 500, lengthUnit: 'tokens', format: 'json' },
language: languageCode,
},
// Convention opt-in -- alle brukervendte workloads bor ha disse:
useStandardTone: true,
vocabularyContext: 'general',
// useSafety: true, // Legg til om workloaden mottar ra brukerinput
metadata: { category: 'my_workload', version: '1.0.0' },
};
}

Sjekkliste for nye workloads

heading.anchorLabel
  • useStandardTone: true (med mindre ren analytisk workload)
  • vocabularyContext satt (clearing/realization/general)
  • useSafety: true om workloaden mottar ra brukerinput
  • personContext sendt inn (fra fetchPersonContext())
  • forbiddenDrift inkluderer perspektivregel (andreperson)
  • NEVER-blokk definert med produktavgrensning
  • Zod-schema validerer all output

Endringsprinsipper

heading.anchorLabel

Trygt a endre

heading.anchorLabel
  • Style.delivery — leveringsinstruksjoner, tone, tilnaerming
  • Variation.openingApproaches — rotasjonsalternativer
  • NEVER-elementer — legge til nye forbud
  • Convention opt-in — aktivere flere konvensjoner

Krever review

heading.anchorLabel
  • Concept.essence — endrer feltets kjernebetydning
  • Concept.requiredElements — endrer hva som MA vaere med
  • GRAMMAR_RULES — treffer alle workloads
  • TONE / VOCABULARY — treffer alle opt-in workloads
  • Fjerne forbiddenDrift-elementer uten a forstaa hvorfor de ble lagt til
  • Endre buildPrompt() seksjonrekkefølge uten Anthropic-testing
  • Fjerne convention opt-in fra eksisterende workloads