codon-model 0.0.4__tar.gz → 0.0.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. {codon_model-0.0.4/codon_model.egg-info → codon_model-0.0.5}/PKG-INFO +1 -1
  2. {codon_model-0.0.4 → codon_model-0.0.5}/codon/__init__.py +1 -1
  3. {codon_model-0.0.4 → codon_model-0.0.5}/codon/base.py +76 -10
  4. {codon_model-0.0.4 → codon_model-0.0.5}/codon/block/__init__.py +4 -1
  5. {codon_model-0.0.4 → codon_model-0.0.5}/codon/block/attention.py +11 -6
  6. {codon_model-0.0.4 → codon_model-0.0.5}/codon/block/embedding.py +3 -3
  7. codon_model-0.0.5/codon/block/fourier.py +106 -0
  8. {codon_model-0.0.4 → codon_model-0.0.5}/codon/block/mlp.py +38 -0
  9. {codon_model-0.0.4 → codon_model-0.0.5}/codon/block/transformer.py +42 -13
  10. codon_model-0.0.5/codon/cli.py +48 -0
  11. codon_model-0.0.5/codon/dev/clear.py +41 -0
  12. codon_model-0.0.5/codon/dev/hash.py +54 -0
  13. {codon_model-0.0.4 → codon_model-0.0.5}/codon/exp/block/bio.py +1 -1
  14. {codon_model-0.0.4 → codon_model-0.0.5}/codon/kit/train/__init__.py +3 -1
  15. codon_model-0.0.5/codon/kit/train/language.py +123 -0
  16. {codon_model-0.0.4 → codon_model-0.0.5}/codon/motif/base.py +4 -8
  17. codon_model-0.0.5/codon/motif/data/__init__.py +7 -0
  18. codon_model-0.0.5/codon/motif/data/prev1.py +87 -0
  19. codon_model-0.0.5/codon/motif/data/sft.py +161 -0
  20. {codon_model-0.0.4 → codon_model-0.0.5}/codon/motif/motif_a1.py +11 -14
  21. {codon_model-0.0.4 → codon_model-0.0.5}/codon/motif/motif_v1.py +2 -3
  22. {codon_model-0.0.4 → codon_model-0.0.5}/codon/ops/attention.py +10 -17
  23. codon_model-0.0.5/codon/ops/fourier.py +33 -0
  24. {codon_model-0.0.4 → codon_model-0.0.5}/codon/ops/pixelshuffle.py +0 -1
  25. codon_model-0.0.5/codon/utils/data/__init__.py +29 -0
  26. codon_model-0.0.5/codon/utils/data/base.py +404 -0
  27. codon_model-0.0.5/codon/utils/data/chunked.py +192 -0
  28. codon_model-0.0.5/codon/utils/generate.py +349 -0
  29. codon_model-0.0.5/codon/utils/layer/__init__.py +0 -0
  30. codon_model-0.0.5/codon/utils/lifecycle.py +56 -0
  31. codon_model-0.0.5/codon/utils/plan.py +314 -0
  32. codon_model-0.0.5/codon/utils/session.py +323 -0
  33. {codon_model-0.0.4 → codon_model-0.0.5}/codon/utils/tokens.py +99 -26
  34. {codon_model-0.0.4 → codon_model-0.0.5/codon_model.egg-info}/PKG-INFO +1 -1
  35. {codon_model-0.0.4 → codon_model-0.0.5}/codon_model.egg-info/SOURCES.txt +22 -11
  36. codon_model-0.0.5/codon_model.egg-info/entry_points.txt +2 -0
  37. {codon_model-0.0.4 → codon_model-0.0.5}/setup.py +5 -0
  38. codon_model-0.0.4/codon/utils/dataset/__init__.py +0 -22
  39. codon_model-0.0.4/codon/utils/dataset/base.py +0 -124
  40. codon_model-0.0.4/codon/utils/dataset/conflux/base.py +0 -316
  41. codon_model-0.0.4/codon/utils/dataset/conflux/reader.py +0 -239
  42. codon_model-0.0.4/codon/utils/dataset/conflux/writer.py +0 -229
  43. codon_model-0.0.4/codon/utils/dataset/corpus.py +0 -630
  44. codon_model-0.0.4/test/test_conflux_dataset.py +0 -113
  45. {codon_model-0.0.4 → codon_model-0.0.5}/LICENSE +0 -0
  46. {codon_model-0.0.4 → codon_model-0.0.5}/codon/block/bio/__init__.py +0 -0
  47. {codon_model-0.0.4 → codon_model-0.0.5}/codon/block/bio/hebian.py +0 -0
  48. {codon_model-0.0.4 → codon_model-0.0.5}/codon/block/bio/predictive.py +0 -0
  49. {codon_model-0.0.4 → codon_model-0.0.5}/codon/block/codebook.py +0 -0
  50. {codon_model-0.0.4 → codon_model-0.0.5}/codon/block/conv.py +0 -0
  51. {codon_model-0.0.4 → codon_model-0.0.5}/codon/block/film.py +0 -0
  52. {codon_model-0.0.4 → codon_model-0.0.5}/codon/block/fusion.py +0 -0
  53. {codon_model-0.0.4 → codon_model-0.0.5}/codon/block/lora.py +0 -0
  54. {codon_model-0.0.4 → codon_model-0.0.5}/codon/block/manifold.py +0 -0
  55. {codon_model-0.0.4 → codon_model-0.0.5}/codon/block/moe.py +0 -0
  56. {codon_model-0.0.4 → codon_model-0.0.5}/codon/block/pixelshuffle.py +0 -0
  57. {codon_model-0.0.4/codon/exp → codon_model-0.0.5/codon/dev}/__init__.py +0 -0
  58. {codon_model-0.0.4/codon/exp/block → codon_model-0.0.5/codon/exp}/__init__.py +0 -0
  59. {codon_model-0.0.4/codon/exp/ops → codon_model-0.0.5/codon/exp/block}/__init__.py +0 -0
  60. {codon_model-0.0.4 → codon_model-0.0.5}/codon/exp/block/manifold.py +0 -0
  61. {codon_model-0.0.4 → codon_model-0.0.5}/codon/exp/block/moe.py +0 -0
  62. {codon_model-0.0.4/codon/kit → codon_model-0.0.5/codon/exp/ops}/__init__.py +0 -0
  63. {codon_model-0.0.4/codon/utils → codon_model-0.0.5/codon/kit}/__init__.py +0 -0
  64. {codon_model-0.0.4 → codon_model-0.0.5}/codon/kit/train/vision.py +0 -0
  65. {codon_model-0.0.4 → codon_model-0.0.5}/codon/model/__init__.py +0 -0
  66. {codon_model-0.0.4 → codon_model-0.0.5}/codon/model/patch_disc.py +0 -0
  67. {codon_model-0.0.4 → codon_model-0.0.5}/codon/model/resnet.py +0 -0
  68. {codon_model-0.0.4 → codon_model-0.0.5}/codon/model/tcn.py +0 -0
  69. {codon_model-0.0.4 → codon_model-0.0.5}/codon/motif/__init__.py +0 -0
  70. /codon_model-0.0.4/codon/utils/dataset/conflux/__init__.py → /codon_model-0.0.5/codon/motif/motif_a2.py +0 -0
  71. {codon_model-0.0.4 → codon_model-0.0.5}/codon/ops/__init__.py +0 -0
  72. {codon_model-0.0.4 → codon_model-0.0.5}/codon/ops/bio.py +0 -0
  73. {codon_model-0.0.4 → codon_model-0.0.5}/codon/ops/manifold/__init__.py +0 -0
  74. {codon_model-0.0.4 → codon_model-0.0.5}/codon/ops/manifold/conv.py +0 -0
  75. {codon_model-0.0.4 → codon_model-0.0.5}/codon/ops/manifold/linear.py +0 -0
  76. {codon_model-0.0.4/codon/utils/layer → codon_model-0.0.5/codon/utils}/__init__.py +0 -0
  77. {codon_model-0.0.4/codon/utils/dataset → codon_model-0.0.5/codon/utils/data}/dataviewer.py +0 -0
  78. {codon_model-0.0.4/codon/utils/dataset → codon_model-0.0.5/codon/utils/data}/flatdata.py +0 -0
  79. {codon_model-0.0.4/codon/utils/dataset → codon_model-0.0.5/codon/utils/data}/image.py +0 -0
  80. {codon_model-0.0.4 → codon_model-0.0.5}/codon/utils/eval/__init__.py +0 -0
  81. {codon_model-0.0.4 → codon_model-0.0.5}/codon/utils/eval/activation.py +0 -0
  82. {codon_model-0.0.4 → codon_model-0.0.5}/codon/utils/eval/base.py +0 -0
  83. {codon_model-0.0.4 → codon_model-0.0.5}/codon/utils/eval/boundary.py +0 -0
  84. {codon_model-0.0.4 → codon_model-0.0.5}/codon/utils/eval/cka.py +0 -0
  85. {codon_model-0.0.4 → codon_model-0.0.5}/codon/utils/eval/confusion.py +0 -0
  86. {codon_model-0.0.4 → codon_model-0.0.5}/codon/utils/eval/gradcam.py +0 -0
  87. {codon_model-0.0.4 → codon_model-0.0.5}/codon/utils/eval/layer_rsa.py +0 -0
  88. {codon_model-0.0.4 → codon_model-0.0.5}/codon/utils/eval/rsa.py +0 -0
  89. {codon_model-0.0.4 → codon_model-0.0.5}/codon/utils/eval/selectivity.py +0 -0
  90. {codon_model-0.0.4 → codon_model-0.0.5}/codon/utils/eval/similarity.py +0 -0
  91. {codon_model-0.0.4 → codon_model-0.0.5}/codon/utils/eval/tsne.py +0 -0
  92. {codon_model-0.0.4 → codon_model-0.0.5}/codon/utils/info.py +0 -0
  93. {codon_model-0.0.4 → codon_model-0.0.5}/codon/utils/layer/lora.py +0 -0
  94. {codon_model-0.0.4 → codon_model-0.0.5}/codon/utils/layer/manifold.py +0 -0
  95. {codon_model-0.0.4 → codon_model-0.0.5}/codon/utils/mask.py +0 -0
  96. {codon_model-0.0.4 → codon_model-0.0.5}/codon/utils/safecode.py +0 -0
  97. {codon_model-0.0.4 → codon_model-0.0.5}/codon/utils/seed.py +0 -0
  98. {codon_model-0.0.4 → codon_model-0.0.5}/codon/utils/split.py +0 -0
  99. {codon_model-0.0.4 → codon_model-0.0.5}/codon/utils/theta.py +0 -0
  100. {codon_model-0.0.4 → codon_model-0.0.5}/codon/utils/transforms.py +0 -0
  101. {codon_model-0.0.4 → codon_model-0.0.5}/codon_model.egg-info/dependency_links.txt +0 -0
  102. {codon_model-0.0.4 → codon_model-0.0.5}/codon_model.egg-info/requires.txt +0 -0
  103. {codon_model-0.0.4 → codon_model-0.0.5}/codon_model.egg-info/top_level.txt +0 -0
  104. {codon_model-0.0.4 → codon_model-0.0.5}/setup.cfg +0 -0
  105. {codon_model-0.0.4 → codon_model-0.0.5}/test/test_motifv1_train.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codon-model
