101 lines
2.9 KiB
Go
101 lines
2.9 KiB
Go
package provider
|
|
|
|
import (
|
|
"encoding/json"
|
|
"math"
|
|
"strings"
|
|
)
|
|
|
|
// DecideAsk is a System One request (body) as via takes it: Vercel's
|
|
// TypeSafe API takes it as it is; its evaluation models name the model in
|
|
// a header and ask a noul as a boolean; Workers AI takes the state and
|
|
// questions as the input of a run of the model, and a Clef there takes
|
|
// the request as it is, its model named as Clef names itself.
|
|
func DecideAsk(via, model string, body []byte) []byte {
|
|
var q map[string]any
|
|
if via == ViaSystemOne || via == ViaVercel || json.Unmarshal(body, &q) != nil {
|
|
return body
|
|
}
|
|
delete(q, "model")
|
|
switch via {
|
|
case ViaVercelEval:
|
|
qs, _ := q["questions"].(map[string]any)
|
|
for _, v := range qs {
|
|
if x, ok := v.(map[string]any); ok && x["type"] == "noul" {
|
|
x["type"] = "boolean"
|
|
}
|
|
}
|
|
b, _ := json.Marshal(q)
|
|
return b
|
|
case ViaCloudflare:
|
|
if CloudflareClef(model) {
|
|
q["model"] = strings.TrimPrefix(model, "@cf/cloudflare/")
|
|
b, _ := json.Marshal(q)
|
|
return b
|
|
}
|
|
b, _ := json.Marshal(map[string]any{"model": model, "input": q})
|
|
return b
|
|
}
|
|
return body
|
|
}
|
|
|
|
// DecideAnswer is a gateway's answer as System One gives it: out of
|
|
// Cloudflare's envelope, or, from Vercel's evaluation models (its TypeSafe
|
|
// API answers as System One does), a boolean's probability as a
|
|
// noul, a confidence from the probabilities where there is none, and its
|
|
// usage named as System One names it.
|
|
func DecideAnswer(via string, b []byte) []byte {
|
|
switch via {
|
|
case ViaCloudflare:
|
|
var env struct {
|
|
Result json.RawMessage `json:"result"`
|
|
}
|
|
if json.Unmarshal(b, &env) == nil && len(env.Result) > 0 && env.Result[0] == '{' {
|
|
return env.Result
|
|
}
|
|
case ViaVercelEval:
|
|
var v struct {
|
|
Model string `json:"model"`
|
|
Answers map[string]map[string]any `json:"answers"`
|
|
Usage struct {
|
|
Input int `json:"inputTokens"`
|
|
Output int `json:"outputTokens"`
|
|
} `json:"usage"`
|
|
}
|
|
if json.Unmarshal(b, &v) != nil || v.Answers == nil {
|
|
return b
|
|
}
|
|
for _, a := range v.Answers {
|
|
if a["type"] == "boolean" {
|
|
a["type"], a["noul"] = "noul", a["probability"]
|
|
continue
|
|
}
|
|
if _, ok := a["confidence"]; !ok {
|
|
if ps, ok := a["probabilities"].(map[string]any); ok {
|
|
a["confidence"] = Confidence(ps)
|
|
}
|
|
}
|
|
}
|
|
out, _ := json.Marshal(map[string]any{"model": v.Model, "answers": v.Answers,
|
|
"usage": map[string]int{"input_tokens": v.Usage.Input, "output_tokens": v.Usage.Output}})
|
|
return out
|
|
}
|
|
return b
|
|
}
|
|
|
|
// Confidence is how sure a set of probabilities is of its likeliest, as
|
|
// System One gives it: 0 with every option as likely, 1 with one certain
|
|
// (its 0.87 of three options is 0.8).
|
|
func Confidence(ps map[string]any) float64 {
|
|
top, n := 0.0, 0
|
|
for _, v := range ps {
|
|
if f, ok := v.(float64); ok {
|
|
top, n = math.Max(top, f), n+1
|
|
}
|
|
}
|
|
if n < 2 {
|
|
return 1
|
|
}
|
|
return max(0, (top-1/float64(n))/(1-1/float64(n)))
|
|
}
|