ai rec works
as intended, needs refinments
This commit is contained in:
1 parent
0183a8ea6a
commit
3ab9908588
21 files changed
+1579
-696
No files matched your search
@@ -0,0 +1,120 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { getDatabase } from "@/lib/database";
|
||||
|
||||
export async function POST(req: Request) {
|
||||
try {
|
||||
const { userId } = 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 }
|
||||
);
|
||||
}
|
||||
|
||||
// Construct prompt for Ollama
|
||||
const prompt = `
|
||||
You are a professional fitness trainer and nutritionist.
|
||||
Generate a detailed daily recommendation for a user with the following profile:
|
||||
- Height: ${profile.height} cm
|
||||
- Weight: ${profile.weight} kg
|
||||
- Age: ${profile.age}
|
||||
- Gender: ${profile.gender}
|
||||
- Goal: ${profile.fitnessGoals.join(", ")}
|
||||
- Activity Level: ${profile.activityLevel}
|
||||
- Medical Conditions: ${profile.medicalConditions || "None"}
|
||||
- Injuries: ${profile.injuries || "None"}
|
||||
|
||||
Please provide the response in the following JSON format ONLY, no other text. Do not use markdown formatting or code blocks:
|
||||
{
|
||||
"recommendationText": "General advice and motivation for today.",
|
||||
"activityPlan": "Detailed workout or activity plan for today.",
|
||||
"dietPlan": "Detailed meal plan for today."
|
||||
}
|
||||
`;
|
||||
|
||||
// Call Ollama
|
||||
const ollamaResponse = await fetch("http://localhost:11434/api/generate", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: "gemma3:latest", // Make sure this model is pulled
|
||||
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 AI service" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
|
||||
const aiData = await ollamaResponse.json();
|
||||
console.log("Raw AI Response:", aiData.response);
|
||||
|
||||
let parsedResponse;
|
||||
try {
|
||||
// Helper to clean up the response
|
||||
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) {
|
||||
// Fallback if model doesn't return perfect JSON despite instruction
|
||||
console.error("Failed to parse AI response:", aiData.response);
|
||||
return NextResponse.json(
|
||||
{ error: "Invalid response format from AI model" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
|
||||
// Save to database
|
||||
const recommendation = await db.createRecommendation({
|
||||
id: crypto.randomUUID(),
|
||||
userId,
|
||||
fitnessProfileId: profile.userId, // Using userId as ID for now since it's 1:1
|
||||
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 }
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user