Skip to content

Commit 2aca63d

Browse files
committed
Add local model door CLI helpers
1 parent b7982f0 commit 2aca63d

1 file changed

Lines changed: 249 additions & 0 deletions

File tree

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
"""Local Model Door helpers.
2+
3+
This module probes local model runtime state and renders routing/profile plans.
4+
It never pulls weights, starts daemons, sends prompts, or performs inference.
5+
"""
6+
7+
from __future__ import annotations
8+
9+
import datetime as _dt
10+
import hashlib
11+
import json
12+
import shutil
13+
import subprocess
14+
import sys
15+
from pathlib import Path
16+
from typing import Any, Dict
17+
18+
19+
DEFAULT_PROFILE_REF = "urn:srcos:model-profile:local-llama32-1b"
20+
QUALITY_PROFILE_REF = "urn:srcos:model-profile:local-llama32-3b"
21+
DEFAULT_ROUTER_BINDING_REF = "urn:socioprophet:model-router-binding:demo-user-local-llama32"
22+
23+
LOCAL_MODEL_PROFILES = {
24+
"local-llama32-1b": {
25+
"profileRef": DEFAULT_PROFILE_REF,
26+
"displayName": "Local Llama 3.2 1B Router",
27+
"runtime": "ollama",
28+
"model": "llama3.2:1b",
29+
"parameterClass": "1b",
30+
"roles": [
31+
"router",
32+
"triage",
33+
"summarization",
34+
"rewrite",
35+
"office-assist",
36+
"agent-machine-assist",
37+
"offline-fallback",
38+
"privacy-first-chat",
39+
],
40+
"policy": {
41+
"localOnlyDefault": True,
42+
"sendPromptOffDeviceDefault": False,
43+
"allowToolUse": False,
44+
"allowNetwork": False,
45+
"requiresExplicitPull": True,
46+
},
47+
},
48+
"local-llama32-3b": {
49+
"profileRef": QUALITY_PROFILE_REF,
50+
"displayName": "Local Llama 3.2 3B Quality Fallback",
51+
"runtime": "ollama",
52+
"model": "llama3.2:3b",
53+
"parameterClass": "3b",
54+
"roles": [
55+
"summarization",
56+
"rewrite",
57+
"office-assist",
58+
"agent-machine-assist",
59+
"offline-fallback",
60+
"coding-assist",
61+
"privacy-first-chat",
62+
],
63+
"policy": {
64+
"localOnlyDefault": True,
65+
"sendPromptOffDeviceDefault": False,
66+
"allowToolUse": False,
67+
"allowNetwork": False,
68+
"requiresExplicitPull": True,
69+
},
70+
},
71+
}
72+
73+
74+
def _print_json(payload: Dict[str, Any]) -> int:
75+
print(json.dumps(payload, indent=2, sort_keys=True))
76+
return 0
77+
78+
79+
def _ollama_path() -> str | None:
80+
return shutil.which("ollama")
81+
82+
83+
def _ollama_list() -> dict[str, Any]:
84+
path = _ollama_path()
85+
if not path:
86+
return {"available": False, "path": None, "models": [], "error": "ollama not found on PATH"}
87+
try:
88+
completed = subprocess.run(
89+
[path, "list"],
90+
check=False,
91+
capture_output=True,
92+
text=True,
93+
timeout=8,
94+
)
95+
except Exception as exc: # pragma: no cover - defensive around host runtime
96+
return {"available": True, "path": path, "models": [], "error": str(exc)}
97+
98+
models: list[str] = []
99+
for line in completed.stdout.splitlines()[1:]:
100+
parts = line.split()
101+
if parts:
102+
models.append(parts[0])
103+
return {
104+
"available": True,
105+
"path": path,
106+
"returnCode": completed.returncode,
107+
"models": models,
108+
"error": completed.stderr.strip() or None,
109+
}
110+
111+
112+
def _profile(profile_name: str) -> dict[str, Any]:
113+
try:
114+
return LOCAL_MODEL_PROFILES[profile_name]
115+
except KeyError:
116+
known = ", ".join(sorted(LOCAL_MODEL_PROFILES))
117+
raise SystemExit(f"unknown local model profile: {profile_name}; known profiles: {known}")
118+
119+
120+
def _prompt_hash(text: str | None) -> str | None:
121+
if text is None:
122+
return None
123+
return "sha256:" + hashlib.sha256(text.encode("utf-8")).hexdigest()
124+
125+
126+
def doctor(args) -> int:
127+
"""Inspect local model runtime availability without pulling or running models."""
128+
runtime = _ollama_list()
129+
installed = set(runtime.get("models", []))
130+
profiles = []
131+
for profile in LOCAL_MODEL_PROFILES.values():
132+
model = profile["model"]
133+
profiles.append(
134+
{
135+
"profileRef": profile["profileRef"],
136+
"model": model,
137+
"runtime": profile["runtime"],
138+
"installed": model in installed,
139+
"roles": profile["roles"],
140+
}
141+
)
142+
return _print_json(
143+
{
144+
"type": "LocalModelDoctor",
145+
"capturedAt": _dt.datetime.now(_dt.timezone.utc).isoformat(),
146+
"runtime": runtime,
147+
"profiles": profiles,
148+
"policy": {
149+
"pullsModels": False,
150+
"startsServices": False,
151+
"runsInference": False,
152+
"promptEgressDefault": "deny",
153+
"promptEvidence": "hash-only",
154+
},
155+
}
156+
)
157+
158+
159+
def profiles(args) -> int:
160+
"""List built-in local model profile refs consumed from sourceos-model-carry."""
161+
return _print_json(
162+
{
163+
"type": "LocalModelProfiles",
164+
"profiles": LOCAL_MODEL_PROFILES,
165+
"sourceRepo": "SourceOS-Linux/sourceos-model-carry",
166+
}
167+
)
168+
169+
170+
def plan(args) -> int:
171+
"""Render a local model runtime plan without pulling or running models."""
172+
profile = _profile(args.profile)
173+
runtime = _ollama_list()
174+
installed = profile["model"] in set(runtime.get("models", []))
175+
return _print_json(
176+
{
177+
"type": "LocalModelPlan",
178+
"profile": profile,
179+
"runtime": runtime,
180+
"installed": installed,
181+
"wouldPull": False,
182+
"wouldStartService": False,
183+
"wouldRunInference": False,
184+
"explicitInstallCommand": f"ollama pull {profile['model']}",
185+
"explicitRunCommand": f"ollama run {profile['model']}",
186+
"policy": profile["policy"],
187+
}
188+
)
189+
190+
191+
def route(args) -> int:
192+
"""Render a hash-only route decision for a task class."""
193+
runtime = _ollama_list()
194+
installed = set(runtime.get("models", []))
195+
default = LOCAL_MODEL_PROFILES["local-llama32-1b"]
196+
quality = LOCAL_MODEL_PROFILES["local-llama32-3b"]
197+
has_default = default["model"] in installed
198+
has_quality = quality["model"] in installed
199+
200+
target = "base-local" if has_default else "quality-local" if has_quality else "hosted-policy-required"
201+
if args.task_class in {"office-assist", "rewrite", "summarization"} and args.personalization_ref:
202+
target = "personal-local-policy-checked"
203+
204+
return _print_json(
205+
{
206+
"type": "LocalModelRouteDecision",
207+
"capturedAt": _dt.datetime.now(_dt.timezone.utc).isoformat(),
208+
"taskClass": args.task_class,
209+
"target": target,
210+
"defaultLocalProfileRef": DEFAULT_PROFILE_REF,
211+
"qualityFallbackLocalProfileRef": QUALITY_PROFILE_REF,
212+
"routerBindingRef": args.router_binding_ref,
213+
"personalizationRef": args.personalization_ref,
214+
"promptHash": _prompt_hash(args.prompt) if args.prompt else None,
215+
"promptStored": False,
216+
"runtimeAvailable": runtime.get("available", False),
217+
"installedModels": sorted(installed),
218+
"requiresPolicyForHostedFallback": target == "hosted-policy-required",
219+
"evidence": {
220+
"emitRouteDecision": True,
221+
"emitRuntimeHealth": True,
222+
"emitGovernanceRefs": True,
223+
"promptHashOnly": True,
224+
},
225+
}
226+
)
227+
228+
229+
def evidence_inspect(args) -> int:
230+
path = Path(args.path)
231+
if not path.exists():
232+
print(f"error: evidence file not found: {path}", file=sys.stderr)
233+
return 1
234+
try:
235+
payload = json.loads(path.read_text())
236+
except json.JSONDecodeError as exc:
237+
print(f"error: invalid JSON: {exc}", file=sys.stderr)
238+
return 1
239+
return _print_json(
240+
{
241+
"path": str(path),
242+
"type": payload.get("type"),
243+
"taskClass": payload.get("taskClass"),
244+
"target": payload.get("target"),
245+
"promptStored": payload.get("promptStored"),
246+
"promptHashPresent": bool(payload.get("promptHash")),
247+
"routerBindingRef": payload.get("routerBindingRef"),
248+
}
249+
)

0 commit comments

Comments
 (0)