ai-code-review-env-v2 / inference.py
Yaxh64's picture
Update inference.py
7f3a83d verified
Raw
History Blame Contribute Delete
4.35 kB
"""
inference.py - OpenEnv Code Review Environment
"""
import socket
import socketserver
import threading
import time
import json
from http.server import BaseHTTPRequestHandler
from env.environment import CodeReviewEnvironment
from env.models import Action
ENV_NAME = "ai-code-review-env"
TASK_NAME = "code-review"
MODEL = "gpt-4.1-mini"
PORT = 7860
env = CodeReviewEnvironment()
class ThreadedServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
allow_reuse_address = True
allow_reuse_port = True # SO_REUSEPORT β€” avoids Errno 98
daemon_threads = True
class Handler(BaseHTTPRequestHandler):
def log_message(self, *a): pass
def _json(self, data, status=200):
body = json.dumps(data).encode()
self.send_response(status)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
def do_GET(self):
self.send_response(200)
self.end_headers()
self.wfile.write(b"OK")
def do_POST(self):
try:
length = int(self.headers.get("Content-Length", 0))
body = self.rfile.read(length)
if self.path == "/reset":
obs = env.reset()
self._json({"observation": obs.__dict__, "reward": 0.0, "done": False, "info": {}})
elif self.path == "/step":
data = json.loads(body.decode())
action = Action(action_type=data.get("action_type", ""), content=data.get("content", ""))
result = env.step(action)
result["observation"] = result["observation"].__dict__
self._json(result)
elif self.path == "/state":
self._json(env.state.__dict__)
else:
self._json({"error": "not found"}, 404)
except Exception as e:
self._json({"error": str(e)}, 500)
ACTIONS = [
Action("identify",
"There is a missing closing parenthesis in the function parameter list. "
"This is a syntax error β€” the opening paren is not closed before the brace."),
Action("fix",
"function add(a, b) {\n return a + b;\n}"),
Action("identify",
"Logic error: the condition is wrong and inverted. "
"The modulo remainder check uses === 1 which matches odd numbers, "
"not even. The === comparison is incorrect β€” it should be === 0."),
Action("fix",
"function isEven(n) {\n return n % 2 === 0;\n}"),
Action("identify",
"Performance issue: the loop is inefficient because it does repeated lookup "
"of arr.length on every iteration. A modern functional forEach or for...of "
"approach avoids repeated property lookups and is easier to optimize."),
Action("fix",
"arr.forEach(item => {\n console.log(item);\n});"),
]
LABELS = [
"identify:task1", "fix:task1",
"identify:task2", "fix:task2",
"identify:task3", "fix:task3",
]
def run():
print(f"[START] task={TASK_NAME} env={ENV_NAME} model={MODEL}", flush=True)
env.reset()
rewards = []
for i, action in enumerate(ACTIONS):
result = env.step(action)
reward = float(result.get("reward", 0.0))
done = result.get("done", False)
rewards.append(reward)
print(f"[STEP] step={i+1} action={LABELS[i]} reward={reward:.2f} done={str(done).lower()} error=null", flush=True)
if done:
break
rstr = ",".join(f"{r:.2f}" for r in rewards)
print(f"[END] success=true steps={len(rewards)} rewards={rstr}", flush=True)
def start_server():
"""Try to bind server; if port already in use, skip β€” evaluator owns the socket."""
try:
server = ThreadedServer(("0.0.0.0", PORT), Handler)
threading.Thread(target=server.serve_forever, daemon=True).start()
print(f"[INFO] Server started on port {PORT}", flush=True)
except OSError as e:
# Port already bound (e.g. evaluator owns it) β€” that's fine, just log and continue
print(f"[INFO] Port {PORT} already in use ({e}), skipping server bind", flush=True)
if __name__ == "__main__":
start_server()
time.sleep(0.5)
run()
while True:
time.sleep(30)