Download app.py from smlflg/PromptGarageUI: direct link, hf CLI and curl.
- Browser
- Download file 6.18 kB
-
https://huggingface.co/smlflg/PromptGarageUI/resolve/main/app.py
- Command line
-
hf download hf://smlflg/PromptGarageUI/app.py
-
curl -L -o app.py https://huggingface.co/smlflg/PromptGarageUI/resolve/main/app.py
6.18 kB
| #!/usr/bin/env python3 | |
| """PromptGarage UI - FastAPI web application.""" | |
| import os | |
| from pathlib import Path | |
| from typing import Optional | |
| from fastapi import FastAPI, Form, Query, Request | |
| from fastapi.responses import HTMLResponse, RedirectResponse | |
| from fastapi.staticfiles import StaticFiles | |
| from fastapi.templating import Jinja2Templates | |
| import db_client as db | |
| app = FastAPI(title="PromptGarage", description="Web UI for your prompts") | |
| # Setup templates | |
| BASE_DIR = Path(__file__).parent | |
| templates = Jinja2Templates(directory=BASE_DIR / "templates") | |
| # Mount static files | |
| app.mount("/static", StaticFiles(directory=BASE_DIR / "static"), name="static") | |
| # --- Routes --- | |
| async def root(): | |
| return RedirectResponse("/prompts") | |
| async def prompts_list( | |
| request: Request, | |
| q: Optional[str] = Query(None, description="Search query"), | |
| tag: Optional[str] = Query(None, description="Filter by tag"), | |
| starred: Optional[int] = Query(None, description="Filter starred (1)"), | |
| page: int = Query(1, ge=1, description="Page number"), | |
| limit: int = Query(20, ge=1, le=100, description="Items per page"), | |
| ): | |
| offset = (page - 1) * limit | |
| # Get all tags for filter dropdown | |
| all_tags = db.get_stats()["by_tag"] | |
| # Search or list | |
| if q: | |
| prompts = db.search_fts(q) | |
| # Apply tag/star filters manually after FTS search | |
| filtered = [] | |
| for p in prompts: | |
| if tag and tag not in (p["tags"] or ""): | |
| continue | |
| if starred is not None and p["is_starred"] != starred: | |
| continue | |
| filtered.append(p) | |
| prompts = filtered[offset:offset + limit] | |
| total = len(filtered) | |
| else: | |
| # Build query params for list_prompts | |
| prompts = db.list_prompts( | |
| starred=bool(starred) if starred is not None else None, | |
| tag=tag, | |
| limit=limit + offset | |
| ) | |
| if offset > 0: | |
| prompts = prompts[offset:] | |
| total = len(db.list_prompts( | |
| starred=bool(starred) if starred is not None else None, | |
| tag=tag, | |
| limit=100000 | |
| )) | |
| total_pages = (total + limit - 1) // limit if total > 0 else 1 | |
| return templates.TemplateResponse("prompts/list.html", { | |
| "request": request, | |
| "prompts": prompts, | |
| "all_tags": all_tags, | |
| "q": q, | |
| "selected_tag": tag, | |
| "starred_filter": starred, | |
| "page": page, | |
| "limit": limit, | |
| "total": total, | |
| "total_pages": total_pages, | |
| }) | |
| async def prompts_new(request: Request): | |
| stats = db.get_stats() | |
| return templates.TemplateResponse("prompts/new.html", { | |
| "request": request, | |
| "all_tags": stats["by_tag"], | |
| }) | |
| async def prompts_create( | |
| title: str = Form(...), | |
| content: str = Form(...), | |
| tags: Optional[str] = Form(None), | |
| model: Optional[str] = Form(None), | |
| ): | |
| prompt_id = db.add_prompt(title=title, content=content, tags=tags, model=model) | |
| return RedirectResponse(f"/prompts/{prompt_id}", status_code=303) | |
| async def prompts_detail(request: Request, prompt_id: int): | |
| prompt = db.get_prompt(prompt_id) | |
| if not prompt: | |
| return templates.TemplateResponse("error.html", { | |
| "request": request, | |
| "error": f"Prompt #{prompt_id} not found", | |
| }, status_code=404) | |
| return templates.TemplateResponse("prompts/detail.html", { | |
| "request": request, | |
| "prompt": prompt, | |
| }) | |
| async def prompts_toggle_star(prompt_id: int): | |
| result = db.toggle_star(prompt_id) | |
| if result is None: | |
| return {"error": "Prompt not found"} | |
| return {"is_starred": result} | |
| async def prompts_set_rating(prompt_id: int, rating: int = Query(..., ge=1, le=5)): | |
| db.set_rating(prompt_id, rating) | |
| return {"rating": rating} | |
| async def prompts_use(prompt_id: int): | |
| db.increment_use(prompt_id) | |
| prompt = db.get_prompt(prompt_id) | |
| if prompt: | |
| return {"use_count": prompt["use_count"]} | |
| return {"error": "Prompt not found"} | |
| async def prompts_edit(request: Request, prompt_id: int): | |
| prompt = db.get_prompt(prompt_id) | |
| if not prompt: | |
| return templates.TemplateResponse("error.html", { | |
| "request": request, | |
| "error": f"Prompt #{prompt_id} not found", | |
| }, status_code=404) | |
| stats = db.get_stats() | |
| return templates.TemplateResponse("prompts/edit.html", { | |
| "request": request, | |
| "prompt": prompt, | |
| "all_tags": stats["by_tag"], | |
| }) | |
| async def prompts_update( | |
| prompt_id: int, | |
| title: str = Form(...), | |
| content: str = Form(...), | |
| tags: Optional[str] = Form(None), | |
| model: Optional[str] = Form(None), | |
| ): | |
| db.update_prompt(prompt_id, title=title, content=content, tags=tags, model=model) | |
| return RedirectResponse(f"/prompts/{prompt_id}", status_code=303) | |
| async def prompts_delete(prompt_id: int): | |
| db.delete_prompt(prompt_id) | |
| return RedirectResponse("/prompts", status_code=303) | |
| async def stats_page(request: Request): | |
| stats = db.get_stats() | |
| # Calculate rating distribution | |
| all_prompts = db.list_prompts(limit=100000) | |
| rating_dist = {0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0} | |
| for p in all_prompts: | |
| r = p["rating"] or 0 | |
| rating_dist[r] = rating_dist.get(r, 0) + 1 | |
| # Get top tags | |
| top_tags = sorted(stats["by_tag"].items(), key=lambda x: -x[1])[:15] | |
| return templates.TemplateResponse("stats.html", { | |
| "request": request, | |
| "stats": stats, | |
| "rating_dist": rating_dist, | |
| "top_tags": top_tags, | |
| }) | |
| if __name__ == "__main__": | |
| import uvicorn | |
| uvicorn.run(app, host="0.0.0.0", port=8000) | |