github-actions[bot] commited on
Commit
e639365
·
1 Parent(s): 775fb16

GitHub deploy: 30c44d431b007c78c9d283a27fdb171e071ea780

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. CHANGELOG.md +0 -27
  2. backend/apps/audio/main.py +7 -7
  3. backend/apps/images/main.py +4 -4
  4. backend/apps/images/utils/comfyui.py +2 -2
  5. backend/apps/ollama/main.py +6 -6
  6. backend/apps/openai/main.py +3 -3
  7. backend/apps/rag/main.py +9 -9
  8. backend/apps/rag/search/brave.py +2 -2
  9. backend/apps/rag/search/duckduckgo.py +3 -3
  10. backend/apps/rag/search/google_pse.py +2 -2
  11. backend/apps/rag/search/jina_search.py +1 -1
  12. backend/apps/rag/search/searxng.py +5 -5
  13. backend/apps/rag/search/serper.py +2 -2
  14. backend/apps/rag/search/serply.py +2 -2
  15. backend/apps/rag/search/serpstack.py +2 -2
  16. backend/apps/rag/search/tavily.py +1 -1
  17. backend/apps/rag/utils.py +6 -6
  18. backend/apps/webui/models/auths.py +6 -6
  19. backend/apps/webui/models/chats.py +20 -20
  20. backend/apps/webui/models/documents.py +5 -5
  21. backend/apps/webui/models/files.py +5 -5
  22. backend/apps/webui/models/functions.py +10 -10
  23. backend/apps/webui/models/memories.py +10 -10
  24. backend/apps/webui/models/models.py +3 -3
  25. backend/apps/webui/models/prompts.py +5 -5
  26. backend/apps/webui/models/tags.py +8 -8
  27. backend/apps/webui/models/tools.py +8 -8
  28. backend/apps/webui/models/users.py +12 -12
  29. backend/apps/webui/routers/chats.py +11 -11
  30. backend/apps/webui/routers/configs.py +7 -7
  31. backend/apps/webui/routers/documents.py +4 -4
  32. backend/apps/webui/routers/files.py +2 -2
  33. backend/apps/webui/routers/functions.py +5 -5
  34. backend/apps/webui/routers/memories.py +2 -2
  35. backend/apps/webui/routers/models.py +2 -2
  36. backend/apps/webui/routers/prompts.py +3 -3
  37. backend/apps/webui/routers/tools.py +3 -3
  38. backend/apps/webui/routers/users.py +2 -2
  39. backend/apps/webui/routers/utils.py +2 -2
  40. backend/apps/webui/utils.py +0 -14
  41. backend/config.py +8 -8
  42. backend/main.py +3 -3
  43. backend/start.sh +1 -0
  44. backend/utils/misc.py +10 -10
  45. backend/utils/tools.py +2 -2
  46. package-lock.json +5 -6
  47. package.json +1 -2
  48. pyproject.toml +5 -5
  49. requirements-dev.lock +6 -8
  50. requirements.lock +6 -8
CHANGELOG.md CHANGED
@@ -5,33 +5,6 @@ All notable changes to this project will be documented in this file.
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
 
8
- ## [0.3.13] - 2024-08-14
9
-
10
- ### Added
11
-
12
- - **🎨 Enhanced Markdown Rendering**: Significant improvements in rendering markdown, ensuring smooth and reliable display of LaTeX and Mermaid charts, enhancing user experience with more robust visual content.
13
- - **🔄 Auto-Install Tools & Functions Python Dependencies**: For 'Tools' and 'Functions', Open WebUI now automatically install extra python requirements specified in the frontmatter, streamlining setup processes and customization.
14
- - **🌀 OAuth Email Claim Customization**: Introduced an 'OAUTH_EMAIL_CLAIM' variable to allow customization of the default "email" claim within OAuth configurations, providing greater flexibility in authentication processes.
15
- - **📶 Websocket Reconnection**: Enhanced reliability with the capability to automatically reconnect when a websocket is closed, ensuring consistent and stable communication.
16
- - **🤳 Haptic Feedback on Support Devices**: Android devices now support haptic feedback for an immersive tactile experience during certain interactions.
17
-
18
- ### Fixed
19
-
20
- - **🛠️ ComfyUI Performance Improvement**: Addressed an issue causing FastAPI to stall when ComfyUI image generation was active; now runs in a separate thread to prevent UI unresponsiveness.
21
- - **🔀 Session Handling**: Fixed an issue mandating session_id on client-side to ensure smoother session management and transitions.
22
- - **🖋️ Minor Bug Fixes and Format Corrections**: Various minor fixes including typo corrections, backend formatting improvements, and test amendments enhancing overall system stability and performance.
23
-
24
- ### Changed
25
-
26
- - **🚀 Migration to SvelteKit 2**: Upgraded the underlying framework to SvelteKit version 2, offering enhanced speed, better code structure, and improved deployment capabilities.
27
- - **🧹 General Cleanup and Refactoring**: Performed broad cleanup and refactoring across the platform, improving code efficiency and maintaining high standards of code health.
28
- - **🚧 Integration Testing Improvements**: Modified how Cypress integration tests detect chat messages and updated sharing tests for better reliability and accuracy.
29
- - **📁 Standardized '.safetensors' File Extension**: Renamed the '.sft' file extension to '.safetensors' for ComfyUI workflows, standardizing file formats across the platform.
30
-
31
- ### Removed
32
-
33
- - **🗑️ Deprecated Frontend Functions**: Removed frontend functions that were migrated to backend to declutter the codebase and reduce redundancy.
34
-
35
  ## [0.3.12] - 2024-08-07
36
 
37
  ### Added
 
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  ## [0.3.12] - 2024-08-07
9
 
10
  ### Added
backend/apps/audio/main.py CHANGED
@@ -15,7 +15,7 @@ from fastapi.responses import StreamingResponse, JSONResponse, FileResponse
15
  from fastapi.middleware.cors import CORSMiddleware
16
  from pydantic import BaseModel
17
 
18
-
19
  import uuid
20
  import requests
21
  import hashlib
@@ -244,7 +244,7 @@ async def speech(request: Request, user=Depends(get_verified_user)):
244
  res = r.json()
245
  if "error" in res:
246
  error_detail = f"External: {res['error']['message']}"
247
- except Exception:
248
  error_detail = f"External: {e}"
249
 
250
  raise HTTPException(
@@ -299,7 +299,7 @@ async def speech(request: Request, user=Depends(get_verified_user)):
299
  res = r.json()
300
  if "error" in res:
301
  error_detail = f"External: {res['error']['message']}"
302
- except Exception:
303
  error_detail = f"External: {e}"
304
 
305
  raise HTTPException(
@@ -353,7 +353,7 @@ def transcribe(
353
 
354
  try:
355
  model = WhisperModel(**whisper_kwargs)
356
- except Exception:
357
  log.warning(
358
  "WhisperModel initialization failed, attempting download with local_files_only=False"
359
  )
@@ -421,7 +421,7 @@ def transcribe(
421
  res = r.json()
422
  if "error" in res:
423
  error_detail = f"External: {res['error']['message']}"
424
- except Exception:
425
  error_detail = f"External: {e}"
426
 
427
  raise HTTPException(
@@ -438,7 +438,7 @@ def transcribe(
438
  )
439
 
440
 
441
- def get_available_models() -> list[dict]:
442
  if app.state.config.TTS_ENGINE == "openai":
443
  return [{"id": "tts-1"}, {"id": "tts-1-hd"}]
444
  elif app.state.config.TTS_ENGINE == "elevenlabs":
@@ -466,7 +466,7 @@ async def get_models(user=Depends(get_verified_user)):
466
  return {"models": get_available_models()}
467
 
468
 
469
- def get_available_voices() -> list[dict]:
470
  if app.state.config.TTS_ENGINE == "openai":
471
  return [
472
  {"name": "alloy", "id": "alloy"},
 
15
  from fastapi.middleware.cors import CORSMiddleware
16
  from pydantic import BaseModel
17
 
18
+ from typing import List
19
  import uuid
20
  import requests
21
  import hashlib
 
244
  res = r.json()
245
  if "error" in res:
246
  error_detail = f"External: {res['error']['message']}"
247
+ except:
248
  error_detail = f"External: {e}"
249
 
250
  raise HTTPException(
 
299
  res = r.json()
300
  if "error" in res:
301
  error_detail = f"External: {res['error']['message']}"
302
+ except:
303
  error_detail = f"External: {e}"
304
 
305
  raise HTTPException(
 
353
 
354
  try:
355
  model = WhisperModel(**whisper_kwargs)
356
+ except:
357
  log.warning(
358
  "WhisperModel initialization failed, attempting download with local_files_only=False"
359
  )
 
421
  res = r.json()
422
  if "error" in res:
423
  error_detail = f"External: {res['error']['message']}"
424
+ except:
425
  error_detail = f"External: {e}"
426
 
427
  raise HTTPException(
 
438
  )
439
 
440
 
441
+ def get_available_models() -> List[dict]:
442
  if app.state.config.TTS_ENGINE == "openai":
443
  return [{"id": "tts-1"}, {"id": "tts-1-hd"}]
444
  elif app.state.config.TTS_ENGINE == "elevenlabs":
 
466
  return {"models": get_available_models()}
467
 
468
 
469
+ def get_available_voices() -> List[dict]:
470
  if app.state.config.TTS_ENGINE == "openai":
471
  return [
472
  {"name": "alloy", "id": "alloy"},
backend/apps/images/main.py CHANGED
@@ -94,7 +94,7 @@ app.state.config.COMFYUI_FLUX_FP8_CLIP = COMFYUI_FLUX_FP8_CLIP
94
 
95
 
96
  def get_automatic1111_api_auth():
97
- if app.state.config.AUTOMATIC1111_API_AUTH is None:
98
  return ""
99
  else:
100
  auth1111_byte_string = app.state.config.AUTOMATIC1111_API_AUTH.encode("utf-8")
@@ -145,7 +145,7 @@ async def get_engine_url(user=Depends(get_admin_user)):
145
  async def update_engine_url(
146
  form_data: EngineUrlUpdateForm, user=Depends(get_admin_user)
147
  ):
148
- if form_data.AUTOMATIC1111_BASE_URL is None:
149
  app.state.config.AUTOMATIC1111_BASE_URL = AUTOMATIC1111_BASE_URL
150
  else:
151
  url = form_data.AUTOMATIC1111_BASE_URL.strip("/")
@@ -156,7 +156,7 @@ async def update_engine_url(
156
  except Exception as e:
157
  raise HTTPException(status_code=400, detail=ERROR_MESSAGES.INVALID_URL)
158
 
159
- if form_data.COMFYUI_BASE_URL is None:
160
  app.state.config.COMFYUI_BASE_URL = COMFYUI_BASE_URL
161
  else:
162
  url = form_data.COMFYUI_BASE_URL.strip("/")
@@ -168,7 +168,7 @@ async def update_engine_url(
168
  except Exception as e:
169
  raise HTTPException(status_code=400, detail=ERROR_MESSAGES.INVALID_URL)
170
 
171
- if form_data.AUTOMATIC1111_API_AUTH is None:
172
  app.state.config.AUTOMATIC1111_API_AUTH = AUTOMATIC1111_API_AUTH
173
  else:
174
  app.state.config.AUTOMATIC1111_API_AUTH = form_data.AUTOMATIC1111_API_AUTH
 
94
 
95
 
96
  def get_automatic1111_api_auth():
97
+ if app.state.config.AUTOMATIC1111_API_AUTH == None:
98
  return ""
99
  else:
100
  auth1111_byte_string = app.state.config.AUTOMATIC1111_API_AUTH.encode("utf-8")
 
145
  async def update_engine_url(
146
  form_data: EngineUrlUpdateForm, user=Depends(get_admin_user)
147
  ):
148
+ if form_data.AUTOMATIC1111_BASE_URL == None:
149
  app.state.config.AUTOMATIC1111_BASE_URL = AUTOMATIC1111_BASE_URL
150
  else:
151
  url = form_data.AUTOMATIC1111_BASE_URL.strip("/")
 
156
  except Exception as e:
157
  raise HTTPException(status_code=400, detail=ERROR_MESSAGES.INVALID_URL)
158
 
159
+ if form_data.COMFYUI_BASE_URL == None:
160
  app.state.config.COMFYUI_BASE_URL = COMFYUI_BASE_URL
161
  else:
162
  url = form_data.COMFYUI_BASE_URL.strip("/")
 
168
  except Exception as e:
169
  raise HTTPException(status_code=400, detail=ERROR_MESSAGES.INVALID_URL)
170
 
171
+ if form_data.AUTOMATIC1111_API_AUTH == None:
172
  app.state.config.AUTOMATIC1111_API_AUTH = AUTOMATIC1111_API_AUTH
173
  else:
174
  app.state.config.AUTOMATIC1111_API_AUTH = form_data.AUTOMATIC1111_API_AUTH
backend/apps/images/utils/comfyui.py CHANGED
@@ -170,7 +170,7 @@ FLUX_DEFAULT_PROMPT = """
170
  },
171
  "10": {
172
  "inputs": {
173
- "vae_name": "ae.safetensors"
174
  },
175
  "class_type": "VAELoader"
176
  },
@@ -184,7 +184,7 @@ FLUX_DEFAULT_PROMPT = """
184
  },
185
  "12": {
186
  "inputs": {
187
- "unet_name": "flux1-dev.safetensors",
188
  "weight_dtype": "default"
189
  },
190
  "class_type": "UNETLoader"
 
170
  },
171
  "10": {
172
  "inputs": {
173
+ "vae_name": "ae.sft"
174
  },
175
  "class_type": "VAELoader"
176
  },
 
184
  },
185
  "12": {
186
  "inputs": {
187
+ "unet_name": "flux1-dev.sft",
188
  "weight_dtype": "default"
189
  },
190
  "class_type": "UNETLoader"
backend/apps/ollama/main.py CHANGED
@@ -21,7 +21,7 @@ import asyncio
21
  import logging
22
  import time
23
  from urllib.parse import urlparse
24
- from typing import Optional, Union
25
 
26
  from starlette.background import BackgroundTask
27
 
@@ -114,7 +114,7 @@ async def get_ollama_api_urls(user=Depends(get_admin_user)):
114
 
115
 
116
  class UrlUpdateForm(BaseModel):
117
- urls: list[str]
118
 
119
 
120
  @app.post("/urls/update")
@@ -646,7 +646,7 @@ def generate_ollama_embeddings(
646
  class GenerateCompletionForm(BaseModel):
647
  model: str
648
  prompt: str
649
- images: Optional[list[str]] = None
650
  format: Optional[str] = None
651
  options: Optional[dict] = None
652
  system: Optional[str] = None
@@ -689,12 +689,12 @@ async def generate_completion(
689
  class ChatMessage(BaseModel):
690
  role: str
691
  content: str
692
- images: Optional[list[str]] = None
693
 
694
 
695
  class GenerateChatCompletionForm(BaseModel):
696
  model: str
697
- messages: list[ChatMessage]
698
  format: Optional[str] = None
699
  options: Optional[dict] = None
700
  template: Optional[str] = None
@@ -772,7 +772,7 @@ class OpenAIChatMessage(BaseModel):
772
 
773
  class OpenAIChatCompletionForm(BaseModel):
774
  model: str
775
- messages: list[OpenAIChatMessage]
776
 
777
  model_config = ConfigDict(extra="allow")
778
 
 
21
  import logging
22
  import time
23
  from urllib.parse import urlparse
24
+ from typing import Optional, List, Union
25
 
26
  from starlette.background import BackgroundTask
27
 
 
114
 
115
 
116
  class UrlUpdateForm(BaseModel):
117
+ urls: List[str]
118
 
119
 
120
  @app.post("/urls/update")
 
646
  class GenerateCompletionForm(BaseModel):
647
  model: str
648
  prompt: str
649
+ images: Optional[List[str]] = None
650
  format: Optional[str] = None
651
  options: Optional[dict] = None
652
  system: Optional[str] = None
 
689
  class ChatMessage(BaseModel):
690
  role: str
691
  content: str
692
+ images: Optional[List[str]] = None
693
 
694
 
695
  class GenerateChatCompletionForm(BaseModel):
696
  model: str
697
+ messages: List[ChatMessage]
698
  format: Optional[str] = None
699
  options: Optional[dict] = None
700
  template: Optional[str] = None
 
772
 
773
  class OpenAIChatCompletionForm(BaseModel):
774
  model: str
775
+ messages: List[OpenAIChatMessage]
776
 
777
  model_config = ConfigDict(extra="allow")
778
 
backend/apps/openai/main.py CHANGED
@@ -33,7 +33,7 @@ from config import (
33
  MODEL_FILTER_LIST,
34
  AppConfig,
35
  )
36
- from typing import Optional, Literal, overload
37
 
38
 
39
  import hashlib
@@ -89,11 +89,11 @@ async def update_config(form_data: OpenAIConfigForm, user=Depends(get_admin_user
89
 
90
 
91
  class UrlsUpdateForm(BaseModel):
92
- urls: list[str]
93
 
94
 
95
  class KeysUpdateForm(BaseModel):
96
- keys: list[str]
97
 
98
 
99
  @app.get("/urls")
 
33
  MODEL_FILTER_LIST,
34
  AppConfig,
35
  )
36
+ from typing import List, Optional, Literal, overload
37
 
38
 
39
  import hashlib
 
89
 
90
 
91
  class UrlsUpdateForm(BaseModel):
92
+ urls: List[str]
93
 
94
 
95
  class KeysUpdateForm(BaseModel):
96
+ keys: List[str]
97
 
98
 
99
  @app.get("/urls")
backend/apps/rag/main.py CHANGED
@@ -13,7 +13,7 @@ import os, shutil, logging, re
13
  from datetime import datetime
14
 
15
  from pathlib import Path
16
- from typing import Union, Sequence, Iterator, Any
17
 
18
  from chromadb.utils.batch_utils import create_batches
19
  from langchain_core.documents import Document
@@ -376,7 +376,7 @@ async def update_reranking_config(
376
  try:
377
  app.state.config.RAG_RERANKING_MODEL = form_data.reranking_model
378
 
379
- update_reranking_model(app.state.config.RAG_RERANKING_MODEL, True)
380
 
381
  return {
382
  "status": True,
@@ -439,7 +439,7 @@ class ChunkParamUpdateForm(BaseModel):
439
 
440
 
441
  class YoutubeLoaderConfig(BaseModel):
442
- language: list[str]
443
  translation: Optional[str] = None
444
 
445
 
@@ -642,7 +642,7 @@ def query_doc_handler(
642
 
643
 
644
  class QueryCollectionsForm(BaseModel):
645
- collection_names: list[str]
646
  query: str
647
  k: Optional[int] = None
648
  r: Optional[float] = None
@@ -1021,7 +1021,7 @@ class TikaLoader:
1021
  self.file_path = file_path
1022
  self.mime_type = mime_type
1023
 
1024
- def load(self) -> list[Document]:
1025
  with open(self.file_path, "rb") as f:
1026
  data = f.read()
1027
 
@@ -1185,7 +1185,7 @@ def store_doc(
1185
  f.close()
1186
 
1187
  f = open(file_path, "rb")
1188
- if collection_name is None:
1189
  collection_name = calculate_sha256(f)[:63]
1190
  f.close()
1191
 
@@ -1238,7 +1238,7 @@ def process_doc(
1238
  f = open(file_path, "rb")
1239
 
1240
  collection_name = form_data.collection_name
1241
- if collection_name is None:
1242
  collection_name = calculate_sha256(f)[:63]
1243
  f.close()
1244
 
@@ -1296,7 +1296,7 @@ def store_text(
1296
  ):
1297
 
1298
  collection_name = form_data.collection_name
1299
- if collection_name is None:
1300
  collection_name = calculate_sha256_string(form_data.content)
1301
 
1302
  result = store_text_in_vector_db(
@@ -1339,7 +1339,7 @@ def scan_docs_dir(user=Depends(get_admin_user)):
1339
  sanitized_filename = sanitize_filename(filename)
1340
  doc = Documents.get_doc_by_name(sanitized_filename)
1341
 
1342
- if doc is None:
1343
  doc = Documents.insert_new_doc(
1344
  user.id,
1345
  DocumentForm(
 
13
  from datetime import datetime
14
 
15
  from pathlib import Path
16
+ from typing import List, Union, Sequence, Iterator, Any
17
 
18
  from chromadb.utils.batch_utils import create_batches
19
  from langchain_core.documents import Document
 
376
  try:
377
  app.state.config.RAG_RERANKING_MODEL = form_data.reranking_model
378
 
379
+ update_reranking_model(app.state.config.RAG_RERANKING_MODEL), True
380
 
381
  return {
382
  "status": True,
 
439
 
440
 
441
  class YoutubeLoaderConfig(BaseModel):
442
+ language: List[str]
443
  translation: Optional[str] = None
444
 
445
 
 
642
 
643
 
644
  class QueryCollectionsForm(BaseModel):
645
+ collection_names: List[str]
646
  query: str
647
  k: Optional[int] = None
648
  r: Optional[float] = None
 
1021
  self.file_path = file_path
1022
  self.mime_type = mime_type
1023
 
1024
+ def load(self) -> List[Document]:
1025
  with open(self.file_path, "rb") as f:
1026
  data = f.read()
1027
 
 
1185
  f.close()
1186
 
1187
  f = open(file_path, "rb")
1188
+ if collection_name == None:
1189
  collection_name = calculate_sha256(f)[:63]
1190
  f.close()
1191
 
 
1238
  f = open(file_path, "rb")
1239
 
1240
  collection_name = form_data.collection_name
1241
+ if collection_name == None:
1242
  collection_name = calculate_sha256(f)[:63]
1243
  f.close()
1244
 
 
1296
  ):
1297
 
1298
  collection_name = form_data.collection_name
1299
+ if collection_name == None:
1300
  collection_name = calculate_sha256_string(form_data.content)
1301
 
1302
  result = store_text_in_vector_db(
 
1339
  sanitized_filename = sanitize_filename(filename)
1340
  doc = Documents.get_doc_by_name(sanitized_filename)
1341
 
1342
+ if doc == None:
1343
  doc = Documents.insert_new_doc(
1344
  user.id,
1345
  DocumentForm(
backend/apps/rag/search/brave.py CHANGED
@@ -1,5 +1,5 @@
1
  import logging
2
- from typing import Optional
3
  import requests
4
 
5
  from apps.rag.search.main import SearchResult, get_filtered_results
@@ -10,7 +10,7 @@ log.setLevel(SRC_LOG_LEVELS["RAG"])
10
 
11
 
12
  def search_brave(
13
- api_key: str, query: str, count: int, filter_list: Optional[list[str]] = None
14
  ) -> list[SearchResult]:
15
  """Search using Brave's Search API and return the results as a list of SearchResult objects.
16
 
 
1
  import logging
2
+ from typing import List, Optional
3
  import requests
4
 
5
  from apps.rag.search.main import SearchResult, get_filtered_results
 
10
 
11
 
12
  def search_brave(
13
+ api_key: str, query: str, count: int, filter_list: Optional[List[str]] = None
14
  ) -> list[SearchResult]:
15
  """Search using Brave's Search API and return the results as a list of SearchResult objects.
16
 
backend/apps/rag/search/duckduckgo.py CHANGED
@@ -1,5 +1,5 @@
1
  import logging
2
- from typing import Optional
3
  from apps.rag.search.main import SearchResult, get_filtered_results
4
  from duckduckgo_search import DDGS
5
  from config import SRC_LOG_LEVELS
@@ -9,7 +9,7 @@ log.setLevel(SRC_LOG_LEVELS["RAG"])
9
 
10
 
11
  def search_duckduckgo(
12
- query: str, count: int, filter_list: Optional[list[str]] = None
13
  ) -> list[SearchResult]:
14
  """
15
  Search using DuckDuckGo's Search API and return the results as a list of SearchResult objects.
@@ -18,7 +18,7 @@ def search_duckduckgo(
18
  count (int): The number of results to return
19
 
20
  Returns:
21
- list[SearchResult]: A list of search results
22
  """
23
  # Use the DDGS context manager to create a DDGS object
24
  with DDGS() as ddgs:
 
1
  import logging
2
+ from typing import List, Optional
3
  from apps.rag.search.main import SearchResult, get_filtered_results
4
  from duckduckgo_search import DDGS
5
  from config import SRC_LOG_LEVELS
 
9
 
10
 
11
  def search_duckduckgo(
12
+ query: str, count: int, filter_list: Optional[List[str]] = None
13
  ) -> list[SearchResult]:
14
  """
15
  Search using DuckDuckGo's Search API and return the results as a list of SearchResult objects.
 
18
  count (int): The number of results to return
19
 
20
  Returns:
21
+ List[SearchResult]: A list of search results
22
  """
23
  # Use the DDGS context manager to create a DDGS object
24
  with DDGS() as ddgs:
backend/apps/rag/search/google_pse.py CHANGED
@@ -1,6 +1,6 @@
1
  import json
2
  import logging
3
- from typing import Optional
4
  import requests
5
 
6
  from apps.rag.search.main import SearchResult, get_filtered_results
@@ -15,7 +15,7 @@ def search_google_pse(
15
  search_engine_id: str,
16
  query: str,
17
  count: int,
18
- filter_list: Optional[list[str]] = None,
19
  ) -> list[SearchResult]:
20
  """Search using Google's Programmable Search Engine API and return the results as a list of SearchResult objects.
21
 
 
1
  import json
2
  import logging
3
+ from typing import List, Optional
4
  import requests
5
 
6
  from apps.rag.search.main import SearchResult, get_filtered_results
 
15
  search_engine_id: str,
16
  query: str,
17
  count: int,
18
+ filter_list: Optional[List[str]] = None,
19
  ) -> list[SearchResult]:
20
  """Search using Google's Programmable Search Engine API and return the results as a list of SearchResult objects.
21
 
backend/apps/rag/search/jina_search.py CHANGED
@@ -17,7 +17,7 @@ def search_jina(query: str, count: int) -> list[SearchResult]:
17
  count (int): The number of results to return
18
 
19
  Returns:
20
- list[SearchResult]: A list of search results
21
  """
22
  jina_search_endpoint = "https://s.jina.ai/"
23
  headers = {
 
17
  count (int): The number of results to return
18
 
19
  Returns:
20
+ List[SearchResult]: A list of search results
21
  """
22
  jina_search_endpoint = "https://s.jina.ai/"
23
  headers = {
backend/apps/rag/search/searxng.py CHANGED
@@ -1,7 +1,7 @@
1
  import logging
2
  import requests
3
 
4
- from typing import Optional
5
 
6
  from apps.rag.search.main import SearchResult, get_filtered_results
7
  from config import SRC_LOG_LEVELS
@@ -14,9 +14,9 @@ def search_searxng(
14
  query_url: str,
15
  query: str,
16
  count: int,
17
- filter_list: Optional[list[str]] = None,
18
  **kwargs,
19
- ) -> list[SearchResult]:
20
  """
21
  Search a SearXNG instance for a given query and return the results as a list of SearchResult objects.
22
 
@@ -31,10 +31,10 @@ def search_searxng(
31
  language (str): Language filter for the search results; e.g., "en-US". Defaults to an empty string.
32
  safesearch (int): Safe search filter for safer web results; 0 = off, 1 = moderate, 2 = strict. Defaults to 1 (moderate).
33
  time_range (str): Time range for filtering results by date; e.g., "2023-04-05..today" or "all-time". Defaults to ''.
34
- categories: (Optional[list[str]]): Specific categories within which the search should be performed, defaulting to an empty string if not provided.
35
 
36
  Returns:
37
- list[SearchResult]: A list of SearchResults sorted by relevance score in descending order.
38
 
39
  Raise:
40
  requests.exceptions.RequestException: If a request error occurs during the search process.
 
1
  import logging
2
  import requests
3
 
4
+ from typing import List, Optional
5
 
6
  from apps.rag.search.main import SearchResult, get_filtered_results
7
  from config import SRC_LOG_LEVELS
 
14
  query_url: str,
15
  query: str,
16
  count: int,
17
+ filter_list: Optional[List[str]] = None,
18
  **kwargs,
19
+ ) -> List[SearchResult]:
20
  """
21
  Search a SearXNG instance for a given query and return the results as a list of SearchResult objects.
22
 
 
31
  language (str): Language filter for the search results; e.g., "en-US". Defaults to an empty string.
32
  safesearch (int): Safe search filter for safer web results; 0 = off, 1 = moderate, 2 = strict. Defaults to 1 (moderate).
33
  time_range (str): Time range for filtering results by date; e.g., "2023-04-05..today" or "all-time". Defaults to ''.
34
+ categories: (Optional[List[str]]): Specific categories within which the search should be performed, defaulting to an empty string if not provided.
35
 
36
  Returns:
37
+ List[SearchResult]: A list of SearchResults sorted by relevance score in descending order.
38
 
39
  Raise:
40
  requests.exceptions.RequestException: If a request error occurs during the search process.
backend/apps/rag/search/serper.py CHANGED
@@ -1,6 +1,6 @@
1
  import json
2
  import logging
3
- from typing import Optional
4
  import requests
5
 
6
  from apps.rag.search.main import SearchResult, get_filtered_results
@@ -11,7 +11,7 @@ log.setLevel(SRC_LOG_LEVELS["RAG"])
11
 
12
 
13
  def search_serper(
14
- api_key: str, query: str, count: int, filter_list: Optional[list[str]] = None
15
  ) -> list[SearchResult]:
16
  """Search using serper.dev's API and return the results as a list of SearchResult objects.
17
 
 
1
  import json
2
  import logging
3
+ from typing import List, Optional
4
  import requests
5
 
6
  from apps.rag.search.main import SearchResult, get_filtered_results
 
11
 
12
 
13
  def search_serper(
14
+ api_key: str, query: str, count: int, filter_list: Optional[List[str]] = None
15
  ) -> list[SearchResult]:
16
  """Search using serper.dev's API and return the results as a list of SearchResult objects.
17
 
backend/apps/rag/search/serply.py CHANGED
@@ -1,6 +1,6 @@
1
  import json
2
  import logging
3
- from typing import Optional
4
  import requests
5
  from urllib.parse import urlencode
6
 
@@ -19,7 +19,7 @@ def search_serply(
19
  limit: int = 10,
20
  device_type: str = "desktop",
21
  proxy_location: str = "US",
22
- filter_list: Optional[list[str]] = None,
23
  ) -> list[SearchResult]:
24
  """Search using serper.dev's API and return the results as a list of SearchResult objects.
25
 
 
1
  import json
2
  import logging
3
+ from typing import List, Optional
4
  import requests
5
  from urllib.parse import urlencode
6
 
 
19
  limit: int = 10,
20
  device_type: str = "desktop",
21
  proxy_location: str = "US",
22
+ filter_list: Optional[List[str]] = None,
23
  ) -> list[SearchResult]:
24
  """Search using serper.dev's API and return the results as a list of SearchResult objects.
25
 
backend/apps/rag/search/serpstack.py CHANGED
@@ -1,6 +1,6 @@
1
  import json
2
  import logging
3
- from typing import Optional
4
  import requests
5
 
6
  from apps.rag.search.main import SearchResult, get_filtered_results
@@ -14,7 +14,7 @@ def search_serpstack(
14
  api_key: str,
15
  query: str,
16
  count: int,
17
- filter_list: Optional[list[str]] = None,
18
  https_enabled: bool = True,
19
  ) -> list[SearchResult]:
20
  """Search using serpstack.com's and return the results as a list of SearchResult objects.
 
1
  import json
2
  import logging
3
+ from typing import List, Optional
4
  import requests
5
 
6
  from apps.rag.search.main import SearchResult, get_filtered_results
 
14
  api_key: str,
15
  query: str,
16
  count: int,
17
+ filter_list: Optional[List[str]] = None,
18
  https_enabled: bool = True,
19
  ) -> list[SearchResult]:
20
  """Search using serpstack.com's and return the results as a list of SearchResult objects.
backend/apps/rag/search/tavily.py CHANGED
@@ -17,7 +17,7 @@ def search_tavily(api_key: str, query: str, count: int) -> list[SearchResult]:
17
  query (str): The query to search for
18
 
19
  Returns:
20
- list[SearchResult]: A list of search results
21
  """
22
  url = "https://api.tavily.com/search"
23
  data = {"query": query, "api_key": api_key}
 
17
  query (str): The query to search for
18
 
19
  Returns:
20
+ List[SearchResult]: A list of search results
21
  """
22
  url = "https://api.tavily.com/search"
23
  data = {"query": query, "api_key": api_key}
backend/apps/rag/utils.py CHANGED
@@ -2,7 +2,7 @@ import os
2
  import logging
3
  import requests
4
 
5
- from typing import Union
6
 
7
  from apps.ollama.main import (
8
  generate_ollama_embeddings,
@@ -142,7 +142,7 @@ def merge_and_sort_query_results(query_results, k, reverse=False):
142
 
143
 
144
  def query_collection(
145
- collection_names: list[str],
146
  query: str,
147
  embedding_function,
148
  k: int,
@@ -157,13 +157,13 @@ def query_collection(
157
  embedding_function=embedding_function,
158
  )
159
  results.append(result)
160
- except Exception:
161
  pass
162
  return merge_and_sort_query_results(results, k=k)
163
 
164
 
165
  def query_collection_with_hybrid_search(
166
- collection_names: list[str],
167
  query: str,
168
  embedding_function,
169
  k: int,
@@ -182,7 +182,7 @@ def query_collection_with_hybrid_search(
182
  r=r,
183
  )
184
  results.append(result)
185
- except Exception:
186
  pass
187
  return merge_and_sort_query_results(results, k=k, reverse=True)
188
 
@@ -411,7 +411,7 @@ class ChromaRetriever(BaseRetriever):
411
  query: str,
412
  *,
413
  run_manager: CallbackManagerForRetrieverRun,
414
- ) -> list[Document]:
415
  query_embeddings = self.embedding_function(query)
416
 
417
  results = self.collection.query(
 
2
  import logging
3
  import requests
4
 
5
+ from typing import List, Union
6
 
7
  from apps.ollama.main import (
8
  generate_ollama_embeddings,
 
142
 
143
 
144
  def query_collection(
145
+ collection_names: List[str],
146
  query: str,
147
  embedding_function,
148
  k: int,
 
157
  embedding_function=embedding_function,
158
  )
159
  results.append(result)
160
+ except:
161
  pass
162
  return merge_and_sort_query_results(results, k=k)
163
 
164
 
165
  def query_collection_with_hybrid_search(
166
+ collection_names: List[str],
167
  query: str,
168
  embedding_function,
169
  k: int,
 
182
  r=r,
183
  )
184
  results.append(result)
185
+ except:
186
  pass
187
  return merge_and_sort_query_results(results, k=k, reverse=True)
188
 
 
411
  query: str,
412
  *,
413
  run_manager: CallbackManagerForRetrieverRun,
414
+ ) -> List[Document]:
415
  query_embeddings = self.embedding_function(query)
416
 
417
  results = self.collection.query(
backend/apps/webui/models/auths.py CHANGED
@@ -140,7 +140,7 @@ class AuthsTable:
140
  return None
141
  else:
142
  return None
143
- except Exception:
144
  return None
145
 
146
  def authenticate_user_by_api_key(self, api_key: str) -> Optional[UserModel]:
@@ -152,7 +152,7 @@ class AuthsTable:
152
  try:
153
  user = Users.get_user_by_api_key(api_key)
154
  return user if user else None
155
- except Exception:
156
  return False
157
 
158
  def authenticate_user_by_trusted_header(self, email: str) -> Optional[UserModel]:
@@ -163,7 +163,7 @@ class AuthsTable:
163
  if auth:
164
  user = Users.get_user_by_id(auth.id)
165
  return user
166
- except Exception:
167
  return None
168
 
169
  def update_user_password_by_id(self, id: str, new_password: str) -> bool:
@@ -174,7 +174,7 @@ class AuthsTable:
174
  )
175
  db.commit()
176
  return True if result == 1 else False
177
- except Exception:
178
  return False
179
 
180
  def update_email_by_id(self, id: str, email: str) -> bool:
@@ -183,7 +183,7 @@ class AuthsTable:
183
  result = db.query(Auth).filter_by(id=id).update({"email": email})
184
  db.commit()
185
  return True if result == 1 else False
186
- except Exception:
187
  return False
188
 
189
  def delete_auth_by_id(self, id: str) -> bool:
@@ -200,7 +200,7 @@ class AuthsTable:
200
  return True
201
  else:
202
  return False
203
- except Exception:
204
  return False
205
 
206
 
 
140
  return None
141
  else:
142
  return None
143
+ except:
144
  return None
145
 
146
  def authenticate_user_by_api_key(self, api_key: str) -> Optional[UserModel]:
 
152
  try:
153
  user = Users.get_user_by_api_key(api_key)
154
  return user if user else None
155
+ except:
156
  return False
157
 
158
  def authenticate_user_by_trusted_header(self, email: str) -> Optional[UserModel]:
 
163
  if auth:
164
  user = Users.get_user_by_id(auth.id)
165
  return user
166
+ except:
167
  return None
168
 
169
  def update_user_password_by_id(self, id: str, new_password: str) -> bool:
 
174
  )
175
  db.commit()
176
  return True if result == 1 else False
177
+ except:
178
  return False
179
 
180
  def update_email_by_id(self, id: str, email: str) -> bool:
 
183
  result = db.query(Auth).filter_by(id=id).update({"email": email})
184
  db.commit()
185
  return True if result == 1 else False
186
+ except:
187
  return False
188
 
189
  def delete_auth_by_id(self, id: str) -> bool:
 
200
  return True
201
  else:
202
  return False
203
+ except:
204
  return False
205
 
206
 
backend/apps/webui/models/chats.py CHANGED
@@ -1,5 +1,5 @@
1
  from pydantic import BaseModel, ConfigDict
2
- from typing import Union, Optional
3
 
4
  import json
5
  import uuid
@@ -164,7 +164,7 @@ class ChatTable:
164
  db.refresh(chat)
165
 
166
  return self.get_chat_by_id(chat.share_id)
167
- except Exception:
168
  return None
169
 
170
  def delete_shared_chat_by_chat_id(self, chat_id: str) -> bool:
@@ -175,7 +175,7 @@ class ChatTable:
175
  db.commit()
176
 
177
  return True
178
- except Exception:
179
  return False
180
 
181
  def update_chat_share_id_by_id(
@@ -189,7 +189,7 @@ class ChatTable:
189
  db.commit()
190
  db.refresh(chat)
191
  return ChatModel.model_validate(chat)
192
- except Exception:
193
  return None
194
 
195
  def toggle_chat_archive_by_id(self, id: str) -> Optional[ChatModel]:
@@ -201,7 +201,7 @@ class ChatTable:
201
  db.commit()
202
  db.refresh(chat)
203
  return ChatModel.model_validate(chat)
204
- except Exception:
205
  return None
206
 
207
  def archive_all_chats_by_user_id(self, user_id: str) -> bool:
@@ -210,12 +210,12 @@ class ChatTable:
210
  db.query(Chat).filter_by(user_id=user_id).update({"archived": True})
211
  db.commit()
212
  return True
213
- except Exception:
214
  return False
215
 
216
  def get_archived_chat_list_by_user_id(
217
  self, user_id: str, skip: int = 0, limit: int = 50
218
- ) -> list[ChatModel]:
219
  with get_db() as db:
220
 
221
  all_chats = (
@@ -233,7 +233,7 @@ class ChatTable:
233
  include_archived: bool = False,
234
  skip: int = 0,
235
  limit: int = 50,
236
- ) -> list[ChatModel]:
237
  with get_db() as db:
238
  query = db.query(Chat).filter_by(user_id=user_id)
239
  if not include_archived:
@@ -251,7 +251,7 @@ class ChatTable:
251
  include_archived: bool = False,
252
  skip: int = 0,
253
  limit: int = -1,
254
- ) -> list[ChatTitleIdResponse]:
255
  with get_db() as db:
256
  query = db.query(Chat).filter_by(user_id=user_id)
257
  if not include_archived:
@@ -279,8 +279,8 @@ class ChatTable:
279
  ]
280
 
281
  def get_chat_list_by_chat_ids(
282
- self, chat_ids: list[str], skip: int = 0, limit: int = 50
283
- ) -> list[ChatModel]:
284
  with get_db() as db:
285
  all_chats = (
286
  db.query(Chat)
@@ -297,7 +297,7 @@ class ChatTable:
297
 
298
  chat = db.get(Chat, id)
299
  return ChatModel.model_validate(chat)
300
- except Exception:
301
  return None
302
 
303
  def get_chat_by_share_id(self, id: str) -> Optional[ChatModel]:
@@ -319,10 +319,10 @@ class ChatTable:
319
 
320
  chat = db.query(Chat).filter_by(id=id, user_id=user_id).first()
321
  return ChatModel.model_validate(chat)
322
- except Exception:
323
  return None
324
 
325
- def get_chats(self, skip: int = 0, limit: int = 50) -> list[ChatModel]:
326
  with get_db() as db:
327
 
328
  all_chats = (
@@ -332,7 +332,7 @@ class ChatTable:
332
  )
333
  return [ChatModel.model_validate(chat) for chat in all_chats]
334
 
335
- def get_chats_by_user_id(self, user_id: str) -> list[ChatModel]:
336
  with get_db() as db:
337
 
338
  all_chats = (
@@ -342,7 +342,7 @@ class ChatTable:
342
  )
343
  return [ChatModel.model_validate(chat) for chat in all_chats]
344
 
345
- def get_archived_chats_by_user_id(self, user_id: str) -> list[ChatModel]:
346
  with get_db() as db:
347
 
348
  all_chats = (
@@ -360,7 +360,7 @@ class ChatTable:
360
  db.commit()
361
 
362
  return True and self.delete_shared_chat_by_chat_id(id)
363
- except Exception:
364
  return False
365
 
366
  def delete_chat_by_id_and_user_id(self, id: str, user_id: str) -> bool:
@@ -371,7 +371,7 @@ class ChatTable:
371
  db.commit()
372
 
373
  return True and self.delete_shared_chat_by_chat_id(id)
374
- except Exception:
375
  return False
376
 
377
  def delete_chats_by_user_id(self, user_id: str) -> bool:
@@ -385,7 +385,7 @@ class ChatTable:
385
  db.commit()
386
 
387
  return True
388
- except Exception:
389
  return False
390
 
391
  def delete_shared_chats_by_user_id(self, user_id: str) -> bool:
@@ -400,7 +400,7 @@ class ChatTable:
400
  db.commit()
401
 
402
  return True
403
- except Exception:
404
  return False
405
 
406
 
 
1
  from pydantic import BaseModel, ConfigDict
2
+ from typing import List, Union, Optional
3
 
4
  import json
5
  import uuid
 
164
  db.refresh(chat)
165
 
166
  return self.get_chat_by_id(chat.share_id)
167
+ except:
168
  return None
169
 
170
  def delete_shared_chat_by_chat_id(self, chat_id: str) -> bool:
 
175
  db.commit()
176
 
177
  return True
178
+ except:
179
  return False
180
 
181
  def update_chat_share_id_by_id(
 
189
  db.commit()
190
  db.refresh(chat)
191
  return ChatModel.model_validate(chat)
192
+ except:
193
  return None
194
 
195
  def toggle_chat_archive_by_id(self, id: str) -> Optional[ChatModel]:
 
201
  db.commit()
202
  db.refresh(chat)
203
  return ChatModel.model_validate(chat)
204
+ except:
205
  return None
206
 
207
  def archive_all_chats_by_user_id(self, user_id: str) -> bool:
 
210
  db.query(Chat).filter_by(user_id=user_id).update({"archived": True})
211
  db.commit()
212
  return True
213
+ except:
214
  return False
215
 
216
  def get_archived_chat_list_by_user_id(
217
  self, user_id: str, skip: int = 0, limit: int = 50
218
+ ) -> List[ChatModel]:
219
  with get_db() as db:
220
 
221
  all_chats = (
 
233
  include_archived: bool = False,
234
  skip: int = 0,
235
  limit: int = 50,
236
+ ) -> List[ChatModel]:
237
  with get_db() as db:
238
  query = db.query(Chat).filter_by(user_id=user_id)
239
  if not include_archived:
 
251
  include_archived: bool = False,
252
  skip: int = 0,
253
  limit: int = -1,
254
+ ) -> List[ChatTitleIdResponse]:
255
  with get_db() as db:
256
  query = db.query(Chat).filter_by(user_id=user_id)
257
  if not include_archived:
 
279
  ]
280
 
281
  def get_chat_list_by_chat_ids(
282
+ self, chat_ids: List[str], skip: int = 0, limit: int = 50
283
+ ) -> List[ChatModel]:
284
  with get_db() as db:
285
  all_chats = (
286
  db.query(Chat)
 
297
 
298
  chat = db.get(Chat, id)
299
  return ChatModel.model_validate(chat)
300
+ except:
301
  return None
302
 
303
  def get_chat_by_share_id(self, id: str) -> Optional[ChatModel]:
 
319
 
320
  chat = db.query(Chat).filter_by(id=id, user_id=user_id).first()
321
  return ChatModel.model_validate(chat)
322
+ except:
323
  return None
324
 
325
+ def get_chats(self, skip: int = 0, limit: int = 50) -> List[ChatModel]:
326
  with get_db() as db:
327
 
328
  all_chats = (
 
332
  )
333
  return [ChatModel.model_validate(chat) for chat in all_chats]
334
 
335
+ def get_chats_by_user_id(self, user_id: str) -> List[ChatModel]:
336
  with get_db() as db:
337
 
338
  all_chats = (
 
342
  )
343
  return [ChatModel.model_validate(chat) for chat in all_chats]
344
 
345
+ def get_archived_chats_by_user_id(self, user_id: str) -> List[ChatModel]:
346
  with get_db() as db:
347
 
348
  all_chats = (
 
360
  db.commit()
361
 
362
  return True and self.delete_shared_chat_by_chat_id(id)
363
+ except:
364
  return False
365
 
366
  def delete_chat_by_id_and_user_id(self, id: str, user_id: str) -> bool:
 
371
  db.commit()
372
 
373
  return True and self.delete_shared_chat_by_chat_id(id)
374
+ except:
375
  return False
376
 
377
  def delete_chats_by_user_id(self, user_id: str) -> bool:
 
385
  db.commit()
386
 
387
  return True
388
+ except:
389
  return False
390
 
391
  def delete_shared_chats_by_user_id(self, user_id: str) -> bool:
 
400
  db.commit()
401
 
402
  return True
403
+ except:
404
  return False
405
 
406
 
backend/apps/webui/models/documents.py CHANGED
@@ -1,5 +1,5 @@
1
  from pydantic import BaseModel, ConfigDict
2
- from typing import Optional
3
  import time
4
  import logging
5
 
@@ -93,7 +93,7 @@ class DocumentsTable:
93
  return DocumentModel.model_validate(result)
94
  else:
95
  return None
96
- except Exception:
97
  return None
98
 
99
  def get_doc_by_name(self, name: str) -> Optional[DocumentModel]:
@@ -102,10 +102,10 @@ class DocumentsTable:
102
 
103
  document = db.query(Document).filter_by(name=name).first()
104
  return DocumentModel.model_validate(document) if document else None
105
- except Exception:
106
  return None
107
 
108
- def get_docs(self) -> list[DocumentModel]:
109
  with get_db() as db:
110
 
111
  return [
@@ -160,7 +160,7 @@ class DocumentsTable:
160
  db.query(Document).filter_by(name=name).delete()
161
  db.commit()
162
  return True
163
- except Exception:
164
  return False
165
 
166
 
 
1
  from pydantic import BaseModel, ConfigDict
2
+ from typing import List, Optional
3
  import time
4
  import logging
5
 
 
93
  return DocumentModel.model_validate(result)
94
  else:
95
  return None
96
+ except:
97
  return None
98
 
99
  def get_doc_by_name(self, name: str) -> Optional[DocumentModel]:
 
102
 
103
  document = db.query(Document).filter_by(name=name).first()
104
  return DocumentModel.model_validate(document) if document else None
105
+ except:
106
  return None
107
 
108
+ def get_docs(self) -> List[DocumentModel]:
109
  with get_db() as db:
110
 
111
  return [
 
160
  db.query(Document).filter_by(name=name).delete()
161
  db.commit()
162
  return True
163
+ except:
164
  return False
165
 
166
 
backend/apps/webui/models/files.py CHANGED
@@ -1,5 +1,5 @@
1
  from pydantic import BaseModel, ConfigDict
2
- from typing import Union, Optional
3
  import time
4
  import logging
5
 
@@ -90,10 +90,10 @@ class FilesTable:
90
  try:
91
  file = db.get(File, id)
92
  return FileModel.model_validate(file)
93
- except Exception:
94
  return None
95
 
96
- def get_files(self) -> list[FileModel]:
97
  with get_db() as db:
98
 
99
  return [FileModel.model_validate(file) for file in db.query(File).all()]
@@ -107,7 +107,7 @@ class FilesTable:
107
  db.commit()
108
 
109
  return True
110
- except Exception:
111
  return False
112
 
113
  def delete_all_files(self) -> bool:
@@ -119,7 +119,7 @@ class FilesTable:
119
  db.commit()
120
 
121
  return True
122
- except Exception:
123
  return False
124
 
125
 
 
1
  from pydantic import BaseModel, ConfigDict
2
+ from typing import List, Union, Optional
3
  import time
4
  import logging
5
 
 
90
  try:
91
  file = db.get(File, id)
92
  return FileModel.model_validate(file)
93
+ except:
94
  return None
95
 
96
+ def get_files(self) -> List[FileModel]:
97
  with get_db() as db:
98
 
99
  return [FileModel.model_validate(file) for file in db.query(File).all()]
 
107
  db.commit()
108
 
109
  return True
110
+ except:
111
  return False
112
 
113
  def delete_all_files(self) -> bool:
 
119
  db.commit()
120
 
121
  return True
122
+ except:
123
  return False
124
 
125
 
backend/apps/webui/models/functions.py CHANGED
@@ -1,5 +1,5 @@
1
  from pydantic import BaseModel, ConfigDict
2
- from typing import Union, Optional
3
  import time
4
  import logging
5
 
@@ -122,10 +122,10 @@ class FunctionsTable:
122
 
123
  function = db.get(Function, id)
124
  return FunctionModel.model_validate(function)
125
- except Exception:
126
  return None
127
 
128
- def get_functions(self, active_only=False) -> list[FunctionModel]:
129
  with get_db() as db:
130
 
131
  if active_only:
@@ -141,7 +141,7 @@ class FunctionsTable:
141
 
142
  def get_functions_by_type(
143
  self, type: str, active_only=False
144
- ) -> list[FunctionModel]:
145
  with get_db() as db:
146
 
147
  if active_only:
@@ -157,7 +157,7 @@ class FunctionsTable:
157
  for function in db.query(Function).filter_by(type=type).all()
158
  ]
159
 
160
- def get_global_filter_functions(self) -> list[FunctionModel]:
161
  with get_db() as db:
162
 
163
  return [
@@ -167,7 +167,7 @@ class FunctionsTable:
167
  .all()
168
  ]
169
 
170
- def get_global_action_functions(self) -> list[FunctionModel]:
171
  with get_db() as db:
172
  return [
173
  FunctionModel.model_validate(function)
@@ -198,7 +198,7 @@ class FunctionsTable:
198
  db.commit()
199
  db.refresh(function)
200
  return self.get_function_by_id(id)
201
- except Exception:
202
  return None
203
 
204
  def get_user_valves_by_id_and_user_id(
@@ -256,7 +256,7 @@ class FunctionsTable:
256
  )
257
  db.commit()
258
  return self.get_function_by_id(id)
259
- except Exception:
260
  return None
261
 
262
  def deactivate_all_functions(self) -> Optional[bool]:
@@ -271,7 +271,7 @@ class FunctionsTable:
271
  )
272
  db.commit()
273
  return True
274
- except Exception:
275
  return None
276
 
277
  def delete_function_by_id(self, id: str) -> bool:
@@ -281,7 +281,7 @@ class FunctionsTable:
281
  db.commit()
282
 
283
  return True
284
- except Exception:
285
  return False
286
 
287
 
 
1
  from pydantic import BaseModel, ConfigDict
2
+ from typing import List, Union, Optional
3
  import time
4
  import logging
5
 
 
122
 
123
  function = db.get(Function, id)
124
  return FunctionModel.model_validate(function)
125
+ except:
126
  return None
127
 
128
+ def get_functions(self, active_only=False) -> List[FunctionModel]:
129
  with get_db() as db:
130
 
131
  if active_only:
 
141
 
142
  def get_functions_by_type(
143
  self, type: str, active_only=False
144
+ ) -> List[FunctionModel]:
145
  with get_db() as db:
146
 
147
  if active_only:
 
157
  for function in db.query(Function).filter_by(type=type).all()
158
  ]
159
 
160
+ def get_global_filter_functions(self) -> List[FunctionModel]:
161
  with get_db() as db:
162
 
163
  return [
 
167
  .all()
168
  ]
169
 
170
+ def get_global_action_functions(self) -> List[FunctionModel]:
171
  with get_db() as db:
172
  return [
173
  FunctionModel.model_validate(function)
 
198
  db.commit()
199
  db.refresh(function)
200
  return self.get_function_by_id(id)
201
+ except:
202
  return None
203
 
204
  def get_user_valves_by_id_and_user_id(
 
256
  )
257
  db.commit()
258
  return self.get_function_by_id(id)
259
+ except:
260
  return None
261
 
262
  def deactivate_all_functions(self) -> Optional[bool]:
 
271
  )
272
  db.commit()
273
  return True
274
+ except:
275
  return None
276
 
277
  def delete_function_by_id(self, id: str) -> bool:
 
281
  db.commit()
282
 
283
  return True
284
+ except:
285
  return False
286
 
287
 
backend/apps/webui/models/memories.py CHANGED
@@ -1,5 +1,5 @@
1
  from pydantic import BaseModel, ConfigDict
2
- from typing import Union, Optional
3
 
4
  from sqlalchemy import Column, String, BigInteger, Text
5
 
@@ -80,25 +80,25 @@ class MemoriesTable:
80
  )
81
  db.commit()
82
  return self.get_memory_by_id(id)
83
- except Exception:
84
  return None
85
 
86
- def get_memories(self) -> list[MemoryModel]:
87
  with get_db() as db:
88
 
89
  try:
90
  memories = db.query(Memory).all()
91
  return [MemoryModel.model_validate(memory) for memory in memories]
92
- except Exception:
93
  return None
94
 
95
- def get_memories_by_user_id(self, user_id: str) -> list[MemoryModel]:
96
  with get_db() as db:
97
 
98
  try:
99
  memories = db.query(Memory).filter_by(user_id=user_id).all()
100
  return [MemoryModel.model_validate(memory) for memory in memories]
101
- except Exception:
102
  return None
103
 
104
  def get_memory_by_id(self, id: str) -> Optional[MemoryModel]:
@@ -107,7 +107,7 @@ class MemoriesTable:
107
  try:
108
  memory = db.get(Memory, id)
109
  return MemoryModel.model_validate(memory)
110
- except Exception:
111
  return None
112
 
113
  def delete_memory_by_id(self, id: str) -> bool:
@@ -119,7 +119,7 @@ class MemoriesTable:
119
 
120
  return True
121
 
122
- except Exception:
123
  return False
124
 
125
  def delete_memories_by_user_id(self, user_id: str) -> bool:
@@ -130,7 +130,7 @@ class MemoriesTable:
130
  db.commit()
131
 
132
  return True
133
- except Exception:
134
  return False
135
 
136
  def delete_memory_by_id_and_user_id(self, id: str, user_id: str) -> bool:
@@ -141,7 +141,7 @@ class MemoriesTable:
141
  db.commit()
142
 
143
  return True
144
- except Exception:
145
  return False
146
 
147
 
 
1
  from pydantic import BaseModel, ConfigDict
2
+ from typing import List, Union, Optional
3
 
4
  from sqlalchemy import Column, String, BigInteger, Text
5
 
 
80
  )
81
  db.commit()
82
  return self.get_memory_by_id(id)
83
+ except:
84
  return None
85
 
86
+ def get_memories(self) -> List[MemoryModel]:
87
  with get_db() as db:
88
 
89
  try:
90
  memories = db.query(Memory).all()
91
  return [MemoryModel.model_validate(memory) for memory in memories]
92
+ except:
93
  return None
94
 
95
+ def get_memories_by_user_id(self, user_id: str) -> List[MemoryModel]:
96
  with get_db() as db:
97
 
98
  try:
99
  memories = db.query(Memory).filter_by(user_id=user_id).all()
100
  return [MemoryModel.model_validate(memory) for memory in memories]
101
+ except:
102
  return None
103
 
104
  def get_memory_by_id(self, id: str) -> Optional[MemoryModel]:
 
107
  try:
108
  memory = db.get(Memory, id)
109
  return MemoryModel.model_validate(memory)
110
+ except:
111
  return None
112
 
113
  def delete_memory_by_id(self, id: str) -> bool:
 
119
 
120
  return True
121
 
122
+ except:
123
  return False
124
 
125
  def delete_memories_by_user_id(self, user_id: str) -> bool:
 
130
  db.commit()
131
 
132
  return True
133
+ except:
134
  return False
135
 
136
  def delete_memory_by_id_and_user_id(self, id: str, user_id: str) -> bool:
 
141
  db.commit()
142
 
143
  return True
144
+ except:
145
  return False
146
 
147
 
backend/apps/webui/models/models.py CHANGED
@@ -137,7 +137,7 @@ class ModelsTable:
137
  print(e)
138
  return None
139
 
140
- def get_all_models(self) -> list[ModelModel]:
141
  with get_db() as db:
142
  return [ModelModel.model_validate(model) for model in db.query(Model).all()]
143
 
@@ -146,7 +146,7 @@ class ModelsTable:
146
  with get_db() as db:
147
  model = db.get(Model, id)
148
  return ModelModel.model_validate(model)
149
- except Exception:
150
  return None
151
 
152
  def update_model_by_id(self, id: str, model: ModelForm) -> Optional[ModelModel]:
@@ -175,7 +175,7 @@ class ModelsTable:
175
  db.commit()
176
 
177
  return True
178
- except Exception:
179
  return False
180
 
181
 
 
137
  print(e)
138
  return None
139
 
140
+ def get_all_models(self) -> List[ModelModel]:
141
  with get_db() as db:
142
  return [ModelModel.model_validate(model) for model in db.query(Model).all()]
143
 
 
146
  with get_db() as db:
147
  model = db.get(Model, id)
148
  return ModelModel.model_validate(model)
149
+ except:
150
  return None
151
 
152
  def update_model_by_id(self, id: str, model: ModelForm) -> Optional[ModelModel]:
 
175
  db.commit()
176
 
177
  return True
178
+ except:
179
  return False
180
 
181
 
backend/apps/webui/models/prompts.py CHANGED
@@ -1,5 +1,5 @@
1
  from pydantic import BaseModel, ConfigDict
2
- from typing import Optional
3
  import time
4
 
5
  from sqlalchemy import String, Column, BigInteger, Text
@@ -79,10 +79,10 @@ class PromptsTable:
79
 
80
  prompt = db.query(Prompt).filter_by(command=command).first()
81
  return PromptModel.model_validate(prompt)
82
- except Exception:
83
  return None
84
 
85
- def get_prompts(self) -> list[PromptModel]:
86
  with get_db() as db:
87
 
88
  return [
@@ -101,7 +101,7 @@ class PromptsTable:
101
  prompt.timestamp = int(time.time())
102
  db.commit()
103
  return PromptModel.model_validate(prompt)
104
- except Exception:
105
  return None
106
 
107
  def delete_prompt_by_command(self, command: str) -> bool:
@@ -112,7 +112,7 @@ class PromptsTable:
112
  db.commit()
113
 
114
  return True
115
- except Exception:
116
  return False
117
 
118
 
 
1
  from pydantic import BaseModel, ConfigDict
2
+ from typing import List, Optional
3
  import time
4
 
5
  from sqlalchemy import String, Column, BigInteger, Text
 
79
 
80
  prompt = db.query(Prompt).filter_by(command=command).first()
81
  return PromptModel.model_validate(prompt)
82
+ except:
83
  return None
84
 
85
+ def get_prompts(self) -> List[PromptModel]:
86
  with get_db() as db:
87
 
88
  return [
 
101
  prompt.timestamp = int(time.time())
102
  db.commit()
103
  return PromptModel.model_validate(prompt)
104
+ except:
105
  return None
106
 
107
  def delete_prompt_by_command(self, command: str) -> bool:
 
112
  db.commit()
113
 
114
  return True
115
+ except:
116
  return False
117
 
118
 
backend/apps/webui/models/tags.py CHANGED
@@ -1,5 +1,5 @@
1
  from pydantic import BaseModel, ConfigDict
2
- from typing import Optional
3
 
4
  import json
5
  import uuid
@@ -69,11 +69,11 @@ class ChatIdTagForm(BaseModel):
69
 
70
 
71
  class TagChatIdsResponse(BaseModel):
72
- chat_ids: list[str]
73
 
74
 
75
  class ChatTagsResponse(BaseModel):
76
- tags: list[str]
77
 
78
 
79
  class TagTable:
@@ -109,7 +109,7 @@ class TagTable:
109
  self, user_id: str, form_data: ChatIdTagForm
110
  ) -> Optional[ChatIdTagModel]:
111
  tag = self.get_tag_by_name_and_user_id(form_data.tag_name, user_id)
112
- if tag is None:
113
  tag = self.insert_new_tag(form_data.tag_name, user_id)
114
 
115
  id = str(uuid.uuid4())
@@ -132,10 +132,10 @@ class TagTable:
132
  return ChatIdTagModel.model_validate(result)
133
  else:
134
  return None
135
- except Exception:
136
  return None
137
 
138
- def get_tags_by_user_id(self, user_id: str) -> list[TagModel]:
139
  with get_db() as db:
140
  tag_names = [
141
  chat_id_tag.tag_name
@@ -159,7 +159,7 @@ class TagTable:
159
 
160
  def get_tags_by_chat_id_and_user_id(
161
  self, chat_id: str, user_id: str
162
- ) -> list[TagModel]:
163
  with get_db() as db:
164
 
165
  tag_names = [
@@ -184,7 +184,7 @@ class TagTable:
184
 
185
  def get_chat_ids_by_tag_name_and_user_id(
186
  self, tag_name: str, user_id: str
187
- ) -> list[ChatIdTagModel]:
188
  with get_db() as db:
189
 
190
  return [
 
1
  from pydantic import BaseModel, ConfigDict
2
+ from typing import List, Optional
3
 
4
  import json
5
  import uuid
 
69
 
70
 
71
  class TagChatIdsResponse(BaseModel):
72
+ chat_ids: List[str]
73
 
74
 
75
  class ChatTagsResponse(BaseModel):
76
+ tags: List[str]
77
 
78
 
79
  class TagTable:
 
109
  self, user_id: str, form_data: ChatIdTagForm
110
  ) -> Optional[ChatIdTagModel]:
111
  tag = self.get_tag_by_name_and_user_id(form_data.tag_name, user_id)
112
+ if tag == None:
113
  tag = self.insert_new_tag(form_data.tag_name, user_id)
114
 
115
  id = str(uuid.uuid4())
 
132
  return ChatIdTagModel.model_validate(result)
133
  else:
134
  return None
135
+ except:
136
  return None
137
 
138
+ def get_tags_by_user_id(self, user_id: str) -> List[TagModel]:
139
  with get_db() as db:
140
  tag_names = [
141
  chat_id_tag.tag_name
 
159
 
160
  def get_tags_by_chat_id_and_user_id(
161
  self, chat_id: str, user_id: str
162
+ ) -> List[TagModel]:
163
  with get_db() as db:
164
 
165
  tag_names = [
 
184
 
185
  def get_chat_ids_by_tag_name_and_user_id(
186
  self, tag_name: str, user_id: str
187
+ ) -> List[ChatIdTagModel]:
188
  with get_db() as db:
189
 
190
  return [
backend/apps/webui/models/tools.py CHANGED
@@ -1,5 +1,5 @@
1
  from pydantic import BaseModel, ConfigDict
2
- from typing import Optional
3
  import time
4
  import logging
5
  from sqlalchemy import String, Column, BigInteger, Text
@@ -45,7 +45,7 @@ class ToolModel(BaseModel):
45
  user_id: str
46
  name: str
47
  content: str
48
- specs: list[dict]
49
  meta: ToolMeta
50
  updated_at: int # timestamp in epoch
51
  created_at: int # timestamp in epoch
@@ -81,7 +81,7 @@ class ToolValves(BaseModel):
81
  class ToolsTable:
82
 
83
  def insert_new_tool(
84
- self, user_id: str, form_data: ToolForm, specs: list[dict]
85
  ) -> Optional[ToolModel]:
86
 
87
  with get_db() as db:
@@ -115,10 +115,10 @@ class ToolsTable:
115
 
116
  tool = db.get(Tool, id)
117
  return ToolModel.model_validate(tool)
118
- except Exception:
119
  return None
120
 
121
- def get_tools(self) -> list[ToolModel]:
122
  with get_db() as db:
123
  return [ToolModel.model_validate(tool) for tool in db.query(Tool).all()]
124
 
@@ -141,7 +141,7 @@ class ToolsTable:
141
  )
142
  db.commit()
143
  return self.get_tool_by_id(id)
144
- except Exception:
145
  return None
146
 
147
  def get_user_valves_by_id_and_user_id(
@@ -196,7 +196,7 @@ class ToolsTable:
196
  tool = db.query(Tool).get(id)
197
  db.refresh(tool)
198
  return ToolModel.model_validate(tool)
199
- except Exception:
200
  return None
201
 
202
  def delete_tool_by_id(self, id: str) -> bool:
@@ -206,7 +206,7 @@ class ToolsTable:
206
  db.commit()
207
 
208
  return True
209
- except Exception:
210
  return False
211
 
212
 
 
1
  from pydantic import BaseModel, ConfigDict
2
+ from typing import List, Optional
3
  import time
4
  import logging
5
  from sqlalchemy import String, Column, BigInteger, Text
 
45
  user_id: str
46
  name: str
47
  content: str
48
+ specs: List[dict]
49
  meta: ToolMeta
50
  updated_at: int # timestamp in epoch
51
  created_at: int # timestamp in epoch
 
81
  class ToolsTable:
82
 
83
  def insert_new_tool(
84
+ self, user_id: str, form_data: ToolForm, specs: List[dict]
85
  ) -> Optional[ToolModel]:
86
 
87
  with get_db() as db:
 
115
 
116
  tool = db.get(Tool, id)
117
  return ToolModel.model_validate(tool)
118
+ except:
119
  return None
120
 
121
+ def get_tools(self) -> List[ToolModel]:
122
  with get_db() as db:
123
  return [ToolModel.model_validate(tool) for tool in db.query(Tool).all()]
124
 
 
141
  )
142
  db.commit()
143
  return self.get_tool_by_id(id)
144
+ except:
145
  return None
146
 
147
  def get_user_valves_by_id_and_user_id(
 
196
  tool = db.query(Tool).get(id)
197
  db.refresh(tool)
198
  return ToolModel.model_validate(tool)
199
+ except:
200
  return None
201
 
202
  def delete_tool_by_id(self, id: str) -> bool:
 
206
  db.commit()
207
 
208
  return True
209
+ except:
210
  return False
211
 
212
 
backend/apps/webui/models/users.py CHANGED
@@ -1,5 +1,5 @@
1
  from pydantic import BaseModel, ConfigDict, parse_obj_as
2
- from typing import Union, Optional
3
  import time
4
 
5
  from sqlalchemy import String, Column, BigInteger, Text
@@ -125,7 +125,7 @@ class UsersTable:
125
 
126
  user = db.query(User).filter_by(api_key=api_key).first()
127
  return UserModel.model_validate(user)
128
- except Exception:
129
  return None
130
 
131
  def get_user_by_email(self, email: str) -> Optional[UserModel]:
@@ -134,7 +134,7 @@ class UsersTable:
134
 
135
  user = db.query(User).filter_by(email=email).first()
136
  return UserModel.model_validate(user)
137
- except Exception:
138
  return None
139
 
140
  def get_user_by_oauth_sub(self, sub: str) -> Optional[UserModel]:
@@ -143,10 +143,10 @@ class UsersTable:
143
 
144
  user = db.query(User).filter_by(oauth_sub=sub).first()
145
  return UserModel.model_validate(user)
146
- except Exception:
147
  return None
148
 
149
- def get_users(self, skip: int = 0, limit: int = 50) -> list[UserModel]:
150
  with get_db() as db:
151
  users = (
152
  db.query(User)
@@ -164,7 +164,7 @@ class UsersTable:
164
  with get_db() as db:
165
  user = db.query(User).order_by(User.created_at).first()
166
  return UserModel.model_validate(user)
167
- except Exception:
168
  return None
169
 
170
  def update_user_role_by_id(self, id: str, role: str) -> Optional[UserModel]:
@@ -174,7 +174,7 @@ class UsersTable:
174
  db.commit()
175
  user = db.query(User).filter_by(id=id).first()
176
  return UserModel.model_validate(user)
177
- except Exception:
178
  return None
179
 
180
  def update_user_profile_image_url_by_id(
@@ -189,7 +189,7 @@ class UsersTable:
189
 
190
  user = db.query(User).filter_by(id=id).first()
191
  return UserModel.model_validate(user)
192
- except Exception:
193
  return None
194
 
195
  def update_user_last_active_by_id(self, id: str) -> Optional[UserModel]:
@@ -203,7 +203,7 @@ class UsersTable:
203
 
204
  user = db.query(User).filter_by(id=id).first()
205
  return UserModel.model_validate(user)
206
- except Exception:
207
  return None
208
 
209
  def update_user_oauth_sub_by_id(
@@ -216,7 +216,7 @@ class UsersTable:
216
 
217
  user = db.query(User).filter_by(id=id).first()
218
  return UserModel.model_validate(user)
219
- except Exception:
220
  return None
221
 
222
  def update_user_by_id(self, id: str, updated: dict) -> Optional[UserModel]:
@@ -245,7 +245,7 @@ class UsersTable:
245
  return True
246
  else:
247
  return False
248
- except Exception:
249
  return False
250
 
251
  def update_user_api_key_by_id(self, id: str, api_key: str) -> str:
@@ -254,7 +254,7 @@ class UsersTable:
254
  result = db.query(User).filter_by(id=id).update({"api_key": api_key})
255
  db.commit()
256
  return True if result == 1 else False
257
- except Exception:
258
  return False
259
 
260
  def get_user_api_key_by_id(self, id: str) -> Optional[str]:
 
1
  from pydantic import BaseModel, ConfigDict, parse_obj_as
2
+ from typing import List, Union, Optional
3
  import time
4
 
5
  from sqlalchemy import String, Column, BigInteger, Text
 
125
 
126
  user = db.query(User).filter_by(api_key=api_key).first()
127
  return UserModel.model_validate(user)
128
+ except:
129
  return None
130
 
131
  def get_user_by_email(self, email: str) -> Optional[UserModel]:
 
134
 
135
  user = db.query(User).filter_by(email=email).first()
136
  return UserModel.model_validate(user)
137
+ except:
138
  return None
139
 
140
  def get_user_by_oauth_sub(self, sub: str) -> Optional[UserModel]:
 
143
 
144
  user = db.query(User).filter_by(oauth_sub=sub).first()
145
  return UserModel.model_validate(user)
146
+ except:
147
  return None
148
 
149
+ def get_users(self, skip: int = 0, limit: int = 50) -> List[UserModel]:
150
  with get_db() as db:
151
  users = (
152
  db.query(User)
 
164
  with get_db() as db:
165
  user = db.query(User).order_by(User.created_at).first()
166
  return UserModel.model_validate(user)
167
+ except:
168
  return None
169
 
170
  def update_user_role_by_id(self, id: str, role: str) -> Optional[UserModel]:
 
174
  db.commit()
175
  user = db.query(User).filter_by(id=id).first()
176
  return UserModel.model_validate(user)
177
+ except:
178
  return None
179
 
180
  def update_user_profile_image_url_by_id(
 
189
 
190
  user = db.query(User).filter_by(id=id).first()
191
  return UserModel.model_validate(user)
192
+ except:
193
  return None
194
 
195
  def update_user_last_active_by_id(self, id: str) -> Optional[UserModel]:
 
203
 
204
  user = db.query(User).filter_by(id=id).first()
205
  return UserModel.model_validate(user)
206
+ except:
207
  return None
208
 
209
  def update_user_oauth_sub_by_id(
 
216
 
217
  user = db.query(User).filter_by(id=id).first()
218
  return UserModel.model_validate(user)
219
+ except:
220
  return None
221
 
222
  def update_user_by_id(self, id: str, updated: dict) -> Optional[UserModel]:
 
245
  return True
246
  else:
247
  return False
248
+ except:
249
  return False
250
 
251
  def update_user_api_key_by_id(self, id: str, api_key: str) -> str:
 
254
  result = db.query(User).filter_by(id=id).update({"api_key": api_key})
255
  db.commit()
256
  return True if result == 1 else False
257
+ except:
258
  return False
259
 
260
  def get_user_api_key_by_id(self, id: str) -> Optional[str]:
backend/apps/webui/routers/chats.py CHANGED
@@ -1,6 +1,6 @@
1
  from fastapi import Depends, Request, HTTPException, status
2
  from datetime import datetime, timedelta
3
- from typing import Union, Optional
4
  from utils.utils import get_verified_user, get_admin_user
5
  from fastapi import APIRouter
6
  from pydantic import BaseModel
@@ -40,8 +40,8 @@ router = APIRouter()
40
  ############################
41
 
42
 
43
- @router.get("/", response_model=list[ChatTitleIdResponse])
44
- @router.get("/list", response_model=list[ChatTitleIdResponse])
45
  async def get_session_user_chat_list(
46
  user=Depends(get_verified_user), page: Optional[int] = None
47
  ):
@@ -80,7 +80,7 @@ async def delete_all_user_chats(request: Request, user=Depends(get_verified_user
80
  ############################
81
 
82
 
83
- @router.get("/list/user/{user_id}", response_model=list[ChatTitleIdResponse])
84
  async def get_user_chat_list_by_user_id(
85
  user_id: str,
86
  user=Depends(get_admin_user),
@@ -119,7 +119,7 @@ async def create_new_chat(form_data: ChatForm, user=Depends(get_verified_user)):
119
  ############################
120
 
121
 
122
- @router.get("/all", response_model=list[ChatResponse])
123
  async def get_user_chats(user=Depends(get_verified_user)):
124
  return [
125
  ChatResponse(**{**chat.model_dump(), "chat": json.loads(chat.chat)})
@@ -132,7 +132,7 @@ async def get_user_chats(user=Depends(get_verified_user)):
132
  ############################
133
 
134
 
135
- @router.get("/all/archived", response_model=list[ChatResponse])
136
  async def get_user_archived_chats(user=Depends(get_verified_user)):
137
  return [
138
  ChatResponse(**{**chat.model_dump(), "chat": json.loads(chat.chat)})
@@ -145,7 +145,7 @@ async def get_user_archived_chats(user=Depends(get_verified_user)):
145
  ############################
146
 
147
 
148
- @router.get("/all/db", response_model=list[ChatResponse])
149
  async def get_all_user_chats_in_db(user=Depends(get_admin_user)):
150
  if not ENABLE_ADMIN_EXPORT:
151
  raise HTTPException(
@@ -163,7 +163,7 @@ async def get_all_user_chats_in_db(user=Depends(get_admin_user)):
163
  ############################
164
 
165
 
166
- @router.get("/archived", response_model=list[ChatTitleIdResponse])
167
  async def get_archived_session_user_chat_list(
168
  user=Depends(get_verified_user), skip: int = 0, limit: int = 50
169
  ):
@@ -216,7 +216,7 @@ class TagNameForm(BaseModel):
216
  limit: Optional[int] = 50
217
 
218
 
219
- @router.post("/tags", response_model=list[ChatTitleIdResponse])
220
  async def get_user_chat_list_by_tag_name(
221
  form_data: TagNameForm, user=Depends(get_verified_user)
222
  ):
@@ -241,7 +241,7 @@ async def get_user_chat_list_by_tag_name(
241
  ############################
242
 
243
 
244
- @router.get("/tags/all", response_model=list[TagModel])
245
  async def get_all_tags(user=Depends(get_verified_user)):
246
  try:
247
  tags = Tags.get_tags_by_user_id(user.id)
@@ -417,7 +417,7 @@ async def delete_shared_chat_by_id(id: str, user=Depends(get_verified_user)):
417
  ############################
418
 
419
 
420
- @router.get("/{id}/tags", response_model=list[TagModel])
421
  async def get_chat_tags_by_id(id: str, user=Depends(get_verified_user)):
422
  tags = Tags.get_tags_by_chat_id_and_user_id(id, user.id)
423
 
 
1
  from fastapi import Depends, Request, HTTPException, status
2
  from datetime import datetime, timedelta
3
+ from typing import List, Union, Optional
4
  from utils.utils import get_verified_user, get_admin_user
5
  from fastapi import APIRouter
6
  from pydantic import BaseModel
 
40
  ############################
41
 
42
 
43
+ @router.get("/", response_model=List[ChatTitleIdResponse])
44
+ @router.get("/list", response_model=List[ChatTitleIdResponse])
45
  async def get_session_user_chat_list(
46
  user=Depends(get_verified_user), page: Optional[int] = None
47
  ):
 
80
  ############################
81
 
82
 
83
+ @router.get("/list/user/{user_id}", response_model=List[ChatTitleIdResponse])
84
  async def get_user_chat_list_by_user_id(
85
  user_id: str,
86
  user=Depends(get_admin_user),
 
119
  ############################
120
 
121
 
122
+ @router.get("/all", response_model=List[ChatResponse])
123
  async def get_user_chats(user=Depends(get_verified_user)):
124
  return [
125
  ChatResponse(**{**chat.model_dump(), "chat": json.loads(chat.chat)})
 
132
  ############################
133
 
134
 
135
+ @router.get("/all/archived", response_model=List[ChatResponse])
136
  async def get_user_archived_chats(user=Depends(get_verified_user)):
137
  return [
138
  ChatResponse(**{**chat.model_dump(), "chat": json.loads(chat.chat)})
 
145
  ############################
146
 
147
 
148
+ @router.get("/all/db", response_model=List[ChatResponse])
149
  async def get_all_user_chats_in_db(user=Depends(get_admin_user)):
150
  if not ENABLE_ADMIN_EXPORT:
151
  raise HTTPException(
 
163
  ############################
164
 
165
 
166
+ @router.get("/archived", response_model=List[ChatTitleIdResponse])
167
  async def get_archived_session_user_chat_list(
168
  user=Depends(get_verified_user), skip: int = 0, limit: int = 50
169
  ):
 
216
  limit: Optional[int] = 50
217
 
218
 
219
+ @router.post("/tags", response_model=List[ChatTitleIdResponse])
220
  async def get_user_chat_list_by_tag_name(
221
  form_data: TagNameForm, user=Depends(get_verified_user)
222
  ):
 
241
  ############################
242
 
243
 
244
+ @router.get("/tags/all", response_model=List[TagModel])
245
  async def get_all_tags(user=Depends(get_verified_user)):
246
  try:
247
  tags = Tags.get_tags_by_user_id(user.id)
 
417
  ############################
418
 
419
 
420
+ @router.get("/{id}/tags", response_model=List[TagModel])
421
  async def get_chat_tags_by_id(id: str, user=Depends(get_verified_user)):
422
  tags = Tags.get_tags_by_chat_id_and_user_id(id, user.id)
423
 
backend/apps/webui/routers/configs.py CHANGED
@@ -1,7 +1,7 @@
1
  from fastapi import Response, Request
2
  from fastapi import Depends, FastAPI, HTTPException, status
3
  from datetime import datetime, timedelta
4
- from typing import Union
5
 
6
  from fastapi import APIRouter
7
  from pydantic import BaseModel
@@ -29,12 +29,12 @@ class SetDefaultModelsForm(BaseModel):
29
 
30
 
31
  class PromptSuggestion(BaseModel):
32
- title: list[str]
33
  content: str
34
 
35
 
36
  class SetDefaultSuggestionsForm(BaseModel):
37
- suggestions: list[PromptSuggestion]
38
 
39
 
40
  ############################
@@ -50,7 +50,7 @@ async def set_global_default_models(
50
  return request.app.state.config.DEFAULT_MODELS
51
 
52
 
53
- @router.post("/default/suggestions", response_model=list[PromptSuggestion])
54
  async def set_global_default_suggestions(
55
  request: Request,
56
  form_data: SetDefaultSuggestionsForm,
@@ -67,10 +67,10 @@ async def set_global_default_suggestions(
67
 
68
 
69
  class SetBannersForm(BaseModel):
70
- banners: list[BannerModel]
71
 
72
 
73
- @router.post("/banners", response_model=list[BannerModel])
74
  async def set_banners(
75
  request: Request,
76
  form_data: SetBannersForm,
@@ -81,7 +81,7 @@ async def set_banners(
81
  return request.app.state.config.BANNERS
82
 
83
 
84
- @router.get("/banners", response_model=list[BannerModel])
85
  async def get_banners(
86
  request: Request,
87
  user=Depends(get_verified_user),
 
1
  from fastapi import Response, Request
2
  from fastapi import Depends, FastAPI, HTTPException, status
3
  from datetime import datetime, timedelta
4
+ from typing import List, Union
5
 
6
  from fastapi import APIRouter
7
  from pydantic import BaseModel
 
29
 
30
 
31
  class PromptSuggestion(BaseModel):
32
+ title: List[str]
33
  content: str
34
 
35
 
36
  class SetDefaultSuggestionsForm(BaseModel):
37
+ suggestions: List[PromptSuggestion]
38
 
39
 
40
  ############################
 
50
  return request.app.state.config.DEFAULT_MODELS
51
 
52
 
53
+ @router.post("/default/suggestions", response_model=List[PromptSuggestion])
54
  async def set_global_default_suggestions(
55
  request: Request,
56
  form_data: SetDefaultSuggestionsForm,
 
67
 
68
 
69
  class SetBannersForm(BaseModel):
70
+ banners: List[BannerModel]
71
 
72
 
73
+ @router.post("/banners", response_model=List[BannerModel])
74
  async def set_banners(
75
  request: Request,
76
  form_data: SetBannersForm,
 
81
  return request.app.state.config.BANNERS
82
 
83
 
84
+ @router.get("/banners", response_model=List[BannerModel])
85
  async def get_banners(
86
  request: Request,
87
  user=Depends(get_verified_user),
backend/apps/webui/routers/documents.py CHANGED
@@ -1,6 +1,6 @@
1
  from fastapi import Depends, FastAPI, HTTPException, status
2
  from datetime import datetime, timedelta
3
- from typing import Union, Optional
4
 
5
  from fastapi import APIRouter
6
  from pydantic import BaseModel
@@ -24,7 +24,7 @@ router = APIRouter()
24
  ############################
25
 
26
 
27
- @router.get("/", response_model=list[DocumentResponse])
28
  async def get_documents(user=Depends(get_verified_user)):
29
  docs = [
30
  DocumentResponse(
@@ -46,7 +46,7 @@ async def get_documents(user=Depends(get_verified_user)):
46
  @router.post("/create", response_model=Optional[DocumentResponse])
47
  async def create_new_doc(form_data: DocumentForm, user=Depends(get_admin_user)):
48
  doc = Documents.get_doc_by_name(form_data.name)
49
- if doc is None:
50
  doc = Documents.insert_new_doc(user.id, form_data)
51
 
52
  if doc:
@@ -102,7 +102,7 @@ class TagItem(BaseModel):
102
 
103
  class TagDocumentForm(BaseModel):
104
  name: str
105
- tags: list[dict]
106
 
107
 
108
  @router.post("/doc/tags", response_model=Optional[DocumentResponse])
 
1
  from fastapi import Depends, FastAPI, HTTPException, status
2
  from datetime import datetime, timedelta
3
+ from typing import List, Union, Optional
4
 
5
  from fastapi import APIRouter
6
  from pydantic import BaseModel
 
24
  ############################
25
 
26
 
27
+ @router.get("/", response_model=List[DocumentResponse])
28
  async def get_documents(user=Depends(get_verified_user)):
29
  docs = [
30
  DocumentResponse(
 
46
  @router.post("/create", response_model=Optional[DocumentResponse])
47
  async def create_new_doc(form_data: DocumentForm, user=Depends(get_admin_user)):
48
  doc = Documents.get_doc_by_name(form_data.name)
49
+ if doc == None:
50
  doc = Documents.insert_new_doc(user.id, form_data)
51
 
52
  if doc:
 
102
 
103
  class TagDocumentForm(BaseModel):
104
  name: str
105
+ tags: List[dict]
106
 
107
 
108
  @router.post("/doc/tags", response_model=Optional[DocumentResponse])
backend/apps/webui/routers/files.py CHANGED
@@ -11,7 +11,7 @@ from fastapi import (
11
 
12
 
13
  from datetime import datetime, timedelta
14
- from typing import Union, Optional
15
  from pathlib import Path
16
 
17
  from fastapi import APIRouter
@@ -104,7 +104,7 @@ def upload_file(file: UploadFile = File(...), user=Depends(get_verified_user)):
104
  ############################
105
 
106
 
107
- @router.get("/", response_model=list[FileModel])
108
  async def list_files(user=Depends(get_verified_user)):
109
  files = Files.get_files()
110
  return files
 
11
 
12
 
13
  from datetime import datetime, timedelta
14
+ from typing import List, Union, Optional
15
  from pathlib import Path
16
 
17
  from fastapi import APIRouter
 
104
  ############################
105
 
106
 
107
+ @router.get("/", response_model=List[FileModel])
108
  async def list_files(user=Depends(get_verified_user)):
109
  files = Files.get_files()
110
  return files
backend/apps/webui/routers/functions.py CHANGED
@@ -1,6 +1,6 @@
1
  from fastapi import Depends, FastAPI, HTTPException, status, Request
2
  from datetime import datetime, timedelta
3
- from typing import Union, Optional
4
 
5
  from fastapi import APIRouter
6
  from pydantic import BaseModel
@@ -30,7 +30,7 @@ router = APIRouter()
30
  ############################
31
 
32
 
33
- @router.get("/", response_model=list[FunctionResponse])
34
  async def get_functions(user=Depends(get_verified_user)):
35
  return Functions.get_functions()
36
 
@@ -40,7 +40,7 @@ async def get_functions(user=Depends(get_verified_user)):
40
  ############################
41
 
42
 
43
- @router.get("/export", response_model=list[FunctionModel])
44
  async def get_functions(user=Depends(get_admin_user)):
45
  return Functions.get_functions()
46
 
@@ -63,7 +63,7 @@ async def create_new_function(
63
  form_data.id = form_data.id.lower()
64
 
65
  function = Functions.get_function_by_id(form_data.id)
66
- if function is None:
67
  function_path = os.path.join(FUNCTIONS_DIR, f"{form_data.id}.py")
68
  try:
69
  with open(function_path, "w") as function_file:
@@ -235,7 +235,7 @@ async def delete_function_by_id(
235
  function_path = os.path.join(FUNCTIONS_DIR, f"{id}.py")
236
  try:
237
  os.remove(function_path)
238
- except Exception:
239
  pass
240
 
241
  return result
 
1
  from fastapi import Depends, FastAPI, HTTPException, status, Request
2
  from datetime import datetime, timedelta
3
+ from typing import List, Union, Optional
4
 
5
  from fastapi import APIRouter
6
  from pydantic import BaseModel
 
30
  ############################
31
 
32
 
33
+ @router.get("/", response_model=List[FunctionResponse])
34
  async def get_functions(user=Depends(get_verified_user)):
35
  return Functions.get_functions()
36
 
 
40
  ############################
41
 
42
 
43
+ @router.get("/export", response_model=List[FunctionModel])
44
  async def get_functions(user=Depends(get_admin_user)):
45
  return Functions.get_functions()
46
 
 
63
  form_data.id = form_data.id.lower()
64
 
65
  function = Functions.get_function_by_id(form_data.id)
66
+ if function == None:
67
  function_path = os.path.join(FUNCTIONS_DIR, f"{form_data.id}.py")
68
  try:
69
  with open(function_path, "w") as function_file:
 
235
  function_path = os.path.join(FUNCTIONS_DIR, f"{id}.py")
236
  try:
237
  os.remove(function_path)
238
+ except:
239
  pass
240
 
241
  return result
backend/apps/webui/routers/memories.py CHANGED
@@ -1,7 +1,7 @@
1
  from fastapi import Response, Request
2
  from fastapi import Depends, FastAPI, HTTPException, status
3
  from datetime import datetime, timedelta
4
- from typing import Union, Optional
5
 
6
  from fastapi import APIRouter
7
  from pydantic import BaseModel
@@ -30,7 +30,7 @@ async def get_embeddings(request: Request):
30
  ############################
31
 
32
 
33
- @router.get("/", response_model=list[MemoryModel])
34
  async def get_memories(user=Depends(get_verified_user)):
35
  return Memories.get_memories_by_user_id(user.id)
36
 
 
1
  from fastapi import Response, Request
2
  from fastapi import Depends, FastAPI, HTTPException, status
3
  from datetime import datetime, timedelta
4
+ from typing import List, Union, Optional
5
 
6
  from fastapi import APIRouter
7
  from pydantic import BaseModel
 
30
  ############################
31
 
32
 
33
+ @router.get("/", response_model=List[MemoryModel])
34
  async def get_memories(user=Depends(get_verified_user)):
35
  return Memories.get_memories_by_user_id(user.id)
36
 
backend/apps/webui/routers/models.py CHANGED
@@ -1,6 +1,6 @@
1
  from fastapi import Depends, FastAPI, HTTPException, status, Request
2
  from datetime import datetime, timedelta
3
- from typing import Union, Optional
4
 
5
  from fastapi import APIRouter
6
  from pydantic import BaseModel
@@ -18,7 +18,7 @@ router = APIRouter()
18
  ###########################
19
 
20
 
21
- @router.get("/", response_model=list[ModelResponse])
22
  async def get_models(user=Depends(get_verified_user)):
23
  return Models.get_all_models()
24
 
 
1
  from fastapi import Depends, FastAPI, HTTPException, status, Request
2
  from datetime import datetime, timedelta
3
+ from typing import List, Union, Optional
4
 
5
  from fastapi import APIRouter
6
  from pydantic import BaseModel
 
18
  ###########################
19
 
20
 
21
+ @router.get("/", response_model=List[ModelResponse])
22
  async def get_models(user=Depends(get_verified_user)):
23
  return Models.get_all_models()
24
 
backend/apps/webui/routers/prompts.py CHANGED
@@ -1,6 +1,6 @@
1
  from fastapi import Depends, FastAPI, HTTPException, status
2
  from datetime import datetime, timedelta
3
- from typing import Union, Optional
4
 
5
  from fastapi import APIRouter
6
  from pydantic import BaseModel
@@ -18,7 +18,7 @@ router = APIRouter()
18
  ############################
19
 
20
 
21
- @router.get("/", response_model=list[PromptModel])
22
  async def get_prompts(user=Depends(get_verified_user)):
23
  return Prompts.get_prompts()
24
 
@@ -31,7 +31,7 @@ async def get_prompts(user=Depends(get_verified_user)):
31
  @router.post("/create", response_model=Optional[PromptModel])
32
  async def create_new_prompt(form_data: PromptForm, user=Depends(get_admin_user)):
33
  prompt = Prompts.get_prompt_by_command(form_data.command)
34
- if prompt is None:
35
  prompt = Prompts.insert_new_prompt(user.id, form_data)
36
 
37
  if prompt:
 
1
  from fastapi import Depends, FastAPI, HTTPException, status
2
  from datetime import datetime, timedelta
3
+ from typing import List, Union, Optional
4
 
5
  from fastapi import APIRouter
6
  from pydantic import BaseModel
 
18
  ############################
19
 
20
 
21
+ @router.get("/", response_model=List[PromptModel])
22
  async def get_prompts(user=Depends(get_verified_user)):
23
  return Prompts.get_prompts()
24
 
 
31
  @router.post("/create", response_model=Optional[PromptModel])
32
  async def create_new_prompt(form_data: PromptForm, user=Depends(get_admin_user)):
33
  prompt = Prompts.get_prompt_by_command(form_data.command)
34
+ if prompt == None:
35
  prompt = Prompts.insert_new_prompt(user.id, form_data)
36
 
37
  if prompt:
backend/apps/webui/routers/tools.py CHANGED
@@ -1,5 +1,5 @@
1
  from fastapi import Depends, HTTPException, status, Request
2
- from typing import Optional
3
 
4
  from fastapi import APIRouter
5
 
@@ -27,7 +27,7 @@ router = APIRouter()
27
  ############################
28
 
29
 
30
- @router.get("/", response_model=list[ToolResponse])
31
  async def get_toolkits(user=Depends(get_verified_user)):
32
  toolkits = [toolkit for toolkit in Tools.get_tools()]
33
  return toolkits
@@ -38,7 +38,7 @@ async def get_toolkits(user=Depends(get_verified_user)):
38
  ############################
39
 
40
 
41
- @router.get("/export", response_model=list[ToolModel])
42
  async def get_toolkits(user=Depends(get_admin_user)):
43
  toolkits = [toolkit for toolkit in Tools.get_tools()]
44
  return toolkits
 
1
  from fastapi import Depends, HTTPException, status, Request
2
+ from typing import List, Optional
3
 
4
  from fastapi import APIRouter
5
 
 
27
  ############################
28
 
29
 
30
+ @router.get("/", response_model=List[ToolResponse])
31
  async def get_toolkits(user=Depends(get_verified_user)):
32
  toolkits = [toolkit for toolkit in Tools.get_tools()]
33
  return toolkits
 
38
  ############################
39
 
40
 
41
+ @router.get("/export", response_model=List[ToolModel])
42
  async def get_toolkits(user=Depends(get_admin_user)):
43
  toolkits = [toolkit for toolkit in Tools.get_tools()]
44
  return toolkits
backend/apps/webui/routers/users.py CHANGED
@@ -1,7 +1,7 @@
1
  from fastapi import Response, Request
2
  from fastapi import Depends, FastAPI, HTTPException, status
3
  from datetime import datetime, timedelta
4
- from typing import Union, Optional
5
 
6
  from fastapi import APIRouter
7
  from pydantic import BaseModel
@@ -39,7 +39,7 @@ router = APIRouter()
39
  ############################
40
 
41
 
42
- @router.get("/", response_model=list[UserModel])
43
  async def get_users(skip: int = 0, limit: int = 50, user=Depends(get_admin_user)):
44
  return Users.get_users(skip, limit)
45
 
 
1
  from fastapi import Response, Request
2
  from fastapi import Depends, FastAPI, HTTPException, status
3
  from datetime import datetime, timedelta
4
+ from typing import List, Union, Optional
5
 
6
  from fastapi import APIRouter
7
  from pydantic import BaseModel
 
39
  ############################
40
 
41
 
42
+ @router.get("/", response_model=List[UserModel])
43
  async def get_users(skip: int = 0, limit: int = 50, user=Depends(get_admin_user)):
44
  return Users.get_users(skip, limit)
45
 
backend/apps/webui/routers/utils.py CHANGED
@@ -17,7 +17,7 @@ from utils.misc import calculate_sha256, get_gravatar_url
17
 
18
  from config import OLLAMA_BASE_URLS, DATA_DIR, UPLOAD_DIR, ENABLE_ADMIN_EXPORT
19
  from constants import ERROR_MESSAGES
20
-
21
 
22
  router = APIRouter()
23
 
@@ -57,7 +57,7 @@ async def get_html_from_markdown(
57
 
58
  class ChatForm(BaseModel):
59
  title: str
60
- messages: list[dict]
61
 
62
 
63
  @router.post("/pdf")
 
17
 
18
  from config import OLLAMA_BASE_URLS, DATA_DIR, UPLOAD_DIR, ENABLE_ADMIN_EXPORT
19
  from constants import ERROR_MESSAGES
20
+ from typing import List
21
 
22
  router = APIRouter()
23
 
 
57
 
58
  class ChatForm(BaseModel):
59
  title: str
60
+ messages: List[dict]
61
 
62
 
63
  @router.post("/pdf")
backend/apps/webui/utils.py CHANGED
@@ -1,8 +1,6 @@
1
  from importlib import util
2
  import os
3
  import re
4
- import sys
5
- import subprocess
6
 
7
  from config import TOOLS_DIR, FUNCTIONS_DIR
8
 
@@ -54,7 +52,6 @@ def load_toolkit_module_by_id(toolkit_id):
54
  frontmatter = extract_frontmatter(toolkit_path)
55
 
56
  try:
57
- install_frontmatter_requirements(frontmatter.get("requirements", ""))
58
  spec.loader.exec_module(module)
59
  print(f"Loaded module: {module.__name__}")
60
  if hasattr(module, "Tools"):
@@ -76,7 +73,6 @@ def load_function_module_by_id(function_id):
76
  frontmatter = extract_frontmatter(function_path)
77
 
78
  try:
79
- install_frontmatter_requirements(frontmatter.get("requirements", ""))
80
  spec.loader.exec_module(module)
81
  print(f"Loaded module: {module.__name__}")
82
  if hasattr(module, "Pipe"):
@@ -92,13 +88,3 @@ def load_function_module_by_id(function_id):
92
  # Move the file to the error folder
93
  os.rename(function_path, f"{function_path}.error")
94
  raise e
95
-
96
-
97
- def install_frontmatter_requirements(requirements):
98
- if requirements:
99
- req_list = [req.strip() for req in requirements.split(",")]
100
- for req in req_list:
101
- print(f"Installing requirement: {req}")
102
- subprocess.check_call([sys.executable, "-m", "pip", "install", req])
103
- else:
104
- print("No requirements found in frontmatter.")
 
1
  from importlib import util
2
  import os
3
  import re
 
 
4
 
5
  from config import TOOLS_DIR, FUNCTIONS_DIR
6
 
 
52
  frontmatter = extract_frontmatter(toolkit_path)
53
 
54
  try:
 
55
  spec.loader.exec_module(module)
56
  print(f"Loaded module: {module.__name__}")
57
  if hasattr(module, "Tools"):
 
73
  frontmatter = extract_frontmatter(function_path)
74
 
75
  try:
 
76
  spec.loader.exec_module(module)
77
  print(f"Loaded module: {module.__name__}")
78
  if hasattr(module, "Pipe"):
 
88
  # Move the file to the error folder
89
  os.rename(function_path, f"{function_path}.error")
90
  raise e
 
 
 
 
 
 
 
 
 
 
backend/config.py CHANGED
@@ -104,7 +104,7 @@ ENV = os.environ.get("ENV", "dev")
104
 
105
  try:
106
  PACKAGE_DATA = json.loads((BASE_DIR / "package.json").read_text())
107
- except Exception:
108
  try:
109
  PACKAGE_DATA = {"version": importlib.metadata.version("open-webui")}
110
  except importlib.metadata.PackageNotFoundError:
@@ -137,7 +137,7 @@ try:
137
  with open(str(changelog_path.absolute()), "r", encoding="utf8") as file:
138
  changelog_content = file.read()
139
 
140
- except Exception:
141
  changelog_content = (pkgutil.get_data("open_webui", "CHANGELOG.md") or b"").decode()
142
 
143
 
@@ -202,12 +202,12 @@ if RESET_CONFIG_ON_START:
202
  os.remove(f"{DATA_DIR}/config.json")
203
  with open(f"{DATA_DIR}/config.json", "w") as f:
204
  f.write("{}")
205
- except Exception:
206
  pass
207
 
208
  try:
209
  CONFIG_DATA = json.loads((DATA_DIR / "config.json").read_text())
210
- except Exception:
211
  CONFIG_DATA = {}
212
 
213
 
@@ -647,7 +647,7 @@ if AIOHTTP_CLIENT_TIMEOUT == "":
647
  else:
648
  try:
649
  AIOHTTP_CLIENT_TIMEOUT = int(AIOHTTP_CLIENT_TIMEOUT)
650
- except Exception:
651
  AIOHTTP_CLIENT_TIMEOUT = 300
652
 
653
 
@@ -727,7 +727,7 @@ try:
727
  OPENAI_API_KEY = OPENAI_API_KEYS.value[
728
  OPENAI_API_BASE_URLS.value.index("https://api.openai.com/v1")
729
  ]
730
- except Exception:
731
  pass
732
 
733
  OPENAI_API_BASE_URL = "https://api.openai.com/v1"
@@ -1043,7 +1043,7 @@ RAG_EMBEDDING_MODEL = PersistentConfig(
1043
  "rag.embedding_model",
1044
  os.environ.get("RAG_EMBEDDING_MODEL", "sentence-transformers/all-MiniLM-L6-v2"),
1045
  )
1046
- log.info(f"Embedding model set: {RAG_EMBEDDING_MODEL.value}")
1047
 
1048
  RAG_EMBEDDING_MODEL_AUTO_UPDATE = (
1049
  os.environ.get("RAG_EMBEDDING_MODEL_AUTO_UPDATE", "").lower() == "true"
@@ -1065,7 +1065,7 @@ RAG_RERANKING_MODEL = PersistentConfig(
1065
  os.environ.get("RAG_RERANKING_MODEL", ""),
1066
  )
1067
  if RAG_RERANKING_MODEL.value != "":
1068
- log.info(f"Reranking model set: {RAG_RERANKING_MODEL.value}")
1069
 
1070
  RAG_RERANKING_MODEL_AUTO_UPDATE = (
1071
  os.environ.get("RAG_RERANKING_MODEL_AUTO_UPDATE", "").lower() == "true"
 
104
 
105
  try:
106
  PACKAGE_DATA = json.loads((BASE_DIR / "package.json").read_text())
107
+ except:
108
  try:
109
  PACKAGE_DATA = {"version": importlib.metadata.version("open-webui")}
110
  except importlib.metadata.PackageNotFoundError:
 
137
  with open(str(changelog_path.absolute()), "r", encoding="utf8") as file:
138
  changelog_content = file.read()
139
 
140
+ except:
141
  changelog_content = (pkgutil.get_data("open_webui", "CHANGELOG.md") or b"").decode()
142
 
143
 
 
202
  os.remove(f"{DATA_DIR}/config.json")
203
  with open(f"{DATA_DIR}/config.json", "w") as f:
204
  f.write("{}")
205
+ except:
206
  pass
207
 
208
  try:
209
  CONFIG_DATA = json.loads((DATA_DIR / "config.json").read_text())
210
+ except:
211
  CONFIG_DATA = {}
212
 
213
 
 
647
  else:
648
  try:
649
  AIOHTTP_CLIENT_TIMEOUT = int(AIOHTTP_CLIENT_TIMEOUT)
650
+ except:
651
  AIOHTTP_CLIENT_TIMEOUT = 300
652
 
653
 
 
727
  OPENAI_API_KEY = OPENAI_API_KEYS.value[
728
  OPENAI_API_BASE_URLS.value.index("https://api.openai.com/v1")
729
  ]
730
+ except:
731
  pass
732
 
733
  OPENAI_API_BASE_URL = "https://api.openai.com/v1"
 
1043
  "rag.embedding_model",
1044
  os.environ.get("RAG_EMBEDDING_MODEL", "sentence-transformers/all-MiniLM-L6-v2"),
1045
  )
1046
+ log.info(f"Embedding model set: {RAG_EMBEDDING_MODEL.value}"),
1047
 
1048
  RAG_EMBEDDING_MODEL_AUTO_UPDATE = (
1049
  os.environ.get("RAG_EMBEDDING_MODEL_AUTO_UPDATE", "").lower() == "true"
 
1065
  os.environ.get("RAG_RERANKING_MODEL", ""),
1066
  )
1067
  if RAG_RERANKING_MODEL.value != "":
1068
+ log.info(f"Reranking model set: {RAG_RERANKING_MODEL.value}"),
1069
 
1070
  RAG_RERANKING_MODEL_AUTO_UPDATE = (
1071
  os.environ.get("RAG_RERANKING_MODEL_AUTO_UPDATE", "").lower() == "true"
backend/main.py CHANGED
@@ -51,7 +51,7 @@ from apps.webui.internal.db import Session
51
 
52
 
53
  from pydantic import BaseModel
54
- from typing import Optional
55
 
56
  from apps.webui.models.auths import Auths
57
  from apps.webui.models.models import Models
@@ -1883,7 +1883,7 @@ async def get_pipeline_valves(
1883
  res = r.json()
1884
  if "detail" in res:
1885
  detail = res["detail"]
1886
- except Exception:
1887
  pass
1888
 
1889
  raise HTTPException(
@@ -2027,7 +2027,7 @@ async def get_model_filter_config(user=Depends(get_admin_user)):
2027
 
2028
  class ModelFilterConfigForm(BaseModel):
2029
  enabled: bool
2030
- models: list[str]
2031
 
2032
 
2033
  @app.post("/api/config/model/filter")
 
51
 
52
 
53
  from pydantic import BaseModel
54
+ from typing import List, Optional
55
 
56
  from apps.webui.models.auths import Auths
57
  from apps.webui.models.models import Models
 
1883
  res = r.json()
1884
  if "detail" in res:
1885
  detail = res["detail"]
1886
+ except:
1887
  pass
1888
 
1889
  raise HTTPException(
 
2027
 
2028
  class ModelFilterConfigForm(BaseModel):
2029
  enabled: bool
2030
+ models: List[str]
2031
 
2032
 
2033
  @app.post("/api/config/model/filter")
backend/start.sh CHANGED
@@ -30,6 +30,7 @@ if [[ "${USE_CUDA_DOCKER,,}" == "true" ]]; then
30
  export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib/python3.11/site-packages/torch/lib:/usr/local/lib/python3.11/site-packages/nvidia/cudnn/lib"
31
  fi
32
 
 
33
  # Check if SPACE_ID is set, if so, configure for space
34
  if [ -n "$SPACE_ID" ]; then
35
  echo "Configuring for HuggingFace Space deployment"
 
30
  export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib/python3.11/site-packages/torch/lib:/usr/local/lib/python3.11/site-packages/nvidia/cudnn/lib"
31
  fi
32
 
33
+
34
  # Check if SPACE_ID is set, if so, configure for space
35
  if [ -n "$SPACE_ID" ]; then
36
  echo "Configuring for HuggingFace Space deployment"
backend/utils/misc.py CHANGED
@@ -2,14 +2,14 @@ from pathlib import Path
2
  import hashlib
3
  import re
4
  from datetime import timedelta
5
- from typing import Optional, Callable
6
  import uuid
7
  import time
8
 
9
  from utils.task import prompt_template
10
 
11
 
12
- def get_last_user_message_item(messages: list[dict]) -> Optional[dict]:
13
  for message in reversed(messages):
14
  if message["role"] == "user":
15
  return message
@@ -26,7 +26,7 @@ def get_content_from_message(message: dict) -> Optional[str]:
26
  return None
27
 
28
 
29
- def get_last_user_message(messages: list[dict]) -> Optional[str]:
30
  message = get_last_user_message_item(messages)
31
  if message is None:
32
  return None
@@ -34,31 +34,31 @@ def get_last_user_message(messages: list[dict]) -> Optional[str]:
34
  return get_content_from_message(message)
35
 
36
 
37
- def get_last_assistant_message(messages: list[dict]) -> Optional[str]:
38
  for message in reversed(messages):
39
  if message["role"] == "assistant":
40
  return get_content_from_message(message)
41
  return None
42
 
43
 
44
- def get_system_message(messages: list[dict]) -> Optional[dict]:
45
  for message in messages:
46
  if message["role"] == "system":
47
  return message
48
  return None
49
 
50
 
51
- def remove_system_message(messages: list[dict]) -> list[dict]:
52
  return [message for message in messages if message["role"] != "system"]
53
 
54
 
55
- def pop_system_message(messages: list[dict]) -> tuple[Optional[dict], list[dict]]:
56
  return get_system_message(messages), remove_system_message(messages)
57
 
58
 
59
  def prepend_to_first_user_message_content(
60
- content: str, messages: list[dict]
61
- ) -> list[dict]:
62
  for message in messages:
63
  if message["role"] == "user":
64
  if isinstance(message["content"], list):
@@ -71,7 +71,7 @@ def prepend_to_first_user_message_content(
71
  return messages
72
 
73
 
74
- def add_or_update_system_message(content: str, messages: list[dict]):
75
  """
76
  Adds a new system message at the beginning of the messages list
77
  or updates the existing system message at the beginning.
 
2
  import hashlib
3
  import re
4
  from datetime import timedelta
5
+ from typing import Optional, List, Tuple, Callable
6
  import uuid
7
  import time
8
 
9
  from utils.task import prompt_template
10
 
11
 
12
+ def get_last_user_message_item(messages: List[dict]) -> Optional[dict]:
13
  for message in reversed(messages):
14
  if message["role"] == "user":
15
  return message
 
26
  return None
27
 
28
 
29
+ def get_last_user_message(messages: List[dict]) -> Optional[str]:
30
  message = get_last_user_message_item(messages)
31
  if message is None:
32
  return None
 
34
  return get_content_from_message(message)
35
 
36
 
37
+ def get_last_assistant_message(messages: List[dict]) -> Optional[str]:
38
  for message in reversed(messages):
39
  if message["role"] == "assistant":
40
  return get_content_from_message(message)
41
  return None
42
 
43
 
44
+ def get_system_message(messages: List[dict]) -> Optional[dict]:
45
  for message in messages:
46
  if message["role"] == "system":
47
  return message
48
  return None
49
 
50
 
51
+ def remove_system_message(messages: List[dict]) -> List[dict]:
52
  return [message for message in messages if message["role"] != "system"]
53
 
54
 
55
+ def pop_system_message(messages: List[dict]) -> Tuple[Optional[dict], List[dict]]:
56
  return get_system_message(messages), remove_system_message(messages)
57
 
58
 
59
  def prepend_to_first_user_message_content(
60
+ content: str, messages: List[dict]
61
+ ) -> List[dict]:
62
  for message in messages:
63
  if message["role"] == "user":
64
  if isinstance(message["content"], list):
 
71
  return messages
72
 
73
 
74
+ def add_or_update_system_message(content: str, messages: List[dict]):
75
  """
76
  Adds a new system message at the beginning of the messages list
77
  or updates the existing system message at the beginning.
backend/utils/tools.py CHANGED
@@ -1,5 +1,5 @@
1
  import inspect
2
- from typing import get_type_hints
3
 
4
 
5
  def doc_to_dict(docstring):
@@ -16,7 +16,7 @@ def doc_to_dict(docstring):
16
  return ret_dict
17
 
18
 
19
- def get_tools_specs(tools) -> list[dict]:
20
  function_list = [
21
  {"name": func, "function": getattr(tools, func)}
22
  for func in dir(tools)
 
1
  import inspect
2
+ from typing import get_type_hints, List, Dict, Any
3
 
4
 
5
  def doc_to_dict(docstring):
 
16
  return ret_dict
17
 
18
 
19
+ def get_tools_specs(tools) -> List[dict]:
20
  function_list = [
21
  {"name": func, "function": getattr(tools, func)}
22
  for func in dir(tools)
package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
  {
2
  "name": "open-webui",
3
- "version": "0.3.13",
4
  "lockfileVersion": 3,
5
  "requires": true,
6
  "packages": {
7
  "": {
8
  "name": "open-webui",
9
- "version": "0.3.13",
10
  "dependencies": {
11
  "@codemirror/lang-javascript": "^6.2.2",
12
  "@codemirror/lang-python": "^6.1.6",
@@ -18,7 +18,6 @@
18
  "codemirror": "^6.0.1",
19
  "crc-32": "^1.2.2",
20
  "dayjs": "^1.11.10",
21
- "dompurify": "^3.1.6",
22
  "eventsource-parser": "^1.1.2",
23
  "file-saver": "^2.0.5",
24
  "fuse.js": "^7.0.0",
@@ -3919,9 +3918,9 @@
3919
  }
3920
  },
3921
  "node_modules/dompurify": {
3922
- "version": "3.1.6",
3923
- "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.6.tgz",
3924
- "integrity": "sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ=="
3925
  },
3926
  "node_modules/domutils": {
3927
  "version": "3.1.0",
 
1
  {
2
  "name": "open-webui",
3
+ "version": "0.3.12",
4
  "lockfileVersion": 3,
5
  "requires": true,
6
  "packages": {
7
  "": {
8
  "name": "open-webui",
9
+ "version": "0.3.12",
10
  "dependencies": {
11
  "@codemirror/lang-javascript": "^6.2.2",
12
  "@codemirror/lang-python": "^6.1.6",
 
18
  "codemirror": "^6.0.1",
19
  "crc-32": "^1.2.2",
20
  "dayjs": "^1.11.10",
 
21
  "eventsource-parser": "^1.1.2",
22
  "file-saver": "^2.0.5",
23
  "fuse.js": "^7.0.0",
 
3918
  }
3919
  },
3920
  "node_modules/dompurify": {
3921
+ "version": "3.1.5",
3922
+ "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.5.tgz",
3923
+ "integrity": "sha512-lwG+n5h8QNpxtyrJW/gJWckL+1/DQiYMX8f7t8Z2AZTPw1esVrqjI63i7Zc2Gz0aKzLVMYC1V1PL/ky+aY/NgA=="
3924
  },
3925
  "node_modules/domutils": {
3926
  "version": "3.1.0",
package.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "name": "open-webui",
3
- "version": "0.3.13",
4
  "private": true,
5
  "scripts": {
6
  "dev": "npm run pyodide:fetch && vite dev --host",
@@ -59,7 +59,6 @@
59
  "codemirror": "^6.0.1",
60
  "crc-32": "^1.2.2",
61
  "dayjs": "^1.11.10",
62
- "dompurify": "^3.1.6",
63
  "eventsource-parser": "^1.1.2",
64
  "file-saver": "^2.0.5",
65
  "fuse.js": "^7.0.0",
 
1
  {
2
  "name": "open-webui",
3
+ "version": "0.3.12",
4
  "private": true,
5
  "scripts": {
6
  "dev": "npm run pyodide:fetch && vite dev --host",
 
59
  "codemirror": "^6.0.1",
60
  "crc-32": "^1.2.2",
61
  "dayjs": "^1.11.10",
 
62
  "eventsource-parser": "^1.1.2",
63
  "file-saver": "^2.0.5",
64
  "fuse.js": "^7.0.0",
pyproject.toml CHANGED
@@ -1,6 +1,6 @@
1
  [project]
2
  name = "open-webui"
3
- description = "Open WebUI"
4
  authors = [
5
  { name = "Timothy Jaeryang Baek", email = "[email protected]" }
6
  ]
@@ -41,12 +41,12 @@ dependencies = [
41
  "google-generativeai==0.7.2",
42
  "tiktoken",
43
 
44
- "langchain==0.2.12",
45
  "langchain-community==0.2.10",
46
  "langchain-chroma==0.1.2",
47
 
48
  "fake-useragent==1.5.1",
49
- "chromadb==0.5.5",
50
  "sentence-transformers==3.0.1",
51
  "pypdf==4.3.1",
52
  "docx2txt==0.8",
@@ -69,11 +69,11 @@ dependencies = [
69
 
70
  "faster-whisper==1.0.2",
71
 
72
- "PyJWT[crypto]==2.9.0",
73
  "authlib==1.3.1",
74
 
75
  "black==24.8.0",
76
- "langfuse==2.43.3",
77
  "youtube-transcript-api==0.6.2",
78
  "pytube==15.0.0",
79
 
 
1
  [project]
2
  name = "open-webui"
3
+ description = "Open WebUI (Formerly Ollama WebUI)"
4
  authors = [
5
  { name = "Timothy Jaeryang Baek", email = "[email protected]" }
6
  ]
 
41
  "google-generativeai==0.7.2",
42
  "tiktoken",
43
 
44
+ "langchain==0.2.11",
45
  "langchain-community==0.2.10",
46
  "langchain-chroma==0.1.2",
47
 
48
  "fake-useragent==1.5.1",
49
+ "chromadb==0.5.4",
50
  "sentence-transformers==3.0.1",
51
  "pypdf==4.3.1",
52
  "docx2txt==0.8",
 
69
 
70
  "faster-whisper==1.0.2",
71
 
72
+ "PyJWT[crypto]==2.8.0",
73
  "authlib==1.3.1",
74
 
75
  "black==24.8.0",
76
+ "langfuse==2.39.2",
77
  "youtube-transcript-api==0.6.2",
78
  "pytube==15.0.0",
79
 
requirements-dev.lock CHANGED
@@ -10,9 +10,7 @@
10
  # universal: false
11
 
12
  -e file:.
13
- aiohappyeyeballs==2.3.5
14
- # via aiohttp
15
- aiohttp==3.10.2
16
  # via langchain
17
  # via langchain-community
18
  # via open-webui
@@ -86,9 +84,9 @@ chardet==5.2.0
86
  charset-normalizer==3.3.2
87
  # via requests
88
  # via unstructured-client
89
- chroma-hnswlib==0.7.6
90
  # via chromadb
91
- chromadb==0.5.5
92
  # via langchain-chroma
93
  # via open-webui
94
  click==8.1.7
@@ -271,7 +269,7 @@ jsonpointer==2.4
271
  # via jsonpatch
272
  kubernetes==29.0.0
273
  # via chromadb
274
- langchain==0.2.12
275
  # via langchain-community
276
  # via open-webui
277
  langchain-chroma==0.1.2
@@ -287,7 +285,7 @@ langchain-text-splitters==0.2.0
287
  # via langchain
288
  langdetect==1.0.9
289
  # via unstructured
290
- langfuse==2.43.3
291
  # via open-webui
292
  langsmith==0.1.96
293
  # via langchain
@@ -493,7 +491,7 @@ pydub==0.25.1
493
  # via open-webui
494
  pygments==2.18.0
495
  # via rich
496
- pyjwt==2.9.0
497
  # via open-webui
498
  pymongo==4.8.0
499
  # via open-webui
 
10
  # universal: false
11
 
12
  -e file:.
13
+ aiohttp==3.9.5
 
 
14
  # via langchain
15
  # via langchain-community
16
  # via open-webui
 
84
  charset-normalizer==3.3.2
85
  # via requests
86
  # via unstructured-client
87
+ chroma-hnswlib==0.7.5
88
  # via chromadb
89
+ chromadb==0.5.4
90
  # via langchain-chroma
91
  # via open-webui
92
  click==8.1.7
 
269
  # via jsonpatch
270
  kubernetes==29.0.0
271
  # via chromadb
272
+ langchain==0.2.11
273
  # via langchain-community
274
  # via open-webui
275
  langchain-chroma==0.1.2
 
285
  # via langchain
286
  langdetect==1.0.9
287
  # via unstructured
288
+ langfuse==2.39.2
289
  # via open-webui
290
  langsmith==0.1.96
291
  # via langchain
 
491
  # via open-webui
492
  pygments==2.18.0
493
  # via rich
494
+ pyjwt==2.8.0
495
  # via open-webui
496
  pymongo==4.8.0
497
  # via open-webui
requirements.lock CHANGED
@@ -10,9 +10,7 @@
10
  # universal: false
11
 
12
  -e file:.
13
- aiohappyeyeballs==2.3.5
14
- # via aiohttp
15
- aiohttp==3.10.2
16
  # via langchain
17
  # via langchain-community
18
  # via open-webui
@@ -86,9 +84,9 @@ chardet==5.2.0
86
  charset-normalizer==3.3.2
87
  # via requests
88
  # via unstructured-client
89
- chroma-hnswlib==0.7.6
90
  # via chromadb
91
- chromadb==0.5.5
92
  # via langchain-chroma
93
  # via open-webui
94
  click==8.1.7
@@ -271,7 +269,7 @@ jsonpointer==2.4
271
  # via jsonpatch
272
  kubernetes==29.0.0
273
  # via chromadb
274
- langchain==0.2.12
275
  # via langchain-community
276
  # via open-webui
277
  langchain-chroma==0.1.2
@@ -287,7 +285,7 @@ langchain-text-splitters==0.2.0
287
  # via langchain
288
  langdetect==1.0.9
289
  # via unstructured
290
- langfuse==2.43.3
291
  # via open-webui
292
  langsmith==0.1.96
293
  # via langchain
@@ -493,7 +491,7 @@ pydub==0.25.1
493
  # via open-webui
494
  pygments==2.18.0
495
  # via rich
496
- pyjwt==2.9.0
497
  # via open-webui
498
  pymongo==4.8.0
499
  # via open-webui
 
10
  # universal: false
11
 
12
  -e file:.
13
+ aiohttp==3.9.5
 
 
14
  # via langchain
15
  # via langchain-community
16
  # via open-webui
 
84
  charset-normalizer==3.3.2
85
  # via requests
86
  # via unstructured-client
87
+ chroma-hnswlib==0.7.5
88
  # via chromadb
89
+ chromadb==0.5.4
90
  # via langchain-chroma
91
  # via open-webui
92
  click==8.1.7
 
269
  # via jsonpatch
270
  kubernetes==29.0.0
271
  # via chromadb
272
+ langchain==0.2.11
273
  # via langchain-community
274
  # via open-webui
275
  langchain-chroma==0.1.2
 
285
  # via langchain
286
  langdetect==1.0.9
287
  # via unstructured
288
+ langfuse==2.39.2
289
  # via open-webui
290
  langsmith==0.1.96
291
  # via langchain
 
491
  # via open-webui
492
  pygments==2.18.0
493
  # via rich
494
+ pyjwt==2.8.0
495
  # via open-webui
496
  pymongo==4.8.0
497
  # via open-webui