Spaces:
Running
Running
File size: 5,044 Bytes
8c4492e 13919c8 b386f62 8c4492e 8c01614 c1043ca 8c01614 8c4492e c1043ca 8c01614 8c4492e 6e52561 8c4492e c1043ca 8c4492e c1043ca 8c4492e c1043ca 8c01614 8c4492e c1043ca 8c4492e 8c01614 f534be4 9c9251a 8c01614 9c9251a f534be4 9c9251a 8c01614 9c9251a 8c01614 74c6fff 8c01614 eeb4027 8c01614 74c6fff f534be4 8c01614 74c6fff 9c9251a 8c01614 9c9251a 8c01614 53fcb59 74c6fff 53fcb59 8c01614 53fcb59 74c6fff 53fcb59 8c01614 6e52561 9c9251a 53fcb59 74c6fff 53fcb59 9c9251a 8c01614 74c6fff 9c9251a 3bbf4ab 9c9251a bcaf273 8c01614 bcaf273 1c29e60 bcaf273 f534be4 8c01614 57d0c38 8c4492e 9c9251a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
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)}")
|