awacke1 commited on
Commit
c1ca117
ยท
verified ยท
1 Parent(s): bd5fd15

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +179 -1439
app.py CHANGED
@@ -1,1476 +1,216 @@
1
- # Import libraries and references:
2
- import anthropic
3
- import base64
4
- import glob
5
- import hashlib
6
- import json
7
- import os
8
- import pandas as pd
9
- import pytz
10
  import random
11
- import re
12
- import shutil
13
- import streamlit as st
14
  import time
15
- import traceback
16
- import uuid
17
- import zipfile
18
- from PIL import Image
19
- from azure.cosmos import CosmosClient, exceptions
20
  from datetime import datetime
21
- from git import Repo
22
- from github import Github
 
 
 
23
  from gradio_client import Client
24
- from urllib.parse import quote
25
-
26
-
27
- # ๐ŸŽญ App Configuration - Because every app needs a good costume!
28
- Site_Name = '๐Ÿ™GitCosmos๐ŸŒŒ - AI Azure Cosmos DB and Github Agent'
29
- title = "๐Ÿ™GitCosmos๐ŸŒŒ - AI Azure Cosmos DB and Github Agent"
30
- helpURL = 'https://huggingface.co/awacke1'
31
- bugURL = 'https://huggingface.co/spaces/awacke1/AzureCosmosDBUI/'
32
- icons = '๐Ÿ™๐ŸŒŒ๐Ÿ’ซ'
33
- st.set_page_config(
34
- page_title=title,
35
- page_icon=icons,
36
- layout="wide",
37
- initial_sidebar_state="auto",
38
- menu_items={
39
- 'Get Help': helpURL,
40
- 'Report a bug': bugURL,
41
- 'About': title
42
- }
43
- )
44
-
45
-
46
- # ๐ŸŒŒ Cosmos DB configuration - Where data goes to party!
47
- ENDPOINT = "https://acae-afd.documents.azure.com:443/"
48
- DATABASE_NAME = os.environ.get("COSMOS_DATABASE_NAME")
49
- CONTAINER_NAME = os.environ.get("COSMOS_CONTAINER_NAME")
50
- Key = os.environ.get("Key")
51
-
52
- # ๐ŸŒ Your local app URL - Home sweet home
53
- LOCAL_APP_URL = "https://huggingface.co/spaces/awacke1/AzureCosmosDBUI"
54
- CosmosDBUrl = 'https://portal.azure.com/#@AaronCWackergmail.onmicrosoft.com/resource/subscriptions/003fba60-5b3f-48f4-ab36-3ed11bc40816/resourceGroups/datasets/providers/Microsoft.DocumentDB/databaseAccounts/acae-afd/dataExplorer'
55
-
56
- # ๐Ÿค– Anthropic configuration - Teaching machines to be more human (and funnier)
57
- anthropicclient = anthropic.Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))
58
-
59
- # ๐Ÿง  Initialize session state - Because even apps need a good memory
60
- if "chat_history" not in st.session_state:
61
- st.session_state.chat_history = []
62
-
63
-
64
-
65
- # ๐Ÿ› ๏ธ Helper Functions - The unsung heroes of our code
66
-
67
- # ๐Ÿ“Ž Get a file download link - Making file sharing as easy as stealing candy from a baby
68
- def get_download_link(file_path):
69
- with open(file_path, "rb") as file:
70
- contents = file.read()
71
- b64 = base64.b64encode(contents).decode()
72
- file_name = os.path.basename(file_path)
73
- return f'<a href="data:file/txt;base64,{b64}" download="{file_name}">Download {file_name}๐Ÿ“‚</a>'
74
-
75
- # ๐ŸŽฒ Generate a unique ID - Because being unique is important (just ask your mother)
76
- def generate_unique_id():
77
- timestamp = datetime.utcnow().strftime('%Y%m%d%H%M%S%f')
78
- unique_uuid = str(uuid.uuid4())
79
- returnValue = f"{timestamp}-{unique_uuid}"
80
- st.write('New Unique ID:' + returnValue)
81
- return
82
-
83
- # ๐Ÿ“ Generate a filename - Naming files like a pro (or a very confused librarian)
84
- def generate_filename(prompt, file_type):
85
- central = pytz.timezone('US/Central')
86
- safe_date_time = datetime.now(central).strftime("%m%d_%H%M")
87
- safe_prompt = re.sub(r'\W+', '', prompt)[:90]
88
- return f"{safe_date_time}{safe_prompt}.{file_type}"
89
-
90
- # ๐Ÿ’พ Create and save a file - Because data hoarding is a legitimate hobby
91
- def create_file(filename, prompt, response, should_save=True):
92
- if not should_save:
93
- return
94
- with open(filename, 'w', encoding='utf-8') as file:
95
- file.write(prompt + "\n\n" + response)
96
-
97
- # ๐Ÿ“– Load file content - Bringing words back from the digital grave
98
- def load_file(file_name):
99
- with open(file_name, "r", encoding='utf-8') as file:
100
- content = file.read()
101
- return content
102
-
103
- # ๐Ÿ” Display glossary entity - Making search fun again (as if it ever was)
104
- def display_glossary_entity(k):
105
- search_urls = {
106
- "๐Ÿš€๐ŸŒŒArXiv": lambda k: f"/?q={quote(k)}",
107
- "๐Ÿ“–": lambda k: f"https://en.wikipedia.org/wiki/{quote(k)}",
108
- "๐Ÿ”": lambda k: f"https://www.google.com/search?q={quote(k)}",
109
- "๐ŸŽฅ": lambda k: f"https://www.youtube.com/results?search_query={quote(k)}",
110
- }
111
- links_md = ' '.join([f"<a href='{url(k)}' target='_blank'>{emoji}</a>" for emoji, url in search_urls.items()])
112
- st.markdown(f"{k} {links_md}", unsafe_allow_html=True)
113
-
114
- # ๐Ÿ—œ๏ธ Create zip of files - Squeezing files together like sardines in a can
115
- def create_zip_of_files(files):
116
- zip_name = "all_files.zip"
117
- with zipfile.ZipFile(zip_name, 'w') as zipf:
118
- for file in files:
119
- zipf.write(file)
120
- return zip_name
121
-
122
- # ๐ŸŽฌ Get video HTML - Making videos play nice (or at least trying to)
123
- def get_video_html(video_path, width="100%"):
124
- video_url = f"data:video/mp4;base64,{base64.b64encode(open(video_path, 'rb').read()).decode()}"
125
- return f'''
126
- <video width="{width}" controls autoplay loop>
127
- <source src="{video_url}" type="video/mp4">
128
- Your browser does not support the video tag.
129
- </video>
130
- '''
131
-
132
- # ๐ŸŽต Get audio HTML - Let the music play (and hope it's not Baby Shark)
133
- def get_audio_html(audio_path, width="100%"):
134
- audio_url = f"data:audio/mpeg;base64,{base64.b64encode(open(audio_path, 'rb').read()).decode()}"
135
- return f'''
136
- <audio controls style="width:{width}">
137
- <source src="{audio_url}" type="audio/mpeg">
138
- Your browser does not support the audio element.
139
- </audio>
140
- '''
141
-
142
- # ๐ŸŒŒ Cosmos DB functions - Where data goes to live its best life
143
-
144
- # ๐Ÿ“š Get databases - Collecting databases like Pokemon cards
145
- def get_databases(client):
146
- return [db['id'] for db in client.list_databases()]
147
-
148
- # ๐Ÿ“ฆ Get containers - Finding where all the good stuff is hidden
149
- def get_containers(database):
150
- return [container['id'] for container in database.list_containers()]
151
-
152
- # ๐Ÿ“„ Get documents - Retrieving the sacred texts (or just some JSON)
153
- def get_documents(container, limit=None):
154
- query = "SELECT * FROM c ORDER BY c._ts DESC"
155
- items = list(container.query_items(query=query, enable_cross_partition_query=True, max_item_count=limit))
156
- return items
157
-
158
- # ๐Ÿ“ฅ Insert record - Adding new data (and crossing fingers it doesn't break anything)
159
- def insert_record(container, record):
160
- try:
161
- container.create_item(body=record)
162
- return True, "Record inserted successfully! ๐ŸŽ‰"
163
- except exceptions.CosmosHttpResponseError as e:
164
- return False, f"HTTP error occurred: {str(e)} ๐Ÿšจ"
165
- except Exception as e:
166
- return False, f"An unexpected error occurred: {str(e)} ๐Ÿ˜ฑ"
167
-
168
- # ๐Ÿ”„ Update record - Giving data a makeover
169
- def update_record(container, updated_record):
170
- try:
171
- container.upsert_item(body=updated_record)
172
- return True, f"Record with id {updated_record['id']} successfully updated. ๐Ÿ› ๏ธ"
173
- except exceptions.CosmosHttpResponseError as e:
174
- return False, f"HTTP error occurred: {str(e)} ๐Ÿšจ"
175
- except Exception as e:
176
- return False, f"An unexpected error occurred: {traceback.format_exc()} ๐Ÿ˜ฑ"
177
-
178
- # ๐Ÿ—‘๏ธ Delete record - Saying goodbye to data (it's not you, it's me)
179
- def delete_record(container, record):
180
- try:
181
- container.delete_item(item=record['id'], partition_key=record['id'])
182
- return True, f"Record with id {record['id']} successfully deleted. ๐Ÿ—‘๏ธ"
183
- except exceptions.CosmosHttpResponseError as e:
184
- return False, f"HTTP error occurred: {str(e)} ๐Ÿšจ"
185
- except Exception as e:
186
- return False, f"An unexpected error occurred: {traceback.format_exc()} ๐Ÿ˜ฑ"
187
-
188
-
189
- # ๐Ÿ’พ Save to Cosmos DB - Preserving data for future generations (or just until the next update)
190
- def save_to_cosmos_db(container, query, response1, response2):
191
- try:
192
- if container:
193
- # Generate a unique ID that includes a timestamp
194
- timestamp = datetime.utcnow().strftime('%Y%m%d%H%M%S%f')
195
- unique_uuid = str(uuid.uuid4())
196
- new_id = f"{timestamp}-{unique_uuid}"
197
-
198
- # Create new document with proper name field
199
- record = {
200
- "id": new_id,
201
- "name": new_id, # Set name equal to ID to avoid null name error
202
- "query": query,
203
- "response1": response1,
204
- "response2": response2,
205
- "timestamp": datetime.utcnow().isoformat(),
206
- "type": "ai_response", # Add document type for better organization
207
- "version": "1.0"
208
- }
209
-
210
- try:
211
- # Create the new document
212
- container.create_item(body=record)
213
- st.success(f"Record saved successfully with ID: {record['id']}")
214
- # Refresh the documents display
215
- st.session_state.documents = get_documents(container)
216
- except exceptions.CosmosHttpResponseError as e:
217
- st.error(f"Error saving record to Cosmos DB: {e}")
218
- else:
219
- st.error("Cosmos DB container is not initialized.")
220
- except Exception as e:
221
- st.error(f"An unexpected error occurred: {str(e)}")
222
-
223
-
224
-
225
-
226
-
227
-
228
 
 
229
 
230
- def save_to_cosmos_db_old(container, query, response1, response2):
 
231
  try:
232
- if container:
233
- record = {
234
- "id": generate_unique_id(),
235
- "query": query,
236
- "response1": response1,
237
- "response2": response2,
238
- "timestamp": datetime.utcnow().isoformat()
239
- }
240
- try:
241
- container.create_item(body=record)
242
- st.success(f"Record saved successfully with ID: {record['id']}")
243
- # Refresh the documents display
244
- st.session_state.documents = get_documents(container)
245
- except exceptions.CosmosHttpResponseError as e:
246
- st.error(f"Error saving record to Cosmos DB: {e}")
247
- else:
248
- st.error("Cosmos DB container is not initialized.")
249
  except Exception as e:
250
- st.error(f"An unexpected error occurred: {str(e)}")
251
-
252
-
253
-
254
- # ๐Ÿ™ GitHub functions - Where code goes to socialize
255
-
256
- # ๐Ÿ“ฅ Download GitHub repo - Cloning repos like it's going out of style
257
- def download_github_repo(url, local_path):
258
- if os.path.exists(local_path):
259
- shutil.rmtree(local_path)
260
- Repo.clone_from(url, local_path)
261
-
262
- # ๐Ÿ—œ๏ธ Create zip file - Squeezing files tighter than your budget
263
- def create_zip_file(source_dir, output_filename):
264
- shutil.make_archive(output_filename, 'zip', source_dir)
265
-
266
- # ๐Ÿ—๏ธ Create repo - Building digital homes for lonely code
267
- def create_repo(g, repo_name):
268
- user = g.get_user()
269
- return user.create_repo(repo_name)
270
-
271
- # ๐Ÿš€ Push to GitHub - Sending code to the cloud (hopefully not the rainy kind)
272
- def push_to_github(local_path, repo, github_token):
273
- repo_url = f"https://{github_token}@github.com/{repo.full_name}.git"
274
- local_repo = Repo(local_path)
275
- if 'origin' in [remote.name for remote in local_repo.remotes]:
276
- origin = local_repo.remote('origin')
277
- origin.set_url(repo_url)
278
- else:
279
- origin = local_repo.create_remote('origin', repo_url)
280
- if not local_repo.heads:
281
- local_repo.git.checkout('-b', 'main')
282
- current_branch = 'main'
283
- else:
284
- current_branch = local_repo.active_branch.name
285
- local_repo.git.add(A=True)
286
- if local_repo.is_dirty():
287
- local_repo.git.commit('-m', 'Initial commit')
288
- origin.push(refspec=f'{current_branch}:{current_branch}')
289
-
290
-
291
- def save_or_clone_to_cosmos_db(container, document=None, clone_id=None):
292
- def generate_complex_unique_id():
293
- timestamp = datetime.utcnow().strftime('%Y%m%d%H%M%S%f')
294
- random_component = ''.join(random.choices('abcdefghijklmnopqrstuvwxyz0123456789', k=8))
295
- return f"{timestamp}-{random_component}-{str(uuid.uuid4())}"
296
- max_retries = 10
297
- base_delay = 0.1
298
- for attempt in range(max_retries):
299
- try:
300
- new_id = generate_complex_unique_id()
301
- if clone_id:
302
- try:
303
- existing_doc = container.read_item(item=clone_id, partition_key=clone_id)
304
- new_doc = {
305
- 'id': new_id,
306
- 'originalText': existing_doc.get('originalText', ''),
307
- 'qtPrompts': existing_doc.get('qtPrompts', []),
308
- 'cloned_from': clone_id,
309
- 'cloned_at': datetime.utcnow().isoformat()
310
- }
311
- except exceptions.CosmosResourceNotFoundError:
312
- return False, f"Document with ID {clone_id} not found for cloning."
313
- else:
314
- if document is None:
315
- return False, "No document provided for saving"
316
- document['id'] = new_id
317
- document['created_at'] = datetime.utcnow().isoformat()
318
- new_doc = document
319
- response = container.create_item(body=new_doc)
320
- return True, f"{'Cloned' if clone_id else 'New'} document saved successfully with ID: {response['id']}"
321
- except exceptions.CosmosHttpResponseError as e:
322
- if e.status_code == 409:
323
- delay = base_delay * (2 ** attempt) + random.uniform(0, 0.1)
324
- time.sleep(delay)
325
- continue
326
- return False, f"Error saving to Cosmos DB: {str(e)}"
327
- except Exception as e:
328
- return False, f"An unexpected error occurred: {str(e)}"
329
- return False, "Failed to save document after maximum retries."
330
 
331
-
332
- # ๐Ÿ“ฆ Archive current container - Packing up data like you're moving to a new digital house
333
- def archive_current_container(database_name, container_name, client):
334
- try:
335
- base_dir = "./cosmos_archive_current_container"
336
- if os.path.exists(base_dir):
337
- shutil.rmtree(base_dir)
338
- os.makedirs(base_dir)
339
- db_client = client.get_database_client(database_name)
340
- container_client = db_client.get_container_client(container_name)
341
- items = list(container_client.read_all_items())
342
- container_dir = os.path.join(base_dir, container_name)
343
- os.makedirs(container_dir)
344
- for item in items:
345
- item_id = item.get('id', f"unknown_{datetime.now().strftime('%Y%m%d%H%M%S')}")
346
- with open(os.path.join(container_dir, f"{item_id}.json"), 'w') as f:
347
- json.dump(item, f, indent=2)
348
- archive_name = f"{container_name}_archive_{datetime.now().strftime('%Y%m%d%H%M%S')}"
349
- shutil.make_archive(archive_name, 'zip', base_dir)
350
- return get_download_link(f"{archive_name}.zip")
351
- except Exception as e:
352
- return f"An error occurred while archiving data: {str(e)} ๐Ÿ˜ข"
353
 
 
354
  def gen_AI_IO_filename(display_query, output):
355
- # Get current time in Central Time Zone with milliseconds
356
  now_central = datetime.now(pytz.timezone("America/Chicago"))
357
  timestamp = now_central.strftime("%Y-%m-%d-%I-%M-%S-%f-%p")
358
-
359
- # Limit components to prevent excessive filename length
360
- display_query = display_query[:50] # Truncate display_query to 50 chars
361
- output_snippet = re.sub(r'[^A-Za-z0-9]+', '_', output[:100]) # Truncate output_snippet to 100 chars
362
-
363
  filename = f"{timestamp} - {display_query} - {output_snippet}.md"
364
  return filename
