mirror of
https://github.com/seemueller-io/sumpin.git
synced 2025-09-08 22:56:46 +00:00
add code
This commit is contained in:
125
generate-template.ts
Executable file
125
generate-template.ts
Executable file
@@ -0,0 +1,125 @@
|
||||
#!/usr/bin/env bun
|
||||
|
||||
/*
|
||||
* hierarchyGenerator.ts
|
||||
* ------------------------------------------------------------
|
||||
* A tiny OpenAI‑powered helper that turns natural‑language prompts
|
||||
* into domain hierarchies matching `HierarchyModel` (mobx‑state‑tree).
|
||||
* ------------------------------------------------------------
|
||||
* Usage example:
|
||||
* import { generateHierarchy } from "./hierarchyGenerator";
|
||||
* const hierarchy = await generateHierarchy("Create a v2 Healthcare hierarchy for mental health services");
|
||||
*
|
||||
* The function returns a live MST instance of `HierarchyModel` so it
|
||||
* can be plugged straight into your state tree or persisted as JSON.
|
||||
*/
|
||||
|
||||
import OpenAI from "openai";
|
||||
import { HierarchyModel } from "./lib/hierarchy-model.ts";
|
||||
import type { Instance } from "mobx-state-tree";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Type Definitions
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Shape produced by the LLM and accepted by `HierarchyModel`.
|
||||
*/
|
||||
export interface Hierarchy {
|
||||
version: "v1" | "v2";
|
||||
domain: string; // e.g. "Finance", "Technology"
|
||||
structure: string[]; // ordered list of hierarchy labels
|
||||
description: string; // plain‑text description
|
||||
commonSkills: string[];
|
||||
commonTools: string[];
|
||||
examples: string[];
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// OpenAI client configuration
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const openai = new OpenAI({
|
||||
// Rely on OPENAI_API_KEY env var or pass explicit key here
|
||||
apiKey: process.env.OPENAI_API_KEY,
|
||||
});
|
||||
|
||||
// System prompt used for every request. Keeps the model focused on
|
||||
// emitting strict JSON with NO extra text.
|
||||
const SYS_PROMPT = `
|
||||
You are an API that converts natural‑language descriptions into JSON
|
||||
objects that conform **exactly** to the following TypeScript interface.
|
||||
Return the JSON only – no markdown, comments, or additional keys.
|
||||
If a field is missing in the user's request, make a sensible inference.
|
||||
|
||||
interface Hierarchy {
|
||||
version: "v1" | "v2"; // one of the two schema versions
|
||||
domain: string; // high‑level sector name
|
||||
structure: string[]; // ordered labels, 4 elements for v1, 6 for v2
|
||||
description: string; // concise explanation of the hierarchy
|
||||
commonSkills: string[]; // 3‑7 bullet items
|
||||
commonTools: string[]; // 3‑7 bullet items
|
||||
examples: string[]; // 3‑7 representative examples
|
||||
}
|
||||
`;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Public API
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Convert a natural‑language prompt into a fully‑typed `HierarchyModel`.
|
||||
*
|
||||
* @param nlPrompt – Human description, e.g. "Define a v1 hierarchy for legal services"
|
||||
* @param model – (optional) Which OpenAI model to use. Defaults to GPT‑4o‑mini.
|
||||
*/
|
||||
export async function generateHierarchy(
|
||||
nlPrompt: string,
|
||||
model: string = "gpt-4o-mini"
|
||||
): Promise<Instance<typeof HierarchyModel>> {
|
||||
const chat = await openai.chat.completions.create({
|
||||
model,
|
||||
response_format: { type: "json_object" }, // guarantees pure JSON
|
||||
messages: [
|
||||
{ role: "system", content: SYS_PROMPT },
|
||||
{ role: "user", content: nlPrompt },
|
||||
],
|
||||
});
|
||||
|
||||
// Defensive parsing — in rare cases the assistant may wrap JSON in text.
|
||||
const raw = chat.choices[0]?.message?.content ?? "{}";
|
||||
let data: Hierarchy;
|
||||
try {
|
||||
data = JSON.parse(raw) as Hierarchy;
|
||||
} catch {
|
||||
// Attempt to salvage JSON embedded in text
|
||||
const match = raw.match(/\{[\s\S]*\}/);
|
||||
if (!match) throw new Error("Failed to parse JSON from LLM response");
|
||||
data = JSON.parse(match[0]) as Hierarchy;
|
||||
}
|
||||
|
||||
// Validate minimal shape before creating MST instance.
|
||||
if (!data.version || !data.domain || !data.structure) {
|
||||
throw new Error("Incomplete hierarchy returned by LLM");
|
||||
}
|
||||
|
||||
return HierarchyModel.create(data);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Helper: quick command‑line demo when run with ts‑node
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
if (require.main === module) {
|
||||
(async () => {
|
||||
const prompt = process.argv.slice(2).join(" ") ||
|
||||
"Create a v2 Technology hierarchy focused on AI safety";
|
||||
try {
|
||||
const hierarchy = await generateHierarchy(prompt);
|
||||
console.log(JSON.stringify(hierarchy.toJSON(), null, 2));
|
||||
} catch (err) {
|
||||
console.error("Error generating hierarchy:", err);
|
||||
process.exitCode = 1;
|
||||
}
|
||||
})();
|
||||
}
|
Reference in New Issue
Block a user