utils.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. from fastapi import APIRouter, UploadFile, File, Response
  2. from fastapi import Depends, HTTPException, status
  3. from peewee import SqliteDatabase
  4. from starlette.responses import StreamingResponse, FileResponse
  5. from pydantic import BaseModel
  6. from fpdf import FPDF
  7. import markdown
  8. import black
  9. from apps.webui.internal.db import DB
  10. from utils.utils import get_admin_user
  11. from utils.misc import calculate_sha256, get_gravatar_url
  12. from config import OLLAMA_BASE_URLS, DATA_DIR, UPLOAD_DIR, ENABLE_ADMIN_EXPORT
  13. from constants import ERROR_MESSAGES
  14. from typing import List
  15. router = APIRouter()
  16. @router.get("/gravatar")
  17. async def get_gravatar(
  18. email: str,
  19. ):
  20. return get_gravatar_url(email)
  21. class CodeFormatRequest(BaseModel):
  22. code: str
  23. @router.post("/code/format")
  24. async def format_code(request: CodeFormatRequest):
  25. try:
  26. formatted_code = black.format_str(request.code, mode=black.Mode())
  27. return {"code": formatted_code}
  28. except black.NothingChanged:
  29. return {"code": request.code}
  30. except Exception as e:
  31. raise HTTPException(status_code=400, detail=str(e))
  32. class MarkdownForm(BaseModel):
  33. md: str
  34. @router.post("/markdown")
  35. async def get_html_from_markdown(
  36. form_data: MarkdownForm,
  37. ):
  38. return {"html": markdown.markdown(form_data.md)}
  39. class ChatForm(BaseModel):
  40. title: str
  41. messages: List[dict]
  42. @router.post("/pdf")
  43. async def download_chat_as_pdf(
  44. form_data: ChatForm,
  45. ):
  46. pdf = FPDF()
  47. pdf.add_page()
  48. STATIC_DIR = "./static"
  49. FONTS_DIR = f"{STATIC_DIR}/fonts"
  50. pdf.add_font("NotoSans", "", f"{FONTS_DIR}/NotoSans-Regular.ttf")
  51. pdf.add_font("NotoSans", "b", f"{FONTS_DIR}/NotoSans-Bold.ttf")
  52. pdf.add_font("NotoSans", "i", f"{FONTS_DIR}/NotoSans-Italic.ttf")
  53. pdf.add_font("NotoSansKR", "", f"{FONTS_DIR}/NotoSansKR-Regular.ttf")
  54. pdf.add_font("NotoSansJP", "", f"{FONTS_DIR}/NotoSansJP-Regular.ttf")
  55. pdf.set_font("NotoSans", size=12)
  56. pdf.set_fallback_fonts(["NotoSansKR", "NotoSansJP"])
  57. pdf.set_auto_page_break(auto=True, margin=15)
  58. # Adjust the effective page width for multi_cell
  59. effective_page_width = (
  60. pdf.w - 2 * pdf.l_margin - 10
  61. ) # Subtracted an additional 10 for extra padding
  62. # Add chat messages
  63. for message in form_data.messages:
  64. role = message["role"]
  65. content = message["content"]
  66. pdf.set_font("NotoSans", "B", size=14) # Bold for the role
  67. pdf.multi_cell(effective_page_width, 10, f"{role.upper()}", 0, "L")
  68. pdf.ln(1) # Extra space between messages
  69. pdf.set_font("NotoSans", size=10) # Regular for content
  70. pdf.multi_cell(effective_page_width, 6, content, 0, "L")
  71. pdf.ln(1.5) # Extra space between messages
  72. # Save the pdf with name .pdf
  73. pdf_bytes = pdf.output()
  74. return Response(
  75. content=bytes(pdf_bytes),
  76. media_type="application/pdf",
  77. headers={"Content-Disposition": f"attachment;filename=chat.pdf"},
  78. )
  79. @router.get("/db/download")
  80. async def download_db(user=Depends(get_admin_user)):
  81. if not ENABLE_ADMIN_EXPORT:
  82. raise HTTPException(
  83. status_code=status.HTTP_401_UNAUTHORIZED,
  84. detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
  85. )
  86. if not isinstance(DB, SqliteDatabase):
  87. raise HTTPException(
  88. status_code=status.HTTP_400_BAD_REQUEST,
  89. detail=ERROR_MESSAGES.DB_NOT_SQLITE,
  90. )
  91. return FileResponse(
  92. DB.database,
  93. media_type="application/octet-stream",
  94. filename="webui.db",
  95. )
  96. @router.get("/litellm/config")
  97. async def download_litellm_config_yaml(user=Depends(get_admin_user)):
  98. return FileResponse(
  99. f"{DATA_DIR}/litellm/config.yaml",
  100. media_type="application/octet-stream",
  101. filename="config.yaml",
  102. )