一般社団法人 全国個人事業主支援協会

COLUMN コラム

  • LLMを活用したコード生成の品質評価:ベンチマークと改善手法

LLMによるコード生成の現状と課題

ChatGPTやGitHub Copilot、Claude等のLLMを活用したコード生成ツールが日常的に利用されるようになった。しかし、生成されたコードの品質を体系的に評価し、改善していく取り組みはまだ発展途上です。本記事では、筆者がチームで実践してきたLLMコード生成の品質評価手法とその改善アプローチを紹介します。

主要なベンチマーク手法

HumanEval

OpenAIが公開したHumanEvalは、LLMのコード生成能力を測定する最も有名なベンチマークです。164個のPythonプログラミング問題で構成され、関数のdocstringから正しい実装を生成できるかを評価します。

# HumanEval形式の問題例
def has_close_elements(numbers: list[float], threshold: float) -> bool:
"""Check if in given list of numbers, are any two numbers
closer to each other than given threshold.
>>> has_close_elements([1.0, 2.0, 3.0], 0.5)
False
>>> has_close_elements([1.0, 2.8, 3.0, 4.0], 0.3)
True
"""
# LLMがここを生成する
for i, num1 in enumerate(numbers):
for j, num2 in enumerate(numbers):
if i != j and abs(num1 - num2) < threshold:
return True
return False

ただしHumanEvalは比較的単純な関数レベルの問題が多く、実務でのコード生成品質とは乖離がある点に注意が必要だ。

MBPP(Mostly Basic Python Problems)

Googleが公開したMBPPは、約1000問のPython問題を含む。HumanEvalよりも多様な問題を扱うが、やはり単一関数レベルの評価に留まる。

SWE-bench

より実践的な評価として注目されているのがSWE-benchです。実際のGitHubリポジトリのIssueを解決できるかを測定します。複数ファイルにまたがる修正が必要な場合もあり、実務に近い評価が可能だ。

独自の品質評価フレームワークの構築

汎用ベンチマークだけでは自チームの用途に合った評価はできません。筆者のチームでは独自の評価フレームワークを構築し運用しています。

import json
from dataclasses import dataclass
from typing import Callable

@dataclass
class EvalCase:
"""評価ケースの定義"""
task_id: str
prompt: str
test_cases: list[dict]
expected_patterns: list[str] # コードに含まれるべきパターン
forbidden_patterns: list[str] # 含まれてはいけないパターン
max_complexity: int # 許容される循環的複雑度

@dataclass
class EvalResult:
"""評価結果"""
task_id: str
pass_rate: float # テストケース通過率
pattern_score: float # パターンマッチスコア
complexity_ok: bool # 複雑度が基準内か
security_issues: list[str] # セキュリティ問題
overall_score: float # 総合スコア

この評価フレームワークでは、単にテストが通るかだけでなく、コードの品質面も含めて多角的に評価します。

評価の4つの軸

  • 機能的正確性:テストケースの通過率
  • コード品質:循環的複雑度、命名規則、パターン準拠
  • セキュリティ:SQLインジェクション、XSS等の脆弱性パターン検出
  • 保守性:適切なコメント、型ヒント、モジュール分割

プロンプトエンジニアリングによる品質改善

品質評価の結果を踏まえ、プロンプトを改善することで生成品質を大幅に向上できます。以下は筆者が効果を実感した手法だ。

Few-shot Examplesの活用

# 改善前のプロンプト
prompt_basic = "ユーザー認証のミドルウェアを実装してください"

# 改善後:コーディング規約とサンプルコードを含むプロンプト
prompt_improved = """
以下の規約に従って、ユーザー認証ミドルウェアを実装してください。

【コーディング規約】
- 関数には型ヒントを必ず付与
- エラーハンドリングはカスタム例外クラスを使用
- ログは構造化ログ形式

【参考実装(rate limitミドルウェア)】
async def rate_limit_middleware(
request: Request,
call_next: Callable
) -> Response:
client_ip: str = request.client.host
if await is_rate_limited(client_ip):
logger.warning("rate_limited", extra={"ip": client_ip})
raise RateLimitError(f"Rate limit exceeded for {client_ip}")
return await call_next(request)

この形式に倣い、認証ミドルウェアを実装してください。
"""

規約と具体例を示すことで、生成コードの品質は格段に向上します。筆者のチームの計測では、パターン準拠率が42%から87%に改善した。

反復的な改善ループ

一度の生成で完璧なコードを期待するのではなく、評価結果をフィードバックとして与え、段階的に改善させるアプローチも有効だ。

def iterative_improve(llm_client, prompt: str, eval_cases: list[EvalCase],
max_iterations: int = 3) -> str:
"""反復的にコード品質を改善する"""
generated_code = llm_client.generate(prompt)

for i in range(max_iterations):
result = evaluate(generated_code, eval_cases)
if result.overall_score >= 0.9:
break

feedback = build_feedback(result)
improved_prompt = f"""
以下のコードに問題があります。修正してください。

【現在のコード】
{generated_code}

【問題点】
{feedback}

修正後のコード全体を出力してください。
"""
generated_code = llm_client.generate(improved_prompt)

return generated_code

実務での運用ポイント

LLMコード生成の品質評価を実務に組み込む際に重要なのは、CI/CDパイプラインとの統合です。PRに含まれるLLM生成コードに対して自動的に品質チェックを走らせ、基準を満たさない場合はアラートを出す仕組みが効果的です。

また、チーム固有のコーディングパターンを評価基準に含めることで、プロジェクト全体のコード一貫性を維持できます。LLMは便利なツールだが、その出力を無批判に受け入れるのではなく、体系的な品質ゲートを設けることが、長期的なコードベースの健全性を保つ鍵となります。

まとめ

LLMによるコード生成は急速に進化していますが、品質評価と改善の仕組みを整備することで、そのポテンシャルを最大限に引き出せる。ベンチマークの理解、独自評価フレームワークの構築、プロンプトの最適化を組み合わせ、チームの生産性を持続的に向上させていきたいです。

この記事をシェアする

  • Twitterでシェア
  • Facebookでシェア
  • LINEでシェア