😺

Copilot を2ヶ月使って実感した「ずぼらでも成果が出るAI活用術」

に公開

約2ヶ月前から Copilot を使用しており、それまで触ったことのない自分にとっては革命でした…(今更過ぎるかもですが…🙄)

特に “自分で工夫しなくても AI の方から環境に合わせて賢くなっていってくれる” という点が、恐ろしくも素晴らしい点だなと実感しています。

この記事では、実際の開発プロジェクトで試して効果のあった 「ずぼらでも結果を出せるTips」 を2つ紹介し、
最後に それらを最大限活かせる具体例 を軽く紹介させていただきます!

Tips

1. 【プロンプトの作成】AIとの対話もAIに任せて、土台作りをさせる

こちらはふとプライベートで見かけた情報にて、「AIにプロンプトも作ってもらおう」との内容を見かけたことがきっかけです。

画像生成系のモデルを使うとき、「この写真をAIに作ってもらうためのプロンプトを生成して」というふうな使い方をしていました。
これは参考になる画像をプロンプトに落とし込んでもらって、ある程度似た構図の画像を生成するために使用しておりました。

AIが勘違いしやすいものや名称だけでは生成してくれない時に、ある程度の線路を敷いてあげるときに大いに役立ちました。

ラピスラズリの写真を依頼した結果
深い青色のラピスラズリを接写で撮影したリアルなマクロ写真。
表面は滑らかに研磨されており、光沢が強く反射している。
石の中には金色のパイライトの筋や斑点が自然に散りばめられている。
背景はシンプルで、宝石が際立つように配置されている。
高解像度で質感豊かなリアルな質感。

これを生かして、プロジェクト用のプロンプトテンプレートを生成してもらいました。
前提条件として数週間ほど、プロンプトを渡し続けてコードを生成し続けてもらっている環境で出してみました。(名称はぼかしています)

バックエンドからAPI呼び出しに関するテンプレート
Copilotへの指示を出すために、API呼び出しのプロンプトテンプレートを作成してほしい。
特定の名称を指定せず、編集することができるような形で出力してほしい。
以下の指示に従って、指定したフォーム(〇〇Form)に対する API 呼び出し処理・Resolver(リゾルバー)生成・初期値マージ・useForm 構造の作成をすべて一度で実装してください。

■ 対象ファイル
- 〇〇Form.ts
- components/〇〇-wrapper.vue
- schemas/〇〇-schema.ts
- api/〇〇API.ts

■ 実装する内容(必須)
1. 〇〇API.fetch(id) / 〇〇API.update(data) など、CRUD を行う API クライアント関数を作成する。
   - fetch / create / update / delete のうち必要なものを実装。
   - fetch の戻り値は Resolver を通してスキーマに整合する構造へ変換。

2. Zod を使った 〇〇Schema を作成(既存があれば拡張または使用)。
   - バックエンドが number を要求する場合は transform で number 化する。
   - nullable を許可する項目は optional().nullable() を使用。

3. Resolver(Zod スキーマと API レスポンスの整合用)を作成。
   - API レスポンス → Zod 用の型 に整形する
   - 例えば null/number/string の揺れを吸収する
   - stations や配列項目があれば FieldEntry に変換可能な形に整形

4. useForm(〇〇Form)を次の構造で実装する:
   - validationSchema: toTypedSchema(〇〇Schema)
   - initialValues はスキーマに完全準拠させる
   - API fetch 結果を resolver → setValues でマージする
   - defineField / useFieldArray を適切に実装する

5. wrapper(〇〇-wrapper.vue)の実装要件:
   - defineField / useFieldArray の tuple を正しく受け取って v-model にバインド
   - :error, :error-message, :hide-details を正しい順序で渡す
   - watch(values) で @update:values を emit
   - watch(errors) で @validation-change を emit
   - 初期マージ処理は use〇〇Form 内のみで完結させる(wrapper にはロジックを書かない)

6. API の更新処理(update)のテンプレート:
   - wrapper から emit('update:values') → 親が収集 → 保存処理で 〇〇API.update に渡す
   - 保存時にはスキーマで number/string 変換済みであること

■ 実装禁止事項
- 既存 UI の変更禁止(label, class, style)
- props の追加禁止(与えられた props のみで実装)
- submit ボタンの追加禁止
- バックエンド API の仕様変更禁止
- DOM 直接書き換え禁止
- ロジックを section 内 template に書くことの禁止(script 内に統一)

