cryogenic22 commited on
Commit
7da1f57
·
verified ·
1 Parent(s): 9748931

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +409 -328
app.py CHANGED
@@ -1,14 +1,13 @@
1
-
2
  import os
3
  import time
4
  import json
5
- import random
6
  import re
7
-
8
- import plotly.graph_objects as go
9
  import streamlit as st
10
- from crewai import Agent, Crew, Process, Task
 
11
  from dotenv import load_dotenv
 
12
 
13
  # Load environment variables
14
  load_dotenv()
@@ -21,100 +20,76 @@ st.set_page_config(
21
  initial_sidebar_state="expanded"
22
  )
23
 
24
- # Enhanced CSS with more animations
25
  st.markdown("""
26
  <style>
27
- /* Animated background */
28
- .stApp {
29
- background: linear-gradient(135deg, #f5f7fa 0%, #e4e7eb 100%);
30
- }
31
-
32
- /* Agent Chat Containers */
33
- .chat-window {
34
- height: 400px;
35
- overflow-y: auto;
36
  padding: 20px;
37
  background: rgba(255, 255, 255, 0.9);
38
  border-radius: 15px;
39
- box-shadow: 0 8px 32px rgba(31, 38, 135, 0.15);
40
- margin: 20px 0;
41
- border: 1px solid rgba(255, 255, 255, 0.18);
42
  }
43
 
44
- .agent-message {
45
- display: flex;
46
- align-items: flex-start;
47
- margin: 15px 0;
48
- animation: messageSlide 0.5s ease forwards;
49
- opacity: 0;
50
- transform: translateX(-20px);
51
  }
52
 
53
- @keyframes messageSlide {
54
- to {
55
- opacity: 1;
56
- transform: translateX(0);
57
- }
58
  }
59
 
60
  .agent-avatar {
61
- width: 45px;
62
- height: 45px;
63
  border-radius: 50%;
 
64
  display: flex;
65
  align-items: center;
66
  justify-content: center;
67
- font-size: 24px;
68
- margin-right: 15px;
69
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
70
- animation: avatarPop 0.3s ease forwards;
71
- }
72
-
73
- @keyframes avatarPop {
74
- 0% { transform: scale(0); }
75
- 50% { transform: scale(1.2); }
76
- 100% { transform: scale(1); }
77
- }
78
-
79
- .message-bubble {
80
  background: white;
81
- padding: 12px 20px;
82
- border-radius: 18px;
83
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
84
- max-width: 80%;
85
- position: relative;
86
- animation: bubbleFade 0.3s ease forwards;
87
  }
88
 
89
- @keyframes bubbleFade {
90
- from { opacity: 0; transform: scale(0.9); }
91
- to { opacity: 1; transform: scale(1); }
 
 
 
 
 
92
  }
93
 
94
- /* Thinking animation */
95
- .thinking-dots {
96
- display: inline-flex;
97
- gap: 4px;
98
- margin-left: 8px;
99
  }
100
 
101
- .dot {
102
- width: 8px;
103
- height: 8px;
104
- background: #4CAF50;
105
- border-radius: 50%;
106
- animation: dotPulse 1.5s infinite;
107
  }
108
 
109
- .dot:nth-child(2) { animation-delay: 0.2s; }
110
- .dot:nth-child(3) { animation-delay: 0.4s; }
111
-
112
- @keyframes dotPulse {
113
- 0%, 100% { transform: scale(0.7); opacity: 0.5; }
114
- 50% { transform: scale(1); opacity: 1; }
 
115
  }
116
 
117
- /* Progress bar animation */
118
  .progress-container {
119
  width: 100%;
120
  height: 8px;
@@ -128,65 +103,193 @@ st.markdown("""
128
  height: 100%;
129
  background: linear-gradient(90deg, #4CAF50, #81C784);
130
  transition: width 0.5s ease;
131
- position: relative;
132
- overflow: hidden;
133
- }
134
-
135
- .progress-bar::after {
136
- content: '';
137
- position: absolute;
138
- top: 0;
139
- left: 0;
140
- width: 100%;
141
- height: 100%;
142
- background: linear-gradient(
143
- 90deg,
144
- transparent,
145
- rgba(255, 255, 255,  
146
- 0.4),
147
- transparent  
148
-
149
- );
150
- animation: shimmer 2s infinite;
151
  }
152
 
153
- @keyframes shimmer {
154
- 0% { transform: translateX(-100%); }
155
- 100% { transform: translateX(100%); }
 
 
 
 
156
  }
157
 
158
- /* Status badges */
159
- .status-badge {
160
- display: inline-flex;
161
- align-items: center;
162
- padding: 6px 12px;
163
- border-radius: 12px;
164
- font-size: 14px;
165
- font-weight: 500;
166
- margin: 4px;
167
- animation: badgeFade 0.3s ease forwards;
168
- }
169
-
170
- @keyframes badgeFade {
171
- from { opacity: 0; transform: translateY(-10px); }
172
- to { opacity: 1; transform: translateY(0); }
173
  }
174
 
175
- /* Agent-specific styles */
176
- .researcher {
177
- background: linear-gradient(135deg, #E3F2FD 0%, #BBDEFB 100%);
 
 
178
  }
179
 
180
- .analyst {
181
- background: linear-gradient(135deg, #F3E5F5 0%, #E1BEE7 100%);
 
 
 
182
  }
183
 
184
- .writer {
185
- background: linear-gradient(135deg, #E8F5E9 0%, #C8E6C9 100%);
 
 
 
 
186
  }
187
  </style>
188
  """, unsafe_allow_html=True)
189
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
 
191
  def format_json_output(raw_output):
192
  """Format CrewOutput or raw string into proper JSON structure"""
@@ -203,199 +306,143 @@ def format_json_output(raw_output):
203
  if match:
204
  try:
205
  return json.loads(match.group())
206
- except json.JSONDecodeError:
207
- pass # Or handle the error as needed
208
 
209
  # If no JSON found, create structured format
210
  return {
211
- "exec_summary": extract_section(raw_text, "Executive Summary"),
 
 
 
 
 
212
  "detailed_report": raw_text,
213
- "sources": extract_sources(raw_text)
 
 
 
 
 
214
  }
215
-
216
  except Exception as e:
217
  st.error(f"Error formatting output: {str(e)}")
218
  return {
219
- "exec_summary": "Error formatting report",
 
 
 
 
 
220
  "detailed_report": raw_text if 'raw_text' in locals() else str(raw_output),
221
- "sources": []
 
 
 
 
 
222
  }
223
 
 
 
 
 
 
224
 
225
- def display_thinking_animation():
226
- """Display thinking animation dots"""
227
- return """
228
- <div class="thinking-dots">
229
- <div class="dot"></div>
230
- <div class="dot"></div>
231
- <div class="dot"></div>
232
- </div>
233
- """
234
-
235
-
236
- def display_agent_message(container, agent_type: str, message: str, thinking: bool = False):
237
- """Display an animated agent message"""
238
- icons = {
239
- "researcher": "🔍",
240
- "analyst": "📊",
241
- "writer": "✍️"
242
- }
243
-
244
- message_html = f"""
245
- <div class="agent-message">
246
- <div class="agent-avatar {agent_type}">
247
- {icons.get(agent_type, "👤")}
248
- </div>
249
- <div class="message-bubble">
250
- {message}
251
- {display_thinking_animation() if thinking else ""}
252
- </div>
253
- </div>
254
- """
255
- container.markdown(message_html, unsafe_allow_html=True)
256
-
257
-
258
- def update_progress(container, progress, message=""):
259
- """Update progress bar with animation"""
260
- progress_html = f"""
261
- <div class="progress-container">
262
- <div class="progress-bar" style="width: {progress}%"></div>
263
- </div>
264
- <div class="status-badge">
265
- {message}
266
- </div>
267
- """
268
- container.markdown(progress_html, unsafe_allow_html=True)
269
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
270
 
271
  def run_market_research(topic: str, progress_container, chat_container):
 
272
  try:
273
- researcher = Agent(
274
- role='Research Analyst',
275
- goal=f'Conduct thorough market research about {topic} with verifiable sources',
276
- backstory='You are an experienced market research analyst with expertise in data analysis and trend identification.',
277
- verbose=True
278
- )
279
-
280
- analyst = Agent(
281
- role='Data Analyst',
282
- goal='Create data-driven insights with specific metrics',
283
- backstory='You are a skilled data analyst who specializes in turning research into actionable insights.',
284
- verbose=True
285
- )
286
-
287
- writer = Agent(
288
- role='Report Writer',
289
- goal='Create both executive summary and detailed reports with citations',
290
- backstory='You are a professional writer who creates clear, structured reports.',
291
- verbose=True
292
- )
293
-
294
  # Research Phase
295
- display_agent_message(chat_container, "researcher",
296
- f"👋 Hello! I'll be researching the {topic} market thoroughly.", False)
 
 
297
  time.sleep(1)
298
-
299
- update_progress(progress_container, 20, "🔍 Gathering market data...")
300
- display_agent_message(chat_container, "researcher", "Processing market information...", True)
301
- time.sleep(1)
302
-
303
- research_task = Task(
304
- description=f"""
305
- Research {topic} with focus on:
306
- 1. Market size and growth projections (with specific numbers)
307
- 2. Key players and market share percentages
308
- 3. Competitive analysis
309
- 4. Future trends
310
- 5. Include verifiable sources
311
-
312
- Format the output as clear sections with numerical data points.
313
- """,
314
- agent=researcher,
315
- expected_output="Detailed market research with data points and sources"
316
- )
317
-
318
  # Analysis Phase
319
- update_progress(progress_container, 40, "📊 Analyzing findings...")
320
- display_agent_message(chat_container, "analyst",
321
- "I've received the research data. Beginning analysis...", False)
 
322
  time.sleep(1)
323
-
324
- analysis_task = Task(
325
- description=f"""
326
- Analyze the research findings and provide:
327
- 1. Growth projections and trends
328
- 2. Market share analysis
329
- 3. Competitive landscape
330
- 4. Key opportunities and challenges
331
-
332
- Include specific metrics and percentages.
333
- """,
334
- agent=analyst,
335
- expected_output="Market analysis with specific metrics",
336
- context=[research_task]
337
- )
338
-
339
  # Report Phase
340
- update_progress(progress_container, 70, "✍️ Generating report...")
341
- display_agent_message(chat_container, "writer",
342
- "Converting analysis into comprehensive report...", False)
343
- time.sleep(1)
344
-
345
- report_task = Task(
346
- description=f"""
347
- Create a market research report with:
348
- 1. Executive Summary (2-3 paragraphs)
349
- 2. Detailed Report (full analysis)
350
- 3. Sources and Citations
351
-
352
- Format as a JSON with:
353
- {{
354
- "exec_summary": "summary text",
355
- "detailed_report": "detailed text",
356
- "sources": ["source1", "source2"]
357
- }}
358
- """,
359
- agent=writer,
360
- expected_output="JSON formatted report with summary and details",
361
- context=[research_task, analysis_task]
362
- )
363
-
364
- crew = Crew(
365
- agents=[researcher, analyst, writer],
366
- tasks=[research_task, analysis_task, report_task],
367
- verbose=True,
368
- process=Process.sequential
369
- )
370
-
371
  result = crew.kickoff()
372
-
373
- # Update final progress
374
- update_progress(progress_container, 100, "✨ Report completed!")
375
- display_agent_message(chat_container, "writer",
376
- "Report generation completed! You can now view the full report.", False)
377
-
378
- return format_json_output(result)
 
 
 
 
 
 
379
 
380
  except Exception as e:
381
- st.error(f"Error generating report: {str(e)}")
382
- return {
383
- "exec_summary": "Error generating report",
384
- "detailed_report": "",
385
- "sources": []
386
- }
387
-
388
- def extract_section(text, section_name):
389
- """Extract a section from the text"""
390
- pattern = rf"{section_name}.*?\n(.*?)(?=\n\n|<span class=\"math-inline\">)"
391
- match = re.search(pattern, text, re.DOTALL | re.IGNORECASE)
392
- return match.group(1).strip() if match else ""
393
-
394
- def extract_sources(text):
395
- """Extract sources from the text"""
396
- source_pattern = r"Source:.*?(?:\n|<span class=\"math-inline\">)|\[.*?\]|\(https?://.*?\)"
397
- matches = re.finditer(source_pattern, text, re.MULTILINE)
398
- return [match.group().strip() for match in matches]
399
 
400
  def main():
401
  st.title("🤖 AI Market Research Generator")
@@ -425,67 +472,101 @@ def main():
425
  st.error("Please enter a research topic")
426
  else:
427
  st.session_state.generating = True
428
- st.rerun()
429
-
430
- # Only show chat window if generating
431
- if st.session_state.generating:
432
- with col2:
433
- st.markdown('<div class="chat-window">', unsafe_allow_html=True)
434
- chat_container = st.empty()
435
- st.markdown('</div>', unsafe_allow_html=True)
436
-
437
- progress_container = st.container()
438
-
439
- try:
440
- result = run_market_research(topic, progress_container, chat_container)
441
-
442
- if result:
443
- st.session_state.current_report = result
444
- st.success("Report generated successfully! View it in the Reports tab.")
445
- except Exception as e:
446
- st.error(f"Error generating report: {str(e)}")
447
- finally:
448
- st.session_state.generating = False
449
- st.rerun()
450
 
451
  with tab2:
452
  if hasattr(st.session_state, 'current_report'):
453
  report = st.session_state.current_report
 
454
 
455
- # Display Executive Summary in a card
456
  st.markdown("""
457
- <div style='background-color: white; padding: 20px; border-radius: 10px; margin: 10px 0;'>
458
- <h3>Executive Summary</h3>
459
- <p>{}</p>
 
 
 
460
  </div>
461
- """.format(report['exec_summary']), unsafe_allow_html=True)
462
 
463
- # Display Detailed Report in a card
 
464
  st.markdown("""
465
- <div style='background-color: white; padding: 20px; border-radius: 10px; margin: 10px 0;'>
466
- <h3>Detailed Report</h3>
467
- <p>{}</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
468
  </div>
469
- """.format(report['detailed_report']), unsafe_allow_html=True)
 
 
 
 
 
470
 
471
- # Display Sources in a card
472
- st.markdown("""
473
- <div style='background-color: white; padding: 20px; border-radius: 10px; margin: 10px 0;'>
474
- <h3>Sources</h3>
475
- <ul>
476
- {}
477
- </ul>
 
 
 
 
478
  </div>
479
- """.format('\n'.join([f"<li>{source}</li>" for source in report['sources']])),
480
- unsafe_allow_html=True)
 
 
 
 
 
481
 
482
  # Download buttons
483
  col1, col2 = st.columns(2)
484
  with col1:
 
 
 
 
 
 
 
485
  st.download_button(
486
  "Download Full Report",
487
  data=report['detailed_report'],
488
- file_name=f"{topic}_report.md",
489
  mime="text/markdown"
490
  )
491
 
 
1
+ # app.py
2
  import os
3
  import time
4
  import json
 
5
  import re
 
 
6
  import streamlit as st
7
+ import plotly.graph_objects as go
8
+ import plotly.express as px
9
  from dotenv import load_dotenv
10
+ from crewai import Agent, Crew, Process, Task
11
 
12
  # Load environment variables
13
  load_dotenv()
 
20
  initial_sidebar_state="expanded"
21
  )
22
 
23
+ # Add all CSS styles
24
  st.markdown("""
25
  <style>
26
+ /* Agent Team Section */
27
+ .agent-team {
28
+ display: flex;
29
+ justify-content: space-around;
30
+ margin-bottom: 20px;
 
 
 
 
31
  padding: 20px;
32
  background: rgba(255, 255, 255, 0.9);
33
  border-radius: 15px;
34
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
 
 
35
  }
36
 
37
+ .agent-card {
38
+ text-align: center;
39
+ padding: 15px;
40
+ border-radius: 10px;
41
+ transition: all 0.3s ease;
 
 
42
  }
43
 
44
+ .agent-card.active {
45
+ transform: scale(1.05);
46
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
 
 
47
  }
48
 
49
  .agent-avatar {
50
+ width: 60px;
51
+ height: 60px;
52
  border-radius: 50%;
53
+ margin: 0 auto 10px;
54
  display: flex;
55
  align-items: center;
56
  justify-content: center;
57
+ font-size: 30px;
 
 
 
 
 
 
 
 
 
 
 
 
58
  background: white;
59
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
 
 
 
 
 
60
  }
61
 
62
+ /* Chat Messages */
63
+ .chat-container {
64
+ height: 400px;
65
+ overflow-y: auto;
66
+ padding: 20px;
67
+ background: rgba(255, 255, 255, 0.9);
68
+ border-radius: 15px;
69
+ margin: 20px 0;
70
  }
71
 
72
+ .chat-message {
73
+ display: flex;
74
+ margin: 15px 0;
75
+ opacity: 0;
76
+ animation: fadeIn 0.5s forwards;
77
  }
78
 
79
+ @keyframes fadeIn {
80
+ to { opacity: 1; }
 
 
 
 
81
  }
82
 
83
+ .message-content {
84
+ background: white;
85
+ padding: 15px;
86
+ border-radius: 15px;
87
+ margin-left: 15px;
88
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
89
+ max-width: 80%;
90
  }
91
 
92
+ /* Progress Bar */
93
  .progress-container {
94
  width: 100%;
95
  height: 8px;
 
103
  height: 100%;
104
  background: linear-gradient(90deg, #4CAF50, #81C784);
105
  transition: width 0.5s ease;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
  }
107
 
108
+ /* Report Sections */
109
+ .report-header {
110
+ background: #f8f9fa;
111
+ padding: 15px;
112
+ border-radius: 10px;
113
+ margin-bottom: 20px;
114
+ border-left: 4px solid #ff4444;
115
  }
116
 
117
+ .exec-summary {
118
+ background: white;
119
+ padding: 25px;
120
+ border-radius: 15px;
121
+ margin-bottom: 30px;
122
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
 
 
 
 
 
 
 
 
 
123
  }
124
 
125
+ .key-findings {
126
+ display: grid;
127
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
128
+ gap: 20px;
129
+ margin: 20px 0;
130
  }
131
 
132
+ .finding-card {
133
+ background: white;
134
+ padding: 20px;
135
+ border-radius: 10px;
136
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
137
  }
138
 
139
+ .detailed-section {
140
+ background: white;
141
+ padding: 30px;
142
+ border-radius: 15px;
143
+ margin: 20px 0;
144
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
145
  }
146
  </style>
147
  """, unsafe_allow_html=True)
148
 
149
+ def display_agent_team(container, active_agent=None):
150
+ """Display the team of agents with active state"""
151
+ agents = [
152
+ {"role": "Research Analyst", "icon": "🔍", "color": "#E3F2FD"},
153
+ {"role": "Data Analyst", "icon": "📊", "color": "#F3E5F5"},
154
+ {"role": "Report Writer", "icon": "✍️", "color": "#E8F5E9"}
155
+ ]
156
+
157
+ html = '<div class="agent-team">'
158
+ for agent in agents:
159
+ active_class = "active" if agent["role"] == active_agent else ""
160
+ html += f"""
161
+ <div class="agent-card {active_class}" style="background: {agent['color']}">
162
+ <div class="agent-avatar">{agent['icon']}</div>
163
+ <div class="agent-role">{agent['role']}</div>
164
+ <div class="agent-status">
165
+ {"Working..." if agent["role"] == active_agent else "Standby"}
166
+ </div>
167
+ </div>
168
+ """
169
+ html += '</div>'
170
+
171
+ container.markdown(html, unsafe_allow_html=True)
172
+
173
+ def display_agent_message(container, agent_type: str, message: str):
174
+ """Display an agent message with improved styling"""
175
+ icons = {"researcher": "🔍", "analyst": "📊", "writer": "✍️"}
176
+ colors = {
177
+ "researcher": "#E3F2FD",
178
+ "analyst": "#F3E5F5",
179
+ "writer": "#E8F5E9"
180
+ }
181
+
182
+ html = f"""
183
+ <div class="chat-message">
184
+ <div class="agent-avatar" style="background: {colors.get(agent_type, '#fff')}">
185
+ {icons.get(agent_type, "👤")}
186
+ </div>
187
+ <div class="message-content">
188
+ <div>{message}</div>
189
+ </div>
190
+ </div>
191
+ """
192
+ container.markdown(html, unsafe_allow_html=True)
193
+
194
+ def update_progress(container, progress, message=""):
195
+ """Update progress bar with animation"""
196
+ progress_html = f"""
197
+ <div class="progress-container">
198
+ <div class="progress-bar" style="width: {progress}%"></div>
199
+ </div>
200
+ <div style="text-align: center; color: #666;">
201
+ {message}
202
+ </div>
203
+ """
204
+ container.markdown(progress_html, unsafe_allow_html=True)
205
+
206
+ def create_research_crew(topic: str):
207
+ """Create the research crew with enhanced prompts"""
208
+ researcher = Agent(
209
+ role='Research Analyst',
210
+ goal=f'Conduct comprehensive market research about {topic} with detailed metrics and verifiable sources',
211
+ backstory="You are an experienced market research analyst who focuses on gathering concrete data points and always verifies sources.",
212
+ verbose=True
213
+ )
214
+
215
+ analyst = Agent(
216
+ role='Data Analyst',
217
+ goal='Transform research data into actionable insights with visualization-ready metrics',
218
+ backstory="You are a skilled data analyst who excels at interpreting market research and creating data-driven insights.",
219
+ verbose=True
220
+ )
221
+
222
+ writer = Agent(
223
+ role='Report Writer',
224
+ goal='Create professional market research reports with executive summary and detailed analysis',
225
+ backstory="You are an expert business writer who specializes in creating clear, comprehensive market research reports.",
226
+ verbose=True
227
+ )
228
+
229
+ research_task = Task(
230
+ description=f"""
231
+ Conduct extensive market research on {topic} with:
232
+ 1. Market Overview (market size, growth rates, projections)
233
+ 2. Competitive Analysis (market shares, positioning)
234
+ 3. Market Dynamics (drivers, challenges, trends)
235
+
236
+ Provide specific numerical values and sources.
237
+ Format data for visualization.
238
+ """,
239
+ agent=researcher,
240
+ expected_output="Comprehensive research data with specific metrics and sources"
241
+ )
242
+
243
+ analysis_task = Task(
244
+ description=f"""
245
+ Analyze the findings and provide:
246
+ 1. Growth projections and trends (5 years)
247
+ 2. Market share analysis
248
+ 3. Competitive landscape
249
+ 4. Strategic recommendations
250
+
251
+ Include specific numbers and percentages.
252
+ """,
253
+ agent=analyst,
254
+ expected_output="Detailed analysis with visualization-ready metrics",
255
+ context=[research_task]
256
+ )
257
+
258
+ report_task = Task(
259
+ description=f"""
260
+ Create a professional report with:
261
+ 1. Executive Summary (2-3 pages)
262
+ 2. Detailed Report (10+ pages)
263
+ 3. Sources and Citations
264
+
265
+ Format as JSON:
266
+ {{
267
+ "exec_summary": {{
268
+ "summary": "text",
269
+ "market_size": "data",
270
+ "growth_rate": "data",
271
+ "key_players": "data"
272
+ }},
273
+ "detailed_report": "text",
274
+ "sources": ["source1", "source2"],
275
+ "metrics": {{
276
+ "market_size_data": [],
277
+ "growth_rates": [],
278
+ "market_shares": []
279
+ }}
280
+ }}
281
+ """,
282
+ agent=writer,
283
+ expected_output="JSON containing executive summary and detailed report",
284
+ context=[research_task, analysis_task]
285
+ )
286
+
287
+ return Crew(
288
+ agents=[researcher, analyst, writer],
289
+ tasks=[research_task, analysis_task, report_task],
290
+ verbose=True,
291
+ process=Process.sequential
292
+ )
293
 
294
  def format_json_output(raw_output):
295
  """Format CrewOutput or raw string into proper JSON structure"""
 
306
  if match:
307
  try:
308
  return json.loads(match.group())
309
+ except:
310
+ pass
311
 
312
  # If no JSON found, create structured format
313
  return {
314
+ "exec_summary": {
315
+ "summary": extract_section(raw_text, "Executive Summary"),
316
+ "market_size": extract_section(raw_text, "Market Size"),
317
+ "growth_rate": extract_section(raw_text, "Growth Rate"),
318
+ "key_players": extract_section(raw_text, "Key Players")
319
+ },
320
  "detailed_report": raw_text,
321
+ "sources": extract_sources(raw_text),
322
+ "metrics": {
323
+ "market_size_data": [],
324
+ "growth_rates": [],
325
+ "market_shares": []
326
+ }
327
  }
 
328
  except Exception as e:
329
  st.error(f"Error formatting output: {str(e)}")
330
  return {
331
+ "exec_summary": {
332
+ "summary": "Error formatting report",
333
+ "market_size": "N/A",
334
+ "growth_rate": "N/A",
335
+ "key_players": "N/A"
336
+ },
337
  "detailed_report": raw_text if 'raw_text' in locals() else str(raw_output),
338
+ "sources": [],
339
+ "metrics": {
340
+ "market_size_data": [],
341
+ "growth_rates": [],
342
+ "market_shares": []
343
+ }
344
  }
345
 
346
+ def extract_section(text, section_name):
347
+ """Extract a section from the text"""
348
+ pattern = f"{section_name}.*?\n(.*?)(?=\n\n|$)"
349
+ match = re.search(pattern, text, re.DOTALL | re.IGNORECASE)
350
+ return match.group(1).strip() if match else ""
351
 
352
+ def extract_sources(text):
353
+ """Extract sources from the text"""
354
+ sources = []
355
+ source_pattern = r"Source:.*?(?:\n|$)|\[.*?\]|\(https?://.*?\)"
356
+ matches = re.finditer(source_pattern, text, re.MULTILINE)
357
+ return [match.group().strip() for match in matches]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
358
 
359
+ def generate_visualizations(data):
360
+ """Generate visualizations based on the report data"""
361
+ charts = []
362
+
363
+ # Market Size Chart
364
+ if data['metrics']['market_size_data']:
365
+ fig = go.Figure(data=[
366
+ go.Bar(
367
+ x=['Current', 'Projected'],
368
+ y=data['metrics']['market_size_data'],
369
+ text=data['metrics']['market_size_data'],
370
+ textposition='auto',
371
+ )
372
+ ])
373
+ fig.update_layout(title='Market Size Projection')
374
+ charts.append(fig)
375
+
376
+ # Growth Rate Chart
377
+ if data['metrics']['growth_rates']:
378
+ fig = go.Figure(data=[
379
+ go.Line(
380
+ x=list(range(len(data['metrics']['growth_rates']))),
381
+ y=data['metrics']['growth_rates'],
382
+ mode='lines+markers'
383
+ )
384
+ ])
385
+ fig.update_layout(title='Growth Rate Trends')
386
+ charts.append(fig)
387
+
388
+ # Market Share Chart
389
+ if data['metrics']['market_shares']:
390
+ fig = go.Figure(data=[go.Pie(
391
+ labels=list(data['metrics']['market_shares'].keys()),
392
+ values=list(data['metrics']['market_shares'].values())
393
+ )])
394
+ fig.update_layout(title='Market Share Distribution')
395
+ charts.append(fig)
396
+
397
+ return charts
398
 
399
  def run_market_research(topic: str, progress_container, chat_container):
400
+ """Run the market research process"""
401
  try:
402
+ # Initialize with team display
403
+ display_agent_team(progress_container, None)
404
+ update_progress(progress_container, 0, "Initializing research team...")
405
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
406
  # Research Phase
407
+ display_agent_team(progress_container, "Research Analyst")
408
+ display_agent_message(chat_container, "researcher",
409
+ f"Starting comprehensive research on {topic}...")
410
+ update_progress(progress_container, 25, "Gathering market data...")
411
  time.sleep(1)
412
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
413
  # Analysis Phase
414
+ display_agent_team(progress_container, "Data Analyst")
415
+ display_agent_message(chat_container, "analyst",
416
+ "Processing research data and identifying key insights...")
417
+ update_progress(progress_container, 50, "Analyzing findings...")
418
  time.sleep(1)
419
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
420
  # Report Phase
421
+ display_agent_team(progress_container, "Report Writer")
422
+ display_agent_message(chat_container, "writer",
423
+ "Compiling final report with executive summary and detailed analysis...")
424
+ update_progress(progress_container, 75, "Generating report...")
425
+
426
+ # Create and run the crew
427
+ crew = create_research_crew(topic)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
428
  result = crew.kickoff()
429
+
430
+ # Format and process the result
431
+ report_data = format_json_output(result)
432
+
433
+ # Add visualizations
434
+ charts = generate_visualizations(report_data)
435
+ report_data['charts'] = charts
436
+
437
+ update_progress(progress_container, 100, "Report completed!")
438
+ display_agent_message(chat_container, "writer",
439
+ "✨ Report generation completed! You can now view the full report.")
440
+
441
+ return report_data
442
 
443
  except Exception as e:
444
+ st.error(f"Error during research: {str(e)}")
445
+ return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
446
 
447
  def main():
448
  st.title("🤖 AI Market Research Generator")
 
472
  st.error("Please enter a research topic")
473
  else:
474
  st.session_state.generating = True
475
+
476
+ # Create containers for progress and chat
477
+ progress_container = st.container()
478
+ chat_container = st.container()
479
+
480
+ try:
481
+ result = run_market_research(topic, progress_container, chat_container)
482
+
483
+ if result:
484
+ st.session_state.current_report = result
485
+ st.session_state.current_topic = topic
486
+ st.success("Report generated successfully! View it in the Reports tab.")
487
+ except Exception as e:
488
+ st.error(f"Error generating report: {str(e)}")
489
+ finally:
490
+ st.session_state.generating = False
 
 
 
 
 
 
491
 
492
  with tab2:
493
  if hasattr(st.session_state, 'current_report'):
494
  report = st.session_state.current_report
495
+ topic = st.session_state.current_topic
496
 
497
+ # Display AI Disclaimer
498
  st.markdown("""
499
+ <div class="report-header">
500
+ <strong>⚠️ AI-Generated Report Disclaimer</strong>
501
+ <p>This report was generated using AI agents for market research and analysis.
502
+ While we strive for accuracy, please review all content and verify critical information
503
+ independently. The analysis and recommendations provided should be used as a
504
+ supplementary resource rather than the sole basis for decision-making.</p>
505
  </div>
506
+ """, unsafe_allow_html=True)
507
 
508
+ # Executive Summary Section
509
+ st.subheader("Executive Summary")
510
  st.markdown("""
511
+ <div class="exec-summary">
512
+ {}
513
+
514
+ <div class="key-findings">
515
+ <div class="finding-card">
516
+ <h4>Market Size</h4>
517
+ {}
518
+ </div>
519
+ <div class="finding-card">
520
+ <h4>Growth Rate</h4>
521
+ {}
522
+ </div>
523
+ <div class="finding-card">
524
+ <h4>Key Players</h4>
525
+ {}
526
+ </div>
527
+ </div>
528
  </div>
529
+ """.format(
530
+ report['exec_summary']['summary'],
531
+ report['exec_summary']['market_size'],
532
+ report['exec_summary']['growth_rate'],
533
+ report['exec_summary']['key_players']
534
+ ), unsafe_allow_html=True)
535
 
536
+ # Visualizations
537
+ if 'charts' in report and report['charts']:
538
+ st.subheader("Market Analysis Visualizations")
539
+ for chart in report['charts']:
540
+ st.plotly_chart(chart, use_container_width=True)
541
+
542
+ # Detailed Report Section
543
+ st.subheader("Detailed Report")
544
+ st.markdown(f"""
545
+ <div class="detailed-section">
546
+ {report['detailed_report']}
547
  </div>
548
+ """, unsafe_allow_html=True)
549
+
550
+ # Sources Section
551
+ if report['sources']:
552
+ st.subheader("Sources")
553
+ for source in report['sources']:
554
+ st.markdown(f"- {source}")
555
 
556
  # Download buttons
557
  col1, col2 = st.columns(2)
558
  with col1:
559
+ st.download_button(
560
+ "Download Executive Summary",
561
+ data=report['exec_summary']['summary'],
562
+ file_name=f"{topic}_executive_summary.md",
563
+ mime="text/markdown"
564
+ )
565
+ with col2:
566
  st.download_button(
567
  "Download Full Report",
568
  data=report['detailed_report'],
569
+ file_name=f"{topic}_detailed_report.md",
570
  mime="text/markdown"
571
  )
572