I am writing the program to build an AI chatbot that accept user input pdf, which run locally, the code:
"
import os
import time
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer, BitsAndBytesConfig
import gradio as gr
from threading import Thread
from PyPDF2 import PdfReader  # Import PyPDF2 for PDF text extraction

MODEL_PATH = r"C:\Users\shermanhonsf\Desktop\Python\llama_develop\model\Llama3.2-1B-Instruct-HF-Model"  # Your model path

TITLE = """
Chat with Llama 3.2 1B
"""

PLACEHOLDER = """
Hi, I'm Llama. Ask me anything or upload a PDF to chat about its content.
"""

CSS = """
.duplicate-button {
    margin: auto !important;
    color: white !important;
    background: black !important;
    border-radius: 100vh !important;
}
h3 {
    text-align: center;
}
"""

# Set the device to "cuda" if you have a compatible GPU, otherwise "cpu"
device = "cuda" if torch.cuda.is_available() else "cpu"

# Configure quantization if needed (optional)
quantization_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_compute_dtype=torch.bfloat16,
    bnb_4bit_use_double_quant=True,
    bnb_4bit_quant_type="nf4"
)

# Load the tokenizer and model from the local directory
tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH)
model = AutoModelForCausalLM.from_pretrained(
    MODEL_PATH,
    torch_dtype=torch.bfloat16,
    device_map="auto",
    # quantization_config=quantization_config
)

# Move the model to the appropriate device
model.to(device)


def extract_pdf_text(pdf_path):
    """Extract all text from a PDF file."""
    try:
        reader = PdfReader(pdf_path)
        text = ""
        for page in reader.pages:
            text += page.extract_text()
        return text
    except Exception as e:
        return f"Error reading PDF: {e}"


def stream_chat(message: str, history: list, system_prompt: str = 'You are a helpful assistant',
                temperature: float = 0.8, max_new_tokens: int = 1024, top_p: float = 1.0, top_k: int = 20, penalty: float = 1.2, pdf_text: str = ""):
    print(f'message: {message}')
    print(f'history: {history}')
    print(f'system_prompt: {system_prompt}')
    print(f'temperature: {temperature}')
    print(f'max_new_tokens: {max_new_tokens}')
    print(f'top_p: {top_p}')
    print(f'top_k: {top_k}')
    print(f'penalty: {penalty}')
    print(f'Message: {message}')
    print(f'History: {history}')
    print(f'PDF Text: {pdf_text}')

    conversation = [
        {"role": "system", "content": system_prompt}
    ]

    # Add PDF content to the system prompt if provided
    if pdf_text.strip():
        pdf_summary = f"The user uploaded a PDF with the following content:\n{pdf_text[:2000]}...\n(This is a truncated summary if the text is too long.)"
        conversation.append({"role": "system", "content": pdf_summary})

    for prompt, answer in history:
        conversation.extend([
            {"role": "user", "content": prompt},
            {"role": "assistant", "content": answer},
        ])

    conversation.append({"role": "user", "content": message})

    # Prepare input IDs
    input_ids = tokenizer.apply_chat_template(
        conversation,
        # tokenize=True,
        add_generation_prompt=True,
        return_tensors="pt"
    ).to(device)

    streamer = TextIteratorStreamer(
        tokenizer,
        timeout=60.0,
        skip_prompt=True,
        skip_special_tokens=True
    )

    generate_kwargs = dict(
        input_ids=input_ids,
        max_new_tokens=max_new_tokens,
        do_sample=False if temperature == 0 else True,
        top_p=top_p,
        top_k=top_k,
        temperature=temperature,
        eos_token_id=[128001, 128008, 128009],
        streamer=streamer,
    )

    # Generate the response in a background thread
    with torch.no_grad():
        thread = Thread(target=model.generate, kwargs=generate_kwargs)
        thread.start()

    # Stream the response back to the user
    buffer = ""
    for new_text in streamer:
        buffer += new_text
        yield buffer


# Create the Gradio interface
chatbot = gr.Chatbot(height=600, show_copy_button=True, layout="panel", placeholder=PLACEHOLDER)