365
-
366
- # ๐Ÿ” Search glossary - Finding needles in digital haystacks
367
- def search_glossary(query):
368
- st.markdown(f"### ๐Ÿ” SearchGlossary for: {query}")
369
- model_options = ['mistralai/Mixtral-8x7B-Instruct-v0.1', 'mistralai/Mistral-7B-Instruct-v0.2']
370
- model_choice = st.selectbox('๐Ÿง  Select LLM Model', options=model_options, index=1, key=f"model_choice_{id(query)}")
371
- database_options = ['Semantic Search', 'Arxiv Search - Latest - (EXPERIMENTAL)']
372
- database_choice = st.selectbox('๐Ÿ“š Select Database', options=database_options, index=0, key=f"database_choice_{id(query)}")
373
-
374
- # ๐Ÿ•ต๏ธโ€โ™‚๏ธ Searching the glossary for: query
375
- all_results = ""
376
- # Limit the query display to 80 characters
377
- display_query = query[:80] + "..." if len(query) > 80 else query
378
- st.markdown(f"๐Ÿ•ต๏ธโ€โ™‚๏ธ Running ArXiV AI Analysis with Query: {display_query} - ML model: {model_choice} and Option: {database_options}")
379
-
380
- # ๐Ÿ” ArXiV RAG researcher expert ~-<>-~ Paper Summary & Ask LLM
381
- client = Client("awacke1/Arxiv-Paper-Search-And-QA-RAG-Pattern")
382
- # ๐Ÿ” ArXiv RAG researcher expert ~-<>-~ Paper Summary & Ask LLM - api_name: /ask_llm
383
- result = client.predict(
384
- prompt=query,
385
- llm_model_picked="mistralai/Mixtral-8x7B-Instruct-v0.1",
386
- stream_outputs=True,
387
- api_name="/ask_llm"
388
- )
389
- st.markdown("# Mixtral-8x7B-Instruct-v0.1")
390
- st.markdown(result)
391
- #st.code(result, language="python", line_numbers=True)
392
-
393
-
394
- # ๐Ÿ” ArXiv RAG researcher expert ~-<>-~ Paper Summary & Ask LLM - api_name: /ask_llm
395
- result2 = client.predict(
396
- prompt=query,
397
- llm_model_picked="mistralai/Mistral-7B-Instruct-v0.2",
398
- stream_outputs=True,
399
- api_name="/ask_llm"
400
- )
401
- st.markdown("# Mistral-7B-Instruct-v0.2")
402
- st.markdown(result2)
403
- #st.code(result2, language="python", line_numbers=True)
404
-
405
- # ๐Ÿ” ArXiv RAG researcher expert ~-<>-~ Paper Summary & Ask LLM - api_name: /update_with_rag_md
406
- response2 = client.predict(
407
- message=query, # str in 'parameter_13' Textbox component
408
- llm_results_use=10,
409
- database_choice="Semantic Search",
410
- llm_model_picked="mistralai/Mistral-7B-Instruct-v0.2",
411
- api_name="/update_with_rag_md"
412
- )
413
- st.markdown("# Mistral-7B-Instruct-v0.2 update_with_rag_md 0")
414
- st.markdown(response2[0])
415
- #st.code(response2[0], language="python", line_numbers=True, wrap_lines=True)
416
-
417
- st.markdown("# Mistral-7B-Instruct-v0.2 update_with_rag_md 1")
418
- st.markdown(response2[1])
419
- #st.code(response2[1], language="python", line_numbers=True, wrap_lines=True)
420
-
421
-
422
- # โœ… Persist AI Results to Markdown Files
423
- filename = gen_AI_IO_filename(display_query, result)
424
- create_file(filename, query, result)
425
- st.markdown(f"โœ… File saved as: `{filename}`")
426
-
427
- filename = gen_AI_IO_filename(display_query, result2)
428
- create_file(filename, query, result2)
429
- st.markdown(f"โœ… File saved as: `{filename}`")
430
-
431
- filename = gen_AI_IO_filename(display_query, response2[0])
432
- create_file(filename, query, response2[0])
433
- st.markdown(f"โœ… File saved as: `{filename}`")
434
-
435
- filename = gen_AI_IO_filename(display_query, response2[1])
436
- create_file(filename, query, response2[1])
437
- st.markdown(f"โœ… File saved as: `{filename}`")
438
 
439
- return result, result2, response2
440
-
441
-
442
- # ๐Ÿ“ Generate a safe filename from the first few lines of content
443
- def generate_filename_from_content(content, file_type="md"):
444
- # Extract the first few lines or sentences
445
- first_sentence = content.split('\n', 1)[0][:90] # Limit the length to 90 characters
446
- # Remove special characters to make it a valid filename
447
- safe_name = re.sub(r'[^\w\s-]', '', first_sentence)
448
- # Limit length to be compatible with Windows and Linux
449
- safe_name = safe_name[:50].strip() # Adjust length limit
450
- return f"{safe_name}.{file_type}"
451
-
452
-
453
- # ๐Ÿ’พ Create and save a file
454
- def create_file_from_content(content, should_save=True):
455
  if not should_save:
456
  return
457
- filename = generate_filename_from_content(content)
458
  with open(filename, 'w', encoding='utf-8') as file:
459
- file.write(content)
460
- return filename
461
-
462
-
463
- # ๐Ÿ“‚ Display list of saved .md files in the sidebar
464
- def display_saved_files_in_sidebar():
465
- all_files = glob.glob("*.md")
466
- all_files.sort(reverse=True)
467
- all_files = [file for file in all_files if not file.lower().startswith('readme')] # Exclude README.md
468
- st.sidebar.markdown("## ๐Ÿ“ Saved Markdown Files")
469
- for file in all_files:
470
- col1, col2, col3 = st.sidebar.columns([6, 2, 1])
471
- with col1:
472
- st.markdown(f"๐Ÿ“„ {file}")
473
- with col2:
474
- st.sidebar.download_button(
475
- label="โฌ‡๏ธ Download",
476
- data=open(file, 'rb').read(),
477
- file_name=file
478
- )
479
- with col3:
480
- if st.sidebar.button("๐Ÿ—‘", key=f"delete_{file}"):
481
- os.remove(file)
482
- st.rerun()
483
-
484
- def clone_record(container, clone_id):
485
- try:
486
- existing_doc = container.read_item(item=clone_id, partition_key=clone_id)
487
- new_doc = existing_doc.copy()
488
- new_doc['id'] = generate_unique_id() # Generate new unique ID with timestamp
489
- new_doc['name'] = new_doc['id'] # Generate new unique ID with timestamp
490
- new_doc['createdAt'] = datetime.utcnow().isoformat() # Update the creation time
491
- new_doc['_rid'] = None # Reset _rid or any system-managed fields
492
- new_doc['_self'] = None
493
- new_doc['_etag'] = None
494
- new_doc['_attachments'] = None
495
- new_doc['_ts'] = None # Reset timestamp to be updated by Cosmos DB automatically
496
- # Insert the cloned document
497
- response = container.create_item(body=new_doc)
498
- st.success(f"Cloned document saved successfully with ID: {new_doc['id']} ๐ŸŽ‰")
499
- # Refresh the documents in session state
500
- st.session_state.documents = list(container.query_items(
501
- query="SELECT * FROM c ORDER BY c._ts DESC",
502
- enable_cross_partition_query=True
503
- ))
504
- except exceptions.CosmosResourceNotFoundError:
505
- st.error(f"Document with ID {clone_id} not found for cloning.")
506
- except exceptions.CosmosHttpResponseError as e:
507
- st.error(f"HTTP error occurred: {str(e)} ๐Ÿšจ")
508
- except Exception as e:
509
- st.error(f"An unexpected error occurred: {str(e)} ๐Ÿ˜ฑ")
510
-
511
-
512
- def create_new_blank_record(container):
513
- try:
514
- # Get the structure of the latest document (to preserve schema)
515
- latest_doc = container.query_items(query="SELECT * FROM c ORDER BY c._ts DESC", enable_cross_partition_query=True, max_item_count=1)
516
- if latest_doc:
517
- new_doc_structure = latest_doc[0].copy()
518
- else:
519
- new_doc_structure = {}
520
- new_doc = {key: "" for key in new_doc_structure.keys()} # Set all fields to blank
521
- new_doc['id'] = generate_unique_id() # Generate new unique ID
522
- new_doc['createdAt'] = datetime.utcnow().isoformat() # Set creation time
523
- # Insert the new blank document
524
- response = container.create_item(body=new_doc)
525
- st.success(f"New blank document saved successfully with ID: {new_doc['id']} ๐ŸŽ‰")
526
- # Refresh the documents in session state
527
- st.session_state.documents = list(container.query_items(
528
- query="SELECT * FROM c ORDER BY c._ts DESC",
529
- enable_cross_partition_query=True
530
- ))
531
- except exceptions.CosmosHttpResponseError as e:
532
- st.error(f"HTTP error occurred: {str(e)} ๐Ÿšจ")
533
- except Exception as e:
534
- st.error(f"An unexpected error occurred: {str(e)} ๐Ÿ˜ฑ")
535
-
536
 
537
- # Function to preprocess the pasted content
538
- def preprocess_text(text):
539
- # Replace CRLF and other newline variations with the JSON newline escape sequence
540
- text = text.replace('\r\n', '\\n')
541
- text = text.replace('\r', '\\n')
542
- text = text.replace('\n', '\\n')
543
- # Escape double quotes inside the text
544
- text = text.replace('"', '\\"')
545
- # Optionally remove or handle other special characters that might not be JSON-safe
546
- # Here, we remove characters like tabs or non-ASCII characters (as an example)
547
- text = re.sub(r'[\t]', ' ', text) # Replace tabs with spaces
548
- text = re.sub(r'[^\x00-\x7F]+', '', text) # Remove non-ASCII characters
549
- # Normalize spaces (strip leading/trailing whitespace)
550
- text = text.strip()
551
- return text
552
-
553
-
554
-
555
- def load_file_content(file_path):
556
- """Load and return file content with error handling"""
557
  try:
558
- with open(file_path, 'r', encoding='utf-8') as file:
559
- return file.read()
 
 
 
560
  except Exception as e:
561
- st.error(f"Error loading file: {str(e)}")
562
  return None
563
 
564
- def save_file_content(file_path, content):
565
- """Save file content with error handling"""
566
  try:
567
- with open(file_path, 'w', encoding='utf-8') as file:
568
- file.write(content)
569
- return True
570
- except Exception as e:
571
- st.error(f"Error saving file: {str(e)}")
572
- return False
573
-
574
- def display_file_viewer(file_path):
575
- """Display file content in markdown viewer"""
576
- content = load_file_content(file_path)
577
- if content:
578
- st.markdown("### ๐Ÿ“„ File Viewer")
579
- st.markdown(f"**Viewing:** {file_path}")
580
-
581
- # Add file metadata
582
- file_stats = os.stat(file_path)
583
- st.markdown(f"**Last modified:** {datetime.fromtimestamp(file_stats.st_mtime).strftime('%Y-%m-%d %H:%M:%S')}")
584
- st.markdown(f"**Size:** {file_stats.st_size} bytes")
585
 
