openarchx 0.1.0__py3-none-any.whl

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 (43) hide show
  1. openarchx/__init__.py +11 -0
  2. openarchx/core/tensor.py +179 -0
  3. openarchx/cuda/__init__.py +27 -0
  4. openarchx/cuda/cuda_ops.py +296 -0
  5. openarchx/layers/activations.py +63 -0
  6. openarchx/layers/base.py +40 -0
  7. openarchx/layers/cnn.py +145 -0
  8. openarchx/layers/transformer.py +131 -0
  9. openarchx/nn/__init__.py +26 -0
  10. openarchx/nn/activations.py +127 -0
  11. openarchx/nn/containers.py +174 -0
  12. openarchx/nn/dropout.py +121 -0
  13. openarchx/nn/layers.py +338 -0
  14. openarchx/nn/losses.py +156 -0
  15. openarchx/nn/module.py +18 -0
  16. openarchx/nn/padding.py +120 -0
  17. openarchx/nn/pooling.py +318 -0
  18. openarchx/nn/rnn.py +226 -0
  19. openarchx/nn/transformers.py +187 -0
  20. openarchx/optimizers/adam.py +49 -0
  21. openarchx/optimizers/adaptive.py +63 -0
  22. openarchx/optimizers/base.py +24 -0
  23. openarchx/optimizers/modern.py +98 -0
  24. openarchx/optimizers/optx.py +91 -0
  25. openarchx/optimizers/sgd.py +63 -0
  26. openarchx/quantum/circuit.py +92 -0
  27. openarchx/quantum/gates.py +126 -0
  28. openarchx/utils/__init__.py +50 -0
  29. openarchx/utils/data.py +229 -0
  30. openarchx/utils/huggingface.py +288 -0
  31. openarchx/utils/losses.py +21 -0
  32. openarchx/utils/model_io.py +553 -0
  33. openarchx/utils/pytorch.py +420 -0
  34. openarchx/utils/tensorflow.py +467 -0
  35. openarchx/utils/transforms.py +259 -0
  36. openarchx-0.1.0.dist-info/METADATA +180 -0
  37. openarchx-0.1.0.dist-info/RECORD +43 -0
  38. openarchx-0.1.0.dist-info/WHEEL +5 -0
  39. openarchx-0.1.0.dist-info/licenses/LICENSE +21 -0
  40. openarchx-0.1.0.dist-info/top_level.txt +2 -0
  41. tests/__init__.py +1 -0
  42. tests/test_cuda_ops.py +205 -0
  43. tests/test_integrations.py +236 -0
