awacke1 commited on
Commit
c3ad907
Β·
verified Β·
1 Parent(s): f5c7e99

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +136 -663
app.py CHANGED
@@ -12,9 +12,25 @@ import json
12
  import uuid # 🎲 For generating unique IDs
13
  from urllib.parse import quote # πŸ”— For encoding URLs
14
  from gradio_client import Client # 🌐 For connecting to Gradio apps
15
-
16
- # πŸŽ‰ Welcome to our fun-filled Cosmos DB and GitHub Integration app!
17
- st.set_page_config(layout="wide")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
  # 🌌 Cosmos DB configuration
20
  ENDPOINT = "https://acae-afd.documents.azure.com:443/"
@@ -22,12 +38,11 @@ DATABASE_NAME = os.environ.get("COSMOS_DATABASE_NAME")
22
  CONTAINER_NAME = os.environ.get("COSMOS_CONTAINER_NAME")
23
  Key = os.environ.get("Key") # πŸ”‘ Don't forget your key!
24
 
25
- # 🏠 Your local app URL (Change this to your app's URL)
26
- LOCAL_APP_URL = "https://huggingface.co/spaces/awacke1/AzureCosmosDBUI"
27
 
28
- # πŸ€– OpenAI configuration
29
- # openai.api_key = os.environ.get("OPENAI_API_KEY")
30
- # MODEL = "gpt-3.5-turbo" # Replace with your desired model
31
 
32
  # πŸ™ GitHub configuration
33
  def download_github_repo(url, local_path):
@@ -41,16 +56,16 @@ def create_zip_file(source_dir, output_filename):
41
  shutil.make_archive(output_filename, 'zip', source_dir)
42
 
43
  def create_repo(g, repo_name):
44
- # πŸ› οΈ Creating a new GitHub repo. Magic!
45
  user = g.get_user()
46
  return user.create_repo(repo_name)
47
 
48
  def push_to_github(local_path, repo, github_token):
49
- # πŸš€ Pushing code to GitHub. Hold on tight!
50
  repo_url = f"https://{github_token}@github.com/{repo.full_name}.git"
51
  local_repo = Repo(local_path)
52
 
53
- if 'origin' in [remote.name for remote in local_repo.remotes]:
54
  origin = local_repo.remote('origin')
55
  origin.set_url(repo_url)
56
  else:
@@ -76,26 +91,8 @@ def get_base64_download_link(file_path, file_name):
76
  base64_encoded = base64.b64encode(contents).decode()
77
  return f'<a href="data:application/zip;base64,{base64_encoded}" download="{file_name}">⬇️ Download {file_name}</a>'
78
 
79
-
80
- # 🧭 New functions for dynamic sidebar navigation
81
- def get_databases(client):
82
- # πŸ“š Fetching list of databases. So many options!
83
- return [db['id'] for db in client.list_databases()]
84
-
85
- def get_containers(database):
86
- # πŸ“‚ Getting containers. Containers within containers!
87
- return [container['id'] for container in database.list_containers()]
88
-
89
- def get_documents(container, limit=None):
90
- # πŸ“ Retrieving documents. Shhh, don't tell anyone!
91
- query = "SELECT * FROM c ORDER BY c._ts DESC"
92
- items = list(container.query_items(query=query, enable_cross_partition_query=True, max_item_count=limit))
93
- return items
94
-
95
-
96
  # 🌟 Cosmos DB functions
97
  def insert_record(container, record):
98
- # πŸ“₯ Inserting a record into the Cosmosβ€”hope we don't disturb any aliens! πŸ‘½
99
  try:
100
  container.create_item(body=record)
101
  return True, "Record inserted successfully! πŸŽ‰"
@@ -104,658 +101,134 @@ def insert_record(container, record):
104
  except Exception as e:
105
  return False, f"An unexpected error occurred: {str(e)} 😱"
106
 
107
- def update_record(container, updated_record):
108
- # πŸ”„ Updating a recordβ€”giving it a cosmic makeover! ✨
109
- try:
110
- container.upsert_item(body=updated_record)
111
- return True, f"Record with id {updated_record['id']} successfully updated. πŸ› οΈ"
112
- except exceptions.CosmosHttpResponseError as e:
113
- return False, f"HTTP error occurred: {str(e)} 🚨"
114
- except Exception as e:
115
- return False, f"An unexpected error occurred: {traceback.format_exc()} 😱"
116
-
117
- def delete_record(container, name, id):
118
- # πŸ—‘οΈ Deleting a recordβ€”sending it into the cosmic void! 🌌
119
- try:
120
- container.delete_item(item=id, partition_key=id)
121
- return True, f"Successfully deleted record with name: {name} and id: {id} πŸ—‘οΈ"
122
- except exceptions.CosmosResourceNotFoundError:
123
- return False, f"Record with id {id} not found. It may have been already deleted. πŸ•΅οΈβ€β™‚οΈ"
124
- except exceptions.CosmosHttpResponseError as e:
125
- return False, f"HTTP error occurred: {str(e)} 🚨"
126
- except Exception as e:
127
- return False, f"An unexpected error occurred: {traceback.format_exc()} 😱"
128
-
129
  # 🎲 Function to generate a unique UUID
130
  def generate_unique_id():
131
- # πŸ§™β€β™‚οΈ Generating a unique UUID!
132
  return str(uuid.uuid4())
133
 