586
- # Display content in markdown
587
- st.markdown("---")
588
- st.markdown(content)
589
-
590
- # Add download button
591
- st.download_button(
592
- label="โฌ‡๏ธ Download File",
593
- data=content,
594
- file_name=os.path.basename(file_path),
595
- mime="text/markdown"
596
  )
597
-
598
-
599
-
600
- def display_file_editor(file_path):
601
- """Display file content in both Markdown and Code Editor views"""
602
- # Initialize file content in session state if not already present
603
- if 'file_content' not in st.session_state:
604
- st.session_state.file_content = {}
605
-
606
- # Load content if not in session state or if it's a different file
607
- if file_path not in st.session_state.file_content:
608
- content = load_file_content(file_path)
609
- if content is not None:
610
- st.session_state.file_content[file_path] = content
611
- else:
612
- return
613
-
614
- st.markdown("### โœ๏ธ File Editor")
615
- st.markdown(f"**Editing:** {file_path}")
616
-
617
- # Create tabs for different views
618
- markdown_tab, code_tab = st.tabs(["Markdown View", "Code Editor"])
619
-
620
- with markdown_tab:
621
- st.markdown("### ๐Ÿ“„ Markdown Preview")
622
- st.markdown(st.session_state.file_content[file_path])
623
-
624
- with code_tab:
625
- st.markdown("### ๐Ÿ’ป Code Editor")
626
- # Create a unique key for the text area
627
- editor_key = f"editor_{hash(file_path)}"
628
 
629
- # Editor with syntax highlighting for markdown
630
- new_content = st.text_area(
631
- "Edit content below:",
632
- value=st.session_state.file_content[file_path],
633
- height=400,
634
- key=editor_key
635
- )
636
-
637
- # Add save and download buttons below both views
638
- col1, col2 = st.columns([1, 5])
639
- with col1:
640
- if st.button("๐Ÿ’พ Save Changes"):
641
- if save_file_content(file_path, new_content):
642
- st.session_state.file_content[file_path] = new_content
643
- st.success("File saved successfully! ๐ŸŽ‰")
644
- time.sleep(1)
645
- st.rerun()
646
-
647
- with col2:
648
- st.download_button(
649
- label="โฌ‡๏ธ Download File",
650
- data=new_content,
651
- file_name=os.path.basename(file_path),
652
- mime="text/markdown"
653
  )
654
-
655
-
656
-
657
-
658
- def display_file_editor_old(file_path):
659
- """Display file content in editor with save functionality"""
660
- # Initialize file content in session state if not already present
661
- if 'file_content' not in st.session_state:
662
- st.session_state.file_content = {}
663
-
664
- # Load content if not in session state or if it's a different file
665
- if file_path not in st.session_state.file_content:
666
- content = load_file_content(file_path)
667
- if content is not None:
668
- st.session_state.file_content[file_path] = content
669
- else:
670
- return
671
-
672
- st.markdown("### โœ๏ธ File Editor")
673
- st.markdown(f"**Editing:** {file_path}")
674
-
675
- # Create a unique key for the text area
676
- editor_key = f"editor_{hash(file_path)}"
677
-
678
- # Editor with syntax highlighting for markdown
679
- new_content = st.text_area(
680
- "Edit content below:",
681
- value=st.session_state.file_content[file_path],
682
- height=400,
683
- key=editor_key
684
- )
685
-
686
- col1, col2 = st.columns([1, 5])
687
- with col1:
688
- if st.button("๐Ÿ’พ Save Changes"):
689
- if save_file_content(file_path, new_content):
690
- st.session_state.file_content[file_path] = new_content
691
- st.success("File saved successfully! ๐ŸŽ‰")
692
- time.sleep(1)
693
- st.rerun()
694
-
695
- with col2:
696
- st.download_button(
697
- label="โฌ‡๏ธ Download File",
698
- data=new_content,
699
- file_name=os.path.basename(file_path),
700
- mime="text/markdown"
701
- )
702
-
703
- def update_file_management_section():
704
- # Initialize session state variables
705
- if 'file_view_mode' not in st.session_state:
706
- st.session_state.file_view_mode = None
707
- if 'current_file' not in st.session_state:
708
- st.session_state.current_file = None
709
- if 'file_content' not in st.session_state:
710
- st.session_state.file_content = {}
711
-
712
- all_files = glob.glob("*.md")
713
- all_files.sort(reverse=True)
714
-
715
- # File management buttons in sidebar
716
- st.sidebar.title("๐Ÿ“ File Management")
717
-
718
- if st.sidebar.button("๐Ÿ—‘ Delete All Files"):
719
- for file in all_files:
720
- os.remove(file)
721
- st.session_state.file_content = {} # Clear the file content cache
722
- st.session_state.current_file = None
723
- st.session_state.file_view_mode = None
724
- st.rerun()
725
-
726
- if st.sidebar.button("โฌ‡๏ธ Download All Files"):
727
- zip_file = create_zip_of_files(all_files)
728
- st.sidebar.markdown(get_download_link(zip_file), unsafe_allow_html=True)
729
-
730
- # Display files in sidebar with action buttons
731
- for file in all_files:
732
- col1, col2, col3, col4 = st.sidebar.columns([1,3,1,1])
733
 
734
- with col1:
735
- if st.button("๐ŸŒ", key=f"view_{file}"):
736
- st.session_state.current_file = file
737
- st.session_state.file_view_mode = 'view'
738
- if file not in st.session_state.file_content:
739
- content = load_file_content(file)
740
- if content is not None:
741
- st.session_state.file_content[file] = content
742
- st.rerun()
743
-
744
- with col2:
745
- st.markdown(get_download_link(file), unsafe_allow_html=True)
746
-
747
- with col3:
748
- if st.button("๐Ÿ“‚", key=f"edit_{file}"):
749
- st.session_state.current_file = file
750
- st.session_state.file_view_mode = 'edit'
751
- if file not in st.session_state.file_content:
752
- content = load_file_content(file)
753
- if content is not None:
754
- st.session_state.file_content[file] = content
755
- st.rerun()
756
-
757
- with col4:
758
- if st.button("๐Ÿ—‘", key=f"delete_{file}"):
759
- os.remove(file)
760
- if file in st.session_state.file_content:
761
- del st.session_state.file_content[file]
762
- if st.session_state.current_file == file:
763
- st.session_state.current_file = None
764
- st.session_state.file_view_mode = None
765
- st.rerun()
766
-
767
- # Display viewer or editor in main area based on mode
768
- if st.session_state.current_file:
769
- if st.session_state.file_view_mode == 'view':
770
- display_file_viewer(st.session_state.current_file)
771
- elif st.session_state.file_view_mode == 'edit':
772
- display_file_editor(st.session_state.current_file)
773
-
774
-
775
- # Function to create HTML for autoplaying and looping video (for the full cinematic effect ๐ŸŽฅ)
776
- def get_video_html(video_path, width="100%"):
777
- video_url = f"data:video/mp4;base64,{base64.b64encode(open(video_path, 'rb').read()).decode()}"
778
- return f'''
779
- <video width="{width}" controls autoplay muted loop>
780
- <source src="{video_url}" type="video/mp4">
781
- Your browser does not support the video tag.
782
- </video>
783
- '''
784
-
785
- # Function to create HTML for audio player (when life needs a soundtrack ๐ŸŽถ)
786
- def get_audio_html(audio_path, width="100%"):
787
- audio_url = f"data:audio/mpeg;base64,{base64.b64encode(open(audio_path, 'rb').read()).decode()}"
788
- return f'''
789
- <audio controls style="width: {width};">
790
- <source src="{audio_url}" type="audio/mpeg">
791
- Your browser does not support the audio element.
792
- </audio>
793
- '''
794
 
795
- # ๐ŸŽญ Main function - "All the world's a stage, and all the code merely players" -Shakespeare, probably
796
- def main():
797
- st.markdown("### ๐Ÿ™Git๐ŸŒŒCosmos๐Ÿ’ซ - Azure Cosmos DB and Github Agent")
798
-
799
- # ๐ŸŽฒ Session state vars - "Life is like a session state, you never know what you're gonna get"
800
- if 'logged_in' not in st.session_state:
801
- st.session_state.logged_in = False
802
- if 'selected_records' not in st.session_state:
803
- st.session_state.selected_records = []
804
- if 'client' not in st.session_state:
805
- st.session_state.client = None
806
- if 'selected_database' not in st.session_state:
807
- st.session_state.selected_database = None
808
- if 'selected_container' not in st.session_state:
809
- st.session_state.selected_container = None
810
- if 'selected_document_id' not in st.session_state:
811
- st.session_state.selected_document_id = None
812
- if 'current_index' not in st.session_state:
813
- st.session_state.current_index = 0
814
- if 'cloned_doc' not in st.session_state:
815
- st.session_state.cloned_doc = None
816
 
817
- # ๐Ÿ” Query processing - "To search or not to search, that is the query"
 
818
  try:
