Enhance .env loading mechanism and EdgeDTO creation with error handling
All checks were successful
Deploy mindnet to llm-node / deploy (push) Successful in 4s
All checks were successful
Deploy mindnet to llm-node / deploy (push) Successful in 4s
- Updated the .env loading process to first check for an explicit path, improving reliability in different working directories. - Added logging for successful .env loading and fallback mechanisms. - Enhanced EdgeDTO creation with robust error handling, including fallbacks for unsupported provenance values and logging of errors for better traceability.
This commit is contained in:
parent
df5f9b3fe4
commit
6d268d9dfb
|
|
@ -15,7 +15,34 @@ from dotenv import load_dotenv
|
||||||
|
|
||||||
# WP-20: Lade Umgebungsvariablen aus der .env Datei
|
# WP-20: Lade Umgebungsvariablen aus der .env Datei
|
||||||
# override=True garantiert, dass Änderungen in der .env immer Vorrang haben.
|
# override=True garantiert, dass Änderungen in der .env immer Vorrang haben.
|
||||||
load_dotenv(override=True)
|
# WP-24c v4.5.10: Expliziter Pfad für .env-Datei, um Probleme mit Arbeitsverzeichnis zu vermeiden
|
||||||
|
# Suche .env im Projekt-Root (3 Ebenen über app/config.py: app/config.py -> app/ -> root/)
|
||||||
|
_project_root = Path(__file__).parent.parent.parent
|
||||||
|
_env_file = _project_root / ".env"
|
||||||
|
_env_loaded = False
|
||||||
|
|
||||||
|
# Versuche zuerst expliziten Pfad
|
||||||
|
if _env_file.exists():
|
||||||
|
_env_loaded = load_dotenv(_env_file, override=True)
|
||||||
|
if _env_loaded:
|
||||||
|
# Optional: Logging (nur wenn logging bereits initialisiert ist)
|
||||||
|
try:
|
||||||
|
import logging
|
||||||
|
_logger = logging.getLogger(__name__)
|
||||||
|
_logger.debug(f"✅ .env geladen von: {_env_file}")
|
||||||
|
except:
|
||||||
|
pass # Logging noch nicht initialisiert
|
||||||
|
|
||||||
|
# Fallback: Automatische Suche (für Dev/Test oder wenn .env an anderer Stelle liegt)
|
||||||
|
if not _env_loaded:
|
||||||
|
_env_loaded = load_dotenv(override=True)
|
||||||
|
if _env_loaded:
|
||||||
|
try:
|
||||||
|
import logging
|
||||||
|
_logger = logging.getLogger(__name__)
|
||||||
|
_logger.debug(f"✅ .env geladen via automatische Suche (cwd: {Path.cwd()})")
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
class Settings:
|
class Settings:
|
||||||
# --- Qdrant Datenbank ---
|
# --- Qdrant Datenbank ---
|
||||||
|
|
|
||||||
|
|
@ -216,6 +216,9 @@ def _build_explanation(
|
||||||
|
|
||||||
direction = "in" if tgt == target_note_id else "out"
|
direction = "in" if tgt == target_note_id else "out"
|
||||||
|
|
||||||
|
# WP-24c v4.5.10: Robuste EdgeDTO-Erstellung mit Fehlerbehandlung
|
||||||
|
# Falls Provenance-Wert nicht unterstützt wird, verwende Fallback
|
||||||
|
try:
|
||||||
edge_obj = EdgeDTO(
|
edge_obj = EdgeDTO(
|
||||||
id=f"{src}->{tgt}:{kind}",
|
id=f"{src}->{tgt}:{kind}",
|
||||||
kind=kind,
|
kind=kind,
|
||||||
|
|
@ -227,6 +230,28 @@ def _build_explanation(
|
||||||
confidence=conf
|
confidence=conf
|
||||||
)
|
)
|
||||||
edges_dto.append(edge_obj)
|
edges_dto.append(edge_obj)
|
||||||
|
except Exception as e:
|
||||||
|
# WP-24c v4.5.10: Fallback bei Validierungsfehler (z.B. alte EdgeDTO-Version im Cache)
|
||||||
|
logger.warning(
|
||||||
|
f"⚠️ [EDGE-DTO] Provenance '{prov}' nicht unterstützt für Edge {src}->{tgt} ({kind}). "
|
||||||
|
f"Fehler: {e}. Verwende Fallback 'explicit'."
|
||||||
|
)
|
||||||
|
# Fallback: Verwende 'explicit' als sicheren Default
|
||||||
|
try:
|
||||||
|
edge_obj = EdgeDTO(
|
||||||
|
id=f"{src}->{tgt}:{kind}",
|
||||||
|
kind=kind,
|
||||||
|
source=src,
|
||||||
|
target=tgt,
|
||||||
|
weight=conf,
|
||||||
|
direction=direction,
|
||||||
|
provenance="explicit", # Fallback
|
||||||
|
confidence=conf
|
||||||
|
)
|
||||||
|
edges_dto.append(edge_obj)
|
||||||
|
except Exception as e2:
|
||||||
|
logger.error(f"❌ [EDGE-DTO] Auch Fallback fehlgeschlagen: {e2}. Überspringe Edge.")
|
||||||
|
# Überspringe diese Kante - besser als kompletter Fehler
|
||||||
|
|
||||||
# Die 3 wichtigsten Kanten als Begründung formulieren
|
# Die 3 wichtigsten Kanten als Begründung formulieren
|
||||||
top_edges = sorted(edges_dto, key=lambda e: e.confidence, reverse=True)
|
top_edges = sorted(edges_dto, key=lambda e: e.confidence, reverse=True)
|
||||||
|
|
|
||||||
105
docs/03_Technical_References/ENV_LOADING_DEBUG.md
Normal file
105
docs/03_Technical_References/ENV_LOADING_DEBUG.md
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
# Debug: .env-Lade-Problem in Prod
|
||||||
|
|
||||||
|
**Datum**: 2026-01-12
|
||||||
|
**Version**: v4.5.10
|
||||||
|
**Status**: 🔴 Kritisch
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
|
||||||
|
Möglicherweise wird die `.env`-Datei in Prod nicht korrekt geladen, was zu:
|
||||||
|
- Falschen Log-Levels (DEBUG=true wird ignoriert)
|
||||||
|
- Falschen Collection-Präfixen
|
||||||
|
- Falschen Konfigurationen
|
||||||
|
führen kann.
|
||||||
|
|
||||||
|
## Diagnose
|
||||||
|
|
||||||
|
### Schritt 1: Prüfe, ob .env-Datei existiert
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# In Prod
|
||||||
|
cd ~/mindnet
|
||||||
|
ls -la .env
|
||||||
|
cat .env | head -20
|
||||||
|
```
|
||||||
|
|
||||||
|
### Schritt 2: Prüfe Arbeitsverzeichnis beim Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# In Prod - prüfe, von wo uvicorn gestartet wird
|
||||||
|
ps aux | grep uvicorn
|
||||||
|
# Oder in systemd service:
|
||||||
|
cat /etc/systemd/system/mindnet.service | grep WorkingDirectory
|
||||||
|
```
|
||||||
|
|
||||||
|
### Schritt 3: Verifikations-Script ausführen
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# In Prod
|
||||||
|
cd ~/mindnet
|
||||||
|
source .venv/bin/activate
|
||||||
|
python3 scripts/verify_env_loading.py
|
||||||
|
```
|
||||||
|
|
||||||
|
**Erwartete Ausgabe**:
|
||||||
|
```
|
||||||
|
✅ .env geladen von: /path/to/mindnet/.env
|
||||||
|
✅ COLLECTION_PREFIX = mindnet
|
||||||
|
✅ DEBUG = true
|
||||||
|
```
|
||||||
|
|
||||||
|
### Schritt 4: Manuelle Verifikation
|
||||||
|
|
||||||
|
```python
|
||||||
|
# In Python-REPL in Prod
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
# Prüfe aktuelles Verzeichnis
|
||||||
|
print(f"CWD: {Path.cwd()}")
|
||||||
|
print(f"Projekt-Root: {Path(__file__).parent.parent.parent}")
|
||||||
|
|
||||||
|
# Lade .env
|
||||||
|
env_file = Path(".env")
|
||||||
|
if env_file.exists():
|
||||||
|
load_dotenv(env_file, override=True)
|
||||||
|
print(f"✅ .env geladen: {env_file.absolute()}")
|
||||||
|
else:
|
||||||
|
print(f"❌ .env nicht gefunden in: {env_file.absolute()}")
|
||||||
|
|
||||||
|
# Prüfe kritische Variablen
|
||||||
|
print(f"DEBUG: {os.getenv('DEBUG', 'NICHT GESETZT')}")
|
||||||
|
print(f"COLLECTION_PREFIX: {os.getenv('COLLECTION_PREFIX', 'NICHT GESETZT')}")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Mögliche Ursachen
|
||||||
|
|
||||||
|
### 1. Arbeitsverzeichnis-Problem
|
||||||
|
- **Problem**: uvicorn wird aus einem anderen Verzeichnis gestartet
|
||||||
|
- **Lösung**: Expliziter Pfad in `config.py` (bereits implementiert)
|
||||||
|
|
||||||
|
### 2. .env-Datei nicht im Projekt-Root
|
||||||
|
- **Problem**: .env liegt in `config/prod.env` statt `.env`
|
||||||
|
- **Lösung**: Symlink erstellen oder Pfad anpassen
|
||||||
|
|
||||||
|
### 3. Systemd-Service ohne WorkingDirectory
|
||||||
|
- **Problem**: Service startet ohne korrektes Arbeitsverzeichnis
|
||||||
|
- **Lösung**: `WorkingDirectory=/path/to/mindnet` in systemd service
|
||||||
|
|
||||||
|
### 4. Mehrere .env-Dateien
|
||||||
|
- **Problem**: Es gibt `.env`, `prod.env`, `config/prod.env` - welche wird geladen?
|
||||||
|
- **Lösung**: Expliziter Pfad oder Umgebungsvariable `DOTENV_PATH`
|
||||||
|
|
||||||
|
## Fix-Implementierung
|
||||||
|
|
||||||
|
Der Code in `app/config.py` wurde erweitert:
|
||||||
|
- ✅ Expliziter Pfad für `.env` im Projekt-Root
|
||||||
|
- ✅ Fallback auf automatische Suche
|
||||||
|
- ✅ Debug-Logging (wenn verfügbar)
|
||||||
|
|
||||||
|
## Verifikation nach Fix
|
||||||
|
|
||||||
|
1. **Log prüfen**: Sollte `✅ .env geladen von: ...` zeigen
|
||||||
|
2. **Umgebungsvariablen prüfen**: `echo $DEBUG`, `echo $COLLECTION_PREFIX`
|
||||||
|
3. **Settings prüfen**: `python3 -c "from app.config import get_settings; s = get_settings(); print(f'DEBUG: {s.DEBUG}, PREFIX: {s.COLLECTION_PREFIX}')"`
|
||||||
134
docs/03_Technical_References/PROD_DEPLOYMENT_CHECKLIST.md
Normal file
134
docs/03_Technical_References/PROD_DEPLOYMENT_CHECKLIST.md
Normal file
|
|
@ -0,0 +1,134 @@
|
||||||
|
# Deployment-Checkliste: Prod vs. Dev Retrieval-Problem
|
||||||
|
|
||||||
|
**Datum**: 2026-01-12
|
||||||
|
**Version**: v4.5.10
|
||||||
|
**Status**: 🔴 Kritisch
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
|
||||||
|
Prod-System findet keine Suchergebnisse, während Dev-System korrekt funktioniert. Identischer Code, identische Daten.
|
||||||
|
|
||||||
|
## Identifizierte Ursachen
|
||||||
|
|
||||||
|
### 1. 🔴 **KRITISCH: Alte EdgeDTO-Version in Prod**
|
||||||
|
|
||||||
|
**Symptom**:
|
||||||
|
```
|
||||||
|
ERROR: 1 validation error for EdgeDTO
|
||||||
|
provenance
|
||||||
|
Input should be 'explicit', 'rule', 'smart' or 'structure'
|
||||||
|
[type=literal_error, input_value='explicit:callout', input_type=str]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Ursache**:
|
||||||
|
- Prod verwendet eine **alte Version** des `EdgeDTO`-Modells aus `app/models/dto.py`
|
||||||
|
- Die alte Version unterstützt nur: `"explicit", "rule", "smart", "structure"`
|
||||||
|
- Die neue Version (v4.5.3+) unterstützt: `"explicit:callout", "explicit:wikilink", "explicit:note_zone", ...`
|
||||||
|
|
||||||
|
**Lösung**:
|
||||||
|
- ✅ Code in `dto.py` ist bereits korrekt (Zeile 51-56)
|
||||||
|
- ⚠️ **Prod muss neu gestartet werden**, um die neue Version zu laden
|
||||||
|
- ⚠️ **Python-Modul-Cache leeren** falls nötig: `find . -type d -name __pycache__ -exec rm -r {} +`
|
||||||
|
|
||||||
|
### 2. ✅ Collection-Präfix korrekt
|
||||||
|
|
||||||
|
- Prod: `COLLECTION_PREFIX=mindnet` → `mindnet_chunks` ✅
|
||||||
|
- Dev: `COLLECTION_PREFIX=mindnet_dev` → `mindnet_dev_chunks` ✅
|
||||||
|
- **Kein Problem hier**
|
||||||
|
|
||||||
|
## Sofortmaßnahmen
|
||||||
|
|
||||||
|
### Schritt 1: Code-Verifikation in Prod
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# In Prod-System
|
||||||
|
cd /path/to/mindnet
|
||||||
|
grep -A 10 "provenance.*Literal" app/models/dto.py
|
||||||
|
```
|
||||||
|
|
||||||
|
**Erwartete Ausgabe**:
|
||||||
|
```python
|
||||||
|
provenance: Optional[Literal[
|
||||||
|
"explicit", "rule", "smart", "structure",
|
||||||
|
"explicit:callout", "explicit:wikilink", "explicit:note_zone", ...
|
||||||
|
]] = "explicit"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Falls nicht vorhanden**: Code ist nicht aktualisiert → Deployment erforderlich
|
||||||
|
|
||||||
|
### Schritt 2: Python-Cache leeren
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# In Prod-System
|
||||||
|
find . -type d -name __pycache__ -exec rm -r {} +
|
||||||
|
find . -name "*.pyc" -delete
|
||||||
|
```
|
||||||
|
|
||||||
|
### Schritt 3: Service neu starten
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# FastAPI/uvicorn neu starten
|
||||||
|
# Oder Docker-Container neu starten
|
||||||
|
```
|
||||||
|
|
||||||
|
### Schritt 4: Verifikation
|
||||||
|
|
||||||
|
1. **Test-Query ausführen**:
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:8001/api/chat \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"message": "Was für einen Status hat das Projekt mindnet?"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Log prüfen**:
|
||||||
|
- ✅ Keine `validation error for EdgeDTO` mehr
|
||||||
|
- ✅ `✨ [SUCCESS] Stream 'facts_stream' lieferte X Treffer.`
|
||||||
|
- ✅ Ergebnisse werden zurückgegeben
|
||||||
|
|
||||||
|
## Code-Vergleich
|
||||||
|
|
||||||
|
### Aktuelle Version (sollte in Prod sein):
|
||||||
|
|
||||||
|
```python
|
||||||
|
# app/models/dto.py (Zeile 51-56)
|
||||||
|
provenance: Optional[Literal[
|
||||||
|
"explicit", "rule", "smart", "structure",
|
||||||
|
"explicit:callout", "explicit:wikilink", "explicit:note_zone", "explicit:note_scope",
|
||||||
|
"inline:rel", "callout:edge", "semantic_ai", "structure:belongs_to", "structure:order",
|
||||||
|
"derived:backlink", "edge_defaults", "global_pool"
|
||||||
|
]] = "explicit"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Alte Version (verursacht Fehler):
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Alte Version (nur 4 Werte)
|
||||||
|
provenance: Optional[Literal[
|
||||||
|
"explicit", "rule", "smart", "structure"
|
||||||
|
]] = "explicit"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Weitere mögliche Ursachen (wenn Fix nicht hilft)
|
||||||
|
|
||||||
|
### 1. Unterschiedliche Python-Versionen
|
||||||
|
- Prüfen: `python --version` in Dev vs. Prod
|
||||||
|
- Pydantic-Verhalten kann zwischen Versionen variieren
|
||||||
|
|
||||||
|
### 2. Unterschiedliche Pydantic-Versionen
|
||||||
|
- Prüfen: `pip list | grep pydantic` in Dev vs. Prod
|
||||||
|
- `requirements.txt` sollte identisch sein
|
||||||
|
|
||||||
|
### 3. Unterschiedliche Embedding-Modelle
|
||||||
|
- Prüfen: `MINDNET_EMBEDDING_MODEL` in beiden Systemen
|
||||||
|
- **Beide verwenden**: `nomic-embed-text` ✅
|
||||||
|
|
||||||
|
### 4. Unterschiedliche Vektor-Dimensionen
|
||||||
|
- Prüfen: `VECTOR_DIM` in beiden Systemen
|
||||||
|
- **Beide verwenden**: `768` ✅
|
||||||
|
|
||||||
|
## Erwartetes Ergebnis nach Fix
|
||||||
|
|
||||||
|
- ✅ Keine Pydantic-Validierungsfehler mehr
|
||||||
|
- ✅ Alle Streams liefern Ergebnisse
|
||||||
|
- ✅ Retrieval funktioniert identisch in Dev und Prod
|
||||||
|
- ✅ `explicit:callout` Provenance wird korrekt akzeptiert
|
||||||
134
docs/03_Technical_References/PROD_PYTHON_CACHE_FIX.md
Normal file
134
docs/03_Technical_References/PROD_PYTHON_CACHE_FIX.md
Normal file
|
|
@ -0,0 +1,134 @@
|
||||||
|
# Fix: Python-Modul-Cache-Problem in Prod
|
||||||
|
|
||||||
|
**Datum**: 2026-01-12
|
||||||
|
**Version**: v4.5.10
|
||||||
|
**Status**: 🔴 Kritisch
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
|
||||||
|
Code in `app/models/dto.py` ist korrekt (enthält `explicit:callout`), aber Prod verwendet trotzdem eine alte Version.
|
||||||
|
|
||||||
|
**Symptom**:
|
||||||
|
```
|
||||||
|
ERROR: 1 validation error for EdgeDTO
|
||||||
|
provenance
|
||||||
|
Input should be 'explicit', 'rule', 'smart' or 'structure'
|
||||||
|
[type=literal_error, input_value='explicit:callout', input_type=str]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Ursache
|
||||||
|
|
||||||
|
**Python-Modul-Cache**: Python speichert kompilierte `.pyc` Dateien in `__pycache__` Verzeichnissen. Wenn der Code aktualisiert wird, aber der Service nicht neu gestartet wird, lädt Python die alte gecachte Version.
|
||||||
|
|
||||||
|
## Sofortmaßnahmen
|
||||||
|
|
||||||
|
### Schritt 1: Python-Cache leeren
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# In Prod-System
|
||||||
|
cd ~/mindnet
|
||||||
|
|
||||||
|
# Finde und lösche alle __pycache__ Verzeichnisse
|
||||||
|
find . -type d -name __pycache__ -exec rm -r {} + 2>/dev/null || true
|
||||||
|
|
||||||
|
# Finde und lösche alle .pyc Dateien
|
||||||
|
find . -name "*.pyc" -delete
|
||||||
|
|
||||||
|
# Speziell für dto.py
|
||||||
|
rm -rf app/models/__pycache__
|
||||||
|
rm -rf app/__pycache__
|
||||||
|
rm -rf __pycache__
|
||||||
|
```
|
||||||
|
|
||||||
|
### Schritt 2: Verifikation des Codes
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Prüfe, ob der Code korrekt ist
|
||||||
|
grep -A 10 "provenance.*Literal" app/models/dto.py | grep "explicit:callout"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Erwartete Ausgabe**: Sollte `explicit:callout` enthalten
|
||||||
|
|
||||||
|
### Schritt 3: Service neu starten
|
||||||
|
|
||||||
|
**Option A: FastAPI/uvicorn direkt**:
|
||||||
|
```bash
|
||||||
|
# Service stoppen (Ctrl+C oder kill)
|
||||||
|
# Dann neu starten
|
||||||
|
source .venv/bin/activate
|
||||||
|
uvicorn app.main:app --host 0.0.0.0 --port 8001 --reload
|
||||||
|
```
|
||||||
|
|
||||||
|
**Option B: Systemd-Service**:
|
||||||
|
```bash
|
||||||
|
sudo systemctl restart mindnet-prod
|
||||||
|
# oder
|
||||||
|
sudo systemctl restart mindnet
|
||||||
|
```
|
||||||
|
|
||||||
|
**Option C: Docker-Container**:
|
||||||
|
```bash
|
||||||
|
docker-compose restart mindnet
|
||||||
|
# oder
|
||||||
|
docker restart mindnet-container
|
||||||
|
```
|
||||||
|
|
||||||
|
### Schritt 4: Verifikation zur Laufzeit
|
||||||
|
|
||||||
|
**Test-Script ausführen** (wenn verfügbar):
|
||||||
|
```bash
|
||||||
|
python3 scripts/verify_dto_import.py
|
||||||
|
```
|
||||||
|
|
||||||
|
**Erwartete Ausgabe**:
|
||||||
|
```
|
||||||
|
✅ EdgeDTO unterstützt 'explicit:callout'
|
||||||
|
✅ 'explicit:callout' ist in der Literal-Liste enthalten
|
||||||
|
✅ EdgeDTO mit 'explicit:callout' erfolgreich erstellt!
|
||||||
|
```
|
||||||
|
|
||||||
|
**Oder manuell testen**:
|
||||||
|
```python
|
||||||
|
python3 -c "
|
||||||
|
from app.models.dto import EdgeDTO
|
||||||
|
test = EdgeDTO(
|
||||||
|
id='test', kind='test', source='test', target='test',
|
||||||
|
weight=1.0, provenance='explicit:callout'
|
||||||
|
)
|
||||||
|
print('✅ EdgeDTO mit explicit:callout funktioniert!')
|
||||||
|
"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Code-Fix (Fallback-Mechanismus)
|
||||||
|
|
||||||
|
Ein Fallback-Mechanismus wurde in `retriever.py` implementiert:
|
||||||
|
- Wenn `EdgeDTO` mit `explicit:callout` fehlschlägt, wird automatisch `explicit` als Fallback verwendet
|
||||||
|
- Dies verhindert, dass der gesamte Retrieval-Prozess fehlschlägt
|
||||||
|
- **WICHTIG**: Dies ist nur eine temporäre Lösung - der Cache muss trotzdem geleert werden!
|
||||||
|
|
||||||
|
## Verifikation nach Fix
|
||||||
|
|
||||||
|
1. **Test-Query ausführen**:
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:8001/api/chat \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"message": "Was für einen Status hat das Projekt mindnet?"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Log prüfen**:
|
||||||
|
- ✅ Keine `validation error for EdgeDTO` mehr
|
||||||
|
- ✅ Keine `⚠️ [EDGE-DTO] Provenance 'explicit:callout' nicht unterstützt` Warnungen
|
||||||
|
- ✅ `✨ [SUCCESS] Stream 'facts_stream' lieferte X Treffer.`
|
||||||
|
- ✅ Ergebnisse werden zurückgegeben
|
||||||
|
|
||||||
|
## Warum passiert das?
|
||||||
|
|
||||||
|
1. **Code wurde aktualisiert**, aber Service läuft noch mit alter Version im Speicher
|
||||||
|
2. **Python lädt Module nur einmal** - nach dem ersten Import wird die gecachte Version verwendet
|
||||||
|
3. **__pycache__ Verzeichnisse** enthalten kompilierte Bytecode-Versionen der alten Dateien
|
||||||
|
|
||||||
|
## Prävention
|
||||||
|
|
||||||
|
- **Immer Service neu starten** nach Code-Änderungen
|
||||||
|
- **Cache regelmäßig leeren** bei Deployment
|
||||||
|
- **Verwende `--reload` Flag** bei uvicorn für automatisches Neuladen (nur für Dev!)
|
||||||
69
scripts/verify_dto_import.py
Normal file
69
scripts/verify_dto_import.py
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Script zur Verifikation der EdgeDTO-Import-Version in Prod.
|
||||||
|
Prüft, ob die korrekte Version des EdgeDTO-Modells geladen wird.
|
||||||
|
"""
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Stelle sicher, dass der Projekt-Pfad im Python-Path ist
|
||||||
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
|
||||||
|
try:
|
||||||
|
from app.models.dto import EdgeDTO
|
||||||
|
import inspect
|
||||||
|
|
||||||
|
# Extrahiere die Literal-Definition aus dem Source-Code
|
||||||
|
source = inspect.getsource(EdgeDTO)
|
||||||
|
|
||||||
|
# Prüfe, ob explicit:callout in der Literal-Liste ist
|
||||||
|
if "explicit:callout" in source:
|
||||||
|
print("✅ EdgeDTO unterstützt 'explicit:callout'")
|
||||||
|
print(f" -> Modul-Pfad: {EdgeDTO.__module__}")
|
||||||
|
print(f" -> Datei: {inspect.getfile(EdgeDTO)}")
|
||||||
|
|
||||||
|
# Zeige die Provenance-Definition
|
||||||
|
import re
|
||||||
|
match = re.search(r'provenance.*?Literal\[(.*?)\]', source, re.DOTALL)
|
||||||
|
if match:
|
||||||
|
literal_values = match.group(1)
|
||||||
|
if "explicit:callout" in literal_values:
|
||||||
|
print("✅ 'explicit:callout' ist in der Literal-Liste enthalten")
|
||||||
|
print(f"\n Literal-Werte (erste 200 Zeichen):\n {literal_values[:200]}...")
|
||||||
|
else:
|
||||||
|
print("❌ 'explicit:callout' ist NICHT in der Literal-Liste!")
|
||||||
|
print(f"\n Gefundene Literal-Werte:\n {literal_values}")
|
||||||
|
else:
|
||||||
|
print("⚠️ Konnte Literal-Definition nicht finden")
|
||||||
|
else:
|
||||||
|
print("❌ EdgeDTO unterstützt NICHT 'explicit:callout'")
|
||||||
|
print(f" -> Modul-Pfad: {EdgeDTO.__module__}")
|
||||||
|
print(f" -> Datei: {inspect.getfile(EdgeDTO)}")
|
||||||
|
print("\n Source-Code (erste 500 Zeichen):")
|
||||||
|
print(f" {source[:500]}...")
|
||||||
|
|
||||||
|
# Test: Versuche ein EdgeDTO mit explicit:callout zu erstellen
|
||||||
|
print("\n🧪 Test: Erstelle EdgeDTO mit provenance='explicit:callout'...")
|
||||||
|
try:
|
||||||
|
test_edge = EdgeDTO(
|
||||||
|
id="test",
|
||||||
|
kind="test",
|
||||||
|
source="test",
|
||||||
|
target="test",
|
||||||
|
weight=1.0,
|
||||||
|
provenance="explicit:callout"
|
||||||
|
)
|
||||||
|
print("✅ EdgeDTO mit 'explicit:callout' erfolgreich erstellt!")
|
||||||
|
print(f" -> Provenance: {test_edge.provenance}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Fehler beim Erstellen: {e}")
|
||||||
|
print(f" -> Typ: {type(e).__name__}")
|
||||||
|
|
||||||
|
except ImportError as e:
|
||||||
|
print(f"❌ Import-Fehler: {e}")
|
||||||
|
sys.exit(1)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Unerwarteter Fehler: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
sys.exit(1)
|
||||||
114
scripts/verify_env_loading.py
Normal file
114
scripts/verify_env_loading.py
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Script zur Verifikation des .env-Ladens in Prod.
|
||||||
|
Prüft, ob die .env-Datei korrekt geladen wird und welche Werte tatsächlich verwendet werden.
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Stelle sicher, dass der Projekt-Pfad im Python-Path ist
|
||||||
|
project_root = Path(__file__).parent.parent
|
||||||
|
sys.path.insert(0, str(project_root))
|
||||||
|
|
||||||
|
print("=" * 80)
|
||||||
|
print("🔍 .env-Lade-Verifikation")
|
||||||
|
print("=" * 80)
|
||||||
|
|
||||||
|
# 1. Prüfe, ob .env-Datei existiert
|
||||||
|
env_files = [
|
||||||
|
project_root / ".env",
|
||||||
|
project_root / "prod.env",
|
||||||
|
project_root / "config" / "prod.env",
|
||||||
|
Path.cwd() / ".env",
|
||||||
|
Path.cwd() / "prod.env",
|
||||||
|
]
|
||||||
|
|
||||||
|
print("\n1. Suche nach .env-Dateien:")
|
||||||
|
found_env = None
|
||||||
|
for env_file in env_files:
|
||||||
|
if env_file.exists():
|
||||||
|
print(f" ✅ Gefunden: {env_file}")
|
||||||
|
if found_env is None:
|
||||||
|
found_env = env_file
|
||||||
|
else:
|
||||||
|
print(f" ❌ Nicht gefunden: {env_file}")
|
||||||
|
|
||||||
|
if not found_env:
|
||||||
|
print("\n ⚠️ WARNUNG: Keine .env-Datei gefunden!")
|
||||||
|
print(" -> load_dotenv() wird Standard-Werte verwenden")
|
||||||
|
|
||||||
|
# 2. Lade .env manuell
|
||||||
|
print("\n2. Lade .env-Datei:")
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
if found_env:
|
||||||
|
result = load_dotenv(found_env, override=True)
|
||||||
|
print(f" ✅ load_dotenv('{found_env}') = {result}")
|
||||||
|
else:
|
||||||
|
result = load_dotenv(override=True)
|
||||||
|
print(f" ⚠️ load_dotenv() ohne expliziten Pfad = {result}")
|
||||||
|
print(" -> Sucht automatisch nach .env im aktuellen Verzeichnis")
|
||||||
|
|
||||||
|
# 3. Prüfe kritische Umgebungsvariablen
|
||||||
|
print("\n3. Kritische Umgebungsvariablen:")
|
||||||
|
critical_vars = [
|
||||||
|
"COLLECTION_PREFIX",
|
||||||
|
"MINDNET_PREFIX",
|
||||||
|
"DEBUG",
|
||||||
|
"VECTOR_DIM",
|
||||||
|
"MINDNET_EMBEDDING_MODEL",
|
||||||
|
"QDRANT_URL",
|
||||||
|
]
|
||||||
|
|
||||||
|
for var in critical_vars:
|
||||||
|
value = os.getenv(var, "NICHT GESETZT")
|
||||||
|
source = "Umgebung" if var in os.environ else "Default/Code"
|
||||||
|
print(f" {var:30} = {value:40} ({source})")
|
||||||
|
|
||||||
|
# 4. Prüfe, welche .env-Datei tatsächlich geladen wurde
|
||||||
|
print("\n4. Verifikation der geladenen Werte:")
|
||||||
|
print(f" Arbeitsverzeichnis: {Path.cwd()}")
|
||||||
|
print(f" Projekt-Root: {project_root}")
|
||||||
|
print(f" Python-Pfad[0]: {sys.path[0] if sys.path else 'N/A'}")
|
||||||
|
|
||||||
|
# 5. Test: Importiere Settings
|
||||||
|
print("\n5. Test: Importiere Settings aus app.config:")
|
||||||
|
try:
|
||||||
|
from app.config import get_settings
|
||||||
|
settings = get_settings()
|
||||||
|
print(f" ✅ Settings erfolgreich geladen")
|
||||||
|
print(f" -> COLLECTION_PREFIX: {settings.COLLECTION_PREFIX}")
|
||||||
|
print(f" -> VECTOR_SIZE: {settings.VECTOR_SIZE}")
|
||||||
|
print(f" -> EMBEDDING_MODEL: {settings.EMBEDDING_MODEL}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f" ❌ Fehler beim Laden der Settings: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
# 6. Test: Prüfe EdgeDTO
|
||||||
|
print("\n6. Test: Prüfe EdgeDTO-Import:")
|
||||||
|
try:
|
||||||
|
from app.models.dto import EdgeDTO
|
||||||
|
import inspect
|
||||||
|
|
||||||
|
source = inspect.getsource(EdgeDTO)
|
||||||
|
if "explicit:callout" in source:
|
||||||
|
print(" ✅ EdgeDTO unterstützt 'explicit:callout'")
|
||||||
|
print(f" -> Modul-Pfad: {EdgeDTO.__module__}")
|
||||||
|
print(f" -> Datei: {inspect.getfile(EdgeDTO)}")
|
||||||
|
else:
|
||||||
|
print(" ❌ EdgeDTO unterstützt NICHT 'explicit:callout'")
|
||||||
|
|
||||||
|
# Test-Erstellung
|
||||||
|
test_edge = EdgeDTO(
|
||||||
|
id="test", kind="test", source="test", target="test",
|
||||||
|
weight=1.0, provenance="explicit:callout"
|
||||||
|
)
|
||||||
|
print(" ✅ EdgeDTO mit 'explicit:callout' erfolgreich erstellt!")
|
||||||
|
except Exception as e:
|
||||||
|
print(f" ❌ Fehler: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
print("\n" + "=" * 80)
|
||||||
Loading…
Reference in New Issue
Block a user