GEMINI LABEN
NANOLITE — Nano Banana 2 Liteが登場しました。Googleで最も速く、最もコスト効率の高いGemini Imageモデルで、軽量な画像生成を安く回したい用途に向いていますOMNIFLASH — Gemini Omni Flashがpublic previewになりました。ネイティブにマルチモーダルなモデルで、企業や開発者が独自の動的な動画ワークフローを構築できますAGENTS — Managed Agentsが拡張されました。background: trueでサーバー側の非同期実行とポーリング、リモートMCPサーバー連携、対話をまたぐ認証情報のリフレッシュに対応しますMEMORY — Memory BankのIngestEvents APIが一般提供になりました。イベントの取り込みとメモリ生成を分離し、コンテンツを継続的にストリームできますTHROUGHPUT — Provisioned Throughputで、同一モデル・同一リージョンに対して最大7件の保留オーダーを提出できるようになりましたDEPRECATE — 画像生成モデルは8月17日に、Gemini Enterprise Agent PlatformのGrok 4.1系は8月20日に停止される予定ですNANOLITE — Nano Banana 2 Liteが登場しました。Googleで最も速く、最もコスト効率の高いGemini Imageモデルで、軽量な画像生成を安く回したい用途に向いていますOMNIFLASH — Gemini Omni Flashがpublic previewになりました。ネイティブにマルチモーダルなモデルで、企業や開発者が独自の動的な動画ワークフローを構築できますAGENTS — Managed Agentsが拡張されました。background: trueでサーバー側の非同期実行とポーリング、リモートMCPサーバー連携、対話をまたぐ認証情報のリフレッシュに対応しますMEMORY — Memory BankのIngestEvents APIが一般提供になりました。イベントの取り込みとメモリ生成を分離し、コンテンツを継続的にストリームできますTHROUGHPUT — Provisioned Throughputで、同一モデル・同一リージョンに対して最大7件の保留オーダーを提出できるようになりましたDEPRECATE — 画像生成モデルは8月17日に、Gemini Enterprise Agent PlatformのGrok 4.1系は8月20日に停止される予定です
記事一覧/高度な活用
高度な活用/2026-05-06上級

Gemma 4 + Ollama + Android Studio — 本番プロジェクトで使えるローカルAI開発環境の構築ガイド

Android Studio×Gemma 4×Ollamaを本番品質で運用するための詳細ガイド。モデル選択戦略・タスク別スイッチング・ファインチューニング・チーム展開・CI/CD統合まで、実装コード付きで解説します。

Android Studio2Gemma 412Ollama8ローカルLLM10ファインチューニング4Android開発2CI/CD2

Ollamaとの接続設定が終わった時点では、「動いた!」という達成感があります。でも本番プロジェクトで実際に使い続けていくと、すぐにいくつかの壁が見えてきます。

「補完が遅い」「新しいAndroidのAPIを知らない」「チームメンバーの環境で同じ設定を再現するのが面倒」——こういった問題を乗り越えるには、もう少し踏み込んだ設定と設計が必要です。

ここでは私が実際のAndroid開発プロジェクトでGemma 4ローカル環境を本番運用するにあたって構築したアーキテクチャをお伝えします。

モデル選択の戦略:用途別スイッチング

最初の大きな判断は「どのGemmaモデルを使うか」です。答えは「一つに固定しない」です。

私が実践している方法は、タスクの種類によってモデルを自動的に切り替える構成です:

# .ollama-profiles(プロジェクトルートに置く)
COMPLETION_MODEL=gemma4:9b     # コード補完:速度優先
REVIEW_MODEL=gemma4:26b        # コードレビュー:品質優先
EXPLAIN_MODEL=gemma4:9b        # コード説明:中間
GENERATE_MODEL=gemma4:26b      # ゼロから生成:品質優先

Android Studioはこのプロファイルを直接読む機能はありませんが、カスタムOllamaプロキシを挟むことで実現できます。

Ollamaプロキシの実装