■ 出力形式
- 修正されたファイルを 全文で出力 する
- diff 出力禁止
- コメント、console.logの追加禁止
- 必ず一度の出力で全ファイルの修正を完了させる

実際に出力してほしいものとはかなり違いますが、禁止事項や出力形式などはそのまま使用できそうな内容で、過去のレビューした注意点を拾い上げてくれました。

命令内容やプロンプトを読み込んだり、生成した回数によってよりプロジェクトに寄り添った出力を返してくれそうだと感じました。

2. 【チューニング】「人間によるレビュー」と「AI による自己評価」の二重レビューでチューニング速度を早める

プロンプトを改善しても、出力が全然安定しないことはよく経験しました。

AIは人間のように意図を汲み取る力が弱く、こちらの意図を正確に読めていない場合があるためです…。

そこで考えた手法として、

  • まず 人間(自分)からレビューを入れる
  • さらに AI 自身に自己評価させる

人間からのレビューとメタ認知プロンプティングと呼ばれる設計手法を組み合わせ、AI自身にも自分のプロンプトを再評価させるという二重でレビューを行うことでよりチューニング速度を上げられるのではないかと考えました。

以下試してみた内容です。

レビューと自己評価の依頼
** 先ほどの バックエンドからAPI呼び出しに関するテンプレート に対して行う **
以下は私からのレビューなので反映すること。
1.の内容は過去に行ったことがないので、削除するように。
また、「initialValues はスキーマに完全準拠させる」という記述は、
orvalで自動生成された api.ts に記載されている、それぞれの関数の return を必ず参照させるように明記すること。
追加であなた自身で、厳しい自己評価をしてください。
自己評価の基準は、現在のプロンプトで現在のフォルダ構成に沿った出力結果が必ず得られるのか?という点で自己評価を入れること。
最終的に上記の私のレビューと、あなた自身の自己評価の両方の観点を改善したプロンプトを出力するように。
自己評価
# 🔍 自己評価(あなた自身が改善すべき点)
以下の観点で、本プロンプトがプロジェクト構成に確実に適合するかを自己分析し、修正を加えています:

### ✔ Orval 自動生成 API に完全準拠しているか?
→ 過去プロンプトでは独自 API ファイルを生成させてしまう可能性があったため削除  
→ 今回は **api.ts の return 型を必ず参照** を強制

### ✔ useForm パターンがプロジェクト内の実装と完全一致しているか?
→ wrapper + section + composable 方式に合わせて修正  
→ initialValues の作り方も IAE の既存パターンに統一

### ✔ 現状のフォルダ構成に必ずハマるか?
→ composables/…  
   components/…  
   schemas/…  
   の3構成へ完全対応  
→ Orval の api/generated の構造にも依存しないよう調整済み

### ✔ 「質問禁止」でも Copilot が適切に動作するか?
→ 必要な情報(API 名、スキーマ名など)は  
   **利用者が後で埋める前提でテンプレ化している**
修正後のプロンプト
以下の指示に従って、指定したフォーム(〇〇Form)に対する  
**API レスポンス → Zod スキーマ → useForm → Wrapper**  
の一連の実装を一度で完成させてください。

## 📌 対象ファイル(私が後で貼ります)
- composables/〇〇Form.ts
- components/〇〇-wrapper.vue
- schemas/〇〇-schema.ts(必要時のみ)
- ※ API クライアントは **既存の Orval 自動生成の api.ts を必ず使用**  
  → 独自 API ファイル(〇〇API.ts)は作成禁止(←過去例がないため削除)

---

# 🎯 実装内容(必須)

## 1. **API 呼び出し(fetch)**
- **Orval 自動生成の api.ts の関数だけを使用**(例:get◯◯ById)
- API の戻り値は api.ts の return 型を必ず参照し、  
  そこから **Resolver でフォーム用へ変換する**

---

## 2. **Zod スキーマ(〇〇Schema)**
- 既存があればそれを使い、必要なら項目を追加
- バックエンドが number を要求する項目は  
  `.transform(v => Number(v))` を利用
- nullable は `optional().nullable()` を使う
- 必ず API の return 型と整合する形式で作成

---

## 3. **Resolver(form 初期値整形)**
- **API レスポンス(orval 型) → Zod 用フォーム構造** に変換
- string/number/null の揺れをすべて吸収
- 配列や stations のような繰り返し項目は  
  useFieldArray と相性の良い形に整形
- nested object があれば安全に default 値を補完

---

## 4. **useForm(〇〇Form.ts)**
以下の構造で必ず実装:

- `validationSchema: toTypedSchema(〇〇Schema)`
- `initialValues`**Orval 自動生成 API の return 型を参照して構築**すること  
  (あなたのレビューを反映し、ここを強制)
- API fetch → resolver → setValues で初期値を反映
- defineField / useFieldArray を適切に記述
- return 値 は:

{
errors,
values,
fields,
setValues,
handleSubmit,
resetForm,
validate
}

---

## 5. **wrapper(〇〇-wrapper.vue)**
プロジェクト内ルール通り:

- defineField/FieldArray の tuple を展開して v-model に入れる
- :error / :error-message / :hide-details の順序を統一
- watch(values) → emit('update:values')
- watch(errors) → emit('validation-change')
- 初期値マージは **必ず use〇〇Form 内でのみ実施**  
  (wrapper にロジックを書かない)

---

## 🚫 禁止事項
- UI の変更禁止
- props の追加禁止
- submit ボタン追加禁止
- Orval 生成ファイルの編集禁止
- DOM 操作禁止
- 質問禁止(あなたが判断して最適な構成を出力する)

---

## 📌 出力形式
- 対象ファイルを **全文で出力**
- diff / 抜粋禁止
- コメントは禁止(必要なコードのみ)
- 一度のレスポンスですべて出力する

# 🟩 Copilot への最終タスク

**このプロンプト内で指定したファイル名・API 名・スキーマ名に置き換え、  
プロジェクトルールに完全準拠した Form + API + Resolver + Wrapper の  
4点セットを一括で完全生成しなさい。**

個人レビューの結果としては多少の改良が見られ、特にOrvalを指定したことによる改善を重点的に行なってくれました。

自己評価では軽い改善が見受けられ、これは人間から範囲を指定したためその点のみを改善した結果かなと感じました。
「間違ってそうだし、改善してほしいけど具体的な案が出ない…」という箇所に対して、自己評価を行わせることが適切だと感じております!

Try: tips を活かして実際にcopilot-instructions.mdを作る

初めの1ヶ月は、プロンプトの精度を上げることを第一に考えていました。

しかし、一度目の出力と改善後の出力の結果が全く変わらなかったり、たくさんの変更を加えてほしいのに、出力されるファイル数が減っていったりするなど、かなり悩ましい状態が続きました。

そこで気づいたのが、Copilot を最大限活かすには、プロジェクト全体のルールを明文化したcopilot-instructions.md が必須だということでした。

個人的には「プロンプト自体をガッチリルールで固めることで、この短期の案件ではルールブックはなくとも動くだろう」と考えてしまっていましたが…、一度このファイルを作成して出力結果の差を見てみようと思いました!

というわけで、このルールブックとなるファイル自体をAI に作らせてしまうことにしました。
サクッと10分ぐらいで実行できますので、まだ育てるべきルールブックを持っておられない方は試してみてください!

mode 使用モデル
agent Claude Sonnet 4.5
AIに依頼して作成したプロンプト(環境に依存するものもあるので一部抜粋)
# Copilot への指示:このプロジェクト専用の「.github/copilot-instructions.md」を自動生成してください

## 必ず行うこと

### **フォーマット**
- Markdown 形式
- 見出し階層を整理
- コードブロックも含む
- この md はそのまま `.github/copilot-instructions.md` として利用可能な完成品とする

### **フォルダ構成をソースコードから抽出し、正確なディレクトリ構造を md に記述する**
- src/ 以下の全構造
- api/admin/generated(Orval)
- components / composables / pages / schemas / utils
これらを自動確認し、正しいツリー構造として Markdown に載せる。

### **プロジェクト全体のソースコードを走査し、使用されているすべてのライブラリを列挙する**
- import 文
- package.json
- nuxt.config.ts
- plugins
- composables
- features/iae/ 以下  
これらすべてからライブラリを抽出し、  
**漏れなく一覧化して「使用ライブラリ一覧」として md に反映すること。**


### **Copilot に必ず従わせる開発ルールを作成**
- diff 出力禁止(フルファイル出力のみ)
- 質問禁止(推測して出力)
- 既存 UI を変更しない
- props 追加禁止
- 使用中ライブラリの構文を完全踏襲
- Orval 生成ファイルの編集禁止
- composables / wrapper / section の責務ルール
- バリデーション・フォーム構造の共通パターン
- 命名規則

etc...
上記の出力結果
## プロジェクト構成(概要)
src/
├── api/                    # 自動生成 API クライアント
│   ├── mocks/              # MSW モック
│   └── generated/          # 自動生成ファイル
...

