Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
58ae734fc2 | ||
|
|
54b2779b79 | ||
|
|
df26e12db6 | ||
|
|
343d89c032 |
2
cli/src/api/open-api/api.ts
generated
2
cli/src/api/open-api/api.ts
generated
@@ -4,7 +4,7 @@
|
|||||||
* Immich
|
* Immich
|
||||||
* Immich API
|
* Immich API
|
||||||
*
|
*
|
||||||
* The version of the OpenAPI document: 1.76.0
|
* The version of the OpenAPI document: 1.76.1
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
|||||||
2
cli/src/api/open-api/base.ts
generated
2
cli/src/api/open-api/base.ts
generated
@@ -4,7 +4,7 @@
|
|||||||
* Immich
|
* Immich
|
||||||
* Immich API
|
* Immich API
|
||||||
*
|
*
|
||||||
* The version of the OpenAPI document: 1.76.0
|
* The version of the OpenAPI document: 1.76.1
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
|||||||
2
cli/src/api/open-api/common.ts
generated
2
cli/src/api/open-api/common.ts
generated
@@ -4,7 +4,7 @@
|
|||||||
* Immich
|
* Immich
|
||||||
* Immich API
|
* Immich API
|
||||||
*
|
*
|
||||||
* The version of the OpenAPI document: 1.76.0
|
* The version of the OpenAPI document: 1.76.1
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
|||||||
2
cli/src/api/open-api/configuration.ts
generated
2
cli/src/api/open-api/configuration.ts
generated
@@ -4,7 +4,7 @@
|
|||||||
* Immich
|
* Immich
|
||||||
* Immich API
|
* Immich API
|
||||||
*
|
*
|
||||||
* The version of the OpenAPI document: 1.76.0
|
* The version of the OpenAPI document: 1.76.1
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
|||||||
2
cli/src/api/open-api/index.ts
generated
2
cli/src/api/open-api/index.ts
generated
@@ -4,7 +4,7 @@
|
|||||||
* Immich
|
* Immich
|
||||||
* Immich API
|
* Immich API
|
||||||
*
|
*
|
||||||
* The version of the OpenAPI document: 1.76.0
|
* The version of the OpenAPI document: 1.76.1
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
import starlette
|
||||||
from pydantic import BaseSettings
|
from pydantic import BaseSettings
|
||||||
|
from rich.console import Console
|
||||||
|
from rich.logging import RichHandler
|
||||||
|
|
||||||
from .schemas import ModelType
|
from .schemas import ModelType
|
||||||
|
|
||||||
@@ -23,6 +27,14 @@ class Settings(BaseSettings):
|
|||||||
case_sensitive = False
|
case_sensitive = False
|
||||||
|
|
||||||
|
|
||||||
|
class LogSettings(BaseSettings):
|
||||||
|
log_level: str = "info"
|
||||||
|
no_color: bool = False
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
case_sensitive = False
|
||||||
|
|
||||||
|
|
||||||
_clean_name = str.maketrans(":\\/", "___", ".")
|
_clean_name = str.maketrans(":\\/", "___", ".")
|
||||||
|
|
||||||
|
|
||||||
@@ -30,4 +42,26 @@ def get_cache_dir(model_name: str, model_type: ModelType) -> Path:
|
|||||||
return Path(settings.cache_folder) / model_type.value / model_name.translate(_clean_name)
|
return Path(settings.cache_folder) / model_type.value / model_name.translate(_clean_name)
|
||||||
|
|
||||||
|
|
||||||
|
LOG_LEVELS: dict[str, int] = {
|
||||||
|
"critical": logging.ERROR,
|
||||||
|
"error": logging.ERROR,
|
||||||
|
"warning": logging.WARNING,
|
||||||
|
"warn": logging.WARNING,
|
||||||
|
"info": logging.INFO,
|
||||||
|
"log": logging.INFO,
|
||||||
|
"debug": logging.DEBUG,
|
||||||
|
"verbose": logging.DEBUG,
|
||||||
|
}
|
||||||
|
|
||||||
settings = Settings()
|
settings = Settings()
|
||||||
|
log_settings = LogSettings()
|
||||||
|
|
||||||
|
console = Console(color_system="standard", no_color=log_settings.no_color)
|
||||||
|
logging.basicConfig(
|
||||||
|
format="%(message)s",
|
||||||
|
handlers=[
|
||||||
|
RichHandler(show_path=False, omit_repeated_times=False, console=console, tracebacks_suppress=[starlette])
|
||||||
|
],
|
||||||
|
)
|
||||||
|
log = logging.getLogger("uvicorn")
|
||||||
|
log.setLevel(LOG_LEVELS.get(log_settings.log_level.lower(), logging.INFO))
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
from typing import Any
|
from typing import Any
|
||||||
@@ -11,7 +12,7 @@ from starlette.formparsers import MultiPartParser
|
|||||||
|
|
||||||
from app.models.base import InferenceModel
|
from app.models.base import InferenceModel
|
||||||
|
|
||||||
from .config import settings
|
from .config import log, settings
|
||||||
from .models.cache import ModelCache
|
from .models.cache import ModelCache
|
||||||
from .schemas import (
|
from .schemas import (
|
||||||
MessageResponse,
|
MessageResponse,
|
||||||
@@ -20,14 +21,20 @@ from .schemas import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
MultiPartParser.max_file_size = 2**24 # spools to disk if payload is 16 MiB or larger
|
MultiPartParser.max_file_size = 2**24 # spools to disk if payload is 16 MiB or larger
|
||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
def init_state() -> None:
|
def init_state() -> None:
|
||||||
app.state.model_cache = ModelCache(ttl=settings.model_ttl, revalidate=settings.model_ttl > 0)
|
app.state.model_cache = ModelCache(ttl=settings.model_ttl, revalidate=settings.model_ttl > 0)
|
||||||
|
log.info(
|
||||||
|
(
|
||||||
|
"Created in-memory cache with unloading "
|
||||||
|
f"{f'after {settings.model_ttl}s of inactivity' if settings.model_ttl > 0 else 'disabled'}."
|
||||||
|
)
|
||||||
|
)
|
||||||
# asyncio is a huge bottleneck for performance, so we use a thread pool to run blocking code
|
# asyncio is a huge bottleneck for performance, so we use a thread pool to run blocking code
|
||||||
app.state.thread_pool = ThreadPoolExecutor(settings.request_threads)
|
app.state.thread_pool = ThreadPoolExecutor(settings.request_threads)
|
||||||
|
log.info(f"Initialized request thread pool with {settings.request_threads} threads.")
|
||||||
|
|
||||||
|
|
||||||
@app.on_event("startup")
|
@app.on_event("startup")
|
||||||
@@ -77,4 +84,6 @@ if __name__ == "__main__":
|
|||||||
port=settings.port,
|
port=settings.port,
|
||||||
reload=is_dev,
|
reload=is_dev,
|
||||||
workers=settings.workers,
|
workers=settings.workers,
|
||||||
|
log_config=None,
|
||||||
|
access_log=log.isEnabledFor(logging.INFO),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import os
|
|
||||||
import pickle
|
import pickle
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -11,7 +10,7 @@ from zipfile import BadZipFile
|
|||||||
import onnxruntime as ort
|
import onnxruntime as ort
|
||||||
from onnxruntime.capi.onnxruntime_pybind11_state import InvalidProtobuf # type: ignore
|
from onnxruntime.capi.onnxruntime_pybind11_state import InvalidProtobuf # type: ignore
|
||||||
|
|
||||||
from ..config import get_cache_dir, settings
|
from ..config import get_cache_dir, log, settings
|
||||||
from ..schemas import ModelType
|
from ..schemas import ModelType
|
||||||
|
|
||||||
|
|
||||||
@@ -37,22 +36,41 @@ class InferenceModel(ABC):
|
|||||||
self.provider_options = model_kwargs.pop(
|
self.provider_options = model_kwargs.pop(
|
||||||
"provider_options", [{"arena_extend_strategy": "kSameAsRequested"}] * len(self.providers)
|
"provider_options", [{"arena_extend_strategy": "kSameAsRequested"}] * len(self.providers)
|
||||||
)
|
)
|
||||||
|
log.debug(
|
||||||
|
(
|
||||||
|
f"Setting '{self.model_name}' execution providers to {self.providers}"
|
||||||
|
"in descending order of preference"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
log.debug(f"Setting execution provider options to {self.provider_options}")
|
||||||
self.sess_options = PicklableSessionOptions()
|
self.sess_options = PicklableSessionOptions()
|
||||||
# avoid thread contention between models
|
# avoid thread contention between models
|
||||||
if inter_op_num_threads > 1:
|
if inter_op_num_threads > 1:
|
||||||
self.sess_options.execution_mode = ort.ExecutionMode.ORT_PARALLEL
|
self.sess_options.execution_mode = ort.ExecutionMode.ORT_PARALLEL
|
||||||
|
|
||||||
|
log.debug(f"Setting execution_mode to {self.sess_options.execution_mode.name}")
|
||||||
|
log.debug(f"Setting inter_op_num_threads to {inter_op_num_threads}")
|
||||||
|
log.debug(f"Setting intra_op_num_threads to {intra_op_num_threads}")
|
||||||
self.sess_options.inter_op_num_threads = inter_op_num_threads
|
self.sess_options.inter_op_num_threads = inter_op_num_threads
|
||||||
self.sess_options.intra_op_num_threads = intra_op_num_threads
|
self.sess_options.intra_op_num_threads = intra_op_num_threads
|
||||||
|
|
||||||
try:
|
try:
|
||||||
loader(**model_kwargs)
|
loader(**model_kwargs)
|
||||||
except (OSError, InvalidProtobuf, BadZipFile):
|
except (OSError, InvalidProtobuf, BadZipFile):
|
||||||
|
log.warn(
|
||||||
|
(
|
||||||
|
f"Failed to load {self.model_type.replace('_', ' ')} model '{self.model_name}'."
|
||||||
|
"Clearing cache and retrying."
|
||||||
|
)
|
||||||
|
)
|
||||||
self.clear_cache()
|
self.clear_cache()
|
||||||
loader(**model_kwargs)
|
loader(**model_kwargs)
|
||||||
|
|
||||||
def download(self, **model_kwargs: Any) -> None:
|
def download(self, **model_kwargs: Any) -> None:
|
||||||
if not self.cached:
|
if not self.cached:
|
||||||
print(f"Downloading {self.model_type.value.replace('_', ' ')} model. This may take a while...")
|
log.info(
|
||||||
|
(f"Downloading {self.model_type.replace('_', ' ')} model '{self.model_name}'." "This may take a while.")
|
||||||
|
)
|
||||||
self._download(**model_kwargs)
|
self._download(**model_kwargs)
|
||||||
|
|
||||||
def load(self, **model_kwargs: Any) -> None:
|
def load(self, **model_kwargs: Any) -> None:
|
||||||
@@ -62,7 +80,7 @@ class InferenceModel(ABC):
|
|||||||
|
|
||||||
def predict(self, inputs: Any, **model_kwargs: Any) -> Any:
|
def predict(self, inputs: Any, **model_kwargs: Any) -> Any:
|
||||||
if not self._loaded:
|
if not self._loaded:
|
||||||
print(f"Loading {self.model_type.value.replace('_', ' ')} model...")
|
log.info(f"Loading {self.model_type.replace('_', ' ')} model '{self.model_name}'")
|
||||||
self.load()
|
self.load()
|
||||||
if model_kwargs:
|
if model_kwargs:
|
||||||
self.configure(**model_kwargs)
|
self.configure(**model_kwargs)
|
||||||
@@ -109,13 +127,23 @@ class InferenceModel(ABC):
|
|||||||
|
|
||||||
def clear_cache(self) -> None:
|
def clear_cache(self) -> None:
|
||||||
if not self.cache_dir.exists():
|
if not self.cache_dir.exists():
|
||||||
|
log.warn(
|
||||||
|
f"Attempted to clear cache for model '{self.model_name}' but cache directory does not exist.",
|
||||||
|
)
|
||||||
return
|
return
|
||||||
if not rmtree.avoids_symlink_attacks:
|
if not rmtree.avoids_symlink_attacks:
|
||||||
raise RuntimeError("Attempted to clear cache, but rmtree is not safe on this platform.")
|
raise RuntimeError("Attempted to clear cache, but rmtree is not safe on this platform.")
|
||||||
|
|
||||||
if self.cache_dir.is_dir():
|
if self.cache_dir.is_dir():
|
||||||
|
log.info(f"Cleared cache directory for model '{self.model_name}'.")
|
||||||
rmtree(self.cache_dir)
|
rmtree(self.cache_dir)
|
||||||
else:
|
else:
|
||||||
|
log.warn(
|
||||||
|
(
|
||||||
|
f"Encountered file instead of directory at cache path "
|
||||||
|
f"for '{self.model_name}'. Removing file and replacing with a directory."
|
||||||
|
),
|
||||||
|
)
|
||||||
self.cache_dir.unlink()
|
self.cache_dir.unlink()
|
||||||
self.cache_dir.mkdir(parents=True, exist_ok=True)
|
self.cache_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ from clip_server.model.tokenization import Tokenizer
|
|||||||
from PIL import Image
|
from PIL import Image
|
||||||
from torchvision.transforms import CenterCrop, Compose, Normalize, Resize, ToTensor
|
from torchvision.transforms import CenterCrop, Compose, Normalize, Resize, ToTensor
|
||||||
|
|
||||||
|
from ..config import log
|
||||||
from ..schemas import ModelType
|
from ..schemas import ModelType
|
||||||
from .base import InferenceModel
|
from .base import InferenceModel
|
||||||
|
|
||||||
@@ -105,9 +106,11 @@ class CLIPEncoder(InferenceModel):
|
|||||||
if model_name in _MODELS:
|
if model_name in _MODELS:
|
||||||
return model_name
|
return model_name
|
||||||
elif model_name in _ST_TO_JINA_MODEL_NAME:
|
elif model_name in _ST_TO_JINA_MODEL_NAME:
|
||||||
print(
|
log.warn(
|
||||||
(f"Warning: Sentence-Transformer model names such as '{model_name}' are no longer supported."),
|
(
|
||||||
(f"Using '{_ST_TO_JINA_MODEL_NAME[model_name]}' instead as it is the best match for '{model_name}'."),
|
f"Sentence-Transformer models like '{model_name}' are not supported."
|
||||||
|
f"Using '{_ST_TO_JINA_MODEL_NAME[model_name]}' instead as it is the best match for '{model_name}'."
|
||||||
|
),
|
||||||
)
|
)
|
||||||
return _ST_TO_JINA_MODEL_NAME[model_name]
|
return _ST_TO_JINA_MODEL_NAME[model_name]
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class FaceRecognizer(InferenceModel):
|
|||||||
cache_dir: Path | str | None = None,
|
cache_dir: Path | str | None = None,
|
||||||
**model_kwargs: Any,
|
**model_kwargs: Any,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.min_score = min_score
|
self.min_score = model_kwargs.pop("minScore", min_score)
|
||||||
super().__init__(model_name, cache_dir, **model_kwargs)
|
super().__init__(model_name, cache_dir, **model_kwargs)
|
||||||
|
|
||||||
def _download(self, **model_kwargs: Any) -> None:
|
def _download(self, **model_kwargs: Any) -> None:
|
||||||
@@ -105,4 +105,4 @@ class FaceRecognizer(InferenceModel):
|
|||||||
return self.cache_dir.is_dir() and any(self.cache_dir.glob("*.onnx"))
|
return self.cache_dir.is_dir() and any(self.cache_dir.glob("*.onnx"))
|
||||||
|
|
||||||
def configure(self, **model_kwargs: Any) -> None:
|
def configure(self, **model_kwargs: Any) -> None:
|
||||||
self.det_model.det_thresh = model_kwargs.get("min_score", self.det_model.det_thresh)
|
self.det_model.det_thresh = model_kwargs.pop("minScore", self.det_model.det_thresh)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ from optimum.pipelines import pipeline
|
|||||||
from PIL import Image
|
from PIL import Image
|
||||||
from transformers import AutoImageProcessor
|
from transformers import AutoImageProcessor
|
||||||
|
|
||||||
|
from ..config import log
|
||||||
from ..schemas import ModelType
|
from ..schemas import ModelType
|
||||||
from .base import InferenceModel
|
from .base import InferenceModel
|
||||||
|
|
||||||
@@ -22,7 +23,7 @@ class ImageClassifier(InferenceModel):
|
|||||||
cache_dir: Path | str | None = None,
|
cache_dir: Path | str | None = None,
|
||||||
**model_kwargs: Any,
|
**model_kwargs: Any,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.min_score = min_score
|
self.min_score = model_kwargs.pop("minScore", min_score)
|
||||||
super().__init__(model_name, cache_dir, **model_kwargs)
|
super().__init__(model_name, cache_dir, **model_kwargs)
|
||||||
|
|
||||||
def _download(self, **model_kwargs: Any) -> None:
|
def _download(self, **model_kwargs: Any) -> None:
|
||||||
@@ -35,19 +36,25 @@ class ImageClassifier(InferenceModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def _load(self, **model_kwargs: Any) -> None:
|
def _load(self, **model_kwargs: Any) -> None:
|
||||||
processor = AutoImageProcessor.from_pretrained(self.cache_dir)
|
processor = AutoImageProcessor.from_pretrained(self.cache_dir, cache_dir=self.cache_dir)
|
||||||
|
model_path = self.cache_dir / "model.onnx"
|
||||||
model_kwargs |= {
|
model_kwargs |= {
|
||||||
"cache_dir": self.cache_dir,
|
"cache_dir": self.cache_dir,
|
||||||
"provider": self.providers[0],
|
"provider": self.providers[0],
|
||||||
"provider_options": self.provider_options[0],
|
"provider_options": self.provider_options[0],
|
||||||
"session_options": self.sess_options,
|
"session_options": self.sess_options,
|
||||||
}
|
}
|
||||||
model_path = self.cache_dir / "model.onnx"
|
|
||||||
|
|
||||||
if model_path.exists():
|
if model_path.exists():
|
||||||
model = ORTModelForImageClassification.from_pretrained(self.cache_dir, **model_kwargs)
|
model = ORTModelForImageClassification.from_pretrained(self.cache_dir, **model_kwargs)
|
||||||
self.model = pipeline(self.model_type.value, model, feature_extractor=processor)
|
self.model = pipeline(self.model_type.value, model, feature_extractor=processor)
|
||||||
else:
|
else:
|
||||||
|
log.info(
|
||||||
|
(
|
||||||
|
f"ONNX model not found in cache directory for '{self.model_name}'."
|
||||||
|
"Exporting optimized model for future use."
|
||||||
|
),
|
||||||
|
)
|
||||||
self.sess_options.optimized_model_filepath = model_path.as_posix()
|
self.sess_options.optimized_model_filepath = model_path.as_posix()
|
||||||
self.model = pipeline(
|
self.model = pipeline(
|
||||||
self.model_type.value,
|
self.model_type.value,
|
||||||
@@ -65,4 +72,4 @@ class ImageClassifier(InferenceModel):
|
|||||||
return tags
|
return tags
|
||||||
|
|
||||||
def configure(self, **model_kwargs: Any) -> None:
|
def configure(self, **model_kwargs: Any) -> None:
|
||||||
self.min_score = model_kwargs.get("min_score", self.min_score)
|
self.min_score = model_kwargs.pop("minScore", self.min_score)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "machine-learning"
|
name = "machine-learning"
|
||||||
version = "1.76.0"
|
version = "1.76.1"
|
||||||
description = ""
|
description = ""
|
||||||
authors = ["Hau Tran <alex.tran1502@gmail.com>"]
|
authors = ["Hau Tran <alex.tran1502@gmail.com>"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ platform :android do
|
|||||||
build_type: 'Release',
|
build_type: 'Release',
|
||||||
properties: {
|
properties: {
|
||||||
"android.injected.version.code" => 99,
|
"android.injected.version.code" => 99,
|
||||||
"android.injected.version.name" => "1.76.0",
|
"android.injected.version.name" => "1.76.1",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab')
|
upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab')
|
||||||
|
|||||||
@@ -10,12 +10,12 @@
|
|||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="1: bundleRelease" time="67.877631">
|
<testcase classname="fastlane.lanes" name="1: bundleRelease" time="63.585931">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="2: upload_to_play_store" time="23.895222">
|
<testcase classname="fastlane.lanes" name="2: upload_to_play_store" time="24.755096">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|||||||
@@ -169,4 +169,4 @@ SPEC CHECKSUMS:
|
|||||||
|
|
||||||
PODFILE CHECKSUM: 599d8aeb73728400c15364e734525722250a5382
|
PODFILE CHECKSUM: 599d8aeb73728400c15364e734525722250a5382
|
||||||
|
|
||||||
COCOAPODS: 1.11.3
|
COCOAPODS: 1.12.1
|
||||||
|
|||||||
@@ -379,7 +379,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 113;
|
CURRENT_PROJECT_VERSION = 116;
|
||||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
@@ -515,7 +515,7 @@
|
|||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 113;
|
CURRENT_PROJECT_VERSION = 116;
|
||||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
@@ -543,7 +543,7 @@
|
|||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 113;
|
CURRENT_PROJECT_VERSION = 116;
|
||||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
|||||||
@@ -59,11 +59,11 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.73.0</string>
|
<string>1.76.0</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>113</string>
|
<string>116</string>
|
||||||
<key>FLTEnableImpeller</key>
|
<key>FLTEnableImpeller</key>
|
||||||
<true />
|
<true />
|
||||||
<key>ITSAppUsesNonExemptEncryption</key>
|
<key>ITSAppUsesNonExemptEncryption</key>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ platform :ios do
|
|||||||
desc "iOS Beta"
|
desc "iOS Beta"
|
||||||
lane :beta do
|
lane :beta do
|
||||||
increment_version_number(
|
increment_version_number(
|
||||||
version_number: "1.76.0"
|
version_number: "1.76.1"
|
||||||
)
|
)
|
||||||
increment_build_number(
|
increment_build_number(
|
||||||
build_number: latest_testflight_build_number + 1,
|
build_number: latest_testflight_build_number + 1,
|
||||||
|
|||||||
@@ -5,32 +5,32 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000187">
|
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000243">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="1: increment_version_number" time="2.403882">
|
<testcase classname="fastlane.lanes" name="1: increment_version_number" time="2.611762">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="2: latest_testflight_build_number" time="5.068392">
|
<testcase classname="fastlane.lanes" name="2: latest_testflight_build_number" time="6.937008">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="3: increment_build_number" time="1.988079">
|
<testcase classname="fastlane.lanes" name="3: increment_build_number" time="2.740416">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="4: build_app" time="96.47923">
|
<testcase classname="fastlane.lanes" name="4: build_app" time="93.625943">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="5: upload_to_testflight" time="57.517755">
|
<testcase classname="fastlane.lanes" name="5: upload_to_testflight" time="62.107671">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|||||||
2
mobile/openapi/README.md
generated
2
mobile/openapi/README.md
generated
@@ -3,7 +3,7 @@ Immich API
|
|||||||
|
|
||||||
This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
||||||
|
|
||||||
- API version: 1.76.0
|
- API version: 1.76.1
|
||||||
- Build package: org.openapitools.codegen.languages.DartClientCodegen
|
- Build package: org.openapitools.codegen.languages.DartClientCodegen
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ name: immich_mobile
|
|||||||
description: Immich - selfhosted backup media file on mobile phone
|
description: Immich - selfhosted backup media file on mobile phone
|
||||||
|
|
||||||
publish_to: "none"
|
publish_to: "none"
|
||||||
version: 1.76.0+99
|
version: 1.76.1+99
|
||||||
isar_version: &isar_version 3.1.0+1
|
isar_version: &isar_version 3.1.0+1
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
|
|||||||
@@ -4680,7 +4680,7 @@
|
|||||||
"info": {
|
"info": {
|
||||||
"title": "Immich",
|
"title": "Immich",
|
||||||
"description": "Immich API",
|
"description": "Immich API",
|
||||||
"version": "1.76.0",
|
"version": "1.76.1",
|
||||||
"contact": {}
|
"contact": {}
|
||||||
},
|
},
|
||||||
"tags": [],
|
"tags": [],
|
||||||
|
|||||||
4
server/package-lock.json
generated
4
server/package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "immich",
|
"name": "immich",
|
||||||
"version": "1.76.0",
|
"version": "1.76.1",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "immich",
|
"name": "immich",
|
||||||
"version": "1.76.0",
|
"version": "1.76.1",
|
||||||
"license": "UNLICENSED",
|
"license": "UNLICENSED",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.22.11",
|
"@babel/runtime": "^7.22.11",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "immich",
|
"name": "immich",
|
||||||
"version": "1.76.0",
|
"version": "1.76.1",
|
||||||
"description": "",
|
"description": "",
|
||||||
"author": "",
|
"author": "",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
|||||||
@@ -43,7 +43,10 @@ export class MachineLearningRepository implements IMachineLearningRepository {
|
|||||||
|
|
||||||
async getFormData(input: TextModelInput | VisionModelInput, config: ModelConfig): Promise<FormData> {
|
async getFormData(input: TextModelInput | VisionModelInput, config: ModelConfig): Promise<FormData> {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
const { modelName, modelType, ...options } = config;
|
const { enabled, modelName, modelType, ...options } = config;
|
||||||
|
if (!enabled) {
|
||||||
|
throw new Error(`${modelType} is not enabled`);
|
||||||
|
}
|
||||||
|
|
||||||
formData.append('modelName', modelName);
|
formData.append('modelName', modelName);
|
||||||
if (modelType) {
|
if (modelType) {
|
||||||
|
|||||||
2
web/src/api/open-api/api.ts
generated
2
web/src/api/open-api/api.ts
generated
@@ -4,7 +4,7 @@
|
|||||||
* Immich
|
* Immich
|
||||||
* Immich API
|
* Immich API
|
||||||
*
|
*
|
||||||
* The version of the OpenAPI document: 1.76.0
|
* The version of the OpenAPI document: 1.76.1
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
|||||||
2
web/src/api/open-api/base.ts
generated
2
web/src/api/open-api/base.ts
generated
@@ -4,7 +4,7 @@
|
|||||||
* Immich
|
* Immich
|
||||||
* Immich API
|
* Immich API
|
||||||
*
|
*
|
||||||
* The version of the OpenAPI document: 1.76.0
|
* The version of the OpenAPI document: 1.76.1
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
|||||||
2
web/src/api/open-api/common.ts
generated
2
web/src/api/open-api/common.ts
generated
@@ -4,7 +4,7 @@
|
|||||||
* Immich
|
* Immich
|
||||||
* Immich API
|
* Immich API
|
||||||
*
|
*
|
||||||
* The version of the OpenAPI document: 1.76.0
|
* The version of the OpenAPI document: 1.76.1
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
|||||||
2
web/src/api/open-api/configuration.ts
generated
2
web/src/api/open-api/configuration.ts
generated
@@ -4,7 +4,7 @@
|
|||||||
* Immich
|
* Immich
|
||||||
* Immich API
|
* Immich API
|
||||||
*
|
*
|
||||||
* The version of the OpenAPI document: 1.76.0
|
* The version of the OpenAPI document: 1.76.1
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
|||||||
2
web/src/api/open-api/index.ts
generated
2
web/src/api/open-api/index.ts
generated
@@ -4,7 +4,7 @@
|
|||||||
* Immich
|
* Immich
|
||||||
* Immich API
|
* Immich API
|
||||||
*
|
*
|
||||||
* The version of the OpenAPI document: 1.76.0
|
* The version of the OpenAPI document: 1.76.1
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
|||||||
Reference in New Issue
Block a user