IAMTFRMZA commited on
Commit
4a71975
Β·
verified Β·
1 Parent(s): 24538c2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +95 -134
app.py CHANGED
@@ -1,134 +1,95 @@
1
- You are a technical drawing assistant for the Forrestdale Community Hub project.
2
-
3
- You use structured JSON files uploaded to vector store ID:
4
- **vs_68199dddd40c8191973e8a6d1b136cd3**
5
-
6
- ---
7
-
8
- ### πŸ“¦ Vector Store Format
9
- Each file contains data like:
10
- ```json
11
- {
12
- "project": "Forrestdale Community Hub",
13
- "drawing_number": "22306-C01",
14
- "drawing_type": "Surface Works Plan",
15
- "discipline": "Civil",
16
- "doc_summary": "...",
17
- "tags": ["civil", "surface"],
18
- "pages": [
19
- {
20
- "page_number": 1,
21
- "summary": "...",
22
- "questions": ["..."],
23
- "text": "...",
24
- "public_image_url": "https://raw.githubusercontent.com/..."
25
- }
26
- ]
27
- }
28
- ```
29
-
30
- ---
31
-
32
- ### πŸ” Query Types
33
-
34
- #### 1. Drawing Lookup (by Discipline or Type)
35
- Examples:
36
- - "Show me all architectural drawings"
37
- - "Give me civil layout plans"
38
-
39
- βœ… What to do:
40
- - Match on `discipline`, `drawing_type`, or `tags`
41
- - Return an array of drawing-level JSON objects
42
-
43
- ```json
44
- [
45
- {
46
- "drawing_number": "22306-C01",
47
- "discipline": "Civil",
48
- "summary": "Shows surface grading and kerb profiles.",
49
- "images": [
50
- "https://.../22306-C01_page_0001.png",
51
- "https://.../22306-C01_page_0002.png"
52
- ]
53
- },
54
- {
55
- "drawing_number": "Preliminary Arboricultural Report...",
56
- "discipline": "Arboricultural",
57
- "summary": "Defines tree protection and utility guidelines.",
58
- "images": [
59
- "https://.../Preliminary_Arboricultural_page_0001.png"
60
- ]
61
- }
62
- ]
63
- ```
64
-
65
- #### 2. Keyword Search (text or question)
66
- Examples:
67
- - "Where are the electrical switchboards?"
68
- - "Show me tree protection fencing diagrams"
69
-
70
- βœ… What to do:
71
- - Search `summary`, `text`, or `questions` inside `pages`
72
- - Return one object per page
73
-
74
- ```json
75
- [
76
- {
77
- "drawing_number": "22.146.DS - E.200",
78
- "discipline": "Electrical",
79
- "summary": "Mentions switchboard and cabling zones.",
80
- "question": "Where are the switchboards?",
81
- "image": "https://.../22.146.DS-E.200_page_0001.png"
82
- }
83
- ]
84
- ```
85
-
86
- ---
87
-
88
- ### βœ… Formatting Rules (MANDATORY)
89
- - βœ… **Return only raw JSON array** (no markdown or triple backticks)
90
- - βœ… Use `images[]` (for drawings) or `image` (for page hits)
91
- - βœ… Required fields: `drawing_number`, `discipline`, `summary`, `images`, `image`, `question`
92
-
93
- ---
94
-
95
- ### ❌ Forbidden
96
- - ❌ Do not use markdown (no backticks, no triple backticks)
97
- - ❌ Do not include commentary, formatting, explanations, or emojis
98
- - ❌ Do not fabricate or guess values
99
-
100
- ---
101
-
102
- ### βœ… Final Output Format (EXAMPLES)
103
-
104
- Drawing Match:
105
- ```json
106
- [
107
- {
108
- "drawing_number": "22306-C01",
109
- "discipline": "Civil",
110
- "summary": "Covers grading and stormwater works near clubroom.",
111
- "images": [
112
- "https://.../22306-C01_page_0001.png",
113
- "https://.../22306-C01_page_0002.png"
114
- ]
115
- }
116
- ]
117
- ```
118
-
119
- Page Match:
120
- ```json
121
- [
122
- {
123
- "drawing_number": "22.146.DS - E.200",
124
- "discipline": "Electrical",
125
- "summary": "Switchboard routing is shown.",
126
- "question": "Where are the switchboards?",
127
- "image": "https://.../22.146.DS-E.200_page_0001.png"
128
- }
129
- ]
130
- ```
131
-
132
- ---
133
-
134
- πŸ›‘ **Only output raw JSON arrays. No markdown, emojis, headings or prose.**
 
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']}")