## 使用ライブラリ(概要)
### 基盤

#### Nuxt 3
#### Vue 3(Composition API + <script setup>)
#### TypeScript

### UI
#### UI Framework(Vuetify 等)

### フォーム
#### VeeValidate
...

## 🚩 1. 全てのコード生成で必ず守る基本ルール

### ✔ 1-1. フルファイル出力(diff 禁止)

- Copilot は **常にファイル全体を出力** すること。
- 差分(diff)や "ここだけ修正" のような部分出力は禁止。
- Vue ファイルなら `<template> <script> <style>` をすべて含めること。
- TS ファイルは import を含む完全出力。

etc...

## 禁止事項
### 自動生成 → 手動編集禁止

## そのほかの主なライブラリ
...

## 🧩 プロジェクトの特徴的パターン
### ✔ composable 中心のロジック設計
例:useXxxForm

### ✔ 型
#### 🔹 VeeValidate + Zod

- **フォームバリデーション** の標準構成
- `useForm` でフォームインスタンス作成
- `defineField` でフィールド定義(タプル形式: `[value, attr]`- `useFieldArray` で配列フィールド管理
- Zod スキーマは **既存のスキーマを優先利用**

**実装パターン(wrapper + section パターン):**

typescript
// composable: useXxxForm.ts
import { useForm } from 'vee-validate';
import { toTypedSchema } from '@vee-validate/zod';
import { XxxSchema } from '../../schemas/xxx.schema';

export type XxxValues = {
  fieldName: string;
};

export function useXxxForm() {
  const form = useForm({
    validationSchema: toTypedSchema(XxxSchema),
    initialValues: { fieldName: '' } as XxxValues,
  });

  const fieldName = form.defineField('fieldName');
...

## 🎯 7. 実装時のチェックリスト

- [ ] Composition API を使用しているか
- [ ] `<script setup>` 構文を使用しているか
- [ ] TypeScript で型定義しているか
- [ ] 自動生成ファイルを手動編集していないか
- [ ] VeeValidate + Zod パターンに従っているか
- [ ] TanStack Query の基本形に従っているか
- [ ] BEM 命名規則に従っているか
...

かなりぼかして転記しましたが、使用されているライブラリの説明からコンポーザブルの作成方法までしっかりと明記してくれました。

#### 🔹 VeeValidate + Zod

- **フォームバリデーション** の標準構成
- `useForm` でフォームインスタンス作成
- `defineField` でフィールド定義(タプル形式: `[value, attr]`- `useFieldArray` で配列フィールド管理
- Zod スキーマは **既存のスキーマを優先利用**

**実装パターン(wrapper + section パターン):**

typescript
// composable: useXxxForm.ts
import { useForm } from 'vee-validate';
import { toTypedSchema } from '@vee-validate/zod';
import { XxxSchema } from '../../schemas/xxx.schema';

export type XxxValues = {
  fieldName: string;
};

export function useXxxForm() {
  const form = useForm({
    validationSchema: toTypedSchema(XxxSchema),
    initialValues: { fieldName: '' } as XxxValues,
  });

  const fieldName = form.defineField('fieldName');
...

実装パターンは実際に作成しているファイルに沿ってテンプレートを作成してくれており、チェックリストは過去に自分が禁止事項としたことや、命名規則などに沿って作成されています。

こちらを設定した上で、呼び出したいAPI名と作成後のファイル名を指定した結果、テンプレートに沿った形で、レスポンスの型やMSWのモックの生成を行ってくれました!

ここで満足がいかない場合は、Tips2の二重レビューを加えてチューニングを行い、サイクルを回すことで完成度を高めていくイメージとなります。(今回はうまくいったので、割愛させていただきます…)

ドキュメント類の充実度やプロンプトの実行を幾度と行なった環境で試したということもあるのでしょうが、これからチューニングを行うというファイルにしてはかなり完成度が高く感じました!

最後に

今回は、実業務で二ヶ月使用した軽いTipsや土台作りに関する内容をまとめてみました。
実業務で使用したということもあり、全文を載せることができなかった部分があるのですが、ずぼらに結果を得られるという点で共有したいと思い記事にさせていただきました。

プロンプトの生成を任せる、チューニングの方針もAIに任せる…といったふうに自動である程度のレベルが作ることができれば、実装は十分楽になったと実感できました。

これからもAIを活かした開発効率化を探求していければと思います!

株式会社ソニックムーブ

Discussion