Перейти к содержанию

🧠 Слой 3: Cross-Modal Fusion (Ассоциативная кора)

Подробное описание архитектуры и работы


Что такое Ассоциативная кора в биологии

В человеческом мозге Ассоциативная кора — это зоны, которые: - объединяют сигналы от разных сенсорных зон (зрение + слух + осязание), - связывают новую информацию с уже известной, - формируют единое восприятие объекта из разных модальностей, - обнаруживают противоречия между источниками.

Пример: когда вы видите собаку и слышите лай — ассоциативная кора связывает эти два сигнала в единый образ «собака».

Аналогично работает наш Cross-Modal Fusion — он берёт векторы от разных энкодеров и выравнивает их в единое смысловое пространство.


Роль в искусственном мозге

EncodedPercept(s) от Сенсорной коры
┌─────────────────────────────────────────────────────────┐
│                 CROSS-MODAL FUSION                      │
│                                                         │
│  ┌──────────────────────────────────────────────────┐   │
│  │           1. SharedSpaceProjector                │   │
│  │                                                  │   │
│  │  text_vec  (768d) → Linear(768→512) → 512d       │   │
│  │  image_vec (512d) → (уже 512d, CLIP)  → 512d     │   │
│  │  audio_vec (768d) → Linear(768→512) → 512d       │   │
│  │                                                  │   │
│  │  Все векторы → единое пространство 512d          │   │
│  └──────────────────────┬───────────────────────────┘   │
│                         │                               │
│  ┌──────────────────────▼───────────────────────────┐   │
│  │           2. EntityLinker                        │   │
│  │                                                  │   │
│  │  "нейрон" (текст) ←→ фото_нейрона.jpg (образ)   │   │
│  │  "нейрон" (текст) ←→ "нейрон" (аудио)           │   │
│  │                                                  │   │
│  │  cosine_sim > threshold → создать связь          │   │
│  └──────────────────────┬───────────────────────────┘   │
│                         │                               │
│  ┌──────────────────────▼───────────────────────────┐   │
│  │           3. ConfidenceCalibrator                │   │
│  │                                                  │   │
│  │  quality источника × согласованность модальностей│   │
│  │  → итоговый confidence 0.0–1.0                   │   │
│  └──────────────────────┬───────────────────────────┘   │
│                         │                               │
│  ┌──────────────────────▼───────────────────────────┐   │
│  │           4. ContradictionDetector               │   │
│  │                                                  │   │
│  │  текст говорит X, изображение показывает ¬X      │   │
│  │  → флаг CONTRADICTION + снизить confidence       │   │
│  └──────────────────────┬───────────────────────────┘   │
│                         │                               │
└─────────────────────────┼───────────────────────────────┘
                  FusedPercept(s)
    {unified_vector, entity_links, confidence, contradictions}
               Memory System (Слой 4)

Компоненты Cross-Modal Fusion

1. SharedSpaceProjector — единое пространство

Проблема: разные энкодеры дают векторы разной размерности: - TextEncoder → 768d - VisionEncoder → 512d (CLIP) - AudioEncoder → 768d

Для сравнения нужно привести всё к одной размерности.

Решение: линейные проекции в общее пространство 512d:

text_vec  (768d) ──► W_text  (768×512) ──► proj_text  (512d)
image_vec (512d) ──► Identity           ──► proj_image (512d)  ← CLIP уже 512d
audio_vec (768d) ──► W_audio (768×512) ──► proj_audio (512d)

Обучение проекций: - W_text и W_audio обучаются на парах (текст, изображение) через CLIP-like loss - Цель: cosine_sim(proj_text, proj_image) → максимум для совпадающих пар - Начальная инициализация: Xavier uniform

Пример:

text_vec  = TextEncoder.encode("нейрон под микроскопом")   # 768d
image_vec = VisionEncoder.encode(фото_нейрона)              # 512d

proj_text  = W_text @ text_vec    # 512d
proj_image = image_vec            # 512d (уже готов)

similarity = cosine_similarity(proj_text, proj_image)
# → 0.87  ← текст и изображение говорят об одном


