Spaces:
Runtime error
Runtime error
File size: 4,196 Bytes
dbf5e96 1a6681a dbf5e96 7e55f05 dbf5e96 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | """
Pydantic Models for CodeReviewEnv
Defines the complete type system for the Semantic MDP:
- PRFile: individual file in a pull request
- Observation: the full state visible to the agent (s β S)
- Action: the structured decision space (a β A)
- Reward: shaped reward with component breakdown (R: SΓAΓS' β [-1,1])
- State: full environment state including trajectory history
All models are serializable to JSON for trajectory logging and API transport.
"""
from pydantic import BaseModel, field_validator
from typing import List, Optional, Dict, Any
class PRFile(BaseModel):
"""A single file within a pull request diff."""
filename: str
language: str # python | javascript | java | go | rust | typescript | ruby
diff: str
lines_changed: int
has_tests: bool
@field_validator("language")
@classmethod
def validate_language(cls, v: str) -> str:
allowed = {"python", "javascript", "java", "go", "rust", "typescript", "ruby"}
if v not in allowed:
raise ValueError(f"language must be one of {allowed}")
return v
class Observation(BaseModel):
"""
The agent's observation at each step β the semantic state s β S.
Unlike continuous MBRL state spaces (e.g. MuJoCo joint angles),
this is structured text carrying semantic meaning: code diffs,
author context, review history. A world model must learn to
predict how review actions transform this state.
"""
pr_id: str
title: str
description: str
author_experience: str # junior | mid | senior
files: List[PRFile]
existing_comments: List[str]
review_queue: List[str]
step_number: int
episode_budget: int
@field_validator("author_experience")
@classmethod
def validate_experience(cls, v: str) -> str:
allowed = {"junior", "mid", "senior"}
if v not in allowed:
raise ValueError(f"author_experience must be one of {allowed}")
return v
class Action(BaseModel):
"""
The agent's action β a structured decision a β A.
The action space is heterogeneous: different action_types require
different fields. This is fundamentally different from continuous
action spaces in standard MBRL β it requires structured encoding
for world model training.
"""
action_type: str # label_severity | prioritize | add_comment | approve | request_changes
severity: Optional[str] = None # critical | high | medium | low | none
priority_order: Optional[List[str]] = None
comment: Optional[str] = None
target_file: Optional[str] = None
target_line: Optional[int] = None
@field_validator("action_type")
@classmethod
def validate_action_type(cls, v: str) -> str:
allowed = {"label_severity", "prioritize", "add_comment", "approve", "request_changes"}
if v not in allowed:
raise ValueError(f"action_type must be one of {allowed}")
return v
@field_validator("severity")
@classmethod
def validate_severity(cls, v: Optional[str]) -> Optional[str]:
if v is not None:
allowed = {"critical", "high", "medium", "low", "none"}
if v not in allowed:
raise ValueError(f"severity must be one of {allowed}")
return v
class Reward(BaseModel):
"""
Shaped reward R: S Γ A Γ S' β [-1, 1].
The breakdown dict exposes every component for analysis:
step_reward, efficiency_bonus, coverage_bonus, consistency_penalty.
This transparency is critical for reward attribution research.
"""
value: float
breakdown: Dict[str, float]
reason: str
@field_validator("value")
@classmethod
def clamp_reward(cls, v: float) -> float:
return max(-1.0, min(1.0, v))
class State(BaseModel):
"""
Full environment state including trajectory history.
The trajectory list enables in-episode analysis and is the raw
material for semantic world model training datasets.
"""
current_pr: Observation
reviewed_prs: List[str]
pending_prs: List[str]
total_reward: float
step: int
done: bool
trajectory: List[Dict[str, Any]]
|