6c9c7fe7f3
CI / integration tests (3.13) (push) Failing after 1s
Commit lint / pull request title (push) Has been skipped
Docs / links (push) Failing after 1s
CI / unit tests (3.13) (push) Failing after 1s
CI / lint (push) Failing after 1s
CI / integration tests (push) Failing after 1s
CI / package build (push) Failing after 1s
Commit lint / commit messages (push) Failing after 1s
CI / unit tests (push) Failing after 1s
158 lines
4.5 KiB
Python
158 lines
4.5 KiB
Python
"""Benchmark configuration.
|
|
|
|
Frozen Pydantic model providing all tunable parameters for the LoCoMo
|
|
benchmark pipeline. Defaults are aligned with the upstream evaluation
|
|
reference so that numbers are directly comparable.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import tomllib
|
|
from pathlib import Path
|
|
from typing import Literal
|
|
|
|
from pydantic import BaseModel, ConfigDict
|
|
|
|
|
|
class BenchmarkConfig(BaseModel):
|
|
"""Immutable benchmark configuration.
|
|
|
|
Args:
|
|
cascade_timeout: Max seconds to wait for cascade queue to drain after flush.
|
|
batch_size: Messages per /add request.
|
|
methods: Comma-separated search methods.
|
|
top_k: Number of episodes to retrieve per question.
|
|
eval_owner: Which speaker's memory partition to query.
|
|
answer_model: LLM model for the Answer phase.
|
|
answer_temperature: Sampling temperature for answers.
|
|
answer_max_tokens: Max output tokens per answer call.
|
|
answer_timeout: Per-request timeout (seconds) for the answer LLM.
|
|
answer_max_retries: Retry budget for the answer phase.
|
|
judge_model: LLM model for the Judge phase.
|
|
judge_temperature: Sampling temperature for judging.
|
|
judge_timeout: Per-request timeout (seconds) for the judge LLM.
|
|
judge_max_retries: Retry budget for the judge phase.
|
|
judge_runs: Independent judge evaluations per question (majority vote).
|
|
conversations_concurrency: How many conversations run at the same time.
|
|
eval_concurrency: How many questions are processed in parallel within each conversation.
|
|
"""
|
|
|
|
model_config = ConfigDict(frozen=True)
|
|
|
|
# --- EverOS server ---
|
|
cascade_timeout: int = 7200
|
|
batch_size: int = 25
|
|
|
|
# --- Search ---
|
|
methods: str = "agentic"
|
|
top_k: int = 10
|
|
eval_owner: Literal["speaker_a", "speaker_b"] = "speaker_a"
|
|
|
|
# --- Answer LLM ---
|
|
answer_model: str = "gpt-4.1-mini"
|
|
answer_temperature: float = 0.0
|
|
answer_max_tokens: int = 32768
|
|
answer_timeout: float = 300.0
|
|
answer_max_retries: int = 5
|
|
|
|
# --- Judge LLM ---
|
|
judge_model: str = "gpt-4o-mini"
|
|
judge_temperature: float = 0.0
|
|
judge_timeout: float = 300.0
|
|
judge_max_retries: int = 5
|
|
judge_runs: int = 3
|
|
|
|
# --- Concurrency ---
|
|
conversations_concurrency: int = 10
|
|
eval_concurrency: int = 20
|
|
search_concurrency: int = 5
|
|
|
|
@property
|
|
def parsed_methods(self) -> list[str]:
|
|
"""Split comma-separated methods string into a list."""
|
|
return [m.strip() for m in self.methods.split(",") if m.strip()]
|
|
|
|
@classmethod
|
|
def from_toml(
|
|
cls, name: str = "config", *, config_dir: Path | None = None
|
|
) -> BenchmarkConfig:
|
|
"""Load config from a TOML file.
|
|
|
|
Args:
|
|
name: Config name without .toml extension.
|
|
config_dir: Directory containing config files.
|
|
Falls back to ``benchmarks/`` relative to the repo root.
|
|
|
|
Raises:
|
|
FileNotFoundError: When the TOML file does not exist.
|
|
"""
|
|
if config_dir is None:
|
|
config_dir = Path(__file__).parent
|
|
path = config_dir / f"{name}.toml"
|
|
if not path.exists():
|
|
raise FileNotFoundError(f"Config file not found: {path}")
|
|
with open(path, "rb") as f:
|
|
overrides = tomllib.load(f)
|
|
return cls(**overrides)
|
|
|
|
|
|
class SearchResult(BaseModel):
|
|
"""One QA pair's search stage output."""
|
|
|
|
model_config = ConfigDict(frozen=True)
|
|
|
|
index: int
|
|
question: str
|
|
golden_answer: str
|
|
category: int | None
|
|
evidence: list[str]
|
|
episodes: list[dict]
|
|
profiles: list[dict]
|
|
search_time_s: float
|
|
method: str
|
|
|
|
|
|
class AnswerResult(BaseModel):
|
|
"""One QA pair's answer stage output."""
|
|
|
|
model_config = ConfigDict(frozen=True)
|
|
|
|
index: int
|
|
question: str
|
|
golden_answer: str
|
|
category: int | None
|
|
generated_answer: str
|
|
answer_time_s: float
|
|
answer_attempts: int
|
|
answer_tokens: int = 0
|
|
|
|
|
|
class JudgeResult(BaseModel):
|
|
"""One QA pair's judge stage output."""
|
|
|
|
model_config = ConfigDict(frozen=True)
|
|
|
|
index: int
|
|
question: str
|
|
golden_answer: str
|
|
generated_answer: str
|
|
category: int | None
|
|
is_correct: bool
|
|
judgments: list[bool]
|
|
judge_tokens: int = 0
|
|
|
|
|
|
class RunSpec(BaseModel):
|
|
"""Reproducibility snapshot serialized at run start."""
|
|
|
|
model_config = ConfigDict(frozen=True)
|
|
|
|
run_name: str
|
|
config: dict
|
|
conversations: list[int]
|
|
stages: list[str]
|
|
git_hash: str
|
|
python_version: str
|
|
everos_version: str
|
|
started_at: str
|