Abs6187 commited on
Commit
b0b9691
·
verified ·
1 Parent(s): 85f1ed2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +163 -98
app.py CHANGED
@@ -1,126 +1,191 @@
1
- import gradio as gr
2
- from openai import OpenAI
3
  import os
4
  import time
 
 
 
 
5
 
6
  HOSTS = {
7
  "Domestic (Lower Latency)": "https://api.chatanywhere.tech/v1",
8
- "Overseas": "https://api.chatanywhere.org/v1"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  }
10
 
11
  def create_client(base_url):
12
  api_key = os.getenv("OPENAI_API_KEY")
13
  if not api_key:
14
- raise ValueError("Missing API key. Please set OPENAI_API_KEY in your environment.")
15
  return OpenAI(api_key=api_key, base_url=base_url)
16
 
17
- def respond_stream(user_message, history, host_choice, temperature):
18
- history = history or []
 
 
 
19
 
20
- # Empty message handling
21
- if not user_message.strip():
22
- yield history + [("", "⚠️ Please enter a message before sending.")]
23
- return
 
 
 
 
24
 
25
- # Prepare conversation context
26
- messages = [{"role": "system", "content": "You are GPT-5, a helpful, friendly, and concise assistant."}]
 
 
 
 
 
 
27
  for human, ai in history:
28
  messages.append({"role": "user", "content": human})
29
  messages.append({"role": "assistant", "content": ai})
30
  messages.append({"role": "user", "content": user_message})
31
-
32
- # API Host handling
33
- try:
34
- client = create_client(HOSTS[host_choice])
35
- except ValueError as e:
36
- yield history + [(user_message, f"❌ {e}")]
37
- return
38
- except Exception as e:
39
- yield history + [(user_message, f"❌ Failed to initialize client: {e}")]
40
- return
41
-
42
- # API request with streaming
43
- try:
44
- with client.chat.completions.stream(
45
- model="gpt-5",
46
- messages=messages,
47
- temperature=temperature,
48
- timeout=30 # network timeout
49
- ) as stream:
50
- partial = ""
51
- last_update_time = time.time()
52
-
53
- for event in stream:
54
- if event.type == "message.delta" and event.delta.content:
55
- partial += event.delta.content
56
-
57
- # Update UI at most 5 times per second
58
- if time.time() - last_update_time > 0.2:
59
- yield history + [(user_message, partial)]
60
- last_update_time = time.time()
61
-
62
- history.append((user_message, partial))
63
- yield history
64
-
65
- except Exception as e:
66
- # Retry with alternate host
67
  try:
68
- alt_host = HOSTS["Overseas"] if host_choice == "Domestic (Lower Latency)" else HOSTS["Domestic (Lower Latency)"]
69
- client = create_client(alt_host)
70
-
71
- with client.chat.completions.stream(
72
- model="gpt-5",
73
- messages=messages,
74
- temperature=temperature,
75
- timeout=30
76
- ) as stream:
77
  partial = ""
78
- for event in stream:
79
- if event.type == "message.delta" and event.delta.content:
80
- partial += event.delta.content
81
- yield history + [(user_message, partial)]
82
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  history.append((user_message, partial))
84
  yield history
85
-
86
- except Exception as e2:
87
- yield history + [(user_message, f"❌ Both API hosts failed.\nHost1 Error: {e}\nHost2 Error: {e2}")]
88
-
89
- # UI Layout
90
- with gr.Blocks(title="GPT-5 Chatbot", theme=gr.themes.Soft()) as demo:
91
- gr.Markdown("<h1 style='text-align:center'>💬 GPT-5 Chatbot</h1><p style='text-align:center'>Fast, resilient, and beautiful</p>")
92
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  with gr.Row():
94
  with gr.Column(scale=3):
95
- chatbot = gr.Chatbot(
96
- label="Conversation",
97
- bubble_full_width=False,
98
- height=500,
99
- show_copy_button=True,
100
- render_markdown=True
101
- )
102
- msg = gr.Textbox(placeholder="Type your message...", lines=1)
103
  with gr.Row():
104
- send_btn = gr.Button("Send", variant="primary")
105
- clear_btn = gr.Button("Clear Chat", variant="secondary")
106
-
 
 
 
 
107
  with gr.Column(scale=1):
