IAMTFRMZA commited on
Commit
9910527
Β·
verified Β·
1 Parent(s): e5575d0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +57 -66
app.py CHANGED
@@ -1,104 +1,95 @@
1
- import time
2
- import streamlit as st
3
- import openai
4
  import os
5
  import json
6
- import re
7
  import requests
8
- from PIL import Image
9
- from io import BytesIO
10
- from urllib.parse import quote
11
 
12
- # ------------------ Configuration ------------------
13
- st.set_page_config(page_title="Forrestdale Technical Drawing Assistant", layout="wide")
14
- st.markdown("""
15
- <h1 style='font-size: 2.5rem;'>πŸͺ Forrestdale Technical Drawing Assistant</h1>
16
- <p style='font-size: 1rem;'>Ask about plans, drawings or components</p>
17
- """, unsafe_allow_html=True)
18
 
19
- # ------------------ Environment ------------------
20
- OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
21
- ASSISTANT_ID = os.getenv("ASSISTANT_ID")
22
 
 
23
  if not OPENAI_API_KEY or not ASSISTANT_ID:
24
- st.error("❌ Missing environment variables: OPENAI_API_KEY or ASSISTANT_ID.")
25
  st.stop()
26
 
27
- client = openai.OpenAI(api_key=OPENAI_API_KEY)
28
 
29
- # ------------------ Helper Functions ------------------
30
- def extract_json_from_response(response_text):
31
- try:
32
- match = re.search(r"```json\s*([\s\S]+?)```", response_text.strip())
33
- if not match:
34
- raise ValueError("No valid JSON block found.")
35
- json_str = match.group(1).strip()
36
- return json.loads(json_str)
37
- except Exception as e:
38
- st.error("⚠️ Could not parse assistant response as JSON.")
39
- st.stop()
40
 
41
- def display_card(item):
42
- st.markdown("""
43
- <div style="border: 1px solid #333; border-radius: 12px; padding: 16px; margin: 10px; background-color: #111;">
44
- <h3>πŸ“ {} ({})</h3>
45
- <p><b>Discipline:</b> {}</p>
46
- <p><b>Summary:</b> {}</p>
47
- <div style="display: flex; flex-wrap: wrap; gap: 10px;">
48
- """.format(item["drawing_number"], item.get("drawing_type", ""), item["discipline"], item["summary"]), unsafe_allow_html=True)
49
-
50
- for img in item.get("images", []):
51
- try:
52
- response = requests.get(img)
53
- if response.status_code == 200:
54
- image = Image.open(BytesIO(response.content))
55
- st.image(image, caption=os.path.basename(img), width=200)
56
- except:
57
- st.warning(f"Image failed to load: {img}")
58
-
59
- st.markdown("</div></div>", unsafe_allow_html=True)
60
-
61
- # ------------------ Input ------------------
62
- query = st.text_input("Ask about plans, drawings or components", placeholder="Show me all architectural plans")
63
 
64
  if query:
65
- with st.spinner("πŸ” Querying assistant..."):
66
  try:
67
- if "thread_id" not in st.session_state:
 
68
  thread = client.beta.threads.create()
69
  st.session_state.thread_id = thread.id
70
 
 
71
  client.beta.threads.messages.create(
72
  thread_id=st.session_state.thread_id,
73
  role="user",
74
  content=query
75
  )
76
 
 
77
  run = client.beta.threads.runs.create(
78
  thread_id=st.session_state.thread_id,
79
  assistant_id=ASSISTANT_ID
80
  )
81
 
 
82
  while True:
83
  run_status = client.beta.threads.runs.retrieve(
84
  thread_id=st.session_state.thread_id,
85
  run_id=run.id
86
  )
87
- if run_status.status in ["completed", "failed", "cancelled"]:
88
  break
 
 
89
  time.sleep(1)
90
 
91
- if run_status.status != "completed":
92
- st.error(f"❌ Assistant run failed: {run_status.status}")
93
- else:
94
- messages = client.beta.threads.messages.list(thread_id=st.session_state.thread_id)
95
- for message in reversed(messages.data):
96
- if message.role == "assistant":
97
- response_text = message.content[0].text.value
98
- data = extract_json_from_response(response_text)
99
- for item in data:
100
- display_card(item)
101
- break
 
