From 3c80617ffbed0f9d5bdb81475e4416c6d4d015ed Mon Sep 17 00:00:00 2001 From: admin Date: Mon, 1 Jun 2026 09:14:57 +0700 Subject: [PATCH] 690601:0914 ADR-032-232 #02 --- backend/src/modules/ai/ai.controller.ts | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/backend/src/modules/ai/ai.controller.ts b/backend/src/modules/ai/ai.controller.ts index 4f8c8526..174917fe 100644 --- a/backend/src/modules/ai/ai.controller.ts +++ b/backend/src/modules/ai/ai.controller.ts @@ -10,6 +10,7 @@ // - 2026-05-23: เพิ่ม Migration Checkpoint API endpoints แทน MySQL direct access (ADR-023A) // - 2026-05-30: เพิ่ม @UseInterceptors(FileInterceptor('file')) ใน submitSandboxOcr เพื่อแก้ไขปัญหา BadRequestException (File is required) // - 2026-05-30: เพิ่ม endpoints GET/POST/PATCH models และ GET vram/status สำหรับ dynamic AI model management และ VRAM monitoring (T031-T034, US2) +// - 2026-06-01: [BUGFIX] submitSandboxOcr: เพิ่ม @ApiBearerAuth(), @HttpCode(ACCEPTED), Body({ engineType }) และส่ง engineType ไปยัง enqueueSandboxJob // Controller สำหรับ AI Gateway Endpoints (ADR-023) import { @@ -516,9 +517,11 @@ export class AiController { // --- Step 1: OCR Only (สำหรับตรวจคุณภาพ OCR ก่อนทดสอบ AI) --- @Post('admin/sandbox/ocr') - @UseGuards(JwtAuthGuard, RbacGuard) + @UseGuards(JwtAuthGuard, AiEnabledGuard, RbacGuard) + @ApiBearerAuth() @RequirePermission('system.manage_all') @UseInterceptors(FileInterceptor('file')) + @HttpCode(HttpStatus.ACCEPTED) @ApiOperation({ summary: 'Step 1: Run OCR Only — สำหรับตรวจคุณภาพ OCR ก่อนทดสอบ AI', description: @@ -533,6 +536,11 @@ export class AiController { type: 'string', format: 'binary', }, + engineType: { + type: 'string', + enum: ['auto', 'tesseract', 'typhoon-ocr-3b'], + description: 'OCR engine ที่ต้องการใช้ (default: auto)', + }, }, }, }) @@ -541,20 +549,30 @@ export class AiController { new ParseFilePipe({ validators: [ new MaxFileSizeValidator({ maxSize: 50 * 1024 * 1024 }), - new FileTypeValidator({ fileType: 'pdf' }), + new FileTypeValidator({ fileType: /(pdf|application\/pdf)/ }), ], }) ) file: Express.Multer.File, + @Body('engineType') engineType: string | undefined, @CurrentUser() user: User ): Promise<{ requestPublicId: string; jobId: string; status: string }> { const attachment = await this.fileStorageService.upload(file, user.user_id); const requestPublicId = uuidv7(); + // ตรวจสอบและ normalize engineType ให้เป็นค่าที่ valid + const validEngineTypes = ['auto', 'tesseract', 'typhoon-ocr-3b'] as const; + const resolvedEngineType: 'auto' | 'tesseract' | 'typhoon-ocr-3b' = + validEngineTypes.includes( + engineType as 'auto' | 'tesseract' | 'typhoon-ocr-3b' + ) + ? (engineType as 'auto' | 'tesseract' | 'typhoon-ocr-3b') + : 'auto'; const jobId = await this.aiQueueService.enqueueSandboxJob( 'sandbox-ocr-only', { idempotencyKey: requestPublicId, pdfPath: attachment.filePath, + engineType: resolvedEngineType, } ); return { requestPublicId, jobId, status: 'queued' };