File size: 2,473 Bytes
c7592d1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import { MODEL_IDS, type ModelId } from "../types";

const KEY = "minicpm5:loaded-models";

/** Quants that have completed a load on this device, mapped to a timestamp. */
export type LoadedModels = Partial<Record<ModelId, number>>;

export type QuantStatus = "ready" | "not-downloaded" | "evicted" | "unknown";

/**
 * Our own record of which quants have actually loaded here.
 *
 * WebLLM's `hasModelInCache` is the only other signal available, and it answers
 * "are every one of the param shards still in Cache Storage". That can be false
 * on a machine that has happily loaded the quant before, because the browser
 * evicts Cache Storage under pressure while the HTTP cache still serves the
 * shards. Remembering the successful load ourselves is what lets us tell that
 * apart from a genuine first visit.
 */
export function readLoadedModels(): LoadedModels {
  try {
    const raw = JSON.parse(localStorage.getItem(KEY) ?? "{}") as Record<string, unknown>;
    const out: LoadedModels = {};
    for (const id of MODEL_IDS) {
      const v = raw[id];
      if (typeof v === "number" && Number.isFinite(v)) out[id] = v;
    }
    return out;
  } catch {
    return {};
  }
}

function write(next: LoadedModels): LoadedModels {
  try {
    localStorage.setItem(KEY, JSON.stringify(next));
  } catch {
    /* storage unavailable; caller still gets the in-memory value */
  }
  return next;
}

export function markLoadedModel(id: ModelId, at = Date.now()): LoadedModels {
  return write({ ...readLoadedModels(), [id]: at });
}

export function clearLoadedModel(id: ModelId): LoadedModels {
  const next = { ...readLoadedModels() };
  delete next[id];
  return write(next);
}

/**
 * Reconcile WebLLM's cache check with what has actually run here.
 * `evicted` is the interesting case: WebLLM reports the shards gone while this
 * device loaded that quant before.
 */
export function quantStatus(cached: boolean | null, loadedAt: number | undefined): QuantStatus {
  if (cached === null) return "unknown";
  if (cached) return "ready";
  return loadedAt ? "evicted" : "not-downloaded";
}

export function formatBytes(bytes: number | null): string {
  if (bytes === null || !Number.isFinite(bytes) || bytes < 0) return "-";
  if (bytes >= 1024 ** 3) return `${(bytes / 1024 ** 3).toFixed(2)} GB`;
  if (bytes >= 1024 ** 2) return `${(bytes / 1024 ** 2).toFixed(0)} MB`;
  if (bytes >= 1024) return `${(bytes / 1024).toFixed(0)} KB`;
  return `${Math.round(bytes)} B`;
}