Spaces:
Paused
Paused
github-actions[bot]
commited on
Commit
·
e639365
1
Parent(s):
775fb16
GitHub deploy: 30c44d431b007c78c9d283a27fdb171e071ea780
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- CHANGELOG.md +0 -27
- backend/apps/audio/main.py +7 -7
- backend/apps/images/main.py +4 -4
- backend/apps/images/utils/comfyui.py +2 -2
- backend/apps/ollama/main.py +6 -6
- backend/apps/openai/main.py +3 -3
- backend/apps/rag/main.py +9 -9
- backend/apps/rag/search/brave.py +2 -2
- backend/apps/rag/search/duckduckgo.py +3 -3
- backend/apps/rag/search/google_pse.py +2 -2
- backend/apps/rag/search/jina_search.py +1 -1
- backend/apps/rag/search/searxng.py +5 -5
- backend/apps/rag/search/serper.py +2 -2
- backend/apps/rag/search/serply.py +2 -2
- backend/apps/rag/search/serpstack.py +2 -2
- backend/apps/rag/search/tavily.py +1 -1
- backend/apps/rag/utils.py +6 -6
- backend/apps/webui/models/auths.py +6 -6
- backend/apps/webui/models/chats.py +20 -20
- backend/apps/webui/models/documents.py +5 -5
- backend/apps/webui/models/files.py +5 -5
- backend/apps/webui/models/functions.py +10 -10
- backend/apps/webui/models/memories.py +10 -10
- backend/apps/webui/models/models.py +3 -3
- backend/apps/webui/models/prompts.py +5 -5
- backend/apps/webui/models/tags.py +8 -8
- backend/apps/webui/models/tools.py +8 -8
- backend/apps/webui/models/users.py +12 -12
- backend/apps/webui/routers/chats.py +11 -11
- backend/apps/webui/routers/configs.py +7 -7
- backend/apps/webui/routers/documents.py +4 -4
- backend/apps/webui/routers/files.py +2 -2
- backend/apps/webui/routers/functions.py +5 -5
- backend/apps/webui/routers/memories.py +2 -2
- backend/apps/webui/routers/models.py +2 -2
- backend/apps/webui/routers/prompts.py +3 -3
- backend/apps/webui/routers/tools.py +3 -3
- backend/apps/webui/routers/users.py +2 -2
- backend/apps/webui/routers/utils.py +2 -2
- backend/apps/webui/utils.py +0 -14
- backend/config.py +8 -8
- backend/main.py +3 -3
- backend/start.sh +1 -0
- backend/utils/misc.py +10 -10
- backend/utils/tools.py +2 -2
- package-lock.json +5 -6
- package.json +1 -2
- pyproject.toml +5 -5
- requirements-dev.lock +6 -8
- 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
|
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
|
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
|
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
|
425 |
error_detail = f"External: {e}"
|
426 |
|
427 |
raise HTTPException(
|
@@ -438,7 +438,7 @@ def transcribe(
|
|
438 |
)
|
439 |
|
440 |
|
441 |
-
def get_available_models() ->
|
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() ->
|
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
|
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
|
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
|
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
|
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.
|
174 |
},
|
175 |
"class_type": "VAELoader"
|
176 |
},
|
@@ -184,7 +184,7 @@ FLUX_DEFAULT_PROMPT = """
|
|
184 |
},
|
185 |
"12": {
|
186 |
"inputs": {
|
187 |
-
"unet_name": "flux1-dev.
|
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:
|
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[
|
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[
|
693 |
|
694 |
|
695 |
class GenerateChatCompletionForm(BaseModel):
|
696 |
model: str
|
697 |
-
messages:
|
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:
|
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:
|
93 |
|
94 |
|
95 |
class KeysUpdateForm(BaseModel):
|
96 |
-
keys:
|
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:
|
443 |
translation: Optional[str] = None
|
444 |
|
445 |
|
@@ -642,7 +642,7 @@ def query_doc_handler(
|
|
642 |
|
643 |
|
644 |
class QueryCollectionsForm(BaseModel):
|
645 |
-
collection_names:
|
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) ->
|
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
|
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
|
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
|
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
|
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[
|
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[
|
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 |
-
|
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[
|
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 |
-
|
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[
|
18 |
**kwargs,
|
19 |
-
) ->
|
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[
|
35 |
|
36 |
Returns:
|
37 |
-
|
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[
|
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[
|
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[
|
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 |
-
|
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:
|
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
|
161 |
pass
|
162 |
return merge_and_sort_query_results(results, k=k)
|
163 |
|
164 |
|
165 |
def query_collection_with_hybrid_search(
|
166 |
-
collection_names:
|
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
|
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 |
-
) ->
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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 |
-
) ->
|
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 |
-
) ->
|
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 |
-
) ->
|
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:
|
283 |
-
) ->
|
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
|
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
|
323 |
return None
|
324 |
|
325 |
-
def get_chats(self, skip: int = 0, limit: int = 50) ->
|
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) ->
|
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) ->
|
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
|
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
|
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
|
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
|
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
|
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
|
106 |
return None
|
107 |
|
108 |
-
def get_docs(self) ->
|
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
|
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
|
94 |
return None
|
95 |
|
96 |
-
def get_files(self) ->
|
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
|
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
|
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
|
126 |
return None
|
127 |
|
128 |
-
def get_functions(self, active_only=False) ->
|
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 |
-
) ->
|
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) ->
|
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) ->
|
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
|
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
|
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
|
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
|
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
|
84 |
return None
|
85 |
|
86 |
-
def get_memories(self) ->
|
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) ->
|
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,7 +107,7 @@ class MemoriesTable:
|
|
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,7 +119,7 @@ class MemoriesTable:
|
|
119 |
|
120 |
return True
|
121 |
|
122 |
-
except
|
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
|
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
|
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) ->
|
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
|
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
|
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
|
83 |
return None
|
84 |
|
85 |
-
def get_prompts(self) ->
|
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
|
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
|
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:
|
73 |
|
74 |
|
75 |
class ChatTagsResponse(BaseModel):
|
76 |
-
tags:
|
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
|
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
|
136 |
return None
|
137 |
|
138 |
-
def get_tags_by_user_id(self, user_id: str) ->
|
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 |
-
) ->
|
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 |
-
) ->
|
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:
|
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:
|
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
|
119 |
return None
|
120 |
|
121 |
-
def get_tools(self) ->
|
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
|
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
|
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
|
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
|
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
|
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
|
147 |
return None
|
148 |
|
149 |
-
def get_users(self, skip: int = 0, limit: int = 50) ->
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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=
|
44 |
-
@router.get("/list", response_model=
|
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=
|
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=
|
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=
|
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=
|
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=
|
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=
|
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=
|
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=
|
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:
|
33 |
content: str
|
34 |
|
35 |
|
36 |
class SetDefaultSuggestionsForm(BaseModel):
|
37 |
-
suggestions:
|
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=
|
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:
|
71 |
|
72 |
|
73 |
-
@router.post("/banners", response_model=
|
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=
|
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=
|
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
|
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:
|
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=
|
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=
|
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=
|
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
|
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
|
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=
|
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=
|
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=
|
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
|
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=
|
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=
|
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=
|
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:
|
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
|
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
|
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
|
206 |
pass
|
207 |
|
208 |
try:
|
209 |
CONFIG_DATA = json.loads((DATA_DIR / "config.json").read_text())
|
210 |
-
except
|
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
|
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
|
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
|
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:
|
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:
|
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:
|
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:
|
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:
|
45 |
for message in messages:
|
46 |
if message["role"] == "system":
|
47 |
return message
|
48 |
return None
|
49 |
|
50 |
|
51 |
-
def remove_system_message(messages:
|
52 |
return [message for message in messages if message["role"] != "system"]
|
53 |
|
54 |
|
55 |
-
def pop_system_message(messages:
|
56 |
return get_system_message(messages), remove_system_message(messages)
|
57 |
|
58 |
|
59 |
def prepend_to_first_user_message_content(
|
60 |
-
content: str, messages:
|
61 |
-
) ->
|
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:
|
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) ->
|
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.
|
4 |
"lockfileVersion": 3,
|
5 |
"requires": true,
|
6 |
"packages": {
|
7 |
"": {
|
8 |
"name": "open-webui",
|
9 |
-
"version": "0.3.
|
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.
|
3923 |
-
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.
|
3924 |
-
"integrity": "sha512-
|
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.
|
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.
|
45 |
"langchain-community==0.2.10",
|
46 |
"langchain-chroma==0.1.2",
|
47 |
|
48 |
"fake-useragent==1.5.1",
|
49 |
-
"chromadb==0.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.
|
73 |
"authlib==1.3.1",
|
74 |
|
75 |
"black==24.8.0",
|
76 |
-
"langfuse==2.
|
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 |
-
|
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.
|
90 |
# via chromadb
|
91 |
-
chromadb==0.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.
|
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.
|
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.
|
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 |
-
|
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.
|
90 |
# via chromadb
|
91 |
-
chromadb==0.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.
|
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.
|
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.
|
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
|