mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-06 23:44:36 +00:00
feat: show llama presets if autoload enabled (#8558)
This commit is contained in:
parent
97fa14e39c
commit
dcd461925d
4 changed files with 116 additions and 8 deletions
|
|
@ -28,6 +28,10 @@ export interface LlamaModelsResponse {
|
|||
object?: string;
|
||||
}
|
||||
|
||||
export interface LlamaServerProps {
|
||||
models_autoload?: boolean;
|
||||
}
|
||||
|
||||
export interface LlamaModelEvent {
|
||||
model: string;
|
||||
event: string;
|
||||
|
|
@ -189,6 +193,13 @@ export class LlamaClient {
|
|||
return data;
|
||||
}
|
||||
|
||||
async props(options: { signal?: AbortSignal } = {}): Promise<LlamaServerProps> {
|
||||
const payload = await this.request("/props", { signal: options.signal });
|
||||
if (typeof payload !== "object" || payload === null) return {};
|
||||
const { models_autoload: modelsAutoload } = payload as Record<string, unknown>;
|
||||
return typeof modelsAutoload === "boolean" ? { models_autoload: modelsAutoload } : {};
|
||||
}
|
||||
|
||||
async load(model: string, signal?: AbortSignal): Promise<void> {
|
||||
await this.request("/models/load", { method: "POST", body: JSON.stringify({ model }), signal });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,9 +25,25 @@ async function resolveServerUrl(
|
|||
return configured ? normalizeLlamaServerUrl(configured) : undefined;
|
||||
}
|
||||
|
||||
function modelIsSelectable(model: LlamaModelInfo): boolean {
|
||||
function modelIsSelectable(model: LlamaModelInfo, routerAutoload: boolean): boolean {
|
||||
if (model.status.value === "loaded") return true;
|
||||
// llama.cpp reports idle-slept models as "sleeping"; requests wake them automatically.
|
||||
return model.status.value === "loaded" || model.status.value === "sleeping";
|
||||
if (model.status.value === "sleeping") return true;
|
||||
// Unloaded presets are routable only when llama.cpp router autoload can load them on first use.
|
||||
return routerAutoload && model.status.value === "unloaded" && !model.status.failed && model.source === "preset";
|
||||
}
|
||||
|
||||
async function routerAutoloadEnabled(
|
||||
client: LlamaClient,
|
||||
catalog: readonly LlamaModelInfo[],
|
||||
signal: AbortSignal,
|
||||
): Promise<boolean> {
|
||||
if (!catalog.some((model) => model.status.value === "unloaded" && model.source === "preset")) return false;
|
||||
try {
|
||||
return (await client.props({ signal })).models_autoload === true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function toPiModel(model: LlamaModelInfo, serverUrl: string): Model<"openai-completions"> {
|
||||
|
|
@ -57,14 +73,20 @@ function toPiModel(model: LlamaModelInfo, serverUrl: string): Model<"openai-comp
|
|||
|
||||
export interface LlamaProviderController {
|
||||
provider: Provider<"openai-completions">;
|
||||
setCatalog(models: readonly LlamaModelInfo[], serverUrl: string): void;
|
||||
setCatalog(models: readonly LlamaModelInfo[], serverUrl: string, options?: { routerAutoload?: boolean }): void;
|
||||
}
|
||||
|
||||
export function createLlamaProvider(): LlamaProviderController {
|
||||
let models: readonly Model<"openai-completions">[] = [];
|
||||
|
||||
const setCatalog = (catalog: readonly LlamaModelInfo[], serverUrl: string): void => {
|
||||
models = catalog.filter((model) => modelIsSelectable(model)).map((model) => toPiModel(model, serverUrl));
|
||||
const setCatalog = (
|
||||
catalog: readonly LlamaModelInfo[],
|
||||
serverUrl: string,
|
||||
options: { routerAutoload?: boolean } = {},
|
||||
): void => {
|
||||
models = catalog
|
||||
.filter((model) => modelIsSelectable(model, options.routerAutoload === true))
|
||||
.map((model) => toPiModel(model, serverUrl));
|
||||
};
|
||||
|
||||
const provider: Provider<"openai-completions"> = {
|
||||
|
|
@ -135,10 +157,13 @@ export function createLlamaProvider(): LlamaProviderController {
|
|||
if (!context.allowNetwork || context.signal.aborted || context.credential?.type !== "api_key") return;
|
||||
const serverUrl = credentialServerUrl(context.credential);
|
||||
if (!serverUrl) return;
|
||||
const catalog = await new LlamaClient(serverUrl, context.credential.key).list({ signal: context.signal });
|
||||
const client = new LlamaClient(serverUrl, context.credential.key);
|
||||
const catalog = await client.list({ signal: context.signal });
|
||||
if (context.signal.aborted) return;
|
||||
const routerAutoload = await routerAutoloadEnabled(client, catalog, context.signal);
|
||||
if (context.signal.aborted) return;
|
||||
const refreshed = catalog
|
||||
.filter((model) => modelIsSelectable(model))
|
||||
.filter((model) => modelIsSelectable(model, routerAutoload))
|
||||
.map((model) => toPiModel(model, serverUrl));
|
||||
await context.publish({
|
||||
persist: { models: refreshed, checkedAt: Date.now() },
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue