cost-estimate.ts
1,772 bytes
| 1 | /** |
|---|---|
| 2 | * Rough upfront cost estimate for a debate, so the builder can warn before a |
| 3 | * user spends real credit. Uses typical per-stage token counts; the actual cost |
| 4 | * is usually lower because convergence can stop the debate early. |
| 5 | */ |
| 6 | export interface TokenPrice { |
| 7 | /** USD per prompt token. */ |
| 8 | prompt: number; |
| 9 | /** USD per completion token. */ |
| 10 | completion: number; |
| 11 | } |
| 12 | |
| 13 | type Stage = 'answer' | 'critique' | 'revision' | 'convergence' | 'synthesis'; |
| 14 | |
| 15 | const AVG: Record<Stage, { prompt: number; completion: number }> = { |
| 16 | answer: { prompt: 250, completion: 320 }, |
| 17 | critique: { prompt: 850, completion: 260 }, |
| 18 | revision: { prompt: 950, completion: 320 }, |
| 19 | convergence: { prompt: 1100, completion: 160 }, |
| 20 | synthesis: { prompt: 1300, completion: 420 }, |
| 21 | }; |
| 22 | |
| 23 | const FALLBACK: TokenPrice = { prompt: 1e-6, completion: 3e-6 }; |
| 24 | |
| 25 | export interface EstimateInput { |
| 26 | councilModels: string[]; |
| 27 | chairmanModel: string; |
| 28 | convergenceModel: string; |
| 29 | /** Maximum number of critique->revision rounds. */ |
| 30 | rounds: number; |
| 31 | price: (modelId: string) => TokenPrice | undefined; |
| 32 | } |
| 33 | |
| 34 | /** Estimated *maximum* USD cost (all rounds run, no early stop). */ |
| 35 | export function estimateDebateCostUsd(input: EstimateInput): number { |
| 36 | const cost = (modelId: string, stage: Stage) => { |
| 37 | const p = input.price(modelId) ?? FALLBACK; |
| 38 | return AVG[stage].prompt * p.prompt + AVG[stage].completion * p.completion; |
| 39 | }; |
| 40 | |
| 41 | let total = 0; |
| 42 | for (const m of input.councilModels) total += cost(m, 'answer'); |
| 43 | for (let r = 0; r < input.rounds; r++) { |
| 44 | for (const m of input.councilModels) { |
| 45 | total += cost(m, 'critique'); |
| 46 | total += cost(m, 'revision'); |
| 47 | } |
| 48 | total += cost(input.convergenceModel, 'convergence'); |
| 49 | } |
| 50 | total += cost(input.chairmanModel, 'synthesis'); |
| 51 | return total; |
| 52 | } |
| 53 | |