API endpoint /decide
Browse files
app.py
CHANGED
|
@@ -155,6 +155,40 @@ def decide(state, n, *fields):
|
|
| 155 |
return run(state, qs)
|
| 156 |
|
| 157 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 158 |
def load_example(i):
|
| 159 |
_, state, qs = EX[i]
|
| 160 |
ups = [state, len(qs), None]
|
|
@@ -201,6 +235,9 @@ with gr.Blocks(title="Blink v0.3 — one forward pass, one calibrated decision")
|
|
| 201 |
temp = gr.Slider(0.5, 3.0, value=T_CALIBRATED, step=0.05, label="Temperature · 1.3 is calibrated")
|
| 202 |
gr.HTML(NOTE)
|
| 203 |
gr.HTML(HOW)
|
|
|
|
|
|
|
|
|
|
| 204 |
|
| 205 |
go.click(decide, [state, nq, *fields], res).then(lambda r, t: readout(r, t, True), [res, temp], out)
|
| 206 |
temp.change(lambda r, t: readout(r, t, False), [res, temp], out, show_progress="hidden")
|
|
|
|
| 155 |
return run(state, qs)
|
| 156 |
|
| 157 |
|
| 158 |
+
def decide_api(state: str, questions: list):
|
| 159 |
+
"""Score typed decisions about one state with Blink v0.3.
|
| 160 |
+
|
| 161 |
+
Args:
|
| 162 |
+
state: the situation — plain text, or a JSON object/array as a string.
|
| 163 |
+
questions: up to 4 items {"type": "choice"|"noul"|"score", "question": str, "options": [str]}.
|
| 164 |
+
choice: "key" or "key: description" per option; score: levels from lowest to highest;
|
| 165 |
+
noul (yes/no): options optional ("false: ...", "true: ...").
|
| 166 |
+
|
| 167 |
+
Returns:
|
| 168 |
+
{"answers": [{type, question, keys, probabilities, best, logprobs, ms}], "temperature": 1.3, "total_ms": int}
|
| 169 |
+
"""
|
| 170 |
+
if not isinstance(questions, list) or not 1 <= len(questions) <= MAXQ:
|
| 171 |
+
raise gr.Error(f"questions must be a list of 1 to {MAXQ} items")
|
| 172 |
+
qs = []
|
| 173 |
+
for q in questions:
|
| 174 |
+
kind = q.get("type")
|
| 175 |
+
if kind not in ("choice", "noul", "score"):
|
| 176 |
+
raise gr.Error("type must be choice, noul or score")
|
| 177 |
+
try:
|
| 178 |
+
build(kind, list(q.get("options") or []))
|
| 179 |
+
except ValueError as e:
|
| 180 |
+
raise gr.Error(f"{q.get('question', '')[:60]}: {e}")
|
| 181 |
+
qs.append((kind, str(q.get("question", "")).strip(), list(q.get("options") or [])))
|
| 182 |
+
res = run(state, qs)
|
| 183 |
+
for a in res["answers"]:
|
| 184 |
+
p = soft(a["logprobs"], T_CALIBRATED)
|
| 185 |
+
a["probabilities"] = dict(zip(a["keys"], [round(v, 4) for v in p]))
|
| 186 |
+
a["best"] = a["keys"][max(range(len(p)), key=p.__getitem__)]
|
| 187 |
+
a.pop("prompt", None)
|
| 188 |
+
res["temperature"] = T_CALIBRATED
|
| 189 |
+
return res
|
| 190 |
+
|
| 191 |
+
|
| 192 |
def load_example(i):
|
| 193 |
_, state, qs = EX[i]
|
| 194 |
ups = [state, len(qs), None]
|
|
|
|
| 235 |
temp = gr.Slider(0.5, 3.0, value=T_CALIBRATED, step=0.05, label="Temperature · 1.3 is calibrated")
|
| 236 |
gr.HTML(NOTE)
|
| 237 |
gr.HTML(HOW)
|
| 238 |
+
with gr.Row(visible=False): # API-only endpoint: POST /decide (state, questions) -> JSON
|
| 239 |
+
api_state, api_qs, api_out = gr.Textbox(), gr.JSON(), gr.JSON()
|
| 240 |
+
gr.Button().click(decide_api, [api_state, api_qs], api_out, api_name="decide")
|
| 241 |
|
| 242 |
go.click(decide, [state, nq, *fields], res).then(lambda r, t: readout(r, t, True), [res, temp], out)
|
| 243 |
temp.change(lambda r, t: readout(r, t, False), [res, temp], out, show_progress="hidden")
|