awacke1 commited on
Commit
dfd6986
Β·
verified Β·
1 Parent(s): 5503f03

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +1449 -158
app.py CHANGED
@@ -1,185 +1,1476 @@
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
 
12
- warnings.filterwarnings('ignore')
 
 
13
 
14
- # Initialize Gradio client
15
- def initialize_clients():
 
 
 
 
 
 
 
 
 
 
16
  try:
17
- client = Client("awacke1/Arxiv-Paper-Search-And-QA-RAG-Pattern")
18
- return client
 
 
19
  except Exception as e:
20
- print(f"Error initializing client: {str(e)}")
21
- return None
22
 
23
- if "client" not in locals():
24
- CLIENT = initialize_clients()
25
-
26
- STORY_GENRES = [
27
- "Science Fiction",
28
- "Fantasy",
29
- "Mystery",
30
- "Romance",
31
- "Horror",
32
- "Adventure",
33
- "Historical Fiction",
34
- "Comedy"
35
- ]
36
-
37
- STORY_STRUCTURES = {
38
- "Three Act": "Setup -> Confrontation -> Resolution",
39
- "Hero's Journey": "Ordinary World -> Call to Adventure -> Trials -> Return",
40
- "Five Act": "Exposition -> Rising Action -> Climax -> Falling Action -> Resolution",
41
- "Seven Point": "Hook -> Plot Turn 1 -> Pinch Point 1 -> Midpoint -> Plot Turn 2 -> Resolution"
42
- }
43
-
44
- async def generate_speech(text, voice="en-US-AriaNeural"):
45
- """Generate speech from text using edge-tts"""
46
  try:
47
- communicate = edge_tts.Communicate(text, voice)
48
- with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp_file:
49
- tmp_path = tmp_file.name
50
- await communicate.save(tmp_path)
51
- return tmp_path
52
  except Exception as e:
53
- print(f"Error in text2speech: {str(e)}")
54
- return None
55
 
56
- def generate_story_prompt(base_prompt, genre, structure):
57
- """Generate an expanded story prompt based on genre and structure"""
58
- prompt = f"""Create a {genre} story using this concept: '{base_prompt}'
59
- Follow this structure: {STORY_STRUCTURES[structure]}
60
- Include vivid descriptions and sensory details.
61
- Make it engaging and suitable for visualization.
62
- Keep each scene description clear and detailed enough for image generation.
63
- Limit the story to 5-7 key scenes.
64
- """
65
- return prompt
66
-
67
- def generate_story(prompt, model_choice):
68
- """Generate story using specified model"""
69
  try:
70
- if CLIENT is None:
71
- return "Error: Story generation service is not available."
 
 
 
 
 
72
 
73
- result = CLIENT.predict(
74
- prompt,
75
- model_choice,
76
- True,
77
- api_name="/ask_llm"
78
- )
79
- return result
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  except Exception as e:
81
- return f"Error generating story: {str(e)}"
82
 
83
- def story_generator_interface(prompt, genre, structure, model_choice, num_scenes, words_per_scene):
84
- """Main story generation and multimedia creation function"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  try:
86
- # Generate expanded prompt
87
- story_prompt = generate_story_prompt(prompt, genre, structure)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
 
89
- # Generate story
90
- story = generate_story(story_prompt, model_choice)
91
- if story.startswith("Error"):
92
- return story, None
93
 
94
- # Generate speech
95
- audio_path = asyncio.run(generate_speech(story))
 
96
 
97
- return story, audio_path
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
 
99
- except Exception as e:
100
- error_msg = f"An error occurred: {str(e)}"
101
- return error_msg, None
102
-
103
- # Create Gradio interface
104
- with gr.Blocks(theme=gr.themes.Soft()) as demo:
105
- gr.Markdown("""
106
- # 🎭 AI Story Generator
107
- Generate creative stories with AI and listen to them!
108
- """)
109
-
110
- with gr.Row():
111
- with gr.Column():
112
- prompt_input = gr.Textbox(
113
- label="Story Concept",
114
- placeholder="Enter your story idea...",
115
- lines=3
116
- )
117
- genre_input = gr.Dropdown(
118
- label="Genre",
119
- choices=STORY_GENRES,
120
- value="Fantasy"
121
- )
122
- structure_input = gr.Dropdown(
123
- label="Story Structure",
124
- choices=list(STORY_STRUCTURES.keys()),
125
- value="Three Act"
126
- )
127
- model_choice = gr.Dropdown(
128
- label="Model",
129
- choices=["mistralai/Mixtral-8x7B-Instruct-v0.1", "mistralai/Mistral-7B-Instruct-v0.2"],
130
- value="mistralai/Mixtral-8x7B-Instruct-v0.1"
131
- )
132
- num_scenes = gr.Slider(
133
- label="Number of Scenes",
134
- minimum=3,
135
- maximum=7,
136
- value=5,
137
- step=1
138
- )
139
- words_per_scene = gr.Slider(
140
- label="Words per Scene",
141
- minimum=20,
142
- maximum=100,
143
- value=50,
144
- step=10
145
- )
146
- generate_btn = gr.Button("Generate Story")
147
-
148
- with gr.Row():
149
- with gr.Column():
150
- story_output = gr.Textbox(
151
- label="Generated Story",
152
- lines=10,
153
- interactive=False
154
- )
155
 
156
- with gr.Row():
157
- audio_output = gr.Audio(
158
- label="Story Narration",
159
- type="filepath"
 
 
 
 
 
 
 
 
 
 
 
 
160
  )
 
 
 
 
 
 
 
 
 
161
 
162
- generate_btn.click(
163
- fn=story_generator_interface,
164
- inputs=[
165
- prompt_input,
166
- genre_input,
167
- structure_input,
168
- model_choice,
169
- num_scenes,
170
- words_per_scene
171
- ],
172
- outputs=[
173
- story_output,
174
- audio_output
175
- ]
 
 
 
 
 
 
176
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
 
178
  if __name__ == "__main__":
179
- demo.launch(
180
- debug=True,
181
- share=True,
182
- server_name="0.0.0.0",
183
- server_port=7860,
184
- show_error=True
185
- )
 
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()