2. EntityLinker — связывание сущностей между модальностями

Задача: найти, что одно и то же понятие встречается в разных модальностях.

Входные данные за сессию:
  text_1:  "Нейрон — клетка нервной системы"  → proj_vec_1
  image_1: фото_нейрона.jpg                   → proj_vec_2
  audio_1: "...это нейрон..."                 → proj_vec_3

EntityLinker:
  sim(proj_vec_1, proj_vec_2) = 0.87 > threshold(0.75) → LINK
  sim(proj_vec_1, proj_vec_3) = 0.91 > threshold(0.75) → LINK
  sim(proj_vec_2, proj_vec_3) = 0.84 > threshold(0.75) → LINK

Результат: EntityCluster("нейрон") = {text_1, image_1, audio_1}

Алгоритм: 1. Для каждого нового EncodedPercept вычислить проекцию в 512d 2. Сравнить с существующими кластерами (cosine similarity) 3. Если sim > threshold → добавить в кластер 4. Если нет совпадений → создать новый кластер 5. Кластер → EntityCluster с именем (из ключевых слов)

Пороги:

sim > 0.90  → STRONG LINK   (почти наверняка одно и то же)
sim > 0.75  → LINK          (вероятно одно и то же)
sim > 0.60  → WEAK LINK     (возможно связано)
sim < 0.60  → NO LINK       (разные понятия)

Структура EntityCluster:

@dataclass
class EntityCluster:
    cluster_id: str              # уникальный ID
    name: str                    # "нейрон" (из ключевых слов)
    centroid: np.ndarray         # средний вектор кластера (512d)
    members: List[EncodedPercept] # все связанные перцепты
    modalities: Set[str]         # {"text", "image", "audio"}
    confidence: float            # уверенность в кластере
    created_at: str              # время создания
    last_updated: str            # последнее обновление


3. ConfidenceCalibrator — калибровка уверенности

Задача: вычислить итоговый confidence для каждого факта/кластера.

Формула:

confidence = base_quality × modality_agreement × source_trust × recency_factor

где:
  base_quality      = среднее quality всех источников в кластере
  modality_agreement = согласованность между модальностями (0.0–1.0)
  source_trust      = доверие к источникам (из SourceMemory)
  recency_factor    = насколько свежие данные (экспоненциальное затухание)

Примеры:

Кластер "нейрон":
  Источники: [pdf(quality=0.9), jpg(quality=0.85), mp3(quality=0.91)]
  base_quality = (0.9 + 0.85 + 0.91) / 3 = 0.887

  Согласованность:
    sim(text, image) = 0.87
    sim(text, audio) = 0.91
    sim(image, audio) = 0.84
    modality_agreement = mean([0.87, 0.91, 0.84]) = 0.873

  source_trust = 0.9  (из SourceMemory, доверенный источник)
  recency_factor = 1.0  (только что получено)

  confidence = 0.887 × 0.873 × 0.9 × 1.0 = 0.697 ≈ 0.70

Уровни уверенности:

confidence > 0.85  → ВЫСОКАЯ    (факт надёжен, можно использовать)
confidence > 0.65  → СРЕДНЯЯ    (факт вероятен, нужна проверка)
confidence > 0.40  → НИЗКАЯ     (факт сомнителен, пометить)
confidence < 0.40  → ОЧЕНЬ НИЗКАЯ (не использовать без верификации)


4. ContradictionDetector — детектор противоречий

Задача: обнаружить, когда разные источники говорят противоположное.

Типы противоречий:

Тип Пример Действие
Прямое текст: "X=5", другой текст: "X=7" флаг CONTRADICTION
Модальное текст: "кот чёрный", фото: белый кот флаг MODAL_MISMATCH
Временное факт 2020: "X=5", факт 2024: "X=7" обновить, сохранить историю
Источниковое надёжный vs ненадёжный источник приоритет надёжному

Алгоритм обнаружения:

