Spaces:
Sleeping
Sleeping
File size: 5,294 Bytes
80e3a1e 4a71975 1d2d6d2 a68bccd 18e25a2 a68bccd 1d2d6d2 4a71975 a68bccd 18e25a2 80e3a1e a68bccd 1d2d6d2 4a71975 a68bccd 4a71975 a68bccd 1d2d6d2 a68bccd 18e25a2 a4a4e16 4a71975 a68bccd 18e25a2 a4a4e16 1d2d6d2 4a71975 18e25a2 a4a4e16 18e25a2 a68bccd a4a4e16 |
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 |
import streamlit as st
import os
import time
import re
import requests
import json
from PIL import Image
from io import BytesIO
from urllib.parse import quote
from openai import OpenAI
# ------------------ App Configuration ------------------
st.set_page_config(page_title="Schlaeger Forrestdale TechDocAIA", layout="wide", initial_sidebar_state="collapsed")
st.title("π Schlaeger Forrestdale Document Assistant")
st.caption("Explore City of Armadale construction documents using AI + OCR π§")
# ------------------ Load API Key and Assistant ID ------------------
OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
ASSISTANT_ID = os.environ.get("ASSISTANT_ID")
if not OPENAI_API_KEY or not ASSISTANT_ID:
st.error("β Missing secrets. Please set both OPENAI_API_KEY and ASSISTANT_ID in 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 "pending_prompt" not in st.session_state:
st.session_state.pending_prompt = None
if "results" not in st.session_state:
st.session_state.results = []
if "lightbox_url" not in st.session_state:
st.session_state.lightbox_url = None
# ------------------ Sidebar ------------------
st.sidebar.header("βΉοΈ Information")
if st.sidebar.button("π§Ή Clear Chat"):
st.session_state.messages = []
st.session_state.thread_id = None
st.session_state.pending_prompt = None
st.session_state.results = []
st.session_state.lightbox_url = None
st.rerun()
# ------------------ Chat Input ------------------
user_prompt = st.chat_input("Ask about plans, drawings or components")
if user_prompt:
st.session_state.messages.append({"role": "user", "content": user_prompt})
# ------------------ Assistant Query ------------------
if st.session_state.messages and st.session_state.messages[-1]["role"] == "user":
try:
if st.session_state.thread_id is None:
thread = client.beta.threads.create()
st.session_state.thread_id = thread.id
client.beta.threads.messages.create(
thread_id=st.session_state.thread_id,
role="user",
content=st.session_state.messages[-1]["content"]
)
run = client.beta.threads.runs.create(
thread_id=st.session_state.thread_id,
assistant_id=ASSISTANT_ID
)
with st.spinner("π€ Parsing and responding..."):
while True:
run_status = client.beta.threads.runs.retrieve(
thread_id=st.session_state.thread_id,
run_id=run.id
)
if run_status.status in ("completed", "failed", "cancelled"):
break
time.sleep(1)
if run_status.status != "completed":
st.error(f"β οΈ Assistant failed: {run_status.status}")
else:
messages = client.beta.threads.messages.list(thread_id=st.session_state.thread_id)
for message in reversed(messages.data):
if message.role == "assistant":
assistant_reply = message.content[0].text.value
st.session_state.messages.append({"role": "assistant", "content": assistant_reply})
try:
json_data = json.loads(assistant_reply.strip("`json "))
st.session_state.results = json_data
except:
st.session_state.results = []
break
st.rerun()
except Exception as e:
st.error(f"β Error: {e}")
# ------------------ Sorting and Filters ------------------
if st.session_state.results:
disciplines = sorted(set(d.get("discipline", "") for d in st.session_state.results))
selected_discipline = st.selectbox("π Filter by discipline", ["All"] + disciplines)
page_size = 8
page_num = st.number_input("Page", min_value=1, step=1, value=1)
filtered_results = [r for r in st.session_state.results if selected_discipline == "All" or r.get("discipline") == selected_discipline]
paged = filtered_results[(page_num - 1) * page_size : page_num * page_size]
st.markdown("---")
st.subheader("π Drawing Results")
cols = st.columns(4)
for i, item in enumerate(paged):
with cols[i % 4]:
st.markdown(f"**{item['drawing_number']}**")
st.markdown(f"_Discipline: {item['discipline']}_")
st.caption(item.get("summary", ""))
for url in item.get("images", [])[:1]:
if st.button("πΌοΈ View Image", key=f"view_{i}"):
st.session_state.lightbox_url = url
if st.session_state.lightbox_url:
st.markdown("---")
st.image(st.session_state.lightbox_url, use_column_width=True, caption="π Enlarged Preview")
if st.button("β Close Viewer"):
st.session_state.lightbox_url = None
st.rerun()
else:
for msg in st.session_state.messages:
with st.chat_message(msg["role"]):
st.markdown(msg["content"], unsafe_allow_html=True) |