StrawberryJelly commited on
Commit
8566f99
verified
1 Parent(s): 89a3ff6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +31 -32
app.py CHANGED
@@ -20,7 +20,6 @@ app.add_middleware(
20
  expose_headers=["*"]
21
  )
22
 
23
- # --- Konfiguracja backend贸w ---
24
  BACKENDS = {
25
  "qwen": {
26
  "url": os.environ.get("KAI_QWEN_URL", "https://your-qwen-space.hf.space"),
@@ -45,7 +44,6 @@ class ChatRequest(BaseModel):
45
  stream: bool = True
46
  model: Optional[str] = None
47
 
48
- # --- Heurystyka wyboru modelu ---
49
  CODE_KEYWORDS = re.compile(r'\b(def|class|import|function|const|let|var|public|private|return|python|javascript|java|c\+\+|sql|html|css|json|api|docker|git|kod|funkcja|program|skrypt|algorytm)\b', re.I)
50
  MATH_KEYWORDS = re.compile(r'\b(oblicz|policz|r贸wnanie|ca艂ka|pochodna|macierz|prawdopodobie艅stwo|logarytm|pierwiastek|ile to|=\?|\d+\s*[\+\-\*\/]\s*\d+)\b', re.I)
51
  CREATIVE_KEYWORDS = re.compile(r'\b(napisz|wiersz|opowiadanie|historia|bajka|rap|tekst|piosenka|kreatywny|stw贸rz|wymy艣l|zr贸b post|dialog)\b', re.I)
@@ -56,24 +54,20 @@ def route_model(messages: List[Message], forced_model: Optional[str] = None) ->
56
 
57
  user_text = " ".join([m.content for m in messages if m.role == "user"]).lower()
58
 
59
- # Priorytet 1: Kod lub matma -> Qwen
60
  if CODE_KEYWORDS.search(user_text) or MATH_KEYWORDS.search(user_text):
61
  return "qwen"
62
 
63
- # Priorytet 2: Kreatywne PL -> Mistral
64
  if CREATIVE_KEYWORDS.search(user_text):
65
  return "mistral"
66
 
67
- # Domy艣lnie: Mistral dla PL, Qwen dla reszty
68
- # Prosta heurystyka PL
69
  pl_chars = len(re.findall(r'[膮膰臋艂艅贸艣藕偶]', user_text))
70
  if pl_chars > 2:
71
  return "mistral"
72
 
73
- return "qwen" # domy艣lnie Qwen bo szybszy
74
 
75
- # --- Proxy do backendu ---
76
- async def proxy_to_backend(backend_name: str, request_data: dict, stream: bool):
77
  backend = BACKENDS[backend_name]
78
  url = f"{backend['url']}/v1/chat/completions"
79
  headers = {
@@ -82,27 +76,33 @@ async def proxy_to_backend(backend_name: str, request_data: dict, stream: bool):
82
  }
83
 
84
  async with httpx.AsyncClient(timeout=180.0) as client:
85
- if stream:
86
- async with client.stream("POST", url, json=request_data, headers=headers) as r:
87
- if r.status_code!= 200:
88
- err = await r.aread()
89
- raise HTTPException(r.status_code, f"Backend {backend_name} error: {err.decode()}")
90
-
91
- # Wysy艂amy info kt贸ry model zosta艂 u偶yty
92
- yield f": x-kai-model-used {backend_name}\n\n"
93
- yield f": connected\n\n"
94
-
95
- async for chunk in r.aiter_bytes():
96
- yield chunk
97
- else:
98
- r = await client.post(url, json=request_data, headers=headers)
99
  if r.status_code!= 200:
100
- raise HTTPException(r.status_code, f"Backend {backend_name} error: {r.text}")
101
- data = r.json()
102
- data["kai_model_used"] = backend_name
103
- return data
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
 
105
- # --- Endpointy ---
106
  @app.get("/", response_class=HTMLResponse)
107
  async def serve_frontend():
108
  with open("static/index.html", "r", encoding="utf-8") as f:
@@ -113,18 +113,17 @@ async def chat_completions(data: ChatRequest, request: Request):
113
  chosen_backend = route_model(data.messages, data.model)
114
 
115
  request_data = data.dict()
116
- request_data.pop("model", None) # usuwamy bo backendy nie potrzebuj膮
117
 
118
  if data.stream:
119
- generator = proxy_to_backend(chosen_backend, request_data, True)
120
  return StreamingResponse(generator, media_type="text/event-stream")
121
  else:
122
- result = await proxy_to_backend(chosen_backend, request_data, False)
123
  return JSONResponse(content=result)
124
 
125
  @app.get("/health")
126
  async def health():
127
  return {"status": "ok", "backends": list(BACKENDS.keys())}
128
 
129
- # Serwuj pliki statyczne
130
  app.mount("/static", StaticFiles(directory="static"), name="static")
 
20
  expose_headers=["*"]
21
  )
22
 
 
23
  BACKENDS = {
24
  "qwen": {
25
  "url": os.environ.get("KAI_QWEN_URL", "https://your-qwen-space.hf.space"),
 
44
  stream: bool = True
45
  model: Optional[str] = None
46
 
 
47
  CODE_KEYWORDS = re.compile(r'\b(def|class|import|function|const|let|var|public|private|return|python|javascript|java|c\+\+|sql|html|css|json|api|docker|git|kod|funkcja|program|skrypt|algorytm)\b', re.I)
48
  MATH_KEYWORDS = re.compile(r'\b(oblicz|policz|r贸wnanie|ca艂ka|pochodna|macierz|prawdopodobie艅stwo|logarytm|pierwiastek|ile to|=\?|\d+\s*[\+\-\*\/]\s*\d+)\b', re.I)
49
  CREATIVE_KEYWORDS = re.compile(r'\b(napisz|wiersz|opowiadanie|historia|bajka|rap|tekst|piosenka|kreatywny|stw贸rz|wymy艣l|zr贸b post|dialog)\b', re.I)
 
54
 
55
  user_text = " ".join([m.content for m in messages if m.role == "user"]).lower()
56
 
 
57
  if CODE_KEYWORDS.search(user_text) or MATH_KEYWORDS.search(user_text):
58
  return "qwen"
59
 
 
60
  if CREATIVE_KEYWORDS.search(user_text):
61
  return "mistral"
62
 
 
 
63
  pl_chars = len(re.findall(r'[膮膰臋艂艅贸艣藕偶]', user_text))
64
  if pl_chars > 2:
65
  return "mistral"
66
 
67
+ return "qwen"
68
 
69
+ # --- 2 oddzielne funkcje: stream i non-stream ---
70
+ async def proxy_stream(backend_name: str, request_data: dict):
71
  backend = BACKENDS[backend_name]
72
  url = f"{backend['url']}/v1/chat/completions"
73
  headers = {
 
76
  }
77
 
78
  async with httpx.AsyncClient(timeout=180.0) as client:
79
+ async with client.stream("POST", url, json=request_data, headers=headers) as r:
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  if r.status_code!= 200:
81
+ err = await r.aread()
82
+ raise HTTPException(r.status_code, f"Backend {backend_name} error: {err.decode()}")
83
+
84
+ yield f": x-kai-model-used {backend_name}\n\n"
85
+ yield f": connected\n\n"
86
+
87
+ async for chunk in r.aiter_bytes():
88
+ yield chunk
89
+
90
+ async def proxy_non_stream(backend_name: str, request_data: dict):
91
+ backend = BACKENDS[backend_name]
92
+ url = f"{backend['url']}/v1/chat/completions"
93
+ headers = {
94
+ "Authorization": f"Bearer {backend['key']}",
95
+ "Content-Type": "application/json"
96
+ }
97
+
98
+ async with httpx.AsyncClient(timeout=180.0) as client:
99
+ r = await client.post(url, json=request_data, headers=headers)
100
+ if r.status_code!= 200:
101
+ raise HTTPException(r.status_code, f"Backend {backend_name} error: {r.text}")
102
+ data = r.json()
103
+ data["kai_model_used"] = backend_name
104
+ return data
105
 
 
106
  @app.get("/", response_class=HTMLResponse)
107
  async def serve_frontend():
108
  with open("static/index.html", "r", encoding="utf-8") as f:
 
113
  chosen_backend = route_model(data.messages, data.model)
114
 
115
  request_data = data.dict()
116
+ request_data.pop("model", None)
117
 
118
  if data.stream:
119
+ generator = proxy_stream(chosen_backend, request_data)
120
  return StreamingResponse(generator, media_type="text/event-stream")
121
  else:
122
+ result = await proxy_non_stream(chosen_backend, request_data)
123
  return JSONResponse(content=result)
124
 
125
  @app.get("/health")
126
  async def health():
127
  return {"status": "ok", "backends": list(BACKENDS.keys())}
128
 
 
129
  app.mount("/static", StaticFiles(directory="static"), name="static")