Nerdur commited on
Commit
fcc7f02
·
verified ·
1 Parent(s): 22cdcb2

Upload 11 files

Browse files
Files changed (2) hide show
  1. coding_priority_pipe.py +80 -28
  2. setup_endpoints.sh +35 -24
coding_priority_pipe.py CHANGED
@@ -2,49 +2,101 @@
2
  title: Coding Fallback Pipe
3
  author: nerdur
4
  author_url: https://nerdur-webui.hf.space
5
- version: 1.0
6
- description: Automatski kruži kroz besplatne provajdere za kodiranje (Gemini -> Groq -> Cerebras -> Sambanova).
7
  """
8
 
9
  from pydantic import BaseModel
10
- from typing import Optional, List, Union, Generator
11
  import requests
 
12
 
13
 
14
  class Pipe:
15
  class Valves(BaseModel):
16
- # Prioritet modela za kodiranje
17
  model_priority: List[str] = [
18
- "google_generative_ai.gemini-2.0-flash",
19
- "groq.llama-3.3-70b-versatile",
20
- "cerebras.llama3.1-70b",
21
- "sambanova.meta-llama-3.1-405b-instruct"
22
  ]
 
 
23
  enabled: bool = True
24
 
25
  def __init__(self):
26
  self.type = "pipe"
27
  self.id = "coding_fallback"
28
- self.name = "Smart Coding Router"
29
  self.valves = self.Valves()
30
 
31
- def pipe(self, body: dict, __user__: Optional[dict] = None) -> Union[str, Generator, dict]:
 
 
 
32
  if not self.valves.enabled:
33
- return "Router is disabled."
34
-
35
- # Ova funkcija u Open WebUI Pipe sistemu prosljeđuje zahtjev
36
- # Prvi model iz liste koji je dostupan u sistemu će biti izabran
37
- # Za pravu fallback logiku (ako API vrati 429), potrebna je kompleksnija
38
- # implementacija unutar samog 'pipe' poziva, ali za početak
39
- # ovo omogućava modelu da "zna" za ostale provajdere.
40
-
41
- # NAPOMENA: Za pravi fallback pri grešci, modelID se mora dinamički mijenjati
42
- # u slučaju Exception-a tokom streaminga.
43
-
44
- selected_model = body.get("model")
45
- if selected_model == f"{self.id}.{self.name}":
46
- # Ako je izabran sam router, stavi prvi model iz prioriteta
47
- body["model"] = self.valves.model_priority[0]
48
-
49
- print(f"Coding Router: Preusmjeravam na {body['model']}")
50
- return body
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  title: Coding Fallback Pipe
3
  author: nerdur
4
  author_url: https://nerdur-webui.hf.space
5
+ version: 2.0
6
+ description: Kruži kroz NVIDIA NIM besplatne coding modele s pravim fallback-om pri 429/500 grešci.
7
  """
8
 
9
  from pydantic import BaseModel
10
+ from typing import Optional, List, Union, Generator, Iterator
11
  import requests
12
+ import json
13
 
14
 
15
  class Pipe:
16
  class Valves(BaseModel):
17
+ # NVIDIA NIM Free Endpoint coding modeli — prioritet od najboljeg ka rezervnom
18
  model_priority: List[str] = [
19
+ "mistral-ai/devstral-2-123b-instruct-2512",
20
+ "deepseek-ai/deepseek-v3.2",
21
+ "qwen/qwen3-coder-480b-a35b-instruct",
22
+ "zhipuai/glm-4.7",
23
  ]
24
+ nvidia_api_key: str = ""
25
+ nvidia_base_url: str = "https://integrate.api.nvidia.com/v1"
26
  enabled: bool = True
27
 
28
  def __init__(self):
29
  self.type = "pipe"
30
  self.id = "coding_fallback"
31
+ self.name = "Smart Coding Router (NVIDIA NIM)"
32
  self.valves = self.Valves()
33
 
34
+ def pipes(self):
35
+ return [{"id": self.id, "name": self.name}]
36
+
37
+ def pipe(self, body: dict, __user__: Optional[dict] = None) -> Union[str, Iterator, dict]:
38
  if not self.valves.enabled:
