Update app.py
Browse files
app.py
CHANGED
|
@@ -6,12 +6,7 @@ import openpyxl
|
|
| 6 |
from pdfminer.high_level import extract_text
|
| 7 |
import csv
|
| 8 |
from pptx import Presentation
|
| 9 |
-
import
|
| 10 |
-
from io import BytesIO
|
| 11 |
-
from reportlab.pdfgen import canvas
|
| 12 |
-
from reportlab.lib.pagesizes import letter
|
| 13 |
-
from reportlab.lib.colors import blue, red
|
| 14 |
-
import streamlit.components.v1 as components
|
| 15 |
|
| 16 |
# Configure Gemini API
|
| 17 |
GOOGLE_API_KEY = os.environ.get("GOOGLE_API_KEY")
|
|
@@ -39,11 +34,11 @@ def load_and_extract_text(file_path):
|
|
| 39 |
elif file_extension == 'pdf':
|
| 40 |
text = extract_text(file_path)
|
| 41 |
elif file_extension == 'csv':
|
| 42 |
-
with open(file_path, 'r', encoding='utf-8') as csvfile:
|
| 43 |
reader = csv.reader(csvfile)
|
| 44 |
-
text = '\n'.join([' '.join(row) for row in reader])
|
| 45 |
elif file_extension == 'txt':
|
| 46 |
-
with open(file_path, 'r', encoding='utf-8') as txtfile:
|
| 47 |
text = txtfile.read()
|
| 48 |
elif file_extension == 'pptx':
|
| 49 |
prs = Presentation(file_path)
|
|
@@ -56,8 +51,11 @@ def load_and_extract_text(file_path):
|
|
| 56 |
return f"Error processing file: {e}"
|
| 57 |
|
| 58 |
|
| 59 |
-
def process_document_and_answer(
|
| 60 |
-
|
|
|
|
|
|
|
|
|
|
| 61 |
|
| 62 |
try:
|
| 63 |
response = model.generate_content(prompt)
|
|
@@ -66,110 +64,22 @@ def process_document_and_answer(context, question, history=""):
|
|
| 66 |
return f"Error generating answer: {e}"
|
| 67 |
|
| 68 |
|
| 69 |
-
def create_download_link(val, filename):
|
| 70 |
-
b64 = base64.b64encode(val) # val looks like b'...'
|
| 71 |
-
return f'<a href="data:application/octet-stream;base64,{b64.decode()}" download="{filename}">Download conversation as PDF</a>'
|
| 72 |
-
|
| 73 |
-
def move_element(element, location="bottom"):
|
| 74 |
-
js_code = f"""
|
| 75 |
-
<script>
|
| 76 |
-
window.onload = function() {{
|
| 77 |
-
var element = document.getElementById('{element}');
|
| 78 |
-
if (element) {{
|
| 79 |
-
element.style.position = 'fixed';
|
| 80 |
-
element.style.bottom = '0';
|
| 81 |
-
element.style.left = '0';
|
| 82 |
-
element.style.width = '100%';
|
| 83 |
-
element.style.backgroundColor = 'white';
|
| 84 |
-
element.style.zIndex = '9999';
|
| 85 |
-
element.style.padding = '10px';
|
| 86 |
-
element.style.boxShadow = '0px -2px 5px #888888';
|
| 87 |
-
document.body.appendChild(element);
|
| 88 |
-
}}
|
| 89 |
-
}}
|
| 90 |
-
</script>
|
| 91 |
-
"""
|
| 92 |
-
components.html(js_code, height=0)
|
| 93 |
-
|
| 94 |
# Streamlit UI
|
| 95 |
st.title("Gemini Document Q&A")
|
| 96 |
|
| 97 |
-
# Initialize session state
|
| 98 |
-
if 'conversation_history' not in st.session_state:
|
| 99 |
-
st.session_state.conversation_history = ""
|
| 100 |
-
|
| 101 |
-
if 'document_content' not in st.session_state:
|
| 102 |
-
st.session_state.document_content = None
|
| 103 |
-
|
| 104 |
-
if 'question_count' not in st.session_state:
|
| 105 |
-
st.session_state.question_count = 0
|
| 106 |
-
|
| 107 |
-
if 'display_answer' not in st.session_state:
|
| 108 |
-
st.session_state.display_answer = False
|
| 109 |
-
|
| 110 |
-
if 'answers' not in st.session_state:
|
| 111 |
-
st.session_state.answers = []
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
# File Upload
|
| 115 |
uploaded_file = st.file_uploader("Upload a document", type=["docx", "xlsx", "pdf", "csv", "txt", "pptx"])
|
| 116 |
|
| 117 |
-
|
|
|
|
|
|
|
| 118 |
# Save the uploaded file to a temporary location
|
| 119 |
temp_file_path = "temp." + uploaded_file.name.split('.')[-1].lower()
|
| 120 |
with open(temp_file_path, "wb") as temp_file:
|
| 121 |
temp_file.write(uploaded_file.read())
|
| 122 |
|
| 123 |
-
|
| 124 |
-
os.remove(temp_file_path) # Clean up
|
| 125 |
-
|
| 126 |
-
if "Error processing file" in st.session_state.document_content:
|
| 127 |
-
st.error(st.session_state.document_content)
|
| 128 |
-
st.session_state.document_content = None
|
| 129 |
|
| 130 |
-
|
| 131 |
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
for i, answer in enumerate(st.session_state.answers):
|
| 135 |
-
st.markdown(f"<p style='color:green;'><b>Answer {i+1}:</b> {answer}</p>", unsafe_allow_html=True)
|
| 136 |
-
|
| 137 |
-
# Question Input at bottom using javascript to stick at the bottom
|
| 138 |
-
move_element("question_input")
|
| 139 |
-
question = st.text_input("**Ask a question (type 'exit' to end):**", key="question_input", value="")
|
| 140 |
-
|
| 141 |
-
if question:
|
| 142 |
-
if question.lower() == "exit":
|
| 143 |
-
st.write("Ending conversation.")
|
| 144 |
-
st.stop() # this one is more appropiate to stop
|
| 145 |
-
else:
|
| 146 |
-
answer = process_document_and_answer(st.session_state.document_content, question, st.session_state.conversation_history)
|
| 147 |
-
st.session_state.answers.append(answer)
|
| 148 |
-
st.session_state.display_answer = True
|
| 149 |
-
|
| 150 |
-
# Update conversation history and question count
|
| 151 |
-
st.session_state.conversation_history += f"\nQuestion: {question}\nAnswer: {answer}"
|
| 152 |
-
st.session_state.question_count += 1
|
| 153 |
-
st.rerun() # Rerun to display new question at bottom and answer at top
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
# PDF Export
|
| 157 |
-
if st.session_state.conversation_history:
|
| 158 |
-
pdf_buffer = BytesIO()
|
| 159 |
-
c = canvas.Canvas(pdf_buffer, pagesize=letter)
|
| 160 |
-
textobject = c.beginText()
|
| 161 |
-
textobject.setTextOrigin(10, 730)
|
| 162 |
-
textobject.setFont("Helvetica", 12)
|
| 163 |
-
|
| 164 |
-
for line in st.session_state.conversation_history.split('\n'):
|
| 165 |
-
textobject.setFillColor(blue)
|
| 166 |
-
if line.startswith("Answer:"):
|
| 167 |
-
textobject.setFillColor(red)
|
| 168 |
-
textobject.textLine(line)
|
| 169 |
-
|
| 170 |
-
c.drawText(textobject)
|
| 171 |
-
c.save()
|
| 172 |
-
pdf_buffer.seek(0)
|
| 173 |
-
|
| 174 |
-
download_link = create_download_link(pdf_buffer.read(), "conversation.pdf")
|
| 175 |
-
st.markdown(download_link, unsafe_allow_html=True)
|
|
|
|
| 6 |
from pdfminer.high_level import extract_text
|
| 7 |
import csv
|
| 8 |
from pptx import Presentation
|
| 9 |
+
from io import StringIO # For handling string-based CSV
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
|
| 11 |
# Configure Gemini API
|
| 12 |
GOOGLE_API_KEY = os.environ.get("GOOGLE_API_KEY")
|
|
|
|
| 34 |
elif file_extension == 'pdf':
|
| 35 |
text = extract_text(file_path)
|
| 36 |
elif file_extension == 'csv':
|
| 37 |
+
with open(file_path, 'r', encoding='utf-8') as csvfile: # Explicit encoding
|
| 38 |
reader = csv.reader(csvfile)
|
| 39 |
+
text = '\n'.join([' '.join(row) for row in reader]) # Join rows with spaces
|
| 40 |
elif file_extension == 'txt':
|
| 41 |
+
with open(file_path, 'r', encoding='utf-8') as txtfile: #Explicit encoding
|
| 42 |
text = txtfile.read()
|
| 43 |
elif file_extension == 'pptx':
|
| 44 |
prs = Presentation(file_path)
|
|
|
|
| 51 |
return f"Error processing file: {e}"
|
| 52 |
|
| 53 |
|
| 54 |
+
def process_document_and_answer(extracted_text, question):
|
| 55 |
+
if "Error processing file" in extracted_text or "Unsupported file format" in extracted_text:
|
| 56 |
+
return extracted_text
|
| 57 |
+
|
| 58 |
+
prompt = f"Context: {extracted_text}\n\nQuestion: {question}\n\nAnswer:"
|
| 59 |
|
| 60 |
try:
|
| 61 |
response = model.generate_content(prompt)
|
|
|
|
| 64 |
return f"Error generating answer: {e}"
|
| 65 |
|
| 66 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
# Streamlit UI
|
| 68 |
st.title("Gemini Document Q&A")
|
| 69 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
uploaded_file = st.file_uploader("Upload a document", type=["docx", "xlsx", "pdf", "csv", "txt", "pptx"])
|
| 71 |
|
| 72 |
+
question = st.text_input("Ask a question about the document:")
|
| 73 |
+
|
| 74 |
+
if uploaded_file is not None and question:
|
| 75 |
# Save the uploaded file to a temporary location
|
| 76 |
temp_file_path = "temp." + uploaded_file.name.split('.')[-1].lower()
|
| 77 |
with open(temp_file_path, "wb") as temp_file:
|
| 78 |
temp_file.write(uploaded_file.read())
|
| 79 |
|
| 80 |
+
extracted_text = load_and_extract_text(temp_file_path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 81 |
|
| 82 |
+
os.remove(temp_file_path) # Clean up the temporary file
|
| 83 |
|
| 84 |
+
answer = process_document_and_answer(extracted_text, question)
|
| 85 |
+
st.write("Answer:", answer)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|