suraj-ml-projects commited on
Commit
5c2bc5e
·
verified ·
1 Parent(s): 32a7c50

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +82 -55
app.py CHANGED
@@ -4,30 +4,37 @@ from utils import process_image, process_video, generate_references
4
  import tempfile
5
  import os
6
  import gc
 
7
 
8
  loader = ModelLoader()
9
 
10
- def chat(message, history, file=None):
11
- # Security: Basic sanitization (expand as needed)
12
  if not message and not file:
13
  return "Please provide a message or upload a file.", history
14
 
15
- # Process uploaded file
16
  context = ""
 
 
17
  if file:
18
- if isinstance(file, str): # Gradio path
19
- ext = os.path.splitext(file)[1].lower()
20
- if ext in ['.jpg', '.jpeg', '.png', '.webp']:
21
- img = Image.open(file)
22
- context = f"Image description: {process_image(img)}\n\n"
23
- elif ext in ['.mp4', '.avi', '.mov']:
24
- context = f"Video analysis:\n{process_video(file)}\n\n"
25
- else:
26
- context = "File uploaded. Describe its content or ask questions about it.\n\n"
 
 
 
 
 
 
 
27
 
28
  full_prompt = f"{context}User: {message}\n\nAssistant:"
29
 
30
- # Generate response
31
  try:
32
  model, tokenizer = loader.load_text_model()
33
  inputs = tokenizer(full_prompt, return_tensors="pt").to(loader.device)
@@ -38,83 +45,103 @@ def chat(message, history, file=None):
38
  max_new_tokens=512,
39
  temperature=0.7,
40
  do_sample=True,
41
- pad_token_id=tokenizer.eos_token_id
 
42
  )
43
 
44
- response = tokenizer.decode(outputs[0][inputs.input_ids.shape[1]:], skip_special_tokens=True)
 
45
 
46
- # Add references
47
  refs = generate_references(message[:100])
48
- final_response = f"{response.strip()}\n\n**Sources/References:**\n{refs}"
49
 
50
  except Exception as e:
51
- final_response = f"I processed your input: {str(e)[:200]}. Please try again or rephrase."
52
-
53
- # Privacy: Clear memory aggressively
54
  gc.collect()
55
  if torch.cuda.is_available():
56
  torch.cuda.empty_cache()
57
-
58
- return final_response, history + [[{"text": message, "files": [file] if file else None}, final_response]]
59
 
60
- # Gradio UI
61
- with gr.Blocks(title="Private Personal AI Chatbot", theme=gr.themes.Soft()) as demo:
62
- gr.Markdown("# 🛡️ Private Personal AI Chatbot\nFully local/open-source • No data stored • No external APIs")
 
 
 
 
63
 
64
  chatbot = gr.Chatbot(
65
- height=600,
66
- show_copy_button=True,
67
- avatar_images=(None, "🧠"),
 
 
68
  )
69
 
70
  with gr.Row():
71
  msg = gr.Textbox(
72
- placeholder="Ask anything... (text + image/video supported)",
73
  scale=4,
74
- container=False
 
75
  )
76
- submit = gr.Button("Send", variant="primary")
77
 
78
  with gr.Row():
79
  file_upload = gr.File(
80
- label="Upload Image or Video (max ~400MB)",
81
- file_types=["image", "video"],
82
  scale=1
83
  )
84
  clear_btn = gr.Button("Clear Chat", variant="stop")
85
-
 
86
  gr.Examples(
87
  examples=[
88
- ["What is in this image?", "example_image.jpg"],
89
- ["Summarize this video", "example_video.mp4"],
90
- ["Explain quantum computing simply"],
91
  ],
92
- inputs=[msg, file_upload]
 
93
  )
 
 
 
 
94
 
95
- gr.Markdown("**Privacy Note**: Everything runs in-memory. No conversations are saved.")
 
 
 
 
 
 
96
 
97
- # Chat logic
98
- def user_input(message, history, file):
99
- if file:
100
- # Display file in chat
101
- return "", history + [[{"text": message, "files": [file]}, None]]
102
- return "", history + [[message, None]]
103
 
104
  msg.submit(
105
- user_input, [msg, chatbot, file_upload], [msg, chatbot]
106
- ).then(
107
- chat, [msg, chatbot, file_upload], [chatbot, chatbot] # Note: Gradio handles multimodal display
108
  )
109
 
110
- submit.click(
111
- user_input, [msg, chatbot, file_upload], [msg, chatbot]
112
- ).then(
113
- chat, [msg, chatbot, file_upload], [chatbot, chatbot]
114
  )
115
 
116
- clear_btn.click(lambda: None, None, chatbot, queue=False)
117
 
118
- # For HF Spaces
119
  if __name__ == "__main__":
120
- demo.queue(max_size=10).launch()
 
 
 
 
 
 
4
  import tempfile
5
  import os
6
  import gc
7
+ from PIL import Image
8
 
9
  loader = ModelLoader()
10
 
