Sayandip commited on
Commit
4c99c64
·
verified ·
1 Parent(s): b74d994

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +170 -47
app.py CHANGED
@@ -1,59 +1,182 @@
1
- import streamlit as st
2
- from google import genai
3
  import os
 
 
 
 
 
 
 
 
 
 
 
4
 
5
- # Access the API key from environment variables
6
- api_key = os.getenv("GOOGLE_API_KEY")
 
 
 
 
 
7
 
8
- # Check if the API key is present
9
- if not api_key:
10
- raise EnvironmentError("GOOGLE_API_KEY not set in environment variables.")
11
 
12
- # Set the environment variable for the Google API client
13
- os.environ["GOOGLE_API_KEY"] = api_key
 
 
 
14
 
15
- # Initialize the client
16
  client = genai.Client()
17
  MODEL_ID = "gemini-2.0-flash"
18
 
19
- # Function to chat with Gemini
20
- def chat_with_gemini(message, history):
21
  try:
22
- response = client.models.generate_content(
23
- model=MODEL_ID,
24
- contents=message,
25
- config={"tools": [{"google_search": {}}]},
26
- )
27
- return response.text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  except Exception as e:
29
- return f"Error: {str(e)}"
30
 
31
- # Streamlit app
32
- st.title("Gemini Chatbot (with Google Search)")
33
- st.write("Ask anything and get responses powered by Gemini 2.0 Flash.")
 
 
 
34
 
35
- # Initialize chat history
36
- if 'history' not in st.session_state:
37
- st.session_state['history'] = []
38
-
39
- # Input field for the user to type their message
40
- user_input = st.text_input("You:", "")
41
-
42
- # Button to send the message
43
- if st.button("Send"):
44
- if user_input:
45
- # Add user message to history
46
- st.session_state.history.append({"role": "user", "message": user_input})
47
-
48
- # Get response from Gemini
49
- gemini_response = chat_with_gemini(user_input, st.session_state.history)
50
-
51
- # Add Gemini response to history
52
- st.session_state.history.append({"role": "assistant", "message": gemini_response})
53
-
54
- # Display the chat history
55
- for chat in st.session_state.history:
56
- if chat["role"] == "user":
57
- st.chat_message("user").markdown(chat["message"])
58
- else:
59
- st.chat_message("assistant").markdown(chat["message"])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
+ import base64
3
+ import streamlit as st
4
+ from docx import Document
5
+ import openpyxl
6
+ from pdfminer.high_level import extract_text
7
+ import csv
8
+ from pptx import Presentation
9
+ from io import StringIO
10
+ from bs4 import BeautifulSoup
11
+ import re
12
+ import google.generativeai as genai
13
 
14
+ # Setup
15
+ st.set_page_config(page_title="Gemini Q&A App", layout="centered")
16
+ st.title("🤖 Q&A - Document & Image with Web Search")
17
+
18
+ # Initialize chat history
19
+ if "chat_history" not in st.session_state:
20
+ st.session_state.chat_history = []
21
 
22
+ # Optional: Clear history button
23
+ if st.button("🧹 Clear Chat History"):
24
+ st.session_state.chat_history = []
25
 
26
+ # Load API key
27
+ GOOGLE_API_KEY = os.environ.get("GOOGLE_API_KEY") or st.secrets.get("GOOGLE_API_KEY")
28
+ if not GOOGLE_API_KEY:
29
+ st.error("GOOGLE_API_KEY not found in environment or Streamlit secrets.")
30
+ st.stop()
31
 
32
+ genai.configure(api_key=GOOGLE_API_KEY)
33
  client = genai.Client()
34
  MODEL_ID = "gemini-2.0-flash"
35
 
36
+ # Helper: Extract text from various documents
37
+ def load_and_extract_text(file_path):
38
  try:
39
+ ext = file_path.split('.')[-1].lower()
40
+
41
+ if ext == 'docx':
42
+ doc = Document(file_path)
43
+ return '\n'.join(p.text for p in doc.paragraphs)
44
+
45
+ elif ext == 'xlsx':
46
+ workbook = openpyxl.load_workbook(file_path)
47
+ return '\n'.join(
48
+ ' '.join(str(cell.value) for cell in row if cell.value is not None)
49
+ for sheet in workbook for row in sheet.iter_rows()
50
+ )
51
+
52
+ elif ext == 'pdf':
53
+ return extract_text(file_path)
54
+
55
+ elif ext == 'csv':
56
+ with open(file_path, 'r', encoding='utf-8') as f:
57
+ reader = csv.reader(f)
58
+ return '\n'.join(' '.join(row) for row in reader)
59
+
60
+ elif ext == 'txt':
61
+ with open(file_path, 'r', encoding='utf-8') as f:
62
+ return f.read()
63
+
64
+ elif ext == 'pptx':
65
+ prs = Presentation(file_path)
66
+ return '\n'.join(
67
+ shape.text for slide in prs.slides for shape in slide.shapes if hasattr(shape, 'text')
68
+ )
69
+
70
+ elif ext == 'tex':
71
+ with open(file_path, 'r', encoding='utf-8') as f:
72
+ content = f.read()
73
+ content = re.sub(r'\\[a-zA-Z]+\*?(?:\[[^\]]*\])?(?:\{[^}]*\})*', '', content)
74
+ content = re.sub(r'%.*', '', content)
75
+ return content.strip()
76
+
77
+ elif ext in ['html', 'htm']:
78
+ with open(file_path, 'r', encoding='utf-8') as f:
79
+ soup = BeautifulSoup(f, 'html.parser')
80
+ for script_or_style in soup(['script', 'style']):
81
+ script_or_style.decompose()
82
+ return soup.get_text(separator='\n', strip=True)
83
+
84
+ else:
85
+ return "Unsupported file format."
86
+
87
  except Exception as e:
88
+ return f"Error processing file: {e}"
89
 
90
+ # Multi-file uploader
91
+ uploaded_files = st.file_uploader(
92
+ "Upload one or more documents or images",
93
+ type=["docx", "xlsx", "pdf", "csv", "txt", "pptx", "tex", "html", "htm", "jpg", "jpeg", "png"],
94
+ accept_multiple_files=True
95
+ )
96
 
97
+ # Question input
98
+ question = st.text_input("💬 Enter your question:")
99
+
100
+ # Processing
101
+ if uploaded_files and question:
102
+ combined_context = ""
103
+ image_contents = []
104
+
105
+ for uploaded_file in uploaded_files:
106
+ file_ext = uploaded_file.name.split('.')[-1].lower()
107
+
108
+ if file_ext in ['jpg', 'jpeg', 'png']:
109
+ image_bytes = uploaded_file.read()
110
+ encoded_image = base64.b64encode(image_bytes).decode("utf-8")
111
+ image_contents.append({
112
+ "inline_data": {
113
+ "mime_type": uploaded_file.type,
114
+ "data": encoded_image
115
+ }
116
+ })
117
+ st.image(image_bytes, caption=uploaded_file.name, use_container_width=True)
118
+ continue
119
+
120
+ temp_file_path = "temp." + file_ext
121
+ with open(temp_file_path, "wb") as temp_file:
122
+ temp_file.write(uploaded_file.read())
123
+
124
+ extracted_text = load_and_extract_text(temp_file_path)
125
+ os.remove(temp_file_path)
126
+
127
+ if "Error" in extracted_text or "Unsupported" in extracted_text:
128
+ st.error(f"{uploaded_file.name}: {extracted_text}")
129
+ else:
130
+ combined_context += f"\n\n---\nDocument: {uploaded_file.name}\n\n{extracted_text}"
131
+
132
+ # Chat with Gemini and use both document and web context
133
+ if combined_context.strip() or image_contents or question.strip():
134
+ with st.spinner("Generating answer..."):
135
+ try:
136
+ content_blocks = []
137
+
138
+ # Add prior Q&A as part of the context
139
+ if st.session_state.chat_history:
140
+ history_text = "\n\n".join(
141
+ f"Q: {entry['question']}\nA: {entry['answer']}"
142
+ for entry in st.session_state.chat_history
143
+ )
144
+ content_blocks.append({"text": f"Previous conversation:\n{history_text}"})
145
+
146
+ # Add file text content
147
+ if combined_context.strip():
148
+ content_blocks.append({"text": f"Context:\n{combined_context}"})
149
+
150
+ # Add image blocks
151
+ content_blocks.extend(image_contents)
152
+
153
+ # Add current question
154
+ content_blocks.append({"text": f"Question: {question}"})
155
+
156
+ # Add web search context
157
+ response = client.models.generate_content(
158
+ model=MODEL_ID,
159
+ contents=content_blocks,
160
+ config={"tools": [{"google_search": {}}]},
161
+ )
162
+
163
+ st.success("💡 Answer:")
164
+ st.write(response.text)
165
+
166
+ # Save to session history
167
+ st.session_state.chat_history.append({
168
+ "question": question,
169
+ "answer": response.text
170
+ })
171
+
172
+ except Exception as e:
173
+ st.error(f"Error generating answer: {e}")
174
+ else:
175
+ st.warning("No valid documents or images processed.")
176
+
177
+ # Optional: Show full conversation history
178
+ if st.session_state.chat_history:
179
+ st.markdown("### 🗂️ Chat History")
180
+ for i, entry in enumerate(st.session_state.chat_history, 1):
181
+ st.markdown(f"**Q{i}:** {entry['question']}")
182
+ st.markdown(f"**A{i}:** {entry['answer']}")