Spaces:
Runtime error
Runtime error
| import "dotenv/config"; | |
| import { readFileSync, writeFileSync, existsSync } from "node:fs"; | |
| import { resolve } from "node:path"; | |
| import { coderAgent } from "../src/agents/coder/agent.ts"; | |
| // βββ Config ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| const FORMAL_EVAL_PATH = | |
| process.env.FORMAL_EVAL_PATH ?? | |
| resolve("..", "formal-eval", "data", "FormalEval.jsonl"); | |
| const OUTPUT_PATH = process.env.BENCHMARK_OUTPUT ?? resolve("benchmarks", "samples.jsonl"); | |
| const SAMPLES_PER_TASK = Number(process.env.SAMPLES_PER_TASK ?? "1"); | |
| const SKIP_REVIEW = process.env.SKIP_REVIEW !== "false"; // skip review by default for speed | |
| // βββ Types βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| interface FormalEvalProblem { | |
| task_id: string; | |
| complexity: string; | |
| description: string; | |
| prompt: string; | |
| canonical_solution: string; | |
| test: string; | |
| entry_point: string; | |
| } | |
| interface SampleOutput { | |
| task_id: string; | |
| completion: string; | |
| } | |
| // βββ Helpers βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| function readProblems(path: string): FormalEvalProblem[] { | |
| const content = readFileSync(path, "utf-8"); | |
| return content | |
| .split("\n") | |
| .filter((line) => line.trim()) | |
| .map((line) => JSON.parse(line)); | |
| } | |
| /** | |
| * Extrai a "completion" (body do contrato) a partir do contrato completo gerado. | |
| * O FormalEval espera: prompt + completion = contrato completo. | |
| * EntΓ£o precisamos remover tudo que jΓ‘ estΓ‘ no prompt. | |
| */ | |
| function extractCompletion(generatedContract: string, prompt: string): string { | |
| // EstratΓ©gia 1: Se o contrato gerado contΓ©m o prompt exato, pegar o que vem depois | |
| const promptTrimmed = prompt.trimEnd(); | |
| const idx = generatedContract.indexOf(promptTrimmed); | |
| if (idx !== -1) { | |
| return generatedContract.slice(idx + promptTrimmed.length); | |
| } | |
| // EstratΓ©gia 2: Encontrar a declaraΓ§Γ£o "contract <Name> {" e pegar o body | |
| // O prompt sempre termina com "contract <Name> {\n" | |
| const contractDeclMatch = prompt.match(/contract\s+(\w+)\s*\{?\s*$/m); | |
| if (contractDeclMatch) { | |
| const contractName = contractDeclMatch[1]; | |
| const pattern = new RegExp(`contract\\s+${contractName}\\s*\\{`); | |
| const match = generatedContract.match(pattern); | |
| if (match?.index !== undefined) { | |
| const afterDecl = generatedContract.slice(match.index + match[0].length); | |
| return afterDecl; | |
| } | |
| } | |
| // EstratΓ©gia 3: Fallback β Tenta remover pragma + imports + declaraΓ§Γ£o atΓ© "{" | |
| const lines = generatedContract.split("\n"); | |
| let bodyStart = 0; | |
| for (let i = 0; i < lines.length; i++) { | |
| if (lines[i].match(/contract\s+\w+.*\{/)) { | |
| bodyStart = i + 1; | |
| break; | |
| } | |
| } | |
| return lines.slice(bodyStart).join("\n"); | |
| } | |
| /** | |
| * Adapta o prompt do FormalEval para ser interpretado pelo Coder Agent. | |
| * Inclui instruΓ§Γ£o explΓcita para gerar apenas o body. | |
| */ | |
| function buildRequirements(problem: FormalEvalProblem): string { | |
| return `Complete the following Solidity contract. Generate ONLY the contract body (state variables, functions, and closing brace "}"). | |
| Do NOT include the SPDX license, pragma, or contract declaration β they are already provided. | |
| The code must compile with solc ^0.8.19. | |
| Here is the contract declaration with its specification: | |
| ${problem.prompt} | |
| IMPORTANT: Return ONLY the code that goes INSIDE the contract (after the opening brace). Include the closing "}" at the end.`; | |
| } | |
| // βββ Main ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| async function main() { | |
| if (!existsSync(FORMAL_EVAL_PATH)) { | |
| console.error(`FormalEval dataset not found at: ${FORMAL_EVAL_PATH}`); | |
| console.error("Set FORMAL_EVAL_PATH env variable to the correct path."); | |
| process.exit(1); | |
| } | |
| const problems = readProblems(FORMAL_EVAL_PATH); | |
| console.log(`Loaded ${problems.length} problems from FormalEval`); | |
| console.log(`Generating ${SAMPLES_PER_TASK} sample(s) per task...`); | |
| console.log(`Output: ${OUTPUT_PATH}\n`); | |
| const samples: SampleOutput[] = []; | |
| let completed = 0; | |
| for (const problem of problems) { | |
| for (let s = 0; s < SAMPLES_PER_TASK; s++) { | |
| const label = `[${problem.task_id}] (${problem.complexity}) sample ${s + 1}/${SAMPLES_PER_TASK}`; | |
| console.log(`β ${label}: ${problem.description}`); | |
| try { | |
| const requirements = buildRequirements(problem); | |
| const result = await coderAgent.invoke({ requirements: [requirements] }); | |
| const generated = result.contract; | |
| const completion = extractCompletion(generated, problem.prompt); | |
| samples.push({ task_id: problem.task_id, completion }); | |
| const hasErrors = result.compilationErrors.length > 0; | |
| console.log(` β Done${hasErrors ? ` (with ${result.compilationErrors.length} compile errors)` : ""}`); | |
| } catch (error) { | |
| const msg = error instanceof Error ? error.message : String(error); | |
| console.error(` β Failed: ${msg}`); | |
| // Still emit an empty completion so FormalEval doesn't complain about missing tasks | |
| samples.push({ task_id: problem.task_id, completion: "// generation failed\n}\n" }); | |
| } | |
| completed++; | |
| } | |
| } | |
| // Write JSONL output | |
| const jsonl = samples.map((s) => JSON.stringify(s)).join("\n") + "\n"; | |
| writeFileSync(OUTPUT_PATH, jsonl, "utf-8"); | |
| console.log(`\n${"β".repeat(60)}`); | |
| console.log(`Benchmark complete: ${completed} completions generated`); | |
| console.log(`Output saved to: ${OUTPUT_PATH}`); | |
| console.log(`\nTo evaluate, run:`); | |
| console.log(` cd ../formal-eval && evaluate_formal_correctness ${resolve(OUTPUT_PATH)}`); | |
| } | |
| main().catch((err) => { | |
| console.error("Fatal error:", err); | |
| process.exit(1); | |
| }); | |