awacke1/PythonAIPairProgrammer
2
1import streamlit as st2import streamlit.components.v1 as components3import os4import base645import glob6import io7import json8import mistune9import pytz10import math11import requests12import sys13import time14import re15import textract16import zipfile 17import random18import httpx # add 11/13/2319import asyncio20from openai import OpenAI21#from openai import AsyncOpenAI22from datetime import datetime23from xml.etree import ElementTree as ET24from bs4 import BeautifulSoup25from collections import deque26from audio_recorder_streamlit import audio_recorder27from dotenv import load_dotenv28from PyPDF2 import PdfReader29from langchain.text_splitter import CharacterTextSplitter30from langchain.embeddings import OpenAIEmbeddings31from langchain.vectorstores import FAISS32from langchain.chat_models import ChatOpenAI33from langchain.memory import ConversationBufferMemory34from langchain.chains import ConversationalRetrievalChain35from templates import css, bot_template, user_template36from io import BytesIO37from contextlib import redirect_stdout38 39 40# set page config once41st.set_page_config(page_title="Python AI Pair Programmer", layout="wide")42 43# UI for sidebar controls44should_save = st.sidebar.checkbox("๐พ Save", value=True)45col1, col2, col3, col4 = st.columns(4)46with col1:47 with st.expander("Settings ๐ง ๐พ", expanded=True):48 # File type for output, model choice49 menu = ["txt", "htm", "xlsx", "csv", "md", "py"]50 choice = st.sidebar.selectbox("Output File Type:", menu)51 model_choice = st.sidebar.radio("Select Model:", ('gpt-3.5-turbo', 'gpt-3.5-turbo-0301'))52 53# Define a context dictionary to maintain the state between exec calls54context = {}55 56def create_file(filename, prompt, response, should_save=True):57 if not should_save:58 return59 60 # Extract base filename without extension61 base_filename, ext = os.path.splitext(filename)62 63 # Initialize the combined content64 combined_content = ""65 66 # Add Prompt with markdown title and emoji67 combined_content += "# Prompt ๐\n" + prompt + "\n\n"68 69 # Add Response with markdown title and emoji70 combined_content += "# Response ๐ฌ\n" + response + "\n\n"71 72 # Check for code blocks in the response73 resources = re.findall(r"```([\s\S]*?)```", response)74 for resource in resources:75 # Check if the resource contains Python code76 if "python" in resource.lower():77 # Remove the 'python' keyword from the code block78 cleaned_code = re.sub(r'^\s*python', '', resource, flags=re.IGNORECASE | re.MULTILINE)79 80 # Add Code Results title with markdown and emoji81 combined_content += "# Code Results ๐\n"82 83 # Redirect standard output to capture it84 original_stdout = sys.stdout85 sys.stdout = io.StringIO()86 87 # Execute the cleaned Python code within the context88 try:89 exec(cleaned_code, context)90 code_output = sys.stdout.getvalue()91 combined_content += f"```\n{code_output}\n```\n\n"92 realtimeEvalResponse = "# Code Results ๐\n" + "```" + code_output + "```\n\n"93 st.code(realtimeEvalResponse)94 95 except Exception as e:96 combined_content += f"```python\nError executing Python code: {e}\n```\n\n"97 98 # Restore the original standard output99 sys.stdout = original_stdout100 else:101 # Add non-Python resources with markdown and emoji102 combined_content += "# Resource ๐ ๏ธ\n" + "```" + resource + "```\n\n"103 104 # Save the combined content to a Markdown file105 if should_save:106 with open(f"{base_filename}.md", 'w') as file:107 file.write(combined_content)108 st.code(combined_content)109 110 # Create a Base64 encoded link for the file111 with open(f"{base_filename}.md", 'rb') as file:112 encoded_file = base64.b64encode(file.read()).decode()113 href = f'<a href="data:file/markdown;base64,{encoded_file}" download="{filename}">Download File ๐</a>'114 st.markdown(href, unsafe_allow_html=True)115 116 117# Read it aloud 118def readitaloud(result):119 documentHTML5='''120 <!DOCTYPE html>121 <html>122 <head>123 <title>Read It Aloud</title>124 <script type="text/javascript">125 function readAloud() {126 const text = document.getElementById("textArea").value;127 const speech = new SpeechSynthesisUtterance(text);128 window.speechSynthesis.speak(speech);129 }130 </script>131 </head>132 <body>133 <h1>๐ Read It Aloud</h1>134 <textarea id="textArea" rows="10" cols="80">135 '''136 documentHTML5 = documentHTML5 + result137 documentHTML5 = documentHTML5 + '''138 </textarea>139 <br>140 <button onclick="readAloud()">๐ Read Aloud</button>141 </body>142 </html>143 '''144 145 components.html(documentHTML5, width=800, height=300)146 #return result147 148def generate_filename(prompt, file_type):149 central = pytz.timezone('US/Central')150 safe_date_time = datetime.now(central).strftime("%m%d_%H%M")151 replaced_prompt = prompt.replace(" ", "_").replace("\n", "_")152 safe_prompt = "".join(x for x in replaced_prompt if x.isalnum() or x == "_")[:90]153 return f"{safe_date_time}_{safe_prompt}.{file_type}"154 155# Chat and Chat with files156def chat_with_model(prompt, document_section, model_choice='gpt-3.5-turbo'):157 model = model_choice158 conversation = [{'role': 'system', 'content': 'You are a python script writer.'}]159 conversation.append({'role': 'user', 'content': prompt})160 if len(document_section)>0:161 conversation.append({'role': 'assistant', 'content': document_section})162 start_time = time.time()163 report = []164 res_box = st.empty()165 collected_chunks = []166 collected_messages = []167 key = os.getenv('OPENAI_API_KEY')168 169 client = OpenAI(170 api_key= os.getenv('OPENAI_API_KEY')171 )172 stream = client.chat.completions.create(173 model='gpt-3.5-turbo',174 messages=conversation,175 stream=True,176 )177 all_content = "" # Initialize an empty string to hold all content178 for part in stream:179 chunk_message = (part.choices[0].delta.content or "")180 collected_messages.append(chunk_message) # save the message181 content=part.choices[0].delta.content182 try:183 if len(content) > 0:184 report.append(content)185 all_content += content 186 result = "".join(report).strip()187 res_box.markdown(f'*{result}*') 188 except:189 st.write(' ')190 full_reply_content = all_content191 st.write("Elapsed time:")192 st.write(time.time() - start_time)193 filename = generate_filename(full_reply_content, choice)194 create_file(filename, prompt, full_reply_content, should_save)195 readitaloud(full_reply_content)196 return full_reply_content197 198def chat_with_file_contents(prompt, file_content, model_choice='gpt-3.5-turbo'):199 conversation = [{'role': 'system', 'content': 'You are a helpful assistant.'}]200 conversation.append({'role': 'user', 'content': prompt})201 if len(file_content)>0:202 conversation.append({'role': 'assistant', 'content': file_content})203 client = OpenAI(204 api_key= os.getenv('OPENAI_API_KEY')205 )206 response = client.chat.completions.create(model=model_choice, messages=conversation)207 return response['choices'][0]['message']['content']208 209def link_button_with_emoji(url, title, emoji_summary):210 emojis = ["๐", "๐ฅ", "๐ก๏ธ", "๐ฉบ", "๐ฌ", "๐", "๐งช", "๐จโโ๏ธ", "๐ฉโโ๏ธ"]211 random_emoji = random.choice(emojis)212 st.markdown(f"[{random_emoji} {emoji_summary} - {title}]({url})")213 214 215# Python parts and their corresponding emojis, with expanded details216python_parts = {217 "Syntax": "โ๏ธ",218 "Data Types": "๐",219 "Control Structures": "๐",220 "Functions": "๐ง",221 "Classes": "๐๏ธ",222 "API Interaction": "๐",223 "Data Visualization": "๐",224 "Error Handling": "โ ๏ธ",225 "Libraries": "๐"226}227 228python_parts_extended = {229 "Syntax": "โ๏ธ (Variables, Comments, Printing)",230 "Data Types": "๐ (Numbers, Strings, Lists, Tuples, Sets, Dictionaries)",231 "Control Structures": "๐ (If, Elif, Else, Loops, Break, Continue)",232 "Functions": "๐ง (Defining, Calling, Parameters, Return Values)",233 "Classes": "๐๏ธ (Creating, Inheritance, Methods, Properties)",234 "API Interaction": "๐ (Requests, JSON Parsing, HTTP Methods)",235 "Data Visualization": "๐ (Matplotlib, Seaborn, Plotly)",236 "Error Handling": "โ ๏ธ (Try, Except, Finally, Raising)",237 "Libraries": "๐ (Numpy, Pandas, Scikit-Learn, TensorFlow)"238}239 240# Placeholder for chat responses and interactive examples241response_placeholders = {}242example_placeholders = {}243 244# Function to display Python concepts with expanders, examples, and quizzes245def display_python_parts():246 st.title("Python Interactive Learning Platform")247 248 for part, emoji in python_parts.items():249 with st.expander(f"{emoji} {part} - {python_parts_extended[part]}", expanded=False):250 # Interactive examples251 if st.button(f"Show Example for {part}", key=f"example_{part}"):252 example = generate_example(part)253 example_placeholders[part] = example254 st.code(example_placeholders[part], language="python")255 response = chat_with_model('Create a STEM related 3 to 5 line python code example with output for:' + example_placeholders[part], part)256 257 # Quizzes258 if st.button(f"Take Quiz on {part}", key=f"quiz_{part}"):259 quiz = generate_quiz(part)260 response = chat_with_model(quiz, part)261 262 # Chat responses263 prompt = f"Learn about {python_parts_extended[part]}"264 if st.button(f"Explore {part}", key=part):265 response = chat_with_model(prompt, part)266 response_placeholders[part] = response267 268 # Display the chat response if available269 if part in response_placeholders:270 st.markdown(f"**Response:** {response_placeholders[part]}")271 272def generate_example(part):273 # This function will return a relevant Python example based on the selected part274 # Examples could be pre-defined or dynamically generated275 return "Python example for " + part276 277def generate_quiz(part):278 # This function will create a simple quiz related to the Python part279 # Quizzes could be multiple-choice questions, true/false, etc.280 return "Python script quiz example for " + part281 282# Define function to add paper buttons and links283def add_paper_buttons_and_links():284 # Python Pair Programmer285 page = st.sidebar.radio("Choose a page:", ["Python Pair Programmer"])286 if page == "Python Pair Programmer":287 # Display Python concepts and interactive sections288 display_python_parts()289 290 291 292 293 col1, col2, col3, col4 = st.columns(4)294 295 with col1:296 with st.expander("MemGPT ๐ง ๐พ", expanded=False):297 link_button_with_emoji("https://arxiv.org/abs/2310.08560", "MemGPT", "๐ง ๐พ Memory OS")298 outline_memgpt = "Memory Hierarchy, Context Paging, Self-directed Memory Updates, Memory Editing, Memory Retrieval, Preprompt Instructions, Semantic Memory, Episodic Memory, Emotional Contextual Understanding"299 if st.button("Discuss MemGPT Features"):300 chat_with_model("Discuss the key features of MemGPT: " + outline_memgpt, "MemGPT")301 302 with col2:303 with st.expander("AutoGen ๐ค๐", expanded=False):304 link_button_with_emoji("https://arxiv.org/abs/2308.08155", "AutoGen", "๐ค๐ Multi-Agent LLM")305 outline_autogen = "Cooperative Conversations, Combining Capabilities, Complex Task Solving, Divergent Thinking, Factuality, Highly Capable Agents, Generic Abstraction, Effective Implementation"306 if st.button("Explore AutoGen Multi-Agent LLM"):307 chat_with_model("Explore the key features of AutoGen: " + outline_autogen, "AutoGen")308 309 with col3:310 with st.expander("Whisper ๐๐งโ๐", expanded=False):311 link_button_with_emoji("https://arxiv.org/abs/2212.04356", "Whisper", "๐๐งโ๐ Robust STT")312 outline_whisper = "Scaling, Deep Learning Approaches, Weak Supervision, Zero-shot Transfer Learning, Accuracy & Robustness, Pre-training Techniques, Broad Range of Environments, Combining Multiple Datasets"313 if st.button("Learn About Whisper STT"):314 chat_with_model("Learn about the key features of Whisper: " + outline_whisper, "Whisper")315 316 with col4:317 with st.expander("ChatDev ๐ฌ๐ป", expanded=False):318 link_button_with_emoji("https://arxiv.org/pdf/2307.07924.pdf", "ChatDev", "๐ฌ๐ป Comm. Agents")319 outline_chatdev = "Effective Communication, Comprehensive Software Solutions, Diverse Social Identities, Tailored Codes, Environment Dependencies, User Manuals"320 if st.button("Deep Dive into ChatDev"):321 chat_with_model("Deep dive into the features of ChatDev: " + outline_chatdev, "ChatDev")322 323add_paper_buttons_and_links()324 325 326# Process user input is a post processor algorithm which runs after document embedding vector DB play of GPT on context of documents..327def process_user_input(user_question):328 # Check and initialize 'conversation' in session state if not present329 if 'conversation' not in st.session_state:330 st.session_state.conversation = {} # Initialize with an empty dictionary or an appropriate default value331 332 response = st.session_state.conversation({'question': user_question})333 st.session_state.chat_history = response['chat_history']334 335 for i, message in enumerate(st.session_state.chat_history):336 template = user_template if i % 2 == 0 else bot_template337 st.write(template.replace("{{MSG}}", message.content), unsafe_allow_html=True)338 339 # Save file output from PDF query results340 filename = generate_filename(user_question, 'txt')341 create_file(filename, user_question, message.content, should_save)342 343 # New functionality to create expanders and buttons344 create_expanders_and_buttons(message.content)345 346def create_expanders_and_buttons(content):347 # Split the content into paragraphs348 paragraphs = content.split("\n\n")349 for paragraph in paragraphs:350 # Identify the header and detail in the paragraph351 header, detail = extract_feature_and_detail(paragraph)352 if header and detail:353 with st.expander(header, expanded=False):354 if st.button(f"Explore {header}"):355 expanded_outline = "Expand on the feature: " + detail356 chat_with_model(expanded_outline, header)357 358def extract_feature_and_detail(paragraph):359 # Use regex to find the header and detail in the paragraph360 match = re.match(r"(.*?):(.*)", paragraph)361 if match:362 header = match.group(1).strip()363 detail = match.group(2).strip()364 return header, detail365 return None, None366 367def transcribe_audio(file_path, model):368 key = os.getenv('OPENAI_API_KEY')369 headers = {370 "Authorization": f"Bearer {key}",371 }372 with open(file_path, 'rb') as f:373 data = {'file': f}374 st.write("Read file {file_path}", file_path)375 OPENAI_API_URL = "https://api.openai.com/v1/audio/transcriptions"376 response = requests.post(OPENAI_API_URL, headers=headers, files=data, data={'model': model})377 if response.status_code == 200:378 st.write(response.json())379 chatResponse = chat_with_model(response.json().get('text'), '') # *************************************380 transcript = response.json().get('text')381 #st.write('Responses:')382 #st.write(chatResponse)383 filename = generate_filename(transcript, 'txt')384 #create_file(filename, transcript, chatResponse)385 response = chatResponse386 user_prompt = transcript387 create_file(filename, user_prompt, response, should_save)388 return transcript389 else:390 st.write(response.json())391 st.error("Error in API call.")392 return None393 394def save_and_play_audio(audio_recorder):395 audio_bytes = audio_recorder()396 if audio_bytes:397 filename = generate_filename("Recording", "wav")398 with open(filename, 'wb') as f:399 f.write(audio_bytes)400 st.audio(audio_bytes, format="audio/wav")401 return filename402 return None403 404 405 406def truncate_document(document, length):407 return document[:length]408 409def divide_document(document, max_length):410 return [document[i:i+max_length] for i in range(0, len(document), max_length)]411 412def get_table_download_link(file_path):413 with open(file_path, 'r') as file:414 try:415 data = file.read()416 except:417 st.write('')418 return file_path 419 b64 = base64.b64encode(data.encode()).decode() 420 file_name = os.path.basename(file_path)421 ext = os.path.splitext(file_name)[1] # get the file extension422 if ext == '.txt':423 mime_type = 'text/plain'424 elif ext == '.py':425 mime_type = 'text/plain'426 elif ext == '.xlsx':427 mime_type = 'text/plain'428 elif ext == '.csv':429 mime_type = 'text/plain'430 elif ext == '.htm':431 mime_type = 'text/html'432 elif ext == '.md':433 mime_type = 'text/markdown'434 else:435 mime_type = 'application/octet-stream' # general binary data type436 href = f'<a href="data:{mime_type};base64,{b64}" target="_blank" download="{file_name}">{file_name}</a>'437 return href438 439def CompressXML(xml_text):440 root = ET.fromstring(xml_text)441 for elem in list(root.iter()):442 if isinstance(elem.tag, str) and 'Comment' in elem.tag:443 elem.parent.remove(elem)444 return ET.tostring(root, encoding='unicode', method="xml")445 446def read_file_content(file,max_length):447 if file.type == "application/json":448 content = json.load(file)449 return str(content)450 elif file.type == "text/html" or file.type == "text/htm":451 content = BeautifulSoup(file, "html.parser")452 return content.text453 elif file.type == "application/xml" or file.type == "text/xml":454 tree = ET.parse(file)455 root = tree.getroot()456 xml = CompressXML(ET.tostring(root, encoding='unicode'))457 return xml458 elif file.type == "text/markdown" or file.type == "text/md":459 md = mistune.create_markdown()460 content = md(file.read().decode())461 return content462 elif file.type == "text/plain":463 return file.getvalue().decode()464 else:465 return ""466 467def extract_mime_type(file):468 # Check if the input is a string469 if isinstance(file, str):470 pattern = r"type='(.*?)'"471 match = re.search(pattern, file)472 if match:473 return match.group(1)474 else:475 raise ValueError(f"Unable to extract MIME type from {file}")476 # If it's not a string, assume it's a streamlit.UploadedFile object477 elif isinstance(file, streamlit.UploadedFile):478 return file.type479 else:480 raise TypeError("Input should be a string or a streamlit.UploadedFile object")481 482 483 484def extract_file_extension(file):485 # get the file name directly from the UploadedFile object486 file_name = file.name487 pattern = r".*?\.(.*?)$"488 match = re.search(pattern, file_name)489 if match:490 return match.group(1)491 else:492 raise ValueError(f"Unable to extract file extension from {file_name}")493 494def pdf2txt(docs):495 text = ""496 for file in docs:497 file_extension = extract_file_extension(file)498 # print the file extension499 st.write(f"File type extension: {file_extension}")500 501 # read the file according to its extension502 try:503 if file_extension.lower() in ['py', 'txt', 'html', 'htm', 'xml', 'json']:504 text += file.getvalue().decode('utf-8')505 elif file_extension.lower() == 'pdf':506 from PyPDF2 import PdfReader507 pdf = PdfReader(BytesIO(file.getvalue()))508 for page in range(len(pdf.pages)):509 text += pdf.pages[page].extract_text() # new PyPDF2 syntax510 except Exception as e:511 st.write(f"Error processing file {file.name}: {e}")512 return text513 514def txt2chunks(text):515 text_splitter = CharacterTextSplitter(separator="\n", chunk_size=1000, chunk_overlap=200, length_function=len)516 return text_splitter.split_text(text)517 518def vector_store(text_chunks):519 key = os.getenv('OPENAI_API_KEY')520 embeddings = OpenAIEmbeddings(openai_api_key=key)521 return FAISS.from_texts(texts=text_chunks, embedding=embeddings)522 523def get_chain(vectorstore):524 llm = ChatOpenAI()525 memory = ConversationBufferMemory(memory_key='chat_history', return_messages=True)526 return ConversationalRetrievalChain.from_llm(llm=llm, retriever=vectorstore.as_retriever(), memory=memory)527 528def divide_prompt(prompt, max_length):529 words = prompt.split()530 chunks = []531 current_chunk = []532 current_length = 0533 for word in words:534 if len(word) + current_length <= max_length:535 current_length += len(word) + 1 # Adding 1 to account for spaces536 current_chunk.append(word)537 else:538 chunks.append(' '.join(current_chunk))539 current_chunk = [word]540 current_length = len(word)541 chunks.append(' '.join(current_chunk)) # Append the final chunk542 return chunks543 544def create_zip_of_files(files):545 """546 Create a zip file from a list of files.547 """548 zip_name = "all_files.zip"549 with zipfile.ZipFile(zip_name, 'w') as zipf:550 for file in files:551 zipf.write(file)552 return zip_name553 554 555def get_zip_download_link(zip_file):556 """557 Generate a link to download the zip file.558 """559 with open(zip_file, 'rb') as f:560 data = f.read()561 b64 = base64.b64encode(data).decode()562 href = f'<a href="data:application/zip;base64,{b64}" download="{zip_file}">Download All</a>'563 return href564 565 566def main():567 568 # Audio, transcribe, GPT:569 filename = save_and_play_audio(audio_recorder)570 571 if filename is not None:572 try:573 transcription = transcribe_audio(filename, "whisper-1")574 except:575 st.write(' ')576 st.sidebar.markdown(get_table_download_link(filename), unsafe_allow_html=True)577 filename = None578 579 # prompt interfaces580 user_prompt = st.text_area("Enter prompts, instructions & questions:", '', height=100)581 582 # file section interface for prompts against large documents as context583 collength, colupload = st.columns([2,3]) # adjust the ratio as needed584 with collength:585 max_length = st.slider("File section length for large files", min_value=1000, max_value=128000, value=12000, step=1000)586 with colupload:587 uploaded_file = st.file_uploader("Add a file for context:", type=["pdf", "xml", "json", "xlsx", "csv", "html", "htm", "md", "txt"])588 589 590 # Document section chat591 592 document_sections = deque()593 document_responses = {}594 if uploaded_file is not None:595 file_content = read_file_content(uploaded_file, max_length)596 document_sections.extend(divide_document(file_content, max_length))597 if len(document_sections) > 0:598 if st.button("๐๏ธ View Upload"):599 st.markdown("**Sections of the uploaded file:**")600 for i, section in enumerate(list(document_sections)):601 st.markdown(f"**Section {i+1}**\n{section}")602 st.markdown("**Chat with the model:**")603 for i, section in enumerate(list(document_sections)):604 if i in document_responses:605 st.markdown(f"**Section {i+1}**\n{document_responses[i]}")606 else:607 if st.button(f"Chat about Section {i+1}"):608 st.write('Reasoning with your inputs...')609 response = chat_with_model(user_prompt, section, model_choice)610 document_responses[i] = response611 filename = generate_filename(f"{user_prompt}_section_{i+1}", choice)612 create_file(filename, user_prompt, response, should_save)613 st.sidebar.markdown(get_table_download_link(filename), unsafe_allow_html=True)614 615 if st.button('๐ฌ Chat'):616 st.write('Reasoning with your inputs...')617 618 # Divide the user_prompt into smaller sections619 user_prompt_sections = divide_prompt(user_prompt, max_length)620 full_response = ''621 for prompt_section in user_prompt_sections:622 # Process each section with the model623 response = chat_with_model(prompt_section, ''.join(list(document_sections)), model_choice)624 full_response += response + '\n' # Combine the responses625 response = full_response626 filename = generate_filename(user_prompt, choice)627 create_file(filename, user_prompt, response, should_save)628 st.sidebar.markdown(get_table_download_link(filename), unsafe_allow_html=True)629 630 all_files = glob.glob("*.*")631 all_files = [file for file in all_files if len(os.path.splitext(file)[0]) >= 20] # exclude files with short names632 all_files.sort(key=lambda x: (os.path.splitext(x)[1], x), reverse=True) # sort by file type and file name in descending order633 634 635 # Sidebar buttons Download All and Delete All636 colDownloadAll, colDeleteAll = st.sidebar.columns([3,3])637 with colDownloadAll:638 if st.button("โฌ๏ธ Download All"):639 zip_file = create_zip_of_files(all_files)640 st.markdown(get_zip_download_link(zip_file), unsafe_allow_html=True)641 with colDeleteAll:642 if st.button("๐ Delete All"):643 for file in all_files:644 os.remove(file)645 st.experimental_rerun()646 647 # Sidebar of Files Saving History and surfacing files as context of prompts and responses648 file_contents=''649 next_action=''650 for file in all_files:651 col1, col2, col3, col4, col5 = st.sidebar.columns([1,6,1,1,1]) # adjust the ratio as needed652 with col1:653 if st.button("๐", key="md_"+file): # md emoji button654 with open(file, 'r') as f:655 file_contents = f.read()656 next_action='md'657 with col2:658 st.markdown(get_table_download_link(file), unsafe_allow_html=True)659 with col3:660 if st.button("๐", key="open_"+file): # open emoji button661 with open(file, 'r') as f:662 file_contents = f.read()663 next_action='open'664 with col4:665 if st.button("๐", key="read_"+file): # search emoji button666 with open(file, 'r') as f:667 file_contents = f.read()668 next_action='search'669 with col5:670 if st.button("๐", key="delete_"+file):671 os.remove(file)672 st.experimental_rerun()673 674 if len(file_contents) > 0:675 if next_action=='open':676 file_content_area = st.text_area("File Contents:", file_contents, height=500)677 if next_action=='md':678 st.markdown(file_contents)679 if next_action=='search':680 file_content_area = st.text_area("File Contents:", file_contents, height=500)681 st.write('Reasoning with your inputs...')682 response = chat_with_model(user_prompt, file_contents, model_choice)683 filename = generate_filename(file_contents, choice)684 create_file(filename, user_prompt, response, should_save)685 686 st.experimental_rerun()687 688if __name__ == "__main__":689 main()690 691load_dotenv()692st.write(css, unsafe_allow_html=True)693 694st.header("Chat with documents :books:")695user_question = st.text_input("Ask a question about your documents:")696if user_question:697 process_user_input(user_question)698 699with st.sidebar:700 st.subheader("Your documents")701 docs = st.file_uploader("import documents", accept_multiple_files=True)702 with st.spinner("Processing"):703 raw = pdf2txt(docs)704 if len(raw) > 0:705 length = str(len(raw))706 text_chunks = txt2chunks(raw)707 vectorstore = vector_store(text_chunks)708 st.session_state.conversation = get_chain(vectorstore)709 st.markdown('# AI Search Index of Length:' + length + ' Created.') # add timing710 filename = generate_filename(raw, 'txt')711 create_file(filename, raw, '', should_save)712 