3
- Version: 0.0.4
3
+ Version: 0.0.5
4
4
  Summary: Codon model package
5
5
  Author: CodonTeam
6
6
  Requires-Python: >=3.8
@@ -1,5 +1,5 @@
1
1
  from typing import Optional
2
2
 
3
- __version__ = '0.0.4'
3
+ __version__ = '0.0.5'
4
4
 
5
5
  __seed__: Optional[int] = None
@@ -5,6 +5,7 @@ import torch.nn.functional as F
5
5
  from typing import Callable, Any, Iterator, Union
6
6
 
7
7
  from safetensors.torch import save_model as safe_save_model
8
+ from safetensors.torch import save_file as safe_save_file
8
9
  from safetensors.torch import load_model as safe_load_model
9
10
 
10
11
 
@@ -133,41 +134,106 @@ class BasicModel(nn.Module):
133
134
 
134
135
  return total
135
136
 
136
- def load_pretrained(self, path: str) -> 'BasicModel':
137
+ def load_pretrained(self, path: str, strict: bool = False) -> 'BasicModel':
137
138
  '''
138
139
  Load a pretrained model from a file.
139
-
140
140
  Args:
141
141
  path (str): The path to the model file.
142
+ strict (bool, optional): Whether to strictly enforce that the keys
143
+ in state_dict match. Defaults to False.
142
144
  '''
