awacke1 commited on
Commit
8d51b6c
Β·
verified Β·
1 Parent(s): 00b2733

Create backup9clonesavenameatlast.app.py

Browse files
Files changed (1) hide show
  1. backup9clonesavenameatlast.app.py +891 -0
backup9clonesavenameatlast.app.py ADDED
@@ -0,0 +1,891 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from azure.cosmos import CosmosClient, exceptions
3
+ import os
4
+ import pandas as pd
5
+ import traceback
6
+ import shutil
7
+ from github import Github
8
+ from git import Repo
9
+ from datetime import datetime
10
+ import base64
11
+ import json
12
+ import uuid
13
+ from urllib.parse import quote
14
+ from gradio_client import Client
15
+ import anthropic
16
+ import glob
17
+ import pytz
18
+ import re
19
+ from PIL import Image
20
+ import zipfile
21
+ import hashlib
22
+ import time
23
+
24
+ # 🎭 App Configuration - Because every app needs a good costume!
25
+ Site_Name = 'πŸ™Git🌌CosmosπŸ’« - Azure Cosmos DB and Github Agent'
26
+ title = "πŸ™Git🌌CosmosπŸ’« - Azure Cosmos DB and Github Agent"
27
+ helpURL = 'https://huggingface.co/awacke1'
28
+ bugURL = 'https://huggingface.co/spaces/awacke1'
29
+ icons = 'πŸ™πŸŒŒπŸ’«'
30
+
31
+ st.set_page_config(
32
+ page_title=title,
33
+ page_icon=icons,
34
+ layout="wide",
35
+ initial_sidebar_state="auto",
36
+ menu_items={
37
+ 'Get Help': helpURL,
38
+ 'Report a bug': bugURL,
39
+ 'About': title
40
+ }
41
+ )
42
+
43
+ # 🌌 Cosmos DB configuration - Where data goes to party!
44
+ ENDPOINT = "https://acae-afd.documents.azure.com:443/"
45
+ DATABASE_NAME = os.environ.get("COSMOS_DATABASE_NAME")
46
+ CONTAINER_NAME = os.environ.get("COSMOS_CONTAINER_NAME")
47
+ Key = os.environ.get("Key")
48
+
49
+ # 🌐 Your local app URL - Home sweet home
50
+ LOCAL_APP_URL = "https://huggingface.co/spaces/awacke1/AzureCosmosDBUI"
51
+
52
+ # πŸ€– Anthropic configuration - Teaching machines to be more human (and funnier)
53
+ client = anthropic.Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))
54
+
55
+ # 🧠 Initialize session state - Because even apps need a good memory
56
+ if "chat_history" not in st.session_state:
57
+ st.session_state.chat_history = []
58
+
59
+ # πŸ› οΈ Helper Functions - The unsung heroes of our code
60
+
61
+ # πŸ“Ž Get a file download link - Making file sharing as easy as stealing candy from a baby
62
+ def get_download_link(file_path):
63
+ with open(file_path, "rb") as file:
64
+ contents = file.read()
65
+ b64 = base64.b64encode(contents).decode()
66
+ file_name = os.path.basename(file_path)
67
+ return f'<a href="data:file/txt;base64,{b64}" download="{file_name}">Download {file_name}πŸ“‚</a>'
68
+
69
+ # 🎲 Generate a unique ID - Because being unique is important (just ask your mother)
70
+ def generate_unique_id():
71
+ timestamp = datetime.utcnow().strftime('%Y%m%d%H%M%S%f')
72
+ unique_uuid = str(uuid.uuid4())
73
+ return f"{timestamp}-{unique_uuid}"
74
+
75
+ # πŸ“ Generate a filename - Naming files like a pro (or a very confused librarian)
76
+ def generate_filename(prompt, file_type):
77
+ central = pytz.timezone('US/Central')
78
+ safe_date_time = datetime.now(central).strftime("%m%d_%H%M")
79
+ safe_prompt = re.sub(r'\W+', '', prompt)[:90]
80
+ return f"{safe_date_time}{safe_prompt}.{file_type}"
81
+
82
+ # πŸ’Ύ Create and save a file - Because data hoarding is a legitimate hobby
83
+ def create_file(filename, prompt, response, should_save=True):
84
+ if not should_save:
85
+ return
86
+ with open(filename, 'w', encoding='utf-8') as file:
87
+ file.write(prompt + "\n\n" + response)
88
+
89
+ # πŸ“– Load file content - Bringing words back from the digital grave
90
+ def load_file(file_name):
91
+ with open(file_name, "r", encoding='utf-8') as file:
92
+ content = file.read()
93
+ return content
94
+
95
+ # πŸ” Display glossary entity - Making search fun again (as if it ever was)
96
+ def display_glossary_entity(k):
97
+ search_urls = {
98
+ "πŸš€πŸŒŒArXiv": lambda k: f"/?q={quote(k)}",
99
+ "πŸ“–": lambda k: f"https://en.wikipedia.org/wiki/{quote(k)}",
100
+ "πŸ”": lambda k: f"https://www.google.com/search?q={quote(k)}",
101
+ "πŸŽ₯": lambda k: f"https://www.youtube.com/results?search_query={quote(k)}",
102
+ }
103
+ links_md = ' '.join([f"<a href='{url(k)}' target='_blank'>{emoji}</a>" for emoji, url in search_urls.items()])
104
+ st.markdown(f"{k} {links_md}", unsafe_allow_html=True)
105
+
106
+ # πŸ—œοΈ Create zip of files - Squeezing files together like sardines in a can
107
+ def create_zip_of_files(files):
108
+ zip_name = "all_files.zip"
109
+ with zipfile.ZipFile(zip_name, 'w') as zipf:
110
+ for file in files:
111
+ zipf.write(file)
112
+ return zip_name
113
+
114
+ # 🎬 Get video HTML - Making videos play nice (or at least trying to)
115
+ def get_video_html(video_path, width="100%"):
116
+ video_url = f"data:video/mp4;base64,{base64.b64encode(open(video_path, 'rb').read()).decode()}"
117
+ return f'''
118
+ <video width="{width}" controls autoplay loop>
119
+ <source src="{video_url}" type="video/mp4">
120
+ Your browser does not support the video tag.
121
+ </video>
122
+ '''
123
+
124
+ # 🎡 Get audio HTML - Let the music play (and hope it's not Baby Shark)
125
+ def get_audio_html(audio_path, width="100%"):
126
+ audio_url = f"data:audio/mpeg;base64,{base64.b64encode(open(audio_path, 'rb').read()).decode()}"
127
+ return f'''
128
+ <audio controls style="width:{width}">
129
+ <source src="{audio_url}" type="audio/mpeg">
130
+ Your browser does not support the audio element.
131
+ </audio>
132
+ '''
133
+
134
+ # 🌌 Cosmos DB functions - Where data goes to live its best life
135
+
136
+ # πŸ“š Get databases - Collecting databases like Pokemon cards
137
+ def get_databases(client):
138
+ return [db['id'] for db in client.list_databases()]
139
+
140
+ # πŸ“¦ Get containers - Finding where all the good stuff is hidden
141
+ def get_containers(database):
142
+ return [container['id'] for container in database.list_containers()]
143
+
144
+ # πŸ“„ Get documents - Retrieving the sacred texts (or just some JSON)
145
+ def get_documents(container, limit=None):
146
+ query = "SELECT * FROM c ORDER BY c._ts DESC"
147
+ items = list(container.query_items(query=query, enable_cross_partition_query=True, max_item_count=limit))
148
+ return items
149
+
150
+ # πŸ“₯ Insert record - Adding new data (and crossing fingers it doesn't break anything)
151
+ def insert_record(container, record):
152
+ try:
153
+ container.create_item(body=record)
154
+ return True, "Record inserted successfully! πŸŽ‰"
155
+ except exceptions.CosmosHttpResponseError as e:
156
+ return False, f"HTTP error occurred: {str(e)} 🚨"
157
+ except Exception as e:
158
+ return False, f"An unexpected error occurred: {str(e)} 😱"
159
+
160
+ # πŸ”„ Update record - Giving data a makeover
161
+ def update_record(container, updated_record):
162
+ try:
163
+ container.upsert_item(body=updated_record)
164
+ return True, f"Record with id {updated_record['id']} successfully updated. πŸ› οΈ"
165
+ except exceptions.CosmosHttpResponseError as e:
166
+ return False, f"HTTP error occurred: {str(e)} 🚨"
167
+ except Exception as e:
168
+ return False, f"An unexpected error occurred: {traceback.format_exc()} 😱"
169
+
170
+ # πŸ—‘οΈ Delete record - Saying goodbye to data (it's not you, it's me)
171
+ def delete_record(container, name, id):
172
+ try:
173
+ container.delete_item(item=id, partition_key=id)
174
+ return True, f"Successfully deleted record with name: {name} and id: {id} πŸ—‘οΈ"
175
+ except exceptions.CosmosResourceNotFoundError:
176
+ return False, f"Record with id {id} not found. It may have been already deleted. πŸ•΅οΈβ€β™‚οΈ"
177
+ except exceptions.CosmosHttpResponseError as e:
178
+ return False, f"HTTP error occurred: {str(e)} 🚨"
179
+ except Exception as e:
180
+ return False, f"An unexpected error occurred: {traceback.format_exc()} 😱"
181
+
182
+ # πŸ’Ύ Save to Cosmos DB - Preserving data for future generations (or just until the next update)
183
+ def save_to_cosmos_db(container, query, response1, response2):
184
+ try:
185
+ if container:
186
+ record = {
187
+ "id": generate_unique_id(),
188
+ "query": query,
189
+ "response1": response1,
190
+ "response2": response2,
191
+ "timestamp": datetime.utcnow().isoformat()
192
+ }
193
+ try:
194
+ container.create_item(body=record)
195
+ st.success(f"Record saved successfully with ID: {record['id']}")
196
+ # Refresh the documents display
197
+ st.session_state.documents = get_documents(container)
198
+ except exceptions.CosmosHttpResponseError as e:
199
+ st.error(f"Error saving record to Cosmos DB: {e}")
200
+ else:
201
+ st.error("Cosmos DB container is not initialized.")
202
+ except Exception as e:
203
+ st.error(f"An unexpected error occurred: {str(e)}")
204
+
205
+ # πŸ™ GitHub functions - Where code goes to socialize
206
+
207
+ # πŸ“₯ Download GitHub repo - Cloning repos like it's going out of style
208
+ def download_github_repo(url, local_path):
209
+ if os.path.exists(local_path):
210
+ shutil.rmtree(local_path)
211
+ Repo.clone_from(url, local_path)
212
+
213
+ # πŸ—œοΈ Create zip file - Squeezing files tighter than your budget
214
+ def create_zip_file(source_dir, output_filename):
215
+ shutil.make_archive(output_filename, 'zip', source_dir)
216
+
217
+ # πŸ—οΈ Create repo - Building digital homes for lonely code
218
+ def create_repo(g, repo_name):
219
+ user = g.get_user()
220
+ return user.create_repo(repo_name)
221
+
222
+ # πŸš€ Push to GitHub - Sending code to the cloud (hopefully not the rainy kind)
223
+ def push_to_github(local_path, repo, github_token):
224
+ repo_url = f"https://{github_token}@github.com/{repo.full_name}.git"
225
+ local_repo = Repo(local_path)
226
+
227
+ if 'origin' in [remote.name for remote in local_repo.remotes]:
228
+ origin = local_repo.remote('origin')
229
+ origin.set_url(repo_url)
230
+ else:
231
+ origin = local_repo.create_remote('origin', repo_url)
232
+
233
+ if not local_repo.heads:
234
+ local_repo.git.checkout('-b', 'main')
235
+ current_branch = 'main'
236
+ else:
237
+ current_branch = local_repo.active_branch.name
238
+
239
+ local_repo.git.add(A=True)
240
+
241
+ if local_repo.is_dirty():
242
+ local_repo.git.commit('-m', 'Initial commit')
243
+
244
+ origin.push(refspec=f'{current_branch}:{current_branch}')
245
+
246
+
247
+
248
+ def save_or_clone_to_cosmos_db(container, query=None, response=None, clone_id=None):
249
+ def generate_complex_unique_id():
250
+ timestamp = datetime.utcnow().strftime('%Y%m%d%H%M%S%f')
251
+ random_component = ''.join(random.choices('abcdefghijklmnopqrstuvwxyz0123456789', k=8))
252
+ return f"{timestamp}-{random_component}-{str(uuid.uuid4())}"
253
+
254
+ max_retries = 10
255
+ base_delay = 0.1 # 100 ms
256
+
257
+ for attempt in range(max_retries):
258
+ try:
259
+ new_id = generate_complex_unique_id()
260
+
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
+ st.error(f"Document with ID {clone_id} not found for cloning.")
273
+ return None
274
+ else:
275
+ new_doc = {
276
+ 'id': new_id,
277
+ 'query': query,
278
+ 'response': response,
279
+ 'created_at': datetime.utcnow().isoformat()
280
+ }
281
+
282
+ # Attempt to create the item
283
+ response = container.create_item(body=new_doc)
284
+
285
+ st.success(f"{'Cloned' if clone_id else 'New'} document saved successfully with ID: {response['id']}")
286
+
287
+ # Refresh the documents in the session state
288
+ st.session_state.documents = list(container.query_items(
289
+ query="SELECT * FROM c ORDER BY c._ts DESC",
290
+ enable_cross_partition_query=True
291
+ ))
292
+
293
+ return response['id']
294
+
295
+ except exceptions.CosmosHttpResponseError as e:
296
+ if e.status_code == 409: # Conflict error
297
+ delay = base_delay * (2 ** attempt) + random.uniform(0, 0.1)
298
+ st.warning(f"ID conflict occurred. Retrying in {delay:.2f} seconds... (Attempt {attempt + 1})")
299
+ time.sleep(delay)
300
+ else:
301
+ st.error(f"Error saving to Cosmos DB: {e}")
302
+ return None
303
+
304
+ except Exception as e:
305
+ st.error(f"An unexpected error occurred: {str(e)}")
306
+ return None
307
+
308
+ st.error("Failed to save document after maximum retries.")
309
+ return None
310
+
311
+
312
+
313
+ # πŸ’Ύ Save or clone to Cosmos DB - Because every document deserves a twin
314
+ def save_or_clone_to_cosmos_db2(container, query=None, response=None, clone_id=None):
315
+ try:
316
+ if not container:
317
+ st.error("Cosmos DB container is not initialized.")
318
+ return
319
+
320
+ # Generate a new unique ID
321
+ new_id = str(uuid.uuid4())
322
+
323
+ # Create a new document
324
+ if clone_id:
325
+ # If clone_id is provided, we're cloning an existing document
326
+ try:
327
+ existing_doc = container.read_item(item=clone_id, partition_key=clone_id)
328
+ new_doc = existing_doc.copy()
329
+ new_doc['id'] = new_id
330
+ new_doc['cloned_from'] = clone_id
331
+ new_doc['cloned_at'] = datetime.utcnow().isoformat()
332
+ except exceptions.CosmosResourceNotFoundError:
333
+ st.error(f"Document with ID {clone_id} not found for cloning.")
334
+ return
335
+ else:
336
+ # If no clone_id, we're creating a new document
337
+ new_doc = {
338
+ 'id': new_id,
339
+ 'query': query,
340
+ 'response': response,
341
+ 'created_at': datetime.utcnow().isoformat()
342
+ }
343
+
344
+ # Insert the new document
345
+ container.create_item(body=new_doc)
346
+
347
+ st.success(f"{'Cloned' if clone_id else 'New'} document saved successfully with ID: {new_id}")
348
+
349
+ # Refresh the documents in the session state
350
+ st.session_state.documents = list(container.query_items(
351
+ query="SELECT * FROM c ORDER BY c._ts DESC",
352
+ enable_cross_partition_query=True
353
+ ))
354
+
355
+ return new_id
356
+
357
+ except exceptions.CosmosHttpResponseError as e:
358
+ st.error(f"Error saving to Cosmos DB: {e}")
359
+ except Exception as e:
360
+ st.error(f"An unexpected error occurred: {str(e)}")
361
+
362
+ # πŸ“¦ Archive current container - Packing up data like you're moving to a new digital house
363
+ def archive_current_container(database_name, container_name, client):
364
+ try:
365
+ base_dir = "./cosmos_archive_current_container"
366
+ if os.path.exists(base_dir):
367
+ shutil.rmtree(base_dir)
368
+ os.makedirs(base_dir)
369
+
370
+ db_client = client.get_database_client(database_name)
371
+ container_client = db_client.get_container_client(container_name)
372
+ items = list(container_client.read_all_items())
373
+
374
+ container_dir = os.path.join(base_dir, container_name)
375
+ os.makedirs(container_dir)
376
+
377
+ for item in items:
378
+ item_id = item.get('id', f"unknown_{datetime.now().strftime('%Y%m%d%H%M%S')}")
379
+ with open(os.path.join(container_dir, f"{item_id}.json"), 'w') as f:
380
+ json.dump(item, f, indent=2)
381
+
382
+ archive_name = f"{container_name}_archive_{datetime.now().strftime('%Y%m%d%H%M%S')}"
383
+ shutil.make_archive(archive_name, 'zip', base_dir)
384
+
385
+ return get_download_link(f"{archive_name}.zip")
386
+ except Exception as e:
387
+ return f"An error occurred while archiving data: {str(e)} 😒"
388
+
389
+ # πŸ” Search glossary - Finding needles in digital haystacks
390
+ def search_glossary(query):
391
+ st.markdown(f"### πŸ” SearchGlossary for: {query}")
392
+
393
+ # Dropdown for model selection
394
+ model_options = ['mistralai/Mixtral-8x7B-Instruct-v0.1', 'mistralai/Mistral-7B-Instruct-v0.2', 'google/gemma-7b-it', 'None']
395
+ model_choice = st.selectbox('🧠 Select LLM Model', options=model_options, index=1)
396
+
397
+ # Dropdown for database selection
398
+ database_options = ['Semantic Search', 'Arxiv Search - Latest - (EXPERIMENTAL)']
399
+ database_choice = st.selectbox('πŸ“š Select Database', options=database_options, index=0)
400
+
401
+ # πŸ•΅οΈβ€β™‚οΈ Searching the glossary for: query
402
+ all_results = ""
403
+ st.markdown(f"- {query}")
404
+
405
+ # πŸ” ArXiv RAG researcher expert ~-<>-~ Paper Summary & Ask LLM
406
+ client = Client("awacke1/Arxiv-Paper-Search-And-QA-RAG-Pattern")
407
+
408
+ # πŸ” ArXiv RAG researcher expert ~-<>-~ Paper Summary & Ask LLM - api_name: /ask_llm
409
+ result = client.predict(
410
+ prompt=query,
411
+ llm_model_picked="mistralai/Mixtral-8x7B-Instruct-v0.1",
412
+ stream_outputs=True,
413
+ api_name="/ask_llm"
414
+ )
415
+ st.markdown(result)
416
+ st.code(result, language="python", line_numbers=True)
417
+
418
+ # πŸ” ArXiv RAG researcher expert ~-<>-~ Paper Summary & Ask LLM - api_name: /ask_llm
419
+ result2 = client.predict(
420
+ prompt=query,
421
+ llm_model_picked="mistralai/Mistral-7B-Instruct-v0.2",
422
+ stream_outputs=True,
423
+ api_name="/ask_llm"
424
+ )
425
+ st.markdown(result2)
426
+ st.code(result2, language="python", line_numbers=True)
427
+
428
+ # πŸ” ArXiv RAG researcher expert ~-<>-~ Paper Summary & Ask LLM - api_name: /ask_llm
429
+ result3 = client.predict(
430
+ prompt=query,
431
+ llm_model_picked="google/gemma-7b-it",
432
+ stream_outputs=True,
433
+ api_name="/ask_llm"
434
+ )
435
+ st.markdown(result3)
436
+ st.code(result3, language="python", line_numbers=True)
437
+
438
+ # πŸ” ArXiv RAG researcher expert ~-<>-~ Paper Summary & Ask LLM - api_name: /update_with_rag_md
439
+ response2 = client.predict(
440
+ message=query, # str in 'parameter_13' Textbox component
441
+ llm_results_use=10,
442
+ database_choice="Semantic Search",
443
+ llm_model_picked="mistralai/Mistral-7B-Instruct-v0.2",
444
+ api_name="/update_with_rag_md"
445
+ )
446
+
447
+ st.markdown(response2[0])
448
+ st.code(response2[0], language="python", line_numbers=True, wrap_lines=True)
449
+
450
+ st.markdown(response2[1])
451
+ st.code(response2[1], language="python", line_numbers=True, wrap_lines=True)
452
+
453
+ return result, result2, result3, response2
454
+
455
+ # 🎭 Main function - Where the magic happens (and occasionally breaks)
456
+ def main():
457
+ st.title("πŸ™Git🌌CosmosπŸ’« - Azure Cosmos DB and Github Agent")
458
+
459
+ # 🚦 Initialize session state
460
+ if 'logged_in' not in st.session_state:
461
+ st.session_state.logged_in = False
462
+ if 'selected_records' not in st.session_state:
463
+ st.session_state.selected_records = []
464
+ if 'client' not in st.session_state:
465
+ st.session_state.client = None
466
+ if 'selected_database' not in st.session_state:
467
+ st.session_state.selected_database = None
468
+ if 'selected_container' not in st.session_state:
469
+ st.session_state.selected_container = None
470
+ if 'selected_document_id' not in st.session_state:
471
+ st.session_state.selected_document_id = None
472
+ if 'current_index' not in st.session_state:
473
+ st.session_state.current_index = 0
474
+ if 'cloned_doc' not in st.session_state:
475
+ st.session_state.cloned_doc = None
476
+
477
+ # βš™οΈ q= Run ArXiv search from query parameters
478
+ try:
479
+ query_params = st.query_params
480
+ query = query_params.get('q') or query_params.get('query') or ''
481
+ if query:
482
+ # πŸ•΅οΈβ€β™‚οΈ We have a query! Let's process it!
483
+ result, result2, result3, response2 = search_glossary(query)
484
+ # When saving results, pass the container
485
+ try:
486
+ save_to_cosmos_db(st.session_state.cosmos_container, query, result, result)
487
+ save_to_cosmos_db(st.session_state.cosmos_container, query, result2, result2)
488
+ save_to_cosmos_db(st.session_state.cosmos_container, query, result3, result3)
489
+ save_to_cosmos_db(st.session_state.cosmos_container, query, response2[0], response2[0])
490
+ save_to_cosmos_db(st.session_state.cosmos_container, query, response2[1], response2[1])
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
+ st.stop() # Stop further execution
497
+ except Exception as e:
498
+ st.markdown(' ')
499
+
500
+ # πŸ” Automatic Login
501
+ if Key:
502
+ st.session_state.primary_key = Key
503
+ st.session_state.logged_in = True
504
+ else:
505
+ st.error("Cosmos DB Key is not set in environment variables. πŸ”‘βŒ")
506
+ return # Can't proceed without a key
507
+
508
+ if st.session_state.logged_in:
509
+ # 🌌 Initialize Cosmos DB client
510
+ try:
511
+ if st.session_state.client is None:
512
+ st.session_state.client = CosmosClient(ENDPOINT, credential=st.session_state.primary_key)
513
+
514
+ # πŸ—„οΈ Sidebar for database, container, and document selection
515
+ st.sidebar.title("πŸ™Git🌌CosmosπŸ’«πŸ—„οΈNavigator")
516
+
517
+ databases = get_databases(st.session_state.client)
518
+ selected_db = st.sidebar.selectbox("πŸ—ƒοΈ Select Database", databases)
519
+
520
+ if selected_db != st.session_state.selected_database:
521
+ st.session_state.selected_database = selected_db
522
+ st.session_state.selected_container = None
523
+ st.session_state.selected_document_id = None
524
+ st.session_state.current_index = 0
525
+ st.rerun()
526
+
527
+ if st.session_state.selected_database:
528
+ database = st.session_state.client.get_database_client(st.session_state.selected_database)
529
+ containers = get_containers(database)
530
+ selected_container = st.sidebar.selectbox("πŸ“ Select Container", containers)
531
+
532
+ if selected_container != st.session_state.selected_container:
533
+ st.session_state.selected_container = selected_container
534
+ st.session_state.selected_document_id = None
535
+ st.session_state.current_index = 0
536
+ st.rerun()
537
+
538
+ if st.session_state.selected_container:
539
+ container = database.get_container_client(st.session_state.selected_container)
540
+
541
+ # πŸ“¦ Add Export button
542
+ if st.button("πŸ“¦ Export Container Data"):
543
+ download_link = archive_current_container(st.session_state.selected_database, st.session_state.selected_container, st.session_state.client)
544
+ if download_link.startswith('<a'):
545
+ st.markdown(download_link, unsafe_allow_html=True)
546
+ else:
547
+ st.error(download_link)
548
+
549
+ # Fetch documents
550
+ documents = get_documents(container)
551
+ total_docs = len(documents)
552
+
553
+ if total_docs > 5:
554
+ documents_to_display = documents[:5]
555
+ st.info("Showing top 5 most recent documents.")
556
+ else:
557
+ documents_to_display = documents
558
+ st.info(f"Showing all {len(documents_to_display)} documents.")
559
+
560
+ if documents_to_display:
561
+ # 🎨 Add Viewer/Editor selection
562
+ view_options = ['Show as Markdown', 'Show as Code Editor', 'Show as Edit and Save', 'Clone Document', 'New Record']
563
+ selected_view = st.selectbox("Select Viewer/Editor", view_options, index=2)
564
+
565
+ if selected_view == 'Show as Markdown':
566
+ # πŸ–ŒοΈ Show each record as Markdown with navigation
567
+ total_docs = len(documents)
568
+ doc = documents[st.session_state.current_index]
569
+ st.markdown(f"#### Document ID: {doc.get('id', '')}")
570
+
571
+ # πŸ•΅οΈβ€β™‚οΈ Let's extract values from the JSON that have at least one space
572
+ values_with_space = []
573
+ def extract_values(obj):
574
+ if isinstance(obj, dict):
575
+ for k, v in obj.items():
576
+ extract_values(v)
577
+ elif isinstance(obj, list):
578
+ for item in obj:
579
+ extract_values(item)
580
+ elif isinstance(obj, str):
581
+ if ' ' in obj:
582
+ values_with_space.append(obj)
583
+
584
+ extract_values(doc)
585
+
586
+ # πŸ”— Let's create a list of links for these values
587
+ st.markdown("#### πŸ”— Links for Extracted Texts")
588
+ for term in values_with_space:
589
+ display_glossary_entity(term)
590
+
591
+ # Show the document content as markdown
592
+ content = json.dumps(doc, indent=2)
593
+ st.markdown(f"```json\n{content}\n```")
594
+
595
+ # Navigation buttons
596
+ col_prev, col_next = st.columns([1, 1])
597
+ with col_prev:
598
+ if st.button("⬅️ Previous", key='prev_markdown'):
599
+ if st.session_state.current_index > 0:
600
+ st.session_state.current_index -= 1
601
+ st.rerun()
602
+ with col_next:
603
+ if st.button("➑️ Next", key='next_markdown'):
604
+ if st.session_state.current_index < total_docs - 1:
605
+ st.session_state.current_index += 1
606
+ st.rerun()
607
+
608
+ elif selected_view == 'Show as Code Editor':
609
+ # πŸ’» Show each record in a code editor with navigation
610
+ total_docs = len(documents)
611
+ doc = documents[st.session_state.current_index]
612
+ st.markdown(f"#### Document ID: {doc.get('id', '')}")
613
+ doc_str = st.text_area("Edit Document", value=json.dumps(doc, indent=2), height=300, key=f'code_editor_{st.session_state.current_index}')
614
+ col_prev, col_next = st.columns([1, 1])
615
+ with col_prev:
616
+ if st.button("⬅️ Previous", key='prev_code'):
617
+ if st.session_state.current_index > 0:
618
+ st.session_state.current_index -= 1
619
+ st.rerun()
620
+ with col_next:
621
+ if st.button("➑️ Next", key='next_code'):
622
+ if st.session_state.current_index < total_docs - 1:
623
+ st.session_state.current_index += 1
624
+ st.rerun()
625
+ if st.button("πŸ’Ύ Save Changes", key=f'save_button_{st.session_state.current_index}'):
626
+ try:
627
+ updated_doc = json.loads(doc_str)
628
+ success, message = update_record(container, updated_doc)
629
+ if success:
630
+ st.success(f"Document {updated_doc['id']} saved successfully.")
631
+ st.session_state.selected_document_id = updated_doc['id']
632
+ st.rerun()
633
+ else:
634
+ st.error(message)
635
+ except json.JSONDecodeError as e:
636
+ st.error(f"Invalid JSON: {str(e)} 🚫")
637
+
638
+ elif selected_view == 'Show as Edit and Save':
639
+ # ✏️ Show as Edit and Save in columns
640
+ st.markdown("#### Edit the document fields below:")
641
+
642
+ # Create columns for each document
643
+ num_cols = len(documents_to_display)
644
+ cols = st.columns(num_cols)
645
+
646
+ for idx, (col, doc) in enumerate(zip(cols, documents_to_display)):
647
+ with col:
648
+ st.markdown(f"##### Document ID: {doc.get('id', '')}")
649
+ editable_id = st.text_input("ID", value=doc.get('id', ''), key=f'edit_id_{idx}')
650
+ # Remove 'id' from the document for editing other fields
651
+ editable_doc = doc.copy()
652
+ editable_doc.pop('id', None)
653
+ doc_str = st.text_area("Document Content (in JSON format)", value=json.dumps(editable_doc, indent=2), height=300, key=f'doc_str_{idx}')
654
+
655
+ # Add the "Run With AI" button next to "Save Changes"
656
+ col_save, col_ai = st.columns(2)
657
+ with col_save:
658
+ if st.button("πŸ’Ύ Save Changes", key=f'save_button_{idx}'):
659
+ try:
660
+ updated_doc = json.loads(doc_str)
661
+ updated_doc['id'] = editable_id # Include the possibly edited ID
662
+ success, message = update_record(container, updated_doc)
663
+ if success:
664
+ st.success(f"Document {updated_doc['id']} saved successfully.")
665
+ st.session_state.selected_document_id = updated_doc['id']
666
+ st.rerun()
667
+ else:
668
+ st.error(message)
669
+ except json.JSONDecodeError as e:
670
+ st.error(f"Invalid JSON: {str(e)} 🚫")
671
+ with col_ai:
672
+ if st.button("πŸ€– Run With AI", key=f'run_with_ai_button_{idx}'):
673
+ # Use the entire document as input
674
+ search_glossary(json.dumps(editable_doc, indent=2))
675
+ # Usage in your Streamlit app
676
+ if st.button("πŸ“„ Clone Document", key=f'clone_button_{idx}'):
677
+ with st.spinner("Cloning document..."):
678
+ cloned_id = save_or_clone_to_cosmos_db(container, clone_id=doc['id'])
679
+ if cloned_id:
680
+ st.success(f"Document cloned successfully with new ID: {cloned_id}")
681
+ st.rerun()
682
+ else:
683
+ st.error("Failed to clone document. Please try again.")
684
+
685
+ elif selected_view == 'Clone Document':
686
+ # 🧬 Clone Document per record
687
+ st.markdown("#### Clone a document:")
688
+ for idx, doc in enumerate(documents_to_display):
689
+ st.markdown(f"##### Document ID: {doc.get('id', '')}")
690
+ if st.button("πŸ“„ Clone Document", key=f'clone_button_{idx}'):
691
+ cloned_doc = doc.copy()
692
+ # Generate a unique ID
693
+ cloned_doc['id'] = generate_unique_id()
694
+ st.session_state.cloned_doc = cloned_doc
695
+ st.session_state.cloned_doc_str = json.dumps(cloned_doc, indent=2)
696
+ st.session_state.clone_mode = True
697
+ st.rerun()
698
+ if st.session_state.get('clone_mode', False):
699
+ st.markdown("#### Edit Cloned Document and Name Your Clone:")
700
+ cloned_doc_str = st.text_area("Cloned Document Content (in JSON format) - Update name please to make it unique before saving!", value=st.session_state.cloned_doc_str, height=300)
701
+ if st.button("πŸ’Ύ Save Cloned Document"):
702
+ try:
703
+ new_doc = json.loads(cloned_doc_str)
704
+ success, message = insert_record(container, new_doc)
705
+ if success:
706
+ st.success(f"Cloned document saved with id: {new_doc['id']} πŸŽ‰")
707
+ st.session_state.selected_document_id = new_doc['id']
708
+ st.session_state.clone_mode = False
709
+ st.session_state.cloned_doc = None
710
+ st.session_state.cloned_doc_str = ''
711
+ st.rerun()
712
+ else:
713
+ st.error(message)
714
+ except json.JSONDecodeError as e:
715
+ st.error(f"Invalid JSON: {str(e)} 🚫")
716
+
717
+ elif selected_view == 'New Record':
718
+ # πŸ†• New Record
719
+ st.markdown("#### Create a new document:")
720
+ if st.button("πŸ€– Insert Auto-Generated Record"):
721
+ success, message = save_or_clone_to_cosmos_db(container, query="Auto-generated", response="This is an auto-generated record.")
722
+ if success:
723
+ st.success(message)
724
+ st.rerun()
725
+ else:
726
+ st.error(message)
727
+ else:
728
+ new_id = st.text_input("ID", value=generate_unique_id(), key='new_id')
729
+ new_doc_str = st.text_area("Document Content (in JSON format)", value='{}', height=300)
730
+ if st.button("βž• Create New Document"):
731
+ try:
732
+ new_doc = json.loads(new_doc_str)
733
+ new_doc['id'] = new_id # Use the provided ID
734
+ success, message = insert_record(container, new_doc)
735
+ if success:
736
+ st.success(f"New document created with id: {new_doc['id']} πŸŽ‰")
737
+ st.session_state.selected_document_id = new_doc['id']
738
+ # Switch to 'Show as Edit and Save' mode
739
+ st.rerun()
740
+ else:
741
+ st.error(message)
742
+ except json.JSONDecodeError as e:
743
+ st.error(f"Invalid JSON: {str(e)} 🚫")
744
+
745
+ else:
746
+ st.sidebar.info("No documents found in this container. πŸ“­")
747
+
748
+ # πŸŽ‰ Main content area
749
+ st.subheader(f"πŸ“Š Container: {st.session_state.selected_container}")
750
+ if st.session_state.selected_container:
751
+ if documents_to_display:
752
+ df = pd.DataFrame(documents_to_display)
753
+ st.dataframe(df)
754
+ else:
755
+ st.info("No documents to display. 🧐")
756
+
757
+ # πŸ™ GitHub section
758
+ st.subheader("πŸ™ GitHub Operations")
759
+ github_token = os.environ.get("GITHUB") # Read GitHub token from environment variable
760
+ source_repo = st.text_input("Source GitHub Repository URL", value="https://github.com/AaronCWacker/AIExamples-8-24-Streamlit")
761
+ new_repo_name = st.text_input("New Repository Name (for cloning)", value=f"AIExample-Clone-{datetime.now().strftime('%Y%m%d_%H%M%S')}")
762
+
763
+ col1, col2 = st.columns(2)
764
+ with col1:
765
+ if st.button("πŸ“₯ Clone Repository"):
766
+ if github_token and source_repo:
767
+ try:
768
+ local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d%H%M%S')}"
769
+ download_github_repo(source_repo, local_path)
770
+ zip_filename = f"{new_repo_name}.zip"
771
+ create_zip_file(local_path, zip_filename[:-4])
772
+ st.markdown(get_download_link(zip_filename), unsafe_allow_html=True)
773
+ st.success("Repository cloned successfully! πŸŽ‰")
774
+ except Exception as e:
775
+ st.error(f"An error occurred: {str(e)} 😒")
776
+ finally:
777
+ if os.path.exists(local_path):
778
+ shutil.rmtree(local_path)
779
+ if os.path.exists(zip_filename):
780
+ os.remove(zip_filename)
781
+ else:
782
+ st.error("Please ensure GitHub token is set in environment variables and source repository URL is provided. πŸ”‘β“")
783
+
784
+ with col2:
785
+ if st.button("πŸ“€ Push to New Repository"):
786
+ if github_token and source_repo:
787
+ try:
788
+ g = Github(github_token)
789
+ new_repo = create_repo(g, new_repo_name)
790
+ local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d%H%M%S')}"
791
+ download_github_repo(source_repo, local_path)
792
+ push_to_github(local_path, new_repo, github_token)
793
+ st.success(f"Repository pushed successfully to {new_repo.html_url} πŸš€")
794
+ except Exception as e:
795
+ st.error(f"An error occurred: {str(e)} 😒")
796
+ finally:
797
+ if os.path.exists(local_path):
798
+ shutil.rmtree(local_path)
799
+ else:
800
+ st.error("Please ensure GitHub token is set in environment variables and source repository URL is provided. πŸ”‘β“")
801
+
802
+ # πŸ’¬ Chat with Claude
803
+ st.subheader("πŸ’¬ Chat with Claude")
804
+ user_input = st.text_area("Message πŸ“¨:", height=100)
805
+
806
+ if st.button("Send πŸ“¨"):
807
+ if user_input:
808
+ response = client.messages.create(
809
+ model="claude-3-sonnet-20240229",
810
+ max_tokens=1000,
811
+ messages=[
812
+ {"role": "user", "content": user_input}
813
+ ]
814
+ )
815
+ st.write("Claude's reply 🧠:")
816
+ st.write(response.content[0].text)
817
+
818
+ filename = generate_filename(user_input, "md")
819
+ create_file(filename, user_input, response.content[0].text)
820
+
821
+ st.session_state.chat_history.append({"user": user_input, "claude": response.content[0].text})
822
+
823
+ # Save to Cosmos DB
824
+ save_to_cosmos_db(container, user_input, response.content[0].text, "")
825
+
826
+ # Display Chat History
827
+ st.subheader("Past Conversations πŸ“œ")
828
+ for chat in st.session_state.chat_history:
829
+ st.text_area("You said πŸ’¬:", chat["user"], height=100, disabled=True)
830
+ st.text_area("Claude replied πŸ€–:", chat["claude"], height=200, disabled=True)
831
+ st.markdown("---")
832
+
833
+ # File Editor
834
+ if hasattr(st.session_state, 'current_file'):
835
+ st.subheader(f"Editing: {st.session_state.current_file} πŸ› ")
836
+ new_content = st.text_area("File Content ✏️:", st.session_state.file_content, height=300)
837
+ if st.button("Save Changes πŸ’Ύ"):
838
+ with open(st.session_state.current_file, 'w', encoding='utf-8') as file:
839
+ file.write(new_content)
840
+ st.success("File updated successfully! πŸŽ‰")
841
+
842
+ # File Management
843
+ st.sidebar.title("πŸ“ File Management")
844
+
845
+ all_files = glob.glob("*.md")
846
+ all_files.sort(reverse=True)
847
+
848
+ if st.sidebar.button("πŸ—‘ Delete All Files"):
849
+ for file in all_files:
850
+ os.remove(file)
851
+ st.rerun()
852
+
853
+ if st.sidebar.button("⬇️ Download All Files"):
854
+ zip_file = create_zip_of_files(all_files)
855
+ st.sidebar.markdown(get_download_link(zip_file), unsafe_allow_html=True)
856
+
857
+ for file in all_files:
858
+ col1, col2, col3, col4 = st.sidebar.columns([1,3,1,1])
859
+ with col1:
860
+ if st.button("🌐", key="view_"+file):
861
+ st.session_state.current_file = file
862
+ st.session_state.file_content = load_file(file)
863
+ with col2:
864
+ st.markdown(get_download_link(file), unsafe_allow_html=True)
865
+ with col3:
866
+ if st.button("πŸ“‚", key="edit_"+file):
867
+ st.session_state.current_file = file
868
+ st.session_state.file_content = load_file(file)
869
+ with col4:
870
+ if st.button("πŸ—‘", key="delete_"+file):
871
+ os.remove(file)
872
+ st.rerun()
873
+
874
+ except exceptions.CosmosHttpResponseError as e:
875
+ st.error(f"Failed to connect to Cosmos DB. HTTP error: {str(e)} 🚨")
876
+ except Exception as e:
877
+ st.error(f"An unexpected error occurred: {str(e)} 😱")
878
+
879
+ # πŸšͺ Logout button
880
+ if st.session_state.logged_in and st.sidebar.button("πŸšͺ Logout"):
881
+ st.session_state.logged_in = False
882
+ st.session_state.selected_records.clear()
883
+ st.session_state.client = None
884
+ st.session_state.selected_database = None
885
+ st.session_state.selected_container = None
886
+ st.session_state.selected_document_id = None
887
+ st.session_state.current_index = 0
888
+ st.rerun()
889
+
890
+ if __name__ == "__main__":
891
+ main()