Enhancement: Refined Phase 1 prompt for less granular features & updated migration guide with troubleshooting tips

This commit is contained in:
2026-01-03 12:49:57 +00:00
parent 0b94a7d5e9
commit d29f9f4d1b
2 changed files with 103 additions and 90 deletions

View File

@@ -1,21 +1,21 @@
# Migration Guide: Google AI Builder Apps -> Local Docker Stack
> **WICHTIGER HINWEIS:** Der Gemini-Agent führt Code **innerhalb** dieses Docker-Containers aus. Er hat keinen Zugriff auf den Docker-Daemon des Host-Systems. Daher kann und wird der Agent **NIEMALS** in der Lage sein, Befehle wie `docker build`, `docker-compose up` oder andere Docker-Management-Aufgaben auszuführen. Diese Befehle müssen immer vom Benutzer auf dem Host-System ausgeführt werden.
> **WICHTIGER HINWEIS:** Der Gemini-Agent f"."hrt Code **innerhalb** dieses Docker-Containers aus. Er hat keinen Zugriff auf den Docker-Daemon des Host-Systems. Daher kann und wird der Agent **NIEMALS** in der Lage sein, Befehle wie `docker build`, `docker-compose up` oder andere Docker-Management-Aufgaben auszuf.hren. Diese Befehle m.ssen immer vom Benutzer auf dem Host-System ausgef.hrt werden.
**Ziel:** Standardisierter Prozess, um eine von Google AI Studio generierte React-App schnell, robust und fehlerfrei in die lokale Docker/Python-Architektur zu integrieren.
**Grundsatz:** "Minimalset & Robustheit". Wir bauen keine aufgeblähten Container, und wir verhindern Timeouts und fehlende Abhängigkeiten proaktiv.
**Grundsatz:** "Minimalset & Robustheit". Wir bauen keine aufgebl.hten Container, und wir verhindern Timeouts und fehlende Abh.ngigkeiten proaktiv.
---
## 1. Vorbereitung & Abhängigkeiten (Common Pitfalls)
## 1. Vorbereitung & Abh.ngigkeiten (Common Pitfalls)
Bevor Code kopiert wird, müssen die Grundlagen stimmen.
Bevor Code kopiert wird, m.ssen die Grundlagen stimmen.
### 1.1 Package.json Check
Generierte Apps haben oft kein `express`, da sie keinen Server erwarten.
* **Aktion:** Öffne `package.json` der App.
* **Prüfung:** Steht `express` unter `dependencies`?
* **Aktion:** "."ffne `package.json` der App.
* **Pr.fung:** Steht `express` unter `dependencies`?
* **Fix:**
```json
"dependencies": {
@@ -34,22 +34,22 @@ Docker kann keine einzelne Datei mounten, wenn sie auf dem Host nicht existiert.
```
### 1.3 Vite Base Path (White Screen Fix)
Wenn die App unter einem Unterverzeichnis (z.B. `/gtm/`) läuft, findet sie ihre JS/CSS-Dateien nicht, wenn Vite Standard-Pfade (`/`) nutzt.
Wenn die App unter einem Unterverzeichnis (z.B. `/gtm/`) l.uft, findet sie ihre JS/CSS-Dateien nicht, wenn Vite Standard-Pfade (`/`) nutzt.
* **Datei:** `vite.config.ts`
* **Fix:** `base` auf `./` setzen.
```typescript
export default defineConfig({
base: './', // WICHTIG für Sub-Pfad Deployment
base: './', // WICHTIG f.r Sub-Pfad Deployment
// ...
});
```
### 1.4 Python Dependencies & Shared Libraries (Critical Pitfall)
Das Projekt nutzt ein zentrales `helpers.py`, das von mehreren Services geteilt wird. Dies führt oft zu `ModuleNotFoundError`, da eine kleine App (wie `gtm-architect`) nicht alle Bibliotheken benötigt, die in `helpers.py` importiert werden (z.B. `gspread`, `pandas`).
Das Projekt nutzt ein zentrales `helpers.py`, das von mehreren Services geteilt wird. Dies f.hrt oft zu `ModuleNotFoundError`, da eine kleine App (wie `gtm-architect`) nicht alle Bibliotheken ben.tigt, die in `helpers.py` importiert werden (z.B. `gspread`, `pandas`).
* **Fehler:** `ModuleNotFoundError: No module named 'gspread'`
* **Ursache:** Die `gtm-architect/requirements.txt` enthält `gspread` nicht, aber `helpers.py` versucht es zu importieren.
* **Fix (in `helpers.py`):** Machen Sie "exotische" Importe optional. Dies ist die robusteste Methode, um die Kompatibilität zu wahren, ohne die `requirements.txt` kleiner Apps aufzublähen.
* **Ursache:** Die `gtm-architect/requirements.txt` enth.lt `gspread` nicht, aber `helpers.py` versucht es zu importieren.
* **Fix (in `helpers.py`):** Machen Sie "exotische" Importe optional. Dies ist die robusteste Methode, um die Kompatibilit.t zu wahren, ohne die `requirements.txt` kleiner Apps aufzubl.hen.
```python
# Beispiel in helpers.py
@@ -60,20 +60,20 @@ Das Projekt nutzt ein zentrales `helpers.py`, das von mehreren Services geteilt
GSPREAD_AVAILABLE = False
gspread = None # Wichtig, damit Referenzen nicht fehlschlagen
```
* **Fix (in `requirements.txt`):** Stellen Sie sicher, dass die für die App **unmittelbar** benötigten Bibliotheken vorhanden sind. Für `gtm-architect` sind das:
* **Fix (in `requirements.txt`):** Stellen Sie sicher, dass die f.r die App **unmittelbar** ben.tigten Bibliotheken vorhanden sind. F.r `gtm-architect` sind das:
```text
google-generativeai
requests
beautifulsoup4
```
google-generativeai
requests
beautifulsoup4
```
### 1.5 Python Syntax & F-Strings
Multi-Line Prompts können in Docker-Umgebungen zu **sehr hartnäckigen Syntaxfehlern** führen, selbst wenn sie lokal korrekt aussehen.
Multi-Line Prompts k.nnen in Docker-Umgebungen zu **sehr hartn.ckigen Syntaxfehlern** f.hren, selbst wenn sie lokal korrekt aussehen.
* **Das Problem:** Der Python-Parser (insbesondere bei `f-strings` in Kombination mit Zahlen/Punkten am Zeilenanfang oder verschachtelten Klammern) kann Multi-Line-Strings (`f"""..."""`) falsch interpretieren, was zu Fehlern wie `SyntaxError: invalid decimal literal` oder `unmatched ')'` führt, auch wenn der Code scheinbar korrekt ist.
* **Das Problem:** Der Python-Parser (insbesondere bei `f-strings` in Kombination mit Zahlen/Punkten am Zeilenanfang oder verschachtelten Klammern) kann Multi-Line-Strings (`f"""..."""`) falsch interpretieren, was zu Fehlern wie `SyntaxError: invalid decimal literal` oder `unmatched ')'` f.hrt, auch wenn der Code scheinbar korrekt ist.
* **ULTIMATIVE LÖSUNG (Maximale Robustheit):**
1. **Vermeide `f"""` komplett für komplexe Multi-Line-Prompts.** Definiere stattdessen den Prompt als **Liste von einzelnen String-Zeilen** und füge sie mit `"\n".join(prompt_parts)` zusammen.
* **ULTIMATIVE L.SUNG (Maximale Robustheit):**
1. **Vermeide `f"""` komplett f.r komplexe Multi-Line-Prompts.** Definiere stattdessen den Prompt als **Liste von einzelnen String-Zeilen** und f.ge sie mit `"\n".join(prompt_parts)` zusammen.
2. **Nutze die `.format()` Methode oder f-Strings in EINZEILIGEN Strings** zur Variablen-Injektion. Dies trennt die String-Definition komplett von der Variablen-Interpolation und ist die robusteste Methode.
```python
@@ -88,23 +88,23 @@ Multi-Line Prompts können in Docker-Umgebungen zu **sehr hartnäckigen Syntaxfe
full_prompt = sys_instr + "\n\n" + prompt
```
* **Versionierung für Debugging:** Um sicherzustellen, dass die korrekte Version des Codes läuft, füge Versionsnummern in die Start-Logs des Node.js Servers (`server.cjs`) und des Python Orchestrators (`gtm_architect_orchestrator.py`) ein.
* **Versionierung f.r Debugging:** Um sicherzustellen, dass die korrekte Version des Codes l.uft, f.ge Versionsnummern in die Start-Logs des Node.js Servers (`server.cjs`) und des Python Orchestrators (`gtm_architect_orchestrator.py`) ein.
* `server.cjs`: `console.log(`... (Version: ${VERSION})`);`
* `gtm_architect_orchestrator.py`: `print(f"DEBUG: Orchestrator v{__version__} loaded ...")`
* **Signaturen prüfen:** Shared Libraries (`helpers.py`) haben oft ältere Signaturen. Immer die tatsächliche Definition prüfen!
* Beispiel: `call_openai_chat` unterstützt oft kein `system_message` Argument. Stattdessen Prompt manuell zusammenbauen (`sys_instr + "\n\n" + prompt`).
* **Signaturen pr.fen:** Shared Libraries (`helpers.py`) haben oft .ltere Signaturen. Immer die tats.chliche Definition pr.fen!
* Beispiel: `call_openai_chat` unterst.tzt oft kein `system_message` Argument. Stattdessen Prompt manuell zusammenbauen (`sys_instr + "\n\n" + prompt`).
### 1.6 Pitfall: Veraltete API-Nutzung & Bibliotheksnamen
**ACHTUNG:** Dies ist eine der häufigsten Fehlerquellen bei der Migration älterer KI-Skripte.
**ACHTUNG:** Dies ist eine der h.ufigsten Fehlerquellen bei der Migration .ltterer KI-Skripte.
* **Das Problem 1 (Name):** Der Name des Pakets (`google-generativeai`) stimmt nicht mit dem Import (`import google.genai`) überein, den neuere Versionen erwarten. In unserem Fall bleiben wir vorerst beim Import von `google.generativeai`.
* **Das Problem 1 (Name):** Der Name des Pakets (`google-generativeai`) stimmt nicht mit dem Import (`import google.genai`) .berein, den neuere Versionen erwarten. In unserem Fall bleiben wir vorerst beim Import von `google.generativeai`.
* **Installation (`requirements.txt`):** `google-generativeai`
* **Import (z.B. in `helpers.py`):** `import google.generativeai as genai`
* **Das Problem 2 (API-Nutzung):** Älterer Code verwendet eine `genai.Client`-Klasse, die **nicht mehr existiert**. Dies führt zu einem Absturz.
* **Das Problem 2 (API-Nutzung):** "."lterer Code verwendet eine `genai.Client`-Klasse, die **nicht mehr existiert**. Dies f.hrt zu einem Absturz.
* **Fehlerbild im Log:** `AttributeError: module 'google.generativeai' has no attribute 'Client'`
* **Lösung:** Der Code MUSS auf die moderne `GenerativeModel`-API umgestellt werden. Siehe **Appendix A.4** für ein Code-Beispiel.
* **L.sung:** Der Code MUSS auf die moderne `GenerativeModel`-API umgestellt werden. Siehe **Appendix A.4** f.r ein Code-Beispiel.
---
@@ -124,14 +124,14 @@ const port = 3005; // ANPASSEN!
app.use(express.json({ limit: '50mb' }));
// 1. Statische Dateien: Robustheit für Docker (Flat) vs. Local (Nested)
// 1. Statische Dateien: Robustheit f.r Docker (Flat) vs. Local (Nested)
const distPath = path.join(__dirname, 'dist'); // Docker Standard
const isProduction = fs.existsSync(distPath);
const staticDir = isProduction ? distPath : __dirname;
console.log(`[Init] Serving static files from: ${staticDir}`);
app.use(express.static(staticDir));
// 2. Python Pfad: Robustheit für Sideloading
// 2. Python Pfad: Robustheit f.r Sideloading
let pythonScriptPath = path.join(__dirname, 'mein_orchestrator.py'); // ANPASSEN!
if (!fs.existsSync(pythonScriptPath)) {
pythonScriptPath = path.join(__dirname, '../mein_orchestrator.py');
@@ -147,7 +147,7 @@ app.get('*', (req, res) => {
res.sendFile(path.join(staticDir, 'index.html'));
});
// 5. Timeout-Härtung (CRITICAL!)
// 5. Timeout-H.rtung (CRITICAL!)
const server = app.listen(port, () => {
console.log(`Server listening on ${port}`);
});
@@ -177,7 +177,7 @@ RUN npm run build
FROM python:3.11-slim
WORKDIR /app
# Node.js installieren (für Server Bridge, optimierte Methode)
# Node.js installieren (f.r Server Bridge, optimierte Methode)
RUN apt-get update && \
apt-get install -y --no-install-recommends curl ca-certificates && \
curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \
@@ -196,7 +196,7 @@ COPY --from=frontend-builder /app/dist ./dist
# Python Logic & Shared Libs
COPY mein_orchestrator.py .
COPY helpers.py .
COPY helpers.py .
COPY config.py .
COPY market_db_manager.py .
@@ -208,18 +208,18 @@ CMD ["node", "server.cjs"]
## 4. Docker Compose & Mounts (WICHTIGER PITFALL)
**WARNUNG: Lokale Dateien überschreiben den Container-Code!**
**WARNUNG: Lokale Dateien .berschreiben den Container-Code!**
Wenn Sie `volumes` für das Sideloading verwenden (wie unten gezeigt), werden die Dateien aus Ihrem lokalen Verzeichnis direkt in den Container geladen. Das bedeutet: **Wenn Sie nicht `git pull` auf dem Host-System ausführen, bevor Sie den Container neu bauen, wird der Container weiterhin den alten, lokalen Code ausführen.**
Wenn Sie `volumes` f.r das Sideloading verwenden (wie unten gezeigt), werden die Dateien aus Ihrem lokalen Verzeichnis direkt in den Container geladen. Das bedeutet: **Wenn Sie nicht `git pull` auf dem Host-System ausf.hren, bevor Sie den Container neu bauen, wird der Container weiterhin den alten, lokalen Code ausf.hren.**
**Workflow:**
1. Änderungen im Git-Repository pushen (oder von einem Agent pushen lassen).
2. **`git pull` auf dem Host-System ausführen.** (Dieser Schritt ist entscheidend!)
3. `docker-compose up -d --build <service-name>` ausführen.
1. "."nderungen im Git-Repository pushen (oder von einem Agent pushen lassen).
2. **`git pull` auf dem Host-System ausf.hren.** (Dieser Schritt ist entscheidend!)
3. `docker-compose up -d --build <service-name>` ausf.hren.
Beim Sideloading müssen **alle** Abhängigkeiten gemountet werden, nicht nur das Hauptskript.
Beim Sideloading m.ssen **alle** Abh.ngigkeiten gemountet werden, nicht nur das Hauptskript.
**Wichtig:** Der Pfad zu `server.cjs` ändert sich durch die "Flat Structure" im Dockerfile!
**Wichtig:** Der Pfad zu `server.cjs` .ndert sich durch die "Flat Structure" im Dockerfile!
```yaml
my-new-app:
@@ -239,6 +239,9 @@ Beim Sideloading müssen **alle** Abhängigkeiten gemountet werden, nicht nur da
environment:
- PYTHONUNBUFFERED=1
- DB_PATH=/app/mein_projekt.db
environment:
- PYTHONUNBUFFERED=1
- DB_PATH=/app/mein_projekt.db
```
---
@@ -265,11 +268,12 @@ Achtung beim Routing. Wenn die App unter `/app/` laufen soll, muss der Trailing
---
## Checkliste vor dem Commit
- [ ] `express` in `package.json`?
- [ ] `vite.config.ts` hat `base: './'`?
- [ ] `requirements.txt` enthält die korrekten (minimalen) Dependencies?
- [ ] `requirements.txt` enth.lt die korrekten (minimalen) Dependencies?
- [ ] `server.cjs` hat Timeouts (>600s)?
- [ ] `docker-compose.yml` mountet auch `helpers.py` und `config.py`?
- [ ] Leere `.db` Datei auf dem Host erstellt?
@@ -277,93 +281,69 @@ Achtung beim Routing. Wenn die App unter `/app/` laufen soll, muss der Trailing
---
## Appendix A: GTM Architect Fixes & Gemini Migration (Jan 2026)
### A.1 Problemstellung
- **SyntaxError bei großen Prompts:** Python-Parser (3.11) hatte massive Probleme mit f-Strings, die 100+ Zeilen lang waren und Sonderzeichen enthielten.
- **SyntaxError bei gro.en Prompts:** Python-Parser (3.11) hatte massive Probleme mit f-Strings, die 100+ Zeilen lang waren und Sonderzeichen enthielten.
- **Library Deprecation:** `google.generativeai` hat Support eingestellt? Nein, aber die Fehlermeldung im Log deutete auf einen Konflikt zwischen alten `openai`-Wrappern und neuen Gemini-Paketen hin.
- **Lösung:**
- **L.sung:**
1. **Prompts ausgelagert:** System-Prompts liegen jetzt in `gtm_prompts.json` und werden zur Laufzeit geladen. Kein Code-Parsing mehr notwendig.
2. **Native Gemini Lib:** Statt OpenAI-Wrapper nutzen wir jetzt `google.generativeai` direkt via `helpers.call_gemini_flash`.
3. **Config:** `gtm-architect/Dockerfile` kopiert nun explizit `gtm_prompts.json`.
### A.2 Neuer Standard für KI-Apps
Für zukünftige Apps gilt:
### A.2 Neuer Standard f.r KI-Apps
F.r zuk.nftige Apps gilt:
1. **Prompts in JSON/Text-Files:** Niemals riesige Strings im Python-Code hardcoden.
2. **`helpers.call_gemini_flash` nutzen:** Diese Funktion ist nun der Gold-Standard für einfache, stateless Calls. Siehe **Appendix A.4** für die korrekte Implementierung.
2. **`helpers.call_gemini_flash` nutzen:** Diese Funktion ist nun der Gold-Standard f.r einfache, stateless Calls. Siehe **Appendix A.4** f.r die korrekte Implementierung.
3. **JSON im Dockerfile:** Vergesst nicht, die externen Prompt-Files mit `COPY` in den Container zu holen!
### A.3 Kritisches Problem & Lösung: `AttributeError` bei Gemini API (Jan 2026)
### A.3 Kritisches Problem & L.sung: `AttributeError` bei Gemini API (Jan 2026)
- **Problem:** Nach der Migration auf die `google-generativeai` Bibliothek schlugen alle API-Aufrufe mit einem `AttributeError: module 'google.generativeai' has no attribute 'Client'` Fehler fehl.
- **Log-Analyse:**
```
ERROR:helpers:Fehler beim Gemini-Flash-Aufruf: module 'google.generativeai' has no attribute 'Client'
```
- **Untersuchung:**
1. Die erste Annahme, es handle sich um einen falschen Modellnamen (`404 NOT_FOUND`), erwies sich als irreführend.
1. Die erste Annahme, es handle sich um einen falschen Modellnamen (`404 NOT_FOUND`), erwies sich als irref.hrend.
2. Die Analyse des `helpers.py`-Skripts zeigte, dass der Code versuchte, eine `genai.Client`-Klasse zu verwenden.
- **Schlussfolgerung & Lösung:**
- **Schlussfolgerung & L.sung:**
Der Fehler lag in der Verwendung einer **veralteten API-Initialisierungsmethode**. Die `google-generativeai`-Bibliothek hat die `Client`-Klasse entfernt und erfordert nun einen modernen Ansatz.
**Die Korrektur (implementiert in `helpers.py`):**
1. **Konfigurieren des API-Schlüssels:** `genai.configure(api_key="IHR_KEY")`
1. **Konfigurieren des API-Schl.ssels:** `genai.configure(api_key="IHR_KEY")`
2. **Instanziieren des Modells:** `model = genai.GenerativeModel('gemini-1.5-flash-latest')`
3. **Aufrufen der Generierung:** `response = model.generate_content(...)`
Dieser Fix wurde in `helpers.py` umgesetzt und hat die Funktionalität des GTM Architect wiederhergestellt. Alle neuen KI-Anwendungen müssen diesem Muster folgen.
Dieser Fix wurde in `helpers.py` umgesetzt und hat die Funktionalit.t des GTM Architect wiederhergestellt. Alle neuen KI-Anwendungen m.ssen diesem Muster folgen.
### A.4 Gold-Standard: Gemini API Wrapper (Robust & Dynamic)
Um 404-Fehler durch sich ändernde Modellnamen oder regionale Unterschiede zu vermeiden, nutzt der neue Standard eine **dynamische Modell-Ermittlung**.
Um die korrekte Implementierung zu standardisieren, hier der "Gold-Standard" Wrapper, wie er in `helpers.py` verwendet wird. Dieser Code ist die Vorlage f.r alle zuk.nftigen Gemini-Aufrufe.
```python
import google.generativeai as genai
import logging
# Cache für den Modellnamen
_CACHED_MODEL_NAME = None
def _get_best_flash_model(api_key):
"""
Ermittelt dynamisch das beste verfügbare Flash-Modell via list_models().
"""
global _CACHED_MODEL_NAME
if _CACHED_MODEL_NAME:
return _CACHED_MODEL_NAME
default_model = "gemini-1.5-flash"
try:
genai.configure(api_key=api_key)
# Suche nach Modellen mit 'flash' und 'generateContent' Support
models = list(genai.list_models())
flash_models = [
m.name.replace('models/', '')
for m in models
if 'flash' in m.name.lower() and 'generateContent' in m.supported_generation_methods
]
# Priorisierung
if "gemini-1.5-flash" in flash_models:
_CACHED_MODEL_NAME = "gemini-1.5-flash"
elif flash_models:
_CACHED_MODEL_NAME = flash_models[0]
else:
_CACHED_MODEL_NAME = default_model
return _CACHED_MODEL_NAME
except Exception:
return default_model
# Annahme: logger und _get_gemini_api_key() sind definiert
# Annahme: Ein @retry_on_failure Decorator existiert
@retry_on_failure
def call_gemini_flash(prompt, system_instruction=None, temperature=0.3, json_mode=False):
"""
Robuster Wrapper mit dynamischer Modellwahl.
Spezifische Funktion f.r Gemini 1.5 Flash Aufrufe mit System-Instruction Support.
Verwendet die korrekte `GenerativeModel` API.
"""
logger = logging.getLogger(__name__)
# HAS_GEMINI Check hier weggelassen f.r die Lesbarkeit
api_key = _get_gemini_api_key()
try:
# 1. API-Schl.ssel konfigurieren
genai.configure(api_key=api_key)
# 2. Generierungs-Konfiguration definieren
generation_config = {
"temperature": temperature,
"top_p": 0.95,
@@ -373,21 +353,51 @@ def call_gemini_flash(prompt, system_instruction=None, temperature=0.3, json_mod
if json_mode:
generation_config["response_mime_type"] = "application/json"
# Dynamisch das richtige Modell wählen
model_name = _get_best_flash_model(api_key)
# 3. Modell instanziieren (mit System-Instruktion)
model = genai.GenerativeModel(
model_name=model_name,
model_name="gemini-1.5-flash-latest", # Eine stabile, spezifische Version verwenden
generation_config=generation_config,
system_instruction=system_instruction
)
# Der Prompt kann ein String oder eine Liste von Teilen sein
contents = [prompt] if isinstance(prompt, str) else prompt
# 4. Inhalt generieren
response = model.generate_content(contents)
return response.text.strip()
except Exception as e:
logger.error(f"Fehler beim Gemini-Flash-Aufruf: {e}")
if "API_KEY_INVALID" in str(e) or "403" in str(e):
raise ValueError(f"Invalid API Key: {str(e)}")
raise e
```
---
## 7. Troubleshooting & Lessons Learned (Jan 2026)
Diese Fehler traten bei der GTM Architect Migration auf und m.ssen zuk.nftig vermieden werden.
### 7.1 Database Initialization (`OperationalError: no such table`)
* **Problem:** Neue SQLite-Datenbanken (`.db` Files) werden zwar als leere Dateien via `touch` erstellt, enthalten aber keine Tabellen. Der Python-Code st.rzt ab, wenn er versucht, in eine nicht existierende Tabelle zu schreiben.
* **L.sung:** Die Initialisierungs-Logik (z.B. `python gtm_db_manager.py init`) MUSS beim Start des `server.cjs` aufgerufen werden. Verlasse dich nicht darauf, dass der User dies manuell tut.
* **Best Practice:** In `server.cjs`:
```javascript
const dbScript = path.join(__dirname, 'gtm_db_manager.py');
require('child_process').spawn('python3', [dbScript, 'init']);
```
### 7.2 Dependency Injection (`ModuleNotFoundError`)
* **Problem:** Wenn eine `requirements.txt` nachtr.glich hinzugef.gt oder ge.ndert wird, reicht ein einfacher Container-Neustart nicht aus. `pip install` l.uft normalerweise nur w.hrend der Build-Phase.
* **L.sung:**
1. **Immer Rebuild:** `docker-compose up -d --build <service>`.
2. **Startup-Check:** F.r maximale Robustheit kann der `CMD` im Dockerfile so angepasst werden, dass er `pip install` vor dem Server-Start ausf.hrt: `CMD ["/bin/bash", "-c", "pip install -r requirements.txt && node server.cjs"]`.
### 7.3 Python Indentation (`IndentationError`)
* **Problem:** Beim Copy-Paste von Code in `config.py` entstehen oft versehentliche Einr.ckungen (Leerzeichen am Zeilenanfang) bei globalen Variablen. Dies f.hrt dazu, dass der gesamte Python-Prozess beim Import abst.rzt.
* **L.sung:** `.py` Dateien immer auf strikte Linksb.ndigkeit bei globalen Definitionen pr.fen. Tools wie `flake8` helfen, sind aber im Container oft nicht verf.gbar. Sorgfalt ist entscheidend.
```

View File

@@ -99,7 +99,10 @@ def phase1(payload):
prompt = f"""
PHASE 1: PRODUCT ANALYSIS & CONSTRAINTS
Input: "{analysis_content}"
Task: 1. Extract technical features. 2. Define hard constraints. 3. Check for internal portfolio conflicts (hypothetical product "Scrubber 5000").
Task:
1. Extract and CONSOLIDATE technical features into 8-12 high-level core capabilities or value propositions. Group minor specs (e.g., specific ports like USB/Ethernet) into broader categories (e.g., "Connectivity & Integration"). Do NOT list every single hardware spec individually. Focus on what matters for the buyer.
2. Define hard constraints (e.g., physical dimensions, max payload, environment limitations).
3. Check for internal portfolio conflicts (hypothetical product "Scrubber 5000").
Output JSON format ONLY: {{"features": [], "constraints": [], "conflictCheck": {{"hasConflict": false, "details": "", "relatedProduct": ""}}, "rawAnalysis": ""}}
"""
log_and_save(project_id, "phase1", "prompt", prompt)