Production Deployment
Best practices for deploying compiled prompts to production.
Workflow Overview
- Compile prompts locally or in CI
- Save compiled JSON as artifacts
- Load compiled prompts in production
- Use CompiledProgram for inference
Save Compiled Prompts
scripts/compile.js
import {
defineSchema, ChainOfThought, BootstrapFewShot,
createProvider, exactMatch, z
} from "@mzhub/promptc";
import { writeFileSync, readFileSync } from "fs";
// Load training data
const trainset = JSON.parse(
readFileSync("data/trainset.json", "utf-8")
);
// Define schema and program
const schema = defineSchema({
description: "Extract names from text",
inputs: { text: z.string() },
outputs: { names: z.array(z.string()) }
});
const provider = createProvider("openai");
const program = new ChainOfThought(schema, provider);
// Compile
const compiler = new BootstrapFewShot(exactMatch());
const result = await compiler.compile(program, trainset, {
candidates: 20,
concurrency: 5
});
// Save to prompts directory
writeFileSync(
"prompts/name-extractor.json",
JSON.stringify(result, null, 2)
);
console.log(`Compiled with score: ${result.meta.score}`);Load in Production
src/services/extractor.js
import {
defineSchema, ChainOfThought,
loadCompiledProgram, createProvider, z
} from "@mzhub/promptc";
import { readFileSync } from "fs";
// Same schema as compilation
const schema = defineSchema({
description: "Extract names from text",
inputs: { text: z.string() },
outputs: { names: z.array(z.string()) }
});
// Production provider (can be different model)
const provider = createProvider("openai", {
apiKey: process.env.OPENAI_API_KEY
});
// Base program
const program = new ChainOfThought(schema, provider);
// Load compiled config
const compiledJson = readFileSync("prompts/name-extractor.json", "utf-8");
const extractor = loadCompiledProgram(compiledJson, program);
// Export for use
export async function extractNames(text) {
const result = await extractor.run({ text });
return result.result.names;
}Version Control
Track your compiled prompts in git for reproducibility:
prompts/
├── name-extractor.json # v1.0
├── summarizer.json # v1.2
└── classifier.json # v2.1
# Commit with meaningful messages
git add prompts/name-extractor.json
git commit -m "feat(prompts): improve name extraction score to 0.95"Prompt Versioning
Include version numbers in filenames or use a prompts manifest file to track which version is deployed.
CI/CD Integration
.github/workflows/compile.yml
name: Compile Prompts
on:
push:
paths:
- 'data/trainset.json'
- 'schemas/**'
jobs:
compile:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Compile prompts
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: node scripts/compile.js
- name: Commit compiled prompts
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add prompts/
git commit -m "chore: update compiled prompts" || exit 0
git pushError Handling
import { withRetry } from "@mzhub/promptc";
async function extractNamesWithRetry(text) {
return withRetry(
() => extractor.run({ text }),
{
maxRetries: 3,
initialDelayMs: 1000,
retryOn: (error) => {
// Retry on rate limits and timeouts
return error.message.includes("rate") ||
error.message.includes("timeout");
}
}
);
}Monitoring
async function runWithMonitoring(input) {
const start = Date.now();
try {
const result = await extractor.run(input);
// Log metrics
console.log(JSON.stringify({
event: "llm_call",
latency_ms: Date.now() - start,
input_tokens: result.trace.usage.inputTokens,
output_tokens: result.trace.usage.outputTokens,
success: true
}));
return result;
} catch (error) {
console.log(JSON.stringify({
event: "llm_call",
latency_ms: Date.now() - start,
error: error.message,
success: false
}));
throw error;
}
}Next: Caching Strategies →