utils.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import black
  2. import logging
  3. import markdown
  4. from open_webui.models.chats import ChatTitleMessagesForm
  5. from open_webui.config import DATA_DIR, ENABLE_ADMIN_EXPORT
  6. from open_webui.constants import ERROR_MESSAGES
  7. from fastapi import APIRouter, Depends, HTTPException, Request, Response, status
  8. from pydantic import BaseModel
  9. from starlette.responses import FileResponse
  10. from open_webui.utils.misc import get_gravatar_url
  11. from open_webui.utils.pdf_generator import PDFGenerator
  12. from open_webui.utils.auth import get_admin_user, get_verified_user
  13. from open_webui.utils.code_interpreter import execute_code_jupyter
  14. from open_webui.env import SRC_LOG_LEVELS
  15. log = logging.getLogger(__name__)
  16. log.setLevel(SRC_LOG_LEVELS["MAIN"])
  17. router = APIRouter()
  18. @router.get("/gravatar")
  19. async def get_gravatar(email: str, user=Depends(get_verified_user)):
  20. return get_gravatar_url(email)
  21. class CodeForm(BaseModel):
  22. code: str
  23. @router.post("/code/format")
  24. async def format_code(form_data: CodeForm, user=Depends(get_verified_user)):
  25. try:
  26. formatted_code = black.format_str(form_data.code, mode=black.Mode())
  27. return {"code": formatted_code}
  28. except black.NothingChanged:
  29. return {"code": form_data.code}
  30. except Exception as e:
  31. raise HTTPException(status_code=400, detail=str(e))
  32. @router.post("/code/execute")
  33. async def execute_code(
  34. request: Request, form_data: CodeForm, user=Depends(get_verified_user)
  35. ):
  36. if request.app.state.config.CODE_EXECUTION_ENGINE == "jupyter":
  37. output = await execute_code_jupyter(
  38. request.app.state.config.CODE_EXECUTION_JUPYTER_URL,
  39. form_data.code,
  40. (
  41. request.app.state.config.CODE_EXECUTION_JUPYTER_AUTH_TOKEN
  42. if request.app.state.config.CODE_EXECUTION_JUPYTER_AUTH == "token"
  43. else None
  44. ),
  45. (
  46. request.app.state.config.CODE_EXECUTION_JUPYTER_AUTH_PASSWORD
  47. if request.app.state.config.CODE_EXECUTION_JUPYTER_AUTH == "password"
  48. else None
  49. ),
  50. request.app.state.config.CODE_EXECUTION_JUPYTER_TIMEOUT,
  51. )
  52. return output
  53. else:
  54. raise HTTPException(
  55. status_code=400,
  56. detail="Code execution engine not supported",
  57. )
  58. class MarkdownForm(BaseModel):
  59. md: str
  60. @router.post("/markdown")
  61. async def get_html_from_markdown(
  62. form_data: MarkdownForm, user=Depends(get_verified_user)
  63. ):
  64. return {"html": markdown.markdown(form_data.md)}
  65. class ChatForm(BaseModel):
  66. title: str
  67. messages: list[dict]
  68. @router.post("/pdf")
  69. async def download_chat_as_pdf(
  70. form_data: ChatTitleMessagesForm, user=Depends(get_verified_user)
  71. ):
  72. try:
  73. pdf_bytes = PDFGenerator(form_data).generate_chat_pdf()
  74. return Response(
  75. content=pdf_bytes,
  76. media_type="application/pdf",
  77. headers={"Content-Disposition": "attachment;filename=chat.pdf"},
  78. )
  79. except Exception as e:
  80. log.exception(f"Error generating PDF: {e}")
  81. raise HTTPException(status_code=400, detail=str(e))
  82. @router.get("/db/download")
  83. async def download_db(user=Depends(get_admin_user)):
  84. if not ENABLE_ADMIN_EXPORT:
  85. raise HTTPException(
  86. status_code=status.HTTP_401_UNAUTHORIZED,
  87. detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
  88. )
  89. from open_webui.internal.db import engine
  90. if engine.name != "sqlite":
  91. raise HTTPException(
  92. status_code=status.HTTP_400_BAD_REQUEST,
  93. detail=ERROR_MESSAGES.DB_NOT_SQLITE,
  94. )
  95. return FileResponse(
  96. engine.url.database,
  97. media_type="application/octet-stream",
  98. filename="webui.db",
  99. )
  100. @router.get("/litellm/config")
  101. async def download_litellm_config_yaml(user=Depends(get_admin_user)):
  102. return FileResponse(
  103. f"{DATA_DIR}/litellm/config.yaml",
  104. media_type="application/octet-stream",
  105. filename="config.yaml",
  106. )