AGofficial commited on
Commit
4bc1d1e
·
verified ·
1 Parent(s): 9bf642a

Upload 7 files

Browse files
Files changed (8) hide show
  1. .gitattributes +1 -0
  2. LICENSE +21 -0
  3. README.md +26 -3
  4. banner.png +3 -0
  5. chat.py +318 -0
  6. feather.py +235 -0
  7. target_train.py +147 -0
  8. train.py +371 -0
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ banner.png filter=lfs diff=lfs merge=lfs -text
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2025 AG
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
README.md CHANGED
@@ -1,3 +1,26 @@
1
- ---
2
- license: mit
3
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ language:
4
+ - en
5
+ ---
6
+
7
+ <img src="banner.png" alt="AgGPT-20 Banner" width="100%">
8
+
9
+ # AgGPT-20
10
+
11
+ **AgGPT-20** is a revolutionary modular AI training framework using Scalable Feather Architecture that automatically discovers and trains on all `.txt` files in `training_corpora/`, creating specialized mini-models stored as `.feather` files in the `models/` directory. The system is extremely modular - you can train individual models using `target_train.py`, manually add `.feather` files to the models folder from other sources, or use the full multi-corpora trainer with `train.py`, and all models will be automatically discovered and used by the chat interface. Install dependencies with `pip install pandas pyarrow tqdm pyyaml`, place training data in the proper format (`user: [input]\n<pad>\nai: [response]\n<eos>`) in `training_corpora/` or `extra_corpora/`, run `python train.py` for full training or `python target_train.py` for single-file training, then chat with `python chat.py`. The architecture enables lightning-fast loading, cross-platform compatibility, and seamless model distribution - just drop any compatible `.feather` model into the models folder and it's instantly available.
12
+
13
+ ## Quick Start
14
+ ```bash
15
+ # Install dependencies
16
+ pip install pandas pyarrow tqdm pyyaml
17
+
18
+ # Train on all corpora files
19
+ python train.py
20
+
21
+ # Or train on a single target file
22
+ python target_train.py
23
+
24
+ # Start chatting
25
+ python chat.py
26
+ ```
banner.png ADDED

Git LFS Details

  • SHA256: c3221b9ec65f6151e463debbfa5009cf3b4c97afaa3d8cc08a9b26bfdc6f2286
  • Pointer size: 131 Bytes
  • Size of remote file: 925 kB