143
145
  if path.endswith('.safetensors'):
144
- safe_load_model(self, path)
146
+ safe_load_model(self, path, strict=strict)
145
147
  return self
146
-
147
148
  state_dict = torch.load(path, map_location=self.device)
148
-
149
149
  if isinstance(state_dict, dict):
150
150
  if 'model_state_dict' in state_dict:
151
151
  state_dict = state_dict['model_state_dict']
152
152
  elif 'state_dict' in state_dict:
153
153
  state_dict = state_dict['state_dict']
154
+ elif 'model' in state_dict:
155
+ state_dict = state_dict['model']
154
156
 
155
- self.load_state_dict(state_dict)
156
-
157
+ clean_state_dict = {k.replace('_orig_mod.', ''): v for k, v in state_dict.items()}
158
+
159
+ self.load_state_dict(clean_state_dict, strict=strict)
157
160
  return self
158
161
 
159
- def save_pretrained(self, path: str) -> 'BasicModel':
162
+ def save_pretrained(
163
+ self,
164
+ path: str,
165
+ trainable_only: bool = False,
166
+ include_buffer: bool = True,
167
+ exclude_modules: list[Union[type, nn.Module]] = None,
168
+ only: list[str] = None,
169
+ exclude: list[str] = None
170
+ ) -> 'BasicModel':
160
171
  '''
161
172
  Save the model to a file.
162
173
 
163
174
  Args:
164
175
  path (str): The path to save the model file.
176
+ trainable_only (bool, optional): If True, only save parameters that require gradients.
177
+ include_buffer (bool, optional): If False, exclude registered buffers from the saved file.
178
+ exclude_modules (list[Union[type, nn.Module]], optional): Module types or instances to exclude.
179
+ only (list[str], optional): If provided, only save parameters whose keys contain ANY of these strings.
180
+ exclude (list[str], optional): If provided, exclude parameters whose keys contain ANY of these strings.
165
181
  '''
