| # AEPO Local Testing Guide β qwen2.5-coder:32b via Ollama |
|
|
| This guide walks you through testing AEPO end-to-end on your local machine using |
| `qwen2.5-coder:32b` served by Ollama as the agent's LLM backend. |
|
|
| --- |
|
|
| ## Prerequisites |
|
|
| | Tool | Version | Install | |
| |---|---|---| |
| | Python | 3.10 | Already installed | |
| | Ollama | latest | https://ollama.com/download | |
| | qwen2.5-coder:32b model | β | `ollama pull qwen2.5-coder:32b` | |
|
|
| --- |
|
|
| ## Step 1 β Pull the model |
|
|
| Open a terminal and run: |
|
|
| ```powershell |
| ollama pull qwen2.5-coder:32b |
| ``` |
|
|
| Wait for the download to finish. Verify it is available: |
|
|
| ```powershell |
| ollama list |
| # Should show: qwen2.5-coder:32b ... xx GB |
| ``` |
|
|
| --- |
|
|
| ## Step 2 β Start the Ollama server |
|
|
| Ollama needs to be running before the inference script talks to it. |
|
|
| ```powershell |
| ollama serve |
| ``` |
|
|
| Leave this terminal open. Ollama listens on `http://localhost:11434` by default. |
|
|
| --- |
|
|
| ## Step 3 β Install project dependencies |
|
|
| In a **new terminal**, from the project root: |
|
|
| ```powershell |
| cd C:\Users\Umesh Maurya\projects\autonomous-enterprise-payment-orchestrator |
| pip install -r requirements.txt |
| ``` |
|
|
| --- |
|
|
| ## Step 4 β Start the AEPO FastAPI server |
|
|
| The inference script calls the environment via HTTP, so the server must be up first. |
|
|
| ```powershell |
| uvicorn server.app:app --host 0.0.0.0 --port 7860 |
| ``` |
|
|
| Verify it is healthy: |
|
|
| ```powershell |
| # In another terminal |
| curl http://localhost:7860/ |
| # Expected: {"status":"healthy","message":"AEPO is live..."} |
| |
| # NEW: Contract declaration (Fix 9.4 β verifies 4-tuple bridge is live) |
| curl http://localhost:7860/contract |
| # Expected: {"step_tuple":"4-tuple","openenv_compliant":true,...} |
| ``` |
|
|
| Leave this terminal open. |
|
|
| --- |
|
|
| ## Step 5 β Run inference with qwen2.5-coder:32b |
|
|
| Open a **third terminal** from the project root. Set environment variables to point |
| inference.py at the local server and the Ollama OpenAI-compatible endpoint: |
|
|
| ```powershell |
| # PowerShell |
| $env:SPACE_URL = "http://localhost:7860" |
| $env:API_BASE_URL = "http://localhost:11434/v1" |
| $env:MODEL_NAME = "qwen2.5-coder:32b" |
| $env:HF_TOKEN = "ollama" # Ollama ignores the token; any non-empty string works |
| $env:DRY_RUN = "false" # Use the real LLM |
| $env:AGENT_MODE = "llm" # Default: use the LLM backend (llm|qtable|heuristic) |
| |
| python inference.py |
| ``` |
|
|
| ```bash |
| # bash / Git Bash equivalent |
| SPACE_URL="http://localhost:7860" \ |
| API_BASE_URL="http://localhost:11434/v1" \ |
| MODEL_NAME="qwen2.5-coder:32b" \ |
| HF_TOKEN="ollama" \ |
| DRY_RUN="false" \ |
| AGENT_MODE="llm" \ |
| python inference.py |
| ``` |
|
|
| ### Expected stdout output |
|
|
| ``` |
| [START] task=easy env=aepo model=qwen2.5-coder:32b |
| [STEP] step=1 action={"risk_decision":0,"crypto_verify":1,"infra_routing":0,"db_retry_policy":0,"settlement_policy":0,"app_priority":2} reward=0.80 done=false error=null |
| [STEP] step=2 action={"risk_decision":0,"crypto_verify":1,"infra_routing":0,"db_retry_policy":0,"settlement_policy":0,"app_priority":2} reward=0.80 done=false error=null |
| ... |
| [END] success=true steps=100 score=0.78 rewards=0.80,0.80,... |
| |
| [START] task=medium env=aepo model=qwen2.5-coder:32b |
| ... |
| [END] success=false steps=100 score=0.42 rewards=... |
| |
| [START] task=hard env=aepo model=qwen2.5-coder:32b |
| ... |
| [END] success=true steps=100 score=0.51 rewards=... |
| ``` |
|
|
| > **Note on action format**: The action JSON now contains **6 integer fields** (Phase 10 expansion). |
| > The three new fields are `db_retry_policy`, `settlement_policy`, and `app_priority`. |
|
|
| ### Rich terminal dashboard (stderr) |
|
|
| When `rich` is installed (`pip install rich`), each step also renders a colour-coded |
| live status line to **stderr** showing system health signals and the action taken: |
|
|
| ``` |
| task=easy step= 42 phase=normal LAG ββββββββββββββββββββββββ 3800 POOL ββββββββββββββββββββββββ 61% rwd=0.800 Reject/Normal |
| task=easy step= 43 phase=spike LAG ββββββββββββββββββββββββ 6100 POOL ββββββββββββββββββββββββ 83% rwd=0.750 Approve/Throttle |
| ``` |
|
|
| - **Red bar** = signal above 75 % of max (danger zone) |
| - **Yellow bar** = 50β75 % (warning zone) |
| - **Green bar** = below 50 % (healthy) |
|
|
| These lines go to `stderr` only β they do not appear in the `[STEP]` stdout stream and do not affect the OpenEnv grader. |
|
|
| --- |
|
|
| ## Step 6 β Quick smoke-test (no LLM needed) |
|
|
| Three modes are available via `AGENT_MODE`. Use the **qtable** mode for exact, reproducible scores: |
|
|
| ### Mode A β Heuristic agent (legacy dry-run) |
| ```powershell |
| $env:SPACE_URL = "http://localhost:7860" |
| $env:DRY_RUN = "true" # equivalent to AGENT_MODE=heuristic |
| python inference.py |
| ``` |
|
|
| ### Mode B β Q-table agent (trained snapshot, 100% reproducible) β recommended for judges |
| ```powershell |
| $env:SPACE_URL = "http://localhost:7860" |
| $env:AGENT_MODE = "qtable" |
| python inference.py |
| ``` |
| Requires `results/qtable.pkl` β run `python train.py` once to generate it. |
|
|
| ### Mode C β Heuristic (explicit) |
| ```powershell |
| $env:SPACE_URL = "http://localhost:7860" |
| $env:AGENT_MODE = "heuristic" |
| python inference.py |
| ``` |
|
|
| Expected scores by mode: |
|
|
| | Task | Heuristic | Q-table | Threshold | Pass? | |
| |---|---|---|---|---| |
| | `easy` | ~0.76 | ~0.81 | β₯ 0.75 | β
| |
| | `medium` | ~0.39β0.44 | ~0.52 | β₯ 0.45 | β
| |
| | `hard` | ~0.30β0.34 | **0.6650** | β₯ 0.30 | β
| |
|
|
| --- |
|
|
| ## Step 7 β Run the full test suite |
|
|
| ```powershell |
| pytest tests/ -v |
| # Expected: 182 passed |
| ``` |
|
|
| Run with coverage: |
|
|
| ```powershell |
| pip install pytest-cov |
| pytest tests/ --cov=unified_gateway --cov-report=term-missing |
| # unified_gateway.py: 97% |
| ``` |
|
|
| --- |
|
|
| ## Step 8 β Train the Q-table agent (optional) |
|
|
| ### Standard run |
|
|
| ```powershell |
| python train.py |
| ``` |
|
|
| Runs 500 episodes on the hard task in ~3β4 seconds on CPU. Produces: |
| - `results/reward_curve.png` β raw + rolling mean reward curve |
| - `results/reward_staircase.png` β phase-coloured staircase chart |
| - `results/qtable.pkl` β trained Q-table snapshot for `AGENT_MODE=qtable` |
| - `results/lag_predictor.pt` β LagPredictor weights (univariate world model) |
| - `results/multi_obs_predictor.pt` β MultiObsPredictor weights (full 10-dim world model, Fix 10.1) |
| - ASCII comparison table: Random vs Heuristic vs Trained |
|
|
| Expected key output lines: |
| ``` |
| [BLIND SPOT #1 DISCOVERED] episode=3 step=42 reward=0.8800 | ... |
| episode=10/500 recent_mean=0.6234 epsilon=0.990 lag_model_loss=0.012345 world_model_loss=0.023456 ... |
| hard 0.2507 0.2955 0.6650 0.30 PASS |
| ``` |
|
|
| ### A/B comparison mode (`--compare`) |
|
|
| ```powershell |
| pip install rich # one-time |
| python train.py --compare |
| ``` |
|
|
| After training, renders a colour-coded rich table comparing the Heuristic (LLM |
| baseline) agent against the Trained AEPO agent across all three tasks: |
|
|
| ``` |
| AEPO β A/B Comparison: Heuristic (LLM Baseline) vs Trained Agent |
| ββββββββββββ¬βββββββββββ¬βββββββββββββββββββββββββββ¬βββββββββββββββββ¬ββββββββββββ¬βββββββββ |
| β Task β Random β Heuristic (LLM Baseline) β Trained (AEPO)β Threshold β Pass? β |
| ββββββββββββΌβββββββββββΌβββββββββββββββββββββββββββΌβββββββββββββββββΌββββββββββββΌβββββββββ€ |
| β EASY β 0.2134 β 0.7612 β 0.8103 β 0.75 β PASS β |
| β MEDIUM β 0.1987 β 0.4102 β 0.5240 β 0.45 β PASS β |
| β HARD β 0.1543 β 0.2955 β 0.6650 β 0.30 β PASS β |
| ββββββββββββ΄βββββββββββ΄βββββββββββββββββββββββββββ΄βββββββββββββββββ΄ββββββββββββ΄βββββββββ |
| ``` |
|
|
| ### Viewing the generated PNG charts |
|
|
| ```powershell |
| # Open both charts (Windows) |
| start results\reward_curve.png |
| start results\reward_staircase.png |
| ``` |
|
|
| The staircase chart (`reward_staircase.png`) colour-codes the background: |
| - **Green region** = Easy curriculum (level 0) |
| - **Orange region** = Medium curriculum (level 1) |
| - **Red region** = Hard curriculum (level 2) |
|
|
| The staircase pattern (agent improves β adversary escalates β agent adapts) is |
| the primary visual proof of recursive self-improvement for the pitch demo. |
|
|
| --- |
|
|
| ## Troubleshooting |
|
|
| ### `ConnectionRefusedError` on inference.py |
|
|
| The FastAPI server is not running. Start it first (Step 4). |
|
|
| ### `qwen2.5-coder:32b` not found by Ollama |
|
|
| Run `ollama list` to confirm the model name. If it shows `qwen2.5-coder:32b` |
| but inference fails, ensure `MODEL_NAME` exactly matches the name shown by `ollama list`. |
|
|
| ### LLM returns malformed action |
|
|
| `parse_llm_action()` in `inference.py` catches all parse errors and falls back to |
| the safe conservative action (Reject + FullVerify + Normal). You will see this in the |
| step log as the same action repeating. This is expected for smaller models that |
| don't follow the 6-integer output format consistently. |
|
|
| To improve LLM compliance, the system prompt in `inference.py` already instructs the |
| model to output exactly six space-separated integers. If the model still produces |
| malformed output, try adjusting `temperature=0.0` (already set) or using a larger |
| quantisation level in Ollama. |
|
|
| ### `ModuleNotFoundError: No module named 'torch'` |
|
|
| ```powershell |
| pip install torch==2.2.0+cpu --extra-index-url https://download.pytorch.org/whl/cpu |
| ``` |
|
|
| ### Ollama OpenAI endpoint not working |
|
|
| Ollama exposes an OpenAI-compatible API at `/v1/chat/completions`. Verify: |
|
|
| ```powershell |
| curl http://localhost:11434/v1/models |
| # Should list available models including qwen2.5-coder:32b |
| ``` |
|
|
| --- |
|
|
| ## Local Testing Checklist |
|
|
| ``` |
| β ollama serve is running in background terminal |
| β ollama list shows qwen2.5-coder:32b |
| β uvicorn server.app:app --port 7860 is running |
| β curl http://localhost:7860/ returns {"status":"healthy"} |
| β curl http://localhost:7860/contract returns {"step_tuple":"4-tuple","openenv_compliant":true} |
| β AGENT_MODE=heuristic python inference.py β [END] lines for all 3 tasks |
| β AGENT_MODE=qtable python inference.py β hard score=0.67 (requires results/qtable.pkl) |
| β pytest tests/ -v β all tests pass |
| β (optional) python train.py β hard PASS; world_model_loss logged; results/multi_obs_predictor.pt created |
| β (optional) python train.py --compare β coloured rich A/B comparison table |
| ``` |
|
|