File size: 3,294 Bytes
209a87c
4a71975
209a87c
9910527
4a71975
209a87c
9910527
 
 
4a71975
209a87c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f1f3914
209a87c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f1f3914
209a87c
18e25a2
209a87c
 
 
 
 
717ae43
209a87c
 
 
 
 
 
f1f3914
209a87c
 
 
717ae43
209a87c
 
9910527
209a87c
717ae43
209a87c
 
 
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
import gradio as gr
import os
import json
from openai import OpenAI

# ========== Config ==========
OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
ASSISTANT_ID = os.environ.get("ASSISTANT_ID")
client = OpenAI(api_key=OPENAI_API_KEY)

# ========== Functions ==========
def query_assistant(message):
    try:
        thread = client.beta.threads.create()
        client.beta.threads.messages.create(
            thread_id=thread.id,
            role="user",
            content=message
        )
        run = client.beta.threads.runs.create(
            thread_id=thread.id,
            assistant_id=ASSISTANT_ID
        )

        # Poll run status
        while True:
            run_status = client.beta.threads.runs.retrieve(
                thread_id=thread.id,
                run_id=run.id
            )
            if run_status.status in ("completed", "failed", "cancelled"):
                break

        if run_status.status != "completed":
            return f"❌ Assistant failed: {run_status.status}", []

        messages = client.beta.threads.messages.list(thread_id=thread.id)
        for m in reversed(messages.data):
            if m.role == "assistant":
                try:
                    parsed = json.loads(m.content[0].text.value)
                    return None, parsed.get("results", [])
                except Exception as e:
                    return f"⚠️ Failed to parse assistant response: {e}", []
        return "⚠️ No assistant response found", []
    except Exception as e:
        return f"❌ Error: {e}", []

def render_cards(results):
    cards = []
    for r in results:
        title = r.get("drawing_title", "Untitled")
        summary = r.get("summary", "")
        pages = r.get("pages", [])
        image_elems = []
        for page in pages:
            url = page.get("public_image_url")
            label = f"{title} – Page {page.get('page_number')}"
            if url:
                image_elems.append(gr.Image(value=url, label=label, show_label=True))

        with gr.Column(scale=1):
            cards.append(
                gr.Group(
                    [
                        gr.Markdown(f"**{title}**\n\n**Summary:** {summary}"),
                        gr.Accordion("πŸ“‚ View Drawing Pages", open=False, children=image_elems)
                    ]
                )
            )
    return cards

def on_query_submit(prompt):
    status, results = query_assistant(prompt)
    if status:
        return status, []
    return "βœ… Found matching drawings", render_cards(results)

# ========== Interface ==========
with gr.Blocks(theme=gr.themes.Base(), title="Forrestdale Technical Drawing Assistant") as app:
    gr.Markdown("""
    # πŸ—οΈ Forrestdale Technical Drawing Assistant
    Ask about plans, drawings or components (e.g. _Show me all electrical plans_)
    """)

    with gr.Row():
        query_input = gr.Textbox(placeholder="e.g. Show me all civil drainage plans", scale=5)
        query_button = gr.Button("πŸ” Search", scale=1)

    status_output = gr.Markdown("", visible=True)
    result_display = gr.Column()

    query_button.click(fn=on_query_submit, inputs=query_input, outputs=[status_output, result_display])

# ========== Launch ==========
if __name__ == "__main__":
    app.launch()