Initial commit
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
"""ReflACT utilities — JSON extraction, scoring, hashing."""
|
||||
|
||||
from skillopt.utils.json_utils import extract_json, extract_json_array # noqa: F401
|
||||
from skillopt.utils.scoring import compute_score, skill_hash # noqa: F401
|
||||
@@ -0,0 +1,42 @@
|
||||
"""JSON extraction helpers for LLM responses."""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
|
||||
|
||||
def extract_json(text: str) -> dict | None:
|
||||
"""Extract a JSON object from LLM response text.
|
||||
|
||||
Tries ```json fences first, then bare {...} patterns.
|
||||
"""
|
||||
m = re.search(r"```json\s*(.*?)```", text, re.DOTALL)
|
||||
if m:
|
||||
try:
|
||||
return json.loads(m.group(1))
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
m = re.search(r"\{.*\}", text, re.DOTALL)
|
||||
if m:
|
||||
try:
|
||||
return json.loads(m.group(0))
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
return None
|
||||
|
||||
|
||||
def extract_json_array(text: str) -> list | None:
|
||||
"""Extract a JSON array from LLM response text."""
|
||||
m = re.search(r"```json\s*(.*?)```", text, re.DOTALL)
|
||||
if m:
|
||||
try:
|
||||
return json.loads(m.group(1))
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
m = re.search(r"\[.*\]", text, re.DOTALL)
|
||||
if m:
|
||||
try:
|
||||
return json.loads(m.group(0))
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
return None
|
||||
@@ -0,0 +1,29 @@
|
||||
"""Scoring and hashing utilities."""
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
|
||||
|
||||
def compute_score(results: list) -> tuple[float, float]:
|
||||
"""Compute hard and soft accuracy from a list of episode results.
|
||||
|
||||
Accepts both plain dicts and :class:`~skillopt.types.RolloutResult`
|
||||
instances.
|
||||
"""
|
||||
if not results:
|
||||
return 0.0, 0.0
|
||||
|
||||
def _hard(r: object) -> int:
|
||||
return int(r.hard if hasattr(r, "hard") else r.get("hard", 0)) # type: ignore[union-attr]
|
||||
|
||||
def _soft(r: object) -> float:
|
||||
return float(r.soft if hasattr(r, "soft") else r.get("soft", 0.0)) # type: ignore[union-attr]
|
||||
|
||||
hard = sum(_hard(r) for r in results) / len(results)
|
||||
soft = sum(_soft(r) for r in results) / len(results)
|
||||
return hard, soft
|
||||
|
||||
|
||||
def skill_hash(content: str) -> str:
|
||||
"""Return a short deterministic hash of skill content (for caching)."""
|
||||
return hashlib.sha256(content.encode()).hexdigest()[:16]
|
||||
Reference in New Issue
Block a user