108
- host_choice = gr.Radio(
109
- label="API Host",
110
- choices=list(HOSTS.keys()),
111
- value="Domestic (Lower Latency)"
112
- )
113
- temperature = gr.Slider(
114
- label="Creativity (Temperature)",
115
- minimum=0.0,
116
- maximum=1.5,
117
- value=0.7,
118
- step=0.1
119
- )
120
-
121
- send_btn.click(respond_stream, [msg, chatbot, host_choice, temperature], chatbot, queue=True)
122
- msg.submit(respond_stream, [msg, chatbot, host_choice, temperature], chatbot, queue=True)
123
- clear_btn.click(lambda: None, None, chatbot)
124
 
125
  if __name__ == "__main__":
126
- demo.queue().launch()
 
 
 
1
  import os
2
  import time
3
+ import json
4
+ import traceback
5
+ import gradio as gr
6
+ from openai import OpenAI
7
 
8
  HOSTS = {
9
  "Domestic (Lower Latency)": "https://api.chatanywhere.tech/v1",
10
+ "Overseas (Fallback)": "https://api.chatanywhere.org/v1"
11
+ }
12
+
13
+ MODELS = {
14
+ "o3": {"input": "0.014 / 1K Tokens", "output": "0.056 / 1K Tokens", "support": "support", "features": "Sets new standards for math, science, coding, visual reasoning tasks, and technical writing. Points o3-2025-04-16"},
15
+ "o3-2025-04-16": {"input": "0.014 / 1K Tokens", "output": "0.056 / 1K Tokens", "support": "support", "features": "Sets new standards for math, science, coding, visual reasoning tasks, and technical writing."},
16
+ "o4-mini": {"input": "0.0088 / 1K Tokens", "output": "0.0352 / 1K Tokens", "support": "support", "features": "Sets new standards for math, science, coding, visual reasoning tasks, and technical writing."},
17
+ "o4-mini-2025-04-16": {"input": "0.0088 / 1K Tokens", "output": "0.0352 / 1K Tokens", "support": "support", "features": "Sets new standards for math, science, coding, visual reasoning tasks, and technical writing."},
18
+ "gpt-4.1": {"input": "0.014 / 1K Tokens", "output": "0.056 / 1K Tokens", "support": "support", "features": "Improvements in encoding, instruction tracking, and long context. 1M input 32k output."},
19
+ "gpt-4.1-2025-04-14": {"input": "0.014 / 1K Tokens", "output": "0.056 / 1K Tokens", "support": "support", "features": "Improvements in encoding, instruction tracking, and long context, with 1M input and 32k output."},
20
+ "gpt-4.1-mini": {"input": "0.0028 / 1K Tokens", "output": "0.0112 / 1K Tokens", "support": "support", "features": "Improvements in encoding, instruction tracking, and long context."},
21
+ "gpt-4.1-mini-2025-04-14": {"input": "0.0028 / 1K Tokens", "output": "0.0112 / 1K Tokens", "support": "support", "features": "Improvements in encoding, instruction tracking, and long context, with 1M input and 32k output."},
22
+ "gpt-4.1-nano": {"input": "0.0007 / 1K Tokens", "output": "0.0028 / 1K Tokens", "support": "support", "features": "Improvements in encoding, instruction tracking, and long context."},
23
+ "gpt-4.1-nano-2025-04-14": {"input": "0.0007 / 1K Tokens", "output": "0.0028 / 1K Tokens", "support": "support", "features": "Improvements in encoding, instruction tracking, and long context, with 1M input and 32k output."},
24
+ "gpt-oss-20b": {"input": "0.0008 / 1K Tokens", "output": "0.0032 / 1K Tokens", "support": "support", "features": "Open source model."},
25
+ "gpt-oss-120b": {"input": "0.0044 / 1K Tokens", "output": "0.0176 / 1K Tokens", "support": "support", "features": "Open source model."},
26
+ "gpt-3.5-turbo": {"input": "0.0035 / 1K Tokens", "output": "0.0105 / 1K Tokens", "support": "support", "features": "Default model, equal to gpt-3.5-turbo-0125."},
27
+ "gpt-3.5-turbo-1106": {"input": "0.007 / 1K Tokens", "output": "0.014 / 1K Tokens", "support": "support", "features": "Model updated on November 6, 2023."},
28
+ "gpt-3.5-turbo-0125": {"input": "0.0035 / 1K Tokens", "output": "0.0105 / 1K Tokens", "support": "support", "features": "Model from January 25, 2024."},
29
+ "gpt-3.5-turbo-16k": {"input": "0.021 / 1K Tokens", "output": "0.028 / 1K Tokens", "support": "support", "features": "Longer context (16k)."},
30
+ "gpt-3.5-turbo-instruct": {"input": "0.0105 / 1K Tokens", "output": "0.014 / 1K Tokens", "support": "support", "features": "Completions-style instruct model."},
31
+ "o1-mini": {"input": "0.0088 / 1K Tokens", "output": "0.0352 / 1K Tokens", "support": "support", "features": "Reasoning models for complex tasks."},
32
+ "o1-preview": {"input": "0.105 / 1K Tokens", "output": "0.42 / 1K Tokens", "support": "support", "features": "Preview reasoning model."},
33
+ "o3-mini [5]": {"input": "0.0088 / 1K Tokens", "output": "0.0352 / 1K Tokens", "support": "support", "features": "Reasoning models."},
34
+ "o1 [5]": {"input": "0.12 / 1K Tokens", "output": "0.48 / 1K Tokens", "support": "support", "features": "Powerful reasoning model."},
35
+ "gpt-4o-search-preview": {"input": "0.0175 / 1K Tokens", "output": "0.07 / 1K Tokens", "support": "support", "features": "Search-enabled model (+search fee)."},
36
+ "gpt-4o-search-preview-2025-03-11": {"input": "0.0175 / 1K Tokens", "output": "0.07 / 1K Tokens", "support": "support", "features": "Search-enabled model."},
37
+ "gpt-4o-mini-search-preview": {"input": "0.00105 / 1K Tokens", "output": "0.0042 / 1K Tokens", "support": "support", "features": "Search-enabled mini model."},
38
+ "gpt-4o-mini-search-preview-2025-03-11": {"input": "0.00105 / 1K Tokens", "output": "0.0042 / 1K Tokens", "support": "support", "features": "Search-enabled mini model."},
39
+ "gpt-4": {"input": "0.21 / 1K Tokens", "output": "0.42 / 1K Tokens", "support": "support", "features": "Default GPT-4 family model."},
40
+ "gpt-4o": {"input": "0.0175 / 1K Tokens + Image Fee", "output": "0.07 / 1K Tokens", "support": "support", "features": "Cheaper/faster GPT-4O variant (+image fee)."},
41
+ "gpt-4o-2024-05-13": {"input": "0.035 / 1K Tokens + image fee", "output": "0.105 / 1K Tokens", "support": "support", "features": "GPT-4O release from 2024-05-13."},
42
+ "gpt-4o-2024-08-06": {"input": "0.0175 / 1K Tokens + Image Fee", "output": "0.07 / 1K Tokens", "support": "support", "features": "Supports 128k input and 16k output."},
43
+ "gpt-4o-2024-11-20": {"input": "0.0175 / 1K Tokens + Image Fee", "output": "0.07 / 1K Tokens", "support": "support", "features": "Improved creative writing."},
44
+ "chatgpt-4o-latest": {"input": "0.035 / 1K Tokens + image fee", "output": "0.105 / 1K Tokens", "support": "support", "features": "Dynamically updated version."},
45
+ "gpt-4o-mini": {"input": "0.00105 / 1K Tokens + Image Fee", "output": "0.0042 / 1K Tokens", "support": "support", "features": "Mini GPT-4O with image reading."},
46
+ "gpt-4-0613": {"input": "0.21 / 1K Tokens", "output": "0.42 / 1K Tokens", "support": "support", "features": "Updated June 13, 2023."},
47
+ "gpt-4-turbo-preview": {"input": "0.07 / 1K Tokens", "output": "0.21 / 1K Tokens", "support": "support", "features": "Preview turbo variant (128K input)."},
48
+ "gpt-4-0125-preview": {"input": "0.07 / 1K Tokens", "output": "0.21 / 1K Tokens", "support": "support", "features": "Preview updated Jan 25, 2024."},
49
+ "gpt-4-1106-preview": {"input": "0.07 / 1K Tokens", "output": "0.21 / 1K Tokens", "support": "support", "features": "Preview updated Nov 6, 2023."},
50
+ "gpt-4-vision-preview": {"input": "0.07 / 1K Tokens + Image Fee", "output": "0.21 / 1K Tokens", "support": "support", "features": "Multimodal with image recognition."},
51
+ "gpt-4-turbo": {"input": "0.07 / 1K Tokens + Image Fee", "output": "0.21 / 1K Tokens", "support": "support", "features": "Multimodal, function tools."},
52
+ "gpt-4-turbo-2024-04-09": {"input": "0.07 / 1K Tokens + image fee", "output": "0.21 / 1K Tokens", "support": "support", "features": "Preview turbo model."},
53
+ "gpt-4.1-ca": {"input": "0.008 / 1K Tokens", "output": "0.032 / 1K Tokens", "support": "support", "features": "Third-party provider CA variant."},
54
+ "gpt-4.1-mini-ca": {"input": "0.0016 / 1K Tokens", "output": "0.0064 / 1K Tokens", "support": "support", "features": "CA mini variant."},
55
+ "gpt-4.1-nano-ca": {"input": "0.0004 / 1K Tokens", "output": "0.003 / 1K Tokens", "support": "support", "features": "CA nano variant."},
56
+ "gpt-3.5-turbo-ca": {"input": "0.001 / 1K Tokens", "output": "0.0016 / 1K Tokens", "support": "support", "features": "CA region variant."},
57
+ "gpt-4-ca": {"input": "0.12 / 1K Tokens", "output": "0.24 / 1K Tokens", "support": "support", "features": "CA region variant."},
58
+ "gpt-4-turbo-ca": {"input": "0.04 / 1K Tokens + image fees", "output": "0.12 / 1K Tokens", "support": "support", "features": "CA region turbo."},
59
+ "gpt-4o-ca": {"input": "0.01 / 1K Tokens + image fees", "output": "0.04 / 1K Tokens", "support": "support", "features": "CA region GPT-4O."},
60
+ "gpt-4o-mini-ca": {"input": "0.00075 / 1K Tokens", "output": "0.003 / 1K Tokens", "support": "support", "features": "CA mini."},
61
+ "o1-mini-ca": {"input": "0.012 / 1K Tokens", "output": "0.048 / 1K Tokens", "support": "support", "features": "CA reasoning mini."},
62
+ "o1-preview-ca": {"input": "0.06 / 1K Tokens", "output": "0.24 / 1K Tokens", "support": "support", "features": "CA preview reasoning."}
63
+
64
  }