102
 
103
  except Exception as e:
104
- st.error(f"❌ Error during assistant call: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
  import json
3
+ import time
4
  import requests
5
+ import streamlit as st
6
+ from openai import OpenAI
 
7
 
8
+ # -------------------- CONFIG --------------------
9
+ OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
10
+ ASSISTANT_ID = os.environ.get("ASSISTANT_ID")
 
 
 
11
 
12
+ st.set_page_config(page_title="Forrestdale Technical Drawing Assistant", layout="wide")
13
+ st.title("🧱 Forrestdale Technical Drawing Assistant")
 
14
 
15
+ # -------------------- ERROR CHECK --------------------
16
  if not OPENAI_API_KEY or not ASSISTANT_ID:
17
+ st.error("❌ Missing API credentials. Please set OPENAI_API_KEY and ASSISTANT_ID as environment variables.")
18
  st.stop()
19
 
20
+ client = OpenAI(api_key=OPENAI_API_KEY)
21
 
22
+ # -------------------- CHAT SESSION --------------------
23
+ if "messages" not in st.session_state:
24
+ st.session_state.messages = []
25
+ if "thread_id" not in st.session_state:
26
+ st.session_state.thread_id = None
 
 
 
 
 
 
27
 
28
+ query = st.text_input("Ask about plans, drawings or components", placeholder="e.g. Show me all electrical plans")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
  if query:
31
+ with st.spinner("Querying assistant..."):
32
  try:
33
+ # Create thread if needed
34
+ if not st.session_state.thread_id:
35
  thread = client.beta.threads.create()
36
  st.session_state.thread_id = thread.id
37
 
38
+ # Submit message
39
  client.beta.threads.messages.create(
40
  thread_id=st.session_state.thread_id,
41
  role="user",
42
  content=query
43
  )
44
 
45
+ # Run assistant
46
  run = client.beta.threads.runs.create(
47
  thread_id=st.session_state.thread_id,
48
  assistant_id=ASSISTANT_ID
49
  )
50
 
51
+ # Poll for result
52
  while True:
53
  run_status = client.beta.threads.runs.retrieve(
54
  thread_id=st.session_state.thread_id,
55
  run_id=run.id
56
  )
57
+ if run_status.status == "completed":
58
  break
59
+ elif run_status.status in ("failed", "cancelled"):
60
+ raise Exception(f"Assistant failed: {run_status.status}")
61
  time.sleep(1)
62
 
63
+ # Fetch assistant message
64
+ messages = client.beta.threads.messages.list(thread_id=st.session_state.thread_id)
65
+ for message in reversed(messages.data):
66
+ if message.role == "assistant":
67
+ content = message.content[0].text.value.strip()
68
+ if content.startswith("```json") and content.endswith("```"):
69
+ json_block = content.strip("```json\n").strip("```")
70
+ parsed = json.loads(json_block)
71
+ st.session_state.messages.append(parsed)
72
+ else:
73
+ st.error("⚠️ Could not parse assistant response as JSON.")
74
+ break
75
 
76
  except Exception as e:
77
+ st.error(f"❌ Error: {e}")
78
+
79
+ # -------------------- DISPLAY RESULTS --------------------
80
+ if st.session_state.messages:
81
+ drawings = st.session_state.messages[-1]
82
+ if isinstance(drawings, list):
83
+ cols = st.columns(4)
84
+ for idx, item in enumerate(drawings):
85
+ with cols[idx % 4]:
86
+ st.subheader(f"πŸ“˜ {item['drawing_number']}")
87
+ st.caption(f"Discipline: {item['discipline']}")
88
+ st.write(item.get("summary", "No summary available."))
89
+ if "images" in item:
90
+ for img in item["images"][:1]:
91
+ st.image(img, use_column_width=True)
92
+ elif "image" in item:
93
+ st.image(item["image"], use_column_width=True)
94
+ if "question" in item:
95
+ st.markdown(f"**Related Question:** {item['question']}")