awacke1 commited on
Commit
9efd341
β€’
1 Parent(s): d45602c

Create backup12.app.py

Browse files
Files changed (1) hide show
  1. backup12.app.py +1166 -0
backup12.app.py ADDED
@@ -0,0 +1,1166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ record = {
194
+ "id": generate_unique_id(),
195
+ "query": query,
196
+ "response1": response1,
197
+ "response2": response2,
198
+ "timestamp": datetime.utcnow().isoformat()
199
+ }
200
+ try:
201
+ container.create_item(body=record)
202
+ st.success(f"Record saved successfully with ID: {record['id']}")
203
+ # Refresh the documents display
204
+ st.session_state.documents = get_documents(container)
205
+ except exceptions.CosmosHttpResponseError as e:
206
+ st.error(f"Error saving record to Cosmos DB: {e}")
207
+ else:
208
+ st.error("Cosmos DB container is not initialized.")
209
+ except Exception as e:
210
+ st.error(f"An unexpected error occurred: {str(e)}")
211
+
212
+
213
+
214
+ # πŸ™ GitHub functions - Where code goes to socialize
215
+
216
+ # πŸ“₯ Download GitHub repo - Cloning repos like it's going out of style
217
+ def download_github_repo(url, local_path):
218
+ if os.path.exists(local_path):
219
+ shutil.rmtree(local_path)
220
+ Repo.clone_from(url, local_path)
221
+
222
+ # πŸ—œοΈ Create zip file - Squeezing files tighter than your budget
223
+ def create_zip_file(source_dir, output_filename):
224
+ shutil.make_archive(output_filename, 'zip', source_dir)
225
+
226
+ # πŸ—οΈ Create repo - Building digital homes for lonely code
227
+ def create_repo(g, repo_name):
228
+ user = g.get_user()
229
+ return user.create_repo(repo_name)
230
+
231
+ # πŸš€ Push to GitHub - Sending code to the cloud (hopefully not the rainy kind)
232
+ def push_to_github(local_path, repo, github_token):
233
+ repo_url = f"https://{github_token}@github.com/{repo.full_name}.git"
234
+ local_repo = Repo(local_path)
235
+ if 'origin' in [remote.name for remote in local_repo.remotes]:
236
+ origin = local_repo.remote('origin')
237
+ origin.set_url(repo_url)
238
+ else:
239
+ origin = local_repo.create_remote('origin', repo_url)
240
+ if not local_repo.heads:
241
+ local_repo.git.checkout('-b', 'main')
242
+ current_branch = 'main'
243
+ else:
244
+ current_branch = local_repo.active_branch.name
245
+ local_repo.git.add(A=True)
246
+ if local_repo.is_dirty():
247
+ local_repo.git.commit('-m', 'Initial commit')
248
+ origin.push(refspec=f'{current_branch}:{current_branch}')
249
+
250
+
251
+ def save_or_clone_to_cosmos_db(container, document=None, clone_id=None):
252
+ def generate_complex_unique_id():
253
+ timestamp = datetime.utcnow().strftime('%Y%m%d%H%M%S%f')
254
+ random_component = ''.join(random.choices('abcdefghijklmnopqrstuvwxyz0123456789', k=8))
255
+ return f"{timestamp}-{random_component}-{str(uuid.uuid4())}"
256
+ max_retries = 10
257
+ base_delay = 0.1
258
+ for attempt in range(max_retries):
259
+ try:
260
+ new_id = generate_complex_unique_id()
261
+ if clone_id:
262
+ try:
263
+ existing_doc = container.read_item(item=clone_id, partition_key=clone_id)
264
+ new_doc = {
265
+ 'id': new_id,
266
+ 'originalText': existing_doc.get('originalText', ''),
267
+ 'qtPrompts': existing_doc.get('qtPrompts', []),
268
+ 'cloned_from': clone_id,
269
+ 'cloned_at': datetime.utcnow().isoformat()
270
+ }
271
+ except exceptions.CosmosResourceNotFoundError:
272
+ return False, f"Document with ID {clone_id} not found for cloning."
273
+ else:
274
+ if document is None:
275
+ return False, "No document provided for saving"
276
+ document['id'] = new_id
277
+ document['created_at'] = datetime.utcnow().isoformat()
278
+ new_doc = document
279
+ response = container.create_item(body=new_doc)
280
+ return True, f"{'Cloned' if clone_id else 'New'} document saved successfully with ID: {response['id']}"
281
+ except exceptions.CosmosHttpResponseError as e:
282
+ if e.status_code == 409:
283
+ delay = base_delay * (2 ** attempt) + random.uniform(0, 0.1)
284
+ time.sleep(delay)
285
+ continue
286
+ return False, f"Error saving to Cosmos DB: {str(e)}"
287
+ except Exception as e:
288
+ return False, f"An unexpected error occurred: {str(e)}"
289
+ return False, "Failed to save document after maximum retries."
290
+
291
+
292
+ # πŸ“¦ Archive current container - Packing up data like you're moving to a new digital house
293
+ def archive_current_container(database_name, container_name, client):
294
+ try:
295
+ base_dir = "./cosmos_archive_current_container"
296
+ if os.path.exists(base_dir):
297
+ shutil.rmtree(base_dir)
298
+ os.makedirs(base_dir)
299
+ db_client = client.get_database_client(database_name)
300
+ container_client = db_client.get_container_client(container_name)
301
+ items = list(container_client.read_all_items())
302
+ container_dir = os.path.join(base_dir, container_name)
303
+ os.makedirs(container_dir)
304
+ for item in items:
305
+ item_id = item.get('id', f"unknown_{datetime.now().strftime('%Y%m%d%H%M%S')}")
306
+ with open(os.path.join(container_dir, f"{item_id}.json"), 'w') as f:
307
+ json.dump(item, f, indent=2)
308
+ archive_name = f"{container_name}_archive_{datetime.now().strftime('%Y%m%d%H%M%S')}"
309
+ shutil.make_archive(archive_name, 'zip', base_dir)
310
+ return get_download_link(f"{archive_name}.zip")
311
+ except Exception as e:
312
+ return f"An error occurred while archiving data: {str(e)} 😒"
313
+
314
+ def gen_AI_IO_filename(display_query, output):
315
+ # Get current time in Central Time Zone with milliseconds
316
+ now_central = datetime.now(pytz.timezone("America/Chicago"))
317
+ timestamp = now_central.strftime("%Y-%m-%d-%I-%M-%S-%f-%p")
318
+
319
+ # Limit components to prevent excessive filename length
320
+ display_query = display_query[:50] # Truncate display_query to 50 chars
321
+ output_snippet = re.sub(r'[^A-Za-z0-9]+', '_', output[:100]) # Truncate output_snippet to 100 chars
322
+
323
+ filename = f"{timestamp} - {display_query} - {output_snippet}.md"
324
+ return filename
325
+
326
+ # πŸ” Search glossary - Finding needles in digital haystacks
327
+ def search_glossary(query):
328
+ st.markdown(f"### πŸ” SearchGlossary for: {query}")
329
+ model_options = ['mistralai/Mixtral-8x7B-Instruct-v0.1', 'mistralai/Mistral-7B-Instruct-v0.2']
330
+ model_choice = st.selectbox('🧠 Select LLM Model', options=model_options, index=1, key=f"model_choice_{id(query)}")
331
+ database_options = ['Semantic Search', 'Arxiv Search - Latest - (EXPERIMENTAL)']
332
+ database_choice = st.selectbox('πŸ“š Select Database', options=database_options, index=0, key=f"database_choice_{id(query)}")
333
+
334
+ # πŸ•΅οΈβ€β™‚οΈ Searching the glossary for: query
335
+ all_results = ""
336
+ # Limit the query display to 80 characters
337
+ display_query = query[:80] + "..." if len(query) > 80 else query
338
+ st.markdown(f"πŸ•΅οΈβ€β™‚οΈ Running ArXiV AI Analysis with Query: {display_query} - ML model: {model_choice} and Option: {database_options}")
339
+
340
+ # πŸ” ArXiV RAG researcher expert ~-<>-~ Paper Summary & Ask LLM
341
+ client = Client("awacke1/Arxiv-Paper-Search-And-QA-RAG-Pattern")
342
+ # πŸ” ArXiv RAG researcher expert ~-<>-~ Paper Summary & Ask LLM - api_name: /ask_llm
343
+ result = client.predict(
344
+ prompt=query,
345
+ llm_model_picked="mistralai/Mixtral-8x7B-Instruct-v0.1",
346
+ stream_outputs=True,
347
+ api_name="/ask_llm"
348
+ )
349
+ st.markdown("# Mixtral-8x7B-Instruct-v0.1")
350
+ st.markdown(result)
351
+ #st.code(result, language="python", line_numbers=True)
352
+
353
+
354
+ # πŸ” ArXiv RAG researcher expert ~-<>-~ Paper Summary & Ask LLM - api_name: /ask_llm
355
+ result2 = client.predict(
356
+ prompt=query,
357
+ llm_model_picked="mistralai/Mistral-7B-Instruct-v0.2",
358
+ stream_outputs=True,
359
+ api_name="/ask_llm"
360
+ )
361
+ st.markdown("# Mistral-7B-Instruct-v0.2")
362
+ st.markdown(result2)
363
+ #st.code(result2, language="python", line_numbers=True)
364
+
365
+ # πŸ” ArXiv RAG researcher expert ~-<>-~ Paper Summary & Ask LLM - api_name: /update_with_rag_md
366
+ response2 = client.predict(
367
+ message=query, # str in 'parameter_13' Textbox component
368
+ llm_results_use=10,
369
+ database_choice="Semantic Search",
370
+ llm_model_picked="mistralai/Mistral-7B-Instruct-v0.2",
371
+ api_name="/update_with_rag_md"
372
+ )
373
+ st.markdown("# Mistral-7B-Instruct-v0.2 update_with_rag_md 0")
374
+ st.markdown(response2[0])
375
+ #st.code(response2[0], language="python", line_numbers=True, wrap_lines=True)
376
+
377
+ st.markdown("# Mistral-7B-Instruct-v0.2 update_with_rag_md 1")
378
+ st.markdown(response2[1])
379
+ #st.code(response2[1], language="python", line_numbers=True, wrap_lines=True)
380
+
381
+
382
+ # βœ… Persist AI Results to Markdown Files
383
+ filename = gen_AI_IO_filename(display_query, result)
384
+ create_file(filename, query, result)
385
+ st.markdown(f"βœ… File saved as: `{filename}`")
386
+
387
+ filename = gen_AI_IO_filename(display_query, result2)
388
+ create_file(filename, query, result2)
389
+ st.markdown(f"βœ… File saved as: `{filename}`")
390
+
391
+ filename = gen_AI_IO_filename(display_query, response2[0])
392
+ create_file(filename, query, response2[0])
393
+ st.markdown(f"βœ… File saved as: `{filename}`")
394
+
395
+ filename = gen_AI_IO_filename(display_query, response2[1])
396
+ create_file(filename, query, response2[1])
397
+ st.markdown(f"βœ… File saved as: `{filename}`")
398
+
399
+ return result, result2, response2
400
+
401
+
402
+ # πŸ“ Generate a safe filename from the first few lines of content
403
+ def generate_filename_from_content(content, file_type="md"):
404
+ # Extract the first few lines or sentences
405
+ first_sentence = content.split('\n', 1)[0][:90] # Limit the length to 90 characters
406
+ # Remove special characters to make it a valid filename
407
+ safe_name = re.sub(r'[^\w\s-]', '', first_sentence)
408
+ # Limit length to be compatible with Windows and Linux
409
+ safe_name = safe_name[:50].strip() # Adjust length limit
410
+ return f"{safe_name}.{file_type}"
411
+
412
+
413
+ # πŸ’Ύ Create and save a file
414
+ def create_file_from_content(content, should_save=True):
415
+ if not should_save:
416
+ return
417
+ filename = generate_filename_from_content(content)
418
+ with open(filename, 'w', encoding='utf-8') as file:
419
+ file.write(content)
420
+ return filename
421
+
422
+
423
+ # πŸ“‚ Display list of saved .md files in the sidebar
424
+ def display_saved_files_in_sidebar():
425
+ all_files = glob.glob("*.md")
426
+ all_files.sort(reverse=True)
427
+ all_files = [file for file in all_files if not file.lower().startswith('readme')] # Exclude README.md
428
+ st.sidebar.markdown("## πŸ“ Saved Markdown Files")
429
+ for file in all_files:
430
+ col1, col2, col3 = st.sidebar.columns([6, 2, 1])
431
+ with col1:
432
+ st.markdown(f"πŸ“„ {file}")
433
+ with col2:
434
+ st.sidebar.download_button(
435
+ label="⬇️ Download",
436
+ data=open(file, 'rb').read(),
437
+ file_name=file
438
+ )
439
+ with col3:
440
+ if st.sidebar.button("πŸ—‘", key=f"delete_{file}"):
441
+ os.remove(file)
442
+ st.rerun()
443
+
444
+ def clone_record(container, clone_id):
445
+ try:
446
+ existing_doc = container.read_item(item=clone_id, partition_key=clone_id)
447
+ new_doc = existing_doc.copy()
448
+ new_doc['id'] = generate_unique_id() # Generate new unique ID with timestamp
449
+ new_doc['name'] = new_doc['id'] # Generate new unique ID with timestamp
450
+ new_doc['createdAt'] = datetime.utcnow().isoformat() # Update the creation time
451
+ new_doc['_rid'] = None # Reset _rid or any system-managed fields
452
+ new_doc['_self'] = None
453
+ new_doc['_etag'] = None
454
+ new_doc['_attachments'] = None
455
+ new_doc['_ts'] = None # Reset timestamp to be updated by Cosmos DB automatically
456
+ # Insert the cloned document
457
+ response = container.create_item(body=new_doc)
458
+ st.success(f"Cloned document saved successfully with ID: {new_doc['id']} πŸŽ‰")
459
+ # Refresh the documents in session state
460
+ st.session_state.documents = list(container.query_items(
461
+ query="SELECT * FROM c ORDER BY c._ts DESC",
462
+ enable_cross_partition_query=True
463
+ ))
464
+ except exceptions.CosmosResourceNotFoundError:
465
+ st.error(f"Document with ID {clone_id} not found for cloning.")
466
+ except exceptions.CosmosHttpResponseError as e:
467
+ st.error(f"HTTP error occurred: {str(e)} 🚨")
468
+ except Exception as e:
469
+ st.error(f"An unexpected error occurred: {str(e)} οΏ½οΏ½")
470
+
471
+
472
+ def create_new_blank_record(container):
473
+ try:
474
+ # Get the structure of the latest document (to preserve schema)
475
+ latest_doc = container.query_items(query="SELECT * FROM c ORDER BY c._ts DESC", enable_cross_partition_query=True, max_item_count=1)
476
+ if latest_doc:
477
+ new_doc_structure = latest_doc[0].copy()
478
+ else:
479
+ new_doc_structure = {}
480
+ new_doc = {key: "" for key in new_doc_structure.keys()} # Set all fields to blank
481
+ new_doc['id'] = generate_unique_id() # Generate new unique ID
482
+ new_doc['createdAt'] = datetime.utcnow().isoformat() # Set creation time
483
+ # Insert the new blank document
484
+ response = container.create_item(body=new_doc)
485
+ st.success(f"New blank document saved successfully with ID: {new_doc['id']} πŸŽ‰")
486
+ # Refresh the documents in session state
487
+ st.session_state.documents = list(container.query_items(
488
+ query="SELECT * FROM c ORDER BY c._ts DESC",
489
+ enable_cross_partition_query=True
490
+ ))
491
+ except exceptions.CosmosHttpResponseError as e:
492
+ st.error(f"HTTP error occurred: {str(e)} 🚨")
493
+ except Exception as e:
494
+ st.error(f"An unexpected error occurred: {str(e)} 😱")
495
+
496
+
497
+ # Function to preprocess the pasted content
498
+ def preprocess_text(text):
499
+ # Replace CRLF and other newline variations with the JSON newline escape sequence
500
+ text = text.replace('\r\n', '\\n')
501
+ text = text.replace('\r', '\\n')
502
+ text = text.replace('\n', '\\n')
503
+ # Escape double quotes inside the text
504
+ text = text.replace('"', '\\"')
505
+ # Optionally remove or handle other special characters that might not be JSON-safe
506
+ # Here, we remove characters like tabs or non-ASCII characters (as an example)
507
+ text = re.sub(r'[\t]', ' ', text) # Replace tabs with spaces
508
+ text = re.sub(r'[^\x00-\x7F]+', '', text) # Remove non-ASCII characters
509
+ # Normalize spaces (strip leading/trailing whitespace)
510
+ text = text.strip()
511
+ return text
512
+
513
+
514
+
515
+ # 🎭 Main function - "All the world's a stage, and all the code merely players" -Shakespeare, probably
516
+ def main():
517
+ st.markdown("### πŸ™Git🌌CosmosπŸ’« - Azure Cosmos DB and Github Agent")
518
+
519
+ # 🎲 Session state vars - "Life is like a session state, you never know what you're gonna get"
520
+ if 'logged_in' not in st.session_state:
521
+ st.session_state.logged_in = False
522
+ if 'selected_records' not in st.session_state:
523
+ st.session_state.selected_records = []
524
+ if 'client' not in st.session_state:
525
+ st.session_state.client = None
526
+ if 'selected_database' not in st.session_state:
527
+ st.session_state.selected_database = None
528
+ if 'selected_container' not in st.session_state:
529
+ st.session_state.selected_container = None
530
+ if 'selected_document_id' not in st.session_state:
531
+ st.session_state.selected_document_id = None
532
+ if 'current_index' not in st.session_state:
533
+ st.session_state.current_index = 0
534
+ if 'cloned_doc' not in st.session_state:
535
+ st.session_state.cloned_doc = None
536
+
537
+ # πŸ” Query processing - "To search or not to search, that is the query"
538
+ try:
539
+ query_params = st.query_params
540
+ query = query_params.get('q') or query_params.get('query') or ''
541
+ if query:
542
+ result, result2, result3, response2 = search_glossary(query)
543
+
544
+ # πŸ’Ύ Save results - "Every file you save is a future you pave"
545
+ try:
546
+ if st.button("Save AI Output"):
547
+ filename = create_file_from_content(result)
548
+ st.success(f"File saved: {filename}")
549
+ filename = create_file_from_content(result2)
550
+ st.success(f"File saved: {filename}")
551
+ filename = create_file_from_content(result3)
552
+ st.success(f"File saved: {filename}")
553
+ filename = create_file_from_content(response2)
554
+ st.success(f"File saved: {filename}")
555
+
556
+ display_saved_files_in_sidebar()
557
+ except Exception as e:
558
+ st.error(f"An unexpected error occurred: {str(e)} 😱")
559
+
560
+ # 🌟 Cosmos DB operations - "In Cosmos DB we trust, but we still handle errors we must"
561
+ try:
562
+ save_to_cosmos_db(st.session_state.cosmos_container, query, result, result)
563
+ save_to_cosmos_db(st.session_state.cosmos_container, query, result2, result2)
564
+ save_to_cosmos_db(st.session_state.cosmos_container, query, result3, result3)
565
+ save_to_cosmos_db(st.session_state.cosmos_container, query, response2[0], response2[0])
566
+ save_to_cosmos_db(st.session_state.cosmos_container, query, response2[1], response2[1])
567
+ except exceptions.CosmosHttpResponseError as e:
568
+ st.error(f"HTTP error occurred: {str(e)} 🚨")
569
+ except Exception as e:
570
+ st.error(f"An unexpected error occurred: {str(e)} 😱")
571
+ st.stop()
572
+ except Exception as e:
573
+ st.markdown(' ')
574
+
575
+ # πŸ” Auth check - "With great keys come great connectivity"
576
+ if Key:
577
+ st.session_state.primary_key = Key
578
+ st.session_state.logged_in = True
579
+ else:
580
+ st.error("Cosmos DB Key is not set in environment variables. πŸ”‘βŒ")
581
+ return
582
+
583
+ if st.session_state.logged_in:
584
+ # 🌌 DB initialization - "In the beginning, there was connection string..."
585
+ try:
586
+ if st.session_state.client is None:
587
+ st.session_state.client = CosmosClient(ENDPOINT, credential=st.session_state.primary_key)
588
+ # πŸ“š Navigation setup - "Navigation is not about where you are, but where you're going"
589
+ st.sidebar.title("πŸ™Git🌌CosmosπŸ’«πŸ—„οΈNavigator")
590
+ databases = get_databases(st.session_state.client)
591
+ selected_db = st.sidebar.selectbox("πŸ—ƒοΈ Select Database", databases)
592
+ st.markdown(CosmosDBUrl)
593
+
594
+ # πŸ”„ State management - "Change is the only constant in state management"
595
+ if selected_db != st.session_state.selected_database:
596
+ st.session_state.selected_database = selected_db
597
+ st.session_state.selected_container = None
598
+ st.session_state.selected_document_id = None
599
+ st.session_state.current_index = 0
600
+ st.rerun()
601
+
602
+ if st.session_state.selected_database:
603
+ database = st.session_state.client.get_database_client(st.session_state.selected_database)
604
+ containers = get_containers(database)
605
+ selected_container = st.sidebar.selectbox("πŸ“ Select Container", containers)
606
+
607
+ # πŸ”„ Container state handling - "Container changes, state arranges"
608
+ if selected_container != st.session_state.selected_container:
609
+ st.session_state.selected_container = selected_container
610
+ st.session_state.selected_document_id = None
611
+ st.session_state.current_index = 0
612
+ st.rerun()
613
+
614
+ if st.session_state.selected_container:
615
+ container = database.get_container_client(st.session_state.selected_container)
616
+ # πŸ“¦ Export functionality - "Pack it, zip it, ship it"
617
+ if st.sidebar.button("πŸ“¦ Export Container Data"):
618
+ download_link = archive_current_container(st.session_state.selected_database,
619
+ st.session_state.selected_container,
620
+ st.session_state.client)
621
+ if download_link.startswith('<a'):
622
+ st.markdown(download_link, unsafe_allow_html=True)
623
+ else:
624
+ st.error(download_link)
625
+
626
+ # πŸ“ Document handling - "Document, document, on the wall, who's the most recent of them all?"
627
+ documents = get_documents(container)
628
+ total_docs = len(documents)
629
+ # Add a slider to let the user choose how many documents to display
630
+ num_docs_to_display = st.slider(
631
+ "Select number of documents to display", 1, 20, 1
632
+ )
633
+ # Adjust the document display logic based on the slider value
634
+ if total_docs > num_docs_to_display:
635
+ documents_to_display = documents[:num_docs_to_display]
636
+ st.sidebar.info(f"Showing top {num_docs_to_display} most recent documents.")
637
+ else:
638
+ documents_to_display = documents
639
+ st.sidebar.info(f"Showing all {len(documents_to_display)} documents.")
640
+
641
+ if documents_to_display:
642
+ # 🎨 View options - "Different strokes for different folks"
643
+ view_options = ['Show as Markdown', 'Show as Code Editor', 'Show as Run AI', 'Clone Document', 'New Record']
644
+ selected_view = st.sidebar.selectbox("Select Viewer/Editor", view_options, index=2)
645
+
646
+
647
+ if selected_view == 'Show as Markdown':
648
+ Label = '#### πŸ“„ Markdown view - Mark it down, mark it up'
649
+ st.markdown(Label)
650
+ total_docs = len(documents)
651
+ doc = documents[st.session_state.current_index]
652
+ # st.markdown(f"#### Document ID: {doc.get('id', '')}")
653
+
654
+ # πŸ•΅οΈ Value extraction - "Finding spaces in all the right places"
655
+ values_with_space = []
656
+ def extract_values(obj):
657
+ if isinstance(obj, dict):
658
+ for k, v in obj.items():
659
+ extract_values(v)
660
+ elif isinstance(obj, list):
661
+ for item in obj:
662
+ extract_values(item)
663
+ elif isinstance(obj, str):
664
+ if ' ' in obj:
665
+ values_with_space.append(obj)
666
+
667
+ extract_values(doc)
668
+ st.markdown("#### πŸ”— Links for Extracted Texts")
669
+ for term in values_with_space:
670
+ display_glossary_entity(term)
671
+
672
+ content = json.dumps(doc, indent=2)
673
+ st.markdown(f"```json\n{content}\n```")
674
+
675
+ # β¬…οΈβž‘οΈ Navigation - "Left and right, day and night"
676
+ col_prev, col_next = st.columns([1, 1])
677
+ with col_prev:
678
+ if st.button("⬅️ Previous", key='prev_markdown'):
679
+ if st.session_state.current_index > 0:
680
+ st.session_state.current_index -= 1
681
+ st.rerun()
682
+ with col_next:
683
+ if st.button("➑️ Next", key='next_markdown'):
684
+ if st.session_state.current_index < total_docs - 1:
685
+ st.session_state.current_index += 1
686
+ st.rerun()
687
+
688
+
689
+
690
+ elif selected_view == 'Show as Code Editor':
691
+ Label = '#### πŸ’» Code editor view'
692
+ st.markdown(Label)
693
+ total_docs = len(documents)
694
+ doc = documents[st.session_state.current_index]
695
+ # st.markdown(f"#### Document ID: {doc.get('id', '')}")
696
+ doc_str = st.text_area("Edit Document",
697
+ value=json.dumps(doc, indent=2),
698
+ height=300,
699
+ key=f'code_editor_{st.session_state.current_index}')
700
+
701
+ col_prev, col_next = st.columns([1, 1])
702
+ with col_prev:
703
+ if st.button("⬅️ Previous", key='prev_code'):
704
+ if st.session_state.current_index > 0:
705
+ st.session_state.current_index -= 1
706
+ st.rerun()
707
+ with col_next:
708
+ if st.button("➑️ Next", key='next_code'):
709
+ if st.session_state.current_index < total_docs - 1:
710
+ st.session_state.current_index += 1
711
+ st.rerun()
712
+
713
+ col_save, col_delete = st.columns([1, 1])
714
+ with col_save:
715
+ if st.button("πŸ’Ύ Save Changes", key=f'save_button_{st.session_state.current_index}'):
716
+ try:
717
+ updated_doc = json.loads(doc_str)
718
+ response = container.upsert_item(body=updated_doc)
719
+ if response:
720
+ st.success(f"Document {updated_doc['id']} saved successfully.")
721
+ st.session_state.selected_document_id = updated_doc['id']
722
+ st.rerun()
723
+ except Exception as e:
724
+ st.error(f"Error saving document: {str(e)}")
725
+
726
+ with col_delete:
727
+ if st.button("πŸ—‘οΈ Delete", key=f'delete_button_{st.session_state.current_index}'):
728
+ try:
729
+ current_doc = json.loads(doc_str)
730
+ # Direct deletion using container method with id and partition key
731
+ delete = container.delete_item(current_doc["id"], current_doc["id"])
732
+ if delete:
733
+ st.success(f"Document {current_doc['id']} deleted successfully.")
734
+ if st.session_state.current_index > 0:
735
+ st.session_state.current_index -= 1
736
+ st.rerun()
737
+ except Exception as e:
738
+ st.error(f"Error deleting document: {str(e)}")
739
+
740
+
741
+ elif selected_view == 'Show as Run AI':
742
+ Label = '#### ✏️ Run AI with wisdom, save with precision'
743
+ st.markdown(Label)
744
+ num_cols = len(documents_to_display)
745
+ cols = st.columns(num_cols)
746
+
747
+ for idx, (col, doc) in enumerate(zip(cols, documents_to_display)):
748
+ with col:
749
+ # ID and Name fields
750
+ editable_id = st.text_input("ID", value=doc.get('id', ''), key=f'edit_id_{idx}')
751
+ editable_name = st.text_input("Name", value=doc.get('name', ''), key=f'edit_name_{idx}')
752
+
753
+ # Create editable document copy without id and name
754
+ editable_doc = doc.copy()
755
+ editable_doc.pop('id', None)
756
+ editable_doc.pop('name', None)
757
+
758
+ doc_str = st.text_area("Document Content (in JSON format)",
759
+ value=json.dumps(editable_doc, indent=2),
760
+ height=300,
761
+ key=f'doc_str_{idx}')
762
+
763
+ # Save and AI operations columns
764
+ col_save, col_ai, col_delete = st.columns(3)
765
+
766
+ with col_save:
767
+ if st.button("πŸ’Ύ Save Changes", key=f'save_runai_{idx}'):
768
+ try:
769
+ updated_doc = json.loads(doc_str)
770
+ # Reinsert ID and name from editable fields
771
+ updated_doc['id'] = editable_id
772
+ updated_doc['name'] = editable_name
773
+ response = container.upsert_item(body=updated_doc)
774
+ if response:
775
+ st.success(f"Document {updated_doc['id']} saved successfully.")
776
+ st.session_state.selected_document_id = updated_doc['id']
777
+ st.rerun()
778
+ except Exception as e:
779
+ st.error(f"Error saving document: {str(e)}")
780
+
781
+ with col_ai:
782
+ if st.button("πŸ€– Run AI", key=f'run_with_ai_button_{idx}'):
783
+ # Your existing AI processing code here
784
+ values_with_space = []
785
+ def extract_values2(obj):
786
+ if isinstance(obj, dict):
787
+ for k, v in obj.items():
788
+ extract_values2(v)
789
+ elif isinstance(obj, list):
790
+ for item in obj:
791
+ extract_values2(item)
792
+ elif isinstance(obj, str):
793
+ if ' ' in obj:
794
+ values_with_space.append(obj)
795
+
796
+ extract_values2(doc)
797
+ for term in values_with_space:
798
+ display_glossary_entity(term)
799
+ search_glossary(term)
800
+
801
+
802
+ elif selected_view == 'Show as Run AI - Old':
803
+ Label = '#### ✏️ Run AI with wisdom, save with precision'
804
+ st.markdown(Label)
805
+ num_cols = len(documents_to_display)
806
+ cols = st.columns(num_cols)
807
+
808
+ for idx, (col, doc) in enumerate(zip(cols, documents_to_display)):
809
+ with col:
810
+
811
+ # st.markdown(f"##### Document ID: {doc.get('id', '')}")
812
+ editable_id = st.text_input("ID", value=doc.get('id', ''), key=f'edit_id_{idx}')
813
+ editable_doc = doc.copy()
814
+ editable_doc.pop('id', None)
815
+
816
+ # st.markdown(f"##### Document Name: {doc.get('name', '')}")
817
+ editable_id = st.text_input("Name", value=doc.get('name', ''), key=f'edit_name_{idx}')
818
+ editable_doc = doc.copy()
819
+ editable_doc.pop('name', None)
820
+
821
+ doc_str = st.text_area("Document Content (in JSON format)",
822
+ value=json.dumps(editable_doc, indent=2),
823
+ height=300,
824
+ key=f'doc_str_{idx}')
825
+
826
+ # πŸ’ΎπŸ€– Save and AI operations
827
+ col_ai, col_delete = st.columns(2)
828
+
829
+ with col_ai:
830
+ if st.button("πŸ€– Run AI", key=f'run_with_ai_button_{idx}'):
831
+
832
+
833
+
834
+
835
+ # Experiment to get content fields πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–
836
+ total_docs = len(documents)
837
+ doc = documents[st.session_state.current_index]
838
+ values_with_space = []
839
+ def extract_values2(obj):
840
+ if isinstance(obj, dict):
841
+ for k, v in obj.items():
842
+ extract_values2(v)
843
+ elif isinstance(obj, list):
844
+ for item in obj:
845
+ extract_values2(item)
846
+ elif isinstance(obj, str):
847
+ if ' ' in obj:
848
+ values_with_space.append(obj)
849
+ extract_values2(doc)
850
+ #st.markdown("#### πŸ”— Links for Extracted Texts")
851
+ for term in values_with_space:
852
+ display_glossary_entity(term)
853
+ search_glossary(term)
854
+
855
+ #content = json.dumps(doc, indent=2)
856
+ #st.markdown(f"```json\n{content}\n```")
857
+ # Experiment to get content fields πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–
858
+
859
+
860
+
861
+
862
+ #search_glossary(json.dumps(editable_doc, indent=2))
863
+
864
+
865
+
866
+
867
+ elif selected_view == 'Clone Document':
868
+ st.markdown("#### Clone a document:")
869
+
870
+ for idx, doc in enumerate(documents_to_display):
871
+ st.markdown(f"##### Original Document ID: {doc.get('id', '')}")
872
+
873
+ if st.button("πŸ“„ Clone Document", key=f'clone_button_{idx}'):
874
+ # Generate unique filename using the provided function
875
+ unique_filename = gen_AI_IO_filename("Clone", doc.get('name', ''))
876
+
877
+ # Create new document with unique ID and name based on timestamp
878
+ new_doc = {
879
+ 'id': unique_filename,
880
+ 'name': f"Clone_{unique_filename[:8]}",
881
+ **{k: v for k, v in doc.items() if k not in ['id', 'name', '_rid', '_self', '_etag', '_attachments', '_ts']}
882
+ }
883
+
884
+ # Show editable preview
885
+ edited_doc = st.text_area(
886
+ "Edit cloned document:",
887
+ value=json.dumps(new_doc, indent=2),
888
+ height=300,
889
+ key=f'edit_clone_{idx}'
890
+ )
891
+
892
+ col_save, col_update = st.columns(2)
893
+
894
+ with col_save:
895
+ if st.button("πŸ’Ύ Save Clone", key=f'save_clone_{idx}'):
896
+ try:
897
+ final_doc = json.loads(edited_doc)
898
+ response = container.create_item(body=final_doc)
899
+ if response:
900
+ st.success(f"New cloned document created with ID: {final_doc['id']}")
901
+ st.rerun()
902
+ else:
903
+ st.error("Failed to create new document")
904
+ except Exception as e:
905
+ st.error(f"Error creating document: {str(e)}")
906
+
907
+ with col_update:
908
+ if st.button("πŸ”„ Update Clone ID/Name", key=f'update_clone_{idx}'):
909
+ try:
910
+ # Generate new unique filename
911
+ new_unique_filename = gen_AI_IO_filename("Clone", doc.get('name', ''))
912
+ current_doc = json.loads(edited_doc)
913
+ current_doc['id'] = new_unique_filename
914
+ current_doc['name'] = f"Clone_{new_unique_filename[:8]}"
915
+
916
+ # Update the text area with new values
917
+ st.session_state[f'edit_clone_{idx}'] = json.dumps(current_doc, indent=2)
918
+ st.rerun()
919
+ except Exception as e:
920
+ st.error(f"Error updating clone: {str(e)}")
921
+
922
+
923
+
924
+
925
+ elif selected_view == 'Clone Document - Old':
926
+ st.markdown("#### Clone a document:")
927
+
928
+ for idx, doc in enumerate(documents_to_display):
929
+ st.markdown(f"##### Original Document ID: {doc.get('id', '')}")
930
+
931
+ if st.button("πŸ“„ Clone Document", key=f'clone_button_{idx}'):
932
+ # Create new document with unique ID and name
933
+ new_doc = {
934
+ 'id': str(uuid.uuid4()),
935
+ 'name': f"Clone_{str(uuid.uuid4())[:8]}",
936
+ **{k: v for k, v in doc.items() if k not in ['id', 'name', '_rid', '_self', '_etag', '_attachments', '_ts']}
937
+ }
938
+
939
+ # Show editable preview
940
+ edited_doc = st.text_area(
941
+ "Edit cloned document:",
942
+ value=json.dumps(new_doc, indent=2),
943
+ height=300,
944
+ key=f'edit_clone_{idx}'
945
+ )
946
+
947
+ if st.button("πŸ’Ύ Save Clone", key=f'save_clone_{idx}'):
948
+ try:
949
+ final_doc = json.loads(edited_doc)
950
+ # Use container.create_item() instead of update_record()
951
+ response = container.create_item(body=final_doc)
952
+ if response:
953
+ st.success(f"New cloned document created with ID: {final_doc['id']}")
954
+ st.rerun()
955
+ else:
956
+ st.error("Failed to create new document")
957
+ except Exception as e:
958
+ st.error(f"Error creating document: {str(e)}")
959
+
960
+
961
+ elif selected_view == 'New Record':
962
+ st.markdown("#### Create a new document:")
963
+
964
+ if st.button("πŸ€– Insert Auto-Generated Record"):
965
+ auto_doc = {
966
+ "id": generate_unique_id(),
967
+ "name": f"Auto-generated Record {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
968
+ "content": "This is an auto-generated record.",
969
+ "timestamp": datetime.now().isoformat()
970
+ }
971
+ success, message = save_or_clone_to_cosmos_db(container, document=auto_doc)
972
+ if success:
973
+ st.success(message)
974
+ st.rerun()
975
+ else:
976
+ st.error(message)
977
+ else:
978
+ new_id = st.text_input("ID", value=generate_unique_id(), key='new_id')
979
+ default_doc = {
980
+ "id": new_id,
981
+ "name": "New Document",
982
+ "content": "",
983
+ "timestamp": datetime.now().isoformat()
984
+ }
985
+ new_doc_str = st.text_area("Document Content (in JSON format)",
986
+ value=json.dumps(default_doc, indent=2),
987
+ height=300)
988
+
989
+ if st.button("βž• Create New Document"):
990
+ try:
991
+ # Preprocess the text before loading it into JSON
992
+ cleaned_doc_str = preprocess_text(new_doc_str)
993
+ new_doc = json.loads(cleaned_doc_str)
994
+ new_doc['id'] = new_id # Ensure ID matches input field
995
+
996
+ success, message = insert_record(container, new_doc)
997
+ if success:
998
+ st.success(f"New document created with id: {new_doc['id']} πŸŽ‰")
999
+ st.session_state.selected_document_id = new_doc['id']
1000
+ st.rerun()
1001
+ else:
1002
+ st.error(message)
1003
+ except json.JSONDecodeError as e:
1004
+ st.error(f"Invalid JSON: {str(e)} 🚫")
1005
+
1006
+ st.subheader(f"πŸ“Š Container: {st.session_state.selected_container}")
1007
+ if st.session_state.selected_container:
1008
+ if documents_to_display:
1009
+ Label = '#### πŸ“Š Data display - Data tells tales that words cannot'
1010
+ st.markdown(Label)
1011
+ df = pd.DataFrame(documents_to_display)
1012
+ st.dataframe(df)
1013
+ else:
1014
+ st.info("No documents to display. 🧐")
1015
+
1016
+
1017
+ Label = '#### πŸ™ GitHub integration - Git happens'
1018
+ st.subheader("πŸ™ GitHub Operations")
1019
+ github_token = os.environ.get("GITHUB")
1020
+ source_repo = st.text_input("Source GitHub Repository URL",
1021
+ value="https://github.com/AaronCWacker/AIExamples-8-24-Streamlit")
1022
+ new_repo_name = st.text_input("New Repository Name (for cloning)",
1023
+ value=f"AIExample-Clone-{datetime.now().strftime('%Y%m%d_%H%M%S')}")
1024
+
1025
+ col1, col2 = st.columns(2)
1026
+ with col1:
1027
+ if st.button("πŸ“₯ Clone Repository"):
1028
+ if github_token and source_repo:
1029
+
1030
+ st.markdown(Label)
1031
+ try:
1032
+ local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d%H%M%S')}"
1033
+ download_github_repo(source_repo, local_path)
1034
+ zip_filename = f"{new_repo_name}.zip"
1035
+ create_zip_file(local_path, zip_filename[:-4])
1036
+ st.markdown(get_download_link(zip_filename), unsafe_allow_html=True)
1037
+ st.success("Repository cloned successfully! πŸŽ‰")
1038
+ except Exception as e:
1039
+ st.error(f"An error occurred: {str(e)} 😒")
1040
+ finally:
1041
+ if os.path.exists(local_path):
1042
+ shutil.rmtree(local_path)
1043
+ if os.path.exists(zip_filename):
1044
+ os.remove(zip_filename)
1045
+ else:
1046
+ st.error("Please ensure GitHub token is set in environment variables and source repository URL is provided. πŸ”‘β“")
1047
+
1048
+ with col2:
1049
+ if st.button("πŸ“€ Push to New Repository"):
1050
+ if github_token and source_repo:
1051
+
1052
+ st.markdown(Label)
1053
+ try:
1054
+ g = Github(github_token)
1055
+ new_repo = create_repo(g, new_repo_name)
1056
+ local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d%H%M%S')}"
1057
+ download_github_repo(source_repo, local_path)
1058
+ push_to_github(local_path, new_repo, github_token)
1059
+ st.success(f"Repository pushed successfully to {new_repo.html_url} πŸš€")
1060
+ except Exception as e:
1061
+ st.error(f"An error occurred: {str(e)} 😒")
1062
+ finally:
1063
+ if os.path.exists(local_path):
1064
+ shutil.rmtree(local_path)
1065
+ else:
1066
+ st.error("Please ensure GitHub token is set in environment variables and source repository URL is provided. πŸ”‘β“")
1067
+
1068
+
1069
+ st.subheader("πŸ’¬ Chat with Claude")
1070
+ user_input = st.text_area("Message πŸ“¨:", height=100)
1071
+
1072
+ if st.button("Send πŸ“¨"):
1073
+ Label = '#### πŸ’¬ Chat functionality - Every chat is a chance to learn'
1074
+ st.markdown(Label)
1075
+ if user_input:
1076
+ response = client.messages.create(
1077
+ model="claude-3-sonnet-20240229",
1078
+ max_tokens=1000,
1079
+ messages=[
1080
+ {"role": "user", "content": user_input}
1081
+ ]
1082
+ )
1083
+ st.write("Claude's reply 🧠:")
1084
+ st.write(response.content[0].text)
1085
+ filename = generate_filename(user_input, "md")
1086
+ create_file(filename, user_input, response.content[0].text)
1087
+ st.session_state.chat_history.append({"user": user_input, "claude": response.content[0].text})
1088
+ # Save to Cosmos DB
1089
+ save_to_cosmos_db(container, user_input, response.content[0].text, "")
1090
+
1091
+
1092
+
1093
+ # πŸ“œ Chat history display - "History repeats itself, first as chat, then as wisdom"
1094
+ st.subheader("Past Conversations πŸ“œ")
1095
+ for chat in st.session_state.chat_history:
1096
+ st.text_area("You said πŸ’¬:", chat["user"], height=100, disabled=True)
1097
+ st.text_area("Claude replied πŸ€–:", chat["claude"], height=200, disabled=True)
1098
+ st.markdown("---")
1099
+
1100
+
1101
+ # πŸ“ File editor - "Edit with care, save with flair"
1102
+ if hasattr(st.session_state, 'current_file'):
1103
+ st.subheader(f"Editing: {st.session_state.current_file} πŸ› ")
1104
+ new_content = st.text_area("File Content ✏️:", st.session_state.file_content, height=300)
1105
+
1106
+ # Preprocess the text before loading it into JSON - Added to protect copy paste into JSON to keep format.
1107
+ cleaned_doc_str = preprocess_text(new_content)
1108
+ new_doc = json.loads(cleaned_doc_str)
1109
+ new_content = cleaned_doc_str
1110
+
1111
+ if st.button("Save Changes πŸ’Ύ"):
1112
+ with open(st.session_state.current_file, 'w', encoding='utf-8') as file:
1113
+ file.write(new_content)
1114
+ st.success("File updated successfully! πŸŽ‰")
1115
+
1116
+ # πŸ“‚ File management - "Manage many, maintain order"
1117
+ st.sidebar.title("πŸ“ File Management")
1118
+
1119
+ all_files = glob.glob("*.md")
1120
+ all_files.sort(reverse=True)
1121
+
1122
+ if st.sidebar.button("πŸ—‘ Delete All Files"):
1123
+ for file in all_files:
1124
+ os.remove(file)
1125
+ st.rerun()
1126
+
1127
+ if st.sidebar.button("⬇️ Download All Files"):
1128
+ zip_file = create_zip_of_files(all_files)
1129
+ st.sidebar.markdown(get_download_link(zip_file), unsafe_allow_html=True)
1130
+
1131
+ for file in all_files:
1132
+ col1, col2, col3, col4 = st.sidebar.columns([1,3,1,1])
1133
+ with col1:
1134
+ if st.button("🌐", key="view_"+file):
1135
+ st.session_state.current_file = file
1136
+ st.session_state.file_content = load_file(file)
1137
+ with col2:
1138
+ st.markdown(get_download_link(file), unsafe_allow_html=True)
1139
+ with col3:
1140
+ if st.button("πŸ“‚", key="edit_"+file):
1141
+ st.session_state.current_file = file
1142
+ st.session_state.file_content = load_file(file)
1143
+ with col4:
1144
+ if st.button("πŸ—‘", key="delete_"+file):
1145
+ os.remove(file)
1146
+ st.rerun()
1147
+
1148
+ except exceptions.CosmosHttpResponseError as e:
1149
+ st.error(f"Failed to connect to Cosmos DB. HTTP error: {str(e)} 🚨")
1150
+ except Exception as e:
1151
+ st.error(f"An unexpected error occurred: {str(e)} 😱")
1152
+
1153
+ if st.session_state.logged_in and st.sidebar.button("πŸšͺ Logout"):
1154
+ Label = '#### πŸšͺ Logout - All good things must come to an end'
1155
+ st.markdown(Label)
1156
+ st.session_state.logged_in = False
1157
+ st.session_state.selected_records.clear()
1158
+ st.session_state.client = None
1159
+ st.session_state.selected_database = None
1160
+ st.session_state.selected_container = None
1161
+ st.session_state.selected_document_id = None
1162
+ st.session_state.current_index = 0
1163
+ st.rerun()
1164
+
1165
+ if __name__ == "__main__":
1166
+ main()