Mirrors /opt/ai-apps/eh-search/ on the server, including the full FastAPI app (intent routing, FTS+fuzzy+substring hybrid, multi-source federation across vehicles + blog + brands + pages + static + tag bridge), SQL schema (Postgres materialized view with german_unaccent text search, pg_trgm for fuzzy), Dockerfile and compose. Sanitized the hardcoded password in sql/01_init.sql — replaced with REPLACE_ME_BEFORE_APPLYING placeholder since this repo is public. The eh-search service binds only on the private network (10.0.0.8:8200) and is reachable only via Pegasus nginx proxy at /api/search. Refs OP#1094 OP#1105 OP#1112 OP#1116 OP#1117 |
||
|---|---|---|
| .. | ||
| app | ||
| .env.example | ||
| Agent.md | ||
| docker-compose.yml | ||
| Dockerfile | ||
| README.md | ||
| requirements.txt | ||
eh-search — Site-Search für electric-horses.de
Live: Via Nginx-Proxy auf https://www.electric-horses.de/api/search?q=...
Interne Adresse: http://10.0.0.8:8200 (privat, nicht public!)
Stack-Pfad: /opt/ai-apps/eh-search/ auf ai-apps
Was macht das?
Ein FastAPI-Service der eine Cmd+K Command Palette auf der Electric-Horses-Website mit Suchergebnissen versorgt. Durchsucht:
- 75 Fahrzeuge (Postgres FTS + Fuzzy + Komm-Nr/DVN Exact Lookup)
- 28 Blog-Posts (mit Tags + neue SEO-Descriptions)
- 24 Marken
- 6 Legal-Pages (Impressum, Datenschutz, ...)
- 8 Static Pages (Werkstatt, Ersatzteile, Kontakt, ...)
- 60 Tag → Page Bridges für semantische Verbindungen
Killer-Feature: Eingabe einer 4-stelligen Komm-Nr (oder D9094 etc.) → Direct Redirect zur Fahrzeug-Detailseite. Latenz <50ms. Ideal für Mitarbeiter am Telefon.
Architektur
Browser Cmd+K
↓
www.electric-horses.de/api/search
↓ (Nginx Proxy auf Pegasus)
10.0.0.8:8200 (eh-search auf ai-apps, privat)
↓
├─ Postgres eh_vehicles (loco-replica-db Container, Port 5433)
├─ Redis Cache (Stack-intern)
├─ Directus REST API (in-memory Content Index)
└─ Static Page Registry (hardcoded in Python)
Sicherheit
- Bind NUR auf privates Netz (10.0.0.8:8200) — nicht über Public-IP erreichbar
- Read-Only DB-User (
search_read) — kann nur SELECT auf Materialized View - Same-Origin via Pegasus Nginx — kein CORS nötig, kein neues Cert, kein neues DNS
- Rate Limit via Nginx (30 req/s pro IP)
Files
docker-compose.yml— StackDockerfile— Python 3.12 + FastAPI + asyncpg + redis-pyrequirements.txt— Python-Deps.env.example— Template für.env(niemals echte.envcommitten!)app/— FastAPI-Anwendungsql/— Postgres-Schema und Migrations (search_vehicles Materialized View, pg_trgm, unaccent)Agent.md— AI-BriefingREADME.md— diese Datei
Live-Update-Workflow
Wenn sich Fahrzeugdaten ändern (vehicle_sync.py nächtlich auf Pegasus), wird am Ende des Syncs automatisch die Materialized View refreshed UND der Redis-Cache invalidiert. Directus-Edits an Blog/Brands/Pages feuern einen Webhook an eh-search → sofortige Cache-Invalidation und Content-Index-Refresh.
OpenProject Phasen (alle abgeschlossen)
- M6 — Postgres FTS + Fuzzy + Exact + Command Palette (Phase 1)
- M6.2 — Federated Multi-Source (Phase 1.5)
- M6.3 — UX Refinement (sleek, mobile-first, smart group ordering)
- M6.4 — Komm-Nr Datenmodell-Fix (D9094 korrekt statt falsche interne Nummer)
- M6.5 — Sync-Fix für deaktivierte Fahrzeuge
Out of Scope (mögliche Phase 2)
- Semantic Vector Search via Qdrant + bge-Embeddings
- Voice Input via Whisper
- LLM Filter-Extraktion via lokales Mistral/Gemma
- Image Search / OCR
- Cross-Encoder Reranking