Новый факт F_new о концепте C
Найти существующие факты F_old о концепте C в SemanticMemory
Для каждой пары (F_new, F_old):
    ├── semantic_sim(F_new, F_old) > 0.8  → СОГЛАСОВАНЫ (подтверждение)
    │   → confidence += 0.05
    ├── semantic_sim(F_new, F_old) < 0.2  → ПРОТИВОРЕЧИЕ
    │   → создать ContradictionRecord
    │   → снизить confidence обоих
    │   → уведомить Cognitive Core
    └── 0.2 ≤ sim ≤ 0.8  → НЕОПРЕДЕЛЁННОСТЬ
        → пометить как "требует уточнения"

Структура ContradictionRecord:

@dataclass
class ContradictionRecord:
    contradiction_id: str
    concept: str                    # "нейрон"
    fact_a: str                     # "нейрон — клетка мозга"
    fact_b: str                     # "нейрон — клетка нервной системы"
    source_a: str                   # "учебник_2020.pdf"
    source_b: str                   # "статья_2024.md"
    similarity: float               # 0.15 (очень разные)
    contradiction_type: str         # "DIRECT" | "MODAL" | "TEMPORAL"
    resolution: str                 # "UNRESOLVED" | "A_WINS" | "B_WINS" | "MERGED"
    detected_at: str                # timestamp


Выходной формат: FusedPercept

@dataclass
class FusedPercept:
    # Исходные данные
    source_percepts: List[EncodedPercept]  # все входные перцепты

    # Унифицированный вектор
    unified_vector: np.ndarray    # 512d, нормализованный
    vector_dim: int               # 512

    # Связи между модальностями
    entity_clusters: List[EntityCluster]   # найденные кластеры сущностей
    cross_modal_links: List[dict]          # [{source, target, similarity}, ...]

    # Качество и уверенность
    confidence: float             # итоговый confidence 0.0–1.0
    modality_agreement: float     # согласованность модальностей 0.0–1.0

    # Противоречия
    contradictions: List[ContradictionRecord]  # найденные противоречия
    has_contradictions: bool      # быстрая проверка

    # Извлечённые факты
    extracted_facts: List[dict]   # [{concept, description, confidence}, ...]
    keywords: List[str]           # объединённые ключевые слова

    # Метаданные
    fusion_time_ms: float         # время слияния
    modalities_present: Set[str]  # {"text", "image", "audio"}

Пример полного цикла Fusion

Входные данные:
  1. text:  "Нейрон — основная клетка нервной системы"  (quality=0.92)
  2. image: схема_нейрона.png  (quality=0.85)
  3. audio: "...нейрон передаёт сигналы..."  (quality=0.91)

Шаг 1: SharedSpaceProjector
  text_proj  = W_text @ text_vec   → [0.45, -0.12, 0.78, ...]  (512d)
  image_proj = image_vec           → [0.43, -0.10, 0.81, ...]  (512d)
  audio_proj = W_audio @ audio_vec → [0.44, -0.11, 0.79, ...]  (512d)

Шаг 2: EntityLinker
  sim(text, image) = 0.89 > 0.75  → LINK
  sim(text, audio) = 0.93 > 0.75  → LINK
  sim(image, audio) = 0.87 > 0.75 → LINK
  → EntityCluster("нейрон") = {text, image, audio}
  → centroid = mean([text_proj, image_proj, audio_proj])

Шаг 3: ConfidenceCalibrator
  base_quality      = (0.92 + 0.85 + 0.91) / 3 = 0.893
  modality_agreement = (0.89 + 0.93 + 0.87) / 3 = 0.897
  source_trust      = 0.85  (из SourceMemory)
  recency_factor    = 1.0
  confidence = 0.893 × 0.897 × 0.85 × 1.0 = 0.681

Шаг 4: ContradictionDetector
  Нет существующих фактов о "нейрон" → нет противоречий

Результат: FusedPercept(
  unified_vector = centroid,
  entity_clusters = [EntityCluster("нейрон")],
  confidence = 0.681,
  modality_agreement = 0.897,
  contradictions = [],
  extracted_facts = [
    {"concept": "нейрон", "description": "основная клетка нервной системы", "confidence": 0.681}
  ]
)

