File size: 6,543 Bytes
75712c5
453fb59
630bdac
453fb59
630bdac
 
 
 
e143e23
630bdac
193fcca
630bdac
193fcca
 
630bdac
 
 
 
 
 
 
453fb59
e438b4f
630bdac
c7a4fb1
e438b4f
630bdac
 
e438b4f
 
 
630bdac
 
 
c7a4fb1
e438b4f
630bdac
e438b4f
 
630bdac
c7a4fb1
630bdac
 
 
 
aa6ed7e
630bdac
 
 
 
 
 
 
 
 
e438b4f
630bdac
453fb59
be83351
630bdac
 
 
 
be83351
e143e23
 
be83351
630bdac
 
 
 
e143e23
 
 
 
be83351
e143e23
 
453fb59
630bdac
 
 
 
 
 
 
 
 
 
 
 
 
 
cc25a12
630bdac
 
 
 
 
e438b4f
630bdac
 
e438b4f
 
 
 
630bdac
 
 
e438b4f
e143e23
e438b4f
 
 
 
be83351
e438b4f
630bdac
c7a4fb1
630bdac
e438b4f
630bdac
 
e438b4f
630bdac
 
 
 
 
 
 
f883ad2
e438b4f
 
 
630bdac
e438b4f
 
f883ad2
630bdac
e438b4f
37bb88e
630bdac
 
 
 
37bb88e
630bdac
e438b4f
 
 
 
 
 
 
 
 
 
f883ad2
630bdac
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import gradio as gr
from huggingface_hub import InferenceClient

import nltk
import json
import io
from fpdf import FPDF
from textblob import TextBlob
import PyPDF2
import tempfile

# Download NLTK punkt tokenizer if needed.
nltk.download("punkt", quiet=True)

###############################################################################
#                           Hugging Face Chat Code                            #
###############################################################################
"""
For more information on Hugging Face Inference API support, please check:
https://huggingface.co/docs/huggingface_hub/v0.22.2/en/guides/inference
"""

# Initialize your Hugging Face model client.
client = InferenceClient("HuggingFaceH4/zephyr-7b-beta")

def respond(message, history: list[dict], system_message, max_tokens, temperature, top_p, file_content):
    """
    Calls the model (in non-streaming mode) to get a complete response.
    The file content is appended to the system message as context.
    Expects conversation history in the format: 
      [{"role": "user", "content": ...}, {"role": "assistant", "content": ...}, ...]
    """
    if file_content and file_content.strip():
        system_message += "\n\nFile content:\n" + file_content

    # Build messages list for the API request.
    messages = [{"role": "system", "content": system_message}]
    for entry in history:
        messages.append(entry)
    messages.append({"role": "user", "content": message})
    
    try:
        completion = client.chat_completion(
            messages,
            max_tokens=max_tokens,
            stream=true,  # Non-streaming mode for simplicity.
            temperature=temperature,
            top_p=top_p,
        )
        response = completion.choices[0].message["content"]
    except Exception as e:
        response = f"Error during model response: {e}"
    return response

###############################################################################
#                       File Upload & Parsing Functions                        #
###############################################################################

def parse_file(file_obj):
    """
    Parses an uploaded file.
    Supports PDF (using PyPDF2) and text files (UTF-8 decoding).
    """
    file_extension = file_obj.name.split('.')[-1].lower()
    if file_extension == "pdf":
        try:
            reader = PyPDF2.PdfReader(file_obj)
            text = ""
            for page in reader.pages:
                text += (page.extract_text() or "") + "\n"
            return text
        except Exception as e:
            return f"Error reading PDF: {e}"
    else:
        try:
            return file_obj.read().decode("utf-8", errors="ignore")
        except Exception as e:
            return f"Error reading file: {e}"

def load_files(files):
    """
    Processes a list of uploaded files (provided as file paths).
    Opens each file, parses its content, and concatenates the text.
    """
    all_text = ""
    for file_path in files:
        try:
            with open(file_path, "rb") as f:
                content = parse_file(f)
            all_text += content + "\n"
        except Exception as e:
            all_text += f"Error processing file {file_path}: {e}\n"
    return all_text

###############################################################################
#                             Gradio UI Layout                                #
###############################################################################

with gr.Blocks() as demo:
    gr.Markdown("# **Combined Chat & File Upload App**")
    gr.Markdown(
        """
This app allows you to upload file(s) (e.g., PDF or TXT) and chat with an AI assistant that uses the uploaded file(s) for context throughout the conversation.

- **Upload File(s):** The file contents are automatically parsed and stored.
- **Chat:** Your message, along with the uploaded file content, is sent to the AI on every prompt.
        """
    )
    
    # State to hold the concatenated file content and conversation history.
    file_content_state = gr.State("")
    chat_history_state = gr.State([])  # List of dictionaries in the form {"role": "user"/"assistant", "content": ...}
    
    # --- File Upload Section ---
    # Use type="filepath" so that we get file paths for processing.
    file_input = gr.File(label="Upload File(s)", file_count="multiple", type="filepath")
    # Automatically process files upon upload.
    file_input.change(fn=load_files, inputs=file_input, outputs=file_content_state)
    
    gr.Markdown("## Chat")
    chatbot = gr.Chatbot(label="Chat History", type="messages")
    user_input = gr.Textbox(label="Your Message", placeholder="Type your message here...", lines=2)
    
    # Additional model parameters (adjustable)
    system_prompt = gr.Textbox(label="System Message", value="You are a helpful AI assistant.", interactive=True)
    max_tokens_slider = gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max New Tokens")
    temperature_slider = gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature")
    top_p_slider = gr.Slider(minimum=0.1, maximum=1.0, value=0.95, step=0.05, label="Top-p (nucleus sampling)")
    
    def chat_fn(user_msg, history, file_content, system_msg, max_tokens, temperature, top_p):
        if not user_msg.strip():
            return "", history
        # Append user's message (in the required format).
        history.append({"role": "user", "content": user_msg})
        # Get the AI's response.
        response = respond(user_msg, history, system_msg, max_tokens, temperature, top_p, file_content)
        # Append the assistant's response.
        history.append({"role": "assistant", "content": response})
        return "", history
    
    # Trigger sending message on Enter in the textbox.
    user_input.submit(
        fn=chat_fn,
        inputs=[user_input, chat_history_state, file_content_state, system_prompt, max_tokens_slider, temperature_slider, top_p_slider],
        outputs=[user_input, chatbot],
        queue=True
    )
    
    # Also add a "Send" button.
    send_button = gr.Button("Send")
    send_button.click(
        fn=chat_fn,
        inputs=[user_input, chat_history_state, file_content_state, system_prompt, max_tokens_slider, temperature_slider, top_p_slider],
        outputs=[user_input, chatbot],
        queue=True
    )
    
    demo.launch(server_name="0.0.0.0", server_port=7860, share=True)

if __name__ == "__main__":
    demo.launch()