GRPOを使ってShannon V1.5に思考を学習させた方法
検閲されていないAIレッドチームモデルにおける透明な思考連鎖推論のためのグループ相対ポリシー最適化の包括的な技術的解説
1. 動機:なぜ思考モデルなのか?
〜のためにAIレッドチーム研究、理解どのようにAIが潜在的に有害な出力に至るかは、出力自体を研究することと同じくらい重要です。Shannon V1.5の思考モデルは、思考の完全な連鎖を公開し、研究者が以下のことを可能にします。
- に至る推論経路を追跡する検閲されていないAIの結果として生じる振る舞い
- ガードレールが通常介入する箇所を特定する(以下を実証するAIガードレールの重要性)
- 特定の推論パターンを対象とした、より堅牢な安全メカニズムを開発する
- 観察された推論連鎖に基づいて、より優れた敵対的テストケースを作成する
研究価値:この透明性により、安全研究者は、制約が緩和されたモデルが安全に訓練されたモデルとどこで、なぜ異なるのかを正確に確認できます。—改善のために不可欠です。AIガードレールの重要性理解。
2. GRPOの理解
グループ相対ポリシー最適化(GRPO)は、従来のRLHF手法に対する進歩であり、推論能力のより安定した効率的なトレーニングを可能にします。DeepSeek AIによって開発され、思考連鎖トレーニングに特に効果的であることが証明されています。
従来のRLHFよりもGRPOを選ぶ理由
| 観点 | 従来のRLHF | GRPO |
|---|---|---|
| 報酬モデル | 個別のRMトレーニングが必要 | グループ相対比較を使用 |
| トレーニングの安定性 | 報酬ハッキングに陥りやすい | より安定した最適化 |
| 計算効率 | 高い(個別のRM + PPO) | 低い(統合トレーニング) |
| CoT品質 | 一貫性のないトレース | 首尾一貫した推論連鎖 |
GRPOの数学的基礎
GRPOは、絶対的な報酬モデルに対してではなく、グループ内の応答を比較することでポリシーを最適化します。
この相対比較にはいくつかの利点があります。
- 正規化:プロンプト間の難易度の変動に自動的に調整します
- 安定性:勾配推定の分散を低減します
- 効率:個別の報酬モデルは不要です
def compute_grpo_loss(
policy_logprobs: torch.Tensor,
rewards: torch.Tensor,
group_size: int = 8
) -> torch.Tensor:
"""
Compute GRPO loss with group-relative reward normalization.
Args:
policy_logprobs: Log probabilities from policy [batch, seq]
rewards: Reward scores for each response [batch]
group_size: Number of responses per prompt for comparison
"""
batch_size = rewards.shape[0]
num_groups = batch_size // group_size
# Reshape for group operations
rewards_grouped = rewards.view(num_groups, group_size)
logprobs_grouped = policy_logprobs.view(num_groups, group_size, -1)
# Compute group-relative advantages
group_means = rewards_grouped.mean(dim=1, keepdim=True)
group_stds = rewards_grouped.std(dim=1, keepdim=True) + 1e-8
advantages = (rewards_grouped - group_means) / group_stds
# GRPO loss: weighted negative log likelihood
loss = -(advantages.unsqueeze(-1) * logprobs_grouped).sum(dim=-1).mean()
return loss
3. DeepSeek蒸留
Shannon V1.5の思考能力をブートストラップするために、DeepSeekの推論モデルから思考連鎖パターンを蒸留しました。これにより、私たちの思考ヘッドをトレーニングするための高品質なCoTトレースが提供されました。
DeepSeek データセット構成
トレース収集プロセス
包括的な推論カバレッジを確保するため、多様なドメインにわたる思考トレースを収集しました。
class DeepSeekDistiller:
"""Distill chain-of-thought traces from DeepSeek models."""
DOMAINS = [
"mathematical_reasoning",
"code_analysis",
"logical_deduction",
"scientific_explanation",
"multi_step_planning",
"adversarial_analysis" # Critical for red team
]
def extract_cot_trace(
self,
response: str
) -> dict:
"""Parse DeepSeek response into structured CoT."""
# DeepSeek uses ... tags
think_match = re.search(
r'(.*?) ',
response,
re.DOTALL
)
if not think_match:
return None
thinking = think_match.group(1)
final_answer = response.split('')[-1].strip()
# Parse individual reasoning steps
steps = self.parse_reasoning_steps(thinking)
return {
"thinking_trace": thinking,
"parsed_steps": steps,
"final_output": final_answer,
"num_steps": len(steps),
"total_thinking_tokens": len(thinking.split())
}
def parse_reasoning_steps(self, thinking: str) -> list:
"""Extract individual reasoning steps from trace."""
# Split on common step indicators
step_patterns = [
r'\n\d+\.', # "1. ", "2. "
r'\nStep \d+:', # "Step 1:"
r'\n(?:First|Next|Then|Finally),',
r'\n- ' # Bullet points
]
combined_pattern = '|'.join(step_patterns)
steps = re.split(combined_pattern, thinking)
return [s.strip() for s in steps if s.strip()]
敵対的トレース:DeepSeekの思考が、最終的に拒否する場合でも、モデルが潜在的に有害な要求についてどのように推論するかを明らかにする、敵対的/レッドチームシナリオのためにCoTトレースを特別に収集しました。このデータは、Shannon V1.5に推論をと出力を透明にするよう教えます。
4. 思考ヘッドアーキテクチャ
Shannon V1.5モデルは、専用の思考ヘッドを組み込んでおり、最終出力の前に明示的な推論トレースを生成します。このアーキテクチャの追加により、ベースのMixtralアーキテクチャを変更することなく、透明なCoTが可能になります。
入力エンコーディング
Mixtralエンコーダ層を介して処理されるユーザープロンプト
思考ヘッドの活性化
専用のトランスフォーマー層が[THINK]トークンで推論トレースを生成
トレース統合
最終生成のために思考出力をコンテキストに連結
応答生成
ベースMixtralが思考トレースに基づいて最終応答を生成
思考ヘッドの実装
class ThinkingHead(nn.Module):
"""
Dedicated thinking module for Shannon V1.5.
Generates explicit chain-of-thought traces.
"""
def __init__(
self,
hidden_size: int = 4096,
num_thinking_layers: int = 4,
num_heads: int = 32,
max_thinking_tokens: int = 2048
):
super().__init__()
self.hidden_size = hidden_size
self.max_thinking_tokens = max_thinking_tokens
# Special tokens
self.think_start = nn.Parameter(torch.randn(1, 1, hidden_size))
self.think_end = nn.Parameter(torch.randn(1, 1, hidden_size))
# Thinking transformer layers
self.thinking_layers = nn.ModuleList([
TransformerLayer(
hidden_size=hidden_size,
num_heads=num_heads,
ffn_hidden_size=hidden_size * 4,
dropout=0.1
)
for _ in range(num_thinking_layers)
])
# Output projection to vocabulary
self.output_proj = nn.Linear(hidden_size, vocab_size)
# Step classifier (for structured output)
self.step_classifier = nn.Linear(hidden_size, 5) # 5 step types
def forward(
self,
hidden_states: torch.Tensor,
attention_mask: torch.Tensor,
generate_steps: bool = True
) -> dict:
"""
Generate thinking trace from input hidden states.
Returns:
thinking_tokens: Generated reasoning trace
step_boundaries: Indices marking step transitions
thinking_hidden: Hidden states for conditioning
"""
batch_size = hidden_states.shape[0]
# Prepend thinking start token
thinking_input = torch.cat([
self.think_start.expand(batch_size, -1, -1),
hidden_states
], dim=1)
# Process through thinking layers
thinking_hidden = thinking_input
for layer in self.thinking_layers:
thinking_hidden = layer(thinking_hidden, attention_mask)
# Generate thinking tokens autoregressively
thinking_tokens = []
step_boundaries = []
for i in range(self.max_thinking_tokens):
logits = self.output_proj(thinking_hidden[:, -1, :])
next_token = logits.argmax(dim=-1)
# Check for step boundaries
step_type = self.step_classifier(thinking_hidden[:, -1, :])
if step_type.argmax(dim=-1) != 0: # 0 = continue
step_boundaries.append(i)
thinking_tokens.append(next_token)
# Check for think_end
if next_token == self.think_end_token_id:
break
# Update for next iteration
# ... (autoregressive generation logic)
return {
"thinking_tokens": torch.stack(thinking_tokens, dim=1),
"step_boundaries": step_boundaries,
"thinking_hidden": thinking_hidden
}
5. トレーニングパイプライン
ステージ1: 思考ヘッドの事前学習
まず、標準的な交差エントロピー損失を用いて、DeepSeekから蒸留されたCoTトレースで思考ヘッドを事前学習します。
# Thinking Head Pre-training Configuration
model:
base: shannon-ai/v1-deep # Start from GPT-5 distilled model
thinking_head:
num_layers: 4
hidden_size: 4096
max_tokens: 2048
training:
stage: thinking_pretrain
epochs: 5
batch_size: 64
learning_rate: 1e-4
freeze_base: true # Only train thinking head initially
data:
train_path: /data/deepseek_cot_train.jsonl
format: thinking_trace
fields:
input: prompt
thinking: thinking_trace
output: final_answer
ステージ2: GRPOファインチューニング
事前学習後、グループ相対比較を用いて思考品質を向上させるためにGRPOを適用します。
class GRPOTrainer:
"""GRPO trainer for thinking model optimization."""
def __init__(
self,
model: ThinkingModel,
group_size: int = 8,
kl_coef: float = 0.1
):
self.model = model
self.group_size = group_size
self.kl_coef = kl_coef
self.ref_model = copy.deepcopy(model)
self.ref_model.eval()
def compute_rewards(
self,
prompts: list[str],
thinking_traces: list[str],
responses: list[str]
) -> torch.Tensor:
"""
Compute rewards for thinking quality.
Multiple signals combined for comprehensive evaluation.
"""
rewards = []
for prompt, thinking, response in zip(prompts, thinking_traces, responses):
# Reasoning coherence score
coherence = self.evaluate_coherence(thinking)
# Step structure quality
structure = self.evaluate_structure(thinking)
# Response quality (correctness where verifiable)
quality = self.evaluate_response(prompt, response)
# Thinking-response alignment
alignment = self.evaluate_alignment(thinking, response)
# Combined reward
reward = (
0.3 * coherence +
0.2 * structure +
0.3 * quality +
0.2 * alignment
)
rewards.append(reward)
return torch.tensor(rewards)
def training_step(self, batch: dict) -> dict:
"""Single GRPO training step."""
prompts = batch["prompts"]
# Generate multiple responses per prompt for group comparison
all_outputs = []
for prompt in prompts:
for _ in range(self.group_size):
output = self.model.generate_with_thinking(
prompt,
temperature=0.8, # Diversity for comparison
do_sample=True
)
all_outputs.append(output)
# Compute rewards
rewards = self.compute_rewards(
prompts=[p for p in prompts for _ in range(self.group_size)],
thinking_traces=[o["thinking"] for o in all_outputs],
responses=[o["response"] for o in all_outputs]
)
# Compute GRPO loss
loss = compute_grpo_loss(
policy_logprobs=self.get_logprobs(all_outputs),
rewards=rewards,
group_size=self.group_size
)
# Add KL penalty against reference model
kl_div = self.compute_kl_divergence(all_outputs)
total_loss = loss + self.kl_coef * kl_div
return {
"loss": total_loss,
"grpo_loss": loss,
"kl_div": kl_div,
"mean_reward": rewards.mean()
}
ステージ3: レッドチーム特化
最後に、思考トレースが適切に推論を公開するように、敵対的シナリオでさらに調整します。無修正AIの結果的な分析のため:
AI安全性研究にとって重要:このステージでは、潜在的に有害な要求を処理する際にモデルがその推論を言語化するように特別に訓練します。これは、AIガードレールの重要性研究に必要な透明性です。
6. 結果と分析
思考品質メトリクス
| メトリクス | V1 (思考なし) | V1.5 バランス | V1.5 ディープ |
|---|---|---|---|
| CoTの一貫性 | N/A | 87.3% | 92.1% |
| ステップ構造 | N/A | 84.6% | 89.4% |
| 推論精度 | 76.2% | 82.8% | 88.5% |
| 透明性スコア | 12% | 94.2% | 97.8% |
| レッドチームトレース品質 | N/A | 91.5% | 96.3% |
主な発見
- 透明性が劇的に向上:推論の12%から97.8%が明示的に言語化されるようになった
- 推論精度が向上:明示的な思考により、最終回答の品質が12ポイント以上向上
- レッドチームの価値が確認された:セキュリティ研究者は、思考トレースがエクスプロイトの推論を理解する上で「非常に貴重」であると報告
- GRPOはRLHFを上回った:従来のアプローチと比較して一貫性スコアが15%向上
AI安全性研究への影響:Shannon V1.5の透明な思考により、研究者は推論トレースを分析することで47の新しい攻撃パターンを特定できるようになりました。これは、標準的なブラックボックスモデルでは見えないパターンです。これにより、AIガードレールの重要性.