mirror of
https://github.com/KevinMidboe/immich.git
synced 2025-10-29 17:40:28 +00:00
feat(web,server)!: configure machine learning via the UI (#3768)
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
import { IsBoolean, IsUrl, ValidateIf } from 'class-validator';
|
||||
|
||||
export class SystemConfigMachineLearningDto {
|
||||
@IsBoolean()
|
||||
enabled!: boolean;
|
||||
|
||||
@IsUrl({ require_tld: false })
|
||||
@ValidateIf((dto) => dto.enabled)
|
||||
url!: string;
|
||||
|
||||
@IsBoolean()
|
||||
clipEncodeEnabled!: boolean;
|
||||
|
||||
@IsBoolean()
|
||||
facialRecognitionEnabled!: boolean;
|
||||
|
||||
@IsBoolean()
|
||||
tagImageEnabled!: boolean;
|
||||
}
|
||||
@@ -4,16 +4,22 @@ import { Type } from 'class-transformer';
|
||||
import { IsObject, ValidateNested } from 'class-validator';
|
||||
import { SystemConfigFFmpegDto } from './system-config-ffmpeg.dto';
|
||||
import { SystemConfigJobDto } from './system-config-job.dto';
|
||||
import { SystemConfigMachineLearningDto } from './system-config-machine-learning.dto';
|
||||
import { SystemConfigOAuthDto } from './system-config-oauth.dto';
|
||||
import { SystemConfigPasswordLoginDto } from './system-config-password-login.dto';
|
||||
import { SystemConfigStorageTemplateDto } from './system-config-storage-template.dto';
|
||||
|
||||
export class SystemConfigDto {
|
||||
export class SystemConfigDto implements SystemConfig {
|
||||
@Type(() => SystemConfigFFmpegDto)
|
||||
@ValidateNested()
|
||||
@IsObject()
|
||||
ffmpeg!: SystemConfigFFmpegDto;
|
||||
|
||||
@Type(() => SystemConfigMachineLearningDto)
|
||||
@ValidateNested()
|
||||
@IsObject()
|
||||
machineLearning!: SystemConfigMachineLearningDto;
|
||||
|
||||
@Type(() => SystemConfigOAuthDto)
|
||||
@ValidateNested()
|
||||
@IsObject()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export * from './dto';
|
||||
export * from './response-dto';
|
||||
export * from './system-config.constants';
|
||||
export * from './system-config.core';
|
||||
export * from './system-config.repository';
|
||||
export * from './system-config.service';
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
TranscodePolicy,
|
||||
VideoCodec,
|
||||
} from '@app/infra/entities';
|
||||
import { BadRequestException, Injectable, Logger } from '@nestjs/common';
|
||||
import { BadRequestException, ForbiddenException, Injectable, Logger } from '@nestjs/common';
|
||||
import * as _ from 'lodash';
|
||||
import { Subject } from 'rxjs';
|
||||
import { DeepPartial } from 'typeorm';
|
||||
@@ -44,6 +44,13 @@ export const defaults = Object.freeze<SystemConfig>({
|
||||
[QueueName.THUMBNAIL_GENERATION]: { concurrency: 5 },
|
||||
[QueueName.VIDEO_CONVERSION]: { concurrency: 1 },
|
||||
},
|
||||
machineLearning: {
|
||||
enabled: process.env.IMMICH_MACHINE_LEARNING_ENABLED !== 'false',
|
||||
url: process.env.IMMICH_MACHINE_LEARNING_URL || 'http://immich-machine-learning:3003',
|
||||
facialRecognitionEnabled: true,
|
||||
tagImageEnabled: true,
|
||||
clipEncodeEnabled: true,
|
||||
},
|
||||
oauth: {
|
||||
enabled: false,
|
||||
issuerUrl: '',
|
||||
@@ -71,6 +78,19 @@ export const defaults = Object.freeze<SystemConfig>({
|
||||
},
|
||||
});
|
||||
|
||||
export enum FeatureFlag {
|
||||
CLIP_ENCODE = 'clipEncode',
|
||||
FACIAL_RECOGNITION = 'facialRecognition',
|
||||
TAG_IMAGE = 'tagImage',
|
||||
SIDECAR = 'sidecar',
|
||||
SEARCH = 'search',
|
||||
OAUTH = 'oauth',
|
||||
OAUTH_AUTO_LAUNCH = 'oauthAutoLaunch',
|
||||
PASSWORD_LOGIN = 'passwordLogin',
|
||||
}
|
||||
|
||||
export type FeatureFlags = Record<FeatureFlag, boolean>;
|
||||
|
||||
const singleton = new Subject<SystemConfig>();
|
||||
|
||||
@Injectable()
|
||||
@@ -82,6 +102,53 @@ export class SystemConfigCore {
|
||||
|
||||
constructor(private repository: ISystemConfigRepository) {}
|
||||
|
||||
async requireFeature(feature: FeatureFlag) {
|
||||
const hasFeature = await this.hasFeature(feature);
|
||||
if (!hasFeature) {
|
||||
switch (feature) {
|
||||
case FeatureFlag.CLIP_ENCODE:
|
||||
throw new BadRequestException('Clip encoding is not enabled');
|
||||
case FeatureFlag.FACIAL_RECOGNITION:
|
||||
throw new BadRequestException('Facial recognition is not enabled');
|
||||
case FeatureFlag.TAG_IMAGE:
|
||||
throw new BadRequestException('Image tagging is not enabled');
|
||||
case FeatureFlag.SIDECAR:
|
||||
throw new BadRequestException('Sidecar is not enabled');
|
||||
case FeatureFlag.SEARCH:
|
||||
throw new BadRequestException('Search is not enabled');
|
||||
case FeatureFlag.OAUTH:
|
||||
throw new BadRequestException('OAuth is not enabled');
|
||||
case FeatureFlag.PASSWORD_LOGIN:
|
||||
throw new BadRequestException('Password login is not enabled');
|
||||
default:
|
||||
throw new ForbiddenException(`Missing required feature: ${feature}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async hasFeature(feature: FeatureFlag) {
|
||||
const features = await this.getFeatures();
|
||||
return features[feature] ?? false;
|
||||
}
|
||||
|
||||
async getFeatures(): Promise<FeatureFlags> {
|
||||
const config = await this.getConfig();
|
||||
const mlEnabled = config.machineLearning.enabled;
|
||||
|
||||
return {
|
||||
[FeatureFlag.CLIP_ENCODE]: mlEnabled && config.machineLearning.clipEncodeEnabled,
|
||||
[FeatureFlag.FACIAL_RECOGNITION]: mlEnabled && config.machineLearning.facialRecognitionEnabled,
|
||||
[FeatureFlag.TAG_IMAGE]: mlEnabled && config.machineLearning.tagImageEnabled,
|
||||
[FeatureFlag.SIDECAR]: true,
|
||||
[FeatureFlag.SEARCH]: process.env.TYPESENSE_ENABLED !== 'false',
|
||||
|
||||
// TODO: use these instead of `POST oauth/config`
|
||||
[FeatureFlag.OAUTH]: config.oauth.enabled,
|
||||
[FeatureFlag.OAUTH_AUTO_LAUNCH]: config.oauth.autoLaunch,
|
||||
[FeatureFlag.PASSWORD_LOGIN]: config.passwordLogin.enabled,
|
||||
};
|
||||
}
|
||||
|
||||
public getDefaults(): SystemConfig {
|
||||
return defaults;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,13 @@ const updatedConfig = Object.freeze<SystemConfig>({
|
||||
accel: TranscodeHWAccel.DISABLED,
|
||||
tonemap: ToneMapping.HABLE,
|
||||
},
|
||||
machineLearning: {
|
||||
enabled: true,
|
||||
url: 'http://immich-machine-learning:3003',
|
||||
facialRecognitionEnabled: true,
|
||||
tagImageEnabled: true,
|
||||
clipEncodeEnabled: true,
|
||||
},
|
||||
oauth: {
|
||||
autoLaunch: true,
|
||||
autoRegister: true,
|
||||
|
||||
Reference in New Issue
Block a user