Files
Sauci/apps/admin/src/lib/ai/tools/topics.ts
T
2026-01-01 12:48:31 +00:00

70 lines
2.9 KiB
TypeScript

// =============================================================================
// Topic Extraction Functions
// Extract topics from packs for categorization
// =============================================================================
import { getOpenAI, getModel } from '../client';
import type { TopicExtractionResult } from '../types';
/**
* Extract topics from a pack based on its name, description, and questions
*/
export async function extractTopicsFromPack(
packName: string,
packDescription: string | null,
questions: string[],
existingTopics: { id: string; name: string }[]
): Promise<TopicExtractionResult> {
const openai = getOpenAI();
const existingTopicNames = existingTopics.map(t => t.name);
const existingTopicsJson = JSON.stringify(existingTopics);
const prompt = `Analyze the following question pack and extract relevant topics/kinks/interests that describe its content.
PACK NAME: "${packName}"
${packDescription ? `PACK DESCRIPTION: "${packDescription}"` : ''}
QUESTIONS IN THIS PACK:
${questions.map((q, i) => `${i + 1}. ${q}`).join('\n')}
EXISTING TOPICS IN THE SYSTEM (prefer matching these when appropriate):
${existingTopicNames.length > 0 ? existingTopicNames.join(', ') : 'None yet'}
EXISTING TOPICS WITH IDs:
${existingTopicsJson}
INSTRUCTIONS:
1. Identify 1-5 topics that best describe this pack's content
2. Topics should be specific kinks, interests, or themes (e.g., "Bondage", "Exhibitionism", "Voyeurism", "Role Play", "Sensory Play", "Oral", "Anal", "Communication", "Romance", "Adventure")
3. ALWAYS prefer matching an existing topic if one fits - use the EXACT name and include the existingTopicId
4. Only suggest a new topic if nothing in the existing list is appropriate
5. Topic names should be title case (e.g., "Bondage" not "bondage")
6. Keep topics broad enough to be reusable across packs
Return a JSON object with:
- topics: Array of objects with:
- name: The topic name (use exact existing name if matching)
- isNew: false if matching an existing topic, true if suggesting a new one
- existingTopicId: The ID of the existing topic if isNew is false (from the EXISTING TOPICS WITH IDs list)
- reasoning: Brief explanation of why these topics were chosen`;
const response = await openai.chat.completions.create({
model: getModel('fix'),
messages: [
{
role: 'system',
content: 'You are a content categorization expert for a couples intimacy app. You analyze question packs and identify relevant topics, kinks, and themes. Always prefer matching existing topics when possible. Always respond with valid JSON only.',
},
{ role: 'user', content: prompt },
],
response_format: { type: 'json_object' },
temperature: 0.3,
});
const content = response.choices[0].message.content;
if (!content) throw new Error('No content generated');
return JSON.parse(content) as TopicExtractionResult;
}