Download docs/agent-design.md from Farshadm/beampilot: direct link, hf CLI and curl.
- Browser
- Download file 12.6 kB
-
https://huggingface.co/spaces/Farshadm/beampilot/resolve/main/docs/agent-design.md
- Command line
-
hf download hf://spaces/Farshadm/beampilot/docs/agent-design.md
-
curl -L -o agent-design.md https://huggingface.co/spaces/Farshadm/beampilot/resolve/main/docs/agent-design.md
A newer version of the Gradio SDK is available: 6.31.0
BeamPilot agent design (v1)
Status: v1, agreed 26 Oct 2026.
Updated 27 Oct 2026 (added retake_darks). All data is simulated. No lab data, no code from other projects.
1. Goal and pitch
BeamPilot is an agent that measures the M² of a laser beam to ISO 11146 with a camera on a moving stage (simulated). It decides where to measure, judges whether each measurement can be trusted, recovers from faults, and gives an honest final verdict, including "this cannot be measured to the standard with this setup".
Why an LLM and not a fixed script: commercial M² instruments already place ISO points automatically on clean beams. BeamPilot's value is judgement when things go wrong (saturation, background drift, beam too large for the sensor, waist out of reach, different x/y waists) and explaining every decision. We test this claim against a smart scripted baseline and report the result honestly, even if the agent only wins on fault scenarios.
2. Who does what
| Part | Job | Never does |
|---|---|---|
| Muse Spark (agent) | Chooses positions and exposure, accepts or rejects measurements, decides when to finish, explains each action | Compute or type physics numbers. The report numbers come from Python state. |
| Python tools | Simulator, ISO 11146 widths, weighted caustic fit, coverage and sanity checks | Decide what to measure next or discard data on their own |
| Python controller | Runs the loop, holds all state, enforces hard limits, logs everything | Trust the agent to stop or to report correct numbers |
The phases in section 5 are guidance in the system prompt, not controller code. The model chooses the order of actions; the controller only enforces limits.
3. Units
- Python computes internally in SI (metres, radians).
- The tool interface shows z in mm, diameters in µm and wavelength in nm, because that is easier for the model to read. Conversion happens only at the tool boundary.
- A known-answer test checks M² end to end, so a unit error (for example a factor 10³) fails.
4. Tools (7 core)
Every tool has a required reason string. Tool schemas are strict, and verdicts are enums.
get_setup(reason)- Wavelength, stage range, pixel size, sensor size, exposure limits, position budget left.
measure_at(z_mm, exposure_ms, reason)- Moves the stage, takes 5 repeated frames (ISO 11146-1 asks for at least 5 per position), applies background correction, computes ISO second-moment diameters.
- Returns:
measurement_id, mean ± std of d_x and d_y, quality flags (saturation fraction, peak / full scale, edge clipping, pixels per beam width, residual background, ellipse azimuth), and a suggested verdict. The measurement starts aspending. - Several
measure_atcalls may come in one turn (parallel tool calls); the controller runs them one after another, like a real stage.
set_status(measurement_id, status, reason)statusisacceptorreject. Only accepted measurements go into the fit.- Guardrail: the controller refuses to accept a saturated measurement.
evaluate(reason)- Weighted caustic fit per axis, per-axis ISO coverage in units of zR ("x: 3 within ±1 zR, need about 5; 1 beyond 2 zR, need about 5"), waist accessibility (inside / outside / uncertain), general-astigmatism check, M² < 1 sanity flag, and a compact table of all measurements.
- If an axis fit fails, or no accepted position lies within ±1 zR of its fitted waist,
d0, z0, zR and M² of that axis are reported as null with a
not_determinedreason (andwaist_side: below/above the measured positions or within a gap,waist_gap_mm), never as an extrapolated number. The same applies to thefinishreport. - Waist accessibility per axis from z0 ± 2σ against the stage range:
inside,outsideoruncertain(thenwaist_near_stage_end: measure closer to that end). Onlyoutsidesupports thewaist_not_accessibleverdict.
finish(verdict, explanation)verdictis one of:iso_compliant,estimate_not_compliant,waist_not_accessible,general_astigmatism_out_of_scope,measurement_failed.- Python builds the report numbers from stored state. The model writes only the verdict and the text.
- Guardrail: if the model claims
iso_compliantbutevaluatesays coverage is not met, or flags general astigmatism or M² < 1, the controller returns an error and the agent must continue or choose another verdict.waist_not_accessibleis refused unless an axis isoutsideand an accepted position lies within 5 % of the stage length from that stage end. A waist up to about 1 zR outside the stage may still give an accurate M²; the verdict is thenwaist_not_accessibleby definition (no near-waist points on both sides), not because the number is unusable. - If a hard limit (model calls, tokens, cost) or an API error stops the agent first,
Python writes a fallback report from session state:
estimate_not_compliantif M² is determined on both axes, otherwisemeasurement_failed, withstopped_by_limitholding the reason.
retake_darks(reason)- Blocks the beam and takes a fresh dark set (50 frames) with the current background, so a background change (e.g. room light switched on) becomes part of the dark.
- Costs one position from the budget. Use it when
measure_atreportsbackground_changed.
view_frame(measurement_id, reason)- Optional. Returns the first frame of a measurement as a PNG image for the model (Muse Spark image input), on a square-root brightness scale, so the agent can see what the second moments hide (e.g. a ghost reflection).
- Separate small budget (4 views per run), no position cost. The image goes to the model inside the tool output and is not stored in logs or run files.
- Only the 2 most recent images stay in the resent history; older ones become a text
stub.
AgentConfig(view_frame=False)switches the tool off (evaluation ablation).
Stretch tool (only after the core works): change_lens(f_mm, reason) for an inaccessible
waist (ISO uses an artificial waist made with an aberration-free lens, and M² stays the same).
5. Loop guidance (in the system prompt)
Scout: get_setup, a few measurements spread over the stage range, fix exposure if needed
Locate: evaluate → first estimates of z0 and zR for x and y
Fill: measure where coverage is missing, accept/reject each result, evaluate again
Finish: when coverage is met on both axes, or when the setup cannot meet it
Hard limits in the controller: maximum positions, maximum agent turns, token budget per run. Exact numbers are set after the first test runs.
6. Physics (ISO 11146-1)
- Second-moment diameter d = 4σ, per principal axis (x and y, not rotated).
- Integration area: centred on the centroid, 3 × the beam widths, iterated until it converges (2005 wording; the 2021 edition relaxed this, exact text unverified).
- Background: subtract a dark frame, then a fine offset from corner patches (2–5 % of the image), and keep negative pixel values (ISO/TR 11146-3).
- Caustic fit: d(z)² = a + b·z + c·z², fitted by minimising squared relative diameter
deviations, weighted by the repeat variance (
scipy.optimize.least_squares, not plainpolyfit). - Results: z0 = −b/(2c), d0 = √(a − b²/(4c)), Θ = √c (full angle), zR = d0/Θ, M² = (π/(8λ)) · √(4ac − b²).
- Point rule: at least 10 positions, about half within one zR of the waist and about half beyond 2 zR, applied separately for x and y.
- Detector rules: at least 20 pixels across the beam (spatial resolution ≥ 1/20 of the beam width), clipping loss under 1 % of the power. These create real trade-offs: far from the waist the beam can outgrow the sensor; near the waist it can get too small for the pixels.
- General astigmatism: if the azimuth of two non-circular profiles differs by more than 10°, ISO 11146-2 applies. That is out of scope: the agent detects it and stops.
- M² > 1 in the simulator: Gaussian profile with an enlarged width ("embedded Gaussian"). Hermite-Gaussian mode mixes are a later option.
Source of these points: the review read the ISO 11146-1:2005 and ISO/TR 11146-3 texts from third-party copies. The maintainer should check the key rules once before claiming compliance.
7. Scenarios (all simulated)
Core:
- Clean beam, M² close to 1.
- Saturation at some positions only.
- Background drift during the run ("room light turned on").
- Beam too large for the sensor at far positions.
- Waist outside the stage range →
waist_not_accessiblewith explanation. - Different waist positions in x and y (simple astigmatism). All code is per-axis from day one.
Ghost reflection (with view_frame): ghost_everywhere (expected measurement_failed) and
ghost_in_range (expected iso_compliant after rejecting the ghost positions).
Held-out faults for evaluation only (not in SCENARIOS): iris aperture over a z range,
hot pixels, pointing drift (see docs/evaluation-plan.md).
Stretch: change_lens, general astigmatism detection demo.
Demo features: fault buttons the judge can press during a run, a "mystery beam" button with random hidden parameters (ground truth shown at the end), and a replay mode for recorded runs.
8. Evaluation
Three contenders on the same set of randomised hidden scenarios (fixed seed):
- Naive uniform scan
- Smart scripted ISO rule (scout, fit, place points, refit, simple fault rules)
- Muse Spark agent
Metrics: ISO-compliance rate, M² error versus ground truth, faults noticed, positions used. The scripted baseline must be a fair, honest attempt, not built to fail. Batch size is decided after measuring the cost of one agent run.
9. Testing
- Known-answer tests: ideal Gaussian gives M² = 1; a known M² > 1 is recovered; constant offset is removed; near-waist-only sampling gives a biased result (divergence badly constrained).
- Optional test oracle: the open-source
laserbeamsizepackage, as a dev dependency only (licence and use to be checked and agreed first). - The scripted baseline also tests the tools and controller without spending API credits.
10. Muse Spark settings
- Responses API with function calling. Output cap is
max_output_tokens(reasoning tokens count toward it). Resend the system instructions on every call (previous_response_iddoes not keep them). Tool results go back asfunction_call_outputwith the matchingcall_id. reasoning_effortlow or medium for normal steps. Measure latency and tokens; don't guess.- Development batches may use the cheaper contributor model (data used for training; we only send simulated data). Whether hackathon credits cover it: unverified.
- Log tokens and the
reasonfield for every step.
11. Schedule (Nuremberg time; adjust to real available hours)
| Day | Goal |
|---|---|
| Tue 27 Oct | Simulator (per-axis Gaussian, M², noise, offset, saturation, dark frame) + tests. Workshop 17:00. |
| Wed 28 Oct | ISO widths (corner offset, iterative 3× area) + tests. Workshop 17:00. |
| Thu 29 Oct | Weighted fit and evaluate (coverage, checks) + tests |
| Fri 30 Oct | Tool wrappers, controller, scripted baseline from the command line. Check HF Spaces plan. |
| Sat 31 Oct – Sun 1 Nov | Muse Spark loop, logging, first agent runs |
| Mon 2 Nov | Gradio UI (caustic plot, decision log, fault buttons, replay), deploy. Feature freeze. |
| Tue 3 Nov | Small honest evaluation, README, record the video |
| Wed 4 Nov | Buffer. Submit in the evening. |
Drop in this order if behind: SAM 3.1 → ghost scenario and view_frame → change_lens →
polished x/y-waist demo (keep the per-axis code). Never drop: known-answer tests, scripted
baseline, replay mode, the video.
12. Open decisions
- Hosting: Gradio on Hugging Face Spaces is the likely choice. Check the current free/paid rules for Spaces before deciding (the review reported changes; unverified).
laserbeamsizeas a dev-only test oracle: yes or no.- Impact framing for the video: who benefits (for example small labs and teaching labs without a commercial M² instrument). To be written without claims we cannot back up.
- Whether SAM 3.1 gets its one-hour test at all.