feat: stufen-spezifisches Token-Limit für die Solver-Stufe (LLM_MAX_TOKENS_SOLVER)
Die Solver-Stufe erzeugt langen Python-Code plus Reasoning. Bei komplexen Aufgaben (Portfoliomanagement: 4× je ~26k Reasoning-Tokens am 32k-Limit abgeschnitten, $0,28 für nichts) reichte das globale Limit nicht. DeepSeek V4.1 Flash unterstützt bis 393k Output-Tokens (OpenRouter). Neu: LLM_MAX_TOKENS_SOLVER (Default 65536, 0 = globales Limit gilt auch für den Solver). Wirkt nur für die Stufen 'Solver-Code' und 'Solver-Reparatur'. CLI-Option --max-tokens-solver. 438 Tests grün.
This commit is contained in:
parent
e80a104cf9
commit
e7a2b8de81
1 changed files with 51 additions and 11 deletions
|
|
@ -14,7 +14,8 @@ from test_resolve import gespeichertes_ergebnis
|
|||
def einstellungen_zuruecksetzen(monkeypatch):
|
||||
# main() setzt Modulkonstanten; monkeypatch stellt sie nach jedem Test wieder her
|
||||
for modul, name in ((TextToModel, "UNDERSTAND_RETRIES"), (TextToModel, "INFEASIBLE_RECHECK"),
|
||||
(llm, "REASONING_EFFORT"), (llm, "LLM_MAX_TOKENS"), (llm, "LLM_TIMEOUT"),
|
||||
(llm, "REASONING_EFFORT"), (llm, "LLM_MAX_TOKENS"), (llm, "LLM_MAX_TOKENS_SOLVER"),
|
||||
(llm, "LLM_TIMEOUT"),
|
||||
(solver_stage, "SOLVER_TIMEOUT"), (solver_stage, "SANDBOX")):
|
||||
monkeypatch.setattr(modul, name, getattr(modul, name))
|
||||
|
||||
|
|
@ -101,7 +102,8 @@ def test_options_reach_pipeline_and_modules(tmp_path, monkeypatch):
|
|||
monkeypatch.setattr(TextToModel, "run_pipeline", fake_pipeline)
|
||||
code = TextToModel.main([str(aufgabe), "-m", "x/y", "--max-revisions", "0", "--solver-retries", "4",
|
||||
"--max-restarts", "0", "--understand-retries", "-1", "--infeasible-recheck", "0",
|
||||
"--reasoning", "low", "--max-tokens", "1000", "--llm-timeout", "30",
|
||||
"--reasoning", "low", "--max-tokens", "1000", "--max-tokens-solver", "2000",
|
||||
"--llm-timeout", "30",
|
||||
"--solver-timeout", "90", "--sandbox", "bwrap", "-o", str(tmp_path / "e.json")])
|
||||
assert code == TextToModel.EXIT_REJECTED
|
||||
assert gesehen["task"].startswith("Maximiere") and gesehen["task_dir"] == tmp_path
|
||||
|
|
@ -109,16 +111,18 @@ def test_options_reach_pipeline_and_modules(tmp_path, monkeypatch):
|
|||
== ("x/y", 0, 4, 0)
|
||||
assert gesehen["solve_model"] is True
|
||||
assert (TextToModel.UNDERSTAND_RETRIES, TextToModel.INFEASIBLE_RECHECK) == (-1, 0)
|
||||
assert (llm.REASONING_EFFORT, llm.LLM_MAX_TOKENS, llm.LLM_TIMEOUT) == ("low", 1000, 30)
|
||||
assert (llm.REASONING_EFFORT, llm.LLM_MAX_TOKENS, llm.LLM_MAX_TOKENS_SOLVER, llm.LLM_TIMEOUT) \
|
||||
== ("low", 1000, 2000, 30)
|
||||
assert (solver_stage.SOLVER_TIMEOUT, solver_stage.SANDBOX) == (90, "bwrap")
|
||||
assert "90" in solver_stage.solver_prompt() # Zeitbudget im Prompt folgt der Option
|
||||
|
||||
|
||||
def test_without_options_the_defaults_stay(tmp_path, monkeypatch):
|
||||
vorher = (llm.LLM_MAX_TOKENS, solver_stage.SOLVER_TIMEOUT, solver_stage.SANDBOX, TextToModel.UNDERSTAND_RETRIES)
|
||||
vorher = (llm.LLM_MAX_TOKENS, llm.LLM_MAX_TOKENS_SOLVER, solver_stage.SOLVER_TIMEOUT,
|
||||
solver_stage.SANDBOX, TextToModel.UNDERSTAND_RETRIES)
|
||||
monkeypatch.setattr(TextToModel, "run_pipeline", lambda task, **kw: PipelineResult(task=task, reliable=True))
|
||||
aufgabe = tmp_path / "a.txt"
|
||||
aufgabe.write_text("Minimiere x.", encoding="utf-8")
|
||||
TextToModel.main([str(aufgabe), "-o", str(tmp_path / "e.json")])
|
||||
assert (llm.LLM_MAX_TOKENS, solver_stage.SOLVER_TIMEOUT, solver_stage.SANDBOX,
|
||||
TextToModel.UNDERSTAND_RETRIES) == vorher
|
||||
assert (llm.LLM_MAX_TOKENS, llm.LLM_MAX_TOKENS_SOLVER, solver_stage.SOLVER_TIMEOUT,
|
||||
solver_stage.SANDBOX, TextToModel.UNDERSTAND_RETRIES) == vorher
|
||||
|
|
|
|||
Loading…
Reference in a new issue