Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
# app.py - HF Spaces compatible version (Fixed)
|
2 |
import os
|
3 |
import re
|
4 |
import json
|
@@ -6,6 +6,10 @@ from datetime import datetime
|
|
6 |
from typing import List, Dict, Any
|
7 |
|
8 |
import gradio as gr
|
|
|
|
|
|
|
|
|
9 |
|
10 |
# Configuration - Use HF Spaces secrets
|
11 |
WEBHOOK_SECRET = os.getenv("WEBHOOK_SECRET")
|
@@ -29,6 +33,12 @@ RECOGNIZED_TAGS = {
|
|
29 |
"llamacpp", "onnx", "mlx"
|
30 |
}
|
31 |
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
def extract_tags_from_text(text: str) -> List[str]:
|
33 |
"""Extract potential tags from discussion text"""
|
34 |
text_lower = text.lower()
|
@@ -231,6 +241,54 @@ async def process_webhook_comment(webhook_data: Dict[str, Any]):
|
|
231 |
print(f"β {error_msg}")
|
232 |
return error_msg
|
233 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
234 |
def create_gradio_interface():
|
235 |
"""Create Gradio interface for monitoring"""
|
236 |
with gr.Blocks(title="HF Tagging Bot", theme=gr.themes.Soft()) as interface:
|
@@ -330,54 +388,13 @@ Visit: `https://your-space-name.hf.space/health`
|
|
330 |
# Create the Gradio interface
|
331 |
demo = create_gradio_interface()
|
332 |
|
333 |
-
#
|
334 |
-
|
335 |
-
import asyncio
|
336 |
-
|
337 |
-
@demo.app.post("/webhook")
|
338 |
-
async def webhook_handler(request: Request):
|
339 |
-
"""Handle HF Hub webhooks"""
|
340 |
-
# Verify webhook secret if configured
|
341 |
-
if WEBHOOK_SECRET:
|
342 |
-
webhook_secret = request.headers.get("X-Webhook-Secret")
|
343 |
-
if webhook_secret != WEBHOOK_SECRET:
|
344 |
-
print("β Invalid webhook secret")
|
345 |
-
return {"error": "Invalid webhook secret"}
|
346 |
-
|
347 |
-
try:
|
348 |
-
payload = await request.json()
|
349 |
-
print(f"π₯ Received webhook: {payload.get('event', {})}")
|
350 |
-
|
351 |
-
event = payload.get("event", {})
|
352 |
-
scope = event.get("scope")
|
353 |
-
action = event.get("action")
|
354 |
-
|
355 |
-
# Only process discussion comment creation (not PRs)
|
356 |
-
if (scope == "discussion" and
|
357 |
-
action == "create" and
|
358 |
-
not payload.get("discussion", {}).get("isPullRequest", False)):
|
359 |
-
|
360 |
-
# Process webhook in background
|
361 |
-
asyncio.create_task(process_webhook_comment(payload))
|
362 |
-
return {"status": "processing"}
|
363 |
-
|
364 |
-
return {"status": "ignored"}
|
365 |
-
except Exception as e:
|
366 |
-
print(f"β Webhook error: {e}")
|
367 |
-
return {"error": str(e)}
|
368 |
-
|
369 |
-
@demo.app.get("/health")
|
370 |
-
async def health_check():
|
371 |
-
return {
|
372 |
-
"status": "healthy",
|
373 |
-
"hf_token_configured": bool(HF_TOKEN),
|
374 |
-
"webhook_secret_configured": bool(WEBHOOK_SECRET),
|
375 |
-
"operations_processed": len(tag_operations_store)
|
376 |
-
}
|
377 |
|
378 |
-
#
|
379 |
if __name__ == "__main__":
|
380 |
-
print("π HF Tagging Bot -
|
381 |
print(f"π HF_TOKEN: {'β
Configured' if HF_TOKEN else 'β Missing'}")
|
382 |
print(f"π Webhook Secret: {'β
Configured' if WEBHOOK_SECRET else 'β Missing'}")
|
383 |
-
|
|
|
|
1 |
+
# app.py - HF Spaces compatible version (Fixed webhook handling)
|
2 |
import os
|
3 |
import re
|
4 |
import json
|
|
|
6 |
from typing import List, Dict, Any
|
7 |
|
8 |
import gradio as gr
|
9 |
+
from fastapi import FastAPI, Request, BackgroundTasks
|
10 |
+
from fastapi.middleware.cors import CORSMiddleware
|
11 |
+
from pydantic import BaseModel
|
12 |
+
import asyncio
|
13 |
|
14 |
# Configuration - Use HF Spaces secrets
|
15 |
WEBHOOK_SECRET = os.getenv("WEBHOOK_SECRET")
|
|
|
33 |
"llamacpp", "onnx", "mlx"
|
34 |
}
|
35 |
|
36 |
+
class WebhookEvent(BaseModel):
|
37 |
+
event: Dict[str, str]
|
38 |
+
comment: Dict[str, Any]
|
39 |
+
discussion: Dict[str, Any]
|
40 |
+
repo: Dict[str, str]
|
41 |
+
|
42 |
def extract_tags_from_text(text: str) -> List[str]:
|
43 |
"""Extract potential tags from discussion text"""
|
44 |
text_lower = text.lower()
|
|
|
241 |
print(f"β {error_msg}")
|
242 |
return error_msg
|
243 |
|
244 |
+
# Create FastAPI app for webhook handling
|
245 |
+
app = FastAPI(title="HF Tagging Bot API")
|
246 |
+
app.add_middleware(CORSMiddleware, allow_origins=["*"])
|
247 |
+
|
248 |
+
@app.post("/webhook")
|
249 |
+
async def webhook_handler(request: Request, background_tasks: BackgroundTasks):
|
250 |
+
"""Handle HF Hub webhooks"""
|
251 |
+
# Verify webhook secret if configured
|
252 |
+
if WEBHOOK_SECRET:
|
253 |
+
webhook_secret = request.headers.get("X-Webhook-Secret")
|
254 |
+
if webhook_secret != WEBHOOK_SECRET:
|
255 |
+
print("β Invalid webhook secret")
|
256 |
+
return {"error": "Invalid webhook secret"}
|
257 |
+
|
258 |
+
try:
|
259 |
+
payload = await request.json()
|
260 |
+
print(f"π₯ Received webhook: {payload.get('event', {})}")
|
261 |
+
|
262 |
+
event = payload.get("event", {})
|
263 |
+
scope = event.get("scope")
|
264 |
+
action = event.get("action")
|
265 |
+
|
266 |
+
# Only process discussion comment creation (not PRs)
|
267 |
+
if (scope == "discussion" and
|
268 |
+
action == "create" and
|
269 |
+
not payload.get("discussion", {}).get("isPullRequest", False)):
|
270 |
+
|
271 |
+
background_tasks.add_task(process_webhook_comment, payload)
|
272 |
+
return {"status": "processing"}
|
273 |
+
|
274 |
+
return {"status": "ignored"}
|
275 |
+
except Exception as e:
|
276 |
+
print(f"β Webhook error: {e}")
|
277 |
+
return {"error": str(e)}
|
278 |
+
|
279 |
+
@app.get("/health")
|
280 |
+
async def health_check():
|
281 |
+
return {
|
282 |
+
"status": "healthy",
|
283 |
+
"hf_token_configured": bool(HF_TOKEN),
|
284 |
+
"webhook_secret_configured": bool(WEBHOOK_SECRET),
|
285 |
+
"operations_processed": len(tag_operations_store)
|
286 |
+
}
|
287 |
+
|
288 |
+
@app.get("/")
|
289 |
+
async def root():
|
290 |
+
return {"message": "HF Tagging Bot is running! Visit /gradio for the interface."}
|
291 |
+
|
292 |
def create_gradio_interface():
|
293 |
"""Create Gradio interface for monitoring"""
|
294 |
with gr.Blocks(title="HF Tagging Bot", theme=gr.themes.Soft()) as interface:
|
|
|
388 |
# Create the Gradio interface
|
389 |
demo = create_gradio_interface()
|
390 |
|
391 |
+
# Mount Gradio app to FastAPI
|
392 |
+
app = gr.mount_gradio_app(app, demo, path="/")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
393 |
|
394 |
+
# This is what HF Spaces will use
|
395 |
if __name__ == "__main__":
|
396 |
+
print("π HF Tagging Bot - Starting with FastAPI + Gradio")
|
397 |
print(f"π HF_TOKEN: {'β
Configured' if HF_TOKEN else 'β Missing'}")
|
398 |
print(f"π Webhook Secret: {'β
Configured' if WEBHOOK_SECRET else 'β Missing'}")
|
399 |
+
import uvicorn
|
400 |
+
uvicorn.run(app, host="0.0.0.0", port=7860)
|