Home Ai Tools Artikel 2
Teil 2 Generative AI

kb: Die Wissens-Pipeline für Agenten

Bild: KI-generiert mit Beuys


kb: Die Wissens-Pipeline für Agenten

Vom statischen PDF zur lebendigen Wissensdatenbank: Wie das kb CLI-Tool Agenten den Zugriff auf Fachliteratur ermöglicht – inklusive Discovery, Vision AI und strukturierter JSON-Ausgabe.


1. Das Problem: Fachwissen ist in Silos gefangen

In der Welt der KI-Agenten ist der Zugriff auf aktuelles und tiefgreifendes Fachwissen oft die größte Hürde. Während LLMs über ein beeindruckendes Allgemeinwissen verfügen, stoßen sie bei spezifischen, mathematischen oder hochaktuellen Themen an ihre Grenzen.

Das wertvollste Wissen liegt oft in Fachbüchern (PDF und EPUB), die jedoch für Agenten schwer zugänglich sind: 1. Unstrukturierte Daten: PDFs und EPUBs sind für Menschen optimiert, nicht für Maschinen. 2. Kontext-Fenster: Man kann nicht einfach 40 Fachbücher in den Prompt eines Agenten kopieren. 3. Quellentreue: Agenten neigen zu Halluzinationen, wenn sie keine festen Referenzen haben. 4. Visuelle Inhalte: Diagramme und Abbildungen in Büchern enthalten oft zentrale Informationen, die reine Textextraktion nicht erfasst.

"The only way to make sense out of change is to plunge into it, move with it, and join the dance." — Alan Watts

Für einen KI-Agenten bedeutet "join the dance", dass er aktiv auf eine externe Wissensbasis zugreifen muss, um valide Antworten zu geben.

2. Die Lösung: Das kb CLI-Tool

kb ist ein spezialisiertes Command-Line-Interface, das eine Brücke zwischen statischer Fachliteratur und dynamischen KI-Workflows schlägt. Es implementiert eine vollständige RAG-Pipeline (Retrieval-Augmented Generation) direkt im Terminal.

Key Features

→ GitHub: github.com/mhennemeyer/knowledgebase

3. In Action: Der Agent-Workflow

Der typische Workflow eines Agenten mit kb besteht aus zwei Schritten: Discovery und Abfrage.

Schritt 1: Discovery – Welche Wissensdatenbanken existieren?

kb kbs --json

Output (JSON):

{
  "knowledgebases": [
    {
      "name": "fp",
      "books": 8,
      "chunks": 4163,
      "book_titles": ["Functional Programming in Scala", "Haskell Programming from First Principles", "..."]
    },
    {
      "name": "cat",
      "books": 8,
      "chunks": 3090,
      "book_titles": ["Category Theory for Programmers", "Category Theory Illustrated", "..."]
    },
    {
      "name": "ai",
      "books": 25,
      "chunks": 14457,
      "book_titles": ["Designing Autonomous AI", "..."]
    }
  ]
}

Der Agent kennt nun die verfügbaren Wissensgebiete, die jeweilige Tiefe (Chunks) und die konkreten Buchtitel. Ohne --name befragt kb ask nur die default-KB – mit kb kbs trifft der Agent eine informierte Entscheidung, welche KB relevant ist.

Schritt 2: Gezielte Abfrage

kb ask "Was ist ein Funktor?" --name cat --json

Output (JSON):

{
  "answer": "Ein Funktor ist ein Konzept aus der Kategorientheorie, das eine Abbildung zwischen Kategorien darstellt. Er besteht aus zwei Abbildungen: einer für Objekte und einer für Morphismen. Diese müssen die Struktur (Identität und Komposition) bewahren...",
  "sources": [
    {
      "book": "Category Theory Illustrated",
      "page": 202,
      "score": 0.55,
      "open_cmd": "open -a Skim 'path/to/book.pdf' --args -page 202"
    },
    {
      "book": "Category Theory for Programmers",
      "page": 122,
      "score": 0.50
    }
  ]
}

Durch den --json-Flag erhält der Agent eine strukturierte Antwort, die er direkt verarbeiten kann. Er kennt die Antwort, die exakten Quellen und könnte dem Benutzer sogar anbieten, das Buch an der richtigen Stelle zu öffnen.

4. Statistische Übersicht

Aktuell verwaltet das kb-Tool für dieses Projekt vier thematische Wissensdatenbanken mit insgesamt 43 Büchern:

KB Name Thema Bücher Chunks
fp Functional Programming 8 4.163
cat Kategorientheorie 8 3.090
arch Software-Architektur 1 898
ai AI & Agentic Systems 25 14.457

Diese Datenmengen wären für einen Agenten ohne semantische Indizierung nicht handhabbar.

5. Architektur: Pipeline mit Vision AI

Die technische Pipeline von kb verarbeitet Bücher in mehreren Stufen:

PDF/EPUB → extract → Markdown + Images → chunk → Chunks → index → FAISS
              ↓                                                     ↓
        Vision AI (GPT-4o)              Question → search → Chunks → LLM → Answer + Sources
         beschreibt Bilder

Durch die optionale Vision-AI-Stufe (GPT-4o Vision) werden Abbildungen aus Büchern extrahiert, beschrieben und als Textchunks indiziert. Diagramme, Grafiken und Formeln stehen dem Agenten damit als durchsuchbares Wissen zur Verfügung.

6. Integration: Warum CLI?

