Spaces:
Running
Running
Bahodir Nematjonov
commited on
Commit
·
9f8a30b
1
Parent(s):
6442e9d
streaming updated
Browse files- main.py +11 -7
- static/index.html +140 -307
- static/script.js +1 -1
- utils.py +17 -4
main.py
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
-
from fastapi import FastAPI, Depends, HTTPException, status
|
2 |
-
from fastapi.responses import FileResponse, StreamingResponse
|
3 |
from fastapi.staticfiles import StaticFiles
|
4 |
from jose import JWTError
|
5 |
from schemas import UserRegister, TokenResponse, RefreshTokenRequest, QueryInput
|
6 |
from auth import register_user, get_db, authenticate_user, create_token, verify_token, verify_access_token, Session
|
7 |
-
from utils import generate_stream
|
8 |
from fastapi.security import OAuth2PasswordRequestForm
|
9 |
from pathlib import Path
|
10 |
from datetime import timedelta
|
@@ -97,13 +97,17 @@ async def refresh(refresh_request: RefreshTokenRequest):
|
|
97 |
headers={"WWW-Authenticate": "Bearer"},
|
98 |
)
|
99 |
|
100 |
-
@app.post("/
|
101 |
-
async def
|
102 |
query_input: QueryInput,
|
103 |
username: str = Depends(verify_access_token),
|
|
|
104 |
):
|
105 |
-
|
106 |
-
|
|
|
|
|
|
|
107 |
# WebSocket endpoint for streaming
|
108 |
@app.on_event("startup")
|
109 |
async def startup_event():
|
|
|
1 |
+
from fastapi import FastAPI, Depends, HTTPException, status, Query
|
2 |
+
from fastapi.responses import FileResponse, StreamingResponse, JSONResponse
|
3 |
from fastapi.staticfiles import StaticFiles
|
4 |
from jose import JWTError
|
5 |
from schemas import UserRegister, TokenResponse, RefreshTokenRequest, QueryInput
|
6 |
from auth import register_user, get_db, authenticate_user, create_token, verify_token, verify_access_token, Session
|
7 |
+
from utils import generate_stream, generate_response
|
8 |
from fastapi.security import OAuth2PasswordRequestForm
|
9 |
from pathlib import Path
|
10 |
from datetime import timedelta
|
|
|
97 |
headers={"WWW-Authenticate": "Bearer"},
|
98 |
)
|
99 |
|
100 |
+
@app.post("/generate")
|
101 |
+
async def generate(
|
102 |
query_input: QueryInput,
|
103 |
username: str = Depends(verify_access_token),
|
104 |
+
stream: bool = Query(False, description="Enable streaming response"),
|
105 |
):
|
106 |
+
"""API endpoint that supports both streaming and non-streaming responses."""
|
107 |
+
if stream:
|
108 |
+
return StreamingResponse(generate_stream(query_input.query), media_type="text/event-stream")
|
109 |
+
else:
|
110 |
+
return JSONResponse(await generate_response(query_input.query))
|
111 |
# WebSocket endpoint for streaming
|
112 |
@app.on_event("startup")
|
113 |
async def startup_event():
|
static/index.html
CHANGED
@@ -22,261 +22,84 @@
|
|
22 |
|
23 |
<section id="endpoints">
|
24 |
<h2>Endpoints</h2>
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
try:
|
64 |
-
response = requests.post(url, json=payload, headers=headers)
|
65 |
-
|
66 |
-
if response.status_code == 200:
|
67 |
-
return RegisterResponse.from_json(response.json())
|
68 |
-
else:
|
69 |
-
raise Exception(f"Failed to register: {response.text}")
|
70 |
-
|
71 |
-
except requests.exceptions.RequestException as e:
|
72 |
-
raise Exception(f"Network error: {e}")
|
73 |
-
|
74 |
-
# Example usage
|
75 |
-
try:
|
76 |
-
result = register("testuser", "testpassword")
|
77 |
-
print(f"✅ Registration successful! User: {result.user}, Message: {result.message}")
|
78 |
-
except Exception as e:
|
79 |
-
print(f"⚠️ Error: {e}")
|
80 |
-
</code></pre>
|
81 |
-
|
82 |
-
<h4>Response:</h4>
|
83 |
-
<pre><code class="language-json">{"message":"User registered successfully","user":"bahodir"}</code></pre>
|
84 |
-
|
85 |
-
</div>
|
86 |
-
<div class="endpoint" id="login">
|
87 |
-
<h3>2. Login Endpoint</h3>
|
88 |
-
<p><span class="method">POST</span><span class="endpoint-url">/login</span></p>
|
89 |
-
<p>This endpoint is used to authenticate a user and retrieve an access token.</p>
|
90 |
-
|
91 |
-
<h4>cURL Request:</h4>
|
92 |
-
<pre><code class="language-bash">curl -X POST 'https://humblebeeai-llm-host.hf.space/login' \
|
93 |
-
-H "Content-Type: application/x-www-form-urlencoded" \
|
94 |
-
-d 'username=testuser&password=testpassword'</code></pre>
|
95 |
-
|
96 |
-
<h4>Python Implementation:</h4>
|
97 |
-
<pre><code class="language-python">
|
98 |
-
import requests
|
99 |
-
|
100 |
-
class LoginResponse:
|
101 |
-
"""Class to handle API login response"""
|
102 |
-
def __init__(self, access_token, refresh_token, token_type):
|
103 |
-
self.access_token = access_token
|
104 |
-
self.refresh_token = refresh_token
|
105 |
-
self.token_type = token_type
|
106 |
-
|
107 |
-
@classmethod
|
108 |
-
def from_json(cls, json_data):
|
109 |
-
return cls(
|
110 |
-
access_token=json_data.get("access_token"),
|
111 |
-
refresh_token=json_data.get("refresh_token"),
|
112 |
-
token_type=json_data.get("token_type"),
|
113 |
-
)
|
114 |
-
|
115 |
-
def login(username: str, password: str):
|
116 |
-
"""Sends a POST request to authenticate a user."""
|
117 |
-
url = "https://humblebeeai-llm-host.hf.space/login"
|
118 |
-
headers = {"Content-Type": "application/x-www-form-urlencoded"}
|
119 |
-
payload = {"username": username, "password": password}
|
120 |
-
|
121 |
-
try:
|
122 |
-
response = requests.post(url, data=payload, headers=headers)
|
123 |
-
|
124 |
-
if response.status_code == 200:
|
125 |
-
return LoginResponse.from_json(response.json())
|
126 |
-
else:
|
127 |
-
raise Exception(f"Failed to login: {response.text}")
|
128 |
-
|
129 |
-
except requests.exceptions.RequestException as e:
|
130 |
-
raise Exception(f"Network error: {e}")
|
131 |
-
|
132 |
-
# Example usage
|
133 |
-
try:
|
134 |
-
result = login("testuser", "testpassword")
|
135 |
-
print(f"✅ Login successful! Access Token: {result.access_token}")
|
136 |
-
except Exception as e:
|
137 |
-
print(f"⚠️ Error: {e}")
|
138 |
-
</code></pre>
|
139 |
-
|
140 |
-
<h4>Response:</h4>
|
141 |
-
<pre><code class="language-json">{ "access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0dXNlciIsImV4cCI6MTczOTE3Nzg5N30.jUfB7vHA4HGrpDiI08cpKGR7s3DOVrchhpf5yBz0hCc",
|
142 |
-
"token_type":"bearer",
|
143 |
-
"refresh_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0dXNlciIsImV4cCI6MTczOTc4MDg5N30.L9_5hGR_lUskUINccE51fOA1-8NOgmQ2bjBK3iMS-K8"}</code></pre>
|
144 |
-
|
145 |
-
</div>
|
146 |
-
|
147 |
-
|
148 |
-
<div class="endpoint" id="refresh">
|
149 |
<h3>3. Refresh Token Endpoint</h3>
|
150 |
<p><span class="method">POST</span><span class="endpoint-url">/refresh</span></p>
|
151 |
<p>This endpoint is used to refresh the access token using a valid refresh token.</p>
|
152 |
-
|
153 |
<h4>cURL Request:</h4>
|
154 |
<pre><code class="language-bash">curl -X POST 'https://humblebeeai-llm-host.hf.space/refresh' \
|
155 |
-H "Content-Type: application/json" \
|
156 |
-d '{"refresh_token": "your-refresh-token"}'</code></pre>
|
157 |
-
|
158 |
-
<h4>Python Implementation:</h4>
|
159 |
-
<pre><code class="language-python">
|
160 |
-
import requests
|
161 |
-
import json
|
162 |
-
|
163 |
-
class RefreshResponse:
|
164 |
-
"""Class to handle API refresh response"""
|
165 |
-
def __init__(self, access_token, refresh_token, token_type):
|
166 |
-
self.access_token = access_token
|
167 |
-
self.refresh_token = refresh_token
|
168 |
-
self.token_type = token_type
|
169 |
-
|
170 |
-
@classmethod
|
171 |
-
def from_json(cls, json_data):
|
172 |
-
return cls(
|
173 |
-
access_token=json_data.get("access_token"),
|
174 |
-
refresh_token=json_data.get("refresh_token"),
|
175 |
-
token_type=json_data.get("token_type"),
|
176 |
-
)
|
177 |
-
|
178 |
-
def refresh_token(refresh_token: str):
|
179 |
-
"""Sends a POST request to refresh the access token."""
|
180 |
-
url = "https://humblebeeai-llm-host.hf.space/refresh"
|
181 |
-
headers = {"Content-Type": "application/json"}
|
182 |
-
payload = {"refresh_token": refresh_token}
|
183 |
-
|
184 |
-
try:
|
185 |
-
response = requests.post(url, json=payload, headers=headers)
|
186 |
-
|
187 |
-
if response.status_code == 200:
|
188 |
-
return RefreshResponse.from_json(response.json())
|
189 |
-
else:
|
190 |
-
raise Exception(f"Failed to refresh token: {response.text}")
|
191 |
-
|
192 |
-
except requests.exceptions.RequestException as e:
|
193 |
-
raise Exception(f"Network error: {e}")
|
194 |
-
|
195 |
-
# Example usage
|
196 |
-
try:
|
197 |
-
result = refresh_token("your-refresh-token")
|
198 |
-
print(f"✅ Token refreshed! New Access Token: {result.access_token}")
|
199 |
-
except Exception as e:
|
200 |
-
print(f"⚠️ Error: {e}")
|
201 |
-
</code></pre>
|
202 |
-
|
203 |
<h4>Response:</h4>
|
204 |
<pre><code class="language-json">{
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
@classmethod
|
235 |
-
def from_json(cls, json_data):
|
236 |
-
return cls(
|
237 |
-
text=json_data.get("text"),
|
238 |
-
similarity=json_data.get("similarity"),
|
239 |
-
model_type=json_data.get("model_type"),
|
240 |
-
)
|
241 |
-
|
242 |
-
def search(query: str, access_token: str):
|
243 |
-
"""Sends a search query and retrieves results."""
|
244 |
-
url = "https://humblebeeai-llm-host.hf.space/search"
|
245 |
-
headers = {
|
246 |
-
"Content-Type": "application/json",
|
247 |
-
"Authorization": f"Bearer {access_token}"
|
248 |
-
}
|
249 |
-
payload = {"query": query}
|
250 |
-
|
251 |
-
try:
|
252 |
-
response = requests.post(url, json=payload, headers=headers)
|
253 |
-
|
254 |
-
if response.status_code == 200:
|
255 |
-
json_list = response.json()
|
256 |
-
return [SearchResult.from_json(item) for item in json_list]
|
257 |
-
else:
|
258 |
-
raise Exception(f"Search failed: {response.text}")
|
259 |
-
|
260 |
-
except requests.exceptions.RequestException as e:
|
261 |
-
raise Exception(f"Network error: {e}")
|
262 |
-
|
263 |
-
# Example usage
|
264 |
-
try:
|
265 |
-
results = search("test query", "your-access-token")
|
266 |
-
for result in results:
|
267 |
-
print(f"✅ Found: {result.text} (Similarity: {result.similarity}, Model: {result.model_type})")
|
268 |
-
except Exception as e:
|
269 |
-
print(f"⚠️ Error: {e}")
|
270 |
-
</code></pre>
|
271 |
-
|
272 |
-
<h4>Response:</h4>
|
273 |
-
<pre><code class="language-json">
|
274 |
-
response based on query
|
275 |
-
</code></pre>
|
276 |
-
</div>
|
277 |
-
|
278 |
-
|
279 |
</section>
|
|
|
280 |
|
281 |
<section id="workflow">
|
282 |
<h2>Workflow Example</h2>
|
@@ -285,29 +108,38 @@ except Exception as e:
|
|
285 |
<h3>cURL Implementation</h3>
|
286 |
|
287 |
<div class="endpoint">
|
288 |
-
<h3>Step 1:
|
289 |
-
<pre><code class="language-bash">curl -X POST https://humblebeeai-llm-host.hf.space/
|
290 |
-
|
291 |
-
|
|
|
|
|
|
|
292 |
</div>
|
293 |
|
294 |
<div class="endpoint">
|
295 |
-
<h3>Step 2:
|
296 |
-
<pre><code class="language-bash">curl -X POST https://humblebeeai-llm-host.hf.space/
|
297 |
-
|
298 |
-
|
299 |
-
-d '{"query": "test query"}'</code></pre>
|
300 |
</div>
|
301 |
|
302 |
<div class="endpoint">
|
303 |
-
<h3>Step 3:
|
304 |
-
<pre><code class="language-bash">curl -X POST https://humblebeeai-llm-host.hf.space/
|
305 |
-
|
306 |
-
|
|
|
307 |
</div>
|
308 |
|
309 |
-
<
|
|
|
|
|
|
|
|
|
|
|
310 |
|
|
|
311 |
<div class="endpoint">
|
312 |
<h4>Complete Python Example</h4>
|
313 |
<pre><code class="language-python">
|
@@ -323,8 +155,20 @@ except Exception as e:
|
|
323 |
self.access_token = None
|
324 |
self.refresh_token = None
|
325 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
326 |
def login(self, username: str, password: str):
|
327 |
-
"""Authenticates the user and retrieves tokens"""
|
328 |
url = f"{API_BASE_URL}/login"
|
329 |
payload = {"username": username, "password": password}
|
330 |
headers = {"Content-Type": "application/x-www-form-urlencoded"}
|
@@ -338,40 +182,29 @@ except Exception as e:
|
|
338 |
else:
|
339 |
raise Exception(f"⚠️ Login failed: {response.text}")
|
340 |
|
341 |
-
def
|
342 |
-
"""
|
343 |
-
url = f"{API_BASE_URL}/
|
344 |
payload = {"query": query}
|
345 |
headers = {
|
346 |
"Content-Type": "application/json",
|
347 |
"Authorization": f"Bearer {self.access_token}",
|
348 |
}
|
349 |
|
350 |
-
response = requests.post(url, json=payload, headers=headers)
|
351 |
-
if response.status_code == 200:
|
352 |
-
results = response.json()
|
353 |
-
print("✅ Search results:", results)
|
354 |
-
return results
|
355 |
-
else:
|
356 |
-
raise Exception(f"⚠️ Search failed: {response.text}")
|
357 |
-
|
358 |
-
def save_data(self, items: list):
|
359 |
-
"""Saves retrieved data"""
|
360 |
-
url = f"{API_BASE_URL}/save"
|
361 |
-
payload = {"items": items}
|
362 |
-
headers = {
|
363 |
-
"Content-Type": "application/json",
|
364 |
-
"Authorization": f"Bearer {self.access_token}",
|
365 |
-
}
|
366 |
|
367 |
-
response = requests.post(url, json=payload, headers=headers)
|
368 |
if response.status_code == 200:
|
369 |
-
|
|
|
|
|
|
|
|
|
|
|
370 |
else:
|
371 |
-
raise Exception(f"⚠️
|
372 |
|
373 |
def refresh_token(self):
|
374 |
-
"""Refreshes access token"""
|
375 |
url = f"{API_BASE_URL}/refresh"
|
376 |
payload = {"refresh_token": self.refresh_token}
|
377 |
headers = {"Content-Type": "application/json"}
|
@@ -388,25 +221,16 @@ except Exception as e:
|
|
388 |
client = APIClient()
|
389 |
|
390 |
try:
|
391 |
-
# Step 1:
|
392 |
-
client.
|
393 |
-
|
394 |
-
# Step 2:
|
395 |
-
|
396 |
-
|
397 |
-
# Step 3:
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
"user_type": "user",
|
402 |
-
"username": "user123",
|
403 |
-
"query": "test query",
|
404 |
-
"retrieved_text": search_results[0]["text"],
|
405 |
-
"model_type": search_results[0]["model_type"],
|
406 |
-
"reaction": "positive",
|
407 |
-
}
|
408 |
-
]
|
409 |
-
client.save_data(save_items)
|
410 |
|
411 |
# Step 4: Refresh Token
|
412 |
client.refresh_token()
|
@@ -416,12 +240,21 @@ except Exception as e:
|
|
416 |
</code></pre>
|
417 |
</div>
|
418 |
|
419 |
-
<
|
420 |
<pre><code class="language-json">{
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
425 |
</section>
|
426 |
|
427 |
</main>
|
|
|
22 |
|
23 |
<section id="endpoints">
|
24 |
<h2>Endpoints</h2>
|
25 |
+
|
26 |
+
<div class="endpoint" id="register">
|
27 |
+
<h3>1. Register Endpoint</h3>
|
28 |
+
<p><span class="method">POST</span><span class="endpoint-url">/register</span></p>
|
29 |
+
<p>This endpoint is used to register the username and password.</p>
|
30 |
+
|
31 |
+
<h4>cURL Request:</h4>
|
32 |
+
<pre><code class="language-bash">curl -X POST 'https://humblebeeai-llm-host.hf.space/register' \
|
33 |
+
-H "Content-Type: application/json" \
|
34 |
+
-d '{
|
35 |
+
"username": "testuser",
|
36 |
+
"password": "testpassword"
|
37 |
+
}'</code></pre>
|
38 |
+
|
39 |
+
<h4>Response:</h4>
|
40 |
+
<pre><code class="language-json">{"message":"User registered successfully","user":"bahodir"}</code></pre>
|
41 |
+
</div>
|
42 |
+
|
43 |
+
<div class="endpoint" id="login">
|
44 |
+
<h3>2. Login Endpoint</h3>
|
45 |
+
<p><span class="method">POST</span><span class="endpoint-url">/login</span></p>
|
46 |
+
<p>This endpoint is used to authenticate a user and retrieve an access token.</p>
|
47 |
+
|
48 |
+
<h4>cURL Request:</h4>
|
49 |
+
<pre><code class="language-bash">curl -X POST 'https://humblebeeai-llm-host.hf.space/login' \
|
50 |
+
-H "Content-Type: application/x-www-form-urlencoded" \
|
51 |
+
-d 'username=testuser&password=testpassword'</code></pre>
|
52 |
+
|
53 |
+
<h4>Response:</h4>
|
54 |
+
<pre><code class="language-json">{
|
55 |
+
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
56 |
+
"token_type": "bearer",
|
57 |
+
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
58 |
+
}</code></pre>
|
59 |
+
</div>
|
60 |
+
|
61 |
+
<div class="endpoint" id="refresh">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
<h3>3. Refresh Token Endpoint</h3>
|
63 |
<p><span class="method">POST</span><span class="endpoint-url">/refresh</span></p>
|
64 |
<p>This endpoint is used to refresh the access token using a valid refresh token.</p>
|
65 |
+
|
66 |
<h4>cURL Request:</h4>
|
67 |
<pre><code class="language-bash">curl -X POST 'https://humblebeeai-llm-host.hf.space/refresh' \
|
68 |
-H "Content-Type: application/json" \
|
69 |
-d '{"refresh_token": "your-refresh-token"}'</code></pre>
|
70 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
71 |
<h4>Response:</h4>
|
72 |
<pre><code class="language-json">{
|
73 |
+
"access_token": "new-access-token",
|
74 |
+
"refresh_token": "your-refresh-token",
|
75 |
+
"token_type": "bearer"
|
76 |
+
}</code></pre>
|
77 |
+
</div>
|
78 |
+
|
79 |
+
<div class="endpoint" id="generate">
|
80 |
+
<h3>4. Generate Endpoint</h3>
|
81 |
+
<p><span class="method">POST</span><span class="endpoint-url">/generate</span></p>
|
82 |
+
<p>This endpoint is used to generate text based on a query. It requires a valid access token and supports optional streaming.</p>
|
83 |
+
|
84 |
+
<h4>cURL Request:</h4>
|
85 |
+
<pre><code class="language-bash">curl -X POST 'https://humblebeeai-llm-host.hf.space/generate?stream=true' \
|
86 |
+
-H "Content-Type: application/json" \
|
87 |
+
-H "Authorization: Bearer your-access-token" \
|
88 |
+
-d '{"query": "test query"}'</code></pre>
|
89 |
+
|
90 |
+
<h4>Response:</h4>
|
91 |
+
<pre><code class="language-json">{
|
92 |
+
"content": "Generated response text based on the query."
|
93 |
+
}</code></pre>
|
94 |
+
|
95 |
+
<h4>Streaming Response:</h4>
|
96 |
+
<pre><code class="language-json">
|
97 |
+
data: {"content": "First streamed response chunk"}
|
98 |
+
data: {"content": "Second streamed response chunk"}
|
99 |
+
</code></pre>
|
100 |
+
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
101 |
</section>
|
102 |
+
|
103 |
|
104 |
<section id="workflow">
|
105 |
<h2>Workflow Example</h2>
|
|
|
108 |
<h3>cURL Implementation</h3>
|
109 |
|
110 |
<div class="endpoint">
|
111 |
+
<h3>Step 1: Register</h3>
|
112 |
+
<pre><code class="language-bash">curl -X POST 'https://humblebeeai-llm-host.hf.space/register' \
|
113 |
+
-H "Content-Type: application/json" \
|
114 |
+
-d '{
|
115 |
+
"username": "testuser",
|
116 |
+
"password": "testpassword"
|
117 |
+
}'</code></pre>
|
118 |
</div>
|
119 |
|
120 |
<div class="endpoint">
|
121 |
+
<h3>Step 2: Login</h3>
|
122 |
+
<pre><code class="language-bash">curl -X POST 'https://humblebeeai-llm-host.hf.space/login' \
|
123 |
+
-H "Content-Type: application/x-www-form-urlencoded" \
|
124 |
+
-d 'username=testuser&password=testpassword'</code></pre>
|
|
|
125 |
</div>
|
126 |
|
127 |
<div class="endpoint">
|
128 |
+
<h3>Step 3: Generate</h3>
|
129 |
+
<pre><code class="language-bash">curl -X POST 'https://humblebeeai-llm-host.hf.space/generate?stream=true' \
|
130 |
+
-H "Content-Type: application/json" \
|
131 |
+
-H "Authorization: Bearer your-access-token" \
|
132 |
+
-d '{"query": "test query"}'</code></pre>
|
133 |
</div>
|
134 |
|
135 |
+
<div class="endpoint">
|
136 |
+
<h3>Step 4: Refresh Token</h3>
|
137 |
+
<pre><code class="language-bash">curl -X POST 'https://humblebeeai-llm-host.hf.space/refresh' \
|
138 |
+
-H "Content-Type: application/json" \
|
139 |
+
-d '{"refresh_token": "your-refresh-token"}'</code></pre>
|
140 |
+
</div>
|
141 |
|
142 |
+
<h3>Python Implementation</h3>
|
143 |
<div class="endpoint">
|
144 |
<h4>Complete Python Example</h4>
|
145 |
<pre><code class="language-python">
|
|
|
155 |
self.access_token = None
|
156 |
self.refresh_token = None
|
157 |
|
158 |
+
def register(self, username: str, password: str):
|
159 |
+
"""Registers a new user."""
|
160 |
+
url = f"{API_BASE_URL}/register"
|
161 |
+
payload = {"username": username, "password": password}
|
162 |
+
headers = {"Content-Type": "application/json"}
|
163 |
+
|
164 |
+
response = requests.post(url, json=payload, headers=headers)
|
165 |
+
if response.status_code == 200:
|
166 |
+
print("✅ Registration successful!")
|
167 |
+
else:
|
168 |
+
raise Exception(f"⚠️ Registration failed: {response.text}")
|
169 |
+
|
170 |
def login(self, username: str, password: str):
|
171 |
+
"""Authenticates the user and retrieves tokens."""
|
172 |
url = f"{API_BASE_URL}/login"
|
173 |
payload = {"username": username, "password": password}
|
174 |
headers = {"Content-Type": "application/x-www-form-urlencoded"}
|
|
|
182 |
else:
|
183 |
raise Exception(f"⚠️ Login failed: {response.text}")
|
184 |
|
185 |
+
def generate(self, query: str, stream: bool = False):
|
186 |
+
"""Generates content based on query."""
|
187 |
+
url = f"{API_BASE_URL}/generate?stream={str(stream).lower()}"
|
188 |
payload = {"query": query}
|
189 |
headers = {
|
190 |
"Content-Type": "application/json",
|
191 |
"Authorization": f"Bearer {self.access_token}",
|
192 |
}
|
193 |
|
194 |
+
response = requests.post(url, json=payload, headers=headers, stream=stream)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
195 |
|
|
|
196 |
if response.status_code == 200:
|
197 |
+
if stream:
|
198 |
+
for line in response.iter_lines():
|
199 |
+
if line:
|
200 |
+
print(json.loads(line.decode("utf-8")).get("content"))
|
201 |
+
else:
|
202 |
+
return response.json()
|
203 |
else:
|
204 |
+
raise Exception(f"⚠️ Request failed: {response.text}")
|
205 |
|
206 |
def refresh_token(self):
|
207 |
+
"""Refreshes access token."""
|
208 |
url = f"{API_BASE_URL}/refresh"
|
209 |
payload = {"refresh_token": self.refresh_token}
|
210 |
headers = {"Content-Type": "application/json"}
|
|
|
221 |
client = APIClient()
|
222 |
|
223 |
try:
|
224 |
+
# Step 1: Register
|
225 |
+
client.register("testuser", "testpassword")
|
226 |
+
|
227 |
+
# Step 2: Login
|
228 |
+
client.login("testuser", "testpassword")
|
229 |
+
|
230 |
+
# Step 3: Generate response
|
231 |
+
response = client.generate("test query", stream=True)
|
232 |
+
if response:
|
233 |
+
print(f"✅ Response: {response}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
234 |
|
235 |
# Step 4: Refresh Token
|
236 |
client.refresh_token()
|
|
|
240 |
</code></pre>
|
241 |
</div>
|
242 |
|
243 |
+
<h3>Example Responses:</h3>
|
244 |
<pre><code class="language-json">{
|
245 |
+
"access_token": "your-access-token",
|
246 |
+
"refresh_token": "your-refresh-token",
|
247 |
+
"token_type": "bearer"
|
248 |
+
}</code></pre>
|
249 |
+
|
250 |
+
<pre><code class="language-json">{
|
251 |
+
"content": "Generated response text based on the query."
|
252 |
+
}</code></pre>
|
253 |
+
|
254 |
+
<pre><code class="language-json">
|
255 |
+
data: {"content": "First streamed response chunk"}
|
256 |
+
data: {"content": "Second streamed response chunk"}
|
257 |
+
</code></pre>
|
258 |
</section>
|
259 |
|
260 |
</main>
|
static/script.js
CHANGED
@@ -4,7 +4,7 @@ const sections = [
|
|
4 |
{ id: 'register', title: 'Register' },
|
5 |
{ id: 'login', title: 'Login' },
|
6 |
{ id: 'refresh', title: 'Refresh Token' },
|
7 |
-
{ id: '
|
8 |
{ id: 'workflow', title: 'Workflow Example' }
|
9 |
];
|
10 |
|
|
|
4 |
{ id: 'register', title: 'Register' },
|
5 |
{ id: 'login', title: 'Login' },
|
6 |
{ id: 'refresh', title: 'Refresh Token' },
|
7 |
+
{ id: 'generate', title: 'Generate' },
|
8 |
{ id: 'workflow', title: 'Workflow Example' }
|
9 |
];
|
10 |
|
utils.py
CHANGED
@@ -1,8 +1,9 @@
|
|
1 |
import asyncio
|
2 |
import ollama
|
|
|
3 |
|
4 |
async def generate_stream(query: str):
|
5 |
-
"""Generates streamed responses from Ollama using LLaMA 3."""
|
6 |
try:
|
7 |
stream = ollama.chat(
|
8 |
model="llama3.2",
|
@@ -10,10 +11,22 @@ async def generate_stream(query: str):
|
|
10 |
stream=True
|
11 |
)
|
12 |
|
13 |
-
# Stream output without unnecessary delay
|
14 |
for chunk in stream:
|
15 |
if "message" in chunk and "content" in chunk["message"]:
|
16 |
-
|
|
|
17 |
|
18 |
except Exception as e:
|
19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import asyncio
|
2 |
import ollama
|
3 |
+
import json
|
4 |
|
5 |
async def generate_stream(query: str):
|
6 |
+
"""Generates streamed responses from Ollama using LLaMA 3 in JSON format."""
|
7 |
try:
|
8 |
stream = ollama.chat(
|
9 |
model="llama3.2",
|
|
|
11 |
stream=True
|
12 |
)
|
13 |
|
|
|
14 |
for chunk in stream:
|
15 |
if "message" in chunk and "content" in chunk["message"]:
|
16 |
+
response_data = json.dumps({"content": chunk["message"]["content"]})
|
17 |
+
yield f"data: {response_data}\n\n" # SSE format
|
18 |
|
19 |
except Exception as e:
|
20 |
+
error_data = json.dumps({"error": str(e)})
|
21 |
+
yield f"data: {error_data}\n\n"
|
22 |
+
|
23 |
+
async def generate_response(query: str):
|
24 |
+
"""Returns a non-streamed response."""
|
25 |
+
try:
|
26 |
+
response = ollama.chat(
|
27 |
+
model="llama3.2",
|
28 |
+
messages=[{"role": "user", "content": query}]
|
29 |
+
)
|
30 |
+
return {"content": response["message"]["content"]}
|
31 |
+
except Exception as e:
|
32 |
+
return {"error": str(e)}
|