kaggle-benchmarks
Write benchmark tasks to evaluate LLMs using the kaggle_benchmarks Python library. Covers task decorators, structured outputs, assertions, tools, dataset evaluation (including failure-tolerant retry patterns for large datasets), and multi-turn conversations.
소스 정보
- 저장소
- Kaggle/kaggle-benchmarks
- 최근 소스 활동
- 2026년 6월 24일 21:49
- 감지된 SKILL.md 언어
- 영어
- 스타
- 201
- 포크
- 55
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
파일 탐색기
2 개 파일SKILL.md 표시 중
SKILL.md
소스 지침 · 읽기 전용 미리보기- name
- kaggle-benchmarks
- version
- 0.7.0
- description
- Write benchmark tasks to evaluate LLMs using the kaggle_benchmarks Python library. Covers task decorators, structured outputs, assertions, tools, dataset evaluation (including failure-tolerant retry patterns for large datasets), and multi-turn conversations.
# Skill: Writing Kaggle Benchmarks Tasks
> This skill file teaches you how to write high-quality benchmark tasks using the `kaggle-benchmarks` Python library (version 0.7.0+).
> Always verify patterns against the actual source code in `src/kaggle_benchmarks/` when in doubt.
## Quick Reference
```python
import kaggle_benchmarks as kbench
```
| Symbol | Purpose |
|--------|---------|
| `kbench.task` / `kbench.benchmark` | Decorator to define a benchmark task |
| `kbench.llm` | Default LLM actor (available when Kaggle is configured) |
| `kbench.judge_llm` | Judge LLM for evaluation |
| `kbench.llms` | Dict of all available models (e.g. `kbench.llms["google/gemini-2.5-flash"]`) |
| `kbench.assertions` | Module with all assertion functions |
| `kbench.chats` | Conversation/chat context management |
| `kbench.ChatRoom` / `kbench.Participant` | Multi-agent conversation room with perspective-aware history |
| `kbench.tools` | Built-in tools (Python runner, etc.) |
| `kbench.user` / `kbench.actors.user` | Send user messages to conversation |
| `kbench.system` / `kbench.actors.system` | Send system-level messages |
| `kbench.last_reasoning_traces()` | Access reasoning traces from last prompt |
| `kbench.content_types.images` | Image input helpers |
| `kbench.content_types.videos` | Video input helpers |
| `kbench.content_types.audios` | Audio input helpers |
| `kbench.client` | Client for caching, storage |
## Minimal Examples
### Simple assertion check
```python
import kaggle_benchmarks as kbench
@kbench.task(name="geography_quiz")
def geography_quiz(llm):
response = llm.prompt("What is the longest river in the world?")
kbench.assertions.assert_contains_regex(
r"(?i)nile", response,
expectation="Should mention the Nile river."
)
geography_quiz.run(kbench.llm)
```
### Evaluating a list of questions
```python
import kaggle_benchmarks as kbench
import pandas as pd
@kbench.task(name="math_qa", store_task=False)
def math_qa(llm, question, expected) -> bool:
answer = llm.prompt(question + "\nAnswer with just the number.", schema=int)
kbench.assertions.assert_equal(expected, answer)
return answer == expected
# %%
df = pd.DataFrame([
{"question": "What is 15% of 200?", "expected": 30},
{"question": "What is 7 × 8?", "expected": 56},
])
@kbench.task(name="math_benchmark")
def math_benchmark(llm) -> float:
results = math_qa.evaluate(llm=[llm], evaluation_data=df, n_jobs=2)
scores = results.as_dataframe()
return float(scores.result.mean())
math_benchmark.run(kbench.llm)
```
## Key Rules
- The first parameter of every task function **must** be the LLM actor.
- If your task returns a value, you **MUST** add a return type annotation (`-> float`, `-> bool`, `-> dict`, etc.).
- Use `kbench.assertions.*` instead of Python `assert` — library assertions are recorded and tracked.
- Always check `assess_response_with_judge` for `None` before using the result.
- Do NOT wrap `.run()` or `.evaluate()` calls inside `if __name__ == "__main__":`. Benchmark files are notebook-style scripts — all code runs at the top level.
- Use `# %%` cell markers to create logical sections in benchmark files.
- Prefer `# !pip install ...` (commented) over `!pip install ...` so the file works everywhere.
- Use `store_task=False` for sub-tasks called inside other tasks.
## Common Mistakes to Avoid
| Mistake | Correct Approach |
|---------|-----------------|
| Missing return type annotation on scoring task | Add `-> float`, `-> bool`, `-> dict`, etc. |
| Using Python `assert` instead of `kbench.assertions.*` | Use library assertions — they're recorded and tracked |
| Not checking `assess_response_with_judge` for `None` | Always check: `if assessment is None:` |
| Using `kbench.llm` locally without Kaggle configured | Run `kaggle benchmarks init` to configure, or set env vars |
| Forgetting `schema=` when needing structured output | Pass `schema=MyDataclass` to `llm.prompt()` |
| Wrapping `.run()` / `.evaluate()` in `if __name__ == "__main__":` | Place them at module top level — benchmark files are scripts, not importable modules |
| Using `user.send()` with image URLs | `user.send()` passes URLs as-is; prefer `llm.prompt(image=)` for auto-conversion |
| Not isolating judge conversations | Use `with kbench.chats.new("judge"):` |
| Multiple tasks sharing conversation history | Each `.run()` creates its own conversation |
| Using `store_task=True` for sub-tasks | Set `store_task=False` for helper tasks called inside other tasks |
| Using `!pip install` without commenting | Use `# !pip install -q pkg` — uncommented magics break local execution |
| Forgetting `last_reasoning_traces()` can be `None` | Always check: `traces = kbench.last_reasoning_traces(); if traces: ...` |
| Aggregating over all runs after `on_failure="continue"` | Filter first: `results.completed_runs.as_dataframe().result.mean()` — failed runs carry the `results.FAILED` sentinel which breaks `.mean()` / `.sum()` |
| Using `max_attempts > 1` without `on_failure="continue"` | The default `"raise"` aborts on first failure, so retries never happen. Pair `max_attempts > 1` with `on_failure="continue"` and `enable_cache()` for selective retry. |
---
## §1. Import Styles
There are two main import styles. **Prefer Style A** for clarity.
### Style A: Module import (Preferred)
```python
import kaggle_benchmarks as kbench
@kbench.task(name="my_task")
def my_task(llm):
response = llm.prompt("Question?")
kbench.assertions.assert_true(True)
```
### Style B: Direct imports
```python
from kaggle_benchmarks import assertions, chats, llm, task, system, user
@task("my_task")
def my_task(llm):
response = llm.prompt("Question?")
assertions.assert_true(True)
```
Style B is shorter but risks name collisions (e.g., `llm` is both a module-level variable and a task parameter).
### File Structure: Cell Markers
Benchmark files are Python scripts (`.py`), but use `# %%` cell markers to create logical sections. This makes them runnable as both standalone Python files and as interactive notebooks (via Jupyter/VS Code cell execution).
```python
# %%
import kaggle_benchmarks as kbench
# %%
@kbench.task()
def my_task(llm):
response = llm.prompt("Hello!")
kbench.assertions.assert_not_empty(response)
my_task.run(kbench.llm)
# %%
@kbench.task()
def another_task(llm) -> float:
...
```
**IPython magics (`!pip install`, `%time`, etc.):** These work on Kaggle notebooks but NOT when running as standalone Python files. If you need a magic command (e.g., to install a dependency), comment it out so the file remains runnable locally:
```python
# %%
# !pip install -q pronouncing syllables # Uncomment on Kaggle
import pronouncing
```
> **Rule:** Prefer `# !pip install ...` (commented) over `!pip install ...` so the file works everywhere. Only use uncommented magics when the file is exclusively for Kaggle notebook execution.
**IMPORTANT — No `if __name__` guards.** Think of benchmark `.py` files as notebooks, not modules. They are never imported — they are always executed directly.
```python
# ❌ WRONG — do not do this
if __name__ == "__main__":
my_task.run(kbench.llm)
# ✅ CORRECT — top-level, in its own cell
# %%
my_task.run(kbench.llm)
```
---
## §2. Defining Tasks
### `@kbench.task()` Parameters
```python
@kbench.task(
name="optional_name", # Defaults to function name, title-cased
description="What it does", # Defaults to docstring
version=1, # Task version
store_task=True, # Set False for sub-tasks
store_run=True, # Set False to skip storing results
)
def my_task(llm):
...
```
`@kbench.benchmark()` is an exact alias for `@kbench.task()`.
### Task First Parameter
The first parameter **must** be the LLM actor. It receives the model to test.
```python
@kbench.task()
def my_task(llm): # ✅ Correct
...
@kbench.task()
def my_task(llm, judge_llm): # ✅ Also fine — second LLM for judging
...
```
### Task Additional Parameters
Extra parameters are passed via `.run()` kwargs:
```python
@kbench.task()
def check_knowledge(llm, question, expected_answer):
response = llm.prompt(question)
kbench.assertions.assert_contains_regex(
rf"(?i){expected_answer}", response
)
check_knowledge.run(kbench.llm, question="Capital of Japan?", expected_answer="Tokyo")
```
### Return Types
**If your task returns a value, you MUST add a return type annotation.**
| Annotation | Result Type | Meaning |
|------------|-------------|---------|
| (none) or `-> None` | PassFail | Pass if no exceptions, based on assertions |
| `-> bool` | Boolean | True = pass, False = fail |
| `-> float` | Score | Numerical score |
| `-> int` | Numerical | Integer value |
| `-> dict` | Dictionary | Arbitrary dict result |
| `-> tuple[int, int]` | PassCount | Count (e.g., `(8, 10)`) |
| `-> tuple[float, float]` | MetricWithCI | Value ± confidence interval |
> **Note:** `-> None` is equivalent to omitting the annotation — both produce PassFail.
```python
# Score task
@kbench.task()
def accuracy(llm) -> float:
return 0.85
# Count task
@kbench.task()
def count_correct(llm) -> tuple[int, int]:
return (8, 10) # 8 out of 10 passed
# Dict task (for rich results)
@kbench.task()
def detailed_result(llm) -> dict:
return {"accuracy": 0.9, "latency": 1.2, "is_correct": True}
```
---
## §3. Running Tasks
### Running a Task
```python
# Single run — returns a Run object
run = my_task.run(kbench.llm)
# With extra parameters
run = my_task.run(kbench.llm, question="What is Python?")
# Multiple models
run1 = my_task.run(kbench.llm) # Default model
run2 = my_task.run(kbench.judge_llm) # Judge model
```
**Available models (loaded from Kaggle environment):**
- `kbench.llm` — default model
- `kbench.judge_llm` — judge model
- `kbench.llms` — list of ALL available models (useful for multi-model comparison)
### Run Object Properties
The `Run` object returned by `.run()` has useful attributes:
```python
run = my_task.run(kbench.llm)
run.passed # bool — True if result + all assertions passed
run.result # The returned value (type depends on task return annotation)
run.assertion_results # list[AssertionResult] — all recorded assertions
run.status # Status enum (PENDING, DONE, FAILED)
run.chat # The conversation log
```
This is especially useful in sub-task composition:
```python
runs = [subtask.run(llm, q=q) for q in questions]
accuracy = sum(r.passed for r in runs) / len(runs)
```
### Batch Evaluation: `.evaluate()`
```python
import pandas as pd
results = my_task.evaluate(
llm=[kbench.llm], # List of models
evaluation_data=df, # DataFrame of test cases
n_jobs=3, # Parallel workers (default: 1)
timeout=120, # Per-job timeout in seconds
max_attempts=3, # Retry count
retry_delay=15, # Seconds between retries
on_failure="raise", # "raise" (default) or "continue"
stop_condition=lambda runs: len(runs) == df.shape[0], # Early stop
remove_run_files=True, # Clean up after
)
# Access results
results.as_dataframe()
```
GitHub에서 보기이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기