Lanjut ke konten
Samkarsa Logbook

v1.0.0-019 : Dynamic RAG Knowledge Injection untuk OCR Engine

Refaktor arsitektur OCR Engine dari prompt hardcode menjadi Dynamic RAG Injection. Pengetahuan penafsiran nota spesifik (seperti format Faktur FI RINCINSARI / KRT.LSN.SAT) kini disuplai secara dinamis dari Vector Database RAG saat runtime, bukan dikodekan statis di source code.

Jualan,MCP,Sajen3mnt baca

Pada sesi sebelumnya (v1.0.0-018), aturan penafsiran nota spesifik vendor seperti kolom KRT.LSN.SAT (Faktur FI RINCINSARI) dan deteksi nama supplier di footer bawah nota di-hardcode langsung ke dalam prompt statis ocrTool.ts. Hal ini merupakan antipattern arsitektur yang merusak generisitas OCR Engine dan menyulitkan pemeliharaan jangka panjang.

Sebelum (Masalah): Aturan penafsiran spesifik vendor/layout ter-hardcode di prompt statis:

// Aturan hardcode yang MERUSAK generisitas engine (SUDAH DIHAPUS):
// - "PENAFSIRAN QTY FAKTUR GROSIR (KRT.LSN.SAT / KRT.TSN.SAT): Split string berdasarkan titik..."
// - "Periksa Kop Atas MAUPUN Footer Paling Bawah nota. Seringkali akibat potongan printer..."

Sesudah (Solusi):

  • Prompt dasar dikembalikan ke 10 aturan generik yang berlaku untuk semua jenis nota (kejujuran OCR, format tanggal ISO, logika harga, anti-double-counting diskon, dsb).
  • Dynamic RAG Lookup ditambahkan sebelum pemanggilan Gemini Vision:
    • Engine melakukan pencarian kesamaan vektor (searchVectorContext) ke tabel knowledge_vectors dengan app_context: "sajen_ocr".
    • Jika ada RAG Knowledge dengan similarity ≥ 75%, aturan penafsiran khusus (_rag_rules) disuntikkan secara DINAMIS ke dalam prompt.
    • Log diagnostik dicetak: ✅ RAG Knowledge ditemukan (similarity: 92%). Menyuntikkan panduan penafsiran secara dinamis...
    • Jika tidak ada match, engine berjalan dengan prompt generik murni tanpa error.
// Pola baru: Lookup RAG sebelum Vision AI dipanggil
const ragDocs = await searchVectorContext({
embedding: ragEmbedding,
tenant_id: tenantId,
app_context: "sajen_ocr",
agent_role: "",
limit: 2
});
const bestMatch = ragDocs.find(d => (d.similarity ?? 0) >= 0.75);
if (bestMatch) {
ragContextPrompt = `\n\n--- PETUNJUK PENAFSIRAN NOTA DARI RAG KNOWLEDGE ---\n${ragRules}\n--- AKHIR PETUNJUK RAG ---`;
}

  • tenant_id kini ikut dikirim dalam context payload ke MCP OCR Tool.
  • RAG lookup bisa menemukan aturan penafsiran yang spesifik per-toko/tenant.

  • RAG Knowledge berisi panduan penafsiran nota PT. DELTA GUNA UTAMA SALATIGA / RINCINSARI (Faktur FI) telah berhasil di-ingest ke knowledge_vectors di MCP Vector DB dengan ID c7c9ad73-2fd0-42d6-b52a-6ee43845c6b9.
  • Isi _rag_rules mencakup:
    1. Nama supplier ada di BAGIAN BAWAH nota (bukan header/penerima).
    2. Tanggal format DD/MM/YYYY → ISO YYYY-MM-DD.
    3. Kolom KRT.TSN.SAT / KRT.LSN.SAT: split titik, ambil angka > 0.
    4. Harga satuan dari kolom HRG.PCS+PPN, diskon dari kolom Diskon (nominal).

Sebelumnya Sesudah
Aturan hardcode di kode sumber Aturan di-ingest ke Vector DB
Harus deploy ulang jika ada nota baru Cukup ingest RAG knowledge baru
Prompt engine makin kotor & panjang Prompt engine bersih & generik
Tidak bisa belajar dari koreksi pengguna Knowledge terakumulasi otomatis via feedback

  • Menambahkan penegasan pada aturan #2 prompt generik di ocrTool.ts bahwa penambahan item secara tulisan tangan (oleh sales/staff) di atas nota cetak adalah hal yang LAZIM dan UMUM terjadi. Jika terbaca dengan jelas, item tersebut WAJIB diekstrak dan dimasukkan ke daftar items.
  • RAG Knowledge Faktur FI di Vector DB di-update ke versi terbaru yang memuat aturan #8 untuk penanganan item tulisan tangan (ID ingest: 39eed53a-ac99-4a4f-bc6c-b9cb0521e57c).

  • Masalah: Sajen OCR Worker memiliki filter penyeleksi JSON yang sangat ketat. Skema JSON dari MCP OCR Hub menggunakan key "merchant" dan "readability_status" yang sebelumnya tidak dikenali oleh validator ocr_worker.py. Hal ini memicu fallback otomatis ke call LLM lokal (non-RAG) untuk menstrukturkan ulang teks mentah, sehingga data diskon/harga/nama toko kembali salah serta membuat proses berjalan lambat karena double LLM call.
  • Solusi: Memodifikasi filter regex dan parser di ocr_worker.py agar mengenali key "items" dan "readability_status" dari format output MCP secara langsung. JSON hasil ekstraksi dari RAG MCP sekarang dapat digunakan secara instan tanpa fallback berulang.

Sebelumnya Sesudah
Aturan hardcode di kode sumber Aturan di-ingest ke Vector DB
Harus deploy ulang jika ada nota baru Cukup ingest RAG knowledge baru
Prompt engine makin kotor & panjang Prompt engine bersih & generik
Tidak bisa belajar dari koreksi pengguna Knowledge terakumulasi otomatis via feedback
Double LLM Call (lambat & salah RAG) Single LLM Call instan dengan validasi skema yang tepat

  • mcp-backend — berhasil, port 3000 ✅
  • sajen-api — berhasil, port 8005 (termasuk update parser JSON di ocr_worker.py) ✅
  • sajen-worker — berhasil, port 8005 ✅