819
- query_params = st.query_params
820
- query = query_params.get('q') or query_params.get('query') or ''
821
- if query:
822
- result, result2, result3, response2 = search_glossary(query)
823
-
824
- # ๐Ÿ’พ Save results - "Every file you save is a future you pave"
825
- try:
826
- if st.button("Save AI Output"):
827
- filename = create_file_from_content(result)
828
- st.success(f"File saved: {filename}")
829
- filename = create_file_from_content(result2)
830
- st.success(f"File saved: {filename}")
831
- filename = create_file_from_content(result3)
832
- st.success(f"File saved: {filename}")
833
- filename = create_file_from_content(response2)
834
- st.success(f"File saved: {filename}")
835
-
836
- display_saved_files_in_sidebar()
837
- except Exception as e:
838
- st.error(f"An unexpected error occurred: {str(e)} ๐Ÿ˜ฑ")
839
-
840
- # ๐ŸŒŸ Cosmos DB operations - "In Cosmos DB we trust, but we still handle errors we must"
841
- try:
842
- save_to_cosmos_db(st.session_state.cosmos_container, query, result, result)
843
- save_to_cosmos_db(st.session_state.cosmos_container, query, result2, result2)
844
- save_to_cosmos_db(st.session_state.cosmos_container, query, result3, result3)
845
- save_to_cosmos_db(st.session_state.cosmos_container, query, response2[0], response2[0])
846
- save_to_cosmos_db(st.session_state.cosmos_container, query, response2[1], response2[1])
847
- except exceptions.CosmosHttpResponseError as e:
848
- st.error(f"HTTP error occurred: {str(e)} ๐Ÿšจ")
849
- except Exception as e:
850
- st.error(f"An unexpected error occurred: {str(e)} ๐Ÿ˜ฑ")
851
- st.stop()
852
  except Exception as e:
