Optimize your Vercel AI SDK agents with GEPA (Genetic-Pareto Prompt Optimization).
Why GEPA?
Writing effective prompts is hard. Small wording changes can dramatically affect accuracy, but finding the right phrasing requires tedious trial and error.
GEPA automates this. You define a metric (e.g., "did it classify correctly?"), provide training examples, and GEPA evolves your prompts to maximize performance—no manual tuning required.
Before: "Classify the support ticket into a category." → 72% accuracy
After: "You are a support ticket routing system. Analyze the → 94% accuracy
customer's intent and classify into exactly one of
the following categories..."
Quick Start
Here's a complete example that optimizes a ticket classifier:
import { Program, Dataset, GEPA, type MetricFunction } from "gepa-rpc";
import { Prompt } from "gepa-rpc/ai-sdk";
import { openai } from "@ai-sdk/openai";
import { Output } from "ai";
// 1. Define your AI system
class TicketClassifier extends Program<{ ticket: string }, string> {
constructor() {
super({
classifier: new Prompt("Classify the support ticket into a category."),
});
}
override async forward(inputs: { ticket: string }): Promise<string> {
const result = await this.classifier.generateText({
model: openai("gpt-4o-mini"),
prompt: `Ticket: ${inputs.ticket}`,
output: Output.choice({
options: ["Login Issue", "Shipping", "Billing", "General Inquiry"],
}),
});
return result.output as string;
}
}
// 2. Load training data
const trainset = new Dataset(
[
{ ticket: "I can't log into my account.", label: "Login Issue" },
{ ticket: "Where is my order #123?", label: "Shipping" },
// ... more examples
],
["ticket"]
);
// 3. Define how to score predictions
const metric: MetricFunction = (example, prediction) => ({
score: example.label === prediction.output ? 1.0 : 0.0,
feedback:
example.label === prediction.output
? "Correct!"
: `Expected "${example.label}", got "${prediction.output}"`,
});
// 4. Run optimization
const gepa = new GEPA({ numThreads: 4, auto: "medium" });
const optimized = await gepa.compile(new TicketClassifier(), metric, trainset);
// 5. Use your optimized program
optimized.save("./optimized_prompts.json");
console.log("New prompt:", optimized.classifier.systemPrompt);
Installation
GEPA has two components: a TypeScript client for your application and a CLI that runs the optimization engine.
1. Install the TypeScript client
npm install gepa-rpc
# or
bun add gepa-rpc
2. Install the CLI
First install uv, then:
uv tool install gepa-rpc
Core Concepts
| Concept | Description |
|---|---|
| Prompt | Wraps your AI calls (generateText/streamText). Injects the optimized system prompt automatically. |
| Program | Container for all Prompt components in your system. Entry point for optimization. |
| Dataset | Your training data—loaded from JSONL or passed as an array. |
| MetricFunction | Scores each prediction. Returns a score (0-1) and optional feedback for the optimizer. |
| GEPA | The optimizer. Spawns the CLI and evolves prompts using Genetic-Pareto optimization. |
Detailed Usage
Loading Data
import { Dataset } from "gepa-rpc";
// From a JSONL file
const trainset = new Dataset("data/train.jsonl", ["question", "answer"]);
// From an array
const trainset = new Dataset(
[
{ ticket: "I can't log into my account.", label: "Login Issue" },
{ ticket: "Where is my order #123?", label: "Shipping" },
],
["ticket"]
); // Fields passed to forward()
Defining Your Program
Class-Based (Recommended)
Best for new projects. Provides type safety and clean encapsulation.
import { Program } from "gepa-rpc";
import { Prompt } from "gepa-rpc/ai-sdk";
import { openai } from "@ai-sdk/openai";
import { Output } from "ai";
class TicketClassifier extends Program<{ ticket: string }, string> {
constructor() {
super({
classifier: new Prompt("Classify the support ticket into a category."),
});
}
override async forward(inputs: { ticket: string }): Promise<string> {
const result = await this.classifier.generateText({
model: openai("gpt-4o-mini"),
prompt: `Ticket: ${inputs.ticket}`,
output: Output.choice({
options: ["Login Issue", "Shipping", "Billing", "General Inquiry"],
}),
});
return result.output as string;
}
}
const program = new TicketClassifier();
Functional (For Existing Codebases)
Best for retrofitting GEPA into an existing system. Replace your generateText/streamText calls with program.<name>.generateText.
// program.ts
import { Program } from "gepa-rpc";
import { Prompt } from "gepa-rpc/ai-sdk";
const program = new Program({
judge: new Prompt(
"Determine which response is better. Respond with A>B or B>A."
),
});
export default program;
// logic.ts
import program from "./program";
import { openai } from "@ai-sdk/openai";
import { Output } from "ai";
export const choose = async (
question: string,
response_A: string,
response_B: string
) => {
const result = await program.judge.generateText({
model: openai("gpt-4o-mini"),
prompt: `Question: ${question}\nA: ${response_A}\nB: ${response_B}`,
output: Output.choice({ options: ["A>B", "B>A"] }),
});
return result.output;
};
// optimize.ts
import { GEPA, Dataset } from "gepa-rpc";
import program from "./program";
import { choose } from "./logic";
program.setForward(async (inputs) => {
return await choose(inputs.question, inputs.response_A, inputs.response_B);
});
const trainset = new Dataset("data/comparisons.jsonl", [
"question",
"response_A",
"response_B",
]);
const metric = (example, prediction) => ({
score: example.winner === prediction.output ? 1.0 : 0.0,
});
const gepa = new GEPA({ numThreads: 4, auto: "medium" });
await gepa.compile(program, metric, trainset);
Writing Metrics
The metric function scores each prediction. Return a score (0-1) and optional feedback to help the optimizer understand mistakes.
import { type MetricFunction } from "gepa-rpc";
const metric: MetricFunction = (example, prediction) => {
const isCorrect = example.label === prediction.output;
return {
score: isCorrect ? 1.0 : 0.0,
feedback: isCorrect
? "Correctly labeled."
: `Incorrectly labeled. Expected "${example.label}" but got "${prediction.output}"`,
};
};
Running Optimization
import { GEPA } from "gepa-rpc";
const gepa = new GEPA({
numThreads: 4, // Concurrent evaluation workers
auto: "medium", // Optimization depth: "light" | "medium" | "heavy"
reflection_lm: "openai/gpt-4o", // Model used for reflection (optional)
});
const optimizedProgram = await gepa.compile(program, metric, trainset);
Saving & Loading
// Save optimized prompts
optimizedProgram.save("./optimized_prompts.json");
// Load in production
const productionProgram = new TicketClassifier();
productionProgram.load("./optimized_prompts.json");
Appendix
Language Support
Currently, the only supported client is the Vercel AI SDK. The gepa-rpc CLI can work with any language or framework—contributions for other clients are welcome!
Concurrency
Optimization uses a dynamic worker pool. Setting numThreads: 4 keeps 4 LLM calls in flight simultaneously during evaluation, maximizing throughput.
Local Development
To run the CLI from local source instead of the published package:
GEPA_RPC_DEV=true bun run your_optimization_script.ts
Network Protocol
GEPA uses HTTP to communicate between the CLI and the TypeScript client. A WebSocket-based protocol for improved robustness is in development.
Metadata
Release files for gepa-rpc 0.2.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| gepa_rpc-0.2.2.tar.gz | 7.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| gepa_rpc-0.2.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 17.4 kB
Release files / gepa_rpc-0.2.2.tar.gz
| Download URL | gepa_rpc-0.2.2.tar.gz |
|---|---|
| Size | 7.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
752b0a4bf3c7656edcf2e224363c2363db3b905149845bbd6f9d362e7b74f34f
|
|
BLAKE2b-256 checksum How to use checksums |
424e303ee3d3ef6e24ce26ed71786b762d59ca3acd81e24b6c77298fccfc8231
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jan 22, 2026.
Transparency logRelease files / gepa_rpc-0.2.2-py3-none-any.whl
| Download URL | gepa_rpc-0.2.2-py3-none-any.whl |
|---|---|
| Size | 9.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
330919012582679a83dd4afa660c9f4e660fca3ee011801f6e09ab39d5f03dad
|
|
BLAKE2b-256 checksum How to use checksums |
b40a7f03b0061a8fb766476dc4f7b1f7d3f4aa02ad0b005961a495fb8765a618
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jan 22, 2026.
Transparency log