npm.io
0.6.0 • Published 5h ago

enterprise-ai-sdk

Licence
MIT
Version
0.6.0
Deps
0
Size
766 kB
Vulns
0
Weekly
0

Enterprise AI SDK — TypeScript / Node.js

Reference implementation dari Enterprise AI SDK. Dokumen ini adalah panduan lengkap stack TS/Node: instalasi, konfigurasi, seluruh fitur, catatan operasional produksi, dan status verifikasi.

Referensi API lengkap per-method: docs/public-api.md (disertakan dalam paket; tautan disajikan via CDN unpkg — juga tersedia di node_modules/enterprise-ai-sdk/docs/public-api.md setelah install).

Catatan: npmjs.com tidak mendukung tautan relatif ke berkas paket (jadi tautan mengarah ke unpkg). Tautan aktif setelah versi yang menyertakan docs/public-api.md (≥ 0.1.1) ter-publish.


Daftar Isi

  1. Kebutuhan
  2. Instalasi & optional dependencies
  3. Mulai cepat
  4. Konfigurasi 3 lapis
  5. Provider
  6. Tools + discovery + permission
  7. Identity
  8. Session, Memory, Knowledge, Prompt
  9. Feedback, Learning, Local Provider (FAQ cache)
  10. Storage
  11. Error handling
  12. Catatan operasional produksi
  13. Status verifikasi & checklist produksi
  14. Skrip pengembangan

1. Kebutuhan

  • Node.js ≥ 22 (ESM).
  • Package manager: pnpm (repo memakai workspace pnpm).

2. Instalasi & optional dependencies

SDK inti tidak punya dependency runtime wajib — semua provider SDK, driver DB, dan library retrieval bersifat optionalDependencies. Pasang HANYA yang kamu pakai. Bila fitur dipakai tanpa package-nya terpasang, SDK melempar error jelas yang menyebut package mana harus di-install (bukan crash misterius).

Fitur Package yang perlu di-install
Provider DeepSeek / OpenAI (kompatibel) openai
Provider Anthropic @anthropic-ai/sdk
Provider Google @google/genai
Knowledge / Local Provider / rerank (embedding lokal) @huggingface/transformers
Storage SQLite (default zero-config) better-sqlite3
Storage PostgreSQL pg
Storage MySQL mysql2
Storage MongoDB mongodb

Contoh (DeepSeek + SQLite + knowledge):

pnpm add enterprise-ai-sdk openai better-sqlite3 @huggingface/transformers

apiKey via .env (JANGAN di-commit): DEEPSEEK_API_KEY, OPENAI_API_KEY, ANTHROPIC_API_KEY, GOOGLE_API_KEY.

3. Mulai cepat

Facade statis (boot otomatis dari eai.config.json + .env):

import { AI } from 'enterprise-ai-sdk';
const res = await AI.chat('Halo, siapa kamu?');
console.log(res.getFinalMessage());

Instance eksplisit (multi-config / DI / test):

const sdk = await AI.create({
    provider: { defaultProvider: 'deepseek', defaultModel: 'deepseek-v4-pro' },
    providers: { deepseek: { apiKey: process.env.DEEPSEEK_API_KEY } },
});
const res = await sdk.chat('Halo');

4. Konfigurasi 3 lapis

Lapis Cara Scope
1 Global AI.create / AI.configure / eai.config.json / env Lifetime
2 Session sdk.setConfig(partial) Sisa lifetime (provider/tool tetap)
3 Per-call sdk.use('x').model('m').temperature(0.2).session('s').as({userId}).chat(...) 1 panggilan, auto-reset

Precedence: Lapis 3 > 2 > programmatic > file > env > default. Contoh file lengkap ada di #4.2; tabel field per-item: docs/api/public-api.md #2.

4.1 Config file & environment
  • File: SDK membaca eai.config.json dari cwd aplikasi (opsional — SDK jalan tanpa file config, cukup AI.create({...})).
  • Override path file: set env EAI_CONFIG_PATH (absolut, atau relatif terhadap cwd) untuk memakai file di lokasi lain.
  • API key: JANGAN taruh di file config. Pakai environment: DEEPSEEK_API_KEY, OPENAI_API_KEY, ANTHROPIC_API_KEY, GOOGLE_API_KEY (pola <PROVIDER-ID>_API_KEY). Nilai env menang atas file untuk apiKey.