853
- st.markdown(' ')
854
-
855
- # ๐Ÿ” Auth check - "With great keys come great connectivity"
856
- if Key:
857
- st.session_state.primary_key = Key
858
- st.session_state.logged_in = True
859
- else:
860
- st.error("Cosmos DB Key is not set in environment variables. ๐Ÿ”‘โŒ")
861
- return
862
-
863
- if st.session_state.logged_in:
864
- # ๐ŸŒŒ DB initialization - "In the beginning, there was connection string..."
865
- try:
866
- if st.session_state.client is None:
867
- st.session_state.client = CosmosClient(ENDPOINT, credential=st.session_state.primary_key)
868
- # ๐Ÿ“š Navigation setup - "Navigation is not about where you are, but where you're going"
869
- st.sidebar.title("๐Ÿ™Git๐ŸŒŒCosmos๐Ÿ’ซ๐Ÿ—„๏ธNavigator")
870
- databases = get_databases(st.session_state.client)
871
- selected_db = st.sidebar.selectbox("๐Ÿ—ƒ๏ธ Select Database", databases)
872
- st.markdown(CosmosDBUrl)
873
-
874
- # ๐Ÿ”„ State management - "Change is the only constant in state management"
875
- if selected_db != st.session_state.selected_database:
876
- st.session_state.selected_database = selected_db
877
- st.session_state.selected_container = None
878
- st.session_state.selected_document_id = None
879
- st.session_state.current_index = 0
880
- st.rerun()
881
-
882
- if st.session_state.selected_database:
883
- database = st.session_state.client.get_database_client(st.session_state.selected_database)
884
- containers = get_containers(database)
885
- selected_container = st.sidebar.selectbox("๐Ÿ“ Select Container", containers)
886
-
887
- # ๐Ÿ”„ Container state handling - "Container changes, state arranges"
888
- if selected_container != st.session_state.selected_container:
889
- st.session_state.selected_container = selected_container
890
- st.session_state.selected_document_id = None
891
- st.session_state.current_index = 0
892
- st.rerun()
893
-
894
- if st.session_state.selected_container:
895
- container = database.get_container_client(st.session_state.selected_container)
896
- # ๐Ÿ“ฆ Export functionality - "Pack it, zip it, ship it"
897
- if st.sidebar.button("๐Ÿ“ฆ Export Container Data"):
898
- download_link = archive_current_container(st.session_state.selected_database,
899
- st.session_state.selected_container,
900
- st.session_state.client)
901
- if download_link.startswith('<a'):
902
- st.markdown(download_link, unsafe_allow_html=True)
903
- else:
904
- st.error(download_link)
905
-
906
- # ๐Ÿ“ Document handling - "Document, document, on the wall, who's the most recent of them all?"
907
- documents = get_documents(container)
908
- total_docs = len(documents)
909
- # Add a slider to let the user choose how many documents to display
910
- num_docs_to_display = st.slider(
911
- "Select number of documents to display", 1, 20, 1
912
- )
913
- # Adjust the document display logic based on the slider value
914
- if total_docs > num_docs_to_display:
915
- documents_to_display = documents[:num_docs_to_display]
916
- st.sidebar.info(f"Showing top {num_docs_to_display} most recent documents.")
917
- else:
918
- documents_to_display = documents
919
- st.sidebar.info(f"Showing all {len(documents_to_display)} documents.")
920
-
921
- if documents_to_display:
922
- # ๐ŸŽจ View options - "Different strokes for different folks"
923
- view_options = ['Show as Markdown', 'Show as Code Editor', 'Show as Run AI', 'Clone Document', 'New Record']
924
- selected_view = st.sidebar.selectbox("Select Viewer/Editor", view_options, index=2)
925
-
926
-
927
- if selected_view == 'Show as Markdown':
928
- Label = '#### ๐Ÿ“„ Markdown view - Mark it down, mark it up'
929
- st.markdown(Label)
930
- total_docs = len(documents)
931
- doc = documents[st.session_state.current_index]
932
- # st.markdown(f"#### Document ID: {doc.get('id', '')}")
933
-
934
- # ๐Ÿ•ต๏ธ Value extraction - "Finding spaces in all the right places"
935
- values_with_space = []
936
- def extract_values(obj):
937
- if isinstance(obj, dict):
938
- for k, v in obj.items():
939
- extract_values(v)
940
- elif isinstance(obj, list):
941
- for item in obj:
942
- extract_values(item)
943
- elif isinstance(obj, str):
944
- if ' ' in obj:
945
- values_with_space.append(obj)
946
-
947
- extract_values(doc)
948
- st.markdown("#### ๐Ÿ”— Links for Extracted Texts")
949
- for term in values_with_space:
950
- display_glossary_entity(term)
951
-
952
- content = json.dumps(doc, indent=2)
953
- st.markdown(f"```json\n{content}\n```")
954
-
955
- # โฌ…๏ธโžก๏ธ Navigation - "Left and right, day and night"
956
- col_prev, col_next = st.columns([1, 1])
957
- with col_prev:
958
- if st.button("โฌ…๏ธ Previous", key='prev_markdown'):
959
- if st.session_state.current_index > 0:
960
- st.session_state.current_index -= 1
961
- st.rerun()
962
- with col_next:
963
- if st.button("โžก๏ธ Next", key='next_markdown'):
964
- if st.session_state.current_index < total_docs - 1:
965
- st.session_state.current_index += 1
966
- st.rerun()
967
-
968
- elif selected_view == 'Show as Code Editor':
969
- Label = '#### ๐Ÿ’ป Code editor view'
970
- st.markdown(Label)
971
- total_docs = len(documents)
972
-
973
- if total_docs == 0:
974
- st.warning("No documents available.")
975
- return
976
-
977
- doc = documents[st.session_state.current_index]
978
- doc_str = st.text_area("Edit Document",
979
- value=json.dumps(doc, indent=2),
980
- height=300,
981
- key=f'code_editor_{st.session_state.current_index}')
982
-
983
- col_prev, col_next = st.columns([1, 1])
984
- with col_prev:
985
- if st.button("โฌ…๏ธ Previous", key='prev_code'):
986
- if st.session_state.current_index > 0:
987
- st.session_state.current_index -= 1
988
- st.rerun()
989
- with col_next:
990
- if st.button("โžก๏ธ Next", key='next_code'):
991
- if st.session_state.current_index < total_docs - 1:
992
- st.session_state.current_index += 1
993
- st.rerun()
994
-
995
- col_save, col_delete = st.columns([1, 1])
996
- with col_save:
997
- if st.button("๐Ÿ’พ Save Changes", key=f'save_button_{st.session_state.current_index}'):
998
- try:
999
- updated_doc = json.loads(doc_str)
1000
- response = container.upsert_item(body=updated_doc)
1001
- if response:
1002
- st.success(f"Document {updated_doc['id']} saved successfully.")
1003
- st.session_state.selected_document_id = updated_doc['id']
1004
- st.rerun()
1005
- except json.JSONDecodeError:
1006
- st.error("Invalid JSON format. Please check your edits.")
1007
- except Exception as e:
1008
- st.error(f"Error saving document: {str(e)}")
1009
-
1010
- with col_delete:
1011
- if st.button("๐Ÿ—‘๏ธ Delete", key=f'delete_button_{st.session_state.current_index}'):
1012
- try:
1013
- current_doc = json.loads(doc_str)
1014
- doc_id = current_doc.get("id")
1015
-
1016
- if not doc_id:
1017
- st.error("Document ID not found.")
1018
- return
1019
-
1020
- # Confirm deletion
1021
- if 'confirm_delete' not in st.session_state:
1022
- st.session_state.confirm_delete = False
1023
-
1024
- if not st.session_state.confirm_delete:
1025
- if st.button("โš ๏ธ Click to confirm deletion", key=f'confirm_delete_{st.session_state.current_index}'):
1026
- st.session_state.confirm_delete = True
1027
- st.rerun()
1028
- else:
1029
- try:
1030
- # Delete the document
1031
- container.delete_item(item=doc_id, partition_key=doc_id)
1032
-
1033
- # Update the session state
1034
- st.session_state.confirm_delete = False
1035
-
1036
- # Update the current index if necessary
1037
- if total_docs > 1:
1038
- if st.session_state.current_index == total_docs - 1:
1039
- st.session_state.current_index = max(0, total_docs - 2)
1040
- documents.pop(st.session_state.current_index)
1041
- else:
1042
- st.session_state.current_index = 0
1043
- documents.clear()
1044
-
1045
- st.success(f"Document {doc_id} deleted successfully.")
1046
- st.rerun()
1047
-
1048
- except Exception as e:
1049
- st.error(f"Error deleting document: {str(e)}")
1050
- st.session_state.confirm_delete = False
1051
-
1052
- except json.JSONDecodeError:
1053
- st.error("Invalid JSON format. Please check the document.")
1054
- except Exception as e:
1055
- st.error(f"Error processing deletion: {str(e)}")
1056
-
1057
- elif selected_view == 'Show as Code Editor - Old':
1058
- Label = '#### ๐Ÿ’ป Code editor view'
1059
- st.markdown(Label)
1060
- total_docs = len(documents)
1061
- doc = documents[st.session_state.current_index]
1062
- # st.markdown(f"#### Document ID: {doc.get('id', '')}")
1063
- doc_str = st.text_area("Edit Document",
1064
- value=json.dumps(doc, indent=2),
1065
- height=300,
1066
- key=f'code_editor_{st.session_state.current_index}')
1067
-
1068
- col_prev, col_next = st.columns([1, 1])
1069
- with col_prev:
1070
- if st.button("โฌ…๏ธ Previous", key='prev_code'):
1071
- if st.session_state.current_index > 0:
1072
- st.session_state.current_index -= 1
1073
- st.rerun()
1074
- with col_next:
1075
- if st.button("โžก๏ธ Next", key='next_code'):
1076
- if st.session_state.current_index < total_docs - 1:
1077
- st.session_state.current_index += 1
1078
- st.rerun()
1079
-
1080
- col_save, col_delete = st.columns([1, 1])
1081
- with col_save:
1082
- if st.button("๐Ÿ’พ Save Changes", key=f'save_button_{st.session_state.current_index}'):
1083
- try:
1084
- updated_doc = json.loads(doc_str)
1085
- response = container.upsert_item(body=updated_doc)
1086
- if response:
1087
- st.success(f"Document {updated_doc['id']} saved successfully.")
1088
- st.session_state.selected_document_id = updated_doc['id']
1089
- st.rerun()
1090
- except Exception as e:
1091
- st.error(f"Error saving document: {str(e)}")
1092
-
1093
- with col_delete:
1094
- if st.button("๐Ÿ—‘๏ธ Delete", key=f'delete_button_{st.session_state.current_index}'):
1095
- try:
1096
- current_doc = json.loads(doc_str)
1097
- # Direct deletion using container method with id and partition key
1098
- delete = container.delete_item(current_doc["id"], current_doc["id"])
1099
- if delete:
1100
- st.success(f"Document {current_doc['id']} deleted successfully.")
1101
- if st.session_state.current_index > 0:
1102
- st.session_state.current_index -= 1
1103
- st.rerun()
1104
- except Exception as e:
1105
- st.error(f"Error deleting document: {str(e)}")
1106
-
1107
-
1108
-
1109
-
1110
- elif selected_view == 'Show as Run AI':
1111
- Label = '#### โœ๏ธ Run AI with wisdom, save with precision'
1112
- st.markdown(Label)
1113
- num_cols = len(documents_to_display)
1114
- cols = st.columns(num_cols)
1115
-
1116
- for idx, (col, doc) in enumerate(zip(cols, documents_to_display)):
1117
- with col:
1118
- # ID and Name fields
1119
- editable_id = st.text_input("ID", value=doc.get('id', ''), key=f'edit_id_{idx}')
1120
- editable_name = st.text_input("Name", value=doc.get('name', ''), key=f'edit_name_{idx}')
1121
-
1122
- # Create editable document copy without id and name
1123
- editable_doc = doc.copy()
1124
- editable_doc.pop('id', None)
1125
- editable_doc.pop('name', None)
1126
-
1127
- doc_str = st.text_area("Document Content (in JSON format)",
1128
- value=json.dumps(editable_doc, indent=2),
1129
- height=300,
1130
- key=f'doc_str_{idx}')
1131
-
1132
- # Save and AI operations columns
1133
-
1134
- if st.button("๐Ÿค– Run AI", key=f'run_with_ai_button_{idx}'):
1135
- # Your existing AI processing code here
1136
- values_with_space = []
1137
- def extract_values2(obj):
1138
- if isinstance(obj, dict):
1139
- for k, v in obj.items():
1140
- extract_values2(v)
1141
- elif isinstance(obj, list):
1142
- for item in obj:
1143
- extract_values2(item)
1144
- elif isinstance(obj, str):
1145
- if ' ' in obj:
1146
- values_with_space.append(obj)
1147
-
1148
- extract_values2(doc)
1149
- for term in values_with_space:
1150
- display_glossary_entity(term)
1151
- search_glossary(term)
1152
-
1153
- if st.button("๐Ÿ’พ Save Changes", key=f'save_runai_{idx}'):
1154
- try:
1155
- updated_doc = json.loads(doc_str)
1156
- # Reinsert ID and name from editable fields
1157
- updated_doc['id'] = editable_id
1158
- updated_doc['name'] = editable_name
1159
- response = container.upsert_item(body=updated_doc)
1160
- if response:
1161
- st.success(f"Document {updated_doc['id']} saved successfully.")
1162
- st.session_state.selected_document_id = updated_doc['id']
1163
- st.rerun()
1164
- except Exception as e:
1165
- st.error(f"Error saving document: {str(e)}")
1166
-
1167
-
1168
- # File Editor (When you need to tweak things โœ๏ธ)
1169
- if hasattr(st.session_state, 'current_file'):
1170
- st.subheader(f"Editing: {st.session_state.current_file} ๐Ÿ› ")
1171
- new_content = st.text_area("File Content โœ๏ธ:", st.session_state.file_content, height=300)
1172
- if st.button("Save Changes ๐Ÿ’พ"):
1173
- with open(st.session_state.current_file, 'w', encoding='utf-8') as file:
1174
- file.write(new_content)
1175
- st.success("File updated successfully! ๐ŸŽ‰")
1176
-
1177
- # Image Gallery (For your viewing pleasure ๐Ÿ“ธ)
1178
- st.subheader("Image Gallery ๐Ÿ–ผ")
1179
- image_files = glob.glob("*.png") + glob.glob("*.jpg") + glob.glob("*.jpeg")
1180
- image_cols = st.slider("Gallery Columns ๐Ÿ–ผ", min_value=1, max_value=15, value=5)
1181
- cols = st.columns(image_cols)
1182
- for idx, image_file in enumerate(image_files):
1183
- with cols[idx % image_cols]:
1184
- img = Image.open(image_file)
1185
- #st.image(img, caption=image_file, use_column_width=True)
1186
- st.image(img, use_column_width=True)
1187
- display_glossary_entity(os.path.splitext(image_file)[0])
1188
-
1189
- # Video Gallery (Letโ€™s roll the tapes ๐ŸŽฌ)
1190
- st.subheader("Video Gallery ๐ŸŽฅ")
1191
- video_files = glob.glob("*.mp4")
1192
- video_cols = st.slider("Gallery Columns ๐ŸŽฌ", min_value=1, max_value=5, value=3)
1193
- cols = st.columns(video_cols)
1194
- for idx, video_file in enumerate(video_files):
1195
- with cols[idx % video_cols]:
1196
- st.markdown(get_video_html(video_file, width="100%"), unsafe_allow_html=True)
1197
- display_glossary_entity(os.path.splitext(video_file)[0])
1198
-
1199
- # Audio Gallery (Tunes for the mood ๐ŸŽถ)
1200
- st.subheader("Audio Gallery ๐ŸŽง")
1201
- audio_files = glob.glob("*.mp3") + glob.glob("*.wav")
1202
- audio_cols = st.slider("Gallery Columns ๐ŸŽถ", min_value=1, max_value=15, value=5)
1203
- cols = st.columns(audio_cols)
1204
- for idx, audio_file in enumerate(audio_files):
1205
- with cols[idx % audio_cols]:
1206
- st.markdown(get_audio_html(audio_file, width="100%"), unsafe_allow_html=True)
1207
- display_glossary_entity(os.path.splitext(audio_file)[0])
1208
-
1209
-
1210
-
1211
-
1212
- elif selected_view == 'Clone Document':
1213
- st.markdown("#### ๐Ÿ“„ Clone Document (Save As)")
1214
-
1215
- total_docs = len(documents)
1216
- doc = documents[st.session_state.current_index]
1217
-
1218
- # Display current document info
1219
- st.markdown(f"**Original Document ID:** {doc.get('id', '')}")
1220
- st.markdown(f"**Original Document Name:** {doc.get('name', '')}")
1221
-
1222
- # Generate new unique ID and name
1223
- unique_filename = gen_AI_IO_filename("Clone", doc.get('name', ''))
1224
- new_id = st.text_input("New Document ID", value=unique_filename, key='new_clone_id')
1225
- new_name = st.text_input("New Document Name", value=f"Clone_{unique_filename[:8]}", key='new_clone_name')
1226
-
1227
- # Create new document with all original content except system fields
1228
- new_doc = {
1229
- 'id': new_id,
1230
- 'name': new_name,
1231
- **{k: v for k, v in doc.items() if k not in ['id', 'name', '_rid', '_self', '_etag', '_attachments', '_ts']}
1232
- }
1233
-
1234
- # Show editable preview of the new document
1235
- doc_str = st.text_area(
1236
- "Edit Document Content (in JSON format)",
1237
- value=json.dumps(new_doc, indent=2),
1238
- height=300,
1239
- key='clone_preview'
1240
- )
1241
-
1242
- col1, col2 = st.columns(2)
1243
-
1244
- with col1:
1245
- if st.button("๐Ÿ”„ Generate New ID/Name", key='regenerate_id'):
1246
- # Generate new unique filename
1247
- new_unique_filename = gen_AI_IO_filename("Clone", doc.get('name', ''))
1248
- st.session_state.new_clone_id = new_unique_filename
1249
- st.session_state.new_clone_name = f"Clone_{new_unique_filename[:8]}"
1250
- st.rerun()
1251
-
1252
- with col2:
1253
- if st.button("๐Ÿ’พ Save As New Document", key='save_clone'):
1254
- try:
1255
- # Parse the edited document content
1256
- final_doc = json.loads(doc_str)
1257
-
1258
- # Ensure the new ID and name are used
1259
- final_doc['id'] = new_id
1260
- final_doc['name'] = new_name
1261
-
1262
- # Remove any system fields that might have been copied
1263
- system_fields = ['_rid', '_self', '_etag', '_attachments', '_ts']
1264
- for field in system_fields:
1265
- final_doc.pop(field, None)
1266
-
1267
- # Create the new document
1268
- response = container.create_item(body=final_doc)
1269
-
1270
- if response:
1271
- st.success(f"""
1272
- โœ… New document created successfully!
1273
- - ID: {final_doc['id']}
1274
- - Name: {final_doc['name']}
1275
- """)
1276
- # Update session state to show the new document
1277
- st.session_state.selected_document_id = final_doc['id']
1278
- st.rerun()
1279
- else:
1280
- st.error("Failed to create new document")
1281
- except json.JSONDecodeError as e:
1282
- st.error(f"Invalid JSON format: {str(e)}")
1283
- except Exception as e:
1284
- st.error(f"Error creating document: {str(e)}")
1285
-
1286
- # Navigation buttons for viewing other documents to clone
1287
- col_prev, col_next = st.columns([1, 1])
1288
- with col_prev:
1289
- if st.button("โฌ…๏ธ Previous", key='prev_clone'):
1290
- if st.session_state.current_index > 0:
1291
- st.session_state.current_index -= 1
1292
- st.rerun()
1293
- with col_next:
1294
- if st.button("โžก๏ธ Next", key='next_clone'):
1295
- if st.session_state.current_index < total_docs - 1:
1296
- st.session_state.current_index += 1
1297
- st.rerun()
1298
-
1299
-
1300
- elif selected_view == 'New Record':
1301
- st.markdown("#### Create a new document:")
1302
-
1303
- if st.button("๐Ÿค– Insert Auto-Generated Record"):
1304
- auto_doc = {
1305
- "id": generate_unique_id(),
1306
- "name": f"Auto-generated Record {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
1307
- "content": "This is an auto-generated record.",
1308
- "timestamp": datetime.now().isoformat()
1309
- }
1310
- success, message = save_or_clone_to_cosmos_db(container, document=auto_doc)
1311
- if success:
1312
- st.success(message)
1313
- st.rerun()
1314
- else:
1315
- st.error(message)
1316
- else:
1317
- new_id = st.text_input("ID", value=generate_unique_id(), key='new_id')
1318
- default_doc = {
1319
- "id": new_id,
1320
- "name": "New Document",
1321
- "content": "",
1322
- "timestamp": datetime.now().isoformat()
1323
- }
1324
- new_doc_str = st.text_area("Document Content (in JSON format)",
1325
- value=json.dumps(default_doc, indent=2),
1326
- height=300)
1327
-
1328
- if st.button("โž• Create New Document"):
1329
- try:
1330
- # Preprocess the text before loading it into JSON
1331
- cleaned_doc_str = preprocess_text(new_doc_str)
1332
- new_doc = json.loads(cleaned_doc_str)
1333
- new_doc['id'] = new_id # Ensure ID matches input field
1334
-
1335
- success, message = insert_record(container, new_doc)
1336
- if success:
1337
- st.success(f"New document created with id: {new_doc['id']} ๐ŸŽ‰")
1338
- st.session_state.selected_document_id = new_doc['id']
1339
- st.rerun()
1340
- else:
1341
- st.error(message)
1342
- except json.JSONDecodeError as e:
1343
- st.error(f"Invalid JSON: {str(e)} ๐Ÿšซ")
1344
-
1345
- st.subheader(f"๐Ÿ“Š Container: {st.session_state.selected_container}")
1346
- if st.session_state.selected_container:
1347
- if documents_to_display:
1348
- Label = '#### ๐Ÿ“Š Data display - Data tells tales that words cannot'
1349
- st.markdown(Label)
1350
- df = pd.DataFrame(documents_to_display)
1351
- st.dataframe(df)
1352
- else:
1353
- st.info("No documents to display. ๐Ÿง")
1354
-
1355
-
1356
- Label = '#### ๐Ÿ™ GitHub integration - Git happens'
1357
- st.subheader("๐Ÿ™ GitHub Operations")
1358
- github_token = os.environ.get("GITHUB")
1359
- source_repo = st.text_input("Source GitHub Repository URL",
1360
- value="https://github.com/AaronCWacker/AIExamples-8-24-Streamlit")
1361
- new_repo_name = st.text_input("New Repository Name (for cloning)",
1362
- value=f"AIExample-Clone-{datetime.now().strftime('%Y%m%d_%H%M%S')}")
1363
-
1364
- col1, col2 = st.columns(2)
1365
- with col1:
1366
- if st.button("๐Ÿ“ฅ Clone Repository"):
1367
- if github_token and source_repo:
1368
-
1369
- st.markdown(Label)
1370
- try:
1371
- local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d%H%M%S')}"
1372
- download_github_repo(source_repo, local_path)
1373
- zip_filename = f"{new_repo_name}.zip"
1374
- create_zip_file(local_path, zip_filename[:-4])
1375
- st.markdown(get_download_link(zip_filename), unsafe_allow_html=True)
1376
- st.success("Repository cloned successfully! ๐ŸŽ‰")
1377
- except Exception as e:
1378
- st.error(f"An error occurred: {str(e)} ๐Ÿ˜ข")
1379
- finally:
1380
- if os.path.exists(local_path):
1381
- shutil.rmtree(local_path)
1382
- if os.path.exists(zip_filename):
1383
- os.remove(zip_filename)
1384
- else:
1385
- st.error("Please ensure GitHub token is set in environment variables and source repository URL is provided. ๐Ÿ”‘โ“")
1386
-
1387
- with col2:
1388
- if st.button("๐Ÿ“ค Push to New Repository"):
1389
- if github_token and source_repo:
1390
-
1391
- st.markdown(Label)
1392
- try:
1393
- g = Github(github_token)
1394
- new_repo = create_repo(g, new_repo_name)
1395
- local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d%H%M%S')}"
1396
- download_github_repo(source_repo, local_path)
1397
- push_to_github(local_path, new_repo, github_token)
1398
- st.success(f"Repository pushed successfully to {new_repo.html_url} ๐Ÿš€")
1399
- except Exception as e:
1400
- st.error(f"An error occurred: {str(e)} ๐Ÿ˜ข")
1401
- finally:
1402
- if os.path.exists(local_path):
1403
- shutil.rmtree(local_path)
1404
- else:
1405
- st.error("Please ensure GitHub token is set in environment variables and source repository URL is provided. ๐Ÿ”‘โ“")
1406
-
1407
-
1408
- st.subheader("๐Ÿ’ฌ Chat with Claude")
1409
- user_input = st.text_area("Message ๐Ÿ“จ:", height=100)
1410
-
1411
- if st.button("Send ๐Ÿ“จ"):
1412
- Label = '#### ๐Ÿ’ฌ Chat functionality - Every chat is a chance to learn'
1413
- st.markdown(Label)
1414
- if user_input:
1415
- response = anthropicclient.messages.create(
1416
- model="claude-3-sonnet-20240229",
1417
- max_tokens=1000,
1418
- messages=[
1419
- {"role": "user", "content": user_input}
1420
- ]
1421
- )
1422
- st.write("Claude's reply ๐Ÿง :")
1423
- st.write(response.content[0].text)
1424
- filename = generate_filename(user_input, "md")
1425
- create_file(filename, user_input, response.content[0].text)
1426
- st.session_state.chat_history.append({"user": user_input, "claude": response.content[0].text})
1427
- # Save to Cosmos DB
1428
- save_to_cosmos_db(container, user_input, response.content[0].text, "")
1429
-
1430
-
1431
-
1432
- # ๐Ÿ“œ Chat history display - "History repeats itself, first as chat, then as wisdom"
1433
- st.subheader("Past Conversations ๐Ÿ“œ")
1434
- for chat in st.session_state.chat_history:
1435
- st.text_area("You said ๐Ÿ’ฌ:", chat["user"], height=100, disabled=True)
1436
- st.text_area("Claude replied ๐Ÿค–:", chat["claude"], height=200, disabled=True)
1437
- st.markdown("---")
1438
-
1439
-
1440
- # ๐Ÿ“ File editor - "Edit with care, save with flair"
1441
- if hasattr(st.session_state, 'current_file'):
1442
- st.subheader(f"Editing: {st.session_state.current_file} ๐Ÿ› ")
1443
- new_content = st.text_area("File Content โœ๏ธ:", st.session_state.file_content, height=300)
1444
-
1445
- # Preprocess the text before loading it into JSON - Added to protect copy paste into JSON to keep format.
1446
- cleaned_doc_str = preprocess_text(new_content)
1447
- new_doc = json.loads(cleaned_doc_str)
1448
- new_content = cleaned_doc_str
1449
-
1450
- if st.button("Save Changes ๐Ÿ’พ"):
1451
- with open(st.session_state.current_file, 'w', encoding='utf-8') as file:
1452
- file.write(new_content)
1453
- st.success("File updated successfully! ๐ŸŽ‰")
1454
-
1455
- # ๐Ÿ“‚ File management - "Manage many, maintain order"
1456
- update_file_management_section()
1457
-
1458
- except exceptions.CosmosHttpResponseError as e:
1459
- st.error(f"Failed to connect to Cosmos DB. HTTP error: {str(e)} ๐Ÿšจ")
1460
- except Exception as e:
1461
- st.error(f"An unexpected error occurred: {str(e)} ๐Ÿ˜ฑ")
1462
 
