mirror of
https://github.com/jjbrunton/Sauci.git
synced 2026-10-31 18:19:43 +00:00
70 lines
2.9 KiB
TypeScript
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;
|
|
}
|