File size: 2,972 Bytes
27ee40d
7cda317
 
 
27ee40d
7cda317
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
407eb2d
 
7cda317
 
 
407eb2d
 
 
7cda317
 
 
 
 
 
 
 
 
 
 
407eb2d
 
7cda317
27ee40d
 
7cda317
 
 
407eb2d
 
 
 
27ee40d
7cda317
27ee40d
a0358a8
27ee40d
7cda317
ea20b3e
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
import os
import tempfile
import requests
import gradio as gr

ROBOT_IP = os.getenv("ROBOT_IP", "localhost")
ROBOT_PORT = int(os.getenv("ROBOT_PORT", "31950"))
OT_API_VERSION = os.getenv("OT_API_VERSION", "3")
TIMEOUT_SEC = float(os.getenv("HTTP_TIMEOUT", "30"))

def upload_protocol_file(filepath: str) -> str:
    endpoint = f"http://{ROBOT_IP}:{ROBOT_PORT}/protocols"
    headers = {"Opentrons-Version": OT_API_VERSION}
    filename = os.path.basename(filepath)

    try:
        with open(filepath, "rb") as f:
            files = {"files": (filename, f, "text/x-python")}
            resp = requests.post(endpoint, headers=headers, files=files, timeout=TIMEOUT_SEC)
    except requests.RequestException as e:
        return f"HTTP error: {e}"

    try:
        data = resp.json()
    except ValueError:
        return f"Non-JSON response (status={resp.status_code}):\n{resp.text[:1000]}"

    if resp.status_code >= 400:
        if isinstance(data, dict) and data.get("errors"):
            err = data["errors"][0]
            return (
                f"Upload failed (HTTP {resp.status_code})\n"
                f"id: {err.get('id')}\n"
                f"code: {err.get('errorCode')}\n"
                f"detail: {err.get('detail')}"
            )
        return f"Upload failed (HTTP {resp.status_code}):\n{data}"

    if isinstance(data, dict) and "data" in data:
        d = data["data"]
        summaries = d.get("analysisSummaries") or []
        return (
            "✅ success\n"
            f"protocol_id: {d.get('id')}\n"
            f"analysis_id: {(summaries[0].get('id') if summaries else None)}\n"
            f"analysis_status: {(summaries[0].get('status') if summaries else None)}"
        )

    return f"Unexpected response:\n{data}"

def send_message(text, history):
    text = (text or "").strip()
    history = history or []

    if not text:
        return history

    # user message
    history.append({"role": "user", "content": text})

    fd, path = tempfile.mkstemp(prefix="protocol_", suffix=".py")
    try:
        with os.fdopen(fd, "w", encoding="utf-8") as f:
            f.write(text)
        result = upload_protocol_file(path)
    finally:
        try:
            os.remove(path)
        except OSError:
            pass

    # assistant message
    history.append({"role": "assistant", "content": result})
    return history

with gr.Blocks() as app:
    gr.Markdown("## Opentrons Protocol Analyzer")
    textbox = gr.Textbox(lines=12, label="Paste protocol Python code")
    send_button = gr.Button(value="Analyze")

    # 旧Gradioでも動きやすい:余計な引数を渡さない
    chatbot = gr.Chatbot(label="Results")

    clear_button = gr.ClearButton([textbox, chatbot])

    send_button.click(send_message, [textbox, chatbot], [chatbot])
    textbox.submit(send_message, [textbox, chatbot], [chatbot])

if __name__ == "__main__":
    app.launch(server_name="0.0.0.0", server_port=int(os.getenv("PORT", "7860")))