utils.py 3.7 KB

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