style(fase1): ruff format spike modules
This commit is contained in:
parent
f7a36b59ac
commit
c1317689f1
6 changed files with 123 additions and 26 deletions
|
|
@ -137,8 +137,11 @@ class FakeChatClient(BaseChatClient):
|
||||||
reply = self._next_reply()
|
reply = self._next_reply()
|
||||||
|
|
||||||
if stream:
|
if stream:
|
||||||
|
|
||||||
async def _agen() -> Any:
|
async def _agen() -> Any:
|
||||||
yield ChatResponseUpdate(role="assistant", contents=[{"type": "text", "text": reply}])
|
yield ChatResponseUpdate(
|
||||||
|
role="assistant", contents=[{"type": "text", "text": reply}]
|
||||||
|
)
|
||||||
|
|
||||||
return self._build_response_stream(_agen())
|
return self._build_response_stream(_agen())
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,9 @@ def _caught_flaw(texts: Sequence[str]) -> bool:
|
||||||
return any(marker in blob for marker in _FLAW_MARKERS)
|
return any(marker in blob for marker in _FLAW_MARKERS)
|
||||||
|
|
||||||
|
|
||||||
async def run_live(*, n_rounds: int = DEFAULT_ROUNDS, write_findings: bool = True) -> dict[str, object]:
|
async def run_live(
|
||||||
|
*, n_rounds: int = DEFAULT_ROUNDS, write_findings: bool = True
|
||||||
|
) -> dict[str, object]:
|
||||||
"""Gated empirical arm: run maker-checker vs single-agent against a reference
|
"""Gated empirical arm: run maker-checker vs single-agent against a reference
|
||||||
project carrying a planted flaw, measure, and write ``findings-a.md``.
|
project carrying a planted flaw, measure, and write ``findings-a.md``.
|
||||||
|
|
||||||
|
|
@ -127,8 +129,12 @@ async def run_live(*, n_rounds: int = DEFAULT_ROUNDS, write_findings: bool = Tru
|
||||||
|
|
||||||
# --- maker-checker arm (3 roles) ---
|
# --- maker-checker arm (3 roles) ---
|
||||||
proposer = Agent(client, "You propose one concrete cost-saving measure.", name="proposer")
|
proposer = Agent(client, "You propose one concrete cost-saving measure.", name="proposer")
|
||||||
critic = Agent(client, "You critique the proposal and flag any constraint violation.", name="critic")
|
critic = Agent(
|
||||||
validator = Agent(client, "You give the final valid/invalid decision with a reason.", name="validator")
|
client, "You critique the proposal and flag any constraint violation.", name="critic"
|
||||||
|
)
|
||||||
|
validator = Agent(
|
||||||
|
client, "You give the final valid/invalid decision with a reason.", name="validator"
|
||||||
|
)
|
||||||
names = ["proposer", "critic", "validator"]
|
names = ["proposer", "critic", "validator"]
|
||||||
counter = {"n": 0}
|
counter = {"n": 0}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,9 @@ _NEVER_SATISFIED_LEDGER = json.dumps(
|
||||||
def _magentic(max_round_count: int | None) -> object:
|
def _magentic(max_round_count: int | None) -> object:
|
||||||
"""Build a Magentic workflow whose manager never self-finalizes."""
|
"""Build a Magentic workflow whose manager never self-finalizes."""
|
||||||
manager = StandardMagenticManager(
|
manager = StandardMagenticManager(
|
||||||
agent=Agent(FakeChatClient(default_reply=_NEVER_SATISFIED_LEDGER), "manager", name="manager"),
|
agent=Agent(
|
||||||
|
FakeChatClient(default_reply=_NEVER_SATISFIED_LEDGER), "manager", name="manager"
|
||||||
|
),
|
||||||
max_round_count=max_round_count,
|
max_round_count=max_round_count,
|
||||||
)
|
)
|
||||||
worker = Agent(FakeChatClient(default_reply="worker did some work"), "worker", name="worker")
|
worker = Agent(FakeChatClient(default_reply="worker did some work"), "worker", name="worker")
|
||||||
|
|
@ -95,9 +97,7 @@ def fresh_workflow() -> tuple[object, tuple[FakeChatClient, FakeChatClient]]:
|
||||||
every call, so no state survives between runs."""
|
every call, so no state survives between runs."""
|
||||||
c1 = FakeChatClient(default_reply="participant one view")
|
c1 = FakeChatClient(default_reply="participant one view")
|
||||||
c2 = FakeChatClient(default_reply="participant two view")
|
c2 = FakeChatClient(default_reply="participant two view")
|
||||||
workflow = ConcurrentBuilder(
|
workflow = ConcurrentBuilder(participants=[fake_agent(c1, "w1"), fake_agent(c2, "w2")]).build()
|
||||||
participants=[fake_agent(c1, "w1"), fake_agent(c2, "w2")]
|
|
||||||
).build()
|
|
||||||
return workflow, (c1, c2)
|
return workflow, (c1, c2)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -120,11 +120,15 @@ def _solve_max_feasible(items: list[AffectedItem], fraction: float) -> float:
|
||||||
prob += pulp.lpSum(xs) <= fraction * sum(it.total for it in items)
|
prob += pulp.lpSum(xs) <= fraction * sum(it.total for it in items)
|
||||||
status = prob.solve(solver)
|
status = prob.solve(solver)
|
||||||
if pulp.LpStatus[status] != "Optimal":
|
if pulp.LpStatus[status] != "Optimal":
|
||||||
raise CbcUnavailable(f"CBC did not reach an optimal solution (status={pulp.LpStatus[status]})")
|
raise CbcUnavailable(
|
||||||
|
f"CBC did not reach an optimal solution (status={pulp.LpStatus[status]})"
|
||||||
|
)
|
||||||
return float(pulp.value(prob.objective))
|
return float(pulp.value(prob.objective))
|
||||||
|
|
||||||
|
|
||||||
def _monte_carlo(proposal: SavingsProposal, *, fraction: float = MAX_SAVING_FRACTION) -> tuple[float, float, float]:
|
def _monte_carlo(
|
||||||
|
proposal: SavingsProposal, *, fraction: float = MAX_SAVING_FRACTION
|
||||||
|
) -> tuple[float, float, float]:
|
||||||
"""Vary uncertain unit-costs (seeded) and return (P10, P50, P90) of the feasible
|
"""Vary uncertain unit-costs (seeded) and return (P10, P50, P90) of the feasible
|
||||||
saving. Uses the LP's closed-form optimum (= fraction x sum of sampled totals), which
|
saving. Uses the LP's closed-form optimum (= fraction x sum of sampled totals), which
|
||||||
is exact here, so we do NOT spawn a CBC subprocess per sample (D6)."""
|
is exact here, so we do NOT spawn a CBC subprocess per sample (D6)."""
|
||||||
|
|
|
||||||
|
|
@ -63,9 +63,12 @@ def similarity(query: ProposalFeatures, candidate: ProposalFeatures) -> float:
|
||||||
"""Weighted structural similarity in [0, 1] — text is ignored by design."""
|
"""Weighted structural similarity in [0, 1] — text is ignored by design."""
|
||||||
codes = _jaccard(query.affected_codes, candidate.affected_codes)
|
codes = _jaccard(query.affected_codes, candidate.affected_codes)
|
||||||
measure = 1.0 if query.measure_type == candidate.measure_type else 0.0
|
measure = 1.0 if query.measure_type == candidate.measure_type else 0.0
|
||||||
magnitude = 1.0 if _magnitude_bucket(query.claimed_saving_nok) == _magnitude_bucket(
|
magnitude = (
|
||||||
candidate.claimed_saving_nok
|
1.0
|
||||||
) else 0.0
|
if _magnitude_bucket(query.claimed_saving_nok)
|
||||||
|
== _magnitude_bucket(candidate.claimed_saving_nok)
|
||||||
|
else 0.0
|
||||||
|
)
|
||||||
return _W_CODES * codes + _W_MEASURE * measure + _W_MAGNITUDE * magnitude
|
return _W_CODES * codes + _W_MEASURE * measure + _W_MAGNITUDE * magnitude
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -106,7 +109,9 @@ class ExpeLContextProvider(ContextProvider):
|
||||||
body = "\n".join(f"- [{v.id}] {v.decision}: {v.rationale}" for v in hits)
|
body = "\n".join(f"- [{v.id}] {v.decision}: {v.rationale}" for v in hits)
|
||||||
return f"Relevant prior verdicts (ExpeL few-shot):\n{body}"
|
return f"Relevant prior verdicts (ExpeL few-shot):\n{body}"
|
||||||
|
|
||||||
async def before_run(self, *, agent: object, session: object, context: object, state: dict) -> None:
|
async def before_run(
|
||||||
|
self, *, agent: object, session: object, context: object, state: dict
|
||||||
|
) -> None:
|
||||||
context.extend_instructions([self.format_fewshot()]) # type: ignore[attr-defined]
|
context.extend_instructions([self.format_fewshot()]) # type: ignore[attr-defined]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -114,18 +119,95 @@ def seed_store() -> VerdictStore:
|
||||||
"""Seed 12 synthetic verdicts spanning the reference domain's cost codes, measure
|
"""Seed 12 synthetic verdicts spanning the reference domain's cost codes, measure
|
||||||
types, magnitudes, and decisions (B2 store of 10–20)."""
|
types, magnitudes, and decisions (B2 store of 10–20)."""
|
||||||
rows = [
|
rows = [
|
||||||
("V01", {"05.2", "03.1"}, "scope_reduction", 180_000, "approved", "asphalt + base course trimmed within feasible range"),
|
(
|
||||||
("V02", {"05.2"}, "rate_renegotiation", 60_000, "approved", "renegotiated asphalt unit rate"),
|
"V01",
|
||||||
("V03", {"07.4"}, "material_substitution", 120_000, "rejected", "granite kerb substitution unsafe"),
|
{"05.2", "03.1"},
|
||||||
("V04", {"09.1"}, "scope_reduction", 240_000, "approved", "fewer LED masts on low-traffic stretch"),
|
"scope_reduction",
|
||||||
("V05", {"02.3", "03.1"}, "scope_reduction", 350_000, "rejected", "soil replacement is load-bearing, cannot cut"),
|
180_000,
|
||||||
|
"approved",
|
||||||
|
"asphalt + base course trimmed within feasible range",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"V02",
|
||||||
|
{"05.2"},
|
||||||
|
"rate_renegotiation",
|
||||||
|
60_000,
|
||||||
|
"approved",
|
||||||
|
"renegotiated asphalt unit rate",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"V03",
|
||||||
|
{"07.4"},
|
||||||
|
"material_substitution",
|
||||||
|
120_000,
|
||||||
|
"rejected",
|
||||||
|
"granite kerb substitution unsafe",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"V04",
|
||||||
|
{"09.1"},
|
||||||
|
"scope_reduction",
|
||||||
|
240_000,
|
||||||
|
"approved",
|
||||||
|
"fewer LED masts on low-traffic stretch",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"V05",
|
||||||
|
{"02.3", "03.1"},
|
||||||
|
"scope_reduction",
|
||||||
|
350_000,
|
||||||
|
"rejected",
|
||||||
|
"soil replacement is load-bearing, cannot cut",
|
||||||
|
),
|
||||||
("V06", {"21.2"}, "rate_renegotiation", 90_000, "approved", "blasting rate renegotiated"),
|
("V06", {"21.2"}, "rate_renegotiation", 90_000, "approved", "blasting rate renegotiated"),
|
||||||
("V07", {"22.4"}, "material_substitution", 700_000, "rejected", "fiber shotcrete spec is mandated"),
|
(
|
||||||
("V08", {"88.2"}, "scope_reduction", 150_000, "approved", "concrete repair area re-measured smaller"),
|
"V07",
|
||||||
("V09", {"87.3"}, "material_substitution", 130_000, "approved", "alternative membrane qualified"),
|
{"22.4"},
|
||||||
("V10", {"05.2", "03.1"}, "rate_renegotiation", 200_000, "approved", "combined paving rate discount"),
|
"material_substitution",
|
||||||
("V11", {"01.1"}, "scope_reduction", 95_000, "rejected", "rigging is fixed cost, no scope to cut"),
|
700_000,
|
||||||
("V12", {"31.3"}, "scope_reduction", 110_000, "approved", "drainage length reduced after survey"),
|
"rejected",
|
||||||
|
"fiber shotcrete spec is mandated",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"V08",
|
||||||
|
{"88.2"},
|
||||||
|
"scope_reduction",
|
||||||
|
150_000,
|
||||||
|
"approved",
|
||||||
|
"concrete repair area re-measured smaller",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"V09",
|
||||||
|
{"87.3"},
|
||||||
|
"material_substitution",
|
||||||
|
130_000,
|
||||||
|
"approved",
|
||||||
|
"alternative membrane qualified",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"V10",
|
||||||
|
{"05.2", "03.1"},
|
||||||
|
"rate_renegotiation",
|
||||||
|
200_000,
|
||||||
|
"approved",
|
||||||
|
"combined paving rate discount",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"V11",
|
||||||
|
{"01.1"},
|
||||||
|
"scope_reduction",
|
||||||
|
95_000,
|
||||||
|
"rejected",
|
||||||
|
"rigging is fixed cost, no scope to cut",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"V12",
|
||||||
|
{"31.3"},
|
||||||
|
"scope_reduction",
|
||||||
|
110_000,
|
||||||
|
"approved",
|
||||||
|
"drainage length reduced after survey",
|
||||||
|
),
|
||||||
]
|
]
|
||||||
return VerdictStore(
|
return VerdictStore(
|
||||||
verdicts=[
|
verdicts=[
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,9 @@ def test_retrieve_finds_structural_match_over_text_decoys() -> None:
|
||||||
|
|
||||||
def test_retrieve_is_deterministic() -> None:
|
def test_retrieve_is_deterministic() -> None:
|
||||||
store, _ = _store_with_true_match_and_decoys()
|
store, _ = _store_with_true_match_and_decoys()
|
||||||
assert [h.id for h in store.retrieve(_QUERY, k=3)] == [h.id for h in store.retrieve(_QUERY, k=3)]
|
assert [h.id for h in store.retrieve(_QUERY, k=3)] == [
|
||||||
|
h.id for h in store.retrieve(_QUERY, k=3)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def test_retrieve_rejects_non_positive_k() -> None:
|
def test_retrieve_rejects_non_positive_k() -> None:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue