wordle-ors / server.py
AdithyaSK's picture
AdithyaSK HF Staff
migrate ors-sdk -> openreward
1019e58 verified
Raw
History Blame Contribute Delete
5.06 kB
"""
Wordle ORS Environment Server.
Exposes 2 tools via the Open Reward Standard (ORS):
1. guess — submit a 5-letter word guess
2. get_history — view all previous guesses and feedback
Each session maps to one WordleGame. Rewards are embedded in every
ToolOutput — the server returns game reward after each guess.
Usage:
python server.py # localhost:8080
python server.py --port 9090 # custom port
Deploy:
docker build -t wordle-ors .
docker run -p 8080:8080 wordle-ors
"""
import os
import sys
import argparse
from pathlib import Path
from pydantic import BaseModel
from openreward.environments import Environment, Server, tool, ToolOutput, TextBlock, Split
# Add parent to path for game import
_parent = str(Path(__file__).resolve().parents[1])
if _parent not in sys.path:
sys.path.insert(0, _parent)
from game import WordleGame, TASKS
# ---------------------------------------------------------------------------
# Pydantic input models for @tool methods
# ---------------------------------------------------------------------------
class GuessInput(BaseModel):
word: str
class HistoryInput(BaseModel):
pass
# ---------------------------------------------------------------------------
# ORS Environment
# ---------------------------------------------------------------------------
class WordleORS(Environment):
"""Wordle environment via ORS protocol.
Each session gets a WordleGame instance. Tools submit guesses and
inspect history. Rewards are computed inline from game state.
"""
def __init__(self, task_spec=None, secrets=None, **kwargs):
if task_spec is None:
task_spec = {}
if secrets is None:
secrets = {}
super().__init__(task_spec=task_spec, secrets=secrets)
self._game = None
# -- ORS lifecycle ------------------------------------------------------
def setup(self):
"""Called on first tool invocation — create WordleGame."""
answer = self.task_spec.get("answer", "")
self._game = WordleGame(answer=answer) if answer else WordleGame()
def teardown(self):
"""Called on session delete."""
self._game = None
# -- ORS metadata -------------------------------------------------------
@classmethod
def list_splits(cls):
return [Split(name="train", type="train")]
@classmethod
def list_tasks(cls, split: str):
return TASKS
def get_prompt(self):
return [TextBlock(
text=(
"Play Wordle! Guess the hidden 5-letter word in 6 attempts.\n"
"After each guess, you'll see feedback:\n"
" 🟩 = correct letter, correct position\n"
" 🟨 = correct letter, wrong position\n"
" ⬛ = letter not in the word\n"
"Use the guess tool to submit each attempt."
)
)]
# -- Tools --------------------------------------------------------------
@tool
def guess(self, params: GuessInput) -> ToolOutput:
"""Submit a 5-letter word guess to the Wordle game.
The game will respond with colored feedback:
🟩 = correct letter in correct position
🟨 = correct letter in wrong position
⬛ = letter not in the word
"""
if not self._game:
return ToolOutput(
blocks=[TextBlock(text="Error: game not initialized.")],
reward=0.0,
finished=False,
)
result = self._game.guess(params.word)
reward = self._game.reward
return ToolOutput(
blocks=[TextBlock(text=result)],
reward=reward,
finished=self._game.done,
)
@tool
def get_history(self, params: HistoryInput) -> ToolOutput:
"""View all previous guesses and their feedback.
Shows each guess with its colored feedback and how many guesses remain.
"""
if not self._game:
return ToolOutput(
blocks=[TextBlock(text="No game in progress.")],
reward=None,
finished=False,
)
result = self._game.get_history()
return ToolOutput(
blocks=[TextBlock(text=result)],
reward=None,
finished=False,
)
# ---------------------------------------------------------------------------
# Entry point
# ---------------------------------------------------------------------------
def main():
parser = argparse.ArgumentParser(description="Wordle ORS Server")
parser.add_argument("--port", type=int, default=8080)
parser.add_argument("--host", type=str, default="0.0.0.0")
args = parser.parse_args()
print(f"Starting Wordle ORS server on {args.host}:{args.port}")
print(f" Tasks: {len(TASKS)}")
print(f" Tools: guess, get_history")
Server([WordleORS]).run(host=args.host, port=args.port)
if __name__ == "__main__":
main()