UNPKG

agentfootprint

Version:

The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.

84 lines • 3.48 kB
"use strict"; /** * SelfConsistency — sample N answers, pick the majority. * * Paper: "Self-Consistency Improves Chain of Thought Reasoning in * Language Models" — Wang et al., 2022 (https://arxiv.org/abs/2203.11171). * * Pattern: Factory (GoF) → produces a `Runner` that composes `Parallel` * of N `LLMCall` branches with a majority-vote merge function. * Role: patterns/ layer. Pure composition of core primitives + * core-flow compositions — no new abstractions. * Emits: Everything `Parallel` + `LLMCall` emit (stream / composition / * context). No pattern-specific event domain needed; consumers * observe via the standard typed listeners. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.selfConsistency = void 0; const LLMCall_js_1 = require("../core/LLMCall.js"); const Parallel_js_1 = require("../core-flow/Parallel.js"); /** * Build a SelfConsistency Runner. Given a system prompt, the Runner * runs `samples` parallel LLMCalls with the same input, extracts each * response's vote token, then returns the most-frequent token. Ties * are broken by the first response's extract. */ function selfConsistency(opts) { if (opts.samples < 1) { throw new Error('SelfConsistency: samples must be >= 1'); } if (opts.samples < 2) { throw new Error('SelfConsistency: samples must be >= 2 to have anything to vote on (use LLMCall for 1 sample)'); } const extract = opts.extract ?? ((s) => s.trim()); let builder = Parallel_js_1.Parallel.create({ name: opts.name ?? 'SelfConsistency', id: opts.id ?? 'self-consistency', }); for (let i = 0; i < opts.samples; i++) { const branch = LLMCall_js_1.LLMCall.create({ provider: opts.provider, model: opts.model, // Higher default temperature for sampling diversity — the whole // point of SelfConsistency is to get DIFFERENT samples. temperature: opts.temperature ?? 0.7, ...(opts.maxTokens !== undefined && { maxTokens: opts.maxTokens }), }) .system(opts.systemPrompt) .build(); builder = builder.branch(`sample-${i}`, branch); } return builder .mergeWithFn((results) => { const tallies = new Map(); const order = []; for (const id of Object.keys(results).sort()) { // Object.keys() guarantees the index hits, so results[id] is defined. const value = results[id]; if (value === undefined) continue; const vote = extract(value); if (!tallies.has(vote)) order.push(vote); tallies.set(vote, (tallies.get(vote) ?? 0) + 1); } // SelfConsistency runs N branches and merges; if N === 0 there's // nothing to vote on. Throw rather than silently returning empty. if (order.length === 0) { throw new Error('SelfConsistency: no branch results to vote on'); } let best = order[0]; let bestCount = tallies.get(best) ?? 0; for (const vote of order) { const count = tallies.get(vote) ?? 0; if (count > bestCount) { best = vote; bestCount = count; } } return best; }) .build(); } exports.selfConsistency = selfConsistency; //# sourceMappingURL=SelfConsistency.js.map