From 75d07b5ac9aa934fc9a7fb398a45dec4b62777ae Mon Sep 17 00:00:00 2001 From: admin Date: Mon, 8 Jun 2026 15:20:34 +0700 Subject: [PATCH] 690608:1520 ADR-035-135 #09 --- .../ai/processors/ai-batch.processor.spec.ts | 10 +++++++++- .../ai/processors/ai-batch.processor.ts | 7 +++++-- specs/88-logs/_backend_logs.md | Bin 7860 -> 37082 bytes 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/backend/src/modules/ai/processors/ai-batch.processor.spec.ts b/backend/src/modules/ai/processors/ai-batch.processor.spec.ts index c57a3d82..619e9da1 100644 --- a/backend/src/modules/ai/processors/ai-batch.processor.spec.ts +++ b/backend/src/modules/ai/processors/ai-batch.processor.spec.ts @@ -1,5 +1,6 @@ // File: src/modules/ai/processors/ai-batch.processor.spec.ts // Change Log +// - 2026-06-08: เพิ่มการทดสอบการส่งตัวเลือก generate (format: json, num_ctx: 16384) สำหรับ migrate-document // - 2026-05-21: สร้าง Unit Test สำหรับ AiBatchProcessor ครอบคลุม embed-document และ sandbox-rag (T032). // - 2026-05-21: เพิ่มการทดสอบ sandbox-extract พร้อม mock OcrService, OllamaService และ Redis (T039). // - 2026-05-21: แก้ไข ESLint unexpected any และ unsafe member access โดยกำหนด type ให้ redis เป็น Record @@ -520,7 +521,14 @@ describe('AiBatchProcessor', () => { expect(ocrService.detectAndExtract).toHaveBeenCalledWith({ pdfPath: '/files/test.pdf', }); - expect(ollamaService.generate).toHaveBeenCalledTimes(1); + expect(ollamaService.generate).toHaveBeenCalledWith( + expect.any(String), + expect.objectContaining({ + format: 'json', + timeoutMs: 120000, + options: { num_ctx: 16384, num_predict: 4096 }, + }) + ); expect(mockTagsService.findOrSuggestTags).toHaveBeenCalledTimes(1); expect(mockMigrationService.enqueueRecord).toHaveBeenCalledWith( expect.objectContaining({ diff --git a/backend/src/modules/ai/processors/ai-batch.processor.ts b/backend/src/modules/ai/processors/ai-batch.processor.ts index 69bbcd60..4d8528c7 100644 --- a/backend/src/modules/ai/processors/ai-batch.processor.ts +++ b/backend/src/modules/ai/processors/ai-batch.processor.ts @@ -1,5 +1,6 @@ // File: src/modules/ai/processors/ai-batch.processor.ts // Change Log +// - 2026-06-08: แก้ไขปัญหา LLM JSON response truncated โดยการเพิ่ม num_ctx เป็น 16384 ใน sandbox-extract, sandbox-ai-extract และ migrate-document // - 2026-05-15: เพิ่ม processor สำหรับ ai-batch queue ตาม ADR-023A. // - 2026-05-15: เพิ่ม EmbeddingService สำหรับ embed-document logic (T022). // - 2026-05-21: เพิ่มการรองรับ sandbox-rag และ sandbox-extract สำหรับ Superadmin sandbox. @@ -533,7 +534,7 @@ export class AiBatchProcessor extends WorkerHost { { format: 'json', timeoutMs: 120000, - ollamaOptions: { num_ctx: 8192, num_predict: 4096 }, // num_predict ป้องกัน output ถูก truncate + ollamaOptions: { num_ctx: 16384, num_predict: 4096 }, // num_predict ป้องกัน output ถูก truncate } ); await this.aiPromptsService.saveTestResult( @@ -737,7 +738,7 @@ export class AiBatchProcessor extends WorkerHost { { format: 'json', timeoutMs: 120000, - ollamaOptions: { num_ctx: 8192, num_predict: 4096 }, // num_predict ป้องกัน output ถูก truncate + ollamaOptions: { num_ctx: 16384, num_predict: 4096 }, // num_predict ป้องกัน output ถูก truncate } ); @@ -930,7 +931,9 @@ export class AiBatchProcessor extends WorkerHost { let aiResponse: string; try { aiResponse = await this.ollamaService.generate(resolvedPrompt, { + format: 'json', timeoutMs: 120000, + options: { num_ctx: 16384, num_predict: 4096 }, }); } catch (err: unknown) { const errMsg = err instanceof Error ? err.message : String(err); diff --git a/specs/88-logs/_backend_logs.md b/specs/88-logs/_backend_logs.md index b436337b87200fc6e9230282a4ce7a7afc27a321..54075380a8c39e11e8a6f03708ff053eaeb36a78 100644 GIT binary patch literal 37082 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 HKq>!!@yde6 literal 7860 zcmeHM+fLj@7_NGW#5;`kDpB!ad|W$P36hXB4JQE+7b%Ly_HWj~>v6_o*lkp)SABr0 zPnaj^@5AnT3CofMlvIKs#f-=Q`7r-CZ}*^(r-Txs5Z%%6*U$}TgBZST`6eX?yQKQr z*?&piKIL2%Qn37#Y~^{HgiIzpBS}F-nPo|KMtJ6vp_I9=Y1D949sg0^)OB5Bd9uFt z_Uo7(U9z(?5ai9PiWj?JNy>s02$RdWMLaBSWM})9yP(^PB!wf%1v`Ty5En@Zr{p2bd&cdh#+#A6^HScX}Xm>WilKd2p&RFaB)hGSQZ6*O!l80D*IVFA@6xW^5%V|=BK~@ zt(Inb0VuZN>5A*JQ1Jq4C?+-CxbFp^>(-Y^)AHUA#ddaE@fA(v~7^9rrRRLq!rn$OOjXEd4w~rA}X^D6Fpgeb=!yw2#sl60karKo zv7}?ZOYDj<_8N#bs^Tvu7(=S6uHxf0qHiA_?jK&q=S5ADNZvB*szF#mYB^XevEdn0 zNeY#q#F;?m-+bHalA4tl&UDZ9Q5pLR#jwd+`il%od zESajXL9qLmRX;vhY{#qG*0vB_e6!|1|5X31uPr*NIz(Z0z8cAD+h$u&Y$em|dQ`Ws z2oD0@`(^@XxpCrFteV-8mxsyL~s;W6QBO=rT)ih@l~H)qYuVnE;}87i_T1wH z#(5&}R94l?u0>;BX3-6$@=MJ4e_^xO+plK&{Fr_JJ+!fIE6?5Z&;^qB*h3pW_K(m* zZzsz4?xDAn@}Y-5^w6d7OC3VA&AArq`R?V5I(In&G%B_v@4I}_7FzngBS53_Dp7uj z^0m@n59RBjeBE5WjA{95#`~8k4_LZA4xxr}a16kC`jpfo9^qkF3Ou#0ujLg|sHu=$ z;4nUW9DyA2Xz+6TxVw7&h9nBh&-ru3pdF*h!La;1AY@OjSJJ{uaBx%Yt z9HPjhlO&7yWkL3i2_k&@6M_ql^@NNa>v0Xv!wCeh6RFvztC|jZ^!nH1-JK1RCg(t2 zBJRu|lV?N3=Rl)Y1Jvt?1IJ7x(@#3$bsjsCc2+x&oefu1>1^secJ_BxJCB_WR|tMT z+rTui5E{mT^g{kgCHCUlw?6aDLr~KDoO4 z_pBY~D-0Yj0M6UNePNbvhV9J^?{nT4zl2=CCPgS(rQW;w;%LOP*>XK?D~S7KMa;zr z#HOy=Dt*_iU$8WZ7+#6sDy{`Uo3Nv>ift@+X<(9)VB@}aijQ+IATDU#8FfH)a{0|zWAFs`&PEu?PFsW0=( zN||RA4bSzxnPFNK>wpP1D(*sHyN?1JbAdBNGw*_~;Zfh7ldW$$8p!OL%nNulQEL2H z)NZ7UDbabYRlclzP(p+#sNEd9&1=+L_jJG|vUTy0LiX5H_yzW;FT Q-Eb{dpH^?x#MjsU1LK#YsQ>@~