with gr.Blocks(css=CSS) as demo:
    gr.HTML(TITLE)
    
    # Add file uploader for PDF input
    pdf_file = gr.File(label="Upload PDF", type="filepath")
    pdf_textbox = gr.Textbox(label="Extracted PDF Text", placeholder="PDF content will appear here after upload.", lines=10, interactive=False)
    
    def process_pdf(file):
        if file is not None:
            pdf_text = extract_pdf_text(file.name)
            return pdf_text
        return "No PDF uploaded."

    pdf_file.change(process_pdf, inputs=pdf_file, outputs=pdf_textbox)
    
    gr.ChatInterface(
        fn=stream_chat,
        chatbot=chatbot,
        fill_height=True,
        additional_inputs_accordion=gr.Accordion(
            label="⚙️ Parameters",
            open=False,
            render=False
        ),
        additional_inputs=[
            gr.Textbox(
                value="You are a helpful assistant",
                label="System Prompt",
                render=False,
            ),
            gr.Slider(
                minimum=0,
                maximum=1,
                step=0.1,
                value=0.8,
                label="Temperature",
                render=False,
            ),
            gr.Slider(
                minimum=128,
                maximum=8192,
                step=1,
                value=1024,
                label="Max new tokens",
                render=False,
            ),
            gr.Slider(
                minimum=0.0,
                maximum=1.0,
                step=0.1,
                value=1.0,
                label="Top_p",
                render=False,
            ),
            gr.Slider(
                minimum=1,
                maximum=20,
                step=1,
                value=20,
                label="Top_k",
                render=False,
            ),
            gr.Slider(
                minimum=0.0,
                maximum=2.0,
                step=0.1,
                value=1.2,
                label="Repetition penalty",
                render=False,
            ),
            pdf_textbox  # Pass the extracted PDF text as an additional input
        ],
        examples=[
            ["What are the main themes explored in the movie 'Dune', and how do they reflect contemporary issues? "],
            ["What are 3 practical techniques I can use to prioritize tasks more effectively in a busy work schedule? "],
            ["How does blockchain technology work, and what are its potential applications beyond cryptocurrencies? "],
            ["Show me a code snippet of a website's sticky header in CSS and JavaScript."],
        ],
        cache_examples=False,
    )

if __name__ == "__main__":
    demo.launch(debug=True)
"
Add the function that let the llm generate excel file as output with the process as follow:
1. User can read and edit the generated excel file in the app
2. Have a download button which user can click it and it will download the file 
The sample code:
"
# Work, but with llm function not tested

import pandas as pd
import gradio as gr

# Function to generate an initial Excel file
def generate_excel():
    # Create a sample DataFrame
    data = {
        'Name': ['Alice', 'Bob', 'Charlie'],
        'Age': [25, 30, 35],
        'City': ['New York', 'Los Angeles', 'Chicago']
    }
    df = pd.DataFrame(data)
    
    # Save the initial DataFrame to an Excel file
    excel_file_path = "initial_data.xlsx"
    df.to_excel(excel_file_path, index=False)
    return excel_file_path, df

# Function to save the edited DataFrame
def save_excel(df):
    excel_file_path = "edited_data.xlsx"
    df.to_excel(excel_file_path, index=False)
    return excel_file_path

# Generate the initial Excel file and DataFrame
initial_file_path, initial_df = generate_excel()

# Gradio Interface
with gr.Blocks() as demo:
    gr.Markdown("## Editable Excel File Generator")
    
    # DataFrame input component
    editable_df = gr.DataFrame(value=initial_df, label="Edit the DataFrame", interactive=True)
    
    # Button to save the edited DataFrame
    save_button = gr.Button("Save and Download Excel")
    
    # Download link
    download_link = gr.File(label="Download your Excel File", interactive=False)
    
    # Logic for saving and updating the download link
    def update_download_link(df):
        saved_path = save_excel(df)  # Save edited DataFrame to new Excel file
        return saved_path
    
    # Button interaction
    save_button.click(update_download_link, inputs=[editable_df], outputs=[download_link])
    
# Launch the app
demo.launch()
"
But the excel is not generated by llm in the above code, I want the llm generated output can be passed to generated the excel file if required, for example, I ask the llm to generate the process flow chart of the electric motor production, then the llm will generate something like this:
1. Design and Engineering
2. Concept development
3. Finalize specifications
and so on...
And the system should convert the llm generated output to excel automatically if required.
how to integrate that keep all the function of my first code and add the generate excel function?