microfactory-lab / core /chief_engineer.py
kylebrodeur's picture
deploy: update Space from deploy_preflight --push
0b338fe verified
Raw
History Blame Contribute Delete
3.69 kB
"""The Chief Engineer — Brain.
Reimplements hubAgent.ts's call shape (pattern-review.md §1): assemble system
prompt → real Ollama call → parse to Pydantic, with a conservative fallback so
a parse failure or an offline Space never crashes the demo. The reasoning text
carries the model's EVALUATION of precedent — the load-bearing moment.
"""
from __future__ import annotations
from dataclasses import dataclass
from . import llm
from .models import Advice, Environment, Job, LessonEntry, PrintSettings, RiskRegion
from .prompts import build_system_prompt
# Conservative per-material starting points for the offline/parse-fail fallback.
_FALLBACK_SETTINGS: dict[str, dict[str, float]] = {
"PLA": {"nozzle_temp": 205, "bed_temp": 60, "retraction_mm": 5, "fan_pct": 100, "first_layer_fan_pct": 0, "layer_height": 0.20},
"PETG": {"nozzle_temp": 235, "bed_temp": 80, "retraction_mm": 4, "fan_pct": 40, "first_layer_fan_pct": 0, "layer_height": 0.20},
"ABS": {"nozzle_temp": 245, "bed_temp": 100, "retraction_mm": 4, "fan_pct": 20, "first_layer_fan_pct": 0, "layer_height": 0.20},
"TPU": {"nozzle_temp": 228, "bed_temp": 50, "retraction_mm": 2, "fan_pct": 40, "first_layer_fan_pct": 0, "layer_height": 0.24},
}
_GEOMETRY_RISK = {
"overhang": ("underside of the overhang", "sag", "steep overhangs droop before the layer freezes", "overhang"),
"bridge": ("the unsupported span", "sag", "long bridges sag without enough cooling", "bridge"),
"stringing": ("travel moves across gaps", "stringing", "molten plastic oozes during travel", None),
"adhesion": ("first layer / corners", "adhesion", "poor first-layer bond lifts the part", "first_layer"),
"vase": ("thin single-wall sections", "warping", "tall thin walls can wobble or warp", None),
}
@dataclass
class Recommendation:
advice: Advice
used_fallback: bool
backend: str
def _fallback_advice(job: Job, env: Environment, retrieved: list[tuple[LessonEntry, float]]) -> Advice:
base = _FALLBACK_SETTINGS.get(job.material.upper(), _FALLBACK_SETTINGS["PLA"])
loc, risk, why, hint = _GEOMETRY_RISK.get(
job.geometry_type, ("the part", "warping", "general risk", None)
)
if retrieved:
e, dist = retrieved[0]
reasoning = (
f"[fallback] Nearest precedent: Job {e.job_id} ({e.material}/{e.geometry_type} "
f"@ {e.env_temp:.0f}°C/{e.env_humidity:.0f}% → {e.outcome}, env-dist {dist:.2f}). "
f"Applying its lesson with conservative {job.material} defaults."
)
else:
reasoning = (
f"[fallback] No close precedent for {job.material}/{job.geometry_type}. "
f"Reasoning from material properties with conservative defaults."
)
return Advice(
reasoning=reasoning,
settings=PrintSettings(**base),
risks=[RiskRegion(location=loc, risk=risk, why=why, anchor_hint=hint)],
)
def advise(
job: Job,
env: Environment,
retrieved: list[tuple[LessonEntry, float]],
references: list[str] | None = None,
policy_note: str | None = None,
) -> Recommendation:
system = build_system_prompt(job, env, retrieved, references, policy_note)
raw = llm.chat_json(system, "Give your recommendation for THIS job now.")
backend = llm.backend_status()
if raw is None:
return Recommendation(_fallback_advice(job, env, retrieved), used_fallback=True, backend=backend)
try:
advice = Advice(**raw)
return Recommendation(advice, used_fallback=False, backend=backend)
except Exception:
return Recommendation(_fallback_advice(job, env, retrieved), used_fallback=True, backend=backend)