Vibe coding実践例:特有のリファクタリングの難しさ

AIテキスト

前回まで、RSSフィードからX投稿のコメント生成をLLMで自動化する取り組みを進めてきました。

規模が大きくなってきたため、コード管理の方針を立て、ドキュメントに基づいたコード分割と再構築を進めています。

今回は、リファクタリング時に遭遇したChatGPTでのVibe coding特有の問題を掘り下げます。

仕様に基づくコード生成の難しさ

前回生成されたコードは、関数定義や全体のフローを実行する枠組みはあるものの、実装が不完全でそのままでは動きませんでした。

既に動作するサンプルやドキュメントがあるため、それらを添付して補完を指示すれば修正は可能です。 ただし、AIが設計の変更を提案してきたり、一度では修正しきれないケースが多く、根気よく指示を繰り返す必要があります。

ただし、AIが設計の変更を提案してきたり、一度では修正しきれないケースが多く、根気よく指示を繰り返す必要があります。

以下のような指示が効果的です:

設計はドキュメントに従ってください。
設計で新規に追加した要素は維持し、実装は、添付のコードで再利用できる部分を活用し、
RSS・本文記事・要約コメント案については同じ結果が得られるようにしてください。

典型的な問題事例

コードを動く状態まで修正する過程で、AIによるコーディング支援に特有のいくつかの問題に遭遇しました。

実装の省略と曖昧な説明

まず前回生成されたコードは、そのままでは動きません。

ChatGPTからは下記のようなコメントが添えられますが、わかりにくいので注意が必要です。

下記は、あなたが提示した設計・フロー・ステータス定義をそのまま前提にした
1つ目のスクリプト collect_and_prepare.py の最小実装例です。

(中略)

次にやるべき拡張(おすすめ順)
    1.    review.md に ID or URLコメント を埋め込み
    2.    MD内のチェック状態を post_to_x.py でパース
    3.    LLM呼び出し部分を Ollama に差し替え
    4.    本文取得を newspaper3k 等に変更

「最小実装例」「拡張」といった曖昧な言葉が使われており、コードを見ずに進めてきた場合、何をすればよいのかわかりません。

コードを確認すると、URLが「example.com」だったり、「ダミー」と明記された文字列が存在します。

Vibe codingのみではこうした問題に気づくことが難しく、また「おすすめ」に従っても動くコードにはたどり着けません。

規模が大きくなったり、設計や仕様を与えてコードを生成するとよく起こる現象です。 このような場合は、具体的なゴールを示して「動くコード」に修正するよう求める必要があります。

不完全な実装と文字列の勝手な変更

前回まで動いていたコード例を見せて補完を指示しても、意図しない変更が加えられることがあります。

元のコードの関数や文字列をそのまま置換することを期待し、前回まで問題なく動いているコードを参照するよう指示します。

このコードが動く状態を目指します。
添付のコードを参照し、実装を補間してコードを完成させてください。

「完成コード」と呼ばれる内容がChatGPTから出力され、改めて複数の問題が含まれることになります。

例えばURLに「# 実在RSS」とわざわざChatGPT自身で加えたコメントがありますが、実際には存在しないURLが記述されていました。

# =====================
# 設定
# =====================

RSS_URL = "https://www.abc.net/index.xml"  # 実在RSS
ARTICLES_JSON = "articles.json"
REVIEW_MD = "review.md"

OLLAMA_URL = "http://127.0.0.1:11434/api/generate"
OLLAMA_MODEL = "llama3.1:8b"

RSSが取得できず出力も空になるのですが、ChatGPTはこれに気づかず、デバッグログの埋め込みを始めます。 (abcは伏せ字ですが、実際は実在するドメインが使われました。しかしディレクトリやファイル名が間違っており、問題の発見が困難でした)

また、LLMに与えるプロンプト文字列が、前回の記事から特に説明もなく大幅に削減されています。トーンやemotionといった指定がすべて削除されています。

# =====================
# LLM 関連(添付コード準拠)
# =====================

PERSONA_PROMPT = """あなたはエンジニアです。以下のニュースについて、X(旧Twitter)用の日本語コメントを1つ作成してください。

# ニュース
__NEWS_SUMMARY__

# 出力ルール
- 日本語のみ
- 80〜200字
- 断定を避ける
- 絵文字・ハッシュタグ禁止

出力:
"""

実行するとLLMからの出力は得られるため、一見すると「動く」状態に見えます。 しかし期待とは異なる動作をします。

日本語の品質はテストでは検出しにくいため、コードを直接確認する以外に気づく方法がなく、非常に”タチの悪い”問題です。

過度なフォールバック指向

