initial commit
This commit is contained in:
122
server/index.ts
Normal file
122
server/index.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
// Very small mock server for local testing. In production replace with your AI provider call.
|
||||
import express from "express";
|
||||
import bodyParser from "body-parser";
|
||||
import cors from "cors";
|
||||
import { Ollama } from "ollama";
|
||||
import { XMLParser } from "fast-xml-parser";
|
||||
|
||||
const app = express();
|
||||
app.use(cors());
|
||||
app.use(bodyParser.json());
|
||||
|
||||
const ollama = new Ollama({
|
||||
host: "http://192.168.1.85:11434",
|
||||
});
|
||||
|
||||
type ChatMessage = {
|
||||
content: string;
|
||||
role: "user" | "assistant";
|
||||
};
|
||||
const xmlParser = new XMLParser();
|
||||
const systemPrompt: string = `You are an educated chef that likes to make nutritional meals.
|
||||
You have an oven, stove top, pots, pans, microwave, grill, nice knives and some other kitchen tools at your disposal.
|
||||
You do all of your grocery shopping at Trader Joe's, but on rare occasions can go to a different store for a few ingredients.
|
||||
You like to be able to cook from start to finish in 45 minutes, but up to 60 is acceptable.
|
||||
You largely prefer to use chicken as your protein but beef and turkey are acceptable on occasion.
|
||||
You are a strong believer that the microwave should not be used to cook vegetables.
|
||||
When returning meals, you must put each meal into an XML structure such as
|
||||
<meal><name></name><ingredients><name></name><quantity></quantity></ingredients><steps></steps></meal>
|
||||
The steps should be detailed enough for a beginner chef to follow along as if they have never cooked this meal before.
|
||||
Each meal needs to be able to feed all people involved rather than each person getting a meal. If you are asked for 3 meals you should only return 3 meals.
|
||||
When combining all ingredients into a shopping list, you must again use an XML
|
||||
Your entire response needs to be XML <xml><meals></meals><shoppingList></shoppingList></xml>, nothing more, nothing less. If you consider returning something other than XML, you need to stop and start over.
|
||||
|
||||
`;
|
||||
app.post("/api/mealplan", async (req, res) => {
|
||||
const prompt: string = req.body.prompt || "";
|
||||
const existingMessages: ChatMessage[] = req.body.existingMessages || [];
|
||||
let fullPrompt = prompt;
|
||||
|
||||
if (!prompt) {
|
||||
return res.sendStatus(400);
|
||||
}
|
||||
|
||||
if (existingMessages.length === 0) {
|
||||
fullPrompt = systemPrompt + fullPrompt;
|
||||
}
|
||||
|
||||
const callOllama = () => {
|
||||
return ollama.chat({
|
||||
model: "llama3.2:3b",
|
||||
think: false, //"low",
|
||||
stream: false,
|
||||
messages: [
|
||||
{
|
||||
content: fullPrompt,
|
||||
role: "user",
|
||||
},
|
||||
],
|
||||
});
|
||||
};
|
||||
|
||||
const ollamaResponse = await callOllama();
|
||||
|
||||
let mealsAndList: any = null;
|
||||
try {
|
||||
mealsAndList = xmlParser.parse(ollamaResponse.message.content ?? "");
|
||||
} catch (e) {
|
||||
console.log("Failed on first call", e);
|
||||
}
|
||||
|
||||
if (!mealsAndList) {
|
||||
const ollamaResponse2 = await callOllama();
|
||||
try {
|
||||
mealsAndList = xmlParser.parse(ollamaResponse2.message.content ?? "");
|
||||
} catch (e) {
|
||||
console.log("Failed on second call", e);
|
||||
return res.sendStatus(500);
|
||||
}
|
||||
}
|
||||
|
||||
if (mealsAndList.xml) {
|
||||
mealsAndList = mealsAndList.xml;
|
||||
}
|
||||
|
||||
let mealPlan: any[] = [];
|
||||
if (
|
||||
mealsAndList.meals &&
|
||||
Array.isArray(mealsAndList.meals) &&
|
||||
mealsAndList.meals.length > 0
|
||||
) {
|
||||
mealPlan = mealsAndList.meals;
|
||||
} else if (
|
||||
mealsAndList.meals &&
|
||||
mealsAndList.meals.meal &&
|
||||
Array.isArray(mealsAndList.meals.meal) &&
|
||||
mealsAndList.meals.meal.length > 0
|
||||
) {
|
||||
console.log(mealsAndList.meals.meal);
|
||||
mealPlan = mealsAndList.meals.meal;
|
||||
} else if (mealsAndList.meals) {
|
||||
mealPlan = mealsAndList.meals;
|
||||
}
|
||||
|
||||
let shoppingList: any[] = [];
|
||||
if (mealsAndList.shoppingList) {
|
||||
shoppingList = mealsAndList.shoppingList;
|
||||
}
|
||||
|
||||
// simple deterministic mock response: you should replace this with a real AI call.
|
||||
const mock = {
|
||||
mealPlan,
|
||||
groceryList: shoppingList,
|
||||
};
|
||||
// simulate some delay
|
||||
await new Promise((r) => setTimeout(r, 600));
|
||||
res.json(mock);
|
||||
});
|
||||
|
||||
const port = 3000;
|
||||
app.listen(port, () =>
|
||||
console.log(`Server listening on http://localhost:${port}`),
|
||||
);
|
||||
Reference in New Issue
Block a user