182
+ state_dict = self.state_dict()
183
+ is_modified = False
184
+
185
+ exclude_prefixes = []
186
+ if exclude_modules:
187
+ exclude_types = tuple(t for t in exclude_modules if isinstance(t, type))
188
+ exclude_instances = set(m for m in exclude_modules if not isinstance(m, type))
189
+
190
+ for name, module in self.named_modules():
191
+ if module in exclude_instances or (exclude_types and isinstance(module, exclude_types)):
192
+ if name != '': exclude_prefixes.append(name + '.')
193
+ exclude_prefixes = tuple(exclude_prefixes)
194
+
195
+ has_filter = trainable_only or not include_buffer or exclude_prefixes or only or exclude
196
+
197
+ if has_filter:
198
+ trainable_names = {name for name, p in self.named_parameters() if p.requires_grad}
199
+ buffer_names = {name for name, _ in self.named_buffers()}
200
+
201
+ filtered_dict = {}
202
+ for key, tensor in state_dict.items():
203
+ keep = True
204
+
205
+ if exclude_prefixes and key.startswith(exclude_prefixes):
206
+ keep = False
207
+
208
+ elif exclude and any(kw in key for kw in exclude):
209
+ keep = False
210
+
211
+ elif only and not any(kw in key for kw in only):
212
+ keep = False
213
+
214
+ else:
215
+ is_buffer = key in buffer_names
216
+ if not include_buffer and is_buffer:
217
+ keep = False
218
+ elif trainable_only and not is_buffer and key not in trainable_names:
219
+ keep = False
220
+
221
+ if keep:
222
+ filtered_dict[key] = tensor
223
+ else:
224
+ is_modified = True
225
+
226
+ if is_modified:
227
+ state_dict = filtered_dict
228
+
166
229
  if path.endswith('.safetensors'):
167
- safe_save_model(self, path)
230
+ if not is_modified:
231
+ safe_save_model(self, path)
232
+ else:
233
+ safe_save_file(state_dict, path)
168
234
  else:
169
- state_dict = self.state_dict()
170
235
  torch.save(state_dict, path)
236
+
171
237
  return self
172
238
 
173
239
  def freeze(self) -> 'BasicModel':
@@ -36,6 +36,7 @@ from .manifold import (
36
36
  BasicManifoldLinear, RiemannianManifoldLinear,
37
37
  BasicManifoldConv2d, RiemannianManifoldConv2d
38
38
  )
39
+ from .fourier import MultiHeadFourier
39
40
 
40
41
  __all__ = [
41
42
  # attention
@@ -90,5 +91,7 @@ __all__ = [
90
91
  'BasicManifoldLinear',
91
92
  'RiemannianManifoldLinear',
92
93
  'BasicManifoldConv2d',
93
- 'RiemannianManifoldConv2d'
94
+ 'RiemannianManifoldConv2d',
95
+ # Fourier
96
+ 'MultiHeadFourier',
94
97
  ]
@@ -1,6 +1,9 @@
1
1
  from codon.base import *
2
2
  from codon.block.embedding import BasicEmbedding
3
- from codon.ops.attention import AttentionOutput, apply_attention
3
+ from codon.ops.attention import (
4
+ AttentionOutput,
5
+ apply_attention
6
+ )
4
7
 
5
8
 
6
9
  class MultiHeadAttention(BasicModel):
@@ -25,6 +28,7 @@ class MultiHeadAttention(BasicModel):
25
28
  use_qk_norm=True,
26
29
  use_gate=False,
27
30
  dropout=0.1,
31
+ bias: bool=True,
28
32
  is_causal=True
29
33
  ):
30
34
  '''
@@ -65,12 +69,12 @@ class MultiHeadAttention(BasicModel):
65
69
  self.k_norm = nn.RMSNorm(self.head_dim)
66
70
 
67
71
  if use_gate:
68
- self.g_proj = nn.Linear(hidden_size, hidden_size)
72
+ self.g_proj = nn.Linear(hidden_size, hidden_size, bias=bias)
69
73
 
70
- self.q_proj = nn.Linear(hidden_size, hidden_size)
71
- self.k_proj = nn.Linear(hidden_size, self.kv_dim)
72
- self.v_proj = nn.Linear(hidden_size, self.kv_dim)
73
- self.o_proj = nn.Linear(hidden_size, hidden_size)
74
+ self.q_proj = nn.Linear(hidden_size, hidden_size, bias=bias)
75
+ self.k_proj = nn.Linear(hidden_size, self.kv_dim, bias=bias)
76
+ self.v_proj = nn.Linear(hidden_size, self.kv_dim, bias=bias)
77
+ self.o_proj = nn.Linear(hidden_size, hidden_size, bias=bias)
74
78
 
75
79
  def forward(
76
80
  self,
@@ -171,3 +175,4 @@ class MultiHeadAttention(BasicModel):
171
175
  attention_weights=attention_weights,
172
176
  past_key_value=current_key_value
173
177
  )
178
+
@@ -69,7 +69,7 @@ class SinusoidalEmbedding(BasicEmbedding):
69
69
  pe[:, 1::2] = torch.cos(position * div_term)
70
70
 
71
71
  pe = pe.unsqueeze(0)
72
- self.register_buffer('pe', pe)
72
+ self.register_buffer('pe', pe, persistent=False)
73
73
 
74
74
  def forward(self, x: torch.Tensor, positions: torch.Tensor = None, start_pos: int = 0) -> torch.Tensor:
75
75
  '''
