File size: 4,912 Bytes
9d10d92
13919c8
 
 
2943948
 
 
13919c8
b386f62
8c4492e
d036356
af951b6
 
c1043ca
3e6c499
8c4492e
 
c1043ca
8c4492e
971b3be
8c4492e
c1043ca
8c4492e
c1043ca
8c4492e
 
 
 
 
 
 
 
 
c1043ca
af951b6
 
 
8c4492e
 
 
 
 
c1043ca
af951b6
8c4492e
af951b6
 
9c9251a
af951b6
 
9c9251a
af951b6
1ba534e
 
 
 
af951b6
1ba534e
 
af951b6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
eeb4027
af951b6
 
f534be4
74c6fff
9c9251a
 
 
 
 
 
af951b6
53fcb59
af951b6
53fcb59
af951b6
9c9251a
af951b6
9c9251a
 
 
 
74c6fff
9c9251a
 
 
af951b6
3bbf4ab
 
925961d
971b3be
7852a85
 
 
af951b6
 
bcaf273
f534be4
3e6c499
8c4492e
af951b6
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
import streamlit as st
import os
import time
import re
import requests
from PIL import Image
from io import BytesIO
from openai import OpenAI

# ------------------ App Configuration ------------------
st.set_page_config(page_title="Schlaeger Forrestdale DocAIA", layout="wide")
st.title("πŸ“„ Schlaeger Forrestdale Document Assistant")
st.caption("Chat with construction documents using OCR-based AI")

# ------------------ 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 "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 ------------------
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.toggle("πŸ“‘ Show Page Image", value=True)

# ------------------ Layout ------------------
image_col, chat_col = st.columns([1, 2])

# ------------------ Image Viewer ------------------
with image_col:
    if show_image and st.session_state.image_url:
        with st.spinner("Loading document preview..."):
            try:
                response = requests.get(st.session_state.image_url)
                response.raise_for_status()
                img = Image.open(BytesIO(response.content))
                st.image(img, caption="πŸ“„ OCR Page Image", use_container_width=True)
                st.session_state.image_updated = False
            except Exception as e:
                st.error(f"❗ Failed to load image: {e}")

# ------------------ Chat Interface ------------------
with chat_col:
    st.markdown("### 🧠 Ask a Question or Choose Below")
    prompt = st.chat_input("What would you like to ask about the construction documents?")

    # Quick Action Buttons
    st.markdown("#### ⚑ Quick Prompts")
    quick_cols = st.columns(3)
    with quick_cols[0]:
        if st.button("πŸ” Summary Mode"):
            prompt = "Summarize this section."
    with quick_cols[1]:
        if st.button("πŸ“˜ FAQ Mode"):
            prompt = "Generate FAQs from this section."
    with quick_cols[2]:
        if st.button("🧾 Compliance Info"):
            prompt = "What are the safety and compliance measures?"

    # Display Message History
    for msg in st.session_state.messages:
        with st.chat_message(msg["role"]):
            st.markdown(msg["content"])

    if prompt:
        st.session_state.messages.append({"role": "user", "content": prompt})
        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=prompt)

            run = client.beta.threads.runs.create(thread_id=st.session_state.thread_id, assistant_id=ASSISTANT_ID)

            with st.spinner("πŸ€– Processing your query..."):
                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)

            messages = client.beta.threads.messages.list(thread_id=st.session_state.thread_id)
            for message in reversed(messages.data):
                if message.role == "assistant":
                    assistant_message = message.content[0].text.value
                    st.session_state.messages.append({"role": "assistant", "content": assistant_message})
                    break

            match = re.search(r'Document Reference:\s+(.+?),\s+Page\s+(\d+)', assistant_message)
            if match:
                doc_name = match.group(1).strip()
                page = int(match.group(2))
                page_str = f"{page:04d}"
                image_url = f"https://raw.githubusercontent.com/AndrewLORTech/c2ozschlaegerforrestdale/main/{doc_name}/{doc_name}_page_{page_str}.png"
                st.session_state.image_url = image_url
                st.session_state.image_updated = True

            st.rerun()
        except Exception as e:
            st.error(f"❌ Error: {e}")