Skip to main content

Context Enrichment

Context enrichment is an optional feature that asks users clarifying questions to improve future recommendations.

Purpose

When enabled, the AI asks up to 2 questions about:

  • Missing budget information
  • Unknown recipient
  • Unclear occasion
  • Recipient age (if known but not specified)
  • Recipient interests/hobbies

Configuration

Location: app/chat/config.ts

export const chatConfig = {
contextEnrichment: {
enabled: false, // Toggle feature on/off
maxQuestions: 2, // Maximum questions per response
requireProducts: true, // Only ask after showing products
minConfidence: 0.6 // Only ask if context extraction confident
}
};

When Questions Are Asked

Question Types

Budget Questions

Asked when: !giftContext.budget || (!budget.min && !budget.max)

Estonian:

  • "Mis on sinu eelarve?"
  • "Milline hinnavahemik sulle sobib?"

English:

  • "What's your budget?"
  • "What price range works for you?"

Recipient Questions

Asked when: !giftContext.recipient

Estonian:

  • "Kellele see kingitus on?"
  • "Kellele mõtled seda kinki?"

English:

  • "Who is this gift for?"
  • "Who are you shopping for?"

Occasion Questions

Asked when: !giftContext.occasion

Estonian:

  • "Mis puhul otsid kingitust?"
  • "Mis sündmuseks see on?"

English:

  • "What's the occasion?"
  • "What event is this for?"

Age Questions

Asked when: context.recipient && !context.recipientAge

Estonian:

  • "Kui vana [saaja] on?"
  • "Milline on [saaja] vanus?"

English:

  • "How old is [recipient]?"
  • "What's [recipient]'s age?"

Interest Questions

Asked when: context.recipient && !context.interests

Estonian:

  • "Millised on [saaja] huvid või hobid?"
  • "Mida [saaja] armastab teha?"

English:

  • "What are [recipient]'s interests or hobbies?"
  • "What does [recipient] enjoy doing?"

Formatting Strategies

Natural Integration

Et saaksin anda veelgi paremaid soovitusi:
- Mis on sinu eelarve?
- Kellele see kingitus on?

Conversational Flow

Mõned küsimused, et sind veel paremini aidata:
- Kellele mõtled kingitust teha?
- Mis on ligikaudne hinnavahemik?

Seamless Continuation

...sobivad suurepäraselt! Kui vana laps on ja millised 
on tema huvid?

Smart Rules

Don't Ask Redundant Questions

// User said: "kingitus emale eelarve 30€"

// GOOD: Skip budget and recipient
// Only ask: occasion or interests

// BAD: Ask budget again
// Annoying and shows poor understanding

Priority Order

  1. Budget - Most impactful for filtering
  2. Recipient - Affects product selection
  3. Occasion - Helps with appropriateness
  4. Age - Refines recommendations
  5. Interests - Fine-tuning

Question Limit

Configuration: maxQuestions: 2

const questions = [];

if (!budget) questions.push(budgetQuestion);
if (!recipient) questions.push(recipientQuestion);
if (!occasion) questions.push(occasionQuestion);

// Take only first 2
return questions.slice(0, 2);

Rationale:

  • 1 question: May not be enough
  • 2 questions: Optimal for UX
  • 3+ questions: Feels like interrogation

Implementation

Location: app/api/chat/utils/context-enrichment-questions.ts

export function generateEnrichmentQuestions(
giftContext: GiftContext,
userMessage: string,
language: 'et' | 'en'
): string | null {
const questions: string[] = [];

// Budget
if (!giftContext.budget?.max && !giftContext.budget?.min) {
questions.push(
language === 'et'
? 'Mis on sinu eelarve?'
: 'What\'s your budget?'
);
}

// Recipient
if (!giftContext.recipient) {
questions.push(
language === 'et'
? 'Kellele see kingitus on?'
: 'Who is this gift for?'
);
}

// Occasion (if recipient known but not occasion)
if (giftContext.recipient && !giftContext.occasion) {
questions.push(
language === 'et'
? 'Mis puhul otsid kingitust?'
: 'What\'s the occasion?'
);
}

// Limit to maxQuestions
const limited = questions.slice(0, chatConfig.contextEnrichment.maxQuestions);

if (limited.length === 0) return null;

// Format naturally
const intro = language === 'et'
? 'Et saaksin anda veelgi paremaid soovitusi:'
: 'To help me give even better recommendations:';

return `\n\n${intro}\n${limited.map(q => `- ${q}`).join('\n')}`;
}

Example Scenarios

Scenario 1: Complete Context

Input:

User: "raamat emale sünnipäevaks kuni 25 eurot"
Context: {
productType: "Raamat",
recipient: "ema",
occasion: "sünnipäev",
budget: { max: 25 }
}

Enrichment: null (all context available)

Scenario 2: Missing Budget

Input:

User: "kingitus sõbrale"
Context: {
recipient: "sõber",
occasion: null,
budget: null
}

Enrichment:

Et saaksin anda veelgi paremaid soovitusi:
- Mis on sinu eelarve?
- Mis puhul otsid kingitust?

Scenario 3: Vague Query

Input:

User: "näita kingitusi"
Context: {
recipient: null,
occasion: null,
budget: null,
confidence: 0.4 // Too low!
}

Enrichment: null (confidence < 0.6)

Strategy: Don't ask questions when context extraction failed - might be off-topic

Validation

export function getContextEnrichmentQuestions(
giftContext: GiftContext,
userMessage: string,
hasProducts: boolean
): string | null {
const config = chatConfig.contextEnrichment;

// Check 1: Feature enabled?
if (!config.enabled) return null;

// Check 2: Products required and available?
if (config.requireProducts && !hasProducts) return null;

// Check 3: Confidence threshold met?
if ((giftContext.confidence ?? 0) < config.minConfidence) {
return null;
}

// Generate questions
return generateEnrichmentQuestions(
giftContext,
userMessage,
giftContext.language || 'et'
);
}

User Experience

Good UX

[3 product cards shown]

"Siin on suurepärased valikud! Et saaksin sind veelgi
paremini aidata:
- Mis on sinu eelarve?
- Mis puhul otsid kingitust?"

Why good:

  • Value delivered first (products)
  • Questions are optional
  • Natural continuation

Poor UX

[No products - search failed]

"Ei leidnud midagi. Palun vasta küsimustele:
- Mis on sinu eelarve?
- Kellele kingitus on?
- Mis puhul otsid?"

Why poor:

  • No value delivered
  • Feels like interrogation
  • Too many questions

Testing

describe('Context Enrichment', () => {
it('asks about missing budget', () => {
const context = { recipient: 'ema', budget: null };
const questions = generateEnrichmentQuestions(context, '', 'et');

expect(questions).toContain('eelarve');
});

it('respects maxQuestions limit', () => {
const context = {
recipient: null,
budget: null,
occasion: null
};

const questions = generateEnrichmentQuestions(context, '', 'et');
const questionCount = (questions?.match(/- /g) || []).length;

expect(questionCount).toBeLessThanOrEqual(2);
});

it('skips when confidence low', () => {
const context = { confidence: 0.3 }; // &lt; 0.6
const questions = getContextEnrichmentQuestions(context, '', true);

expect(questions).toBeNull();
});
});