@@ -132,8 +132,8 @@ class BasicRotaryEmbedding(BasicEmbedding):
132
132
 
133
133
  emb = torch.cat((freqs, freqs), dim=-1)
134
134
 
135
- self.register_buffer('cos_cached', emb.cos())
136
- self.register_buffer('sin_cached', emb.sin())
135
+ self.register_buffer('cos_cached', emb.cos(), persistent=False)
136
+ self.register_buffer('sin_cached', emb.sin(), persistent=False)
137
137
 
138
138
  def _rotate_half(self, x: torch.Tensor) -> torch.Tensor:
139
139
  '''
@@ -0,0 +1,106 @@
1
+ import torch
2
+ import torch.nn as nn
3
+ import torch.nn.functional as F
4
+
5
+ from codon.base import BasicModel
6
+ from codon.ops.attention import AttentionOutput
7
+ from codon.ops.fourier import apply_fourier_mixing
8
+
9
+
10
+ class MultiHeadFourier(BasicModel):
11
+ '''
12
+ Multi-Head Fourier (MHF) module from 'Caracal: Causal Architecture via Spectral Mixing'.
13
+ Replaces dense Attention with O(L log L) frequency-domain mixing.
14
+ '''
15
+ def __init__(
16
+ self,
17
+ hidden_size: int,
18
+ num_heads: int,
19
+ **kwargs
20
+ ):
21
+ super().__init__()
22
+
23
+ assert hidden_size % num_heads == 0, 'hidden_size must be divisible by num_heads'
24
+
25
+ self.d_model = hidden_size
26
+ self.n_heads = num_heads
27
+ self.d_head = hidden_size // num_heads
28
+
29
+ self.pre_conv = nn.Conv1d(
30
+ in_channels=self.d_model,
31
+ out_channels=self.d_model,
32
+ kernel_size=3,
33
+ groups=self.d_model,
34
+ bias=False
35
+ )
36
+ self.ln = nn.LayerNorm(self.d_model)
37
+ self.silu = nn.SiLU()
38
+
39
+ self.W_V = nn.Linear(self.d_model, self.d_model)
40
+ self.W_G1 = nn.Linear(self.d_model, self.d_model)
41
+ self.W_G2 = nn.Conv1d(
42
+ in_channels=self.d_model,
43
+ out_channels=self.d_model,
44
+ kernel_size=1,
45
+ groups=self.n_heads
46
+ )
47
+
48
+ self.linear = nn.Linear(self.d_model, self.d_model)
49
+ self.linear.NEED_SCALE_INIT = 1
50
+
51
+ def forward(
52
+ self,
53
+ hidden_states: torch.Tensor,
54
+ use_cache: bool = False,
55
+ past_key_value: tuple = None,
56
+ **kwargs
57
+ ) -> AttentionOutput:
58
+
59
+ batch_size, seq_len, _ = hidden_states.size()
60
+
61
+ x_permuted = hidden_states.permute(0, 2, 1) # [B, D, L]
62
+
63
+ if past_key_value is not None:
64
+ conv_state, v_cache, g_cache = past_key_value
65
+ x_padded = torch.cat([conv_state, x_permuted], dim=2)
66
+ x = self.pre_conv(x_padded).permute(0, 2, 1) # [B, 1, D]
67
+
68
+ new_conv_state = x_padded[:, :, 1:]
69
+ else:
70
+ padding = self.pre_conv.kernel_size[0] - 1
71
+ x_padded = F.pad(x_permuted, (padding, 0))
72
+ x = self.pre_conv(x_padded).permute(0, 2, 1) # [B, L, D]
73
+
74
+ new_conv_state = x_padded[:, :, -padding:] if use_cache else None
75
+
76
+ x_norm = self.ln(x)
77
+
78
+ x_v = self.W_V(x_norm).reshape(batch_size, seq_len, self.n_heads, self.d_head).transpose(1, 2)
79
+
80
+ x_g = self.W_G1(x_norm).transpose(1, 2)
81
+ x_g = self.W_G2(self.silu(x_g)).transpose(1, 2)
82
+ x_g = x_g.reshape(batch_size, seq_len, self.n_heads, self.d_head).transpose(1, 2)
83
+
84
+ if past_key_value is not None:
85
+ new_v_cache = torch.cat([v_cache, x_v], dim=2)
86
+ new_g_cache = torch.cat([g_cache, x_g], dim=2)
87
+
88
+ g_flipped = torch.flip(new_g_cache, dims=[2])
89
+
90
+ x_mixed = torch.sum(new_v_cache * g_flipped, dim=2, keepdim=True)
91
+ else:
92
+ x_mixed = apply_fourier_mixing(x_v, x_g, seq_len)
93
+
94
+ new_v_cache = x_v if use_cache else None
95
+ new_g_cache = x_g if use_cache else None
96
+
97
+ x_mixed = x_mixed.transpose(1, 2).contiguous().reshape(batch_size, seq_len, self.d_model)
98
+ output = self.linear(x_mixed)
99
+
100
+ current_key_value = (new_conv_state, new_v_cache, new_g_cache) if use_cache else None
101
+
102
+ return AttentionOutput(
103
+ output=output,
104
+ attention_weights=None,
105
+ past_key_value=current_key_value
106
+ )
@@ -86,3 +86,41 @@ class MLP(BasicModel):
86
86
  x = self.dropout(x)
87
87
  x = self.fc2(x)
88
88
  return x
89
+
90
+ @staticmethod
91
+ def SwiGLU(
92
+ in_features: int,
93
+ hidden_features: int = None,
94
+ out_features: int = None,
95
+ bias: bool = False,
96
+ dropout: float = 0.0,
97
+ ) -> 'MLP':
98
+ '''
99
+ Factory method to create a SwiGLU MLP module.
100
+
101
+ SwiGLU formulation:
102
+ output = down_proj(SiLU(gate_proj(x)) * up_proj(x))
103
+
104
+ Args:
105
+ in_features (int): Input dimension.
106
+ hidden_features (int): Intermediate dimension (gate & up proj).
107
+ out_features (int, optional): Output dimension. Defaults to in_features.
108
+ bias (bool, optional): Whether to use bias. LLMs typically set False. Defaults to False.
109
+ dropout (float, optional): Dropout rate. Usually 0.0 for SwiGLU. Defaults to 0.0.
110
+
111
+ Returns:
112
+ MLP: Configured SwiGLU module.
113
+ '''
114
+ if hidden_features is None:
115
+ h = int(in_features * 8 / 3)
116
+ hidden_features = (h + 127) // 128 * 128
117
+
118
+ return MLP(
119
+ in_features=in_features,
120
+ hidden_features=hidden_features,
121
+ out_features=out_features,
122
+ bias=bias,
123
+ use_gate=True,
124
+ dropout=dropout,
125
+ act_layer='silu'
126
+ )
@@ -5,6 +5,7 @@ from typing import Union, Optional, Tuple
5
5
  from codon.utils.safecode import safecode
6
6
  from codon.block.embedding import BasicEmbedding
7
7
  from codon.block.attention import MultiHeadAttention, AttentionOutput
8
+ from codon.block.fourier import MultiHeadFourier
8
9
  from codon.block.mlp import MLP
9
10
  from codon.block.moe import MoE, MoEOutput
10
11
 
@@ -75,6 +76,8 @@ class _TransformerDecoder(BasicModel):
75
76
  use_qk_norm=True,
76
77
  use_attn_gate=False,
77
78
  dropout=0.1,
79
+ attn_type: str = 'multihead',
80
+ attn_bias: bool=False,
78
81
  idx: Union[int, str] = None
79
82
  ):
80
83
  '''
