Appendix B · section 7 of 32
ask/scope.ts
From Talking to a Model.
import Anthropic from "@anthropic-ai/sdk";
import { ANSWER_MODEL, requireApiKey, textOf } from "./setup.js";
requireApiKey();
const client = new Anthropic();
// The only words the model may answer with. An enum in the schema is a
// promise the API keeps: the reply is one of these or the request fails.
const SCOPES = ["road-law", "other"] as const;
type Scope = (typeof SCOPES)[number];
const SCHEMA = {
type: "object",
properties: {
scope: { type: "string", enum: [...SCOPES] },
why: { type: "string" },
},
required: ["scope", "why"],
additionalProperties: false,
} as const;
const RULES = [
"You sort a learner driver's question into one of two scopes.",
'A rule of the road, a sign, a speed limit, a fine, an age, a document, or a',
'requirement of a particular state is "road-law".',
'Anything else - the app, the weather, the capital of France - is "other".',
"Say why in one short sentence.",
].join(" ");
async function scopeOf(question: string): Promise<{ scope: Scope; why: string } | null> {
const response = await client.messages.create({
model: ANSWER_MODEL,
max_tokens: 1024,
system: RULES,
output_config: {
effort: "low",
format: { type: "json_schema", schema: SCHEMA },
},
messages: [{ role: "user", content: question }],
});
// A refusal is a 200 with no answer in it. Check it before reading.
if (response.stop_reason === "refusal") return null;
const parsed = JSON.parse(textOf(response)) as { scope?: unknown; why?: unknown };
if (
typeof parsed.scope !== "string" ||
!(SCOPES as readonly string[]).includes(parsed.scope) ||
typeof parsed.why !== "string"
) {
return null;
}
return { scope: parsed.scope as Scope, why: parsed.why };
}
async function main(): Promise<void> {
const question = process.argv.slice(2).join(" ");
if (question.length === 0) {
console.error('usage: tsx ask/scope.ts "<question>"');
process.exit(1);
}
const sorted = await scopeOf(question);
console.log(sorted === null ? "no usable reply" : `${sorted.scope}: ${sorted.why}`);
}
main().catch((error: unknown) => {
console.error(error instanceof Error ? error.message : String(error));
process.exit(1);
});