File size: 3,294 Bytes
beed6a9
13919c8
930629f
13919c8
b386f62
beed6a9
8c4492e
beed6a9
8c4492e
c1043ca
beed6a9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2e0eb4d
beed6a9
 
56b7b50
beed6a9
 
 
 
 
 
 
 
 
 
 
2e0eb4d
beed6a9
 
 
 
 
 
 
 
 
 
 
 
2e0eb4d
beed6a9
 
 
 
 
 
 
 
56b7b50
beed6a9
56b7b50
beed6a9
 
 
 
 
56b7b50
beed6a9
 
 
 
 
 
56b7b50
beed6a9
 
 
930629f
beed6a9
 
7794a19
beed6a9
dc07f4a
beed6a9
 
 
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()