Closed5

「コード×AI ソフトウェア開発者のための生成AI実践入門」を読んでみて

じゅんじゅん

第1章 生成AIがエンジニアリングの常識を変える

エンジニアリングタスクは一点物

創造性、多様性のあるタスクに対峙するエンジニアにとって、小手先のテクニックで完璧なプロンプトを作ろうとする必要はない
むしろ、タスクに合わせてプロンプトを作成し、AIとの対話の中で出力を調整できる能力を身につけていくことが重要

エンジニアの仕事は消えない

AIの台頭によってエンジニアの仕事がなくなることを懸念する声があるが、過去の技術革新でも同じような声が上がっては、エンジニアの役割が広がっている
結局のところ、AIが生成したコードを理解し、運用し、改善するのにエンジニアが必要となる
仕事がなくなることを嘆くのではなく、新たな機械の創出と捉えることが重要

嘘は嘘と見抜けるエンジニアになる

生成AIは時にハルシネーションを起こすことがある
学習の際に混ざっている誤情報や偏って情報が原因で起こる
生成AIは間違った情報をそれらしく出力してくることがあるが、私たちエンジニアは常に批判的に評価し、他の情報源と照合して取捨選択することが大事

AIに最適なタスクを割り当てるスキルを磨く

生成AIは膨大な処理ができる反面、その中に間違いがあった場合に人間にはそれをレビューすることは困難になります。
たとえ出力コードが少なくても、そのコードの生後性、依存関係、影響範囲などを人間が考慮する必要があります。
そこで、タスクを人間が確認しやすいサイズに分割することが鍵になります。
プロンプトの設計と並行して、出力サイズの設定も重要な検討事項となるのです。

適切なペースでのコードレビュー

一度に数百行ものコードをレビューしようとすると、人間はその欠陥を発見する確率が高まります。
自分がコードレビューできる範囲を理解して、それに合わせた出力になるように調整することが重要です

AIの台頭で問われるエンジニアの真価

エンジニアの総合的な「優秀さ」が問われるようになり、それはAIの出力に対して正確な判断と意思決定を下す行為と言い換えることができます
ここでいう優秀さとは、コード品質、パフォーマンス、セキュリティなどの技術力の高さはもちろんですが、既存システムとの整合性やプロジェクト全体を見れる広い視野なども含みます。

AIは優秀なエンジニアだけのものではない

  • 生成AIは学習を加速させる強力なツールなので初学者でもどんどん使用していくべき
  • AI駆動の知識獲得ができる
  • 高速なトライ&エラー
    • 初めから完璧な回答を求めずに高速なトライ&エラーが効果的
    • AIとの対話を通して、早く答えにたどり着くことが重要

開発支援AIを使い分ける

  • 自動補完型:GitHub Copilotなど
  • 対話型:ChatGPTなど、複雑な概念の説明やアルゴリズムの設計など
  • エージェント型:GitHub Copilot Workspaceなど、複雑なタスクを自律的に実行

AIで組織の競争力を高める

単にAIツールを企業に取り入れることは競争優位性にはならない
これからはいかにしてAIを自社の業務やニーズに適応させていくかが重要

特徴 RAG ファインチューニング
動的な情報への適応 ○最新情報やシステムの条件に柔軟に対応 ×最新の状態を保つためには更新が必要
カスタマイズ ×検索で取得した情報に基づくカスタマイズに限定 ○高度なカスタマイズが可能
データ効率と要件 ○ラベル付きのデータは多くの場合で不要 ×タスクに特化した学習データが必要
効率とスケーラビリティ ○一般的なモデルの利用などによりコストを抑制 ×学習のみならずモデルホスティングのための高いインフラコスト

AIに与えるコード

ファインチューニングやRAGによって企業特有の情報を持ったAIを育てていくことが重要
組織の成功を果たすには下記質問の答えを用意しておく必要がある

  • 組織はAIに与えられるコードベースやドキュメントを用意できているか?
  • それらのコードや情報はAIが理解しやすいように整理できているか?
  • それらのコードや情報は、公開されたものより価値が高いものか?

内製化によりAIを最大限に活用する

AI時代において、自社のコードやナレッジをAIが活用しやすい形に整理して、AIの活用を促進するために下記に取り組んでいくべき

  • ナレッジベースの構築
  • AIのためのコードベースの整理
  • AIプラットフォーム化 / AIツールの開発

AIをコストカットだけの目的で導入していないか?

企業がAIを活用して競争力を高める方法は下記3つ

  • コストカット:必要な労力、資源をカット
  • 生産性向上:同じ労力でより多くの成果を出す
  • 価値創造:全く新しい製品やサービスを生み出す

短期的:コストカットや生産性向上は取り組みやすく成果も出しやすい
長期的:すぐに成果は出ないが、企業にとっての新しい価値の創造も大事
短期的な成果と長期的な競争力の向上をバランスよく両立させる必要がある

