-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
2103 lines (1858 loc) · 133 KB
/
app.py
File metadata and controls
2103 lines (1858 loc) · 133 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
import streamlit as st
import google.generativeai as genai
from datetime import datetime, timedelta
import pandas as pd
import json
import os
import re
import markdown # For HTML export
from gtts import gTTS # For Text-to-Speech
import io # For Text-to-Speech
import random
# App title and configuration
st.set_page_config(page_title="AI Note Maker", page_icon="📝", layout="wide")
# --- FLASHCARD CSS (Define globally and inject once) ---
FLASHCARD_CSS = """
<style>
.flashcard-container {
margin-bottom: 20px;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.35);
}
.flashcard-question {
background: linear-gradient(135deg, #1D2B64, #4A00E0); /* Dark Blue to Purple gradient */
color: #f0f0f0; /* Light text for contrast */
padding: 20px;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; /* Modern font stack */
font-size: 1.1em;
}
.flashcard-question p { margin: 0; line-height: 1.5; }
.flashcard-question strong { color: #ffffff; font-weight: 600; }
.flashcard-answer-content {
background-color: #283040; /* A complementary dark background for the answer */
color: #e0e0e0; /* Light text for readability */
padding: 15px 20px; /* More padding */
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
border-top: 1px solid #4A00E0; /* A colored top border to link with question gradient */
}
</style>
"""
st.markdown(FLASHCARD_CSS, unsafe_allow_html=True)
# Constants for selectbox options
DETAIL_LEVEL_OPTIONS = ["Brief", "Standard", "Comprehensive", "Expert"]
TONE_OPTIONS = ["Formal", "Casual", "Academic", "Enthusiastic", "Technical", "Simplified"]
LANGUAGE_STYLE_OPTIONS = ["Standard", "Creative", "Concise", "Elaborate", "Scientific", "Conversational"]
# Initialize session state
if 'history' not in st.session_state:
st.session_state.history = []
if 'favorites' not in st.session_state:
st.session_state.favorites = []
if 'api_key' not in st.session_state:
st.session_state.api_key = ""
if 'custom_templates' not in st.session_state:
st.session_state.custom_templates = {}
if 'user_knowledge_level' not in st.session_state:
st.session_state.user_knowledge_level = {}
if 'spaced_repetition' not in st.session_state:
st.session_state.spaced_repetition = []
if 'quiz_scores' not in st.session_state:
st.session_state.quiz_scores = []
if 'default_detail_level' not in st.session_state:
st.session_state.default_detail_level = "Standard"
if 'default_tone' not in st.session_state:
st.session_state.default_tone = "Formal"
if 'default_language_style' not in st.session_state:
st.session_state.default_language_style = "Standard"
if 'topic_suggestions' not in st.session_state:
st.session_state.topic_suggestions = []
# New session states for the 4 features
if 'parsed_quiz_questions' not in st.session_state: # Changed from interactive_quiz_data
st.session_state.parsed_quiz_questions = []
if 'interactive_quiz_active' not in st.session_state:
st.session_state.interactive_quiz_active = False
if 'user_quiz_answers' not in st.session_state:
st.session_state.user_quiz_answers = {}
if 'quiz_score' not in st.session_state:
st.session_state.quiz_score = 0
if 'current_interactive_question_idx' not in st.session_state:
st.session_state.current_interactive_question_idx = 0
if 'study_tasks' not in st.session_state:
st.session_state.study_tasks = []
if 'selected_main_tab' not in st.session_state:
st.session_state.selected_main_tab = "📝 Note Generation" # Default tab
# Main app header
st.title("📝 AI Note Maker")
st.markdown("Generate comprehensive, customized notes on any topic using AI")
# Sidebar for API key and settings
with st.sidebar:
st.header("🔑 API Configuration")
saved_api_key = st.text_input("Enter your Gemini API Key", value=st.session_state.api_key, type="password")
if saved_api_key != st.session_state.api_key:
st.session_state.api_key = saved_api_key
model_name = st.selectbox("Select AI Model",
["gemini-2.0-flash", "gemini-2.5-flash-preview-04-17", "gemini-2.5-pro-preview-03-25", "gemini-2.0-flash-lite", "gemini-2.0-pro-exp-02-05",
"gemini-2.0-flash-thinking-exp-01-21", "gemini-1.5-pro",
"gemini-1.5-flash", "gemini-1.5-flash-8b"],
index=0)
st.header("⚙️ User Preferences")
pref_detail_level = st.selectbox(
"Default Detail Level",
options=DETAIL_LEVEL_OPTIONS,
index=DETAIL_LEVEL_OPTIONS.index(st.session_state.default_detail_level)
)
if pref_detail_level != st.session_state.default_detail_level:
st.session_state.default_detail_level = pref_detail_level
st.rerun()
pref_tone = st.selectbox(
"Default Tone",
options=TONE_OPTIONS,
index=TONE_OPTIONS.index(st.session_state.default_tone)
)
if pref_tone != st.session_state.default_tone:
st.session_state.default_tone = pref_tone
st.rerun()
pref_language_style = st.selectbox(
"Default Language Style",
options=LANGUAGE_STYLE_OPTIONS,
index=LANGUAGE_STYLE_OPTIONS.index(st.session_state.default_language_style)
)
if pref_language_style != st.session_state.default_language_style:
st.session_state.default_language_style = pref_language_style
st.rerun()
# Theme settings
st.header("🎨 Theme")
theme_options = ["Light", "Dark", "Blue", "Green"]
selected_theme = st.selectbox("Select Theme", theme_options, index=0)
# History and Favorites tabs
tab1, tab2, tab3 = st.tabs(["History", "Favorites", "Learning"])
with tab1:
if st.button("Clear History"):
st.session_state.history = []
st.success("History cleared!")
# Display compact history
if st.session_state.history:
for i, item in enumerate(st.session_state.history[:10]):
st.caption(f"{i+1}. {item['topic']} ({item['tool']})")
with tab2:
# Display favorites
if st.session_state.favorites:
for i, item in enumerate(st.session_state.favorites):
st.caption(f"{i+1}. {item['topic']} ({item['tool']})")
if st.button("Clear Favorites"):
st.session_state.favorites = []
st.success("Favorites cleared!")
with tab3:
# Display learning data
st.caption("Knowledge Levels:")
if st.session_state.user_knowledge_level:
for topic, level in st.session_state.user_knowledge_level.items():
st.caption(f"{topic}: {level}/5")
st.caption("Upcoming Flashcards:")
due_cards = [card for card in st.session_state.spaced_repetition
if card['next_review'] <= datetime.now()]
st.caption(f"{len(due_cards)} cards due for review")
st.caption("Quiz Performance:")
if st.session_state.quiz_scores:
avg_score = sum(score['score'] for score in st.session_state.quiz_scores) / len(st.session_state.quiz_scores)
st.caption(f"Average Score: {avg_score:.1f}%")
st.markdown("---")
st.subheader("🚀 Topic Exploration")
exploration_interest = st.text_input("Interest to explore related topics:", key="exploration_interest_input")
if st.button("Suggest Related Topics"):
if not st.session_state.api_key:
st.error("API key is required for topic suggestion.")
elif not exploration_interest:
st.warning("Please enter an interest to get suggestions.")
else:
with st.spinner("AI is brainstorming..."):
# This is a placeholder. In a real scenario, you'd call the AI.
# prompt = f"Suggest 3-5 related academic topics for further study based on the interest: '{exploration_interest}'. Provide a brief (1-sentence) explanation for each suggestion."
# suggestions_text = generate_ai_content(prompt, st.session_state.api_key, model_name, 0.7, "Brief", {"tone": "Creative", "language_style": "Concise"})
# st.session_state.topic_suggestions = suggestions_text.split('\n') # Process appropriately
st.session_state.topic_suggestions = [
f"Exploring sub-field A of {exploration_interest}",
f"The history of {exploration_interest}",
f"Future trends in {exploration_interest}"
]
st.success("Suggestions generated!")
if st.session_state.get('topic_suggestions'):
st.markdown("**Suggested Topics:**")
for suggestion in st.session_state.topic_suggestions:
st.caption(f"- {suggestion}")
st.markdown("---")
st.subheader("📈 Advanced Analytics")
notes_this_week = 0
one_week_ago = datetime.now() - timedelta(days=7)
for item in st.session_state.history:
try:
item_timestamp = datetime.strptime(item['timestamp'], "%Y-%m-%d %H:%M:%S")
if item_timestamp > one_week_ago:
notes_this_week += 1
except ValueError:
pass # Ignore items with unexpected timestamp format
st.metric("Notes Generated (Last 7 Days)", notes_this_week)
if st.session_state.history:
from collections import Counter
tool_counts = Counter(item['tool'] for item in st.session_state.history)
most_common_tool, most_common_count = tool_counts.most_common(1)[0] if tool_counts else ("N/A", 0)
st.metric("Most Used Note Format", f"{most_common_tool} ({most_common_count} times)")
focus_areas = [topic for topic, level in st.session_state.user_knowledge_level.items() if level < 3]
st.caption(f"Learning Focus Areas (Knowledge < 3/5): {len(focus_areas)}")
for area in focus_areas[:3]: # Display top 3
st.caption(f"- {area} (Level: {st.session_state.user_knowledge_level[area]}/5)")
st.markdown("---")
st.markdown("### About")
st.markdown("AI Note Maker helps you create detailed notes on any topic using Google's Gemini AI.")
st.markdown("v3.0 - Smart Learning Features")
# Function to generate list of AI tools
def generate_ai_tools():
tools = [
"Bullet Points",
"Cornell Notes",
"Mind Map Structure",
"Flashcards",
"Summary Notes",
"Detailed Explanation",
"Question & Answer Format",
"Key Concepts & Definitions",
"Timeline Format",
"Comparative Analysis",
"Exam Preparation",
"Deep research",
"Case Study Analysis",
"Custom Template"
]
categories = {
"Note Formats": ["Bullet Points", "Cornell Notes","Mind Map Structure", "Summary Notes", "Detailed Explanation"],
"Study Aids": ["Flashcards", "Question & Answer Format", "Key Concepts & Definitions", "Exam Preparation"],
"Specialized": ["Timeline Format", "Comparative Analysis", "Deep research", "Case Study Analysis"],
"Custom": ["Custom Template"]
}
return tools, categories
# Get all tools and categories
ai_tools, tool_categories = generate_ai_tools()
# Function to load prompt templates
@st.cache_data
def load_prompt_templates():
templates = {
"Bullet Points": "Create comprehensive bullet point notes on: {prompt}. Format with clear hierarchical structure (main points and sub-points) using bullet symbols. Make notes concise yet complete, covering all important aspects. Use appropriate spacing for readability.",
"Cornell Notes": "Create Cornell-style notes on: {prompt}. Structure with three sections: 1) Right column (main notes area): detailed content with clear paragraphs and hierarchical organization, 2) Left column (cue column): key questions, terms, and concepts that align with the main notes, 3) Bottom section: concise summary of the entire topic. Use proper formatting and spacing.",
"Comprehensive Quiz": "Generate a comprehensive quiz on: {prompt}. Include a mix of multiple choice questions (MCQs), short answer, and true/false questions with a total of 30 questions. Ensure a range of difficulty levels. For MCQs, provide four options with one correct answer clearly marked. Group questions by subtopics if applicable. Include an answer key at the end.",
"Mind Map Structure": "Create a text-based mind map structure on: {prompt}. Format with the core concept in the center, main branches using level 1 headings, sub-branches using level 2 headings, and leaf nodes using bullet points. Use indentation to show relationships between concepts. Include all important relationships and hierarchies.",
"Flashcards": "Create a set of flashcards on: {prompt}. Format with 'Q:' for questions and 'A:' for answers, separating each flashcard with a divider line. Include comprehensive coverage of key facts, definitions, concepts, and their applications. Number each flashcard.",
"Summary Notes": "Create concise summary notes on: {prompt}. Include only the most essential information, key concepts, and critical takeaways. Format with clear headings and short paragraphs. Ensure comprehensive coverage while maintaining brevity (maximum 1/3 the length of detailed notes).",
"Detailed Explanation": "Create detailed explanatory notes on: {prompt}. Include thorough explanations of concepts, supporting evidence, examples, and applications. Structure with clear headings, subheadings, and logical flow. Use appropriate technical language while ensuring clarity.",
"Question & Answer Format": "Create comprehensive Q&A format notes on: {prompt}. Format with clear questions followed by detailed answers. Cover all important aspects of the topic with questions ranging from basic understanding to advanced application. Group related questions together under appropriate headings.",
"Key Concepts & Definitions": "Create a glossary of key concepts and definitions for: {prompt}. Format each entry with the term in bold followed by a comprehensive definition. Include examples where helpful. Organize alphabetically or by related concept groups with clear headings.",
"Timeline Format": "Create chronological timeline notes on: {prompt}. Format with clear date/period indicators followed by detailed descriptions of events, developments, or phases. Include significant milestones, causes, and effects. Use appropriate headings for major eras or transitions.",
"Comparative Analysis": "Create comparative analysis notes on: {prompt}. Structure with clear categories for comparison in the left column and entities being compared across the top. Include detailed points of comparison with similarities and differences clearly marked. Conclude with synthesis of key insights from the comparison.",
"Exam Preparation": "Create comprehensive exam preparation notes on: {prompt}. Include key definitions, formulas, concepts, potential exam questions, and model answers. Format with clear sections for different question types and difficulty levels. Highlight common pitfalls and strategies for tackling complex problems.",
"Deep research": """
You are a high-level research assistant writing in-depth academic responses.
Structure the output as a formal article (~8000 tokens) with:
1. Executive Summary
2. Introduction
3. History & Evolution
4. Concepts & Frameworks
5. Current State
6. Challenges
7. Applications
8. Comparisons
9. Future Outlook
10. Conclusion
11. References (Optional)
Query:
\"\"\"{user_prompt}\"\"\"
""",
"Case Study Analysis": """
You are a high-level research assistant writing comprehensive academic case study analyses.
Structure the response as a formal case study (~8000 tokens) with:
1. Executive Summary
2. Introduction & Background
3. History & Context
4. Key Issues
5. Stakeholder Analysis
6. Root Cause Analysis
7. Strategic Alternatives
8. Recommendation
9. Implementation Plan
10. Challenges & Risk Mitigation
11. Conclusion
12. References (Optional)
Query:
\"\"\"{user_prompt}\"\"\"
"""
}
# New templates for enhanced features
templates.update({
"Auto-Summary": "Provide a concise 3-paragraph summary of the following notes, highlighting only the most critical concepts and takeaways: {content}",
"Refinement": "Refine the following notes on '{topic}' to make them {refinement_type}. Maintain the original structure but improve the content based on the refinement request: {content}",
"Adaptive Content": "Create {detail_level} notes on {prompt} specifically tailored for someone with a knowledge level of {knowledge_level}/5 in this subject. Adjust complexity, depth, and examples accordingly.",
"Citation Generation": "Generate a citation in {style} format for the following source material. If it's a text snippet, try to identify key bibliographic information first. Source: {source_details}",
"Spaced Repetition Cards": "Based on the following notes, create 5-10 spaced repetition flashcards covering the most important concepts that would be suitable for long-term memorization. Each flashcard should have a 'Q:' for the question and an 'A:' for the answer. Separate each flashcard with three hyphens ('---'). Content: {content}",
"Quiz Generation": "Create a 5-question quiz with multiple-choice answers based on the following notes. Include 4 options per question with only one correct answer. Format with the question followed by options labeled A, B, C, D, and mark the correct answer at the end: {content}",
"Research Assistant Query": "Provide a detailed and well-structured answer to the following research query: '{query}'. Structure the output as {output_format}. Draw upon general knowledge and provide explanations, examples, and context where appropriate. Aim for a comprehensive yet understandable response.",
"Research Follow-up Questions": "Based on the following research findings, suggest 3-5 insightful follow-up questions that a student might want to explore next: {research_findings}",
"Writing Enhancer - Rephrase": "Rephrase the following text to improve its clarity, conciseness, and flow, while retaining the original meaning. If a target tone is specified as '{target_tone}', adapt the rephrased text to that tone. Original text: '{text_to_rephrase}'",
"Writing Enhancer - Expand": "Expand on the following point or idea, providing more detail, examples, or supporting arguments. Point to expand: '{text_to_expand}'",
"Writing Enhancer - Summarize": "Provide a concise summary of the following text, capturing the main points. Text to summarize: '{text_to_summarize}'",
"Writing Enhancer - Clarity Check": "Review the following text for clarity and conciseness. Identify areas that could be improved and suggest specific revisions. Text for review: '{text_for_review}'"
})
# Templates for Misc. Features
templates["Quick Fact Finder"] = "Provide a concise definition or key fact for the term: '{term}'."
templates["Synonym Antonym Finder"] = "For the word '{word}', provide a list of 3-5 synonyms and 3-5 antonyms."
templates["Simple Translator"] = "Translate the following text to {target_language}. Text: '{text_to_translate}'"
templates["Idea Generator"] = "Generate 3-5 creative ideas related to the theme or problem: '{theme_or_problem}'."
templates["Code Explainer"] = "Explain the following code snippet in simple terms, outlining its main purpose and functionality. Code: \n```\n{code_snippet}\n```"
# Templates for 20 New Misc. Features
templates["Email Subject Generator"] = "Generate 5 creative and effective email subject lines for an email with the following core message or topic: '{email_topic}'."
templates["Headline Analyzer"] = "Analyze the following headline and provide feedback on its effectiveness (clarity, engagement, SEO potential if applicable). Suggest 3 alternative headlines. Headline: '{headline_text}'."
templates["Secure Password Idea Generator"] = "Suggest 3 ideas for creating a secure password based on the following criteria (do not generate the password itself, just the method or pattern): Length at least {length} characters, must include {char_types_count} types of characters (uppercase, lowercase, numbers, symbols)."
templates["Meeting Agenda Creator"] = "Create a basic meeting agenda for a meeting about '{meeting_topic}'. Include sections for: Attendees (list: {attendees}), Objectives, Discussion Points (3-5), Action Items, and Next Steps."
templates["Pros and Cons Lister"] = "List the potential pros and cons for the following topic or decision: '{decision_topic}'."
templates["ELI5 Explainer"] = "Explain the following complex topic as if you were explaining it to a 5-year-old: '{complex_topic}'."
templates["Text Mood Analyzer"] = "Analyze the overall mood or tone of the following text. Identify the dominant emotion(s) conveyed. Text: '{text_for_mood_analysis}'."
templates["Keyword Extractor"] = "Extract the 5-7 most important keywords or key phrases from the following text: '{text_for_keywords}'."
templates["Hashtag Generator"] = "Generate 5-7 relevant and trending hashtags for a social media post about: '{post_topic_or_text}'."
templates["Story Idea Kicker"] = "Provide 3 unique story prompts or starting ideas based on the following genre or theme: '{story_genre_theme}'."
templates["Historical Event Summarizer"] = "Provide a brief (3-5 sentences) summary of the historical event: '{event_name}'."
templates["Book Plot Summarizer"] = "Provide a concise plot summary (avoiding major spoilers if possible) for the book titled: '{book_title}'. If you don't know it, say so."
templates["Recipe Idea Generator"] = "Suggest a recipe idea using the following main ingredients: '{ingredients_list}'. Briefly outline the cooking steps."
templates["Learning Path Suggester"] = "Suggest a high-level learning path (3-5 key stages or topics) for someone wanting to learn about: '{skill_or_topic_to_learn}'."
templates["Debate Topic Generator"] = "Generate 3 interesting and debatable topics suitable for a student debate."
templates["Short Poem Generator"] = "Write a short, 4-8 line poem about: '{poem_theme_keywords}'."
templates["Joke Teller"] = "Tell me a family-friendly joke. If you know one about {joke_topic}, tell that, otherwise a general one."
templates["Character Name Generator"] = "Suggest 5 unique character names suitable for a story in the {character_genre_theme} genre/setting."
templates["Random Quote Generator"] = "Provide an inspirational or thought-provoking quote. If possible, relate it to the theme of '{quote_theme}'."
templates["Fictional World Idea Generator"] = "Generate a core concept or unique feature for a fictional world in the {world_genre} genre."
# Keeping some useful misc templates from previous additions
templates["Code Comment Generator"] = "Generate helpful comments for the following code snippet. Explain what each major part does. Code:\n```\n{code_to_comment}\n```"
templates["Analogy Generator"] = "Create a simple analogy to explain the concept: '{concept_for_analogy}'. Make it easy to understand."
templates["Ethical Dilemma Generator"] = "Pose an interesting ethical dilemma related to the topic: '{dilemma_topic}'. Provide a brief scenario."
templates["SWOT Analysis Generator"] = "Generate a basic SWOT (Strengths, Weaknesses, Opportunities, Threats) analysis for the following idea or topic: '{swot_topic}'."
templates["Acronym Explainer"] = "Explain what the acronym '{acronym_to_explain}' stands for and briefly describe its meaning or context."
# Adding 20 NEW serious, student-focused templates to reach 35 total in Misc tab
templates["Essay Outline Generator"] = "Generate a structured outline for an essay on the topic: '{essay_topic}'. Include sections for Introduction, Body Paragraphs (suggesting 3-5 main points), and Conclusion."
templates["Study Plan Creator (Daily/Weekly)"] = "Create a simple {timeframe} study plan for the topic '{study_topic}'. Suggest key areas to focus on and allocate time slots." # timeframe: 'daily' or 'weekly'
templates["Concept Mapping (Text-based)"] = "Generate a text-based concept map structure for the topic: '{concept_map_topic}'. Start with the central concept and branch out to related sub-concepts and details using indentation and bullet points."
templates["Research Question Refiner"] = "Refine the following initial research question to make it more focused, specific, and researchable: '{initial_research_question}'."
templates["Abstract Generator"] = "Write a concise abstract (approx. 150-250 words) for a paper or study on the topic: '{abstract_topic}'. Include brief mention of purpose, methods (if applicable), key findings, and conclusion."
templates["Literature Review Outline Generator"] = "Generate a structured outline for a literature review on the topic: '{lit_review_topic}'. Include sections for Introduction, Thematic Analysis (suggesting key themes), Discussion, and Conclusion."
templates["Problem Solving Steps Generator"] = "Outline the general steps involved in solving a problem related to: '{problem_domain}'. Provide a structured approach."
templates["Critical Thinking Prompt Generator"] = "Generate 3-5 critical thinking questions or prompts related to the topic: '{critical_thinking_topic}'."
templates["Study Group Discussion Questions"] = "Generate 5-7 discussion questions suitable for a study group focusing on the topic: '{study_group_topic}'."
templates["Exam Question Predictor"] = "Based on the topic '{exam_topic}', suggest 3-5 potential exam questions (e.g., essay, short answer) that might be asked."
templates["Academic Terminology Explainer"] = "Explain the academic term '{academic_term}' in detail, providing its definition, context, and usage examples."
templates["Historical Context Generator"] = "Provide the key historical context surrounding the event or person: '{historical_subject}'. Briefly explain the relevant time period, major influences, and immediate aftermath."
templates["Scientific Process Outline"] = "Outline the typical steps of the scientific process as applied to studying: '{scientific_topic}'."
templates["Mathematical Concept Explainer"] = "Explain the mathematical concept '{math_concept}' in clear terms, including its definition, key properties, and a simple example."
templates["Grammar/Style Checker (Basic)"] = "Review the following text for basic grammar errors, awkward phrasing, and suggestions for improving clarity and conciseness. Provide specific suggestions for improvement. Text: '{text_to_check}'."
templates["Paraphrasing Tool (Academic)"] = "Paraphrase the following text in an academic style, ensuring the original meaning is retained but the wording is significantly different. Original text: '{text_to_paraphrase}'."
templates["Counter-Argument Generator"] = "For the argument '{main_argument}', generate 2-3 potential counter-arguments or opposing viewpoints."
templates["Hypothesis Generator"] = "Based on the topic or observation '{observation_or_topic}', suggest 1-2 testable hypotheses for a study or experiment."
templates["Data Interpretation Helper"] = "Given the following simple data description or observation: '{data_description}', provide a brief interpretation or suggest what it might imply."
templates["Learning Objective Generator"] = "Generate 3-5 clear and measurable learning objectives for a lesson or study session on the topic: '{learning_topic}'."
# Adding 10 NEW advanced, serious, student/professional-focused templates (41-50)
templates["Argumentative Essay Component Generator"] = "For an argumentative essay on the topic: '{essay_topic}', generate a strong {component_type} (e.g., Thesis Statement, Counter-Argument, Rebuttal, Supporting Point with evidence). Be specific and well-reasoned."
templates["Research Methodology Suggester"] = "For a research study in the field of '{field_of_study}' addressing the research question/problem: '{research_question}', suggest 2-3 appropriate research methodologies. Briefly explain the suitability and limitations of each."
templates["Data Analysis Plan Outline"] = "Outline a detailed data analysis plan for a study with the primary objective: '{research_objective}', expecting to work with {data_type} data (e.g., quantitative survey data, qualitative interview transcripts, mixed-methods). Include key steps from data preparation/cleaning, descriptive analysis, inferential analysis (if applicable), to interpretation and reporting."
templates["Grant Proposal Snippet Generator"] = "Draft a compelling and concise snippet for the '{target_section}' section (e.g., Problem Statement, Project Objectives, Expected Outcomes, Broader Impacts) of a grant proposal for a project focused on: '{project_idea}'. Aim for clarity, impact, and alignment with typical grant requirements."
templates["Peer Review Feedback Generator (Constructive)"] = "Provide constructive and actionable peer review feedback on the following academic text snippet, focusing specifically on '{focus_area}' (e.g., clarity of argument, methodological rigor, literature engagement, contribution to knowledge). Offer 3-4 specific suggestions for improvement. Text: '{text_for_review}'"
templates["Presentation Script Outline Generator"] = "Create a structured and engaging outline for a {length} (e.g., 15-minute, 30-minute, 1-hour) academic or professional presentation on the topic: '{presentation_topic}'. The target audience is '{target_audience}'. Include sections for Introduction (hook, agenda), Key Talking Points (with sub-points and suggested visuals/examples), and Conclusion (summary, call to action, Q&A)."
templates["Technical Document Explainer (Advanced)"] = "Explain the following complex technical document snippet in terms understandable for a '{explanation_level}' (e.g., non-technical manager, junior engineer in a different field, subject matter expert needing a refresher). Focus on its core technical meaning, operational implications, and potential challenges or benefits. Snippet: '{technical_snippet}'"
templates["Case Study Creator (from scenario)"] = "Based on the following detailed scenario or problem description, structure a comprehensive case study. Identify the core problem/challenge, relevant background and context, key stakeholders and their perspectives, critical decisions or events, and formulate 3-5 insightful discussion questions for analysis. Scenario: '{scenario_description}'"
templates["Syllabus Component Generator (Advanced)"] = "For a university-level course titled '{course_title}', draft a detailed and pedagogically sound '{component_type}' section of a syllabus (e.g., Detailed Weekly Schedule with Readings, Comprehensive Assessment Strategy with Rubric Criteria, Policy on Academic Integrity with Examples, Inclusive Learning Environment Statement). Ensure it is clear, comprehensive, and aligns with best practices in higher education."
templates["Ethical Review Considerations Lister (Research)"] = "For a research project proposal focused on '{research_proposal_idea}', identify and elaborate on 4-6 key ethical considerations that would need to be thoroughly addressed in an Institutional Review Board (IRB) or ethics committee application. For each consideration, explain why it's relevant and suggest how it might be mitigated or managed."
return templates
# Function to generate content with AI
def generate_ai_content(prompt, api_key, model_name, temperature, detail_level, style_params):
try:
genai.configure(api_key=api_key)
model = genai.GenerativeModel(model_name)
with st.spinner("🔮 AI is working its magic..."):
# Adjust max tokens based on detail level
max_tokens = {
"Brief": 2048,
"Standard": 4096,
"Comprehensive": 8192,
"Expert": 8192
}
# Apply style adjustments to prompt
style_prefix = f"Using {style_params['tone']} tone and {style_params['language_style']} language style, "
enhanced_prompt = style_prefix + prompt
generation_config = {
"temperature": temperature,
"top_p": 0.95,
"top_k": 40,
"max_output_tokens": max_tokens[detail_level]
}
response = model.generate_content(enhanced_prompt, generation_config=generation_config)
return response.text
except Exception as e:
return f"Error: {str(e)}"
# Function to save content to history
def save_to_history(tool_name, topic, output, favorite=False):
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
item = {"timestamp": timestamp, "tool": tool_name, "topic": topic, "output": output, "favorite": favorite}
st.session_state.history.insert(0, item)
if len(st.session_state.history) > 30:
st.session_state.history = st.session_state.history[:30]
if favorite:
st.session_state.favorites.insert(0, item)
if len(st.session_state.favorites) > 20:
st.session_state.favorites = st.session_state.favorites[:20]
# Function to export notes
def export_notes(content, format="txt"):
if format == "txt":
return content
elif format == "md":
# The content from Gemini is often already markdown-like.
return content
elif format == "csv":
lines = content.split('\n')
csv_output_lines = []
for line in lines:
# Remove common markdown list/block prefixes
cleaned_line = re.sub(r'^\s*[-*#>]+\s*', '', line).strip()
if cleaned_line: # Only process non-empty lines
# Escape double quotes
cleaned_line_csv = cleaned_line.replace('"', '""')
# Enclose in double quotes if it contains a comma, a double quote, or needs it
if ',' in cleaned_line_csv or '"' in cleaned_line_csv or ' ' in cleaned_line_csv or '\n' in cleaned_line_csv:
csv_output_lines.append(f'"{cleaned_line_csv}"')
else:
csv_output_lines.append(cleaned_line_csv)
return '\n'.join(csv_output_lines)
elif format == "html":
# Convert markdown content to HTML
html_body = markdown.markdown(content, extensions=['fenced_code', 'tables', 'extra'])
html_full = f"""
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Notes</title>
<style>
body {{ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; line-height: 1.6; padding: 20px; max-width: 800px; margin: auto; color: #333; }}
h1, h2, h3, h4, h5, h6 {{ color: #1a1a1a; margin-top: 1.5em; margin-bottom: 0.5em; }}
p {{ margin-bottom: 1em; }}
ul, ol {{ padding-left: 20px; margin-bottom: 1em; }}
li {{ margin-bottom: 0.25em; }}
code {{ background-color: #f0f0f0; padding: 0.2em 0.4em; margin: 0; font-size: 85%; border-radius: 3px; font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;}}
pre {{ background-color: #f0f0f0; padding: 10px; border-radius: 5px; overflow-x: auto; }}
pre code {{ background-color: transparent; padding: 0; margin: 0; font-size: inherit; border-radius: 0; }}
table {{ border-collapse: collapse; width: 100%; margin-bottom: 1em; border: 1px solid #ddd; }}
th, td {{ border: 1px solid #ddd; padding: 8px; text-align: left; }}
th {{ background-color: #f9f9f9; }}
blockquote {{ border-left: 4px solid #ccc; padding-left: 10px; color: #555; margin-left: 0; margin-right: 0; font-style: italic;}}
</style>
</head>
<body>
{html_body}
</body>
</html>
"""
return html_full
else:
return content
# New function for AI-powered summarization
def summarize_notes(content, api_key, model_name):
templates = load_prompt_templates()
prompt = templates["Auto-Summary"].format(content=content)
summary = generate_ai_content(
prompt,
api_key,
model_name,
temperature=0.3,
detail_level="Brief",
style_params={"tone": "Concise", "language_style": "Standard"}
)
return summary
# New function for adaptive refinement
def refine_notes(content, topic, refinement_type, api_key, model_name):
templates = load_prompt_templates()
prompt = templates["Refinement"].format(
content=content,
topic=topic,
refinement_type=refinement_type
)
refined = generate_ai_content(
prompt,
api_key,
model_name,
temperature=0.5,
detail_level="Standard",
style_params={"tone": "Academic", "language_style": "Standard"}
)
return refined
# Function for deep search
def deep_search_notes(query, content, api_key, model_name):
prompt = f"Given the following notes content, perform a deep semantic search for '{query}'. Return the most relevant sections that answer or relate to this query, along with brief explanations of why they're relevant:\n\n{content}"
results = generate_ai_content(
prompt,
api_key,
model_name,
temperature=0.3,
detail_level="Standard",
style_params={"tone": "Analytical", "language_style": "Concise"}
)
return results
# New function for generating quiz from notes
def generate_quiz(content, api_key, model_name):
templates = load_prompt_templates()
prompt = f"Create a 20 -question quiz with multiple-choice answers based on the following notes. " \
f"Include 4 options per question with only one correct answer. " \
f"Format with the question followed by options labeled A, B, C, D, and mark the correct answer at the end:\n\n{content}"
quiz = generate_ai_content(
prompt,
api_key,
model_name,
temperature=0.7,
detail_level="Standard",
style_params={"tone": "Enthusiastic", "language_style": "Conversational"}
)
return quiz
# New function to create spaced repetition cards
def create_spaced_repetition(content, topic, api_key, model_name):
templates = load_prompt_templates()
prompt = templates["Spaced Repetition Cards"].format(content=content)
cards_text = generate_ai_content(
prompt,
api_key,
model_name,
temperature=0.5,
detail_level="Standard",
style_params={"tone": "Academic", "language_style": "Concise"}
)
# Process raw text into cards
cards = []
raw_cards = cards_text.split("---")
for card_text in raw_cards:
if "Q:" in card_text and "A:" in card_text:
question_match = re.search(r"Q:(.*?)A:", card_text, re.DOTALL)
answer_match = re.search(r"A:(.*)", card_text, re.DOTALL)
if question_match and answer_match:
question = question_match.group(1).strip()
answer = answer_match.group(1).strip()
# Create card with spaced repetition metadata
card = {
"topic": topic,
"question": question,
"answer": answer,
"created": datetime.now(),
"next_review": datetime.now() + timedelta(days=1),
"ease_factor": 2.5,
"interval": 1,
"repetitions": 0
}
cards.append(card)
# else: # Optional: Log or notify if a card-like segment couldn't be parsed
# st.caption(f"Could not fully parse a card segment: {card_text[:50]}...")
# Add to session state
if cards: # Only append if cards were successfully parsed
for card_item in cards: # Use a different variable name to avoid conflict with 'card' from outer scope if any
st.session_state.spaced_repetition.append(card_item)
st.session_state.spaced_repetition.sort(key=lambda x: x['next_review']) # Keep them sorted
return len(cards)
# New function to process quiz answers and calculate score
def grade_quiz(quiz_text, user_answers):
# Extract correct answers from quiz text
correct_answers = []
questions = quiz_text.split("\n\n")
for q in questions:
if "Correct answer:" in q:
correct = re.search(r"Correct answer: ([A-D])", q).group(1)
correct_answers.append(correct)
# Calculate score
if len(correct_answers) != len(user_answers):
return 0
score = sum(1 for correct, user in zip(correct_answers, user_answers) if correct == user)
percentage = (score / len(correct_answers)) * 100
# Record score in history
st.session_state.quiz_scores.append({
"timestamp": datetime.now(),
"score": percentage,
"total_questions": len(correct_answers)
})
return percentage
# Main content area
# --- Helper function for Interactive Quiz ---
def parse_quiz_text(quiz_text):
questions = []
# Regex to find question, options, and correct answer
# This regex assumes a fairly consistent format like:
# 1. Question text?
# A. Option A
# B. Option B
# C. Option C
# D. Option D
# Correct answer: B
pattern = re.compile(
r"(\d+\.\s*.*?)\n" # Question (e.g., "1. What is...")
r"A\.\s*(.*?)\n" # Option A
r"B\.\s*(.*?)\n" # Option B
r"C\.\s*(.*?)\n" # Option C
r"D\s*[:.]\s*(.*?)\n" # Option D (allowing for slight variations like "D." or "D:")
r"Correct answer:\s*([A-D])", # Correct answer
re.DOTALL | re.IGNORECASE
)
matches = pattern.findall(quiz_text)
for match in matches:
questions.append({
"question": match[0].strip(),
"options": {"A": match[1].strip(), "B": match[2].strip(), "C": match[3].strip(), "D": match[4].strip()},
"correct": match[5].strip().upper()
})
return questions
templates = load_prompt_templates()
# --- Interactive Quiz Display Logic ---
if st.session_state.get('interactive_quiz_active', False) and st.session_state.parsed_quiz_questions:
st.header("📝 Interactive Quiz")
questions = st.session_state.parsed_quiz_questions
current_idx = st.session_state.current_interactive_question_idx
if current_idx < len(questions):
q = questions[current_idx]
st.subheader(f"Question {current_idx + 1}/{len(questions)}")
st.markdown(q["question"])
options_keys = list(q["options"].keys())
options_values = [f"{key}. {q['options'][key]}" for key in options_keys]
user_answer_key = f"quiz_q_{current_idx}"
# Use st.radio and store the selected *option text* for now, then map back to A, B, C, D
selected_option_text = st.radio("Your Answer:", options_values, key=user_answer_key, index=None)
if st.button("Next Question", key=f"next_q_{current_idx}"):
if selected_option_text:
# Extract the letter (A, B, C, D) from the selected_option_text
selected_letter = selected_option_text.split('.')[0].strip().upper()
st.session_state.user_quiz_answers[current_idx] = selected_letter
if selected_letter == q["correct"]:
st.session_state.quiz_score += 1
st.session_state.current_interactive_question_idx += 1
else:
st.warning("Please select an answer.")
st.rerun()
else:
st.subheader("🎉 Quiz Completed!")
score_percentage = (st.session_state.quiz_score / len(questions)) * 100 if questions else 0
st.metric("Your Score", f"{st.session_state.quiz_score}/{len(questions)} ({score_percentage:.2f}%)")
st.session_state.interactive_quiz_active = False # Reset for next time
# Optionally, show correct answers vs user answers here
if st.button("Back to Notes"):
st.rerun()
# NEW: Main tabs for core functionality and new features
# main_tabs = st.tabs(["📝 Note Generation", "🔬 Research Assistant", "🎯 Study Hub", "✍️ Writing Enhancer", "🧠 Spaced Repetition", "📊 Analytics & History", "🛠️ Misc. Features"])
tab_names = ["📝 Note Generation", "🔬 Research Assistant", "🎯 Study Hub", "✍️ Writing Enhancer", "🧠 Spaced Repetition", "📊 Analytics & History", "🛠️ Misc. Features"]
st.session_state.selected_main_tab = st.radio(
"Main Navigation:",
tab_names,
index=tab_names.index(st.session_state.selected_main_tab), # Set current selection
horizontal=True,
key="main_tab_selector_radio" # Changed key to avoid conflict if old one lingers
)
if st.session_state.selected_main_tab == "📝 Note Generation": # Note Generation (existing main layout)
col1_ng, col2_ng = st.columns([2, 1]) # Use different variable names to avoid conflict if any
# Topic and parameters input
with col1_ng:
st.header("Create New Notes")
topic_ng = st.text_area("Enter Topic", height=100, placeholder="Enter the topic you want to create notes for...", key="topic_ng_input")
with col2_ng:
st.header("Note Parameters")
note_type_ng = st.selectbox("Note Format", ai_tools, key="note_type_ng_select")
if note_type_ng == "Custom Template":
template_name_ng = st.text_input("Template Name", key="template_name_ng_input")
template_value_ng = st.session_state.custom_templates.get(template_name_ng, "")
custom_template_ng = st.text_area("Custom Prompt Template",
value=template_value_ng,
height=150,
placeholder="Create {detail_level} notes on {prompt}. Use {education_level} language...",
key="custom_template_ng_area")
if st.button("Save Template", key="save_template_ng_btn"):
st.session_state.custom_templates[template_name_ng] = custom_template_ng
st.success(f"Template '{template_name_ng}' saved!")
detail_level_ng = st.select_slider(
"Detail Level",
options=DETAIL_LEVEL_OPTIONS,
value=st.session_state.default_detail_level,
key="detail_level_ng_slider"
)
with st.expander("Advanced Parameters", expanded=False):
temperature_ng = st.slider("Creativity Level", min_value=0.1, max_value=1.0, value=0.7, step=0.1, key="temp_ng_slider")
education_level_ng = st.selectbox(
"Education Level",
["Elementary", "Middle School", "High School", "Undergraduate", "Graduate", "Professional"],
index=3, key="edu_level_ng_select"
)
tone_ng = st.selectbox("Tone", TONE_OPTIONS, index=TONE_OPTIONS.index(st.session_state.default_tone), key="tone_ng_select")
language_style_ng = st.selectbox("Language Style", LANGUAGE_STYLE_OPTIONS, index=LANGUAGE_STYLE_OPTIONS.index(st.session_state.default_language_style), key="lang_style_ng_select")
if topic_ng: # Check if topic is entered in this tab
default_knowledge_ng = st.session_state.user_knowledge_level.get(topic_ng, 3)
knowledge_level_ng = st.slider(
"Your Knowledge Level on This Topic",
min_value=1, max_value=5, value=default_knowledge_ng,
help="1=Beginner, 5=Expert", key="knowledge_ng_slider"
)
st.session_state.user_knowledge_level[topic_ng] = knowledge_level_ng
style_params_ng = {"tone": tone_ng, "language_style": language_style_ng}
if topic_ng: # Process only if topic is entered in this tab
if note_type_ng == "Custom Template" and 'custom_template_ng' in locals():
base_prompt_ng = custom_template_ng.format(prompt=topic_ng, detail_level=detail_level_ng, education_level=education_level_ng)
else:
if topic_ng in st.session_state.user_knowledge_level:
knowledge_level_val = st.session_state.user_knowledge_level[topic_ng]
base_prompt_ng = templates["Adaptive Content"].format(prompt=topic_ng, detail_level=detail_level_ng, knowledge_level=knowledge_level_val)
else:
base_prompt_ng = templates[note_type_ng].format(prompt=topic_ng)
final_prompt_ng = f"{base_prompt_ng}\n\nAdditional parameters:\n- Detail level: {detail_level_ng}\n- Education level: {education_level_ng}"
st.markdown("---")
if st.button("Generate Notes", key="generate_notes_ng_btn"):
if not st.session_state.api_key:
st.error("Please enter your Gemini API key in the sidebar")
elif not topic_ng:
st.warning("Please enter a topic to generate notes.")
else:
# Ensure style_params_ng is defined, provide default if not (e.g. if expander is closed)
if 'style_params_ng' not in locals():
style_params_ng = {"tone": st.session_state.default_tone, "language_style": st.session_state.default_language_style}
if 'temperature_ng' not in locals():
temperature_ng = 0.7 # Default if expander not opened
output_ng = generate_ai_content(final_prompt_ng, st.session_state.api_key, model_name, temperature_ng, detail_level_ng, style_params_ng)
save_to_history(note_type_ng, topic_ng, output_ng)
st.session_state.output = output_ng # Store for display in this tab
st.rerun() # Rerun to ensure output display section is updated
# Display of currently generated notes (moved inside main_tabs[0])
if 'output' in st.session_state and st.session_state.output and not st.session_state.interactive_quiz_active:
# Use the topic that generated the current output, if available from history or a temp session var
current_topic_display = st.session_state.history[0]['topic'] if st.session_state.history else "Generated Notes"
st.header(f"📄 Notes on: {current_topic_display}")
output_display_tabs = st.tabs(["View Notes", "Export Options"])
with output_display_tabs[0]: # View Notes for current output
st.markdown(st.session_state.output)
if st.button("⭐ Add to Favorites", key="fav_current_output"):
save_to_history(st.session_state.history[0]['tool'], current_topic_display, st.session_state.output, favorite=True)
st.success("Added to favorites!")
if st.button("➕ Create SR Cards from these Notes", key="sr_cards_current_output"):
if st.session_state.output and st.session_state.api_key:
with st.spinner("AI is creating spaced repetition flashcards..."):
num_created = create_spaced_repetition(
st.session_state.output, # The content of the current notes
current_topic_display, # The topic of the current notes
st.session_state.api_key,
model_name # AI model selected in the sidebar
)
if num_created > 0:
st.success(f"{num_created} flashcards added! You can now find them in the '🧠 Spaced Repetition' tab.")
else:
st.warning("No flashcards could be created or parsed from the notes. The AI might not have returned content in the expected Q:/A:/--- format.")
st.rerun() # To update stats in the SR tab
elif not st.session_state.api_key:
st.error("API key is required to generate SR cards.")
else:
st.warning("No notes available to create flashcards from.")
if st.button("🎧 Listen to Notes", key="tts_current_output"):
if st.session_state.output:
try:
with st.spinner("Synthesizing audio... 🔊"):
tts = gTTS(text=st.session_state.output, lang='en')
audio_fp = io.BytesIO()
tts.write_to_fp(audio_fp)
audio_fp.seek(0)
st.audio(audio_fp, format='audio/mp3')
except Exception as e:
st.error(f"Error generating audio: {e}")
else:
st.warning("No notes available to read.")
with output_display_tabs[1]: # Export Options for current output
st.subheader("💾 Download Notes")
export_options = ["Text (.txt)", "Markdown (.md)", "CSV (.csv)", "HTML (.html)"]
export_format_selected = st.selectbox("Select Export Format", export_options, key="export_select_current")
format_extension_map = {"Text (.txt)": "txt", "Markdown (.md)": "md", "CSV (.csv)": "csv", "HTML (.html)": "html"}
mime_type_map = {"txt": "text/plain", "md": "text/markdown", "csv": "text/csv", "html": "text/html"}
format_extension = format_extension_map.get(export_format_selected, "txt")
mime_type = mime_type_map.get(format_extension, "text/plain")
export_content = export_notes(st.session_state.output, format_extension)
st.download_button(
label=f"Download as .{format_extension}",
data=export_content,
file_name=f"notes_{current_topic_display.replace(' ', '_').lower()}_{datetime.now().strftime('%Y%m%d')}.{format_extension}",
mime=mime_type,
key="download_current_btn"
)
st.markdown("---")
st.subheader("📋 Copy to Clipboard")
st.caption("Use the copy icon in the top right of the code box below to copy the raw notes.")
st.code(st.session_state.output, language="markdown")
st.markdown("---")
st.subheader("📊 Note Statistics")
word_count = len(st.session_state.output.split())
char_count = len(st.session_state.output)
stat_col1, stat_col2 = st.columns(2)
stat_col1.metric(label="Word Count", value=word_count)
stat_col2.metric(label="Character Count", value=char_count)
if st.session_state.selected_main_tab == "🔬 Research Assistant":
st.header("🔬 Research Assistant")
st.markdown("Pose specific questions or sub-topics for a deeper dive. The AI will provide a focused response.")
research_query = st.text_area("Enter your research query or sub-topic:", height=100, key="research_query_input")
output_format_options = ["Detailed Report", "Bulleted Key Points", "Q&A Format", "Pros and Cons List"]
research_output_format = st.selectbox("Desired Output Format:", output_format_options, key="research_output_format_select")
if st.button("🔍 Conduct Research", key="conduct_research_btn"):
if not st.session_state.api_key:
st.error("Please enter your Gemini API key in the sidebar.")
elif not research_query:
st.warning("Please enter a research query.")
elif not research_output_format:
st.warning("Please select an output format.")
else:
with st.spinner("AI is conducting in-depth research..."):
# Use a specific prompt for research assistance
research_prompt = templates["Research Assistant Query"].format(
query=research_query,
output_format=research_output_format
)
# You might want to use different parameters for research, e.g., more comprehensive
research_output = generate_ai_content(
research_prompt,
st.session_state.api_key,
model_name, # Use the globally selected model
temperature=0.5, # Slightly more creative/exploratory for research
detail_level="Comprehensive", # Aim for more detail
style_params={"tone": "Academic", "language_style": "Elaborate"} # Suitable for research
)
st.session_state.research_assistant_output = research_output # Store the output
st.session_state.current_research_query = research_query # Save for potential history saving
st.success("Research complete!")
if 'research_assistant_output' in st.session_state and st.session_state.research_assistant_output:
st.markdown("---")
st.subheader("💡 Research Findings")
st.markdown(st.session_state.research_assistant_output)
res_col1, res_col2, res_col3 = st.columns(3)
with res_col1:
if st.button("💾 Save Research to History", key="save_research_hist_btn"):
if 'current_research_query' in st.session_state and st.session_state.current_research_query:
save_to_history(
tool_name="Research Assistant",
topic=st.session_state.current_research_query,
output=st.session_state.research_assistant_output
)
st.success(f"Research on '{st.session_state.current_research_query}' saved to history!")
else:
st.warning("No current research query to associate with this save.")
with res_col2:
if st.button("❓ Suggest Follow-up Questions", key="suggest_follow_up_btn"):
with st.spinner("AI is thinking of next steps..."):
follow_up_prompt = templates["Research Follow-up Questions"].format(research_findings=st.session_state.research_assistant_output)
follow_up_questions = generate_ai_content(follow_up_prompt, st.session_state.api_key, model_name, 0.7, "Brief", {"tone": "Inquisitive", "language_style": "Concise"})
st.session_state.follow_up_questions_output = follow_up_questions
with res_col3:
if st.button("Clear Research Findings", key="clear_research_btn"):
st.session_state.research_assistant_output = ""
st.session_state.follow_up_questions_output = "" # Clear follow-ups too
st.rerun()
if 'follow_up_questions_output' in st.session_state and st.session_state.follow_up_questions_output:
st.markdown("---")
st.subheader("🤔 Potential Follow-up Questions:")
st.markdown(st.session_state.follow_up_questions_output)
if st.session_state.selected_main_tab == "🎯 Study Hub":
st.header("🎯 Study Hub")
study_hub_tabs = st.tabs(["📚 Planner", "✍️ Citation Helper"])
with study_hub_tabs[0]: # Planner
st.subheader("My Study Tasks")