134
- # πŸ“¦ Function to archive current container
135
- def archive_current_container(database_name, container_name, client):
136
- # πŸ“¦ Archiving the entire containerβ€”time to pack up the stars! 🌠
137
- try:
138
- base_dir = "./cosmos_archive_current_container"
139
- if os.path.exists(base_dir):
140
- shutil.rmtree(base_dir)
141
- os.makedirs(base_dir)
142
-
143
- db_client = client.get_database_client(database_name)
144
- container_client = db_client.get_container_client(container_name)
145
- items = list(container_client.read_all_items())
146
-
147
- container_dir = os.path.join(base_dir, container_name)
148
- os.makedirs(container_dir)
149
-
150
- for item in items:
151
- item_id = item.get('id', f"unknown_{datetime.now().strftime('%Y%m%d%H%M%S')}")
152
- with open(os.path.join(container_dir, f"{item_id}.json"), 'w') as f:
153
- json.dump(item, f, indent=2)
154
-
155
- archive_name = f"{container_name}_archive_{datetime.now().strftime('%Y%m%d%H%M%S')}"
156
- shutil.make_archive(archive_name, 'zip', base_dir)
157
-
158
- return get_base64_download_link(f"{archive_name}.zip", f"{archive_name}.zip")
159
- except Exception as e:
160
- return f"An error occurred while archiving data: {str(e)} 😒"
161
-
162
-
163
- # πŸ”— Helper to extract hyperlinks
164
- def extract_hyperlinks(responses):
165
- # πŸ”— Extracting hyperlinksβ€”connecting the dots across the universe! πŸ•ΈοΈ
166
- hyperlinks = []
167
- for response in responses:
168
- parsed_response = json.loads(response)
169
- links = [value for key, value in parsed_response.items() if isinstance(value, str) and value.startswith("http")]
170
- hyperlinks.extend(links)
171
- return hyperlinks
172
-
173
- # πŸ“‹ Helper to format text with line numbers
174
- def format_with_line_numbers(text):
175
- # πŸ“‹ Formatting text with line numbersβ€”organizing the cosmos one line at a time! πŸ“
176
- lines = text.splitlines()
177
- formatted_text = '\n'.join(f"{i+1}: {line}" for i, line in enumerate(lines))
178
- return formatted_text
179
-
180
-
181
- def generate_unique_id():
182
- return str(uuid.uuid4())
183
-
184
- def get_databases(client):
185
- return [db['id'] for db in client.list_databases()]
186
-
187
- def get_containers(database):
188
- return [container['id'] for container in database.list_containers()]
189
-
190
- def get_documents(container, limit=None):
191
- query = "SELECT * FROM c ORDER BY c._ts DESC"
192
- items = list(container.query_items(query=query, enable_cross_partition_query=True, max_item_count=limit))
193
- return items
194
-
195
- def save_to_cosmos_db(container, query, response1, response2):
196
- try:
197
- if container:
198
- record = {
199
- "id": generate_unique_id(),
200
- "query": query,
201
- "response1": response1,
202
- "response2": response2
203
- }
204
- try:
205
- container.create_item(body=record)
206
- st.success(f"Record saved successfully with ID: {record['id']}")
207
- # Refresh the documents display
208
- st.session_state.documents = get_documents(container)
209
- except exceptions.CosmosHttpResponseError as e:
210
- st.error(f"Error saving record to Cosmos DB: {e}")
211
- else:
212
- st.error("Cosmos DB container is not initialized.")
213
- except Exception as e:
214
- st.error(f"An unexpected error occurred: {str(e)}")
215
-
216
- # Add dropdowns for model and database choices
217
- def search_glossary(query):
218
- st.markdown(f"### πŸ” Search Glossary for: `{query}`")
219
-
220
- # Dropdown for model selection
221
- model_options = ['mistralai/Mixtral-8x7B-Instruct-v0.1', 'mistralai/Mistral-7B-Instruct-v0.2', 'google/gemma-7b-it', 'None']
222
- model_choice = st.selectbox('🧠 Select LLM Model', options=model_options, index=1)
223
-
224
- # Dropdown for database selection
225
- database_options = ['Semantic Search', 'Arxiv Search - Latest - (EXPERIMENTAL)']
226
- database_choice = st.selectbox('πŸ“š Select Database', options=database_options, index=0)
227
-
228
-
229
-
230
- # Run Button with Emoji
231
- #if st.button("πŸš€ Run"):
232
-
233
- # πŸ•΅οΈβ€β™‚οΈ Searching the glossary for: query
234
- all_results = ""
235
- st.markdown(f"- {query}")
236
-
237
- # πŸ” ArXiv RAG researcher expert ~-<>-~ Paper Summary & Ask LLM
238
- #database_choice Literal['Semantic Search', 'Arxiv Search - Latest - (EXPERIMENTAL)'] Default: "Semantic Search"
239
- #llm_model_picked Literal['mistralai/Mixtral-8x7B-Instruct-v0.1', 'mistralai/Mistral-7B-Instruct-v0.2', 'google/gemma-7b-it', 'None'] Default: "mistralai/Mistral-7B-Instruct-v0.2"
240
- client = Client("awacke1/Arxiv-Paper-Search-And-QA-RAG-Pattern")
241
-
242
-
243
- # πŸ” ArXiv RAG researcher expert ~-<>-~ Paper Summary & Ask LLM - api_name: /ask_llm
244
- result = client.predict(
245
- prompt=query,
246
- llm_model_picked="mistralai/Mixtral-8x7B-Instruct-v0.1",
247
- stream_outputs=True,
248
- api_name="/ask_llm"
249
- )
250
- st.markdown(result)
251
- st.code(result, language="python", line_numbers=True)
252
-
253
- # πŸ” ArXiv RAG researcher expert ~-<>-~ Paper Summary & Ask LLM - api_name: /ask_llm
254
- result2 = client.predict(
255
- prompt=query,
256
- llm_model_picked="mistralai/Mistral-7B-Instruct-v0.2",
257
- stream_outputs=True,
258
- api_name="/ask_llm"
259
  )
260
- st.markdown(result2)
261
- st.code(result2, language="python", line_numbers=True)
262
-
263
- # πŸ” ArXiv RAG researcher expert ~-<>-~ Paper Summary & Ask LLM - api_name: /ask_llm
264
- result3 = client.predict(
265
- prompt=query,
266
- llm_model_picked="google/gemma-7b-it",
267
- stream_outputs=True,
268
- api_name="/ask_llm"
269
- )
270
- st.markdown(result3)
271
- st.code(result3, language="python", line_numbers=True)
272
-
273
-
274
- # πŸ” ArXiv RAG researcher expert ~-<>-~ Paper Summary & Ask LLM - api_name: /update_with_rag_md
275
- response2 = client.predict(
276
- message=query, # str in 'parameter_13' Textbox component
277
- llm_results_use=10,
278
- database_choice="Semantic Search",
279
- llm_model_picked="mistralai/Mistral-7B-Instruct-v0.2",
280
- api_name="/update_with_rag_md"
281
- ) # update_with_rag_md Returns tuple of 2 elements [0] str The output value that appears in the "value_14" Markdown component. [1] str
282
-
283
- st.markdown(response2[0])
284
- st.code(response2[0], language="python", line_numbers=True, wrap_lines=True)
285
-
286
- st.markdown(response2[1])
287
- st.code(response2[1], language="python", line_numbers=True, wrap_lines=True)
288
-
289
- # When saving results, pass the container
290
- try:
291
- save_to_cosmos_db(st.session_state.cosmos_container, query, result, result)
292
- save_to_cosmos_db(st.session_state.cosmos_container, query, result2, result2)
293
- save_to_cosmos_db(st.session_state.cosmos_container, query, result3, result3)
294
- save_to_cosmos_db(st.session_state.cosmos_container, query, response2[0], response2[0])
295
- save_to_cosmos_db(st.session_state.cosmos_container, query, response2[1], response2[1])
296
- except exceptions.CosmosHttpResponseError as e:
297
- return False, f"HTTP error occurred: {str(e)} 🚨"
298
- except Exception as e:
299
- return False, f"An unexpected error occurred: {str(e)} 😱"
300
-
301
-
302
- try:
303
- # Aggregate hyperlinks and show with emojis
304
- hyperlinks = extract_hyperlinks([response1, response2])
305
- st.markdown("### πŸ”— Aggregated Hyperlinks")
306
- for link in hyperlinks:
307
- st.markdown(f"πŸ”— [{link}]({link})")
308
-
309
- # Show responses in a code format with line numbers
310
- st.markdown("### πŸ“œ Response Outputs with Line Numbers")
311
- st.code(f"Response 1: \n{format_with_line_numbers(response1)}\n\nResponse 2: \n{format_with_line_numbers(response2)}", language="json")
312
- except exceptions.CosmosHttpResponseError as e:
313
- return False, f"HTTP error occurred: {str(e)} 🚨"
314
- except Exception as e:
315
- return False, f"An unexpected error occurred: {str(e)} 😱"
316
-
317
-
318
 
 
 
 
 
 
 
319
 
320
- # 🎀 Function to process text input
321
- def process_text(text_input):
322
- # 🎀 Processing text inputβ€”translating human words into cosmic signals! πŸ“‘
323
- if text_input:
324
- if 'messages' not in st.session_state:
325
- st.session_state.messages = []
326
-
327
- st.session_state.messages.append({"role": "user", "content": text_input})
328
-
329
- with st.chat_message("user"):
330
- st.markdown(text_input)
331
-
332
- with st.chat_message("assistant"):
333
- search_glossary(text_input)
334
-
335
- # πŸ“ Function to generate a filename
336
- def generate_filename(text, file_type):
337
- # πŸ“ Generate a filename based on the text input
338
- safe_text = "".join(c if c.isalnum() or c in (' ', '.', '_') else '_' for c in text)
339
- safe_text = "_".join(safe_text.strip().split())
340
- filename = f"{safe_text}.{file_type}"
341
- return filename
342
-
343
- # πŸ•΅οΈβ€β™€οΈ Function to extract markdown title
344
- def extract_markdown_title(content):
345
- # πŸ•΅οΈβ€β™€οΈ Extracting markdown titleβ€”finding the headline in the cosmic news! πŸ“°
346
- lines = content.splitlines()
347
- for line in lines:
348
- if line.startswith('#'):
349
- return line.lstrip('#').strip()
350
- return None
351
-
352
- # πŸ’Ύ Function to create and save a file
353
- def create_and_save_file(content, file_type="md", prompt=None, is_image=False, should_save=True):
354
- # πŸ’Ύ Creating and saving a fileβ€”capturing cosmic wisdom! πŸ“
355
  if not should_save:
356
- return None
357
-
358
- # Step 1: Generate filename based on the prompt or content
359
- filename = generate_filename(prompt if prompt else content, file_type)
360
-
361
- # Step 2: If it's a markdown file, check if it has a title
362
- if file_type == "md":
363
- title_from_content = extract_markdown_title(content)
364
- if title_from_content:
365
- filename = generate_filename(title_from_content, file_type)
366
-
367
- # Step 3: Save the file
368
- with open(filename, "w", encoding="utf-8") as f:
369
- if is_image:
370
- f.write(content)
371
- else:
372
- f.write(prompt + "\n\n" + content)
373
-
374
- return filename
375
-
376
- # πŸ€– Function to insert an auto-generated record
377
- def insert_auto_generated_record(container):
378
- # πŸ€– Automatically generating a record and inserting it into Cosmos DB!
379
- try:
380
- # Generate a unique id
381
- new_id = generate_unique_id()
382
- # Create a sample JSON document
383
- new_doc = {
384
- 'id': new_id,
385
- 'name': f'Sample Name {new_id[:8]}',
386
- 'description': 'This is a sample auto-generated description.',
387
- 'timestamp': datetime.utcnow().isoformat()
388
- }
389
- # Insert the document
390
- container.create_item(body=new_doc)
391
- return True, f"Record inserted successfully with id: {new_id} πŸŽ‰"
392
- except exceptions.CosmosHttpResponseError as e:
393
- return False, f"HTTP error occurred: {str(e)} 🚨"
394
- except Exception as e:
395
- return False, f"An unexpected error occurred: {str(e)} 😱"
396
-
397
- # 🎈 Main function
398
  def main():
399
- # 🎈 Let's modify the main app to be more fun!
400
- st.title("πŸ™Git🌌CosmosπŸ’« - Azure Cosmos DB and Github Agent")
401
 
402
- # 🚦 Initialize session state
403
- if 'logged_in' not in st.session_state:
404
- st.session_state.logged_in = False
405
- if 'selected_records' not in st.session_state:
406
- st.session_state.selected_records = []
407
- if 'client' not in st.session_state:
408
- st.session_state.client = None
409
- if 'selected_database' not in st.session_state:
410
- st.session_state.selected_database = None
411
- if 'selected_container' not in st.session_state:
412
- st.session_state.selected_container = None
413
- if 'selected_document_id' not in st.session_state:
414
- st.session_state.selected_document_id = None
415
- if 'current_index' not in st.session_state:
416
- st.session_state.current_index = 0
417
- if 'cloned_doc' not in st.session_state:
418
- st.session_state.cloned_doc = None
419
-
420
- # βš™οΈ q= Run ArXiv search from query parameters
421
- try:
422
- query_params = st.query_params
423
- query = query_params.get('q') or query_params.get('query') or ''
424
- if query:
425
- # πŸ•΅οΈβ€β™‚οΈ We have a query! Let's process it!
426
- process_text(query)
427
- st.stop() # Stop further execution
428
- except Exception as e:
429
- st.markdown(' ')
430
-
431
- # πŸ” Automatic Login
432
  if Key:
433
  st.session_state.primary_key = Key
434
  st.session_state.logged_in = True
435
- else:
436
- st.error("Cosmos DB Key is not set in environment variables. πŸ”‘βŒ")
437
- return # Can't proceed without a key
438
 
439
- if st.session_state.logged_in:
440
- # 🌌 Initialize Cosmos DB client
441
- try:
442
- if st.session_state.client is None:
443
- st.session_state.client = CosmosClient(ENDPOINT, credential=st.session_state.primary_key)
444
-
445
- # πŸ—„οΈ Sidebar for database, container, and document selection
446
- st.sidebar.title("πŸ™Git🌌CosmosπŸ’«πŸ—„οΈNavigator")
447
 
448
- databases = get_databases(st.session_state.client)
449
- selected_db = st.sidebar.selectbox("πŸ—ƒοΈ Select Database", databases)
 
 
450
 
451
- if selected_db != st.session_state.selected_database:
452
- st.session_state.selected_database = selected_db
453
- st.session_state.selected_container = None
454
- st.session_state.selected_document_id = None
455
- st.session_state.current_index = 0
456
- st.rerun()
457
-
458
- if st.session_state.selected_database:
459
- database = st.session_state.client.get_database_client(st.session_state.selected_database)
460
- containers = get_containers(database)
461
- selected_container = st.sidebar.selectbox("πŸ“ Select Container", containers)
462
-
463
- if selected_container != st.session_state.selected_container:
464
- st.session_state.selected_container = selected_container
465
- st.session_state.selected_document_id = None
466
- st.session_state.current_index = 0
467
- st.rerun()
468
 
