import streamlit as st import os import time import json from openai import OpenAI # App config st.set_page_config(page_title="🏗️ Forrestdale Technical Drawing Assistant", layout="wide") st.title("🏗️ Forrestdale Technical Drawing Assistant") st.caption("Ask about plans, drawings or components") # Load secrets OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY") ASSISTANT_ID = os.environ.get("ASSISTANT_ID") client = OpenAI(api_key=OPENAI_API_KEY) if not OPENAI_API_KEY or not ASSISTANT_ID: st.error("Missing secrets: OPENAI_API_KEY or ASSISTANT_ID") st.stop() # Session setup 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 # Prompt input prompt = st.chat_input("Ask something like 'Show me all civil drawings' or 'Where are the switchboards?'") if prompt: st.session_state.messages.append({"role": "user", "content": prompt}) # Chat + assistant processing if st.session_state.messages and st.session_state.messages[-1]["role"] == "user": 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("🔎 Querying assistant..."): 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": try: raw = message.content[0].text.value.strip() if raw.startswith("```json"): raw = raw.removeprefix("```json").removesuffix("```").strip() data = json.loads(raw) st.session_state.messages.append({"role": "assistant", "content": data}) except Exception as e: st.error(f"⚠️ Could not parse assistant response as JSON.\n{e}") break st.rerun() # Card view rendering for msg in st.session_state.messages: if msg["role"] == "assistant": data = msg["content"] if isinstance(data, list) and len(data) > 0: st.markdown("### 📋 Results") cols = st.columns(4) for i, item in enumerate(data): with cols[i % 4]: st.image(item.get("images", [item.get("image")])[0], caption=item["drawing_number"], use_column_width=True) with st.expander("Details"): st.write(f"**Discipline:** {item['discipline']}") st.write(f"**Summary:** {item['summary']}") if "question" in item: st.write(f"**Question:** {item['question']}") for idx, img in enumerate(item.get("images", [])): st.image(img, caption=f"Page {idx+1}", use_column_width=True) else: st.warning("Assistant returned no matching drawings.") elif msg["role"] == "user": with st.chat_message("user"): st.markdown(msg["content"])