shukdevdatta123 commited on
Commit
990ba8a
·
verified ·
1 Parent(s): 06c35fe

Create v1.txt

Browse files
Files changed (1) hide show
  1. v1.txt +846 -0
v1.txt ADDED
@@ -0,0 +1,846 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ import time
4
+ import gradio as gr
5
+ from datetime import datetime
6
+ from pathlib import Path
7
+ from typing import List, Dict, Any, Optional, Union
8
+
9
+ # Import Groq - we'll install it in requirements.txt
10
+ from groq import Groq
11
+
12
+ class PersonalAIResearchAssistant:
13
+ """
14
+ Personal AI Research Assistant (PARA) using Groq's compound models with agentic capabilities.
15
+ """
16
+
17
+ def __init__(self, api_key: str,
18
+ knowledge_base_path: str = "knowledge_base.json",
19
+ model: str = "compound-beta"):
20
+ """
21
+ Initialize the PARA system.
22
+
23
+ Args:
24
+ api_key: Groq API key
25
+ knowledge_base_path: Path to store persistent knowledge
26
+ model: Which Groq model to use ('compound-beta' or 'compound-beta-mini')
27
+ """
28
+ self.api_key = api_key
29
+ if not self.api_key:
30
+ raise ValueError("No API key provided")
31
+
32
+ self.client = Groq(api_key=self.api_key)
33
+ self.model = model
34
+ self.knowledge_base_path = Path(knowledge_base_path)
35
+ self.knowledge_base = self._load_knowledge_base()
36
+
37
+ def _load_knowledge_base(self) -> Dict:
38
+ """Load existing knowledge base or create a new one"""
39
+ if self.knowledge_base_path.exists():
40
+ with open(self.knowledge_base_path, 'r') as f:
41
+ return json.load(f)
42
+ else:
43
+ # Initialize with empty collections
44
+ kb = {
45
+ "topics": {},
46
+ "research_digests": [],
47
+ "code_analyses": [],
48
+ "concept_connections": [],
49
+ "metadata": {
50
+ "created_at": datetime.now().isoformat(),
51
+ "last_updated": datetime.now().isoformat()
52
+ }
53
+ }
54
+ self._save_knowledge_base(kb)
55
+ return kb
56
+
57
+ def _save_knowledge_base(self, kb: Dict = None) -> None:
58
+ """Save the knowledge base to disk"""
59
+ if kb is None:
60
+ kb = self.knowledge_base
61
+
62
+ # Update metadata
63
+ kb["metadata"]["last_updated"] = datetime.now().isoformat()
64
+
65
+ with open(self.knowledge_base_path, 'w') as f:
66
+ json.dump(kb, f, indent=2)
67
+
68
+ def _extract_tool_info(self, response) -> Dict:
69
+ """
70
+ Extract tool usage information in a JSON serializable format
71
+ """
72
+ tool_info = None
73
+ if hasattr(response.choices[0].message, 'executed_tools'):
74
+ # Convert ExecutedTool objects to dictionaries
75
+ tools = response.choices[0].message.executed_tools
76
+ if tools:
77
+ tool_info = []
78
+ for tool in tools:
79
+ # Extract only serializable data
80
+ tool_dict = {
81
+ "tool_type": getattr(tool, "type", "unknown"),
82
+ "tool_name": getattr(tool, "name", "unknown"),
83
+ }
84
+ # Add any other relevant attributes in a serializable form
85
+ if hasattr(tool, "input"):
86
+ tool_dict["input"] = str(tool.input)
87
+ if hasattr(tool, "output"):
88
+ tool_dict["output"] = str(tool.output)
89
+ tool_info.append(tool_dict)
90
+ return tool_info
91
+
92
+ def research_digest(self, topic: str,
93
+ include_domains: List[str] = None,
94
+ exclude_domains: List[str] = None,
95
+ max_results: int = 5) -> Dict:
96
+ """
97
+ Generate a research digest on a specific topic
98
+
99
+ Args:
100
+ topic: The research topic to investigate
101
+ include_domains: List of domains to include (e.g., ["arxiv.org", "*.edu"])
102
+ exclude_domains: List of domains to exclude
103
+ max_results: Maximum number of key findings to include
104
+
105
+ Returns:
106
+ Research digest including key findings and references
107
+ """
108
+ # Build the prompt
109
+ prompt = f"""Generate a research digest on the topic: {topic}
110
+
111
+ Please find the most recent and relevant information, focusing on:
112
+ 1. Key findings or breakthroughs
113
+ 2. Current trends and methodologies
114
+ 3. Influential researchers or organizations
115
+ 4. Practical applications
116
+
117
+ Structure your response as a concise summary with {max_results} key points maximum.
118
+ Include source information where possible.
119
+ """
120
+
121
+ # Set up API parameters
122
+ params = {
123
+ "messages": [
124
+ {"role": "system", "content": "You are a research assistant tasked with finding and summarizing the latest information on specific topics."},
125
+ {"role": "user", "content": prompt}
126
+ ],
127
+ "model": self.model
128
+ }
129
+
130
+ # Add domain filtering if specified
131
+ if include_domains and include_domains[0].strip():
132
+ params["include_domains"] = [domain.strip() for domain in include_domains]
133
+ if exclude_domains and exclude_domains[0].strip():
134
+ params["exclude_domains"] = [domain.strip() for domain in exclude_domains]
135
+
136
+ # Make the API call
137
+ response = self.client.chat.completions.create(**params)
138
+ content = response.choices[0].message.content
139
+
140
+ # Extract tool usage information in a serializable format
141
+ tool_info = self._extract_tool_info(response)
142
+
143
+ # Create digest entry
144
+ digest = {
145
+ "topic": topic,
146
+ "timestamp": datetime.now().isoformat(),
147
+ "content": content,
148
+ "tool_usage": tool_info,
149
+ "parameters": {
150
+ "include_domains": include_domains,
151
+ "exclude_domains": exclude_domains,
152
+ }
153
+ }
154
+
155
+ # Add to knowledge base
156
+ self.knowledge_base["research_digests"].append(digest)
157
+
158
+ # Update topic entry in knowledge base
159
+ if topic not in self.knowledge_base["topics"]:
160
+ self.knowledge_base["topics"][topic] = {
161
+ "first_researched": datetime.now().isoformat(),
162
+ "research_count": 1,
163
+ "related_topics": []
164
+ }
165
+ else:
166
+ self.knowledge_base["topics"][topic]["research_count"] += 1
167
+ self.knowledge_base["topics"][topic]["last_researched"] = datetime.now().isoformat()
168
+
169
+ # Save updated knowledge base
170
+ self._save_knowledge_base()
171
+
172
+ return digest
173
+
174
+ def evaluate_code(self, code_snippet: str, language: str = "python",
175
+ analysis_type: str = "full") -> Dict:
176
+ """
177
+ Evaluate a code snippet for issues and suggest improvements
178
+
179
+ Args:
180
+ code_snippet: The code to evaluate
181
+ language: Programming language of the code
182
+ analysis_type: Type of analysis to perform ('full', 'security', 'performance', 'style')
183
+
184
+ Returns:
185
+ Analysis results including issues and suggestions
186
+ """
187
+ # Build the prompt
188
+ prompt = f"""Analyze the following {language} code:
189
+
190
+ ```{language}
191
+ {code_snippet}
192
+ ```
193
+
194
+ Please perform a {analysis_type} analysis, including:
195
+ 1. Identifying any bugs or potential issues
196
+ 2. Security vulnerabilities (if applicable)
197
+ 3. Performance considerations
198
+ 4. Style and best practices
199
+ 5. Suggested improvements
200
+
201
+ If possible, execute the code to verify functionality.
202
+ """
203
+
204
+ # Make the API call
205
+ response = self.client.chat.completions.create(
206
+ messages=[
207
+ {"role": "system", "content": f"You are a code analysis expert specializing in {language}."},
208
+ {"role": "user", "content": prompt}
209
+ ],
210
+ model=self.model
211
+ )
212
+
213
+ content = response.choices[0].message.content
214
+
215
+ # Extract tool usage information in a serializable format
216
+ tool_info = self._extract_tool_info(response)
217
+
218
+ # Create code analysis entry
219
+ analysis = {
220
+ "code_snippet": code_snippet,
221
+ "language": language,
222
+ "analysis_type": analysis_type,
223
+ "timestamp": datetime.now().isoformat(),
224
+ "content": content,
225
+ "tool_usage": tool_info
226
+ }
227
+
228
+ # Add to knowledge base
229
+ self.knowledge_base["code_analyses"].append(analysis)
230
+ self._save_knowledge_base()
231
+
232
+ return analysis
233
+
234
+ def connect_concepts(self, concept_a: str, concept_b: str) -> Dict:
235
+ """
236
+ Identify connections between two seemingly different concepts
237
+
238
+ Args:
239
+ concept_a: First concept
240
+ concept_b: Second concept
241
+
242
+ Returns:
243
+ Analysis of connections between the concepts
244
+ """
245
+ # Build the prompt
246
+ prompt = f"""Explore the connections between these two concepts:
247
+
248
+ Concept A: {concept_a}
249
+ Concept B: {concept_b}
250
+
251
+ Please identify:
252
+ 1. Direct connections or shared principles
253
+ 2. Historical influences between them
254
+ 3. Common applications or use cases
255
+ 4. How insights from one field might benefit the other
256
+ 5. Potential for innovative combinations
257
+
258
+ Search for the most up-to-date information that might connect these concepts.
259
+ """
260
+
261
+ # Make the API call
262
+ response = self.client.chat.completions.create(
263
+ messages=[
264
+ {"role": "system", "content": "You are a cross-disciplinary research assistant specialized in finding connections between different fields and concepts."},
265
+ {"role": "user", "content": prompt}
266
+ ],
267
+ model=self.model
268
+ )
269
+
270
+ content = response.choices[0].message.content
271
+
272
+ # Extract tool usage information in a serializable format
273
+ tool_info = self._extract_tool_info(response)
274
+
275
+ # Create connection entry
276
+ connection = {
277
+ "concept_a": concept_a,
278
+ "concept_b": concept_b,
279
+ "timestamp": datetime.now().isoformat(),
280
+ "content": content,
281
+ "tool_usage": tool_info
282
+ }
283
+
284
+ # Add to knowledge base
285
+ self.knowledge_base["concept_connections"].append(connection)
286
+
287
+ # Update topic entries
288
+ for concept in [concept_a, concept_b]:
289
+ if concept not in self.knowledge_base["topics"]:
290
+ self.knowledge_base["topics"][concept] = {
291
+ "first_researched": datetime.now().isoformat(),
292
+ "research_count": 1,
293
+ "related_topics": [concept_a if concept == concept_b else concept_b]
294
+ }
295
+ else:
296
+ if concept_a if concept == concept_b else concept_b not in self.knowledge_base["topics"][concept]["related_topics"]:
297
+ self.knowledge_base["topics"][concept]["related_topics"].append(
298
+ concept_a if concept == concept_b else concept_b
299
+ )
300
+
301
+ self._save_knowledge_base()
302
+
303
+ return connection
304
+
305
+ def ask_knowledge_base(self, query: str) -> Dict:
306
+ """
307
+ Query the accumulated knowledge base
308
+
309
+ Args:
310
+ query: Question about topics in the knowledge base
311
+
312
+ Returns:
313
+ Response based on accumulated knowledge
314
+ """
315
+ # Create a temporary context from the knowledge base
316
+ context = {
317
+ "topics_researched": list(self.knowledge_base["topics"].keys()),
318
+ "research_count": len(self.knowledge_base["research_digests"]),
319
+ "code_analyses_count": len(self.knowledge_base["code_analyses"]),
320
+ "concept_connections_count": len(self.knowledge_base["concept_connections"]),
321
+ "last_updated": self.knowledge_base["metadata"]["last_updated"]
322
+ }
323
+
324
+ # Add recent research digests (limited to keep context manageable)
325
+ recent_digests = self.knowledge_base["research_digests"][-3:] if self.knowledge_base["research_digests"] else []
326
+ context["recent_research"] = recent_digests
327
+
328
+ # Build the prompt
329
+ prompt = f"""Query: {query}
330
+
331
+ Please answer based on the following knowledge base context:
332
+ {json.dumps(context, indent=2)}
333
+
334
+ If the knowledge base doesn't contain relevant information, please indicate this and suggest how we might research this topic.
335
+ """
336
+
337
+ # Make the API call
338
+ response = self.client.chat.completions.create(
339
+ messages=[
340
+ {"role": "system", "content": "You are a research assistant with access to a personal knowledge base. Answer questions based on the accumulated knowledge."},
341
+ {"role": "user", "content": prompt}
342
+ ],
343
+ model=self.model
344
+ )
345
+
346
+ content = response.choices[0].message.content
347
+
348
+ return {
349
+ "query": query,
350
+ "timestamp": datetime.now().isoformat(),
351
+ "response": content,
352
+ "knowledge_base_state": context
353
+ }
354
+
355
+ def generate_weekly_report(self) -> Dict:
356
+ """
357
+ Generate a weekly summary of research and insights
358
+
359
+ Returns:
360
+ Weekly report of activity and key findings
361
+ """
362
+ # Get weekly statistics
363
+ one_week_ago = datetime.now().isoformat() # Simplified, should subtract 7 days
364
+
365
+ # Count activities in the last week
366
+ recent_research = [d for d in self.knowledge_base["research_digests"]
367
+ if d["timestamp"] > one_week_ago]
368
+ recent_code = [c for c in self.knowledge_base["code_analyses"]
369
+ if c["timestamp"] > one_week_ago]
370
+ recent_connections = [c for c in self.knowledge_base["concept_connections"]
371
+ if c["timestamp"] > one_week_ago]
372
+
373
+ # Build context for the report
374
+ context = {
375
+ "period": "weekly",
376
+ "research_count": len(recent_research),
377
+ "code_analyses_count": len(recent_code),
378
+ "concept_connections_count": len(recent_connections),
379
+ "topics_explored": list(set([r["topic"] for r in recent_research])),
380
+ "recent_research": recent_research[:3], # Include only top 3
381
+ "recent_connections": recent_connections[:3]
382
+ }
383
+
384
+ # Build the prompt
385
+ prompt = f"""Generate a weekly research summary based on the following activity:
386
+
387
+ {json.dumps(context, indent=2)}
388
+
389
+ Please include:
390
+ 1. Overview of research activity
391
+ 2. Key findings and insights
392
+ 3. Emerging patterns or trends
393
+ 4. Suggestions for further exploration
394
+
395
+ Format as a concise weekly report.
396
+ """
397
+
398
+ # Make the API call
399
+ response = self.client.chat.completions.create(
400
+ messages=[
401
+ {"role": "system", "content": "You are a research assistant generating a weekly summary of research activities and findings."},
402
+ {"role": "user", "content": prompt}
403
+ ],
404
+ model=self.model
405
+ )
406
+
407
+ content = response.choices[0].message.content
408
+
409
+ report = {
410
+ "type": "weekly_report",
411
+ "timestamp": datetime.now().isoformat(),
412
+ "content": content,
413
+ "stats": context
414
+ }
415
+
416
+ return report
417
+
418
+ def get_kb_stats(self):
419
+ """Get statistics about the knowledge base"""
420
+ return {
421
+ "topics_count": len(self.knowledge_base["topics"]),
422
+ "research_count": len(self.knowledge_base["research_digests"]),
423
+ "code_analyses_count": len(self.knowledge_base["code_analyses"]),
424
+ "concept_connections_count": len(self.knowledge_base["concept_connections"]),
425
+ "created": self.knowledge_base["metadata"]["created_at"],
426
+ "last_updated": self.knowledge_base["metadata"]["last_updated"],
427
+ "topics": list(self.knowledge_base["topics"].keys())
428
+ }
429
+
430
+ # Global variables for the Gradio app
431
+ para_instance = None
432
+ api_key_status = "Not Set"
433
+
434
+ # Helper functions for Gradio
435
+ def validate_api_key(api_key):
436
+ """Validate Groq API key"""
437
+ global para_instance, api_key_status
438
+
439
+ if not api_key or len(api_key.strip()) < 10:
440
+ return "❌ Please enter a valid API key"
441
+
442
+ try:
443
+ # Try to initialize with minimal actions
444
+ client = Groq(api_key=api_key)
445
+ # Create PARA instance
446
+ para_instance = PersonalAIResearchAssistant(
447
+ api_key=api_key,
448
+ knowledge_base_path="para_knowledge.json"
449
+ )
450
+ api_key_status = "Valid ✅"
451
+
452
+ # Get KB stats
453
+ stats = para_instance.get_kb_stats()
454
+ kb_info = f"**Knowledge Base Stats:**\n\n" \
455
+ f"- Topics: {stats['topics_count']}\n" \
456
+ f"- Research Digests: {stats['research_count']}\n" \
457
+ f"- Code Analyses: {stats['code_analyses_count']}\n" \
458
+ f"- Concept Connections: {stats['concept_connections_count']}\n" \
459
+ f"- Last Updated: {stats['last_updated'][:10]}\n\n" \
460
+ f"**Topics Explored:** {', '.join(stats['topics'][:10])}" + \
461
+ ("..." if len(stats['topics']) > 10 else "")
462
+
463
+ return f"✅ API Key Valid! PARA is ready.\n\n{kb_info}"
464
+ except Exception as e:
465
+ api_key_status = "Invalid ❌"
466
+ para_instance = None
467
+ return f"❌ Error: {str(e)}"
468
+
469
+ def check_api_key():
470
+ """Check if API key is set"""
471
+ if para_instance is None:
472
+ return "Please set your Groq API key first"
473
+ return None
474
+
475
+ def update_model_selection(model_choice):
476
+ """Update model selection"""
477
+ global para_instance
478
+
479
+ if para_instance:
480
+ para_instance.model = model_choice
481
+ return f"Model updated to: {model_choice}"
482
+ else:
483
+ return "Set API key first"
484
+
485
+ def research_topic(topic, include_domains, exclude_domains):
486
+ """Research a topic with domain filters"""
487
+ # Check if API key is set
488
+ check_result = check_api_key()
489
+ if check_result:
490
+ return check_result
491
+
492
+ if not topic:
493
+ return "Please enter a topic to research"
494
+
495
+ # Process domain lists
496
+ include_list = [d.strip() for d in include_domains.split(",")] if include_domains else []
497
+ exclude_list = [d.strip() for d in exclude_domains.split(",")] if exclude_domains else []
498
+
499
+ try:
500
+ # Perform research
501
+ result = para_instance.research_digest(
502
+ topic=topic,
503
+ include_domains=include_list if include_list and include_list[0] else None,
504
+ exclude_domains=exclude_list if exclude_list and exclude_list[0] else None
505
+ )
506
+
507
+ # Format response
508
+ response = f"# Research: {topic}\n\n{result['content']}"
509
+
510
+ # Add tool usage info if available
511
+ if result.get("tool_usage"):
512
+ response += f"\n\n*Tool Usage Information Available*"
513
+
514
+ return response
515
+ except Exception as e:
516
+ return f"Error: {str(e)}"
517
+
518
+ def analyze_code(code_snippet, language, analysis_type):
519
+ """Analyze code with Groq"""
520
+ # Check if API key is set
521
+ check_result = check_api_key()
522
+ if check_result:
523
+ return check_result
524
+
525
+ if not code_snippet:
526
+ return "Please enter code to analyze"
527
+
528
+ try:
529
+ # Perform analysis
530
+ result = para_instance.evaluate_code(
531
+ code_snippet=code_snippet,
532
+ language=language,
533
+ analysis_type=analysis_type
534
+ )
535
+
536
+ # Format response
537
+ response = f"# Code Analysis ({language}, {analysis_type})\n\n{result['content']}"
538
+
539
+ # Add tool usage info if available
540
+ if result.get("tool_usage"):
541
+ response += f"\n\n*Tool Usage Information Available*"
542
+
543
+ return response
544
+ except Exception as e:
545
+ return f"Error: {str(e)}"
546
+
547
+ def connect_concepts_handler(concept_a, concept_b):
548
+ """Connect two concepts"""
549
+ # Check if API key is set
550
+ check_result = check_api_key()
551
+ if check_result:
552
+ return check_result
553
+
554
+ if not concept_a or not concept_b:
555
+ return "Please enter both concepts"
556
+
557
+ try:
558
+ # Find connections
559
+ result = para_instance.connect_concepts(
560
+ concept_a=concept_a,
561
+ concept_b=concept_b
562
+ )
563
+
564
+ # Format response
565
+ response = f"# Connection: {concept_a} & {concept_b}\n\n{result['content']}"
566
+
567
+ # Add tool usage info if available
568
+ if result.get("tool_usage"):
569
+ response += f"\n\n*Tool Usage Information Available*"
570
+
571
+ return response
572
+ except Exception as e:
573
+ return f"Error: {str(e)}"
574
+
575
+ def query_knowledge_base(query):
576
+ """Query the knowledge base"""
577
+ # Check if API key is set
578
+ check_result = check_api_key()
579
+ if check_result:
580
+ return check_result
581
+
582
+ if not query:
583
+ return "Please enter a query"
584
+
585
+ try:
586
+ # Query knowledge base
587
+ result = para_instance.ask_knowledge_base(query=query)
588
+
589
+ # Format response
590
+ response = f"# Knowledge Base Query: {query}\n\n{result['response']}"
591
+
592
+ # Add KB stats
593
+ stats = result.get("knowledge_base_state", {})
594
+ if stats:
595
+ topics = stats.get("topics_researched", [])
596
+ response += f"\n\n*Knowledge Base contains {len(topics)} topics: {', '.join(topics[:5])}" + \
597
+ ("..." if len(topics) > 5 else "") + "*"
598
+
599
+ return response
600
+ except Exception as e:
601
+ return f"Error: {str(e)}"
602
+
603
+ def generate_report_handler():
604
+ """Generate weekly report"""
605
+ # Check if API key is set
606
+ check_result = check_api_key()
607
+ if check_result:
608
+ return check_result
609
+
610
+ try:
611
+ # Generate report
612
+ result = para_instance.generate_weekly_report()
613
+
614
+ # Format response
615
+ response = f"# Weekly Research Report\n\n{result['content']}"
616
+
617
+ return response
618
+ except Exception as e:
619
+ return f"Error: {str(e)}"
620
+
621
+ # Create the Gradio interface
622
+ def create_gradio_app():
623
+ # Define CSS for styling
624
+ css = """
625
+ .title-container {
626
+ text-align: center;
627
+ margin-bottom: 20px;
628
+ }
629
+ .container {
630
+ margin: 0 auto;
631
+ max-width: 1200px;
632
+ }
633
+ .tab-content {
634
+ padding: 20px;
635
+ border-radius: 10px;
636
+ background-color: #f9f9f9;
637
+ }
638
+ """
639
+
640
+ with gr.Blocks(css=css, title="PARA - Personal AI Research Assistant") as app:
641
+ gr.Markdown(
642
+ """
643
+ <div class="title-container">
644
+ # 🧠 PARA - Personal AI Research Assistant
645
+ *Powered by Groq's Compound Beta models for intelligent research*
646
+ </div>
647
+ """
648
+ )
649
+
650
+ with gr.Row():
651
+ with gr.Column(scale=4):
652
+ api_key_input = gr.Textbox(
653
+ label="Groq API Key",
654
+ placeholder="Enter your Groq API key here...",
655
+ type="password"
656
+ )
657
+ with gr.Column(scale=2):
658
+ model_choice = gr.Radio(
659
+ ["compound-beta", "compound-beta-mini"],
660
+ label="Model Selection",
661
+ value="compound-beta"
662
+ )
663
+ with gr.Column(scale=1):
664
+ validate_btn = gr.Button("Validate & Connect")
665
+
666
+ api_status = gr.Markdown("### Status: Not connected")
667
+
668
+ # Connect validation button
669
+ validate_btn.click(
670
+ fn=validate_api_key,
671
+ inputs=[api_key_input],
672
+ outputs=[api_status]
673
+ )
674
+
675
+ # Connect model selection
676
+ model_choice.change(
677
+ fn=update_model_selection,
678
+ inputs=[model_choice],
679
+ outputs=[api_status]
680
+ )
681
+
682
+ # Tabs for different features
683
+ with gr.Tabs() as tabs:
684
+ # Research Tab
685
+ with gr.Tab("Research Topics"):
686
+ with gr.Row():
687
+ with gr.Column(scale=1):
688
+ research_topic_input = gr.Textbox(
689
+ label="Research Topic",
690
+ placeholder="Enter a topic to research..."
691
+ )
692
+ with gr.Column(scale=1):
693
+ include_domains = gr.Textbox(
694
+ label="Include Domains (comma-separated)",
695
+ placeholder="arxiv.org, *.edu, example.com"
696
+ )
697
+ exclude_domains = gr.Textbox(
698
+ label="Exclude Domains (comma-separated)",
699
+ placeholder="wikipedia.org, twitter.com"
700
+ )
701
+ research_btn = gr.Button("Research Topic")
702
+ research_output = gr.Markdown("Results will appear here...")
703
+
704
+ research_btn.click(
705
+ fn=research_topic,
706
+ inputs=[research_topic_input, include_domains, exclude_domains],
707
+ outputs=[research_output]
708
+ )
709
+
710
+ gr.Markdown("""
711
+ ### Examples:
712
+ - "Latest developments in quantum computing"
713
+ - "Climate change mitigation strategies"
714
+ - "Advancements in protein folding algorithms"
715
+
716
+ *Include domains like "arxiv.org, *.edu" for academic sources*
717
+ """)
718
+
719
+ # Code Analysis Tab
720
+ with gr.Tab("Code Analysis"):
721
+ code_input = gr.Code(
722
+ label="Code Snippet",
723
+ language="python",
724
+ lines=10
725
+ )
726
+ with gr.Row():
727
+ language_select = gr.Dropdown(
728
+ ["python", "javascript", "java", "c++", "go", "rust", "typescript", "sql", "bash"],
729
+ label="Language",
730
+ value="python"
731
+ )
732
+ analysis_type = gr.Dropdown(
733
+ ["full", "security", "performance", "style"],
734
+ label="Analysis Type",
735
+ value="full"
736
+ )
737
+ analyze_btn = gr.Button("Analyze Code")
738
+ analysis_output = gr.Markdown("Results will appear here...")
739
+
740
+ analyze_btn.click(
741
+ fn=analyze_code,
742
+ inputs=[code_input, language_select, analysis_type],
743
+ outputs=[analysis_output]
744
+ )
745
+
746
+ gr.Markdown("""
747
+ ### Example Python Code:
748
+ ```python
749
+ def fibonacci(n):
750
+ if n <= 0:
751
+ return []
752
+ elif n == 1:
753
+ return [0]
754
+ else:
755
+ result = [0, 1]
756
+ for i in range(2, n):
757
+ result.append(result[i-1] + result[i-2])
758
+ return result
759
+
760
+ print(fibonacci(10))
761
+ ```
762
+ """)
763
+
764
+ # Concept Connections Tab
765
+ with gr.Tab("Connect Concepts"):
766
+ with gr.Row():
767
+ concept_a = gr.Textbox(
768
+ label="Concept A",
769
+ placeholder="First concept or field..."
770
+ )
771
+ concept_b = gr.Textbox(
772
+ label="Concept B",
773
+ placeholder="Second concept or field..."
774
+ )
775
+ connect_btn = gr.Button("Find Connections")
776
+ connection_output = gr.Markdown("Results will appear here...")
777
+
778
+ connect_btn.click(
779
+ fn=connect_concepts_handler,
780
+ inputs=[concept_a, concept_b],
781
+ outputs=[connection_output]
782
+ )
783
+
784
+ gr.Markdown("""
785
+ ### Example Concept Pairs:
786
+ - "quantum computing" and "machine learning"
787
+ - "blockchain" and "supply chain management"
788
+ - "gene editing" and "ethics"
789
+ """)
790
+
791
+ # Knowledge Base Tab
792
+ with gr.Tab("Knowledge Base"):
793
+ kb_query = gr.Textbox(
794
+ label="Query Knowledge Base",
795
+ placeholder="Ask about topics in your knowledge base..."
796
+ )
797
+ kb_btn = gr.Button("Query Knowledge Base")
798
+ kb_output = gr.Markdown("Results will appear here...")
799
+
800
+ kb_btn.click(
801
+ fn=query_knowledge_base,
802
+ inputs=[kb_query],
803
+ outputs=[kb_output]
804
+ )
805
+
806
+ report_btn = gr.Button("Generate Weekly Report")
807
+ report_output = gr.Markdown("Report will appear here...")
808
+
809
+ report_btn.click(
810
+ fn=generate_report_handler,
811
+ inputs=[],
812
+ outputs=[report_output]
813
+ )
814
+
815
+ gr.Markdown("""
816
+ ### Example Queries:
817
+ - "What have we learned about quantum computing?"
818
+ - "Summarize our research on AI safety"
819
+ - "What connections exist between the topics we've studied?"
820
+ """)
821
+
822
+ gr.Markdown("""
823
+ ## About PARA
824
+
825
+ PARA (Personal AI Research Assistant) leverages Groq's compound models with agentic capabilities to help you research topics, analyze code, find connections between concepts, and build a personalized knowledge base.
826
+
827
+ **How it works:**
828
+ 1. Set your Groq API key
829
+ 2. Choose between compound-beta (more powerful) and compound-beta-mini (faster)
830
+ 3. Use the tabs to access different features
831
+ 4. Your research is automatically saved to a knowledge base for future reference
832
+
833
+ **Features:**
834
+ - Web search with domain filtering
835
+ - Code execution and analysis
836
+ - Concept connections discovery
837
+ - Persistent knowledge base
838
+ - Weekly research reports
839
+ """)
840
+
841
+ return app
842
+
843
+ # Launch the app
844
+ if __name__ == "__main__":
845
+ app = create_gradio_app()
846
+ app.launch()