Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
node_modules
npm-debug.log
Dockerfile
docker-compose.yml
.vscode
.git
.gitignore
.env
32 changes: 25 additions & 7 deletions controllers/predictController.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@

// controllers/predictController.js
const { getModelInfo, predict } = require("../services/tfModelService");
const Prediction = require("../model/Prediction");

function health(req, res) {
res.json({
Expand Down Expand Up @@ -60,20 +62,36 @@ async function doPredict(req, res) {
});
}

const prediction = await predict(features);
// Ejecutar el modelo
const predictionValue = await predict(features);
const latencyMs = Date.now() - start;
const timestamp = new Date().toISOString();
const timestamp = new Date();

// De momento sin MongoDB → predictionId null
res.status(201).json({
predictionId: null,
prediction,
// Guardar en Mongo solo campos válidos
const responsePred = await Prediction.create({
features,
prediction: predictionValue,
timestamp,
latencyMs,
featureCount: meta.featureCount,
scalerVersion: meta.scalerVersion || "v1",
createdAt: timestamp,
predictGroup: "predict"
});

res.status(201).json({
predictionId: responsePred._id,
prediction: predictionValue,
timestamp: timestamp.toISOString(),
latencyMs
});

} catch (err) {
console.error("Error en /predict:", err);
res.status(500).json({ error: "Internal error" });

res.status(500).json({
error: "Internal error",
});
}
}

Expand Down
26 changes: 26 additions & 0 deletions dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Imagen base con Node 22
FROM node:22-slim


# Directorio de trabajo dentro del contenedor
WORKDIR /usr/src/app


# Copiamos primero manifiestos para cachear dependencias
COPY package*.json ./


# Instalamos dependencias de producción
RUN npm ci --omit=dev


# Copiamos el resto del código (incluye /model)
COPY . .


# El servicio escucha en 3002
EXPOSE 3002


# Comando de arranque
CMD ["node", "server.js"]
23 changes: 23 additions & 0 deletions model/Prediction.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//model/prediction.js
'use strict'

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const PredictionSchema = new Schema({
source: String,
timestamp: { type: Date, default: Date.now },
latencyMs: Number,
features: [Number],
prediction: Number,

featureCount: Number,
scalerVersion: String,
createdAt: { type: Date, default: Date.now },
targetDate: Date,
dailyValues: [Number],


});

module.exports = mongoose.model("Prediction", PredictionSchema);
11 changes: 7 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@
},
"author": "Iren Lorenzo Fonseca",
"license": "ISC",
"bugs": {
},
"bugs": {},
"dependencies": {
"@tensorflow/tfjs": "^4.22.0",
"@tensorflow/tfjs-backend-wasm": "^4.22.0",
"express": "^5.1.0"
"dotenv": "^17.2.3",
"express": "^5.1.0",
"mongodb": "^7.0.0",
"mongoose": "^9.0.1"
}
}
}

24 changes: 19 additions & 5 deletions server.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,46 @@
// server.js
// Entry point del servicio PREDICT
require("dotenv").config();

const express = require("express");
const app = express();
const path = require("path");
const mongoose = require("mongoose");
const predictRoutes = require("./routes/predictRoutes");
const { initModel } = require("./services/tfModelService");

const PORT = process.env.PORT || 3002;
const MONGO_URI = process.env.MONGO_URI;

// conectar a Mongo
mongoose
.connect(MONGO_URI)
.then(() => {console.log("MongoDB conectado (PREDICT)")})
.catch((err) => {
console.error("Error al conectar MongoDB:", err);
process.exit(1);
});

const app = express();
app.use(express.json());

// Servir la carpeta del modelo TFJS (model/model.json + pesos)
const modelDir = path.resolve(__dirname, "model");
app.use("/model", express.static(modelDir));

// Rutas del servicio PREDICT

app.use("/", predictRoutes);

// Arranque del servidor + carga del modelo

app.listen(PORT, async () => {
const serverUrl = `http://localhost:${PORT}`;
console.log(`[PREDICT] Servicio escuchando en ${serverUrl}`);
console.log(`PREDICT escuchando en ${serverUrl}`);

try {
// Inicializa el modelo predictivo
await initModel(serverUrl);
console.log(" Modelo predictivo cargado correctamente.");
} catch (err) {
console.error("Error al inicializar modelo:", err);
console.error("Error al inicializar el modelo predictivo:", err);
process.exit(1);
}
});
2 changes: 1 addition & 1 deletion services/tfModelService.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,4 @@ module.exports = {
initModel,
getModelInfo,
predict
};
};