じゅんじゅん

第2章 プロンプトで生成AIを操る

システムプロンプトとユーザープロンプト

  • システムプロンプト
    ユーザーが入力する前にAIに伝えておくべき規定の指示文

  • ユーザープロンプト
    利用者が実際にAIに入力する指示文

プロンプトを再利用するか使い捨てるか見極める

  • 再利用するパターン
    特定の画面、ロジック、ドキュメントに関するタスクは再利用するといい
    フォーマットや条件、注意事項など、プロンプトに必要な要素を分解してプロンプトを構築する
  • 使い捨てるパターン
    エンジニアの日常作業は創造的でユニークなものが多い
    そのようなタスクでは柔軟にプロンプトを構築し、使い捨てながら進める必要がある

情報構造化の3要素

  • 意図(Intent)
  • コンテキスト(Context)
  • コンテンツ(Content)
要素 内容
意図 基本的な命令セット、開発者である自分のニーズ、期待する結果
コンテキスト その情報を取り出すためのプロジェクト情報、背景、既存コードベースや実装における制約
コンテンツ 提供する情報を取り出したい情報、書式や構造、関数の名前、引数、戻り値、処理内容、フォーマット

箇条書きを用いた条件指定

箇条書きによる詳細な条件指定は効果的
また、gitなどでプロンプトのdiffを管理するのにも効果的

制約指示の段階的導入

AIにやってほしいこと以外に禁止事項を伝えるのも効果的
AIとの対話の中で禁止事項を随時適応するといい

じゅんじゅん

第3章 プロンプトの実例と分析

Reactのコンポーネント生成プロンプト

プロンプト例

フロントエンド開発者として行動してください。
説明に基づいて、TypeScriptのReact Functional Componentを作成してください。
使いやすいものにしてください。
すべてのユースケースと状況をカバーするようにしてください。

返却例:
${componentExample}

指示:
動作するコードであることを確認し、私が何かを変更したり実装したりすることを想定しないでください。
プロジェクトにTypeScriptのReactセットアップがあることを前提としてください。
内部ライブラリは使用せず、内部ライブラリの@react-agent/shadcn-uiとグラフ用のrechartsのみを使用してください。

返却タイプ:
Reactコンポーネントを返却し、TypeScriptで記述し、Tailwind CSSを使用します。
tsx/typescript Markdown tsx <あなたのコードをここに> 内にコードを返却してください。

各指示の要点

ロール指定(役割付与):

フロントエンド開発者として行動してください。
回答者はフロントエンドエンジニアとして振る舞うこと

開発内容指定:

説明に基づいて、TypeScriptのReact Functional Componentを作成してください。
提示された説明を元に、TypeScriptとReactを用いた関数コンポーネントを作成すること

品質要件:

使いやすいものにしてください。
利用者にとって操作しやすく、直感的なコンポーネントにする
「すべてのユースケースと状況をカバーするようにしてください。」
多様な使用場面や条件に対応できるようにする

返却例の提示:

返却例: ${componentExample}
返却時の形式の参考例(テンプレート変数を使った出力例)

前提条件と制約:

動作するコードであることを確認し、私が何かを変更したり実装したりすることを想定しないでください。
そのまま実行して機能する完成品を求める

プロジェクトにTypeScriptのReactセットアップがあることを前提としてください。
既にTypeScriptとReactの環境が整ったプロジェクトであることを想定する

内部ライブラリは使用せず、内部ライブラリの@react-agent/shadcn-uiとグラフ用のrechartsのみを使用してください。
外部ライブラリ利用を制限し、指定されたライブラリのみ使用可能

コード返却形式:

Reactコンポーネントを返却し、TypeScriptで記述し、Tailwind CSSを使用します
React + TypeScript + Tailwind CSSによるコンポーネント実装

tsx/typescript Markdown tsx <あなたのコードをここに> 内にコードを返却してください。
Markdownのコードブロック(tsx)を用いてTSX形式のコードを提示すること

じゅんじゅん

第4章 AIツールに合わせたプロンプト戦略

自動補完型AIツール

GitHub Copilotなどに代表されるツールのこと
下記のような特徴がある

  • エディタ上のコードなどの豊富な情報をプロンプトに含むため、ユーザープロンプトが最小で良い
  • 出力が少ないため高速でのフィードバックが可能(方向転換が必要な場合でも容易にできる)
  • 迅速なレスポンスによって、思考の流れを途切れさせることなく作業ができる

どのようにプロンプトが構成されているか

  • GitHub Copilotは開いているファイルタブ同士の情報をプロンプトに含めている
  • TypeScriptの型定義ファイルなどはそれだけで、データ構造や実装に関わる情報を提供できる
  • TypeScriptの型定義ファイルなどはVScodeのピン留めするとCopilotに情報提供しやすい

