File size: 4,345 Bytes
a943362
b0b9691
 
2293c14
dd87cb1
 
 
b0b9691
 
dd87cb1
dbce7ce
 
 
 
f995bdc
9817165
dd87cb1
 
 
 
 
f995bdc
b0b9691
dd87cb1
 
 
 
 
 
 
 
 
85f1ed2
dd87cb1
 
 
dbce7ce
 
 
b0b9691
dd87cb1
b0b9691
dbce7ce
 
 
dd87cb1
 
 
 
 
b0b9691
dd87cb1
dbce7ce
dd87cb1
 
 
 
dbce7ce
 
dd87cb1
dbce7ce
 
 
 
 
 
 
 
 
 
 
dd87cb1
 
 
 
dbce7ce
 
dd87cb1
 
 
dbce7ce
 
b0b9691
dbce7ce
 
f995bdc
 
dbce7ce
 
 
 
 
f995bdc
dd87cb1
 
b0b9691
 
 
dbce7ce
dd87cb1
dbce7ce
dd87cb1
dbce7ce
 
 
 
 
dd87cb1
baa3d07
dbce7ce
 
9817165
dd87cb1
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
import os
import gradio as gr
from openai import OpenAI

API_HOSTS = {
    "Domestic": "https://api.chatanywhere.tech/v1",
    "Overseas": "https://api.chatanywhere.org/v1"
}

MODELS_INFO = {
    "gpt-3.5-turbo": {"input_price": "0.0035", "output_price": "0.0105", "features": "Default, fast, affordable"},
    "gpt-4o": {"input_price": "0.0175", "output_price": "0.07", "features": "Cheaper & faster GPT-4O"},
    "gpt-4-turbo": {"input_price": "0.07", "output_price": "0.21", "features": "Multimodal, tool use"},
    "gpt-4o-ca": {"input_price": "0.01", "output_price": "0.04", "features": "CA variant, daily free limit"},
}

def create_client(host):
    key = os.getenv("OPENAI_API_KEY")
    if not key:
        raise ValueError("Missing environment variable: OPENAI_API_KEY")
    return OpenAI(api_key=key, base_url=host)

def get_model_card(model_name):
    info = MODELS_INFO.get(model_name, {})
    if not info:
        return "Model info not available."
    return (
        f"**{model_name}**\n\n"
        f"Input price (/1K tokens): {info['input_price']}\n\n"
        f"Output price (/1K tokens): {info['output_price']}\n\n"
        f"Features: {info['features']}"
    )

def respond(user, history, host_choice, model_name, temperature, top_p, max_tokens, sys_prompt):
    history = history or []
    if not user.strip():
        yield history + [("", "⚠️ Please enter a message.")]
        return

    try:
        client = create_client(API_HOSTS[host_choice])
    except Exception as e:
        yield history + [("", f"❌ {e}")]
        return

    messages = [{"role": "system", "content": sys_prompt or "You are a helpful assistant."}]
    for u, a in history:
        messages.append({"role": "user", "content": u})
        messages.append({"role": "assistant", "content": a})
    messages.append({"role": "user", "content": user})

    try:
        stream = client.chat.completions.create(
            model=model_name,
            messages=messages,
            temperature=temperature,
            top_p=top_p,
            max_tokens=max_tokens,
            stream=True
        )

        partial = ""
        history.append((user, partial))
        yield history

        for chunk in stream:
            delta = chunk.choices[0].delta.content or ""
            partial += delta
            history[-1] = (user, partial)
            yield history

    except Exception as e:
        err = str(e)
        if "429" in err:
            out = (
                "🚫 Daily quota reached for this model.\n"
                "Please try again after 00:00 China time or switch model/host."
            )
        else:
            out = f"❌ API Error: {e}"
        history.append((user, out))
        yield history

with gr.Blocks(title="ChatAnywhere Realtime Chatbot", theme=gr.themes.Soft()) as demo:
    gr.Markdown("## πŸ’¬ ChatAnywhere Realtime Chatbot\nPowered by GPT-5 via ChatAnywhere API")
    with gr.Row():
        with gr.Column(scale=3):
            chat = gr.Chatbot(label="Conversation", height=500, show_copy_button=True, render_markdown=True)
            with gr.Row():
                msg = gr.Textbox(placeholder="Type your message...", lines=2, scale=4)
                send = gr.Button("Send", scale=1)
                clear = gr.Button("Clear", scale=1)
        with gr.Column(scale=1):
            host = gr.Radio(list(API_HOSTS.keys()), value="Domestic", label="API Host")
            model = gr.Dropdown(list(MODELS_INFO.keys()), value="gpt-3.5-turbo", label="Model")
            model_card = gr.Markdown(get_model_card("gpt-3.5-turbo"))
            temperature = gr.Slider(0.0, 1.5, value=0.7, step=0.05, label="Temperature")
            top_p = gr.Slider(0.05, 1.0, value=1.0, step=0.05, label="Top-p")
            max_tokens = gr.Slider(64, 4096, value=512, step=64, label="Max Tokens")
            sys_prompt = gr.Textbox(label="System Prompt (optional)", lines=2)

    model.change(lambda m: get_model_card(m), model, model_card)

    send.click(respond, [msg, chat, host, model, temperature, top_p, max_tokens, sys_prompt], chat)
    msg.submit(respond, [msg, chat, host, model, temperature, top_p, max_tokens, sys_prompt], chat)

    send.click(lambda _: "", msg, msg)
    msg.submit(lambda _: "", msg, msg)

    clear.click(lambda: [], None, chat)

if __name__ == "__main__":
    demo.launch()