File size: 5,369 Bytes
9d10d92
13919c8
 
 
2943948
 
 
13919c8
b386f62
8c4492e
d036356
8c4492e
7852a85
c1043ca
3e6c499
8c4492e
 
c1043ca
8c4492e
971b3be
8c4492e
c1043ca
8c4492e
c1043ca
8c4492e
 
 
 
 
 
 
 
 
c1043ca
8c01614
8c4492e
 
 
 
 
 
 
c1043ca
8c4492e
 
3e6c499
f534be4
9c9251a
3e6c499
9c9251a
 
1ba534e
 
 
 
 
 
 
 
 
9c9251a
3e6c499
9c9251a
1ba534e
74c6fff
1ba534e
eeb4027
 
 
 
 
 
 
 
 
 
3e6c499
 
 
1ba534e
f534be4
74c6fff
9c9251a
 
 
 
 
 
 
53fcb59
74c6fff
53fcb59
 
 
 
 
74c6fff
53fcb59
 
 
1ba534e
9c9251a
53fcb59
74c6fff
53fcb59
 
9c9251a
 
 
 
74c6fff
9c9251a
 
 
 
3bbf4ab
 
9c9251a
bcaf273
925961d
971b3be
7852a85
 
 
925961d
971b3be
7852a85
971b3be
925961d
bcaf273
f534be4
3e6c499
57d0c38
8c4492e
1ba534e
 
 
 
 
 
 
 
 
 
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
134
135
136
137
138
139
140
141
142
143
144
145
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("πŸ“„ Document AI Assistant")
st.caption("Chat with an AI Assistant on your construction documents")

# ------------------ 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 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 + Chat ------------------
col1, col2 = st.columns([1, 2])

# ------------------ Left Panel: Image ------------------
with col1:
    if show_image and st.session_state.image_url:
        with st.spinner("πŸ–ΌοΈ Loading image preview..."):
            try:
                response = requests.get(st.session_state.image_url)
                response.raise_for_status()
                img = Image.open(BytesIO(response.content))
                st.image(img, caption="πŸ“‘ Extracted Page", use_container_width=True)
                st.session_state.image_updated = False
            except Exception as e:
                st.warning(f"⚠️ Failed to load image from URL:\n{st.session_state.image_url}\n\nError: {e}")

# ------------------ Right Panel: Chat ------------------
with col2:
    prompt = st.chat_input("Type your question about the document or choose from FAQs below...")

    # Display chat history in a cleaner bubble layout
    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())

    for pair in reversed(paired_messages):
        for msg in pair:
            with st.chat_message(msg["role"]):
                st.markdown(f"{msg['content']}", unsafe_allow_html=True)

    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("πŸ€– 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)

            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})

            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}"
                corrected_url = (
                    f"https://raw.githubusercontent.com/AndrewLORTech/c2ozschlaegerforrestdale/main/"
                    f"{doc_name}/{doc_name}_page_{page_str}.png"
                )
                st.session_state.image_url = corrected_url
                st.session_state.image_updated = True

            st.rerun()

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

# ------------------ Suggested FAQs Section ------------------
st.markdown("""
<hr>
<b>🧠 Suggested FAQs:</b>
- What are the mechanical services on page 3?
- Summarize the demolition schedule.
- List the safety compliance steps.
""")