spb/vquant Public MIT
VibeQuant — AI-powered institutional-grade financial intelligence platform.
TypeScript 84.3%
Python 11.7%
JavaScript 1.6%
CSS 1.5%
HTML 0.7%
1/*2 * =============================================================================3 * VibeQuant (vquant) — AI-Powered Financial Intelligence Platform4 * -----------------------------------------------------------------------------5 * File: server/services/slidesConverterService.ts6 *7 * Author: Simon-Pierre Boucher8 * Contact: contact@spboucher.ai9 * Website: https://www.spboucher.ai10 * Demo: https://www.vquant.ai11 * License: MIT (see LICENSE)12 *13 * Copyright © 2026 Simon-Pierre Boucher. All rights reserved.14 * =============================================================================15 */1617import axios from 'axios';1819const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY;20const ANTHROPIC_API_URL = 'https://api.anthropic.com/v1/messages';2122interface SlideConversionOptions {23 question: string;24 answer: string;25 author: string;26 company?: string;27}2829export interface SlideStructure {30 title: string;31 subtitle: string;32 author: string;33 company: string;34 date: string;35 slides: Array<{36 type: 'title' | 'content' | 'two-column' | 'stats' | 'conclusion';37 title?: string;38 content?: string[];39 leftColumn?: string[];40 rightColumn?: string[];41 stats?: Array<{ label: string; value: string; trend?: string }>;42 background?: string;43 }>;44}4546export async function convertToSlidesStructure(options: SlideConversionOptions): Promise<SlideStructure> {47 if (!ANTHROPIC_API_KEY) {48 throw new Error('ANTHROPIC_API_KEY not configured');49 }5051 const today = new Date().toLocaleDateString('fr-FR', {52 year: 'numeric',53 month: 'long',54 day: 'numeric'55 });5657 const systemPrompt = `You are a presentation structure expert. Analyze financial analysis content and extract a clean JSON structure for slides.5859YOUR TASK: Return ONLY a JSON object (no explanations) with this structure:60{61 "title": "Main title from question",62 "subtitle": "Brief subtitle",63 "slides": [64 {"type": "content", "title": "Slide title", "content": ["Bullet 1", "Bullet 2"]},65 {"type": "stats", "title": "Key Metrics", "stats": [{"label": "Revenue", "value": "$35.1B", "trend": "+94%"}]},66 {"type": "two-column", "title": "Comparison", "leftColumn": ["Point 1"], "rightColumn": ["Point A"]},67 {"type": "conclusion", "title": "Conclusion", "content": ["Summary point"]}68 ]69}7071RULES:72- Max 10 slides total73- Each content slide: max 5 bullets74- Extract key numbers for stats slides75- One main idea per slide76- Use type "stats" for financial metrics77- Use type "two-column" for comparisons78- Last slide must be type "conclusion"`;7980 const userPrompt = `Analyze and structure this for slides. Return ONLY JSON:8182QUESTION: ${options.question}8384ANALYSIS:85${options.answer.substring(0, 40000)}8687Extract the main points, key metrics, and insights. Structure into 6-10 slides.`;8889 try {90 console.log('[SlidesConverter] Structuring content with Claude...');9192 const response = await axios.post(93 ANTHROPIC_API_URL,94 {95 model: 'claude-opus-4-8',96 max_tokens: 8000,97 temperature: 0.1,98 messages: [{ role: 'user', content: userPrompt }],99 system: systemPrompt100 },101 {102 headers: {103 'x-api-key': ANTHROPIC_API_KEY,104 'anthropic-version': '2023-06-01',105 'content-type': 'application/json'106 },107 timeout: 60000108 }109 );110111 let jsonText = response.data.content[0].text;112 jsonText = jsonText.replace(/^```json\n?/gm, '').replace(/\n?```$/gm, '').trim();113114 const structure = JSON.parse(jsonText) as SlideStructure;115116 // Add metadata117 structure.author = options.author;118 structure.company = options.company || 'VQuant';119 structure.date = today;120121 console.log('[SlidesConverter] ✓ Structure created:', structure.slides.length, 'slides');122 return structure;123124 } catch (error) {125 console.error('[SlidesConverter] Error:', error);126 throw new Error(`Failed to structure slides: ${(error as Error).message}`);127 }128}129