UNPKG

gepa-spo

Version:

Genetic-Pareto prompt optimizer to evolve system prompts from a few rollouts with modular support and intelligent crossover

53 lines (52 loc) 2.5 kB
import { proposeNewSystem, summarizeTraces } from './reflection.js'; /** Generate seeded candidates with top-K strategies and keep the top few by average judge score */ export async function seedPopulation({ seed, screen, strategies, K, execute, muf, llm, budgetLeft, mufCosts = true }) { const out = [{ system: seed.system ?? '', _via: 'seed', _uplift: 0 }]; let usedCalls = 0; for (const s of strategies.slice(0, K)) { if (budgetLeft !== undefined && budgetLeft <= 0) break; // Execute the seed system on screen items to get actual examples with traces const examples = []; for (const item of screen) { if (budgetLeft !== undefined && budgetLeft <= 0) break; const { output, traces } = await execute({ candidate: seed, item }); const f = await muf({ item, output, traces: traces ?? null }); const execTrace = summarizeTraces(traces, 1000); examples.push({ user: item.user, output, feedback: f.feedbackText, ...(execTrace && { execTrace }) }); // Count execute always, plus muf when configured const delta = 1 + (mufCosts ? 1 : 0); usedCalls += delta; if (budgetLeft !== undefined) budgetLeft -= delta; } const sys2 = await proposeNewSystem(llm, seed.system ?? '', examples, s.hint); usedCalls += 1; if (budgetLeft !== undefined) budgetLeft -= 1; // propose call const scores = []; for (const item of screen) { if (budgetLeft !== undefined && budgetLeft <= 0) break; const { output, traces } = await execute({ candidate: { system: sys2 }, item }); // Judge may or may not count to usedCalls const f = await muf({ item, output, traces: traces ?? null }); scores.push(f.score); // Count execute always, plus muf when configured const delta = 1 + (mufCosts ? 1 : 0); usedCalls += delta; if (budgetLeft !== undefined) budgetLeft -= delta; } out.push({ system: sys2, _via: s.id, _uplift: avg(scores) }); } out.sort((a, b) => b._uplift - a._uplift); return { candidates: out.slice(0, Math.min(5, out.length)), usedCalls }; } const avg = (xs) => (xs.length ? xs.reduce((a, b) => a + b, 0) / xs.length : 0);