Spaces:
Sleeping
Sleeping
File size: 6,831 Bytes
0483756 | 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 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | import asyncio
import os
import random
import csv
import json
import statistics
import time
import subprocess
import socket
from datetime import datetime
from typing import List, Dict
# Standardize environment variables BEFORE importing inference
# This handles the case where users set variables with quotes in CMD
for key in ["API_BASE_URL", "API_KEY", "MODEL_NAME"]:
val = os.environ.get(key)
if val:
# Strip literal quotes that CMD sometimes includes
os.environ[key] = val.strip('"').strip("'")
# Set defaults if not provided
if "API_BASE_URL" not in os.environ:
os.environ["API_BASE_URL"] = "http://127.0.0.1:11434/v1"
if "API_KEY" not in os.environ:
os.environ["API_KEY"] = "ollama"
# (MODEL_NAME is handled inside inference.py default, but we can set it here too)
if "MODEL_NAME" not in os.environ:
os.environ["MODEL_NAME"] = "qwen3.5:latest"
# Import the core logic from inference.py
from inference import (
MaterialForgeEnv,
run_episode,
start_environment_server,
TASKS as ORIGINAL_TASKS,
MODEL_NAME,
SUCCESS_THRESHOLD
)
from openai import OpenAI
def is_port_open(port):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
return s.connect_ex(('127.0.0.1', port)) == 0
def start_ollama_server():
if is_port_open(11434):
print("[INFO] Ollama server is already running on port 11434.")
return None
print("[INFO] Ollama server not detected. Starting 'ollama serve'...")
try:
proc = subprocess.Popen(
["ollama", "serve"],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP | subprocess.DETACHED_PROCESS if os.name == 'nt' else 0
)
# Wait up to 30 seconds for Ollama to become ready
start_time = time.time()
while time.time() - start_time < 30:
if is_port_open(11434):
print("[INFO] Ollama server started successfully.")
# Give it an extra second to initialize routes
time.sleep(2)
return proc
time.sleep(1)
print("[WARNING] Ollama server start timed out. It may still be warming up.")
return proc
except Exception as e:
print(f"[ERROR] Failed to start Ollama server: {e}")
return None
async def run_analytical_suite(num_trials: int = 100, mode: str = "llm"):
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
report_file = f"benchmark_{mode}_{timestamp}.csv"
summary_file = f"summary_{mode}_{timestamp}.txt"
ollama_proc = None
if mode == "llm":
ollama_proc = start_ollama_server()
print(f"π Starting Analytical Benchmark Task ({mode.upper()} mode)")
print(f"π Timestamp: {timestamp}")
print(f"π Logging results to: {report_file}")
api_url = os.environ.get("API_BASE_URL", "http://localhost:11434/v1")
api_key = os.environ.get("API_KEY", "ollama")
# In heuristic mode, we don't need a real client
client = OpenAI(base_url=api_url, api_key=api_key) if mode == "llm" else None
if mode == "heuristic":
print("π Mode: Pure Heuristic (LLM Bypassed)")
else:
print(f"π€ Model: {os.getenv('MODEL_NAME', MODEL_NAME)}")
# Start the environment server once
server_proc = start_environment_server(port=7860)
env = MaterialForgeEnv(base_url="http://127.0.0.1:7860")
try:
await env.connect()
except Exception as e:
print(f"β Connection failed: {e}. Is Ollama or the server running?")
if server_proc: server_proc.terminate()
return
results = []
successes = 0
print("\n" + "="*50)
print(f"{'Trial':<8} | {'Seed':<8} | {'Score':<8} | {'Status':<10}")
print("-" * 50)
with open(report_file, mode='w', newline='') as csvfile:
fieldnames = ['trial', 'seed', 'score', 'success', 'timestamp']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
for i in range(1, num_trials + 1):
seed = random.randint(1000, 9999)
# Select a random task type from the original list as a template
template = random.choice(ORIGINAL_TASKS)
task = {
"name": f"analytical-{i}",
"difficulty": template["difficulty"],
"seed": seed
}
try:
# Run the episode without printing every single [STEP] to keep log clean
# We wrap it to suppress standard prints if we wanted to, but let's keep it simple
score = await run_episode(env, client, task)
is_success = score >= SUCCESS_THRESHOLD
results.append(score)
if is_success:
successes += 1
status = "β
PASS" if is_success else "β FAIL"
print(f"{i:<8} | {seed:<8} | {score:<8.3f} | {status:<10}")
writer.writerow({
'trial': i,
'seed': seed,
'score': f"{score:.3f}",
'success': is_success,
'timestamp': datetime.now().isoformat()
})
except Exception as e:
print(f"Trial {i} Error: {e}")
# Final Analysis
summary_data = [
"="*50,
"π FINAL ANALYTICAL REPORT",
"="*50,
f"Mode: {mode.upper()}",
f"Model: {os.getenv('MODEL_NAME', MODEL_NAME) if mode == 'llm' else 'Heuristic-Only'}",
f"Total Trials: {num_trials}",
f"Success Rate: {(successes/num_trials)*100:.1f}%",
f"Average Score: {statistics.mean(results):.3f}",
f"Max Score: {max(results):.3f}",
f"Min Score: {min(results):.3f}",
"="*50
]
report_text = "\n".join(summary_data)
print("\n" + report_text)
with open(summary_file, 'w') as f:
f.write(report_text)
# Cleanup
await env.close()
if server_proc:
server_proc.terminate()
server_proc.wait()
if ollama_proc:
print("[INFO] Terminating local Ollama server...")
ollama_proc.terminate()
try:
ollama_proc.wait(timeout=5)
except subprocess.TimeoutExpired:
ollama_proc.kill()
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--trials", type=int, default=100)
parser.add_argument("--mode", type=str, choices=["llm", "heuristic"], default="llm")
args = parser.parse_args()
asyncio.run(run_analytical_suite(args.trials, mode=args.mode))
|