65
 
66
  def create_client(base_url):
67
  api_key = os.getenv("OPENAI_API_KEY")
68
  if not api_key:
69
+ raise ValueError("Missing OPENAI_API_KEY environment variable")
70
  return OpenAI(api_key=api_key, base_url=base_url)
71
 
72
+ def get_model_card(model_name):
73
+ m = MODELS.get(model_name)
74
+ if not m:
75
+ return "Model not found in catalog"
76
+ return f"**{model_name}**\n\nInput price: {m['input']}\n\nOutput price: {m['output']}\n\nSupport: {m['support']}\n\n{m['features']}"
77
 
78
+ def export_history(history):
79
+ try:
80
+ fname = f"chat_history_{int(time.time())}.json"
81
+ with open(fname, "w", encoding="utf-8") as f:
82
+ json.dump([{"user": u, "assistant": a} for u, a in (history or [])], f, ensure_ascii=False, indent=2)
83
+ return f"Saved to {fname}"
84
+ except Exception as e:
85
+ return f"Export failed: {e}"
86
 
87
+ def respond_stream(user_message, history, host_choice, model_name, temperature, top_p, max_tokens, system_prompt):
88
+ history = history or []
89
+ if not user_message or not user_message.strip():
90
+ yield history + [("", "⚠️ Please enter a message to send.")]
91
+ return
92
+ messages = []
93
+ sys_prompt = system_prompt.strip() if system_prompt and system_prompt.strip() else "You are a helpful, concise assistant."
94
+ messages.append({"role": "system", "content": sys_prompt})
95
  for human, ai in history:
96
  messages.append({"role": "user", "content": human})
97
  messages.append({"role": "assistant", "content": ai})
98
  messages.append({"role": "user", "content": user_message})
99
+ last_error = None
100
+ hosts_to_try = [HOSTS.get(host_choice)] if HOSTS.get(host_choice) else list(HOSTS.values())
101
+ for base in hosts_to_try:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
  try:
103
+ client = create_client(base)
104
+ except Exception as e:
105
+ last_error = e
106
+ continue
107
+ try:
108
+ try:
109
+ stream = client.chat.completions.stream(model=model_name, messages=messages, temperature=float(temperature), top_p=float(top_p), max_tokens=int(max_tokens), timeout=30)
 
 
110
  partial = ""
111
+ last_update = time.time()
112
+ with stream as s:
113
+ for event in s:
114
+ try:
115
+ if getattr(event, "type", None) == "message.delta":
116
+ delta = getattr(event, "delta", None)
117
+ content = getattr(delta, "content", None) if delta is not None else None
118
+ if content:
119
+ partial += content
120
+ if time.time() - last_update > 0.15:
121
+ yield history + [(user_message, partial)]
122
+ last_update = time.time()
123
+ elif getattr(event, "type", None) == "message":
124
+ content = getattr(event, "message", None)
125
+ content_text = None
126
+ if content and hasattr(content, "content"):
127
+ content_text = getattr(content.content, "get", lambda k, d=None: None)("text", None) if hasattr(content, "content") else None
128
+ if content_text:
129
+ partial += content_text
130
+ yield history + [(user_message, partial)]
131
+ except Exception:
132
+ pass
133
+ if not partial.strip():
134
+ partial = "No output received from model. Possible reasons: invalid model, API error, usage limits, or network timeout."
135
  history.append((user_message, partial))
