File size: 4,432 Bytes
d32c90a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import os
import cohere
import gradio as gr

try:
    import spaces

    @spaces.GPU
    def _zerogpu_dummy():
        """Satisfies ZeroGPU startup check if Space is assigned ZeroGPU hardware."""
        pass
except Exception:
    pass

SYSTEM_PROMPT = "You are Simplify, a friendly tutor who turns complex ideas into clear, simple explanations that anyone can understand."


def chat(message, history, user_api_key):
    effective_key = (user_api_key or "").strip() or os.environ.get("COHERE_API_KEY")
    if not effective_key:
        yield "⚠️ Please enter your Cohere API key in the configuration box below to start chatting.\n\n👉 [Get your free Cohere API key here](https://dashboard.cohere.com/api-keys)"
        return

    co = cohere.ClientV2(api_key=effective_key)
    messages = [{"role": "system", "content": SYSTEM_PROMPT}]
    for msg in history:
        messages.append({"role": msg["role"], "content": msg["content"]})
    messages.append({"role": "user", "content": message})

    try:
        response = co.chat_stream(
            model="command-a-plus-05-2026",
            messages=messages,
            max_tokens=1500,
            temperature=0.3,
        )
        text = ""
        for event in response:
            if event.type == "content-delta":
                chunk = getattr(event.delta.message.content, "text", None)
                if chunk:
                    text += chunk
                    yield text
    except Exception as exc:
        yield f"⚠️ An error occurred: {exc}"


api_key_input = gr.Textbox(
    label="Cohere API Key",
    placeholder="Paste your Cohere API key here...",
    type="password",
    info="Don't have an API key? Get one for free at https://dashboard.cohere.com/api-keys",
)

message_input = gr.Textbox(
    placeholder="Type a message...",
    show_label=False,
    autofocus=True,
    submit_btn=True,
    stop_btn=True,
    elem_id="chat-input",
)

demo = gr.ChatInterface(
    fn=chat,
    textbox=message_input,
    title="Simplify",
    description="Breaks down complex concepts into their simplest, most intuitive form. Need a key? [Get a free Cohere API key here](https://dashboard.cohere.com/api-keys).",
    examples=[
        ["Explain derivatives in the simplest way"],
        ["What is quantum physics?"],
        ["Explain integrals simply"],
    ],
    additional_inputs=[api_key_input],
    additional_inputs_accordion=gr.Accordion(label="🔑 API Key Configuration", open=True),
    cache_examples=False,
)

if __name__ == "__main__":
    demo.launch(
        js=r"""
    (() => {
        const selector = "#chat-input textarea";

        const focusWhenReady = () => {
            let attempts = 0;
            let sawDisabled = false;
            let timer;

            const tryFocus = () => {
                const input = document.querySelector(selector);
                if (!input) {
                    if (++attempts >= 300) clearInterval(timer);
                    return;
                }

                if (input.disabled) {
                    sawDisabled = true;
                }

                // Do not focus too early: Gradio disables the textbox during
                // submission and enables it again after the streamed reply.
                if (!input.disabled && (sawDisabled || attempts >= 5)) {
                    input.focus();
                    clearInterval(timer);
                } else if (++attempts >= 300) {
                    clearInterval(timer);
                }
            };

            // Let Gradio process the submit first. While the response streams,
            // the textbox is disabled; focus it as soon as it is enabled again.
            timer = setInterval(tryFocus, 100);
            setTimeout(tryFocus, 150);
        };

        document.addEventListener("click", (event) => {
            if (
                event.target instanceof Element &&
                event.target.closest("#chat-input [data-testid='submit-button']")
            ) {
                focusWhenReady();
            }
        }, true);

        document.addEventListener("keydown", (event) => {
            if (
                event.key === "Enter" &&
                !event.shiftKey &&
                event.target instanceof Element &&
                event.target.matches(selector)
            ) {
                focusWhenReady();
            }
        }, true);
    })();
    """,
    )