Die Entscheidung, die Wissensdatenbank als CLI-Tool zu realisieren, folgt dem Prinzip der Modularen Intelligenz. Anstatt die RAG-Logik in jede Applikation neu zu implementieren, bietet kb eine universelle Schnittstelle:

  1. Unabhängigkeit: Das Tool funktioniert unabhängig von der Web-Plattform oder dem spezifischen Agenten.
  2. Kombinierbarkeit: Via Pipes (|) können Suchergebnisse in andere Tools (wie grep oder jq) geleitet werden.
  3. Agent-Ready: Moderne Agenten sind exzellent darin, CLI-Tools zu bedienen. Sie "verstehen" die Hilfe-Seiten von Typer/Click und können Parameter korrekt setzen.
  4. Discovery-First: Der kb kbs --json-Befehl ermöglicht Agenten, die verfügbaren Wissensgebiete zu erkunden, bevor sie eine Abfrage stellen – ein Self-Service-Ansatz für autonome Agenten.

Selbst ausprobieren

Genau das macht kb für Agenten so attraktiv: Die kbs --json-Antwort ist Daten, die sich mit reinen Funktionen verarbeiten lassen. Hier ein kleines Discovery-Match: Gegeben die JSON-Struktur und eine Nutzerfrage, wird per simplem Keyword-Score die passendste KB ausgewählt – ohne LLM, ohne Embeddings, nur Standardbibliothek.

import json
import re

kbs_response = """
{
  "knowledgebases": [
    {"name": "fp",   "books": 8,  "chunks": 4163,
     "book_titles": ["Functional Programming in Scala", "Haskell Programming from First Principles"]},
    {"name": "cat",  "books": 8,  "chunks": 3090,
     "book_titles": ["Category Theory for Programmers", "Category Theory Illustrated"]},
    {"name": "ai",   "books": 25, "chunks": 14457,
     "book_titles": ["Designing Autonomous AI", "Building LLM Agents"]}
  ]
}
"""

def tokens(text):
    return set(re.findall(r"[a-zäöüß]+", text.lower()))

def score_kb(kb, question_tokens):
    """Reiner Score: Anzahl Token-Treffer in Name + Buchtiteln."""
    haystack = kb["name"] + " " + " ".join(kb["book_titles"])
    return len(question_tokens & tokens(haystack))

def best_kb(kbs_json, question):
    data = json.loads(kbs_json)
    q = tokens(question)
    ranked = sorted(
        data["knowledgebases"],
        key=lambda kb: (score_kb(kb, q), kb["chunks"]),
        reverse=True,
    )
    return ranked[0]

questions = [
    "Was ist ein Funktor in der Category Theory?",
    "Wie baue ich einen autonomen LLM-Agent?",
    "Erkläre Monaden in Haskell",
]

for q in questions:
    kb = best_kb(kbs_response, q)
    print(f"{q!r:55} → best KB: {kb['name']:4}  (chunks={kb['chunks']})")

Erweiterungs-Idee: Ersetze den Keyword-Score durch eine reine Funktion score_by_overlap(kb, query_tokens), die zusätzlich die Buchtitel höher gewichtet als den KB-Namen – Auswahl-Logik bleibt testbar, ganz ohne externe Abhängigkeit.

Genau das ist der zweite, vertiefte Schritt: Buchtitel sind aussagekräftiger als der knappe KB-Name – also gewichten wir sie höher. Die Auswahl-Logik bleibt eine reine Funktion und das Scoring jeder KB ist nachvollziehbar.

import json, re

kbs_response = """
{
  "knowledgebases": [
    {"name": "fp",   "books": 8,  "chunks": 4163,
     "book_titles": ["Functional Programming in Scala", "Haskell Programming from First Principles"]},
    {"name": "cat",  "books": 8,  "chunks": 3090,
     "book_titles": ["Category Theory for Programmers", "Category Theory Illustrated"]},
    {"name": "ai",   "books": 25, "chunks": 14457,
     "book_titles": ["Designing Autonomous AI", "Building LLM Agents"]}
  ]
}
"""

def tokens(text):
    return set(re.findall(r"[a-zäöüß]+", text.lower()))

def score_by_overlap(kb, q, w_name: int = 1, w_title: int = 3) -> int:
    """Reiner gewichteter Score: Titel zählen stärker als der KB-Name."""
    name_hits  = len(q & tokens(kb["name"]))
    title_hits = len(q & tokens(" ".join(kb["book_titles"])))
    return w_name * name_hits + w_title * title_hits

def rank(kbs_json, question):
    data = json.loads(kbs_json)
    q = tokens(question)
    scored = [(kb["name"], score_by_overlap(kb, q)) for kb in data["knowledgebases"]]
    return sorted(scored, key=lambda t: t[1], reverse=True)

for q in [
    "Was ist ein Funktor in der Category Theory?",
    "Wie baue ich einen autonomen LLM-Agent?",
    "Erkläre Monaden in Haskell",
]:
    ranking = rank(kbs_response, q)
    print(f"{q!r:50} → ranking={ranking}")

Beobachtung: Die Reihenfolge folgt der Aussagekraft der Buchtitel, nicht dem KB-Namen – cat schlägt fp bei „Category Theory", weil beide Titel zur Frage passen.

7. Fazit

kb verwandelt eine Sammlung von PDFs und EPUBs in ein abfragbares Gehirn – inklusive der visuellen Inhalte. Der Discovery-Workflow (kbsask --name) und die durchgängige JSON-Unterstützung machen das Tool zu einer natürlichen Schnittstelle für KI-Agenten, die auf fundiertes Fachwissen zugreifen müssen.


Quellen & Ressourcen

📄 Als PDF