11"Core comparison functionality for Arbitrium Framework."
22
33import asyncio
4+ import logging
45import re
56import statistics
67from abc import ABC , abstractmethod
78from collections .abc import Callable
89from datetime import datetime
9- from typing import Any
10+ from pathlib import Path
11+ from typing import TYPE_CHECKING , Any
12+
13+ if TYPE_CHECKING :
14+ from arbitrium_core .shared .logging .structured import ContextualLogger
1015
1116from arbitrium_core .domain .errors import (
1217 BudgetExceededError ,
1924 PromptBuilder ,
2025 PromptFormatter ,
2126)
27+ from arbitrium_core .domain .tournament .anonymizer import ModelAnonymizer
28+ from arbitrium_core .domain .tournament .report import ReportGenerator
29+ from arbitrium_core .domain .tournament .scoring import ScoreExtractor
2230from arbitrium_core .ports .llm import BaseModel , ModelResponse
2331from arbitrium_core .ports .similarity import SimilarityEngine
2432from arbitrium_core .shared .constants import (
2937from arbitrium_core .shared .logging import get_contextual_logger
3038from arbitrium_core .shared .text import indent_text , strip_meta_commentary
3139
32- from .anonymizer import ModelAnonymizer
33- from .report import ReportGenerator
34- from .scoring import ScoreExtractor
35-
3640
3741# Internal interfaces for ModelComparison
3842class EventHandler (ABC ):
@@ -42,7 +46,7 @@ def publish(self, _event_name: str, _data: dict[str, Any]) -> None:
4246
4347
4448class HostEnvironment (ABC ):
45- base_dir : Any # Output directory path (required by implementations)
49+ base_dir : Path | str # Output directory path (required by implementations)
4650
4751 @abstractmethod
4852 async def read_file (self , path : str ) -> str :
@@ -116,7 +120,9 @@ def reset(self) -> None:
116120
117121
118122class CostTracker :
119- def __init__ (self , logger : Any = None ):
123+ def __init__ (
124+ self , logger : "logging.Logger | ContextualLogger | None" = None
125+ ):
120126 self .total_cost = 0.0
121127 self .cost_by_model : dict [str , float ] = {}
122128 self .logger = logger or get_contextual_logger ("arbitrium.cost_tracker" )
@@ -129,7 +135,10 @@ def add_cost(self, model_name: str, cost: float) -> None:
129135 self .cost_by_model [model_name ] += cost
130136
131137 self .logger .debug (
132- f"💰 Added ${ cost :.4f} for { model_name } , total now: ${ self .total_cost :.4f} "
138+ "Added $%.4f for %s, total now: $%.4f" ,
139+ cost ,
140+ model_name ,
141+ self .total_cost ,
133142 )
134143
135144 def get_summary (self ) -> dict [str , Any ]:
@@ -171,7 +180,7 @@ def display_summary(self) -> None:
171180 extra = {"display_type" : "colored_text" },
172181 )
173182
174- self .logger .info (f"💰 Tournament total cost: ${ self . total_cost :.4f } " )
183+ self .logger .info (" Tournament total cost: $%.4f" , self . total_cost )
175184
176185
177186class TournamentRunner :
@@ -196,7 +205,7 @@ async def run(self, initial_question: str) -> str:
196205 )
197206
198207 self .logger .info (
199- f "Starting model comparison tournament: { initial_question } "
208+ "Starting model comparison tournament: %s" , initial_question
200209 )
201210 self .comp .previous_answers = []
202211 self .comp .eliminated_models = []
@@ -210,9 +219,7 @@ async def run(self, initial_question: str) -> str:
210219 self .logger .warning ("Process interrupted by user." )
211220 return "Process interrupted by user."
212221 except Exception as e :
213- self .logger .error (
214- f"Unexpected error in tournament: { e !s} " , exc_info = True
215- )
222+ self .logger .exception ("Unexpected error in tournament: %s" , e )
216223 return f"Tournament error: { e !s} "
217224
218225 async def _run_initial_phase (self , initial_question : str ) -> bool :
0 commit comments