mirror of
https://github.com/open-webui/open-webui
synced 2025-06-26 18:26:48 +00:00
@@ -2,6 +2,10 @@ import os
|
|||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
|
||||||
|
from peewee_migrate import Router
|
||||||
|
from apps.webui.internal.wrappers import register_connection
|
||||||
|
|
||||||
from typing import Optional, Any
|
from typing import Optional, Any
|
||||||
from typing_extensions import Self
|
from typing_extensions import Self
|
||||||
|
|
||||||
@@ -46,6 +50,35 @@ if os.path.exists(f"{DATA_DIR}/ollama.db"):
|
|||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# Workaround to handle the peewee migration
|
||||||
|
# This is required to ensure the peewee migration is handled before the alembic migration
|
||||||
|
def handle_peewee_migration():
|
||||||
|
try:
|
||||||
|
db = register_connection(DATABASE_URL)
|
||||||
|
migrate_dir = BACKEND_DIR / "apps" / "webui" / "internal" / "migrations"
|
||||||
|
router = Router(db, logger=log, migrate_dir=migrate_dir)
|
||||||
|
router.run()
|
||||||
|
db.close()
|
||||||
|
|
||||||
|
# check if db connection has been closed
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
log.error(f"Failed to initialize the database connection: {e}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
finally:
|
||||||
|
# Properly closing the database connection
|
||||||
|
if db and not db.is_closed():
|
||||||
|
db.close()
|
||||||
|
|
||||||
|
# Assert if db connection has been closed
|
||||||
|
assert db.is_closed(), "Database connection is still open."
|
||||||
|
|
||||||
|
|
||||||
|
handle_peewee_migration()
|
||||||
|
|
||||||
|
|
||||||
SQLALCHEMY_DATABASE_URL = DATABASE_URL
|
SQLALCHEMY_DATABASE_URL = DATABASE_URL
|
||||||
if "sqlite" in SQLALCHEMY_DATABASE_URL:
|
if "sqlite" in SQLALCHEMY_DATABASE_URL:
|
||||||
engine = create_engine(
|
engine = create_engine(
|
||||||
@@ -53,8 +86,22 @@ if "sqlite" in SQLALCHEMY_DATABASE_URL:
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
engine = create_engine(SQLALCHEMY_DATABASE_URL, pool_pre_ping=True)
|
engine = create_engine(SQLALCHEMY_DATABASE_URL, pool_pre_ping=True)
|
||||||
|
|
||||||
|
|
||||||
SessionLocal = sessionmaker(
|
SessionLocal = sessionmaker(
|
||||||
autocommit=False, autoflush=False, bind=engine, expire_on_commit=False
|
autocommit=False, autoflush=False, bind=engine, expire_on_commit=False
|
||||||
)
|
)
|
||||||
Base = declarative_base()
|
Base = declarative_base()
|
||||||
Session = scoped_session(SessionLocal)
|
Session = scoped_session(SessionLocal)
|
||||||
|
|
||||||
|
|
||||||
|
# Dependency
|
||||||
|
def get_session():
|
||||||
|
db = SessionLocal()
|
||||||
|
try:
|
||||||
|
yield db
|
||||||
|
finally:
|
||||||
|
db.close()
|
||||||
|
|
||||||
|
|
||||||
|
get_db = contextmanager(get_session)
|
||||||
|
|||||||
72
backend/apps/webui/internal/wrappers.py
Normal file
72
backend/apps/webui/internal/wrappers.py
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
from contextvars import ContextVar
|
||||||
|
from peewee import *
|
||||||
|
from peewee import PostgresqlDatabase, InterfaceError as PeeWeeInterfaceError
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from playhouse.db_url import connect, parse
|
||||||
|
from playhouse.shortcuts import ReconnectMixin
|
||||||
|
|
||||||
|
from config import SRC_LOG_LEVELS
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
log.setLevel(SRC_LOG_LEVELS["DB"])
|
||||||
|
|
||||||
|
db_state_default = {"closed": None, "conn": None, "ctx": None, "transactions": None}
|
||||||
|
db_state = ContextVar("db_state", default=db_state_default.copy())
|
||||||
|
|
||||||
|
|
||||||
|
class PeeweeConnectionState(object):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super().__setattr__("_state", db_state)
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
def __setattr__(self, name, value):
|
||||||
|
self._state.get()[name] = value
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
value = self._state.get()[name]
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
class CustomReconnectMixin(ReconnectMixin):
|
||||||
|
reconnect_errors = (
|
||||||
|
# psycopg2
|
||||||
|
(OperationalError, "termin"),
|
||||||
|
(InterfaceError, "closed"),
|
||||||
|
# peewee
|
||||||
|
(PeeWeeInterfaceError, "closed"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ReconnectingPostgresqlDatabase(CustomReconnectMixin, PostgresqlDatabase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def register_connection(db_url):
|
||||||
|
db = connect(db_url)
|
||||||
|
if isinstance(db, PostgresqlDatabase):
|
||||||
|
# Enable autoconnect for SQLite databases, managed by Peewee
|
||||||
|
db.autoconnect = True
|
||||||
|
db.reuse_if_open = True
|
||||||
|
log.info("Connected to PostgreSQL database")
|
||||||
|
|
||||||
|
# Get the connection details
|
||||||
|
connection = parse(db_url)
|
||||||
|
|
||||||
|
# Use our custom database class that supports reconnection
|
||||||
|
db = ReconnectingPostgresqlDatabase(
|
||||||
|
connection["database"],
|
||||||
|
user=connection["user"],
|
||||||
|
password=connection["password"],
|
||||||
|
host=connection["host"],
|
||||||
|
port=connection["port"],
|
||||||
|
)
|
||||||
|
db.connect(reuse_if_open=True)
|
||||||
|
elif isinstance(db, SqliteDatabase):
|
||||||
|
# Enable autoconnect for SQLite databases, managed by Peewee
|
||||||
|
db.autoconnect = True
|
||||||
|
db.reuse_if_open = True
|
||||||
|
log.info("Connected to SQLite database")
|
||||||
|
else:
|
||||||
|
raise ValueError("Unsupported database connection")
|
||||||
|
return db
|
||||||
@@ -19,8 +19,13 @@ from apps.webui.routers import (
|
|||||||
functions,
|
functions,
|
||||||
)
|
)
|
||||||
from apps.webui.models.functions import Functions
|
from apps.webui.models.functions import Functions
|
||||||
|
from apps.webui.models.models import Models
|
||||||
|
|
||||||
from apps.webui.utils import load_function_module_by_id
|
from apps.webui.utils import load_function_module_by_id
|
||||||
|
|
||||||
from utils.misc import stream_message_template
|
from utils.misc import stream_message_template
|
||||||
|
from utils.task import prompt_template
|
||||||
|
|
||||||
|
|
||||||
from config import (
|
from config import (
|
||||||
WEBUI_BUILD_HASH,
|
WEBUI_BUILD_HASH,
|
||||||
@@ -186,6 +191,77 @@ async def get_pipe_models():
|
|||||||
|
|
||||||
|
|
||||||
async def generate_function_chat_completion(form_data, user):
|
async def generate_function_chat_completion(form_data, user):
|
||||||
|
model_id = form_data.get("model")
|
||||||
|
model_info = Models.get_model_by_id(model_id)
|
||||||
|
|
||||||
|
if model_info:
|
||||||
|
if model_info.base_model_id:
|
||||||
|
form_data["model"] = model_info.base_model_id
|
||||||
|
|
||||||
|
model_info.params = model_info.params.model_dump()
|
||||||
|
|
||||||
|
if model_info.params:
|
||||||
|
if model_info.params.get("temperature", None) is not None:
|
||||||
|
form_data["temperature"] = float(model_info.params.get("temperature"))
|
||||||
|
|
||||||
|
if model_info.params.get("top_p", None):
|
||||||
|
form_data["top_p"] = int(model_info.params.get("top_p", None))
|
||||||
|
|
||||||
|
if model_info.params.get("max_tokens", None):
|
||||||
|
form_data["max_tokens"] = int(model_info.params.get("max_tokens", None))
|
||||||
|
|
||||||
|
if model_info.params.get("frequency_penalty", None):
|
||||||
|
form_data["frequency_penalty"] = int(
|
||||||
|
model_info.params.get("frequency_penalty", None)
|
||||||
|
)
|
||||||
|
|
||||||
|
if model_info.params.get("seed", None):
|
||||||
|
form_data["seed"] = model_info.params.get("seed", None)
|
||||||
|
|
||||||
|
if model_info.params.get("stop", None):
|
||||||
|
form_data["stop"] = (
|
||||||
|
[
|
||||||
|
bytes(stop, "utf-8").decode("unicode_escape")
|
||||||
|
for stop in model_info.params["stop"]
|
||||||
|
]
|
||||||
|
if model_info.params.get("stop", None)
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
|
||||||
|
system = model_info.params.get("system", None)
|
||||||
|
if system:
|
||||||
|
system = prompt_template(
|
||||||
|
system,
|
||||||
|
**(
|
||||||
|
{
|
||||||
|
"user_name": user.name,
|
||||||
|
"user_location": (
|
||||||
|
user.info.get("location") if user.info else None
|
||||||
|
),
|
||||||
|
}
|
||||||
|
if user
|
||||||
|
else {}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
# Check if the payload already has a system message
|
||||||
|
# If not, add a system message to the payload
|
||||||
|
if form_data.get("messages"):
|
||||||
|
for message in form_data["messages"]:
|
||||||
|
if message.get("role") == "system":
|
||||||
|
message["content"] = system + message["content"]
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
form_data["messages"].insert(
|
||||||
|
0,
|
||||||
|
{
|
||||||
|
"role": "system",
|
||||||
|
"content": system,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
async def job():
|
async def job():
|
||||||
pipe_id = form_data["model"]
|
pipe_id = form_data["model"]
|
||||||
if "." in pipe_id:
|
if "." in pipe_id:
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from sqlalchemy import String, Column, Boolean, Text
|
|||||||
from apps.webui.models.users import UserModel, Users
|
from apps.webui.models.users import UserModel, Users
|
||||||
from utils.utils import verify_password
|
from utils.utils import verify_password
|
||||||
|
|
||||||
from apps.webui.internal.db import Base, Session
|
from apps.webui.internal.db import Base, get_db
|
||||||
|
|
||||||
from config import SRC_LOG_LEVELS
|
from config import SRC_LOG_LEVELS
|
||||||
|
|
||||||
@@ -102,40 +102,44 @@ class AuthsTable:
|
|||||||
role: str = "pending",
|
role: str = "pending",
|
||||||
oauth_sub: Optional[str] = None,
|
oauth_sub: Optional[str] = None,
|
||||||
) -> Optional[UserModel]:
|
) -> Optional[UserModel]:
|
||||||
log.info("insert_new_auth")
|
with get_db() as db:
|
||||||
|
|
||||||
id = str(uuid.uuid4())
|
log.info("insert_new_auth")
|
||||||
|
|
||||||
auth = AuthModel(
|
id = str(uuid.uuid4())
|
||||||
**{"id": id, "email": email, "password": password, "active": True}
|
|
||||||
)
|
|
||||||
result = Auth(**auth.model_dump())
|
|
||||||
Session.add(result)
|
|
||||||
|
|
||||||
user = Users.insert_new_user(
|
auth = AuthModel(
|
||||||
id, name, email, profile_image_url, role, oauth_sub
|
**{"id": id, "email": email, "password": password, "active": True}
|
||||||
)
|
)
|
||||||
|
result = Auth(**auth.model_dump())
|
||||||
|
db.add(result)
|
||||||
|
|
||||||
Session.commit()
|
user = Users.insert_new_user(
|
||||||
Session.refresh(result)
|
id, name, email, profile_image_url, role, oauth_sub
|
||||||
|
)
|
||||||
|
|
||||||
if result and user:
|
db.commit()
|
||||||
return user
|
db.refresh(result)
|
||||||
else:
|
|
||||||
return None
|
if result and user:
|
||||||
|
return user
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
def authenticate_user(self, email: str, password: str) -> Optional[UserModel]:
|
def authenticate_user(self, email: str, password: str) -> Optional[UserModel]:
|
||||||
log.info(f"authenticate_user: {email}")
|
log.info(f"authenticate_user: {email}")
|
||||||
try:
|
try:
|
||||||
auth = Session.query(Auth).filter_by(email=email, active=True).first()
|
with get_db() as db:
|
||||||
if auth:
|
|
||||||
if verify_password(password, auth.password):
|
auth = db.query(Auth).filter_by(email=email, active=True).first()
|
||||||
user = Users.get_user_by_id(auth.id)
|
if auth:
|
||||||
return user
|
if verify_password(password, auth.password):
|
||||||
|
user = Users.get_user_by_id(auth.id)
|
||||||
|
return user
|
||||||
|
else:
|
||||||
|
return None
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
else:
|
|
||||||
return None
|
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -154,40 +158,47 @@ class AuthsTable:
|
|||||||
def authenticate_user_by_trusted_header(self, email: str) -> Optional[UserModel]:
|
def authenticate_user_by_trusted_header(self, email: str) -> Optional[UserModel]:
|
||||||
log.info(f"authenticate_user_by_trusted_header: {email}")
|
log.info(f"authenticate_user_by_trusted_header: {email}")
|
||||||
try:
|
try:
|
||||||
auth = Session.query(Auth).filter(email=email, active=True).first()
|
with get_db() as db:
|
||||||
if auth:
|
auth = db.query(Auth).filter(email=email, active=True).first()
|
||||||
user = Users.get_user_by_id(auth.id)
|
if auth:
|
||||||
return user
|
user = Users.get_user_by_id(auth.id)
|
||||||
|
return user
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def update_user_password_by_id(self, id: str, new_password: str) -> bool:
|
def update_user_password_by_id(self, id: str, new_password: str) -> bool:
|
||||||
try:
|
try:
|
||||||
result = (
|
with get_db() as db:
|
||||||
Session.query(Auth).filter_by(id=id).update({"password": new_password})
|
|
||||||
)
|
result = (
|
||||||
return True if result == 1 else False
|
db.query(Auth).filter_by(id=id).update({"password": new_password})
|
||||||
|
)
|
||||||
|
return True if result == 1 else False
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def update_email_by_id(self, id: str, email: str) -> bool:
|
def update_email_by_id(self, id: str, email: str) -> bool:
|
||||||
try:
|
try:
|
||||||
result = Session.query(Auth).filter_by(id=id).update({"email": email})
|
with get_db() as db:
|
||||||
return True if result == 1 else False
|
|
||||||
|
result = db.query(Auth).filter_by(id=id).update({"email": email})
|
||||||
|
return True if result == 1 else False
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def delete_auth_by_id(self, id: str) -> bool:
|
def delete_auth_by_id(self, id: str) -> bool:
|
||||||
try:
|
try:
|
||||||
# Delete User
|
with get_db() as db:
|
||||||
result = Users.delete_user_by_id(id)
|
|
||||||
|
|
||||||
if result:
|
# Delete User
|
||||||
Session.query(Auth).filter_by(id=id).delete()
|
result = Users.delete_user_by_id(id)
|
||||||
|
|
||||||
return True
|
if result:
|
||||||
else:
|
db.query(Auth).filter_by(id=id).delete()
|
||||||
return False
|
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import time
|
|||||||
|
|
||||||
from sqlalchemy import Column, String, BigInteger, Boolean, Text
|
from sqlalchemy import Column, String, BigInteger, Boolean, Text
|
||||||
|
|
||||||
from apps.webui.internal.db import Base, Session
|
from apps.webui.internal.db import Base, get_db
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
@@ -79,87 +79,99 @@ class ChatTitleIdResponse(BaseModel):
|
|||||||
class ChatTable:
|
class ChatTable:
|
||||||
|
|
||||||
def insert_new_chat(self, user_id: str, form_data: ChatForm) -> Optional[ChatModel]:
|
def insert_new_chat(self, user_id: str, form_data: ChatForm) -> Optional[ChatModel]:
|
||||||
id = str(uuid.uuid4())
|
with get_db() as db:
|
||||||
chat = ChatModel(
|
|
||||||
**{
|
|
||||||
"id": id,
|
|
||||||
"user_id": user_id,
|
|
||||||
"title": (
|
|
||||||
form_data.chat["title"] if "title" in form_data.chat else "New Chat"
|
|
||||||
),
|
|
||||||
"chat": json.dumps(form_data.chat),
|
|
||||||
"created_at": int(time.time()),
|
|
||||||
"updated_at": int(time.time()),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
result = Chat(**chat.model_dump())
|
id = str(uuid.uuid4())
|
||||||
Session.add(result)
|
chat = ChatModel(
|
||||||
Session.commit()
|
**{
|
||||||
Session.refresh(result)
|
"id": id,
|
||||||
return ChatModel.model_validate(result) if result else None
|
"user_id": user_id,
|
||||||
|
"title": (
|
||||||
|
form_data.chat["title"]
|
||||||
|
if "title" in form_data.chat
|
||||||
|
else "New Chat"
|
||||||
|
),
|
||||||
|
"chat": json.dumps(form_data.chat),
|
||||||
|
"created_at": int(time.time()),
|
||||||
|
"updated_at": int(time.time()),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
result = Chat(**chat.model_dump())
|
||||||
|
db.add(result)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(result)
|
||||||
|
return ChatModel.model_validate(result) if result else None
|
||||||
|
|
||||||
def update_chat_by_id(self, id: str, chat: dict) -> Optional[ChatModel]:
|
def update_chat_by_id(self, id: str, chat: dict) -> Optional[ChatModel]:
|
||||||
try:
|
try:
|
||||||
chat_obj = Session.get(Chat, id)
|
with get_db() as db:
|
||||||
chat_obj.chat = json.dumps(chat)
|
|
||||||
chat_obj.title = chat["title"] if "title" in chat else "New Chat"
|
|
||||||
chat_obj.updated_at = int(time.time())
|
|
||||||
Session.commit()
|
|
||||||
Session.refresh(chat_obj)
|
|
||||||
|
|
||||||
return ChatModel.model_validate(chat_obj)
|
chat_obj = db.get(Chat, id)
|
||||||
|
chat_obj.chat = json.dumps(chat)
|
||||||
|
chat_obj.title = chat["title"] if "title" in chat else "New Chat"
|
||||||
|
chat_obj.updated_at = int(time.time())
|
||||||
|
db.commit()
|
||||||
|
db.refresh(chat_obj)
|
||||||
|
|
||||||
|
return ChatModel.model_validate(chat_obj)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def insert_shared_chat_by_chat_id(self, chat_id: str) -> Optional[ChatModel]:
|
def insert_shared_chat_by_chat_id(self, chat_id: str) -> Optional[ChatModel]:
|
||||||
# Get the existing chat to share
|
with get_db() as db:
|
||||||
chat = Session.get(Chat, chat_id)
|
|
||||||
# Check if the chat is already shared
|
|
||||||
if chat.share_id:
|
|
||||||
return self.get_chat_by_id_and_user_id(chat.share_id, "shared")
|
|
||||||
# Create a new chat with the same data, but with a new ID
|
|
||||||
shared_chat = ChatModel(
|
|
||||||
**{
|
|
||||||
"id": str(uuid.uuid4()),
|
|
||||||
"user_id": f"shared-{chat_id}",
|
|
||||||
"title": chat.title,
|
|
||||||
"chat": chat.chat,
|
|
||||||
"created_at": chat.created_at,
|
|
||||||
"updated_at": int(time.time()),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
shared_result = Chat(**shared_chat.model_dump())
|
|
||||||
Session.add(shared_result)
|
|
||||||
Session.commit()
|
|
||||||
Session.refresh(shared_result)
|
|
||||||
# Update the original chat with the share_id
|
|
||||||
result = (
|
|
||||||
Session.query(Chat)
|
|
||||||
.filter_by(id=chat_id)
|
|
||||||
.update({"share_id": shared_chat.id})
|
|
||||||
)
|
|
||||||
|
|
||||||
return shared_chat if (shared_result and result) else None
|
# Get the existing chat to share
|
||||||
|
chat = db.get(Chat, chat_id)
|
||||||
|
# Check if the chat is already shared
|
||||||
|
if chat.share_id:
|
||||||
|
return self.get_chat_by_id_and_user_id(chat.share_id, "shared")
|
||||||
|
# Create a new chat with the same data, but with a new ID
|
||||||
|
shared_chat = ChatModel(
|
||||||
|
**{
|
||||||
|
"id": str(uuid.uuid4()),
|
||||||
|
"user_id": f"shared-{chat_id}",
|
||||||
|
"title": chat.title,
|
||||||
|
"chat": chat.chat,
|
||||||
|
"created_at": chat.created_at,
|
||||||
|
"updated_at": int(time.time()),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
shared_result = Chat(**shared_chat.model_dump())
|
||||||
|
db.add(shared_result)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(shared_result)
|
||||||
|
# Update the original chat with the share_id
|
||||||
|
result = (
|
||||||
|
db.query(Chat)
|
||||||
|
.filter_by(id=chat_id)
|
||||||
|
.update({"share_id": shared_chat.id})
|
||||||
|
)
|
||||||
|
|
||||||
|
return shared_chat if (shared_result and result) else None
|
||||||
|
|
||||||
def update_shared_chat_by_chat_id(self, chat_id: str) -> Optional[ChatModel]:
|
def update_shared_chat_by_chat_id(self, chat_id: str) -> Optional[ChatModel]:
|
||||||
try:
|
try:
|
||||||
print("update_shared_chat_by_id")
|
with get_db() as db:
|
||||||
chat = Session.get(Chat, chat_id)
|
|
||||||
print(chat)
|
|
||||||
chat.title = chat.title
|
|
||||||
chat.chat = chat.chat
|
|
||||||
Session.commit()
|
|
||||||
Session.refresh(chat)
|
|
||||||
|
|
||||||
return self.get_chat_by_id(chat.share_id)
|
print("update_shared_chat_by_id")
|
||||||
|
chat = db.get(Chat, chat_id)
|
||||||
|
print(chat)
|
||||||
|
chat.title = chat.title
|
||||||
|
chat.chat = chat.chat
|
||||||
|
db.commit()
|
||||||
|
db.refresh(chat)
|
||||||
|
|
||||||
|
return self.get_chat_by_id(chat.share_id)
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def delete_shared_chat_by_chat_id(self, chat_id: str) -> bool:
|
def delete_shared_chat_by_chat_id(self, chat_id: str) -> bool:
|
||||||
try:
|
try:
|
||||||
Session.query(Chat).filter_by(user_id=f"shared-{chat_id}").delete()
|
with get_db() as db:
|
||||||
return True
|
|
||||||
|
db.query(Chat).filter_by(user_id=f"shared-{chat_id}").delete()
|
||||||
|
return True
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -167,42 +179,50 @@ class ChatTable:
|
|||||||
self, id: str, share_id: Optional[str]
|
self, id: str, share_id: Optional[str]
|
||||||
) -> Optional[ChatModel]:
|
) -> Optional[ChatModel]:
|
||||||
try:
|
try:
|
||||||
chat = Session.get(Chat, id)
|
with get_db() as db:
|
||||||
chat.share_id = share_id
|
|
||||||
Session.commit()
|
chat = db.get(Chat, id)
|
||||||
Session.refresh(chat)
|
chat.share_id = share_id
|
||||||
return ChatModel.model_validate(chat)
|
db.commit()
|
||||||
|
db.refresh(chat)
|
||||||
|
return ChatModel.model_validate(chat)
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def toggle_chat_archive_by_id(self, id: str) -> Optional[ChatModel]:
|
def toggle_chat_archive_by_id(self, id: str) -> Optional[ChatModel]:
|
||||||
try:
|
try:
|
||||||
chat = Session.get(Chat, id)
|
with get_db() as db:
|
||||||
chat.archived = not chat.archived
|
|
||||||
Session.commit()
|
chat = db.get(Chat, id)
|
||||||
Session.refresh(chat)
|
chat.archived = not chat.archived
|
||||||
return ChatModel.model_validate(chat)
|
db.commit()
|
||||||
|
db.refresh(chat)
|
||||||
|
return ChatModel.model_validate(chat)
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def archive_all_chats_by_user_id(self, user_id: str) -> bool:
|
def archive_all_chats_by_user_id(self, user_id: str) -> bool:
|
||||||
try:
|
try:
|
||||||
Session.query(Chat).filter_by(user_id=user_id).update({"archived": True})
|
with get_db() as db:
|
||||||
return True
|
|
||||||
|
db.query(Chat).filter_by(user_id=user_id).update({"archived": True})
|
||||||
|
return True
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_archived_chat_list_by_user_id(
|
def get_archived_chat_list_by_user_id(
|
||||||
self, user_id: str, skip: int = 0, limit: int = 50
|
self, user_id: str, skip: int = 0, limit: int = 50
|
||||||
) -> List[ChatModel]:
|
) -> List[ChatModel]:
|
||||||
all_chats = (
|
with get_db() as db:
|
||||||
Session.query(Chat)
|
|
||||||
.filter_by(user_id=user_id, archived=True)
|
all_chats = (
|
||||||
.order_by(Chat.updated_at.desc())
|
db.query(Chat)
|
||||||
# .limit(limit).offset(skip)
|
.filter_by(user_id=user_id, archived=True)
|
||||||
.all()
|
.order_by(Chat.updated_at.desc())
|
||||||
)
|
# .limit(limit).offset(skip)
|
||||||
return [ChatModel.model_validate(chat) for chat in all_chats]
|
.all()
|
||||||
|
)
|
||||||
|
return [ChatModel.model_validate(chat) for chat in all_chats]
|
||||||
|
|
||||||
def get_chat_list_by_user_id(
|
def get_chat_list_by_user_id(
|
||||||
self,
|
self,
|
||||||
@@ -211,110 +231,136 @@ class ChatTable:
|
|||||||
skip: int = 0,
|
skip: int = 0,
|
||||||
limit: int = 50,
|
limit: int = 50,
|
||||||
) -> List[ChatModel]:
|
) -> List[ChatModel]:
|
||||||
query = Session.query(Chat).filter_by(user_id=user_id)
|
with get_db() as db:
|
||||||
if not include_archived:
|
query = db.query(Chat).filter_by(user_id=user_id)
|
||||||
query = query.filter_by(archived=False)
|
if not include_archived:
|
||||||
all_chats = (
|
query = query.filter_by(archived=False)
|
||||||
query.order_by(Chat.updated_at.desc())
|
all_chats = (
|
||||||
# .limit(limit).offset(skip)
|
query.order_by(Chat.updated_at.desc())
|
||||||
.all()
|
# .limit(limit).offset(skip)
|
||||||
)
|
.all()
|
||||||
return [ChatModel.model_validate(chat) for chat in all_chats]
|
)
|
||||||
|
return [ChatModel.model_validate(chat) for chat in all_chats]
|
||||||
|
|
||||||
def get_chat_list_by_chat_ids(
|
def get_chat_list_by_chat_ids(
|
||||||
self, chat_ids: List[str], skip: int = 0, limit: int = 50
|
self, chat_ids: List[str], skip: int = 0, limit: int = 50
|
||||||
) -> List[ChatModel]:
|
) -> List[ChatModel]:
|
||||||
all_chats = (
|
|
||||||
Session.query(Chat)
|
with get_db() as db:
|
||||||
.filter(Chat.id.in_(chat_ids))
|
|
||||||
.filter_by(archived=False)
|
all_chats = (
|
||||||
.order_by(Chat.updated_at.desc())
|
db.query(Chat)
|
||||||
.all()
|
.filter(Chat.id.in_(chat_ids))
|
||||||
)
|
.filter_by(archived=False)
|
||||||
return [ChatModel.model_validate(chat) for chat in all_chats]
|
.order_by(Chat.updated_at.desc())
|
||||||
|
.all()
|
||||||
|
)
|
||||||
|
return [ChatModel.model_validate(chat) for chat in all_chats]
|
||||||
|
|
||||||
def get_chat_by_id(self, id: str) -> Optional[ChatModel]:
|
def get_chat_by_id(self, id: str) -> Optional[ChatModel]:
|
||||||
try:
|
try:
|
||||||
chat = Session.get(Chat, id)
|
with get_db() as db:
|
||||||
return ChatModel.model_validate(chat)
|
|
||||||
|
chat = db.get(Chat, id)
|
||||||
|
return ChatModel.model_validate(chat)
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_chat_by_share_id(self, id: str) -> Optional[ChatModel]:
|
def get_chat_by_share_id(self, id: str) -> Optional[ChatModel]:
|
||||||
try:
|
try:
|
||||||
chat = Session.query(Chat).filter_by(share_id=id).first()
|
with get_db() as db:
|
||||||
|
|
||||||
if chat:
|
chat = db.query(Chat).filter_by(share_id=id).first()
|
||||||
return self.get_chat_by_id(id)
|
|
||||||
else:
|
if chat:
|
||||||
return None
|
return self.get_chat_by_id(id)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_chat_by_id_and_user_id(self, id: str, user_id: str) -> Optional[ChatModel]:
|
def get_chat_by_id_and_user_id(self, id: str, user_id: str) -> Optional[ChatModel]:
|
||||||
try:
|
try:
|
||||||
chat = Session.query(Chat).filter_by(id=id, user_id=user_id).first()
|
with get_db() as db:
|
||||||
return ChatModel.model_validate(chat)
|
|
||||||
|
chat = db.query(Chat).filter_by(id=id, user_id=user_id).first()
|
||||||
|
return ChatModel.model_validate(chat)
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_chats(self, skip: int = 0, limit: int = 50) -> List[ChatModel]:
|
def get_chats(self, skip: int = 0, limit: int = 50) -> List[ChatModel]:
|
||||||
all_chats = (
|
with get_db() as db:
|
||||||
Session.query(Chat)
|
|
||||||
# .limit(limit).offset(skip)
|
all_chats = (
|
||||||
.order_by(Chat.updated_at.desc())
|
db.query(Chat)
|
||||||
)
|
# .limit(limit).offset(skip)
|
||||||
return [ChatModel.model_validate(chat) for chat in all_chats]
|
.order_by(Chat.updated_at.desc())
|
||||||
|
)
|
||||||
|
return [ChatModel.model_validate(chat) for chat in all_chats]
|
||||||
|
|
||||||
def get_chats_by_user_id(self, user_id: str) -> List[ChatModel]:
|
def get_chats_by_user_id(self, user_id: str) -> List[ChatModel]:
|
||||||
all_chats = (
|
with get_db() as db:
|
||||||
Session.query(Chat)
|
|
||||||
.filter_by(user_id=user_id)
|
all_chats = (
|
||||||
.order_by(Chat.updated_at.desc())
|
db.query(Chat)
|
||||||
)
|
.filter_by(user_id=user_id)
|
||||||
return [ChatModel.model_validate(chat) for chat in all_chats]
|
.order_by(Chat.updated_at.desc())
|
||||||
|
)
|
||||||
|
return [ChatModel.model_validate(chat) for chat in all_chats]
|
||||||
|
|
||||||
def get_archived_chats_by_user_id(self, user_id: str) -> List[ChatModel]:
|
def get_archived_chats_by_user_id(self, user_id: str) -> List[ChatModel]:
|
||||||
all_chats = (
|
with get_db() as db:
|
||||||
Session.query(Chat)
|
|
||||||
.filter_by(user_id=user_id, archived=True)
|
all_chats = (
|
||||||
.order_by(Chat.updated_at.desc())
|
db.query(Chat)
|
||||||
)
|
.filter_by(user_id=user_id, archived=True)
|
||||||
return [ChatModel.model_validate(chat) for chat in all_chats]
|
.order_by(Chat.updated_at.desc())
|
||||||
|
)
|
||||||
|
return [ChatModel.model_validate(chat) for chat in all_chats]
|
||||||
|
|
||||||
def delete_chat_by_id(self, id: str) -> bool:
|
def delete_chat_by_id(self, id: str) -> bool:
|
||||||
try:
|
try:
|
||||||
Session.query(Chat).filter_by(id=id).delete()
|
with get_db() as db:
|
||||||
|
|
||||||
return True and self.delete_shared_chat_by_chat_id(id)
|
db.query(Chat).filter_by(id=id).delete()
|
||||||
|
|
||||||
|
return True and self.delete_shared_chat_by_chat_id(id)
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def delete_chat_by_id_and_user_id(self, id: str, user_id: str) -> bool:
|
def delete_chat_by_id_and_user_id(self, id: str, user_id: str) -> bool:
|
||||||
try:
|
try:
|
||||||
Session.query(Chat).filter_by(id=id, user_id=user_id).delete()
|
with get_db() as db:
|
||||||
|
|
||||||
return True and self.delete_shared_chat_by_chat_id(id)
|
db.query(Chat).filter_by(id=id, user_id=user_id).delete()
|
||||||
|
|
||||||
|
return True and self.delete_shared_chat_by_chat_id(id)
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def delete_chats_by_user_id(self, user_id: str) -> bool:
|
def delete_chats_by_user_id(self, user_id: str) -> bool:
|
||||||
try:
|
try:
|
||||||
self.delete_shared_chats_by_user_id(user_id)
|
|
||||||
|
|
||||||
Session.query(Chat).filter_by(user_id=user_id).delete()
|
with get_db() as db:
|
||||||
return True
|
|
||||||
|
self.delete_shared_chats_by_user_id(user_id)
|
||||||
|
|
||||||
|
db.query(Chat).filter_by(user_id=user_id).delete()
|
||||||
|
return True
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def delete_shared_chats_by_user_id(self, user_id: str) -> bool:
|
def delete_shared_chats_by_user_id(self, user_id: str) -> bool:
|
||||||
try:
|
try:
|
||||||
chats_by_user = Session.query(Chat).filter_by(user_id=user_id).all()
|
|
||||||
shared_chat_ids = [f"shared-{chat.id}" for chat in chats_by_user]
|
|
||||||
|
|
||||||
Session.query(Chat).filter(Chat.user_id.in_(shared_chat_ids)).delete()
|
with get_db() as db:
|
||||||
|
|
||||||
return True
|
chats_by_user = db.query(Chat).filter_by(user_id=user_id).all()
|
||||||
|
shared_chat_ids = [f"shared-{chat.id}" for chat in chats_by_user]
|
||||||
|
|
||||||
|
db.query(Chat).filter(Chat.user_id.in_(shared_chat_ids)).delete()
|
||||||
|
|
||||||
|
return True
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import logging
|
|||||||
|
|
||||||
from sqlalchemy import String, Column, BigInteger, Text
|
from sqlalchemy import String, Column, BigInteger, Text
|
||||||
|
|
||||||
from apps.webui.internal.db import Base, Session
|
from apps.webui.internal.db import Base, get_db
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
@@ -74,51 +74,59 @@ class DocumentsTable:
|
|||||||
def insert_new_doc(
|
def insert_new_doc(
|
||||||
self, user_id: str, form_data: DocumentForm
|
self, user_id: str, form_data: DocumentForm
|
||||||
) -> Optional[DocumentModel]:
|
) -> Optional[DocumentModel]:
|
||||||
document = DocumentModel(
|
with get_db() as db:
|
||||||
**{
|
|
||||||
**form_data.model_dump(),
|
|
||||||
"user_id": user_id,
|
|
||||||
"timestamp": int(time.time()),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
document = DocumentModel(
|
||||||
result = Document(**document.model_dump())
|
**{
|
||||||
Session.add(result)
|
**form_data.model_dump(),
|
||||||
Session.commit()
|
"user_id": user_id,
|
||||||
Session.refresh(result)
|
"timestamp": int(time.time()),
|
||||||
if result:
|
}
|
||||||
return DocumentModel.model_validate(result)
|
)
|
||||||
else:
|
|
||||||
|
try:
|
||||||
|
result = Document(**document.model_dump())
|
||||||
|
db.add(result)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(result)
|
||||||
|
if result:
|
||||||
|
return DocumentModel.model_validate(result)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
except:
|
||||||
return None
|
return None
|
||||||
except:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def get_doc_by_name(self, name: str) -> Optional[DocumentModel]:
|
def get_doc_by_name(self, name: str) -> Optional[DocumentModel]:
|
||||||
try:
|
try:
|
||||||
document = Session.query(Document).filter_by(name=name).first()
|
with get_db() as db:
|
||||||
return DocumentModel.model_validate(document) if document else None
|
|
||||||
|
document = db.query(Document).filter_by(name=name).first()
|
||||||
|
return DocumentModel.model_validate(document) if document else None
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_docs(self) -> List[DocumentModel]:
|
def get_docs(self) -> List[DocumentModel]:
|
||||||
return [
|
with get_db() as db:
|
||||||
DocumentModel.model_validate(doc) for doc in Session.query(Document).all()
|
|
||||||
]
|
return [
|
||||||
|
DocumentModel.model_validate(doc) for doc in db.query(Document).all()
|
||||||
|
]
|
||||||
|
|
||||||
def update_doc_by_name(
|
def update_doc_by_name(
|
||||||
self, name: str, form_data: DocumentUpdateForm
|
self, name: str, form_data: DocumentUpdateForm
|
||||||
) -> Optional[DocumentModel]:
|
) -> Optional[DocumentModel]:
|
||||||
try:
|
try:
|
||||||
Session.query(Document).filter_by(name=name).update(
|
with get_db() as db:
|
||||||
{
|
|
||||||
"title": form_data.title,
|
db.query(Document).filter_by(name=name).update(
|
||||||
"name": form_data.name,
|
{
|
||||||
"timestamp": int(time.time()),
|
"title": form_data.title,
|
||||||
}
|
"name": form_data.name,
|
||||||
)
|
"timestamp": int(time.time()),
|
||||||
Session.commit()
|
}
|
||||||
return self.get_doc_by_name(form_data.name)
|
)
|
||||||
|
db.commit()
|
||||||
|
return self.get_doc_by_name(form_data.name)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.exception(e)
|
log.exception(e)
|
||||||
return None
|
return None
|
||||||
@@ -131,22 +139,26 @@ class DocumentsTable:
|
|||||||
doc_content = json.loads(doc.content if doc.content else "{}")
|
doc_content = json.loads(doc.content if doc.content else "{}")
|
||||||
doc_content = {**doc_content, **updated}
|
doc_content = {**doc_content, **updated}
|
||||||
|
|
||||||
Session.query(Document).filter_by(name=name).update(
|
with get_db() as db:
|
||||||
{
|
|
||||||
"content": json.dumps(doc_content),
|
db.query(Document).filter_by(name=name).update(
|
||||||
"timestamp": int(time.time()),
|
{
|
||||||
}
|
"content": json.dumps(doc_content),
|
||||||
)
|
"timestamp": int(time.time()),
|
||||||
Session.commit()
|
}
|
||||||
return self.get_doc_by_name(name)
|
)
|
||||||
|
db.commit()
|
||||||
|
return self.get_doc_by_name(name)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.exception(e)
|
log.exception(e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def delete_doc_by_name(self, name: str) -> bool:
|
def delete_doc_by_name(self, name: str) -> bool:
|
||||||
try:
|
try:
|
||||||
Session.query(Document).filter_by(name=name).delete()
|
with get_db() as db:
|
||||||
return True
|
|
||||||
|
db.query(Document).filter_by(name=name).delete()
|
||||||
|
return True
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import logging
|
|||||||
|
|
||||||
from sqlalchemy import Column, String, BigInteger, Text
|
from sqlalchemy import Column, String, BigInteger, Text
|
||||||
|
|
||||||
from apps.webui.internal.db import JSONField, Base, Session
|
from apps.webui.internal.db import JSONField, Base, get_db
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
@@ -61,50 +61,62 @@ class FileForm(BaseModel):
|
|||||||
class FilesTable:
|
class FilesTable:
|
||||||
|
|
||||||
def insert_new_file(self, user_id: str, form_data: FileForm) -> Optional[FileModel]:
|
def insert_new_file(self, user_id: str, form_data: FileForm) -> Optional[FileModel]:
|
||||||
file = FileModel(
|
with get_db() as db:
|
||||||
**{
|
|
||||||
**form_data.model_dump(),
|
|
||||||
"user_id": user_id,
|
|
||||||
"created_at": int(time.time()),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
file = FileModel(
|
||||||
result = File(**file.model_dump())
|
**{
|
||||||
Session.add(result)
|
**form_data.model_dump(),
|
||||||
Session.commit()
|
"user_id": user_id,
|
||||||
Session.refresh(result)
|
"created_at": int(time.time()),
|
||||||
if result:
|
}
|
||||||
return FileModel.model_validate(result)
|
)
|
||||||
else:
|
|
||||||
|
try:
|
||||||
|
result = File(**file.model_dump())
|
||||||
|
db.add(result)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(result)
|
||||||
|
if result:
|
||||||
|
return FileModel.model_validate(result)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error creating tool: {e}")
|
||||||
return None
|
return None
|
||||||
except Exception as e:
|
|
||||||
print(f"Error creating tool: {e}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
def get_file_by_id(self, id: str) -> Optional[FileModel]:
|
def get_file_by_id(self, id: str) -> Optional[FileModel]:
|
||||||
try:
|
with get_db() as db:
|
||||||
file = Session.get(File, id)
|
|
||||||
return FileModel.model_validate(file)
|
try:
|
||||||
except:
|
file = db.get(File, id)
|
||||||
return None
|
return FileModel.model_validate(file)
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
def get_files(self) -> List[FileModel]:
|
def get_files(self) -> List[FileModel]:
|
||||||
return [FileModel.model_validate(file) for file in Session.query(File).all()]
|
with get_db() as db:
|
||||||
|
|
||||||
|
return [FileModel.model_validate(file) for file in db.query(File).all()]
|
||||||
|
|
||||||
def delete_file_by_id(self, id: str) -> bool:
|
def delete_file_by_id(self, id: str) -> bool:
|
||||||
try:
|
|
||||||
Session.query(File).filter_by(id=id).delete()
|
with get_db() as db:
|
||||||
return True
|
|
||||||
except:
|
try:
|
||||||
return False
|
db.query(File).filter_by(id=id).delete()
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
def delete_all_files(self) -> bool:
|
def delete_all_files(self) -> bool:
|
||||||
try:
|
|
||||||
Session.query(File).delete()
|
with get_db() as db:
|
||||||
return True
|
|
||||||
except:
|
try:
|
||||||
return False
|
db.query(File).delete()
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
Files = FilesTable()
|
Files = FilesTable()
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import logging
|
|||||||
|
|
||||||
from sqlalchemy import Column, String, Text, BigInteger, Boolean
|
from sqlalchemy import Column, String, Text, BigInteger, Boolean
|
||||||
|
|
||||||
from apps.webui.internal.db import JSONField, Base, Session
|
from apps.webui.internal.db import JSONField, Base, get_db
|
||||||
from apps.webui.models.users import Users
|
from apps.webui.models.users import Users
|
||||||
|
|
||||||
import json
|
import json
|
||||||
@@ -91,6 +91,7 @@ class FunctionsTable:
|
|||||||
def insert_new_function(
|
def insert_new_function(
|
||||||
self, user_id: str, type: str, form_data: FunctionForm
|
self, user_id: str, type: str, form_data: FunctionForm
|
||||||
) -> Optional[FunctionModel]:
|
) -> Optional[FunctionModel]:
|
||||||
|
|
||||||
function = FunctionModel(
|
function = FunctionModel(
|
||||||
**{
|
**{
|
||||||
**form_data.model_dump(),
|
**form_data.model_dump(),
|
||||||
@@ -102,88 +103,102 @@ class FunctionsTable:
|
|||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = Function(**function.model_dump())
|
with get_db() as db:
|
||||||
Session.add(result)
|
result = Function(**function.model_dump())
|
||||||
Session.commit()
|
db.add(result)
|
||||||
Session.refresh(result)
|
db.commit()
|
||||||
if result:
|
db.refresh(result)
|
||||||
return FunctionModel.model_validate(result)
|
if result:
|
||||||
else:
|
return FunctionModel.model_validate(result)
|
||||||
return None
|
else:
|
||||||
|
return None
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error creating tool: {e}")
|
print(f"Error creating tool: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_function_by_id(self, id: str) -> Optional[FunctionModel]:
|
def get_function_by_id(self, id: str) -> Optional[FunctionModel]:
|
||||||
try:
|
try:
|
||||||
function = Session.get(Function, id)
|
with get_db() as db:
|
||||||
return FunctionModel.model_validate(function)
|
|
||||||
|
function = db.get(Function, id)
|
||||||
|
return FunctionModel.model_validate(function)
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_functions(self, active_only=False) -> List[FunctionModel]:
|
def get_functions(self, active_only=False) -> List[FunctionModel]:
|
||||||
if active_only:
|
with get_db() as db:
|
||||||
return [
|
|
||||||
FunctionModel.model_validate(function)
|
if active_only:
|
||||||
for function in Session.query(Function).filter_by(is_active=True).all()
|
return [
|
||||||
]
|
FunctionModel.model_validate(function)
|
||||||
else:
|
for function in db.query(Function).filter_by(is_active=True).all()
|
||||||
return [
|
]
|
||||||
FunctionModel.model_validate(function)
|
else:
|
||||||
for function in Session.query(Function).all()
|
return [
|
||||||
]
|
FunctionModel.model_validate(function)
|
||||||
|
for function in db.query(Function).all()
|
||||||
|
]
|
||||||
|
|
||||||
def get_functions_by_type(
|
def get_functions_by_type(
|
||||||
self, type: str, active_only=False
|
self, type: str, active_only=False
|
||||||
) -> List[FunctionModel]:
|
) -> List[FunctionModel]:
|
||||||
if active_only:
|
with get_db() as db:
|
||||||
return [
|
|
||||||
FunctionModel.model_validate(function)
|
if active_only:
|
||||||
for function in Session.query(Function)
|
return [
|
||||||
.filter_by(type=type, is_active=True)
|
FunctionModel.model_validate(function)
|
||||||
.all()
|
for function in db.query(Function)
|
||||||
]
|
.filter_by(type=type, is_active=True)
|
||||||
else:
|
.all()
|
||||||
return [
|
]
|
||||||
FunctionModel.model_validate(function)
|
else:
|
||||||
for function in Session.query(Function).filter_by(type=type).all()
|
return [
|
||||||
]
|
FunctionModel.model_validate(function)
|
||||||
|
for function in db.query(Function).filter_by(type=type).all()
|
||||||
|
]
|
||||||
|
|
||||||
def get_global_filter_functions(self) -> List[FunctionModel]:
|
def get_global_filter_functions(self) -> List[FunctionModel]:
|
||||||
return [
|
with get_db() as db:
|
||||||
FunctionModel.model_validate(function)
|
|
||||||
for function in Session.query(Function)
|
return [
|
||||||
.filter_by(type="filter", is_active=True, is_global=True)
|
FunctionModel.model_validate(function)
|
||||||
.all()
|
for function in db.query(Function)
|
||||||
]
|
.filter_by(type="filter", is_active=True, is_global=True)
|
||||||
|
.all()
|
||||||
|
]
|
||||||
|
|
||||||
def get_function_valves_by_id(self, id: str) -> Optional[dict]:
|
def get_function_valves_by_id(self, id: str) -> Optional[dict]:
|
||||||
try:
|
with get_db() as db:
|
||||||
function = Session.get(Function, id)
|
|
||||||
return function.valves if function.valves else {}
|
try:
|
||||||
except Exception as e:
|
function = db.get(Function, id)
|
||||||
print(f"An error occurred: {e}")
|
return function.valves if function.valves else {}
|
||||||
return None
|
except Exception as e:
|
||||||
|
print(f"An error occurred: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
def update_function_valves_by_id(
|
def update_function_valves_by_id(
|
||||||
self, id: str, valves: dict
|
self, id: str, valves: dict
|
||||||
) -> Optional[FunctionValves]:
|
) -> Optional[FunctionValves]:
|
||||||
try:
|
with get_db() as db:
|
||||||
function = Session.get(Function, id)
|
|
||||||
function.valves = valves
|
try:
|
||||||
function.updated_at = int(time.time())
|
function = db.get(Function, id)
|
||||||
Session.commit()
|
function.valves = valves
|
||||||
Session.refresh(function)
|
function.updated_at = int(time.time())
|
||||||
return self.get_function_by_id(id)
|
db.commit()
|
||||||
except:
|
db.refresh(function)
|
||||||
return None
|
return self.get_function_by_id(id)
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
def get_user_valves_by_id_and_user_id(
|
def get_user_valves_by_id_and_user_id(
|
||||||
self, id: str, user_id: str
|
self, id: str, user_id: str
|
||||||
) -> Optional[dict]:
|
) -> Optional[dict]:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
user = Users.get_user_by_id(user_id)
|
user = Users.get_user_by_id(user_id)
|
||||||
user_settings = user.settings.model_dump()
|
user_settings = user.settings.model_dump() if user.settings else {}
|
||||||
|
|
||||||
# Check if user has "functions" and "valves" settings
|
# Check if user has "functions" and "valves" settings
|
||||||
if "functions" not in user_settings:
|
if "functions" not in user_settings:
|
||||||
@@ -199,9 +214,10 @@ class FunctionsTable:
|
|||||||
def update_user_valves_by_id_and_user_id(
|
def update_user_valves_by_id_and_user_id(
|
||||||
self, id: str, user_id: str, valves: dict
|
self, id: str, user_id: str, valves: dict
|
||||||
) -> Optional[dict]:
|
) -> Optional[dict]:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
user = Users.get_user_by_id(user_id)
|
user = Users.get_user_by_id(user_id)
|
||||||
user_settings = user.settings.model_dump()
|
user_settings = user.settings.model_dump() if user.settings else {}
|
||||||
|
|
||||||
# Check if user has "functions" and "valves" settings
|
# Check if user has "functions" and "valves" settings
|
||||||
if "functions" not in user_settings:
|
if "functions" not in user_settings:
|
||||||
@@ -220,37 +236,43 @@ class FunctionsTable:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def update_function_by_id(self, id: str, updated: dict) -> Optional[FunctionModel]:
|
def update_function_by_id(self, id: str, updated: dict) -> Optional[FunctionModel]:
|
||||||
try:
|
with get_db() as db:
|
||||||
Session.query(Function).filter_by(id=id).update(
|
|
||||||
{
|
try:
|
||||||
**updated,
|
db.query(Function).filter_by(id=id).update(
|
||||||
"updated_at": int(time.time()),
|
{
|
||||||
}
|
**updated,
|
||||||
)
|
"updated_at": int(time.time()),
|
||||||
Session.commit()
|
}
|
||||||
return self.get_function_by_id(id)
|
)
|
||||||
except:
|
db.commit()
|
||||||
return None
|
return self.get_function_by_id(id)
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
def deactivate_all_functions(self) -> Optional[bool]:
|
def deactivate_all_functions(self) -> Optional[bool]:
|
||||||
try:
|
with get_db() as db:
|
||||||
Session.query(Function).update(
|
|
||||||
{
|
try:
|
||||||
"is_active": False,
|
db.query(Function).update(
|
||||||
"updated_at": int(time.time()),
|
{
|
||||||
}
|
"is_active": False,
|
||||||
)
|
"updated_at": int(time.time()),
|
||||||
Session.commit()
|
}
|
||||||
return True
|
)
|
||||||
except:
|
db.commit()
|
||||||
return None
|
return True
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
def delete_function_by_id(self, id: str) -> bool:
|
def delete_function_by_id(self, id: str) -> bool:
|
||||||
try:
|
with get_db() as db:
|
||||||
Session.query(Function).filter_by(id=id).delete()
|
|
||||||
return True
|
try:
|
||||||
except:
|
db.query(Function).filter_by(id=id).delete()
|
||||||
return False
|
return True
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
Functions = FunctionsTable()
|
Functions = FunctionsTable()
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from typing import List, Union, Optional
|
|||||||
|
|
||||||
from sqlalchemy import Column, String, BigInteger, Text
|
from sqlalchemy import Column, String, BigInteger, Text
|
||||||
|
|
||||||
from apps.webui.internal.db import Base, Session
|
from apps.webui.internal.db import Base, get_db
|
||||||
|
|
||||||
import time
|
import time
|
||||||
import uuid
|
import uuid
|
||||||
@@ -45,82 +45,98 @@ class MemoriesTable:
|
|||||||
user_id: str,
|
user_id: str,
|
||||||
content: str,
|
content: str,
|
||||||
) -> Optional[MemoryModel]:
|
) -> Optional[MemoryModel]:
|
||||||
id = str(uuid.uuid4())
|
|
||||||
|
|
||||||
memory = MemoryModel(
|
with get_db() as db:
|
||||||
**{
|
id = str(uuid.uuid4())
|
||||||
"id": id,
|
|
||||||
"user_id": user_id,
|
memory = MemoryModel(
|
||||||
"content": content,
|
**{
|
||||||
"created_at": int(time.time()),
|
"id": id,
|
||||||
"updated_at": int(time.time()),
|
"user_id": user_id,
|
||||||
}
|
"content": content,
|
||||||
)
|
"created_at": int(time.time()),
|
||||||
result = Memory(**memory.model_dump())
|
"updated_at": int(time.time()),
|
||||||
Session.add(result)
|
}
|
||||||
Session.commit()
|
)
|
||||||
Session.refresh(result)
|
result = Memory(**memory.model_dump())
|
||||||
if result:
|
db.add(result)
|
||||||
return MemoryModel.model_validate(result)
|
db.commit()
|
||||||
else:
|
db.refresh(result)
|
||||||
return None
|
if result:
|
||||||
|
return MemoryModel.model_validate(result)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
def update_memory_by_id(
|
def update_memory_by_id(
|
||||||
self,
|
self,
|
||||||
id: str,
|
id: str,
|
||||||
content: str,
|
content: str,
|
||||||
) -> Optional[MemoryModel]:
|
) -> Optional[MemoryModel]:
|
||||||
try:
|
with get_db() as db:
|
||||||
Session.query(Memory).filter_by(id=id).update(
|
|
||||||
{"content": content, "updated_at": int(time.time())}
|
try:
|
||||||
)
|
db.query(Memory).filter_by(id=id).update(
|
||||||
Session.commit()
|
{"content": content, "updated_at": int(time.time())}
|
||||||
return self.get_memory_by_id(id)
|
)
|
||||||
except:
|
db.commit()
|
||||||
return None
|
return self.get_memory_by_id(id)
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
def get_memories(self) -> List[MemoryModel]:
|
def get_memories(self) -> List[MemoryModel]:
|
||||||
try:
|
with get_db() as db:
|
||||||
memories = Session.query(Memory).all()
|
|
||||||
return [MemoryModel.model_validate(memory) for memory in memories]
|
try:
|
||||||
except:
|
memories = db.query(Memory).all()
|
||||||
return None
|
return [MemoryModel.model_validate(memory) for memory in memories]
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
def get_memories_by_user_id(self, user_id: str) -> List[MemoryModel]:
|
def get_memories_by_user_id(self, user_id: str) -> List[MemoryModel]:
|
||||||
try:
|
with get_db() as db:
|
||||||
memories = Session.query(Memory).filter_by(user_id=user_id).all()
|
|
||||||
return [MemoryModel.model_validate(memory) for memory in memories]
|
try:
|
||||||
except:
|
memories = db.query(Memory).filter_by(user_id=user_id).all()
|
||||||
return None
|
return [MemoryModel.model_validate(memory) for memory in memories]
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
def get_memory_by_id(self, id: str) -> Optional[MemoryModel]:
|
def get_memory_by_id(self, id: str) -> Optional[MemoryModel]:
|
||||||
try:
|
with get_db() as db:
|
||||||
memory = Session.get(Memory, id)
|
|
||||||
return MemoryModel.model_validate(memory)
|
try:
|
||||||
except:
|
memory = db.get(Memory, id)
|
||||||
return None
|
return MemoryModel.model_validate(memory)
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
def delete_memory_by_id(self, id: str) -> bool:
|
def delete_memory_by_id(self, id: str) -> bool:
|
||||||
try:
|
with get_db() as db:
|
||||||
Session.query(Memory).filter_by(id=id).delete()
|
|
||||||
return True
|
|
||||||
|
|
||||||
except:
|
try:
|
||||||
return False
|
db.query(Memory).filter_by(id=id).delete()
|
||||||
|
return True
|
||||||
|
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
def delete_memories_by_user_id(self, user_id: str) -> bool:
|
def delete_memories_by_user_id(self, user_id: str) -> bool:
|
||||||
try:
|
with get_db() as db:
|
||||||
Session.query(Memory).filter_by(user_id=user_id).delete()
|
|
||||||
return True
|
try:
|
||||||
except:
|
db.query(Memory).filter_by(user_id=user_id).delete()
|
||||||
return False
|
return True
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
def delete_memory_by_id_and_user_id(self, id: str, user_id: str) -> bool:
|
def delete_memory_by_id_and_user_id(self, id: str, user_id: str) -> bool:
|
||||||
try:
|
with get_db() as db:
|
||||||
Session.query(Memory).filter_by(id=id, user_id=user_id).delete()
|
|
||||||
return True
|
try:
|
||||||
except:
|
db.query(Memory).filter_by(id=id, user_id=user_id).delete()
|
||||||
return False
|
return True
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
Memories = MemoriesTable()
|
Memories = MemoriesTable()
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from typing import Optional
|
|||||||
from pydantic import BaseModel, ConfigDict
|
from pydantic import BaseModel, ConfigDict
|
||||||
from sqlalchemy import String, Column, BigInteger, Text
|
from sqlalchemy import String, Column, BigInteger, Text
|
||||||
|
|
||||||
from apps.webui.internal.db import Base, JSONField, Session
|
from apps.webui.internal.db import Base, JSONField, get_db
|
||||||
|
|
||||||
from typing import List, Union, Optional
|
from typing import List, Union, Optional
|
||||||
from config import SRC_LOG_LEVELS
|
from config import SRC_LOG_LEVELS
|
||||||
@@ -126,39 +126,46 @@ class ModelsTable:
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
result = Model(**model.model_dump())
|
|
||||||
Session.add(result)
|
|
||||||
Session.commit()
|
|
||||||
Session.refresh(result)
|
|
||||||
|
|
||||||
if result:
|
with get_db() as db:
|
||||||
return ModelModel.model_validate(result)
|
|
||||||
else:
|
result = Model(**model.model_dump())
|
||||||
return None
|
db.add(result)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(result)
|
||||||
|
|
||||||
|
if result:
|
||||||
|
return ModelModel.model_validate(result)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_all_models(self) -> List[ModelModel]:
|
def get_all_models(self) -> List[ModelModel]:
|
||||||
return [
|
with get_db() as db:
|
||||||
ModelModel.model_validate(model) for model in Session.query(Model).all()
|
|
||||||
]
|
return [ModelModel.model_validate(model) for model in db.query(Model).all()]
|
||||||
|
|
||||||
def get_model_by_id(self, id: str) -> Optional[ModelModel]:
|
def get_model_by_id(self, id: str) -> Optional[ModelModel]:
|
||||||
try:
|
try:
|
||||||
model = Session.get(Model, id)
|
with get_db() as db:
|
||||||
return ModelModel.model_validate(model)
|
|
||||||
|
model = db.get(Model, id)
|
||||||
|
return ModelModel.model_validate(model)
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def update_model_by_id(self, id: str, model: ModelForm) -> Optional[ModelModel]:
|
def update_model_by_id(self, id: str, model: ModelForm) -> Optional[ModelModel]:
|
||||||
try:
|
try:
|
||||||
# update only the fields that are present in the model
|
with get_db() as db:
|
||||||
model = Session.query(Model).get(id)
|
|
||||||
model.update(**model.model_dump())
|
# update only the fields that are present in the model
|
||||||
Session.commit()
|
model = db.query(Model).get(id)
|
||||||
Session.refresh(model)
|
model.update(**model.model_dump())
|
||||||
return ModelModel.model_validate(model)
|
db.commit()
|
||||||
|
db.refresh(model)
|
||||||
|
return ModelModel.model_validate(model)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
@@ -166,8 +173,10 @@ class ModelsTable:
|
|||||||
|
|
||||||
def delete_model_by_id(self, id: str) -> bool:
|
def delete_model_by_id(self, id: str) -> bool:
|
||||||
try:
|
try:
|
||||||
Session.query(Model).filter_by(id=id).delete()
|
with get_db() as db:
|
||||||
return True
|
|
||||||
|
db.query(Model).filter_by(id=id).delete()
|
||||||
|
return True
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import time
|
|||||||
|
|
||||||
from sqlalchemy import String, Column, BigInteger, Text
|
from sqlalchemy import String, Column, BigInteger, Text
|
||||||
|
|
||||||
from apps.webui.internal.db import Base, Session
|
from apps.webui.internal.db import Base, get_db
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
@@ -60,46 +60,56 @@ class PromptsTable:
|
|||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = Prompt(**prompt.dict())
|
with get_db() as db:
|
||||||
Session.add(result)
|
|
||||||
Session.commit()
|
result = Prompt(**prompt.dict())
|
||||||
Session.refresh(result)
|
db.add(result)
|
||||||
if result:
|
db.commit()
|
||||||
return PromptModel.model_validate(result)
|
db.refresh(result)
|
||||||
else:
|
if result:
|
||||||
return None
|
return PromptModel.model_validate(result)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_prompt_by_command(self, command: str) -> Optional[PromptModel]:
|
def get_prompt_by_command(self, command: str) -> Optional[PromptModel]:
|
||||||
try:
|
try:
|
||||||
prompt = Session.query(Prompt).filter_by(command=command).first()
|
with get_db() as db:
|
||||||
return PromptModel.model_validate(prompt)
|
|
||||||
|
prompt = db.query(Prompt).filter_by(command=command).first()
|
||||||
|
return PromptModel.model_validate(prompt)
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_prompts(self) -> List[PromptModel]:
|
def get_prompts(self) -> List[PromptModel]:
|
||||||
return [
|
with get_db() as db:
|
||||||
PromptModel.model_validate(prompt) for prompt in Session.query(Prompt).all()
|
|
||||||
]
|
return [
|
||||||
|
PromptModel.model_validate(prompt) for prompt in db.query(Prompt).all()
|
||||||
|
]
|
||||||
|
|
||||||
def update_prompt_by_command(
|
def update_prompt_by_command(
|
||||||
self, command: str, form_data: PromptForm
|
self, command: str, form_data: PromptForm
|
||||||
) -> Optional[PromptModel]:
|
) -> Optional[PromptModel]:
|
||||||
try:
|
try:
|
||||||
prompt = Session.query(Prompt).filter_by(command=command).first()
|
with get_db() as db:
|
||||||
prompt.title = form_data.title
|
|
||||||
prompt.content = form_data.content
|
prompt = db.query(Prompt).filter_by(command=command).first()
|
||||||
prompt.timestamp = int(time.time())
|
prompt.title = form_data.title
|
||||||
Session.commit()
|
prompt.content = form_data.content
|
||||||
return PromptModel.model_validate(prompt)
|
prompt.timestamp = int(time.time())
|
||||||
|
db.commit()
|
||||||
|
return PromptModel.model_validate(prompt)
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def delete_prompt_by_command(self, command: str) -> bool:
|
def delete_prompt_by_command(self, command: str) -> bool:
|
||||||
try:
|
try:
|
||||||
Session.query(Prompt).filter_by(command=command).delete()
|
with get_db() as db:
|
||||||
return True
|
|
||||||
|
db.query(Prompt).filter_by(command=command).delete()
|
||||||
|
return True
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import logging
|
|||||||
|
|
||||||
from sqlalchemy import String, Column, BigInteger, Text
|
from sqlalchemy import String, Column, BigInteger, Text
|
||||||
|
|
||||||
from apps.webui.internal.db import Base, Session
|
from apps.webui.internal.db import Base, get_db
|
||||||
|
|
||||||
from config import SRC_LOG_LEVELS
|
from config import SRC_LOG_LEVELS
|
||||||
|
|
||||||
@@ -79,26 +79,29 @@ class ChatTagsResponse(BaseModel):
|
|||||||
class TagTable:
|
class TagTable:
|
||||||
|
|
||||||
def insert_new_tag(self, name: str, user_id: str) -> Optional[TagModel]:
|
def insert_new_tag(self, name: str, user_id: str) -> Optional[TagModel]:
|
||||||
id = str(uuid.uuid4())
|
with get_db() as db:
|
||||||
tag = TagModel(**{"id": id, "user_id": user_id, "name": name})
|
|
||||||
try:
|
id = str(uuid.uuid4())
|
||||||
result = Tag(**tag.model_dump())
|
tag = TagModel(**{"id": id, "user_id": user_id, "name": name})
|
||||||
Session.add(result)
|
try:
|
||||||
Session.commit()
|
result = Tag(**tag.model_dump())
|
||||||
Session.refresh(result)
|
db.add(result)
|
||||||
if result:
|
db.commit()
|
||||||
return TagModel.model_validate(result)
|
db.refresh(result)
|
||||||
else:
|
if result:
|
||||||
|
return TagModel.model_validate(result)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
except Exception as e:
|
||||||
return None
|
return None
|
||||||
except Exception as e:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def get_tag_by_name_and_user_id(
|
def get_tag_by_name_and_user_id(
|
||||||
self, name: str, user_id: str
|
self, name: str, user_id: str
|
||||||
) -> Optional[TagModel]:
|
) -> Optional[TagModel]:
|
||||||
try:
|
try:
|
||||||
tag = Session.query(Tag).filter(name=name, user_id=user_id).first()
|
with get_db() as db:
|
||||||
return TagModel.model_validate(tag)
|
tag = db.query(Tag).filter(name=name, user_id=user_id).first()
|
||||||
|
return TagModel.model_validate(tag)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -120,98 +123,109 @@ class TagTable:
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
result = ChatIdTag(**chatIdTag.model_dump())
|
with get_db() as db:
|
||||||
Session.add(result)
|
result = ChatIdTag(**chatIdTag.model_dump())
|
||||||
Session.commit()
|
db.add(result)
|
||||||
Session.refresh(result)
|
db.commit()
|
||||||
if result:
|
db.refresh(result)
|
||||||
return ChatIdTagModel.model_validate(result)
|
if result:
|
||||||
else:
|
return ChatIdTagModel.model_validate(result)
|
||||||
return None
|
else:
|
||||||
|
return None
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_tags_by_user_id(self, user_id: str) -> List[TagModel]:
|
def get_tags_by_user_id(self, user_id: str) -> List[TagModel]:
|
||||||
tag_names = [
|
with get_db() as db:
|
||||||
chat_id_tag.tag_name
|
tag_names = [
|
||||||
for chat_id_tag in (
|
chat_id_tag.tag_name
|
||||||
Session.query(ChatIdTag)
|
for chat_id_tag in (
|
||||||
.filter_by(user_id=user_id)
|
db.query(ChatIdTag)
|
||||||
.order_by(ChatIdTag.timestamp.desc())
|
.filter_by(user_id=user_id)
|
||||||
.all()
|
.order_by(ChatIdTag.timestamp.desc())
|
||||||
)
|
.all()
|
||||||
]
|
)
|
||||||
|
]
|
||||||
|
|
||||||
return [
|
return [
|
||||||
TagModel.model_validate(tag)
|
TagModel.model_validate(tag)
|
||||||
for tag in (
|
for tag in (
|
||||||
Session.query(Tag)
|
db.query(Tag)
|
||||||
.filter_by(user_id=user_id)
|
.filter_by(user_id=user_id)
|
||||||
.filter(Tag.name.in_(tag_names))
|
.filter(Tag.name.in_(tag_names))
|
||||||
.all()
|
.all()
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_tags_by_chat_id_and_user_id(
|
def get_tags_by_chat_id_and_user_id(
|
||||||
self, chat_id: str, user_id: str
|
self, chat_id: str, user_id: str
|
||||||
) -> List[TagModel]:
|
) -> List[TagModel]:
|
||||||
tag_names = [
|
with get_db() as db:
|
||||||
chat_id_tag.tag_name
|
|
||||||
for chat_id_tag in (
|
|
||||||
Session.query(ChatIdTag)
|
|
||||||
.filter_by(user_id=user_id, chat_id=chat_id)
|
|
||||||
.order_by(ChatIdTag.timestamp.desc())
|
|
||||||
.all()
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
return [
|
tag_names = [
|
||||||
TagModel.model_validate(tag)
|
chat_id_tag.tag_name
|
||||||
for tag in (
|
for chat_id_tag in (
|
||||||
Session.query(Tag)
|
db.query(ChatIdTag)
|
||||||
.filter_by(user_id=user_id)
|
.filter_by(user_id=user_id, chat_id=chat_id)
|
||||||
.filter(Tag.name.in_(tag_names))
|
.order_by(ChatIdTag.timestamp.desc())
|
||||||
.all()
|
.all()
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
return [
|
||||||
|
TagModel.model_validate(tag)
|
||||||
|
for tag in (
|
||||||
|
db.query(Tag)
|
||||||
|
.filter_by(user_id=user_id)
|
||||||
|
.filter(Tag.name.in_(tag_names))
|
||||||
|
.all()
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
def get_chat_ids_by_tag_name_and_user_id(
|
def get_chat_ids_by_tag_name_and_user_id(
|
||||||
self, tag_name: str, user_id: str
|
self, tag_name: str, user_id: str
|
||||||
) -> List[ChatIdTagModel]:
|
) -> List[ChatIdTagModel]:
|
||||||
return [
|
with get_db() as db:
|
||||||
ChatIdTagModel.model_validate(chat_id_tag)
|
|
||||||
for chat_id_tag in (
|
return [
|
||||||
Session.query(ChatIdTag)
|
ChatIdTagModel.model_validate(chat_id_tag)
|
||||||
.filter_by(user_id=user_id, tag_name=tag_name)
|
for chat_id_tag in (
|
||||||
.order_by(ChatIdTag.timestamp.desc())
|
db.query(ChatIdTag)
|
||||||
.all()
|
.filter_by(user_id=user_id, tag_name=tag_name)
|
||||||
)
|
.order_by(ChatIdTag.timestamp.desc())
|
||||||
]
|
.all()
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
def count_chat_ids_by_tag_name_and_user_id(
|
def count_chat_ids_by_tag_name_and_user_id(
|
||||||
self, tag_name: str, user_id: str
|
self, tag_name: str, user_id: str
|
||||||
) -> int:
|
) -> int:
|
||||||
return (
|
with get_db() as db:
|
||||||
Session.query(ChatIdTag)
|
|
||||||
.filter_by(tag_name=tag_name, user_id=user_id)
|
return (
|
||||||
.count()
|
db.query(ChatIdTag)
|
||||||
)
|
.filter_by(tag_name=tag_name, user_id=user_id)
|
||||||
|
.count()
|
||||||
|
)
|
||||||
|
|
||||||
def delete_tag_by_tag_name_and_user_id(self, tag_name: str, user_id: str) -> bool:
|
def delete_tag_by_tag_name_and_user_id(self, tag_name: str, user_id: str) -> bool:
|
||||||
try:
|
try:
|
||||||
res = (
|
with get_db() as db:
|
||||||
Session.query(ChatIdTag)
|
res = (
|
||||||
.filter_by(tag_name=tag_name, user_id=user_id)
|
db.query(ChatIdTag)
|
||||||
.delete()
|
.filter_by(tag_name=tag_name, user_id=user_id)
|
||||||
)
|
.delete()
|
||||||
log.debug(f"res: {res}")
|
)
|
||||||
Session.commit()
|
log.debug(f"res: {res}")
|
||||||
|
db.commit()
|
||||||
|
|
||||||
tag_count = self.count_chat_ids_by_tag_name_and_user_id(tag_name, user_id)
|
tag_count = self.count_chat_ids_by_tag_name_and_user_id(
|
||||||
if tag_count == 0:
|
tag_name, user_id
|
||||||
# Remove tag item from Tag col as well
|
)
|
||||||
Session.query(Tag).filter_by(name=tag_name, user_id=user_id).delete()
|
if tag_count == 0:
|
||||||
return True
|
# Remove tag item from Tag col as well
|
||||||
|
db.query(Tag).filter_by(name=tag_name, user_id=user_id).delete()
|
||||||
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.error(f"delete_tag: {e}")
|
log.error(f"delete_tag: {e}")
|
||||||
return False
|
return False
|
||||||
@@ -220,20 +234,24 @@ class TagTable:
|
|||||||
self, tag_name: str, chat_id: str, user_id: str
|
self, tag_name: str, chat_id: str, user_id: str
|
||||||
) -> bool:
|
) -> bool:
|
||||||
try:
|
try:
|
||||||
res = (
|
with get_db() as db:
|
||||||
Session.query(ChatIdTag)
|
|
||||||
.filter_by(tag_name=tag_name, chat_id=chat_id, user_id=user_id)
|
|
||||||
.delete()
|
|
||||||
)
|
|
||||||
log.debug(f"res: {res}")
|
|
||||||
Session.commit()
|
|
||||||
|
|
||||||
tag_count = self.count_chat_ids_by_tag_name_and_user_id(tag_name, user_id)
|
res = (
|
||||||
if tag_count == 0:
|
db.query(ChatIdTag)
|
||||||
# Remove tag item from Tag col as well
|
.filter_by(tag_name=tag_name, chat_id=chat_id, user_id=user_id)
|
||||||
Session.query(Tag).filter_by(name=tag_name, user_id=user_id).delete()
|
.delete()
|
||||||
|
)
|
||||||
|
log.debug(f"res: {res}")
|
||||||
|
db.commit()
|
||||||
|
|
||||||
return True
|
tag_count = self.count_chat_ids_by_tag_name_and_user_id(
|
||||||
|
tag_name, user_id
|
||||||
|
)
|
||||||
|
if tag_count == 0:
|
||||||
|
# Remove tag item from Tag col as well
|
||||||
|
db.query(Tag).filter_by(name=tag_name, user_id=user_id).delete()
|
||||||
|
|
||||||
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.error(f"delete_tag: {e}")
|
log.error(f"delete_tag: {e}")
|
||||||
return False
|
return False
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import time
|
|||||||
import logging
|
import logging
|
||||||
from sqlalchemy import String, Column, BigInteger, Text
|
from sqlalchemy import String, Column, BigInteger, Text
|
||||||
|
|
||||||
from apps.webui.internal.db import Base, JSONField, Session
|
from apps.webui.internal.db import Base, JSONField, get_db
|
||||||
from apps.webui.models.users import Users
|
from apps.webui.models.users import Users
|
||||||
|
|
||||||
import json
|
import json
|
||||||
@@ -83,54 +83,64 @@ class ToolsTable:
|
|||||||
def insert_new_tool(
|
def insert_new_tool(
|
||||||
self, user_id: str, form_data: ToolForm, specs: List[dict]
|
self, user_id: str, form_data: ToolForm, specs: List[dict]
|
||||||
) -> Optional[ToolModel]:
|
) -> Optional[ToolModel]:
|
||||||
tool = ToolModel(
|
|
||||||
**{
|
|
||||||
**form_data.model_dump(),
|
|
||||||
"specs": specs,
|
|
||||||
"user_id": user_id,
|
|
||||||
"updated_at": int(time.time()),
|
|
||||||
"created_at": int(time.time()),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
with get_db() as db:
|
||||||
result = Tool(**tool.model_dump())
|
|
||||||
Session.add(result)
|
tool = ToolModel(
|
||||||
Session.commit()
|
**{
|
||||||
Session.refresh(result)
|
**form_data.model_dump(),
|
||||||
if result:
|
"specs": specs,
|
||||||
return ToolModel.model_validate(result)
|
"user_id": user_id,
|
||||||
else:
|
"updated_at": int(time.time()),
|
||||||
|
"created_at": int(time.time()),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = Tool(**tool.model_dump())
|
||||||
|
db.add(result)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(result)
|
||||||
|
if result:
|
||||||
|
return ToolModel.model_validate(result)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error creating tool: {e}")
|
||||||
return None
|
return None
|
||||||
except Exception as e:
|
|
||||||
print(f"Error creating tool: {e}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
def get_tool_by_id(self, id: str) -> Optional[ToolModel]:
|
def get_tool_by_id(self, id: str) -> Optional[ToolModel]:
|
||||||
try:
|
try:
|
||||||
tool = Session.get(Tool, id)
|
with get_db() as db:
|
||||||
return ToolModel.model_validate(tool)
|
|
||||||
|
tool = db.get(Tool, id)
|
||||||
|
return ToolModel.model_validate(tool)
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_tools(self) -> List[ToolModel]:
|
def get_tools(self) -> List[ToolModel]:
|
||||||
return [ToolModel.model_validate(tool) for tool in Session.query(Tool).all()]
|
with get_db() as db:
|
||||||
|
return [ToolModel.model_validate(tool) for tool in db.query(Tool).all()]
|
||||||
|
|
||||||
def get_tool_valves_by_id(self, id: str) -> Optional[dict]:
|
def get_tool_valves_by_id(self, id: str) -> Optional[dict]:
|
||||||
try:
|
try:
|
||||||
tool = Session.get(Tool, id)
|
with get_db() as db:
|
||||||
return tool.valves if tool.valves else {}
|
|
||||||
|
tool = db.get(Tool, id)
|
||||||
|
return tool.valves if tool.valves else {}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"An error occurred: {e}")
|
print(f"An error occurred: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def update_tool_valves_by_id(self, id: str, valves: dict) -> Optional[ToolValves]:
|
def update_tool_valves_by_id(self, id: str, valves: dict) -> Optional[ToolValves]:
|
||||||
try:
|
try:
|
||||||
Session.query(Tool).filter_by(id=id).update(
|
with get_db() as db:
|
||||||
{"valves": valves, "updated_at": int(time.time())}
|
|
||||||
)
|
db.query(Tool).filter_by(id=id).update(
|
||||||
Session.commit()
|
{"valves": valves, "updated_at": int(time.time())}
|
||||||
return self.get_tool_by_id(id)
|
)
|
||||||
|
db.commit()
|
||||||
|
return self.get_tool_by_id(id)
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -139,7 +149,7 @@ class ToolsTable:
|
|||||||
) -> Optional[dict]:
|
) -> Optional[dict]:
|
||||||
try:
|
try:
|
||||||
user = Users.get_user_by_id(user_id)
|
user = Users.get_user_by_id(user_id)
|
||||||
user_settings = user.settings.model_dump()
|
user_settings = user.settings.model_dump() if user.settings else {}
|
||||||
|
|
||||||
# Check if user has "tools" and "valves" settings
|
# Check if user has "tools" and "valves" settings
|
||||||
if "tools" not in user_settings:
|
if "tools" not in user_settings:
|
||||||
@@ -157,7 +167,7 @@ class ToolsTable:
|
|||||||
) -> Optional[dict]:
|
) -> Optional[dict]:
|
||||||
try:
|
try:
|
||||||
user = Users.get_user_by_id(user_id)
|
user = Users.get_user_by_id(user_id)
|
||||||
user_settings = user.settings.model_dump()
|
user_settings = user.settings.model_dump() if user.settings else {}
|
||||||
|
|
||||||
# Check if user has "tools" and "valves" settings
|
# Check if user has "tools" and "valves" settings
|
||||||
if "tools" not in user_settings:
|
if "tools" not in user_settings:
|
||||||
@@ -177,19 +187,21 @@ class ToolsTable:
|
|||||||
|
|
||||||
def update_tool_by_id(self, id: str, updated: dict) -> Optional[ToolModel]:
|
def update_tool_by_id(self, id: str, updated: dict) -> Optional[ToolModel]:
|
||||||
try:
|
try:
|
||||||
tool = Session.get(Tool, id)
|
with get_db() as db:
|
||||||
tool.update(**updated)
|
tool = db.get(Tool, id)
|
||||||
tool.updated_at = int(time.time())
|
tool.update(**updated)
|
||||||
Session.commit()
|
tool.updated_at = int(time.time())
|
||||||
Session.refresh(tool)
|
db.commit()
|
||||||
return ToolModel.model_validate(tool)
|
db.refresh(tool)
|
||||||
|
return ToolModel.model_validate(tool)
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def delete_tool_by_id(self, id: str) -> bool:
|
def delete_tool_by_id(self, id: str) -> bool:
|
||||||
try:
|
try:
|
||||||
Session.query(Tool).filter_by(id=id).delete()
|
with get_db() as db:
|
||||||
return True
|
db.query(Tool).filter_by(id=id).delete()
|
||||||
|
return True
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from sqlalchemy import String, Column, BigInteger, Text
|
|||||||
|
|
||||||
from utils.misc import get_gravatar_url
|
from utils.misc import get_gravatar_url
|
||||||
|
|
||||||
from apps.webui.internal.db import Base, JSONField, Session
|
from apps.webui.internal.db import Base, JSONField, Session, get_db
|
||||||
from apps.webui.models.chats import Chats
|
from apps.webui.models.chats import Chats
|
||||||
|
|
||||||
####################
|
####################
|
||||||
@@ -88,81 +88,92 @@ class UsersTable:
|
|||||||
role: str = "pending",
|
role: str = "pending",
|
||||||
oauth_sub: Optional[str] = None,
|
oauth_sub: Optional[str] = None,
|
||||||
) -> Optional[UserModel]:
|
) -> Optional[UserModel]:
|
||||||
user = UserModel(
|
with get_db() as db:
|
||||||
**{
|
user = UserModel(
|
||||||
"id": id,
|
**{
|
||||||
"name": name,
|
"id": id,
|
||||||
"email": email,
|
"name": name,
|
||||||
"role": role,
|
"email": email,
|
||||||
"profile_image_url": profile_image_url,
|
"role": role,
|
||||||
"last_active_at": int(time.time()),
|
"profile_image_url": profile_image_url,
|
||||||
"created_at": int(time.time()),
|
"last_active_at": int(time.time()),
|
||||||
"updated_at": int(time.time()),
|
"created_at": int(time.time()),
|
||||||
"oauth_sub": oauth_sub,
|
"updated_at": int(time.time()),
|
||||||
}
|
"oauth_sub": oauth_sub,
|
||||||
)
|
}
|
||||||
result = User(**user.model_dump())
|
)
|
||||||
Session.add(result)
|
result = User(**user.model_dump())
|
||||||
Session.commit()
|
db.add(result)
|
||||||
Session.refresh(result)
|
db.commit()
|
||||||
if result:
|
db.refresh(result)
|
||||||
return user
|
if result:
|
||||||
else:
|
return user
|
||||||
return None
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
def get_user_by_id(self, id: str) -> Optional[UserModel]:
|
def get_user_by_id(self, id: str) -> Optional[UserModel]:
|
||||||
try:
|
try:
|
||||||
user = Session.query(User).filter_by(id=id).first()
|
with get_db() as db:
|
||||||
return UserModel.model_validate(user)
|
user = db.query(User).filter_by(id=id).first()
|
||||||
|
return UserModel.model_validate(user)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_user_by_api_key(self, api_key: str) -> Optional[UserModel]:
|
def get_user_by_api_key(self, api_key: str) -> Optional[UserModel]:
|
||||||
try:
|
try:
|
||||||
user = Session.query(User).filter_by(api_key=api_key).first()
|
with get_db() as db:
|
||||||
return UserModel.model_validate(user)
|
|
||||||
|
user = db.query(User).filter_by(api_key=api_key).first()
|
||||||
|
return UserModel.model_validate(user)
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_user_by_email(self, email: str) -> Optional[UserModel]:
|
def get_user_by_email(self, email: str) -> Optional[UserModel]:
|
||||||
try:
|
try:
|
||||||
user = Session.query(User).filter_by(email=email).first()
|
with get_db() as db:
|
||||||
return UserModel.model_validate(user)
|
|
||||||
|
user = db.query(User).filter_by(email=email).first()
|
||||||
|
return UserModel.model_validate(user)
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_user_by_oauth_sub(self, sub: str) -> Optional[UserModel]:
|
def get_user_by_oauth_sub(self, sub: str) -> Optional[UserModel]:
|
||||||
try:
|
try:
|
||||||
user = Session.query(User).filter_by(oauth_sub=sub).first()
|
with get_db() as db:
|
||||||
return UserModel.model_validate(user)
|
|
||||||
|
user = db.query(User).filter_by(oauth_sub=sub).first()
|
||||||
|
return UserModel.model_validate(user)
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_users(self, skip: int = 0, limit: int = 50) -> List[UserModel]:
|
def get_users(self, skip: int = 0, limit: int = 50) -> List[UserModel]:
|
||||||
users = (
|
with get_db() as db:
|
||||||
Session.query(User)
|
users = (
|
||||||
# .offset(skip).limit(limit)
|
db.query(User)
|
||||||
.all()
|
# .offset(skip).limit(limit)
|
||||||
)
|
.all()
|
||||||
return [UserModel.model_validate(user) for user in users]
|
)
|
||||||
|
return [UserModel.model_validate(user) for user in users]
|
||||||
|
|
||||||
def get_num_users(self) -> Optional[int]:
|
def get_num_users(self) -> Optional[int]:
|
||||||
return Session.query(User).count()
|
with get_db() as db:
|
||||||
|
return db.query(User).count()
|
||||||
|
|
||||||
def get_first_user(self) -> UserModel:
|
def get_first_user(self) -> UserModel:
|
||||||
try:
|
try:
|
||||||
user = Session.query(User).order_by(User.created_at).first()
|
with get_db() as db:
|
||||||
return UserModel.model_validate(user)
|
user = db.query(User).order_by(User.created_at).first()
|
||||||
|
return UserModel.model_validate(user)
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def update_user_role_by_id(self, id: str, role: str) -> Optional[UserModel]:
|
def update_user_role_by_id(self, id: str, role: str) -> Optional[UserModel]:
|
||||||
try:
|
try:
|
||||||
Session.query(User).filter_by(id=id).update({"role": role})
|
with get_db() as db:
|
||||||
Session.commit()
|
db.query(User).filter_by(id=id).update({"role": role})
|
||||||
|
db.commit()
|
||||||
user = Session.query(User).filter_by(id=id).first()
|
user = db.query(User).filter_by(id=id).first()
|
||||||
return UserModel.model_validate(user)
|
return UserModel.model_validate(user)
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -170,25 +181,28 @@ class UsersTable:
|
|||||||
self, id: str, profile_image_url: str
|
self, id: str, profile_image_url: str
|
||||||
) -> Optional[UserModel]:
|
) -> Optional[UserModel]:
|
||||||
try:
|
try:
|
||||||
Session.query(User).filter_by(id=id).update(
|
with get_db() as db:
|
||||||
{"profile_image_url": profile_image_url}
|
db.query(User).filter_by(id=id).update(
|
||||||
)
|
{"profile_image_url": profile_image_url}
|
||||||
Session.commit()
|
)
|
||||||
|
db.commit()
|
||||||
|
|
||||||
user = Session.query(User).filter_by(id=id).first()
|
user = db.query(User).filter_by(id=id).first()
|
||||||
return UserModel.model_validate(user)
|
return UserModel.model_validate(user)
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def update_user_last_active_by_id(self, id: str) -> Optional[UserModel]:
|
def update_user_last_active_by_id(self, id: str) -> Optional[UserModel]:
|
||||||
try:
|
try:
|
||||||
Session.query(User).filter_by(id=id).update(
|
with get_db() as db:
|
||||||
{"last_active_at": int(time.time())}
|
|
||||||
)
|
|
||||||
Session.commit()
|
|
||||||
|
|
||||||
user = Session.query(User).filter_by(id=id).first()
|
db.query(User).filter_by(id=id).update(
|
||||||
return UserModel.model_validate(user)
|
{"last_active_at": int(time.time())}
|
||||||
|
)
|
||||||
|
db.commit()
|
||||||
|
|
||||||
|
user = db.query(User).filter_by(id=id).first()
|
||||||
|
return UserModel.model_validate(user)
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -196,21 +210,23 @@ class UsersTable:
|
|||||||
self, id: str, oauth_sub: str
|
self, id: str, oauth_sub: str
|
||||||
) -> Optional[UserModel]:
|
) -> Optional[UserModel]:
|
||||||
try:
|
try:
|
||||||
Session.query(User).filter_by(id=id).update({"oauth_sub": oauth_sub})
|
with get_db() as db:
|
||||||
|
db.query(User).filter_by(id=id).update({"oauth_sub": oauth_sub})
|
||||||
|
|
||||||
user = Session.query(User).filter_by(id=id).first()
|
user = db.query(User).filter_by(id=id).first()
|
||||||
return UserModel.model_validate(user)
|
return UserModel.model_validate(user)
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def update_user_by_id(self, id: str, updated: dict) -> Optional[UserModel]:
|
def update_user_by_id(self, id: str, updated: dict) -> Optional[UserModel]:
|
||||||
try:
|
try:
|
||||||
Session.query(User).filter_by(id=id).update(updated)
|
with get_db() as db:
|
||||||
Session.commit()
|
db.query(User).filter_by(id=id).update(updated)
|
||||||
|
db.commit()
|
||||||
|
|
||||||
user = Session.query(User).filter_by(id=id).first()
|
user = db.query(User).filter_by(id=id).first()
|
||||||
return UserModel.model_validate(user)
|
return UserModel.model_validate(user)
|
||||||
# return UserModel(**user.dict())
|
# return UserModel(**user.dict())
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -220,9 +236,10 @@ class UsersTable:
|
|||||||
result = Chats.delete_chats_by_user_id(id)
|
result = Chats.delete_chats_by_user_id(id)
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
# Delete User
|
with get_db() as db:
|
||||||
Session.query(User).filter_by(id=id).delete()
|
# Delete User
|
||||||
Session.commit()
|
db.query(User).filter_by(id=id).delete()
|
||||||
|
db.commit()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
@@ -232,16 +249,18 @@ class UsersTable:
|
|||||||
|
|
||||||
def update_user_api_key_by_id(self, id: str, api_key: str) -> str:
|
def update_user_api_key_by_id(self, id: str, api_key: str) -> str:
|
||||||
try:
|
try:
|
||||||
result = Session.query(User).filter_by(id=id).update({"api_key": api_key})
|
with get_db() as db:
|
||||||
Session.commit()
|
result = db.query(User).filter_by(id=id).update({"api_key": api_key})
|
||||||
return True if result == 1 else False
|
db.commit()
|
||||||
|
return True if result == 1 else False
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_user_api_key_by_id(self, id: str) -> Optional[str]:
|
def get_user_api_key_by_id(self, id: str) -> Optional[str]:
|
||||||
try:
|
try:
|
||||||
user = Session.query(User).filter_by(id=id).first()
|
with get_db() as db:
|
||||||
return user.api_key
|
user = db.query(User).filter_by(id=id).first()
|
||||||
|
return user.api_key
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|||||||
@@ -999,12 +999,16 @@ async def get_all_models():
|
|||||||
model["info"] = custom_model.model_dump()
|
model["info"] = custom_model.model_dump()
|
||||||
else:
|
else:
|
||||||
owned_by = "openai"
|
owned_by = "openai"
|
||||||
|
pipe = None
|
||||||
|
|
||||||
for model in models:
|
for model in models:
|
||||||
if (
|
if (
|
||||||
custom_model.base_model_id == model["id"]
|
custom_model.base_model_id == model["id"]
|
||||||
or custom_model.base_model_id == model["id"].split(":")[0]
|
or custom_model.base_model_id == model["id"].split(":")[0]
|
||||||
):
|
):
|
||||||
owned_by = model["owned_by"]
|
owned_by = model["owned_by"]
|
||||||
|
if "pipe" in model:
|
||||||
|
pipe = model["pipe"]
|
||||||
break
|
break
|
||||||
|
|
||||||
models.append(
|
models.append(
|
||||||
@@ -1016,11 +1020,11 @@ async def get_all_models():
|
|||||||
"owned_by": owned_by,
|
"owned_by": owned_by,
|
||||||
"info": custom_model.model_dump(),
|
"info": custom_model.model_dump(),
|
||||||
"preset": True,
|
"preset": True,
|
||||||
|
**({"pipe": pipe} if pipe is not None else {}),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
app.state.MODELS = {model["id"]: model for model in models}
|
app.state.MODELS = {model["id"]: model for model in models}
|
||||||
|
|
||||||
webui_app.state.MODELS = app.state.MODELS
|
webui_app.state.MODELS = app.state.MODELS
|
||||||
|
|
||||||
return models
|
return models
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script>
|
<script>
|
||||||
import { getContext, tick } from 'svelte';
|
import { getContext, tick, onMount } from 'svelte';
|
||||||
import { toast } from 'svelte-sonner';
|
import { toast } from 'svelte-sonner';
|
||||||
|
|
||||||
import Database from './Settings/Database.svelte';
|
import Database from './Settings/Database.svelte';
|
||||||
@@ -21,11 +21,24 @@
|
|||||||
const i18n = getContext('i18n');
|
const i18n = getContext('i18n');
|
||||||
|
|
||||||
let selectedTab = 'general';
|
let selectedTab = 'general';
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
const containerElement = document.getElementById('admin-settings-tabs-container');
|
||||||
|
|
||||||
|
if (containerElement) {
|
||||||
|
containerElement.addEventListener('wheel', function (event) {
|
||||||
|
if (event.deltaY !== 0) {
|
||||||
|
// Adjust horizontal scroll position based on vertical scroll
|
||||||
|
containerElement.scrollLeft += event.deltaY;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex flex-col lg:flex-row w-full h-full py-2 lg:space-x-4">
|
<div class="flex flex-col lg:flex-row w-full h-full py-2 lg:space-x-4">
|
||||||
<div
|
<div
|
||||||
class="tabs flex flex-row overflow-x-auto space-x-1 max-w-full lg:space-x-0 lg:space-y-1 lg:flex-col lg:flex-none lg:w-44 dark:text-gray-200 text-xs text-left scrollbar-none"
|
id="admin-settings-tabs-container" class="tabs flex flex-row overflow-x-auto space-x-1 max-w-full lg:space-x-0 lg:space-y-1 lg:flex-col lg:flex-none lg:w-44 dark:text-gray-200 text-xs text-left scrollbar-none"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 lg:flex-none flex text-right transition {selectedTab ===
|
class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 lg:flex-none flex text-right transition {selectedTab ===
|
||||||
|
|||||||
@@ -158,12 +158,14 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const [res, controller] = await pullModel(localStorage.token, sanitizedModelTag, '0').catch(
|
const [res, controller] = await pullModel(
|
||||||
(error) => {
|
localStorage.token,
|
||||||
toast.error(error);
|
sanitizedModelTag,
|
||||||
return null;
|
selectedOllamaUrlIdx
|
||||||
}
|
).catch((error) => {
|
||||||
);
|
toast.error(error);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
if (res) {
|
if (res) {
|
||||||
const reader = res.body
|
const reader = res.body
|
||||||
|
|||||||
@@ -126,21 +126,29 @@
|
|||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
|
||||||
const chatEventHandler = async (data) => {
|
const chatEventHandler = async (event) => {
|
||||||
if (data.chat_id === $chatId) {
|
if (event.chat_id === $chatId) {
|
||||||
await tick();
|
await tick();
|
||||||
console.log(data);
|
console.log(event);
|
||||||
let message = history.messages[data.message_id];
|
let message = history.messages[event.message_id];
|
||||||
|
|
||||||
const status = {
|
const type = event?.data?.type ?? null;
|
||||||
done: data?.data?.done ?? null,
|
const data = event?.data?.data ?? null;
|
||||||
description: data?.data?.status ?? null
|
|
||||||
};
|
|
||||||
|
|
||||||
if (message.statusHistory) {
|
if (type === 'status') {
|
||||||
message.statusHistory.push(status);
|
if (message.statusHistory) {
|
||||||
|
message.statusHistory.push(data);
|
||||||
|
} else {
|
||||||
|
message.statusHistory = [data];
|
||||||
|
}
|
||||||
|
} else if (type === 'citation') {
|
||||||
|
if (message.citations) {
|
||||||
|
message.citations.push(data);
|
||||||
|
} else {
|
||||||
|
message.citations = [data];
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
message.statusHistory = [status];
|
console.log('Unknown message type', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
messages = messages;
|
messages = messages;
|
||||||
|
|||||||
@@ -2,32 +2,25 @@
|
|||||||
import ChevronDown from '$lib/components/icons/ChevronDown.svelte';
|
import ChevronDown from '$lib/components/icons/ChevronDown.svelte';
|
||||||
import ChevronUp from '$lib/components/icons/ChevronUp.svelte';
|
import ChevronUp from '$lib/components/icons/ChevronUp.svelte';
|
||||||
import MagnifyingGlass from '$lib/components/icons/MagnifyingGlass.svelte';
|
import MagnifyingGlass from '$lib/components/icons/MagnifyingGlass.svelte';
|
||||||
import { Collapsible } from 'bits-ui';
|
import Collapsible from '$lib/components/common/Collapsible.svelte';
|
||||||
import { slide } from 'svelte/transition';
|
|
||||||
|
|
||||||
export let status = { urls: [], query: '' };
|
export let status = { urls: [], query: '' };
|
||||||
let state = false;
|
let state = false;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Collapsible.Root class="w-full space-y-1" bind:open={state}>
|
<Collapsible bind:open={state} className="w-full space-y-1">
|
||||||
<Collapsible.Trigger>
|
<div
|
||||||
<div
|
class="flex items-center gap-2 text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 transition"
|
||||||
class="flex items-center gap-2 text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 transition"
|
|
||||||
>
|
|
||||||
<slot />
|
|
||||||
|
|
||||||
{#if state}
|
|
||||||
<ChevronUp strokeWidth="3.5" className="size-3.5 " />
|
|
||||||
{:else}
|
|
||||||
<ChevronDown strokeWidth="3.5" className="size-3.5 " />
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</Collapsible.Trigger>
|
|
||||||
|
|
||||||
<Collapsible.Content
|
|
||||||
class=" text-sm border border-gray-300/30 dark:border-gray-700/50 rounded-xl"
|
|
||||||
transition={slide}
|
|
||||||
>
|
>
|
||||||
|
<slot />
|
||||||
|
|
||||||
|
{#if state}
|
||||||
|
<ChevronUp strokeWidth="3.5" className="size-3.5 " />
|
||||||
|
{:else}
|
||||||
|
<ChevronDown strokeWidth="3.5" className="size-3.5 " />
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<div class="text-sm border border-gray-300/30 dark:border-gray-700/50 rounded-xl" slot="content">
|
||||||
{#if status?.query}
|
{#if status?.query}
|
||||||
<a
|
<a
|
||||||
href="https://www.google.com/search?q={status.query}"
|
href="https://www.google.com/search?q={status.query}"
|
||||||
@@ -93,5 +86,5 @@
|
|||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
{/each}
|
{/each}
|
||||||
</Collapsible.Content>
|
</div>
|
||||||
</Collapsible.Root>
|
</Collapsible>
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { getContext } from 'svelte';
|
import { getContext, tick } from 'svelte';
|
||||||
import { toast } from 'svelte-sonner';
|
import { toast } from 'svelte-sonner';
|
||||||
import { models, settings, user } from '$lib/stores';
|
import { models, settings, user } from '$lib/stores';
|
||||||
|
import { updateUserSettings } from '$lib/apis/users';
|
||||||
import { getModels as _getModels } from '$lib/apis';
|
import { getModels as _getModels } from '$lib/apis';
|
||||||
|
import { goto } from '$app/navigation';
|
||||||
|
|
||||||
import Modal from '../common/Modal.svelte';
|
import Modal from '../common/Modal.svelte';
|
||||||
import Account from './Settings/Account.svelte';
|
import Account from './Settings/Account.svelte';
|
||||||
@@ -14,8 +15,6 @@
|
|||||||
import Chats from './Settings/Chats.svelte';
|
import Chats from './Settings/Chats.svelte';
|
||||||
import User from '../icons/User.svelte';
|
import User from '../icons/User.svelte';
|
||||||
import Personalization from './Settings/Personalization.svelte';
|
import Personalization from './Settings/Personalization.svelte';
|
||||||
import { updateUserSettings } from '$lib/apis/users';
|
|
||||||
import { goto } from '$app/navigation';
|
|
||||||
import Valves from './Settings/Valves.svelte';
|
import Valves from './Settings/Valves.svelte';
|
||||||
|
|
||||||
const i18n = getContext('i18n');
|
const i18n = getContext('i18n');
|
||||||
@@ -34,6 +33,37 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
let selectedTab = 'general';
|
let selectedTab = 'general';
|
||||||
|
|
||||||
|
// Function to handle sideways scrolling
|
||||||
|
const scrollHandler = (event) => {
|
||||||
|
const settingsTabsContainer = document.getElementById('settings-tabs-container');
|
||||||
|
if (settingsTabsContainer) {
|
||||||
|
event.preventDefault(); // Prevent default vertical scrolling
|
||||||
|
settingsTabsContainer.scrollLeft += event.deltaY; // Scroll sideways
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const addScrollListener = async () => {
|
||||||
|
await tick();
|
||||||
|
const settingsTabsContainer = document.getElementById('settings-tabs-container');
|
||||||
|
if (settingsTabsContainer) {
|
||||||
|
settingsTabsContainer.addEventListener('wheel', scrollHandler);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeScrollListener = async () => {
|
||||||
|
await tick();
|
||||||
|
const settingsTabsContainer = document.getElementById('settings-tabs-container');
|
||||||
|
if (settingsTabsContainer) {
|
||||||
|
settingsTabsContainer.removeEventListener('wheel', scrollHandler);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$: if (show) {
|
||||||
|
addScrollListener();
|
||||||
|
} else {
|
||||||
|
removeScrollListener();
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Modal bind:show>
|
<Modal bind:show>
|
||||||
@@ -61,6 +91,7 @@
|
|||||||
|
|
||||||
<div class="flex flex-col md:flex-row w-full p-4 md:space-x-4">
|
<div class="flex flex-col md:flex-row w-full p-4 md:space-x-4">
|
||||||
<div
|
<div
|
||||||
|
id="settings-tabs-container"
|
||||||
class="tabs flex flex-row overflow-x-auto space-x-1 md:space-x-0 md:space-y-1 md:flex-col flex-1 md:flex-none md:w-40 dark:text-gray-200 text-xs text-left mb-3 md:mb-0"
|
class="tabs flex flex-row overflow-x-auto space-x-1 md:space-x-0 md:space-y-1 md:flex-col flex-1 md:flex-none md:w-40 dark:text-gray-200 text-xs text-left mb-3 md:mb-0"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
|
|||||||
18
src/lib/components/common/Collapsible.svelte
Normal file
18
src/lib/components/common/Collapsible.svelte
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { slide } from 'svelte/transition';
|
||||||
|
import { quintOut } from 'svelte/easing';
|
||||||
|
export let open = false;
|
||||||
|
export let className = '';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class={className}>
|
||||||
|
<button on:click={() => (open = !open)}>
|
||||||
|
<slot />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{#if open}
|
||||||
|
<div transition:slide={{ duration: 300, easing: quintOut, axis: 'y' }}>
|
||||||
|
<slot name="content" />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
@@ -186,6 +186,7 @@
|
|||||||
goto('/');
|
goto('/');
|
||||||
}
|
}
|
||||||
await chats.set(await getChatList(localStorage.token));
|
await chats.set(await getChatList(localStorage.token));
|
||||||
|
await pinnedChats.set(await getChatListByTagName(localStorage.token, 'pinned'));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -126,7 +126,7 @@
|
|||||||
"Connections": "Connexions",
|
"Connections": "Connexions",
|
||||||
"Contact Admin for WebUI Access": "Posat en contacte amb l'administrador per accedir a WebUI",
|
"Contact Admin for WebUI Access": "Posat en contacte amb l'administrador per accedir a WebUI",
|
||||||
"Content": "Contingut",
|
"Content": "Contingut",
|
||||||
"Content Extraction": "",
|
"Content Extraction": "Extraccció de contingut",
|
||||||
"Context Length": "Mida del context",
|
"Context Length": "Mida del context",
|
||||||
"Continue Response": "Continuar la resposta",
|
"Continue Response": "Continuar la resposta",
|
||||||
"Continue with {{provider}}": "Continuar amb {{provider}}",
|
"Continue with {{provider}}": "Continuar amb {{provider}}",
|
||||||
@@ -213,7 +213,7 @@
|
|||||||
"Enable Community Sharing": "Activar l'ús compartit amb la comunitat",
|
"Enable Community Sharing": "Activar l'ús compartit amb la comunitat",
|
||||||
"Enable New Sign Ups": "Permetre nous registres",
|
"Enable New Sign Ups": "Permetre nous registres",
|
||||||
"Enable Web Search": "Activar la cerca web",
|
"Enable Web Search": "Activar la cerca web",
|
||||||
"Engine": "",
|
"Engine": "Motor",
|
||||||
"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Assegura't que els teus fitxers CSV inclouen 4 columnes en aquest ordre: Nom, Correu electrònic, Contrasenya, Rol.",
|
"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Assegura't que els teus fitxers CSV inclouen 4 columnes en aquest ordre: Nom, Correu electrònic, Contrasenya, Rol.",
|
||||||
"Enter {{role}} message here": "Introdueix aquí el missatge de {{role}}",
|
"Enter {{role}} message here": "Introdueix aquí el missatge de {{role}}",
|
||||||
"Enter a detail about yourself for your LLMs to recall": "Introdueix un detall sobre tu què els teus models de llenguatge puguin recordar",
|
"Enter a detail about yourself for your LLMs to recall": "Introdueix un detall sobre tu què els teus models de llenguatge puguin recordar",
|
||||||
@@ -235,7 +235,7 @@
|
|||||||
"Enter Serpstack API Key": "Introdueix la clau API Serpstack",
|
"Enter Serpstack API Key": "Introdueix la clau API Serpstack",
|
||||||
"Enter stop sequence": "Introdueix la seqüència de parada",
|
"Enter stop sequence": "Introdueix la seqüència de parada",
|
||||||
"Enter Tavily API Key": "Introdueix la clau API de Tavily",
|
"Enter Tavily API Key": "Introdueix la clau API de Tavily",
|
||||||
"Enter Tika Server URL": "",
|
"Enter Tika Server URL": "Introdueix l'URL del servidor Tika",
|
||||||
"Enter Top K": "Introdueix Top K",
|
"Enter Top K": "Introdueix Top K",
|
||||||
"Enter URL (e.g. http://127.0.0.1:7860/)": "Introdueix l'URL (p. ex. http://127.0.0.1:7860/)",
|
"Enter URL (e.g. http://127.0.0.1:7860/)": "Introdueix l'URL (p. ex. http://127.0.0.1:7860/)",
|
||||||
"Enter URL (e.g. http://localhost:11434)": "Introdueix l'URL (p. ex. http://localhost:11434)",
|
"Enter URL (e.g. http://localhost:11434)": "Introdueix l'URL (p. ex. http://localhost:11434)",
|
||||||
@@ -412,7 +412,7 @@
|
|||||||
"Open": "Obre",
|
"Open": "Obre",
|
||||||
"Open AI (Dall-E)": "Open AI (Dall-E)",
|
"Open AI (Dall-E)": "Open AI (Dall-E)",
|
||||||
"Open new chat": "Obre un xat nou",
|
"Open new chat": "Obre un xat nou",
|
||||||
"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
|
"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "La versió d'Open WebUI (v{{OPEN_WEBUI_VERSION}}) és inferior a la versió requerida (v{{REQUIRED_VERSION}})",
|
||||||
"OpenAI": "OpenAI",
|
"OpenAI": "OpenAI",
|
||||||
"OpenAI API": "API d'OpenAI",
|
"OpenAI API": "API d'OpenAI",
|
||||||
"OpenAI API Config": "Configuració de l'API d'OpenAI",
|
"OpenAI API Config": "Configuració de l'API d'OpenAI",
|
||||||
@@ -428,8 +428,8 @@
|
|||||||
"Permission denied when accessing microphone": "Permís denegat en accedir al micròfon",
|
"Permission denied when accessing microphone": "Permís denegat en accedir al micròfon",
|
||||||
"Permission denied when accessing microphone: {{error}}": "Permís denegat en accedir al micròfon: {{error}}",
|
"Permission denied when accessing microphone: {{error}}": "Permís denegat en accedir al micròfon: {{error}}",
|
||||||
"Personalization": "Personalització",
|
"Personalization": "Personalització",
|
||||||
"Pin": "",
|
"Pin": "Fixar",
|
||||||
"Pinned": "",
|
"Pinned": "Fixat",
|
||||||
"Pipeline deleted successfully": "Pipeline eliminada correctament",
|
"Pipeline deleted successfully": "Pipeline eliminada correctament",
|
||||||
"Pipeline downloaded successfully": "Pipeline descarregada correctament",
|
"Pipeline downloaded successfully": "Pipeline descarregada correctament",
|
||||||
"Pipelines": "Pipelines",
|
"Pipelines": "Pipelines",
|
||||||
@@ -580,8 +580,8 @@
|
|||||||
"This setting does not sync across browsers or devices.": "Aquesta preferència no es sincronitza entre navegadors ni dispositius.",
|
"This setting does not sync across browsers or devices.": "Aquesta preferència no es sincronitza entre navegadors ni dispositius.",
|
||||||
"This will delete": "Això eliminarà",
|
"This will delete": "Això eliminarà",
|
||||||
"Thorough explanation": "Explicació en detall",
|
"Thorough explanation": "Explicació en detall",
|
||||||
"Tika": "",
|
"Tika": "Tika",
|
||||||
"Tika Server URL required.": "",
|
"Tika Server URL required.": "La URL del servidor Tika és obligatòria.",
|
||||||
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Consell: Actualitza les diverses variables consecutivament prement la tecla de tabulació en l'entrada del xat després de cada reemplaçament.",
|
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Consell: Actualitza les diverses variables consecutivament prement la tecla de tabulació en l'entrada del xat després de cada reemplaçament.",
|
||||||
"Title": "Títol",
|
"Title": "Títol",
|
||||||
"Title (e.g. Tell me a fun fact)": "Títol (p. ex. Digues-me quelcom divertit)",
|
"Title (e.g. Tell me a fun fact)": "Títol (p. ex. Digues-me quelcom divertit)",
|
||||||
@@ -616,7 +616,7 @@
|
|||||||
"Uh-oh! There was an issue connecting to {{provider}}.": "Oh! Hi ha hagut un problema connectant a {{provider}}.",
|
"Uh-oh! There was an issue connecting to {{provider}}.": "Oh! Hi ha hagut un problema connectant a {{provider}}.",
|
||||||
"UI": "UI",
|
"UI": "UI",
|
||||||
"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "Tipus de fitxer desconegut '{{file_type}}'. Continuant amb la càrrega del fitxer.",
|
"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "Tipus de fitxer desconegut '{{file_type}}'. Continuant amb la càrrega del fitxer.",
|
||||||
"Unpin": "",
|
"Unpin": "Alliberar",
|
||||||
"Update": "Actualitzar",
|
"Update": "Actualitzar",
|
||||||
"Update and Copy Link": "Actualitzar i copiar l'enllaç",
|
"Update and Copy Link": "Actualitzar i copiar l'enllaç",
|
||||||
"Update password": "Actualitzar la contrasenya",
|
"Update password": "Actualitzar la contrasenya",
|
||||||
|
|||||||
@@ -126,7 +126,7 @@
|
|||||||
"Connections": "外部连接",
|
"Connections": "外部连接",
|
||||||
"Contact Admin for WebUI Access": "请联系管理员以获取访问权限",
|
"Contact Admin for WebUI Access": "请联系管理员以获取访问权限",
|
||||||
"Content": "内容",
|
"Content": "内容",
|
||||||
"Content Extraction": "",
|
"Content Extraction": "内容提取",
|
||||||
"Context Length": "上下文长度",
|
"Context Length": "上下文长度",
|
||||||
"Continue Response": "继续生成",
|
"Continue Response": "继续生成",
|
||||||
"Continue with {{provider}}": "使用 {{provider}} 继续",
|
"Continue with {{provider}}": "使用 {{provider}} 继续",
|
||||||
@@ -213,7 +213,7 @@
|
|||||||
"Enable Community Sharing": "启用分享至社区",
|
"Enable Community Sharing": "启用分享至社区",
|
||||||
"Enable New Sign Ups": "允许新用户注册",
|
"Enable New Sign Ups": "允许新用户注册",
|
||||||
"Enable Web Search": "启用网络搜索",
|
"Enable Web Search": "启用网络搜索",
|
||||||
"Engine": "",
|
"Engine": "引擎",
|
||||||
"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "确保您的 CSV 文件按以下顺序包含 4 列: 姓名、电子邮箱、密码、角色。",
|
"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "确保您的 CSV 文件按以下顺序包含 4 列: 姓名、电子邮箱、密码、角色。",
|
||||||
"Enter {{role}} message here": "在此处输入 {{role}} 信息",
|
"Enter {{role}} message here": "在此处输入 {{role}} 信息",
|
||||||
"Enter a detail about yourself for your LLMs to recall": "输入一个关于你自己的详细信息,方便你的大语言模型记住这些内容",
|
"Enter a detail about yourself for your LLMs to recall": "输入一个关于你自己的详细信息,方便你的大语言模型记住这些内容",
|
||||||
@@ -235,7 +235,7 @@
|
|||||||
"Enter Serpstack API Key": "输入 Serpstack API 密钥",
|
"Enter Serpstack API Key": "输入 Serpstack API 密钥",
|
||||||
"Enter stop sequence": "输入停止序列 (Stop Sequence)",
|
"Enter stop sequence": "输入停止序列 (Stop Sequence)",
|
||||||
"Enter Tavily API Key": "输入 Tavily API 密钥",
|
"Enter Tavily API Key": "输入 Tavily API 密钥",
|
||||||
"Enter Tika Server URL": "",
|
"Enter Tika Server URL": "输入 Tika 服务器地址",
|
||||||
"Enter Top K": "输入 Top K",
|
"Enter Top K": "输入 Top K",
|
||||||
"Enter URL (e.g. http://127.0.0.1:7860/)": "输入地址 (例如:http://127.0.0.1:7860/)",
|
"Enter URL (e.g. http://127.0.0.1:7860/)": "输入地址 (例如:http://127.0.0.1:7860/)",
|
||||||
"Enter URL (e.g. http://localhost:11434)": "输入地址 (例如:http://localhost:11434)",
|
"Enter URL (e.g. http://localhost:11434)": "输入地址 (例如:http://localhost:11434)",
|
||||||
@@ -412,7 +412,7 @@
|
|||||||
"Open": "打开",
|
"Open": "打开",
|
||||||
"Open AI (Dall-E)": "Open AI (Dall-E)",
|
"Open AI (Dall-E)": "Open AI (Dall-E)",
|
||||||
"Open new chat": "打开新对话",
|
"Open new chat": "打开新对话",
|
||||||
"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
|
"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "当前 Open WebUI 版本 (v{{OPEN_WEBUI_VERSION}}) 低于所需的版本 (v{{REQUIRED_VERSION}})",
|
||||||
"OpenAI": "OpenAI",
|
"OpenAI": "OpenAI",
|
||||||
"OpenAI API": "OpenAI API",
|
"OpenAI API": "OpenAI API",
|
||||||
"OpenAI API Config": "OpenAI API 配置",
|
"OpenAI API Config": "OpenAI API 配置",
|
||||||
@@ -428,8 +428,8 @@
|
|||||||
"Permission denied when accessing microphone": "申请麦克风权限被拒绝",
|
"Permission denied when accessing microphone": "申请麦克风权限被拒绝",
|
||||||
"Permission denied when accessing microphone: {{error}}": "申请麦克风权限被拒绝:{{error}}",
|
"Permission denied when accessing microphone: {{error}}": "申请麦克风权限被拒绝:{{error}}",
|
||||||
"Personalization": "个性化",
|
"Personalization": "个性化",
|
||||||
"Pin": "",
|
"Pin": "置顶",
|
||||||
"Pinned": "",
|
"Pinned": "已置顶",
|
||||||
"Pipeline deleted successfully": "Pipeline 删除成功",
|
"Pipeline deleted successfully": "Pipeline 删除成功",
|
||||||
"Pipeline downloaded successfully": "Pipeline 下载成功",
|
"Pipeline downloaded successfully": "Pipeline 下载成功",
|
||||||
"Pipelines": "Pipeline",
|
"Pipelines": "Pipeline",
|
||||||
@@ -578,8 +578,8 @@
|
|||||||
"This setting does not sync across browsers or devices.": "此设置不会在浏览器或设备之间同步。",
|
"This setting does not sync across browsers or devices.": "此设置不会在浏览器或设备之间同步。",
|
||||||
"This will delete": "这将删除",
|
"This will delete": "这将删除",
|
||||||
"Thorough explanation": "解释较为详细",
|
"Thorough explanation": "解释较为详细",
|
||||||
"Tika": "",
|
"Tika": "Tika",
|
||||||
"Tika Server URL required.": "",
|
"Tika Server URL required.": "请输入 Tika 服务器地址。",
|
||||||
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "提示:在每次替换后,在对话输入中按 Tab 键可以连续更新多个变量。",
|
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "提示:在每次替换后,在对话输入中按 Tab 键可以连续更新多个变量。",
|
||||||
"Title": "标题",
|
"Title": "标题",
|
||||||
"Title (e.g. Tell me a fun fact)": "标题(例如 给我讲一个有趣的事实)",
|
"Title (e.g. Tell me a fun fact)": "标题(例如 给我讲一个有趣的事实)",
|
||||||
@@ -614,7 +614,7 @@
|
|||||||
"Uh-oh! There was an issue connecting to {{provider}}.": "糟糕!连接到 {{provider}} 时出现问题。",
|
"Uh-oh! There was an issue connecting to {{provider}}.": "糟糕!连接到 {{provider}} 时出现问题。",
|
||||||
"UI": "界面",
|
"UI": "界面",
|
||||||
"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "未知文件类型“{{file_type}}”,将无视继续上传文件。",
|
"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "未知文件类型“{{file_type}}”,将无视继续上传文件。",
|
||||||
"Unpin": "",
|
"Unpin": "取消置顶",
|
||||||
"Update": "更新",
|
"Update": "更新",
|
||||||
"Update and Copy Link": "更新和复制链接",
|
"Update and Copy Link": "更新和复制链接",
|
||||||
"Update password": "更新密码",
|
"Update password": "更新密码",
|
||||||
|
|||||||
Reference in New Issue
Block a user