IAMTFRMZA commited on
Commit
beed6a9
Β·
verified Β·
1 Parent(s): dc07f4a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +79 -77
app.py CHANGED
@@ -1,95 +1,97 @@
1
- import streamlit as st
2
  import os
3
- import time
4
  import json
5
- import re
6
  from openai import OpenAI
7
 
8
- # Basic config
9
- st.set_page_config(page_title="Forrestdale Drawing Viewer", layout="wide")
10
- st.title("πŸ“ Forrestdale Technical Drawing Assistant")
11
-
12
  OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
13
- ASSISTANT_ID = "asst_DjvuWBc7tCvMbAhY7n1em4BZ"
14
-
15
- if not OPENAI_API_KEY:
16
- st.error("❌ Missing OPENAI_API_KEY.")
17
- st.stop()
18
-
19
  client = OpenAI(api_key=OPENAI_API_KEY)
20
 
21
- if "tech_thread_id" not in st.session_state:
22
- thread = client.beta.threads.create()
23
- st.session_state.tech_thread_id = thread.id
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
- if "tech_messages" not in st.session_state:
26
- st.session_state.tech_messages = []
27
 
28
- prompt = st.chat_input("Ask about plans, drawings or components (e.g. Show me all electrical plans)")
29
- if prompt:
30
- st.session_state.tech_messages.append({"role": "user", "content": prompt})
 
 
 
 
 
 
 
 
31
 
32
- for msg in st.session_state.tech_messages:
33
- with st.chat_message(msg["role"]):
34
- st.markdown(msg["content"])
 
 
 
 
 
 
 
 
 
35
 
36
- # Fetch assistant reply
37
- if st.session_state.tech_messages and st.session_state.tech_messages[-1]["role"] == "user":
38
- with st.spinner("⏳ Fetching results from assistant..."):
39
- try:
40
- client.beta.threads.messages.create(
41
- thread_id=st.session_state.tech_thread_id,
42
- role="user",
43
- content=st.session_state.tech_messages[-1]["content"]
44
  )
 
45
 
46
- run = client.beta.threads.runs.create(
47
- thread_id=st.session_state.tech_thread_id,
48
- assistant_id=ASSISTANT_ID
49
- )
 
50
 
51
- while True:
52
- run_status = client.beta.threads.runs.retrieve(
53
- thread_id=st.session_state.tech_thread_id,
54
- run_id=run.id
55
- )
56
- if run_status.status in ["completed", "failed", "cancelled"]:
57
- break
58
- time.sleep(1)
59
 
60
- if run_status.status != "completed":
61
- st.error("⚠️ Assistant run failed.")
62
- else:
63
- messages = client.beta.threads.messages.list(thread_id=st.session_state.tech_thread_id)
64
- for message in reversed(messages.data):
65
- if message.role == "assistant":
66
- reply_content = message.content[0].text.value.strip()
67
- st.session_state.tech_messages.append({"role": "assistant", "content": reply_content})
68
 
69
- try:
70
- match = re.search(r"```json\s*(.*?)```", reply_content, re.DOTALL)
71
- json_str = match.group(1) if match else reply_content
72
- results = json.loads(json_str)
73
 
74
- if isinstance(results, list):
75
- cols = st.columns(4)
76
- for idx, item in enumerate(results):
77
- with cols[idx % 4]:
78
- with st.container(border=True):
79
- st.markdown(f"### πŸ“ {item.get('drawing_number')} ({item.get('discipline')})", help=item.get("summary"))
80
- st.caption(item.get("summary"))
81
 
82
- with st.expander("πŸ“‚ View Drawing Details"):
83
- if item.get("question"):
84
- st.markdown(f"**Question Match:** {item.get('question')}")
85
- if item.get("image"):
86
- st.image(item.get("image"), caption=item.get("drawing_number"))
87
- elif item.get("images"):
88
- for i, img in enumerate(item["images"]):
89
- if img.startswith("http"):
90
- st.image(img, caption=f"{item['drawing_number']} – Page {i+1}")
91
- except Exception as parse_error:
92
- st.warning("🟑 Could not parse assistant response as JSON.")
93
- break
94
- except Exception as e:
95
- st.error(f"❌ Error occurred: {e}")
 
