AGofficial commited on
Commit
cd5b50b
·
verified ·
1 Parent(s): ef9acf5

Upload 6 files

Browse files
Files changed (7) hide show
  1. .gitattributes +1 -0
  2. LICENSE +21 -0
  3. README.md +16 -3
  4. banner.png +3 -0
  5. chat.py +522 -0
  6. feather.py +424 -0
  7. train.py +690 -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,16 @@
1
- ---
2
- license: mit
3
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ language:
4
+ - en
5
+ ---
6
+
7
+ <img src="banner.png" alt="AgGPT-19 Banner" width="100%">
8
+
9
+ # AgGPT-19
10
+
11
+ ## Heavy Duty intelligence
12
+
13
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
14
+
15
+ # HEAVY
16
+ AgGPT-19 is a powerful AI language model designed to assist with a wide range of tasks, from answering questions to generating creative content. It is built on advanced machine learning techniques and trained on diverse datasets to ensure high-quality responses.
banner.png ADDED

Git LFS Details

  • SHA256: e86602e05227b348438ee797692561734626dca1b79422655e189395ca1ad6c1
  • Pointer size: 131 Bytes
  • Size of remote file: 941 kB
chat.py ADDED
@@ -0,0 +1,522 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+
11
+ class SimpleReasoningEngine:
12
+ """Basic reasoning engine for AgGPT-19"""
13
+
14
+ def __init__(self):
15
+ self.logical_patterns = {
16
+ 'cause_effect': ['because', 'since', 'therefore', 'as a result', 'leads to'],
17
+ 'comparison': ['better than', 'worse than', 'similar to', 'different from', 'compared to'],
18
+ 'sequence': ['first', 'then', 'next', 'finally', 'after that'],
19
+ 'conditional': ['if', 'unless', 'provided that', 'in case'],
20
+ }
21
+
22
+ self.context_memory = {}
23
+
24
+ def analyze_intent(self, user_input: str, context: List[Tuple[str, str]]) -> Dict[str, Any]:
25
+ """Analyze user intent and context"""
26
+ input_lower = user_input.lower()
27
+
28
+ intent = {
29
+ 'type': 'unknown',
30
+ 'topic': '',
31
+ 'emotion': 'neutral',
32
+ 'requires_reasoning': False,
33
+ 'context_dependent': False
34
+ }
35
+
36
+ # Detect intent type
37
+ if any(word in input_lower for word in ['what', 'how', 'why', 'when', 'where', 'who']):
38
+ intent['type'] = 'question'
39
+ elif any(word in input_lower for word in ['hello', 'hi', 'hey', 'good morning']):
40
+ intent['type'] = 'greeting'
41
+ elif any(word in input_lower for word in ['please', 'can you', 'help me']):
42
+ intent['type'] = 'request'
43
+ elif any(word in input_lower for word in ['thank', 'thanks', 'bye', 'goodbye']):
44
+ intent['type'] = 'social'
45
+
46
+ # Detect if reasoning is needed
47
+ if any(pattern in input_lower for patterns in self.logical_patterns.values() for pattern in patterns):
48
+ intent['requires_reasoning'] = True
49
+
50
+ # Check context dependency
51
+ if any(word in input_lower for word in ['this', 'that', 'it', 'they', 'what about']):
52
+ intent['context_dependent'] = True
53
+
54
+ # Extract topic
55
+ words = [word for word in input_lower.split() if len(word) > 3]
56
+ if words:
57
+ intent['topic'] = ' '.join(words[:3])
58
+
59
+ return intent
60
+
61
+ def apply_reasoning(self, intent: Dict[str, Any], knowledge: Dict[str, str], context: List[Tuple[str, str]]) -> str:
62
+ """Apply basic reasoning to generate more intelligent responses"""
63
+
64
+ if intent['context_dependent'] and context:
65
+ # Use recent context
66
+ recent_context = ' '.join([item[0] + ' ' + item[1] for item in context[-2:]])
67
+ return f"Building on our conversation: {recent_context[:100]}..."
68
+
69
+ if intent['requires_reasoning']:
70
+ # Apply logical reasoning patterns
71
+ if intent['type'] == 'question' and 'why' in intent['topic']:
72
+ return "This is likely due to several factors that work together..."
73
+ elif 'how' in intent['topic']:
74
+ return "Here's a step-by-step approach to understand this..."
75
+
76
+ return ""
77
+
78
+
79
+ class ResponseGenerator:
80
+ def __init__(self, feather_manager: FeatherManager):
81
+ self.feather_manager = feather_manager
82
+ self.pattern_extractor = PatternExtractor()
83
+ self.grammar_rules = GrammarRules()
84
+ self.models = []
85
+ self.context_window = []
86
+ self.max_context_length = 10
87
+ self.knowledge_cache = {}
88
+
89
+ # Enhanced response generation for AgGPT-19
90
+ self.reasoning_engine = SimpleReasoningEngine()
91
+ self.response_templates = {
92
+ 'greeting': ["Hello! {topic}", "Hi there! {topic}", "Good {time_of_day}! {topic}"],
93
+ 'question': ["Based on what I know, {answer}", "Let me think about that. {answer}", "{answer}"],
94
+ 'explanation': ["Here's how it works: {explanation}", "The key point is {explanation}", "{explanation}"],
95
+ 'request': ["I'd be happy to help with {request}", "Sure, I can assist with {request}", "Let me help you with {request}"]
96
+ }
97
+
98
+ def load_models(self):
99
+ print("Loading enhanced mini-models...")
100
+ self.models = self.feather_manager.load_all_models()
101
+ print(f"Loaded {len(self.models)} enhanced mini-models")
102
+
103
+ if not self.models:
104
+ print("No trained models found! Please run train.py first.")
105
+ return False
106
+
107
+ # Build knowledge cache from all models
108
+ self._build_knowledge_cache()
109
+
110
+ return True
111
+
112
+ def _build_knowledge_cache(self):
113
+ """Build a unified knowledge cache from all models"""
114
+ for model in self.models:
115
+ knowledge_base = model.get('knowledge_base', {})
116
+ if knowledge_base:
117
+ self.knowledge_cache.update(knowledge_base)
118
+
119
+ print(f"Built knowledge cache with {len(self.knowledge_cache)} entries")
120
+
121
+ def calculate_model_scores(self, user_input: str) -> List[Tuple[Dict[str, Any], float]]:
122
+ if not self.models:
123
+ return []
124
+
125
+ input_pattern = self.pattern_extractor.create_pattern(user_input)
126
+ input_keywords = set(self.pattern_extractor.extract_keywords(user_input))
127
+
128
+ model_scores = []
129
+
130
+ for model in self.models:
131
+ score = 0.0
132
+ pattern_matches = 0
133
+ keyword_matches = 0
134
+
135
+ for pattern in model.get('patterns', []):
136
+ pattern_sim = self.pattern_extractor.calculate_pattern_similarity(input_pattern, pattern)
137
+ score += pattern_sim
138
+ if pattern_sim > 0.3:
139
+ pattern_matches += 1
140
+
141
+ model_keywords = set(model.get('keywords', []))
142
+ if model_keywords and input_keywords:
143
+ keyword_overlap = len(input_keywords.intersection(model_keywords))
144
+ keyword_total = len(input_keywords.union(model_keywords))
145
+ keyword_score = keyword_overlap / keyword_total if keyword_total > 0 else 0
146
+ score += keyword_score * 2
147
+ keyword_matches = keyword_overlap
148
+
149
+ confidence = model.get('confidence', 0.5)
150
+ score *= confidence
151
+
152
+ training_samples = model.get('training_samples', 1)
153
+ training_bonus = min(0.2, training_samples / 100)
154
+ score += training_bonus
155
+
156
+ context_bonus = self._calculate_context_bonus(user_input, model)
157
+ score += context_bonus
158
+
159
+ model_scores.append((model, score))
160
+
161
+ model_scores.sort(key=lambda x: x[1], reverse=True)
162
+
163
+ return model_scores
164
+
165
+ def _calculate_context_bonus(self, user_input: str, model: Dict[str, Any]) -> float:
166
+ if not self.context_window:
167
+ return 0.0
168
+
169
+ context_bonus = 0.0
170
+
171
+ for prev_input, prev_response in self.context_window[-3:]:
172
+ for pattern in model.get('patterns', [])[:5]:
173
+ pattern_sim = similarity_score(prev_input, pattern.strip())
174
+ context_bonus += pattern_sim * 0.1
175
+
176
+ return min(context_bonus, 0.3)
177
+
178
+ def select_top_models(self, model_scores: List[Tuple[Dict[str, Any], float]], top_k: int = 5) -> List[Tuple[Dict[str, Any], float]]:
179
+ valid_models = [(model, score) for model, score in model_scores if score > 0.01]
180
+
181
+ if not valid_models:
182
+ valid_models = random.sample(model_scores, min(3, len(model_scores)))
183
+
184
+ return valid_models[:top_k]
185
+
186
+ def generate_responses_from_models(self, user_input: str, top_models: List[Tuple[Dict[str, Any], float]]) -> List[Tuple[str, float]]:
187
+ responses = []
188
+ input_pattern = self.pattern_extractor.create_pattern(user_input)
189
+
190
+ for model, model_score in top_models:
191
+ model_responses = []
192
+ best_similarity = 0.0
193
+
194
+ patterns = model.get('patterns', [])
195
+ model_responses_list = model.get('responses', [])
196
+
197
+ if not patterns or not model_responses_list:
198
+ continue
199
+
200
+ best_matches = []
201
+ for i, pattern in enumerate(patterns):
202
+ if i < len(model_responses_list):
203
+ sim = self.pattern_extractor.calculate_pattern_similarity(input_pattern, pattern)
204
+ if sim > 0.1:
205
+ best_matches.append((model_responses_list[i], sim))
206
+
207
+ best_matches.sort(key=lambda x: x[1], reverse=True)
208
+
209
+ selected_responses = best_matches[:3] if best_matches else [(random.choice(model_responses_list), 0.1)]
210
+
211
+ for response, pattern_sim in selected_responses:
212
+ weight = model_score * (0.7 + pattern_sim * 0.3)
213
+ responses.append((response, weight))
214
+
215
+ return responses
216
+
217
+ def combine_responses(self, responses: List[Tuple[str, float]], intent: Dict[str, Any] = None, reasoning_response: str = "") -> str:
218
+ """Intelligently combine responses using context and reasoning"""
219
+ if not responses:
220
+ return "I'm not sure how to respond to that."
221
+
222
+ # If we have reasoning response, prioritize it
223
+ if reasoning_response:
224
+ best_response = responses[0][0] if responses else ""
225
+ if best_response:
226
+ combined = f"{reasoning_response} {best_response}"
227
+ return combined[:300] # Limit length
228
+ return reasoning_response
229
+
230
+ filtered_responses = [(resp, weight) for resp, weight in responses if weight > 0.05]
231
+ if not filtered_responses:
232
+ filtered_responses = responses[:1]
233
+
234
+ # Smart response grouping
235
+ response_groups = defaultdict(list)
236
+ for response, weight in filtered_responses:
237
+ # Group by semantic similarity rather than just first words
238
+ key = self._get_semantic_key(response)
239
+ response_groups[key].append((response, weight))
240
+
241
+ best_responses = []
242
+ for group in response_groups.values():
243
+ best_resp, best_weight = max(group, key=lambda x: x[1])
244
+ best_responses.append((best_resp, best_weight))
245
+
246
+ # Select best response intelligently
247
+ if len(best_responses) > 1:
248
+ # Consider intent when selecting response
249
+ if intent and intent.get('type') == 'greeting':
250
+ # Prefer shorter, friendlier responses for greetings
251
+ best_responses.sort(key=lambda x: len(x[0]) + (0 if any(word in x[0].lower() for word in ['hello', 'hi', 'good']) else 100))
252
+ elif intent and intent.get('type') == 'question':
253
+ # Prefer longer, more informative responses for questions
254
+ best_responses.sort(key=lambda x: -len(x[0]))
255
+
256
+ selected_response = best_responses[0][0]
257
+ else:
258
+ selected_response = best_responses[0][0]
259
+
260
+ # Apply response template if appropriate
261
+ if intent:
262
+ templated_response = self._apply_response_template(selected_response, intent)
263
+ if templated_response:
264
+ selected_response = templated_response
265
+
266
+ final_response = selected_response
267
+
268
+ if not final_response.endswith('<eos>'):
269
+ final_response += ' <eos>'
270
+
271
+ return final_response
272
+
273
+ def _get_semantic_key(self, response: str) -> str:
274
+ """Get semantic grouping key for response"""
275
+ words = response.lower().split()
276
+
277
+ # Group by intent/sentiment
278
+ if any(word in words for word in ['hello', 'hi', 'good']):
279
+ return 'greeting'
280
+ elif any(word in words for word in ['thank', 'welcome']):
281
+ return 'gratitude'
282
+ elif any(word in words for word in ['sorry', 'apologize']):
283
+ return 'apology'
284
+ elif len(words) > 20:
285
+ return 'explanation'
286
+ else:
287
+ return 'simple'
288
+
289
+ def _apply_response_template(self, response: str, intent: Dict[str, Any]) -> str:
290
+ """Apply response templates for more natural responses"""
291
+ intent_type = intent.get('type', 'unknown')
292
+
293
+ if intent_type in self.response_templates:
294
+ templates = self.response_templates[intent_type]
295
+ template = random.choice(templates)
296
+
297
+ # Simple template filling
298
+ if '{topic}' in template:
299
+ template = template.replace('{topic}', intent.get('topic', ''))
300
+ if '{answer}' in template:
301
+ template = template.replace('{answer}', response[:100])
302
+ if '{explanation}' in template:
303
+ template = template.replace('{explanation}', response[:150])
304
+ if '{request}' in template:
305
+ template = template.replace('{request}', intent.get('topic', 'that'))
306
+
307
+ return template
308
+
309
+ return ""
310
+
311
+ def generate_response(self, user_input: str) -> str:
312
+ if not user_input.strip():
313
+ return "Please say something! <eos>"
314
+
315
+ # Enhanced response generation for AgGPT-19
316
+ # 1. Analyze intent and context
317
+ intent = self.reasoning_engine.analyze_intent(user_input, self.context_window)
318
+
319
+ # 2. Check for direct knowledge match
320
+ knowledge_response = self._check_knowledge_base(user_input, intent)
321
+ if knowledge_response:
322
+ self.context_window.append((user_input, knowledge_response))
323
+ if len(self.context_window) > self.max_context_length:
324
+ self.context_window.pop(0)
325
+ return knowledge_response
326
+
327
+ # 3. Apply reasoning if needed
328
+ reasoning_response = self.reasoning_engine.apply_reasoning(intent, self.knowledge_cache, self.context_window)
329
+
330
+ # 4. Get model-based responses
331
+ model_scores = self.calculate_model_scores(user_input)
332
+
333
+ if not model_scores:
334
+ fallback_response = self._generate_fallback_response(intent)
335
+ self.context_window.append((user_input, fallback_response))
336
+ return fallback_response
337
+
338
+ top_models = self.select_top_models(model_scores, top_k=5)
339
+ responses = self.generate_responses_from_models(user_input, top_models)
340
+
341
+ # 5. Intelligently combine responses
342
+ final_response = self.combine_responses(responses, intent, reasoning_response)
343
+
344
+ # 6. Apply post-processing
345
+ final_response = self._post_process_response(final_response, intent)
346
+
347
+ self.context_window.append((user_input, final_response))
348
+ if len(self.context_window) > self.max_context_length:
349
+ self.context_window.pop(0)
350
+
351
+ return final_response
352
+
353
+ def _check_knowledge_base(self, user_input: str, intent: Dict[str, Any]) -> str:
354
+ """Check if we have direct knowledge to answer this query"""
355
+ input_lower = user_input.lower()
356
+
357
+ # Look for exact matches first
358
+ for key, value in self.knowledge_cache.items():
359
+ if key.replace('_', ' ') in input_lower or any(word in key for word in input_lower.split() if len(word) > 3):
360
+ return f"{value} <eos>"
361
+
362
+ return ""
363
+
364
+ def _generate_fallback_response(self, intent: Dict[str, Any]) -> str:
365
+ """Generate intelligent fallback responses"""
366
+ if intent['type'] == 'greeting':
367
+ return random.choice([
368
+ "Hello! How can I help you today?",
369
+ "Hi there! What would you like to know?",
370
+ "Good day! I'm here to assist you."
371
+ ]) + " <eos>"
372
+ elif intent['type'] == 'question':
373
+ return "That's an interesting question. I'd need to learn more about that topic to give you a good answer. <eos>"
374
+ elif intent['type'] == 'request':
375
+ return "I'd like to help you with that. Could you provide more details about what you need? <eos>"
376
+ else:
377
+ return "I understand what you're saying. Could you tell me more about that? <eos>"
378
+
379
+ def _post_process_response(self, response: str, intent: Dict[str, Any]) -> str:
380
+ """Apply post-processing to make responses more natural"""
381
+ if not response.endswith('<eos>'):
382
+ response += ' <eos>'
383
+
384
+ # Add conversational elements based on intent
385
+ if intent['type'] == 'question' and not any(phrase in response.lower() for phrase in ['based on', 'according to']):
386
+ response = response.replace('<eos>', '').strip()
387
+ response = f"From what I understand, {response} <eos>"
388
+
389
+ # Ensure proper capitalization
390
+ response = response[0].upper() + response[1:] if response else response
391
+
392
+ return response
393
+
394
+ def get_model_statistics(self) -> Dict[str, Any]:
395
+ if not self.models:
396
+ return {"total_models": 0}
397
+
398
+ total_patterns = sum(len(model.get('patterns', [])) for model in self.models)
399
+ total_responses = sum(len(model.get('responses', [])) for model in self.models)
400
+ avg_confidence = sum(model.get('confidence', 0) for model in self.models) / len(self.models)
401
+ total_training_samples = sum(model.get('training_samples', 0) for model in self.models)
402
+
403
+ return {
404
+ "total_models": len(self.models),
405
+ "total_patterns": total_patterns,
406
+ "total_responses": total_responses,
407
+ "average_confidence": avg_confidence,
408
+ "total_training_samples": total_training_samples
409
+ }
410
+
411
+
412
+ class AgGPTChat:
413
+
414
+ def __init__(self, models_dir: str = "models"):
415
+ self.feather_manager = FeatherManager(models_dir)
416
+ self.response_generator = ResponseGenerator(self.feather_manager)
417
+ self.conversation_history = []
418
+
419
+ def initialize(self) -> bool:
420
+ print("AgGPT-19 Enhanced Intelligence Chat System")
421
+ print("=" * 50)
422
+
423
+ success = self.response_generator.load_models()
424
+ if success:
425
+ stats = self.response_generator.get_model_statistics()
426
+ print(f"Enhanced Model Statistics:")
427
+ print(f" Mini-models loaded: {stats['total_models']}")
428
+ print(f" Total patterns: {stats['total_patterns']}")
429
+ print(f" Total responses: {stats['total_responses']}")
430
+ print(f" Average confidence: {stats['average_confidence']:.3f}")
431
+ print(f" Training samples: {stats['total_training_samples']}")
432
+ print(f" Knowledge entries: {len(self.response_generator.knowledge_cache)}")
433
+ print("=" * 50)
434
+ print("Enhanced chat initialized! Type 'quit' to exit.")
435
+ print("Features: Context awareness, semantic understanding, reasoning!")
436
+ print()
437
+
438
+ return success
439
+
440
+ def chat_loop(self):
441
+ if not self.initialize():
442
+ return
443
+
444
+ while True:
445
+ try:
446
+ user_input = input("You: ").strip()
447
+
448
+ if not user_input:
449
+ continue
450
+
451
+ if user_input.lower() in ['quit', 'exit', 'bye', 'goodbye']:
452
+ print("AgGPT-19: Goodbye! Thanks for chatting with me! <eos>")
453
+ break
454
+
455
+ if user_input.lower() in ['stats', 'statistics']:
456
+ stats = self.response_generator.get_model_statistics()
457
+ print("Current Statistics:")
458
+ for key, value in stats.items():
459
+ print(f" {key}: {value}")
460
+ continue
461
+
462
+ if user_input.lower() in ['clear', 'reset']:
463
+ self.response_generator.context_window = []
464
+ print("Context cleared!")
465
+ continue
466
+
467
+ print("AgGPT: ", end="", flush=True)
468
+ response = self.response_generator.generate_response(user_input)
469
+
470
+ display_response = response.replace(' <eos>', '').replace('<eos>', '')
471
+ print(display_response)
472
+ print()
473
+
474
+ self.conversation_history.append({
475
+ 'user': user_input,
476
+ 'assistant': display_response
477
+ })
478
+
479
+ except KeyboardInterrupt:
480
+ print("\n\nAgGPT-19: Chat interrupted. Goodbye!")
481
+ break
482
+ except Exception as e:
483
+ print(f"\nError: {e}")
484
+ print("Let me try again...")
485
+ continue
486
+
487
+ def batch_test(self, test_inputs: List[str]):
488
+ if not self.initialize():
489
+ return
490
+
491
+ print("Running enhanced batch test...")
492
+ print("=" * 50)
493
+
494
+ for i, test_input in enumerate(test_inputs, 1):
495
+ print(f"Test {i}: {test_input}")
496
+ response = self.response_generator.generate_response(test_input)
497
+ display_response = response.replace(' <eos>', '').replace('<eos>', '')
498
+ print(f"Response: {display_response}")
499
+ print("-" * 30)
500
+
501
+
502
+ def main():
503
+ chat = AgGPTChat()
504
+
505
+ import sys
506
+ if len(sys.argv) > 1 and sys.argv[1] == "test":
507
+ test_inputs = [
508
+ "hi",
509
+ "hello there",
510
+ "how are you?",
511
+ "what's your favorite color?",
512
+ "tell me a joke",
513
+ "thank you",
514
+ "goodbye"
515
+ ]
516
+ chat.batch_test(test_inputs)
517
+ else:
518
+ chat.chat_loop()
519
+
520
+
521
+ if __name__ == "__main__":
522
+ main()
feather.py ADDED
@@ -0,0 +1,424 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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) -> str:
14
+ filename = f"AgGPT_Expert_{model_id:04d}.feather"
15
+ filepath = os.path.join(self.models_dir, filename)
16
+
17
+ patterns = model_data.get('patterns', [])
18
+ responses = model_data.get('responses', [])
19
+
20
+ if not patterns or not responses:
21
+ print(f"Warning: Model {model_id} has empty patterns or responses")
22
+ patterns = patterns or ['hello']
23
+ responses = responses or ['Hello!']
24
+
25
+ # FIXED: Efficient data structure for AgGPT-19
26
+ # Store only pattern-level data in main table
27
+ df_data = {
28
+ 'patterns': [str(pattern) for pattern in patterns],
29
+ 'responses': [str(response) for response in responses],
30
+ 'weights': model_data.get('weights', [1.0] * len(patterns)),
31
+ 'response_templates': model_data.get('response_templates', [{}] * len(patterns)),
32
+ }
33
+
34
+ # Ensure all arrays are same length
35
+ max_len = len(patterns)
36
+ for key, value in df_data.items():
37
+ if isinstance(value, list):
38
+ while len(value) < max_len:
39
+ if key == 'weights':
40
+ value.append(1.0)
41
+ elif key == 'response_templates':
42
+ value.append({})
43
+ else:
44
+ value.append('')
45
+
46
+ # Store model-level metadata separately (NO DUPLICATION!)
47
+ model_metadata = {
48
+ 'model_id': model_id,
49
+ 'confidence': model_data.get('confidence', 0.5),
50
+ 'keywords': ' '.join(model_data.get('keywords', [])),
51
+ 'training_samples': model_data.get('training_samples', 0),
52
+ 'knowledge_base': str(model_data.get('knowledge_base', {})),
53
+ 'semantic_categories': str(model_data.get('semantic_categories', {})),
54
+ 'grammar_rules': str(model_data.get('grammar_rules', []))
55
+ }
56
+
57
+ # Create main patterns DataFrame
58
+ df_patterns = pd.DataFrame(df_data)
59
+
60
+ # Create single-row metadata DataFrame
61
+ df_metadata = pd.DataFrame([model_metadata])
62
+
63
+ # Save both as separate sheets in the same feather file using a different approach
64
+ # Since feather doesn't support multiple sheets, we'll store metadata as the first row
65
+ # and add a special marker
66
+
67
+ # Create combined structure with metadata as first row
68
+ metadata_row = {
69
+ 'patterns': f"__METADATA__{model_metadata['model_id']}",
70
+ 'responses': model_metadata['knowledge_base'],
71
+ 'weights': float(model_metadata['confidence']),
72
+ 'response_templates': f"{model_metadata['keywords']}|{model_metadata['training_samples']}|{model_metadata['semantic_categories']}|{model_metadata['grammar_rules']}"
73
+ }
74
+
75
+ # Combine metadata row with pattern data
76
+ combined_data = [metadata_row]
77
+
78
+ for i in range(len(patterns)):
79
+ row = {
80
+ 'patterns': df_data['patterns'][i],
81
+ 'responses': df_data['responses'][i],
82
+ 'weights': df_data['weights'][i],
83
+ 'response_templates': str(df_data['response_templates'][i])
84
+ }
85
+ combined_data.append(row)
86
+
87
+ df_combined = pd.DataFrame(combined_data)
88
+ df_combined.to_feather(filepath)
89
+
90
+ print(f"Saved optimized mini-model: {filename} ({len(patterns)} patterns + metadata)")
91
+ return filepath
92
+
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
+
97
+ if not os.path.exists(filepath):
98
+ return None
99
+
100
+ try:
101
+ df = pd.read_feather(filepath)
102
+
103
+ # FIXED: Load optimized structure for AgGPT-19
104
+ if len(df) == 0:
105
+ return None
106
+
107
+ # First row contains metadata (marked with __METADATA__)
108
+ if df['patterns'].iloc[0].startswith('__METADATA__'):
109
+ # Extract metadata from first row
110
+ metadata_parts = df['response_templates'].iloc[0].split('|')
111
+
112
+ model_data = {
113
+ 'model_id': model_id,
114
+ 'confidence': float(df['weights'].iloc[0]),
115
+ 'keywords': metadata_parts[0].split() if len(metadata_parts) > 0 else [],
116
+ 'training_samples': int(metadata_parts[1]) if len(metadata_parts) > 1 and metadata_parts[1].isdigit() else 0,
117
+ }
118
+
119
+ # Parse knowledge base from responses column
120
+ try:
121
+ kb_str = df['responses'].iloc[0]
122
+ model_data['knowledge_base'] = eval(kb_str) if kb_str != '{}' else {}
123
+ except:
124
+ model_data['knowledge_base'] = {}
125
+
126
+ # Parse semantic categories
127
+ try:
128
+ if len(metadata_parts) > 2:
129
+ model_data['semantic_categories'] = eval(metadata_parts[2]) if metadata_parts[2] != '{}' else {}
130
+ else:
131
+ model_data['semantic_categories'] = {}
132
+ except:
133
+ model_data['semantic_categories'] = {}
134
+
135
+ # Parse grammar rules
136
+ try:
137
+ if len(metadata_parts) > 3:
138
+ model_data['grammar_rules'] = eval(metadata_parts[3]) if metadata_parts[3] != '[]' else []
139
+ else:
140
+ model_data['grammar_rules'] = []
141
+ except:
142
+ model_data['grammar_rules'] = []
143
+
144
+ # Extract pattern data (skip metadata row)
145
+ pattern_df = df.iloc[1:].copy()
146
+
147
+ model_data['patterns'] = [p for p in pattern_df['patterns'].tolist() if p]
148
+ model_data['responses'] = [r for r in pattern_df['responses'].tolist() if r]
149
+ model_data['weights'] = pattern_df['weights'].tolist()
150
+
151
+ # Parse response templates
152
+ response_templates = []
153
+ for template_str in pattern_df['response_templates'].tolist():
154
+ try:
155
+ template = eval(template_str) if template_str not in ['{}', ''] else {}
156
+ response_templates.append(template)
157
+ except:
158
+ response_templates.append({})
159
+
160
+ model_data['response_templates'] = response_templates
161
+
162
+ else:
163
+ # Fallback: Load old format (for backward compatibility)
164
+ model_data = {
165
+ 'patterns': [p for p in df['patterns'].tolist() if p],
166
+ 'responses': [r for r in df['responses'].tolist() if r],
167
+ 'weights': df['weights'].tolist(),
168
+ 'confidence': df.get('confidence', pd.Series([0.5])).iloc[0] if 'confidence' in df.columns else 0.5,
169
+ 'keywords': df.get('keywords', pd.Series([''])).iloc[0].split() if 'keywords' in df.columns else [],
170
+ 'training_samples': df.get('training_samples', pd.Series([0])).iloc[0] if 'training_samples' in df.columns else 0,
171
+ 'model_id': model_id,
172
+ 'knowledge_base': {},
173
+ 'semantic_categories': {},
174
+ 'response_templates': [],
175
+ 'grammar_rules': []
176
+ }
177
+
178
+ return model_data
179
+
180
+ except Exception as e:
181
+ print(f"Error loading optimized model {model_id}: {e}")
182
+ return None
183
+
184
+ def load_all_models(self) -> List[Dict[str, Any]]:
185
+ models = []
186
+
187
+ if not os.path.exists(self.models_dir):
188
+ return models
189
+
190
+ for filename in os.listdir(self.models_dir):
191
+ if filename.startswith("AgGPT_Expert_") and filename.endswith(".feather"):
192
+ try:
193
+ model_id = int(filename.split("_")[2].split(".")[0])
194
+ model = self.load_mini_model(model_id)
195
+ if model:
196
+ models.append(model)
197
+ except (ValueError, IndexError):
198
+ print(f"Warning: Invalid model filename format: {filename}")
199
+ continue
200
+
201
+ return models
202
+
203
+ def get_model_count(self) -> int:
204
+ if not os.path.exists(self.models_dir):
205
+ return 0
206
+
207
+ count = 0
208
+ for filename in os.listdir(self.models_dir):
209
+ if filename.startswith("AgGPT_Expert_") and filename.endswith(".feather"):
210
+ count += 1
211
+
212
+ return count
213
+
214
+ def get_next_model_id(self) -> int:
215
+ if not os.path.exists(self.models_dir):
216
+ return 1
217
+
218
+ max_id = 0
219
+ for filename in os.listdir(self.models_dir):
220
+ if filename.startswith("AgGPT_Expert_") and filename.endswith(".feather"):
221
+ try:
222
+ model_id = int(filename.split("_")[2].split(".")[0])
223
+ max_id = max(max_id, model_id)
224
+ except (ValueError, IndexError):
225
+ continue
226
+
227
+ return max_id + 1
228
+
229
+ def delete_model(self, model_id: int) -> bool:
230
+ filename = f"AgGPT_Expert_{model_id:04d}.feather"
231
+ filepath = os.path.join(self.models_dir, filename)
232
+
233
+ if os.path.exists(filepath):
234
+ try:
235
+ os.remove(filepath)
236
+ print(f"Deleted model: {filename}")
237
+ return True
238
+ except Exception as e:
239
+ print(f"Error deleting model {model_id}: {e}")
240
+ return False
241
+
242
+ return False
243
+
244
+ def clear_all_models(self) -> int:
245
+ if not os.path.exists(self.models_dir):
246
+ return 0
247
+
248
+ deleted_count = 0
249
+ for filename in os.listdir(self.models_dir):
250
+ if filename.startswith("AgGPT_Expert_") and filename.endswith(".feather"):
251
+ try:
252
+ os.remove(os.path.join(self.models_dir, filename))
253
+ deleted_count += 1
254
+ except Exception as e:
255
+ print(f"Error deleting {filename}: {e}")
256
+
257
+ print(f"Deleted {deleted_count} model files")
258
+ return deleted_count
259
+
260
+
261
+ def similarity_score(text1: str, text2: str) -> float:
262
+ """Enhanced semantic similarity calculation for AgGPT-19"""
263
+ if not text1 or not text2:
264
+ return 0.0
265
+
266
+ # Normalize texts
267
+ text1_clean = text1.lower().strip()
268
+ text2_clean = text2.lower().strip()
269
+
270
+ # Exact match bonus
271
+ if text1_clean == text2_clean:
272
+ return 1.0
273
+
274
+ # Character-level similarity (for typos and variations)
275
+ char_sim = _character_similarity(text1_clean, text2_clean)
276
+
277
+ # Word-level analysis
278
+ words1 = set(text1_clean.split())
279
+ words2 = set(text2_clean.split())
280
+
281
+ if not words1 or not words2:
282
+ return char_sim * 0.3
283
+
284
+ # Jaccard similarity (word overlap)
285
+ intersection = len(words1.intersection(words2))
286
+ union = len(words1.union(words2))
287
+ jaccard = intersection / union if union > 0 else 0.0
288
+
289
+ # Semantic word analysis
290
+ semantic_sim = _semantic_word_similarity(words1, words2)
291
+
292
+ # N-gram similarity
293
+ ngram_sim = _ngram_similarity(text1_clean, text2_clean)
294
+
295
+ # Length penalty for very different lengths
296
+ len1, len2 = len(text1_clean.split()), len(text2_clean.split())
297
+ length_penalty = 1.0 - min(abs(len1 - len2) / max(len1, len2, 1), 0.5)
298
+
299
+ # Combine all similarity measures
300
+ final_score = (
301
+ jaccard * 0.4 + # Word overlap
302
+ semantic_sim * 0.3 + # Semantic similarity
303
+ ngram_sim * 0.2 + # Character patterns
304
+ char_sim * 0.1 # Character similarity
305
+ ) * length_penalty
306
+
307
+ return min(final_score, 1.0)
308
+
309
+
310
+ def _character_similarity(text1: str, text2: str) -> float:
311
+ """Calculate character-level similarity using longest common subsequence"""
312
+ if not text1 or not text2:
313
+ return 0.0
314
+
315
+ # Simple LCS implementation
316
+ len1, len2 = len(text1), len(text2)
317
+ dp = [[0] * (len2 + 1) for _ in range(len1 + 1)]
318
+
319
+ for i in range(1, len1 + 1):
320
+ for j in range(1, len2 + 1):
321
+ if text1[i-1] == text2[j-1]:
322
+ dp[i][j] = dp[i-1][j-1] + 1
323
+ else:
324
+ dp[i][j] = max(dp[i-1][j], dp[i][j-1])
325
+
326
+ lcs_length = dp[len1][len2]
327
+ return (2.0 * lcs_length) / (len1 + len2) if (len1 + len2) > 0 else 0.0
328
+
329
+
330
+ def _semantic_word_similarity(words1: set, words2: set) -> float:
331
+ """Calculate semantic similarity between word sets"""
332
+ if not words1 or not words2:
333
+ return 0.0
334
+
335
+ # Common semantic patterns
336
+ synonyms = {
337
+ 'hello': {'hi', 'hey', 'greetings', 'good morning', 'good afternoon'},
338
+ 'thanks': {'thank you', 'appreciate', 'grateful'},
339
+ 'yes': {'yeah', 'yep', 'sure', 'absolutely', 'definitely'},
340
+ 'no': {'nope', 'negative', 'not really'},
341
+ 'good': {'great', 'excellent', 'wonderful', 'amazing', 'fantastic'},
342
+ 'bad': {'terrible', 'awful', 'horrible', 'poor'},
343
+ 'big': {'large', 'huge', 'enormous', 'massive'},
344
+ 'small': {'little', 'tiny', 'mini', 'minute'},
345
+ }
346
+
347
+ # Find semantic matches
348
+ semantic_matches = 0
349
+ total_comparisons = 0
350
+
351
+ for word1 in words1:
352
+ for word2 in words2:
353
+ total_comparisons += 1
354
+
355
+ # Direct match
356
+ if word1 == word2:
357
+ semantic_matches += 1
358
+ continue
359
+
360
+ # Check synonyms
361
+ for key, synonym_set in synonyms.items():
362
+ if word1 in synonym_set and word2 in synonym_set:
363
+ semantic_matches += 0.8
364
+ break
365
+ elif (word1 == key and word2 in synonym_set) or (word2 == key and word1 in synonym_set):
366
+ semantic_matches += 0.9
367
+ break
368
+
369
+ # Partial word matching (for variations)
370
+ if len(word1) > 3 and len(word2) > 3:
371
+ if word1 in word2 or word2 in word1:
372
+ semantic_matches += 0.6
373
+ elif word1[:3] == word2[:3]: # Same prefix
374
+ semantic_matches += 0.4
375
+
376
+ return semantic_matches / total_comparisons if total_comparisons > 0 else 0.0
377
+
378
+
379
+ def _ngram_similarity(text1: str, text2: str, n: int = 3) -> float:
380
+ """Calculate n-gram similarity for character patterns"""
381
+ if len(text1) < n or len(text2) < n:
382
+ return 0.0
383
+
384
+ ngrams1 = set(text1[i:i+n] for i in range(len(text1) - n + 1))
385
+ ngrams2 = set(text2[i:i+n] for i in range(len(text2) - n + 1))
386
+
387
+ if not ngrams1 or not ngrams2:
388
+ return 0.0
389
+
390
+ intersection = len(ngrams1.intersection(ngrams2))
391
+ union = len(ngrams1.union(ngrams2))
392
+
393
+ return intersection / union if union > 0 else 0.0
394
+
395
+
396
+ def calculate_confidence_score(patterns: List[str], responses: List[str]) -> float:
397
+ if not patterns or not responses or len(patterns) != len(responses):
398
+ return 0.1
399
+
400
+ base_confidence = min(0.9, len(patterns) / 10.0)
401
+
402
+ return max(0.1, min(1.0, base_confidence))
403
+
404
+
405
+ if __name__ == "__main__":
406
+ manager = FeatherManager()
407
+
408
+ test_model = {
409
+ 'patterns': ['hello', 'hi', 'hey'],
410
+ 'responses': ['Hello! How can I help you?', 'Hi there!', 'Hey! What\'s up?'],
411
+ 'weights': [1.0, 0.9, 0.8],
412
+ 'confidence': 0.8,
413
+ 'grammar_rules': ['capitalize_first_word', 'end_with_punctuation'],
414
+ 'keywords': ['greeting', 'hello', 'hi'],
415
+ 'training_samples': 150
416
+ }
417
+
418
+ model_id = manager.get_next_model_id()
419
+ manager.save_mini_model(test_model, model_id)
420
+ loaded_model = manager.load_mini_model(model_id)
421
+
422
+ print(f"Original model: {test_model}")
423
+ print(f"Loaded model: {loaded_model}")
424
+ print(f"Models count: {manager.get_model_count()}")
train.py ADDED
@@ -0,0 +1,690 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ # Enhanced semantic patterns for AgGPT-19
25
+ self.semantic_groups = {
26
+ 'questions': ['what', 'how', 'why', 'when', 'where', 'who', 'which', 'can', 'could', 'would', 'should', 'is', 'are', 'do', 'does'],
27
+ 'greetings': ['hello', 'hi', 'hey', 'greetings', 'good morning', 'good afternoon', 'good evening'],
28
+ 'farewells': ['goodbye', 'bye', 'see you', 'farewell', 'take care'],
29
+ 'requests': ['please', 'can you', 'could you', 'would you', 'help me', 'i need', 'i want'],
30
+ 'emotions': ['happy', 'sad', 'angry', 'excited', 'worried', 'confused', 'frustrated'],
31
+ 'affirmations': ['yes', 'yeah', 'sure', 'okay', 'alright', 'definitely', 'absolutely'],
32
+ 'negations': ['no', 'not', 'never', 'nothing', 'none', 'neither'],
33
+ }
34
+
35
+ self.stop_words = {'the', 'a', 'an', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for', 'of', 'with', 'by'}
36
+
37
+ def extract_keywords(self, text: str) -> List[str]:
38
+ if not text:
39
+ return []
40
+
41
+ full_text_normalized = re.sub(r'\s+', ' ', text.strip().lower())
42
+ words = re.findall(r'\b[a-zA-Z]+\b', full_text_normalized)
43
+
44
+ # Remove stop words for better keyword extraction
45
+ meaningful_words = [word for word in words if word not in self.stop_words and len(word) > 2]
46
+
47
+ # Add semantic categories
48
+ semantic_keywords = []
49
+ for category, category_words in self.semantic_groups.items():
50
+ if any(word in meaningful_words for word in category_words):
51
+ semantic_keywords.append(f'semantic_{category}')
52
+
53
+ # Extract named entities (simple approach)
54
+ entities = self._extract_simple_entities(full_text_normalized)
55
+
56
+ result = [full_text_normalized]
57
+ result.extend(meaningful_words[:10]) # Limit to top 10 words
58
+ result.extend(semantic_keywords)
59
+ result.extend(entities)
60
+
61
+ return list(set(result))
62
+
63
+ def _extract_simple_entities(self, text: str) -> List[str]:
64
+ """Extract simple entities without external libraries"""
65
+ entities = []
66
+
67
+ # Numbers
68
+ numbers = re.findall(r'\b\d+\b', text)
69
+ entities.extend([f'number_{num}' for num in numbers[:3]])
70
+
71
+ # Capitalized words (potential names/places)
72
+ original_words = re.findall(r'\b[A-Z][a-z]+\b', text)
73
+ entities.extend([f'entity_{word.lower()}' for word in original_words[:3]])
74
+
75
+ # Time expressions
76
+ time_patterns = ['today', 'tomorrow', 'yesterday', 'morning', 'evening', 'night', 'afternoon']
77
+ for pattern in time_patterns:
78
+ if pattern in text.lower():
79
+ entities.append(f'time_{pattern}')
80
+
81
+ return entities
82
+
83
+ def create_pattern(self, user_input: str) -> str:
84
+ if not user_input:
85
+ return ""
86
+
87
+ # Enhanced pattern creation with semantic understanding
88
+ normalized = re.sub(r'\s+', ' ', user_input.strip().lower())
89
+
90
+ # Extract semantic structure
91
+ words = normalized.split()
92
+ semantic_pattern = []
93
+
94
+ for word in words:
95
+ # Check if word belongs to semantic groups
96
+ added_semantic = False
97
+ for category, category_words in self.semantic_groups.items():
98
+ if word in category_words:
99
+ semantic_pattern.append(f'<{category}>')
100
+ added_semantic = True
101
+ break
102
+
103
+ if not added_semantic:
104
+ if word in self.stop_words:
105
+ semantic_pattern.append(f'<stop>')
106
+ elif word.isdigit():
107
+ semantic_pattern.append('<number>')
108
+ elif len(word) > 6: # Longer words are more specific
109
+ semantic_pattern.append(word)
110
+ else:
111
+ semantic_pattern.append(f'<word>')
112
+
113
+ # Create both literal and semantic patterns
114
+ literal_pattern = f" {normalized} "
115
+ semantic_structure = " ".join(semantic_pattern)
116
+
117
+ return f"{literal_pattern}|{semantic_structure}"
118
+
119
+ def calculate_pattern_similarity(self, pattern1: str, pattern2: str) -> float:
120
+ # Enhanced similarity calculation for AgGPT-19
121
+ if not pattern1 or not pattern2:
122
+ return 0.0
123
+
124
+ # Split patterns if they contain semantic structure
125
+ parts1 = pattern1.strip().split('|')
126
+ parts2 = pattern2.strip().split('|')
127
+
128
+ literal1 = parts1[0].strip()
129
+ literal2 = parts2[0].strip()
130
+
131
+ # Calculate literal similarity
132
+ literal_sim = similarity_score(literal1, literal2)
133
+
134
+ # Calculate semantic similarity if available
135
+ semantic_sim = 0.0
136
+ if len(parts1) > 1 and len(parts2) > 1:
137
+ semantic1 = parts1[1].strip()
138
+ semantic2 = parts2[1].strip()
139
+ semantic_sim = self._semantic_structure_similarity(semantic1, semantic2)
140
+
141
+ # Combine similarities
142
+ if semantic_sim > 0:
143
+ return (literal_sim * 0.7 + semantic_sim * 0.3)
144
+ else:
145
+ return literal_sim
146
+
147
+ def _semantic_structure_similarity(self, struct1: str, struct2: str) -> float:
148
+ """Compare semantic structures"""
149
+ if not struct1 or not struct2:
150
+ return 0.0
151
+
152
+ tokens1 = struct1.split()
153
+ tokens2 = struct2.split()
154
+
155
+ if not tokens1 or not tokens2:
156
+ return 0.0
157
+
158
+ # Compare token patterns
159
+ matches = 0
160
+ total = max(len(tokens1), len(tokens2))
161
+
162
+ for i in range(min(len(tokens1), len(tokens2))):
163
+ if tokens1[i] == tokens2[i]:
164
+ matches += 1
165
+ elif tokens1[i].startswith('<') and tokens2[i].startswith('<'):
166
+ # Both are semantic tokens, partial match
167
+ matches += 0.5
168
+
169
+ return matches / total if total > 0 else 0.0
170
+
171
+
172
+ class MiniModelTrainer:
173
+
174
+ def __init__(self, feather_manager: FeatherManager):
175
+ self.feather_manager = feather_manager
176
+ self.pattern_extractor = PatternExtractor()
177
+ self.grammar_rules = GrammarRules()
178
+
179
+ def train_mini_model(self, training_pairs: List[Tuple[str, str]], confidence_threshold: float = 0.1) -> Dict[str, Any]:
180
+ if not training_pairs or len(training_pairs) < 2:
181
+ return None
182
+
183
+ # Enhanced training for AgGPT-19
184
+ keyword_patterns = []
185
+ responses = []
186
+ pattern_confidences = []
187
+ all_keywords = []
188
+ response_templates = []
189
+ knowledge_base = {}
190
+
191
+ for user_input, ai_response in training_pairs:
192
+ processed_response = ai_response.strip()
193
+
194
+ # Extract both patterns and semantic understanding
195
+ pattern = self.pattern_extractor.create_pattern(user_input)
196
+ keywords = self.pattern_extractor.extract_keywords(user_input)
197
+ all_keywords.extend(keywords)
198
+
199
+ # Create response templates for generation
200
+ template = self._create_response_template(ai_response, user_input)
201
+ response_templates.append(template)
202
+
203
+ # Build knowledge base
204
+ knowledge_entry = self._extract_knowledge(user_input, ai_response)
205
+ if knowledge_entry:
206
+ knowledge_base.update(knowledge_entry)
207
+
208
+ # Add the main pattern
209
+ keyword_patterns.append(pattern)
210
+ responses.append(processed_response)
211
+ individual_confidence = min(0.9, len(training_pairs) / 20.0)
212
+ pattern_confidences.append(individual_confidence)
213
+
214
+ if not keyword_patterns:
215
+ return None
216
+
217
+ base_confidence = min(0.9, len(training_pairs) / 20.0)
218
+ keyword_counter = Counter(all_keywords)
219
+ top_keywords = [word for word, count in keyword_counter.most_common(15)]
220
+
221
+ # Enhanced mini-model structure for AgGPT-19
222
+ mini_model = {
223
+ 'patterns': keyword_patterns,
224
+ 'responses': responses,
225
+ 'response_templates': response_templates,
226
+ 'knowledge_base': knowledge_base,
227
+ 'pattern_confidences': pattern_confidences,
228
+ 'confidence': base_confidence,
229
+ 'grammar_rules': [],
230
+ 'keywords': top_keywords,
231
+ 'training_samples': len(training_pairs),
232
+ 'semantic_categories': self._analyze_semantic_categories(training_pairs)
233
+ }
234
+
235
+ return mini_model
236
+
237
+ def _create_response_template(self, response: str, input_text: str) -> Dict[str, Any]:
238
+ """Create a template for generating similar responses"""
239
+ # Extract placeholders and structure
240
+ template = {
241
+ 'structure': 'direct', # direct, question, explanation, list
242
+ 'length': 'medium', # short, medium, long
243
+ 'tone': 'neutral', # friendly, formal, casual, neutral
244
+ 'placeholders': [],
245
+ 'key_phrases': [],
246
+ }
247
+
248
+ words = response.split()
249
+
250
+ # Determine response structure
251
+ if '?' in response:
252
+ template['structure'] = 'question'
253
+ elif any(word in response.lower() for word in ['first', 'second', 'then', 'next', '1.', '2.']):
254
+ template['structure'] = 'list'
255
+ elif len(words) > 50:
256
+ template['structure'] = 'explanation'
257
+
258
+ # Determine length
259
+ if len(words) < 10:
260
+ template['length'] = 'short'
261
+ elif len(words) > 30:
262
+ template['length'] = 'long'
263
+
264
+ # Determine tone
265
+ if any(word in response.lower() for word in ['please', 'thank you', 'great', 'wonderful']):
266
+ template['tone'] = 'friendly'
267
+ elif any(word in response.lower() for word in ['hey', 'yeah', 'cool', 'awesome']):
268
+ template['tone'] = 'casual'
269
+
270
+ # Extract key phrases (simple approach)
271
+ sentences = response.split('.')
272
+ template['key_phrases'] = [sent.strip() for sent in sentences if sent.strip() and len(sent.strip()) > 10][:3]
273
+
274
+ return template
275
+
276
+ def _extract_knowledge(self, question: str, answer: str) -> Dict[str, str]:
277
+ """Extract knowledge facts from Q&A pairs"""
278
+ knowledge = {}
279
+
280
+ # Simple fact extraction
281
+ question_lower = question.lower()
282
+
283
+ # Extract definitions
284
+ if any(word in question_lower for word in ['what is', 'what are', 'define']):
285
+ subject = self._extract_subject(question)
286
+ if subject:
287
+ knowledge[f'definition_{subject}'] = answer[:200] # Limit length
288
+
289
+ # Extract how-to knowledge
290
+ elif 'how to' in question_lower or 'how do' in question_lower:
291
+ topic = question_lower.replace('how to', '').replace('how do', '').strip()
292
+ if topic:
293
+ knowledge[f'howto_{topic[:20]}'] = answer[:300]
294
+
295
+ # Extract factual knowledge
296
+ elif any(word in question_lower for word in ['where', 'when', 'who', 'which']):
297
+ knowledge[f'fact_{hash(question) % 10000}'] = answer[:150]
298
+
299
+ return knowledge
300
+
301
+ def _extract_subject(self, question: str) -> str:
302
+ """Extract the main subject from a question"""
303
+ words = question.lower().split()
304
+
305
+ # Remove question words
306
+ question_words = {'what', 'is', 'are', 'the', 'a', 'an'}
307
+ filtered_words = [word for word in words if word not in question_words]
308
+
309
+ if filtered_words:
310
+ return '_'.join(filtered_words[:3]) # Take first 3 meaningful words
311
+
312
+ return ''
313
+
314
+ def _analyze_semantic_categories(self, training_pairs: List[Tuple[str, str]]) -> Dict[str, int]:
315
+ """Analyze what types of conversations this model handles"""
316
+ categories = {
317
+ 'questions': 0, 'greetings': 0, 'requests': 0, 'explanations': 0,
318
+ 'personal': 0, 'technical': 0, 'casual': 0, 'factual': 0
319
+ }
320
+
321
+ for user_input, ai_response in training_pairs:
322
+ input_lower = user_input.lower()
323
+
324
+ # Categorize inputs
325
+ if any(word in input_lower for word in ['what', 'how', 'why', 'when', 'where']):
326
+ categories['questions'] += 1
327
+ if any(word in input_lower for word in ['hello', 'hi', 'hey']):
328
+ categories['greetings'] += 1
329
+ if any(word in input_lower for word in ['please', 'can you', 'help']):
330
+ categories['requests'] += 1
331
+ if any(word in input_lower for word in ['i', 'my', 'me']):
332
+ categories['personal'] += 1
333
+ if any(word in input_lower for word in ['code', 'program', 'technical', 'computer']):
334
+ categories['technical'] += 1
335
+ if len(ai_response.split()) > 30:
336
+ categories['explanations'] += 1
337
+
338
+ return categories
339
+
340
+ def should_merge_models(self, model1: Dict[str, Any], model2: Dict[str, Any], merge_threshold: float = 0.8) -> bool:
341
+ keywords1 = set(model1.get('keywords', []))
342
+ keywords2 = set(model2.get('keywords', []))
343
+
344
+ if not keywords1 or not keywords2:
345
+ return False
346
+
347
+ keyword_similarity = len(keywords1.intersection(keywords2)) / len(keywords1.union(keywords2))
348
+
349
+ responses1 = model1.get('responses', [])
350
+ responses2 = model2.get('responses', [])
351
+
352
+ response_similarities = []
353
+ for r1 in responses1[:5]:
354
+ for r2 in responses2[:5]:
355
+ sim = similarity_score(r1, r2)
356
+ response_similarities.append(sim)
357
+
358
+ avg_response_similarity = sum(response_similarities) / len(response_similarities) if response_similarities else 0
359
+
360
+ min_confidence = min(model1.get('confidence', 0), model2.get('confidence', 0))
361
+
362
+ return (keyword_similarity > merge_threshold and
363
+ avg_response_similarity > merge_threshold and
364
+ min_confidence > 0.7)
365
+
366
+ def merge_mini_models(self, model1: Dict[str, Any], model2: Dict[str, Any]) -> Dict[str, Any]:
367
+ patterns1 = model1.get('patterns', [])
368
+ patterns2 = model2.get('patterns', [])
369
+ responses1 = model1.get('responses', [])
370
+ responses2 = model2.get('responses', [])
371
+ confidences1 = model1.get('pattern_confidences', [1.0] * len(patterns1))
372
+ confidences2 = model2.get('pattern_confidences', [1.0] * len(patterns2))
373
+
374
+ merged_model = {
375
+ 'patterns': patterns1 + patterns2,
376
+ 'responses': responses1 + responses2,
377
+ 'pattern_confidences': confidences1 + confidences2,
378
+ 'confidence': (model1.get('confidence', 0) + model2.get('confidence', 0)) / 2,
379
+ 'grammar_rules': list(set(model1.get('grammar_rules', []) + model2.get('grammar_rules', []))),
380
+ 'keywords': list(set(model1.get('keywords', []) + model2.get('keywords', []))),
381
+ 'training_samples': model1.get('training_samples', 0) + model2.get('training_samples', 0)
382
+ }
383
+
384
+ return merged_model
385
+
386
+
387
+ class AgGPTTrainer:
388
+
389
+ def __init__(self, models_dir: str = "models"):
390
+ self.feather_manager = FeatherManager(models_dir)
391
+ self.mini_trainer = MiniModelTrainer(self.feather_manager)
392
+ self.target_size_mb = 5
393
+ self.estimated_size_per_pair = 1000
394
+ self.chunk_size = (self.target_size_mb * 1024 * 1024) // self.estimated_size_per_pair
395
+ self.readable_weights_dir = "readable_weights"
396
+ os.makedirs(self.readable_weights_dir, exist_ok=True)
397
+
398
+ def save_model_as_yaml(self, model_data: Dict[str, Any], model_id: int):
399
+ try:
400
+ filename = f"AgGPT_Model_{model_id:04d}.yaml"
401
+ filepath = os.path.join(self.readable_weights_dir, filename)
402
+
403
+ print(f"Creating YAML data for model {model_id}...")
404
+ yaml_data = {
405
+ 'model_info': {
406
+ 'model_id': model_id,
407
+ 'confidence': model_data.get('confidence', 0.5),
408
+ 'training_samples': model_data.get('training_samples', 0),
409
+ 'keywords': model_data.get('keywords', [])
410
+ },
411
+ 'patterns_and_responses': []
412
+ }
413
+
414
+ patterns = model_data.get('patterns', [])
415
+ responses = model_data.get('responses', [])
416
+ weights = model_data.get('weights', [])
417
+
418
+ print(f"Processing {len(patterns)} patterns...")
419
+ for i in range(len(patterns)):
420
+ entry = {
421
+ 'pattern': patterns[i] if i < len(patterns) else '',
422
+ 'response': responses[i] if i < len(responses) else '',
423
+ 'weight': weights[i] if i < len(weights) else 1.0
424
+ }
425
+ yaml_data['patterns_and_responses'].append(entry)
426
+
427
+ print(f"Writing YAML to {filepath}...")
428
+ with open(filepath, 'w', encoding='utf-8') as f:
429
+ yaml.dump(yaml_data, f, default_flow_style=False, allow_unicode=True, indent=2)
430
+
431
+ print(f"Saved readable model: {filename}")
432
+ except Exception as e:
433
+ print(f"Error in save_model_as_yaml: {e}")
434
+ import traceback
435
+ traceback.print_exc()
436
+
437
+ def load_training_data(self, file_path: str) -> List[Tuple[str, str]]:
438
+ training_pairs = []
439
+
440
+ with open(file_path, 'r', encoding='utf-8') as f:
441
+ content = f.read()
442
+
443
+ conversations = content.split('<eos>')
444
+
445
+ print(f"Processing {len(conversations)} conversation chunks...")
446
+
447
+ for conversation in tqdm(conversations, desc="Parsing conversations"):
448
+ conversation = conversation.strip()
449
+ if not conversation:
450
+ continue
451
+
452
+ user_match = re.search(r'user:\s*(.*?)(?=\n<pad>|\nai:|$)', conversation, re.DOTALL)
453
+ ai_match = re.search(r'ai:\s*(.*?)$', conversation, re.DOTALL)
454
+
455
+ if user_match and ai_match:
456
+ user_input = user_match.group(1).strip()
457
+ ai_response = ai_match.group(1).strip()
458
+
459
+ user_input = re.sub(r'<pad>', '', user_input).strip()
460
+ ai_response = re.sub(r'<pad>', '', ai_response).strip()
461
+
462
+ if user_input and ai_response and len(user_input) > 0 and len(ai_response) > 0:
463
+ training_pairs.append((user_input, ai_response))
464
+
465
+ print(f"Extracted {len(training_pairs)} training pairs")
466
+ return training_pairs
467
+
468
+ def create_training_chunks(self, training_pairs: List[Tuple[str, str]]) -> List[List[Tuple[str, str]]]:
469
+ shuffled_pairs = training_pairs.copy()
470
+ random.shuffle(shuffled_pairs)
471
+
472
+ chunks = []
473
+ total_pairs = len(shuffled_pairs)
474
+
475
+ for i in range(0, total_pairs, self.chunk_size):
476
+ chunk = shuffled_pairs[i:i + self.chunk_size]
477
+ if len(chunk) >= 5:
478
+ chunks.append(chunk)
479
+
480
+ print(f"Created {len(chunks)} training chunks (target: {self.target_size_mb}MB each)")
481
+ return chunks
482
+
483
+ def train_multiple_corpora(self, training_files: List[str] = None, merge_similar: bool = True):
484
+ """Train on multiple corpora files sequentially"""
485
+ if training_files is None:
486
+ # Automatically find all text files in training_corpora directory
487
+ training_dir = "training_corpora"
488
+ if os.path.exists(training_dir):
489
+ training_files = []
490
+ for filename in sorted(os.listdir(training_dir)):
491
+ if filename.endswith('.txt'):
492
+ training_files.append(os.path.join(training_dir, filename))
493
+ print(f"Found {len(training_files)} text files in {training_dir}")
494
+ else:
495
+ print(f"Warning: {training_dir} directory not found, falling back to default files")
496
+ training_files = ["training_data/corpora.txt", "training_data/corpora2.txt"]
497
+
498
+ print("Starting AgGPT-19 Multi-Corpora Training with Enhanced Intelligence")
499
+ print("=" * 70)
500
+
501
+ cleared_count = self.feather_manager.clear_all_models()
502
+ if cleared_count > 0:
503
+ print(f"Cleared {cleared_count} existing models")
504
+
505
+ all_trained_models = []
506
+ total_model_id = 1
507
+
508
+ for file_idx, training_file in enumerate(training_files, 1):
509
+ print(f"\n--- Training on file {file_idx}/{len(training_files)}: {training_file} ---")
510
+
511
+ if not os.path.exists(training_file):
512
+ print(f"Warning: Training file {training_file} does not exist. Skipping...")
513
+ continue
514
+
515
+ if os.path.getsize(training_file) == 0:
516
+ print(f"Warning: Training file {training_file} is empty. Skipping...")
517
+ continue
518
+
519
+ print(f"Loading training data from {training_file}...")
520
+ training_pairs = self.load_training_data(training_file)
521
+
522
+ if not training_pairs:
523
+ print(f"No training data found in {training_file}. Skipping...")
524
+ continue
525
+
526
+ print(f"Creating training chunks for {training_file}...")
527
+ training_chunks = self.create_training_chunks(training_pairs)
528
+
529
+ print(f"Training mini-models from {training_file}...")
530
+ file_trained_models = []
531
+
532
+ progress_bar = tqdm(training_chunks, desc=f"Training from {os.path.basename(training_file)}")
533
+ for chunk_idx, chunk in enumerate(progress_bar):
534
+ print(f"\nProcessing chunk {chunk_idx + 1}/{len(training_chunks)}")
535
+ mini_model = self.mini_trainer.train_mini_model(chunk)
536
+
537
+ if mini_model:
538
+ file_trained_models.append(mini_model)
539
+ all_trained_models.append(mini_model)
540
+ print(f"Saving model {total_model_id}...")
541
+ self.feather_manager.save_mini_model(mini_model, total_model_id)
542
+
543
+ if total_model_id == 1:
544
+ print("Saving first model as YAML...")
545
+ try:
546
+ self.save_model_as_yaml(mini_model, total_model_id)
547
+ print("YAML saved successfully")
548
+ except Exception as e:
549
+ print(f"Error saving YAML: {e}")
550
+
551
+ total_model_id += 1
552
+ print(f"Model {total_model_id - 1} completed")
553
+
554
+ try:
555
+ progress_bar.set_postfix({
556
+ 'File Models': len(file_trained_models),
557
+ 'Total Models': len(all_trained_models),
558
+ 'Confidence': f"{mini_model['confidence']:.3f}"
559
+ })
560
+ except Exception as e:
561
+ print(f"Error updating progress bar: {e}")
562
+
563
+ print(f"Completed training on {training_file}: {len(file_trained_models)} mini-models created")
564
+ print(f"Total models so far: {len(all_trained_models)}")
565
+
566
+ if merge_similar and len(all_trained_models) > 1:
567
+ print(f"Merging similar models after processing {training_file}...")
568
+ self._merge_similar_models()
569
+ current_count = self.feather_manager.get_model_count()
570
+ print(f"Models after merging: {current_count}")
571
+
572
+ print(f"\n--- Multi-Corpora Training Complete ---")
573
+ final_count = self.feather_manager.get_model_count()
574
+ print(f"Final model count: {final_count}")
575
+ print(f"Trained on {len([f for f in training_files if os.path.exists(f) and os.path.getsize(f) > 0])} corpora files")
576
+ print("=" * 70)
577
+
578
+ def train(self, training_file: str = "training_data/corpora.txt", merge_similar: bool = True):
579
+ print("Starting AgGPT-19 Training with Enhanced Intelligence")
580
+ print("=" * 60)
581
+
582
+ cleared_count = self.feather_manager.clear_all_models()
583
+ if cleared_count > 0:
584
+ print(f"Cleared {cleared_count} existing models")
585
+
586
+ print("Loading training data...")
587
+ training_pairs = self.load_training_data(training_file)
588
+
589
+ if not training_pairs:
590
+ print("No training data found!")
591
+ return
592
+
593
+ print("Creating training chunks...")
594
+ training_chunks = self.create_training_chunks(training_pairs)
595
+
596
+ print("Training mini-models...")
597
+ trained_models = []
598
+ model_id = 1
599
+
600
+ progress_bar = tqdm(training_chunks, desc="Training mini-models")
601
+ for chunk in progress_bar:
602
+ mini_model = self.mini_trainer.train_mini_model(chunk)
603
+
604
+ if mini_model:
605
+ trained_models.append(mini_model)
606
+ self.feather_manager.save_mini_model(mini_model, model_id)
607
+
608
+ if model_id == 1:
609
+ self.save_model_as_yaml(mini_model, model_id)
610
+
611
+ model_id += 1
612
+
613
+ progress_bar.set_postfix({
614
+ 'Models': len(trained_models),
615
+ 'Confidence': f"{mini_model['confidence']:.3f}"
616
+ })
617
+
618
+ print(f"Trained {len(trained_models)} mini-models")
619
+
620
+ if merge_similar and len(trained_models) > 1:
621
+ print("Merging similar models...")
622
+ self._merge_similar_models()
623
+
624
+ final_count = self.feather_manager.get_model_count()
625
+ print(f"Training complete! Final model count: {final_count}")
626
+ print("=" * 60)
627
+
628
+ def _merge_similar_models(self):
629
+ all_models = self.feather_manager.load_all_models()
630
+ if len(all_models) < 2:
631
+ return
632
+
633
+ merged_pairs = []
634
+ models_to_delete = set()
635
+
636
+ print(f"Checking {len(all_models)} models for merging opportunities...")
637
+
638
+ progress_bar = tqdm(range(len(all_models)), desc="Merging models")
639
+ for i in progress_bar:
640
+ if i in models_to_delete:
641
+ continue
642
+
643
+ for j in range(i + 1, len(all_models)):
644
+ if j in models_to_delete:
645
+ continue
646
+
647
+ model1 = all_models[i]
648
+ model2 = all_models[j]
649
+
650
+ if self.mini_trainer.should_merge_models(model1, model2):
651
+ merged_model = self.mini_trainer.merge_mini_models(model1, model2)
652
+
653
+ new_id = self.feather_manager.get_next_model_id()
654
+ self.feather_manager.save_mini_model(merged_model, new_id)
655
+
656
+ models_to_delete.add(i)
657
+ models_to_delete.add(j)
658
+ merged_pairs.append((model1.get('model_id', i), model2.get('model_id', j), new_id))
659
+
660
+ break
661
+
662
+ for model_idx in models_to_delete:
663
+ if model_idx < len(all_models):
664
+ model_id = all_models[model_idx].get('model_id', model_idx + 1)
665
+ self.feather_manager.delete_model(model_id)
666
+
667
+ if merged_pairs:
668
+ print(f"Merged {len(merged_pairs)} pairs of similar models")
669
+ else:
670
+ print("No similar models found for merging")
671
+
672
+
673
+ def main():
674
+ print("AgGPT-19 Enhanced Intelligence Trainer")
675
+ print("=" * 50)
676
+
677
+ trainer = AgGPTTrainer()
678
+
679
+ try:
680
+ trainer.train_multiple_corpora(merge_similar=False) # DISABLED: merging takes too long
681
+ except KeyboardInterrupt:
682
+ print("\nTraining interrupted by user")
683
+ except Exception as e:
684
+ print(f"Training failed: {e}")
685
+ import traceback
686
+ traceback.print_exc()
687
+
688
+
689
+ if __name__ == "__main__":
690
+ main()