replicalab / docs /map /models.md
maxxie114's picture
Initial HF Spaces deployment
80d8c84
# Models Map β€” `replicalab/models.py`
> All Pydantic data contracts. Frozen with `extra="forbid"` unless noted.
>
> **Tasks implemented:** MOD 01, 02, 03, 04, 09, 11, 12
## Enums
### `ScientistActionType(str, Enum)`
| Value | Meaning |
|-------|---------|
| `propose_protocol` | First protocol submission |
| `revise_protocol` | Modify existing protocol |
| `request_info` | Ask lab manager a question |
| `accept` | Agree to current protocol |
### `LabManagerActionType(str, Enum)`
| Value | Meaning |
|-------|---------|
| `report_feasibility` | Report on feasibility without suggestions |
| `suggest_alternative` | Propose revised protocol |
| `reject` | Reject protocol outright |
| `accept` | Approve protocol |
## Action Models
### `ScientistAction(BaseModel)` β€” `extra="forbid"`
MOD 01 + MOD 09. Strict contract for scientist output.
| Field | Type | Constraint | Notes |
|-------|------|-----------|-------|
| `action_type` | `ScientistActionType` | required | |
| `sample_size` | `int` | `ge=0` | Must be `>=1` for propose/revise |
| `controls` | `list[str]` | normalized | |
| `technique` | `str` | stripped | Required for propose/revise |
| `duration_days` | `int` | `ge=0` | |
| `required_equipment` | `list[str]` | normalized | |
| `required_reagents` | `list[str]` | normalized | |
| `questions` | `list[str]` | normalized | Required non-empty for request_info |
| `rationale` | `str` | stripped | Required for propose/revise |
**Validation rules:**
- `propose_protocol` / `revise_protocol`: sample_size >= 1, technique required, rationale required, questions must be empty
- `request_info`: questions non-empty, no protocol payload fields
- `accept`: no questions, no protocol payload fields
### `LabManagerAction(BaseModel)` β€” `extra="forbid"`
MOD 02. Strict contract with feasible-flag consistency.
| Field | Type | Constraint | Notes |
|-------|------|-----------|-------|
| `action_type` | `LabManagerActionType` | required | |
| `feasible` | `bool` | required | Must equal AND of all constraint flags |
| `budget_ok` | `bool` | required | |
| `equipment_ok` | `bool` | required | |
| `reagents_ok` | `bool` | required | |
| `schedule_ok` | `bool` | required | |
| `staff_ok` | `bool` | required | |
| `suggested_technique` | `str` | stripped | Only for suggest_alternative |
| `suggested_sample_size` | `int` | `ge=0` | Only for suggest_alternative |
| `suggested_controls` | `list[str]` | normalized | Only for suggest_alternative |
| `explanation` | `str` | required non-empty | |
**Validation rules:**
- `feasible` must equal `all(budget_ok, equipment_ok, reagents_ok, schedule_ok, staff_ok)`
- `accept` requires `feasible=True`
- `reject` requires `feasible=False`
- `suggest_alternative` requires `feasible=False` + at least one suggestion field
- Suggestion fields forbidden for non-suggest_alternative actions
## Observation Models
### `ConversationEntry(BaseModel)` β€” `extra="forbid"`
| Field | Type | Notes |
|-------|------|-------|
| `role` | `Literal["scientist", "lab_manager", "system"]` | |
| `message` | `str` | Required non-empty |
| `round_number` | `int` | `ge=0` |
| `action_type` | `Optional[str]` | Null or non-empty |
### `Protocol(BaseModel)` β€” `extra="forbid"`
Shared protocol payload used in observations and actions.
| Field | Type | Notes |
|-------|------|-------|
| `sample_size` | `int` | `ge=0` |
| `controls` | `list[str]` | normalized |
| `technique` | `str` | required non-empty |
| `duration_days` | `int` | `ge=0` |
| `required_equipment` | `list[str]` | normalized |
| `required_reagents` | `list[str]` | normalized |
| `rationale` | `str` | required non-empty |
### `ScientistObservation(BaseModel)` β€” `extra="forbid"`
| Field | Type |
|-------|------|
| `paper_title` | `str` |
| `paper_hypothesis` | `str` |
| `paper_method` | `str` |
| `paper_key_finding` | `str` |
| `experiment_goal` | `str` |
| `conversation_history` | `list[ConversationEntry]` |
| `current_protocol` | `Optional[Protocol]` |
| `round_number` | `int` (ge=0) |
| `max_rounds` | `int` (ge=0) |
### `LabManagerObservation(BaseModel)` β€” `extra="forbid"`
| Field | Type |
|-------|------|
| `budget_total` | `float` (ge=0) |
| `budget_remaining` | `float` (ge=0) |
| `equipment_available` | `list[str]` |
| `equipment_booked` | `list[str]` |
| `reagents_in_stock` | `list[str]` |
| `reagents_out_of_stock` | `list[str]` |
| `staff_count` | `int` (ge=0) |
| `time_limit_days` | `int` (ge=0) |
| `safety_restrictions` | `list[str]` |
| `conversation_history` | `list[ConversationEntry]` |
| `current_protocol` | `Optional[Protocol]` |
| `round_number` | `int` (ge=0) |
| `max_rounds` | `int` (ge=0) |
### `Observation(BaseModel)` β€” `extra="forbid"`
Combined wrapper. Each role receives its own view.
| Field | Type |
|-------|------|
| `scientist` | `Optional[ScientistObservation]` |
| `lab_manager` | `Optional[LabManagerObservation]` |
## Reward & Step Models
### `RewardBreakdown(BaseModel)` β€” default `extra="forbid"`
MOD 11. Component scores from judge rubric engine.
| Field | Type | Default | Range |
|-------|------|---------|-------|
| `rigor` | `float` | 0.0 | [0, 1] |
| `feasibility` | `float` | 0.0 | [0, 1] |
| `fidelity` | `float` | 0.0 | [0, 1] |
| `efficiency_bonus` | `float` | 0.0 | unbounded |
| `communication_bonus` | `float` | 0.0 | unbounded |
| `penalties` | `dict[str, float]` | {} | unbounded |
### `StepInfo(BaseModel)` β€” `extra="allow"`
MOD 11. Extensible metadata returned with each step.
| Field | Type | Default |
|-------|------|---------|
| `agreement_reached` | `bool` | False |
| `error` | `Optional[str]` | None |
| `reward_breakdown` | `Optional[RewardBreakdown]` | None |
| `judge_notes` | `Optional[str]` | None |
| `verdict` | `Optional[str]` | None |
### `StepResult(BaseModel)`
| Field | Type | Default |
|-------|------|---------|
| `observation` | `Optional[Observation]` | None |
| `reward` | `float` | 0.0 |
| `done` | `bool` | False |
| `info` | `StepInfo` | StepInfo() |
## Episode Models
### `EpisodeState(BaseModel)` β€” MOD 04
Full internal state for debugging and replay.
| Field | Type | Default |
|-------|------|---------|
| `seed` | `int` | 0 |
| `scenario_template` | `str` | "" |
| `difficulty` | `str` | "easy" |
| `paper_title` | `str` | "" |
| `paper_hypothesis` | `str` | "" |
| `paper_method` | `str` | "" |
| `paper_key_finding` | `str` | "" |
| `experiment_goal` | `str` | "" |
| `lab_budget_total` | `float` | 0.0 |
| `lab_budget_remaining` | `float` | 0.0 |
| `lab_equipment` | `list[str]` | [] |
| `lab_reagents` | `list[str]` | [] |
| `lab_staff_count` | `int` | 0 |
| `lab_time_limit_days` | `int` | 0 |
| `current_protocol` | `Optional[Protocol]` | None |
| `conversation_history` | `list[ConversationEntry]` | [] |
| `round_number` | `int` | 0 |
| `max_rounds` | `int` | 0 |
| `done` | `bool` | False |
| `agreement_reached` | `bool` | False |
| `reward` | `float` | 0.0 |
| `rigor_score` | `float` | 0.0 |
| `feasibility_score` | `float` | 0.0 |
| `fidelity_score` | `float` | 0.0 |
### `EpisodeLog(BaseModel)` β€” MOD 04
Completed episode record for logging, replay, evaluation.
| Field | Type | Default |
|-------|------|---------|
| `episode_id` | `str` | "" |
| `seed` | `int` | 0 |
| `scenario_template` | `str` | "" |
| `difficulty` | `str` | "easy" |
| `final_state` | `Optional[EpisodeState]` | None |
| `transcript` | `list[ConversationEntry]` | [] |
| `reward_breakdown` | `Optional[RewardBreakdown]` | None |
| `total_reward` | `float` | 0.0 |
| `rounds_used` | `int` | 0 |
| `agreement_reached` | `bool` | False |
| `judge_notes` | `str` | "" |
| `verdict` | `str` | "" |
## Helper Functions
| Function | Purpose |
|----------|---------|
| `_normalize_string_list(value)` | Strip whitespace, reject empty strings |