# Compression Engines (ไทย) 🌐 **Languages:** 🇺🇸 [English](../../../../compression/COMPRESSION_ENGINES.md) · 🇪🇹 [am](../../../am/docs/compression/COMPRESSION_ENGINES.md) · 🇸🇦 [ar](../../../ar/docs/compression/COMPRESSION_ENGINES.md) · 🇦🇿 [az](../../../az/docs/compression/COMPRESSION_ENGINES.md) · 🇧🇬 [bg](../../../bg/docs/compression/COMPRESSION_ENGINES.md) · 🇧🇩 [bn](../../../bn/docs/compression/COMPRESSION_ENGINES.md) · 🇧🇦 [bs](../../../bs/docs/compression/COMPRESSION_ENGINES.md) · 🇨🇿 [cs](../../../cs/docs/compression/COMPRESSION_ENGINES.md) · 🇩🇰 [da](../../../da/docs/compression/COMPRESSION_ENGINES.md) · 🇩🇪 [de](../../../de/docs/compression/COMPRESSION_ENGINES.md) · 🇬🇷 [el](../../../el/docs/compression/COMPRESSION_ENGINES.md) · 🇪🇸 [es](../../../es/docs/compression/COMPRESSION_ENGINES.md) · 🇪🇪 [et](../../../et/docs/compression/COMPRESSION_ENGINES.md) · 🇮🇷 [fa](../../../fa/docs/compression/COMPRESSION_ENGINES.md) · 🇫🇮 [fi](../../../fi/docs/compression/COMPRESSION_ENGINES.md) · 🇫🇷 [fr](../../../fr/docs/compression/COMPRESSION_ENGINES.md) · 🇮🇪 [ga](../../../ga/docs/compression/COMPRESSION_ENGINES.md) · 🇮🇳 [gu](../../../gu/docs/compression/COMPRESSION_ENGINES.md) · 🇳🇬 [ha](../../../ha/docs/compression/COMPRESSION_ENGINES.md) · 🇮🇱 [he](../../../he/docs/compression/COMPRESSION_ENGINES.md) · 🇮🇳 [hi](../../../hi/docs/compression/COMPRESSION_ENGINES.md) · 🇭🇷 [hr](../../../hr/docs/compression/COMPRESSION_ENGINES.md) · 🇭🇺 [hu](../../../hu/docs/compression/COMPRESSION_ENGINES.md) · 🇦🇲 [hy](../../../hy/docs/compression/COMPRESSION_ENGINES.md) · 🇮🇩 [id](../../../id/docs/compression/COMPRESSION_ENGINES.md) · 🇳🇬 [ig](../../../ig/docs/compression/COMPRESSION_ENGINES.md) · 🇮🇹 [it](../../../it/docs/compression/COMPRESSION_ENGINES.md) · 🇯🇵 [ja](../../../ja/docs/compression/COMPRESSION_ENGINES.md) · 🇬🇪 [ka](../../../ka/docs/compression/COMPRESSION_ENGINES.md) · 🇰🇭 [km](../../../km/docs/compression/COMPRESSION_ENGINES.md) · 🇮🇳 [kn](../../../kn/docs/compression/COMPRESSION_ENGINES.md) · 🇰🇷 [ko](../../../ko/docs/compression/COMPRESSION_ENGINES.md) · 🇱🇹 [lt](../../../lt/docs/compression/COMPRESSION_ENGINES.md) · 🇱🇻 [lv](../../../lv/docs/compression/COMPRESSION_ENGINES.md) · 🇮🇳 [ml](../../../ml/docs/compression/COMPRESSION_ENGINES.md) · 🇮🇳 [mr](../../../mr/docs/compression/COMPRESSION_ENGINES.md) · 🇲🇾 [ms](../../../ms/docs/compression/COMPRESSION_ENGINES.md) · 🇲🇹 [mt](../../../mt/docs/compression/COMPRESSION_ENGINES.md) · 🇲🇲 [my](../../../my/docs/compression/COMPRESSION_ENGINES.md) · 🇳🇵 [ne](../../../ne/docs/compression/COMPRESSION_ENGINES.md) · 🇳🇱 [nl](../../../nl/docs/compression/COMPRESSION_ENGINES.md) · 🇳🇴 [no](../../../no/docs/compression/COMPRESSION_ENGINES.md) · 🇮🇳 [or](../../../or/docs/compression/COMPRESSION_ENGINES.md) · 🇮🇳 [pa](../../../pa/docs/compression/COMPRESSION_ENGINES.md) · 🇵🇭 [phi](../../../phi/docs/compression/COMPRESSION_ENGINES.md) · 🇵🇱 [pl](../../../pl/docs/compression/COMPRESSION_ENGINES.md) · 🇵🇹 [pt](../../../pt/docs/compression/COMPRESSION_ENGINES.md) · 🇧🇷 [pt-BR](../../../pt-BR/docs/compression/COMPRESSION_ENGINES.md) · 🇷🇴 [ro](../../../ro/docs/compression/COMPRESSION_ENGINES.md) · 🇷🇺 [ru](../../../ru/docs/compression/COMPRESSION_ENGINES.md) · 🇱🇰 [si](../../../si/docs/compression/COMPRESSION_ENGINES.md) · 🇸🇰 [sk](../../../sk/docs/compression/COMPRESSION_ENGINES.md) · 🇸🇮 [sl](../../../sl/docs/compression/COMPRESSION_ENGINES.md) · 🇷🇸 [sr](../../../sr/docs/compression/COMPRESSION_ENGINES.md) · 🇸🇪 [sv](../../../sv/docs/compression/COMPRESSION_ENGINES.md) · 🇰🇪 [sw](../../../sw/docs/compression/COMPRESSION_ENGINES.md) · 🇮🇳 [ta](../../../ta/docs/compression/COMPRESSION_ENGINES.md) · 🇮🇳 [te](../../../te/docs/compression/COMPRESSION_ENGINES.md) · 🇹🇷 [tr](../../../tr/docs/compression/COMPRESSION_ENGINES.md) · 🇺🇦 [uk-UA](../../../uk-UA/docs/compression/COMPRESSION_ENGINES.md) · 🇵🇰 [ur](../../../ur/docs/compression/COMPRESSION_ENGINES.md) · 🇺🇿 [uz](../../../uz/docs/compression/COMPRESSION_ENGINES.md) · 🇻🇳 [vi](../../../vi/docs/compression/COMPRESSION_ENGINES.md) · 🇳🇬 [yo](../../../yo/docs/compression/COMPRESSION_ENGINES.md) · 🇨🇳 [zh-CN](../../../zh-CN/docs/compression/COMPRESSION_ENGINES.md) · 🇹🇼 [zh-TW](../../../zh-TW/docs/compression/COMPRESSION_ENGINES.md) --- การบีบอัดของ OmniRoute สร้างขึ้นโดยยึดตามสัญญาของเอนจิน แต่ละโหมดสามารถเรียกใช้เอนจินเดียวได้โดยตรง (`caveman` หรือ `rtk`) หรือใช้ไปป์ไลน์แบบซ้อนที่ให้ผลลัพธ์แน่นอนและเรียกใช้หลายเอนจินตามลำดับ ## โหมด | โหมด | เส้นทางเอนจิน | อินพุตที่ตั้งใจ | | ------------ | ------------------------------------------------------------------------------------------ | ------------------------------------------------ | | `off` | none | การเก็บรักษาพรอมต์ที่แม่นยำ | | `lite` | Caveman lite helpers | การล้างข้อมูลที่มีความเสี่ยงต่ำและทำงานตลอดเวลา | | `standard` | Caveman | การย่อพรอมต์ภาษาธรรมชาติ | | `aggressive` | Caveman + history/tool summarizers | เซสชันแชทที่ยาวนาน | | `ultra` | Caveman + pruning helpers | การกู้คืนขีดจำกัดบริบท | | `rtk` | RTK | เอาต์พุต Terminal, shell, build, test และ git | | `omniglyph` | OmniGlyph | บริบทในรูปแบบรูปภาพบนสายผู้ให้บริการดั้งเดิม | | `stacked` | Pipeline. ค่าเริ่มต้นของคำขอคือ `session-dedup -> lite` ส่วน `rtk -> caveman` เป็นทางเลือก | บันทึกเครื่องมือและข้อความผสมผสาน, ประหยัดสูงสุด | ### โปรไฟล์การบีบอัด OmniGlyph เอนจิน `omniglyph` (แพ็กเกจ `omniglyph`, 1.4.0+) รองรับโปรไฟล์เชิงความหมายที่มีชื่อ ซึ่งตั้งค่าได้ทั่วโลกผ่าน `omniglyph.profile` ในการตั้งค่าการบีบอัด หรือต่อขั้นตอนผ่านการกำหนดค่าขั้นตอนของ stacked pipeline: | โปรไฟล์ | ขอบเขต | | ------------- | ------------------------------------------------------------------------------------------------- | | `aggressive` | ค่าเริ่มต้น. นโยบายที่ใบเสร็จที่เผยแพร่วัดได้ — ระบบรูปภาพ, เอกสารเครื่องมือ และประวัติที่หนาแน่น | | `balanced` | รักษาสถานะปัจจุบันให้เป็นแบบเนทีฟ, ปกป้อง 8 รอบสุดท้าย, ยุบประวัติที่ปิดไปแล้วที่เก่ากว่า | | `coding-safe` | รักษาสิทธิ์, สคีมาเครื่องมือ และเอาต์พุตเครื่องมือปัจจุบันให้เป็นแบบเนทีฟ, ปกป้อง 12 รอบสุดท้าย | | `passthrough` | ส่งต่อโดยไม่มีการแปลง; เอนจินจะถูกข้ามไป | โปรไฟล์เป็น **เพดาน ไม่ใช่พื้น**: `mergeCompressionProfileOptions` ในแพ็กเกจจะปฏิเสธไม่ให้ผู้เรียกใช้เขียนทับเพื่อเปิดเลนที่สูญเสียข้อมูลซึ่งโปรไฟล์ได้ปิดไปแล้ว ดังนั้น `preserveSystemPrompt: false` ต่อขั้นตอนจึงไม่สามารถเปิดใช้งานการบีบอัดระบบใหม่ภายใต้ `coding-safe` ได้ จากการวัดบน codebase นี้: `coding-safe` และ `balanced` จะเพิ่ม `minCompressChars` ให้สูงสุด และรักษาระบบ, สคีมาเครื่องมือ และผลลัพธ์เครื่องมือให้เป็นแบบเนทีฟ ดังนั้นเซสชันที่ยังไม่ได้สะสมประวัติจะหยุดที่ `below_min_chars` และเอนจินจะไม่แปลงอะไรเลย นั่นคือเหตุผลที่ค่าเริ่มต้นคือ `aggressive` แทนที่จะเป็นโปรไฟล์ที่ปลอดภัยที่สุด แพ็กเกจจะแก้ไขขอบเขตโมเดลและโปรไฟล์ของตัวเองจากการกำหนดค่าสภาพแวดล้อม OmniRoute ไม่เคยมอบหมายการตัดสินใจ: อะแดปเตอร์จะตรึงเกตโมเดลไว้ที่ขอบเขตที่จำกัดที่สุดของแพ็กเกจ ดังนั้นการตั้งค่าสภาพแวดล้อมโฮสต์จึงสามารถจำกัด allowlist ให้แคบลงได้เท่านั้น ไม่สามารถขยายให้กว้างเกินกว่าใบเสร็จที่ OmniRoute วัดได้ ## รีจิสทรีเอนจิน รีจิสทรีอยู่ใน `open-sse/services/compression/engines/registry.ts` เอนจินต่าง ๆ ใช้ สัญญาร่วมกันดังนี้: - `id`: รหัสเอนจินที่คงที่ เช่น `caveman` หรือ `rtk` - `apply(text, config)`: เส้นทางการดำเนินการแบบเดิมที่ใช้โดยไปป์ไลน์แบบซ้อน - `compress(input, config)`: เส้นทางการดำเนินการหลักที่ส่งคืนข้อความ + สถิติ - `getConfigSchema()`: ส่งคืนโครงสร้างคล้าย JSON Schema ของการกำหนดค่าที่ถูกต้อง - `validateConfig(config)`: ส่งคืน `{ valid, errors[] }` การลงทะเบียนใช้ `registerCompressionEngine(engine)` (หรือ `registerEngine` สำหรับกรณีขั้นสูง) ซึ่งจะเรียก `assertValidEngine()` และ `validateConfig(defaultConfig)` ก่อนยอมรับ ใช้ `unregisterCompressionEngine(id)` เพื่อลบเอนจินขณะรันไทม์ `strategySelector.ts` ลงทะเบียนเอนจินในตัวก่อนเริ่มการบีบอัด ซึ่งทำให้การแสดงตัวอย่าง การบีบอัดขณะรันไทม์ โหมดซ้อน การทดสอบ และเอนจินในอนาคตใช้เส้นทางการดำเนินการเดียวกัน ### การบีบอัดคำอธิบาย MCP (ที่เกี่ยวข้อง) รีจิสทรีแยกต่างหากจะบีบอัดข้อมูลเมตาคำอธิบายเครื่องมือ MCP ในระดับรีจิสทรี — ดู `open-sse/mcp-server/descriptionCompressor.ts` และ [MCP-SERVER.md](../frameworks/MCP-SERVER.md) โดยนำกฎของ Caveman มาใช้ซ้ำ แต่ทำงานกับข้อมูลเมตาของเครื่องมือ ไม่ใช่เพย์โหลดคำขอ ### เอนจินในตัวเพิ่มเติม นอกเหนือจาก Caveman, RTK และ LLMLingua-2 แล้ว รีจิสทรียังมีเอนจินแบบไม่สูญเสียข้อมูล / เชิงโครงสร้างเฉพาะทางอีกหลายรายการ (ใช้โดยไปป์ไลน์แบบซ้อน สนามทดลอง และการทดสอบ): | เอนจิน | Id | สิ่งที่ทำ | | ------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | CCR | `ccr` | Content-Compress-Retrieve (H4): แทนที่บล็อกข้อความขนาดใหญ่ที่ต่อเนื่องกันด้วยการอ้างอิงตามที่อยู่เนื้อหา เพื่อให้บล็อกที่ซ้ำกัน/ขนาดใหญ่ถูกส่งเพียงครั้งเดียวและอ้างอิงถึงในภายหลัง | | headroom | `headroom` | SmartCrusher (H3 + N5): การย่อข้อมูลแบบตารางโดยไม่สูญเสียข้อมูล สำหรับเพย์โหลดอาร์เรย์ JSON ที่เป็นเนื้อเดียวกัน ให้อยู่ในรูปแบบเชิงคอลัมน์ `[N rows]` | | ionizer | `ionizer` | สุ่มตัวอย่างแถวส่วนหัว/กลาง/ท้ายสำหรับบล็อกเนื้อเดียวกันที่มีขนาดใหญ่มาก โดยจัดเก็บส่วนกลางที่ถูกละไว้เป็นการอ้างอิงตามที่อยู่เนื้อหาของ CCR | | session-dedup | `session-dedup` | การขจัดข้อมูลซ้ำข้ามเทิร์นตามที่อยู่เนื้อหา (ได้แรงบันดาลใจจาก TokenMizer): ละข้อความที่เคยพบแล้วในเทิร์นก่อนหน้าของเซสชันเดียวกัน | **คำสั่งโปรโตคอลการดึงข้อมูลของ CCR (#8033):** ครั้งแรกที่ CCR แทนที่บล็อก ≥1 บล็อกใน คำขอ เอนจินจะเพิ่มข้อความ `system` เพียงข้อความเดียวที่เป็นแบบ idempotent ไว้ด้านหน้า (ขึ้นต้นด้วย เซนทิเนล `[CCR protocol]`) เพื่ออธิบายสัญญาระหว่างมาร์กเกอร์ → เครื่องมือแก่ผู้เรียก ได้แก่ ความหมายของ มาร์กเกอร์ `[CCR retrieve hash=<24hex> chars=N]` ว่าต้องคัดลอกแฮชตามต้นฉบับทุกประการ (อักขระเลขฐานสิบหกทั้ง 24 ตัว — การคัดลอกแฮชผิดเป็นสาเหตุที่เป็นไปได้มากที่สุดของข้อผิดพลาด "block not found") และมาร์กเกอร์ `[dedup:ref sha=...]` หมายถึง "ย้อนกลับไปดูในประวัติ" ไม่ใช่ "เรียกใช้ เครื่องมือ" หมายเหตุนี้จะถูกแทรก **เฉพาะเมื่อ `tools[]` ที่ผู้เรียกประกาศไว้พิสูจน์ได้ว่าสามารถ เข้าถึง `omniroute_ccr_retrieve` ได้จริง** (`callerSupportsCcrRetrieve()` ใน `open-sse/services/compression/engines/ccr/protocolInstruction.ts`) — ผู้เรียกที่เข้ากันได้กับ OpenAI แบบทั่วไปซึ่งไม่มีเครื่องมือนั้น จะไม่ได้รับคำสั่งให้เรียกสิ่งที่ตนเองเข้าถึงไม่ได้ ความเป็น idempotent บังคับใช้โดยการสแกนประวัติข้อความเพื่อหาเซนทิเนลก่อนแทรก ดังนั้น คำขอแบบหลายเทิร์น (ซึ่งเล่นข้อความก่อนหน้าซ้ำ) จะไม่เพิ่มหมายเหตุซ้ำหนึ่งครั้งต่อเทิร์น ## Caveman โหมด Caveman มุ่งเน้นการย่อความเชิงความหมายของข้อความร้อยแก้วทั่วไป: - คงบล็อกโค้ด, URL, JSON, พาธ และข้อมูลที่มีโครงสร้างไว้ - ตัดข้อความส่วนเกิน การใช้ถ้อยคำเลี่ยงความมั่นใจ บริบทที่ซ้ำกัน และวลีเชื่อมความที่เยิ่นเย้อ - รองรับชุดกฎสำหรับไฟล์ที่คำนึงถึงภาษาใน `open-sse/services/compression/rules/` - ยังคงใช้งานได้ผ่านโหมดเดิม `standard`, `aggressive` และ `ultra` ส่วนที่เกี่ยวข้องบนแดชบอร์ดคือ `Dashboard -> Context & Cache -> Caveman` ต้นทางของ Caveman รายงานว่าจำนวนโทเค็นเอาต์พุตลดลง `~75%` และประหยัดเอาต์พุตเฉลี่ย `65%` ในการทดสอบเกณฑ์มาตรฐาน โดยมีช่วงอยู่ที่ `22-87%` รวมถึงเครื่องมือบีบอัดอินพุตที่ `~46%` OmniRoute ใช้ตัวเลขฝั่งอินพุตของ Caveman เมื่อจัดทำเอกสารเกี่ยวกับการประหยัดพรอมต์/บริบทแบบซ้อนกัน ส่วนโหมดเอาต์พุตของ Caveman ยังคงเป็น คุณสมบัติด้านพฤติกรรมการตอบกลับที่แยกต่างหาก ## RTK โหมด RTK มุ่งเน้นเอาต์พุตจากคำสั่งและเครื่องมือ: - ตรวจจับประเภทเอาต์พุต เช่น `git status`, `git branch`, `git diff`, Vitest/Jest/Pytest, การทดสอบ Cargo/Go, บิลด์ TypeScript/Vite/Webpack, ESLint, การตรวจสอบ/ติดตั้งด้วย npm, ล็อก Docker, `find`/`grep` ของเชลล์, สแต็กเทรซ และล็อกทั่วไป - ใช้ตัวกรอง JSON 49 รายการจาก `open-sse/services/compression/engines/rtk/filters/` - รองรับไปป์ไลน์เชิงประกาศแบบ RTK ได้แก่ การตัด ANSI, การแทนที่, การลัดวงจรเมื่อเอาต์พุตตรงกัน, การตัด/เก็บบรรทัด, การตัดทอนรายบรรทัด, การตัดทอนส่วนต้น/ส่วนท้าย/จำนวนบรรทัดสูงสุด และการใช้ค่าทดแทนเมื่อว่าง - รองรับตัวกรองโปรเจกต์ที่ควบคุมด้วยความเชื่อถือใน `.rtk/filters.json` และตัวกรองส่วนกลางใน `DATA_DIR/rtk/filters.json` - ตัดลำดับ ANSI, ข้อความรบกวนจากความคืบหน้า, บรรทัดที่ซ้ำกัน และข้อความสำเร็จรูปที่ไม่เป็นประโยชน์ - คงข้อผิดพลาดที่ดำเนินการแก้ไขได้ คำเตือน สรุป ไฟล์ที่เปลี่ยนแปลง และบริบทส่วนท้ายไว้ - สามารถเลือกเก็บเอาต์พุตดิบที่ผ่านการปกปิดข้อมูลไว้เพื่อการกู้คืน/ดีบักผ่านเส้นทางการจัดการที่ผ่านการยืนยันตัวตน ส่วนที่เกี่ยวข้องบนแดชบอร์ดคือ `Dashboard -> Context & Cache -> RTK` รายละเอียดการดำเนินงานสำหรับตัวกรองแบบกำหนดเอง ความเชื่อถือ การตรวจสอบ และการกู้คืนเอาต์พุตดิบอยู่ใน [`RTK_COMPRESSION.md`](./RTK_COMPRESSION.md) ต้นทางของ RTK รายงานการประหยัด `60-90%` สำหรับการบีบอัดเอาต์พุตจากคำสั่ง ตัวอย่างใน README แสดงให้เห็นว่า เซสชัน Claude Code ระยะเวลา 30 นาทีลดจาก `~118,000` โทเค็นเหลือ `~23,900` หรือประหยัดได้ `79.7%` ## LLMLingua-2 (การตัดทอนเชิงความหมาย) โหมด LLMLingua-2 ดำเนินการ **ตัดทอนโทเค็นเชิงความหมาย** กับข้อความร้อยแก้วโดยใช้ตัวจำแนก โทเค็น ONNX ขนาดเล็ก เพื่อเสริมเอนจิน Caveman และ RTK ที่อิงกฎ: - บีบอัดข้อความร้อยแก้วเฉพาะในข้อความที่ไม่ใช่ system เท่านั้น โดยจะไม่แก้ไขบล็อกโค้ดแบบมีรั้วและ โครงสร้างอื่นๆ ที่ต้องคงไว้ - รันแบ็กเอนด์ `@atjsh/llmlingua-2` (ONNX ผ่าน `@huggingface/transformers`) ใน worker thread ดังนั้นการอนุมานของโมเดลจะไม่บล็อก event loop ของคำขอ - **สามารถซ้อนกันได้** (`stackPriority` 35): ในไปป์ไลน์แบบซ้อน ระบบจะรันหลัง เอนจินเชิงโครงสร้าง (CCR, session-dedup, headroom, Caveman) แต่ก่อน `ultra` เนื่องจาก การตัดทอนเชิงความหมายมีประสิทธิภาพสูงสุดกับข้อความที่ผ่านการบีบอัดเชิงโครงสร้างแล้ว เช่น `rtk -> caveman -> llmlingua` - **เปิดให้ทำงานต่อเมื่อเกิดข้อผิดพลาดทุกประเภท** (ไม่มี optional deps, การสร้าง worker, การโหลดโมเดล, การอนุมาน หรือหมดเวลา) → ระบบจะส่งคืนข้อความต้นฉบับโดยไม่เปลี่ยนแปลง และจะไม่ส่งคืนข้อผิดพลาด ตำแหน่งเอนจิน: `open-sse/services/compression/engines/llmlingua/` ส่วนที่เกี่ยวข้องบนแดชบอร์ด คือ `Dashboard -> Context & Cache -> LLMLingua` ### โมเดล โมเดลเริ่มต้นคือ **TinyBERT** (`atjsh/llmlingua-2-js-tinybert-meetingbank`, ~57 MB, รวดเร็ว) มีโมเดล **BERT-base** ที่มีความแม่นยำสูงกว่า (`Arcoldd/llmlingua4j-bert-base-onnx`, ~710 MB) ให้ใช้งานผ่านฟิลด์ `model` ในการกำหนดค่าเอนจิน `@huggingface/transformers` จะดาวน์โหลดโมเดลที่เลือกแบบล่าช้าจาก HuggingFace Hub ไปยัง `${DATA_DIR}/models/llmlingua` ในการเรียกใช้ครั้งแรก (`modelStore.ts`) ส่วนการกำหนดค่า `modelPath` แบบเขียนทับจะชี้ไปยังสำเนาในเครื่องแทน (สำหรับการติดตั้งแบบออฟไลน์ / แยกขาดจากเครือข่าย) ### การขึ้นต่อกันแบบไม่บังคับและการติดตั้งตามความต้องการ สแต็ก peer ของรันไทม์ LLMLingua ที่สามารถตัดออกได้เป็น **ตัวเลือก** มีการประกาศแพ็กเกจสองรายการเป็น `optionalDependencies` ใน `package.json` และกำหนดให้เป็น **ภายนอก** ในบิลด์สำหรับการใช้งานจริง (`scripts/build/prepublish.ts` จะไม่รวมแพ็กเกจเหล่านี้ไว้): | แพ็กเกจ | เวอร์ชัน (ตรึงไว้) | หมายเหตุ | | -------------------- | ------------------ | --------------------------------------------- | | `@atjsh/llmlingua-2` | `2.0.5` | แพ็กเกจทางเข้า ซึ่งประกาศรายการอื่นเป็น peers | | `js-tiktoken` | `^1.0.20` | ตัวแบ่งโทเค็น | `@huggingface/transformers` ถูกตรึงไว้ที่ `^4.2.0` (ใช้ร่วมกับพาธ embeddings ในเครื่องและ ติดตามรวมไว้ในบันเดิลแบบสแตนด์อโลนด้วย) ส่วน `@atjsh/llmlingua-2@2.0.5` กำหนด peer ไว้เป็น `"^3.5.2 || ^4.0.0"` ดังนั้นจึงรองรับทั้ง Transformers.js v3 และ v4 ตั้งแต่ 2.0.4 เป็นต้นมา `@atjsh/llmlingua-2` ไม่ต้องใช้ `@tensorflow/tfjs` อีกต่อไป ซึ่งนำองค์ประกอบเดี่ยวที่มีขนาดใหญ่ที่สุด (TensorFlow.js) ออกจากสแต็ก SLM มีเพียงสองแพ็กเกจข้างต้นเท่านั้นที่เป็น peer ของ SLM ซึ่งสามารถตัดออกได้ การใช้ `npm install` แบบมาตรฐาน (dev) จะติดตั้งสแต็กตัวเลือกโดยอัตโนมัติ เว้นแต่จะละเว้น การขึ้นต่อกันแบบไม่บังคับ **เหตุผลที่ติดตั้งตามความต้องการ:** แพ็กเกจที่เผยแพร่บน npm, บันเดิลแบบสแตนด์อโลน และอิมเมจ Docker จัดส่งมา **โดยไม่มี** deps เหล่านี้เพื่อให้มีขนาดเล็ก เมื่อไม่มี deps เหล่านี้ เกตตรวจสอบการขึ้นต่อกัน ของ worker (การตรวจสอบการ resolve ของ `@atjsh/llmlingua-2` ใน `worker.ts`) จะล้มเหลว และเอนจินจะ **เปิดให้ทำงานต่อโดยไม่แจ้งเตือน** — การเลือก LLMLingua จะไม่มีผลใดๆ (ส่งคืนข้อความโดยไม่เปลี่ยนแปลงและ ไม่มีการบันทึกข้อผิดพลาด) หากต้องการเปิดใช้งานในสภาพแวดล้อมที่ผ่านการตัดแพ็กเกจออก ให้ติดตั้งสแต็กตัวเลือก: ```bash # ตรึงไว้ตามเวอร์ชันที่ประกาศใน package.json optionalDependencies npm install @atjsh/llmlingua-2@2.0.5 js-tiktoken ``` การนำ `@tensorflow/tfjs` ออก (2.0.4+) ช่วยกำจัดองค์ประกอบขนาด ~800 MB ซึ่งก่อนหน้านี้มีขนาดมากที่สุด โดยพื้นที่ที่เหลือมาจากรันไทม์ transformers.js + onnxruntime-node รวมถึงโมเดล TinyBERT (~57 MB) ที่ดาวน์โหลดเมื่อใช้งานครั้งแรก (ไม่ใช่ผ่าน npm) สำหรับแต่ละสภาพแวดล้อม: - **Dev / `npm install`** — ติดตั้งโดยอัตโนมัติ เว้นแต่คุณจะระบุ `--omit=optional` (หรือ `--no-optional`) ไม่ต้องดำเนินการใดๆ - **Global npm (`npm i -g omniroute`) / แบบสแตนด์อโลน** — เรียกใช้คำสั่งติดตั้งข้างต้นภายใน ไดเรกทอรีของแพ็กเกจที่ติดตั้งไว้ หรือติดตั้งใหม่โดยไม่ละเว้น optional deps - **Docker** — เพิ่มคำสั่งติดตั้งในเลเยอร์ของอิมเมจที่สืบทอดมา โดยอิมเมจที่เผยแพร่ ถูกออกแบบมาให้มีขนาดเล็ก - **VPS (PM2)** — ติดตั้งลงใน `node_modules` ของแอป จากนั้นรีสตาร์ตโปรเซสเพื่อให้ worker ตรวจสอบ gate อีกครั้ง - **Raw Next แบบสแตนด์อโลน (`npm run build` → `.build/next/standalone/server.js`)** — trace แบบสแตนด์อโลนไม่มีทั้ง worker และ optional deps ดังนั้น engine จึงเปิดให้ผ่านเมื่อเกิดข้อผิดพลาดโดยไม่แจ้งเตือน `scripts/build/colocate-standalone.mjs` จะนำทั้งสองส่วนกลับมาใช้อีกครั้ง (worker esbuild + closure ของ optional deps ลงในโครงสร้างสแตนด์อโลน) โดยจะทำงานโดยอัตโนมัติผ่าน npm hook `postbuild` หลังการ build ทุกครั้ง สามารถเรียกซ้ำได้อย่างปลอดภัย และไม่ล้มเหลวรุนแรงเมื่อไม่มี deps **ตรวจสอบว่าเปิดใช้งานอยู่:** เมื่อเลือก LLMLingua แล้ว ข้อความร้อยแก้วจริงจะสั้นลงอย่างเห็นได้ชัด (engine จะหยุดเปิดให้ผ่านเมื่อเกิดข้อผิดพลาด) และคำขอแรกจะทริกเกอร์การดาวน์โหลดโมเดลไปยัง `${DATA_DIR}/models/llmlingua` โดยตั้งใจให้ gate ตรวจสอบเฉพาะ `@atjsh/llmlingua-2` เท่านั้น — peer อื่นๆ เป็น ESM-only และ `require.resolve` จะ throw กับแพ็กเกจเหล่านั้นแม้จะมีอยู่ก็ตาม — ดังนั้น worker จะยังคงเปิดให้ผ่านเมื่อเกิดข้อผิดพลาด หาก peer ใดๆ ขาดหายไปจริงๆ ในขณะ `import()` ## ไปป์ไลน์แบบซ้อน โหมดซ้อนจะเรียกใช้ขั้นตอนของไปป์ไลน์ตามลำดับ ค่าเริ่มต้นคือ: ```txt rtk -> caveman ``` ใช้โหมดนี้สำหรับเซสชันของเอเจนต์เขียนโค้ดที่พรอมต์รวมเอาต์พุตจากคำสั่งเข้ากับข้อความร้อยแก้วจากมนุษย์หรือผู้ช่วย RTK จะลดความฟุ่มเฟือยของบันทึกจากเครื่องมือก่อน จากนั้น Caveman จะบีบอัดภาษาธรรมชาติที่เหลืออยู่ ขั้นตอนของไปป์ไลน์กำหนดค่าได้ด้วย `stackedPipeline` ในการตั้งค่าการบีบอัด หรือผ่านชุดค่าผสมการบีบอัด เมื่อเอนจินทั้งสองลดเพย์โหลดเดียวกันที่เข้าเกณฑ์ การประหยัดจะทบกัน: ```txt combined = 1 - (1 - การประหยัดของ RTK) * (1 - การประหยัดอินพุตของ Caveman) ค่าเฉลี่ย = 1 - (1 - 0.80) * (1 - 0.46) = 89.2% ช่วง = 1 - (1 - 0.60..0.90) * (1 - 0.46) = 78.4-94.6% ``` ## ตัวกรองแผนผังการช่วยการเข้าถึงของ MCP ตัวกรองอัจฉริยะสำหรับแผนผังการช่วยการเข้าถึงของ MCP เป็นชั้นการบีบอัดหลังการดำเนินการที่ทำงานกับ **ผลลัพธ์จากเครื่องมือ** ของ MCP ไม่ใช่กับพรอมต์หรือบริบท โดยมุ่งจัดการเพย์โหลดของแผนผังการช่วยการเข้าถึงและสแนปช็อตของเบราว์เซอร์ที่มีรายละเอียดมาก ซึ่งส่งคืนมาจากเครื่องมือต่างๆ เช่น Playwright, computer-use และเซิร์ฟเวอร์ MCP สำหรับระบบอัตโนมัติของเบราว์เซอร์ ### การทำงาน 1. **การกำจัดข้อมูลรบกวน** — ลบรายการทั่วไป/ข้อความที่ว่างเปล่า (`- generic:`, `- text: ""`) 2. **การยุบรายการระดับเดียวกัน** — เมื่อมีบรรทัดต่อเนื่อง ≥ `collapseThreshold` (ค่าเริ่มต้น 30) ที่มีโครงสร้างซ้ำกัน จะยุบให้เหลือ `collapseKeepHead` บรรทัดแรก (ค่าเริ่มต้น 10) + สรุปจำนวน + `collapseKeepTail` บรรทัดสุดท้าย (ค่าเริ่มต้น 5) 3. **การคง ref ไว้** — จุดอ้างอิง `[ref=eXX]` ที่ Playwright/computer-use ต้องใช้จะไม่ถูกแก้ไข 4. **การตัดทอนแบบตายตัว** — หากข้อความหลังการยุบยังคงเกิน `maxTextChars` (ค่าเริ่มต้น 50,000) จะตัดทอนพร้อมคำแนะนำในการนำทาง เพื่อให้เอเจนต์ทำงานต่อได้ ### ตำแหน่งของเอนจิน ```txt open-sse/services/compression/engines/mcpAccessibility/ index.ts ← จุดเริ่มต้น smartFilterText() collapseRepeated.ts ← อัลกอริทึมการยุบรายการระดับเดียวกัน constants.ts ← DEFAULT_MCP_ACCESSIBILITY_CONFIG ``` ### การกำหนดค่า ควบคุมด้วย `compression.mcpAccessibility` ในการตั้งค่าส่วนกลาง (การย้ายข้อมูล 056) การกำหนดค่าเริ่มต้น: ```json { "enabled": true, "maxTextChars": 50000, "collapseThreshold": 30, "collapseKeepHead": 10, "collapseKeepTail": 5, "minLengthToProcess": 2000 } ``` ตัวกรองจะใช้กับเพย์โหลดผลลัพธ์จากเครื่องมือที่มี `type` เป็น `"text"` และมีความยาวเกิน `minLengthToProcess` เท่านั้น โดยไม่มีผลต่อการบีบอัดพรอมต์หรือเพย์โหลดของคำขอ ### การประหยัดที่คาดไว้ 60–80% สำหรับผลลัพธ์จากเครื่องมือสแนปช็อตของเบราว์เซอร์ โดยขึ้นอยู่กับความซับซ้อนของหน้าเว็บ อัลกอริทึมการยุบมีความซับซ้อน O(n) ตามจำนวนบรรทัด และเพิ่มเวลาแฝงเพียงเล็กน้อยจนแทบไม่มีนัยสำคัญ ### ตัวกรองนี้เทียบกับเอนจินการบีบอัดข้างต้น | ด้าน | Caveman / RTK / Stacked | ตัวกรองการช่วยการเข้าถึงของ MCP | | -------------- | ----------------------- | -------------------------------------- | | เป้าหมาย | พรอมต์คำขอ / บริบท | ผลลัพธ์จากเครื่องมือ MCP | | ตัวกระตุ้น | การตั้งค่าโหมดการบีบอัด | `compression.mcpAccessibility.enabled` | | ขอบเขต | ข้อความ SSE ทั้งหมด | ผลลัพธ์จากเครื่องมือเท่านั้น | | จุดอ้างอิง ref | ไม่มีผล | คงไว้โดยไม่มีเงื่อนไข | --- ## คอมโบการบีบอัด คอมโบการบีบอัดคือโปรไฟล์การบีบอัดที่มีชื่อ ซึ่งสามารถกำหนดให้กับคอมโบการกำหนดเส้นทางได้: - `compression_combos`: จัดเก็บโหมด ไปป์ไลน์ การกำหนดค่า RTK การกำหนดค่าภาษา และตัวบ่งชี้ค่าเริ่มต้น - `compression_combo_assignments`: จับคู่คอมโบการบีบอัดกับคอมโบการกำหนดเส้นทาง - การผสานรวมขณะรันไทม์จะแก้ไขคอมโบการบีบอัดที่กำหนดไว้ก่อนการแทนที่คอมโบทั่วไป - การวิเคราะห์ประกอบด้วย `compression_combo_id` และ `engine` ตำแหน่งในแดชบอร์ด: `Dashboard -> Context & Cache -> Compression Combos` ## พื้นผิว API | เส้นทาง | วัตถุประสงค์ | | -------------------------------------- | --------------------------------------------------------------- | | `/api/settings/compression` | การตั้งค่าการบีบอัดส่วนกลาง (รวมการกำหนดค่า `mcpAccessibility`) | | `/api/compression/preview` | แสดงตัวอย่างโหมดการบีบอัดใดๆ | | `/api/compression/language-packs` | แสดงรายการแพ็กภาษา Caveman ที่พร้อมใช้งาน | | `/api/context/caveman/config` | นามแฝงการตั้งค่า Caveman | | `/api/context/rtk/config` | ค่าเริ่มต้นและการตั้งค่า RTK | | `/api/context/rtk/filters` | แค็ตตาล็อกตัวกรอง RTK | | `/api/context/rtk/test` | เอ็นด์พอยต์แสดงตัวอย่าง/ทดสอบ RTK | | `/api/context/rtk/raw-output/[id]` | การกู้คืนเอาต์พุตดิบที่ปกปิดข้อมูลแล้วและผ่านการยืนยันตัวตน | | `/api/context/combos` | CRUD ของคอมโบการบีบอัด | | `/api/context/combos/[id]/assignments` | CRUD ของการกำหนดคอมโบการกำหนดเส้นทาง | | `/api/context/analytics` | นามแฝงการวิเคราะห์การบีบอัด | เส้นทางการจัดการต้องผ่านการยืนยันตัวตนสำหรับการจัดการหรือการตรวจสอบนโยบายคีย์ API ## เครื่องมือ MCP การบีบอัดมีเครื่องมือ MCP ห้ารายการ: | เครื่องมือ | ขอบเขต | วัตถุประสงค์ | | ----------------------------------- | ------------------- | ----------------------------------- | | `omniroute_compression_status` | `read:compression` | การตั้งค่า การวิเคราะห์ และสถิติแคช | | `omniroute_compression_configure` | `write:compression` | อัปเดตการตั้งค่าส่วนกลาง | | `omniroute_set_compression_engine` | `write:compression` | ตั้งค่าโหมดและไปป์ไลน์เสริม | | `omniroute_list_compression_combos` | `read:compression` | แสดงรายการคอมโบการบีบอัด | | `omniroute_compression_combo_stats` | `read:compression` | อ่านการวิเคราะห์คอมโบ/เอนจิน | ## ขอบเขตและข้อยกเว้น **Embeddings จะไม่ถูกบีบอัดโดยเด็ดขาด** `open-sse/handlers/embeddings.ts` ไม่เคยเรียกใช้ เอนจินการบีบอัดใดๆ — เนื้อหาคำขอ/การตอบกลับจะถูกส่งตรงไปยังตัวดำเนินการโดยไม่มีการแก้ไข ปัจจุบันนี่เป็นผลจากโครงสร้าง (ตัวจัดการ embeddings และ chat completions แยกจากกัน) ไม่ใช่ การตรวจสอบขณะรันไทม์ แต่หมายความว่าข้อกังวลเรื่องการบิดเบือนเวกเตอร์ใน #8034 ไม่มีพื้นผิว ที่ได้รับผลกระทบในเส้นทาง embeddings **ตัวกรองการยกเว้นต่อโมเดล/เอ็นด์พอยต์ (#8034)** สำหรับ chat completions ผู้ปฏิบัติงานสามารถระบุ รหัสโมเดล / เป้าหมาย `provider/model` ที่ต้องไม่ถูกบีบอัดโดยเด็ดขาดได้ — เป็นมาตรการป้องกันที่มีประโยชน์หาก ในอนาคตมีการเชื่อมต่อการบีบอัดให้ใกล้กับเส้นทางที่อยู่ติดกับ embeddings มากขึ้น และมีประโยชน์โดยทั่วไป สำหรับโมเดลใดๆ ที่พรอมต์ต้องตรงกันทุกไบต์อย่างแม่นยำ (การประเมินแบบกำหนดผลลัพธ์ได้ คำนำหน้าที่ไวต่อแคช ฯลฯ) - ฟิลด์การตั้งค่า: `exclusions?: string[]` ในการกำหนดค่าการบีบอัดส่วนกลาง (`GET`/`PUT /api/settings/compression`) ซึ่งจัดเก็บถาวรผ่านเนมสเปซการบีบอัด `key_value` ที่มีอยู่ (`src/lib/db/compression.ts`) — ไม่มีตารางใหม่ - แท็บแดชบอร์ด: **Dashboard → Compression → Exclusions** (`/dashboard/compression/exclusions`) - ไวยากรณ์รูปแบบ: `*` เป็นไวลด์การ์ดเพียงตัวเดียว เมตาคาแรกเตอร์ regex อื่นทั้งหมดในรูปแบบจะถูก เอสเคปก่อนการจับคู่ ดังนั้น `gpt-5.6` จึงจับคู่เฉพาะสตริงตามตัวอักษรเท่านั้น ไม่จับคู่กับ `gpt-5x6` (ปลอดภัยจาก ReDoS มีขอบเขตจำกัด และไม่มีตัวระบุจำนวนแบบซ้อน) รูปแบบจะจับคู่โดยไม่คำนึงถึงตัวพิมพ์เล็ก-ใหญ่กับ ทั้งรหัสโมเดลเดี่ยวและรูปแบบผสม `provider/model` — `gpt-5-6`, `openai/gpt-5-6` และ `openai/*` ใช้งานได้ทั้งหมด และ `*` เพียงตัวเดียวจะยกเว้นทุกโมเดล - การจับคู่: `isCompressionExcluded()` / `normalizeCompressionExclusions()` ใน `open-sse/services/compression/exclusions.ts` โดย `chatCore.ts` จะตรวจสอบเป้าหมายที่ถูกยกเว้น ทันทีหลังจากแก้ไขการตั้งค่าการบีบอัด **ก่อนที่เอนจินใดๆ จะทำงาน** และจะจัดการผลการจับคู่ เหมือนกับการปิดใช้งานการบีบอัดทั่วทั้งระบบทุกประการ — สามารถพิสูจน์ได้ว่าเนื้อหาคำขอ เหมือนกันทุกไบต์ การข้ามนี้จะถูกบันทึกผ่าน `writeCompressionSkip(..., "excluded")` เพื่อให้ มองเห็นได้ในการวิเคราะห์ - ค่าเริ่มต้น (รายการว่าง/ไม่มีรายการ): เหมือนกับพฤติกรรมก่อน #8034 — ไม่มีสิ่งใดถูกยกเว้น ## ข้อจำกัดที่ทราบ - **LLMLingua-2 (SLM) ต้องการ optional deps ที่ติดตั้งร่วมกัน** worker จะทำงานใน production build เฉพาะเมื่อ `@atjsh/llmlingua-2` และ peers ถูกติดตั้งร่วมกันไว้ใน `dist/node_modules` (ดู `scripts/build/colocateOptionals.mjs`, #4286) หากไม่มีรายการเหล่านี้ engine จะ fail-open (ส่งคืนข้อความต้นฉบับ) การ resolve worker จะไม่ขึ้นอยู่กับ `import.meta.url` อีกต่อไป (เนื่องจากใช้ไม่ได้ใน standalone bundle) — แต่จะอ้างอิงจาก runtime cwd / `argv[1]` - **language packs `de` / `fr` / `ja` ของ Caveman ยังไม่สมบูรณ์** โดยมี rules สำหรับ `context` + `filler` + `structural` แต่ไม่มี packs สำหรับ `dedup` / `ultra` ดังนั้น intensity ระดับ `ultra` จึงไม่ได้เข้มข้นกว่า `full` สำหรับภาษาเหล่านี้ (ภาษาเหล่านี้ใช้เฉพาะ rules ของตนเองเท่านั้น — ไม่มี การ fall-back ไปใช้ rules `dedup`/`ultra` ของภาษาอังกฤษโดยไม่แจ้งให้ทราบ ซึ่งจะทำให้ข้อความภาษาต่างประเทศ เสียหาย) `en` / `es` / `id` / `pt-BR` มีความสมบูรณ์แล้ว ยินดีรับการมีส่วนร่วมจัดทำ `dedup.json` + `ultra.json` สำหรับ packs ที่ยังไม่สมบูรณ์ - **telemetry แบบ stacked แสดงเฉพาะ engines ที่ทำการบีบอัดเท่านั้น** ขั้นตอนหนึ่งใน stacked-pipeline ที่ engine ทำงานแล้วแต่ประหยัดพื้นที่ได้ 0 % จะส่งคืน `stats:null` และจึงไม่ปรากฏใน `engineBreakdown` — ทำให้แยกไม่ออกจากขั้นตอนที่ถูกข้ามไป การแยกความแตกต่างระหว่าง "ทำงานแล้ว, 0 %" กับ "ถูกข้าม" จำเป็นต้องเปลี่ยน breakdown model และถูกเลื่อนออกไปก่อน ## การตรวจสอบความถูกต้อง gates ที่เน้นเฉพาะสำหรับส่วนนี้ ได้แก่: ```bash node --import tsx/esm --test tests/unit/compression/rtk-*.test.ts tests/unit/compression/pipeline-integration.test.ts tests/unit/compression/context-compression-api.test.ts node --import tsx/esm --test tests/unit/compression/*.test.ts tests/golden-set/*.test.ts tests/integration/compression-pipeline.test.ts tests/unit/api/compression/compression-api.test.ts node --import tsx/esm --test tests/unit/compression/mcpAccessibility*.test.ts npm run typecheck:core ```