Paket npm tidak menyertakan file contoh (hanya dist). Buat sendiri eai.config.json di root project-mu — salin templat di bawah, ubah seperlunya. Semua field opsional; yang tidak diisi memakai default.

4.2 Contoh eai.config.json (LENGKAP — nilai = default)
{
  "namespace": null,
  "provider": { "defaultProvider": "deepseek", "defaultModel": "deepseek-v4-pro", "allowedProviders": [] },
  "providers": { "deepseek": { "model": "deepseek-v4-pro", "baseUrl": null, "temperature": null, "maxTokens": null } },
  "timeout":  { "requestTimeoutMs": 30000, "providerTimeoutMs": 25000 },
  "retry":    { "enabled": false, "maxRetries": 2, "retryDelayMs": 1000 },
  "fallback": { "enabled": false, "fallbackProviders": [] },
  "streaming":{ "enabled": false },
  "logging":  { "enabled": true, "level": "info", "redactionEnabled": true },
  "cost":     { "trackingEnabled": true, "pricing": null },
  "security": { "redactionEnabled": true, "promptDebuggingEnabled": false },
  "storage":  { "enabled": false, "defaultConnection": "sqlite",
                "databases": { "sqlite": { "adapter": "sqlite", "connectionString": null, "prefix": "eai_" } } },
  "session":  { "enabled": false, "maxMessages": 20, "fields": {} },
  "memory":   { "enabled": false, "maxEntries": 100 },
  "knowledge":{ "enabled": false, "maxEntries": 500 },
  "learning": { "enabled": false, "autoRecord": false },
  "cache":    { "enabled": false, "ttlMs": 300000, "maxEntries": 500 },
  "embedding":{ "model": "Xenova/multilingual-e5-small", "threshold": 0.8, "scanLimit": 500, "candidateLimit": 100 },
  "rerank":   { "model": "Xenova/bge-reranker-base", "threshold": 0.1, "topK": 10 },
  "prompt":   { "systemPrompt": null },
  "tools":    { "autoExec": true, "maxDiscoveryIterations": 1 },
  "localProvider": { "enabled": false, "similarityThreshold": 0.9, "rerankThreshold": 0.3, "scanLimit": 500 }
}

5. Provider

Bawaan (auto-register bila apiKey ter-resolve): deepseek, openai, anthropic, google. Kustom: sdk.registerProvider(id, adapter).

await sdk.use('anthropic').chat('...');            // per-call
const sdk2 = await AI.create({ provider: { defaultProvider: 'openai' }, providers: { openai: { apiKey: '...' } } });

baseUrl per provider: tiap provider punya default endpoint; override via providers.<id>.baseUrl (proxy/gateway/Azure/self-hosted). Berlaku di AI.create maupun setConfig. Detail + tabel default: docs/public-api.md.

await AI.create({ providers: { openai: { apiKey: '...', baseUrl: 'https://openrouter.ai/api/v1' } } });

6. Tools + discovery + permission

sdk.registerTool({
    name: 'getSalary',
    description: 'Ambil gaji karyawan. WAJIB untuk pertanyaan gaji.',
    placeholders: ['salary_info'],
    roles: ['hr'],                                   // izin berbasis role (opsional)
    handler: async () => ({ success: true, data: { salary_info: 'Rp 15.000.000' } }),
});

// autoExec default true → SDK eksekusi tool + isi placeholder otomatis:
const res = await sdk.as({ userId: 'u1', roles: ['hr'] }).chat('Berapa gaji saya?');
console.log(res.getFinalMessage());                  // "{salary_info}" sudah terisi
  • Discovery (meta-tools): schema tool tak dijejalkan ke tiap prompt; SDK menawarkan listTools, menyaring (embed+rerank), lalu menyuntik yang relevan.
  • Permission: roles:[] = publik; non-kosong → identity wajib punya ≥1 role.
  • autoExec=false: aplikasi panggil res.executeTools() lalu (opsional) res.saveToHistory().

Reliabilitas discovery — lihat #12.

7. Identity

SDK tidak melakukan authentication — aplikasi menyetel identity tervalidasi.

