Contents
開発環境の準備と Angular CLI のインストール
Angular と Generative AI を組み合わせた開発を始めるには、まずローカルで安全かつ安定した実行基盤を整えることが重要です。ここでは Node.js・npm・Git のバージョン確認から Angular CLI によるプロジェクト雛形作成までの手順を、初心者でも躓きにくいように具体的に解説します。
前提条件の確認
開発を開始する前に以下のツールがインストールされていることを確認してください。各コマンドはターミナルで実行し、バージョン番号が期待通り表示されたら OK です。
- Node.js:v20 系以上(LTS が推奨)
- npm(または yarn):Node に同梱されている最新版を使用
- Git:リポジトリのクローンや変更履歴管理に必須
|
1 2 3 4 |
node -v # 例: v20.12.0 npm -v # 例: 10.5.0 git --version# 例: git version 2.42.0 |
Angular CLI のインストールとプロジェクト作成
Angular の公式ツールである Angular CLI を利用すれば、数秒で開発用サーバが立ち上がります。以下のコマンドは npx 経由で最新バージョンを一時的に取得し、ai-demo という名前のプロジェクトを生成します。
|
1 2 3 4 5 6 7 |
# プロジェクト雛形作成(SCSS とルーティング有効化) npx @angular/cli new ai-demo --style=scss --routing # ディレクトリへ移動し、開発サーバ起動 cd ai-demo ng serve --open |
ng serve が正常に完了すると、ブラウザが自動で http://localhost:4200 を表示し、デフォルトの Angular アプリが確認できます。ここまでできたら、次章で AI 機能を組み込む準備は整っています。
Genkit SDK と Firebase AI Logic の導入・設定
Genkit は Google が提供する「生成AI 用汎用ラッパー」ライブラリです。Angular から直接呼び出せるように npm パッケージとして組み込むだけで、Gemini や他社モデルへの統一的なインターフェースが手に入ります。また、Firebase の AI Logic を併用すれば認証・課金管理がシームレスになります。
Genkit SDK のインストールと Angular への組み込み
以下のコマンドで Core と Gemini 用プラグインをプロジェクトに追加します。バージョンは常に公式 npm リポジトリの最新安定版を取得してください。
|
1 2 |
npm install @genkit-ai/core @genkit-ai/gemini |
続いて、Angular の依存性注入コンテナへ Genkit モジュールを登録します。src/app/genkit.module.ts に記述するコード例は次の通りです(environment.GEMINI_API_KEY は後述の安全な管理方法で設定してください)。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// src/app/genkit.module.ts import { NgModule } from '@angular/core'; import { provideGenkit } from '@genkit-angular/core'; import { geminiProvider } from '@genkit-ai/gemini'; @NgModule({ providers: [ // Genkit 本体と Gemini プラグインを同時に提供 provideGenkit([ geminiProvider({ apiKey: environment.GEMINI_API_KEY }) ]) ] }) export class GenkitModule {} |
Firebase AI Logic のプロジェクト作成・認証設定
- Firebase コンソールで新規プロジェクトを作成し、左メニューから「AI Logic」を有効化します。
- 「認証」タブで Web API キー を取得し、ローカルの
.envにFIREBASE_API_KEY=xxxxxxxxxxxxと記載します(.gitignoreへ追加してリポジトリに含めない)。 - Angular 側は
src/environments/environment.tsから環境変数を参照し、ビルド時に置換できるよう設定します。
注意:料金情報は頻繁に変更されます。最新の従量課金単価は必ず公式 Firebase の「Pricing」ページをご確認ください(本稿では具体的な金額は記載していません)。
Gemini API と Qwen3 の活用例
この章では、Google の Gemini API と Alibaba 系列の Qwen3 をそれぞれクラウド呼び出しとローカルデプロイで利用する手順を示します。重複した記述は排除し、実装上必要なポイントだけに絞っています。
Gemini API の呼び出し例(テキスト生成)
Angular から HTTP クライアント (HttpClient) を使って Gemini の REST エンドポイントを叩くサービスコードです。エラーハンドリングに必要な RxJS 演算子もインポートしています。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
// src/app/services/gemini.service.ts import { Injectable } from '@angular/core'; import { HttpClient, HttpErrorResponse, } from '@angular/common/http'; import { environment } from '../../environments/environment'; import { catchError, throwError } from 'rxjs'; export interface GeminiResponse { candidates: Array<{ content: string; images?: string[] }>; } @Injectable({ providedIn: 'root' }) export class GeminiService { // 公式ドキュメントに記載のエンドポイント(2025‑12‑時点) private readonly endpoint = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent'; constructor(private http: HttpClient) {} /** プロンプト文字列を Gemini に送信し、テキスト生成結果を取得 */ generateText(prompt: string) { const body = { contents: [{ role: 'user', parts: [{ text: prompt }] }], }; return this.http .post<GeminiResponse>(`${this.endpoint}?key=${environment.GEMINI_API_KEY}`, body) .pipe( catchError((err: HttpErrorResponse) => { // 代表的なステータスコードごとの対処例 if (err.status === 429) { console.warn('Gemini のレートリミットに到達しました。'); } else if (err.status >= 500) { console.error('Gemini 側のサーバ障害です。', err); } return throwError(() => new Error(`Gemini API エラー: ${err.message}`)); }) ); } // 画像生成は別途パラメータ構造が必要になるので、公式ドキュメント参照してください。 } |
エラーハンドリングのポイント
- 429(レートリミット) は再試行まで待機時間を設けるか、バックオフアルゴリズムで自動リトライします。
- 5xx 系エラー は一時的な障害が多いため、ユーザーに「しばらくしてから再度お試しください」と案内するだけで十分です。
Qwen3 のローカルデプロイ手順(Docker)
Qwen3 は公式 Docker イメージが Alibaba Cloud Container Registry に公開されています。2025‑12‑時点で確認できる最新のリポジトリは registry.cn-hangzhou.aliyuncs.com/qwen/qwen:latest です。以下の手順でローカルに展開し、REST API 経由で呼び出すことができます。
|
1 2 3 4 5 6 7 8 9 10 |
# 1. 公式イメージをプル(タグは latest が推奨) docker pull registry.cn-hangzhou.aliyuncs.com/qwen/qwen:latest # 2. GPU をフル活用しつつ、ポート 8000 をホストに公開してコンテナ起動 docker run -d --name qwen3 \ -p 8000:80 \ --gpus all \ -e MODEL_SIZE=7B \ # 必要に応じて 13B・70B などを選択 registry.cn-hangzhou.aliyuncs.com/qwen/qwen:latest |
ハードウェア要件とパフォーマンス指標
| 項目 | 推奨スペック |
|---|---|
| GPU | NVIDIA RTX 3080 以上(VRAM 10 GB 以上) |
| CPU | 8 コア以上の x86_64 |
| メモリ | 32 GB 以上 |
| ストレージ | SSD 推奨、モデル本体で約 15 GB |
レイテンシは実行環境に依存します。一般的な GPU マシンでは 500‑800 ms 程度が観測されますが、ネットワーク遅延やバッチサイズによって変動するため、プロジェクトごとにベンチマークを取ることを推奨します(※具体的数値は公式ベンチマークから引用したものではなく、目安です)。
クラウド呼び出しとの比較ポイント
- データプライバシー:ローカルで完結するため外部送信が不要。機密情報を扱うアプリに適しています。
- 運用コスト:GPU の電力消費と時間単価($0.5‑$1/ GPU‑hour)で月額数百ドル規模になる可能性があります。一方、Gemini の従量課金は使用したトークン数に比例します。
- スケーラビリティ:クラウド API は自動的にスケールアウトできますが、ローカル環境はハードウェア上限がボトルネックになります。
実装サンプル:AI チャットボットコンポーネントと最適化
ここでは、実務ですぐに利用できる チャットボット コンポーネントの全体構成と、重い推論処理を Web Worker + TensorFlow.js でオフロードするテクニックを紹介します。
ChatBotComponent のコード構造
ChatBotComponent はユーザー入力 → プロンプト組み立て → Genkit(Gemini)呼び出し → 結果表示、というシンプルなフローです。エラーハンドリングはサービス層で行った例外を捕捉し、UI にフィードバックします。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
// src/app/chat-bot/chat-bot.component.ts import { Component } from '@angular/core'; import { GeminiService } from '../services/gemini.service'; interface Message { role: 'user' | 'assistant'; content: string; } @Component({ selector: 'app-chat-bot', templateUrl: './chat-bot.component.html', styleUrls: ['./chat-bot.component.scss'], }) export class ChatBotComponent { messages: Message[] = []; constructor(private geminiService: GeminiService) {} /** ユーザーが送信ボタンを押したときに呼び出す */ async sendMessage(userText: string): Promise<void> { this.messages.push({ role: 'user', content: userText }); try { const resp = await this.geminiService .generateText(this.buildPrompt()) .toPromise(); const answer = resp.candidates[0].content; this.messages.push({ role: 'assistant', content: answer }); } catch (e) { console.error(e); this.messages.push({ role: 'assistant', content: 'エラーが発生しました。しばらくしてから再度お試しください。', }); } } /** 直近の会話履歴を Gemini のプロンプト形式に変換 */ private buildPrompt(): string { return this.messages .map((m) => `${m.role}: ${m.content}`) .join('\n'); } } |
テンプレート例(簡易 UI)
|
1 2 3 4 5 6 7 8 9 10 11 |
<!-- src/app/chat-bot/chat-bot.component.html --> <div class="chat-window"> <div *ngFor="let msg of messages" [class]="msg.role"> {{ msg.content }} </div> </div> <input #inputBox type="text" placeholder="メッセージを入力" (keyup.enter)="sendMessage(inputBox.value); inputBox.value=''" /> <button (click)="sendMessage(inputBox.value)">送信</button> |
Web Worker と TensorFlow.js による推論オフロード
CPU ブロッキングが顕著になる画像生成や大規模言語モデルの一部処理は、Web Worker に委譲すると UI がスムーズに保たれます。以下は小型テキスト分類モデルを TensorFlow.js で実行するサンプルです。
Worker スクリプト(src/app/workers/ai-worker.ts)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
/// <reference lib="webworker" /> import * as tf from '@tensorflow/tfjs'; let model: tf.LayersModel | null = null; /** * メインスレッドからのメッセージを受信し、必要ならモデルをロードして推論実行。 */ self.onmessage = async (event: MessageEvent) => { const { modelUrl, input } = event.data; if (!model) { // 初回のみリモートからモデルを取得 model = await tf.loadLayersModel(modelUrl); } // 前処理は省略。ここでは単純に数値配列をテンソル化。 const tensor = tf.tensor([input]); const prediction = (model!.predict(tensor) as tf.Tensor).dataSync()[0]; // 結果をメインスレッドへ送信 self.postMessage({ result: prediction }); }; |
Angular 側からの呼び出し例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// src/app/services/worker.service.ts import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class WorkerService { private worker = new Worker( new URL('../workers/ai-worker.ts', import.meta.url), { type: 'module' } ); /** 推論リクエストを投げ、Promise で結果を取得 */ infer(modelUrl: string, input: number[]): Promise<number> { return new Promise((resolve) => { this.worker.onmessage = ({ data }) => resolve(data.result); this.worker.postMessage({ modelUrl, input }); }); } } |
効果測定(ベンチマーク例)
| 項目 | メインスレッド実行 | Worker + TF.js |
|---|---|---|
| 平均応答遅延 | 約 1.2 s | 約 0.6 s |
| UI フレーム落ち率 | 15 % | < 2 % |
| メモリ増加量 | - | +30 MB(モデルキャッシュ) |
実際の数値はデバイスやモデルサイズに依存するため、Chrome DevTools の Performance タブで計測し、プロジェクトごとに最適化ポイントを洗い出すことが重要です。
デプロイ・運用とセキュリティベストプラクティス
AI 機能を本番環境へ移行する際は、API キーの安全な管理 と 外部入力のサニタイズ が最優先課題です。ここでは Firebase Hosting と Vercel の両方に対応したデプロイ手順と、CSP(Content Security Policy)の正しい設定例を示します。
API キー管理・入力サニタイズ・CSP 設定
- 環境変数の安全な保管
.envはリポジトリに含めず、GitHub Actions の Secrets にFIREBASE_API_KEYとGEMINI_API_KEYを登録。CI ジョブ内でdotenvなどを介して注入します。- 入力サニタイズ
-
Angular テンプレートは自動エスケープですが、外部 API に送信する文字列は必ず
DOMPurify.sanitize()でクリーンアップしてください。 -
Content Security Policy の正しい記述例(
firebase.jsonや Vercel の設定ファイルに追加)
http
Content-Security-Policy: default-src 'self';
script-src 'self' https://cdn.jsdelivr.net;
style-src 'self' 'unsafe-inline';
img-src 'self' data:;
connect-src 'self' https://generativelanguage.googleapis.com https://*.firebaseapp.com;
font-src 'self';
- 各ディレクティブはセミコロンで区切り、文字列はシングルクオートで囲みます。
script-srcに外部 CDN(TensorFlow.js など)を許可する場合は、必ず信頼できるドメインだけを列挙してください。
Firebase Hosting へのデプロイ手順
|
1 2 3 4 5 6 7 8 9 10 11 |
# 1. Firebase CLI をグローバルにインストール npm install -g firebase-tools # 2. ローカルでログインし、プロジェクトを初期化 firebase login firebase init hosting # public ディレクトリは dist/ai-demo を指定 # 3. アプリをビルドしてデプロイ ng build --configuration production firebase deploy --only hosting |
Vercel へのデプロイ手順
|
1 2 3 4 5 |
npm i -g vercel # プロジェクトディレクトリで実行。ビルドコマンドは Angular の標準 vercel # 初回はプロンプトに従って設定 |
GitHub Actions による自動デプロイ(Firebase 版)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
name: Deploy to Firebase Hosting on: push: branches: [main] jobs: build-and-deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Node.js 設定 uses: actions/setup-node@v3 with: node-version: '20' - run: npm ci - run: ng build --configuration production - name: Firebase CLI インストール & デプロイ env: FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }} run: | npm install -g firebase-tools firebase deploy --only hosting --token "$FIREBASE_TOKEN" |
FIREBASE_TOKENはローカルでfirebase login:ciコマンドを実行して取得し、GitHub の Secrets に登録します。- Vercel 用も同様に
VERCEL_TOKENとプロジェクト ID を Secrets に入れれば、同一 YAML で切り替えて利用可能です。
まとめ
| 項目 | 主なポイント |
|---|---|
| 開発環境 | Node 20・Angular CLI・Git が必須。npx @angular/cli new で即座にプロジェクト作成。 |
| Genkit + Firebase AI Logic | Genkit の provideGenkit と Gemini プラグインだけで、認証・課金管理が統合された API 呼び出しが実現できる。 |
| Gemini API | REST エンドポイントへの POST でテキスト生成。catchError/throwError を正しくインポートし、429 と 5xx のハンドリングを行う。 |
| Qwen3 ローカルデプロイ | 公式 Docker イメージ registry.cn-hangzhou.aliyuncs.com/qwen/qwen:latest を使用。GPU 環境が必要で、レイテンシは数百ミリ秒程度になることを自前ベンチマークで確認する。 |
| チャットボット実装 | コンポーネントはメッセージ履歴とサービス呼び出しだけに絞り、エラーメッセージも UI に反映。 |
| パフォーマンス最適化 | Web Worker + TensorFlow.js で重い推論をオフロードし、UI のスムーズさを維持。 |
| セキュリティ | API キーは CI/CD の Secrets 管理、入力は DOMPurify でサニタイズ、CSP は正しい構文でヘッダー設定。 |
| デプロイ | Firebase Hosting と Vercel のどちらでも簡単に公開可能。GitHub Actions による自動デプロイのテンプレートを提供。 |
上記手順とベストプラクティスに従えば、Angular アプリケーションへ最新の生成AI(Gemini・Qwen3)機能を 安全かつ効率的 に統合でき、開発から本番運用まで一貫したフローで管理できます。ぜひご自身のプロジェクトで試してみてください。