@@ -97,17 +100,32 @@ class _TransformerDecoder(BasicModel):
97
100
  self.num_kv_heads = num_kv_heads
98
101
  self.use_qk_norm = use_qk_norm
99
102
  self.use_attn_gate = use_attn_gate
103
+ self.attn_bias = attn_bias
104
+ self.attn_type = attn_type.lower()
100
105
 
101
106
  self.attn_norm = nn.RMSNorm(model_dim)
102
- self.attn = MultiHeadAttention(
103
- hidden_size=model_dim,
104
- num_heads=num_heads,
105
- num_kv_heads=num_kv_heads,
106
- use_qk_norm=use_qk_norm,
107
- use_gate=use_attn_gate,
108
- dropout=dropout,
109
- is_causal=True
110
- )
107
+
108
+ if self.attn_type in ['multihead', 'mha']:
109
+ self.attn = MultiHeadAttention(
110
+ hidden_size=model_dim,
111
+ num_heads=num_heads,
112
+ num_kv_heads=num_kv_heads,
113
+ use_qk_norm=use_qk_norm,
114
+ use_gate=use_attn_gate,
115
+ dropout=dropout,
116
+ is_causal=True,
117
+ bias=attn_bias
118
+ )
119
+
120
+ elif self.attn_type in ['fourier', 'mhf']:
121
+ self.attn = MultiHeadFourier(
122
+ hidden_size=model_dim,
123
+ num_heads=num_heads
124
+ )
125
+
126
+ else:
127
+ raise ValueError(f"Unsupported attn_type: {attn_type}. Choose from 'multihead', 'linear', or 'gated_linear'.")
128
+
111
129
  self.fn_norm = nn.RMSNorm(model_dim)
