Spaces:
Running
Running
File size: 3,950 Bytes
d0b546b e1d8498 a3cd373 e1d8498 a3cd373 e1d8498 a3cd373 e1d8498 a3cd373 e1d8498 a3cd373 e1d8498 a3cd373 e1d8498 a3cd373 e1d8498 a3cd373 e1d8498 a3cd373 e1d8498 a3cd373 e1d8498 a3cd373 e1d8498 a3cd373 e1d8498 a3cd373 e1d8498 a3cd373 e1d8498 a3cd373 e1d8498 a3cd373 e1d8498 a3cd373 e1d8498 a3cd373 e1d8498 a3cd373 e1d8498 a3cd373 e1d8498 a3cd373 e1d8498 a3cd373 e1d8498 a3cd373 e1d8498 a3cd373 e1d8498 a3cd373 e1d8498 a3cd373 e1d8498 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | "use strict";
/**
* LiteLLM Proxy Management Client
* Wraps LiteLLM admin API for dynamic model registration.
*/
const axios = require("axios");
const { logger } = require("./logger");
const LITELLM_BASE_URL = process.env.LITELLM_BASE_URL || "http://litellm:4000";
const LITELLM_MASTER_KEY = process.env.LITELLM_MASTER_KEY || "sk-gateway-master-key";
const client = axios.create({
baseURL: LITELLM_BASE_URL,
timeout: 15000,
headers: {
Authorization: "Bearer " + LITELLM_MASTER_KEY,
"Content-Type": "application/json",
},
});
async function registerModel(model) {
const payload = {
model_name: model.name,
litellm_params: buildLitellmParams(model),
model_info: {
id: model.id,
description: model.description || "",
model_type: model.modelType || "chat",
},
};
logger.info("Registering model with LiteLLM", { modelName: model.name });
const response = await client.post("/model/new", payload);
const litellmId =
(response.data && response.data.model_info && response.data.model_info.id) ||
(response.data && response.data.id) ||
null;
if (!litellmId) {
logger.warn(
"LiteLLM /model/new response contained no recognisable model ID. " +
"Falling back to internal UUID. " +
"Deregistration may fail silently leaving a ghost model in LiteLLM.",
{
modelName: model.name,
internalId: model.id,
responseTopLevelKeys: response.data ? Object.keys(response.data) : [],
responseData: response.data,
}
);
return model.id;
}
logger.info("Model registered in LiteLLM", { modelName: model.name, litellmId: litellmId });
return litellmId;
}
async function deregisterModel(litellmId) {
if (!litellmId) return;
try {
await client.post("/model/delete", {
id: litellmId,
model_id: litellmId,
});
logger.info("Model deregistered from LiteLLM", { litellmId: litellmId });
} catch (err) {
logger.warn("Could not deregister model from LiteLLM", {
litellmId: litellmId,
httpStatus: err.response && err.response.status,
error: err.message,
});
}
}
async function listLitellmModels() {
const response = await client.get("/model/info");
return (response.data && response.data.data) || response.data || [];
}
async function updateModel(oldLitellmId, model) {
await deregisterModel(oldLitellmId);
return registerModel(model);
}
async function healthCheck() {
const response = await client.get("/health/liveliness");
return response.data;
}
async function testModel(modelName, options) {
if (!options) { options = {}; }
const start = Date.now();
const messages =
options.messages && options.messages.length > 0
? options.messages
: [{ role: "user", content: options.prompt || "Say OK in one word." }];
try {
const response = await client.post(
"/v1/chat/completions",
{
model: modelName,
messages: messages,
max_tokens: 256,
stream: false,
},
{ timeout: 30000 }
);
return {
success: true,
latencyMs: Date.now() - start,
response: response.data,
};
} catch (err) {
return {
success: false,
latencyMs: Date.now() - start,
error: (err.response && err.response.data) || err.message,
};
}
}
function buildLitellmParams(model) {
const params = {
model: model.litellmModel,
};
if (model.apiBase) {
params.api_base = model.apiBase;
}
const key = model._apiKey || model.apiKey;
if (key && key !== "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" && key.trim() !== "") {
params.api_key = key.trim();
} else {
params.api_key = "none";
}
return params;
}
module.exports = {
registerModel: registerModel,
deregisterModel: deregisterModel,
listLitellmModels: listLitellmModels,
updateModel: updateModel,
healthCheck: healthCheck,
testModel: testModel,
}; |