# ollama_router.py — タスク種別に応じてモデルを振り分けるプロキシ
from fastapi import FastAPI, Request
from fastapi.responses import StreamingResponse
import httpx
import json
 
app = FastAPI()
 
# タスク種別とモデルのマッピング
MODEL_ROUTING = {
    "completion": "gemma4:9b",   # 速度優先
    "review": "gemma4:26b",       # 品質優先
    "generate": "gemma4:26b",     # ゼロから生成
    "default": "gemma4:9b",
}
 
def detect_task_type(prompt: str) -> str:
    """プロンプトの内容からタスク種別を判定"""
    prompt_lower = prompt.lower()
    if any(word in prompt_lower for word in ["review", "レビュー", "問題", "bug", "error"]):
        return "review"
    if any(word in prompt_lower for word in ["generate", "作成", "create", "write", "実装"]):
        return "generate"
    return "default"
 
@app.post("/api/generate")
async def route_generation(request: Request):
    body = await request.json()
    prompt = body.get("prompt", "")
    task_type = detect_task_type(prompt)
    target_model = MODEL_ROUTING.get(task_type, MODEL_ROUTING["default"])
    
    # 実際のOllamaに転送(モデルを置き換えて)
    body["model"] = target_model
    
    async with httpx.AsyncClient(timeout=120.0) as client:
        async with client.stream(
            "POST",
            "http://localhost:11434/api/generate",
            json=body
        ) as response:
            return StreamingResponse(
                response.aiter_bytes(),
                media_type="application/x-ndjson"
            )
 
# プロキシを起動
# uvicorn ollama_router:app --host 0.0.0.0 --port 11435

Android Studioのエンドポイントを http://localhost:11434 から http://localhost:11435(プロキシ)に変更すると、タスクに応じたモデルルーティングが自動的に機能します。

Gemma 4のファインチューニング:プロジェクト固有パターンの学習

Ollamaで動くGemma 4はベースモデルです。プロジェクト固有のパターン(独自のアーキテクチャ規約、社内ライブラリの使い方、チームのコーディングスタイル)を学習させると、補完の精度が大きく向上します。

トレーニングデータの準備

既存のコードベースから訓練データを作ります。「入力(不完全なコード)→出力(完成形)」のペアを用意します。

# prepare_training_data.py
import json
import os
from pathlib import Path
 
def extract_kotlin_pairs(repo_path: str) -> list[dict]:
    """Kotlinファイルから訓練データを抽出"""
    pairs = []
    repo = Path(repo_path)
    
    for kotlin_file in repo.rglob("*.kt"):
        content = kotlin_file.read_text(encoding="utf-8")
        
        # クラス定義のパターンを抽出
        # 実際には正規表現でメソッドシグネチャ+実装を分離する
        pairs.append({
            "instruction": f"以下のシグネチャのKotlinメソッドを実装してください:\n{extract_signature(content)}",
            "output": extract_implementation(content),
            "source": str(kotlin_file.relative_to(repo))
        })
    
    return pairs
 
def create_training_jsonl(output_path: str, pairs: list[dict]):
    """Ollama/HuggingFace形式のJSONLファイルを生成"""
    with open(output_path, "w", encoding="utf-8") as f:
        for pair in pairs:
            training_example = {
                "prompt": pair["instruction"],
                "completion": pair["output"]
            }
            f.write(json.dumps(training_example, ensure_ascii=False) + "\n")
    
    print(f"訓練データ {len(pairs)} 件を {output_path} に保存しました")
 
# 実行
pairs = extract_kotlin_pairs("/path/to/your/android/project")
create_training_jsonl("training_data.jsonl", pairs)

LoRAによる軽量ファインチューニング

フルモデルのファインチューニングは計算コストが高いため、LoRA(Low-Rank Adaptation)を使います。

# ファインチューニング環境の準備
pip install transformers peft trl bitsandbytes
 
# fine_tune_gemma.py の実行
python fine_tune_gemma.py \
    --base_model "google/gemma-4-9b" \
    --training_data "training_data.jsonl" \
    --output_dir "./gemma4-android-finetuned" \
    --lora_r 16 \
    --lora_alpha 32 \
    --num_epochs 3 \
    --batch_size 4
