Add admin LLM model setting; rename Pi to LLM in the UI; drop table Review column
Test and deploy / test-and-deploy (push) Successful in 49s
Test and deploy / test-and-deploy (push) Successful in 49s
- New server/llm.js consolidates ModelRuntime + model selection: admin setting (app_settings.llm_model) > LLM_MODEL/PREFILL_MODEL env > first available; used by both prefill and roast evaluation - GET/PUT /api/admin/llm lists configured models and stores the choice (validated against the list; empty = auto; audited); admin page gains an LLM section with a model picker - All user-facing 'Pi agent' wording is now 'LLM'; no_model error message no longer references the pi CLI - /roasts table: Review column removed (review lives in the detail view) Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Fable 5
parent
eb82263ead
commit
5efaeb63c9
@@ -0,0 +1,44 @@
|
||||
// Shared LLM model runtime + selection for every model-backed feature (URL prefill, roast
|
||||
// evaluation). One ModelRuntime per process; which model actually runs is decided here:
|
||||
// the admin-chosen setting (app_settings.llm_model, passed in as `preferred`) wins, then the
|
||||
// LLM_MODEL / PREFILL_MODEL env overrides, then the first available configured model.
|
||||
|
||||
import { ModelRuntime } from "@earendil-works/pi-coding-agent";
|
||||
|
||||
let modelRuntimePromise = null;
|
||||
export async function getModelRuntime() {
|
||||
if (!modelRuntimePromise) modelRuntimePromise = ModelRuntime.create();
|
||||
return modelRuntimePromise;
|
||||
}
|
||||
|
||||
export const modelKey = (model) => `${model.provider}:${model.id}`;
|
||||
|
||||
/** Every configured model, as stable "provider:id" keys for the admin picker. */
|
||||
export async function listAvailableModels() {
|
||||
const runtime = await getModelRuntime();
|
||||
return (await runtime.getAvailable()).map((model) => ({
|
||||
key: modelKey(model),
|
||||
name: model.name ?? model.id,
|
||||
provider: model.provider,
|
||||
}));
|
||||
}
|
||||
|
||||
/** @param {string|null} preferred "provider:id" from the admin setting, or empty for auto. */
|
||||
export async function pickModel(preferred = null) {
|
||||
const runtime = await getModelRuntime();
|
||||
for (const candidate of [preferred, process.env.LLM_MODEL, process.env.PREFILL_MODEL]) {
|
||||
if (!candidate) continue;
|
||||
const sep = candidate.indexOf(":");
|
||||
if (sep === -1) continue;
|
||||
const model = runtime.getModel(candidate.slice(0, sep), candidate.slice(sep + 1));
|
||||
if (model) return model;
|
||||
}
|
||||
return (await runtime.getAvailable())[0];
|
||||
}
|
||||
|
||||
/** Consistent error for "the server has no usable model" across features. */
|
||||
export function noModelError() {
|
||||
const err = new Error("No LLM model is configured on the server.");
|
||||
err.code = "no_model";
|
||||
return err;
|
||||
}
|
||||
Reference in New Issue
Block a user