Darstellung
Knowledge Base
Die Knowledge Base ist das zentrale Wissens-System von VIA. Dokumente, FAQs, Produkte und Kalender-Eintraege werden als Vektor-Embeddings in Qdrant gespeichert und stehen den Bots als semantisch durchsuchbarer Kontext zur Verfuegung.
Architektur-Überblick
Upload/Eingabe → TextExtractor → TextChunker → MistralEmbedding → Qdrant
↑
1024-dim Vektoren- Embedding-Modell:
mistral-embed(1024 Dimensionen) - Vektor-Datenbank: Qdrant (Port 6335, Docker Container
qdrant-customers) - Collection-Schema:
tenant_{uuid}_knowledge(eine Collection pro Tenant) - Chunking: Zeichenbasiert, max 1000 Zeichen, min 200, Overlap 100, satzerhaltend
Haupt-Tabelle: knowledge_items
| Spalte | Typ | Nullable | Default | Beschreibung |
|---|---|---|---|---|
| id | uuid | NOT NULL | gen_random_uuid() | Primaerschlüssel |
| tenant_id | uuid | NOT NULL | — | Tenant-Zuordnung (FK → tenants) |
| type | varchar(50) | NOT NULL | — | Dateityp (pdf, txt, md, json, url, …) |
| title | varchar(255) | NULL | — | Anzeigename |
| description | text | NULL | — | Beschreibung / Notizen |
| filename | varchar(255) | NULL | — | Original-Dateiname |
| mime_type | varchar(100) | NULL | — | MIME-Typ der Datei |
| file_size_bytes | bigint | NULL | 0 | Dateigröße in Bytes |
| content | text | NULL | — | Extrahierter Textinhalt |
| qdrant_collection | varchar(100) | NULL | — | Qdrant Collection Name |
| qdrant_point_ids | text[] | NULL | — | Array der Qdrant Point-IDs |
| embedding_model | varchar(50) | NULL | 'mistral-embed' | Verwendetes Embedding-Modell |
| vectors_count | integer | NULL | 0 | Anzahl erzeugter Vektoren |
| status | varchar(20) | NULL | 'pending' | Status (pending, processing, ready, error, pending_review, deleted) |
| error_message | text | NULL | — | Fehlermeldung bei status=error |
| language | varchar(10) | NULL | 'de' | Sprache des Inhalts |
| created_at | timestamptz | NULL | now() | Erstellungszeitpunkt |
| updated_at | timestamptz | NULL | now() | Letzte Änderung |
| processed_at | timestamptz | NULL | — | Zeitpunkt der Vektorisierung |
| bot_id | uuid | NULL | — | Legacy Bot-Zuordnung (FK → bots, ON DELETE SET NULL) |
| content_type | varchar(20) | NOT NULL | 'text' | Inhaltstyp für Auto-Regeln |
| last_synced_content_hash | text | NULL | — | Hash des letzten Sync-Inhalts |
| last_sync_check | timestamptz | NULL | — | Letzter Sync-Pruefzeitpunkt |
| sync_content_changed | boolean | NULL | false | Ob sich der Inhalt seit letztem Sync geändert hat |
| knowledge_rules | jsonb | NULL | '{}' | Auto-generierte Regeln für buildFinalPrompt() |
| calendar_valid_from | date | NULL | — | Kalender: Gültig ab |
| calendar_valid_until | date | NULL | — | Kalender: Gültig bis |
| calendar_time_from | varchar(10) | NULL | — | Kalender: Uhrzeit von |
| calendar_time_to | varchar(10) | NULL | — | Kalender: Uhrzeit bis |
| calendar_recurrence | varchar(20) | NULL | — | Kalender: Wiederholung (daily, interval, weekly, monthly, none) |
| calendar_interval | integer | NULL | — | Kalender: Intervall in Tagen |
| calendar_days | jsonb | NULL | — | Kalender: Wochentage (Array) |
| calendar_price | varchar(50) | NULL | — | Kalender: Preis-Info |
| calendar_booking_url | text | NULL | — | Kalender: Buchungs-Link |
| calendar_category | varchar(100) | NULL | — | Kalender: Kategorie |
Indizes
| Index | Typ | Spalte(n) |
|---|---|---|
| knowledge_items_pkey | PRIMARY KEY | id |
| idx_ki_content_type | btree | content_type |
| idx_knowledge_items_status | btree | status |
| idx_knowledge_items_tenant | btree | tenant_id |
| idx_knowledge_items_type | btree | type |
content_type Werte
Der content_type steuert die automatische Regelgenerierung via generateAutoRules():
| content_type | Auto-Regel | Beschreibung |
|---|---|---|
text | — | Standard, keine spezielle Regel |
pricing | PREISREGEL | Exakte Preise nennen, nicht runden, keine Rabatte erfinden |
faq | FAQ-REGEL | Antwort nah an der Vorlage, nicht abweichen |
policy | RICHTLINIEN-REGEL | Strikt an Richtlinie halten, nicht frei interpretieren |
schedule | ZEITPLAN-REGEL | Exakte Zeiten/Daten, keine Termine erfinden |
contact | KONTAKT-REGEL | Nur angegebene Kontaktdaten weitergeben |
product | PRODUKT-REGEL | Produkte anhand vorhandener Infos beschreiben |
knowledge_rules (JSONB)
Das Feld knowledge_rules wird beim Onboarding gesetzt und von generateAutoRules() in Regel-Strings umgewandelt. Diese Regeln fliessen in buildFinalPrompt() ein.
javascript
// Struktur:
{
content_type: 'pricing', // Einer der obigen Werte
accuracy: 'exact', // 'exact' oder 'approximate'
usage_hint: 'Nur für ...', // Freitext-Hinweis
restrictions: '...', // Einschraenkungen
priority: 8 // Prioritaet (1-10)
}accuracy-Werte:
exact— Wortgenaue Wiedergabe, keine Umformulierung von Zahlen/Faktenapproximate— Sinngemaeß formulieren erlaubt, aber Fakten beibehalten
Bot-Zuweisung: knowledge_bot_assignments
Jedes Knowledge-Item muss mindestens eine Bot-Zuweisung haben. Ohne Zuweisung wird das Item vom Bot nicht gefunden, auch wenn es vektorisiert ist.
| Spalte | Typ | Nullable | Default | Beschreibung |
|---|---|---|---|---|
| id | uuid | NOT NULL | uuid_generate_v4() | Primaerschlüssel |
| knowledge_item_id | uuid | NOT NULL | — | FK → knowledge_items (ON DELETE CASCADE) |
| bot_id | uuid | NOT NULL | — | FK → bots (ON DELETE CASCADE) |
| tenant_id | uuid | NOT NULL | — | FK → tenants (ON DELETE CASCADE) |
| created_at | timestamptz | NULL | CURRENT_TIMESTAMP | Erstellungszeitpunkt |
| item_type | varchar(20) | NULL | 'document' | Typ der Zuweisung |
Unique Constraint: (knowledge_item_id, bot_id, item_type) — verhindert doppelte Zuweisungen.
Kritische Regel
Ein Knowledge-Item ohne Eintrag in knowledge_bot_assignments ist unsichtbar für alle Bots. Das Backend erzwingt Auto-Assign bei Erstellung.
Unter-Tabelle: knowledge_faqs
Strukturierte FAQ-Eintraege, verknuepft mit einem Knowledge-Item.
| Spalte | Typ | Nullable | Default | Beschreibung |
|---|---|---|---|---|
| id | uuid | NOT NULL | gen_random_uuid() | Primaerschlüssel |
| tenant_id | uuid | NOT NULL | — | FK → tenants (ON DELETE CASCADE) |
| knowledge_item_id | uuid | NULL | — | FK → knowledge_items (ON DELETE SET NULL) |
| question | text | NOT NULL | — | Die Frage |
| answer | text | NOT NULL | — | Die Antwort |
| category | varchar(100) | NULL | — | Kategorie |
| tags | text[] | NULL | — | Tags als Array |
| priority | integer | NULL | 0 | Sortier-Prioritaet |
| is_active | boolean | NULL | true | Aktiv/Inaktiv |
| created_at | timestamptz | NULL | now() | Erstellungszeitpunkt |
| updated_at | timestamptz | NULL | now() | Letzte Änderung |
Unter-Tabelle: knowledge_products
Strukturierte Produktdaten, verknuepft mit einem Knowledge-Item.
| Spalte | Typ | Nullable | Default | Beschreibung |
|---|---|---|---|---|
| id | uuid | NOT NULL | gen_random_uuid() | Primaerschlüssel |
| tenant_id | uuid | NOT NULL | — | FK → tenants (ON DELETE CASCADE) |
| knowledge_item_id | uuid | NULL | — | FK → knowledge_items (ON DELETE SET NULL) |
| name | varchar(255) | NOT NULL | — | Produktname |
| description | text | NULL | — | Beschreibung |
| sku | varchar(100) | NULL | — | Artikelnummer |
| price | numeric(10,2) | NULL | — | Preis |
| currency | varchar(3) | NULL | 'EUR' | Waehrung |
| price_info | text | NULL | — | Zusaetzliche Preis-Infos |
| category | varchar(100) | NULL | — | Kategorie |
| tags | text[] | NULL | — | Tags als Array |
| is_available | boolean | NULL | true | Verfügbar? |
| availability_info | text | NULL | — | Verfügbarkeits-Hinweis |
| image_url | text | NULL | — | Bild-URL |
| is_active | boolean | NULL | true | Aktiv/Inaktiv |
| created_at | timestamptz | NULL | now() | Erstellungszeitpunkt |
| updated_at | timestamptz | NULL | now() | Letzte Änderung |
Qdrant Konfiguration
| Parameter | Wert |
|---|---|
| URL | http://localhost:6335 (ENV: QDRANT_CUSTOMERS_URL) |
| Collection-Name | tenant_{uuid}_knowledge |
| Vektor-Dimension | 1024 |
| Embedding-Modell | mistral-embed |
| Chunk-Größe | max 1000 Zeichen |
| Chunk-Minimum | 200 Zeichen |
| Overlap | 100 Zeichen |
| Satzerhaltend | Ja (respectSentences: true) |
KB Onboarding Checkliste
Der KBOnboardingService prueft automatisch 6 Kriterien (gespeichert in tenants.kb_onboarding als JSONB):
| Check | Feld | Bestanden wenn... |
|---|---|---|
| Preisdokument vorhanden | has_structured_prices | Mindestens 1 Item mit content_type='pricing' |
| FAQ vorhanden | has_faq | Item mit content_type='faq' ODER Eintraege in knowledge_faqs |
| Kontaktdaten in KB | has_contact_info | Content enthaelt Keywords: telefon, e-mail, kontakt, anruf |
| Keine E-Mail-Dumps | no_email_dumps | Keine Items mit status='pending_review' |
| PII-Scan bestanden | pii_scan_passed | Keine Items mit status='pending_review' |
| Bot-Zuweisungen komplett | bot_assignments_complete | Alle nicht-gelöschten Items haben Bot-Zuweisung |
Wenn alle 6 Checks bestanden sind, wird completed_at gesetzt. Faellt ein Check spaeter durch, wird completed_at zurückgesetzt auf null.
Verarbeitungs-Pipeline
1. Upload (PDF/TXT/MD/JSON/URL)
2. TextExtractor → Rohtext
3. KnowledgeValidator → PII-Scan (warnt, blockiert nicht)
4. DB-Insert in knowledge_items (status='pending')
5. TextChunker → Chunks (1000 Zeichen, 100 Overlap)
6. MistralEmbedding → 1024-dim Vektoren (NaN/Infinity Check!)
7. Qdrant Upsert → tenant_{uuid}_knowledge
8. DB-Update: status='ready', vectors_count, qdrant_point_ids
9. knowledge_bot_assignments INSERT (Auto-Assign!)