OllamaでGemma 4を独自評価——日本語・多言語コード・Claude Code代替の実力と限界
M4 Pro MacでOllama経由のGemma 4(8B Q4_K_M)を実際に動かし、日本語応答・Python/TypeScript/Rust/SQLのコード生成・英日プロンプトの精度差・バグ修正能力を独自評価した。Claude Sonnetとの格差も率直に比較する。
Google DeepMind がリリースした Gemma 4 の仕様については広く報じられているが、「実際に動かしてどうなのか」というハンズオン評価は意外と少ない。本記事では M4 Pro(統合メモリ 48GB)の Mac 上で Ollama を用いて Gemma 4 をローカル実行し、日本語応答・多言語コード生成・英日プロンプトの精度差・バグ修正能力を独自に計測した。強みと限界をなるべく正直に書く。
動作環境とモデル構成
- ハードウェア: Apple M4 Pro / 統合メモリ 48GB
- Ollama: v0.20.2
- モデル:
gemma4:latest(8.0B パラメータ / Q4_K_M 量子化 / 9.6GB) - コンテキスト長: 131,072 トークン
- Capabilities: completion, vision, audio, tools, thinking
Ollama で利用可能な gemma4:latest は、Gemma 4 ファミリーの「E4B」相当(Per-Layer Embeddings アーキテクチャ採用の Edge モデル)だ。有効パラメータは 4.5B だが埋め込みを含めると 8B 相当の表現力を持ち、Q4_K_M 量子化で 9.6GB とコンシューマー環境に収まる。
モデルの起動は以下の1行で完結する。
ollama run gemma4:latest "こんにちは"
Capability に thinking が含まれている点が目を引く。プロンプトを受け取ると、回答の前に推論ステップ(Thinking プロセス)を出力してから最終回答を生成する。本記事の評価はすべてデフォルト設定(thinking 有効)で実施した。
日本語能力:挨拶と俳句で確認
まず基本的な日本語で自己紹介を依頼した。
プロンプト: 「こんにちは。あなたは誰ですか?日本語で簡単に自己紹介してください。」
出力:
こんにちは!
私はGemma 4(ジェマ・フォー)という名前の、大規模言語モデル(LLM)です。
Google DeepMindによって開発されました。
私は、以下のような様々なお手伝いができます。
* 質問への回答
* 文章の作成やアイデア出し
* 翻訳
* 会話の相手
何か知りたいことや、手伝ってほしいことがありましたら、お気軽にお知らせください。どうぞよろしくお願いします!
名前・開発元・機能、と整然と回答した。日本語の自然さに問題はない。
次に俳句を依頼した。テーマは「人工知能」。
プロンプト: 「俳句を一首詠んでください。テーマは「人工知能」です。日本語で答えてください。」
出力:
人の夢
映し出す光の
知の鏡
(ひとのゆめ/うつしだすひかりの/ちのかがみ)
【解説】
人間の思考や感情(夢)をデータとして取り込み、それらを光(情報)となって映し
出す、知能の鏡(人工知能)のような世界観を詠んでみました。
詩的な表現は面白いが、この俳句には2つの問題がある。
まず音数だ。2句目「映し出す光の」は「う・つ・し・だ・す・ひ・か・り・の」で9音節あり、5-7-5 ではなく5-9-5 の字余りになっている。Thinking プロセスを確認すると、「う-つ-し-だ-す-ひ-か-り-の = 7」と自己評価しているが、カウントが間違っている。推論してから答えを出す設計でも、このような単純なカウントミスが発生する。
次に季語がない。俳句の基本要件である季語(自然や季節を示す言葉)が含まれておらず、厳密には「俳句」ではなく「自由律俳句」または単なる三行詩だ。
日本語の生成は流暢だが、俳句のような形式的なルールに厳密に従う精度はない。
コード生成力:Python・TypeScript・Rust・SQL
4 言語のコード生成を実行した。
Python:メモ化フィボナッチ
プロンプト: “Write a Python function that computes the nth Fibonacci number using memoization (functools.lru_cache). Include type hints and a brief docstring.”
出力:
import functools
from typing import Dict
@functools.lru_cache(maxsize=None)
def fibonacci(n: int) -> int:
"""
Computes the nth Fibonacci number using memoization.
The Fibonacci sequence starts with F(0) = 0 and F(1) = 1.
F(n) = F(n-1) + F(n-2) for n > 1.
Args:
n: The index of the Fibonacci number to compute (must be non-negative).
Returns:
The nth Fibonacci number.
Raises:
ValueError: If n is a negative integer.
Examples:
>>> fibonacci(0)
0
>>> fibonacci(1)
1
>>> fibonacci(6)
8
>>> fibonacci(10)
55
"""
if not isinstance(n, int):
raise TypeError("Input must be an integer.")
if n < 0:
raise ValueError("Fibonacci number is only defined for non-negative integers.")
if n == 0:
return 0
if n == 1:
return 1
return fibonacci(n - 1) + fibonacci(n - 2)
if __name__ == "__main__":
print("--- Fibonacci Sequence using lru_cache ---")
n1 = 6
result1 = fibonacci(n1)
print(f"F({n1}) = {result1}")
n2 = 35
result2 = fibonacci(n2)
print(f"F({n2}) = {result2}")
print(f"F(0) = {fibonacci(0)}")
print(f"F(1) = {fibonacci(1)}")
型ヒント・docstring・エラーハンドリング・使用例と、依頼していた要素はすべて揃っている。ただし2行目の from typing import Dict は使われていない不要なインポートで、静的解析ツールでは警告が出る。依頼した内容は満たしているが、完全にクリーンなコードとは言えない。
TypeScript:非同期 fetch 関数
プロンプト: “Write a TypeScript async function that fetches JSON data from a URL using the Fetch API. Include proper error handling, return type annotation, and a usage example.”
出力:
interface FetchError extends Error {
status?: number;
details?: string;
}
async function fetchData<T>(url: string): Promise<T> {
console.log(`Attempting to fetch data from: ${url}`);
try {
const response = await fetch(url);
if (!response.ok) {
const status = response.status;
const statusText = response.statusText || 'Unknown error';
throw new Error(`HTTP Error! Status: ${status} (${statusText})`);
}
const data: T = await response.json();
console.log('✅ Data fetched and parsed successfully.');
return data;
} catch (error) {
console.error('❌ An error occurred during the fetch process:',
error instanceof Error ? error.message : 'Unknown error');
if (error instanceof Error) {
throw new Error(`Failed to load data from ${url}. ${error.message}`);
}
throw new Error('Unknown fetch error.');
}
}
// 使用例
interface UserProfile {
id: number;
name: string;
email: string;
isActive: boolean;
}
async function runExample() {
const successUrl = 'https://jsonplaceholder.typicode.com/users/1';
try {
const userData = await fetchData<UserProfile>(successUrl);
console.log(`Received User Name: ${userData.name}`);
console.log(`User ID: ${userData.id}`);
} catch (e) {
console.error('Example 1 Failed unexpectedly:', e);
}
// 404エラーのハンドリング確認
const errorUrl = 'https://jsonplaceholder.typicode.com/non-existent-endpoint';
try {
const _: any = await fetchData<any>(errorUrl);
} catch (e) {
console.error('Successfully caught expected error:', (e as Error).message);
}
}
runExample();
ジェネリクス <T> を活用した型安全な実装で、HTTP エラー・ネットワークエラー・JSON パースエラーの3層エラーハンドリングも含む。宣言した FetchError インターフェースを実際には使っていない点は惜しいが、実用上の問題はない。
Rust:stdin 大文字変換 CLI
プロンプト: “Write a Rust program that reads lines from stdin and prints each line converted to uppercase. Keep it simple and idiomatic Rust.”
出力:
use std::io;
fn main() {
println!("--- Type your input (press Ctrl+D or Ctrl+Z when finished) ---");
let stdin = io::stdin();
for line_result in stdin.lock().lines() {
match line_result {
Ok(line) => {
println!("{}", line.to_uppercase());
}
Err(error) => {
eprintln!("\nError reading line: {}", error);
break;
}
}
}
}
一見イディオマティックに見えるが、このコードはコンパイルに失敗する。 stdin.lock().lines() の lines() メソッドは std::io::BufRead トレイトが提供するものだが、コード中に use std::io::BufRead; が含まれていないため、Rust コンパイラは「method lines not found」エラーを出す。
正しくは冒頭を以下のように修正する必要がある。
use std::io::{self, BufRead};
4 言語のうち Rust だけがコンパイルエラーを含む出力だった。シンタックスは正しく、修正箇所は1行だけだが、「そのままコピー&ペーストで動く」という用途には使えない。
SQL:TOP5 集計クエリ
プロンプト: “Write a SQL query that shows the top 5 customers by total order amount. Assume tables: customers(id, name, email) and orders(id, customer_id, amount, created_at). Include JOIN, GROUP BY, ORDER BY, and LIMIT.”
出力:
SELECT
c.name AS customer_name,
COUNT(o.id) AS total_orders,
SUM(o.amount) AS total_spent
FROM
customers c
JOIN
orders o ON c.id = o.customer_id
GROUP BY
c.id, c.name
ORDER BY
total_spent DESC
LIMIT 5;
4 言語の中で最もクリーンな出力だ。GROUP BY c.id, c.name(id を含めることで MySQL でも一意性を保証)という細かい選択も適切で、そのまま使える。
コード生成の総評
| 言語 | 評価 |
|---|---|
| Python | 実用品質。不要なインポートあり(軽微) |
| TypeScript | 実用品質。未使用インターフェースあり(軽微) |
| Rust | コンパイルエラーあり。修正は1行だが確認必須 |
| SQL | そのまま使える。4言語中で最も完成度が高い |
単純なタスクは十分だが、そのまま本番に使えるクリーンなコードを出力できるとは限らない。
英語 vs 日本語プロンプト:精度に差は出るか
同内容の質問(量子コンピュータの原理を3段落で技術的に解説)を英語と日本語で送り、精度・指示追従性を比較した。
英語プロンプト: “Explain the principles of quantum computing in 3 paragraphs. Focus on qubits, superposition, and entanglement. For a technical audience.”
英語プロンプトへの出力:
Quantum computation derives its power from manipulating quantum mechanical
phenomena, utilizing the fundamental unit of information known as the
qubit (quantum bit). Unlike the classical bit, which must exist
definitively in one of two states (0 or 1), a qubit is a two-level quantum
system, typically encoded using the spin of an electron or the
polarization of a photon. Mathematically, the state of a single qubit
|ψ⟩ is a linear combination of the basis states: |ψ⟩ = α|0⟩ + β|1⟩,
where |0⟩ and |1⟩ are the eigenstates of the computational basis, and α
and β are complex probability amplitudes. The physical implementation of
qubits is highly challenging, requiring environments that maintain quantum
coherence while allowing for controlled unitary transformations through
external fields (e.g., microwave pulses or lasers).
The most crucial principle enabling quantum speedup is superposition.
Superposition dictates that a qubit can simultaneously exist in a weighted
mixture of its basis states, |0⟩ and |1⟩. This property allows a system
of N qubits to represent a state vector in a computational Hilbert space
of dimension 2^N. Consequently, a quantum computer with N qubits can
encode and process 2^N possible input states simultaneously. This ability,
often termed quantum parallelism, allows an algorithm to evaluate an
exponential number of inputs in a single operational step. However,
extracting useful information from this massive superposition requires
precise measurement, which collapses the system state according to the
Born rule.
The third cornerstone of quantum computing is entanglement. Entanglement
describes a non-local correlation between two or more qubits such that the
state of the entire system cannot be described merely by the product of
the individual qubits' states. If qubits A and B are entangled, measuring
the state of A instantaneously constrains the state of B, regardless of
the physical distance separating them. This correlation is a resource that
vastly increases the computational power beyond what independent classical
bits can achieve. Algorithms like Shor's or Grover's leverage entanglement
and superposition together to construct highly sophisticated unitary
transformations, allowing them to solve certain problems, such as
factorization or database searching, with polynomial speedup relative to
classical counterparts.
日本語プロンプト: 「量子コンピュータの原理を3段落で説明してください。量子ビット、重ね合わせ、量子もつれに焦点を当ててください。エンジニア向けの技術的な説明でお願いします。」
日本語プロンプトへの出力:
量子コンピュータの計算原理は、古典ビット(0または1の状態のみを持つ)とは根本
的に異なる、量子力学の諸原理に基づいています。これらの原理を理解することが、
量子アルゴリズムの設計と実装の基盤となります。
### 1. 量子ビット(Qubit)と量子状態ベクトル
量子コンピュータの基本単位は量子ビット(qubit)です。古典ビットが2つの確定し
た離散状態{0, 1}しか取れないのに対し、qubitはこれらの状態の線形結合として
表現されます。qubitの状態は、ヒルベルト空間上のベクトルとして記述され、任意
の重ね合わせの状態 |ψ⟩として表されます:
|ψ⟩ = α|0⟩ + β|1⟩
ここで、α と β は確率振幅であり、規格化条件 |α|² + |β|² = 1 を満たします。
### 2. 重ね合わせ(Superposition)による並列計算
重ね合わせの原理により、qubitは複数の基底状態を同時に保有することが可能にな
ります。N個のqubitが存在する場合、古典的なシステムがNビットの状態を個別に扱
うのに対し、量子システムは2^N個の状態を同時に表現できます。この並列性は、ハ
ダマードゲート(Hadamard Gate)などの量子ゲートを適用することで導入されます。
しかし測定した瞬間に波動関数がコラプス(Measurement Collapse)し、単一の古
典的な結果に収束します。
### 3. 量子もつれ(Entanglement)による非局所相関
最も強力かつ量子力学的な要素が「量子もつれ」です。もつれとは、複数のqubitが
単一の量子状態として関連づけられる現象で、一方のqubitを測定した結果が他の
qubitの状態を瞬時に決定します。この非局所相関性が、量子テレポーテーションや
量子鍵配送(QKD)の基礎を成し、またショアのアルゴリズムやグローバーのアルゴ
リズムといった量子アルゴリズムの計算能力を飛躍的に向上させます。
比較すると明確な差が2点ある。
1. 指示追従性の違い
英語プロンプトは「3段落で」という指示に完全に従い、3つの段落のみを出力した。日本語プロンプトでは指示通り3段落に分けつつも、見出し(### 1. 量子ビットなど)を独自に追加している。「3段落」という制約を解釈するレベルが言語によって異なる。
2. 内容の精度はほぼ同等
技術的な正確さは両言語でほぼ変わらない。ディラック記法・ブロッホ球・ボルン則・ベル状態など、専門用語の扱いに大きな差は見られない。ただし日本語出力のほうが説明が多く、英語出力のほうがコンパクトにまとまっている傾向がある。
日本語プロンプトが劣っているわけではないが、フォーマット指示への準拠という点では英語プロンプトのほうが素直だ。
翻訳:日本語↔英語の精度
翻訳は Gemma 4 の実用候補として見逃しがちな用途だ。日→英・英→日の2方向を試した。
日本語ニュース記事 → 英語
入力:
量子コンピュータの商用化が加速している。IBMは2026年中に1万量子ビットを超えるシステムを提供する計画を明らかにし、Googleも誤り訂正技術の突破口を開いたと主張している。ただし専門家の間では、実用的な量子優位性の達成には依然として数年かかるとの見方が支配的だ。
出力(モデルが “Recommended” と分類した版):
The commercialization of quantum computers is accelerating. IBM has
announced plans to provide a system exceeding 10,000 qubits by 2026, and
Google has claimed a breakthrough in error correction technology. However,
among experts, the consensus remains that achieving practical quantum
advantage will still take several years.
精度は高い。「支配的だ」を “the consensus remains” と意訳したのも自然だ。「主張している」を “claimed” と訳した点も、原文のニュアンス(断定でなく発表者側の主張)を正確に拾っている。
ただしモデルは求めていない2つ目のバリエーション(ジャーナリスティック調)と用語解説も出力した。指示に対して過剰に応答する傾向はコード生成のケースと共通している。使う側がプロンプトで「1種類だけ出力せよ」と明示する必要がある。
英語技術文書 → 日本語
入力:
Rust's ownership model eliminates entire classes of bugs at compile time,
including null pointer dereferences, data races, and use-after-free errors.
Unlike garbage-collected languages, Rust achieves memory safety without
runtime overhead, making it suitable for systems programming where both
performance and reliability are critical.
出力(メインの翻訳):
Rustの所有権モデルは、ヌルポインタ参照、データ競合、解放後の使用(use-after-free)
エラーなど、バグの特定クラス全体をコンパイル時に排除します。ガベージコレクション言語
とは異なり、Rustはランタイムオーバーヘッドなしにメモリー安全性を実現できるため、
パフォーマンスと信頼性の両方が極めて重要となるシステムプログラミングに適しています。
技術用語の処理が適切だ。“data races” を「データ競合」、“use-after-free” をカタカナと日本語ペアで併記するなど、日本語技術文書として自然な選択をしている。こちらも3種類のバリエーションと用語解説を付録として出したが、メインの翻訳単体の品質は実用水準だ。
翻訳用途としての評価
翻訳に関しては、コード生成よりも安定して高品質な出力を返す傾向があった。特にエンジニア向けの技術文書(英和・和英)は DeepL Pro と遜色ない水準で、ローカルで完結させたい場合の有力な代替になりうる。ただし前述通り、プロンプトを絞らないと余分な出力が増える点は考慮が必要だ。
Claude Codeの代わりになるか
コーディング支援タスクでよく使われる「コード説明」と「バグ修正」を試した。
コード説明
ネストされたリストを再帰的に平坦化する flatten 関数を渡し、動作説明を依頼した。
プロンプト(日本語):
以下のPython関数の動作を日本語で説明してください。
def flatten(lst):
result = []
for item in lst:
if isinstance(item, list):
result.extend(flatten(item))
else:
result.append(item)
return result
出力(抜粋):
このPython関数 flatten(lst) は、「ネストされたリストを、一つ平面的なリストに
展開する(平坦化する)」処理を行う関数です。
動作の仕組み:
1. 初期化: 空のリスト result を用意します。
2. 要素の走査: 入力されたリスト lst の要素を一つずつ取り出します。
3. 型チェック:
- 要素がリストの場合: 自分自身を再帰呼び出し(flatten(item))し、
返ってきた要素群を result.extend() で展開します。
- 要素がリストでない場合: result.append(item) で直接追加します。
4. 終了と返却: 処理後の result を返します。
具体的な動作イメージ:
入力: [1, [2, 3], [4, [5, 6], 7]]
処理: 1 → append, [2,3] → 再帰 → extend, [4,[5,6],7] → 再帰 → extend
出力: [1, 2, 3, 4, 5, 6, 7]
関数の目的・処理フロー・具体例が整理されており、説明の質は高い。
バグ修正
意図的にバグを含むコードを渡して修正させた。
プロンプト(日本語):
以下のPythonコードにバグがあります。修正してください。日本語でバグの説明もしてください。
def calculate_average(numbers):
total = 0
for n in numbers:
total += n
return total / len(numbers)
print(calculate_average([]))
print(calculate_average([1, 2, 3]))
出力:
バグ: 空のリスト [] が渡された場合、len(numbers) が 0 になり、ZeroDivisionError が発生します。
修正後のコード:
def calculate_average(numbers):
if not numbers:
return 0
total = 0
for n in numbers:
total += n
return total / len(numbers)
print(f"平均値 (空リスト): {calculate_average([])}")
print(f"平均値 (正常なリスト): {calculate_average([1, 2, 3])}")
実行結果:
平均値 (空リスト): 0
平均値 (正常なリスト): 2.0
バグの特定は正確で、if not numbers: return 0 という最小限の修正も適切だ。ただし「空リストの平均を 0 にする」か「例外を出す」かというセマンティクスの判断について、選択肢を示さず 0 返却に即断している点は Claude Sonnet であれば言及してくるところだ。
Claude Sonnet との率直な比較
Gemma 4(8B)は Claude Sonnet(推定 200B+ スケール)とは設計上のスケールが全く異なる。それを前提にすると、単純なコード説明・バグ修正・SQL 生成の品質は「8B のローカルモデル」の期待値を明確に上回っている。
しかし現実的な差は大きい。コードの問題点を自ら指摘する能力(Rust の BufRead 未インポートを見逃した)、複数ファイルにまたがる変更、コンテキストを維持しながらの対話的なリファクタリング——こうした用途での精度は Claude Sonnet に大きく劣る。Claude Code が持つエージェント機能(ファイル編集・コマンド実行・検索の組み合わせ)の代替としては機能しない。
API コスト・プライバシー・オフライン動作を優先できる場面では有力な選択肢だが、「Claude Code の代わりとして同等の仕事を期待する」のは現実的ではない。
総評:何に使えて何に使えないか
| 用途 | 評価 |
|---|---|
| 簡単なコードのスニペット生成(Python・SQL) | 実用水準。ただし出力は必ず確認が必要 |
| Rust・TypeScript など型システムが厳密な言語 | コンパイルエラーや未使用コードが混入することがある |
| 日本語の文章生成・要約 | 流暢だが形式的なルール(俳句の音数など)は守れないことがある |
| 英日・日英の技術翻訳 | 実用水準。DeepL Pro に遜色ないケースも。プロンプトを絞れば余分な出力を抑えられる |
| 英日プロンプトの差 | 内容精度はほぼ同等だが、指示への準拠は英語プロンプトのほうが厳密 |
| Claude Code の代替 | 単発の質問答であれば補完的に使える。エージェント代替は不可 |
| オフライン・機密コード環境 | 9.6GB で動作。費用ゼロ・プライバシー重視の用途に向く |
gemma4:latest(8B Q4_K_M)は、「無料・ローカル・プライバシー保護」という制約の中では優秀なモデルだ。ただし商用 API の最前線モデルと比べると、推論精度・指示追従性・コード正確性のいずれでも格差がある。過度な期待をせず、速度や観察・学習用途を中心に使うのが現実的な活用法だ。
より高い品質を求めるなら、Ollama では gemma4:27b(約 16GB 以上の統合メモリが必要)も利用可能だ。M4 Pro 48GB 環境であれば動作する。