39
+ return "Router je isključen."
40
+
41
+ import os
42
+ api_key = self.valves.nvidia_api_key or os.getenv("NVIDIA_API_KEY") or os.getenv("NVIDIA_ID_API_KEY", "")
43
+
44
+ if not api_key:
45
+ return " NVIDIA_API_KEY nije postavljen."
46
+
47
+ messages = body.get("messages", [])
48
+ stream = body.get("stream", False)
49
+
50
+ headers = {
51
+ "Authorization": f"Bearer {api_key}",
52
+ "Content-Type": "application/json",
53
+ }
54
+
55
+ last_error = None
56
+ for model_id in self.valves.model_priority:
57
+ payload = {
58
+ "model": model_id,
59
+ "messages": messages,
60
+ "stream": stream,
61
+ "max_tokens": body.get("max_tokens", 4096),
62
+ "temperature": body.get("temperature", 0.2),
63
+ }
64
+
65
+ try:
66
+ print(f"Coding Router: Pokušavam {model_id}...")
67
+ response = requests.post(
68
+ f"{self.valves.nvidia_base_url}/chat/completions",
69
+ headers=headers,
70
+ json=payload,
71
+ stream=stream,
72
+ timeout=60,
73
+ )
74
+
75
+ # Preskači na sljedeći model ako je rate limit ili server greška
76
+ if response.status_code in (429, 500, 502, 503):
77
+ print(f"⚠️ {model_id} vratio {response.status_code}, prelazim na sljedeći...")
78
+ last_error = f"{model_id}: HTTP {response.status_code}"
79
+ continue
80
+
81
+ response.raise_for_status()
82
+
83
+ if stream:
84
+ def generate():
85
+ for line in response.iter_lines():
86
+ if line:
87
+ yield line.decode("utf-8") + "\n"
88
+ return generate()
89
+ else:
90
+ data = response.json()
91
+ return data["choices"][0]["message"]["content"]
92
+
93
+ except requests.exceptions.Timeout:
94
+ print(f"⚠️ {model_id} timeout, prelazim...")
95
+ last_error = f"{model_id}: timeout"
96
+ continue
97
+ except Exception as e:
98
+ print(f"⚠️ {model_id} greška: {e}")
99
+ last_error = str(e)
100
+ continue
101
+
102
+ return f"❌ Svi modeli neuspješni. Posljednja greška: {last_error}"
setup_endpoints.sh CHANGED
@@ -39,48 +39,59 @@ fi
39
 
40
  if [ -z "$TOKEN" ]; then echo "❌ Nije moguće dobiti token."; exit 0; fi
41
 
42
- # Pokreni instalaciju funkcija
43
  python3 /app/install_functions.py "$BASE_URL" "$TOKEN" &
44
 
45
  echo "✅ Ulogovan, filtriram provajdere s praznim ključevima..."
46
 
47
- # Python skripta za dinamičko generisanje JSON-a (sprečava 500 Error: KeyError 'id')
48
  python3 - <<PYEOF
49
  import requests, os, json
50
 
51
  base_url = "$BASE_URL"
52
  token = "$TOKEN"
53
 
 
 
 
 
 
 
 
54
  providers = [
55
- ("https://api.openai.com/v1", os.getenv("OPENAI_API_KEY")),
56
- ("https://api.anthropic.com/v1", os.getenv("ANTHROPIC_API_KEY")),
57
  ("https://generativelanguage.googleapis.com/v1beta/openai", os.getenv("GOOGLE_API_KEY")),
58
- ("https://models.inference.ai.azure.com", os.getenv("GITHUB_TOKEN")),
59
- ("https://api.groq.com/openai/v1", os.getenv("GROQ_API_KEY")),
60
- ("https://api.mistral.ai/v1", os.getenv("MISTRAL_API_KEY")),
61
- ("https://api.deepseek.com/v1", os.getenv("DEEPSEEK_API_KEY")),
62
- ("https://api.together.xyz/v1", os.getenv("TOGETHER_API_KEY")),
63
- ("https://integrate.api.nvidia.com/v1", os.getenv("NVIDIA_ID_API_KEY") or os.getenv("NVIDIA_API_KEY")),
64
- ("https://api.sambanova.ai/v1", os.getenv("SAMBANOVA_API_KEY")),
65
- ("https://openrouter.ai/api/v1", os.getenv("OPENROUTER_API_KEY")),
66
- ("https://api.cloudflare.com/client/v4/accounts/" + (os.getenv("CLOUDFLARE_ACCOUNT_ID") or "") + "/ai/v1", os.getenv("CLOUDFLARE_API_TOKEN")),
67
- ("https://api.cerebras.ai/v1", os.getenv("CEREBRAS_API_KEY")),
68
- ("https://api.fireworks.ai/inference/v1", os.getenv("FIREWORKS_API_KEY")),
69
- ("https://api.x.ai/v1", os.getenv("XAI_API_KEY")),
70
- ("https://router.huggingface.co/v1", os.getenv("HF_INFERENCE_TOKEN")),
71
- ("https://api.cohere.ai/compatibility/v1", os.getenv("COHERE_API_KEY")),
72
- ("https://gen.pollinations.ai/v1", "noapikey")
73
  ]