112
130
  self.dropout = nn.Dropout(dropout)
113
131
 
@@ -228,7 +246,11 @@ class TransformerDenseDecoder(_TransformerDecoder):
228
246
  use_mlp_gate: bool = False,
229
247
  use_qk_norm: bool = True,
230
248
  use_attn_gate: bool = False,
249
+ attn_type: str = 'multihead',
250
+ use_swiglu: bool = False,
231
251
  dropout: float = 0.1,
252
+ attn_bias: bool=False,
253
+ mlp_bias: bool=False,
232
254
  idx: Union[int, str] = None
233
255
  ):
234
256
  '''
@@ -252,15 +274,18 @@ class TransformerDenseDecoder(_TransformerDecoder):
252
274
  use_qk_norm=use_qk_norm,
253
275
  use_attn_gate=use_attn_gate,
254
276
  dropout=dropout,
255
- idx=idx
277
+ attn_type=attn_type,
278
+ idx=idx,
279
+ attn_bias=attn_bias
256
280
  )
257
281
  self.mlp = MLP(
258
282
  in_features=model_dim,
259
283
  hidden_features=int(model_dim * mlp_ratio),
260
284
  out_features=model_dim,
261
285
  use_gate=use_mlp_gate,
262
- dropout=dropout
263
- )
286
+ dropout=dropout,
287
+ bias=mlp_bias
288
+ ) if not use_swiglu else MLP.SwiGLU(model_dim)
264
289
 
265
290
  def flow(self, x: torch.Tensor) -> FlowOutput:
266
291
  '''
@@ -294,7 +319,9 @@ class TransformerMoEDecoder(_TransformerDecoder):
294
319
  use_expert_gate: bool = False,
295
320
  use_qk_norm: bool = True,
296
321
  use_attn_gate: bool = False,
322
+ attn_type: str = 'multihead',
297
323
  dropout: float = 0.1,
324
+ attn_bias: bool=False,
298
325
  idx: Union[int, str] = None
299
326
  ):
