Files
dev/third_party/pi/packages/durable/test/examples/16-real-model.ts
alexion 6081e3e325 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
2026-10-15 17:58:48 -04:00

70 lines
2.9 KiB
TypeScript

// A real model: stream an answer from OpenAI.
// Run from packages/durable (needs OPENAI_API_KEY):
// node --conditions=source --experimental-strip-types test/examples/16-real-model.ts
import { BACKGROUND_CONTEXT } from "@earendil-works/chord/context";
import { createModels } from "@earendil-works/pi-ai/models";
import { openaiProvider } from "@earendil-works/pi-ai/providers/openai";
import {
AssistantEntry,
createRegistry,
defineExtension,
Harness,
LiveDoc,
MemoryStorage,
section,
} from "../../src/index.ts";
const context = BACKGROUND_CONTEXT;
// Production code passes a Models collection with real providers; the Harness
// never talks to a provider any other way. openaiProvider() reads
// OPENAI_API_KEY from the environment. While the answer streams, generation
// commits throttled partials to the conversation's pi.live document. Watching
// that document streams the answer; the watch sees only committed values.
if (process.env.OPENAI_API_KEY === undefined) {
console.log("skipped: OPENAI_API_KEY is not set");
} else {
const models = createModels();
models.setProvider(openaiProvider());
const registry = createRegistry();
registry.install(
defineExtension({
name: "concise",
sections: [section("preamble", () => "You are a concise assistant.", { tag: false })],
}),
);
const harness = await Harness.open(new MemoryStorage(), { models, registry }, context);
const root = await harness.root(context, {
agent: { model: { provider: "openai", modelId: "gpt-6-sol" }, thinkingLevel: "high" },
});
const liveWatch = (await harness.watchDoc(LiveDoc, root.id, context))!;
// Print only what each committed partial adds to the text printed so far.
let printed = "";
const printText = (text: string): void => {
if (text.length <= printed.length || !text.startsWith(printed)) return;
process.stdout.write(text.slice(printed.length));
printed = text;
};
liveWatch.start(async (value) => {
const block = value?.generation?.message?.content.find((content) => content.type === "text");
if (block?.type === "text") printText(block.text);
});
harness.resume();
process.stdout.write("answer: ");
const poem = await root.submit({ type: "input", content: "Write a long poem" }, context);
const settledPoem = await poem.wait(context);
await liveWatch.stop();
if (settledPoem.status === "done" && settledPoem.type === "input") {
// The last throttle window may not have been committed as a partial; the answer entry has the rest.
const entry = await root.commit((tx) => tx.entry(AssistantEntry, settledPoem.answer), context);
const message = entry?.model?.[0];
const block =
message?.role === "assistant" ? message.content.find((content) => content.type === "text") : undefined;
if (block?.type === "text") printText(block.text);
process.stdout.write("\n");
} else {
console.log("unanswered:", settledPoem.reason, settledPoem.detail);
}
await harness.close(context);
}