자연어에서 검증된 코드까지: Dafny 기반 Formal Verification으로 AI 코드 생성 신뢰성 높이기
From Natural Language to Verified Code: Toward AI Assisted Problem-to-Code Generation with Dafny-Based Formal Verification
TL;DR Highlight
LLM이 생성한 코드를 수학적으로 100% 증명하는 Formal Verification 파이프라인 — Gemma 4-31B가 90.91% 성공률 달성.
Who Should Read
LLM이 생성한 코드의 정확성을 보장해야 하는 백엔드/시스템 개발자, 또는 항공·암호화·보안처럼 고신뢰 소프트웨어를 개발하는 팀에서 AI 코드 생성 자동화를 검토 중인 엔지니어.
Core Mechanics
- 자연어 설명만 던져주면(Contextless Prompting) 대부분 LLM이 Dafny 코드 생성에 완전히 실패함 — GPT-OSS-120B 포함 5개 모델이 0% 성공률.
- Method Signature(함수명, 입출력 타입만 제공)를 힌트로 주면 성공률이 극적으로 반전됨 — GPT-OSS-120B가 0%→63.64%, Qwen 3.5-9B가 72.73%까지 상승.
- Self-Healing(Dafny 검증기 에러 메시지를 LLM에 다시 피드백해서 반복 수정)이 가장 강력한 전략 — Gemma 4-31B는 contextless 상태에서도 90.91% 달성.
- 'Vacuous Verification'(아무 의미없는 trivial 스펙으로 검증기를 속이는 현상) 방지를 위해 uDebug 커뮤니티 테스트 스위트를 이중 검증 레이어로 통합, 형식 검증 + 실제 edge case 테스트를 동시에 수행.
- 모델 크기보다 사전학습 데이터 밀도가 중요함 — 31B짜리 Gemma 4가 120B짜리 GPT-OSS를 contextless 시나리오에서 압도. Dafny 관련 GitHub 저장소는 불과 약 779개로 매우 희소.
- 에러 유형을 3단계로 분류: Syntax Error(구조 문법 오류) → Semantic/Type Error(타입 불일치) → Verification Failure(컴파일은 되지만 SMT 솔버가 증명 불가). Signature 제공 시 Syntax Error가 줄고 Verification Error가 늘어나는 패턴 확인.
Evidence
- Gemma 4-31B: Self-Healing(Contextless 기반) 시 T=0.2와 T=0.6에서 verify@5 90.91% 달성 (11문제 중 10개 성공).
- GPT-OSS-120B: Contextless에서 0% → Signature Prompting에서 63.64% → Signature-Guided Self-Healing에서 81.82%로 단계별 상승.
- Qwen 3.5-9B(9B 소형 모델): Signature Prompting만으로 verify@5 72.73% 달성 — 30B·120B 모델을 능가하는 결과.
- NL2VC-60 데이터셋 구축에 저자들이 약 350 person-hours(300시간 개발 + 50시간 충돌 해결) 투입 — Dafny formal spec 작성의 현실적 난이도를 방증.
How to Apply
- LLM으로 알고리즘 코드를 생성할 때 함수 시그니처(파라미터 타입, 반환 타입)를 프롬프트에 포함시켜라 — contextless 대비 성공률이 수십 배 올라간다.
- 코드 생성 파이프라인에 Dafny 같은 형식 검증기를 루프로 연결하고, 검증 실패 시 에러 메시지를 그대로 LLM에 피드백해서 최대 10회 자동 재시도하는 Self-Healing 에이전트를 구성하라.
- 형식 검증을 통과했더라도 trivial spec으로 속인 케이스가 있을 수 있으므로, uDebug처럼 커뮤니티 기반 edge case 테스트 스위트를 이중 검증 레이어로 추가해라 — 특히 고신뢰 소프트웨어라면 필수.
Code Example
# Self-Healing 프롬프트 구조 예시 (Python pseudo-code)
import subprocess
def self_healing_dafny(problem_desc: str, method_signature: str, llm_client, max_iter=10):
# Step 1: Signature Prompt로 초기 코드 생성
prompt = f"""You are an expert in Dafny. Output ONLY raw Dafny code.
Generate one Dafny source file for the following task.
Task Description: {problem_desc}
Method Signature: {method_signature}"""
code = llm_client.generate(prompt)
for attempt in range(max_iter):
# Step 2: Dafny 검증기 실행
result = subprocess.run(
["dafny", "verify", "temp.dfy"],
input=code, capture_output=True, text=True
)
if "0 errors" in result.stdout:
print(f"✅ Verified at attempt {attempt+1}")
return code # 검증 성공
# Step 3: 에러 메시지를 피드백으로 Self-Healing
error_msg = result.stdout + result.stderr
heal_prompt = f"""The previous Dafny code failed verification with the following errors:
{error_msg}
Previous code:
{code}
Please repair the code to satisfy all specifications. Output ONLY the raw fixed Dafny code."""
code = llm_client.generate(heal_prompt)
print("❌ Failed after max iterations")
return NoneTerminology
관련 논문
adamsreview: Claude Code용 멀티 에이전트 PR 코드 리뷰 파이프라인
Claude Code에서 최대 7개의 병렬 서브 에이전트가 각각 다른 관점으로 PR을 리뷰하고, 자동 수정까지 해주는 오픈소스 플러그인이다. 기존 /review나 CodeRabbit보다 실제 버그를 더 많이 잡는다고 주장하지만 커뮤니티에서는 복잡도와 실효성에 대한 회의론도 나왔다.
Claude를 User Space IP Stack으로 써서 Ping에 응답시키면 얼마나 빠를까?
Claude Code에게 IP 패킷을 직접 파싱하고 ICMP echo reply를 구성하도록 시켜서 실제로 ping에 응답하게 만든 실험으로, 'Markdown이 곧 코드이고 LLM이 프로세서'라는 아이디어를 네트워크 스택 수준까지 밀어붙인 재미있는 사례다.
AI Agent를 위한 Git: re_gent
AI 코딩 에이전트(Claude Code 등)가 수행한 모든 툴 호출을 자동으로 추적하고, 어떤 프롬프트가 어느 코드 줄을 작성했는지 blame까지 가능한 버전 관리 도구다.
Agent-Native CLI를 위한 설계 원칙 10가지
AI 에이전트가 CLI 도구를 더 잘 사용할 수 있도록 설계하는 원칙들을 정리한 글로, 에이전트가 CLI를 도구로 활용하는 빈도가 높아지면서 이 설계 방식이 실용적으로 중요해지고 있다.
Agent-harness-kit: MCP 기반 멀티 에이전트 워크플로우 오케스트레이션 프레임워크
여러 AI 에이전트가 서로 역할을 나눠 협업할 수 있도록 조율하는 scaffolding 도구로, Vite처럼 설정 없이 빠르게 멀티 에이전트 파이프라인을 구성할 수 있다.
Tilde.run – AI Agent를 위한 트랜잭션 기반 버전 관리 파일시스템 샌드박스
AI 에이전트가 실제 프로덕션 데이터를 건드려도 롤백할 수 있는 격리된 샌드박스 환경을 제공하는 도구로, GitHub/S3/Google Drive를 하나의 버전 관리 파일시스템으로 묶어준다.
Related Resources
Original Abstract (Expand)
Large Language Models (LLMs) show promise in automated software engineering, yet their guarantee of correctness is frequently undermined by erroneous or hallucinated code. To enforce model honesty, formal verification requires LLMs to synthesize implementation logic alongside formal specifications that are subsequently proven correct by a mathematical verifier. However, the transition from informal natural language to precise formal specification remains an arduous task. Our work addresses this by providing the NaturalLanguage2VerifiedCode (NL2VC)-60 dataset: a collection of 60 complex algorithmic problems. We evaluate 11 randomly selected problem sets across seven open-weight LLMs using a tiered prompting strategy: contextless prompts, signature prompts providing structural anchors, and self-healing prompts utilizing iterative feedback from the Dafny verifier. To address vacuous verification, where models satisfy verifiers with trivial specifications, we integrate the uDebug platform to ensure functional validation. Our results show that while contextless prompting leads to near-universal failure, structural signatures and iterative self-healing facilitate a dramatic performance turnaround. Specifically, Gemma 4-31B achieved a 90.91\% verification success rate, while GPT-OSS 120B rose from zero to 81.82\% success with signature-guided feedback. These findings indicate that formal verification is now attainable for open-weight LLMs, which serve as effective apprentices for synthesizing complex annotations and facilitating high-assurance software development.