FlyBrain-Lab / src /prompts /render.py
timfromhcs's picture
FlyBrain V5.0.0 Space sync (v1 API, backup, watchdog, fixed tabs)
3865888 verified
Raw
History Blame Contribute Delete
2.38 kB
"""Render + validate prompt templates (prompts/templates.json).
Rules enforced: every template declares system/user/schema/temperature/
max_tokens; every render fills all placeholders; every parsed output must
contain the schema keys (validated by callers via check_output).
"""
import json
import os
import string
from typing import Any, Dict
TEMPLATE_PATH = os.path.join("prompts", "templates.json")
def load_templates(path: str = TEMPLATE_PATH) -> Dict[str, Any]:
with open(path, encoding="utf-8") as f:
data = json.load(f)
assert "version" in data and isinstance(data["version"], str)
return data
def render(name: str, templates: Dict[str, Any], **kwargs) -> Dict[str, Any]:
if name not in templates or not isinstance(templates[name], dict):
raise KeyError(f"unknown template {name!r}")
t = templates[name]
for field in ("system", "user", "schema", "temperature", "max_tokens"):
if field not in t:
raise ValueError(f"template {name!r} missing {field!r}")
needed = {n for _, n, _, _ in string.Formatter().parse(t["user"]) if n}
missing = needed - set(kwargs)
if missing:
raise ValueError(f"template {name!r} missing params {sorted(missing)}")
return {"system": t["system"], "user": t["user"].format(**kwargs),
"schema": list(t["schema"]), "temperature": float(t["temperature"]),
"max_tokens": int(t["max_tokens"]), "template_version": templates["version"]}
def extract_json(text: str, key: str) -> Dict[str, Any]:
"""Last-balanced-object extraction for thinking models."""
start = text.rfind('{"' + key + '"')
if start < 0:
start = text.find("{")
depth, end = 0, -1
for i in range(max(start, 0), len(text)):
if text[i] == "{":
depth += 1
elif text[i] == "}":
depth -= 1
if depth == 0:
end = i + 1
break
if start < 0 or end <= start:
raise ValueError(f"no JSON with {key!r} in output")
data = json.loads(text[start:end])
if key not in data:
raise ValueError(f"output missing {key!r}")
return data
def check_output(data: Dict[str, Any], schema: list) -> Dict[str, Any]:
missing = [k for k in schema if k not in data]
if missing:
raise ValueError(f"output missing schema keys {missing}")
return data