issamlaradji commited on
Commit
a4936fb
·
verified ·
1 Parent(s): b154229

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +285 -0
app.py ADDED
@@ -0,0 +1,285 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # suppress warnings
2
+ import warnings
3
+
4
+ warnings.filterwarnings("ignore")
5
+
6
+ # import libraries
7
+ import argparse
8
+ from together import Together
9
+ import textwrap
10
+ import os
11
+ from datetime import datetime
12
+ import gradio as gr
13
+
14
+ # Parse command line arguments
15
+ parser = argparse.ArgumentParser(description="AI Study Tool")
16
+ parser.add_argument(
17
+ "--together_api_key",
18
+ "-k",
19
+ default="9806a2601560024637df1e4acd804862faa67e08637db6598d920b64eebba43e",
20
+ help="Together AI API key",
21
+ )
22
+ args = parser.parse_args()
23
+
24
+ # Initialize client with API key
25
+ client = Together(api_key=args.together_api_key)
26
+
27
+ # Add the cats content as a constant string
28
+ CATS_CONTENT = """The cat (Felis catus), also referred to as the domestic cat or house cat, is a small domesticated carnivorous mammal. It is the only domesticated species of the family Felidae. Advances in archaeology and genetics have shown that the domestication of the cat occurred in the Near East around 7500 BC. It is commonly kept as a pet and working cat, but also ranges freely as a feral cat avoiding human contact. It is valued by humans for companionship and its ability to kill vermin. Its retractable claws are adapted to killing small prey species such as mice and rats. It has a strong, flexible body, quick reflexes, and sharp teeth, and its night vision and sense of smell are well developed. It is a social species, but a solitary hunter and a crepuscular predator.
29
+
30
+ Cat intelligence is evident in their ability to adapt, learn through observation, and solve problems. Research has shown they possess strong memories, exhibit neuroplasticity, and display cognitive skills comparable to those of a young child. Cat communication includes meowing, purring, trilling, hissing, growling, grunting, and body language. It can hear sounds too faint or too high in frequency for human ears, such as those made by small mammals. It secretes and perceives pheromones.
31
+
32
+ Female domestic cats can have kittens from spring to late autumn in temperate zones and throughout the year in equatorial regions, with litter sizes often ranging from two to five kittens. Domestic cats are bred and shown at cat fancy events as registered pedigreed cats. Population control includes spaying and neutering, but pet abandonment has exploded the global feral cat population, which has driven the extinction of bird, mammal, and reptile species.
33
+
34
+ Domestic cats are found across the globe, though their popularity as pets varies by region. Out of the estimated 600 million cats worldwide, 400 million reside in Asia, including 58 million pet cats in China. The United States leads in cat ownership with 73.8 million cats. In the United Kingdom, approximately 10.9 million domestic cats are kept as pets.
35
+
36
+ Etymology and naming
37
+ The origin of the English word cat, Old English catt, is thought to be the Late Latin word cattus, which was first used at the beginning of the 6th century.[4] The Late Latin word may be derived from an unidentified African language.[5] The Nubian word kaddîska (wildcat) and Nobiin kadīs are possible sources or cognates.[6]
38
+
39
+ The forms might also have derived from an ancient Germanic word that was absorbed into Latin and then into Greek, Syriac, and Arabic.[7] The word may be derived from Germanic and Northern European languages, and ultimately be borrowed from Uralic, cf. Northern Sámi gáđfi, female stoat, and Hungarian hölgy, lady, female stoat; from Proto-Uralic *käďwä, female (of a furred animal).[8]
40
+
41
+ The English puss, extended as pussy and pussycat, is attested from the 16th century and may have been introduced from Dutch poes or from Low German puuskatte, related to Swedish kattepus, or Norwegian pus, pusekatt. Similar forms exist in Lithuanian puižė and Irish puisín or puiscín. The etymology is unknown, but it may be an onomatopoeia from using a sound to attract a cat.[9][10]
42
+
43
+ A male cat is called a tom or tomcat[11] (or a gib,[12] if neutered). A female is called a queen.[13] Some sources write that queen refers solely to unspayed cats that are in an estrous cycle.[14] (or sometimes a molly,[15] if spayed). A juvenile cat is referred to as a kitten, a term interchangeable with the now-obsolete word catling in Early Modern English.[16] A group of cats can be referred to as a clowder, a glaring,[17] or a colony.[18]
44
+
45
+ Taxonomy
46
+ The scientific name Felis catus was proposed by Carl Linnaeus in 1758 for a domestic cat.[1][2] Felis catus domesticus was proposed by Johann Christian Polycarp Erxleben in 1777.[3] Felis daemon proposed by Konstantin Satunin in 1904 was a black cat from the Transcaucasus, later identified as a domestic cat.[19][20]
47
+
48
+ In 2003, the International Commission on Zoological Nomenclature ruled that the domestic cat is a distinct species, namely Felis catus.[21][22] In 2007, the modern domesticated subspecies F. silvestris catus sampled worldwide was considered to have probably descended from the African wildcat (F. lybica), following results of phylogenetic research.[23][24][a] In 2017, the IUCN Cat Classification Taskforce followed the recommendation of the ICZN in regarding the domestic cat as a distinct species, Felis catus.[25]"""
49
+
50
+
51
+ ## FUNCTION 1: This Allows Us to Prompt the AI MODEL
52
+ # -------------------------------------------------
53
+ def prompt_llm(prompt, with_linebreak=False):
54
+ # This function allows us to prompt an LLM via the Together API
55
+
56
+ # model
57
+ model = "meta-llama/Meta-Llama-3-8B-Instruct-Lite"
58
+
59
+ # Make the API call
60
+ response = client.chat.completions.create(
61
+ model=model,
62
+ messages=[{"role": "user", "content": prompt}],
63
+ )
64
+ output = response.choices[0].message.content
65
+
66
+ if with_linebreak:
67
+ # Wrap the output
68
+ wrapped_output = textwrap.fill(output, width=50)
69
+
70
+ return wrapped_output
71
+ else:
72
+ return output
73
+
74
+
75
+ ## FUNCTION 2: Load text file content
76
+ # -------------------------------------------------
77
+ def load_file(filepath):
78
+ """Load content from a text file"""
79
+ try:
80
+ with open(filepath, "r", encoding="utf-8") as file:
81
+ return file.read()
82
+ except FileNotFoundError:
83
+ print(f"Error: File {filepath} not found.")
84
+ return None
85
+ except Exception as e:
86
+ print(f"Error reading file: {e}")
87
+ return None
88
+
89
+
90
+ ## FUNCTION 3: Generate bite-sized concept summaries
91
+ # -------------------------------------------------
92
+ def summarize_concepts(text_content):
93
+ """Generate bite-sized 2-sentence concepts from text content"""
94
+ prompt = f"""
95
+ Please analyze the following text and break it down into bite-sized learning concepts.
96
+ For each concept, provide exactly 2 sentences that capture the key idea in a clear,
97
+ easy-to-understand way suitable for studying.
98
+
99
+ Format each concept as:
100
+ Concept X: [2 sentences explaining the concept]
101
+
102
+ Text to analyze:
103
+ {text_content}
104
+ """
105
+
106
+ return prompt_llm(prompt)
107
+
108
+
109
+ ## FUNCTION 4: Save results to timestamped file
110
+ # -------------------------------------------------
111
+ def save_results(content, output_dir="results"):
112
+ """Save content to a timestamped file in the results directory"""
113
+ # Create results directory if it doesn't exist
114
+ os.makedirs(output_dir, exist_ok=True)
115
+
116
+ # Generate timestamp
117
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
118
+ filename = f"{timestamp}.txt"
119
+ filepath = os.path.join(output_dir, filename)
120
+
121
+ # Save content
122
+ try:
123
+ with open(filepath, "w", encoding="utf-8") as file:
124
+ file.write(content)
125
+ print(f"Results saved to: {filepath}")
126
+ return filepath
127
+ except Exception as e:
128
+ print(f"Error saving file: {e}")
129
+ return None
130
+
131
+
132
+ ## FUNCTION 5: Create Gradio Interface
133
+ # -------------------------------------------------
134
+ def create_gradio_interface():
135
+ """Create a Gradio interface for the study tool"""
136
+
137
+ def process_file_and_generate_content():
138
+ """Process the cats content and generate study content"""
139
+ try:
140
+ # Use the hardcoded content instead of loading from file
141
+ content = CATS_CONTENT
142
+
143
+ # Generate summaries
144
+ summaries = summarize_concepts(content)
145
+
146
+ # Parse summaries into individual concepts - improved parsing for **Concept X:** format
147
+ concepts = []
148
+
149
+ # Split by **Concept and filter out empty parts
150
+ parts = summaries.split("**Concept")
151
+
152
+ for i, part in enumerate(parts):
153
+ if i == 0: # Skip the intro text before first concept
154
+ continue
155
+
156
+ # Clean up the part and add back "Concept" prefix
157
+ concept_text = "Concept" + part.strip()
158
+
159
+ # Remove the closing ** if present
160
+ if concept_text.endswith("**"):
161
+ concept_text = concept_text[:-2].strip()
162
+
163
+ # Remove any ** formatting within the text
164
+ concept_text = concept_text.replace("**", "")
165
+
166
+ if concept_text:
167
+ concepts.append(concept_text)
168
+
169
+ # Save results
170
+ save_results(f"BITE-SIZED CONCEPT SUMMARIES:\n{summaries}")
171
+
172
+ # Return first concept for immediate display
173
+ first_concept = concepts[0] if concepts else "No concepts generated."
174
+
175
+ return (
176
+ f"Content processed successfully! Found {len(concepts)} concepts. Navigate through them below.",
177
+ summaries,
178
+ concepts,
179
+ 0, # current concept index
180
+ first_concept, # display first concept immediately
181
+ )
182
+
183
+ except Exception as e:
184
+ return f"Error processing content: {str(e)}", "", [], 0, "Error occurred."
185
+
186
+ def navigate_concept(concepts, current_idx, direction):
187
+ """Navigate through concepts (previous/next)"""
188
+ if not concepts:
189
+ return "No concepts available.", 0
190
+
191
+ if direction == "next":
192
+ new_idx = min(current_idx + 1, len(concepts) - 1)
193
+ else: # previous
194
+ new_idx = max(current_idx - 1, 0)
195
+
196
+ concept_text = (
197
+ concepts[new_idx] if new_idx < len(concepts) else "No concept available."
198
+ )
199
+ return concept_text, new_idx
200
+
201
+ # Create Gradio interface
202
+ with gr.Blocks(title="AI Study Tool", theme=gr.themes.Soft()) as interface:
203
+ gr.Markdown("# 📚 AI Study Tool")
204
+ gr.Markdown("Generate bite-sized concepts from cat information for studying!")
205
+
206
+ # Process button section
207
+ with gr.Row():
208
+ process_btn = gr.Button("Process Cat Content", variant="primary")
209
+
210
+ # Status and results
211
+ status_output = gr.Textbox(label="Status", interactive=False)
212
+
213
+ # Hidden state variables
214
+ full_summaries = gr.State("")
215
+ concepts_list = gr.State([])
216
+ current_concept_idx = gr.State(0)
217
+
218
+ # Concept navigation section
219
+ with gr.Row():
220
+ gr.Markdown("## 🧠 Study Concepts")
221
+
222
+ with gr.Row():
223
+ prev_btn = gr.Button("← Previous Concept")
224
+ concept_counter = gr.Textbox(
225
+ label="Concept Position", interactive=False, value="0 / 0"
226
+ )
227
+ next_btn = gr.Button("Next Concept →")
228
+
229
+ concept_display = gr.Textbox(
230
+ label="Current Concept",
231
+ lines=4,
232
+ interactive=False,
233
+ placeholder="Process a file to see concepts here...",
234
+ )
235
+
236
+ # Event handlers
237
+ process_btn.click(
238
+ fn=process_file_and_generate_content,
239
+ inputs=[],
240
+ outputs=[
241
+ status_output,
242
+ full_summaries,
243
+ concepts_list,
244
+ current_concept_idx,
245
+ concept_display,
246
+ ],
247
+ ).then(
248
+ fn=lambda concepts, idx: (
249
+ f"{idx + 1} / {len(concepts)}" if concepts else "0 / 0"
250
+ ),
251
+ inputs=[concepts_list, current_concept_idx],
252
+ outputs=[concept_counter],
253
+ )
254
+
255
+ prev_btn.click(
256
+ fn=lambda concepts, idx: navigate_concept(concepts, idx, "previous"),
257
+ inputs=[concepts_list, current_concept_idx],
258
+ outputs=[concept_display, current_concept_idx],
259
+ ).then(
260
+ fn=lambda concepts, idx: (
261
+ f"{idx + 1} / {len(concepts)}" if concepts else "0 / 0"
262
+ ),
263
+ inputs=[concepts_list, current_concept_idx],
264
+ outputs=[concept_counter],
265
+ )
266
+
267
+ next_btn.click(
268
+ fn=lambda concepts, idx: navigate_concept(concepts, idx, "next"),
269
+ inputs=[concepts_list, current_concept_idx],
270
+ outputs=[concept_display, current_concept_idx],
271
+ ).then(
272
+ fn=lambda concepts, idx: (
273
+ f"{idx + 1} / {len(concepts)}" if concepts else "0 / 0"
274
+ ),
275
+ inputs=[concepts_list, current_concept_idx],
276
+ outputs=[concept_counter],
277
+ )
278
+
279
+ return interface
280
+
281
+
282
+ if __name__ == "__main__":
283
+ # Launch Gradio interface
284
+ interface = create_gradio_interface()
285
+ interface.launch()