74
 
 
 
 
 
75
  valid_urls = []
76
  valid_keys = []
77
 
78
  for url, key in providers:
79
- # Preskači ako je URL nepotpun ili ključ prazan
80
- if "/accounts//ai" in url: continue
81
- if key and key.strip() and key not in ['""', "''"]:
82
- valid_urls.append(url)
83
- valid_keys.append(key)
 
 
84
 
85
  payload = {
86
  "ENABLE_OPENAI_API": True,
 
39
 
40
  if [ -z "$TOKEN" ]; then echo "❌ Nije moguće dobiti token."; exit 0; fi
41
 
42
+ # Pokreni instalaciju funkcija u pozadini
43
  python3 /app/install_functions.py "$BASE_URL" "$TOKEN" &
44
 
45
  echo "✅ Ulogovan, filtriram provajdere s praznim ključevima..."
46
 
 
47
  python3 - <<PYEOF
48
  import requests, os, json
49
 
50
  base_url = "$BASE_URL"
51
  token = "$TOKEN"
52
 
53
+ # NVIDIA: podržava i NVIDIA_API_KEY i NVIDIA_ID_API_KEY
54
+ nvidia_key = os.getenv("NVIDIA_ID_API_KEY") or os.getenv("NVIDIA_API_KEY")
55
+
56
+ # Cloudflare: sklopi URL samo ako postoji account ID
57
+ cf_account = os.getenv("CLOUDFLARE_ACCOUNT_ID") or ""
58
+ cf_url = f"https://api.cloudflare.com/client/v4/accounts/{cf_account}/ai/v1" if cf_account else None
59
+
60
  providers = [
61
+ ("https://api.openai.com/v1", os.getenv("OPENAI_API_KEY")),
62
+ ("https://api.anthropic.com/v1", os.getenv("ANTHROPIC_API_KEY")),
63
  ("https://generativelanguage.googleapis.com/v1beta/openai", os.getenv("GOOGLE_API_KEY")),
64
+ ("https://models.inference.ai.azure.com", os.getenv("GITHUB_TOKEN")),
65
+ ("https://api.groq.com/openai/v1", os.getenv("GROQ_API_KEY")),
66
+ ("https://api.mistral.ai/v1", os.getenv("MISTRAL_API_KEY")),
67
+ ("https://api.deepseek.com/v1", os.getenv("DEEPSEEK_API_KEY")),
68
+ ("https://api.together.xyz/v1", os.getenv("TOGETHER_API_KEY")),
69
+ ("https://integrate.api.nvidia.com/v1", nvidia_key),
70
+ ("https://api.sambanova.ai/v1", os.getenv("SAMBANOVA_API_KEY")),
71
+ ("https://openrouter.ai/api/v1", os.getenv("OPENROUTER_API_KEY")),
72
+ ("https://api.cerebras.ai/v1", os.getenv("CEREBRAS_API_KEY")),
73
+ ("https://api.fireworks.ai/inference/v1", os.getenv("FIREWORKS_API_KEY")),
74
+ ("https://api.x.ai/v1", os.getenv("XAI_API_KEY")),
75
+ ("https://router.huggingface.co/v1", os.getenv("HF_INFERENCE_TOKEN")),
76
+ ("https://api.cohere.ai/compatibility/v1", os.getenv("COHERE_API_KEY")),
77
+ ("https://gen.pollinations.ai/v1", "noapikey"),
 
78
  ]
79
 
80
+ # Dodaj Cloudflare samo ako postoji account ID
81
+ if cf_url:
82
+ providers.append((cf_url, os.getenv("CLOUDFLARE_API_TOKEN")))
83
+
84
  valid_urls = []
85
  valid_keys = []
86
 
87
  for url, key in providers:
88
+ if not url:
89
+ continue
90
+ if not key or not key.strip() or key in ['""', "''"]:
91
+ continue
92
+ valid_urls.append(url)
93
+ valid_keys.append(key)
94
+ print(f" ✔ {url.split('/')[2]}")
95
 
96
  payload = {
97
  "ENABLE_OPENAI_API": True,