import { NextResponse } from "next/server"; import { getDatabase } from "@/lib/database"; import { buildAIContext } from "@/lib/ai/ai-context"; import { buildEnhancedPrompt, buildBasicPrompt } from "@/lib/ai/prompt-builder"; export async function POST(req: Request) { try { const { userId, useExternalModel } = await req.json(); if (!userId) { return NextResponse.json({ error: "User ID is required" }, { status: 400 }); } const db = await getDatabase(); // Fetch fitness profile const profile = await db.getFitnessProfileByUserId(userId); if (!profile) { return NextResponse.json( { error: "Fitness profile not found for this user" }, { status: 404 } ); } // Build AI context with goals and recommendations let prompt: string; try { const context = await buildAIContext(userId); prompt = buildEnhancedPrompt(context); console.log('Using enhanced AI context with goals and history'); } catch (error) { // Fallback to basic prompt if context building fails console.warn('Failed to build AI context, using basic prompt:', error); prompt = buildBasicPrompt(profile); } let parsedResponse; if (useExternalModel) { // Use DeepSeek AI const deepseekApiKey = process.env.DEEPSEEK_API_KEY; if (!deepseekApiKey) { return NextResponse.json( { error: "DeepSeek API key not configured" }, { status: 500 } ); } console.log("Using DeepSeek AI model..."); const deepseekResponse = await fetch("https://api.deepseek.com/v1/chat/completions", { method: "POST", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${deepseekApiKey}`, }, body: JSON.stringify({ model: "deepseek-chat", messages: [ { role: "system", content: "You are a professional fitness trainer and nutritionist. Always respond with valid JSON only, no markdown or code blocks." }, { role: "user", content: prompt } ], temperature: 0.7, max_tokens: 1000, }), }); if (!deepseekResponse.ok) { const errorText = await deepseekResponse.text(); console.error("DeepSeek API error:", errorText); return NextResponse.json( { error: "Failed to generate recommendation from DeepSeek AI" }, { status: 500 } ); } const deepseekData = await deepseekResponse.json(); console.log("Raw DeepSeek Response:", deepseekData); try { const content = deepseekData.choices[0].message.content; let cleanResponse = content.trim(); // Remove markdown code blocks if present if (cleanResponse.startsWith("```json")) { cleanResponse = cleanResponse.replace(/^```json\s*/, "").replace(/\s*```$/, ""); } else if (cleanResponse.startsWith("```")) { cleanResponse = cleanResponse.replace(/^```\s*/, "").replace(/\s*```$/, ""); } // Find the first '{' and last '}' to extract the JSON object const firstBrace = cleanResponse.indexOf("{"); const lastBrace = cleanResponse.lastIndexOf("}"); if (firstBrace !== -1 && lastBrace !== -1) { cleanResponse = cleanResponse.substring(firstBrace, lastBrace + 1); } parsedResponse = JSON.parse(cleanResponse); } catch (e) { console.error("Failed to parse DeepSeek response:", deepseekData); return NextResponse.json( { error: "Invalid response format from DeepSeek AI" }, { status: 500 } ); } } else { // Use local Ollama console.log("Using local Ollama model..."); const ollamaResponse = await fetch("http://localhost:11434/api/generate", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ model: "gemma3:latest", prompt: prompt, stream: false, format: "json", }), }); if (!ollamaResponse.ok) { console.error("Ollama API error:", await ollamaResponse.text()); return NextResponse.json( { error: "Failed to generate recommendation from Ollama" }, { status: 500 } ); } const aiData = await ollamaResponse.json(); console.log("Raw Ollama Response:", aiData.response); try { let cleanResponse = aiData.response.trim(); // Remove markdown code blocks if present if (cleanResponse.startsWith("```json")) { cleanResponse = cleanResponse.replace(/^```json\s*/, "").replace(/\s*```$/, ""); } else if (cleanResponse.startsWith("```")) { cleanResponse = cleanResponse.replace(/^```\s*/, "").replace(/\s*```$/, ""); } // Find the first '{' and last '}' to extract the JSON object const firstBrace = cleanResponse.indexOf("{"); const lastBrace = cleanResponse.lastIndexOf("}"); if (firstBrace !== -1 && lastBrace !== -1) { cleanResponse = cleanResponse.substring(firstBrace, lastBrace + 1); } parsedResponse = JSON.parse(cleanResponse); } catch (e) { console.error("Failed to parse Ollama response:", aiData.response); return NextResponse.json( { error: "Invalid response format from Ollama" }, { status: 500 } ); } } // Save to database const recommendation = await db.createRecommendation({ id: crypto.randomUUID(), userId, fitnessProfileId: profile.userId, type: 'ai_plan', content: parsedResponse.recommendationText, activityPlan: parsedResponse.activityPlan, dietPlan: parsedResponse.dietPlan, status: 'pending' }); return NextResponse.json(recommendation); } catch (error) { console.error("Error generating recommendation:", error); return NextResponse.json( { error: "Internal server error" }, { status: 500 } ); } }