Vlad Bastina
send height
f93e87a
import streamlit as st
from pypdf import PdfReader
import os
from gemini_call import GeminiQanA
from docx import Document
from pathlib import Path
from extract_text import extract_text_pypdf
def load_css(file_name):
"""Loads a CSS file and injects it into the Streamlit app."""
try:
css_path = Path(__file__).parent / file_name
with open(css_path) as f:
st.markdown(f'<style>{f.read()}</style>', unsafe_allow_html=True)
# st.info(f"Loaded CSS: {file_name}") # Optional: uncomment for debugging
except FileNotFoundError:
st.error(f"CSS file not found: {file_name}. Make sure it's in the same directory as app.py.")
except Exception as e:
st.error(f"Error loading CSS file {file_name}: {e}")
from extract_text import extract_text_pypdf
@st.cache_resource()
def load_resources():
text_from_pdf: str = ""
file_name = 'CFR-2019-title21-vol2.pdf'
text_from_pdf = extract_text_pypdf(file_name)
with st.spinner("Reading document..."):
chatbot = GeminiQanA(text_from_pdf)
return chatbot , file_name
if __name__ == "__main__":
# Setup env variables
os.environ['GOOGLE_API_KEY'] = st.secrets['GOOGLE_API_KEY']
st.set_page_config(page_title=None, page_icon=None, layout="centered", initial_sidebar_state="expanded", menu_items=None)
st.markdown("""
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter+Tight:ital,wght@0,100..900;1,100..900&family=Space+Grotesk:wght@300..700&display=swap" rel="stylesheet">
""", unsafe_allow_html=True)
load_css("style.css")
st.markdown("<br></br>",unsafe_allow_html=True)
# Streamlit UI
st.title("๐Ÿ“„ FDA Question Answering Demo")
st.write('''This demo showcases an AI-powered system designed to interpret and answer questions based on Title 21 of the Code of Federal Regulations, Part 1 (21 CFR 1). These regulations, governed by the U.S. Food and Drug Administration (FDA), cover general enforcement provisions related to food, drugs, and cosmetics. The system enables users to navigate complex regulatory text efficiently, providing accurate, context-aware answers to compliance and procedural queries.''')
# Display logo
st.sidebar.write('Click the button bellow to download the sample document')
# Load the chatbot resources AND get the PDF path
chatbot, pdf_file_path_for_download = load_resources()
# --- Add PDF Download Button to Sidebar ---
if os.path.exists(pdf_file_path_for_download):
try:
with open(pdf_file_path_for_download, "rb") as pdf_file:
pdf_bytes = pdf_file.read()
st.sidebar.download_button(
label="Download Full PDF Document",
data=pdf_bytes,
file_name=os.path.basename(pdf_file_path_for_download), # Use basename to get just the filename
mime="application/pdf",
key='pdf_download' # Optional: add a key
)
except Exception as e:
st.sidebar.error(f"Error reading PDF for download: {e}")
else:
# This case should ideally be caught by load_resources, but added as a safeguard
st.sidebar.warning(f"PDF file '{pdf_file_path_for_download}' not found for download.")
st.sidebar.markdown("---") # Add another separator
# Sample questions for the combobox
sample_questions = [
"How is \"slack-fill\" defined, and what are the exceptions to considering it misbranding?",
"What is the difference between the principal display panel and the information panel on a food package?",
"What criteria determine the minimum type size for information on a food label? Are there any exemptions?",
"Under what circumstances is a food considered an \"imitation\" and what labeling requirements apply?",
"How must ingredients be listed on a food label? What exceptions are there to the descending order of predominance rule?",
"What are the requirements for declaring the net quantity of contents on a food label? What are some examples?",
"How are the terms \"fresh,\" \"freshly frozen,\" \"fresh frozen,\" and \"frozen fresh\" defined for food labeling purposes?",
"What exemptions exist for certain foods from the nutrition labeling requirements?",
"What are the requirements for calorie labeling of foods sold in vending machines?",
"What specific labeling requirements apply to spices, flavorings, colorings, and chemical preservatives?",
"What is the required statement regarding iodine content for salt?",
"How is the percentage juice declaration determined for beverages containing fruit or vegetable juice?",
"What are the specific labeling requirements for dietary supplements?",
"What are the guidelines for voluntary nutrition labeling of raw fruits, vegetables, and fish?",
"What are the requirements for making nutrient content claims such as \"good source\", \"high\", and \"light\"?",
"What are the general requirements for making health claims on food labels?",
"What are the specific health claims authorized for calcium, vitamin D, and osteoporosis?",
"What are the specific health claims related to soluble fiber and coronary heart disease?",
"Under what conditions can the terms \"gluten-free,\" \"no gluten,\" \"free of gluten,\" and \"without gluten\" be used on food labels?",
"What is the process for a state or locality to petition for exemption from federal preemption of their food labeling requirements?",
"How can states enforce federal food regulations?"
]
# Sidebar combobox to select a sample question
selected_question = st.sidebar.selectbox("Select a sample question:", sample_questions)
# Autofill the selected question into the text input
question = st.text_input("**Ask a question about the document:**", value=selected_question)
if "messages" not in st.session_state:
st.session_state.messages = []
# Handle user question and AI response
if st.button("Ask AI") and question:
st.session_state.messages.append({"role": "user", "content": question})
with st.spinner("Fetching response from assistant..."):
answer = chatbot.answer_question(question)
st.session_state.messages.append({"role": "assistant", "content": answer})
# Display previous messages in descending order
for i in range(len(st.session_state.messages)-1, -1, -2): # Start from the latest message and step by -2
# Display assistant message (if available)
if i-1 >= 0 and st.session_state.messages[i-1]["role"] == "user":
with st.chat_message("user"):
st.markdown(st.session_state.messages[i-1]["content"])
if i >= 0 and st.session_state.messages[i]["role"] == "assistant":
with st.chat_message("assistant"):
st.markdown(st.session_state.messages[i]["content"])
import streamlit.components.v1 as components
components.html(
"""
<script>
function sendHeightWhenReady() {
const el = window.parent.document.getElementsByClassName('stMain')[0];
if (el) {
const height = el.scrollHeight;
console.log("Sending height to parent:", height);
window.parent.parent.postMessage({ type: 'setHeight', height: height }, '*');
} else {
// Retry in 100ms until the element appears
setTimeout(sendHeightWhenReady, 1000);
}
}
window.onload = sendHeightWhenReady;
window.addEventListener('resize', sendHeightWhenReady);
setInterval(sendHeightWhenReady, 1000);
</script>
""",height=0
)