# fine_tune_gemma.py
from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments
from peft import LoraConfig, get_peft_model
from trl import SFTTrainer
import torch
 
def fine_tune_gemma(base_model: str, training_data: str, output_dir: str, **kwargs):
    # モデルとトークナイザーのロード
    tokenizer = AutoTokenizer.from_pretrained(base_model)
    model = AutoModelForCausalLM.from_pretrained(
        base_model,
        torch_dtype=torch.bfloat16,
        device_map="auto",
        load_in_4bit=True  # 4bit量子化でVRAMを節約
    )
    
    # LoRA設定
    lora_config = LoraConfig(
        r=kwargs.get("lora_r", 16),
        lora_alpha=kwargs.get("lora_alpha", 32),
        target_modules=["q_proj", "v_proj"],
        lora_dropout=0.05,
        bias="none",
        task_type="CAUSAL_LM"
    )
    
    model = get_peft_model(model, lora_config)
    model.print_trainable_parameters()
    
    # 訓練設定
    training_args = TrainingArguments(
        output_dir=output_dir,
        num_train_epochs=kwargs.get("num_epochs", 3),
        per_device_train_batch_size=kwargs.get("batch_size", 4),
        warmup_steps=100,
        learning_rate=2e-4,
        fp16=True,
        save_strategy="epoch",
        logging_steps=50,
    )
    
    trainer = SFTTrainer(
        model=model,
        args=training_args,
        train_dataset=load_dataset("json", data_files=training_data)["train"],
        tokenizer=tokenizer,
        max_seq_length=2048,
    )
    
    trainer.train()
    trainer.save_model(output_dir)
    print(f"✅ ファインチューニング完了: {output_dir}")

ファインチューニング後、OllamaでカスタムModelfileを作成して登録します:

# Modelfile(ファインチューニング済みモデル用)
FROM ./gemma4-android-finetuned

SYSTEM """
あなたはAndroid/Kotlinの専門家AIアシスタントです。
このプロジェクトでは以下の規約を守ってください:
- ViewModelにはAndroid ViewModelを使用する
- Repository層を必ず経由してデータアクセスする
- Kotlinコルーチンを使用する(RxJavaは使わない)
- DIにはHiltを使用する
"""

PARAMETER temperature 0.3
PARAMETER top_p 0.9
ollama create gemma4-android-project -f Modelfile

チーム展開:Docker Composeによる環境再現

個人環境で動いても、チーム全員が同じ設定を再現できなければ意味がありません。Docker Composeを使って、Ollama環境をコード化します。

# docker-compose.yml
version: "3.8"
services:
  ollama:
    image: ollama/ollama:latest
    ports:
      - "11434:11434"
    volumes:
      - ollama_models:/root/.ollama
      - ./models:/models  # カスタムModelfileの場所
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]
    restart: unless-stopped
 
  ollama-router:
    build: ./ollama-router
    ports:
      - "11435:11435"
    environment:
      - OLLAMA_URL=http://ollama:11434
    depends_on:
      - ollama
    restart: unless-stopped
 
  model-initializer:
    image: ollama/ollama:latest
    volumes:
      - ollama_models:/root/.ollama
      - ./scripts:/scripts
    entrypoint: ["/scripts/init-models.sh"]
    depends_on:
      - ollama
 
volumes:
  ollama_models:
# scripts/init-models.sh
#!/bin/bash
# 必要なモデルを自動ダウンロード
ollama pull gemma4:9b
ollama pull gemma4:26b
 
# カスタムモデルの登録
if [ -f /models/Modelfile.android ]; then
  ollama create gemma4-android-project -f /models/Modelfile.android
fi
 
echo "✅ モデルの初期化完了"

新しいチームメンバーのオンボーディング手順はシンプルになります:

git clone <project-repo>
docker compose up -d
# → Ollamaが自動起動し、必要なモデルが自動ダウンロードされる
# Android Studioのエンドポイントを http://localhost:11435 に設定するだけ

