Team Ai
Apppublic

awacke1/PythonAIPairProgrammer

sourceHugging Facemitupdated 3y agoView on Hugging Face
2likes
backupapp.py712 linesDownload Raw Back to root
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