documentaitest / app.py
IAMTFRMZA's picture
Update app.py
8c01614 verified
import streamlit as st
import os
import time
import re
from openai import OpenAI
# ------------------ App Configuration ------------------
st.set_page_config(page_title="Document AI Assistant", layout="wide")
st.title("πŸ“„ Document AI Assistant")
st.caption("Chat with an AI Assistant on your medical/pathology documents")
# ------------------ Load API Key and Assistant ID from Hugging Face Secrets ------------------
OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
ASSISTANT_ID = os.environ.get("ASSISTANT_ID")
# ------------------ Error Handling for Missing Secrets ------------------
if not OPENAI_API_KEY or not ASSISTANT_ID:
st.error("Missing secrets. Please ensure both OPENAI_API_KEY and ASSISTANT_ID are set in your Hugging Face Space secrets.")
st.stop()
client = OpenAI(api_key=OPENAI_API_KEY)
# ------------------ Session State Initialization ------------------
if "messages" not in st.session_state:
st.session_state.messages = []
if "thread_id" not in st.session_state:
st.session_state.thread_id = None
if "image_url" not in st.session_state:
st.session_state.image_url = None
if "image_updated" not in st.session_state:
st.session_state.image_updated = False
# ------------------ Sidebar Controls ------------------
st.sidebar.header("πŸ”§ Settings")
if st.sidebar.button("πŸ”„ Clear Chat"):
st.session_state.messages = []
st.session_state.thread_id = None
st.session_state.image_url = None
st.session_state.image_updated = False
st.rerun()
show_image = st.sidebar.checkbox("πŸ“– Show Document Image", value=True)
# ------------------ Layout: Image (Left) and Chat (Right) ------------------
col1, col2 = st.columns([1, 2])
# ------------------ Left Panel: Document Image ------------------
with col1:
if show_image and st.session_state.image_url:
st.image(st.session_state.image_url, caption="πŸ“‘ Extracted Page", use_container_width=True)
st.session_state.image_updated = False
# ------------------ Right Panel: Chat Interface ------------------
with col2:
# -- Chat Input (Always at the Top)
prompt = st.chat_input("Type your question about the document...")
# -- Pair messages (user + assistant) for display
paired_messages = []
buffer = []
for msg in st.session_state.messages:
buffer.append(msg)
if msg["role"] == "assistant" and len(buffer) == 2:
paired_messages.append(buffer.copy())
buffer.clear()
if buffer:
paired_messages.append(buffer.copy())
# -- Display chat history (latest first, older scroll down)
with st.container():
for pair in reversed(paired_messages):
for msg in pair:
with st.chat_message(msg["role"]):
st.write(msg["content"])
# -- Process new prompt if entered
if prompt:
st.session_state.messages.append({"role": "user", "content": prompt})
try:
# Initialize thread if not already done
if st.session_state.thread_id is None:
thread = client.beta.threads.create()
st.session_state.thread_id = thread.id
# Send user message to assistant
client.beta.threads.messages.create(
thread_id=st.session_state.thread_id,
role="user",
content=prompt
)
# Trigger assistant run
run = client.beta.threads.runs.create(
thread_id=st.session_state.thread_id,
assistant_id=ASSISTANT_ID
)
# Wait for assistant to respond
with st.spinner("Assistant is thinking..."):
while True:
run_status = client.beta.threads.runs.retrieve(
thread_id=st.session_state.thread_id,
run_id=run.id
)
if run_status.status == "completed":
break
time.sleep(1)
# Retrieve latest assistant message
messages = client.beta.threads.messages.list(thread_id=st.session_state.thread_id)
assistant_message = None
for message in reversed(messages.data):
if message.role == "assistant":
assistant_message = message.content[0].text.value
break
st.session_state.messages.append({"role": "assistant", "content": assistant_message})
# -- Extract GitHub-hosted image URL if present
image_match = re.search(
r'https://raw\.githubusercontent\.com/AndrewLORTech/surgical-pathology-manual/main/[\w\-/]*\.png',
assistant_message
)
if image_match:
st.session_state.image_url = image_match.group(0)
st.session_state.image_updated = True
st.rerun() # Rerun to show updated image + message at top
except Exception as e:
st.error(f"❌ Error: {str(e)}")