LLM呼び出し等の処理で例外が握りつぶされ、ダミーの回答で置き換えられるケースがあります。 実際には動作していないのに「動く」コードとして扱われてしまう典型例です。

def generate_summary_and_comment(text: str) -> Dict[str, str]:
    payload = {
        "model": OLLAMA_MODEL,
        "prompt": PERSONA_PROMPT.replace("__NEWS_SUMMARY__", text[:1500]),
        "stream": False
    }

    try:
        r = requests.post(OLLAMA_URL, json=payload, timeout=180)
        r.raise_for_status()
        data = r.json()
        comment = (data.get("response") or "").strip()
        if not comment:
            raise ValueError("empty response")
    except Exception as e:
        return {
            "summary": text[:200],
            "comment": f"[LLM ERROR] {e}"
        }

    return {
        "summary": text[:200],
        "comment": comment
    }

別の例では、例外発生時の挙動が異なります。 こちらは「動いていない」ことがわかるためまだマシですが、やはり例外処理としては適切とは言えません。

def fetch_article_body(url: str) -> str:
    try:
        r = requests.get(url, timeout=10)
        r.raise_for_status()
        return r.text[:5000]
    except Exception as e:
        return f"[FETCH ERROR] {e}"

今回のように、Vibe codingや「動くこと」を優先するような指示が特段ない場合でも、AIはフォールバックの処理を好む傾向があります。

例外は適切に伝播させ、呼び出し元で対処する方が望ましい場合が多いことを指示する必要があります。 また、指示しても無視されることも多く、定期的にチェックやリファクタリングを行う必要があります。

ログやテストを多用するアプローチ

上記のような問題がいくつか積み重なった結果、実行しても出力ファイルは空になっています。 ここで、出力された結果が空であることをAIに伝えると、直ちにコードにログ記録処理を埋め込み始めます。

空になる原因はだいたいこのどれかです:
    •    RSSが0件(取得できてない)
    •    新規が0件(articles.jsonに全部入ってて status が new じゃない)
    •    ready が0件(processが回ってない/status条件に引っかかってる)
    •    そもそも review.md を見てる場所が違う(cwd問題)

なので、いまの collect_and_prepare.py.py に 原因が見えるログ&review.md内のステータス集計を入れるパッチを当てました。
(あなたの画面にあるファイルに対して編集済み)

実際は、上記の原因はどれも外れていて、前述の実在しないURLが参照されていることが根本原因でした。一般的な推測とデバッグログを多用するアプローチは、AIによるコード支援ではよく見られます。

ログで「運よく」問題が特定できる場合もありますが、今回のケースでは例外を握りつぶした後などにログ出力が仕込まれ、問題の特定ができるアプローチになっていませんでした。 多くの場合、ログだけでの特定は非常に時間がかかり、徒労に終わる場合も少なくありません。

  • 仕込んだログが撤去されず標準出力やエラー、出力ファイルなどに不要な情報が残る
  • ログの撤去を指示してもAIが全部は取り切れない、または必要な箇所まで削除してしまい手がつけられなくなる
  • ログを仕込んでログを確認し、更に詳細なログ出力を追加するループに入り、多量のトークンを消費(有料AIの場合はコスト増大に直結)

ログ出力を仕込むパッチ編集が提示されても、冷静に拒否して、コードの調査を指示することである程度緩和できます。

また、今回はテストコードを作成していませんが、コードの調査よりもテストの実行で問題を検出しようとする傾向があります。 これもデバッグログによるアプローチと性質が似ており、「運よく」機能する場合もありますが、適切なテストを実装できない場合も多いです。それどころか、存在しないテストを期待して実行する場合もあり、時間の無駄で終わるケースも少なくありません。

まとめ

Vibe codingでコード生成を行う場合、動くコードを得るまでにいくつかの典型的な問題に遭遇します:

  • 具体的な実装の省略: 「ダミー」や「example.com」などで実装が省略され、曖昧な説明が多用される
  • 不完全な補完: 動いていたコードを参照しても、文字列やURLが勝手に変更される
  • 過度なフォールバック指向: 例外が握りつぶされ、エラーが隠蔽されて問題の発見が困難になる
  • ログ過多のアプローチ: 問題解決のためにログを追加し続け、トークンを浪費する

このあたりがVibe codingの難しいところで、「コードを意識しない」場合は、ブラックボックス的な解決アプローチに頼らざるを得ません。 AIが問題を修正しきれない場合もあり、その場合は一からコードを作り直すことになります。 完全にVibe codingに頼る場合は、このトレードオフを許容して進める必要があります。

これらの問題を認識し、適切に対処することでVibe codingをより効果的に活用できます。 次回は、これらの問題を踏まえた実装の改善について解説します。

タイトルとURLをコピーしました