sdk.setIdentity({ userId: 'u-1', displayName: 'John Doe', roles: ['admin'] }); // default
await sdk.as({ userId: 'u-2', roles: ['hr'] }).chat('...');                     // per-call

Resolusi: per-call as() → default setIdentity → anonymous. roles = basis permission tool.

8. Session, Memory, Knowledge, Prompt

// Session (butuh session.enabled):
await sdk.session('sesi-42').chat('Namaku John Doe');
await sdk.session('sesi-42').chat('Siapa namaku?');   // → "John Doe"

// Memory PER-USER (butuh memory.enabled + identity non-anonim):
sdk.setIdentity({ userId: 'u-1' });
await sdk.remember('User suka jawaban singkat');       // anonim tanpa scope → TIDAK disimpan

// Knowledge (butuh knowledge.enabled; retrieval embed→rerank):
await sdk.addKnowledge({ title: 'Jam kerja', content: 'Kantor buka 09.00-17.00 WIB.' });

// Prompt global (persona/aturan, selalu dibawa):
sdk.setPrompt('Kamu asisten HR. Jawab dalam Bahasa Indonesia.');

9. Feedback, Learning, Local Provider (FAQ cache)

AI menandai jawaban cacheable (stabil). Hanya cacheable:true yang direkam ke learning. Feedback diberikan admin, asinkron:

const items = await sdk.listHistory(20);
await sdk.historyFeedback(items[0].id, 'positive');    // positive|neutral|negative

Local Provider (FAQ cache lokal-first) menjawab dari learning ber-feedback SEBELUM memanggil provider berbayar (hemat biaya):

const sdk = await AI.create({
    storage: { enabled: true }, learning: { enabled: true, autoRecord: true },
    localProvider: { enabled: true },                  // WAJIB storage.enabled
});
const res = await sdk.chat('berapa hari cuti tahunan');
res.usedLocalProvider();                               // true bila dijawab dari cache

Seleksi kandidat: positive dulu (acak bila >1, sengaja — agar terasa manusiawi), neutral fallback, negative/null tak pernah.

Batasan Local Provider: untuk FAQ stabil, bukan pemahaman bahasa umum. Cache kosong sampai admin memberi feedback. Threshold tinggi (minim false-positive) → recall lebih rendah. Jawaban terhitung/promo time-limited otomatis cacheable:false. Detail: public-api.md #8.

9b. Vision (analisis gambar)

Analisis gambar oleh model multimodal. Provider: OpenAI (diverifikasi), Anthropic, Google (kode siap; DeepSeek dukungan vision terbatas). Tiga tipe input — SDK menyesuaikan format per provider:

const res = await sdk.vision('Bacakan nominal & nomor referensi.', [
    { type: 'file', path: './bukti-transfer.jpg' },   // dirFile
    // { type: 'url', url: 'https://…/receipt.png' },  // di-fetch SDK
    // { type: 'base64', data: 'iVBOR…', mimeType: 'image/png' },
]);
console.log(res.getFinalMessage());

Output terstandar via fields — samakan nama field lintas format (mis. jumlah/amount → satu nama kanonik). Model mengisi data.payload pakai nama kamu persis; dalam session, payload otomatis tersimpan ke session data (§9c):

const res = await sdk.session('trx-42').vision('Baca bukti transfer.',
    [{ type: 'file', path: './bukti.jpg' }],
    { fields: { pengirim: 'nama pengirim', nominal: 'nominal (angka)', noRef: 'no. referensi' } },
);
res.raw.data.payload;   // → { pengirim:'Budi', nominal:'170000', noRef:'FT…' }

Keputusan & risiko ada pada aplikasi — SDK hanya menyiapkan alat:

  • Gambar BUKAN bukti final (bisa dipalsukan). Pakai vision untuk MEMBACA; verifikasi kebenaran ke sistem asli (mis. lookup nomor referensi ke gateway).
  • Vision bisa salah baca (mirip OCR). Minta field terstruktur lalu cocokkan di aplikasi; jangan andalkan interpretasi bebas untuk keputusan penting.

Detail + tabel tipe input: public-api.md #12.

9c. Session Data (fakta terstruktur per-session)

Beda dari history (pesan, dipotong maxMessages), session data = fakta mesin (nama, nominal, hasil vision) yang selalu disuntik penuh ke prompt — tak pernah terpotong selama session hidup. Akumulatif; kunci sessionId.