469
- if st.session_state.selected_container:
470
- container = database.get_container_client(st.session_state.selected_container)
471
-
472
- # πŸ“¦ Add Export button
473
- if st.button("πŸ“¦ Export Container Data"):
474
- download_link = archive_current_container(st.session_state.selected_database, st.session_state.selected_container, st.session_state.client)
475
- if download_link.startswith('<a'):
476
- st.markdown(download_link, unsafe_allow_html=True)
477
- else:
478
- st.error(download_link)
479
-
480
- # Fetch documents
481
- documents = get_documents(container)
482
- total_docs = len(documents)
483
-
484
- if total_docs > 5:
485
- documents_to_display = documents[:5]
486
- st.info("Showing top 5 most recent documents.")
487
- else:
488
- documents_to_display = documents
489
- st.info(f"Showing all {len(documents_to_display)} documents.")
490
-
491
- if documents_to_display:
492
- # 🎨 Add Viewer/Editor selection
493
- view_options = ['Show as Markdown', 'Show as Code Editor', 'Show as Edit and Save', 'Clone Document', 'New Record']
494
- selected_view = st.selectbox("Select Viewer/Editor", view_options, index=2)
495
-
496
- if selected_view == 'Show as Markdown':
497
- # πŸ–ŒοΈ Show each record as Markdown with navigation
498
- total_docs = len(documents)
499
- doc = documents[st.session_state.current_index]
500
- st.markdown(f"#### Document ID: {doc.get('id', '')}")
501
-
502
- # πŸ•΅οΈβ€β™‚οΈ Let's extract values from the JSON that have at least one space
503
- values_with_space = []
504
- def extract_values(obj):
505
- if isinstance(obj, dict):
506
- for k, v in obj.items():
507
- extract_values(v)
508
- elif isinstance(obj, list):
509
- for item in obj:
510
- extract_values(item)
511
- elif isinstance(obj, str):
512
- if ' ' in obj:
513
- values_with_space.append(obj)
514
-
515
- extract_values(doc)
516
-
517
- # πŸ”— Let's create a list of links for these values
518
- search_urls = {
519
- "πŸš€πŸŒŒArXiv": lambda k: f"{LOCAL_APP_URL}/?q={quote(k)}",
520
- "πŸƒAnalyst": lambda k: f"{LOCAL_APP_URL}/?q={quote(k)}-{quote('PromptPrefix')}",
521
- "πŸ“šPyCoder": lambda k: f"{LOCAL_APP_URL}/?q={quote(k)}-{quote('PromptPrefix2')}",
522
- "πŸ”¬JSCoder": lambda k: f"{LOCAL_APP_URL}/?q={quote(k)}-{quote('PromptPrefix3')}",
523
- "🏠": lambda k: f"{LOCAL_APP_URL}/?q={quote(k)}",
524
- "πŸ“–": lambda k: f"https://en.wikipedia.org/wiki/{quote(k)}",
525
- "πŸ”": lambda k: f"https://www.google.com/search?q={quote(k)}",
526
- "▢️": lambda k: f"https://www.youtube.com/results?search_query={quote(k)}",
527
- "πŸ”Ž": lambda k: f"https://www.bing.com/search?q={quote(k)}",
528
- "πŸŽ₯": lambda k: f"https://www.youtube.com/results?search_query={quote(k)}",
529
- "🐦": lambda k: f"https://twitter.com/search?q={quote(k)}",
530
- }
531
-
532
- st.markdown("#### πŸ”— Links for Extracted Texts")
533
- for term in values_with_space:
534
- links_md = ' '.join([f"[{emoji}]({url(term)})" for emoji, url in search_urls.items()])
535
- st.markdown(f"**{term}** <small>{links_md}</small>", unsafe_allow_html=True)
536
-
537
- # Show the document content as markdown
538
- content = json.dumps(doc, indent=2)
539
- st.markdown(f"```json\n{content}\n```")
540
-
541
- # Navigation buttons
542
- col_prev, col_next = st.columns([1, 1])
543
- with col_prev:
544
- if st.button("⬅️ Previous", key='prev_markdown'):
545
- if st.session_state.current_index > 0:
546
- st.session_state.current_index -= 1
547
- st.rerun()
548
- with col_next:
549
- if st.button("➑️ Next", key='next_markdown'):
550
- if st.session_state.current_index < total_docs - 1:
551
- st.session_state.current_index += 1
552
- st.rerun()
553
-
554
- elif selected_view == 'Show as Code Editor':
555
- # πŸ’» Show each record in a code editor with navigation
556
- total_docs = len(documents)
557
- doc = documents[st.session_state.current_index]
558
- st.markdown(f"#### Document ID: {doc.get('id', '')}")
559
- doc_str = st.text_area("Edit Document", value=json.dumps(doc, indent=2), height=300, key=f'code_editor_{st.session_state.current_index}')
560
- col_prev, col_next = st.columns([1, 1])
561
- with col_prev:
562
- if st.button("⬅️ Previous", key='prev_code'):
563
- if st.session_state.current_index > 0:
564
- st.session_state.current_index -= 1
565
- st.rerun()
566
- with col_next:
567
- if st.button("➑️ Next", key='next_code'):
568
- if st.session_state.current_index < total_docs - 1:
569
- st.session_state.current_index += 1
570
- st.rerun()
571
- if st.button("πŸ’Ύ Save Changes", key=f'save_button_{st.session_state.current_index}'):
572
- try:
573
- updated_doc = json.loads(doc_str)
574
- success, message = update_record(container, updated_doc)
575
- if success:
576
- st.success(f"Document {updated_doc['id']} saved successfully.")
577
- st.session_state.selected_document_id = updated_doc['id']
578
- st.rerun()
579
- else:
580
- st.error(message)
581
- except json.JSONDecodeError as e:
582
- st.error(f"Invalid JSON: {str(e)} 🚫")
583
-
584
- elif selected_view == 'Show as Edit and Save':
585
- # ✏️ Show as Edit and Save in columns
586
- st.markdown("#### Edit the document fields below:")
587
-
588
- # Create columns for each document
589
- num_cols = len(documents_to_display)
590
- cols = st.columns(num_cols)
591
-
592
-
593
- for idx, (col, doc) in enumerate(zip(cols, documents_to_display)):
594
- with col:
595
- st.markdown(f"##### Document ID: {doc.get('id', '')}")
596
- editable_id = st.text_input("ID", value=doc.get('id', ''), key=f'edit_id_{idx}')
597
- # Remove 'id' from the document for editing other fields
598
- editable_doc = doc.copy()
599
- editable_doc.pop('id', None)
600
- doc_str = st.text_area("Document Content (in JSON format)", value=json.dumps(editable_doc, indent=2), height=300, key=f'doc_str_{idx}')
601
-
602
- # Add the "Run With AI" button next to "Save Changes"
603
- col_save, col_ai = st.columns(2)
604
- with col_save:
605
- if st.button("πŸ’Ύ Save Changes", key=f'save_button_{idx}'):
606
- try:
607
- updated_doc = json.loads(doc_str)
608
- updated_doc['id'] = editable_id # Include the possibly edited ID
609
- success, message = update_record(container, updated_doc)
610
- if success:
611
- st.success(f"Document {updated_doc['id']} saved successfully.")
612
- st.session_state.selected_document_id = updated_doc['id']
613
- st.rerun()
614
- else:
615
- st.error(message)
616
- except json.JSONDecodeError as e:
617
- st.error(f"Invalid JSON: {str(e)} 🚫")
618
- with col_ai:
619
- if st.button("πŸ€– Run With AI", key=f'run_with_ai_button_{idx}'):
620
- # Use the entire document as input
621
- search_glossary(json.dumps(editable_doc, indent=2))
622
-
623
-
624
-
625
-
626
-
627
- elif selected_view == 'Clone Document':
628
- # 🧬 Clone Document per record
629
- st.markdown("#### Clone a document:")
630
- for idx, doc in enumerate(documents_to_display):
631
- st.markdown(f"##### Document ID: {doc.get('id', '')}")
632
- if st.button("πŸ“„ Clone Document", key=f'clone_button_{idx}'):
633
- cloned_doc = doc.copy()
634
- # Generate a unique ID
635
- cloned_doc['id'] = generate_unique_id()
636
- st.session_state.cloned_doc = cloned_doc
637
- st.session_state.cloned_doc_str = json.dumps(cloned_doc, indent=2)
638
- st.session_state.clone_mode = True
639
- st.rerun()
640
- if st.session_state.get('clone_mode', False):
641
- st.markdown("#### Edit Cloned Document:")
642
- cloned_doc_str = st.text_area("Cloned Document Content (in JSON format)", value=st.session_state.cloned_doc_str, height=300)
643
- if st.button("πŸ’Ύ Save Cloned Document"):
644
- try:
645
- new_doc = json.loads(cloned_doc_str)
646
- success, message = insert_record(container, new_doc)
647
- if success:
648
- st.success(f"Cloned document saved with id: {new_doc['id']} πŸŽ‰")
649
- st.session_state.selected_document_id = new_doc['id']
650
- st.session_state.clone_mode = False
651
- st.session_state.cloned_doc = None
652
- st.session_state.cloned_doc_str = ''
653
- st.rerun()
654
- else:
655
- st.error(message)
656
- except json.JSONDecodeError as e:
657
- st.error(f"Invalid JSON: {str(e)} 🚫")
658
-
659
- elif selected_view == 'New Record':
660
- # πŸ†• New Record
661
- st.markdown("#### Create a new document:")
662
- if st.button("πŸ€– Insert Auto-Generated Record"):
663
- success, message = insert_auto_generated_record(container)
664
- if success:
665
- st.success(message)
666
- st.rerun()
667
- else:
668
- st.error(message)
669
- else:
670
- new_id = st.text_input("ID", value=generate_unique_id(), key='new_id')
671
- new_doc_str = st.text_area("Document Content (in JSON format)", value='{}', height=300)
672
- if st.button("βž• Create New Document"):
673
- try:
674
- new_doc = json.loads(new_doc_str)
675
- new_doc['id'] = new_id # Use the provided ID
676
- success, message = insert_record(container, new_doc)
677
- if success:
678
- st.success(f"New document created with id: {new_doc['id']} πŸŽ‰")
679
- st.session_state.selected_document_id = new_doc['id']
680
- # Switch to 'Show as Edit and Save' mode
681
- st.rerun()
682
- else:
683
- st.error(message)
684
- except json.JSONDecodeError as e:
685
- st.error(f"Invalid JSON: {str(e)} 🚫")
686
-
687
  else:
688
- st.sidebar.info("No documents found in this container. πŸ“­")
689
-
690
- # πŸŽ‰ Main content area
691
- st.subheader(f"πŸ“Š Container: {st.session_state.selected_container}")
692
- if st.session_state.selected_container:
693
- if documents_to_display:
694
- df = pd.DataFrame(documents_to_display)
695
- st.dataframe(df)
696
- else:
697
- st.info("No documents to display. 🧐")
698
-
699
- # πŸ™ GitHub section
700
- st.subheader("πŸ™ GitHub Operations")
701
- github_token = os.environ.get("GITHUB") # Read GitHub token from environment variable
702
- source_repo = st.text_input("Source GitHub Repository URL", value="https://github.com/AaronCWacker/AIExamples-8-24-Streamlit")
703
- new_repo_name = st.text_input("New Repository Name (for cloning)", value=f"AIExample-Clone-{datetime.now().strftime('%Y%m%d_%H%M%S')}")
704
-
705
- col1, col2 = st.columns(2)
706
- with col1:
707
- if st.button("πŸ“₯ Clone Repository"):
708
- if github_token and source_repo:
709
- try:
710
- local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d%H%M%S')}"
711
- download_github_repo(source_repo, local_path)
712
- zip_filename = f"{new_repo_name}.zip"
713
- create_zip_file(local_path, zip_filename[:-4])
714
- st.markdown(get_base64_download_link(zip_filename, zip_filename), unsafe_allow_html=True)
715
- st.success("Repository cloned successfully! πŸŽ‰")
716
- except Exception as e:
717
- st.error(f"An error occurred: {str(e)} 😒")
718
- finally:
719
- if os.path.exists(local_path):
720
- shutil.rmtree(local_path)
721
- if os.path.exists(zip_filename):
722
- os.remove(zip_filename)
723
- else:
724
- st.error("Please ensure GitHub token is set in environment variables and source repository URL is provided. πŸ”‘β“")
725
-
726
- with col2:
727
- if st.button("πŸ“€ Push to New Repository"):
728
- if github_token and source_repo:
729
- try:
730
- g = Github(github_token)
731
- new_repo = create_repo(g, new_repo_name)
732
- local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d%H%M%S')}"
733
- download_github_repo(source_repo, local_path)
734
- push_to_github(local_path, new_repo, github_token)
735
- st.success(f"Repository pushed successfully to {new_repo.html_url} πŸš€")
736
- except Exception as e:
737
- st.error(f"An error occurred: {str(e)} 😒")
738
- finally:
739
- if os.path.exists(local_path):
740
- shutil.rmtree(local_path)
741
- else:
742
- st.error("Please ensure GitHub token is set in environment variables and source repository URL is provided. πŸ”‘β“")
743
-
744
- except exceptions.CosmosHttpResponseError as e:
745
- st.error(f"Failed to connect to Cosmos DB. HTTP error: {str(e)} 🚨")
746
- except Exception as e:
747
- st.error(f"An unexpected error occurred: {str(e)} 😱")
748
-
749
- # πŸšͺ Logout button
750
- if st.session_state.logged_in and st.sidebar.button("πŸšͺ Logout"):
751
- st.session_state.logged_in = False
752
- st.session_state.selected_records.clear()
753
- st.session_state.client = None
754
- st.session_state.selected_database = None
755
- st.session_state.selected_container = None
756
- st.session_state.selected_document_id = None
757
- st.session_state.current_index = 0
758
- st.rerun()
759
 