11
+ def chat(message: str, history, file=None):
 
12
  if not message and not file:
13
  return "Please provide a message or upload a file.", history
14
 
 
15
  context = ""
16
+ file_path = None
17
+
18
  if file:
19
+ file_path = file if isinstance(file, str) else file.name
20
+ ext = os.path.splitext(file_path)[1].lower()
21
+
22
+ if ext in ['.jpg', '.jpeg', '.png', '.webp', '.gif']:
23
+ try:
24
+ img = Image.open(file_path)
25
+ context = f"**Image Description**: {process_image(img)}\n\n"
26
+ except:
27
+ context = "**Image uploaded.** Please ask questions about it.\n\n"
28
+ elif ext in ['.mp4', '.avi', '.mov', '.webm']:
29
+ try:
30
+ context = f"**Video Analysis**:\n{process_video(file_path)}\n\n"
31
+ except:
32
+ context = "**Video uploaded.** Summarized from key frames.\n\n"
33
+ else:
34
+ context = "**File uploaded.** Describe its content if needed.\n\n"
35
 
36
  full_prompt = f"{context}User: {message}\n\nAssistant:"
37
 
 
38
  try:
39
  model, tokenizer = loader.load_text_model()
40
  inputs = tokenizer(full_prompt, return_tensors="pt").to(loader.device)
 
45
  max_new_tokens=512,
46
  temperature=0.7,
47
  do_sample=True,
48
+ pad_token_id=tokenizer.eos_token_id,
49
+ repetition_penalty=1.1
50
  )
51
 
52
+ response = tokenizer.decode(outputs[0][inputs.input_ids.shape[1]:],
53
+ skip_special_tokens=True)
54
 
 
55
  refs = generate_references(message[:100])
56
+ final_response = f"{response.strip()}\n\n**Sources / References:**\n{refs}"
57
 
58
  except Exception as e:
59
+ final_response = f"Error processing request: {str(e)[:150]}\nPlease try again."
60
+
61
+ # Privacy: Aggressive cleanup
62
  gc.collect()
63
  if torch.cuda.is_available():
64
  torch.cuda.empty_cache()
 
 
65
 
66
+ return final_response
67
+
68
+
69
+ # ==================== Gradio 6.x UI ====================
70
+
71
+ with gr.Blocks() as demo:
72
+ gr.Markdown("# 🛡️ Private Personal AI Chatbot\n**Fully local • No data stored • Open-source**")
73
 
74
  chatbot = gr.Chatbot(
75
+ height=650,
76
+ avatar_images=(None, "🧠"), # Still supported in Gradio 6
77
+ bubble_full_width=False,
78
+ show_copy_button=False, # Will be replaced with buttons=
79
+ buttons=["copy", "copy_all"] # New Gradio 6 way
80
  )
81
 
82
  with gr.Row():
83
  msg = gr.Textbox(
84
+ placeholder="Type your message here... (supports image/video uploads)",
85
  scale=4,
86
+ container=False,
87
+ autofocus=True
88
  )
89
+ submit_btn = gr.Button("Send", variant="primary", scale=1)
90
 
91
  with gr.Row():
92
  file_upload = gr.File(
93
+ label="📎 Upload Image or Video",
94
+ file_types=["image", ".mp4", ".mov", ".avi", ".webm"],
95
  scale=1
96
  )
97
  clear_btn = gr.Button("Clear Chat", variant="stop")
98
+
99
+ # Examples
100
  gr.Examples(
101
  examples=[
102
+ ["Explain how transformers work in simple terms"],
103
+ ["What is visible in this image?", "example.jpg"],
 
104
  ],
105
+ inputs=[msg, file_upload],
106
+ label="Try these examples"
107
  )
108
+
109
+ gr.Markdown("**Privacy**: Everything runs in memory. Nothing is logged or stored permanently.")
110
+
111
+ # ===================== Event Handlers =====================
112
 
113
+ def respond(message, history, file):
114
+ if not history:
115
+ history = []
116
+
117
+ bot_response = chat(message, history, file)
118
+ history.append([message, bot_response])
119
+ return "", history, None # Clear message + return history + clear file
120
 
121
+ # Submit via button or Enter
122
+ submit_btn.click(
123
+ respond,
124
+ inputs=[msg, chatbot, file_upload],
125
+ outputs=[msg, chatbot, file_upload]
126
+ )
127
 
128
  msg.submit(
129
+ respond,
130
+ inputs=[msg, chatbot, file_upload],
131
+ outputs=[msg, chatbot, file_upload]
132
  )
133
 
134
+ clear_btn.click(
135
+ lambda: [],
136
+ outputs=chatbot,
137
+ queue=False
138
  )
139
 
 
140
 
 
141
  if __name__ == "__main__":
142
+ demo.launch(
143
+ server_name="0.0.0.0",
144
+ server_port=7860,
145
+ theme=gr.themes.Soft(), # Moved here for Gradio 6.x
146
+ share=False
147
+ )