Skip to content

Commit 094a53c

Browse files
authored
refactor(proxy): isolate output effort policy (#1961)
## Description Extracts provider-neutral output effort decisions into a pure `output_effort_policy` module. `output_shaper` still owns request mutation and labels, while the rank comparisons, legacy thinking clamp, and OpenAI text verbosity eligibility now live behind small deterministic functions. Closes # ## Type of Change - [ ] Bug fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update - [ ] Performance improvement - [x] Code refactoring (no functional changes) ## Changes Made - Added `headroom.proxy.output_effort_policy` for effort lowering, legacy thinking budget clamping, and OpenAI text verbosity decisions. - Updated `output_shaper` to delegate those pure decisions while preserving existing labels and request mutation behavior. - Added focused policy tests for effort rank transitions, thinking clamp boundaries, and verbosity creation/lowering. - Included the current LiteLLM callback signature compatibility shim required for repo-wide mypy on main-based slices. ## Testing - [x] Unit tests pass (`pytest`) - [x] Linting passes (`ruff check .`) - [x] Type checking passes (`mypy headroom`) - [x] New tests added for new functionality - [ ] Manual testing performed ### Test Output ```text python -m pytest tests/test_output_effort_policy.py tests/test_output_shaper.py tests/test_litellm_callback.py -q 56 passed in 6.34s python -m ruff check . All checks passed! python -m ruff format --check . 1095 files already formatted python -m mypy headroom --ignore-missing-imports Success: no issues found in 409 source files gitleaks protect --staged --no-banner --redact no leaks found ``` ## Real Behavior Proof - Environment: Windows, Python 3.13.13, clean worktree based on `headroomlabs/main`. - Exact command / steps: targeted pytest, ruff, format check, repo-wide mypy, staged gitleaks scan. - Observed result: output effort policy/shaper/callback tests pass; static checks pass; no staged secrets detected. - Not tested: live provider calls; this slice preserves existing request mutation behavior and only moves pure policy decisions. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [x] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] I have updated the CHANGELOG.md if applicable ## Screenshots (if applicable) N/A ## Additional Notes Documentation and changelog updates are not applicable for this internal architecture slice. PR-specific GHAS checks will be monitored after opening.
1 parent b1e871d commit 094a53c

3 files changed

Lines changed: 145 additions & 37 deletions

File tree

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
"""Pure output-effort policy decisions.
2+
3+
The output shaper mutates provider request bodies. This module owns the
4+
provider-neutral decisions behind those mutations so rank comparisons and
5+
legacy budget clamping stay testable without request dictionaries.
6+
"""
7+
8+
from __future__ import annotations
9+
10+
EFFORT_RANK = {"low": 0, "medium": 1, "high": 2, "xhigh": 3, "max": 4}
11+
TEXT_VERBOSITY_RANK = {"low": 0, "medium": 1, "high": 2}
12+
LEGACY_THINKING_FLOOR = 1024
13+
14+
15+
def lower_effort_value(current: object, target: str) -> str | None:
16+
"""Return ``target`` when an existing effort should be lowered."""
17+
if not isinstance(current, str):
18+
return None
19+
if current not in EFFORT_RANK or target not in EFFORT_RANK:
20+
return None
21+
if EFFORT_RANK[current] <= EFFORT_RANK[target]:
22+
return None
23+
return target
24+
25+
26+
def clamp_legacy_thinking_budget(
27+
*,
28+
thinking_type: object,
29+
budget_tokens: object,
30+
floor: int = LEGACY_THINKING_FLOOR,
31+
) -> int | None:
32+
"""Return the clamped budget for legacy enabled thinking, else ``None``."""
33+
if thinking_type != "enabled":
34+
return None
35+
if not isinstance(budget_tokens, int):
36+
return None
37+
if budget_tokens <= floor:
38+
return None
39+
return floor
40+
41+
42+
def can_create_openai_text_verbosity(model: object) -> bool:
43+
"""Whether it is safe to create a new OpenAI ``text.verbosity`` block."""
44+
return str(model or "").lower().startswith("gpt-5")
45+
46+
47+
def lower_text_verbosity_value(current: object) -> str | None:
48+
"""Return ``low`` when an existing OpenAI text verbosity should be lowered."""
49+
if not isinstance(current, str):
50+
return None
51+
if current not in TEXT_VERBOSITY_RANK:
52+
return None
53+
if TEXT_VERBOSITY_RANK[current] <= TEXT_VERBOSITY_RANK["low"]:
54+
return None
55+
return "low"

headroom/proxy/output_shaper.py

Lines changed: 32 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,16 @@
3939
from typing import Any
4040

4141
from headroom.proxy import runtime_env
42+
from headroom.proxy.output_effort_policy import (
43+
EFFORT_RANK as _EFFORT_RANK,
44+
)
45+
from headroom.proxy.output_effort_policy import (
46+
LEGACY_THINKING_FLOOR,
47+
can_create_openai_text_verbosity,
48+
clamp_legacy_thinking_budget,
49+
lower_effort_value,
50+
lower_text_verbosity_value,
51+
)
4252
from headroom.proxy.output_steering import (
4353
apply_openai_responses_verbosity_steering,
4454
apply_verbosity_steering,
@@ -66,15 +76,6 @@
6676
"steering_text",
6777
]
6878

69-
# Documented Anthropic API minimum for thinking.budget_tokens on models
70-
# that still accept the legacy enabled/budget_tokens form.
71-
LEGACY_THINKING_FLOOR = 1024
72-
73-
# Ordering for output_config.effort values. Unknown values are left alone.
74-
_EFFORT_RANK = {"low": 0, "medium": 1, "high": 2, "xhigh": 3, "max": 4}
75-
76-
_TEXT_VERBOSITY_RANK = {"low": 0, "medium": 1, "high": 2}
77-
7879
_OPENAI_RESPONSES_OUTPUT_ITEM_TYPES = frozenset(
7980
{
8081
"custom_tool_call_output",
@@ -265,22 +266,24 @@ def route_effort(
265266
output_config = body.get("output_config")
266267
if isinstance(output_config, dict):
267268
effort = output_config.get("effort")
268-
if (
269-
isinstance(effort, str)
270-
and effort in _EFFORT_RANK
271-
and _EFFORT_RANK[effort] > _EFFORT_RANK[settings.mechanical_effort]
272-
):
273-
output_config["effort"] = settings.mechanical_effort
274-
labels.append(f"output_shaper:effort:{effort}->{settings.mechanical_effort}")
269+
lowered = lower_effort_value(effort, settings.mechanical_effort)
270+
if lowered is not None:
271+
output_config["effort"] = lowered
272+
labels.append(f"output_shaper:effort:{effort}->{lowered}")
275273

276274
# Legacy lever: clamp thinking.budget_tokens on models still using the
277275
# enabled/budget_tokens form. The type field itself is never touched.
278276
thinking = body.get("thinking")
279-
if isinstance(thinking, dict) and thinking.get("type") == "enabled":
277+
if isinstance(thinking, dict):
280278
budget = thinking.get("budget_tokens")
281-
if isinstance(budget, int) and budget > LEGACY_THINKING_FLOOR:
282-
thinking["budget_tokens"] = LEGACY_THINKING_FLOOR
283-
labels.append(f"output_shaper:thinking_budget:{budget}->{LEGACY_THINKING_FLOOR}")
279+
clamped = clamp_legacy_thinking_budget(
280+
thinking_type=thinking.get("type"),
281+
budget_tokens=budget,
282+
floor=LEGACY_THINKING_FLOOR,
283+
)
284+
if clamped is not None:
285+
thinking["budget_tokens"] = clamped
286+
labels.append(f"output_shaper:thinking_budget:{budget}->{clamped}")
284287

285288
return labels
286289

@@ -363,22 +366,17 @@ def route_openai_reasoning_effort(
363366
return []
364367
effort = reasoning.get("effort")
365368
target = settings.mechanical_effort
366-
if (
367-
isinstance(effort, str)
368-
and effort in _EFFORT_RANK
369-
and target in _EFFORT_RANK
370-
and _EFFORT_RANK[effort] > _EFFORT_RANK[target]
371-
):
372-
reasoning["effort"] = target
373-
return [f"output_shaper:reasoning_effort:{effort}->{target}"]
369+
lowered = lower_effort_value(effort, target)
370+
if lowered is not None:
371+
reasoning["effort"] = lowered
372+
return [f"output_shaper:reasoning_effort:{effort}->{lowered}"]
374373
return []
375374

376375

377376
def route_openai_text_verbosity(body: dict[str, Any]) -> list[str]:
378377
"""Set or lower OpenAI ``text.verbosity`` conservatively."""
379-
model = str(body.get("model") or "").lower()
380378
text_config = body.get("text")
381-
can_create = model.startswith("gpt-5")
379+
can_create = can_create_openai_text_verbosity(body.get("model"))
382380
if text_config is None:
383381
if not can_create:
384382
return []
@@ -393,13 +391,10 @@ def route_openai_text_verbosity(body: dict[str, Any]) -> list[str]:
393391
return []
394392
text_config["verbosity"] = "low"
395393
return ["output_shaper:text_verbosity:unset->low"]
396-
if (
397-
isinstance(verbosity, str)
398-
and verbosity in _TEXT_VERBOSITY_RANK
399-
and _TEXT_VERBOSITY_RANK[verbosity] > _TEXT_VERBOSITY_RANK["low"]
400-
):
401-
text_config["verbosity"] = "low"
402-
return [f"output_shaper:text_verbosity:{verbosity}->low"]
394+
lowered = lower_text_verbosity_value(verbosity)
395+
if lowered is not None:
396+
text_config["verbosity"] = lowered
397+
return [f"output_shaper:text_verbosity:{verbosity}->{lowered}"]
403398
return []
404399

405400

tests/test_output_effort_policy.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
"""Tests for pure output effort policy decisions."""
2+
3+
from __future__ import annotations
4+
5+
from headroom.proxy.output_effort_policy import (
6+
LEGACY_THINKING_FLOOR,
7+
can_create_openai_text_verbosity,
8+
clamp_legacy_thinking_budget,
9+
lower_effort_value,
10+
lower_text_verbosity_value,
11+
)
12+
13+
14+
def test_lower_effort_value_lowers_known_higher_effort_to_target() -> None:
15+
assert lower_effort_value("xhigh", "low") == "low"
16+
assert lower_effort_value("max", "medium") == "medium"
17+
18+
19+
def test_lower_effort_value_keeps_lower_equal_unknown_or_non_string_values() -> None:
20+
assert lower_effort_value("low", "medium") is None
21+
assert lower_effort_value("medium", "medium") is None
22+
assert lower_effort_value("turbo", "low") is None
23+
assert lower_effort_value("high", "turbo") is None
24+
assert lower_effort_value(None, "low") is None
25+
26+
27+
def test_clamp_legacy_thinking_budget_only_clamps_enabled_over_floor() -> None:
28+
assert (
29+
clamp_legacy_thinking_budget(
30+
thinking_type="enabled",
31+
budget_tokens=32_000,
32+
)
33+
== LEGACY_THINKING_FLOOR
34+
)
35+
assert (
36+
clamp_legacy_thinking_budget(
37+
thinking_type="enabled",
38+
budget_tokens=LEGACY_THINKING_FLOOR,
39+
)
40+
is None
41+
)
42+
assert clamp_legacy_thinking_budget(thinking_type="adaptive", budget_tokens=32_000) is None
43+
assert clamp_legacy_thinking_budget(thinking_type="enabled", budget_tokens="32000") is None
44+
45+
46+
def test_can_create_openai_text_verbosity_only_for_gpt5_family() -> None:
47+
assert can_create_openai_text_verbosity("gpt-5")
48+
assert can_create_openai_text_verbosity("GPT-5.1")
49+
assert not can_create_openai_text_verbosity("gpt-4o")
50+
assert not can_create_openai_text_verbosity(None)
51+
52+
53+
def test_lower_text_verbosity_value_lowers_existing_verbose_values() -> None:
54+
assert lower_text_verbosity_value("medium") == "low"
55+
assert lower_text_verbosity_value("high") == "low"
56+
assert lower_text_verbosity_value("low") is None
57+
assert lower_text_verbosity_value("chatty") is None
58+
assert lower_text_verbosity_value(None) is None

0 commit comments

Comments
 (0)