added google-cloud-storage package, added gcs related functions

This commit is contained in:
kahghi 2025-01-17 16:16:25 +08:00
parent 42b7beb8a7
commit 8efc543f49
4 changed files with 1757 additions and 1132 deletions

View File

@ -582,13 +582,16 @@ if CUSTOM_NAME:
#################################### ####################################
STORAGE_PROVIDER = os.environ.get("STORAGE_PROVIDER", "local") # defaults to local, s3 STORAGE_PROVIDER = os.environ.get("STORAGE_PROVIDER", "local") # defaults to local, s3
print(f"storage provider: {STORAGE_PROVIDER}")
S3_ACCESS_KEY_ID = os.environ.get("S3_ACCESS_KEY_ID", None) S3_ACCESS_KEY_ID = os.environ.get("S3_ACCESS_KEY_ID", None)
S3_SECRET_ACCESS_KEY = os.environ.get("S3_SECRET_ACCESS_KEY", None) S3_SECRET_ACCESS_KEY = os.environ.get("S3_SECRET_ACCESS_KEY", None)
S3_REGION_NAME = os.environ.get("S3_REGION_NAME", None) S3_REGION_NAME = os.environ.get("S3_REGION_NAME", None)
S3_BUCKET_NAME = os.environ.get("S3_BUCKET_NAME", None) S3_BUCKET_NAME = os.environ.get("S3_BUCKET_NAME", None)
S3_ENDPOINT_URL = os.environ.get("S3_ENDPOINT_URL", None) S3_ENDPOINT_URL = os.environ.get("S3_ENDPOINT_URL", None)
GCS_PROJECT_ID = os.environ.get("GCS_PROJECT_ID", None)
GCS_BUCKET_NAME = os.environ.get("GCS_BUCKET_NAME", FileNotFoundError)
#################################### ####################################
# File Upload DIR # File Upload DIR
#################################### ####################################

View File

@ -11,10 +11,13 @@ from open_webui.config import (
S3_ENDPOINT_URL, S3_ENDPOINT_URL,
S3_REGION_NAME, S3_REGION_NAME,
S3_SECRET_ACCESS_KEY, S3_SECRET_ACCESS_KEY,
GCS_PROJECT_ID,
GCS_BUCKET_NAME,
STORAGE_PROVIDER, STORAGE_PROVIDER,
UPLOAD_DIR, UPLOAD_DIR,
) )
from google.cloud import storage from google.cloud import storage
from google.cloud.exceptions import GoogleCloudError, NotFound
from open_webui.constants import ERROR_MESSAGES from open_webui.constants import ERROR_MESSAGES
@ -140,18 +143,71 @@ class S3StorageProvider(StorageProvider):
class GCSStorageProvider(StorageProvider): class GCSStorageProvider(StorageProvider):
def __init__(self): def __init__(self):
self.gcs_client = storage.Client() self.gcs_client = storage.Client(project=GCS_PROJECT_ID)
self.bucket_name = GCS_BUCKET_NAME self.bucket_name = self.gcs_client.bucket(GCS_BUCKET_NAME)
def upload_file(self, file: BinaryIO, filename: str):
"""Handles uploading of the file to GCS storage."""
contents, _ = LocalStorageProvider.upload_file(file, filename)
try:
# Get the blob (object in the bucket)
blob = self.bucket_name.blob(filename)
# Upload the file to the bucket
blob.upload_from_file(BytesIO(contents))
print("file successfully uploaded")
except GoogleCloudError as e:
raise RuntimeError(f"Error uploading file to GCS: {e}")
def get_file(self, file_path:str) -> str:
"""Handles downloading of the file from GCS storage."""
try:
local_file_path = f"{UPLOAD_DIR}/{file_path}"
# Get the blob (object in the bucket)
blob = self.bucket_name.blob(file_path)
# Download the file to a local destination
blob.download_to_filename(local_file_path)
except NotFound as e:
raise RuntimeError(f"Error downloading file from GCS: {e}")
def delete_file(self, file_path:str) -> None:
"""Handles deletion of the file from GCS storage."""
try:
# Get the blob (object in the bucket)
blob = self.bucket_name.blob(file_path)
# Delete the file
blob.delete()
except NotFound as e:
raise RuntimeError(f"Error deleting file from GCS: {e}")
# Always delete from local storage
LocalStorageProvider.delete_file(file_path)
def delete_all_files(self) -> None:
"""Handles deletion of all files from GCS storage."""
try:
# List all objects in the bucket
blobs = self.bucket_name.list_blobs()
# Delete all files
for blob in blobs:
blob.delete()
except NotFound as e:
raise RuntimeError(f"Error deleting all files from GCS: {e}")
# Always delete from local storage
LocalStorageProvider.delete_all_files()
def get_storage_provider(storage_provider: str): def get_storage_provider(storage_provider: str):
if storage_provider == "local": if storage_provider == "local":
Storage = LocalStorageProvider() Storage = LocalStorageProvider()
elif storage_provider == "s3": elif storage_provider == "s3":
Storage = S3StorageProvider() Storage = S3StorageProvider()
elif storage_provider == "gcs":
Storage = GCSStorageProvider()
else: else:
raise RuntimeError(f"Unsupported storage provider: {storage_provider}") raise RuntimeError(f"Unsupported storage provider: {storage_provider}")
return Storage return Storage
Storage = get_storage_provider(STORAGE_PROVIDER) Storage = get_storage_provider(STORAGE_PROVIDER)

View File

@ -10,20 +10,16 @@ dependencies = [
"uvicorn[standard]==0.30.6", "uvicorn[standard]==0.30.6",
"pydantic==2.9.2", "pydantic==2.9.2",
"python-multipart==0.0.18", "python-multipart==0.0.18",
"Flask==3.1.0", "Flask==3.1.0",
"Flask-Cors==5.0.0", "Flask-Cors==5.0.0",
"python-socketio==5.11.3", "python-socketio==5.11.3",
"python-jose==3.3.0", "python-jose==3.3.0",
"passlib[bcrypt]==1.7.4", "passlib[bcrypt]==1.7.4",
"requests==2.32.3", "requests==2.32.3",
"aiohttp==3.11.8", "aiohttp==3.11.8",
"async-timeout", "async-timeout",
"aiocache", "aiocache",
"aiofiles", "aiofiles",
"sqlalchemy==2.0.32", "sqlalchemy==2.0.32",
"alembic==1.14.0", "alembic==1.14.0",
"peewee==3.17.8", "peewee==3.17.8",
@ -32,33 +28,26 @@ dependencies = [
"pgvector==0.3.5", "pgvector==0.3.5",
"PyMySQL==1.1.1", "PyMySQL==1.1.1",
"bcrypt==4.2.0", "bcrypt==4.2.0",
"pymongo", "pymongo",
"redis", "redis",
"boto3==1.35.53", "boto3==1.35.53",
"argon2-cffi==23.1.0", "argon2-cffi==23.1.0",
"APScheduler==3.10.4", "APScheduler==3.10.4",
"openai", "openai",
"anthropic", "anthropic",
"google-generativeai==0.7.2", "google-generativeai==0.7.2",
"tiktoken", "tiktoken",
"langchain==0.3.7", "langchain==0.3.7",
"langchain-community==0.3.7", "langchain-community==0.3.7",
"fake-useragent==1.5.1", "fake-useragent==1.5.1",
"chromadb==0.6.2", "chromadb==0.6.2",
"pymilvus==2.5.0", "pymilvus==2.5.0",
"qdrant-client~=1.12.0", "qdrant-client~=1.12.0",
"opensearch-py==2.7.1", "opensearch-py==2.7.1",
"transformers", "transformers",
"sentence-transformers==3.3.1", "sentence-transformers==3.3.1",
"colbert-ai==0.2.21", "colbert-ai==0.2.21",
"einops==0.8.0", "einops==0.8.0",
"ftfy==6.2.3", "ftfy==6.2.3",
"pypdf==4.3.1", "pypdf==4.3.1",
"fpdf2==2.8.2", "fpdf2==2.8.2",
@ -77,33 +66,26 @@ dependencies = [
"psutil", "psutil",
"sentencepiece", "sentencepiece",
"soundfile==0.12.1", "soundfile==0.12.1",
"opencv-python-headless==4.10.0.84", "opencv-python-headless==4.10.0.84",
"rapidocr-onnxruntime==1.3.24", "rapidocr-onnxruntime==1.3.24",
"rank-bm25==0.2.2", "rank-bm25==0.2.2",
"faster-whisper==1.0.3", "faster-whisper==1.0.3",
"PyJWT[crypto]==2.10.1", "PyJWT[crypto]==2.10.1",
"authlib==1.3.2", "authlib==1.3.2",
"black==24.8.0", "black==24.8.0",
"langfuse==2.44.0", "langfuse==2.44.0",
"youtube-transcript-api==0.6.3", "youtube-transcript-api==0.6.3",
"pytube==15.0.0", "pytube==15.0.0",
"extract_msg", "extract_msg",
"pydub", "pydub",
"duckduckgo-search~=6.3.5", "duckduckgo-search~=6.3.5",
"docker~=7.1.0", "docker~=7.1.0",
"pytest~=8.3.2", "pytest~=8.3.2",
"pytest-docker~=3.1.1", "pytest-docker~=3.1.1",
"moto[s3]>=5.0.26", "moto[s3]>=5.0.26",
"googleapis-common-protos==1.63.2", "googleapis-common-protos==1.63.2",
"ldap3==2.9.1",
"ldap3==2.9.1" "google-cloud-storage>=2.19.0",
] ]
readme = "README.md" readme = "README.md"
requires-python = ">= 3.11, < 3.13.0a1" requires-python = ">= 3.11, < 3.13.0a1"

2800
uv.lock

File diff suppressed because it is too large Load Diff