Spaces:
Running
Running
adds update attribute for trl compatibility
Browse files- docs/TRACKIO_UPDATE_FIX.md +90 -0
- src/trackio.py +14 -0
- tests/test_trackio_update_fix.py +127 -0
- tests/test_update_fix.py +27 -0
docs/TRACKIO_UPDATE_FIX.md
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# TrackioConfig Update Method Fix
|
2 |
+
|
3 |
+
## Problem Description
|
4 |
+
|
5 |
+
The error `'TrackioConfig' object has no attribute 'update'` occurred because the TRL library (specifically SFTTrainer) expects the Trackio configuration object to have an `update` method, but our custom `TrackioConfig` class didn't implement it.
|
6 |
+
|
7 |
+
## Root Cause
|
8 |
+
|
9 |
+
Based on the [Trackio documentation](https://github.com/gradio-app/trackio?tab=readme-ov-file), Trackio is designed to be API compatible with `wandb.init`, `wandb.log`, and `wandb.finish`. However, the TRL library has additional expectations for the configuration object, including an `update` method that allows dynamic configuration updates.
|
10 |
+
|
11 |
+
## Solution Implementation
|
12 |
+
|
13 |
+
### 1. Added Update Method to TrackioConfig
|
14 |
+
|
15 |
+
Modified `src/trackio.py` to add the missing `update` method:
|
16 |
+
|
17 |
+
```python
|
18 |
+
class TrackioConfig:
|
19 |
+
"""Configuration class for trackio (TRL compatibility)"""
|
20 |
+
|
21 |
+
def __init__(self):
|
22 |
+
self.project_name = os.environ.get('EXPERIMENT_NAME', 'smollm3_experiment')
|
23 |
+
self.experiment_name = os.environ.get('EXPERIMENT_NAME', 'smollm3_experiment')
|
24 |
+
self.trackio_url = os.environ.get('TRACKIO_URL')
|
25 |
+
self.trackio_token = os.environ.get('TRACKIO_TOKEN')
|
26 |
+
self.hf_token = os.environ.get('HF_TOKEN')
|
27 |
+
self.dataset_repo = os.environ.get('TRACKIO_DATASET_REPO', 'tonic/trackio-experiments')
|
28 |
+
|
29 |
+
def update(self, config_dict: Dict[str, Any]):
|
30 |
+
"""
|
31 |
+
Update configuration with new values (TRL compatibility)
|
32 |
+
|
33 |
+
Args:
|
34 |
+
config_dict: Dictionary of configuration values to update
|
35 |
+
"""
|
36 |
+
for key, value in config_dict.items():
|
37 |
+
if hasattr(self, key):
|
38 |
+
setattr(self, key, value)
|
39 |
+
else:
|
40 |
+
# Add new attributes dynamically
|
41 |
+
setattr(self, key, value)
|
42 |
+
```
|
43 |
+
|
44 |
+
### 2. Key Features of the Fix
|
45 |
+
|
46 |
+
- **Dynamic Attribute Updates**: The `update` method can update existing attributes and add new ones dynamically
|
47 |
+
- **TRL Compatibility**: Satisfies TRL's expectation for a config object with an `update` method
|
48 |
+
- **Backward Compatibility**: Doesn't break existing functionality
|
49 |
+
- **Flexible Configuration**: Allows runtime configuration updates
|
50 |
+
|
51 |
+
### 3. Usage Example
|
52 |
+
|
53 |
+
```python
|
54 |
+
import trackio
|
55 |
+
|
56 |
+
# Access the config
|
57 |
+
config = trackio.config
|
58 |
+
|
59 |
+
# Update configuration
|
60 |
+
config.update({
|
61 |
+
'project_name': 'my_experiment',
|
62 |
+
'experiment_name': 'test_run_1',
|
63 |
+
'custom_setting': 'value'
|
64 |
+
})
|
65 |
+
|
66 |
+
# New attributes are added dynamically
|
67 |
+
print(config.custom_setting) # Output: 'value'
|
68 |
+
```
|
69 |
+
|
70 |
+
## Verification
|
71 |
+
|
72 |
+
The fix has been verified to work correctly:
|
73 |
+
|
74 |
+
1. **Import Test**: `import trackio` works without errors
|
75 |
+
2. **Config Access**: `trackio.config` is available
|
76 |
+
3. **Update Method**: `trackio.config.update()` method exists and works
|
77 |
+
4. **TRL Compatibility**: All TRL-expected methods are available
|
78 |
+
|
79 |
+
## Benefits
|
80 |
+
|
81 |
+
1. **Resolves Training Error**: Fixes the `'TrackioConfig' object has no attribute 'update'` error
|
82 |
+
2. **Maintains TRL Compatibility**: Ensures SFTTrainer can use Trackio for logging
|
83 |
+
3. **Dynamic Configuration**: Allows runtime configuration updates
|
84 |
+
4. **Future-Proof**: Supports additional TRL requirements
|
85 |
+
|
86 |
+
## Related Documentation
|
87 |
+
|
88 |
+
- [Trackio TRL Fix Summary](TRACKIO_TRL_FIX_SUMMARY.md)
|
89 |
+
- [Trackio Integration Guide](TRACKIO_INTEGRATION.md)
|
90 |
+
- [Monitoring Integration Guide](MONITORING_INTEGRATION_GUIDE.md)
|
src/trackio.py
CHANGED
@@ -213,6 +213,20 @@ class TrackioConfig:
|
|
213 |
self.trackio_token = os.environ.get('TRACKIO_TOKEN')
|
214 |
self.hf_token = os.environ.get('HF_TOKEN')
|
215 |
self.dataset_repo = os.environ.get('TRACKIO_DATASET_REPO', 'tonic/trackio-experiments')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
216 |
|
217 |
# Create config instance
|
218 |
config = TrackioConfig()
|
|
|
213 |
self.trackio_token = os.environ.get('TRACKIO_TOKEN')
|
214 |
self.hf_token = os.environ.get('HF_TOKEN')
|
215 |
self.dataset_repo = os.environ.get('TRACKIO_DATASET_REPO', 'tonic/trackio-experiments')
|
216 |
+
|
217 |
+
def update(self, config_dict: Dict[str, Any]):
|
218 |
+
"""
|
219 |
+
Update configuration with new values (TRL compatibility)
|
220 |
+
|
221 |
+
Args:
|
222 |
+
config_dict: Dictionary of configuration values to update
|
223 |
+
"""
|
224 |
+
for key, value in config_dict.items():
|
225 |
+
if hasattr(self, key):
|
226 |
+
setattr(self, key, value)
|
227 |
+
else:
|
228 |
+
# Add new attributes dynamically
|
229 |
+
setattr(self, key, value)
|
230 |
|
231 |
# Create config instance
|
232 |
config = TrackioConfig()
|
tests/test_trackio_update_fix.py
ADDED
@@ -0,0 +1,127 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env python3
|
2 |
+
"""
|
3 |
+
Test script to verify TrackioConfig update method fix
|
4 |
+
"""
|
5 |
+
|
6 |
+
import sys
|
7 |
+
import os
|
8 |
+
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
9 |
+
|
10 |
+
def test_trackio_config_update():
|
11 |
+
"""Test that TrackioConfig update method works correctly"""
|
12 |
+
print("π§ͺ Testing TrackioConfig update method...")
|
13 |
+
|
14 |
+
try:
|
15 |
+
# Import trackio module
|
16 |
+
import trackio
|
17 |
+
|
18 |
+
# Test that config attribute exists
|
19 |
+
assert hasattr(trackio, 'config'), "trackio.config not found"
|
20 |
+
print("β
trackio.config exists")
|
21 |
+
|
22 |
+
# Test that config has update method
|
23 |
+
config = trackio.config
|
24 |
+
assert hasattr(config, 'update'), "TrackioConfig.update method not found"
|
25 |
+
print("β
TrackioConfig.update method exists")
|
26 |
+
|
27 |
+
# Test update method functionality
|
28 |
+
test_config = {
|
29 |
+
'project_name': 'test_project',
|
30 |
+
'experiment_name': 'test_experiment',
|
31 |
+
'new_attribute': 'test_value'
|
32 |
+
}
|
33 |
+
|
34 |
+
# Call update method
|
35 |
+
config.update(test_config)
|
36 |
+
|
37 |
+
# Verify updates
|
38 |
+
assert config.project_name == 'test_project', f"Expected 'test_project', got '{config.project_name}'"
|
39 |
+
assert config.experiment_name == 'test_experiment', f"Expected 'test_experiment', got '{config.experiment_name}'"
|
40 |
+
assert config.new_attribute == 'test_value', f"Expected 'test_value', got '{config.new_attribute}'"
|
41 |
+
|
42 |
+
print("β
TrackioConfig.update method works correctly")
|
43 |
+
print("β
All attributes updated successfully")
|
44 |
+
|
45 |
+
return True
|
46 |
+
|
47 |
+
except Exception as e:
|
48 |
+
print(f"β Test failed: {e}")
|
49 |
+
return False
|
50 |
+
|
51 |
+
def test_trackio_trl_compatibility():
|
52 |
+
"""Test that trackio is fully compatible with TRL expectations"""
|
53 |
+
print("\nπ Testing TRL Compatibility...")
|
54 |
+
|
55 |
+
try:
|
56 |
+
import trackio
|
57 |
+
|
58 |
+
# Test all required functions exist
|
59 |
+
required_functions = ['init', 'log', 'finish']
|
60 |
+
for func_name in required_functions:
|
61 |
+
assert hasattr(trackio, func_name), f"trackio.{func_name} not found"
|
62 |
+
print(f"β
trackio.{func_name} exists")
|
63 |
+
|
64 |
+
# Test config attribute exists and has update method
|
65 |
+
assert hasattr(trackio, 'config'), "trackio.config not found"
|
66 |
+
assert hasattr(trackio.config, 'update'), "trackio.config.update not found"
|
67 |
+
print("β
trackio.config.update exists")
|
68 |
+
|
69 |
+
# Test that init can be called without arguments (TRL compatibility)
|
70 |
+
try:
|
71 |
+
experiment_id = trackio.init()
|
72 |
+
print(f"β
trackio.init() called successfully: {experiment_id}")
|
73 |
+
except Exception as e:
|
74 |
+
print(f"β trackio.init() failed: {e}")
|
75 |
+
return False
|
76 |
+
|
77 |
+
# Test that log can be called
|
78 |
+
try:
|
79 |
+
trackio.log({'test_metric': 1.0})
|
80 |
+
print("β
trackio.log() called successfully")
|
81 |
+
except Exception as e:
|
82 |
+
print(f"β trackio.log() failed: {e}")
|
83 |
+
return False
|
84 |
+
|
85 |
+
# Test that finish can be called
|
86 |
+
try:
|
87 |
+
trackio.finish()
|
88 |
+
print("β
trackio.finish() called successfully")
|
89 |
+
except Exception as e:
|
90 |
+
print(f"β trackio.finish() failed: {e}")
|
91 |
+
return False
|
92 |
+
|
93 |
+
print("β
All TRL compatibility tests passed")
|
94 |
+
return True
|
95 |
+
|
96 |
+
except Exception as e:
|
97 |
+
print(f"β TRL compatibility test failed: {e}")
|
98 |
+
return False
|
99 |
+
|
100 |
+
def main():
|
101 |
+
"""Run all tests"""
|
102 |
+
print("π§ͺ TrackioConfig Update Fix Test")
|
103 |
+
print("=" * 40)
|
104 |
+
|
105 |
+
# Test 1: Update method functionality
|
106 |
+
test1_passed = test_trackio_config_update()
|
107 |
+
|
108 |
+
# Test 2: TRL compatibility
|
109 |
+
test2_passed = test_trackio_trl_compatibility()
|
110 |
+
|
111 |
+
# Summary
|
112 |
+
print("\n" + "=" * 40)
|
113 |
+
print("π Test Results Summary")
|
114 |
+
print("=" * 40)
|
115 |
+
print(f"β
Update Method Test: {'PASSED' if test1_passed else 'FAILED'}")
|
116 |
+
print(f"β
TRL Compatibility Test: {'PASSED' if test2_passed else 'FAILED'}")
|
117 |
+
|
118 |
+
if test1_passed and test2_passed:
|
119 |
+
print("\nπ All tests passed! TrackioConfig update fix is working correctly.")
|
120 |
+
return True
|
121 |
+
else:
|
122 |
+
print("\nβ Some tests failed. Please check the implementation.")
|
123 |
+
return False
|
124 |
+
|
125 |
+
if __name__ == "__main__":
|
126 |
+
success = main()
|
127 |
+
sys.exit(0 if success else 1)
|
tests/test_update_fix.py
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env python3
|
2 |
+
"""
|
3 |
+
Simple test for TrackioConfig update method fix
|
4 |
+
"""
|
5 |
+
|
6 |
+
import trackio
|
7 |
+
|
8 |
+
print("Testing TrackioConfig update method...")
|
9 |
+
|
10 |
+
# Test that config exists and has update method
|
11 |
+
config = trackio.config
|
12 |
+
print(f"Config type: {type(config)}")
|
13 |
+
print(f"Has update method: {hasattr(config, 'update')}")
|
14 |
+
|
15 |
+
# Test update functionality
|
16 |
+
test_data = {
|
17 |
+
'project_name': 'test_project',
|
18 |
+
'experiment_name': 'test_experiment',
|
19 |
+
'new_attribute': 'test_value'
|
20 |
+
}
|
21 |
+
|
22 |
+
print(f"Before update - project_name: {config.project_name}")
|
23 |
+
config.update(test_data)
|
24 |
+
print(f"After update - project_name: {config.project_name}")
|
25 |
+
print(f"New attribute: {config.new_attribute}")
|
26 |
+
|
27 |
+
print("β
Update method works correctly!")
|