StrawberryJelly commited on
Commit
3ced951
·
verified ·
1 Parent(s): 67d45db

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +70 -7
app.py CHANGED
@@ -1,7 +1,8 @@
1
  from fastapi import FastAPI, Request, HTTPException, Depends
2
  from fastapi.security import APIKeyHeader
3
  from fastapi.middleware.cors import CORSMiddleware
4
- from fastapi.responses import JSONResponse
 
5
  import os
6
  import json
7
  import time
@@ -17,10 +18,30 @@ app.add_middleware(
17
  allow_headers=["*"],
18
  )
19
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  API_KEY = os.environ.get("QWEN_API_KEY")
21
  MODEL_PATH = "/models/Qwen2.5-7B-Instruct-Q4_K_M.gguf"
22
 
23
-
24
  print(f"Loading model from {MODEL_PATH}...")
25
  llm = Llama(
26
  model_path=MODEL_PATH,
@@ -36,10 +57,55 @@ api_key_header = APIKeyHeader(name="X-API-Key", auto_error=False)
36
  async def verify_key(api_key: str = Depends(api_key_header)):
37
  if not API_KEY:
38
  raise HTTPException(status_code=500, detail="QWEN_API_KEY not set in HF Secrets")
39
- if api_key!= API_KEY:
40
  raise HTTPException(status_code=401, detail="Invalid API key")
41
  return api_key
42
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  @app.get("/health")
44
  async def health():
45
  return {
@@ -49,7 +115,6 @@ async def health():
49
  }
50
 
51
  def format_prompt(messages):
52
- """ChatML format dla Qwena"""
53
  prompt = ""
54
  for msg in messages:
55
  role = msg["role"]
@@ -61,7 +126,6 @@ def format_prompt(messages):
61
  @app.post("/v1/chat/completions")
62
  async def chat_completions(request: Request, api_key: str = Depends(verify_key)):
63
  body = await request.json()
64
-
65
  messages = body.get("messages", [])
66
  max_tokens = body.get("max_tokens", 512)
67
  temperature = body.get("temperature", 0.7)
@@ -71,7 +135,6 @@ async def chat_completions(request: Request, api_key: str = Depends(verify_key))
71
  raise HTTPException(status_code=400, detail="messages is required")
72
 
73
  prompt = format_prompt(messages)
74
-
75
  output = llm(
76
  prompt,
77
  max_tokens=max_tokens,
@@ -97,4 +160,4 @@ async def chat_completions(request: Request, api_key: str = Depends(verify_key))
97
  "completion_tokens": output["usage"]["completion_tokens"],
98
  "total_tokens": output["usage"]["total_tokens"]
99
  }
100
- })
 
1
  from fastapi import FastAPI, Request, HTTPException, Depends
2
  from fastapi.security import APIKeyHeader
3
  from fastapi.middleware.cors import CORSMiddleware
4
+ from fastapi.responses import JSONResponse, HTMLResponse
5
+ from fastapi.openapi.utils import get_openapi
6
  import os
7
  import json
8
  import time
 
18
  allow_headers=["*"],
19
  )
20
 
21
+ def custom_openapi():
22
+ if app.openapi_schema:
23
+ return app.openapi_schema
24
+ schema = get_openapi(
25
+ title="Qwen API",
26
+ version="0.1.0",
27
+ routes=app.routes,
28
+ )
29
+ schema["components"]["securitySchemes"] = {
30
+ "ApiKeyAuth": {
31
+ "type": "apiKey",
32
+ "in": "header",
33
+ "name": "X-API-Key"
34
+ }
35
+ }
36
+ schema["security"] = [{"ApiKeyAuth": []}]
37
+ app.openapi_schema = schema
38
+ return schema
39
+
40
+ app.openapi = custom_openapi
41
+
42
  API_KEY = os.environ.get("QWEN_API_KEY")
43
  MODEL_PATH = "/models/Qwen2.5-7B-Instruct-Q4_K_M.gguf"