chat.py ADDED
@@ -0,0 +1,318 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import re
3
+ import random
4
+ from typing import List, Dict, Tuple, Any
5
+ from collections import defaultdict
6
+ import math
7
+ from feather import FeatherManager, similarity_score
8
+ from train import GrammarRules, PatternExtractor
9
+
10
+ class ResponseGenerator:
11
+ def __init__(self, feather_manager: FeatherManager):
12
+ self.feather_manager = feather_manager
13
+ self.pattern_extractor = PatternExtractor()
14
+ self.grammar_rules = GrammarRules()
15
+ self.models = []
16
+ self.context_window = []
17
+ self.max_context_length = 10
18
+
19
+ def load_models(self):
20
+ print("Loading mini-models...")
21
+ self.models = self.feather_manager.load_all_models()
22
+ print(f"Loaded {len(self.models)} mini-models")
23
+
24
+ if not self.models:
25
+ print("No trained models found! Please run train.py first.")
26
+ return False
27
+
28
+ return True
29
+
30
+ def calculate_model_scores(self, user_input: str) -> List[Tuple[Dict[str, Any], float]]:
31
+ if not self.models:
32
+ return []
33
+
34
+ input_pattern = self.pattern_extractor.create_pattern(user_input)
35
+ input_keywords = set(self.pattern_extractor.extract_keywords(user_input))
36
+
37
+ model_scores = []
38
+
39
+ for model in self.models:
40
+ score = 0.0
41
+ pattern_matches = 0
42
+ keyword_matches = 0
43
+
44
+ for pattern in model.get('patterns', []):
45
+ pattern_sim = self.pattern_extractor.calculate_pattern_similarity(input_pattern, pattern)
46
+ score += pattern_sim
47
+ if pattern_sim > 0.3:
48
+ pattern_matches += 1
49
+
50
+ model_keywords = set(model.get('keywords', []))
51
+ if model_keywords and input_keywords:
52
+ keyword_overlap = len(input_keywords.intersection(model_keywords))
53
+ keyword_total = len(input_keywords.union(model_keywords))
54
+ keyword_score = keyword_overlap / keyword_total if keyword_total > 0 else 0
55
+ score += keyword_score * 2
56
+ keyword_matches = keyword_overlap
57
+
58
+ confidence = model.get('confidence', 0.5)
59
+ score *= confidence
60
+
61
+ training_samples = model.get('training_samples', 1)
62
+ training_bonus = min(0.2, training_samples / 100)
63
+ score += training_bonus
64
+
65
+ context_bonus = self._calculate_context_bonus(user_input, model)
66
+ score += context_bonus
67
+
68
+ model_scores.append((model, score))
69
+
70
+ model_scores.sort(key=lambda x: x[1], reverse=True)
71
+
72
+ return model_scores
73
+
74
+ def _calculate_context_bonus(self, user_input: str, model: Dict[str, Any]) -> float:
75
+ if not self.context_window:
76
+ return 0.0
77
+
78
+ context_bonus = 0.0
79
+
80
+ for prev_input, prev_response in self.context_window[-3:]:
81
+ for pattern in model.get('patterns', [])[:5]:
82
+ pattern_sim = similarity_score(prev_input, pattern.strip())
83
+ context_bonus += pattern_sim * 0.1
84
+
85
+ return min(context_bonus, 0.3)
86
+
87
+ def select_top_models(self, model_scores: List[Tuple[Dict[str, Any], float]], top_k: int = 5) -> List[Tuple[Dict[str, Any], float]]:
88
+ valid_models = [(model, score) for model, score in model_scores if score > 0.01]
89
+
90
+ if not valid_models:
91
+ valid_models = random.sample(model_scores, min(3, len(model_scores)))
92
+
93
+ return valid_models[:top_k]
94
+
95
+ def generate_responses_from_models(self, user_input: str, top_models: List[Tuple[Dict[str, Any], float]]) -> List[Tuple[str, float]]:
96
+ responses = []
97
+ input_pattern = self.pattern_extractor.create_pattern(user_input)
98
+
99
+ for model, model_score in top_models:
100
+ model_responses = []
101
+ best_similarity = 0.0
102
+
103
+ patterns = model.get('patterns', [])
104
+ model_responses_list = model.get('responses', [])
105
+
106
+ if not patterns or not model_responses_list:
107
+ continue
108
+
109
+ best_matches = []
110
+ for i, pattern in enumerate(patterns):
111
+ if i < len(model_responses_list):
112
+ sim = self.pattern_extractor.calculate_pattern_similarity(input_pattern, pattern)
113
+ if sim > 0.1:
114
+ best_matches.append((model_responses_list[i], sim))
115
+
116
+ best_matches.sort(key=lambda x: x[1], reverse=True)
117
+
118
+ selected_responses = best_matches[:3] if best_matches else [(random.choice(model_responses_list), 0.1)]
119
+
120
+ for response, pattern_sim in selected_responses:
121
+ weight = model_score * (0.7 + pattern_sim * 0.3)
122
+ responses.append((response, weight))
123
+
124
+ return responses
125
+
126
+ def combine_responses(self, responses: List[Tuple[str, float]]) -> str:
127
+ if not responses:
128
+ return "I'm not sure how to respond to that."
129
+
130
+ filtered_responses = [(resp, weight) for resp, weight in responses if weight > 0.05]
131
+ if not filtered_responses:
132
+ filtered_responses = responses[:1]
133
+
134
+ response_groups = defaultdict(list)
135
+ for response, weight in filtered_responses:
136
+ key = ' '.join(response.split()[:3]).lower()
137
+ response_groups[key].append((response, weight))
138
+
139
+ best_responses = []
140
+ for group in response_groups.values():
141
+ best_resp, best_weight = max(group, key=lambda x: x[1])
142
+ best_responses.append((best_resp, best_weight))
143
+
144
+ if len(best_responses) > 1:
145
+ total_weight = sum(weight for _, weight in best_responses)
146
+ if total_weight > 0:
147
+ normalized_weights = [weight / total_weight for _, weight in best_responses]
148
+
149
+ rand_val = random.random()
150
+ cumsum = 0.0
151
+ for i, norm_weight in enumerate(normalized_weights):
152
+ cumsum += norm_weight
153
+ if rand_val <= cumsum:
154
+ selected_response = best_responses[i][0]
155
+ break
156
+ else:
157
+ selected_response = best_responses[0][0]
158
+ else:
159
+ selected_response = best_responses[0][0]
160
+ else:
161
+ selected_response = best_responses[0][0]
162
+
163
+ final_response = selected_response
164
+
165
+ if not final_response.endswith('<eos>'):
166
+ final_response += ' <eos>'
167
+
168
+ return final_response
169
+
170
+ def generate_response(self, user_input: str) -> str:
171
+ if not user_input.strip():
172
+ return "Please say something! <eos>"
173
+
174
+ model_scores = self.calculate_model_scores(user_input)
175
+
176
+ if not model_scores:
177
+ return "I need to learn more before I can respond properly. <eos>"
178
+
179
+ top_models = self.select_top_models(model_scores, top_k=5)
180
+
181
+ responses = self.generate_responses_from_models(user_input, top_models)
182
+
183
+ final_response = self.combine_responses(responses)
184
+
185
+ self.context_window.append((user_input, final_response))
186
+ if len(self.context_window) > self.max_context_length:
187
+ self.context_window.pop(0)
188
+
189
+ return final_response
190
+
191
+ def get_model_statistics(self) -> Dict[str, Any]:
192
+ if not self.models:
193
+ return {"total_models": 0}
194
+
195
+ total_patterns = sum(len(model.get('patterns', [])) for model in self.models)
196
+ total_responses = sum(len(model.get('responses', [])) for model in self.models)
197
+ avg_confidence = sum(model.get('confidence', 0) for model in self.models) / len(self.models)
198
+ total_training_samples = sum(model.get('training_samples', 0) for model in self.models)
199
+
200
+ return {
201
+ "total_models": len(self.models),
202
+ "total_patterns": total_patterns,
203
+ "total_responses": total_responses,
204
+ "average_confidence": avg_confidence,
205
+ "total_training_samples": total_training_samples
206
+ }
207
+
208
+
209
+ class AgGPTChat:
210
+
211
+ def __init__(self, models_dir: str = "models"):
212
+ self.feather_manager = FeatherManager(models_dir)
213
+ self.response_generator = ResponseGenerator(self.feather_manager)
214
+ self.conversation_history = []
215
+
216
+ def initialize(self) -> bool:
217
+ print("AgGPT-20 Scalable Feather Architecture Chat")
218
+ print("=" * 50)
219
+
220
+ success = self.response_generator.load_models()
221
+ if success:
222
+ stats = self.response_generator.get_model_statistics()
223
+ print(f"Model Statistics:")
224
+ print(f" Mini-models loaded: {stats['total_models']}")
225
+ print(f" Total patterns: {stats['total_patterns']}")
226
+ print(f" Total responses: {stats['total_responses']}")
227
+ print(f" Average confidence: {stats['average_confidence']:.3f}")
228
+ print(f" Training samples: {stats['total_training_samples']}")
229
+ print("=" * 50)
230
+ print("Chat initialized! Type 'quit' to exit.")
231
+ print("Large context window active - I'll remember our conversation!")
232
+ print()
233
+
234
+ return success
235
+
236
+ def chat_loop(self):
237
+ if not self.initialize():
238
+ return
239
+
240
+ while True:
241
+ try:
242
+ user_input = input("You: ").strip()
243
+
244
+ if not user_input:
245
+ continue
246
+
247
+ if user_input.lower() in ['quit', 'exit', 'bye', 'goodbye']:
248
+ print("AgGPT: Goodbye! Thanks for chatting with me! <eos>")
249
+ break
250
+
251
+ if user_input.lower() in ['stats', 'statistics']:
252
+ stats = self.response_generator.get_model_statistics()
253
+ print("Current Statistics:")
254
+ for key, value in stats.items():
255
+ print(f" {key}: {value}")
256
+ continue
257
+
258
+ if user_input.lower() in ['clear', 'reset']:
259
+ self.response_generator.context_window = []
260
+ print("Context cleared!")
261
+ continue
262
+
263
+ print("AgGPT: ", end="", flush=True)
264
+ response = self.response_generator.generate_response(user_input)
265
+
266
+ display_response = response.replace(' <eos>', '').replace('<eos>', '')
267
+ print(display_response)
268
+ print()
269
+
270
+ self.conversation_history.append({
271
+ 'user': user_input,
272
+ 'assistant': display_response
273
+ })
274
+
275
+ except KeyboardInterrupt:
276
+ print("\n\nAgGPT: Chat interrupted. Goodbye!")
277
+ break
278
+ except Exception as e:
279
+ print(f"\nError: {e}")
280
+ print("Let me try again...")
281
+ continue
282
+
283
+ def batch_test(self, test_inputs: List[str]):
284
+ if not self.initialize():
285
+ return
286
+
287
+ print("Running batch test...")
288
+ print("=" * 50)
289
+
290
+ for i, test_input in enumerate(test_inputs, 1):
291
+ print(f"Test {i}: {test_input}")
292
+ response = self.response_generator.generate_response(test_input)
293
+ display_response = response.replace(' <eos>', '').replace('<eos>', '')
294
+ print(f"Response: {display_response}")
295
+ print("-" * 30)
296
+
297
+
298
+ def main():
299
+ chat = AgGPTChat()
300
+
301
+ import sys
302
+ if len(sys.argv) > 1 and sys.argv[1] == "test":
303
+ test_inputs = [
304
+ "hi",
305
+ "hello there",
306
+ "how are you?",
307
+ "what's your favorite color?",
308
+ "tell me a joke",
309
+ "thank you",
310
+ "goodbye"
311
+ ]
312
+ chat.batch_test(test_inputs)
313
+ else:
314
+ chat.chat_loop()
315
+
316
+
317
+ if __name__ == "__main__":
318
+ main()
feather.py ADDED
@@ -0,0 +1,235 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import os
3
+ from typing import Dict, List, Any, Optional
4
+ import math
5
+
6
+
7
+ class FeatherManager:
8
+
9
+ def __init__(self, models_dir: str = "models"):
10
+ self.models_dir = models_dir
11
+ os.makedirs(models_dir, exist_ok=True)
12
+
13
+ def save_mini_model(self, model_data: Dict[str, Any], model_id: int, filename: str = None) -> str:
14
+ """Save model with custom filename or default naming"""
15
+ if filename is None:
16
+ filename = f"AgGPT_Expert_{model_id:04d}.feather"
17
+
18
+ filepath = os.path.join(self.models_dir, filename)
19
+
20
+ patterns = model_data.get('patterns', [])
21
+ responses = model_data.get('responses', [])
22
+
23
+ if not patterns or not responses:
24
+ print(f"Warning: Model {model_id} has empty patterns or responses")
25
+ patterns = patterns or ['hello']
26
+ responses = responses or ['Hello!']
27
+
28
+ df_data = {
29
+ 'patterns': [str(pattern) for pattern in patterns],
30
+ 'responses': [str(response) for response in responses],
31
+ 'weights': model_data.get('weights', [1.0] * len(patterns)),
32
+ 'confidence': [model_data.get('confidence', 0.5)] * len(patterns),
33
+ 'grammar_rules': [str(rule) for rule in model_data.get('grammar_rules', [])] or ['none'],
34
+ 'keywords': [' '.join(model_data.get('keywords', []))] * len(patterns),
35
+ 'training_samples': [model_data.get('training_samples', 0)] * len(patterns)
36
+ }
37
+
38
+ max_len = max(len(v) if isinstance(v, list) else 1 for v in df_data.values())
39
+
40
+ for key, value in df_data.items():
41
+ if isinstance(value, list):
42
+ while len(value) < max_len:
43
+ value.append(value[-1] if value else '')
44
+
45
+ df = pd.DataFrame(df_data)
46
+ df.to_feather(filepath)
47
+
48
+ print(f"Saved mini-model: {filename}")
49
+ return filepath
50
+
51
+ def load_feather_file(self, filepath: str) -> Optional[Dict[str, Any]]:
52
+ """Load any .feather file and convert it to model format"""
53
+ if not os.path.exists(filepath):
54
+ return None
55
+
56
+ try:
57
+ df = pd.read_feather(filepath)
58
+
59
+ # Try to extract model ID from filename
60
+ filename = os.path.basename(filepath)
61
+ model_id = 0
62
+
63
+ if filename.startswith("AgGPT_Expert_"):
64
+ try:
65
+ model_id = int(filename.split("_")[2].split(".")[0])
66
+ except (ValueError, IndexError):
67
+ model_id = hash(filename) % 10000
68
+ elif filename.startswith("target_AgGPT_"):
69
+ try:
70
+ model_id = int(filename.split("_")[2].split(".")[0])
71
+ except (ValueError, IndexError):
72
+ model_id = hash(filename) % 10000
73
+ else:
74
+ model_id = hash(filename) % 10000
75
+
76
+ model_data = {
77
+ 'patterns': [p for p in df['patterns'].tolist() if p],
78
+ 'responses': [r for r in df['responses'].tolist() if r],
79
+ 'weights': df['weights'].tolist() if 'weights' in df.columns else [1.0] * len(df),
80
+ 'confidence': df['confidence'].iloc[0] if len(df) > 0 and 'confidence' in df.columns else 0.5,
81
+ 'grammar_rules': [rule for rule in df['grammar_rules'].tolist() if rule] if 'grammar_rules' in df.columns else [],
82
+ 'keywords': df['keywords'].iloc[0].split() if len(df) > 0 and 'keywords' in df.columns and df['keywords'].iloc[0] else [],
83
+ 'training_samples': df['training_samples'].iloc[0] if len(df) > 0 and 'training_samples' in df.columns else 0,
84
+ 'model_id': model_id,
85
+ 'filename': filename
86
+ }
87
+
88
+ return model_data
89
+
90
+ except Exception as e:
91
+ print(f"Error loading feather file {filepath}: {e}")
92
+ return None
93
+ def load_mini_model(self, model_id: int) -> Optional[Dict[str, Any]]:
94
+ filename = f"AgGPT_Expert_{model_id:04d}.feather"
95
+ filepath = os.path.join(self.models_dir, filename)
96
+ return self.load_feather_file(filepath)
97
+
98
+ def load_all_models(self) -> List[Dict[str, Any]]:
99
+ """Load ALL .feather files from the models directory"""
100
+ models = []
101
+
102
+ if not os.path.exists(self.models_dir):
103
+ return models
104
+
105
+ print(f"Scanning {self.models_dir} for .feather files...")
106
+
107
+ for filename in sorted(os.listdir(self.models_dir)):
108
+ if filename.endswith(".feather"):
109
+ filepath = os.path.join(self.models_dir, filename)
110
+ model = self.load_feather_file(filepath)
111
+ if model:
112
+ models.append(model)
113
+ print(f" ✅ Loaded: {filename}")
114
+ else:
115
+ print(f" ❌ Failed to load: {filename}")
116
+
117
+ print(f"Total models loaded: {len(models)}")
118
+ return models
119
+
120
+ def get_model_count(self) -> int:
121
+ """Count ALL .feather files in the models directory"""
122
+ if not os.path.exists(self.models_dir):
123
+ return 0
124
+
125
+ count = 0
126
+ for filename in os.listdir(self.models_dir):
127
+ if filename.endswith(".feather"):
128
+ count += 1
129
+
130
+ return count
131
+
132
+ def get_next_model_id(self) -> int:
133
+ """Get next available model ID for AgGPT_Expert_ files"""
134
+ if not os.path.exists(self.models_dir):
135
+ return 1
136
+
137
+ max_id = 0
138
+ for filename in os.listdir(self.models_dir):
139
+ if filename.startswith("AgGPT_Expert_") and filename.endswith(".feather"):
140
+ try:
141
+ model_id = int(filename.split("_")[2].split(".")[0])
142
+ max_id = max(max_id, model_id)
143
+ except (ValueError, IndexError):
144
+ continue
145
+ elif filename.endswith(".feather"):
146
+ # For non-standard named files, use a high number to avoid conflicts
147
+ try:
148
+ # Extract numbers from any part of the filename
149
+ import re
150
+ numbers = re.findall(r'\d+', filename)
151
+ if numbers:
152
+ file_id = int(numbers[-1]) # Use the last number found
153
+ max_id = max(max_id, file_id)
154
+ except (ValueError, IndexError):
155
+ continue
156
+
157
+ return max_id + 1
158
+
159
+ def delete_model(self, model_id: int) -> bool:
160
+ filename = f"AgGPT_Expert_{model_id:04d}.feather"
161
+ filepath = os.path.join(self.models_dir, filename)
162
+
163
+ if os.path.exists(filepath):
164
+ try:
165
+ os.remove(filepath)
166
+ print(f"Deleted model: {filename}")
167
+ return True
168
+ except Exception as e:
169
+ print(f"Error deleting model {model_id}: {e}")
170
+ return False
171
+
172
+ return False
173
+
174
+ def clear_all_models(self) -> int:
175
+ if not os.path.exists(self.models_dir):
176
+ return 0
177
+
178
+ deleted_count = 0
179
+ for filename in os.listdir(self.models_dir):
180
+ if filename.startswith("AgGPT_Expert_") and filename.endswith(".feather"):
181
+ try:
182
+ os.remove(os.path.join(self.models_dir, filename))
183
+ deleted_count += 1
184
+ except Exception as e:
185
+ print(f"Error deleting {filename}: {e}")
186
+
187
+ print(f"Deleted {deleted_count} model files")
188
+ return deleted_count
189
+
190
+
191
+ def similarity_score(text1: str, text2: str) -> float:
192
+ if not text1 or not text2:
193
+ return 0.0
194
+
195
+ words1 = set(text1.lower().split())
196
+ words2 = set(text2.lower().split())
197
+
198
+ if not words1 or not words2:
199
+ return 0.0
200
+
201
+ intersection = len(words1.intersection(words2))
202
+ union = len(words1.union(words2))
203
+
204
+ return intersection / union if union > 0 else 0.0
205
+
206
+
207
+ def calculate_confidence_score(patterns: List[str], responses: List[str]) -> float:
208
+ if not patterns or not responses or len(patterns) != len(responses):
209
+ return 0.1
210
+
211
+ base_confidence = min(0.9, len(patterns) / 10.0)
212
+
213
+ return max(0.1, min(1.0, base_confidence))
214
+
215
+
216
+ if __name__ == "__main__":
217
+ manager = FeatherManager()
218
+
219
+ test_model = {
220
+ 'patterns': ['hello', 'hi', 'hey'],
221
+ 'responses': ['Hello! How can I help you?', 'Hi there!', 'Hey! What\'s up?'],
222
+ 'weights': [1.0, 0.9, 0.8],
223
+ 'confidence': 0.8,
224
+ 'grammar_rules': ['capitalize_first_word', 'end_with_punctuation'],
225
+ 'keywords': ['greeting', 'hello', 'hi'],
226
+ 'training_samples': 150
227
+ }
228
+
229
+ model_id = manager.get_next_model_id()
230
+ manager.save_mini_model(test_model, model_id)
231
+ loaded_model = manager.load_mini_model(model_id)
232
+
233
+ print(f"Original model: {test_model}")
234
+ print(f"Loaded model: {loaded_model}")
235
+ print(f"Models count: {manager.get_model_count()}")
target_train.py ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ AgGPT-20 Target Trainer
4
+ Simple single-file training script that creates individual .feather models
5
+
6
+ Usage:
7
+ python target_train.py [file_path]
8
+
9
+ If no file path is provided, it will use extra_corpora/example.txt by default.
10
+ """
11
+
12
+ import os
13
+ import glob
14
+ from train import AgGPTTrainer, MiniModelTrainer
15
+ from feather import FeatherManager
16
+
17
+ def get_next_target_model_number(models_dir="models"):
18
+ """Find the next available target_AgGPT_X.feather number"""
19
+ if not os.path.exists(models_dir):
20
+ os.makedirs(models_dir)
21
+
22
+ # Find all existing target_AgGPT_*.feather files
23
+ pattern = os.path.join(models_dir, "target_AgGPT_*.feather")
24
+ existing_files = glob.glob(pattern)
25
+
26
+ if not existing_files:
27
+ return 1
28
+
29
+ # Extract numbers from existing files
30
+ numbers = []
31
+ for file_path in existing_files:
32
+ filename = os.path.basename(file_path)
33
+ # Extract number from target_AgGPT_X.feather
34
+ try:
35
+ number_str = filename.split('_')[2].split('.')[0]
36
+ numbers.append(int(number_str))
37
+ except (IndexError, ValueError):
38
+ continue
39
+
40
+ return max(numbers) + 1 if numbers else 1
41
+
42
+ def train_target_model(file_path="extra_corpora/example.txt", models_dir="models"):
43
+ """Train a single target model from a text file"""
44
+ print("AgGPT-20 Target Trainer")
45
+ print("=" * 40)
46
+
47
+ # Check if file exists
48
+ if not os.path.exists(file_path):
49
+ print(f"Error: Training file '{file_path}' not found!")
50
+ print(f"Please create the file or specify a different path.")
51
+ return False
52
+
53
+ # Check file size
54
+ file_size = os.path.getsize(file_path)
55
+ if file_size == 0:
56
+ print(f"Error: Training file '{file_path}' is empty!")
57
+ return False
58
+
59
+ print(f"Training file: {file_path}")
60
+ print(f"File size: {file_size} bytes")
61
+
62
+ # Create models directory if it doesn't exist
63
+ if not os.path.exists(models_dir):
64
+ os.makedirs(models_dir)
65
+
66
+ # Initialize trainer components
67
+ feather_manager = FeatherManager(models_dir)
68
+ trainer = AgGPTTrainer(models_dir)
69
+ mini_trainer = MiniModelTrainer(feather_manager)
70
+
71
+ # Load training data
72
+ print(f"Loading training data from {file_path}...")
73
+ try:
74
+ training_pairs = trainer.load_training_data(file_path)
75
+ except Exception as e:
76
+ print(f"Error loading training data: {e}")
77
+ return False
78
+
79
+ if not training_pairs:
80
+ print("No valid training pairs found in the file!")
81
+ print("Please check the file format:")
82
+ print("user: [your message]")
83
+ print("<pad>")
84
+ print("ai: [response]")
85
+ print("<eos>")
86
+ return False
87
+
88
+ print(f"Found {len(training_pairs)} training pairs")
89
+
90
+ # Train the mini-model
91
+ print("Training mini-model...")
92
+ try:
93
+ mini_model = mini_trainer.train_mini_model(training_pairs)
94
+ except Exception as e:
95
+ print(f"Error during training: {e}")
96
+ return False
97
+
98
+ if not mini_model:
99
+ print("Failed to create mini-model!")
100
+ return False
101
+
102
+ # Get next available model number
103
+ model_number = get_next_target_model_number(models_dir)
104
+ model_filename = f"target_AgGPT_{model_number}.feather"
105
+
106
+ # Save the model with custom filename
107
+ print(f"Saving model as {model_filename}...")
108
+ try:
109
+ feather_manager.save_mini_model(mini_model, model_number, model_filename)
110
+ model_path = os.path.join(models_dir, model_filename)
111
+ print(f"✅ Successfully created: {model_path}")
112
+
113
+ except Exception as e:
114
+ print(f"Error saving model: {e}")
115
+ return False
116
+
117
+ # Display model statistics
118
+ print("\nModel Statistics:")
119
+ print(f" Training samples: {mini_model.get('training_samples', 0)}")
120
+ print(f" Patterns: {len(mini_model.get('patterns', []))}")
121
+ print(f" Responses: {len(mini_model.get('responses', []))}")
122
+ print(f" Confidence: {mini_model.get('confidence', 0.0):.3f}")
123
+ print(f" Keywords: {len(mini_model.get('keywords', []))}")
124
+
125
+ print(f"\n🎉 Target model training complete!")
126
+ print(f"The model will be automatically discovered by chat.py")
127
+ print("Run 'python chat.py' to test your new model!")
128
+
129
+ return True
130
+
131
+ def main():
132
+ import sys
133
+
134
+ # Check command line arguments
135
+ if len(sys.argv) > 1:
136
+ file_path = sys.argv[1]
137
+ else:
138
+ file_path = "extra_corpora/example.txt"
139
+
140
+ success = train_target_model(file_path)
141
+
142
+ if not success:
143
+ print("\n❌ Training failed!")
144
+ sys.exit(1)
145
+
146
+ if __name__ == "__main__":
147
+ main()
train.py ADDED
@@ -0,0 +1,371 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import re
3
+ import random
4
+ import math
5
+ import yaml
6
+ from typing import List, Dict, Tuple, Set, Any
7
+ from collections import defaultdict, Counter
8
+ import pandas as pd
9
+ from tqdm import tqdm
10
+
11
+ from feather import FeatherManager, similarity_score, calculate_confidence_score
12
+
13
+ class GrammarRules:
14
+ @staticmethod
15
+ def apply_all_rules(text: str) -> str:
16
+ if not text:
17
+ return text
18
+
19
+ return text.strip()
20
+
21
+ class PatternExtractor:
22
+
23
+ def __init__(self):
24
+ pass
25
+
26
+ def extract_keywords(self, text: str) -> List[str]:
27
+ if not text:
28
+ return []
29
+
30
+ full_text_normalized = re.sub(r'\s+', ' ', text.strip().lower())
31
+ words = re.findall(r'\b[a-zA-Z]+\b', full_text_normalized)
32
+
33
+ result = [full_text_normalized]
34
+ result.extend(words)
35
+
36
+ return list(set(result))
37
+
38
+ def create_pattern(self, user_input: str) -> str:
39
+ if not user_input:
40
+ return ""
41
+
42
+ pattern = re.sub(r'\s+', ' ', user_input.strip().lower())
43
+
44
+ pattern = f" {pattern} "
45
+
46
+ return pattern
47
+
48
+ def calculate_pattern_similarity(self, pattern1: str, pattern2: str) -> float:
49
+ return similarity_score(pattern1.strip(), pattern2.strip())
50
+
51
+
52
+ class MiniModelTrainer:
53
+
54
+ def __init__(self, feather_manager: FeatherManager):
55
+ self.feather_manager = feather_manager
56
+ self.pattern_extractor = PatternExtractor()
57
+ self.grammar_rules = GrammarRules()
58
+
59
+ def train_mini_model(self, training_pairs: List[Tuple[str, str]], confidence_threshold: float = 0.1) -> Dict[str, Any]:
60
+ if not training_pairs or len(training_pairs) < 2:
61
+ return None
62
+
63
+ keyword_patterns = []
64
+ responses = []
65
+ pattern_confidences = []
66
+ all_keywords = []
67
+
68
+ for user_input, ai_response in training_pairs:
69
+ processed_response = ai_response.strip()
70
+
71
+ # Get both the pattern and keywords
72
+ pattern = self.pattern_extractor.create_pattern(user_input)
73
+ keywords = self.pattern_extractor.extract_keywords(user_input)
74
+ all_keywords.extend(keywords)
75
+
76
+ # Add the main pattern
77
+ keyword_patterns.append(pattern)
78
+ responses.append(processed_response)
79
+ individual_confidence = min(0.9, len(training_pairs) / 20.0)
80
+ pattern_confidences.append(individual_confidence)
81
+
82
+ if not keyword_patterns:
83
+ return None
84
+
85
+ base_confidence = min(0.9, len(training_pairs) / 20.0)
86
+ keyword_counter = Counter(all_keywords)
87
+ top_keywords = [word for word, count in keyword_counter.most_common(10)]
88
+
89
+ mini_model = {
90
+ 'patterns': keyword_patterns,
91
+ 'responses': responses,
92
+ 'pattern_confidences': pattern_confidences,
93
+ 'confidence': base_confidence,
94
+ 'grammar_rules': [],
95
+ 'keywords': top_keywords,
96
+ 'training_samples': len(training_pairs)
97
+ }
98
+
99
+ return mini_model
100
+
101
+
102
+ class AgGPTTrainer:
103
+
104
+ def __init__(self, models_dir: str = "models"):
105
+ self.feather_manager = FeatherManager(models_dir)
106
+ self.mini_trainer = MiniModelTrainer(self.feather_manager)
107
+ self.target_size_mb = 5
108
+ self.estimated_size_per_pair = 1000
109
+ self.chunk_size = (self.target_size_mb * 1024 * 1024) // self.estimated_size_per_pair
110
+ self.readable_weights_dir = "readable_weights"
111
+ os.makedirs(self.readable_weights_dir, exist_ok=True)
112
+
113
+ def save_model_as_yaml(self, model_data: Dict[str, Any], model_id: int):
114
+ try:
115
+ filename = f"AgGPT_Model_{model_id:04d}.yaml"
116
+ filepath = os.path.join(self.readable_weights_dir, filename)
117
+
118
+ print(f"Creating YAML data for model {model_id}...")
119
+ yaml_data = {
120
+ 'model_info': {
121
+ 'model_id': model_id,
122
+ 'confidence': model_data.get('confidence', 0.5),
123
+ 'training_samples': model_data.get('training_samples', 0),
124
+ 'keywords': model_data.get('keywords', [])
125
+ },
126
+ 'patterns_and_responses': []
127
+ }
128
+
129
+ patterns = model_data.get('patterns', [])
130
+ responses = model_data.get('responses', [])
131
+ weights = model_data.get('weights', [])
132
+
133
+ print(f"Processing {len(patterns)} patterns...")
134
+ for i in range(len(patterns)):
135
+ entry = {
136
+ 'pattern': patterns[i] if i < len(patterns) else '',
137
+ 'response': responses[i] if i < len(responses) else '',
138
+ 'weight': weights[i] if i < len(weights) else 1.0
139
+ }
140
+ yaml_data['patterns_and_responses'].append(entry)
141
+
142
+ print(f"Writing YAML to {filepath}...")
143
+ with open(filepath, 'w', encoding='utf-8') as f:
144
+ yaml.dump(yaml_data, f, default_flow_style=False, allow_unicode=True, indent=2)
145
+
146
+ print(f"Saved readable model: {filename}")
147
+ except Exception as e:
148
+ print(f"Error in save_model_as_yaml: {e}")
149
+ import traceback
150
+ traceback.print_exc()
151
+
152
+ def load_training_data(self, file_path: str) -> List[Tuple[str, str]]:
153
+ training_pairs = []
154
+
155
+ with open(file_path, 'r', encoding='utf-8') as f:
156
+ content = f.read()
157
+
158
+ conversations = content.split('<eos>')
159
+
160
+ print(f"Processing {len(conversations)} conversation chunks...")
161
+
162
+ for conversation in tqdm(conversations, desc="Parsing conversations"):
163
+ conversation = conversation.strip()
164
+ if not conversation:
165
+ continue
166
+
167
+ user_match = re.search(r'user:\s*(.*?)(?=\n<pad>|\nai:|$)', conversation, re.DOTALL)
168
+ ai_match = re.search(r'ai:\s*(.*?)$', conversation, re.DOTALL)
169
+
170
+ if user_match and ai_match:
171
+ user_input = user_match.group(1).strip()
172
+ ai_response = ai_match.group(1).strip()
173
+
174
+ user_input = re.sub(r'<pad>', '', user_input).strip()
175
+ ai_response = re.sub(r'<pad>', '', ai_response).strip()
176
+
177
+ if user_input and ai_response and len(user_input) > 0 and len(ai_response) > 0:
178
+ training_pairs.append((user_input, ai_response))
179
+
180
+ print(f"Extracted {len(training_pairs)} training pairs")
181
+ return training_pairs
182
+
183
+ def create_training_chunks(self, training_pairs: List[Tuple[str, str]]) -> List[List[Tuple[str, str]]]:
184
+ shuffled_pairs = training_pairs.copy()
185
+ random.shuffle(shuffled_pairs)
186
+
187
+ chunks = []
188
+ total_pairs = len(shuffled_pairs)
189
+
190
+ for i in range(0, total_pairs, self.chunk_size):
191
+ chunk = shuffled_pairs[i:i + self.chunk_size]
192
+ if len(chunk) >= 5:
193
+ chunks.append(chunk)
194
+
195
+ print(f"Created {len(chunks)} training chunks (target: {self.target_size_mb}MB each)")
196
+ return chunks
197
+
198
+ def train_multiple_corpora(self, training_files: List[str] = None):
199
+ """Train on multiple corpora files sequentially"""
200
+ if training_files is None:
201
+ # Automatically find all .txt files in training_corpora directory
202
+ training_corpora_dir = "training_corpora"
203
+ if os.path.exists(training_corpora_dir):
204
+ training_files = []
205
+ for filename in sorted(os.listdir(training_corpora_dir)):
206
+ if filename.endswith('.txt'):
207
+ file_path = os.path.join(training_corpora_dir, filename)
208
+ training_files.append(file_path)
209
+ print(f"Auto-discovered {len(training_files)} training files in {training_corpora_dir}/")
210
+ else:
211
+ # Fallback to old default for backward compatibility
212
+ training_files = ["training_data/corpora.txt", "training_data/corpora2.txt"]
213
+ print("Using fallback training files (training_corpora/ not found)")
214
+
215
+ print("Starting AgGPT-20 Multi-Corpora Training with Scalable Feather Architecture")
216
+ print("=" * 70)
217
+
218
+ cleared_count = self.feather_manager.clear_all_models()
219
+ if cleared_count > 0:
220
+ print(f"Cleared {cleared_count} existing models")
221
+
222
+ all_trained_models = []
223
+ total_model_id = 1
224
+
225
+ for file_idx, training_file in enumerate(training_files, 1):
226
+ print(f"\n--- Training on file {file_idx}/{len(training_files)}: {training_file} ---")
227
+
228
+ if not os.path.exists(training_file):
229
+ print(f"Warning: Training file {training_file} does not exist. Skipping...")
230
+ continue
231
+
232
+ if os.path.getsize(training_file) == 0:
233
+ print(f"Warning: Training file {training_file} is empty. Skipping...")
234
+ continue
235
+
236
+ print(f"Loading training data from {training_file}...")
237
+ training_pairs = self.load_training_data(training_file)
238
+
239
+ if not training_pairs:
240
+ print(f"No training data found in {training_file}. Skipping...")
241
+ continue
242
+
243
+ print(f"Creating training chunks for {training_file}...")
244
+ training_chunks = self.create_training_chunks(training_pairs)
245
+
246
+ print(f"Training mini-models from {training_file}...")
247
+ file_trained_models = []
248
+
249
+ progress_bar = tqdm(training_chunks, desc=f"Training from {os.path.basename(training_file)}")
250
+ for chunk_idx, chunk in enumerate(progress_bar):
251
+ print(f"\nProcessing chunk {chunk_idx + 1}/{len(training_chunks)}")
252
+ mini_model = self.mini_trainer.train_mini_model(chunk)
253
+
254
+ if mini_model:
255
+ file_trained_models.append(mini_model)
256
+ all_trained_models.append(mini_model)
257
+ print(f"Saving model {total_model_id}...")
258
+ self.feather_manager.save_mini_model(mini_model, total_model_id)
259
+
260
+ if total_model_id == 1:
261
+ print("Saving first model as YAML...")
262
+ try:
263
+ self.save_model_as_yaml(mini_model, total_model_id)
264
+ print("YAML saved successfully")
265
+ except Exception as e:
266
+ print(f"Error saving YAML: {e}")
267
+
268
+ total_model_id += 1
269
+ print(f"Model {total_model_id - 1} completed")
270
+
271
+ try:
272
+ progress_bar.set_postfix({
273
+ 'File Models': len(file_trained_models),
274
+ 'Total Models': len(all_trained_models),
275
+ 'Confidence': f"{mini_model['confidence']:.3f}"
276
+ })
277
+ except Exception as e:
278
+ print(f"Error updating progress bar: {e}")
279
+
280
+ print(f"Completed training on {training_file}: {len(file_trained_models)} mini-models created")
281
+ print(f"Total models so far: {len(all_trained_models)}")
282
+
283
+ print(f"\n--- Multi-Corpora Training Complete ---")
284
+ final_count = self.feather_manager.get_model_count()
285
+ print(f"Final model count: {final_count}")
286
+ print(f"Trained on {len([f for f in training_files if os.path.exists(f) and os.path.getsize(f) > 0])} corpora files")
287
+ print("=" * 70)
288
+
289
+ def train(self, training_file: str = "training_data/corpora.txt"):
290
+ print("Starting AgGPT-20 Training with Scalable Feather Architecture")
291
+ print("=" * 60)
292
+
293
+ cleared_count = self.feather_manager.clear_all_models()
294
+ if cleared_count > 0:
295
+ print(f"Cleared {cleared_count} existing models")
296
+
297
+ print("Loading training data...")
298
+ training_pairs = self.load_training_data(training_file)
299
+
300
+ if not training_pairs:
301
+ print("No training data found!")
302
+ return
303
+
304
+ print("Creating training chunks...")
305
+ training_chunks = self.create_training_chunks(training_pairs)
306
+
307
+ print("Training mini-models...")
308
+ trained_models = []
309
+ model_id = 1
310
+
311
+ progress_bar = tqdm(training_chunks, desc="Training mini-models")
312
+ for chunk in progress_bar:
313
+ mini_model = self.mini_trainer.train_mini_model(chunk)
314
+
315
+ if mini_model:
316
+ trained_models.append(mini_model)
317
+ self.feather_manager.save_mini_model(mini_model, model_id)
318
+
319
+ if model_id == 1:
320
+ self.save_model_as_yaml(mini_model, model_id)
321
+
322
+ model_id += 1
323
+
324
+ progress_bar.set_postfix({
325
+ 'Models': len(trained_models),
326
+ 'Confidence': f"{mini_model['confidence']:.3f}"
327
+ })
328
+
329
+ print(f"Trained {len(trained_models)} mini-models")
330
+
331
+ final_count = self.feather_manager.get_model_count()
332
+ print(f"Training complete! Final model count: {final_count}")
333
+ print("=" * 60)
334
+
335
+
336
+ def main():
337
+ print("AgGPT-20 Scalable Feather Architecture Trainer")
338
+ print("=" * 50)
339
+
340
+ # Automatically find all .txt files in training_corpora directory
341
+ training_corpora_dir = "training_corpora"
342
+ training_files = []
343
+
344
+ if os.path.exists(training_corpora_dir):
345
+ print(f"Scanning {training_corpora_dir} directory for training files...")
346
+ for filename in sorted(os.listdir(training_corpora_dir)):
347
+ if filename.endswith('.txt'):
348
+ file_path = os.path.join(training_corpora_dir, filename)
349
+ training_files.append(file_path)
350
+
351
+ print(f"Found {len(training_files)} training files:")
352
+ for file_path in training_files:
353
+ print(f" - {file_path}")
354
+ else:
355
+ print(f"Warning: {training_corpora_dir} directory not found!")
356
+ training_files = None
357
+
358
+ trainer = AgGPTTrainer()
359
+
360
+ try:
361
+ trainer.train_multiple_corpora(training_files=training_files)
362
+ except KeyboardInterrupt:
363
+ print("\nTraining interrupted by user")
364
+ except Exception as e:
365
+ print(f"Training failed: {e}")
366
+ import traceback
367
+ traceback.print_exc()
368
+
369
+
370
+ if __name__ == "__main__":
371
+ main()