Callbacks enable the retrieval of a model’s status when it transitions to either ‘complete’ or ‘error’. This is accomplished by sending a POST request to the specified URL, with the payload structured as follows:
{
"name": "my_model",
"version": 1,
"active": true,
"predictor_id": 123,
"project_name": "mindsdb",
"predictor_created_at": "Fri, 09 Sep 2023 11:50:27 GMT",
"old_status": "training",
"new_status": "complete",
"changed_at": "Fri, 09 Sep 2023 11:59:00 GMT"
}
Let’s break down each key:
name
: name of the model
version
: version of the trained model
active
: indicates whether the newly trained model is active
predictor_id
: unique identifier for the trained model
project_name
: the name of the project in which the model was created
predictor_created_at
: time at which the model was created
old_status
: status the model had prior to receiving the new_status
new_status
: current status of the model
changed_at
: time when the model’s status transitioned from old_status
to new_status
Please note that this feature works only in MinsdDB Cloud and only for MindsDB Starter users.
Callbacks API
Callback API provides information on how to add, get, edit, and delete callbacks.
Add a Callback
This is the Request format:
POST /cloud/callback/model_status
Content-Type: application/json
{
// url will be called on model status change
"url": "https://my.endpoint.com/",
"filter": {
"model_name": ".*",
"project_name": ".*"
},
"attempt": {
"count": 5,
"http_timeout": 10,
"interval": 10
}
}
And this is the Response format:
Status: 200 OK
Content-Type: application/json
{
// id of created 'callback'
"id": 123456
}
Only the url
key is required in the Request. All others are optional.
url
- this represents the address that will be utilized to send a POST request, containing detailed information about the model’s status
filter
- this is used to restrict the triggering of callbacks:
model_name
- python-style regular expression used to filter the names of models that trigger a callback
project_name
- python-style regular expression used to filter the names of projects
attempt
- this outlines the configuration of the number and frequency of attempts to send callbacks
count
- maximum number of attempts
interval
- represents the interval between failed attempts
http_timeout
- time allotted to wait for a successful response.
Get a Callback
This is the Request format:
GET /cloud/callback/model_status
And this is the Response format:
Status: 200 OK
Content-Type: application/json
[{
"id": 123456,
"created_at": "Fri, 09 Sep 2023 11:50:27 GMT",
"url": "https://my.endpoint.com/"
}]
Edit a Callback
This is the Request format:
PUT /cloud/callback/model_status/<id>
Content-Type: application/json
{
// new callback url
"url": "https://my.endpoint.com/"
}
And this is the Response format:
Delete a Callback
This is the Request format:
DELETE /cloud/callback/model_status/<id>
And this is the Response format:
Handling Callbacks using Python SDK
Below is an example of using callbacks with the home_rentals
model. Be sure that your endpoint HOSTNAME
is accessible from the internet.
Please note that localhost
is not accessible from the internet - you can make localhost
accessible via multiple ways, like ngrok tunnel.
import requests
import mindsdb_sdk
from flask import Flask, request
MODEL_NAME = 'home_rentals'
HOSTNAME = 'my.endpoint.com'
PORT = 5000
app = Flask(__name__)
con = mindsdb_sdk.connect(
'https://cloud.mindsdb.com',
login='name@email.com',
password='password'
)
# add callback
con.api.session.post(
'https://cloud.mindsdb.com/cloud/callback/model_status',
json={
'url': f'https://{HOSTNAME}:{PORT}/'
}
)
@app.route('/', methods=['POST'])
def callback():
data = request.json
if data['version'] == 1:
# let retrain the model
model = con.models.get(MODEL_NAME)
model.retrain()
elif data['version'] == 2:
# let make a prediciton
model = con.models.get(MODEL_NAME)
prediction = model.predict({"sqft": 1000})
print(prediction)
return '', 200
# connect to database
db = con.databases.create(
'example_db',
engine='postgres',
connection_args={
"user": "demo_user",
"password": "demo_password",
"host": "samples.mindsdb.com",
"port": "5432",
"database": "demo"
}
)
# train base model
model = con.models.create(
MODEL_NAME,
predict='rental_price',
query=db.tables.get('demo_data.home_rentals')
)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=PORT)
Handling Callbacks using JavaScript SDK
Below is an example of using callbacks with the home_rentals
model. Be sure that the callback HOSTNAME
is accessible from MindsDB Cloud.
import express from 'express';
import axios from 'axios';
import * as MindsDB from 'mindsdb-js-sdk';
const mdb = MindsDB.default.default;
const app = express();
const PORT = 54321;
const MODEL_NAME = 'home_rentals';
const HOSTNAME = 'my.endpoint.com';
// Create an Axios instance with interceptors for timeout and error handling
const customAxios = axios.create();
customAxios.interceptors.request.use(config => {
config.timeout = 120000; // Set a request timeout of 120 seconds
return config;
});
customAxios.interceptors.response.use(
response => response,
error => {
console.error('Axios Error:', error.message);
return Promise.reject(error);
}
);
// Connect to MindsDB Cloud
try {
await mdb.connect({
host: 'https://cloud.mindsdb.com',
user: 'name@email.com',
password: 'password',
httpClient: customAxios,
});
} catch (error) {
console.error('MindsDB Cloud Connection Error:', error);
process.exit(1);
}
// Connect to the database
await mdb.Databases.createDatabase('example_db', 'postgres', {
user: 'demo_user',
password: 'demo_password',
host: 'samples.mindsdb.com',
port: '5432',
database: 'demo',
});
// Express Middleware to parse JSON requests
app.use(express.json());
// Define an Express route to handle model status updates
app.post('/model-status', async (req, res) => {
const data = req.body;
if (data.new_status !== 'complete') {
console.error(`Error! Got model status: ${data.new_status}`);
return res.status(400).send({ error: 'Invalid model status' });
}
const trained_model_version = data.version;
console.log(`Model training completed, model version=${trained_model_version}`);
if (trained_model_version === 1) {
// Base model finished training, let's retrain it
let model = await mdb.Models.getModel(MODEL_NAME, 'mindsdb');
model.retrain();
} else if (trained_model_version === 2) {
// Model retraining finished, let's make a prediction
let model = await mdb.Models.getModel(MODEL_NAME, 'mindsdb');
let prediction = await model.query({
where: [
'sqft = 823',
'location = "good"',
'neighborhood = "downtown"',
'days_on_market = 10',
],
});
console.log(`Prediction: ${JSON.stringify(prediction)}`);
}
res.sendStatus(200);
});
// Start the Express server
app.listen(PORT, () => {
console.log(`Express server started on port ${PORT}`);
});
// Add a callback to notify MindsDB Cloud about the endpoint
try {
await customAxios.post('https://cloud.mindsdb.com/cloud/callback/model_status', {
url: `https://${HOSTNAME}:${PORT}/model-status`,
});
} catch (error) {
console.error('Callback Error:', error);
}
// Train a model
try {
await mdb.Models.trainModel(MODEL_NAME, 'rental_price', 'mindsdb', {
integration: 'example_db',
select: 'SELECT * FROM demo_data.home_rentals',
});
} catch (error) {
console.error('Model Training Error:', error);
}