@xtatistix/rag-wiki
v0.1.34
Published
Narrow-domain, guideline-in-the-loop RAG system built on top of a compiled wiki
Downloads
4,387
Readme
@xtatistix/rag-wiki
Yapılandırılmış bir wiki üzerinden çalışan, kaynak gösterebilen, kapsam dışı soruları reddedebilen hafif bir RAG sistemi.
Ham belge chunk'ları yerine markdown sayfalardan oluşan derlenmiş bir wiki tutar. Sorular bu wikiye dayanarak yanıtlanır. Sistem emin olmadığında söyler — tahmin yürütmez.
Node.js ve tarayıcı ortamlarında çalışır.
Kurulum
npm install @xtatistix/rag-wikiOpenAI API anahtarı gerektirir.
Nasıl Çalışır
Üç katman:
- Wiki —
{projectId}/wiki/altındaki markdown sayfalar.ingest()ile eklenir veya elle yazılır. - Index —
index.md. Tüm wiki sayfalarının tek satırlık özetlerini içeren katalog.ingest()her çağrıda otomatik günceller. - Guideline —
{projectId}/guideline.md. LLM'e neyi yanıtlayıp neyi reddedeceğini söyleyen kural dosyası. İsteğe bağlıdır.
ask() çağrısında:
index.mdokunur, soruyla ilgili sayfalar seçilir- Seçilen sayfaların içeriği yüklenir
- Guideline varsa eklenir
- Hepsi LLM'e gönderilir
- LLM ya yanıtlar (kaynak göstererek) ya da reddeder
- Sonuç
{projectId}/log.md'ye kaydedilir
Hızlı Başlangıç — Node.js
import { createRagWiki } from "@xtatistix/rag-wiki";
const wiki = createRagWiki({
projectId: "destek",
openaiApiKey: "sk-...", // ya da OPENAI_API_KEY env değişkeni
});
// Sayfa ekle
await wiki.ingest("İade Politikası", "## Genel Bakış\nTüm ürünler 30 gün içinde iade edilebilir...");
// Soru sor
const result = await wiki.ask("Ürünümü nasıl iade ederim?");
if (result.answered) {
console.log(result.answer);
console.log("Kaynaklar:", result.sources?.map((s) => s.summary));
} else {
console.log(result.escalationMessage);
}Hızlı Başlangıç — Tarayıcı (PresignedAdapter)
S3 gibi bir depolama servisini presigned URL'lerle kullanmak için:
import { createRagWiki, PresignedAdapter } from "@xtatistix/rag-wiki/dist/browser";
const wiki = createRagWiki({
openaiApiKey: "sk-...",
baseURL: "https://api.openai.com/v1",
fallback: {
apiKey: "AIza...",
baseURL: "https://generativelanguage.googleapis.com/v1beta/openai",
model: "gemini-3.1-flash-lite-preview",
},
model: "gpt-4o",
adapter: new PresignedAdapter({
getReadUrl: (path) =>
fetch(`/api/presigned/read?path=${path}`).then((r) => r.json()).then((r) => r.url),
getWriteUrl: (path) =>
fetch("/api/presigned/write", {
method: "POST",
body: JSON.stringify({ path }),
}).then((r) => r.json()).then((r) => r.url),
}),
});
await wiki.ingest("Rapor Başlığı", raporIcerigi, { projectId: "proje-42" });
const result = await wiki.ask("Bu raporu yorumlar mısın?", { projectId: "proje-42" });API
createRagWiki(config)
const wiki = createRagWiki({
projectId: "proje-id", // varsayılan proje — her çağrıda override edilebilir
openaiApiKey: "sk-...", // tarayıcıda zorunlu, Node'da env'den okunabilir
baseURL: "https://api.openai.com/v1", // varsayılan
model: "gpt-4o", // varsayılan: "gpt-4o-mini"
fallback: {
apiKey: "AIza...",
baseURL: "https://generativelanguage.googleapis.com/v1beta/openai",
model: "gemini-3.1-flash-lite-preview",
},
rawPath: "./data", // Node only, varsayılan: "./raw"
adapter: customAdapter, // LocalAdapter, BrowserAdapter, PresignedAdapter veya custom
});wiki.ingest(title, content, options?)
Wiki'ye sayfa ekler, index.md'yi günceller. Aynı başlıkla tekrar çağrılırsa sayfa güncellenir.
await wiki.ingest("İade Politikası", "30 gün iade garantisi...");
// Farklı proje için
await wiki.ingest("Kargo Bilgisi", "...", { projectId: "lojistik" });titledosya adına dönüştürülür:"İade Politikası"→iade-politikas.md- İçerik
#başlığıyla başlamıyorsa otomatik eklenir
wiki.ask(question, options?)
const result = await wiki.ask("Nasıl iade yaparım?");
const result = await wiki.ask("Sözleşme maddeleri?", { projectId: "hukuk" });QueryResult
interface QueryResult {
answered: boolean;
answer?: string;
sources?: { path: string; summary: string }[];
escalationReason?: "out_of_scope" | "insufficient_sources" | "guideline_violation" | "no_index";
escalationMessage?: string;
}Adaptörler
| Adaptör | Ortam | Okuma | Yazma |
|---|---|---|---|
| LocalAdapter | Node.js | Dosya sistemi | Dosya sistemi |
| BrowserAdapter | Tarayıcı | fetch() (public/) | localStorage |
| PresignedAdapter | Tarayıcı | Presigned URL (S3 vb.) | Presigned URL (S3 vb.) |
| Custom | Her ikisi | Senin backend'in | Senin backend'in |
Custom Adaptör
import { RagWikiAdapter } from "@xtatistix/rag-wiki";
const myAdapter: RagWikiAdapter = {
async read(path: string): Promise<string | null> { ... },
async write(path: string, content: string): Promise<void> { ... },
async list(prefix: string): Promise<string[]> { ... },
};Çoklu Proje
Her projectId tamamen izoledir — kendi wiki'si, kılavuzu ve logu vardır.
const wiki = createRagWiki({ adapter }); // varsayılan projectId yok
await wiki.ask("İade politikası?", { projectId: "destek" });
await wiki.ask("Sözleşme maddeleri?", { projectId: "hukuk" });Guideline Dosyası
Sistemi disiplinli bir domain asistanına dönüştürür. {projectId}/guideline.md oluştur:
# Kılavuz — destek
## Kapsam
Bu wiki yalnızca ürün iadesi, kargo ve hesap sorunlarını yanıtlar.
Rakip ürünler veya genel alışveriş tavsiyeleri kapsam dışıdır.
## Kesinlikle yanıtlama
- Hukuki tavsiye
- Tıbbi tavsiye
- Kişisel müşteri verileriGuideline dosyası yoksa sistem çalışmaya devam eder, sadece domain kısıtlaması olmaz.
Dizin Yapısı
raw/
├── index.md ← ingest() tarafından otomatik yönetilir
└── {projectId}/
├── guideline.md ← isteğe bağlı kural dosyası
├── log.md ← ask() çağrılarının otomatik logu
└── wiki/
├── iade-politikasi.md
└── kargo-bilgisi.mdTypeScript Tipleri
import type {
RagWikiConfig,
RagWikiAdapter,
QueryResult,
WikiPage,
WikiIndex,
EscalationReason,
} from "@xtatistix/rag-wiki";