@@ -7,6 +7,67 @@ import {
77 generatePresentationText ,
88 generateChartData
99} from '@/lib/mistral' ;
10+ import OpenAI from 'openai' ;
11+
12+ // Fallback to Nebius/Qwen when Gemini fails
13+ const nebiusClient = new OpenAI ( {
14+ baseURL : 'https://api.tokenfactory.nebius.com/v1/' ,
15+ apiKey : process . env . NEBIUS_API_KEY ,
16+ } ) ;
17+
18+ async function generateWithNebius ( prompt : string , pageCount : number ) {
19+ console . log ( '🔄 Using Nebius/Qwen as fallback...' ) ;
20+
21+ const completion = await nebiusClient . chat . completions . create ( {
22+ model : 'Qwen/Qwen3-235B-A22B-Instruct-2507' ,
23+ messages : [
24+ {
25+ role : 'system' ,
26+ content : `You are a professional presentation designer. Generate exactly ${ pageCount } slides for a presentation.
27+ Return a JSON array of slides with this structure:
28+ [
29+ {
30+ "slideNumber": 1,
31+ "type": "title",
32+ "title": "Main Title",
33+ "subtitle": "Subtitle text",
34+ "content": "Brief description",
35+ "bulletPoints": ["Point 1", "Point 2", "Point 3"]
36+ }
37+ ]
38+ Slide types: title, content, bullets, stats, comparison, timeline, conclusion
39+ Make content professional, engaging, and visually focused.`
40+ } ,
41+ {
42+ role : 'user' ,
43+ content : `Create a ${ pageCount } -slide presentation about: ${ prompt } `
44+ }
45+ ] ,
46+ max_tokens : 4000 ,
47+ temperature : 0.7 ,
48+ } ) ;
49+
50+ const content = completion . choices [ 0 ] ?. message ?. content || '[]' ;
51+
52+ // Extract JSON from response
53+ const jsonMatch = content . match ( / \[ [ \s \S ] * \] / ) ;
54+ if ( jsonMatch ) {
55+ try {
56+ return JSON . parse ( jsonMatch [ 0 ] ) ;
57+ } catch ( e ) {
58+ console . error ( 'Failed to parse Nebius response:' , e ) ;
59+ }
60+ }
61+
62+ // Fallback: create basic slides
63+ return Array . from ( { length : pageCount } , ( _ , i ) => ( {
64+ slideNumber : i + 1 ,
65+ type : i === 0 ? 'title' : i === pageCount - 1 ? 'conclusion' : 'content' ,
66+ title : i === 0 ? prompt : `Slide ${ i + 1 } ` ,
67+ content : 'Content for this slide' ,
68+ bulletPoints : [ 'Key point 1' , 'Key point 2' , 'Key point 3' ]
69+ } ) ) ;
70+ }
1071
1172
1273export async function POST ( request : Request ) {
@@ -23,14 +84,20 @@ export async function POST(request: Request) {
2384
2485 console . log ( '📝 Step 1: Generating slide text content...' ) ;
2586
26- // Step 1: Generate text content (choice between Gemini or Mistral)
87+ // Step 1: Generate text content with fallback
2788 let outlines ;
28- if ( useGemini ) {
29- console . log ( 'Using Gemini 2.0 Flash for text generation' ) ;
30- outlines = await generatePresentationOutline ( { prompt, pageCount } ) ;
31- } else {
32- console . log ( 'Using Mistral Large for text generation' ) ;
33- outlines = await generatePresentationText ( prompt , pageCount ) ;
89+ try {
90+ if ( useGemini ) {
91+ console . log ( 'Using Gemini 2.0 Flash for text generation' ) ;
92+ outlines = await generatePresentationOutline ( { prompt, pageCount } ) ;
93+ } else {
94+ console . log ( 'Using Mistral Large for text generation' ) ;
95+ outlines = await generatePresentationText ( prompt , pageCount ) ;
96+ }
97+ } catch ( geminiError : any ) {
98+ console . error ( '⚠️ Gemini failed:' , geminiError . message ) ;
99+ console . log ( '🔄 Falling back to Nebius/Qwen...' ) ;
100+ outlines = await generateWithNebius ( prompt , pageCount ) ;
34101 }
35102
36103 console . log ( `✅ Generated ${ outlines . length } slides` ) ;
0 commit comments