Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,17 @@ jobs:
- name: Install dependencies
run: uv sync --all-extras

# Whole repository, not just openadapt_ml/. Every defect the ruff 0.16
# audit surfaced (an undefined name, two bare `except:`, four dead
# bindings, five shadowed imports) was in scripts/ or tests/, i.e.
# outside the old gate. Ruff runs in well under a second, so widening the
# path costs no measurable CI time.
- name: Run ruff linter (check)
run: uv run ruff check openadapt_ml/
run: uv run ruff check .

# Formatting stays scoped to openadapt_ml/. 37 files under scripts/,
# tests/ and examples/ have never been formatted; normalising them is a
# separate, purely cosmetic change and does not belong in this one.
- name: Run ruff formatter (check)
run: uv run ruff format --check openadapt_ml/

Expand Down
8 changes: 4 additions & 4 deletions deprecated/waa_deploy/api_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,10 +212,10 @@ def __init__(
from anthropic import Anthropic

self._client = Anthropic(api_key=self.api_key)
except ImportError:
except ImportError as e:
raise RuntimeError(
"anthropic package required. Install with: pip install anthropic"
)
) from e

elif provider == "openai":
self.api_key = api_key or os.getenv("OPENAI_API_KEY")
Expand All @@ -228,10 +228,10 @@ def __init__(
from openai import OpenAI

self._client = OpenAI(api_key=self.api_key)
except ImportError:
except ImportError as e:
raise RuntimeError(
"openai package required. Install with: pip install openai"
)
) from e
else:
raise ValueError(f"Unsupported provider: {provider}")

