You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Complete 0083 with the token-budget failure path (#238)
* Add 0083 failure path and mark implemented
Complete proposal 0083 (per-prompt token-budget observability) with
the structured-output-failure path. No source change was needed: the
budget already evaluates on any usage-bearing per-attempt event, so a
structured_output_invalid failure (which carries usage, proposal 0082)
drives the span, metrics, and section 7 log via the generic path, and
a no-usage provider_unavailable failure records nothing token-budget.
- conformance harness: route fixture 131 to the token-budget runner;
add expected_error handling (raises + raised_from), make the exact
metric assertion conditional on a declared metrics block (a failure
still records the baseline operation.duration), and implement the
two without-usage invariants.
- conformance.toml: mark 0083 implemented (all fixtures 126-131 run).
* Fold whole-proposal review findings into 0083
Address the six findings from the whole-proposal adversarial review
(0 blockers): cross-surface robustness plus the end-to-end coverage
the per-PR reviews could not see.
- langfuse: read token_budget via getattr in the metadata block,
matching the OTel span + shared helper, so a non-TokenBudget value
degrades instead of crashing the Generation.
- harness: fail loudly on an unmapped token-budget invariant name
(no more vacuous pass) and handle exception_propagates.
- tests: a structured_output_invalid over-budget failure through
Langfuse (ERROR wins, metadata.token_budget present, no WARNING);
the PromptManager.render -> PromptResult.token_budget propagation;
the langfuse extra-key tolerate case; and the filesystem unified
malformed-budget fallback-eligible path.
Copy file name to clipboardExpand all lines: conformance.toml
+5-6Lines changed: 5 additions & 6 deletions
Original file line number
Diff line number
Diff line change
@@ -825,13 +825,12 @@ since = "0.17.0"
825
825
note = "The graph-engine §6 event surface + llm-provider §7 error surface (PR A). LlmFailedEvent gains five response-side fields (output_content / finish_reason / usage / response_id / response_model), populated ONLY for structured_output_invalid (None for every other category); output_content is payload-bearing, the other four are not gated. StructuredOutputInvalid gains finish_reason / usage (the §7-mandated pair) plus response_id / response_model (internal, for the event builder), attached at the OpenAI provider's parse/validate call site where the intact wire response is in hand; the failed-event builder reads them off the enriched error. Un-defers observability fixtures 120 (truncation, finish_reason=length) / 121 (schema-mismatch, finish_reason=stop) / 122 (null-on-non-body companion), driven via the typed-event collector with a new calls_llm.response_schema harness lever; and llm-provider fixtures 022 / 023, whose carries block now asserts finish_reason + usage (the carries reader gained subset matching for a mapping-valued field like usage). PR B adds the OTel rendering + the metric: the per-attempt LlmRetryAttemptEvent now carries the same response-side surface on a structured_output_invalid failed attempt, so the OTel error span renders it (a structured_output_invalid failure falls through the failed-attempt early-return to render finish_reason / usage / gated output.content / response id+model while keeping ERROR status + category) and the §11.2 token-usage histogram records the failure's usage (the metric already recorded whenever usage was present; a structured failure now carries it). Un-defers observability fixtures 124 (OTel error span, payload on/off) and 125 (token metric on the failure). PR C completes it with the Langfuse failed-Generation rendering: _handle_typed_llm_failed renders output (payload-gated) + usage on the ERROR Generation and _typed_event_metadata renders finish_reason / response id+model for a structured_output_invalid failure (the isinstance(LlmCompletionEvent) guard widened to include it), alongside the existing level=ERROR + statusMessage=category. Un-defers observability fixture 123, driven in the dedicated test_observability_langfuse harness (calls_llm.response_schema threaded + expected_error handled). 0082 now fully implemented."
# / §11.2). Implemented across three PRs; all six fixtures 126-131 run.
833
830
[proposals."0083"]
834
-
status = "not-yet"
831
+
status = "implemented"
832
+
since = "0.17.0"
833
+
note = "Advisory, observability-only per-prompt token budget. PR A (completion path): a TokenBudget sub-record ({input_max_tokens?, total_max_tokens?}, non-negative) on Prompt / PromptResult, sourced from the same config sidecar as sampling (filesystem + langfuse backends); carried on LlmCompletionEvent / LlmFailedEvent / LlmRetryAttemptEvent (the OTel span + §11 metrics render from the per-attempt event). The OTel LLM span gains openarmature.prompt.token_budget.input_max_tokens / .total_max_tokens (each only when declared) + the reactive openarmature.llm.token_budget.exceeded boolean (emitted only when a bound is declared AND usage is present -- absent, not false, otherwise); two opt-in §11.2 instruments: openarmature.gen_ai.client.token_budget.exceeded counter (per breached bound) + .utilization histogram (actual / max per declared bound on every budgeted call), both dimensioned by openarmature.gen_ai.token_budget.kind = input | total. Evaluation gates each bound on its reported count being present (mirrors token.usage, does NOT coerce a missing count to 0); a declared bound of 0 is exceeded by any positive usage (strict >) but its utilization sample is skipped (ratio undefined). Un-defers fixtures 126-129. PR B (WARNING surfaces): the shared _token_budget_evaluations helper lifted to observability/llm_event.py; the Langfuse success Generation ends at level WARNING + statusMessage naming the breached bound(s) + metadata.token_budget on a breach (a hard ERROR still wins on the failure path); a §7 WARNING log per over-budget attempt on the openarmature.observability logger, dispatched independently of the disable_llm_spans / enable_metrics gates (correlates via correlation_id -- OA never activates spans, so no trace_id/span_id). Un-defers fixture 130. PR C (failure path): the budget evaluates on a usage-bearing structured_output_invalid failure exactly as on a completion (span + metrics + §7 log fall out of the generic per-attempt handling), and is populated-but-not-evaluated on a no-usage failure (provider_unavailable); the token-budget runner gained expected_error handling + the without-usage invariants. Un-defers fixture 131 (both cases). 0083 now fully implemented."
0 commit comments