usage.md (3356B)
semif-api usage
semif-api serves SemIf's semantic decision readout over HTTP: send evidence
- a natural-language question + typed options, get back the model's softmax over exactly those options — read from logits, not generated text.
Base URL: http://127.0.0.1:8321. Request/response field details live in
../semif-api/README.md.
probabilitiesare conditional option scores, not calibrated confidence — use them for ranking and coarse thresholds, not as "88% sure."- Always include an
insufficient-style option when the evidence might not decide the question; without one, the model is forced to pick. statemay be a string, JSON object, or array.
Endpoints
GET /healthz— liveness + model metadataPOST /decide— one decisionPOST /decide-batch— many decisions against one identical state (single KV-cache prefill on torch; sequential with prefix caching on llama)POST /plan— rule generation from an action transcript (llama backend only; see games.md for the learning loop it powers)
Example: one decision
curl -s -X POST localhost:8321/decide \
-H 'Content-Type: application/json' \
-d '{
"id": "ticket-1042",
"state": "Customer asks to reset a forgotten password and says the reset email never arrived.",
"question": "Which queue should handle this request?",
"options": [
{"id": "account_access", "description": "Account access and authentication support."},
{"id": "billing", "description": "Billing and payment support."},
{"id": "insufficient", "description": "The evidence does not clearly fit one queue."}
]
}' | jq -r '[.option_ids, .probabilities] | transpose | max_by(.[1]) | .[0]'
# -> account_access
Example: batch against one state
Every decision in a batch shares the exact same state:
curl -s -X POST localhost:8321/decide-batch \
-H 'Content-Type: application/json' \
-d '{
"state": "Postmortem: API latency spiked from 14:02 to 14:40 UTC after a config push removed the rate-limit cache key. Error rate stayed below 0.1%. No customer data was affected.",
"decisions": [
{"id": "customer-impact", "question": "Was there customer-visible impact?",
"options": [{"id": "yes", "description": "Customers were affected."},
{"id": "no", "description": "No customer-visible impact."}]},
{"id": "action-required", "question": "Does the postmortem identify a concrete follow-up action?",
"options": [{"id": "yes", "description": "A follow-up action is identified."},
{"id": "no", "description": "No follow-up action is identified."}]}
]
}' | jq -r '.results[] | ([.option_ids, .probabilities] | transpose | max_by(.[1])) as $w | "\(.id)\t\($w[0])\tp=\($w[1])"'
Error contract
Bad input fails fast with 422 and the upstream validation message:
curl -s -X POST localhost:8321/decide -H 'Content-Type: application/json' \
-d '{"id": "x", "state": "s", "question": "q?", "options": [{"id": "only", "description": "one"}]}'
# {"detail":"options must contain 2-16 entries"}
Other hard rules: duplicate option ids, empty state, missing fields, prompts
over max_tokens — all 422. Remote llama-server failures are 502; scores are
never invented.