@@ -0,0 +1,467 @@
1
+ """
2
+ TensorFlow Integration Utilities for OpenArchX.
3
+
4
+ This module provides conversion and adapter utilities for using TensorFlow models
5
+ and datasets with OpenArchX. These utilities are completely optional and do not
6
+ affect OpenArchX's core functionality, which remains independent from external libraries.
7
+ """
8
+
9
+ import numpy as np
10
+ import importlib.util
11
+ from ..core.tensor import Tensor
12
+
13
+
14
+ class TensorFlowModelAdapter:
15
+ """Adapter for using TensorFlow models with OpenArchX."""
16
+
17
+ def __init__(self, tf_model, device=None):
18
+ """
19
+ Initialize a TensorFlow model adapter.
20
+
21
+ Args:
22
+ tf_model: A TensorFlow/Keras model.
23
+ device: The device to run the model on ('/CPU:0', '/GPU:0', etc.).
24
+ """
25
+ # Check if tensorflow is installed
26
+ if importlib.util.find_spec("tensorflow") is None:
27
+ raise ImportError("TensorFlow is required. Install with 'pip install tensorflow'")
28
+
29
+ import tensorflow as tf
30
+
31
+ self.model = tf_model
32
+
33
+ # Handle device placement
34
+ if device is not None:
35
+ with tf.device(device):
36
+ # Create a duplicate model on the specified device
37
+ self.model = tf.keras.models.clone_model(tf_model)
38
+ self.model.set_weights(tf_model.get_weights())
39
+
40
+ def __call__(self, inputs, **kwargs):
41
+ """
42
+ Process inputs through the TensorFlow model.
43
+
44
+ Args:
45
+ inputs: Input data, can be numpy arrays, lists, or OpenArchX Tensors.
46
+ **kwargs: Additional arguments to pass to the model.
47
+
48
+ Returns:
49
+ OpenArchX Tensor containing the model output.
50
+ """
51
+ import tensorflow as tf
52
+
53
+ # Convert inputs to tf tensors
54
+ if isinstance(inputs, Tensor):
55
+ inputs = inputs.data
56
+
57
+ if isinstance(inputs, np.ndarray):
58
+ inputs = tf.convert_to_tensor(inputs, dtype=tf.float32)
59
+ elif isinstance(inputs, list):
60
+ inputs = tf.convert_to_tensor(np.array(inputs), dtype=tf.float32)
61
+ elif not isinstance(inputs, tf.Tensor):
62
+ raise TypeError(f"Unsupported input type: {type(inputs)}")
63
+
64
+ # Forward pass
65
+ outputs = self.model(inputs, training=False, **kwargs)
66
+
67
+ # Convert output to numpy and then to Tensor
68
+ if isinstance(outputs, tf.Tensor):
69
+ return Tensor(outputs.numpy())
70
+ elif isinstance(outputs, (tuple, list)):
71
+ return tuple(Tensor(output.numpy()) for output in outputs
72
+ if isinstance(output, tf.Tensor))
73
+ elif isinstance(outputs, dict):
74
+ return {k: Tensor(v.numpy()) if isinstance(v, tf.Tensor) else v
75
+ for k, v in outputs.items()}
76
+ else:
77
+ return outputs
78
+
79
+
80
+ class TensorFlowDatasetConverter:
81
+ """Utility for converting between TensorFlow and OpenArchX datasets."""
82
+
83
+ @staticmethod
84
+ def to_openarchx_dataset(tf_dataset, transform=None):
85
+ """
86
+ Convert a TensorFlow Dataset to an OpenArchX Dataset.
87
+
88
+ Args:
89
+ tf_dataset: A TensorFlow tf.data.Dataset instance.
90
+ transform: Optional transform to apply to the data.
91
+
92
+ Returns:
93
+ An OpenArchX Dataset.
94
+ """
95
+ from .data import Dataset
96
+
97
+ # Check if tensorflow is installed
98
+ if importlib.util.find_spec("tensorflow") is None:
99
+ raise ImportError("TensorFlow is required. Install with 'pip install tensorflow'")
100
+
101
+ import tensorflow as tf
102
+
103
+ class OpenArchXDatasetFromTensorFlow(Dataset):
104
+ def __init__(self, tf_dataset, transform=None):
105
+ self.tf_dataset = tf_dataset
106
+ self.transform = transform
107
+
108
+ # Convert tf.data.Dataset to a list for random access
109
+ self.data_list = list(tf_dataset.as_numpy_iterator())
110
+
111
+ def __len__(self):
112
+ return len(self.data_list)
113
+
114
+ def __getitem__(self, idx):
115
+ data = self.data_list[idx]
116
+
117
+ # Handle different return types from TensorFlow dataset
118
+ if isinstance(data, tuple) and len(data) == 2:
119
+ # Standard (input, target) format
120
+ features, target = data
121
+
122
+ # Apply transform if provided
123
+ if self.transform:
124
+ features = self.transform(features)
125
+
126
+ return features, target
127
+ else:
128
+ # Generic handling for other formats
129
+ return data
130
+
131
+ return OpenArchXDatasetFromTensorFlow(tf_dataset, transform)
132
+
133
+ @staticmethod
134
+ def from_openarchx_dataset(ox_dataset, tensor_dtype=None):
135
+ """
136
+ Convert an OpenArchX Dataset to a TensorFlow Dataset.
137
+
138
+ Args:
139
+ ox_dataset: An OpenArchX Dataset instance.
140
+ tensor_dtype: Optional dtype for the TensorFlow tensors.
141
+
142
+ Returns:
143
+ A TensorFlow tf.data.Dataset.
144
+ """
145
+ # Check if tensorflow is installed
146
+ if importlib.util.find_spec("tensorflow") is None:
147
+ raise ImportError("TensorFlow is required. Install with 'pip install tensorflow'")
148
+
149
+ import tensorflow as tf
150
+
151
+ # Use a generator to create a tf.data.Dataset
152
+ def generator():
153
+ for i in range(len(ox_dataset)):
154
+ data = ox_dataset[i]
155
+
156
+ # Handle different return types from OpenArchX dataset
157
+ if isinstance(data, tuple) and len(data) == 2:
158
+ # Standard (input, target) format
159
+ features, target = data
160
+
161
+ # Convert to numpy if needed
162
+ if isinstance(features, Tensor):
163
+ features = features.data
164
+ if isinstance(target, Tensor):
165
+ target = target.data
166
+
167
+ yield features, target
168
+ else:
169
+ # Generic handling for other formats
170
+ if isinstance(data, Tensor):
171
+ yield data.data
172
+ else:
173
+ yield data
174
+
175
+ # Get the first element to determine shapes and types
176
+ sample = ox_dataset[0]
177
+
178
+ if isinstance(sample, tuple) and len(sample) == 2:
179
+ features, target = sample
180
+ feature_shape = features.shape if hasattr(features, 'shape') else None
181
+ target_shape = target.shape if hasattr(target, 'shape') else None
182
+
183
+ feature_dtype = tensor_dtype or tf.float32
184
+ target_dtype = tensor_dtype or tf.float32
185
+
186
+ return tf.data.Dataset.from_generator(
187
+ generator,
188
+ output_signature=(
189
+ tf.TensorSpec(shape=feature_shape, dtype=feature_dtype),
190
+ tf.TensorSpec(shape=target_shape, dtype=target_dtype)
191
+ )
192
+ )
193
+ else:
194
+ sample_shape = sample.shape if hasattr(sample, 'shape') else None
195
+ sample_dtype = tensor_dtype or tf.float32
196
+
197
+ return tf.data.Dataset.from_generator(
198
+ generator,
199
+ output_signature=tf.TensorSpec(shape=sample_shape, dtype=sample_dtype)
200
+ )
201
+
202
+
203
+ class TensorFlowModelConverter:
204
+ """Utility for converting TensorFlow models to OpenArchX architecture."""
205
+
206
+ @staticmethod
207
+ def convert_model(tf_model, framework_dependence=False):
208
+ """
209
+ Convert a TensorFlow/Keras model to an OpenArchX model.
210
+
211
+ Args:
212
+ tf_model: A TensorFlow/Keras model.
213
+ framework_dependence: If True, the resulting model will still rely on TensorFlow
214
+ for forward passes. If False, it will be converted to
215
+ pure OpenArchX layers.
216
+
217
+ Returns:
218
+ An OpenArchX model.
219
+ """
220
+ # Check if tensorflow is installed
221
+ if importlib.util.find_spec("tensorflow") is None:
222
+ raise ImportError("TensorFlow is required. Install with 'pip install tensorflow'")
223
+
224
+ import tensorflow as tf
225
+ from ..nn.base import Layer, Model
226
+ from ..nn.layers import Dense, Conv2D, MaxPool2D, Flatten, Dropout
227
+
228
+ if framework_dependence:
229
+ # Create a wrapper around the TensorFlow model
230
+ class TensorFlowWrappedModel(Model):
231
+ def __init__(self, tf_model):
232
+ super().__init__()
233
+ self.tf_model = tf_model
234
+
235
+ def forward(self, x):
236
+ # Convert OpenArchX Tensor to TensorFlow tensor
237
+ if isinstance(x, Tensor):
238
+ x_tf = tf.convert_to_tensor(x.data, dtype=tf.float32)
239
+ else:
240
+ x_tf = tf.convert_to_tensor(x, dtype=tf.float32)
241
+
242
+ # Forward pass
243
+ output = self.tf_model(x_tf, training=False)
244
+
245
+ # Convert back to OpenArchX Tensor
246
+ if isinstance(output, tf.Tensor):
247
+ return Tensor(output.numpy())
248
+ else:
249
+ return output
250
+
251
+ return TensorFlowWrappedModel(tf_model)
252
+
253
+ else:
254
+ # Convert to pure OpenArchX model by translating each layer
255
+ class OpenArchXModelFromTensorFlow(Model):
256
+ def __init__(self, tf_model):
257
+ super().__init__()
258
+ self.layers = []
259
+
260
+ # Convert each layer
261
+ for layer in tf_model.layers:
262
+ # Dense (Fully Connected) layer
263
+ if isinstance(layer, tf.keras.layers.Dense):
264
+ ox_layer = Dense(layer.units)
265
+ # Set weights and biases
266
+ weights, bias = layer.get_weights()
267
+ ox_layer.weights = Tensor(weights)
268
+ ox_layer.bias = Tensor(bias)
269
+ self.layers.append(ox_layer)
270
+
271
+ # Convolutional layer
272
+ elif isinstance(layer, tf.keras.layers.Conv2D):
273
+ ox_layer = Conv2D(
274
+ filters=layer.filters,
275
+ kernel_size=layer.kernel_size,
276
+ strides=layer.strides,
277
+ padding='same' if layer.padding.lower() == 'same' else 'valid'
278
+ )
279
+ # Set weights and biases
280
+ weights, bias = layer.get_weights()
281
+ ox_layer.kernels = Tensor(weights)
282
+ ox_layer.bias = Tensor(bias)
283
+ self.layers.append(ox_layer)
284
+
285
+ # MaxPooling layer
286
+ elif isinstance(layer, tf.keras.layers.MaxPool2D):
287
+ ox_layer = MaxPool2D(
288
+ pool_size=layer.pool_size,
289
+ strides=layer.strides,
290
+ padding='same' if layer.padding.lower() == 'same' else 'valid'
291
+ )
292
+ self.layers.append(ox_layer)
293
+
294
+ # Flatten layer
295
+ elif isinstance(layer, tf.keras.layers.Flatten):
296
+ ox_layer = Flatten()
297
+ self.layers.append(ox_layer)
298
+
299
+ # Dropout layer
300
+ elif isinstance(layer, tf.keras.layers.Dropout):
301
+ ox_layer = Dropout(rate=layer.rate)
302
+ self.layers.append(ox_layer)
303
+
304
+ # Other layer types could be added as needed
305
+ else:
306
+ raise ValueError(f"Unsupported layer type: {type(layer).__name__}")
307
+
308
+ def forward(self, x):
309
+ for layer in self.layers:
310
+ x = layer(x)
311
+ return x
312
+
313
+ return OpenArchXModelFromTensorFlow(tf_model)
314
+
315
+
316
+ class ModelWeightsExtractor:
317
+ """Utility for extracting weights from TensorFlow models for use in OpenArchX."""
318
+
319
+ @staticmethod
320
+ def extract_transformer_weights(tf_model, layer_mapping=None):
321
+ """
322
+ Extract weights from a TensorFlow transformer model into a format usable by OpenArchX.
323
+
324
+ Args:
325
+ tf_model: A TensorFlow transformer model.
326
+ layer_mapping: Optional dictionary mapping TensorFlow layer names to
327
+ OpenArchX parameter names.
328
+
329
+ Returns:
330
+ Dictionary mapping OpenArchX parameter names to weights as Tensors.
331
+ """
332
+ # Check if tensorflow is installed
333
+ if importlib.util.find_spec("tensorflow") is None:
334
+ raise ImportError("TensorFlow is required. Install with 'pip install tensorflow'")
335
+
336
+ # Default mapping for common transformer architectures
337
+ default_mapping = {
338
+ 'embeddings': 'embedding',
339
+ 'encoder': 'encoder',
340
+ 'decoder': 'decoder',
341
+ 'attention': 'attention',
342
+ 'dense': 'linear',
343
+ 'layer_norm': 'norm',
344
+ 'kernel': 'weight',
345
+ 'bias': 'bias'
346
+ }
347
+
348
+ mapping = default_mapping
349
+ if layer_mapping:
350
+ mapping.update(layer_mapping)
351
+
352
+ result = {}
353
+
354
+ # Process weights
355
+ for weight in tf_model.weights:
356
+ name = weight.name
357
+ value = weight.numpy()
358
+
359
+ # Transform the name according to the mapping
360
+ transformed_name = name
361
+ for tf_key, ox_key in mapping.items():
362
+ transformed_name = transformed_name.replace(tf_key, ox_key)
363
+
364
+ # Remove any TensorFlow-specific suffixes
365
+ transformed_name = transformed_name.replace(':0', '')
366
+
367
+ # Store the weight as a Tensor
368
+ result[transformed_name] = Tensor(value)
369
+
370
+ return result
371
+
372
+
373
+ # Convenience functions
374
+
375
+ def get_tensorflow_model_adapter(tf_model, device=None):
376
+ """
377
+ Helper function to get a TensorFlow model adapter.
378
+
379
+ Args:
380
+ tf_model: A TensorFlow/Keras model.
381
+ device: The device to run the model on.
382
+
383
+ Returns:
384
+ A TensorFlowModelAdapter instance.
385
+ """
386
+ return TensorFlowModelAdapter(tf_model, device)
387
+
388
+
389
+ def convert_to_tensorflow_dataset(ox_dataset, tensor_dtype=None):
390
+ """
391
+ Convert an OpenArchX Dataset to a TensorFlow Dataset.
392
+
393
+ Args:
394
+ ox_dataset: An OpenArchX Dataset instance.
395
+ tensor_dtype: Optional dtype for the TensorFlow tensors.
396
+
397
+ Returns:
398
+ A TensorFlow Dataset.
399
+ """
400
+ return TensorFlowDatasetConverter.from_openarchx_dataset(ox_dataset, tensor_dtype)
401
+
402
+
403
+ def convert_from_tensorflow_dataset(tf_dataset, transform=None):
404
+ """
405
+ Convert a TensorFlow Dataset to an OpenArchX Dataset.
406
+
407
+ Args:
408
+ tf_dataset: A TensorFlow Dataset instance.
409
+ transform: Optional transform to apply to the data.
410
+
411
+ Returns:
412
+ An OpenArchX Dataset.
413
+ """
414
+ return TensorFlowDatasetConverter.to_openarchx_dataset(tf_dataset, transform)
415
+
416
+
417
+ def convert_tensorflow_model(tf_model, framework_dependence=False):
418
+ """
419
+ Convert a TensorFlow model to an OpenArchX model.
420
+
421
+ Args:
422
+ tf_model: A TensorFlow/Keras model.
423
+ framework_dependence: If True, the resulting model will still rely on TensorFlow.
424
+ If False, it will be converted to pure OpenArchX layers.
425
+
426
+ Returns:
427
+ An OpenArchX model.
428
+ """
429
+ return TensorFlowModelConverter.convert_model(tf_model, framework_dependence)
430
+
431
+
432
+ def extract_tensorflow_weights(tf_model):
433
+ """
434
+ Extract weights from a TensorFlow model.
435
+
436
+ Args:
437
+ tf_model: A TensorFlow model.
438
+
439
+ Returns:
440
+ Dictionary mapping parameter names to OpenArchX Tensors.
441
+ """
442
+ # Check if tensorflow is installed
443
+ if importlib.util.find_spec("tensorflow") is None:
444
+ raise ImportError("TensorFlow is required. Install with 'pip install tensorflow'")
445
+
446
+ weights_dict = {}
447
+
448
+ # Extract weights from the model
449
+ for weight in tf_model.weights:
450
+ name = weight.name.replace(':0', '') # Remove TensorFlow-specific suffix
451
+ weights_dict[name] = Tensor(weight.numpy())
452
+
453
+ return weights_dict
454
+
455
+
456
+ def extract_transformer_weights(tf_model, layer_mapping=None):
457
+ """
458
+ Extract weights from a TensorFlow transformer model for use in OpenArchX.
459
+
460
+ Args:
461
+ tf_model: A TensorFlow transformer model.
462
+ layer_mapping: Optional dictionary mapping TensorFlow layer names to OpenArchX names.
463
+
464
+ Returns:
465
+ Dictionary mapping OpenArchX parameter names to weights as Tensors.
466
+ """
467
+ return ModelWeightsExtractor.extract_transformer_weights(tf_model, layer_mapping)