Spaces:
Sleeping
TalkingHeadBench β Hackathon Compliance Change Plan
A file-by-file breakdown of every change needed to fully comply with the OpenEnv hackathon requirements.
1. inference.py (ROOT) β MISSING, MUST CREATE
Status: Does not exist. This is an immediate disqualification condition.
What it needs to do
- Connect to the running TalkingHeadBench environment at a configurable URL.
- Run a full benchmark episode across all 3 task tiers (image audit, clip audit,
weight audit) using test-set cases loaded from
tests/test_set/. - Use the OpenAI Python client (
from openai import OpenAI) for LLM calls β not the current rawurllib/httpxapproach. - Pull LLM config exclusively from the three required environment variables:
API_BASE_URLMODEL_NAMEHF_TOKEN
- Print a structured score report at the end: per-sub-env scores and the weighted final score.
- Complete in under 20 minutes on 2 vCPU / 8 GB RAM.
Required structure (pseudocode)
inference.py
βββ Load API_BASE_URL, MODEL_NAME, HF_TOKEN from os.environ
βββ Instantiate: client = OpenAI(api_key=HF_TOKEN, base_url=API_BASE_URL)
βββ For each task: "image", "clips", "weights"
β βββ Call env.reset(mode=<task>) β via HTTP to the running server
β βββ Read observation, construct LLM prompt
β βββ Call client.chat.completions.create(model=MODEL_NAME, ...)
β βββ Parse structured JSON action
β βββ Call env.step(action)
β βββ Record reward / scores
βββ Print final score report
Why examples/simple_agent.py does NOT qualify
- Uses raw
httpxand manually constructed HF Inference Router calls instead of the OpenAI Python client. - Reads API key from
HF_API_KEY/HUGGINGFACEHUB_API_TOKEN, not from the requiredHF_TOKEN/API_BASE_URL/MODEL_NAMEvariables. - Is not named
inference.pyand is not in the root directory. - Does not iterate over all 3 task tiers with per-sub-env scoring output.
2. server/llm_adapter.py β LLM Client Replace
Status: Uses raw urllib.request for HTTP calls β no OpenAI client.
Lines affected
_call_openai()(L627β667): uses_http_post_json()viaurllib. Must be replaced withclient.chat.completions.create(...)._call_anthropic()(L669β697): same issue._call_huggingface()(L700β776): same issue β currently usesurllibdirectly torouter.huggingface.co.- All calls to
_http_post_json()from provider functions should be replaced.
Changes needed
- Add
from openai import OpenAIat the top. - Replace
_call_openai()to use the OpenAI client:client = OpenAI(api_key=api_key, base_url=base_url or "https://api.openai.com/v1") response = client.chat.completions.create(model=model_id, messages=..., ...) return response.choices[0].message.content - Replace
_call_huggingface()to also use OpenAI client pointed athttps://router.huggingface.co/v1:client = OpenAI(api_key=api_key, base_url="https://router.huggingface.co/v1") - Replace
_call_anthropic()β either use the Anthropic SDK or the OpenAI client via the Anthropic OpenAI-compatible endpoint. - Add
openai>=1.0toserver/requirements.txtand rootrequirements.txt.
Why this matters
The hackathon rules explicitly state: "Participants must use OpenAI Client for
all LLM calls". Using raw urllib.request violates this even if the wire
protocol is identical.
3. server/requirements.txt β ADD openai
Status: Missing openai package.
openenv-core[core]>=0.2.2,<0.3
fastapi>=0.115.0
pydantic>=2.0
uvicorn>=0.24.0
+ openai>=1.0
numpy
torch
scipy
safetensors
opencv-python
mediapipe
4. requirements.txt (ROOT) β ADD openai
Status: Missing openai package.
numpy
torch
pydantic>=2.0
scipy
safetensors
opencv-python
mediapipe>=0.10.33
+ openai>=1.0
pytest
5. pyproject.toml β ADD openai to dependencies
Status: openai is absent from the package's dependency list.
dependencies = [
"openenv-core[core]>=0.2.2,<0.3",
"fastapi>=0.115.0",
"pydantic>=2.0",
"uvicorn>=0.24.0",
"numpy",
"torch",
"scipy",
"safetensors",
"opencv-python",
"mediapipe",
+ "openai>=1.0",
]
6. server/Dockerfile β VALIDATE ENV VAR PASSTHROUGH
Status: Partially compliant. Does not explicitly declare required env vars.
The Dockerfile currently just copies files and runs uvicorn. No issue with the build itself, but the following should be verified / added:
# Add explicit ARG/ENV declarations so evaluators can see the required
# environment variables are expected and forwarded at runtime.
ENV API_BASE_URL=""
ENV MODEL_NAME=""
ENV HF_TOKEN=""
Also confirm the image actually builds without network access to pip:
torchis very heavy. Consider usingtorch --index-url https://download.pytorch.org/whl/cpufor a CPU-only build since the infrastructure constraint is 2 vCPU / 8 GB RAM (no GPU). This will also substantially reduce image size.
- RUN pip install --no-cache-dir -r /app/requirements.txt
+ RUN pip install --no-cache-dir -r /app/requirements.txt \
+ --extra-index-url https://download.pytorch.org/whl/cpu
7. openenv.yaml β OPTIONALLY CLEAN UP CUSTOM VARS
Status: Mostly fine. Contains two non-standard env vars that may confuse validators.
# Current:
env_vars:
- API_BASE_URL
- MODEL_NAME
- HF_TOKEN
- THB_ALLOW_CUSTOM_BASE_URLS # <-- custom, not required by spec
- THB_ALLOWED_BASE_URL_PREFIXES # <-- custom, not required by spec
These two extra env vars are not harmful, but if the validator script only checks for the three required ones, they may be flagged as unexpected. Consider moving them to a comment block or keeping them with a clear inline explanation.
8. examples/simple_agent.py β DOES NOT USE OPENAI CLIENT
Status: Uses raw httpx + custom HF URL. Needs to be converted but is NOT
the inference.py required by the hackathon.
- This file uses
httpx.Clientwith a manually constructed HF router URL. - It reads from
HF_API_KEY/HUGGINGFACEHUB_API_TOKENinstead of the required variable names.
This file should either:
- Be left as-is (fine, it's an example), but
inference.pyat root level must be written from scratch using the OpenAI client and the correct env var names (API_BASE_URL,MODEL_NAME,HF_TOKEN). - Or be upgraded to use the OpenAI client as well to avoid confusion.
9. server/talking_head_environment.py β COMBINED EPISODE REWARD FORMULA
Status: The per-episode reward formula for individual task modes is correct.
However, the COMBINED reward formula hardcoded in _handle_node8_action() does
NOT match the REWARD_LOGIC.md documentation.
The discrepancy
REWARD_LOGIC.md(andmodels.pydocstring, line 12) states the final reward across ALL three sub-envs is:final_reward = 0.25 * subenv1 + 0.35 * subenv2 + 0.40 * subenv3- But
_handle_node8_action()(L590β591) uses:β¦forfinal_score = 0.50 * s2 + 0.50 * s3clips_and_weightsmode, which is a different formula and excludes subenv1.
If the hackathon evaluators run a full-episode combined audit and compare reported scores against your REWARD_LOGIC.md, this inconsistency will be flagged.
Fix needed
Either:
- Update
REWARD_LOGIC.mdto explicitly document the per-mode formulas (it currently only documents the "global" combined formula), OR - Implement a proper 3-way episode type that runs
subenv1 + subenv2 + subenv3with the full0.25/0.35/0.40weighting.
10. server/app.py β MODEL_NAME / API_BASE_URL NOT USED BY SERVER ITSELF
Status: The server reads LLM settings from the AnalyzeIngestionRequest
body (per-request model override), not from the required standard env vars.
The hackathon spec requires API_BASE_URL, MODEL_NAME, and HF_TOKEN to be
defined in the environment configuration and used for all LLM calls. Currently:
API_BASE_URLandMODEL_NAMEare declared inopenenv.yamlas expected vars but the server'sanalyze_ingestionendpoint ignores them β it readsrequest.model_idandrequest.base_urlfrom the request body instead.- The env vars are never fetched with
os.environ.get("MODEL_NAME")etc.
Fix needed
In server/app.py (or server/llm_adapter.py), the analyze_ingested_bundle
function should default to the env vars when the request body fields are absent:
import os
model_id = request.model_id or os.environ.get("MODEL_NAME")
api_key = request.api_key or os.environ.get("HF_TOKEN")
base_url = request.base_url or os.environ.get("API_BASE_URL")
11. README.md β MISSING ACTION/OBSERVATION SPACE TABLE
Status: The README documents architecture, scoring, and deployment. However, it lacks a dedicated, explicit Action Space / Observation Space section.
The hackathon spec requires:
"README with environment description, action/observation spaces, setup instructions"
The current README has architecture diagrams and episode flow tables but no clean, dedicated section labelled "Action Space" / "Observation Space" that clearly lists all fields, types, and ranges in a format a new agent developer could immediately use.
Add a section like:
## Action & Observation Spaces
### Observation Space (reset output per mode)
| Mode | Schema | Key Fields |
|---------|-----------------------------|-----------------------------------------|
| image | ImageDiagnosticsObservation | face_occupancy_ratio, yaw_degrees, ... |
| clips | ClipDispositionObservation | evidence_dossier, marginal_drift, ... |
| weights | PhonemeRiskObservation | layer_entropy, rank_utilization, ... |
### Action Space (step input per mode)
| Mode | Schema | Key Fields |
|---------|-------------------------|----------------------------------------------|
| image | ImageDiagnosticsAction | regime_classification, risk_factors, score |
| clips | ClipDispositionAction | disposition, fix_instructions, override |
| weights | PhonemeRiskAction | phoneme_risk_ranking, mitigation_recs, ... |
All numeric reward outputs are bounded in [0.0, 1.0].
12. examples/simple_agent.py β ESCAPE SEQUENCES BUG
Status: Minor but causes broken prompts at runtime.
Lines 282β288: The build_user_prompt() function uses Python literal \\n
(escaped backslash + n) inside a regular string, which means the actual prompt
string will contain the two characters \n instead of a real newline:
# Current (BROKEN β sends literal \n characters):
f"Environment step index: {step_index}\\n"
# Should be:
f"Environment step index: {step_index}\n"
This affects all agent prompts and will cause the LLM to receive mangled single-line instructions rather than well-structured multi-line prompts.
13. server/llm_adapter.py β _call_local() FALLS THROUGH TO OLLAMA FORMAT
Status: When no base_url is provided for the local provider, it sends
requests to the Ollama native API format (/api/generate) with a prompt key
rather than the OpenAI-compatible chat completions format.
This means if evaluators provide API_BASE_URL pointing to any OpenAI-compatible
local server (vLLM, LM Studio, etc.), the request format will be wrong.
Fix needed
_call_local() should always use the OpenAI-compatible endpoint:
client = OpenAI(api_key="local", base_url=base_url or "http://localhost:11434/v1")
response = client.chat.completions.create(...)
Summary Priority Table
| Priority | File | Change |
|---|---|---|
| π¨ CRITICAL | inference.py |
CREATE from scratch using OpenAI client + correct env vars |
| π¨ CRITICAL | server/llm_adapter.py |
Replace all urllib/httpx calls with OpenAI Python client |
| π¨ CRITICAL | server/requirements.txt |
Add openai>=1.0 |
| π¨ CRITICAL | requirements.txt |
Add openai>=1.0 |
| π¨ CRITICAL | pyproject.toml |
Add openai>=1.0 to dependencies |
| π΄ HIGH | server/app.py |
Default model_id, api_key, base_url from env vars |
| π΄ HIGH | README.md |
Add explicit Action/Observation Space section |
| π‘ MEDIUM | server/Dockerfile |
Declare ENV vars; switch to CPU torch wheel |
| π‘ MEDIUM | server/talking_head_environment.py |
Clarify/fix reward formula discrepancy vs REWARD_LOGIC.md |
| π‘ MEDIUM | examples/simple_agent.py |
Fix \\n escape sequence bug in prompt builder |
| π’ LOW | openenv.yaml |
Annotate/clean up non-standard env vars |
| π’ LOW | examples/simple_agent.py |
Switch to OpenAI client + correct env var names |