chore(vendor): import pi 1.3.0

Imported as a linear vendor commit so forge rebases do not replay the upstream root tree.

git-subtree-dir: third_party/pi

git-subtree-split: 71023aec1546d6d677a65669c5665c0927ce0dd0
This commit is contained in:
alexion committed 2026-10-15 17:58:48 -04:00
1 parent 719370c8f7
commit 6081e3e325
1743 files changed
+205459 -131704

No files matched your search

+135
View File
@@ -0,0 +1,135 @@
import type {
ClassifierAnswer,
ClassifierApi,
ClassifierContext,
ClassifierModel,
ClassifierOptions,
ClassifierResult,
} from "../types.ts";
import { formatProviderError, normalizeProviderError } from "../utils/error-body.ts";
import { isRecord, parseClassifierUsage, postClassifierRequest, requiredNumber } from "./classifier-shared.ts";
/** TypeSafe System One request body without the transport-specific envelope. */
export interface SystemOneWireRequest {
state: ClassifierContext["state"];
questions: Record<string, unknown>;
}
/** Differences between services that serve System One models. */
export interface SystemOneTransport {
/** Classifier API implemented by this transport. */
api: ClassifierApi;
/** Service name used in error messages. */
label: string;
/** Absolute request URL. */
url(model: ClassifierModel<ClassifierApi>): URL;
/** Wraps the System One request in the service's request envelope. */
payload(model: ClassifierModel<ClassifierApi>, request: SystemOneWireRequest): unknown;
/** Extracts the System One output (`{ answers, usage }`) from the service's response envelope. */
output(body: unknown): Record<string, unknown>;
}
function probabilities(label: string, value: unknown, id: string): Record<string, number> {
if (!isRecord(value)) throw new Error(`${label} returned invalid probabilities for ${id}`);
return Object.fromEntries(
Object.entries(value).map(([key, probability]) => [
key,
requiredNumber(label, probability, `probability for ${id}.${key}`),
]),
);
}
function parseAnswers(label: string, value: unknown, context: ClassifierContext): Record<string, ClassifierAnswer> {
if (!isRecord(value)) throw new Error(`${label} returned an unexpected response`);
const answers: Array<[string, ClassifierAnswer]> = [];
for (const [id, question] of Object.entries(context.questions)) {
const answer = value[id];
if (!isRecord(answer)) throw new Error(`${label} did not return an answer for ${id}`);
if (question.type === "choice") {
if (answer.type !== "choice" || typeof answer.choice !== "string") {
throw new Error(`${label} did not return a choice answer for ${id}`);
}
answers.push([
id,
{
type: "choice",
choice: answer.choice,
probabilities: probabilities(label, answer.probabilities, id),
confidence: requiredNumber(label, answer.confidence, `confidence for ${id}`),
},
]);
} else if (question.type === "score") {
if (answer.type !== "score") throw new Error(`${label} did not return a score answer for ${id}`);
answers.push([
id,
{
type: "score",
score: requiredNumber(label, answer.score, `score for ${id}`),
confidence: requiredNumber(label, answer.confidence, `confidence for ${id}`),
},
]);
} else {
if (answer.type !== "noul") throw new Error(`${label} did not return a bool answer for ${id}`);
answers.push([
id,
{
type: "bool",
probability: requiredNumber(label, answer.noul, `probability for ${id}`),
},
]);
}
}
return Object.fromEntries(answers);
}
/** Maps public `bool` questions to TypeSafe's wire-level `noul` type. */
function wireRequest(context: ClassifierContext): SystemOneWireRequest {
return {
state: context.state,
questions: Object.fromEntries(
Object.entries(context.questions).map(([id, question]) => [
id,
question.type === "bool" ? { ...question, type: "noul" } : question,
]),
),
};
}
/** Runs one System One classification over the given transport. */
export async function classifySystemOne(
transport: SystemOneTransport,
model: ClassifierModel<ClassifierApi>,
context: ClassifierContext,
options: ClassifierOptions | undefined,
): Promise<ClassifierResult> {
const output: ClassifierResult = {
api: model.api,
provider: model.provider,
model: model.id,
answers: {},
stopReason: "stop",
timestamp: Date.now(),
};
try {
if (model.api !== transport.api) throw new Error(`Unsupported classifier API: ${model.api}`);
if (context.images?.length) throw new Error(`${transport.label} does not support image input`);
const body = await postClassifierRequest(
transport.label,
transport.url(model),
model,
transport.payload(model, wireRequest(context)),
options,
);
const result = transport.output(body);
// Set before parsing answers: a request with malformed answers was still billed.
const usage = parseClassifierUsage(result.usage, model);
if (usage) output.usage = usage;
output.answers = parseAnswers(transport.label, result.answers, context);
return output;
} catch (error) {
output.stopReason = options?.signal?.aborted ? "aborted" : "error";
output.errorMessage = formatProviderError(normalizeProviderError(error), `${transport.label} error`);
return output;
}
}