eleeter commited on
Commit
bb8bed6
Β·
verified Β·
1 Parent(s): 74fe474

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +61 -39
app.py CHANGED
@@ -33,7 +33,7 @@ ALL_PROVIDERS = [
33
  {
34
  "name": "gemini",
35
  "base_url": "https://generativelanguage.googleapis.com/v1beta/openai/",
36
- "model": "gemini-2.0-flash",
37
  "daily_limit": 1500,
38
  "priority": 2,
39
  },
@@ -68,17 +68,28 @@ ACTIVE_PROVIDERS = [
68
 
69
  # ── Usage tracker ──
70
  usage_count = defaultdict(int)
 
71
  last_reset = time.time()
72
 
73
- def pick_provider():
74
  global last_reset
75
- if time.time() - last_reset > 86400: # reset every 24h
 
 
 
76
  usage_count.clear()
 
77
  last_reset = time.time()
78
 
79
- # Pick provider with most remaining capacity, respecting priority
 
 
 
 
 
 
80
  return min(
81
- ACTIVE_PROVIDERS,
82
  key=lambda p: (
83
  usage_count[p["name"]] / p["daily_limit"], # % used
84
  p["priority"] # tiebreak by priority
@@ -92,14 +103,7 @@ def respond(message, history):
92
  yield "❌ No API keys provided! Add them in your Space's Settings β†’ Variables and Secrets."
93
  return
94
 
95
- provider = pick_provider()
96
- print(f"Using: {provider['name']} | uses today: {usage_count[provider['name']]}")
97
-
98
- client = OpenAI(
99
- api_key=API_KEYS[provider["name"]],
100
- base_url=provider["base_url"],
101
- )
102
-
103
  messages = [{"role": "system", "content": SYSTEM_PROMPT}]
104
  for exchange in history[-3:]:
105
  user_msg = exchange[0] if isinstance(exchange, (list, tuple)) else ""
@@ -110,32 +114,50 @@ def respond(message, history):
110
  messages.append({"role": "assistant", "content": asst_msg})
111
  messages.append({"role": "user", "content": message})
112
 
113
- try:
114
- stream = client.chat.completions.create(
115
- model=provider["model"],
116
- messages=messages,
117
- max_tokens=200,
118
- temperature=0.7,
119
- stream=True,
 
 
 
 
 
 
 
120
  )
121
- usage_count[provider["name"]] += 1
122
-
123
- response_text = ""
124
- for chunk in stream:
125
- token = chunk.choices[0].delta.content or ""
126
- response_text += token
127
- yield response_text
128
-
129
- except Exception as e:
130
- err = str(e).lower()
131
- if "401" in err or "unauthorized" in err or "invalid api key" in err:
132
- yield f"❌ API key for **{provider['name']}** is invalid or expired!"
133
- elif "429" in err or "rate limit" in err:
134
- yield f"⚠️ **{provider['name']}** hit rate limit β€” try again in a moment"
135
- elif "quota" in err or "exceeded" in err:
136
- yield f"⚠️ **{provider['name']}** daily quota exceeded"
137
- else:
138
- yield f"⚠️ **{provider['name']}** error: {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
139
 
140
  # ── Startup summary ──
141
  print("\n=== Provider Status ===")
@@ -162,4 +184,4 @@ demo = gr.ChatInterface(
162
  )
163
 
164
  if __name__ == "__main__":
165
- demo.launch()
 
33
  {
34
  "name": "gemini",
35
  "base_url": "https://generativelanguage.googleapis.com/v1beta/openai/",
36
+ "model": "gemini-2.5-flash",
37
  "daily_limit": 1500,
38
  "priority": 2,
39
  },
 
68
 
69
  # ── Usage tracker ──
70
  usage_count = defaultdict(int)
71
+ bad_keys = set() # permanently skip these for the session (bad key)
72
  last_reset = time.time()
73
 
74
+ def pick_provider(exclude=None):
75
  global last_reset
76
+ if exclude is None:
77
+ exclude = set()
78
+
79
+ if time.time() - last_reset > 86400: # reset counts every 24h
80
  usage_count.clear()
81
+ bad_keys.clear()
82
  last_reset = time.time()
83
 
84
+ available = [
85
+ p for p in ACTIVE_PROVIDERS
86
+ if p["name"] not in exclude and p["name"] not in bad_keys
87
+ ]
88
+ if not available:
89
+ return None
90
+
91
  return min(
92
+ available,
93
  key=lambda p: (
94
  usage_count[p["name"]] / p["daily_limit"], # % used
95
  p["priority"] # tiebreak by priority
 
103
  yield "❌ No API keys provided! Add them in your Space's Settings β†’ Variables and Secrets."
104
  return
105
 
106
+ # Build messages once β€” reused across retries
 
 
 
 
 
 
 
107
  messages = [{"role": "system", "content": SYSTEM_PROMPT}]
108
  for exchange in history[-3:]:
109
  user_msg = exchange[0] if isinstance(exchange, (list, tuple)) else ""
 
114
  messages.append({"role": "assistant", "content": asst_msg})
115
  messages.append({"role": "user", "content": message})
116
 
117
+ tried = set() # skip these for this request only
118
+
119
+ while True:
120
+ provider = pick_provider(exclude=tried)
121
+
122
+ if provider is None:
123
+ yield "❌ All providers failed or hit limits. Try again later."
124
+ return
125
+
126
+ print(f"Trying: {provider['name']} | uses today: {usage_count[provider['name']]}")
127
+
128
+ client = OpenAI(
129
+ api_key=API_KEYS[provider["name"]],
130
+ base_url=provider["base_url"],
131
  )
132
+
133
+ try:
134
+ stream = client.chat.completions.create(
135
+ model=provider["model"],
136
+ messages=messages,
137
+ max_tokens=200,
138
+ temperature=0.7,
139
+ stream=True,
140
+ )
141
+ usage_count[provider["name"]] += 1
142
+
143
+ response_text = ""
144
+ for chunk in stream:
145
+ token = chunk.choices[0].delta.content or ""
146
+ response_text += token
147
+ yield response_text
148
+ return # success β€” stop retrying
149
+
150
+ except Exception as e:
151
+ err = str(e).lower()
152
+ tried.add(provider["name"])
153
+
154
+ if "401" in err or "unauthorized" in err or "invalid api key" in err:
155
+ bad_keys.add(provider["name"]) # skip for whole session
156
+ print(f"❌ {provider['name']} bad key β€” skipping for session")
157
+ elif "429" in err or "rate limit" in err or "quota" in err or "exceeded" in err:
158
+ print(f"⚠️ {provider['name']} rate limited β€” trying next provider")
159
+ else:
160
+ print(f"⚠️ {provider['name']} error: {e} β€” trying next provider")
161
 
162
  # ── Startup summary ──
163
  print("\n=== Provider Status ===")
 
184
  )
185
 
186
  if __name__ == "__main__":
187
+ demo.launch()