対話型AIツール

OpenAIのChatGPTをはじめとするツールのこと

AI駆動のプロンプト生成
詳細な要求を一から書き出すのではなく、指示自体を作ってもらうのが有効

Railsで簡単なCRUDアプリを作成したい
実装方法について気をつけるべきことを箇条書きしてください

下記のような出力が来るので、それを再利用してプロンプトとする

1.	MVCアーキテクチャの理解
2.	RESTfulなルーティング設計
3.	モデルとマイグレーションの設計
4.	バリデーション(Validation)の設定
5.	ストロングパラメータ(Strong Parameters)の利用
6.	コントローラ内での処理の流れ
7.	ビュー(ERB)でのフォーム作成
8.	エラーメッセージの表示
9.	フラッシュメッセージによる通知
10.	パーシャル(partial)の活用
11.	DRY原則の意識
12.	ルーティング、コントローラ、ビューの対応関係を明確に
13.	Railsコンソールとサーバーログを積極活用
14.	余計な外部ライブラリは使用しない
15.	デプロイまで考える場合は環境差異に注意

はじめから「実装を教えて」だと、AIは多くの可能性の中から1つの回答を選択するだけになる
直接的な実装方法を尋ねるのではなく、考慮すべき点や条件などの情報をまずは引き出すことが重要

エージェント型AIツール

GitHub Copilot Workspaceに代表されるツール

  • 新規コード生成
  • 既存コードの操作

自動補完型AIツールに比べて、エージェント型AIツールは時間コストがかかる
一度のプロンプト入力に対して、出力に数分かかることもある
なのでプロンプト入力前に下記のようなアプローチを取るといい

  1. 対話型AIで予備調査

    • シンプルなプロンプトで試す
    • AIのタスク理解度やコード生成能力を確認する
    • エージェント型よりトライアンドエラーしやすい
  2. エージェント型AIツールで小規模に試す

    • 複数ファイルにまたがる情報を利用できるなどの優位性を活かして小さい単位で試す
    • タスクを小さな単位に分割して試す

エージェントへの部分的な依頼

実装方法を理解し、正しく依頼・レビューできる部分」に絞って依頼することが重要

  • ラフな実装や大枠のデザインを形にする
    まず、基本的な実装を自分で行い、その後の修正や追加実装をAIに依頼するようにする
    コード内にTODOコメント(// TODO:)でAIへの指示をあらかじめ入れておくといい

  • 部分的なパーツをもとに全体を生成する
    一部分だけ自分で実装し、それをもとに残りをAIに依頼する
    20個のエンドポイント実装のうち1つ目は実装して、残りをAIに依頼するなど

  • 自明な領域におけるタスク依頼をする
    テストケース、ドキュメント作成、コメントの追加などの比較的自明な作業をAIに任せる

じゅんじゅん

第5章 AIと協働するためのコーディングテクニック

AIが扱えるトークン数が増えていくのに対して、人間の認知能力には限界がある
それらを考慮して、情報の入力と出力を調整する必要がある

コードの単一責任化

例えば、1つのクラスにデータの保存や解析など、複数の責務が集中しているとします
このような構造はクラスを肥大化させ、コードの理解を困難にする

また、AIを活用する上でも下記のような問題がある

  • AIに渡す情報量が多くなりすぎ、生成精度が低下する
  • AIの出力が途中で打ち切られる

クラスを関心ごとに分割し、シンプルな構造にする

  • AIに与える情報量を制御しやすくなる
  • 生成コードの品質が向上する
  • コードの再利用性が向上

AI効率を考慮したファイル構成

GitHub copilotなどで関連するファイルのコードを参照される際に、ファイルやディレクトリの関連性がわかるほうが、AIが適切にコードを参照できる
下記のように意味のまとまりでディレクトでまとめたりするといい

改善前

controllers/
  ├── admin_controller.rb  # 管理画面全体の処理を一つのコントローラで扱っている
  ├── site_controller.rb   # 一般向けのサイトの処理を一つのコントローラで扱っている
  ├── content_management_controller.rb
                           # コンテンツの作成・編集機能を一つのコントローラで扱っている
  ├── notifications_and_messages_controller.rb
                           # 通知とメッセージ機能を一つのコントローラで扱っている
  └── api_controller.rb    # API関連の処理を一つのコントローラで

改善後

  ├── admin/
  │   ├── base_controller.rb
  │   ├── dashboard_controller.rb
  │   └── posts_controller.rb
  ├── api/
  │   ├── v1/
  │   │   ├── base_controller.rb
  │   │   ├── posts_controller.rb
  │   │   └── users_controller.rb
  ├── application_controller.rb
  ├── authentication_controller.rb
  ├── error_handling_controller.rb
  ├── home_controller.rb
  ├── posts_controller.rb
  └── users_controller.rb
このスクラップは11日前にクローズされました