Spaces:
Running
Running
Deploy Project Epsilon Space bundle
Browse files- .env.app.example +8 -0
- .env.training.example +7 -0
- README.md +3 -1
- docs/HF_SPACE_README.md +3 -1
- inference.py +16 -6
- scripts/deploy_hf_space.py +15 -2
- src/executive_assistant/deployment.py +3 -1
- tests/test_inference.py +13 -0
.env.app.example
CHANGED
|
@@ -1,3 +1,11 @@
|
|
| 1 |
OPENROUTER_API_KEY=
|
|
|
|
|
|
|
| 2 |
OPENROUTER_SITE_URL=http://localhost:7860
|
| 3 |
OPENROUTER_APP_NAME=Autonomous Executive Assistant Sandbox
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
OPENROUTER_API_KEY=
|
| 2 |
+
OPENROUTER_MODEL=google/gemma-4-31b-it
|
| 3 |
+
OPENROUTER_BASE_URL=https://openrouter.ai/api/v1
|
| 4 |
OPENROUTER_SITE_URL=http://localhost:7860
|
| 5 |
OPENROUTER_APP_NAME=Autonomous Executive Assistant Sandbox
|
| 6 |
+
|
| 7 |
+
# Hackathon-compatible aliases. Set OPENAI_API_KEY to the same OpenRouter key
|
| 8 |
+
# only when running inference.py under a validator that expects this name.
|
| 9 |
+
OPENAI_API_KEY=
|
| 10 |
+
API_BASE_URL=https://openrouter.ai/api/v1
|
| 11 |
+
MODEL_NAME=google/gemma-4-31b-it
|
.env.training.example
CHANGED
|
@@ -1,6 +1,13 @@
|
|
| 1 |
OPENROUTER_API_KEY=
|
| 2 |
OPENROUTER_MODEL=google/gemma-4-31b-it
|
|
|
|
| 3 |
OPENROUTER_SITE_URL=http://localhost:8888
|
| 4 |
OPENROUTER_APP_NAME=Autonomous Executive Assistant Sandbox Training
|
| 5 |
OPENROUTER_TEMPERATURE=0.1
|
| 6 |
OPENROUTER_MAX_TOKENS=600
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
OPENROUTER_API_KEY=
|
| 2 |
OPENROUTER_MODEL=google/gemma-4-31b-it
|
| 3 |
+
OPENROUTER_BASE_URL=https://openrouter.ai/api/v1
|
| 4 |
OPENROUTER_SITE_URL=http://localhost:8888
|
| 5 |
OPENROUTER_APP_NAME=Autonomous Executive Assistant Sandbox Training
|
| 6 |
OPENROUTER_TEMPERATURE=0.1
|
| 7 |
OPENROUTER_MAX_TOKENS=600
|
| 8 |
+
|
| 9 |
+
# Hackathon-compatible aliases for inference.py. OPENAI_API_KEY should contain
|
| 10 |
+
# the same OpenRouter API key when using the validator-facing script.
|
| 11 |
+
OPENAI_API_KEY=
|
| 12 |
+
API_BASE_URL=https://openrouter.ai/api/v1
|
| 13 |
+
MODEL_NAME=google/gemma-4-31b-it
|
README.md
CHANGED
|
@@ -65,7 +65,7 @@ To make that possible under hackathon constraints, we replaced live services wit
|
|
| 65 |
- **Environment state:** in-memory SQLite workspace simulating emails, todos, files, and action history
|
| 66 |
- **OpenEnv contract:** Pydantic models defining observations, actions, rewards, and policy decisions
|
| 67 |
- **Execution loop:** shared `EpisodeRunner` used by tests, scripts, notebook experiments, and the Gradio app
|
| 68 |
-
- **Policies:** deterministic baseline, tabular RL checkpoint replay, and optional OpenRouter-backed live policy execution
|
| 69 |
- **UI layer:** Gradio control room plus visible workspace snapshots for judges
|
| 70 |
|
| 71 |
## Seeded Judge Tasks
|
|
@@ -95,6 +95,8 @@ The environment includes a stakeholder email asking for exact metrics from a loc
|
|
| 95 |
- App port: `7860`
|
| 96 |
- Entry point: `python app.py`
|
| 97 |
- Optional secret: `OPENROUTER_API_KEY`
|
|
|
|
|
|
|
| 98 |
- A trained RL checkpoint is bundled in `artifacts/checkpoints/` so the `rl` policy is available immediately in the demo.
|
| 99 |
- The bundled RL artifact lives at `artifacts/checkpoints/q_policy_notebook.json`
|
| 100 |
- The Space is deployed from the same repository used for local tests and notebook-backed experiments
|
|
|
|
| 65 |
- **Environment state:** in-memory SQLite workspace simulating emails, todos, files, and action history
|
| 66 |
- **OpenEnv contract:** Pydantic models defining observations, actions, rewards, and policy decisions
|
| 67 |
- **Execution loop:** shared `EpisodeRunner` used by tests, scripts, notebook experiments, and the Gradio app
|
| 68 |
+
- **Policies:** deterministic baseline, tabular RL checkpoint replay, and optional OpenRouter-backed live policy execution through the OpenAI client compatibility layer
|
| 69 |
- **UI layer:** Gradio control room plus visible workspace snapshots for judges
|
| 70 |
|
| 71 |
## Seeded Judge Tasks
|
|
|
|
| 95 |
- App port: `7860`
|
| 96 |
- Entry point: `python app.py`
|
| 97 |
- Optional secret: `OPENROUTER_API_KEY`
|
| 98 |
+
- OpenAI-compatible base URL: `https://openrouter.ai/api/v1`
|
| 99 |
+
- Model: `google/gemma-4-31b-it`
|
| 100 |
- A trained RL checkpoint is bundled in `artifacts/checkpoints/` so the `rl` policy is available immediately in the demo.
|
| 101 |
- The bundled RL artifact lives at `artifacts/checkpoints/q_policy_notebook.json`
|
| 102 |
- The Space is deployed from the same repository used for local tests and notebook-backed experiments
|
docs/HF_SPACE_README.md
CHANGED
|
@@ -65,7 +65,7 @@ To make that possible under hackathon constraints, we replaced live services wit
|
|
| 65 |
- **Environment state:** in-memory SQLite workspace simulating emails, todos, files, and action history
|
| 66 |
- **OpenEnv contract:** Pydantic models defining observations, actions, rewards, and policy decisions
|
| 67 |
- **Execution loop:** shared `EpisodeRunner` used by tests, scripts, notebook experiments, and the Gradio app
|
| 68 |
-
- **Policies:** deterministic baseline, tabular RL checkpoint replay, and optional OpenRouter-backed live policy execution
|
| 69 |
- **UI layer:** Gradio control room plus visible workspace snapshots for judges
|
| 70 |
|
| 71 |
## Seeded Judge Tasks
|
|
@@ -95,6 +95,8 @@ The environment includes a stakeholder email asking for exact metrics from a loc
|
|
| 95 |
- App port: `7860`
|
| 96 |
- Entry point: `python app.py`
|
| 97 |
- Optional secret: `OPENROUTER_API_KEY`
|
|
|
|
|
|
|
| 98 |
- Bundled RL checkpoint path: `artifacts/checkpoints/q_policy_notebook.json`
|
| 99 |
- The Space is deployed from the same repository used for local tests and notebook-backed experiments
|
| 100 |
|
|
|
|
| 65 |
- **Environment state:** in-memory SQLite workspace simulating emails, todos, files, and action history
|
| 66 |
- **OpenEnv contract:** Pydantic models defining observations, actions, rewards, and policy decisions
|
| 67 |
- **Execution loop:** shared `EpisodeRunner` used by tests, scripts, notebook experiments, and the Gradio app
|
| 68 |
+
- **Policies:** deterministic baseline, tabular RL checkpoint replay, and optional OpenRouter-backed live policy execution through the OpenAI client compatibility layer
|
| 69 |
- **UI layer:** Gradio control room plus visible workspace snapshots for judges
|
| 70 |
|
| 71 |
## Seeded Judge Tasks
|
|
|
|
| 95 |
- App port: `7860`
|
| 96 |
- Entry point: `python app.py`
|
| 97 |
- Optional secret: `OPENROUTER_API_KEY`
|
| 98 |
+
- OpenAI-compatible base URL: `https://openrouter.ai/api/v1`
|
| 99 |
+
- Model: `google/gemma-4-31b-it`
|
| 100 |
- Bundled RL checkpoint path: `artifacts/checkpoints/q_policy_notebook.json`
|
| 101 |
- The Space is deployed from the same repository used for local tests and notebook-backed experiments
|
| 102 |
|
inference.py
CHANGED
|
@@ -17,15 +17,25 @@ TASKS = [
|
|
| 17 |
|
| 18 |
|
| 19 |
def build_openai_compatible_policy() -> OpenRouterPolicy:
|
| 20 |
-
api_key = os.environ.get("
|
| 21 |
-
|
| 22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
if not api_key:
|
| 24 |
-
raise RuntimeError("OPENAI_API_KEY is required.")
|
| 25 |
if not base_url:
|
| 26 |
-
raise RuntimeError("API_BASE_URL is required.")
|
| 27 |
if not model_name:
|
| 28 |
-
raise RuntimeError("MODEL_NAME is required.")
|
| 29 |
config = OpenRouterConfig(
|
| 30 |
api_key=api_key,
|
| 31 |
base_url=base_url,
|
|
|
|
| 17 |
|
| 18 |
|
| 19 |
def build_openai_compatible_policy() -> OpenRouterPolicy:
|
| 20 |
+
api_key = os.environ.get("OPENROUTER_API_KEY", "").strip() or os.environ.get(
|
| 21 |
+
"OPENAI_API_KEY", ""
|
| 22 |
+
).strip()
|
| 23 |
+
base_url = (
|
| 24 |
+
os.environ.get("OPENROUTER_BASE_URL", "").strip()
|
| 25 |
+
or os.environ.get("API_BASE_URL", "").strip()
|
| 26 |
+
or "https://openrouter.ai/api/v1"
|
| 27 |
+
)
|
| 28 |
+
model_name = (
|
| 29 |
+
os.environ.get("OPENROUTER_MODEL", "").strip()
|
| 30 |
+
or os.environ.get("MODEL_NAME", "").strip()
|
| 31 |
+
or "google/gemma-4-31b-it"
|
| 32 |
+
)
|
| 33 |
if not api_key:
|
| 34 |
+
raise RuntimeError("OPENROUTER_API_KEY or OPENAI_API_KEY is required.")
|
| 35 |
if not base_url:
|
| 36 |
+
raise RuntimeError("API_BASE_URL or OPENROUTER_BASE_URL is required.")
|
| 37 |
if not model_name:
|
| 38 |
+
raise RuntimeError("MODEL_NAME or OPENROUTER_MODEL is required.")
|
| 39 |
config = OpenRouterConfig(
|
| 40 |
api_key=api_key,
|
| 41 |
base_url=base_url,
|
scripts/deploy_hf_space.py
CHANGED
|
@@ -40,14 +40,14 @@ def build_parser() -> argparse.ArgumentParser:
|
|
| 40 |
)
|
| 41 |
parser.add_argument(
|
| 42 |
"--team-name",
|
| 43 |
-
default=os.environ.get("HF_SPACE_TEAM_NAME", "
|
| 44 |
help="Team name shown in the generated HF README.",
|
| 45 |
)
|
| 46 |
parser.add_argument(
|
| 47 |
"--hf-usernames",
|
| 48 |
default=os.environ.get(
|
| 49 |
"HF_SPACE_TEAM_USERNAMES",
|
| 50 |
-
"
|
| 51 |
),
|
| 52 |
help="Comma-separated HF usernames for the HF README placeholders.",
|
| 53 |
)
|
|
@@ -61,6 +61,16 @@ def build_parser() -> argparse.ArgumentParser:
|
|
| 61 |
default=os.environ.get("OPENROUTER_API_KEY", "").strip(),
|
| 62 |
help="Optional secret to set on the Space during deployment.",
|
| 63 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
parser.add_argument(
|
| 65 |
"--private",
|
| 66 |
action="store_true",
|
|
@@ -159,6 +169,9 @@ def main() -> int:
|
|
| 159 |
if checkpoint_path is not None:
|
| 160 |
messages.append(f"Bundled RL checkpoint: {checkpoint_path.relative_to(stage_dir)}")
|
| 161 |
messages.append(maybe_set_space_secret(api, config.repo_id, "OPENROUTER_API_KEY", args.openrouter_api_key))
|
|
|
|
|
|
|
|
|
|
| 162 |
messages.append(maybe_set_space_variable(api, config.repo_id, "OPENROUTER_APP_NAME", config.title))
|
| 163 |
messages.append(maybe_set_space_variable(api, config.repo_id, "OPENROUTER_SITE_URL", config.app_url))
|
| 164 |
|
|
|
|
| 40 |
)
|
| 41 |
parser.add_argument(
|
| 42 |
"--team-name",
|
| 43 |
+
default=os.environ.get("HF_SPACE_TEAM_NAME", "Team Epsilon"),
|
| 44 |
help="Team name shown in the generated HF README.",
|
| 45 |
)
|
| 46 |
parser.add_argument(
|
| 47 |
"--hf-usernames",
|
| 48 |
default=os.environ.get(
|
| 49 |
"HF_SPACE_TEAM_USERNAMES",
|
| 50 |
+
"flickinshots,ShreyaKhatik,itsayushdey",
|
| 51 |
),
|
| 52 |
help="Comma-separated HF usernames for the HF README placeholders.",
|
| 53 |
)
|
|
|
|
| 61 |
default=os.environ.get("OPENROUTER_API_KEY", "").strip(),
|
| 62 |
help="Optional secret to set on the Space during deployment.",
|
| 63 |
)
|
| 64 |
+
parser.add_argument(
|
| 65 |
+
"--api-base-url",
|
| 66 |
+
default=os.environ.get("API_BASE_URL", "https://openrouter.ai/api/v1").strip(),
|
| 67 |
+
help="OpenAI-compatible API base URL for inference.py. Defaults to OpenRouter.",
|
| 68 |
+
)
|
| 69 |
+
parser.add_argument(
|
| 70 |
+
"--model-name",
|
| 71 |
+
default=os.environ.get("MODEL_NAME", "google/gemma-4-31b-it").strip(),
|
| 72 |
+
help="OpenRouter model id for inference.py. Defaults to Gemma 4.",
|
| 73 |
+
)
|
| 74 |
parser.add_argument(
|
| 75 |
"--private",
|
| 76 |
action="store_true",
|
|
|
|
| 169 |
if checkpoint_path is not None:
|
| 170 |
messages.append(f"Bundled RL checkpoint: {checkpoint_path.relative_to(stage_dir)}")
|
| 171 |
messages.append(maybe_set_space_secret(api, config.repo_id, "OPENROUTER_API_KEY", args.openrouter_api_key))
|
| 172 |
+
messages.append(maybe_set_space_secret(api, config.repo_id, "OPENAI_API_KEY", args.openrouter_api_key))
|
| 173 |
+
messages.append(maybe_set_space_variable(api, config.repo_id, "API_BASE_URL", args.api_base_url))
|
| 174 |
+
messages.append(maybe_set_space_variable(api, config.repo_id, "MODEL_NAME", args.model_name))
|
| 175 |
messages.append(maybe_set_space_variable(api, config.repo_id, "OPENROUTER_APP_NAME", config.title))
|
| 176 |
messages.append(maybe_set_space_variable(api, config.repo_id, "OPENROUTER_SITE_URL", config.app_url))
|
| 177 |
|
src/executive_assistant/deployment.py
CHANGED
|
@@ -155,7 +155,7 @@ To make that possible under hackathon constraints, we replaced live services wit
|
|
| 155 |
- **Environment state:** in-memory SQLite workspace simulating emails, todos, files, and action history
|
| 156 |
- **OpenEnv contract:** Pydantic models defining observations, actions, rewards, and policy decisions
|
| 157 |
- **Execution loop:** shared `EpisodeRunner` used by tests, scripts, notebook experiments, and the Gradio app
|
| 158 |
-
- **Policies:** deterministic baseline, tabular RL checkpoint replay, and optional OpenRouter-backed live policy execution
|
| 159 |
- **UI layer:** Gradio control room plus visible workspace snapshots for judges
|
| 160 |
|
| 161 |
## Seeded Judge Tasks
|
|
@@ -185,6 +185,8 @@ The environment includes a stakeholder email asking for exact metrics from a loc
|
|
| 185 |
- App port: `{config.app_port}`
|
| 186 |
- Entry point: `python app.py`
|
| 187 |
- Optional secret: `OPENROUTER_API_KEY`
|
|
|
|
|
|
|
| 188 |
- {checkpoint_note}
|
| 189 |
- The bundled RL artifact lives at `artifacts/checkpoints/{config.checkpoint_name}`
|
| 190 |
- The Space is deployed from the same repository used for local tests and notebook-backed experiments
|
|
|
|
| 155 |
- **Environment state:** in-memory SQLite workspace simulating emails, todos, files, and action history
|
| 156 |
- **OpenEnv contract:** Pydantic models defining observations, actions, rewards, and policy decisions
|
| 157 |
- **Execution loop:** shared `EpisodeRunner` used by tests, scripts, notebook experiments, and the Gradio app
|
| 158 |
+
- **Policies:** deterministic baseline, tabular RL checkpoint replay, and optional OpenRouter-backed live policy execution through the OpenAI client compatibility layer
|
| 159 |
- **UI layer:** Gradio control room plus visible workspace snapshots for judges
|
| 160 |
|
| 161 |
## Seeded Judge Tasks
|
|
|
|
| 185 |
- App port: `{config.app_port}`
|
| 186 |
- Entry point: `python app.py`
|
| 187 |
- Optional secret: `OPENROUTER_API_KEY`
|
| 188 |
+
- OpenAI-compatible base URL: `https://openrouter.ai/api/v1`
|
| 189 |
+
- Model: `google/gemma-4-31b-it`
|
| 190 |
- {checkpoint_note}
|
| 191 |
- The bundled RL artifact lives at `artifacts/checkpoints/{config.checkpoint_name}`
|
| 192 |
- The Space is deployed from the same repository used for local tests and notebook-backed experiments
|
tests/test_inference.py
CHANGED
|
@@ -4,6 +4,19 @@ from inference import build_openai_compatible_policy
|
|
| 4 |
from src.executive_assistant.config import OpenRouterConfig
|
| 5 |
|
| 6 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
def test_openrouter_config_accepts_hackathon_env_names(monkeypatch) -> None:
|
| 8 |
monkeypatch.delenv("OPENROUTER_API_KEY", raising=False)
|
| 9 |
monkeypatch.delenv("OPENROUTER_BASE_URL", raising=False)
|
|
|
|
| 4 |
from src.executive_assistant.config import OpenRouterConfig
|
| 5 |
|
| 6 |
|
| 7 |
+
def test_inference_prefers_openrouter_api_with_openai_client(monkeypatch) -> None:
|
| 8 |
+
monkeypatch.setenv("OPENROUTER_API_KEY", "openrouter-key")
|
| 9 |
+
monkeypatch.setenv("OPENROUTER_BASE_URL", "https://openrouter.ai/api/v1")
|
| 10 |
+
monkeypatch.setenv("OPENROUTER_MODEL", "google/gemma-4-31b-it")
|
| 11 |
+
monkeypatch.setenv("OPENAI_API_KEY", "wrong-openai-key")
|
| 12 |
+
monkeypatch.setenv("API_BASE_URL", "https://api.openai.com/v1")
|
| 13 |
+
monkeypatch.setenv("MODEL_NAME", "wrong-model")
|
| 14 |
+
policy = build_openai_compatible_policy()
|
| 15 |
+
assert policy.config.api_key == "openrouter-key"
|
| 16 |
+
assert policy.config.base_url == "https://openrouter.ai/api/v1"
|
| 17 |
+
assert policy.config.model_name == "google/gemma-4-31b-it"
|
| 18 |
+
|
| 19 |
+
|
| 20 |
def test_openrouter_config_accepts_hackathon_env_names(monkeypatch) -> None:
|
| 21 |
monkeypatch.delenv("OPENROUTER_API_KEY", raising=False)
|
| 22 |
monkeypatch.delenv("OPENROUTER_BASE_URL", raising=False)
|