Isi otomatis dari chat & vision via skema session-global setSessionFields: selama session aktif, tiap request mengekstrak field ke payload → auto-store (dedup, record identik dibuang).

sdk.setSessionFields({ userId: 'user yang dicek', tanggal: 'tanggal (YYYY-MM-DD)' });
// User chatting biasa: "cek transaksi dian tanggal 2026-04-02"
//   → tersimpan { userId:'dian', tanggal:'2026-04-02' }. "cek anto 2026-05-02" → record ke-2.

Di prompt, data tampil dua bentuk — per-field unik (userId: dian, anto) + kombinasi records — sehingga AI bisa merekomendasikan pilihan yang sudah pernah diproses ("mau cek dian 2026-04-02 atau anto 2026-05-02?").

Isi manual (WAJIB .session(id), tanpa itu → session_id_required):

await sdk.session('trx-42').rememberData({ pengirim: 'Budi', bank: 'BCA' });
const facts = await sdk.session('trx-42').sessionData();          // baca semua

Data hanya disuntik ke prompt (bukan dilempar ke tool). Belum ada TTL — bertahan sampai storage di-clear.

Hapus session. sessionId menyatukan history + session data + pending-tool. clearSession(id) menghapus ketiganya sekaligus (idempoten):

await sdk.clearSession('trx-42');   // history + session data + pending-tool → hilang

Detail + tabel perbandingan: public-api.md #7a.

10. Storage

Multi-connection gaya Laravel:

storage: {
    enabled: true,
    defaultConnection: 'main',
    databases: {
        main: { adapter: 'postgres', connectionString: 'postgres://…', prefix: 'eai_' },
    },
}

