stage20: context budgeting - per-stage token limits (planner 12k, claim 16k, contradiction 24k, synthesis 48k)
Implemented: - context_budget.py: ContextBudgetConfig (Pydantic, frozen) mit 4 Stage-Limits, validation (ge/le), get_limit(), total_max_tokens, stage_keys - context_budget.py: ContextBudgetTracker mit track_tokens(), get_usage(), is_exhausted(), reset_stage(), reset_all(), total_usage, elapsed_seconds - context_budget.py: ContextBudgetExhaustedError mit stage_name, used_tokens, limit_tokens - orchestrator.py: _track_context_tokens() Methode, context_budget_config/tracker init - orchestrator.py: context_budget_tracker property export - __init__.py: exports ContextBudgetConfig, ContextBudgetExhaustedError, ContextBudgetTracker - priority_queue.py: __aenter__/__aexit__ auf async geandert (Testfix) - test_context_budget.py: 28 Tests (DefaultConfig, TrackAccumulation, ExhaustedError, GetUsage, Reset, IsExhausted, InvalidStageNames, InvalidTokens) - test_context_budget_integration.py: 6 Tests (Orchestrator-Integration) - HANDOFF.md: Stage 20 abgeschlossen dokumentiert Tests: 34 passed (28 unit + 6 integration) + 14 performance = 48 total
This commit is contained in:
@@ -30,6 +30,11 @@ from nsct.metrics import (
|
||||
)
|
||||
from nsct.models.claim import Claim
|
||||
from nsct.orchestration.budget import BudgetExhaustedError, BudgetTracker, HardBudgetConfig
|
||||
from nsct.orchestration.context_budget import (
|
||||
ContextBudgetConfig,
|
||||
ContextBudgetExhaustedError,
|
||||
ContextBudgetTracker,
|
||||
)
|
||||
from nsct.orchestration.models import ResearchRun
|
||||
from nsct.orchestration.state import ResearchRunState, StateMachine
|
||||
from nsct.providers.abstract import MultiProviderSearch, SearchProvider
|
||||
@@ -61,6 +66,7 @@ class ResearchOrchestrator:
|
||||
research_id: UUID,
|
||||
query: str,
|
||||
budget_config: HardBudgetConfig | None = None,
|
||||
context_budget_config: ContextBudgetConfig | None = None,
|
||||
depth: str = "normal",
|
||||
priority: Priority = Priority.NORMAL,
|
||||
) -> None:
|
||||
@@ -76,6 +82,8 @@ class ResearchOrchestrator:
|
||||
Die Forschungsfrage / Query.
|
||||
budget_config : HardBudgetConfig | None
|
||||
Optionales Budget. Wird aus config abgeleitet, wenn None.
|
||||
context_budget_config : ContextBudgetConfig | None
|
||||
Optionales Context-Budget. Wird aus config abgeleitet, wenn None.
|
||||
depth : str
|
||||
Suchtiefe ("quick", "normal", "deep").
|
||||
priority : Priority
|
||||
@@ -94,6 +102,13 @@ class ResearchOrchestrator:
|
||||
self._budget_config = HardBudgetConfig()
|
||||
self._budget_tracker = BudgetTracker(self._budget_config)
|
||||
|
||||
# Context Budget (Stage 20)
|
||||
if context_budget_config is not None:
|
||||
self._context_budget_config = context_budget_config
|
||||
else:
|
||||
self._context_budget_config = ContextBudgetConfig()
|
||||
self._context_budget_tracker = ContextBudgetTracker(self._context_budget_config)
|
||||
|
||||
# State Machine & Run
|
||||
self._state_machine = StateMachine(ResearchRunState.CREATED)
|
||||
self._run: ResearchRun | None = None
|
||||
@@ -131,6 +146,11 @@ class ResearchOrchestrator:
|
||||
"""BudgetTracker des aktuellen Runs."""
|
||||
return self._budget_tracker
|
||||
|
||||
@property
|
||||
def context_budget_tracker(self) -> ContextBudgetTracker:
|
||||
"""ContextBudgetTracker des aktuellen Runs (Stage 20)."""
|
||||
return self._context_budget_tracker
|
||||
|
||||
@property
|
||||
def is_completed(self) -> bool:
|
||||
"""True, wenn State == COMPLETED."""
|
||||
@@ -209,6 +229,24 @@ class ResearchOrchestrator:
|
||||
"""
|
||||
self._budget_tracker.check_budget()
|
||||
|
||||
def _track_context_tokens(self, stage_name: str, tokens: int) -> None:
|
||||
"""Tracke verbrauchte Token fuer Context Budgeting (Stage 20).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
stage_name : str
|
||||
Human-readable stage name (e.g. 'planner', 'claim_extraction',
|
||||
'contradiction', 'synthesis').
|
||||
tokens : int
|
||||
Number of tokens consumed.
|
||||
|
||||
Raises
|
||||
------
|
||||
ContextBudgetExhaustedError
|
||||
Wenn das Budget fuer die Stage erreicht ist.
|
||||
"""
|
||||
self._context_budget_tracker.track_tokens(stage_name, tokens)
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# Private: Sub-Component Init
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user