136
  yield history
137
+ return
138
+ except AttributeError:
139
+ resp = client.chat.completions.create(model=model_name, messages=messages, temperature=float(temperature), top_p=float(top_p), max_tokens=int(max_tokens))
140
+ bot_reply = ""
141
+ try:
142
+ bot_reply = resp.choices[0].message.content
143
+ except Exception:
144
+ try:
145
+ bot_reply = resp["choices"][0]["message"]["content"]
146
+ except Exception:
147
+ bot_reply = str(resp)
148
+ if not bot_reply or not str(bot_reply).strip():
149
+ bot_reply = "No output received from model. Possible reasons: invalid model, API error, usage limits, or network timeout."
150
+ history.append((user_message, bot_reply))
151
+ yield history
152
+ return
153
+ except Exception as e:
154
+ last_error = e
155
+ continue
156
+ err_text = f"❌ All hosts failed. Last error: {last_error}\nCheck OPENAI_API_KEY, selected model, and network connectivity."
157
+ history.append((user_message, err_text))
158
+ yield history
159
+
160
+ model_choices = sorted(MODELS.keys())
161
+
162
+ with gr.Blocks(title="Polished GPT App", theme=gr.themes.Soft()) as demo:
163
+ gr.Markdown("<h2 style='text-align:center'>Polished GPT UI — Model Catalog Integrated</h2>")
164
  with gr.Row():
165
  with gr.Column(scale=3):
166
+ chatbot = gr.Chatbot(label="Conversation", height=520, show_copy_button=True, render_markdown=True)
 
 
 
 
 
 
 
167
  with gr.Row():
168
+ txt = gr.Textbox(placeholder="Type a message and press Enter", lines=2)
169
+ send = gr.Button("Send", variant="primary")
170
+ with gr.Row():
171
+ stop_btn = gr.Button("Stop", variant="secondary")
172
+ clear_btn = gr.Button("Clear", variant="secondary")
173
+ export_btn = gr.Button("Export")
174
+ status = gr.Markdown("")
175
  with gr.Column(scale=1):
176
+ host = gr.Radio(list(HOSTS.keys()), value="Domestic (Lower Latency)", label="API Host")
177
+ model_dropdown = gr.Dropdown(model_choices, value="gpt-3.5-turbo", label="Model")
178
+ model_card = gr.Markdown(get_model_card("gpt-3.5-turbo"))
179
+ temperature = gr.Slider(0.0, 1.5, value=0.7, step=0.05, label="Temperature")
180
+ top_p = gr.Slider(0.05, 1.0, value=1.0, step=0.05, label="Top-p")
181
+ max_tokens = gr.Slider(64, 8192, value=512, step=64, label="Max Tokens")
182
+ system_prompt = gr.Textbox(label="System Prompt (optional)", lines=3, placeholder="You are a helpful assistant.")
183
+ send.click(respond_stream, [txt, chatbot, host, model_dropdown, temperature, top_p, max_tokens, system_prompt], chatbot, queue=True)
184
+ txt.submit(respond_stream, [txt, chatbot, host, model_dropdown, temperature, top_p, max_tokens, system_prompt], chatbot, queue=True)
185
+ model_dropdown.change(lambda m: get_model_card(m), model_dropdown, model_card)
186
+ clear_btn.click(lambda: [], None, chatbot)
187
+ export_btn.click(lambda h: export_history(h), chatbot, status)
188
+ stop_btn.click(lambda: "stop", None, None)
 
 
 
189
 
190
  if __name__ == "__main__":
191
+ demo.queue().launch(server_name="0.0.0.0", server_port=7860, show_api=False)