読者が抱える課題
LLM(大規模言語モデル)をコード生成や技術調査に活用する際、一見すると正しく動作しそうな「存在しないAPI」「架空のライブラリ」「廃止されたメソッド」がもっともらしく出力される現象(ハルシネーション)に遭遇することがあります。これを鵜呑みにして実装を進めると、ビルドエラーの解消に時間を取られたり、セキュリティ脆弱性のある未検証のパッケージを誤って導入したりするリスクが生じます。
この記事で分かること
- LLMが架空のAPIやライブラリを生成してしまう技術的背景
- ハルシネーションを抑制するためのプロンプト設計パターン
- 生成されたコードやライブラリの存在を自動検証する仕組みの実装例
- 実務で使える「AI生成コード検証チェックリスト」
対象読者・前提条件
- 開発業務でGitHub Copilot、ChatGPT、Claudeなどのコード生成AIを利用しているエンジニア
- AIが提案したライブラリやAPIの妥当性を効率的に検証したい開発リーダー
- 前提知識:基本的なPythonの実行環境、APIおよびパッケージ管理(pipなど)の基礎知識
1. なぜAIは存在しないAPIやライブラリを生成するのか
LLMが架空の情報を出力する主な原因は、その仕組みにあります。
-
確率的な単語予測(Next-Token Prediction)
LLMは「次に続く確率が最も高い単語」を順番に出力しているだけであり、出力内容の真偽をリアルタイムに検証しているわけではありません。それらしい命名規則(例:boto3.client('s3').download_file_to_streamのような、ありそうで存在しないメソッド)を確率的に合成してしまうことがあります。 -
学習データのカットオフと情報の風化
LLMの学習データは特定の時点でカットオフされています。その後に廃止されたAPIや、新しく追加されたライブラリの仕様を正確に把握できず、古い情報と新しい情報を混同して出力することがあります。 -
「知らない」と言えないバイアス
指示(プロンプト)に対して何らかの回答を返そうとする性質があるため、適切な制約がない場合、存在しないライブラリをその場で「創作」して回答を埋めてしまいます。
2. プロンプトによるハルシネーション抑制対策
プロンプトに明確な制約条件と役割を与えることで、架空のAPI生成を一定数抑制できます。以下に「悪い例」と「良い例」を示します。
悪いプロンプトの例
PythonでPDFからテキストを抽出して、特定のキーワードでフィルタリングするコードを書いてください。できるだけ便利な外部ライブラリを使ってください。
問題点: 自由度が高すぎるため、AIが「便利だが存在しない架空のPDF操作ライブラリ」を創作して提案する可能性が高まります。
良いプロンプトの例(制約事項の明確化)
役割
あなたは信頼性を最優先するPythonシニアエンジニアです。
依頼内容
PythonでPDFからテキストを抽出するコードを作成してください。
制約条件
- 使用する外部ライブラリは、PyPIで広く使われている実績のあるもの(例:
pypdfまたはpdfplumber)に限定してください。- 存在するか不確かなサードパーティ製ライブラリや、独自のラッパーライブラリは絶対に提案しないでください。
- 使用するメソッドやプロパティは、最新の公式ドキュメントで推奨されているものに限定し、非推奨(Deprecated)のものは避けてください。
- もし特定の処理を実現する標準的なAPIやライブラリが不明な場合は、架空のコードを生成せず、「該当する標準的なライブラリを特定できませんでした」と回答してください。
3. 実装例:生成されたライブラリの存在検証自動化
AIが提案してきた外部パッケージが実際にPyPI(Python Package Index)に存在するかどうかを、Pythonスクリプトで自動検証する仕組みを構築します。これにより、コードを実行する前にパッケージの存在有無を確認できます。
以下は、指定されたパッケージ名がPyPIに登録されているかを検証する簡易スクリプトです。
import requests
import sys
def verify_pypi_package(package_name: str) -> bool:
"""
指定されたパッケージがPyPIに存在するか確認する(独自検証用関数)
"""
# PyPIのJSON APIを利用してパッケージ情報を取得
url = f"https://pypi.org/pypi/{package_name}/json"
try:
response = requests.get(url, timeout=5)
if response.status_code == 200:
data = response.json()
info = data.get("info", {})
print(f"[OK] パッケージ '{package_name}' は存在します。")
print(f" 最新バージョン: {info.get('version')}")
print(f" プロジェクトURL: {info.get('project_url')}")
return True
elif response.status_code == 404:
print(f"[WARNING] パッケージ '{package_name}' はPyPIに存在しません。ハルシネーションの可能性があります。")
return False
else:
print(f"[ERROR] ステータスコード {response.status_code} により確認できませんでした。")
return False
except requests.exceptions.RequestException as e:
print(f"[ERROR] 通信エラーが発生しました: {e}")
return False
if __name__ == "__main__":
# 検証したいパッケージ名のリスト
# 例として、実在する 'pypdf' と、架空の 'fake-pdf-extractor-ai' を検証します
target_packages = ["pypdf", "fake-pdf-extractor-ai"]
print("--- パッケージ検証開始 ---")
for pkg in target_packages:
verify_pypi_package(pkg)
注意: このスクリプトはPyPIのパブリックAPIを使用しています。短時間に大量のリクエストを送信するとレート制限に達する可能性があるため、実際の運用環境やCI/CDに組み込む際は、適切なリトライ処理やキャッシュ機構を検討してください。
4. 実務用:AI生成コード検証チェックリスト
AIが生成したコードを実際のプロジェクトにマージする前に、以下のチェックリストを用いてレビューを行うことを推奨します。
| チェック項目 | 検証方法・判断基準 | 判定 (OK/NG) |
|---|---|---|
| 1. パッケージの実在性 | 提案されたサードパーティ製パッケージが、PyPIやnpm等の公式レジストリに実在するか。 | [ ] |
| 2. メソッド・プロパティの存在 | 使用されているAPIやメソッドが、公式ドキュメントの最新バージョンに記載されているか。 | [ ] |
| 3. 非推奨機能の排除 | 生成されたコードに、すでに非推奨(Deprecated)となっている古いAPIが含まれていないか。 | [ ] |
| 4. セキュリティ・脆弱性 | 提案されたパッケージのメンテナンス状況(最終更新日、スター数、未解決の脆弱性情報)に問題はないか。 | [ ] |
| 5. ローカル環境での動作確認 | 隔離されたサンドボックス環境(Docker等)で実際にコードを動かし、インポートエラーやランタイムエラーが発生しないか。 | [ ] |
5. 導入時の注意点と運用上の判断基準
-
公式ドキュメントを「正」とする
LLMの出力はあくまで「下書き」や「アイデア出し」として扱い、最終的なAPI仕様やパラメータの指定方法は、必ず各技術の公式ドキュメント(最新版)を参照して裏付けを取ってください。 -
依存関係の安易な追加を避ける
AIが「便利なライブラリ」として提案してきたものをそのままrequirements.txtやpackage.jsonに追加すると、サプライチェーン攻撃のリスクや、プロジェクトの依存関係肥大化(デプロイサイズの増加)を招きます。標準ライブラリで代替可能か、またはすでにプロジェクト内に導入済みのライブラリで実現できないかを最初に検討してください。 -
RAG(検索拡張生成)の活用検討
社内独自のAPIや、最新のライブラリ仕様についてAIにコード生成させたい場合は、プロンプトに最新のAPIリファレンス(MarkdownやJSON形式)をコンテキストとして直接流し込む(RAGやコンテキスト注入)手法が有効です。
まとめ
AIによるコード生成は開発効率を大きく向上させますが、ハルシネーションによる「存在しないAPIやライブラリの生成」は避けて通れない課題です。プロンプトでの制約定義、外部レジストリAPIを用いた自動検証、そして開発プロセスにおけるチェックリストの運用を組み合わせることで、安全かつ効率的にAIの恩恵を享受することができます。