1
+ import gradio as gr
2
  import os
 
3
  import json
 
4
  from openai import OpenAI
5
 
6
+ # ========== Config ==========
 
 
 
7
  OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
8
+ ASSISTANT_ID = os.environ.get("ASSISTANT_ID")
 
 
 
 
 
9
  client = OpenAI(api_key=OPENAI_API_KEY)
10
 
11
+ # ========== Functions ==========
12
+ def query_assistant(message):
13
+ try:
14
+ thread = client.beta.threads.create()
15
+ client.beta.threads.messages.create(
16
+ thread_id=thread.id,
17
+ role="user",
18
+ content=message
19
+ )
20
+ run = client.beta.threads.runs.create(
21
+ thread_id=thread.id,
22
+ assistant_id=ASSISTANT_ID
23
+ )
24
+
25
+ # Poll run status
26
+ while True:
27
+ run_status = client.beta.threads.runs.retrieve(
28
+ thread_id=thread.id,
29
+ run_id=run.id
30
+ )
31
+ if run_status.status in ("completed", "failed", "cancelled"):
32
+ break
33
 
34
+ if run_status.status != "completed":
35
+ return f"❌ Assistant failed: {run_status.status}", []
36
 
37
+ messages = client.beta.threads.messages.list(thread_id=thread.id)
38
+ for m in reversed(messages.data):
39
+ if m.role == "assistant":
40
+ try:
41
+ parsed = json.loads(m.content[0].text.value)
42
+ return None, parsed.get("results", [])
43
+ except Exception as e:
44
+ return f"⚠️ Failed to parse assistant response: {e}", []
45
+ return "⚠️ No assistant response found", []
46
+ except Exception as e:
47
+ return f"❌ Error: {e}", []
48
 
49
+ def render_cards(results):
50
+ cards = []
51
+ for r in results:
52
+ title = r.get("drawing_title", "Untitled")
53
+ summary = r.get("summary", "")
54
+ pages = r.get("pages", [])
55
+ image_elems = []
56
+ for page in pages:
57
+ url = page.get("public_image_url")
58
+ label = f"{title} – Page {page.get('page_number')}"
59
+ if url:
60
+ image_elems.append(gr.Image(value=url, label=label, show_label=True))
61
 
62
+ with gr.Column(scale=1):
63
+ cards.append(
64
+ gr.Group(
65
+ [
66
+ gr.Markdown(f"**{title}**\n\n**Summary:** {summary}"),
67
+ gr.Accordion("πŸ“‚ View Drawing Pages", open=False, children=image_elems)
68
+ ]
69
+ )
70
  )
71
+ return cards
72
 
73
+ def on_query_submit(prompt):
74
+ status, results = query_assistant(prompt)
75
+ if status:
76
+ return status, []
77
+ return "βœ… Found matching drawings", render_cards(results)
78
 
79
+ # ========== Interface ==========
80
+ with gr.Blocks(theme=gr.themes.Base(), title="Forrestdale Technical Drawing Assistant") as app:
81
+ gr.Markdown("""
82
+ # πŸ—οΈ Forrestdale Technical Drawing Assistant
83
+ Ask about plans, drawings or components (e.g. _Show me all electrical plans_)
84
+ """)
 
 
85
 
86
+ with gr.Row():
87
+ query_input = gr.Textbox(placeholder="e.g. Show me all civil drainage plans", scale=5)
88
+ query_button = gr.Button("πŸ” Search", scale=1)
 
 
 
 
 
89
 
90
+ status_output = gr.Markdown("", visible=True)
91
+ result_display = gr.Column()
 
 
92
 
93
+ query_button.click(fn=on_query_submit, inputs=query_input, outputs=[status_output, result_display])
 
 
 
 
 
 
94
 
95
+ # ========== Launch ==========
96
+ if __name__ == "__main__":
97
+ app.launch()