mirror of
https://github.com/yacy/yacy_search_server.git
synced 2026-10-25 05:54:15 +00:00
distinguish between usage columns and feature columns, added tooling
This commit is contained in:
1 parent
576d3b2657
commit
0887619a1f
2 files changed
+44
-59
No files matched your search
+42
-59
@@ -17,10 +17,12 @@
|
||||
event.preventDefault();
|
||||
event.returnValue = "Model downloads are still running. Please wait until they finish.";
|
||||
};
|
||||
const PRODUCTION_MODEL_TOTAL_COLUMNS = 13;
|
||||
const PRODUCTION_MODEL_TOTAL_COLUMNS = 14;
|
||||
const PRODUCTION_MODEL_MODEL_COLUMN_INDEX = 1;
|
||||
const PRODUCTION_MODEL_FEATURE_COLUMN_START = 5;
|
||||
const PRODUCTION_MODEL_FEATURE_COLUMN_END = 11;
|
||||
const PRODUCTION_MODEL_USAGE_COLUMN_START = 5;
|
||||
const PRODUCTION_MODEL_USAGE_COLUMN_END = 10; // including
|
||||
const PRODUCTION_MODEL_FEATURE_COLUMN_START = 11;
|
||||
const PRODUCTION_MODEL_FEATURE_COLUMN_END = 12; // including
|
||||
const PRODUCTION_MODEL_ACTION_COLUMN_INDEX = PRODUCTION_MODEL_TOTAL_COLUMNS - 1;
|
||||
const PRODUCTION_MODEL_COLUMN_NAMES = [
|
||||
"service",
|
||||
@@ -34,6 +36,7 @@
|
||||
"qa-generation",
|
||||
"classification",
|
||||
"tldr-shortener",
|
||||
"tooling",
|
||||
"vision"
|
||||
];
|
||||
const PRODUCTION_MODEL_SUBMIT_URL = "LLMSelection_p.html";
|
||||
@@ -79,10 +82,6 @@
|
||||
return response.json();
|
||||
}
|
||||
|
||||
async function fetchOllamaModels(hoststub) {
|
||||
return fetchJsonOrThrow(`${hoststub}/api/tags`);
|
||||
}
|
||||
|
||||
async function deleteOllamaModel(hoststub, modelName) {
|
||||
const response = await fetch(`${hoststub}/api/delete`, {
|
||||
method: "DELETE",
|
||||
@@ -117,14 +116,8 @@
|
||||
return payload;
|
||||
}
|
||||
|
||||
async function fetchOpenAICompatibleModels(hoststub) {
|
||||
return fetchJsonOrThrow(`${hoststub}/v1/models`);
|
||||
}
|
||||
|
||||
async function requestModelsForService(service, hoststub) {
|
||||
return service === "OLLAMA"
|
||||
? fetchOllamaModels(hoststub)
|
||||
: fetchOpenAICompatibleModels(hoststub);
|
||||
return service === "OLLAMA" ? fetchJsonOrThrow(`${hoststub}/api/tags`) : fetchJsonOrThrow(`${hoststub}/v1/models`);
|
||||
}
|
||||
|
||||
function handleModelLoadError(service, error) {
|
||||
@@ -278,7 +271,7 @@
|
||||
|
||||
async function handleModelDelete(modelName, deleteButton) {
|
||||
if (!modelName) return;
|
||||
if (isModelInProduction(modelName)) {
|
||||
if (getProductionModelNames().has(modelName)) {
|
||||
alert(`Model "${modelName}" is currently used in the production table and cannot be deleted.`);
|
||||
updateAvailableModelButtons();
|
||||
return;
|
||||
@@ -450,11 +443,6 @@
|
||||
return modelNames;
|
||||
}
|
||||
|
||||
function isModelInProduction(modelName) {
|
||||
if (!modelName) return false;
|
||||
return getProductionModelNames().has(modelName);
|
||||
}
|
||||
|
||||
function updateAvailableModelButtons() {
|
||||
const productionModels = getProductionModelNames();
|
||||
document.querySelectorAll('button[data-action="delete-model"]').forEach(button => {
|
||||
@@ -572,8 +560,7 @@
|
||||
}
|
||||
});
|
||||
|
||||
const shouldEnableFeatures = !hadRowsBeforeInsert;
|
||||
ensureProductionRowFeatureCells(targetRow, shouldEnableFeatures);
|
||||
ensureProductionRowUsageCells(targetRow, !hadRowsBeforeInsert);
|
||||
ensureProductionRowActionButton(targetRow);
|
||||
persistProductionModels();
|
||||
}
|
||||
@@ -591,15 +578,16 @@
|
||||
for (let i = 0; i < missingCells; i += 1) {
|
||||
row.appendChild(document.createElement("td"));
|
||||
}
|
||||
ensureProductionRowFeatureCells(row, false);
|
||||
ensureProductionRowUsageCells(row, false);
|
||||
ensureProductionRowActionButton(row);
|
||||
});
|
||||
updateAvailableModelButtons();
|
||||
}
|
||||
|
||||
function ensureProductionRowFeatureCells(row, defaultChecked) {
|
||||
function ensureProductionRowUsageCells(row, defaultChecked) {
|
||||
if (!row) return;
|
||||
for (let col = PRODUCTION_MODEL_FEATURE_COLUMN_START; col <= PRODUCTION_MODEL_FEATURE_COLUMN_END; col += 1) {
|
||||
// ensure existence of checkboxes
|
||||
for (let col = PRODUCTION_MODEL_USAGE_COLUMN_START; col <= PRODUCTION_MODEL_FEATURE_COLUMN_END; col += 1) {
|
||||
const cell = row.cells[col];
|
||||
if (!cell) continue;
|
||||
let checkbox = cell.querySelector('input[type="checkbox"]');
|
||||
@@ -609,28 +597,40 @@
|
||||
cell.textContent = "";
|
||||
cell.appendChild(checkbox);
|
||||
checkbox.checked = !!defaultChecked;
|
||||
if (col >= PRODUCTION_MODEL_FEATURE_COLUMN_START) {
|
||||
// disable the checkbox
|
||||
checkbox.disabled = true
|
||||
}
|
||||
}
|
||||
initializeFeatureCheckbox(checkbox, col);
|
||||
initializeUsageCheckbox(checkbox, col);
|
||||
}
|
||||
if (defaultChecked) {
|
||||
enforceFeatureExclusivityForRow(row);
|
||||
// enforce feature exclusivity for row
|
||||
if (!row) return;
|
||||
for (let col = PRODUCTION_MODEL_USAGE_COLUMN_START; col <= PRODUCTION_MODEL_USAGE_COLUMN_END; col += 1) {
|
||||
const cell = row.cells[col];
|
||||
if (!cell) continue;
|
||||
const checkbox = cell.querySelector('input[type="checkbox"]');
|
||||
if (!checkbox || !checkbox.checked) continue;
|
||||
handleUsageCheckboxToggle(col, checkbox);
|
||||
}
|
||||
}
|
||||
updateUndeployButtonState(row);
|
||||
}
|
||||
|
||||
function initializeFeatureCheckbox(checkbox, columnIndex) {
|
||||
function initializeUsageCheckbox(checkbox, col) {
|
||||
if (!checkbox) return;
|
||||
checkbox.dataset.featureColumn = String(columnIndex);
|
||||
checkbox.dataset.featureColumn = String(col);
|
||||
if (checkbox.dataset.listenerAttached === "true") {
|
||||
return;
|
||||
}
|
||||
checkbox.addEventListener("change", event => {
|
||||
handleFeatureCheckboxToggle(columnIndex, event.currentTarget);
|
||||
handleUsageCheckboxToggle(col, event.currentTarget);
|
||||
});
|
||||
checkbox.dataset.listenerAttached = "true";
|
||||
}
|
||||
|
||||
function handleFeatureCheckboxToggle(columnIndex, checkbox) {
|
||||
function handleUsageCheckboxToggle(columnIndex, checkbox) {
|
||||
if (!checkbox) return;
|
||||
const tbody = getProductionTableBody();
|
||||
if (!tbody) return;
|
||||
@@ -655,17 +655,6 @@
|
||||
persistProductionModels();
|
||||
}
|
||||
|
||||
function enforceFeatureExclusivityForRow(row) {
|
||||
if (!row) return;
|
||||
for (let col = PRODUCTION_MODEL_FEATURE_COLUMN_START; col <= PRODUCTION_MODEL_FEATURE_COLUMN_END; col += 1) {
|
||||
const cell = row.cells[col];
|
||||
if (!cell) continue;
|
||||
const checkbox = cell.querySelector('input[type="checkbox"]');
|
||||
if (!checkbox || !checkbox.checked) continue;
|
||||
handleFeatureCheckboxToggle(col, checkbox);
|
||||
}
|
||||
}
|
||||
|
||||
function ensureProductionRowActionButton(row) {
|
||||
if (!row || row.cells.length < PRODUCTION_MODEL_TOTAL_COLUMNS) {
|
||||
return;
|
||||
@@ -691,23 +680,18 @@
|
||||
if (!row) return;
|
||||
const button = row.querySelector('button[data-action="undeploy"]');
|
||||
if (!button) return;
|
||||
const hasFeatureChecked = isAnyFeatureCheckboxChecked(row);
|
||||
button.disabled = hasFeatureChecked;
|
||||
button.title = hasFeatureChecked
|
||||
? "Disable the assigned features before undeploying."
|
||||
: "";
|
||||
}
|
||||
|
||||
function isAnyFeatureCheckboxChecked(row) {
|
||||
for (let col = PRODUCTION_MODEL_FEATURE_COLUMN_START; col <= PRODUCTION_MODEL_FEATURE_COLUMN_END; col += 1) {
|
||||
hasFeatureChecked = false;
|
||||
for (let col = PRODUCTION_MODEL_USAGE_COLUMN_START; col <= PRODUCTION_MODEL_USAGE_COLUMN_END; col += 1) {
|
||||
const cell = row.cells[col];
|
||||
if (!cell) continue;
|
||||
const checkbox = cell.querySelector('input[type="checkbox"]');
|
||||
if (checkbox && checkbox.checked) {
|
||||
return true;
|
||||
hasFeatureChecked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
button.disabled = hasFeatureChecked;
|
||||
button.title = hasFeatureChecked ? "Disable the assigned features before undeploying." : "";
|
||||
}
|
||||
|
||||
function persistProductionModels() {
|
||||
@@ -721,10 +705,8 @@
|
||||
}
|
||||
const rowData = {};
|
||||
PRODUCTION_MODEL_COLUMN_NAMES.forEach((columnName, index) => {
|
||||
if (index >= PRODUCTION_MODEL_FEATURE_COLUMN_START && index <= PRODUCTION_MODEL_FEATURE_COLUMN_END) {
|
||||
const checkbox = row.cells[index]
|
||||
? row.cells[index].querySelector('input[type="checkbox"]')
|
||||
: null;
|
||||
if (index >= PRODUCTION_MODEL_USAGE_COLUMN_START && index <= PRODUCTION_MODEL_FEATURE_COLUMN_END) {
|
||||
const checkbox = row.cells[index] ? row.cells[index].querySelector('input[type="checkbox"]') : null;
|
||||
rowData[columnName] = checkbox ? checkbox.checked : false;
|
||||
} else {
|
||||
rowData[columnName] = row.cells[index] ? row.cells[index].textContent.trim() : "";
|
||||
@@ -845,7 +827,7 @@
|
||||
<fieldset id="productionModelsContainer" style="display: block;"><legend>Production Models</legend>
|
||||
<table class="table table-striped" id="productionModelsTable">
|
||||
<thead class="thead-dark">
|
||||
<tr><td>service</td><td>model</td><td>hoststub</td><td>api_key</td><td>max_tokens</td><td>answers</td><td>chat</td><td>translation</td><td>qa-generation</td><td>classification</td><td>shortener</td><td>vision</td><td>Actions</td></tr>
|
||||
<tr><td>service</td><td>model</td><td>hoststub</td><td>api_key</td><td>max_tokens</td><td>answers</td><td>chat</td><td>translation</td><td>qa-generation</td><td>classification</td><td>shortener</td><td><i>tooling</i></td><td><i>vision</i></td><td>Actions</td></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
#{productionmodels}#
|
||||
@@ -857,7 +839,8 @@
|
||||
<td><input type="checkbox" #(qa-generation)#::checked=true#(/qa-generation)#></td>
|
||||
<td><input type="checkbox" #(classification)#::checked=true#(/classification)#></td>
|
||||
<td><input type="checkbox" #(tldr-shortener)#::checked=true#(/tldr-shortener)#></td>
|
||||
<td><input type="checkbox" #(vision)#::checked=true#(/vision)#></td>
|
||||
<td><input type="checkbox" #(tooling)#::checked=true#(/tooling)# disabled=true></td>
|
||||
<td><input type="checkbox" #(vision)#::checked=true#(/vision)# disabled=true></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
#{/productionmodels}#
|
||||
|
||||
@@ -71,6 +71,7 @@ public class LLMSelection_p {
|
||||
"qa-generation":true,
|
||||
"classification":true,
|
||||
"tldr-shortener":true,
|
||||
"tooling":true,
|
||||
"vision":true
|
||||
}]}
|
||||
*/
|
||||
@@ -92,6 +93,7 @@ public class LLMSelection_p {
|
||||
prop.put("productionmodels_" + i + "_qa-generation", row.optBoolean("qa-generation", false));
|
||||
prop.put("productionmodels_" + i + "_classification", row.optBoolean("classification", false));
|
||||
prop.put("productionmodels_" + i + "_tldr-shortener", row.optBoolean("tldr-shortener", false));
|
||||
prop.put("productionmodels_" + i + "_tooling", row.optBoolean("tooling", false));
|
||||
prop.put("productionmodels_" + i + "_vision", row.optBoolean("vision", false));
|
||||
}
|
||||
prop.put("productionmodels", production_models.length());
|
||||
|
||||
Reference in new issue
Block a user