|
@@ -212,7 +212,11 @@ class TimingChatClient:
|
|
|
if first_item_at is None:
|
|
if first_item_at is None:
|
|
|
first_item_at = item_at
|
|
first_item_at = item_at
|
|
|
first_item_kind = item.kind
|
|
first_item_kind = item.kind
|
|
|
- if item.kind == "message_delta" and first_message_delta_at is None:
|
|
|
|
|
|
|
+ if (
|
|
|
|
|
+ item.kind == "message_delta"
|
|
|
|
|
+ and (item.content or "").strip()
|
|
|
|
|
+ and first_message_delta_at is None
|
|
|
|
|
+ ):
|
|
|
first_message_delta_at = item_at
|
|
first_message_delta_at = item_at
|
|
|
if item.kind == "usage" and item.usage is not None:
|
|
if item.kind == "usage" and item.usage is not None:
|
|
|
usage = item.usage
|
|
usage = item.usage
|
|
@@ -253,6 +257,8 @@ class BenchmarkExpectation(_FrozenStrictBenchmarkModel):
|
|
|
visible_messages: tuple[str, ...]
|
|
visible_messages: tuple[str, ...]
|
|
|
event_names: tuple[str, ...]
|
|
event_names: tuple[str, ...]
|
|
|
answer_count: int = Field(ge=1)
|
|
answer_count: int = Field(ge=1)
|
|
|
|
|
+ expected_model_call_count: int = Field(ge=1)
|
|
|
|
|
+ expected_fallback_count: int = Field(ge=0)
|
|
|
terminal: bool
|
|
terminal: bool
|
|
|
first_reply_before_tool: bool
|
|
first_reply_before_tool: bool
|
|
|
|
|
|
|
@@ -340,6 +346,8 @@ BENCHMARK_CASE_CATALOG: Mapping[BenchmarkCaseId, BenchmarkCase] = MappingProxyTy
|
|
|
visible_messages=("Ordinary answer.",),
|
|
visible_messages=("Ordinary answer.",),
|
|
|
event_names=(),
|
|
event_names=(),
|
|
|
answer_count=1,
|
|
answer_count=1,
|
|
|
|
|
+ expected_model_call_count=1,
|
|
|
|
|
+ expected_fallback_count=0,
|
|
|
terminal=False,
|
|
terminal=False,
|
|
|
first_reply_before_tool=False,
|
|
first_reply_before_tool=False,
|
|
|
),
|
|
),
|
|
@@ -354,6 +362,8 @@ BENCHMARK_CASE_CATALOG: Mapping[BenchmarkCaseId, BenchmarkCase] = MappingProxyTy
|
|
|
visible_messages=("I will set the volume to 30.",),
|
|
visible_messages=("I will set the volume to 30.",),
|
|
|
event_names=("device.volume.adjust",),
|
|
event_names=("device.volume.adjust",),
|
|
|
answer_count=1,
|
|
answer_count=1,
|
|
|
|
|
+ expected_model_call_count=1,
|
|
|
|
|
+ expected_fallback_count=0,
|
|
|
terminal=False,
|
|
terminal=False,
|
|
|
first_reply_before_tool=True,
|
|
first_reply_before_tool=True,
|
|
|
),
|
|
),
|
|
@@ -377,6 +387,8 @@ BENCHMARK_CASE_CATALOG: Mapping[BenchmarkCaseId, BenchmarkCase] = MappingProxyTy
|
|
|
visible_messages=("I will schedule that.", _SCHEDULE_CONFIRMATION),
|
|
visible_messages=("I will schedule that.", _SCHEDULE_CONFIRMATION),
|
|
|
event_names=("calendar.schedule.create",),
|
|
event_names=("calendar.schedule.create",),
|
|
|
answer_count=2,
|
|
answer_count=2,
|
|
|
|
|
+ expected_model_call_count=1,
|
|
|
|
|
+ expected_fallback_count=0,
|
|
|
terminal=False,
|
|
terminal=False,
|
|
|
first_reply_before_tool=True,
|
|
first_reply_before_tool=True,
|
|
|
),
|
|
),
|
|
@@ -397,6 +409,8 @@ BENCHMARK_CASE_CATALOG: Mapping[BenchmarkCaseId, BenchmarkCase] = MappingProxyTy
|
|
|
visible_messages=("I will check.", "Grounded search update."),
|
|
visible_messages=("I will check.", "Grounded search update."),
|
|
|
event_names=("knowledge.web.search",),
|
|
event_names=("knowledge.web.search",),
|
|
|
answer_count=2,
|
|
answer_count=2,
|
|
|
|
|
+ expected_model_call_count=2,
|
|
|
|
|
+ expected_fallback_count=0,
|
|
|
terminal=False,
|
|
terminal=False,
|
|
|
first_reply_before_tool=True,
|
|
first_reply_before_tool=True,
|
|
|
),
|
|
),
|
|
@@ -417,6 +431,8 @@ BENCHMARK_CASE_CATALOG: Mapping[BenchmarkCaseId, BenchmarkCase] = MappingProxyTy
|
|
|
visible_messages=("Goodbye.",),
|
|
visible_messages=("Goodbye.",),
|
|
|
event_names=("session.terminate",),
|
|
event_names=("session.terminate",),
|
|
|
answer_count=1,
|
|
answer_count=1,
|
|
|
|
|
+ expected_model_call_count=1,
|
|
|
|
|
+ expected_fallback_count=0,
|
|
|
terminal=True,
|
|
terminal=True,
|
|
|
first_reply_before_tool=True,
|
|
first_reply_before_tool=True,
|
|
|
),
|
|
),
|
|
@@ -443,6 +459,8 @@ BENCHMARK_CASE_CATALOG: Mapping[BenchmarkCaseId, BenchmarkCase] = MappingProxyTy
|
|
|
"calendar.schedule.create",
|
|
"calendar.schedule.create",
|
|
|
),
|
|
),
|
|
|
answer_count=2,
|
|
answer_count=2,
|
|
|
|
|
+ expected_model_call_count=1,
|
|
|
|
|
+ expected_fallback_count=0,
|
|
|
terminal=False,
|
|
terminal=False,
|
|
|
first_reply_before_tool=True,
|
|
first_reply_before_tool=True,
|
|
|
),
|
|
),
|
|
@@ -596,8 +614,11 @@ class _BenchmarkOutputQueue(asyncio.Queue[dict[str, Any]]):
|
|
|
self.first_message_delta_at: float | None = None
|
|
self.first_message_delta_at: float | None = None
|
|
|
|
|
|
|
|
async def put(self, item: dict[str, Any]) -> None:
|
|
async def put(self, item: dict[str, Any]) -> None:
|
|
|
|
|
+ content = item.get("content")
|
|
|
if (
|
|
if (
|
|
|
item.get("type") == "message_delta"
|
|
item.get("type") == "message_delta"
|
|
|
|
|
+ and isinstance(content, str)
|
|
|
|
|
+ and content.strip()
|
|
|
and self.first_message_delta_at is None
|
|
and self.first_message_delta_at is None
|
|
|
):
|
|
):
|
|
|
self.first_message_delta_at = self.clock()
|
|
self.first_message_delta_at = self.clock()
|
|
@@ -886,6 +907,27 @@ class BenchmarkRunner:
|
|
|
timing_fallback_count = sum(
|
|
timing_fallback_count = sum(
|
|
|
timing.call_kind == "argument_fallback" for timing in timings
|
|
timing.call_kind == "argument_fallback" for timing in timings
|
|
|
)
|
|
)
|
|
|
|
|
+ if model_call_count != expected.expected_model_call_count:
|
|
|
|
|
+ failures.append(
|
|
|
|
|
+ "model_call_count expected "
|
|
|
|
|
+ f"{expected.expected_model_call_count}, ledger got {model_call_count}"
|
|
|
|
|
+ )
|
|
|
|
|
+ if timing_chat_count != expected.expected_model_call_count:
|
|
|
|
|
+ failures.append(
|
|
|
|
|
+ "model_call_count expected "
|
|
|
|
|
+ f"{expected.expected_model_call_count}, timing got {timing_chat_count}"
|
|
|
|
|
+ )
|
|
|
|
|
+ if fallback_count != expected.expected_fallback_count:
|
|
|
|
|
+ failures.append(
|
|
|
|
|
+ "fallback_count expected "
|
|
|
|
|
+ f"{expected.expected_fallback_count}, ledger got {fallback_count}"
|
|
|
|
|
+ )
|
|
|
|
|
+ if timing_fallback_count != expected.expected_fallback_count:
|
|
|
|
|
+ failures.append(
|
|
|
|
|
+ "fallback_count expected "
|
|
|
|
|
+ f"{expected.expected_fallback_count}, timing got "
|
|
|
|
|
+ f"{timing_fallback_count}"
|
|
|
|
|
+ )
|
|
|
if model_call_count != timing_chat_count:
|
|
if model_call_count != timing_chat_count:
|
|
|
failures.append(
|
|
failures.append(
|
|
|
f"model_call_count ledger={model_call_count}, timing={timing_chat_count}"
|
|
f"model_call_count ledger={model_call_count}, timing={timing_chat_count}"
|