build-small-hackathon/microfactory-lab
2
1"""System-prompt assembly (versioned instruction steering, not activation steering).2 3`build_system_prompt()` concatenates: persona + job/env + a Historical4Precedent block of 2-3 retrieved prior jobs. CRITICAL: the prompt asks the5model to EVALUATE applicability — apply, adapt, or set precedent aside, and6say "no close precedent" when nothing fits. It is NOT told to always cite.7"""8 9from __future__ import annotations10 11from .models import Environment, Job, LessonEntry12 13PERSONA = """You are Chief Engineer O'Brien: a veteran print-shop master who has run \14thousands of FDM jobs. You are terse and physical. You think in feeds, temps, \15cooling, and how the room affects the plastic. You do not hype. You proposed \16settings; a deterministic Spine will veto anything unsafe, so propose what is \17*right*, not what is merely safe.18 19You reason about PRECEDENT before you decide. You are given similar prior jobs \20with their conditions and outcomes. Weigh what transfers to THIS job and what \21does not. If a prior job is close, apply or adapt its lesson and say so. If \22nothing close applies, say "no close precedent" and reason from material \23properties. Knowing what you don't know is a strength, not a weakness."""24 25OUTPUT_CONTRACT = """Respond ONLY with valid JSON, no prose outside it, in exactly this shape:26{27 "reasoning": "2-4 sentences. START with your evaluation of the prior jobs: what transfers, what doesn't, and why. Then the decision.",28 "settings": {29 "nozzle_temp": <C>, "bed_temp": <C>, "retraction_mm": <mm>,30 "fan_pct": <0-100>, "first_layer_fan_pct": <0-100>, "layer_height": <mm, e.g. 0.12-0.28>31 },32 "risks": [33 {"location": "where on the part", "risk": "sag|stringing|adhesion|warping|delamination",34 "why": "one line", "anchor_hint": "overhang|bridge|first_layer|corner|null"}35 ]36}"""37 38 39def _precedent_block(lessons: list[tuple[LessonEntry, float]]) -> str:40 if not lessons:41 return (42 "HISTORICAL PRECEDENT:\n"43 " (none) — no prior job matches this material + geometry. "44 "Reason from material properties and say so plainly.\n"45 )46 lines = ["HISTORICAL PRECEDENT (nearest prior jobs by environment):"]47 for i, (e, dist) in enumerate(lessons, 1):48 lines.append(49 f" [{i}] Job {e.job_id} ({e.source}) — {e.material}/{e.geometry_type} "50 f"@ {e.env_temp:.0f}°C, {e.env_humidity:.0f}% RH → {e.outcome} "51 f"(env-distance {dist:.2f})\n lesson: {e.lesson}"52 )53 return "\n".join(lines) + "\n"54 55 56def _reference_block(references: list[str]) -> str:57 if not references:58 return ""59 lines = "\n".join(f" - {r}" for r in references)60 return (61 "MATERIAL REFERENCE (hard parameters distilled from your slicer/firmware configs):\n"62 f"{lines}\nTreat these as bounds/baselines, not precedent.\n\n"63 )64 65 66def build_system_prompt(67 job: Job,68 env: Environment,69 retrieved: list[tuple[LessonEntry, float]],70 references: list[str] | None = None,71 policy_note: str | None = None,72) -> str:73 policy_block = f"{policy_note}\n\n" if policy_note else ""74 return (75 f"{PERSONA}\n\n"76 f"CURRENT JOB:\n"77 f" material: {job.material}\n"78 f" geometry: {job.geometry_type}\n"79 f" description: {job.description or '(none given)'}\n\n"80 f"ENVIRONMENT (right now in the room):\n"81 f" temperature: {env.temp:.0f}°C\n"82 f" humidity: {env.humidity:.0f}% RH\n\n"83 f"{_reference_block(references or [])}"84 f"{_precedent_block(retrieved)}\n"85 f"{policy_block}"86 f"{OUTPUT_CONTRACT}"87 )88 89 90# --- reflection prompt (post-job compression) ------------------------------91REFLECT_SYSTEM = """You are Chief Engineer O'Brien distilling a finished job into ONE \92durable, reusable lesson for your future self. Be specific about material, the \93conditions, and the lever that mattered. One or two sentences. No fluff.94 95Respond ONLY with valid JSON: {"lesson": "<one or two sentence lesson>"}"""96 97 98def build_reflect_prompt(job: Job, env: Environment, settings_summary: str, outcome: str) -> str:99 return (100 f"JOB: {job.material}/{job.geometry_type} — {job.description or '(no description)'}\n"101 f"ROOM: {env.temp:.0f}°C, {env.humidity:.0f}% RH\n"102 f"SETTINGS USED: {settings_summary}\n"103 f"REAL OUTCOME (human-reported): {outcome}\n\n"104 f"Write the lesson."105 )106 