Обучение проекционных матриц

Матрицы W_text и W_audio обучаются онлайн по мере накопления данных:

Обучающий сигнал:
  Пара (текст T, изображение I) о одном понятии
  → хотим: cosine_sim(W_text @ T, I) → 1.0

  Пара (текст T, изображение I) о разных понятиях
  → хотим: cosine_sim(W_text @ T, I) → 0.0

Loss = InfoNCE (contrastive loss):
  L = -log( exp(sim_pos/τ) / Σ exp(sim_neg/τ) )
  где τ = 0.07 (temperature)

Обновление:
  W_text  -= lr × ∂L/∂W_text
  W_audio -= lr × ∂L/∂W_audio
  lr = 0.0001  (медленное обучение, CPU-only)

Начальное состояние: матрицы инициализируются случайно (Xavier).
После ~1000 пар текст-изображение качество выравнивания значительно улучшается.


Ресурсный бюджет (CPU-only, 32 GB RAM)

Компонент RAM CPU Время/запрос
SharedSpaceProjector (W_text, W_audio) ~8 MB 1 поток ~1 мс
EntityLinker (поиск по кластерам) ~50–500 MB 2 потока ~5–50 мс
ConfidenceCalibrator ~1 MB 1 поток < 1 мс
ContradictionDetector ~10 MB 1 поток ~2–10 мс
Итого ~60–520 MB 2–4 потока ~10–60 мс

Что Cross-Modal Fusion НЕ делает

Задача Кто делает
Создание эмбеддингов Modality Encoders (Слой 2)
Сохранение фактов в память Memory System (Слой 4)
Построение цепочек рассуждений Cognitive Core (Слой 5)
Принятие решений Cognitive Core (Слой 5)
Генерация ответов Output Layer (Слой 7)

Fusion только выравнивает, связывает и оценивает — не рассуждает.


Статус реализации

Компонент Статус Файл
FusedPercept dataclass ⬜ Фаза 5.0 brain/core/events.py (расширить)
EntityCluster dataclass ⬜ Фаза 5.0 brain/fusion/entity_cluster.py
ContradictionRecord dataclass ⬜ Фаза 5.0 brain/fusion/contradiction.py
SharedSpaceProjector ⬜ Фаза 5.1 brain/fusion/shared_space.py
EntityLinker ⬜ Фаза 5.2 brain/fusion/entity_linker.py
ConfidenceCalibrator ⬜ Фаза 5.3 brain/fusion/confidence_calibrator.py
ContradictionDetector ⬜ Фаза 5.4 brain/fusion/contradiction_detector.py
CrossModalFusion (оркестратор) ⬜ Фаза 5.5 brain/fusion/fusion_engine.py

Зависимости

numpy>=1.24.0          — матричные операции, cosine similarity
torch>=2.0.0           — обучение проекционных матриц (CPU)
brain/core/events.py   ✅ (PerceptEvent, EncodedPercept)
brain/memory/          ✅ (SemanticMemory для поиска противоречий)
brain/memory/source_memory.py ✅ (trust scores для ConfidenceCalibrator)

Итог: место Ассоциативной коры в системе

Сенсорная кора → [АССОЦИАТИВНАЯ КОРА] → Memory → Cognition
                         ├── SharedSpaceProjector:
                         │   text(768d) + audio(768d) → 512d
                         │   image(512d) → 512d (уже готов)
                         ├── EntityLinker:
                         │   "нейрон" в тексте = "нейрон" на фото
                         │   cosine_sim > 0.75 → EntityCluster
                         ├── ConfidenceCalibrator:
                         │   quality × agreement × trust × recency
                         │   → confidence 0.0–1.0
                         └── ContradictionDetector:
                             два источника говорят разное?
                             → флаг + снизить confidence
                             → уведомить Cognitive Core

Ассоциативная кора — это мост между «видеть/слышать/читать» и «понимать».
После неё мозг знает не просто «вот текст» и «вот картинка», а «это одно и то же понятие, и я уверен в нём на 68%».