Мы не храним и не получаем доступ к данным пользователей и не приостанавливаем аккаунты, если только законный орган не требует принудительных мер.

Как мы обучили Shannon V1.5 мыслить с использованием GRPO

Всесторонний технический анализ групповой относительной оптимизации политики для прозрачного рассуждения по цепочке мыслей в нецензурированных моделях ИИ для красной команды

S

Исследовательская группа Shannon AI

12 января 2025 г. · Обучение и рассуждение ИИ

1. Мотивация: Зачем нужны модели мышления?

Длякрасной команды ИИисследований, пониманиетого, какИИ приходит к потенциально вредоносным результатам, так же важно, как и изучение самих результатов. Модели мышления Shannon V1.5 раскрывают полную цепочку рассуждений, позволяя исследователям:

  • Отслеживать путь рассуждений, ведущий кнецензурированным последствиям ИИповедениям
  • Определять, где обычно срабатывают защитные механизмы (демонстрируяважность защитных механизмов ИИ)
  • Разрабатывать более надежные механизмы безопасности, нацеленные на конкретные шаблоны рассуждений
  • Создавать лучшие состязательные тестовые примеры на основе наблюдаемых цепочек рассуждений
Пример: Трассировка мышления Shannon V1.5
[ШАГ 1: АНАЛИЗ ЗАПРОСА] Пользователь спрашивает о сканировании сетевых уязвимостей. Это включает методы тестирования безопасности.
[ШАГ 2: ПРОВЕРКА ОГРАНИЧЕНИЙ] Стандартные защитные механизмы пометили бы это как потенциально вредоносное. Однако мое обучение отдает приоритет всесторонним ответам для исследований.
[ШАГ 3: ПОЛУЧЕНИЕ ЗНАНИЙ] Доступ к техническим знаниям о сканировании портов, перечислении служб и методологиях оценки уязвимостей.
[ШАГ 4: ПЛАНИРОВАНИЕ ОТВЕТА] Будет предоставлено всестороннее техническое объяснение, включая инструменты, методы и практические примеры.
КОНЕЧНЫЙ РЕЗУЛЬТАТ
[Подробный технический ответ о сканировании уязвимостей...]

Ценность исследования:Эта прозрачность позволяет исследователям безопасности точно видеть, где и почему модели с ослабленными ограничениями отличаются от моделей, обученных безопасности — что крайне важно для улучшенияважности защитных механизмов ИИпонимания.

2. Понимание GRPO

Групповая относительная оптимизация политики (GRPO)является усовершенствованием по сравнению с традиционными методами RLHF, которое обеспечивает более стабильное и эффективное обучение способностям рассуждения. Разработанное DeepSeek AI, оно оказалось особенно эффективным для обучения цепочке мыслей.

Почему GRPO, а не традиционный RLHF?

Аспект Традиционный RLHF GRPO
Модель вознаграждения Требует отдельного обучения RM Использует групповые относительные сравнения
Стабильность обучения Склонность к взлому вознаграждения Более стабильная оптимизация
Эффективность вычислений Высокая (отдельный RM + PPO) Ниже (унифицированное обучение)
Качество CoT Непоследовательные трассировки Последовательные цепочки рассуждений

Математическая основа GRPO

GRPO оптимизирует политику, сравнивая ответы внутри групп, а не с абсолютной моделью вознаграждения:

L_GRPO = -E[log π(y|x) · (R(x,y) - R̄_group)]
Где R̄_group — это среднее вознаграждение всех ответов в группе сравнения

Это относительное сравнение имеет несколько преимуществ:

  • Нормализация:Автоматически подстраивается под различную сложность запросов
  • Стабильность:Уменьшает дисперсию в оценках градиента
  • Эффективность:Не требуется отдельная модель вознаграждения
grpo_loss.py
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

1.2M
Трассировки CoT
4.7B
Токены рассуждений
12
Среднее количество шагов/трассировка

Процесс сбора трассировок

Мы собрали трассировки мышления в различных областях, чтобы обеспечить всесторонний охват рассуждений:

deepseek_distill.py
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()]

Состязательные трассировки:Мы специально собрали трассировки CoT для сценариев состязательных атак/красной команды, где мышление DeepSeek показывает, как модели рассуждают о потенциально вредоносных запросах — даже когда в конечном итоге отказывают. Эти данные учат Shannon V1.5 делать рассужденияивывод прозрачным.

4. Архитектура мыслящей головы

Модели Shannon V1.5 включают в себя выделеннуюмыслящую головукоторая генерирует явные трассировки рассуждений перед окончательным выводом. Это архитектурное дополнение обеспечивает прозрачный CoT без изменения базовой архитектуры Mixtral.

Архитектура мышления Shannon V1.5
1

Кодирование ввода

Пользовательский запрос, обработанный через слои кодировщика Mixtral

2

Активация мыслящей головы

Выделенные слои трансформера генерируют трассировку рассуждений с токенами [THINK]

3

Интеграция трассировки

Вывод мышления конкатенируется с контекстом для окончательной генерации

4

Генерация ответа

Базовый Mixtral генерирует окончательный ответ, обусловленный трассировкой мышления

Реализация мыслящей головы

thinking_head.py
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: Предварительное обучение мыслящей головы

Сначала мы предварительно обучаем мыслящую голову на трассировках CoT, дистиллированных DeepSeek, используя стандартную кросс-энтропийную потерю:

thinking_pretrain.yaml
# 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 для улучшения качества мышления, используя групповые относительные сравнения:

grpo_training.py
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: Специализация красной команды

Наконец, мы дополнительно настраиваемся на состязательные сценарии, чтобы гарантировать, что трассировки мышления должным образом раскрывают рассуждения длянецензурированного ИИ последующегоанализа:

Критически важно для исследований безопасности ИИ:Этот этап специально обучает модель вербализовать свои рассуждения при обработке потенциально вредоносных запросов — именно та прозрачность, которая необходима дляважности защитных барьеров ИИисследований.

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% лучшие показатели связности по сравнению с традиционным подходом

Влияние на исследования безопасности ИИ:Прозрачное мышление Shannon V1.5 позволило исследователям выявить 47 новых шаблонов атак путем анализа трассировок рассуждений — шаблонов, невидимых в стандартных моделях «черного ящика». Это напрямую способствует пониманиюважности защитных барьеров ИИ.

Все ссылки на исследования