760
  if __name__ == "__main__":
761
  main()
 
12
  import uuid # 🎲 For generating unique IDs
13
  from urllib.parse import quote # πŸ”— For encoding URLs
14
  from gradio_client import Client # 🌐 For connecting to Gradio apps
15
+ import anthropic
16
+ import pytz
17
+ import re
18
+ from PIL import Image
19
+ import glob
20
+ from streamlit.components.v1 import html
21
+
22
+ # πŸŽ‰ Welcome to our epic Cosmos DB, GitHub, and Claude App! The universe is at your command πŸš€
23
+ st.set_page_config(
24
+ page_title="πŸ€–Git🌌CosmosπŸ’« & Claude🧠",
25
+ page_icon="πŸ€–πŸŒŒπŸ’«πŸ“",
26
+ layout="wide",
27
+ initial_sidebar_state="auto",
28
+ menu_items={
29
+ 'Get Help': 'https://huggingface.co/awacke1',
30
+ 'Report a bug': 'https://huggingface.co/spaces/awacke1',
31
+ 'About': 'πŸ™Git🌌CosmosπŸ’« - Azure Cosmos DB and GitHub Agent, Now with Claude!'
32
+ }
33
+ )
34
 
35
  # 🌌 Cosmos DB configuration
36
  ENDPOINT = "https://acae-afd.documents.azure.com:443/"
 
38
  CONTAINER_NAME = os.environ.get("COSMOS_CONTAINER_NAME")
39
  Key = os.environ.get("Key") # πŸ”‘ Don't forget your key!
40
 
41
+ # Set up the Anthropic client (Claude time πŸ€–πŸ§ )
42
+ client_anthropic = anthropic.Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))
43
 
44
+ # Set up Gradio client for ArXiv queries (ArXiv, the scholar's playground πŸŽ“)
45
+ client_gradio = Client("awacke1/Arxiv-Paper-Search-And-QA-RAG-Pattern")
 
46
 
47
  # πŸ™ GitHub configuration
48
  def download_github_repo(url, local_path):
 
56
  shutil.make_archive(output_filename, 'zip', source_dir)
57
 
58
  def create_repo(g, repo_name):
59
+ # πŸ› οΈ Creating a new GitHub repo. It's alive!
60
  user = g.get_user()
61
  return user.create_repo(repo_name)
62
 
63
  def push_to_github(local_path, repo, github_token):
64
+ # πŸš€ Pushing code to GitHub. Blast off!
65
  repo_url = f"https://{github_token}@github.com/{repo.full_name}.git"
66
  local_repo = Repo(local_path)
67
 
68
+ if 'origin' in [remote.name for remote.local_repo.remotes]:
69
  origin = local_repo.remote('origin')
70
  origin.set_url(repo_url)
71
  else:
 
91
  base64_encoded = base64.b64encode(contents).decode()
92
  return f'<a href="data:application/zip;base64,{base64_encoded}" download="{file_name}">⬇️ Download {file_name}</a>'
93
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  # 🌟 Cosmos DB functions
95
  def insert_record(container, record):
 
96
  try:
97
  container.create_item(body=record)
98
  return True, "Record inserted successfully! πŸŽ‰"
 
101
  except Exception as e:
102
  return False, f"An unexpected error occurred: {str(e)} 😱"
103
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  # 🎲 Function to generate a unique UUID
105
  def generate_unique_id():
 
106
  return str(uuid.uuid4())
107
 
