File size: 17,506 Bytes
068bc7f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
#!/usr/bin/env python3
"""
Stack 2.9 Enhanced Chat Interface

Integrates all enhancement modules:
- NLP: Contextual embeddings, entity recognition, intent detection
- Knowledge Graph: RAG-based context retrieval
- Emotional Intelligence: Sentiment analysis, empathetic responses
- Collaboration: Multi-session conversation management
- Learning: Feedback collection, performance monitoring
"""

import os
import sys
import time
from pathlib import Path
from typing import Dict, Optional, Any

# Add src to path
sys.path.insert(0, str(Path(__file__).parent / "src"))

# Import enhancements
from enhancements import (
    get_config,
    EnhancementConfig,
    NLPConfig,
    KnowledgeGraphConfig,
    EmotionalIntelligenceConfig,
    CollaborationConfig,
    LearningConfig,
)

# Import enhancement modules
from enhancements.nlp import ContextualEmbedder, EntityRecognizer, IntentDetector
from enhancements.knowledge_graph import KnowledgeGraph, RAGEngine
from enhancements.emotional_intelligence import SentimentAnalyzer, EmpathyEngine
from enhancements.collaboration import ConversationStateManager, MCPIntegration
from enhancements.learning import FeedbackCollector, PerformanceMonitor


