tasks.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  1. from fastapi import APIRouter, Depends, HTTPException, Response, status, Request
  2. from fastapi.responses import JSONResponse, RedirectResponse
  3. from pydantic import BaseModel
  4. from typing import Optional
  5. import logging
  6. import re
  7. from open_webui.utils.chat import generate_chat_completion
  8. from open_webui.utils.task import (
  9. title_generation_template,
  10. query_generation_template,
  11. image_prompt_generation_template,
  12. autocomplete_generation_template,
  13. tags_generation_template,
  14. emoji_generation_template,
  15. moa_response_generation_template,
  16. )
  17. from open_webui.utils.auth import get_admin_user, get_verified_user
  18. from open_webui.constants import TASKS
  19. from open_webui.routers.pipelines import process_pipeline_inlet_filter
  20. from open_webui.utils.task import get_task_model_id
  21. from open_webui.config import (
  22. DEFAULT_TITLE_GENERATION_PROMPT_TEMPLATE,
  23. DEFAULT_TAGS_GENERATION_PROMPT_TEMPLATE,
  24. DEFAULT_IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE,
  25. DEFAULT_QUERY_GENERATION_PROMPT_TEMPLATE,
  26. DEFAULT_AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE,
  27. DEFAULT_EMOJI_GENERATION_PROMPT_TEMPLATE,
  28. DEFAULT_MOA_GENERATION_PROMPT_TEMPLATE,
  29. )
  30. from open_webui.env import SRC_LOG_LEVELS
  31. log = logging.getLogger(__name__)
  32. log.setLevel(SRC_LOG_LEVELS["MODELS"])
  33. router = APIRouter()
  34. ##################################
  35. #
  36. # Task Endpoints
  37. #
  38. ##################################
  39. @router.get("/config")
  40. async def get_task_config(request: Request, user=Depends(get_verified_user)):
  41. return {
  42. "TASK_MODEL": request.app.state.config.TASK_MODEL,
  43. "TASK_MODEL_EXTERNAL": request.app.state.config.TASK_MODEL_EXTERNAL,
  44. "TITLE_GENERATION_PROMPT_TEMPLATE": request.app.state.config.TITLE_GENERATION_PROMPT_TEMPLATE,
  45. "IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE": request.app.state.config.IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE,
  46. "ENABLE_AUTOCOMPLETE_GENERATION": request.app.state.config.ENABLE_AUTOCOMPLETE_GENERATION,
  47. "AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH": request.app.state.config.AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH,
  48. "TAGS_GENERATION_PROMPT_TEMPLATE": request.app.state.config.TAGS_GENERATION_PROMPT_TEMPLATE,
  49. "ENABLE_TAGS_GENERATION": request.app.state.config.ENABLE_TAGS_GENERATION,
  50. "ENABLE_SEARCH_QUERY_GENERATION": request.app.state.config.ENABLE_SEARCH_QUERY_GENERATION,
  51. "ENABLE_RETRIEVAL_QUERY_GENERATION": request.app.state.config.ENABLE_RETRIEVAL_QUERY_GENERATION,
  52. "QUERY_GENERATION_PROMPT_TEMPLATE": request.app.state.config.QUERY_GENERATION_PROMPT_TEMPLATE,
  53. "TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE": request.app.state.config.TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE,
  54. }
  55. class TaskConfigForm(BaseModel):
  56. TASK_MODEL: Optional[str]
  57. TASK_MODEL_EXTERNAL: Optional[str]
  58. TITLE_GENERATION_PROMPT_TEMPLATE: str
  59. IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE: str
  60. ENABLE_AUTOCOMPLETE_GENERATION: bool
  61. AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH: int
  62. TAGS_GENERATION_PROMPT_TEMPLATE: str
  63. ENABLE_TAGS_GENERATION: bool
  64. ENABLE_SEARCH_QUERY_GENERATION: bool
  65. ENABLE_RETRIEVAL_QUERY_GENERATION: bool
  66. QUERY_GENERATION_PROMPT_TEMPLATE: str
  67. TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE: str
  68. @router.post("/config/update")
  69. async def update_task_config(
  70. request: Request, form_data: TaskConfigForm, user=Depends(get_admin_user)
  71. ):
  72. request.app.state.config.TASK_MODEL = form_data.TASK_MODEL
  73. request.app.state.config.TASK_MODEL_EXTERNAL = form_data.TASK_MODEL_EXTERNAL
  74. request.app.state.config.TITLE_GENERATION_PROMPT_TEMPLATE = (
  75. form_data.TITLE_GENERATION_PROMPT_TEMPLATE
  76. )
  77. request.app.state.config.IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE = (
  78. form_data.IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE
  79. )
  80. request.app.state.config.ENABLE_AUTOCOMPLETE_GENERATION = (
  81. form_data.ENABLE_AUTOCOMPLETE_GENERATION
  82. )
  83. request.app.state.config.AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH = (
  84. form_data.AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH
  85. )
  86. request.app.state.config.TAGS_GENERATION_PROMPT_TEMPLATE = (
  87. form_data.TAGS_GENERATION_PROMPT_TEMPLATE
  88. )
  89. request.app.state.config.ENABLE_TAGS_GENERATION = form_data.ENABLE_TAGS_GENERATION
  90. request.app.state.config.ENABLE_SEARCH_QUERY_GENERATION = (
  91. form_data.ENABLE_SEARCH_QUERY_GENERATION
  92. )
  93. request.app.state.config.ENABLE_RETRIEVAL_QUERY_GENERATION = (
  94. form_data.ENABLE_RETRIEVAL_QUERY_GENERATION
  95. )
  96. request.app.state.config.QUERY_GENERATION_PROMPT_TEMPLATE = (
  97. form_data.QUERY_GENERATION_PROMPT_TEMPLATE
  98. )
  99. request.app.state.config.TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE = (
  100. form_data.TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE
  101. )
  102. return {
  103. "TASK_MODEL": request.app.state.config.TASK_MODEL,
  104. "TASK_MODEL_EXTERNAL": request.app.state.config.TASK_MODEL_EXTERNAL,
  105. "TITLE_GENERATION_PROMPT_TEMPLATE": request.app.state.config.TITLE_GENERATION_PROMPT_TEMPLATE,
  106. "IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE": request.app.state.config.IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE,
  107. "ENABLE_AUTOCOMPLETE_GENERATION": request.app.state.config.ENABLE_AUTOCOMPLETE_GENERATION,
  108. "AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH": request.app.state.config.AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH,
  109. "TAGS_GENERATION_PROMPT_TEMPLATE": request.app.state.config.TAGS_GENERATION_PROMPT_TEMPLATE,
  110. "ENABLE_TAGS_GENERATION": request.app.state.config.ENABLE_TAGS_GENERATION,
  111. "ENABLE_SEARCH_QUERY_GENERATION": request.app.state.config.ENABLE_SEARCH_QUERY_GENERATION,
  112. "ENABLE_RETRIEVAL_QUERY_GENERATION": request.app.state.config.ENABLE_RETRIEVAL_QUERY_GENERATION,
  113. "QUERY_GENERATION_PROMPT_TEMPLATE": request.app.state.config.QUERY_GENERATION_PROMPT_TEMPLATE,
  114. "TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE": request.app.state.config.TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE,
  115. }
  116. @router.post("/title/completions")
  117. async def generate_title(
  118. request: Request, form_data: dict, user=Depends(get_verified_user)
  119. ):
  120. models = request.app.state.MODELS
  121. model_id = form_data["model"]
  122. if model_id not in models:
  123. raise HTTPException(
  124. status_code=status.HTTP_404_NOT_FOUND,
  125. detail="Model not found",
  126. )
  127. # Check if the user has a custom task model
  128. # If the user has a custom task model, use that model
  129. task_model_id = get_task_model_id(
  130. model_id,
  131. request.app.state.config.TASK_MODEL,
  132. request.app.state.config.TASK_MODEL_EXTERNAL,
  133. models,
  134. )
  135. log.debug(
  136. f"generating chat title using model {task_model_id} for user {user.email} "
  137. )
  138. if request.app.state.config.TITLE_GENERATION_PROMPT_TEMPLATE != "":
  139. template = request.app.state.config.TITLE_GENERATION_PROMPT_TEMPLATE
  140. else:
  141. template = DEFAULT_TITLE_GENERATION_PROMPT_TEMPLATE
  142. messages = form_data["messages"]
  143. # Remove reasoning details from the messages
  144. for message in messages:
  145. message["content"] = re.sub(
  146. r"<details\s+type=\"reasoning\"[^>]*>.*?<\/details>",
  147. "",
  148. message["content"],
  149. flags=re.S,
  150. ).strip()
  151. content = title_generation_template(
  152. template,
  153. messages,
  154. {
  155. "name": user.name,
  156. "location": user.info.get("location") if user.info else None,
  157. },
  158. )
  159. payload = {
  160. "model": task_model_id,
  161. "messages": [{"role": "user", "content": content}],
  162. "stream": False,
  163. **(
  164. {"max_tokens": 1000}
  165. if models[task_model_id]["owned_by"] == "ollama"
  166. else {
  167. "max_completion_tokens": 1000,
  168. }
  169. ),
  170. "metadata": {
  171. "task": str(TASKS.TITLE_GENERATION),
  172. "task_body": form_data,
  173. "chat_id": form_data.get("chat_id", None),
  174. },
  175. }
  176. try:
  177. return await generate_chat_completion(request, form_data=payload, user=user)
  178. except Exception as e:
  179. log.error("Exception occurred", exc_info=True)
  180. return JSONResponse(
  181. status_code=status.HTTP_400_BAD_REQUEST,
  182. content={"detail": "An internal error has occurred."},
  183. )
  184. @router.post("/tags/completions")
  185. async def generate_chat_tags(
  186. request: Request, form_data: dict, user=Depends(get_verified_user)
  187. ):
  188. if not request.app.state.config.ENABLE_TAGS_GENERATION:
  189. return JSONResponse(
  190. status_code=status.HTTP_200_OK,
  191. content={"detail": "Tags generation is disabled"},
  192. )
  193. models = request.app.state.MODELS
  194. model_id = form_data["model"]
  195. if model_id not in models:
  196. raise HTTPException(
  197. status_code=status.HTTP_404_NOT_FOUND,
  198. detail="Model not found",
  199. )
  200. # Check if the user has a custom task model
  201. # If the user has a custom task model, use that model
  202. task_model_id = get_task_model_id(
  203. model_id,
  204. request.app.state.config.TASK_MODEL,
  205. request.app.state.config.TASK_MODEL_EXTERNAL,
  206. models,
  207. )
  208. log.debug(
  209. f"generating chat tags using model {task_model_id} for user {user.email} "
  210. )
  211. if request.app.state.config.TAGS_GENERATION_PROMPT_TEMPLATE != "":
  212. template = request.app.state.config.TAGS_GENERATION_PROMPT_TEMPLATE
  213. else:
  214. template = DEFAULT_TAGS_GENERATION_PROMPT_TEMPLATE
  215. content = tags_generation_template(
  216. template, form_data["messages"], {"name": user.name}
  217. )
  218. payload = {
  219. "model": task_model_id,
  220. "messages": [{"role": "user", "content": content}],
  221. "stream": False,
  222. "metadata": {
  223. "task": str(TASKS.TAGS_GENERATION),
  224. "task_body": form_data,
  225. "chat_id": form_data.get("chat_id", None),
  226. },
  227. }
  228. try:
  229. return await generate_chat_completion(request, form_data=payload, user=user)
  230. except Exception as e:
  231. log.error(f"Error generating chat completion: {e}")
  232. return JSONResponse(
  233. status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
  234. content={"detail": "An internal error has occurred."},
  235. )
  236. @router.post("/image_prompt/completions")
  237. async def generate_image_prompt(
  238. request: Request, form_data: dict, user=Depends(get_verified_user)
  239. ):
  240. models = request.app.state.MODELS
  241. model_id = form_data["model"]
  242. if model_id not in models:
  243. raise HTTPException(
  244. status_code=status.HTTP_404_NOT_FOUND,
  245. detail="Model not found",
  246. )
  247. # Check if the user has a custom task model
  248. # If the user has a custom task model, use that model
  249. task_model_id = get_task_model_id(
  250. model_id,
  251. request.app.state.config.TASK_MODEL,
  252. request.app.state.config.TASK_MODEL_EXTERNAL,
  253. models,
  254. )
  255. log.debug(
  256. f"generating image prompt using model {task_model_id} for user {user.email} "
  257. )
  258. if request.app.state.config.IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE != "":
  259. template = request.app.state.config.IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE
  260. else:
  261. template = DEFAULT_IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE
  262. content = image_prompt_generation_template(
  263. template,
  264. form_data["messages"],
  265. user={
  266. "name": user.name,
  267. },
  268. )
  269. payload = {
  270. "model": task_model_id,
  271. "messages": [{"role": "user", "content": content}],
  272. "stream": False,
  273. "metadata": {
  274. "task": str(TASKS.IMAGE_PROMPT_GENERATION),
  275. "task_body": form_data,
  276. "chat_id": form_data.get("chat_id", None),
  277. },
  278. }
  279. try:
  280. return await generate_chat_completion(request, form_data=payload, user=user)
  281. except Exception as e:
  282. log.error("Exception occurred", exc_info=True)
  283. return JSONResponse(
  284. status_code=status.HTTP_400_BAD_REQUEST,
  285. content={"detail": "An internal error has occurred."},
  286. )
  287. @router.post("/queries/completions")
  288. async def generate_queries(
  289. request: Request, form_data: dict, user=Depends(get_verified_user)
  290. ):
  291. type = form_data.get("type")
  292. if type == "web_search":
  293. if not request.app.state.config.ENABLE_SEARCH_QUERY_GENERATION:
  294. raise HTTPException(
  295. status_code=status.HTTP_400_BAD_REQUEST,
  296. detail=f"Search query generation is disabled",
  297. )
  298. elif type == "retrieval":
  299. if not request.app.state.config.ENABLE_RETRIEVAL_QUERY_GENERATION:
  300. raise HTTPException(
  301. status_code=status.HTTP_400_BAD_REQUEST,
  302. detail=f"Query generation is disabled",
  303. )
  304. models = request.app.state.MODELS
  305. model_id = form_data["model"]
  306. if model_id not in models:
  307. raise HTTPException(
  308. status_code=status.HTTP_404_NOT_FOUND,
  309. detail="Model not found",
  310. )
  311. # Check if the user has a custom task model
  312. # If the user has a custom task model, use that model
  313. task_model_id = get_task_model_id(
  314. model_id,
  315. request.app.state.config.TASK_MODEL,
  316. request.app.state.config.TASK_MODEL_EXTERNAL,
  317. models,
  318. )
  319. log.debug(
  320. f"generating {type} queries using model {task_model_id} for user {user.email}"
  321. )
  322. if (request.app.state.config.QUERY_GENERATION_PROMPT_TEMPLATE).strip() != "":
  323. template = request.app.state.config.QUERY_GENERATION_PROMPT_TEMPLATE
  324. else:
  325. template = DEFAULT_QUERY_GENERATION_PROMPT_TEMPLATE
  326. content = query_generation_template(
  327. template, form_data["messages"], {"name": user.name}
  328. )
  329. payload = {
  330. "model": task_model_id,
  331. "messages": [{"role": "user", "content": content}],
  332. "stream": False,
  333. "metadata": {
  334. "task": str(TASKS.QUERY_GENERATION),
  335. "task_body": form_data,
  336. "chat_id": form_data.get("chat_id", None),
  337. },
  338. }
  339. try:
  340. return await generate_chat_completion(request, form_data=payload, user=user)
  341. except Exception as e:
  342. return JSONResponse(
  343. status_code=status.HTTP_400_BAD_REQUEST,
  344. content={"detail": str(e)},
  345. )
  346. @router.post("/auto/completions")
  347. async def generate_autocompletion(
  348. request: Request, form_data: dict, user=Depends(get_verified_user)
  349. ):
  350. if not request.app.state.config.ENABLE_AUTOCOMPLETE_GENERATION:
  351. raise HTTPException(
  352. status_code=status.HTTP_400_BAD_REQUEST,
  353. detail=f"Autocompletion generation is disabled",
  354. )
  355. type = form_data.get("type")
  356. prompt = form_data.get("prompt")
  357. messages = form_data.get("messages")
  358. if request.app.state.config.AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH > 0:
  359. if (
  360. len(prompt)
  361. > request.app.state.config.AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH
  362. ):
  363. raise HTTPException(
  364. status_code=status.HTTP_400_BAD_REQUEST,
  365. detail=f"Input prompt exceeds maximum length of {request.app.state.config.AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH}",
  366. )
  367. models = request.app.state.MODELS
  368. model_id = form_data["model"]
  369. if model_id not in models:
  370. raise HTTPException(
  371. status_code=status.HTTP_404_NOT_FOUND,
  372. detail="Model not found",
  373. )
  374. # Check if the user has a custom task model
  375. # If the user has a custom task model, use that model
  376. task_model_id = get_task_model_id(
  377. model_id,
  378. request.app.state.config.TASK_MODEL,
  379. request.app.state.config.TASK_MODEL_EXTERNAL,
  380. models,
  381. )
  382. log.debug(
  383. f"generating autocompletion using model {task_model_id} for user {user.email}"
  384. )
  385. if (request.app.state.config.AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE).strip() != "":
  386. template = request.app.state.config.AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE
  387. else:
  388. template = DEFAULT_AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE
  389. content = autocomplete_generation_template(
  390. template, prompt, messages, type, {"name": user.name}
  391. )
  392. payload = {
  393. "model": task_model_id,
  394. "messages": [{"role": "user", "content": content}],
  395. "stream": False,
  396. "metadata": {
  397. "task": str(TASKS.AUTOCOMPLETE_GENERATION),
  398. "task_body": form_data,
  399. "chat_id": form_data.get("chat_id", None),
  400. },
  401. }
  402. try:
  403. return await generate_chat_completion(request, form_data=payload, user=user)
  404. except Exception as e:
  405. log.error(f"Error generating chat completion: {e}")
  406. return JSONResponse(
  407. status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
  408. content={"detail": "An internal error has occurred."},
  409. )
  410. @router.post("/emoji/completions")
  411. async def generate_emoji(
  412. request: Request, form_data: dict, user=Depends(get_verified_user)
  413. ):
  414. models = request.app.state.MODELS
  415. model_id = form_data["model"]
  416. if model_id not in models:
  417. raise HTTPException(
  418. status_code=status.HTTP_404_NOT_FOUND,
  419. detail="Model not found",
  420. )
  421. # Check if the user has a custom task model
  422. # If the user has a custom task model, use that model
  423. task_model_id = get_task_model_id(
  424. model_id,
  425. request.app.state.config.TASK_MODEL,
  426. request.app.state.config.TASK_MODEL_EXTERNAL,
  427. models,
  428. )
  429. log.debug(f"generating emoji using model {task_model_id} for user {user.email} ")
  430. template = DEFAULT_EMOJI_GENERATION_PROMPT_TEMPLATE
  431. content = emoji_generation_template(
  432. template,
  433. form_data["prompt"],
  434. {
  435. "name": user.name,
  436. "location": user.info.get("location") if user.info else None,
  437. },
  438. )
  439. payload = {
  440. "model": task_model_id,
  441. "messages": [{"role": "user", "content": content}],
  442. "stream": False,
  443. **(
  444. {"max_tokens": 4}
  445. if models[task_model_id]["owned_by"] == "ollama"
  446. else {
  447. "max_completion_tokens": 4,
  448. }
  449. ),
  450. "chat_id": form_data.get("chat_id", None),
  451. "metadata": {"task": str(TASKS.EMOJI_GENERATION), "task_body": form_data},
  452. }
  453. try:
  454. return await generate_chat_completion(request, form_data=payload, user=user)
  455. except Exception as e:
  456. return JSONResponse(
  457. status_code=status.HTTP_400_BAD_REQUEST,
  458. content={"detail": str(e)},
  459. )
  460. @router.post("/moa/completions")
  461. async def generate_moa_response(
  462. request: Request, form_data: dict, user=Depends(get_verified_user)
  463. ):
  464. models = request.app.state.MODELS
  465. model_id = form_data["model"]
  466. if model_id not in models:
  467. raise HTTPException(
  468. status_code=status.HTTP_404_NOT_FOUND,
  469. detail="Model not found",
  470. )
  471. # Check if the user has a custom task model
  472. # If the user has a custom task model, use that model
  473. task_model_id = get_task_model_id(
  474. model_id,
  475. request.app.state.config.TASK_MODEL,
  476. request.app.state.config.TASK_MODEL_EXTERNAL,
  477. models,
  478. )
  479. log.debug(f"generating MOA model {task_model_id} for user {user.email} ")
  480. template = DEFAULT_MOA_GENERATION_PROMPT_TEMPLATE
  481. content = moa_response_generation_template(
  482. template,
  483. form_data["prompt"],
  484. form_data["responses"],
  485. )
  486. payload = {
  487. "model": task_model_id,
  488. "messages": [{"role": "user", "content": content}],
  489. "stream": form_data.get("stream", False),
  490. "metadata": {
  491. "chat_id": form_data.get("chat_id", None),
  492. "task": str(TASKS.MOA_RESPONSE_GENERATION),
  493. "task_body": form_data,
  494. },
  495. }
  496. try:
  497. return await generate_chat_completion(request, form_data=payload, user=user)
  498. except Exception as e:
  499. return JSONResponse(
  500. status_code=status.HTTP_400_BAD_REQUEST,
  501. content={"detail": str(e)},
  502. )