108
+ # Claude 🧠 Chat handling (Wise responses guaranteed! πŸ€–)
109
+ def chat_with_claude(user_input):
110
+ response = client_anthropic.messages.create(
111
+ model="claude-3-sonnet-20240229",
112
+ max_tokens=1000,
113
+ messages=[
114
+ {"role": "user", "content": user_input}
115
+ ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  )
117
+ return response.content[0].text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
 
119
+ # File handling (Save that wisdom in files! πŸ’Ύ)
120
+ def generate_filename(prompt, file_type):
121
+ central = pytz.timezone('US/Central')
122
+ safe_date_time = datetime.now(central).strftime("%m%d_%H%M")
123
+ safe_prompt = re.sub(r'\W+', '_', prompt)[:90]
124
+ return f"{safe_date_time}_{safe_prompt}.{file_type}"
125
 
126
+ def create_file(filename, prompt, response, should_save=True):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
  if not should_save:
128
+ return
129
+ with open(filename, 'w', encoding='utf-8') as file:
130
+ file.write(prompt + "\n\n" + response)
131
+
132
+ def load_file(file_name):
133
+ with open(file_name, "r", encoding='utf-8') as file:
134
+ content = file.read()
135
+ return content
136
+
137
+ # 🎨 Image and media handling (Let's look at some visuals! πŸ“ΈπŸŽ¬πŸŽΆ)
138
+ def get_video_html(video_path, width="100%"):
139
+ video_url = f"data:video/mp4;base64,{base64.b64encode(open(video_path, 'rb').read()).decode()}"
140
+ return f'''
141
+ <video width="{width}" controls autoplay muted loop>
142
+ <source src="{video_url}" type="video/mp4">
143
+ Your browser does not support the video tag.
144
+ </video>
145
+ '''
146
+
147
+ def get_audio_html(audio_path, width="100%"):
148
+ audio_url = f"data:audio/mpeg;base64,{base64.b64encode(open(audio_path, 'rb').read()).decode()}"
149
+ return f'''
150
+ <audio controls style="width: {width};">
151
+ <source src="{audio_url}" type="audio/mpeg">
152
+ Your browser does not support the audio element.
153
+ </audio>
154
+ '''
155
+
156
+ # Streamlit layout (because a clean UI is key! 🏠)
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  def main():
158
+ st.title("πŸ™Git🌌CosmosπŸ’« & Claude🧠 - The Ultimate App")
 
159
 
160
+ # Sidebar navigation (The command center 🧭)
161
+ st.sidebar.title("🧠ClaudeπŸ“ & Cosmos Explorer")
162
+
163
+ # Cosmos DB Section
164
+ st.sidebar.header("Cosmos DB Controls")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
  if Key:
166
  st.session_state.primary_key = Key
167
  st.session_state.logged_in = True
 
 
 
168
 
169
+ if st.session_state.logged_in:
170
+ st.sidebar.write("πŸ” Connected to Cosmos DB!")
 
 
 
 
 
 
171
 
172
+ # Fetch documents
173
+ cosmos_client = CosmosClient(ENDPOINT, credential=st.session_state.primary_key)
174
+ databases = [db['id'] for db in cosmos_client.list_databases()]
175
+ selected_db = st.sidebar.selectbox("Select Database", databases)
176
 
177
+ if selected_db:
178
+ db_client = cosmos_client.get_database_client(selected_db)
179
+ containers = [container['id'] for container in db_client.list_containers()]
180
+ selected_container = st.sidebar.selectbox("Select Container", containers)
 
 
 
 
 
 
 
 
 
 
 
 
 
181
 
182
+ if selected_container:
183
+ container = db_client.get_container_client(selected_container)
184
+ documents = list(container.read_all_items())
185
+ if documents:
186
+ st.write("πŸ“ Document List:")
187
+ df = pd.DataFrame(documents)
188
+ st.dataframe(df)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
189
  else:
190
+ st.write("πŸ“­ No documents in this container.")
191
+
192
+ # Claude Chat Section
193
+ st.header("Chat with Claude πŸ€–πŸ§ ")
194
+ user_input = st.text_area("Ask Claude anything:")
195
+ if st.button("Send"):
196
+ if user_input:
197
+ response = chat_with_claude(user_input)
198
+ st.write(f"Claude says: {response}")
199
+
200
+ filename = generate_filename(user_input, "md")
201
+ create_file(filename, user_input, response)
202
+
203
+ if 'chat_history' not in st.session_state:
204
+ st.session_state.chat_history = []
205
+ st.session_state.chat_history.append({"user": user_input, "claude": response})
206
+
207
+ if "chat_history" in st.session_state:
208
+ st.subheader("Past Conversations πŸ“œ")
209
+ for chat in st.session_state.chat_history:
210
+ st.text_area("You said πŸ’¬:", chat["user"], height=100, disabled=True)
211
+ st.text_area("Claude replied πŸ€–:", chat["claude"], height=200, disabled=True)
212
+ st.markdown("---")
213
+
214
+ # Media Galleries (For those who prefer images and videos πŸ–ΌπŸŽ₯🎢)
215
+ st.subheader("Image Gallery πŸ–Ό")
216
+ image_files = glob.glob("*.png") + glob.glob("*.jpg")
217
+ cols = st.columns(3)
218
+ for idx, image_file in enumerate(image_files):
219
+ with cols[idx % 3]:
220
+ img = Image.open(image_file)
221
+ st.image(img)
222
+
223
+ st.subheader("Video Gallery πŸŽ₯")
224
+ video_files = glob.glob("*.mp4")
225
+ for video_file in video_files:
226
+ st.markdown(get_video_html(video_file), unsafe_allow_html=True)
227
+
228
+ st.subheader("Audio Gallery 🎢")
229
+ audio_files = glob.glob("*.mp3") + glob.glob("*.wav")
230
+ for audio_file in audio_files:
231
+ st.markdown(get_audio_html(audio_file), unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232
 
233
  if __name__ == "__main__":
234
  main()