300
327
  '''
@@ -321,7 +348,9 @@ class TransformerMoEDecoder(_TransformerDecoder):
321
348
  use_qk_norm=use_qk_norm,
322
349
  use_attn_gate=use_attn_gate,
323
350
  dropout=dropout,
324
- idx=idx
351
+ attn_type=attn_type,
352
+ idx=idx,
353
+ attn_bias=attn_bias
325
354
  )
326
355
  self.moe = MoE(
327
356
  model_dim=model_dim,
@@ -0,0 +1,48 @@
1
+ import argparse
2
+ import os
3
+
4
+ from codon.dev.hash import hash_target
5
+ from codon.dev.clear import clear_pycache
6
+
7
+ def handle_hash(args):
8
+ '''处理 codon hash 命令'''
9
+ try:
10
+ results = hash_target(args.filename_or_dirname)
11
+ for path, md5_val in results.items():
12
+ print(f'{md5_val} {path}')
13
+ except ValueError as e:
14
+ print(e)
15
+ except Exception as e:
16
+ print(f'发生意外错误: {e}')
17
+
18
+ def handle_clear(args):
19
+ '''处理 codon clear 命令'''
20
+ if not os.path.isdir(args.target_path):
21
+ print(f'错误: 目录不存在 - {args.target_path}')
22
+ return
23
+ clear_pycache(args.target_path)
24
+
25
+ def main():
26
+ parser = argparse.ArgumentParser(
27
+ prog='codon',
28
+ description='Codon Model 统一命令行工具箱'
29
+ )
30
+
31
+ subparsers = parser.add_subparsers(title='可用子命令', dest='command', required=True)
32
+
33
+ # codon hash
34
+ parser_hash = subparsers.add_parser('hash', help='计算文件或目录的 MD5 值')
35
+ parser_hash.add_argument('filename_or_dirname', type=str, help='需要计算 MD5 的文件或文件夹路径')
36
+ parser_hash.set_defaults(func=handle_hash)
37
+
38
+ # codon clear
39
+ parser_clear = subparsers.add_parser('clear', help='递归清理目录下的所有 __pycache__ 缓存')
40
+ parser_clear.add_argument('target_path', type=str, nargs='?', default='.',
41
+ help='要清理的根目录路径 (默认为当前所在目录)')
42
+ parser_clear.set_defaults(func=handle_clear)
43
+
44
+ args = parser.parse_args()
45
+ args.func(args)
46
+
47
+ if __name__ == '__main__':
48
+ main()
@@ -0,0 +1,41 @@
1
+ import os
2
+ import shutil
3
+ import argparse
4
+
5
+ def clear_pycache(target_dir: str):
6
+ '''
7
+ 递归遍历并删除目标路径下的所有 __pycache__ 文件夹。
8
+
9
+ 参数:
10
+ target_dir (str): 需要清理的根目录路径。
11
+ '''
12
+ deleted_count = 0
13
+ target_dir = os.path.abspath(target_dir)
14
+
15
+ print(f'开始清理 {target_dir} 下的 __pycache__ ...')
16
+
17
+ for root, dirs, files in os.walk(target_dir):
18
+ if '__pycache__' in dirs:
19
+ cache_dir = os.path.join(root, '__pycache__')
20
+ try:
21
+ shutil.rmtree(cache_dir)
22
+ print(f'Deleted: {cache_dir}')
23
+ deleted_count += 1
24
+
25
+ dirs.remove('__pycache__')
26
+ except Exception as e:
27
+ print(f'Error deleting {cache_dir}: {e}')
28
+
29
+ print(f'清理完成。共移除了 {deleted_count} 个 __pycache__ 缓存目录。')
30
+
31
+ def main():
32
+ parser = argparse.ArgumentParser(description='递归清理目标路径下的所有 __pycache__ 文件夹')
33
+ parser.add_argument('target_path', type=str, nargs='?', default='.',
34
+ help='要清理的根目录路径 (默认为当前所在目录)')
35
+ args = parser.parse_args()
36
+
37
+ if not os.path.isdir(args.target_path):
38
+ print(f'错误: 目录不存在 - {args.target_path}')
39
+ return
40
+
41
+ clear_pycache(args.target_path)
@@ -0,0 +1,54 @@
1
+ import hashlib
2
+ import os
3
+ import argparse
4
+ from typing import Dict
5
+
6
+ from tqdm import tqdm
7
+
8
+ def calculate_md5(file_path: str, chunk_size: int = 8192) -> str:
9
+ '''
10
+ 计算单个文件的 MD5 摘要,带有阅后即焚的进度条。
11
+ '''
12
+ md5_hash = hashlib.md5()
13
+ try:
14
+ total_size = os.path.getsize(file_path)
15
+ with tqdm(total=total_size, unit='B', unit_scale=True, unit_divisor=1024,
16
+ desc=f'Hashing {os.path.basename(file_path)}', leave=False) as pbar:
17
+ with open(file_path, 'rb') as f:
18
+ for chunk in iter(lambda: f.read(chunk_size), b''):
19
+ md5_hash.update(chunk)
20
+ pbar.update(len(chunk))
21
+
22
+ return md5_hash.hexdigest()
23
+ except Exception as e:
24
+ return f'Error: {e}'
25
+
26
+ def hash_target(target_path: str) -> Dict[str, str]:
27
+ results = {}
28
+ if os.path.isfile(target_path):
29
+ results[target_path] = calculate_md5(target_path)
30
+ elif os.path.isdir(target_path):
31
+ for root, _, files in os.walk(target_path):
32
+ for file in files:
33
+ file_path = os.path.join(root, file)
34
+ results[file_path] = calculate_md5(file_path)
35
+ else:
36
+ raise ValueError(f'无效的路径: {target_path}')
37
+
38
+ return results
39
+
40
+ def main():
41
+ parser = argparse.ArgumentParser(description='计算文件或目录下所有文件的 MD5 值')
42
+ parser.add_argument('target', type=str, help='需要计算 MD5 的文件或文件夹路径')
43
+ args = parser.parse_args()
44
+
45
+ try:
46
+ results = hash_target(args.target)
47
+ for path, md5_val in results.items():
48
+ path = path.replace('\\', '/')
49
+ print(f'{md5_val} ➜ {path}')
50
+ except ValueError as e:
51
+ print(e)
52
+
53
+ if __name__ == '__main__':
54
+ main()
@@ -3,7 +3,7 @@ from codon.base import *
3
3
  from typing import List, Optional
4
4
  from dataclasses import dataclass
5
5
 
6
- from codon.utils.dataset.base import CodonDataset
6
+ from codon.utils.data.base import CodonDataset
7
7
 
8
8
  @dataclass
9
9
  class EABStats:
@@ -1,6 +1,8 @@
1
1
  from .vision import auto_vision_train, AutoVisionTrainResult
2
+ from .language import run_sanity_check
2
3
 
3
4
  __all__ = [
4
5
  'auto_vision_train',
5
- 'AutoVisionTrainResult'
6
+ 'AutoVisionTrainResult',
7
+ 'run_sanity_check'
6
8
  ]