File size: 5,943 Bytes
4cfa289
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# Path: QAgents-workflows/ui/chat_components.py
# Relations: Uses orchestrators/orchestrator.py (NakedOrchestrator)
#            Used by __init__.py, app.py
# Description: Chat UI components for interacting with quantum circuit agents
"""
Chat Components: Gradio 6.0 compatible chat interface for QAgents.

Provides:
- Chat tab creation
- Message handling with NAKED mode orchestrator
- Help and status commands
"""

import gradio as gr
import logging
from typing import List, Dict, Any, Tuple

logger = logging.getLogger(__name__)


def generate_circuit_with_naked(prompt: str) -> str:
    """
    Generate a quantum circuit using NAKED mode (direct LLM call).
    This is the simplest and fastest mode.
    
    Args:
        prompt: User's natural language request
        
    Returns:
        Formatted response with circuit or error message
    """
    try:
        # Lazy import to avoid startup issues
        from orchestrators import create_orchestrator
        
        orch = create_orchestrator("naked")
        result = orch.run(prompt)

        if result.success:
            output = f"✅ **Success** ({result.execution_time_ms:.0f}ms)\n\n"
            if result.final_output:
                if 'OPENQASM' in str(result.final_output) or 'qreg' in str(result.final_output):
                    output += f"```qasm\n{result.final_output}\n```"
                else:
                    output += str(result.final_output)
            return output
        else:
            error_msg = "\n".join(result.errors) if result.errors else "Unknown error"
            return f"❌ **Failed** ({result.execution_time_ms:.0f}ms)\n\n{error_msg}"
    except Exception as e:
        logger.error(f"NAKED mode error: {e}")
        return f"❌ **Error**: {str(e)}"


def get_help_text() -> str:
    """Return help text for the chat interface."""
    return """## 🤖 QAgents Help

I can help you with quantum circuits! Try asking me to:

**Create Circuits:**
- "Create a Bell state"
- "Generate a 3-qubit GHZ state"
- "Make a QFT circuit for 4 qubits"
- "Build a simple superposition"

**Examples:**
- "Create a circuit that puts 2 qubits in superposition"
- "Generate a CNOT gate between qubit 0 and 1"
- "Build a quantum teleportation circuit"

💡 **Tip:** Be specific about the number of qubits and desired operations!

**Commands:**
- `help` - Show this help message
- `status` - Check system status"""


def get_status_text(mcp_server_url: str) -> str:
    """Return status text for the chat interface."""
    try:
        from ui.mcp_health import check_mcp_health
        health = check_mcp_health()
        return f"## 📊 System Status\n\n{health}\n\n**MCP Server:** `{mcp_server_url}`"
    except Exception as e:
        return f"## 📊 System Status\n\n🔴 **Error checking status**: {str(e)}"


def chat_response(message: str, history: List, mcp_server_url: str = "") -> str:
    """
    Handle chat messages and generate responses.
    Uses NAKED mode for circuit generation.
    
    Args:
        message: User's message
        history: Chat history
        mcp_server_url: URL of the MCP server
        
    Returns:
        Bot's response message
    """
    if not message.strip():
        return ""

    message_lower = message.lower().strip()

    # Help command
    if message_lower in ['help', '/help', '?']:
        return get_help_text()

    # Status command
    if message_lower in ['status', '/status']:
        return get_status_text(mcp_server_url)

    # Generate circuit
    logger.info(f"Generating circuit for: {message}")
    return generate_circuit_with_naked(message)


def create_chat_tab(mcp_server_url: str = "") -> Tuple[gr.Chatbot, gr.Textbox, gr.Button]:
    """
    Create the chat tab components for Gradio 6.0.
    
    Args:
        mcp_server_url: URL of the MCP server for status checks
        
    Returns:
        Tuple of (chatbot, textbox, send_button) components
    """
    gr.Markdown("### Chat with Quantum Circuit Agent")
    gr.Markdown("Ask me to create quantum circuits! Try: *'Create a Bell state'* or *'Generate a 3-qubit GHZ state'*")

    chatbot = gr.Chatbot(
        value=[],
        height=400,
        label="Quantum Circuit Agent"
    )

    with gr.Row():
        msg_input = gr.Textbox(
            placeholder="Ask me to create a quantum circuit...",
            label="Your Message",
            scale=4,
            lines=1
        )
        send_btn = gr.Button("Send 🚀", variant="primary", scale=1)

    with gr.Row():
        clear_btn = gr.Button("🗑️ Clear", size="sm")
        help_btn = gr.Button("❓ Help", size="sm")
        status_btn = gr.Button("📊 Status", size="sm")

    # Chat handlers
    def respond(message: str, chat_history: List):
        if not message.strip():
            return "", chat_history

        bot_response = chat_response(message, chat_history, mcp_server_url)
        chat_history.append({"role": "user", "content": message})
        chat_history.append({"role": "assistant", "content": bot_response})
        return "", chat_history

    def show_help(chat_history: List):
        help_text = get_help_text()
        chat_history.append({"role": "user", "content": "help"})
        chat_history.append({"role": "assistant", "content": help_text})
        return chat_history

    def show_status(chat_history: List):
        status_text = get_status_text(mcp_server_url)
        chat_history.append({"role": "user", "content": "status"})
        chat_history.append({"role": "assistant", "content": status_text})
        return chat_history

    # Wire up events
    send_btn.click(respond, [msg_input, chatbot], [msg_input, chatbot])
    msg_input.submit(respond, [msg_input, chatbot], [msg_input, chatbot])
    clear_btn.click(lambda: [], outputs=[chatbot])
    help_btn.click(show_help, [chatbot], [chatbot])
    status_btn.click(show_status, [chatbot], [chatbot])

    return chatbot, msg_input, send_btn