1463
- if st.session_state.logged_in and st.sidebar.button("๐Ÿšช Logout"):
1464
- Label = '#### ๐Ÿšช Logout - All good things must come to an end'
1465
- st.markdown(Label)
1466
- st.session_state.logged_in = False
1467
- st.session_state.selected_records.clear()
1468
- st.session_state.client = None
1469
- st.session_state.selected_database = None
1470
- st.session_state.selected_container = None
1471
- st.session_state.selected_document_id = None
1472
- st.session_state.current_index = 0
1473
- st.rerun()
 
 
 
 
 
 
 
 
 
 
1474
 
1475
  if __name__ == "__main__":
1476
- main()
 
 
 
 
 
 
1
+ import gradio as gr
 
 
 
 
 
 
 
 
2
  import random
 
 
 
3
  import time
 
 
 
 
 
4
  from datetime import datetime
5
+ import tempfile
6
+ import os
7
+ import edge_tts
8
+ import asyncio
9
+ import warnings
10
  from gradio_client import Client
11
+ import json
12
+ import pytz
13
+ import re
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
+ warnings.filterwarnings('ignore')
16
 
17
+ # Initialize the Gradio client for model access
18
+ def initialize_clients():
19
  try:
20
+ client = Client("awacke1/Arxiv-Paper-Search-And-QA-RAG-Pattern")
21
+ return client
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  except Exception as e:
23
+ print(f"Error initializing client: {str(e)}")
24
+ return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
+ if "client" not in locals():
27
+ CLIENT = initialize_clients()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
+ # Helper function to generate a filename
30
  def gen_AI_IO_filename(display_query, output):
 
