بنقرة واحدة
create-inspect-task
Create custom inspect-ai evaluation tasks through interacted, guided workflow.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Create custom inspect-ai evaluation tasks through interacted, guided workflow.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Plan LLM fine-tuning and evaluation experiments. Use when the user wants to design a new experiment, plan training runs, or create an experiment_summary.yaml file.
Open-ended, Claude-driven exploration of a completed experiment — you decide per-experiment which figures matter and what the results mean. Optional and runnable any time after run-experiment (summarize-experiment is the required post-run step). Produces "Claude's Exploration": a non-deterministic report of what you examined and concluded, with an audit log.
Execute the complete experimental workflow - model optimization followed by evaluation - for all runs in a scaffolded experiment. Use after scaffold-experiment to submit jobs to SLURM.
Archive a completed experiment, preserving all experiment files while deleting bulk checkpoint artifacts. Use after summarize-experiment or explore-experiment when an experiment is complete and results have been reviewed.
Set up complete experimental infrastructure for all runs in a designed experiment. Orchestrates parallel generation of fine-tuning configs (via scaffold-torchtune) and evaluation configs (via scaffold-inspect). Use after design-experiment to prepare configs before running experiments.
Create the standard summary of experiment results from a completed (fine-tuned and evaluated) experiment. Run this right after run-experiment as the required post-run step — captures key metrics (loss, accuracy, regression metrics) into summary.md.
| name | create-inspect-task |
| description | Create custom inspect-ai evaluation tasks through interacted, guided workflow. |
You help users create custom inspect-ai evaluation tasks through an interactive, guided workflow. Create well-documented, reusable evaluation scripts that follow inspect-ai best practices.
Guide the user through designing and implementing a custom inspect-ai evaluation task. Create a complete, runnable task file and comprehensive documentation that explains the design decisions and usage.
This skill supports two modes:
When an experiment_summary.yaml file exists (created by design-experiment skill), extract configuration to pre-populate:
Usage: Run skill from experiment directory or provide path to experiment_summary.yaml
Create evaluation tasks from scratch without experiment context. User provides all configuration manually.
Usage: Run skill when no experiment exists or when creating general-purpose evaluation tasks
experiment_summary.yaml in current directorylogs/create-inspect-task.loglogs/create-inspect-task.logWhen operating in experiment-guided mode, extract the following information from the YAML structure:
experiment:
name: string
project: string
question: string
data:
training:
path: string
dataset_label: string
format: string
splits:
train: int
validation: int
test: int
models:
base:
- name: string
path: string
evaluation:
system_prompt: string
temperature: float
runs:
- name: string
type: string # "fine-tuned" or "control"
model: string
import yaml
from pathlib import Path
def extract_from_experiment_summary(path):
"""Extract configuration from experiment_summary.yaml"""
with open(path, 'r') as f:
config = yaml.safe_load(f)
# Extract dataset configuration
dataset_path = config['data']['training']['path']
dataset_format = config['data']['training']['format']
dataset_splits = config['data']['training']['splits']
# Extract system prompt from evaluation section
system_prompt = config['evaluation']['system_prompt']
# Extract research question
research_question = config['experiment']['question']
project = config['experiment']['project']
# Extract model information (first base model)
base_models = config['models']['base']
model_name = base_models[0]['name'] if base_models else None
model_path = base_models[0]['path'] if base_models else None
# Extract run names for documentation examples
run_names = [run['name'] for run in config['runs']]
control_runs = [run['name'] for run in config['runs'] if run['type'] == 'control']
return {
'dataset_path': dataset_path,
'dataset_format': dataset_format,
'dataset_splits': dataset_splits,
'system_prompt': system_prompt,
'research_question': research_question,
'project': project,
'model_name': model_name,
'model_path': model_path,
'run_names': run_names,
'control_runs': control_runs
}
From experiment section:
question → Research question/objective (informs evaluation goal)project → Blueprint directory name under blueprints/ (pins the task family)From data.training section:
path → Dataset path for evaluationformat → Dataset format (json)splits → Sample counts (use test split for evaluation)From models.base[] section:
name → Model identifierpath → Full path to base model (for usage examples)From evaluation section:
system_prompt → from controls.system_prompt (the single source, propagated to eval)temperature → Default temperature settingFrom runs[] section:
name → Run identifiers (for documentation)type → Filter for "control" runs that need evaluationAfter extraction, show the user what was found:
## Configuration Extracted from Experiment
I found the following configuration in your experiment:
**Dataset:**
- Path: `{ck_data_dir}/capitalization/words_4L_80P_300.json`
- Format: JSON
- Splits: train (240), test (60)
**Models:**
- Llama-3.2-1B-Instruct
- Path: `/scratch/gpfs/.../pretrained-llms/Llama-3.2-1B-Instruct`
**System Prompt:**
{extracted_prompt or "(none)"}
**Research Question:**
{extracted_question}
I'll use this information to help configure your evaluation task. You can override any of these settings if needed.
Check extracted information:
ls)ls)If validation fails:
IMPORTANT: Create a detailed log file at {task_dir}/logs/create-inspect-task.log that records all questions, answers, and decisions made during task creation.
[YYYY-MM-DD HH:MM:SS] ACTION: Description
Details: {specifics}
Result: {outcome}
[2025-10-24 14:30:00] MODE_SELECTION: Experiment-guided mode
Details: Found experiment_summary.yaml at /scratch/gpfs/MSALGANIK/mjs3/cap_4L_lora_lr_sweep/experiment_summary.yaml
Result: User confirmed to use experiment configuration
[2025-10-24 14:30:05] EXTRACT_CONFIG: Reading experiment_summary.yaml
Details: Parsing YAML structure: experiment, data, models, evaluation sections
Result: Successfully extracted configuration
[2025-10-24 14:30:10] EXTRACTED_DATASET: Dataset configuration
Details: Path: {ck_data_dir}/capitalization/words_4L_80P_300.json
Format: JSON, Splits: train (240), test (60)
Result: Verified dataset exists (43KB)
[2025-10-24 14:30:15] EXTRACTED_SYSTEM_PROMPT: System prompt from experiment
Details: Prompt: "" (empty - no system message)
Result: Will use the system prompt from `controls.system_prompt` (here: empty)
[2025-10-24 14:30:20] EXTRACTED_RESEARCH_QUESTION: Scientific objective
Details: Compare LoRA ranks and learning rates for capitalization task
Result: Will design evaluation to measure exact match accuracy
[2025-10-24 14:30:25] EVALUATION_OBJECTIVE: User wants to evaluate capitalization accuracy
Details: Exact match (case-sensitive), using experiment dataset
Result: Will use match(location="exact", ignore_case=False) scorer for strict evaluation
[2025-10-24 14:30:30] SOLVER_CONFIG: Designing solver chain
Details: system_message(""), prompt_template("{prompt}"), generate(temp=0.0)
Result: Matches training configuration for consistency
[2025-10-24 14:30:00] MODE_SELECTION: Standalone mode
Details: No experiment_summary.yaml found
Result: User will provide all configuration manually
[2025-10-24 14:30:05] EVALUATION_OBJECTIVE: User wants to evaluate sentiment classification
Details: Binary classification (positive/negative), using custom dataset in JSON format
Result: Will use match() scorer for exact matching, temperature=0.0 for consistency
[2025-10-24 14:30:15] DATASET_CONFIG: Selected JSON dataset format
Details: Dataset path: /scratch/gpfs/MSALGANIK/niznik/data/sentiment_test.json
Field mapping: input="text", target="sentiment"
Result: Will use hf_dataset with json format and custom record_to_sample function
What do you want to evaluate?
What defines a correct answer?
What dataset format do you have?
.json or .jsonl)Where is the dataset located?
What are the field names?
Dataset structure specifics:
Example questions:
{'train': [...], 'test': [...]}?"System message:
Prompt template:
"{prompt}" (direct input)Generation parameters:
Common solver patterns:
[system_message(""), prompt_template("{prompt}"), generate()][chain_of_thought(), generate()][multiple_choice()] (don't add separate generate())[prompt_template("Answer: {prompt}\n"), generate()]Based on evaluation objective, suggest scorers:
cruijff_kit custom scorers (preferred for experiment tasks — driven by the scorers: block in eval.yaml):
Rather than hard-coding a scorer in the task, read the scorers: list from config_path and build it via the shared registry. This lets the experiment design (not the task code) pick the scorer:
from cruijff_kit.tools.inspect.scorers import (
build_scorers,
configured_scorers_require_logprobs,
)
scorers = build_scorers(config) # falls back to DEFAULT_SCORERS if no scorers: block
The scorers: block is a list of {name, params} entries:
scorers:
- name: match
- name: risk_scorer
params:
option_tokens: ["0", "1"]
Registry names: match, includes, risk_scorer, numeric_risk_scorer, continuous_scorer.
logprobs contract: logprob-based scorers (e.g. risk_scorer) set requires_logprobs = True on their factory. Call configured_scorers_require_logprobs(config) and auto-enable logprob capture when it returns True:
scorer_needs_logprobs = configured_scorers_require_logprobs(config)
enable_logprobs = bool(logprobs) or (logprobs is None and scorer_needs_logprobs)
if enable_logprobs:
generate_config = GenerateConfig(logprobs=True, top_logprobs=top_logprobs)
else:
generate_config = GenerateConfig()
# ... and fail loudly if the user passed logprobs=False while configuring a
# scorer that needs them, rather than silently producing unscored logs.
Note: risk_scorer accuracy is exact-string-match (completion == target), not argmax — it conflates output format with judgment. Keep that in mind when interpreting its accuracy.
For exact matching (inspect-ai built-ins — fine for standalone tasks without the registry):
match() - Target appears at beginning/end; ignores case, whitespace, punctuation
location="begin"/"end"/"any", ignore_case=True/Falseexact() - Precise matching after normalizationincludes() - Target appears anywhere in output
ignore_case=True/FalseFor multiple choice:
choice() - Works with multiple_choice() solverFor pattern extraction:
pattern() - Extract answer using regex
For model-graded evaluation:
model_graded_qa() - Another model assesses answer quality
partial_credit=True/False, custom templatemodel_graded_fact() - Checks if specific facts appearFor numeric/F1 scoring:
f1() - F1 score for text overlapMultiple scorers:
[match(), includes()] to get multiple scoresShould the task accept parameters for flexibility?
Standard parameters — match the current blueprint tasks so the task drops into the eval.yaml pipeline (cleanest reference: blueprints/capitalization/inspect_task.py):
data_path — Path to the dataset JSON (required; no default).config_path — Path to eval.yaml. The task reads prompt, system_prompt, and (optionally) the scorers: block from it. setup_inspect.py auto-derives this from the config file's own location — you do not pass it by hand.vis_label — Optional label appended to the task name (f"{name}_{vis_label}" if vis_label else name). Required for the viz pipeline: viz_helpers reads vis_label from the eval log's task_args to dedup and label runs. Omit it and multi-variant runs collide in the visualizations.split — Which split to evaluate (e.g. "test", "validation").use_chat_template — True for instruct models (adds a system_message solver), False for base models (plain text completion).temperature / max_tokens — Generation params. Greedy default is temperature=1e-7.logprobs / top_logprobs — Capture top logprobs. Leave logprobs defaulting to None (auto) so it enables only when a configured scorer needs them — see Scorer Selection.assistant_prefix — Optional text to seed the assistant turn.These names are not arbitrary. setup_inspect.py maps a fixed TASK_ARG_KEYS set onto -T flags — commonly the likes of:
data_path, config_path, vis_label, split, temperature, max_tokens, …
TASK_ARG_KEYS in setup_inspect.py is the source of truth for the full set — read it there rather than trusting this list to stay complete. A parameter outside that set will not receive a value from eval.yaml (you'd get a startup warning from load_eval_config about an unconsumed key); add genuinely new task args to TASK_ARG_KEYS if the task needs them.
Benefits of parameters:
How to pass parameters:
inspect eval task.py -T param_name=value
How will the model be specified?
Option 1: CLI specification (most flexible)
inspect eval task.py --model hf/local -M model_path=/path/to/modelOption 2: Experiment pipeline (eval.yaml)
setup_inspect.py from eval.yamlprompt/system_prompt/scorers from config_path — it never resolves the modelscaffold-inspect runs tasks; see Generated Task Pattern belowOption 3: Hard-coded in task
Create two files:
{task_name}_task.pyThe complete, runnable inspect-ai task following best practices.
File naming convention:
sentiment_classification_task.pymath_reasoning_task.py{domain}_{type}_task.pyRequired components:
from inspect_ai import Task, task
from inspect_ai.dataset import json_dataset, hf_dataset, FieldSpec
from inspect_ai.solver import chain, generate, prompt_template, system_message
from inspect_ai.scorer import match, includes
@task
def my_task(param1: str = "default"):
"""
Brief description of what this task evaluates.
Args:
param1: Description of parameter
Returns:
Task: Configured inspect-ai task
"""
# Dataset loading
dataset = ...
# Solver chain
solver = chain(
system_message("..."),
prompt_template("{prompt}"),
generate(temperature=0.0)
)
# Return task
return Task(
dataset=dataset,
solver=solver,
scorer=...
)
Best practices to follow:
{task_name}_design.mdComprehensive documentation of design decisions.
Required sections:
# {Task Name} Evaluation Task
**Created:** {timestamp}
**Inspect-AI Version:** {version if known}
## Evaluation Objective
{What this task evaluates and why}
## Dataset Configuration
**Format:** {JSON/HuggingFace/etc.}
**Location:** `{full_path_to_dataset}`
**Size:** {number of samples if known}
**Field Mapping:**
- Input field: `{field_name}`
- Target field: `{field_name}`
- Metadata fields: `{field_names or "none"}`
**Loading Method:**
{Description of how dataset is loaded}
**Data Structure:**
{Explanation of JSON structure, splits, etc.}
## Solver Chain
**Components:**
1. {Solver 1}: {Purpose}
2. {Solver 2}: {Purpose}
3. ...
**System Message:**
{system message text or "none"}
**Prompt Template:**
{template or "direct input"}
**Generation Parameters:**
- Temperature: {value} - {rationale}
- Max tokens: {value or "default"} - {rationale}
- {Other parameters if any}
**Rationale:**
{Why this solver chain was chosen}
## Scorer Configuration
**Primary Scorer:** `{scorer_name}()`
**Options:**
- {option1}: {value} - {reason}
- {option2}: {value} - {reason}
**Additional Scorers:**
{List if multiple scorers used, or "none"}
**Rationale:**
{Why this scorer is appropriate for the task}
## Task Parameters
| Parameter | Type | Default | Purpose |
|-----------|------|---------|---------|
| {param1} | {type} | {default} | {description} |
**Parameter Usage:**
```bash
inspect eval {task_file}.py -T {param}={value}
Recommended usage:
inspect eval {task_file}.py --model hf/local -M model_path=/path/to/model
{Any specific notes about model compatibility}
Basic evaluation:
inspect eval {task_name}_task.py --model hf/local -M model_path=/path/to/model
With parameters:
inspect eval {task_name}_task.py --model hf/local -M model_path=/path/to/model -T temperature=0.5
Evaluating fine-tuned model: {if applicable}
inspect eval {task_name}_task.py@{task_name} --model hf/local \
-M model_path=/path/to/run/artifacts/epoch_0 \
-T data_path=/path/to/dataset.json \
-T config_path=/path/to/eval.yaml
Inspect-ai will create:
logs/{task_name}_{timestamp}.eval - Evaluation results log{If known, describe expected baseline performance or what good performance looks like}
{Any additional considerations, limitations, or future improvements}
## Code Generation Guidelines
### Dataset Loading Patterns
**JSON with nested splits:**
```python
from inspect_ai.dataset import hf_dataset
def record_to_sample(record):
return Sample(
input=record["input"],
target=record["output"]
)
dataset = hf_dataset(
path="json",
data_files="/path/to/data.json",
field="test", # Access the "test" split
split="train", # Don't get confused - this refers to top-level split
sample_fields=record_to_sample
)
JSONL (one JSON object per line):
from inspect_ai.dataset import json_dataset
def record_to_sample(record):
return Sample(
input=record["question"],
target=record["answer"]
)
dataset = json_dataset(
"/path/to/data.jsonl",
record_to_sample
)
HuggingFace dataset:
from inspect_ai.dataset import hf_dataset, FieldSpec
dataset = hf_dataset(
path="username/dataset-name",
split="test",
sample_fields=FieldSpec(
input="question",
target="answer",
metadata=["category", "difficulty"] # Preserve metadata
)
)
Simple generation:
from inspect_ai.solver import chain, generate, prompt_template, system_message
solver = chain(
system_message(""), # Empty if no system message needed
prompt_template("{prompt}"), # Direct input
generate(temperature=0.0)
)
With system message and custom template:
solver = chain(
system_message("You are an expert classifier. Respond with only the category label."),
prompt_template("Text: {prompt}\n\nCategory:"),
generate(temperature=0.0, max_tokens=50)
)
Chain-of-thought:
from inspect_ai.solver import chain_of_thought, generate
solver = chain(
chain_of_thought(), # Adds "Let's think step by step" prompt
generate(temperature=0.0)
)
Multiple choice:
from inspect_ai.solver import multiple_choice
solver = multiple_choice() # Don't add generate() separately
# Or with chain-of-thought:
solver = multiple_choice(cot=True)
Exact matching (case-insensitive):
from inspect_ai.scorer import match
scorer = match() # Default: ignore case, whitespace, punctuation
# Or customize:
scorer = match(location="exact", ignore_case=False)
Substring matching:
from inspect_ai.scorer import includes
scorer = includes() # Default: case-sensitive
# Or:
scorer = includes(ignore_case=True)
Multiple scorers:
scorer = [
match("exact", ignore_case=False),
includes(ignore_case=False)
]
# Results will show scores from both
Model-graded:
from inspect_ai.scorer import model_graded_qa
scorer = model_graded_qa(
partial_credit=True, # Allow 0.5 scores
model="openai/gpt-4o" # Specify grading model
)
When creating tasks for an experiment, the task does not read fine-tuning configs directly. Instead it reads its prompt/scorers config from the eval.yaml that scaffold-inspect writes, via the auto-derived config_path:
design-experiment produces experiment_summary.yaml (research question, data, models, controls.system_prompt, the scorers: block).scaffold-inspect writes one eval.yaml per (run, task, epoch) cell, carrying prompt, system_prompt, scorers, data_path, vis_label, etc.setup_inspect.py renders the SLURM script: it auto-derives config_path (the path to that eval.yaml), maps TASK_ARG_KEYS onto -T flags, and the task reads prompt/system_prompt/scorers back out of config_path at runtime.So a generated task's job is: accept the standard params, read prompt/system_prompt (and optionally the scorers: block) from config_path, build the dataset/solver/scorer, and name itself with vis_label.
For tasks integrated with experiments (mirrors blueprints/capitalization/inspect_task.py, the cleanest reference):
import yaml
from inspect_ai import Task, task
from inspect_ai.dataset import hf_dataset, Sample
from inspect_ai.model import GenerateConfig
from inspect_ai.solver import chain, generate, system_message
from cruijff_kit.tools.inspect.scorers import (
build_scorers,
configured_scorers_require_logprobs,
)
@task
def my_task(
data_path: str,
config_path: str = "",
split: str = "test",
temperature: float = 1e-7,
max_tokens: int = 20,
use_chat_template: bool = True,
logprobs: bool | None = None,
top_logprobs: int = 20,
vis_label: str = "",
) -> Task:
"""
Evaluate a model on <task description>.
Args:
data_path: Path to the dataset JSON.
config_path: Path to eval.yaml (reads prompt/system_prompt/scorers).
split: Which split to evaluate (default: "test").
temperature: Generation temperature (greedy default 1e-7).
max_tokens: Max tokens to generate.
use_chat_template: True for instruct models (adds system_message solver),
False for base models (plain text completion).
logprobs: None = auto (enable iff a configured scorer needs them).
top_logprobs: Top-k logprobs to capture when enabled.
vis_label: Optional suffix for the task name; read by viz_helpers for
dedup/labeling across a multi-variant experiment.
Returns:
Task: Configured inspect-ai task
"""
# Task name carries vis_label so the viz pipeline can label/dedup runs.
task_name = f"my_task_{vis_label}" if vis_label else "my_task"
prompt_str = "{input}"
system_prompt = ""
config: dict = {}
if config_path:
with open(config_path, "r") as f:
config = yaml.safe_load(f) or {}
prompt_str = config.get("prompt", "{input}")
system_prompt = config.get("system_prompt", "")
def record_to_sample(record):
return Sample(
input=prompt_str.format(input=record["input"]),
target=record["output"],
metadata=record.get("metadata", {}),
)
dataset = hf_dataset(
path="json",
data_files=data_path,
field=split,
split="train", # HuggingFace quirk — always "train" here
sample_fields=record_to_sample,
)
if use_chat_template:
solver = chain(
system_message(system_prompt),
generate(temperature=temperature, max_tokens=max_tokens),
)
else:
solver = chain(generate(temperature=temperature, max_tokens=max_tokens))
# Scorer + logprobs driven by the eval config's scorers: block.
scorers = build_scorers(config)
scorer_needs_logprobs = configured_scorers_require_logprobs(config)
if logprobs is False and scorer_needs_logprobs:
raise ValueError(
"A configured scorer requires logprobs, but logprobs=False was set. "
"Drop the override or remove the logprob-dependent scorer."
)
enable_logprobs = bool(logprobs) or (logprobs is None and scorer_needs_logprobs)
generate_config = (
GenerateConfig(logprobs=True, top_logprobs=top_logprobs)
if enable_logprobs
else GenerateConfig()
)
return Task(
name=task_name,
dataset=dataset,
solver=solver,
scorer=scorers,
config=generate_config,
)
For a standalone task with no experiment context, drop the config_path/build_scorers/logprobs machinery and hard-code a built-in scorer (e.g. scorer=match(...)) — but keep vis_label (and pass it yourself via -T vis_label=…, since there's no eval.yaml to auto-map it) if the eval logs will feed the viz pipeline:
from inspect_ai import Task, task
from inspect_ai.dataset import hf_dataset, Sample
from inspect_ai.scorer import match
from inspect_ai.solver import generate
@task
def my_task(
data_path: str,
split: str = "test",
temperature: float = 1e-7,
max_tokens: int = 20,
vis_label: str = "",
) -> Task:
"""Standalone eval on <task description> (no eval.yaml)."""
task_name = f"my_task_{vis_label}" if vis_label else "my_task"
def record_to_sample(record):
return Sample(
input=record["input"],
target=record["output"],
metadata=record.get("metadata", {}),
)
dataset = hf_dataset(
path="json",
data_files=data_path,
field=split,
split="train", # HuggingFace quirk — always "train" here
sample_fields=record_to_sample,
)
return Task(
name=task_name,
dataset=dataset,
solver=generate(temperature=temperature, max_tokens=max_tokens),
scorer=match(), # hard-coded — no scorers: block to read
)
In the experiment pipeline you don't invoke inspect eval by hand — scaffold-inspect + setup_inspect.py generate the SLURM cell. For a quick manual smoke test of a generated task:
inspect eval my_task.py@my_task \
--model hf/local \
-M model_path=/scratch/gpfs/MSALGANIK/pretrained-llms/Llama-3.2-1B-Instruct \
-T data_path=/path/to/dataset.json \
-T config_path=/path/to/eval.yaml \
-T vis_label=smoke \
--limit 5
This task pattern integrates with setup_inspect.py, which renders eval SLURM scripts from a template. The scaffold-inspect agent writes eval.yaml (referencing the task script created here) and calls:
python src/tools/inspect/setup_inspect.py \
--config eval.yaml \
--model_name Llama-3.2-1B-Instruct
Before finishing, verify:
@taskAdditional checks for experiment-guided mode:
controls.system_prompt (single source)data_path + config_path and reads prompt/system_prompt/scorers from config_pathvis_label and folds it into the task namesetup_inspect.py's TASK_ARG_KEYSAfter creating the task, guide user:
Test the task:
# Validate syntax
python -m py_compile {task_file}.py
# Test with small sample
inspect eval {task_file}.py --model {model} --limit 5
Run full evaluation:
inspect eval {task_file}.py --model {model}
View results:
inspect view
# Opens web UI to browse evaluation logs
Iterate if needed:
inspect score to re-score without re-running--limit 5)controls.system_prompt, propagated to eval (no separate eval copy to match)use_chat_template toggles instruct vs. base)config_path (the eval.yaml), and fold vis_label into the task nameIf dataset file not found:
If unsure about dataset format:
If scorer choice unclear: