This repository has been archived on 2026-02-15. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Benjamin Admin 21a844cb8a fix: Restore all files lost during destructive rebase
A previous `git pull --rebase origin main` dropped 177 local commits,
losing 3400+ files across admin-v2, backend, studio-v2, website,
klausur-service, and many other services. The partial restore attempt
(660295e2) only recovered some files.

This commit restores all missing files from pre-rebase ref 98933f5e
while preserving post-rebase additions (night-scheduler, night-mode UI,
NightModeWidget dashboard integration).

Restored features include:
- AI Module Sidebar (FAB), OCR Labeling, OCR Compare
- GPU Dashboard, RAG Pipeline, Magic Help
- Klausur-Korrektur (8 files), Abitur-Archiv (5+ files)
- Companion, Zeugnisse-Crawler, Screen Flow
- Full backend, studio-v2, website, klausur-service
- All compliance SDKs, agent-core, voice-service
- CI/CD configs, documentation, scripts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 09:51:32 +01:00
..

edu-search-service

Spezialisierter Suchdienst für deutsche Bildungsinhalte - eine Alternative zu Tavily, optimiert für den deutschen Bildungssektor.

Übersicht

Der edu-search-service crawlt, extrahiert und indiziert Bildungsinhalte von deutschen Bildungsquellen (Kultusministerien, Bildungsserver, wissenschaftliche Studien, etc.) und stellt eine Such-API bereit.

Features

  • BM25 Keyword-Suche mit German Analyzer (OpenSearch)
  • Semantic Search mit Embeddings (OpenAI oder Ollama)
  • Hybrid Search kombiniert BM25 + Vektor-Ähnlichkeit
  • Automatisches Tagging für Dokumenttyp, Fächer, Schulstufe, Bundesland
  • Trust-Score basierend auf Domain-Reputation und Content-Qualität
  • Rate-Limited Crawler mit robots.txt Respekt
  • Admin API für Seed-Verwaltung und Crawl-Steuerung

Architektur

┌─────────────────────────────────────────────────────────────────────┐
│                        edu-search-service                           │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│   ┌─────────┐    ┌───────────┐    ┌────────┐    ┌─────────┐       │
│   │ Crawler │───▶│ Extractor │───▶│ Tagger │───▶│ Indexer │       │
│   └─────────┘    └───────────┘    └────────┘    └─────────┘       │
│        │                                              │             │
│        ▼                                              ▼             │
│   ┌─────────┐                                  ┌────────────┐      │
│   │  Seeds  │                                  │ OpenSearch │      │
│   └─────────┘                                  └────────────┘      │
│                                                      │             │
│                     ┌────────────┐                   │             │
│                     │ Search API │◀──────────────────┘             │
│                     └────────────┘                                 │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

Komponenten

Crawler (internal/crawler/)

  • Rate-Limited HTTP Client (Standard: 0.2 req/sec pro Domain)
  • Denylist-Support für ungewünschte Domains
  • Seeds aus Backend-API (primär) oder lokale Seed-Files (Fallback)
  • URL-Normalisierung und Deduplication
  • Seed-Metadaten: Trust-Boost, Crawl-Tiefe, Kategorie, Bundesland
  • Crawl-Status-Feedback an Backend (Dokumentenzahl, Dauer, Fehler)

Robots (internal/robots/)

  • robots.txt Parser mit Caching (24h TTL)
  • Unterstützt Disallow, Allow, Crawl-delay
  • Wildcard-Patterns (*) und End-Anchors ($)
  • User-Agent-spezifische Regeln
  • Leniente Behandlung bei fehlenden robots.txt

Extractor (internal/extractor/)

  • HTML-Extraktion mit goquery
  • PDF-Textextraktion mit ledongthuc/pdf Bibliothek
    • ExtractPDF() - Standard-Extraktion mit GetPlainText
    • ExtractPDFWithMetadata() - Seiten-weise Extraktion für mehr Kontrolle
    • Fallback-Extraktion bei beschädigten PDFs
    • Automatische Titel-Erkennung (erste signifikante Zeile)
    • Heading-Erkennung (All-Caps, nummerierte Zeilen)
  • Metadaten-Extraktion (og:title, description, etc.)
  • Content-Feature-Berechnung (Ad-Density, Link-Density)
  • Sprach-Erkennung (Deutsch/Englisch)

Tagger (internal/tagger/)

  • Regelbasiertes Tagging via YAML-Konfiguration
  • DocType-Erkennung (Lehrplan, Arbeitsblatt, Studie, etc.)
  • Fächer-Erkennung (Mathematik, Deutsch, etc.)
  • Schulstufen-Erkennung (Grundschule, Sek I/II, etc.)
  • Bundesland-Erkennung aus URL-Patterns
  • Trust-Score-Berechnung

Quality (internal/quality/)

  • Multi-Faktor Quality-Score (0-1)
    • Content Length (20%)
    • Heading Structure (15%)
    • Link/Ad Quality (15%)
    • Text-to-HTML Ratio (15%)
    • Metadata Presence (10%)
    • Language Clarity (10%)
    • Content Freshness (10%)
    • PDF-Specific Signals (5%)
  • Konfigurierbare Gewichtungen
  • Date-Indicator-Extraktion für Frische-Bewertung

Indexer (internal/indexer/)

  • OpenSearch 2.11 Client
  • German Analyzer für BM25
  • Bulk-Indexierung
  • Custom Mapping für Bildungsdokumente

Search (internal/search/)

  • Multi-Match Query mit Boosting
  • Filter für alle Taxonomie-Felder
  • Function-Score mit Trust/Quality-Boosting
  • Highlighting-Support
  • Drei Suchmodi:
    • keyword - Klassische BM25-Suche (Default)
    • semantic - Reine Vektor-Ähnlichkeitssuche (k-NN)
    • hybrid - Kombination aus BM25 und Vektor-Score

Embedding (internal/embedding/)

  • OpenAI Provider - text-embedding-3-small (1536 Dimensionen)
  • Ollama Provider - Lokale Modelle (z.B. nomic-embed-text, 384-768 Dim.)
  • Batch-Embedding für effiziente Indexierung
  • Automatische Text-Kürzung (max. 30.000 Zeichen)

Scheduler (internal/scheduler/)

  • Automatisches Crawling in konfigurierbaren Intervallen
  • Default: täglich um 2:00 Uhr (minimale Auswirkung)
  • Manuelles Triggern via Admin-API
  • Status-Tracking (letzter Lauf, nächster Lauf, Ergebnis)

API Endpoints

Public Endpoints

Method Endpoint Beschreibung
GET /v1/health Health Check (kein Auth)
POST /v1/search Suche ausführen
GET /v1/document Einzeldokument abrufen

Admin Endpoints (Auth erforderlich)

Method Endpoint Beschreibung
GET /v1/admin/seeds Alle Seeds abrufen
POST /v1/admin/seeds Neuen Seed erstellen
PUT /v1/admin/seeds/:id Seed aktualisieren
DELETE /v1/admin/seeds/:id Seed löschen
GET /v1/admin/stats Crawl-Statistiken
POST /v1/admin/crawl/start Crawl starten

API Dokumentation

POST /v1/search

Request Body:

{
  "q": "Lehrplan Mathematik Gymnasium",
  "mode": "keyword",
  "limit": 10,
  "offset": 0,
  "filters": {
    "language": ["de"],
    "doc_type": ["Lehrplan"],
    "school_level": ["Gymnasium"],
    "state": ["BY", "NW"],
    "subjects": ["Mathematik"],
    "min_trust_score": 0.5
  },
  "include": {
    "snippets": true,
    "highlights": true
  }
}

Such-Modi (mode):

Mode Beschreibung
keyword BM25-Textsuche (Default)
semantic Vektor-Ähnlichkeitssuche via Embeddings
hybrid Kombination: 70% BM25 + 30% Vektor-Score

Hinweis: semantic und hybrid Modi erfordern SEMANTIC_SEARCH_ENABLED=true und konfigurierte Embedding-Provider.

Response:

{
  "query_id": "q-12345",
  "results": [
    {
      "doc_id": "uuid-...",
      "title": "Lehrplan Mathematik Gymnasium Bayern",
      "url": "https://www.isb.bayern.de/...",
      "domain": "isb.bayern.de",
      "language": "de",
      "doc_type": "Lehrplan",
      "school_level": "Gymnasium",
      "subjects": ["Mathematik"],
      "scores": {
        "bm25": 12.5,
        "trust": 0.85,
        "quality": 0.9,
        "final": 10.6
      },
      "snippet": "Der Lehrplan für das Fach Mathematik...",
      "highlights": ["<em>Lehrplan</em> für das Fach <em>Mathematik</em>..."]
    }
  ],
  "pagination": {
    "limit": 10,
    "offset": 0,
    "total_estimate": 156
  }
}

Filter-Optionen

Filter Werte
language de, en
doc_type Lehrplan, Arbeitsblatt, Unterrichtsentwurf, Erlass_Verordnung, Pruefung_Abitur, Studie_Bericht, Sonstiges
school_level Grundschule, Sek_I, Gymnasium, Berufsschule, Hochschule, Alle, NA
state BW, BY, BE, BB, HB, HH, HE, MV, NI, NW, RP, SL, SN, ST, SH, TH
subjects Mathematik, Deutsch, Englisch, Geschichte, Physik, Biologie, Chemie, etc.

Konfiguration

Umgebungsvariablen

Variable Beschreibung Default
PORT Server Port 8084
OPENSEARCH_URL OpenSearch URL http://opensearch:9200
OPENSEARCH_USERNAME OpenSearch User admin
OPENSEARCH_PASSWORD OpenSearch Passwort admin
INDEX_NAME Index Name bp_documents_v1
USER_AGENT Crawler User Agent BreakpilotEduCrawler/1.0
RATE_LIMIT_PER_SEC Requests pro Sekunde/Domain 0.2
MAX_DEPTH Max Crawl-Tiefe 4
MAX_PAGES_PER_RUN Max Seiten pro Crawl 500
SEEDS_DIR Seed-Dateien Verzeichnis ./seeds
RULES_DIR Tagging-Regeln Verzeichnis ./rules
EDU_SEARCH_API_KEY API Key für Auth ``
BACKEND_URL URL zum Python Backend http://backend:8000
SEEDS_FROM_API Seeds aus API laden true
Semantic Search
SEMANTIC_SEARCH_ENABLED Semantic Search aktivieren false
EMBEDDING_PROVIDER Provider: openai, ollama, none none
OPENAI_API_KEY API Key für OpenAI Embeddings ``
EMBEDDING_MODEL Embedding-Modell text-embedding-3-small
EMBEDDING_DIMENSION Vektor-Dimension 1536
OLLAMA_URL Ollama Server URL http://ollama:11434
Scheduler
SCHEDULER_ENABLED Automatisches Crawling aktivieren false
SCHEDULER_INTERVAL Crawl-Intervall 24h (täglich)

Installation & Start

Docker (empfohlen)

# Im edu-search-service Verzeichnis
docker compose up -d

# Logs anzeigen
docker compose logs -f edu-search

# Nur der Service (OpenSearch extern)
docker build -t edu-search-service .
docker run -p 8084:8084 \
  -e OPENSEARCH_URL=http://host.docker.internal:9200 \
  edu-search-service

Lokal (Entwicklung)

# Dependencies installieren
go mod download

# Service starten
go run cmd/server/main.go

# Tests ausführen
go test -v ./...

Seed-Kategorien

Kategorie Beschreibung Beispiele
federal Bundesweite Institutionen KMK, BMBF, IQB
states Landeskultusbehörden Kultusministerien, Landesinstitute
science Wissenschaftliche Studien PISA, IGLU, TIMSS
universities Hochschulen Pädagogische Hochschulen
schools Schulen direkt Schulhomepages
portals Bildungsportale Lehrer-Online, 4teachers
eu EU-Bildungsprogramme Erasmus+, Eurydice
authorities Schulbehörden Regierungspräsidien

Tagging-Regeln

Die YAML-Regeldateien im rules/ Verzeichnis definieren das Tagging:

  • doc_type_rules.yaml - Dokumenttyp-Erkennung
  • subject_rules.yaml - Fächer-Erkennung
  • level_rules.yaml - Schulstufen-Erkennung
  • trust_rules.yaml - Trust-Score-Berechnung

Beispiel: doc_type_rules.yaml

doc_types:
  Lehrplan:
    strong_terms:
      - Lehrplan
      - Kernlehrplan
      - Bildungsplan
    medium_terms:
      - Curriculum
      - Kompetenzerwartungen
    url_patterns:
      - /lehrplan
      - /kernlehrplan

priority_order:
  - Pruefung_Abitur
  - Lehrplan
  - Arbeitsblatt

Projektstruktur

edu-search-service/
├── cmd/
│   └── server/
│       └── main.go          # Entry Point
├── internal/
│   ├── api/
│   │   └── handlers/
│   │       ├── handlers.go       # Search & Health Handler
│   │       └── admin_handlers.go # Admin API Handler
│   ├── config/
│   │   └── config.go        # Konfiguration
│   ├── crawler/
│   │   ├── crawler.go       # URL Fetcher
│   │   └── api_client.go    # Backend API Client (Seeds)
│   ├── robots/
│   │   └── robots.go        # robots.txt Parser & Checker
│   ├── embedding/
│   │   └── embedding.go     # Embedding Provider (OpenAI/Ollama)
│   ├── extractor/
│   │   └── extractor.go     # HTML/PDF Extraktion
│   ├── indexer/
│   │   └── mapping.go       # OpenSearch Indexer
│   ├── pipeline/
│   │   └── pipeline.go      # Crawl Orchestrierung
│   ├── quality/
│   │   └── quality.go       # Multi-Faktor Quality Scoring
│   ├── scheduler/
│   │   └── scheduler.go     # Automatisches Crawl-Scheduling
│   ├── search/
│   │   └── search.go        # Search Service (Keyword/Semantic/Hybrid)
│   └── tagger/
│       └── tagger.go        # Regelbasiertes Tagging
├── rules/
│   ├── doc_type_rules.yaml
│   ├── subject_rules.yaml
│   ├── level_rules.yaml
│   └── trust_rules.yaml
├── seeds/
│   ├── federal.txt
│   ├── states.txt
│   └── denylist.txt
├── Dockerfile
├── docker-compose.yml
├── go.mod
└── README.md

Abhängigkeiten

Package Version Beschreibung Lizenz
github.com/gin-gonic/gin v1.9+ HTTP Framework MIT
github.com/opensearch-project/opensearch-go/v2 v2.3+ OpenSearch Client Apache-2.0
github.com/PuerkitoBio/goquery v1.8+ HTML Parser BSD-3-Clause
github.com/ledongthuc/pdf v0.0.0-20240201 PDF Text Extraktion MIT
gopkg.in/yaml.v3 v3.0+ YAML Parser MIT
github.com/google/uuid v1.4+ UUID Generation BSD-3-Clause
golang.org/x/net v0.19+ HTML Utilities BSD-3-Clause

Tests ausführen

# Alle Tests
go test -v ./...

# Mit Coverage
go test -cover ./...

# Nur Tagger Tests
go test -v ./internal/tagger/...

# Nur Crawler Tests
go test -v ./internal/crawler/...

Lizenz

Proprietär - BreakPilot GmbH

Kontakt