44
 
 
45
  print(f"Loading model from {MODEL_PATH}...")
46
  llm = Llama(
47
  model_path=MODEL_PATH,
 
57
  async def verify_key(api_key: str = Depends(api_key_header)):
58
  if not API_KEY:
59
  raise HTTPException(status_code=500, detail="QWEN_API_KEY not set in HF Secrets")
60
+ if api_key != API_KEY:
61
  raise HTTPException(status_code=401, detail="Invalid API key")
62
  return api_key
63
 
64
+ @app.get("/", response_class=HTMLResponse)
65
+ async def ui():
66
+ return """
67
+ <!DOCTYPE html>
68
+ <html>
69
+ <head>
70
+ <title>Qwen API Tester</title>
71
+ <style>
72
+ body { font-family: Arial; max-width: 800px; margin: 40px auto; padding: 20px; background: #1a1a1a; color: #fff; }
73
+ input, textarea { width: 100%; padding: 10px; margin: 8px 0; background: #2a2a2a; color: #fff; border: 1px solid #444; border-radius: 6px; box-sizing: border-box; }
74
+ button { background: #ff6b35; color: white; padding: 12px 24px; border: none; border-radius: 6px; cursor: pointer; font-size: 16px; }
75
+ pre { background: #2a2a2a; padding: 15px; border-radius: 6px; overflow-x: auto; white-space: pre-wrap; }
76
+ label { color: #aaa; font-size: 14px; }
77
+ h1 { color: #ff6b35; }
78
+ </style>
79
+ </head>
80
+ <body>
81
+ <h1>🤖 Qwen API Tester</h1>
82
+ <label>API Key</label>
83
+ <input type="password" id="apikey" placeholder="Twój klucz API">
84
+ <label>System prompt</label>
85
+ <input type="text" id="system" value="You are a helpful assistant.">
86
+ <label>Wiadomość</label>
87
+ <textarea id="message" rows="4" placeholder="Napisz coś..."></textarea>
88
+ <button onclick="send()">Wyślij 🚀</button>
89
+ <pre id="output">Odpowiedź pojawi się tutaj...</pre>
90
+ <script>
91
+ async function send() {
92
+ const key = document.getElementById('apikey').value;
93
+ const system = document.getElementById('system').value;
94
+ const msg = document.getElementById('message').value;
95
+ document.getElementById('output').textContent = 'Ładowanie...';
96
+ const res = await fetch('/v1/chat/completions', {
97
+ method: 'POST',
98
+ headers: { 'Content-Type': 'application/json', 'X-API-Key': key },
99
+ body: JSON.stringify({ messages: [{ role: 'system', content: system }, { role: 'user', content: msg }] })
100
+ });
101
+ const data = await res.json();
102
+ document.getElementById('output').textContent = data.choices?.[0]?.message?.content || JSON.stringify(data, null, 2);
103
+ }
104
+ </script>
105
+ </body>
106
+ </html>
107
+ """
108
+
109
  @app.get("/health")
110
  async def health():
111
  return {
 
115
  }
116
 
117
  def format_prompt(messages):
 
118
  prompt = ""
119
  for msg in messages:
120
  role = msg["role"]
 
126
  @app.post("/v1/chat/completions")
127
  async def chat_completions(request: Request, api_key: str = Depends(verify_key)):
128
  body = await request.json()
 
129
  messages = body.get("messages", [])
130
  max_tokens = body.get("max_tokens", 512)
131
  temperature = body.get("temperature", 0.7)
 
135
  raise HTTPException(status_code=400, detail="messages is required")
136
 
137
  prompt = format_prompt(messages)
 
138
  output = llm(
139
  prompt,
140
  max_tokens=max_tokens,
 
160
  "completion_tokens": output["usage"]["completion_tokens"],
161
  "total_tokens": output["usage"]["total_tokens"]
162
  }
163
+ })