storage.enabled:false → in-memory ephemeral. Adapter: sqlite (default, fallback ./.eai/llm-storage.sqlite), postgres, mysql, mongodb — install driver terkait (lihat #2).

pgvector (opsional, PostgreSQL). Bila ekstensi vector terpasang, recall cosine knowledge & FAQ cache dihitung di database (<=>) — otomatis, tanpa migration. Aktifkan sekali: CREATE EXTENSION IF NOT EXISTS vector; (SDK juga mencobanya saat init). Tanpa pgvector → tetap jalan (fetch + cosine). Detail: public-api.md #7.

Penamaan: MemoryStorageAdapter = adapter storage in-memory (RAM), BEDA dari subsystem memory (sdk.remember).

10b. Multi-tenant (namespace + berbagi resource)

Pola sah: satu instance SDK per tenant (karena setPrompt/setSessionFields/ baseUrl di level instance), sering berbagi satu database. Tiga penopang:

  • namespace — set sdk.setNamespace('site-42') (atau config namespace): di-fold ke scope-key semua subsistem storage (memory/session/session-data/ knowledge/learning) → tenant berbagi tabel tak saling melihat data. null = perilaku lama.
  • Model retrieval di-share otomatis (berkunci identitas model) → N instance model sama = 1 sesi ONNX di RAM, bukan N × ~400 MB. setConfig ganti model kini berlaku saat runtime.
  • Pool koneksi di-share otomatis (berkunci adapter|connectionString|prefix) → instance koneksi sama = 1 pool (hindari kehabisan max_connections). Refcount; graceful shutdown: import { closeAllStorage } from 'enterprise-ai-sdk'.

Cache response, ConfigState, ToolRegistry, provider registry tetap per-instance (sengaja). Detail: public-api.md #13.

11. Error handling

chat() TIDAK melempar untuk kegagalan runtime — selalu envelope. Cek res.status; detail res.raw.error (code, category, retryable, …). Kategori: validation, configuration, provider, timeout, rate_limit, tool, runtime, internal. Yang MELEMPAR: setup invalid (AI.create/ setConfig), registerTool invalid, pemakaian salah executeTools/ saveToHistory/recordToLearning.

12. Catatan operasional produksi

12.1 Cold-start model lokal

Embedding & rerank (@huggingface/transformers) mengunduh + memuat model saat pemakaian PERTAMA (puluhan detik + memori). Request knowledge/ localProvider pertama lambat; berikutnya cepat (model ter-cache di proses).

  • Rekomendasi: panggil await sdk.warmup() (atau AI.warmup()) sekali saat boot aplikasi — preload model embedding+rerank sebelum melayani trafik, sehingga request pertama tidak lambat.
    const sdk = await AI.create({ /* ... */ });
    await sdk.warmup();   // model siap
  • Ini hanya latensi hit-pertama; wajar untuk deployment yang di-test sebelum go-live.
12.2 Reliabilitas tool discovery (meta-tools)

Discovery adalah loop agentic: model harus (a) meminta listTools, lalu (b) memilih tool + params yang benar. Mekaniknya benar & deterministik di dev, TAPI bergantung kepatuhan model saat itu — model yang lambat/kurang patuh bisa gagal memicu tool atau timeout di tengah.

  • Cara aplikasi menangani:
    • Aktifkan retry (retry.enabled: true) untuk request ber-tool.
    • Selalu cek res.hasAction() — jangan asumsikan tool pasti terpilih.
    • Sediakan fallback ketika tool tak terpanggil (mis. minta user memperjelas).
    • Naikkan timeout.providerTimeoutMs untuk alur discovery (2 panggilan).
    • tools.maxDiscoveryIterations (default 1) menjaga dari loop.
  • Alternatif bila butuh determinisme tinggi: model lebih patuh, atau strategi native function-calling (lebih boros token, mengikat ke provider).
12.3 Skala retrieval

Tanpa vector query native, learning/knowledge besar = fetch semua kandidat

  • cosine di Node tiap query (O(n); vektor sudah di-precompute saat tulis, jadi tak ada re-embed). Aman untuk kecil–menengah; ada plafon skala. Native pgvector/Atlas ditunda ke slice terpisah.

13. Status verifikasi & checklist produksi

Terverifikasi terhadap backend nyata:

  • DeepSeek (chat, resiliency, tools, subsystem)
  • Storage SQLite / PostgreSQL / MySQL / MongoDB (CRUD)
  • Retrieval embed/rerank lokal, feedback, Local Provider, identity, permission
  • Adapter Anthropic — terverifikasi sampai batas API (chat penuh butuh kredit API)

Belum diuji real (butuh kredensial): provider OpenAI & Google (execute()).

Checklist sebelum production:

  • Smoke test provider yang dipakai dengan API key + kredit nyata.
  • Pasang driver DB yang dipakai (optional dep).
  • Warmup model lokal saat boot bila pakai knowledge/localProvider.
  • Aktifkan retry untuk alur ber-tool + tangani hasAction() false.
  • Tetapkan license, versi rilis, CI (belum disiapkan).

TODO by design: capability stream/reason/embedding/vision/ocr (stub), vector query native, telemetry backend, LocalProviderAdapter sebagai provider 'local'.

14. Skrip pengembangan

pnpm build            # tsc → dist/
pnpm typecheck        # tsc --noEmit (source)
pnpm typecheck:test   # typecheck test
pnpm test             # vitest (real DeepSeek bila DEEPSEEK_API_KEY ada; sisanya di-skip)
pnpm test:coverage    # + coverage
pnpm lint             # eslint

Test REAL terhadap provider/DB nyata aktif otomatis bila env kredensial diisi (mis. DEEPSEEK_API_KEY, POSTGRES_TEST_URL, MYSQL_TEST_URL, MONGODB_TEST_URL).

15. Publikasi (npm publik)

Paket ini di-publish publik ke npm (nama unscoped enterprise-ai-sdk, lisensi MIT, publishConfig.access: "public"). prepublishOnly menjalankan typecheck + lint + build otomatis sebelum publish; hanya dist/ + README.md

  • LICENSE yang masuk tarball.
# 1. Login npm (sekali):
npm login
npm whoami                 # verifikasi ter-autentikasi

# 2. Publish (dari implementations/typescript-node/):
npm publish

# Rilis berikutnya: naikkan versi dulu
npm version patch          # 0.1.0 → 0.1.1 (atau minor/major)
npm publish

ESM-only — consumer harus mendukung ESM ("type": "module" atau import dinamis).


Referensi API lengkap ada di docs/public-api.md (disertakan dalam paket). Dokumen desain (ADR & review per-slice) berada di repositori sumber (privat/internal).

Keywords