Expand Down
2 changes: 1 addition & 1 deletion docs/grpo_trl_rewrite_draft.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ def make_rollout_func(
"""
# Deferred import: openadapt-evals is optional at install time
from openadapt_evals.adapters import WAALiveAdapter, WAALiveConfig
from openadapt_evals.adapters.rl_env import RLEnvironment, ResetConfig
from openadapt_evals.adapters.rl_env import ResetConfig, RLEnvironment

# Create adapter and environment (reused across rollouts)
adapter = WAALiveAdapter(WAALiveConfig(server_url=waa_config.server_url))
Expand Down
2 changes: 1 addition & 1 deletion examples/demo_retrieval_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ def main() -> None:
print(f"App context: {app_context}")

# Retrieve relevant demos
print(f"\nRetrieving top-3 similar demonstrations...")
print("\nRetrieving top-3 similar demonstrations...")
results = retriever.retrieve(new_task, top_k=3, app_context=app_context)

print(f"\nFound {len(results)} similar demos:")
Expand Down
2 changes: 1 addition & 1 deletion examples/retrieval_with_capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def main() -> None:
print(f"App context: {app_context}")

# Retrieve with scores
print(f"\nRetrieving top-3 demonstrations...")
print("\nRetrieving top-3 demonstrations...")
results = retriever.retrieve_with_scores(task, app_context, top_k=3)

print(f"\nFound {len(results)} similar demo(s):")
Expand Down
7 changes: 4 additions & 3 deletions examples/train_from_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
from pathlib import Path

from openadapt_ml.ingest import load_episodes
from openadapt_ml.schema import Episode


def main():
Expand Down Expand Up @@ -154,9 +153,10 @@ def _train_standard_mode(episodes: list, args, use_unsloth: bool) -> None:
print(" Input: screenshot + task")
print(" Output: next action")

from openadapt_ml.training.trl_trainer import TRLTrainingConfig, train_with_trl
import os

from openadapt_ml.training.trl_trainer import train_with_trl

Path(args.output).mkdir(parents=True, exist_ok=True)

# Load config if available
Expand Down Expand Up @@ -190,10 +190,11 @@ def _train_demo_conditioned_mode(episodes: list, args, use_unsloth: bool) -> Non
print(" Output: next action")
print(" Note: Full demo-conditioning requires custom prompt formatting.")

from openadapt_ml.training.trl_trainer import TRLTrainingConfig, train_with_trl
import os
import random

from openadapt_ml.training.trl_trainer import train_with_trl

# Split episodes: some for retrieval library, rest for training
random.seed(42)
shuffled = episodes.copy()
Expand Down
8 changes: 4 additions & 4 deletions openadapt_ml/baselines/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,19 @@

from openadapt_ml.baselines.adapter import UnifiedBaselineAdapter
from openadapt_ml.baselines.config import (
# Registry
MODELS,
# Enums
ActionOutputFormat,
CoordinateSystem,
TrackType,
# Config dataclasses
BaselineConfig,
CoordinateSystem,
ModelSpec,
ReActConfig,
ScreenConfig,
SoMConfig,
TrackConfig,
# Registry
MODELS,
TrackType,
# Helper functions
get_default_model,
get_model_spec,
Expand Down
4 changes: 2 additions & 2 deletions openadapt_ml/baselines/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def run(
"""
from PIL import Image

from openadapt_ml.baselines import UnifiedBaselineAdapter, TrackConfig
from openadapt_ml.baselines import TrackConfig, UnifiedBaselineAdapter

# Select track config
track_configs = {
Expand Down Expand Up @@ -196,7 +196,7 @@ def compare(
"""
from PIL import Image

from openadapt_ml.baselines import UnifiedBaselineAdapter, TrackConfig
from openadapt_ml.baselines import TrackConfig, UnifiedBaselineAdapter

model_list = [m.strip() for m in models.split(",")]

Expand Down
2 changes: 1 addition & 1 deletion openadapt_ml/benchmarks/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ def _format_history(
) -> str:
"""Format action history for prompt."""
lines = []
for i, (obs, action) in enumerate(history[-5:], 1):
for i, (_obs, action) in enumerate(history[-5:], 1):
action_str = self._action_to_string(action)
lines.append(f"{i}. {action_str}")
return "\n".join(lines)
Expand Down
21 changes: 12 additions & 9 deletions openadapt_ml/cloud/lambda_labs.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@

import requests


API_BASE = "https://cloud.lambdalabs.com/api/v1"

# Default port for HTTP server
Expand Down Expand Up @@ -1413,14 +1412,15 @@ def main():
print(f" Max runtime: {args.max_runtime} minutes")

# Generate initial dashboard with setup status
import time as time_module
from pathlib import Path

from openadapt_ml.training.trainer import (
TrainingState,
TrainingConfig,
TrainingState,
generate_training_dashboard,
setup_job_directory,
)
import time as time_module

job_id = time_module.strftime("%Y%m%d_%H%M%S")
output_dir = setup_job_directory("training_output", job_id)
Expand Down Expand Up @@ -1824,9 +1824,10 @@ def update_dashboard(
# One-shot dashboard refresh
import time as time_module
from pathlib import Path

from openadapt_ml.training.trainer import (
TrainingState,
TrainingConfig,
TrainingState,
generate_training_dashboard,
)

Expand Down Expand Up @@ -1952,8 +1953,8 @@ def update_dashboard(
if getattr(args, "stub", False):
from openadapt_ml.training.stub_provider import StubTrainingProvider
from openadapt_ml.training.trainer import (
TrainingState,
TrainingConfig,
TrainingState,
generate_training_dashboard,
)

Expand Down Expand Up @@ -2041,11 +2042,11 @@ def update_dashboard(status):

# Use job-scoped directory structure
from openadapt_ml.training.trainer import (
TrainingState,
TrainingConfig,
TrainingState,
generate_training_dashboard,
setup_job_directory,
get_current_job_directory,
setup_job_directory,
)

base_dir = Path("training_output")
Expand Down Expand Up @@ -2767,9 +2768,10 @@ def log_message(self, format, *args):
elif args.command == "sync":
# Sync training output from Lambda and regenerate navigation for file:// protocol
from pathlib import Path

from openadapt_ml.training.trainer import (
TrainingState,
TrainingConfig,
TrainingState,
generate_training_dashboard,
regenerate_all_dashboards,
)
Expand Down Expand Up @@ -2878,9 +2880,10 @@ def log_message(self, format, *args):

elif args.command == "viewer":
# Regenerate and open local viewer (no Lambda required)
import re
from pathlib import Path

from openadapt_ml.training.trainer import regenerate_all_dashboards
import re

output_dir = Path(args.output)

Expand Down
29 changes: 15 additions & 14 deletions openadapt_ml/cloud/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ def _regenerate_benchmark_viewer_if_available(output_dir: Path) -> bool:
Returns True if benchmark viewer was regenerated, False otherwise.
"""
from openadapt_ml.training.benchmark_viewer import (
generate_multi_run_benchmark_viewer,
generate_empty_benchmark_viewer,
generate_multi_run_benchmark_viewer,
)

benchmark_results_dir = Path("benchmark_results")
Expand Down Expand Up @@ -578,6 +578,7 @@ def do_POST(self):
# Run benchmark in background thread with progress logging
def run_benchmark():
import subprocess

from dotenv import load_dotenv

# Load .env file for API keys
Expand Down Expand Up @@ -753,7 +754,7 @@ def do_GET(self):
# Return LIVE Azure job status from Azure ML
# Supports ?force=true parameter for manual refresh (always fetches live)
try:
from urllib.parse import urlparse, parse_qs
from urllib.parse import parse_qs, urlparse

query = parse_qs(urlparse(self.path).query)
force_refresh = query.get("force", ["false"])[0].lower() == "true"
Expand All @@ -777,7 +778,7 @@ def do_GET(self):
elif self.path.startswith("/api/benchmark-sse"):
# Server-Sent Events endpoint for real-time benchmark updates
try:
from urllib.parse import urlparse, parse_qs
from urllib.parse import parse_qs, urlparse

query = parse_qs(urlparse(self.path).query)
interval = int(query.get("interval", [5])[0])
Expand Down Expand Up @@ -807,7 +808,7 @@ def do_GET(self):
# Return live logs for running Azure job
try:
# Parse job_id from query string
from urllib.parse import urlparse, parse_qs
from urllib.parse import parse_qs, urlparse

query = parse_qs(urlparse(self.path).query)
job_id = query.get("job_id", [None])[0]
Expand Down Expand Up @@ -2319,8 +2320,8 @@ def _get_current_run(self) -> dict:
- started_at: str - ISO timestamp
- elapsed_minutes: int
"""
import subprocess
import re
import subprocess

result = {
"running": False,
Expand Down Expand Up @@ -2627,7 +2628,7 @@ def _get_benchmark_metrics(self) -> dict:
continue

# Calculate averages
for domain, stats in domain_breakdown.items():
for stats in domain_breakdown.values():
if stats["total"] > 0:
stats["rate"] = stats["success"] / stats["total"]
stats["avg_steps"] = stats["total_steps"] / stats["total"]
Expand Down Expand Up @@ -2726,7 +2727,7 @@ def _get_task_execution(self, run_name: str, task_id: str) -> dict:
try:
return json.loads(execution_file.read_text())
except (json.JSONDecodeError, IOError) as e:
raise Exception(f"Failed to load execution data: {e}")
raise Exception(f"Failed to load execution data: {e}") from e

async def _detect_running_benchmark(
self, vm_ip: str, container_name: str = "winarena"
Expand All @@ -2744,8 +2745,8 @@ async def _detect_running_benchmark(
- progress: dict with tasks_completed, total_tasks, current_step
- recent_logs: str (last few log lines)
"""
import subprocess
import re
import subprocess

result = {
"running": False,
Expand Down Expand Up @@ -2889,8 +2890,8 @@ def _stream_benchmark_updates(self, interval: int):
Uses a generator-based approach to avoid blocking the main thread
and properly handles client disconnection.
"""
import time
import select
import time

HEARTBEAT_INTERVAL = 30 # seconds

Expand Down Expand Up @@ -3125,8 +3126,8 @@ def _stream_azure_ops_updates(self):
- heartbeat: Keep-alive signal every 30 seconds
- error: Error messages
"""
import time
import select
import time
from pathlib import Path

HEARTBEAT_INTERVAL = 30 # seconds
Expand Down Expand Up @@ -3191,9 +3192,9 @@ def check_client_connected() -> bool:
read_status,
)
from openadapt_evals.infrastructure.session_tracker import (
DEFAULT_SESSION_FILE,
get_session,
update_session_vm_state,
DEFAULT_SESSION_FILE,
)

status_file = Path(DEFAULT_OUTPUT_FILE)
Expand Down Expand Up @@ -3356,8 +3357,8 @@ def _detect_running_benchmark_sync(
Avoids creating a new event loop on each call which causes issues
when called from a synchronous context.
"""
import subprocess
import re
import subprocess

result = {
"running": False,
Expand Down Expand Up @@ -3643,10 +3644,10 @@ class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
def cmd_viewer(args: argparse.Namespace) -> int:
"""Regenerate viewer from local training output."""
from openadapt_ml.training.trainer import (
TrainingConfig,
TrainingState,
generate_training_dashboard,
generate_unified_viewer_from_output_dir,
TrainingState,
TrainingConfig,
)

current_dir = get_current_output_dir()
Expand Down
2 changes: 1 addition & 1 deletion openadapt_ml/cloud/ssh_tunnel.py
Original file line number Diff line number Diff line change
Expand Up @@ -542,8 +542,8 @@ def _check_tunnel_works(self, local_port: int, remote_port: int) -> bool:
Returns:
True if tunnel appears to be working.
"""
import urllib.request
import urllib.error
import urllib.request

try:
if remote_port == 5000:
Expand Down
1 change: 0 additions & 1 deletion openadapt_ml/datasets/next_action.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

from openadapt_ml.schema import Action, ActionType, Episode, Step, UIElement


# Coordinate-based DSL system prompt (original)
SYSTEM_PROMPT = (
"You are a GUI automation agent. Given a screenshot and a user goal, "
Expand Down
Loading
Loading