HassanJalil commited on
Commit
51a41f8
·
verified ·
1 Parent(s): 19f2060

Delete app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -1240
app.py DELETED
@@ -1,1240 +0,0 @@
1
- import streamlit as st
2
- import google.generativeai as genai
3
- from PyPDF2 import PdfReader
4
- import os
5
- import re
6
- import json
7
- import pickle
8
- import hashlib
9
- from datetime import datetime
10
- from pathlib import Path
11
- from langchain_text_splitters import RecursiveCharacterTextSplitter
12
- from langchain_huggingface.embeddings import HuggingFaceEmbeddings
13
- from langchain_community.vectorstores import FAISS
14
- from langchain.schema import Document
15
- import tempfile
16
- import warnings
17
- import numpy as np
18
- import shutil
19
- import time
20
- warnings.filterwarnings('ignore')
21
-
22
- # Configure page
23
- st.set_page_config(
24
- page_title="Ashok 2.0 - AI Problem Solving Assistant",
25
- page_icon="🧠",
26
- layout="centered",
27
- initial_sidebar_state="collapsed"
28
- )
29
-
30
- # World-class minimal UI styling
31
- st.markdown("""
32
- <style>
33
- /* Import premium font */
34
- @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
35
-
36
- /* Global Reset & Base */
37
- .stApp {
38
- background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
39
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
40
- }
41
-
42
- .main .block-container {
43
- padding-top: 2rem;
44
- padding-bottom: 2rem;
45
- max-width: 800px;
46
- }
47
-
48
- /* Hide Streamlit UI elements */
49
- #MainMenu {visibility: hidden;}
50
- footer {visibility: hidden;}
51
- header {visibility: hidden;}
52
- .stDeployButton {display: none;}
53
-
54
- /* Main Heading */
55
- .main-title {
56
- font-size: 4rem;
57
- font-weight: 700;
58
- text-align: center;
59
- background: linear-gradient(135deg, #1e40af 0%, #3b82f6 50%, #60a5fa 100%);
60
- -webkit-background-clip: text;
61
- -webkit-text-fill-color: transparent;
62
- background-clip: text;
63
- margin: 2rem 0 3rem 0;
64
- letter-spacing: -0.02em;
65
- line-height: 1.1;
66
- }
67
-
68
- /* API Key Setup Container */
69
- .api-setup-container {
70
- background: rgba(255, 255, 255, 0.9);
71
- backdrop-filter: blur(10px);
72
- border: 1px solid rgba(229, 231, 235, 0.6);
73
- border-radius: 24px;
74
- padding: 3rem;
75
- margin: 2rem auto;
76
- max-width: 500px;
77
- box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.05), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
78
- text-align: center;
79
- }
80
-
81
- .api-setup-title {
82
- font-size: 1.5rem;
83
- font-weight: 600;
84
- color: #1f2937;
85
- margin-bottom: 1rem;
86
- }
87
-
88
- .api-setup-subtitle {
89
- color: #6b7280;
90
- margin-bottom: 2rem;
91
- line-height: 1.6;
92
- }
93
-
94
- /* API Key Input Styling */
95
- .stTextInput > div > div > input {
96
- background: rgba(255, 255, 255, 0.8);
97
- border: 2px solid rgba(229, 231, 235, 0.6);
98
- border-radius: 16px;
99
- padding: 1rem 1.5rem;
100
- font-size: 1rem;
101
- transition: all 0.3s ease;
102
- backdrop-filter: blur(5px);
103
- }
104
-
105
- .stTextInput > div > div > input:focus {
106
- border-color: #3b82f6;
107
- box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.1);
108
- outline: none;
109
- background: rgba(255, 255, 255, 0.95);
110
- }
111
-
112
- .stTextInput label {
113
- font-weight: 500;
114
- color: #374151;
115
- margin-bottom: 0.5rem;
116
- }
117
-
118
- /* Chat Interface */
119
- .chat-container {
120
- background: rgba(255, 255, 255, 0.7);
121
- backdrop-filter: blur(10px);
122
- border: 1px solid rgba(229, 231, 235, 0.4);
123
- border-radius: 24px;
124
- padding: 2rem;
125
- margin: 2rem 0;
126
- box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.03), 0 4px 6px -2px rgba(0, 0, 0, 0.02);
127
- }
128
-
129
- /* Chat Messages */
130
- .stChatMessage {
131
- background: rgba(255, 255, 255, 0.9) !important;
132
- border: 1px solid rgba(0, 0, 0, 0.08) !important;
133
- border-radius: 16px !important;
134
- margin-bottom: 1rem !important;
135
- padding: 1.5rem !important;
136
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.02) !important;
137
- backdrop-filter: blur(5px) !important;
138
- }
139
-
140
- .stChatMessage[data-testid="chat-message-user"] {
141
- background: rgba(248, 250, 252, 0.9) !important;
142
- border-left: 3px solid #3b82f6 !important;
143
- }
144
-
145
- .stChatMessage[data-testid="chat-message-assistant"] {
146
- background: rgba(255, 255, 255, 0.9) !important;
147
- border-left: 3px solid #10b981 !important;
148
- }
149
-
150
- .stChatMessage .stMarkdown {
151
- color: #1f2937 !important;
152
- line-height: 1.6;
153
- }
154
-
155
- .stChatMessage .stMarkdown p {
156
- color: #1f2937 !important;
157
- margin-bottom: 0.5rem;
158
- }
159
-
160
- /* Chat Input */
161
- .stChatInput > div {
162
- background: rgba(255, 255, 255, 0.9);
163
- border: 1px solid rgba(229, 231, 235, 0.6);
164
- border-radius: 20px;
165
- backdrop-filter: blur(10px);
166
- }
167
-
168
- .stChatInput input {
169
- color: #1f2937 !important;
170
- background: transparent !important;
171
- border: none !important;
172
- padding: 1rem 1.5rem !important;
173
- }
174
-
175
- .stChatInput input::placeholder {
176
- color: #9ca3af !important;
177
- }
178
-
179
- /* Quick Actions */
180
- .quick-actions-container {
181
- background: rgba(255, 255, 255, 0.6);
182
- backdrop-filter: blur(10px);
183
- border: 1px solid rgba(229, 231, 235, 0.4);
184
- border-radius: 20px;
185
- padding: 2rem;
186
- margin: 2rem 0;
187
- }
188
-
189
- .quick-actions-title {
190
- font-size: 1.25rem;
191
- font-weight: 600;
192
- color: #1f2937;
193
- text-align: center;
194
- margin-bottom: 1.5rem;
195
- }
196
-
197
- .quick-action-grid {
198
- display: grid;
199
- grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
200
- gap: 1rem;
201
- margin-top: 1rem;
202
- }
203
-
204
- .quick-action-item {
205
- background: rgba(255, 255, 255, 0.8);
206
- border: 1px solid rgba(229, 231, 235, 0.5);
207
- border-radius: 16px;
208
- padding: 1.5rem;
209
- cursor: pointer;
210
- transition: all 0.3s ease;
211
- text-align: left;
212
- backdrop-filter: blur(5px);
213
- }
214
-
215
- .quick-action-item:hover {
216
- background: rgba(248, 250, 252, 0.9);
217
- border-color: #3b82f6;
218
- transform: translateY(-2px);
219
- box-shadow: 0 8px 25px rgba(59, 130, 246, 0.1);
220
- }
221
-
222
- .quick-action-icon {
223
- font-size: 1.5rem;
224
- margin-bottom: 0.5rem;
225
- }
226
-
227
- .quick-action-title {
228
- font-weight: 600;
229
- color: #1f2937;
230
- margin-bottom: 0.5rem;
231
- font-size: 1rem;
232
- }
233
-
234
- .quick-action-desc {
235
- color: #6b7280;
236
- font-size: 0.9rem;
237
- line-height: 1.5;
238
- }
239
-
240
- /* Control Panel */
241
- .control-panel {
242
- display: flex;
243
- justify-content: center;
244
- gap: 1rem;
245
- margin: 2rem 0;
246
- }
247
-
248
- .control-button {
249
- background: rgba(255, 255, 255, 0.8);
250
- border: 1px solid rgba(229, 231, 235, 0.6);
251
- border-radius: 12px;
252
- padding: 0.75rem 1.5rem;
253
- color: #374151;
254
- font-weight: 500;
255
- cursor: pointer;
256
- transition: all 0.3s ease;
257
- backdrop-filter: blur(5px);
258
- }
259
-
260
- .control-button:hover {
261
- background: rgba(248, 250, 252, 0.9);
262
- border-color: #3b82f6;
263
- color: #1f2937;
264
- transform: translateY(-1px);
265
- }
266
-
267
- /* Status Indicators */
268
- .status-success {
269
- background: linear-gradient(135deg, rgba(16, 185, 129, 0.1) 0%, rgba(5, 150, 105, 0.1) 100%);
270
- border: 1px solid rgba(16, 185, 129, 0.2);
271
- border-radius: 16px;
272
- padding: 1rem 1.5rem;
273
- margin: 1rem 0;
274
- color: #065f46;
275
- font-weight: 500;
276
- text-align: center;
277
- backdrop-filter: blur(5px);
278
- }
279
-
280
- .status-warning {
281
- background: linear-gradient(135deg, rgba(245, 158, 11, 0.1) 0%, rgba(217, 119, 6, 0.1) 100%);
282
- border: 1px solid rgba(245, 158, 11, 0.2);
283
- border-radius: 16px;
284
- padding: 1rem 1.5rem;
285
- margin: 1rem 0;
286
- color: #92400e;
287
- font-weight: 500;
288
- text-align: center;
289
- backdrop-filter: blur(5px);
290
- }
291
-
292
- /* Learning Indicator */
293
- .learning-indicator {
294
- background: linear-gradient(135deg, rgba(16, 185, 129, 0.9) 0%, rgba(5, 150, 105, 0.9) 100%);
295
- color: white;
296
- padding: 1rem 1.5rem;
297
- border-radius: 16px;
298
- margin: 1rem 0;
299
- font-weight: 500;
300
- text-align: center;
301
- box-shadow: 0 4px 6px rgba(16, 185, 129, 0.2);
302
- backdrop-filter: blur(10px);
303
- }
304
-
305
- /* Typing Indicator */
306
- .typing-indicator {
307
- background: rgba(248, 250, 252, 0.9);
308
- border: 1px solid rgba(229, 231, 235, 0.6);
309
- border-radius: 16px;
310
- padding: 1rem 1.5rem;
311
- margin: 1rem 0;
312
- display: flex;
313
- align-items: center;
314
- gap: 0.75rem;
315
- color: #6b7280;
316
- backdrop-filter: blur(5px);
317
- }
318
-
319
- .typing-dots {
320
- display: flex;
321
- gap: 4px;
322
- }
323
-
324
- .typing-dot {
325
- width: 6px;
326
- height: 6px;
327
- border-radius: 50%;
328
- background-color: #9ca3af;
329
- animation: typing 1.4s infinite ease-in-out;
330
- }
331
-
332
- .typing-dot:nth-child(1) { animation-delay: -0.32s; }
333
- .typing-dot:nth-child(2) { animation-delay: -0.16s; }
334
-
335
- @keyframes typing {
336
- 0%, 80%, 100% { transform: scale(0.8); opacity: 0.4; }
337
- 40% { transform: scale(1); opacity: 1; }
338
- }
339
-
340
- /* Button Styling */
341
- .stButton > button {
342
- background: linear-gradient(135deg, rgba(59, 130, 246, 0.9) 0%, rgba(37, 99, 235, 0.9) 100%);
343
- color: white !important;
344
- border: none;
345
- border-radius: 12px;
346
- padding: 0.75rem 2rem;
347
- font-weight: 500;
348
- transition: all 0.3s ease;
349
- backdrop-filter: blur(10px);
350
- box-shadow: 0 4px 6px rgba(59, 130, 246, 0.2);
351
- }
352
-
353
- .stButton > button:hover {
354
- background: linear-gradient(135deg, rgba(37, 99, 235, 0.9) 0%, rgba(29, 78, 216, 0.9) 100%);
355
- transform: translateY(-1px);
356
- box-shadow: 0 6px 12px rgba(59, 130, 246, 0.25);
357
- }
358
-
359
- /* API Key Guide */
360
- .api-guide {
361
- background: rgba(255, 255, 255, 0.6);
362
- border: 1px solid rgba(229, 231, 235, 0.4);
363
- border-radius: 16px;
364
- padding: 1.5rem;
365
- margin: 1.5rem 0;
366
- backdrop-filter: blur(5px);
367
- }
368
-
369
- .api-guide-title {
370
- font-weight: 600;
371
- color: #1f2937;
372
- margin-bottom: 1rem;
373
- }
374
-
375
- .api-guide-text {
376
- color: #6b7280;
377
- line-height: 1.6;
378
- margin-bottom: 0.5rem;
379
- }
380
-
381
- .api-link {
382
- color: #3b82f6;
383
- text-decoration: none;
384
- font-weight: 500;
385
- transition: color 0.2s ease;
386
- }
387
-
388
- .api-link:hover {
389
- color: #1d4ed8;
390
- }
391
-
392
- /* Responsive Design */
393
- @media (max-width: 768px) {
394
- .main-title {
395
- font-size: 3rem;
396
- }
397
-
398
- .api-setup-container {
399
- padding: 2rem;
400
- margin: 1rem;
401
- }
402
-
403
- .quick-action-grid {
404
- grid-template-columns: 1fr;
405
- }
406
-
407
- .control-panel {
408
- flex-direction: column;
409
- align-items: center;
410
- }
411
- }
412
- </style>
413
- """, unsafe_allow_html=True)
414
-
415
- class PersistentHFKnowledgeBase:
416
- """Persistent Knowledge Base with silent initialization"""
417
-
418
- def __init__(self):
419
- # Create persistent directories
420
- self.data_dir = Path("./persistent_data")
421
- self.data_dir.mkdir(exist_ok=True)
422
-
423
- # File paths for persistence
424
- self.vectorstore_path = self.data_dir / "vectorstore"
425
- self.metadata_path = self.data_dir / "metadata.json"
426
- self.conversations_path = self.data_dir / "conversations.json"
427
- self.stats_path = self.data_dir / "stats.json"
428
- self.init_flag_path = self.data_dir / "initialized.flag"
429
-
430
- # Initialize components
431
- self.embeddings = None
432
- self.vectorstore = None
433
- self.metadata = {}
434
- self.conversations = []
435
- self.stats = {}
436
-
437
- # Initialize system silently
438
- self.initialize_system()
439
-
440
- def initialize_system(self):
441
- """Initialize the complete system with silent book processing"""
442
- try:
443
- # Initialize embeddings first
444
- self.init_embeddings()
445
-
446
- # Check if system was already initialized
447
- if self.init_flag_path.exists():
448
- # Load existing knowledge base silently
449
- self.load_existing_knowledge()
450
- else:
451
- # First time initialization - do it silently
452
- self.first_time_initialization()
453
-
454
- except Exception as e:
455
- # Silent fallback initialization
456
- self.fallback_initialization()
457
-
458
- def init_embeddings(self):
459
- """Initialize embeddings model with silent caching"""
460
- if self.embeddings is None:
461
- try:
462
- cache_dir = self.data_dir / "embeddings_cache"
463
- cache_dir.mkdir(exist_ok=True)
464
-
465
- self.embeddings = HuggingFaceEmbeddings(
466
- model_name="sentence-transformers/all-MiniLM-L6-v2",
467
- cache_folder=str(cache_dir)
468
- )
469
- except Exception as e:
470
- return False
471
- return True
472
-
473
- def first_time_initialization(self):
474
- """Complete first-time setup with silent book processing"""
475
- try:
476
- # Initialize metadata
477
- self.metadata = {
478
- 'version': '2.0-minimal',
479
- 'created_at': datetime.now().isoformat(),
480
- 'last_updated': datetime.now().isoformat(),
481
- 'total_documents': 0,
482
- 'book_processed': False,
483
- 'book_info': {},
484
- 'initialization_complete': False
485
- }
486
-
487
- # Initialize stats
488
- self.stats = {
489
- 'total_queries': 0,
490
- 'learning_sessions': 0,
491
- 'book_chunks': 0,
492
- 'conversation_chunks': 0,
493
- 'silly_questions_blocked': 0
494
- }
495
-
496
- # Initialize conversations
497
- self.conversations = []
498
-
499
- # Process book if available (silently)
500
- book_processed = self.process_startup_book()
501
-
502
- # Create default knowledge if no book
503
- if not book_processed:
504
- self.create_default_knowledge()
505
-
506
- # Mark as initialized
507
- self.metadata['initialization_complete'] = True
508
- self.save_all_data()
509
-
510
- # Create initialization flag
511
- with open(self.init_flag_path, 'w') as f:
512
- f.write(f"Initialized on {datetime.now().isoformat()}")
513
-
514
- except Exception as e:
515
- self.fallback_initialization()
516
-
517
- def process_startup_book(self):
518
- """Process the book included with the deployment (silently)"""
519
- book_paths = [
520
- "book.pdf",
521
- "problem_solving_book.pdf",
522
- "default_book.pdf",
523
- "ashok_book.pdf"
524
- ]
525
-
526
- for book_path in book_paths:
527
- if Path(book_path).exists():
528
- success = self.process_book_file(Path(book_path))
529
- if success:
530
- return True
531
-
532
- return False
533
-
534
- def process_book_file(self, book_path):
535
- """Process a specific book file (silently)"""
536
- try:
537
- # Extract text from PDF
538
- reader = PdfReader(str(book_path))
539
- page_texts = []
540
-
541
- for page_num, page in enumerate(reader.pages, 1):
542
- page_text = page.extract_text()
543
- if page_text.strip():
544
- page_texts.append({
545
- 'page': page_num,
546
- 'text': page_text,
547
- 'word_count': len(page_text.split())
548
- })
549
-
550
- if not page_texts:
551
- return False
552
-
553
- # Create book info
554
- book_info = {
555
- 'title': book_path.name,
556
- 'path': str(book_path),
557
- 'pages': len(page_texts),
558
- 'processed_at': datetime.now().isoformat(),
559
- 'source': 'deployment_book'
560
- }
561
-
562
- # Process content
563
- success, message = self.process_book_content("", page_texts, book_info)
564
-
565
- return success
566
-
567
- except Exception as e:
568
- return False
569
-
570
- def create_default_knowledge(self):
571
- """Create comprehensive default knowledge base"""
572
- default_knowledge = [
573
- {
574
- "content": "Problem-solving methodology: 1) Problem Definition - Clearly articulate what needs to be solved, 2) Information Gathering - Collect relevant data and context, 3) Root Cause Analysis - Identify underlying causes, not just symptoms, 4) Solution Generation - Brainstorm multiple potential solutions, 5) Solution Evaluation - Assess feasibility, impact, and resources, 6) Implementation Planning - Create detailed action steps, 7) Execution and Monitoring - Implement and track progress, 8) Review and Learning - Evaluate outcomes and extract lessons.",
575
- "metadata": {
576
- "source": "core_knowledge",
577
- "type": "framework",
578
- "topic": "problem_solving_process",
579
- "chapter": "Core Problem-Solving Framework"
580
- }
581
- },
582
- {
583
- "content": "Decision-making best practices: Use the DECIDE framework - D: Define the problem clearly, E: Establish criteria for solutions, C: Consider alternatives systematically, I: Identify best alternatives using criteria, D: Develop and implement action plan, E: Evaluate and monitor solution effectiveness. Always consider stakeholder impact, resource constraints, time limitations, and potential risks.",
584
- "metadata": {
585
- "source": "core_knowledge",
586
- "type": "framework",
587
- "topic": "decision_making",
588
- "chapter": "Decision-Making Framework"
589
- }
590
- },
591
- {
592
- "content": "Conflict resolution strategies: 1) Active Listening - Understand all perspectives without judgment, 2) Identify Interests - Focus on underlying needs, not stated positions, 3) Find Common Ground - Identify shared goals and values, 4) Generate Options - Create win-win solutions collaboratively, 5) Use Objective Criteria - Apply fair standards for evaluation, 6) Separate People from Problems - Address issues, not personalities, 7) Maintain Relationships - Preserve working relationships while solving problems.",
593
- "metadata": {
594
- "source": "core_knowledge",
595
- "type": "strategy",
596
- "topic": "conflict_resolution",
597
- "chapter": "Conflict Resolution Techniques"
598
- }
599
- },
600
- {
601
- "content": "Critical thinking skills development: Analysis (breaking complex information into components), Evaluation (assessing credibility and logical strength), Inference (drawing reasonable conclusions), Interpretation (understanding meaning and significance), Explanation (articulating reasoning clearly), Self-regulation (monitoring and correcting one's thinking). Practice questioning assumptions, considering multiple perspectives, examining evidence quality, and recognizing logical fallacies.",
602
- "metadata": {
603
- "source": "core_knowledge",
604
- "type": "skills",
605
- "topic": "critical_thinking",
606
- "chapter": "Critical Thinking Development"
607
- }
608
- },
609
- {
610
- "content": "Team problem-solving dynamics: Establish psychological safety for open communication, define roles and responsibilities clearly, use structured problem-solving processes, encourage diverse perspectives, facilitate effective meetings, manage conflicts constructively, ensure equal participation, document decisions and action items, follow up on commitments, celebrate successes and learn from failures.",
611
- "metadata": {
612
- "source": "core_knowledge",
613
- "type": "team_dynamics",
614
- "topic": "team_problem_solving",
615
- "chapter": "Team Collaboration for Problem Solving"
616
- }
617
- }
618
- ]
619
-
620
- # Create documents
621
- documents = []
622
- for item in default_knowledge:
623
- doc = Document(
624
- page_content=item["content"],
625
- metadata=item["metadata"]
626
- )
627
- documents.append(doc)
628
-
629
- # Create vectorstore
630
- if documents and self.embeddings:
631
- self.vectorstore = FAISS.from_documents(documents, self.embeddings)
632
- self.stats['book_chunks'] = len(documents)
633
- self.metadata['total_documents'] = len(documents)
634
- self.metadata['book_processed'] = True
635
- self.metadata['book_info'] = {
636
- 'title': 'Core Problem-Solving Knowledge',
637
- 'type': 'built_in',
638
- 'chunks': len(documents)
639
- }
640
- return True
641
- return False
642
-
643
- def load_existing_knowledge(self):
644
- """Load existing knowledge base from persistent storage"""
645
- try:
646
- # Load metadata
647
- if self.metadata_path.exists():
648
- with open(self.metadata_path, 'r') as f:
649
- self.metadata = json.load(f)
650
-
651
- # Load stats
652
- if self.stats_path.exists():
653
- with open(self.stats_path, 'r') as f:
654
- self.stats = json.load(f)
655
-
656
- # Load conversations
657
- if self.conversations_path.exists():
658
- with open(self.conversations_path, 'r') as f:
659
- self.conversations = json.load(f)
660
-
661
- # Load vectorstore
662
- if self.vectorstore_path.exists() and self.embeddings:
663
- self.vectorstore = FAISS.load_local(
664
- str(self.vectorstore_path),
665
- self.embeddings,
666
- allow_dangerous_deserialization=True
667
- )
668
- return True
669
- except Exception as e:
670
- return False
671
- return False
672
-
673
- def save_all_data(self):
674
- """Save all knowledge base data to persistent storage"""
675
- try:
676
- # Save metadata
677
- self.metadata['last_updated'] = datetime.now().isoformat()
678
- with open(self.metadata_path, 'w') as f:
679
- json.dump(self.metadata, f, indent=2)
680
-
681
- # Save stats
682
- with open(self.stats_path, 'w') as f:
683
- json.dump(self.stats, f, indent=2)
684
-
685
- # Save conversations
686
- with open(self.conversations_path, 'w') as f:
687
- json.dump(self.conversations, f, indent=2)
688
-
689
- # Save vectorstore
690
- if self.vectorstore:
691
- self.vectorstore.save_local(str(self.vectorstore_path))
692
-
693
- return True
694
- except Exception as e:
695
- return False
696
-
697
- def fallback_initialization(self):
698
- """Fallback initialization if main process fails"""
699
- self.create_default_knowledge()
700
- self.metadata = {'fallback': True, 'created_at': datetime.now().isoformat()}
701
- self.stats = {'total_queries': 0, 'learning_sessions': 0, 'book_chunks': 0, 'conversation_chunks': 0, 'silly_questions_blocked': 0}
702
- self.conversations = []
703
-
704
- def process_book_content(self, text, page_texts, book_info):
705
- """Process book content and add to knowledge base"""
706
- try:
707
- # Text splitter
708
- text_splitter = RecursiveCharacterTextSplitter(
709
- chunk_size=800,
710
- chunk_overlap=150,
711
- length_function=len,
712
- separators=["\n\n", "\n", ".", "!", "?", ",", " ", ""]
713
- )
714
-
715
- # Create documents
716
- documents = []
717
- for page_info in page_texts:
718
- page_text = page_info['text']
719
- chapter_title = self._extract_chapter_title(page_text.split('\n'))
720
-
721
- doc = Document(
722
- page_content=page_text,
723
- metadata={
724
- "source": "book",
725
- "type": "book_content",
726
- "page": page_info['page'],
727
- "chapter": chapter_title,
728
- "word_count": page_info['word_count'],
729
- "book_title": book_info.get('title', 'Problem Solving Book'),
730
- "processed_at": datetime.now().isoformat()
731
- }
732
- )
733
- documents.append(doc)
734
-
735
- # Split into chunks
736
- chunks = text_splitter.split_documents(documents)
737
-
738
- # Add to vectorstore
739
- if self.vectorstore is None:
740
- self.vectorstore = FAISS.from_documents(chunks, self.embeddings)
741
- else:
742
- new_vectorstore = FAISS.from_documents(chunks, self.embeddings)
743
- self.vectorstore.merge_from(new_vectorstore)
744
-
745
- # Update metadata
746
- self.metadata['book_processed'] = True
747
- self.metadata['book_info'] = book_info
748
- self.metadata['total_documents'] += len(chunks)
749
- self.stats['book_chunks'] += len(chunks)
750
-
751
- return True, f"Successfully processed {len(chunks)} chunks from {len(page_texts)} pages!"
752
-
753
- except Exception as e:
754
- return False, f"Error processing book: {str(e)}"
755
-
756
- def add_conversation_to_knowledge(self, question, answer):
757
- """Add conversation to persistent knowledge base (auto-save)"""
758
- if len(question.strip()) < 10 or len(answer.strip()) < 20:
759
- return False
760
-
761
- try:
762
- conversation_text = f"Question: {question}\n\nAnswer: {answer}"
763
-
764
- doc = Document(
765
- page_content=conversation_text,
766
- metadata={
767
- "source": "learned_conversation",
768
- "type": "qa_pair",
769
- "question": question,
770
- "answer_preview": answer[:200] + "..." if len(answer) > 200 else answer,
771
- "conversation_id": hashlib.md5(conversation_text.encode()).hexdigest()[:8],
772
- "added_at": datetime.now().isoformat(),
773
- "quality_score": self._calculate_quality_score(question, answer)
774
- }
775
- )
776
-
777
- # Add to vectorstore
778
- if self.vectorstore is None:
779
- self.vectorstore = FAISS.from_documents([doc], self.embeddings)
780
- else:
781
- new_vectorstore = FAISS.from_documents([doc], self.embeddings)
782
- self.vectorstore.merge_from(new_vectorstore)
783
-
784
- # Store conversation
785
- self.conversations.append({
786
- 'question': question,
787
- 'answer': answer,
788
- 'timestamp': datetime.now().isoformat(),
789
- 'learned': True
790
- })
791
-
792
- # Update stats
793
- self.stats['conversation_chunks'] += 1
794
- self.stats['learning_sessions'] += 1
795
- self.metadata['total_documents'] += 1
796
-
797
- # Auto-save to persistent storage
798
- self.save_all_data()
799
-
800
- return True
801
-
802
- except Exception as e:
803
- return False
804
-
805
- def search_knowledge_base(self, query, k=5):
806
- """Search the persistent knowledge base"""
807
- if self.vectorstore is None:
808
- return []
809
-
810
- try:
811
- self.stats['total_queries'] += 1
812
- docs = self.vectorstore.similarity_search_with_score(query, k=k)
813
-
814
- results = []
815
- for doc, score in docs:
816
- result = {
817
- 'content': doc.page_content,
818
- 'source': doc.metadata.get('source', 'unknown'),
819
- 'type': doc.metadata.get('type', 'unknown'),
820
- 'page': doc.metadata.get('page', 'N/A'),
821
- 'chapter': doc.metadata.get('chapter', 'Unknown Section'),
822
- 'similarity_score': float(score),
823
- 'metadata': doc.metadata
824
- }
825
- results.append(result)
826
-
827
- return results
828
-
829
- except Exception as e:
830
- return []
831
-
832
- def _extract_chapter_title(self, lines):
833
- """Extract chapter title from text lines"""
834
- for line in lines[:10]:
835
- line = line.strip()
836
- if line and len(line) < 100:
837
- if re.match(r'(chapter|section|part|unit)\s+\d+', line.lower()):
838
- return line
839
- if line.isupper() or line.istitle():
840
- return line
841
- return "General Content"
842
-
843
- def _calculate_quality_score(self, question, answer):
844
- """Calculate conversation quality score"""
845
- score = 0
846
-
847
- # Question quality
848
- if len(question.split()) >= 5: score += 1
849
- if any(word in question.lower() for word in ['how', 'what', 'why', 'strategy', 'problem']): score += 1
850
- if '?' in question: score += 1
851
-
852
- # Answer quality
853
- if len(answer.split()) >= 20: score += 1
854
- if any(word in answer.lower() for word in ['approach', 'solution', 'method', 'step']): score += 1
855
-
856
- return min(score, 5)
857
-
858
- class AshokMinimalChatbot:
859
- def __init__(self):
860
- self.knowledge_base = PersistentHFKnowledgeBase()
861
-
862
- def is_silly_question(self, question):
863
- """Detect silly or irrelevant questions"""
864
- question_lower = question.lower().strip()
865
-
866
- if len(question_lower) < 3:
867
- return True
868
-
869
- # Greeting patterns
870
- greeting_patterns = [
871
- r'\b(hello|hi|hey|salam|namaste|adab)\b',
872
- r'\b(good morning|evening|afternoon)\b',
873
- r'\b(how are you|kaise ho|kya hal)\b',
874
- r'\b(what.*your name|who are you)\b'
875
- ]
876
-
877
- # Silly keywords
878
- silly_keywords = [
879
- 'stupid', 'dumb', 'joke', 'funny', 'lol', 'weather', 'movie',
880
- 'song', 'game', 'gossip', 'love', 'dating', 'facebook',
881
- 'instagram', 'politics', 'religion', 'age', 'appearance'
882
- ]
883
-
884
- # Problem-solving keywords
885
- good_keywords = [
886
- 'problem', 'solve', 'solution', 'strategy', 'approach',
887
- 'method', 'challenge', 'decision', 'plan', 'analyze',
888
- 'conflict', 'team', 'work', 'project', 'manage'
889
- ]
890
-
891
- # Check patterns
892
- for pattern in greeting_patterns:
893
- if re.search(pattern, question_lower):
894
- return True
895
-
896
- # Score keywords
897
- good_score = sum(1 for keyword in good_keywords if keyword in question_lower)
898
- if good_score >= 2:
899
- return False
900
-
901
- silly_score = sum(1 for keyword in silly_keywords if keyword in question_lower)
902
- if silly_score >= 1:
903
- return True
904
-
905
- # Check structure
906
- question_words = ['what', 'how', 'why', 'when', 'where', 'can', 'should']
907
- has_question_word = any(word in question_lower.split() for word in question_words)
908
- word_count = len(question_lower.split())
909
-
910
- if word_count < 4 and not has_question_word:
911
- return True
912
-
913
- return False
914
-
915
- def generate_response(self, question, api_key):
916
- """Generate response using Gemini"""
917
- try:
918
- # Check for silly questions
919
- if self.is_silly_question(question):
920
- self.knowledge_base.stats['silly_questions_blocked'] += 1
921
-
922
- silly_responses = [
923
- "Abay Sallay! Don't waste my time with such bakwas. Ask me something related to problem solving yaar!",
924
- "Abay Sallay! Ye kya timepass hai? I'm here to help with problem solving, not for chit-chat. Be serious!",
925
- "Abay Sallay! Focus on real problems that need solving, samjha? Ask about strategies and approaches!",
926
- "Abay Sallay! This is a problem-solving platform. Ask me about challenges, decisions, ya conflict resolution!",
927
- "Abay Sallay! Tumhara dimagh kahan hai? Ask meaningful questions about problem-solving techniques, yaar!"
928
- ]
929
-
930
- import random
931
- return random.choice(silly_responses), False
932
-
933
- # Configure Gemini
934
- genai.configure(api_key=api_key)
935
- model = genai.GenerativeModel('gemini-2.0-flash')
936
-
937
- # Search knowledge base
938
- relevant_results = self.knowledge_base.search_knowledge_base(question, k=5)
939
-
940
- # Build context
941
- context = ""
942
- references = []
943
-
944
- if relevant_results:
945
- context = "=== RELEVANT KNOWLEDGE ===\n\n"
946
- for i, result in enumerate(relevant_results, 1):
947
- source_type = result['type']
948
- if source_type == 'book_content':
949
- context += f"**Reference {i}** (Chapter: {result['chapter']}, Page: {result['page']}):\n"
950
- elif source_type == 'qa_pair':
951
- context += f"**Learning {i}** (From past conversations):\n"
952
- else:
953
- context += f"**Framework {i}** (Core knowledge):\n"
954
-
955
- context += f"{result['content']}\n\n"
956
- references.append(result)
957
-
958
- # Create prompt
959
- prompt = f"""
960
- You are Ashok, a problem-solving expert with Pakistani/Indian conversational style.
961
-
962
- Your characteristics:
963
- 1. Mix English with Urdu naturally: "yaar", "acha", "bilkul", "samjha", "dekho"
964
- 2. Enthusiastic responses: "Excellent question yaar!" or "Bahut acha sawal!"
965
- 3. Reference knowledge sources when available
966
- 4. Provide practical, actionable advice
967
- 5. Encouraging and professional tone
968
-
969
- {context}
970
-
971
- User Question: {question}
972
-
973
- Provide a comprehensive, practical response using your characteristic style.
974
- Reference the knowledge sources when relevant and give actionable steps.
975
- """
976
-
977
- response = model.generate_content(prompt)
978
- final_response = response.text
979
-
980
- # Add clean references section
981
- if references:
982
- final_response += "\n\n**Knowledge Sources:**\n"
983
- for ref in references:
984
- if ref['type'] == 'book_content':
985
- final_response += f"• Book: {ref['chapter']} (Page {ref['page']})\n"
986
- elif ref['type'] == 'qa_pair':
987
- final_response += f"• Previous Learning\n"
988
- else:
989
- final_response += f"• Core Framework: {ref['metadata'].get('topic', 'Problem-solving')}\n"
990
-
991
- return final_response, True
992
-
993
- except Exception as e:
994
- return f"Sorry yaar, I encountered an error: {str(e)}. Please check your API key and try again!", False
995
-
996
- def show_typing_indicator():
997
- """Show typing indicator"""
998
- st.markdown("""
999
- <div class="typing-indicator">
1000
- <span>Ashok is thinking</span>
1001
- <div class="typing-dots">
1002
- <div class="typing-dot"></div>
1003
- <div class="typing-dot"></div>
1004
- <div class="typing-dot"></div>
1005
- </div>
1006
- </div>
1007
- """, unsafe_allow_html=True)
1008
-
1009
- def show_api_setup():
1010
- """Show API key setup interface"""
1011
- st.markdown("""
1012
- <div class="api-setup-container">
1013
- <div class="api-setup-title">Welcome to Ashok 2.0</div>
1014
- <div class="api-setup-subtitle">To get started, please enter your Gemini API key</div>
1015
- </div>
1016
- """, unsafe_allow_html=True)
1017
-
1018
- # API key input
1019
- api_key = st.text_input(
1020
- "Gemini API Key",
1021
- type="password",
1022
- placeholder="Enter your API key here...",
1023
- label_visibility="collapsed"
1024
- )
1025
-
1026
- # API guide
1027
- st.markdown("""
1028
- <div class="api-guide">
1029
- <div class="api-guide-title">How to get your free API key:</div>
1030
- <div class="api-guide-text">1. Visit <a href="https://makersuite.google.com/app/apikey" target="_blank" class="api-link">Google AI Studio</a></div>
1031
- <div class="api-guide-text">2. Sign in with your Google account</div>
1032
- <div class="api-guide-text">3. Click "Create API Key"</div>
1033
- <div class="api-guide-text">4. Copy and paste the key above</div>
1034
- </div>
1035
- """, unsafe_allow_html=True)
1036
-
1037
- return api_key
1038
-
1039
- def show_quick_actions():
1040
- """Show enhanced quick action buttons"""
1041
- st.markdown("""
1042
- <div class="quick-actions-container">
1043
- <div class="quick-actions-title">Quick Start Questions</div>
1044
- <div class="quick-action-grid">
1045
- """, unsafe_allow_html=True)
1046
-
1047
- # Quick action data
1048
- actions = [
1049
- {
1050
- "icon": "🎯",
1051
- "title": "Task Prioritization",
1052
- "desc": "Learn how to prioritize when everything seems urgent",
1053
- "question": "How do I prioritize tasks when everything seems urgent and important?"
1054
- },
1055
- {
1056
- "icon": "🤝",
1057
- "title": "Conflict Resolution",
1058
- "desc": "Effective strategies for resolving team conflicts",
1059
- "question": "What's the best approach to resolve conflicts in my team?"
1060
- },
1061
- {
1062
- "icon": "⚡",
1063
- "title": "Decision Making",
1064
- "desc": "Improve your decision-making process",
1065
- "question": "How can I improve my decision-making process for complex problems?"
1066
- },
1067
- {
1068
- "icon": "🎪",
1069
- "title": "Difficult People",
1070
- "desc": "Handle challenging stakeholders professionally",
1071
- "question": "How do I deal with difficult stakeholders effectively?"
1072
- },
1073
- {
1074
- "icon": "🔄",
1075
- "title": "Change Management",
1076
- "desc": "Navigate organizational changes smoothly",
1077
- "question": "How can I help my team adapt to organizational changes?"
1078
- },
1079
- {
1080
- "icon": "💡",
1081
- "title": "Creative Solutions",
1082
- "desc": "Generate innovative solutions to problems",
1083
- "question": "What techniques can I use to think more creatively about problems?"
1084
- }
1085
- ]
1086
-
1087
- # Create columns for actions
1088
- cols = st.columns(2)
1089
- for i, action in enumerate(actions):
1090
- with cols[i % 2]:
1091
- if st.button(
1092
- f"{action['icon']} {action['title']}",
1093
- key=f"action_{i}",
1094
- help=action['desc'],
1095
- use_container_width=True
1096
- ):
1097
- st.session_state.auto_question = action['question']
1098
- st.rerun()
1099
-
1100
- st.markdown("</div></div>", unsafe_allow_html=True)
1101
-
1102
- def test_api_key(api_key):
1103
- """Test if API key is valid"""
1104
- try:
1105
- genai.configure(api_key=api_key)
1106
- model = genai.GenerativeModel('gemini-2.0-flash')
1107
- test_response = model.generate_content("Hello")
1108
- return True
1109
- except Exception as e:
1110
- return False
1111
-
1112
- # Global instance for the app
1113
- @st.cache_resource
1114
- def get_chatbot():
1115
- """Get cached chatbot instance"""
1116
- return AshokMinimalChatbot()
1117
-
1118
- def main():
1119
- # Get cached chatbot instance
1120
- chatbot = get_chatbot()
1121
-
1122
- # Initialize session state
1123
- if 'messages' not in st.session_state:
1124
- st.session_state.messages = []
1125
-
1126
- if 'auto_question' not in st.session_state:
1127
- st.session_state.auto_question = None
1128
-
1129
- if 'api_key_valid' not in st.session_state:
1130
- st.session_state.api_key_valid = False
1131
-
1132
- # Main title
1133
- st.markdown('<h1 class="main-title">ASHOK 2.0</h1>', unsafe_allow_html=True)
1134
-
1135
- # API Key Setup Phase
1136
- if not st.session_state.api_key_valid:
1137
- api_key = show_api_setup()
1138
-
1139
- if api_key:
1140
- if test_api_key(api_key):
1141
- st.session_state.api_key = api_key
1142
- st.session_state.api_key_valid = True
1143
- st.markdown("""
1144
- <div class="status-success">
1145
- API key configured successfully! Ready to chat.
1146
- </div>
1147
- """, unsafe_allow_html=True)
1148
- time.sleep(1)
1149
- st.rerun()
1150
- else:
1151
- st.markdown("""
1152
- <div class="status-warning">
1153
- Invalid API key. Please check and try again.
1154
- </div>
1155
- """, unsafe_allow_html=True)
1156
-
1157
- # Main Chat Interface Phase
1158
- else:
1159
- api_key = st.session_state.api_key
1160
-
1161
- # Handle auto questions from quick actions
1162
- if st.session_state.auto_question:
1163
- # Add user message
1164
- st.session_state.messages.append({"role": "user", "content": st.session_state.auto_question})
1165
-
1166
- # Generate response
1167
- with st.spinner("Processing your question..."):
1168
- response, is_helpful = chatbot.generate_response(st.session_state.auto_question, api_key)
1169
- st.session_state.messages.append({"role": "assistant", "content": response})
1170
-
1171
- # Auto-learn from helpful conversations
1172
- if is_helpful and not chatbot.is_silly_question(st.session_state.auto_question):
1173
- chatbot.knowledge_base.add_conversation_to_knowledge(st.session_state.auto_question, response)
1174
-
1175
- # Clear auto question
1176
- st.session_state.auto_question = None
1177
- st.rerun()
1178
-
1179
- # Display chat history
1180
- if st.session_state.messages:
1181
- st.markdown('<div class="chat-container">', unsafe_allow_html=True)
1182
- for message in st.session_state.messages:
1183
- with st.chat_message(message["role"]):
1184
- st.markdown(message["content"])
1185
- st.markdown('</div>', unsafe_allow_html=True)
1186
-
1187
- # Chat input
1188
- if prompt := st.chat_input("Ask about problem-solving strategies...", key="main_chat"):
1189
- # Add user message
1190
- st.session_state.messages.append({"role": "user", "content": prompt})
1191
- with st.chat_message("user"):
1192
- st.markdown(prompt)
1193
-
1194
- # Generate response with typing indicator
1195
- with st.chat_message("assistant"):
1196
- # Show typing indicator
1197
- typing_placeholder = st.empty()
1198
- with typing_placeholder:
1199
- show_typing_indicator()
1200
-
1201
- # Simulate typing delay
1202
- time.sleep(1)
1203
-
1204
- # Clear typing indicator and show response
1205
- typing_placeholder.empty()
1206
-
1207
- with st.spinner("Processing..."):
1208
- response, is_helpful = chatbot.generate_response(prompt, api_key)
1209
- st.markdown(response)
1210
-
1211
- # Add to chat history
1212
- st.session_state.messages.append({"role": "assistant", "content": response})
1213
-
1214
- # Auto-learn from helpful conversations
1215
- if is_helpful and not chatbot.is_silly_question(prompt):
1216
- learned = chatbot.knowledge_base.add_conversation_to_knowledge(prompt, response)
1217
- if learned:
1218
- st.markdown(
1219
- '<div class="learning-indicator">Knowledge updated - This conversation has been learned!</div>',
1220
- unsafe_allow_html=True
1221
- )
1222
-
1223
- # Show quick actions if no messages yet
1224
- if not st.session_state.messages:
1225
- show_quick_actions()
1226
-
1227
- # Control panel
1228
- if st.session_state.messages:
1229
- st.markdown("""
1230
- <div class="control-panel">
1231
- """, unsafe_allow_html=True)
1232
-
1233
- if st.button("Clear Chat", key="clear_chat"):
1234
- st.session_state.messages = []
1235
- st.rerun()
1236
-
1237
- st.markdown("</div>", unsafe_allow_html=True)
1238
-
1239
- if __name__ == "__main__":
1240
- main()