31
  now_central = datetime.now(pytz.timezone("America/Chicago"))
32
  timestamp = now_central.strftime("%Y-%m-%d-%I-%M-%S-%f-%p")
33
+ display_query = display_query[:50]
34
+ output_snippet = re.sub(r'[^A-Za-z0-9]+', '_', output[:100])
 
 
 
35
  filename = f"{timestamp} - {display_query} - {output_snippet}.md"
36
  return filename
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
+ def create_file(filename, prompt, response, should_save=True):
39
+ """Create and save a file with prompt and response"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  if not should_save:
41
  return
 
42
  with open(filename, 'w', encoding='utf-8') as file:
43
+ file.write(f"Prompt:\n{prompt}\n\nResponse:\n{response}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
 
45
+ async def generate_speech(text, voice="en-US-AriaNeural"):
46
+ """Generate speech from text using edge-tts"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  try:
48
+ communicate = edge_tts.Communicate(text, voice)
49
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp_file:
50
+ tmp_path = tmp_file.name
51
+ await communicate.save(tmp_path)
52
+ return tmp_path
53
  except Exception as e:
54
+ print(f"Error in text2speech: {str(e)}")
55
  return None
56
 
57
+ def generate_story(prompt, model_choice):
58
+ """Generate story using specified model through ArXiv RAG pattern"""
59
  try:
60
+ if CLIENT is None:
61
+ return "Error: Story generation service is not available."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
 
63
+ # First pass: Generate initial story with chosen model
64
+ initial_result = CLIENT.predict(
65
+ prompt=prompt,
66
+ llm_model_picked=model_choice,
67
+ stream_outputs=True,
68
+ api_name="/ask_llm"
 
 
 
 
69
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
 
71
+ # Second pass: Enhance with RAG pattern
72
+ enhanced_result = CLIENT.predict(
73
+ message=prompt,
74
+ llm_results_use=10,
75
+ database_choice="Semantic Search",
76
+ llm_model_picked=model_choice,
77
+ api_name="/update_with_rag_md"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
 
80
+ # Combine results and save
81
+ story = initial_result + "\n\nEnhanced version:\n" + enhanced_result[0]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
 
83
+ # Save outputs
84
+ filename = gen_AI_IO_filename("Story", initial_result)
85
+ create_file(filename, prompt, initial_result)
86
+
87
+ filename = gen_AI_IO_filename("Enhanced", enhanced_result[0])
88
+ create_file(filename, prompt, enhanced_result[0])
89
+
90
+ return story
91
+ except Exception as e:
92
+ return f"Error generating story: {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
93
 
94
+ def story_generator_interface(prompt, genre, structure, model_choice, num_scenes, words_per_scene):
95
+ """Main story generation and audio creation function"""
96
  try:
97
+ # Create storytelling prompt
98
+ story_prompt = f"""Create a {genre} story following this structure: {structure}
99
+ Base concept: {prompt}
100
+ Make it engaging and suitable for narration.
101
+ Include vivid descriptions and sensory details.
102
+ Use approximately {words_per_scene} words per scene.
103
+ Create {num_scenes} distinct scenes."""
104
+
105
+ # Generate story
106
+ story = generate_story(story_prompt, model_choice)
107
+ if story.startswith("Error"):
108
+ return story, None
109
+
110
+ # Generate speech
111
+ audio_path = asyncio.run(generate_speech(story))
112
+
113
+ return story, audio_path
114
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  except Exception as e:
116
+ error_msg = f"An error occurred: {str(e)}"
117
+ return error_msg, None
118
+
119
+ # Create Gradio interface
120
+ with gr.Blocks(title="AI Story Generator", theme=gr.themes.Soft()) as demo:
121
+ gr.Markdown("""
122
+ # ๐ŸŽญ AI Story Generator
123
+ Generate creative stories with AI and listen to them! Using Mistral and Mixtral models.
124
+ """)
125
+
126
+ with gr.Row():
127
+ with gr.Column():
128
+ prompt_input = gr.Textbox(
129
+ label="Story Concept",
130
+ placeholder="Enter your story idea...",
131
+ lines=3
132
+ )
133
+ genre_input = gr.Dropdown(
134
+ label="Genre",
135
+ choices=[
136
+ "Science Fiction",
137
+ "Fantasy",
138
+ "Mystery",
139
+ "Romance",
140
+ "Horror",
141
+ "Adventure",
142
+ "Historical Fiction",
143
+ "Comedy"
144
+ ],
145
+ value="Fantasy"
146
+ )
147
+ structure_input = gr.Dropdown(
148
+ label="Story Structure",
149
+ choices=[
150
+ "Three Act (Setup -> Confrontation -> Resolution)",
151
+ "Hero's Journey (Call -> Adventure -> Return)",
152
+ "Five Act (Exposition -> Rising Action -> Climax -> Falling Action -> Resolution)"
153
+ ],
154
+ value="Three Act (Setup -> Confrontation -> Resolution)"
155
+ )
156
+ model_choice = gr.Dropdown(
157
+ label="Model",
158
+ choices=[
159
+ "mistralai/Mixtral-8x7B-Instruct-v0.1",
160
+ "mistralai/Mistral-7B-Instruct-v0.2"
161
+ ],
162
+ value="mistralai/Mixtral-8x7B-Instruct-v0.1"
163
+ )
164
+ num_scenes = gr.Slider(
165
+ label="Number of Scenes",
166
+ minimum=3,
167
+ maximum=7,
168
+ value=5,
169
+ step=1
170
+ )
171
+ words_per_scene = gr.Slider(
172
+ label="Words per Scene",
173
+ minimum=20,
174
+ maximum=100,
175
+ value=50,
176
+ step=10
177
+ )
178
+ generate_btn = gr.Button("Generate Story")
179
+
180
+ with gr.Row():
181
+ with gr.Column():
182
+ story_output = gr.Textbox(
183
+ label="Generated Story",
184
+ lines=10,
185
+ interactive=False
186
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
 
188
+ with gr.Row():
189
+ audio_output = gr.Audio(
190
+ label="Story Narration",
191
+ type="filepath"
192
+ )
193
+
194
+ generate_btn.click(
195
+ fn=story_generator_interface,
196
+ inputs=[
197
+ prompt_input,
198
+ genre_input,
199
+ structure_input,
200
+ model_choice,
201
+ num_scenes,
202
+ words_per_scene
203
+ ],
204
+ outputs=[
205
+ story_output,
206
+ audio_output
207
+ ]
208
+ )
209
 
210
  if __name__ == "__main__":
211
+ demo.launch(
212
+ debug=True,
213
+ share=True,
214
+ server_name="0.0.0.0",
215
+ server_port=7860
216
+ )