IAMTFRMZA commited on
Commit
3d9fd27
Β·
verified Β·
1 Parent(s): 209a87c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +77 -79
app.py CHANGED
@@ -1,97 +1,95 @@
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()
 
 
 
 
 
 
 
 
 
 
 
 
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}")