CI/CDパイプラインでのローカルLLM活用

コードレビューをCI/CDに組み込むことで、Pull Request時に自動的にAIレビューを実行できます。

# .github/workflows/ai-review.yml
name: AI Code Review
 
on:
  pull_request:
    paths:
      - 'app/src/**/*.kt'
 
jobs:
  ai-review:
    runs-on: self-hosted  # ローカルLLMを持つセルフホステッドランナー
    steps:
      - uses: actions/checkout@v4
 
      - name: Start Ollama
        run: docker compose up -d ollama
        
      - name: Wait for Ollama ready
        run: |
          until curl -sf http://localhost:11434/api/version; do
            sleep 2
          done
 
      - name: Run AI code review
        run: |
          # 変更されたKotlinファイルを取得
          CHANGED_FILES=$(git diff --name-only origin/main -- '*.kt')
          
          for file in $CHANGED_FILES; do
            echo "## Reviewing $file" >> review_results.md
            python scripts/ai_review.py "$file" >> review_results.md
            echo "" >> review_results.md
          done
 
      - name: Post review as PR comment
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const review = fs.readFileSync('review_results.md', 'utf8');
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: `## 🤖 AI Code Review (Gemma 4 ローカル)\n\n${review}`
            });
# scripts/ai_review.py
import sys
import httpx
import json
 
def review_kotlin_file(file_path: str) -> str:
    with open(file_path) as f:
        code = f.read()
    
    prompt = f"""以下のKotlinコードをAndroid開発のベストプラクティスの観点からレビューしてください:
    
1. アーキテクチャの問題点
2. パフォーマンスの懸念事項  
3. テスタビリティ
4. メモリリークの可能性
 
コード:
```kotlin
{code}

具体的な改善提案を3点以内で日本語で簡潔に述べてください。"""

response = httpx.post(
    "http://localhost:11434/api/generate",
    json={
        "model": "gemma4:26b",
        "prompt": prompt,
        "stream": False
    },
    timeout=120.0
)

return response.json()["response"]

if name == "main": result = review_kotlin_file(sys.argv[1]) print(result)


## 実運用で学んだこと

半年ほどこの構成で開発してみて、予想外に良かったのは「AIの提案が"社内文化"を反映するようになる」という点です。クラウドのGemini APIは汎用的な提案をしますが、ファインチューニングしたモデルは「このプロジェクトではこう書くべき」という提案をしてきます。

一方で、継続的な更新が課題です。AndroidのAPIやJetpack Composeは進化が速く、ファインチューニングモデルの知識は作った時点で止まります。重要なAPIアップデート後には再訓練を検討する必要があります。

クラウドAPIとローカルLLMを用途で使い分けるハイブリッド構成(機密コードはローカル、新APIの調査はクラウド)が現実的なバランスだと感じています。

## 個人開発12年の視点で見る Gemini 運用

### 運用時に毎月見ているメトリクス

- API 呼び出し成功率と平均レイテンシ
- 1リクエストあたりの平均トークン消費
- AdMob 売上との比較で見た ROI
シェア

お読みいただきありがとうございます

Gemini Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

開発ツール2026-05-06
Android StudioのローカルLLM機能でGemma 4を動かす — Ollamaとの連携設定から実際の開発体験まで
Android StudioのローカルLLM機能とOllamaを使ってGemma 4を開発環境に組み込む方法を解説。MacOS環境での設定手順、26Bモデルの実用性、実際の開発体験を詳しく紹介します。
高度な活用2026-05-05
Gemma 4 × OpenCode本格活用ガイド:ローカルLLMで実用的なAI開発環境を作る
Gemma 4とOpenCodeを組み合わせたローカルAI開発環境を実務レベルで使いこなすための詳細ガイド。モデル選定・コンテキスト管理・プロンプト設計・ハイブリッド活用まで徹底解説します。
高度な活用2026-04-28
Gemma 4のFunction Callingでローカルエージェントを構築する
Gemma 4の専用Function Callingトークンを活用して、プライベートなローカルエージェントを実装する方法を解説します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →