From 85c64eeb0ac6c8058d7ebef71fcd57f9fb01ed37 Mon Sep 17 00:00:00 2001 From: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Fri, 31 Jul 2026 19:27:36 +0900 Subject: [PATCH] =?UTF-8?q?refactor(backend):=20AiService=E3=82=92Sensitiv?= =?UTF-8?q?eMediaDetectionService=E3=81=AB=E3=83=AA=E3=83=8D=E3=83=BC?= =?UTF-8?q?=E3=83=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NSFW推論を本体で行わなくなり、外部サービス (sensitive-detector) への アダプタになったため、AiServiceという名前が実態と合わなくなっていた。 ログドメインも `ai` から `sensitive-media-detection` に変更する。 Co-Authored-By: Claude Opus 5 (1M context) --- CHANGELOG.md | 3 ++- packages/backend/src/core/CoreModule.ts | 12 ++++++------ packages/backend/src/core/FileInfoService.ts | 10 +++++----- ...iService.ts => SensitiveMediaDetectionService.ts} | 7 +++++-- packages/backend/test/unit/FileInfoService.ts | 6 +++--- ...iService.ts => SensitiveMediaDetectionService.ts} | 8 ++++---- .../backend/test/unit/server/FileServerService.ts | 8 ++++---- 7 files changed, 29 insertions(+), 25 deletions(-) rename packages/backend/src/core/{AiService.ts => SensitiveMediaDetectionService.ts} (96%) rename packages/backend/test/unit/{AiService.ts => SensitiveMediaDetectionService.ts} (95%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7051a35b78..a8730616ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,8 @@ - ### Server -- +- Enhance: センシティブメディア判定のログドメイン名を `ai` から `sensitive-media-detection` に変更 + - `logging.domains` で `ai` を指定していた場合は設定の更新が必要です ## 2026.7.0 diff --git a/packages/backend/src/core/CoreModule.ts b/packages/backend/src/core/CoreModule.ts index 6ac4eb9079..b93fcaacb3 100644 --- a/packages/backend/src/core/CoreModule.ts +++ b/packages/backend/src/core/CoreModule.ts @@ -18,7 +18,7 @@ import { FlashService } from '@/core/FlashService.js'; import { ChannelMutingService } from '@/core/ChannelMutingService.js'; import { AccountMoveService } from './AccountMoveService.js'; import { AccountUpdateService } from './AccountUpdateService.js'; -import { AiService } from './AiService.js'; +import { SensitiveMediaDetectionService } from './SensitiveMediaDetectionService.js'; import { AnnouncementService } from './AnnouncementService.js'; import { AntennaService } from './AntennaService.js'; import { AchievementService } from './AchievementService.js'; @@ -164,7 +164,7 @@ const $AbuseReportService: Provider = { provide: 'AbuseReportService', useExisti const $AbuseReportNotificationService: Provider = { provide: 'AbuseReportNotificationService', useExisting: AbuseReportNotificationService }; const $AccountMoveService: Provider = { provide: 'AccountMoveService', useExisting: AccountMoveService }; const $AccountUpdateService: Provider = { provide: 'AccountUpdateService', useExisting: AccountUpdateService }; -const $AiService: Provider = { provide: 'AiService', useExisting: AiService }; +const $SensitiveMediaDetectionService: Provider = { provide: 'SensitiveMediaDetectionService', useExisting: SensitiveMediaDetectionService }; const $AnnouncementService: Provider = { provide: 'AnnouncementService', useExisting: AnnouncementService }; const $AntennaService: Provider = { provide: 'AntennaService', useExisting: AntennaService }; const $AchievementService: Provider = { provide: 'AchievementService', useExisting: AchievementService }; @@ -317,7 +317,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting AbuseReportNotificationService, AccountMoveService, AccountUpdateService, - AiService, + SensitiveMediaDetectionService, AnnouncementService, AntennaService, AchievementService, @@ -468,7 +468,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $AbuseReportNotificationService, $AccountMoveService, $AccountUpdateService, - $AiService, + $SensitiveMediaDetectionService, $AnnouncementService, $AntennaService, $AchievementService, @@ -619,7 +619,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting AbuseReportNotificationService, AccountMoveService, AccountUpdateService, - AiService, + SensitiveMediaDetectionService, AnnouncementService, AntennaService, AchievementService, @@ -769,7 +769,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $AbuseReportNotificationService, $AccountMoveService, $AccountUpdateService, - $AiService, + $SensitiveMediaDetectionService, $AnnouncementService, $AntennaService, $AchievementService, diff --git a/packages/backend/src/core/FileInfoService.ts b/packages/backend/src/core/FileInfoService.ts index 516eb74514..f0befc2a85 100644 --- a/packages/backend/src/core/FileInfoService.ts +++ b/packages/backend/src/core/FileInfoService.ts @@ -16,12 +16,12 @@ import probeImageSize from 'probe-image-size'; import { sharpBmp } from '@misskey-dev/sharp-read-bmp'; import * as blurhash from 'blurhash'; import { createTempDir } from '@/misc/create-temp.js'; -import { AiService } from '@/core/AiService.js'; +import { SensitiveMediaDetectionService } from '@/core/SensitiveMediaDetectionService.js'; import { LoggerService } from '@/core/LoggerService.js'; import type Logger from '@/logger.js'; import { bindThis } from '@/decorators.js'; import { isMimeImage } from '@/misc/is-mime-image.js'; -import type { Prediction } from '@/core/AiService.js'; +import type { Prediction } from '@/core/SensitiveMediaDetectionService.js'; export type FileInfo = { size: number; @@ -54,7 +54,7 @@ export class FileInfoService { private logger: Logger; constructor( - private aiService: AiService, + private sensitiveMediaDetectionService: SensitiveMediaDetectionService, private loggerService: LoggerService, ) { this.logger = this.loggerService.getLogger('file-info'); @@ -266,7 +266,7 @@ export class FileInfoService { fs.promises.unlink(path); } } - const predictions = await this.aiService.detectSensitiveMany(frameBuffers); + const predictions = await this.sensitiveMediaDetectionService.detectSensitiveMany(frameBuffers); const results = predictions.filter((x): x is Prediction[] => x != null).map(x => judgePrediction(x)); // 判定に成功したフレームが 0 件のとき(接続先未設定・通信失敗等)は、 // Math.ceil(0) との比較が 0 >= 0 で真になり全動画がセンシティブ扱いになってしまうため、 @@ -291,7 +291,7 @@ export class FileInfoService { .flatten({ background: { r: 119, g: 119, b: 119 } }) // 透過部分を18%グレーで塗りつぶす .png() .toBuffer(); - const result = await this.aiService.detectSensitive(png); + const result = await this.sensitiveMediaDetectionService.detectSensitive(png); if (result) { [sensitive, porn] = judgePrediction(result); } diff --git a/packages/backend/src/core/AiService.ts b/packages/backend/src/core/SensitiveMediaDetectionService.ts similarity index 96% rename from packages/backend/src/core/AiService.ts rename to packages/backend/src/core/SensitiveMediaDetectionService.ts index fa4792d638..342718f676 100644 --- a/packages/backend/src/core/AiService.ts +++ b/packages/backend/src/core/SensitiveMediaDetectionService.ts @@ -68,8 +68,11 @@ function isDetectImagesResponse(v: unknown): v is DetectImagesResponse { // サイドカーの判定エンドポイント。baseUrl にパスプレフィックスがあっても連結できるよう先頭スラッシュは付けない。 const DETECT_IMAGES_PATH = 'v1/detect-images'; +/** + * センシティブメディア判定 (NSFW検出) を行う外部サービス (sensitive-detector) へのアダプタ。 + */ @Injectable() -export class AiService { +export class SensitiveMediaDetectionService { private logger: Logger; constructor( @@ -79,7 +82,7 @@ export class AiService { private httpRequestService: HttpRequestService, private loggerService: LoggerService, ) { - this.logger = this.loggerService.getLogger('ai'); + this.logger = this.loggerService.getLogger('sensitive-media-detection'); } /** diff --git a/packages/backend/test/unit/FileInfoService.ts b/packages/backend/test/unit/FileInfoService.ts index fa4a13b171..001501fa89 100644 --- a/packages/backend/test/unit/FileInfoService.ts +++ b/packages/backend/test/unit/FileInfoService.ts @@ -14,7 +14,7 @@ import { mockDeep } from 'vitest-mock-extended'; import { GlobalModule } from '@/GlobalModule.js'; import { FileInfo, FileInfoService } from '@/core/FileInfoService.js'; //import { DI } from '@/di-symbols.js'; -import { AiService } from '@/core/AiService.js'; +import { SensitiveMediaDetectionService } from '@/core/SensitiveMediaDetectionService.js'; import { LoggerService } from '@/core/LoggerService.js'; import type { TestingModule } from '@nestjs/testing'; @@ -41,13 +41,13 @@ describe('FileInfoService', () => { GlobalModule, ], providers: [ - AiService, + SensitiveMediaDetectionService, LoggerService, FileInfoService, ], }) .useMocker((token) => { - //if (token === AiService) { + //if (token === SensitiveMediaDetectionService) { // return { }; //} if (typeof token === 'function') { diff --git a/packages/backend/test/unit/AiService.ts b/packages/backend/test/unit/SensitiveMediaDetectionService.ts similarity index 95% rename from packages/backend/test/unit/AiService.ts rename to packages/backend/test/unit/SensitiveMediaDetectionService.ts index 83bf33c079..58155e6932 100644 --- a/packages/backend/test/unit/AiService.ts +++ b/packages/backend/test/unit/SensitiveMediaDetectionService.ts @@ -7,7 +7,7 @@ import { describe, test, expect, vi, beforeEach } from 'vitest'; import type { MiMeta } from '@/models/_.js'; import type { HttpRequestService } from '@/core/HttpRequestService.js'; import type { LoggerService } from '@/core/LoggerService.js'; -import { AiService, type Prediction } from '@/core/AiService.js'; +import { SensitiveMediaDetectionService, type Prediction } from '@/core/SensitiveMediaDetectionService.js'; const sendMock = vi.fn(); @@ -18,13 +18,13 @@ const DEFAULT_META = { sensitiveMediaDetectionMaxImagesPerRequest: 4, }; -function makeService(metaOverrides: Partial = {}): AiService { +function makeService(metaOverrides: Partial = {}): SensitiveMediaDetectionService { const meta = { ...DEFAULT_META, ...metaOverrides } as unknown as MiMeta; const httpRequestService = { send: sendMock } as unknown as HttpRequestService; const loggerService = { getLogger: () => ({ warn: () => {}, error: () => {}, info: () => {} }), } as unknown as LoggerService; - return new AiService(meta, httpRequestService, loggerService); + return new SensitiveMediaDetectionService(meta, httpRequestService, loggerService); } function neutral(): Prediction[] { @@ -42,7 +42,7 @@ function okResponse(results: unknown[]) { const buf = (s: string) => Buffer.from(s); -describe('AiService', () => { +describe('SensitiveMediaDetectionService', () => { beforeEach(() => { sendMock.mockReset(); }); diff --git a/packages/backend/test/unit/server/FileServerService.ts b/packages/backend/test/unit/server/FileServerService.ts index 66843cc4c1..9a8ed97fcb 100644 --- a/packages/backend/test/unit/server/FileServerService.ts +++ b/packages/backend/test/unit/server/FileServerService.ts @@ -11,7 +11,7 @@ import { describe, expect, test, beforeAll, afterAll, afterEach } from 'vitest'; import sharp from 'sharp'; import { DataSource, type Repository } from 'typeorm'; import { initTestDb, randomString } from '../../utils.js'; -import type { AiService } from '@/core/AiService.js'; +import type { SensitiveMediaDetectionService } from '@/core/SensitiveMediaDetectionService.js'; import { DownloadService } from '@/core/DownloadService.js'; import { FileInfoService } from '@/core/FileInfoService.js'; import { HttpRequestService } from '@/core/HttpRequestService.js'; @@ -147,11 +147,11 @@ describe('FileServerService', () => { driveFilesRepository = db.getRepository(MiDriveFile); const loggerService = new LoggerService(); - const aiService = { + const sensitiveMediaDetectionService = { detectSensitive: async () => null, detectSensitiveMany: async (sources: Buffer[]) => sources.map(() => null), - } as unknown as AiService; - const fileInfoService = new FileInfoService(aiService, loggerService); + } as unknown as SensitiveMediaDetectionService; + const fileInfoService = new FileInfoService(sensitiveMediaDetectionService, loggerService); const httpRequestService = new HttpRequestService(config); const downloadService = new DownloadService(config, httpRequestService, loggerService); const imageProcessingService = new ImageProcessingService();