class Stack2_9Enhanced:
    """Enhanced Stack 2.9 with all enhancement modules."""

    def __init__(
        self,
        model_path: str = "/Users/walidsobhi/stack-2-9-final-model",
        config: Optional[EnhancementConfig] = None,
    ):
        """
        Initialize enhanced Stack 2.9.

        Args:
            model_path: Path to the model
            config: Enhancement configuration (uses default if not provided)
        """
        self.model_path = model_path
        self.config = config or get_config()

        # Initialize model (loaded lazily)
        self._model = None
        self._tokenizer = None

        # Initialize enhancement modules
        self._init_modules()

        print("=" * 50)
        print("Stack 2.9 - Enhanced Edition")
        print("=" * 50)
        print("\nEnhancements loaded:")
        print(f"  β€’ NLP: Intent Detection, Entity Recognition")
        print(f"  β€’ Knowledge Graph: RAG Enabled")
        print(f"  β€’ Emotional Intelligence: Sentiment + Empathy")
        print(f"  β€’ Collaboration: Multi-session Support")
        print(f"  β€’ Learning: Feedback + Performance Monitoring")
        print("\n" + "=" * 50)

    def _init_modules(self):
        """Initialize all enhancement modules."""
        # NLP Modules
        if self.config.nlp.use_bert_embeddings:
            self.embedder = ContextualEmbedder(
                model_name=self.config.nlp.bert_model,
                cache_size=self.config.nlp.embedding_cache_size,
            )
            print("  βœ“ BERT Embeddings loaded")
        else:
            self.embedder = None

        if self.config.nlp.use_entity_recognition:
            self.entity_recognizer = EntityRecognizer()
            print("  βœ“ Entity Recognition loaded")
        else:
            self.entity_recognizer = None

        if self.config.nlp.use_intent_detection:
            self.intent_detector = IntentDetector()
            print("  βœ“ Intent Detection loaded")
        else:
            self.intent_detector = None

        # Knowledge Graph
        if self.config.knowledge_graph.enabled:
            self.knowledge_graph = KnowledgeGraph(
                max_nodes=self.config.knowledge_graph.max_nodes,
                max_edges=self.config.knowledge_graph.max_edges,
            )
            print("  βœ“ Knowledge Graph initialized")
        else:
            self.knowledge_graph = None

        if self.config.knowledge_graph.rag_enabled:
            self.rag_engine = RAGEngine(
                top_k=self.config.knowledge_graph.rag_top_k,
                similarity_threshold=self.config.knowledge_graph.similarity_threshold,
            )
            # Add some seed documents
            self._seed_rag()
            print("  βœ“ RAG Engine initialized")
        else:
            self.rag_engine = None

        # Emotional Intelligence
        if self.config.emotional_intelligence.enabled:
            self.sentiment_analyzer = SentimentAnalyzer()
            self.empathy_engine = EmpathyEngine()
            print("  βœ“ Emotional Intelligence loaded")
        else:
            self.sentiment_analyzer = None
            self.empathy_engine = None

        # Collaboration
        if self.config.collaboration.conversation_state_enabled:
            self.conversation_manager = ConversationStateManager(
                max_sessions=self.config.collaboration.max_sessions,
                session_timeout_minutes=self.config.collaboration.session_timeout_minutes,
            )
            print("  βœ“ Conversation Manager loaded")
        else:
            self.conversation_manager = None

        if self.config.collaboration.mcp_enabled:
            self.mcp = MCPIntegration()
            print("  βœ“ MCP Integration loaded")
        else:
            self.mcp = None

        # Learning
        if self.config.learning.enabled:
            self.feedback_collector = FeedbackCollector(
                storage_path=self.config.learning.feedback_storage_path,
            )
            self.performance_monitor = PerformanceMonitor()
            print("  βœ“ Learning System loaded")
        else:
            self.feedback_collector = None
            self.performance_monitor = None

    def _seed_rag(self):
        """Add seed documents to RAG engine."""
        seed_docs = [
            {
                "id": "intro",
                "content": "Stack 2.9 is an expert AI coding assistant. It helps with programming, debugging, and technical questions.",
            },
            {
                "id": "commands",
                "content": "Available commands: search:<query> for web search, quit/exit to end session, feedback to rate response.",
            },
            {
                "id": "capabilities",
                "content": "Stack 2.9 can: write code, debug errors, explain concepts, refactor code, analyze projects, and more.",
            },
        ]
        for doc in seed_docs:
            self.rag_engine.add_document(doc["id"], doc["content"])

    def load_model(self):
        """Lazy load the model from local files only."""
        if self._model is None:
            import os
            from pathlib import Path

            model_dir = Path(self.model_path)

            # Check local files exist
            required_files = ["model.safetensors", "config.json", "tokenizer.json"]
            missing = [f for f in required_files if not (model_dir / f).exists()]

            if missing:
                print(f"\n❌ Missing files: {missing}")
                print(f"   Model path: {self.model_path}")
                return

            print(f"\nLoading model from {self.model_path}...")
            print(f"   Found: {required_files}")
            import torch
            from transformers import AutoModelForCausalLM, AutoTokenizer

            # Load from local files only - force no network
            self._tokenizer = AutoTokenizer.from_pretrained(
                str(model_dir),
                local_files_only=True,
            )
            self._model = AutoModelForCausalLM.from_pretrained(
                str(model_dir),
                torch_dtype=torch.float16,
                device_map="auto",
                local_files_only=True,
            )
            print("βœ“ Model loaded from local files!\n")

    def process_input(self, user_input: str) -> Dict[str, Any]:
        """
        Process user input with all enhancements.

        Returns:
            Dictionary with processed data
        """
        result = {
            "original_input": user_input,
            "entities": [],
            "intent": None,
            "sentiment": None,
            "rag_context": "",
            "response": None,
            "emotion_tone": "neutral",
        }

        # 1. Intent Detection
        if self.intent_detector:
            intent_result = self.intent_detector.detect_intent(user_input)
            result["intent"] = intent_result

        # 2. Entity Recognition
        if self.entity_recognizer:
            entities = self.entity_recognizer.recognize_entities(user_input)
            result["entities"] = entities

            # Add entities to knowledge graph
            if self.knowledge_graph:
                for entity in entities:
                    self.knowledge_graph.add_entity(
                        entity["text"],
                        entity["type"],
                        {"confidence": entity.get("score", 1.0)}
                    )

        # 3. Sentiment Analysis
        if self.sentiment_analyzer:
            sentiment = self.sentiment_analyzer.analyze_sentiment(user_input)
            result["sentiment"] = sentiment
            result["emotion_tone"] = self.sentiment_analyzer.get_tone_adjustment(user_input)

        # 4. RAG Context Retrieval
        if self.rag_engine:
            result["rag_context"] = self.rag_engine.retrieve_as_context(
                user_input,
                max_context_length=500
            )

        # 5. Conversation State
        if self.conversation_manager:
            self.conversation_manager.add_message("user", user_input)
            # Store context
            self.conversation_manager.update_context("last_intent", result["intent"]["intent"] if result["intent"] else None)

        return result

    def generate_response(
        self,
        user_input: str,
        processed_data: Dict[str, Any],
    ) -> str:
        """Generate model response with enhancements."""
        self.load_model()

        # Build enhanced prompt
        system_parts = ["You are Stack 2.9, an expert AI coding assistant."]

        # Add RAG context if available
        if processed_data.get("rag_context"):
            system_parts.append(f"\nContext: {processed_data['rag_context']}")

        # Add emotional tone guidance
        emotion_tone = processed_data.get("emotion_tone", "neutral")
        if emotion_tone == "empathetic":
            system_parts.append("\nBe empathetic and understanding.")
        elif emotion_tone == "enthusiastic":
            system_parts.append("\nBe enthusiastic and positive.")
        elif emotion_tone == "supportive":
            system_parts.append("\nBe supportive and reassuring.")

        system_prompt = " ".join(system_parts)

        # Build full prompt
        full_prompt = f"{system_prompt}\n\nUser: {user_input}\nAssistant:"

        # Generate
        start_time = time.time()
        inputs = self._tokenizer(full_prompt, return_tensors='pt').to(self._model.device)

        outputs = self._model.generate(
            **inputs,
            max_new_tokens=200,
            temperature=0.4,
            top_p=0.9,
            repetition_penalty=1.2,
            do_sample=True,
            pad_token_id=self._tokenizer.eos_token_id
        )

        response_time = time.time() - start_time

        # Decode response
        full_response = self._tokenizer.decode(outputs[0], skip_special_tokens=True)

        # Extract assistant response
        if "Assistant:" in full_response:
            response = full_response.split("Assistant:")[-1].strip()
        else:
            response = full_response[len(full_prompt):].strip()

        # Clean up response
        for stop in ['\n\n\n', 'User:', 'You:']:
            if stop in response:
                response = response.split(stop)[0].strip()

        # Apply empathy if emotional intelligence enabled
        if self.empathy_engine and processed_data.get("sentiment"):
            response = self.empathy_engine.generate_empathetic_response(
                user_input,
                response
            )

        # Record performance
        if self.performance_monitor:
            self.performance_monitor.record_response_time(response_time)
            self.performance_monitor.record_successful_interaction()
            self.performance_monitor.increment_message_count()

        # Add to conversation history
        if self.conversation_manager:
            self.conversation_manager.add_message("assistant", response)

        return response

    def chat_loop(self):
        """Run interactive chat loop."""
        print("\n" + "=" * 50)
        print("Chat Commands:")
        print("  β€’ Type your message to chat")
        print("  β€’ 'search:<query>' - Web search")
        print("  β€’ 'feedback' - Rate last response")
        print("  β€’ 'quit' or 'exit' - End session")
        print("=" * 50 + "\n")

        # Create session
        if self.conversation_manager:
            session_id = self.conversation_manager.create_session()
            self.performance_monitor.increment_session_count()
            print(f"Session started: {session_id[:8]}...\n")

        last_response = None
        last_user_input = None

        while True:
            try:
                user_input = input("You: ").strip()

                if not user_input:
                    continue

                if user_input.lower() in ['quit', 'exit', 'q']:
                    print("\nEnding session...")
                    if self.feedback_collector and last_user_input and last_response:
                        print("Thanks for chatting!")
                    break

                # Handle feedback command
                if user_input.lower() == 'feedback' and self.feedback_collector:
                    print("\nRate last response (1-5): ", end="")
                    rating_input = input().strip()
                    try:
                        rating = int(rating_input)
                        if 1 <= rating <= 5:
                            self.feedback_collector.add_feedback(
                                feedback_type="rating",
                                message=last_user_input or "",
                                response=last_response or "",
                                rating=rating,
                            )
                            print("βœ“ Thanks for your feedback!")
                    except ValueError:
                        print("Invalid rating.")
                    continue

                # Handle search command
                if user_input.lower().startswith("search:"):
                    query = user_input[7:].strip()
                    print("πŸ” Searching...")
                    result = self._mcp_search(query)
                    if result["success"]:
                        print(f"\nβœ… Results for '{result['query']}':\n")
                        for i, r in enumerate(result["results"], 1):
                            print(f"  {i}. {r}")
                    else:
                        print(f"❌ Search failed: {result['error']}")
                    continue

                # Process and generate response
                processed = self.process_input(user_input)

                # Show intent detection (debug)
                if processed.get("intent") and processed["intent"]["confidence"] > 0.5:
                    intent = processed["intent"]["intent"]
                    print(f"  [Intent: {intent}]")

                response = self.generate_response(user_input, processed)

                print(f"AI: {response}\n")

                last_user_input = user_input
                last_response = response

            except KeyboardInterrupt:
                print("\n\nInterrupted. Goodbye!")
                break

        # Show session stats
        if self.performance_monitor:
            stats = self.performance_monitor.get_session_stats()
            print(f"\nSession Stats: {stats['total_messages']} messages")

    def _mcp_search(self, query: str) -> Dict[str, Any]:
        """Simple web search using MCP tool."""
        try:
            from ddgs import DDGS
            results = []
            with DDGS() as ddgs:
                for r in ddgs.text(query, max_results=5):
                    results.append(r['body'][:200])
                    if len(results) >= 5:
                        break

            if results:
                return {"success": True, "results": results, "query": query}
            return {"success": False, "error": "No results found"}
        except Exception as e:
            return {"success": False, "error": str(e)}


def main():
    """Main entry point."""
    import argparse

    parser = argparse.ArgumentParser(description="Stack 2.9 Enhanced Chat")
    parser.add_argument("--model", "-m", type=str,
                        default="/Users/walidsobhi/stack-2-9-final-model",
                        help="Path to model")
    parser.add_argument("--no-bert", action="store_true",
                        help="Disable BERT embeddings")
    parser.add_argument("--no-rag", action="store_true",
                        help="Disable RAG")
    parser.add_argument("--no-empathy", action="store_true",
                        help="Disable emotional intelligence")

    args = parser.parse_args()

    # Build config from args
    config = EnhancementConfig()
    config.nlp.use_bert_embeddings = not args.no_bert
    config.knowledge_graph.rag_enabled = not args.no_rag
    config.emotional_intelligence.empathetic_responses = not args.no_empathy

    # Create enhanced instance
    stack = Stack2_9Enhanced(model_path=args.model, config=config)

    # Run chat
    stack.chat_loop()


if __name__ == "__main__":
    main()