Fix: Resolved [object Object] report bug, enforced German output language across all phases, and documented troubleshooting steps

This commit is contained in:
2026-01-03 13:01:32 +00:00
parent d29f9f4d1b
commit 69297d990b
2 changed files with 58 additions and 7 deletions

View File

@@ -298,9 +298,9 @@ const App: React.FC = () => {
};
const generateFullReportMarkdown = (): string => {
if (!state.phase5Result) return "";
if (!state.phase5Result || !state.phase5Result.report) return "";
let fullReport = state.phase5Result;
let fullReport = state.phase5Result.report;
if (state.phase6Result) {
fullReport += `\n\n# SALES ENABLEMENT & VISUALS (PHASE 6)\n\n`;

View File

@@ -1,4 +1,3 @@
import argparse
import base64
import json
@@ -21,7 +20,7 @@ LOG_DIR = "Log_from_docker"
if not os.path.exists(LOG_DIR):
os.makedirs(LOG_DIR)
ORCHESTRATOR_VERSION = "1.1.0"
ORCHESTRATOR_VERSION = "1.2.0" # Bump version for language fix
run_timestamp = datetime.now().strftime("%y-%m-%d_%H-%M-%S")
log_file_path = os.path.join(LOG_DIR, f"{run_timestamp}_gtm_orchestrator_run.log")
@@ -33,11 +32,12 @@ logging.basicConfig(
logging.StreamHandler(sys.stdout)
]
)
logging.info(f"GTM Architect Orchestrator v{{ORCHESTRATOR_VERSION}} ({{run_timestamp}}) starting...")
logging.info(f"GTM Architect Orchestrator v{ORCHESTRATOR_VERSION} ({run_timestamp}) starting...")
# !!! CRITICAL FIX: Load API keys at the very beginning !!!
# This ensures Config.API_KEYS is populated before any AI functions are called.
Config.load_api_keys()
def log_and_save(project_id, step_name, data_type, content):
logging.info(f"Project {project_id} - Step: {step_name} - Type: {data_type}")
filename = f"{run_timestamp}_{step_name}_{data_type}.txt"
@@ -63,6 +63,7 @@ def get_system_instruction(lang):
Führe eine interne Plausibilitätsprüfung durch, bevor du eine Antwort gibst.
Verwende "Wackler Symbiosis" als internes Framework für die Analyse von Produkt-Synergien.
Nutze das "Hybrid Service Logic" Konzept, um zu bewerten, ob ein Produkt mit einer Dienstleistung kombiniert werden muss (z.B. bei hohen Wartungsanforderungen).
WICHTIG: Antworte immer in der vom User geforderten Sprache (Deutsch), auch wenn der Input Englisch ist.
"""
else: # Default to English
return """
@@ -76,6 +77,12 @@ def get_system_instruction(lang):
Use the "Hybrid Service Logic" concept to evaluate if a product needs to be combined with a service (e.g., due to high maintenance requirements).
"""
def get_output_lang_instruction(lang):
"""Returns a strong instruction to enforce the output language."""
if lang == 'de':
return "ACHTUNG: Die gesamte Ausgabe (JSON-Werte, Texte, Analysen) MUSS in DEUTSCH sein. Übersetze englische Input-Daten."
return "IMPORTANT: The entire output MUST be in ENGLISH."
# --- ORCHESTRATOR PHASES ---
def phase1(payload):
@@ -96,6 +103,8 @@ def phase1(payload):
logging.info("Input is raw text. Analyzing directly.")
sys_instr = get_system_instruction(lang)
lang_instr = get_output_lang_instruction(lang)
prompt = f"""
PHASE 1: PRODUCT ANALYSIS & CONSTRAINTS
Input: "{analysis_content}"
@@ -103,6 +112,9 @@ def phase1(payload):
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").
{lang_instr}
Output JSON format ONLY: {{"features": [], "constraints": [], "conflictCheck": {{"hasConflict": false, "details": "", "relatedProduct": ""}}, "rawAnalysis": ""}}
"""
log_and_save(project_id, "phase1", "prompt", prompt)
@@ -115,7 +127,6 @@ def phase1(payload):
return data
except json.JSONDecodeError:
logging.error(f"Failed to decode JSON from Gemini response in phase1: {response}")
# Return a structured error that the frontend can display
error_response = {
"error": "Die Antwort des KI-Modells war kein gültiges JSON. Das passiert manchmal bei hoher Auslastung. Bitte versuchen Sie es in Kürze erneut.",
"details": response
@@ -129,10 +140,15 @@ def phase2(payload):
project_id = payload.get('projectId')
sys_instr = get_system_instruction(lang)
lang_instr = get_output_lang_instruction(lang)
prompt = f"""
PHASE 2: IDEAL CUSTOMER PROFILE (ICP) & DATA PROXIES
Product Context: {json.dumps(phase1_data)}
Task: 1. Identify top 3 ICPs (Ideal Customer Profiles/Industries). 2. Define data proxies for identifying these ICPs online.
{lang_instr}
Output JSON format ONLY: {{"icps": [{{"name": "", "rationale": ""}}], "dataProxies": [{{"target": "", "method": ""}}]}}
"""
log_and_save(project_id, "phase2", "prompt", prompt)
@@ -148,10 +164,15 @@ def phase3(payload):
project_id = payload.get('projectId')
sys_instr = get_system_instruction(lang)
lang_instr = get_output_lang_instruction(lang)
prompt = f"""
PHASE 3: WHALE HUNTING
Target ICPs (Industries): {json.dumps(phase2_data.get('icps'))}
Task: 1. Group 'Whales' (Key Accounts) strictly by ICP industries. 2. Identify 3-5 concrete top companies in DACH market per industry. 3. Define Buying Center Roles.
{lang_instr}
Output JSON format ONLY: {{"whales": [{{"industry": "", "accounts": []}}], "roles": []}}
"""
log_and_save(project_id, "phase3", "prompt", prompt)
@@ -168,6 +189,8 @@ def phase4(payload):
project_id = payload.get('projectId')
sys_instr = get_system_instruction(lang)
lang_instr = get_output_lang_instruction(lang)
all_accounts = []
for w in phase3_data.get('whales', []):
all_accounts.extend(w.get('accounts', []))
@@ -178,6 +201,9 @@ def phase4(payload):
Target Industries: {json.dumps([w.get('industry') for w in phase3_data.get('whales', [])])}
Product Features: {json.dumps(phase1_data.get('features'))}
Task: 1. Develop specific "Angle" per target/industry. 2. Consistency Check against Product Matrix. 3. **IMPORTANT:** Apply "Hybrid Service Logic" if constraints exist!
{lang_instr}
Output JSON format ONLY: {{"strategyMatrix": [{{"segment": "", "painPoint": "", "angle": "", "differentiation": ""}}]}}
"""
log_and_save(project_id, "phase4", "prompt", prompt)
@@ -196,6 +222,8 @@ def phase5(payload):
project_id = payload.get('projectId')
sys_instr = get_system_instruction(lang)
lang_instr = get_output_lang_instruction(lang)
prompt = f"""
PHASE 5: ASSET GENERATION & FINAL REPORT
CONTEXT DATA:
@@ -207,6 +235,9 @@ def phase5(payload):
1. Create a "GTM STRATEGY REPORT" in Markdown.
2. Report Structure: Executive Summary, Product Analysis, Target Audience, Target Accounts, Strategy Matrix, Assets.
3. Hybrid-Check: Ensure "Hybrid Service Logic" is visible.
{lang_instr}
Output: Return strictly MARKDOWN formatted text. Start with "# GTM STRATEGY REPORT".
"""
log_and_save(project_id, "phase5", "prompt", prompt)
@@ -223,10 +254,15 @@ def phase6(payload):
project_id = payload.get('projectId')
sys_instr = get_system_instruction(lang)
lang_instr = get_output_lang_instruction(lang)
prompt = f"""
PHASE 6: SALES ENABLEMENT & VISUALS
CONTEXT: - Product Features: {json.dumps(phase1_data.get('features'))} - Personas: {json.dumps(phase3_data.get('roles'))} - Strategy: {json.dumps(phase4_data.get('strategyMatrix'))}
TASK: 1. Anticipate Friction & Objections. 2. Formulate Battlecards. 3. Create Visual Prompts.
{lang_instr}
Output JSON format ONLY: {{"battlecards": [{{"persona": "", "objection": "", "responseScript": ""}}], "visualPrompts": [{{"title": "", "context": "", "prompt": ""}}]}}
"""
log_and_save(project_id, "phase6", "prompt", prompt)
@@ -243,11 +279,16 @@ def phase7(payload):
project_id = payload.get('projectId')
sys_instr = get_system_instruction(lang)
lang_instr = get_output_lang_instruction(lang)
prompt = f"""
PHASE 7: VERTICAL LANDING PAGE COPY (Conversion Optimization)
ICPs: {json.dumps(phase2_data.get('icps'))}
Strategy: {json.dumps(phase4_data.get('strategyMatrix'))}
TASK: 1. Transform generic features into specific benefits for the Top 2 ICPs. 2. Apply "Wackler Symbiosis". 3. Create Landing Page Drafts (Hero Section).
{lang_instr}
Output JSON format ONLY: {{"landingPages": [{{"industry": "", "headline": "", "subline": "", "bullets": [], "cta": ""}}]}}
"""
log_and_save(project_id, "phase7", "prompt", prompt)
@@ -264,10 +305,15 @@ def phase8(payload):
project_id = payload.get('projectId')
sys_instr = get_system_instruction(lang)
lang_instr = get_output_lang_instruction(lang)
prompt = f"""
PHASE 8: BUSINESS CASE BUILDER (The CFO Pitch)
Input: ICPs: {json.dumps(phase2_data.get('icps'))}, Features: {json.dumps(phase1_data.get('features'))}
TASK: 1. Estimate labor costs/pain points. 2. Compare against Robot Leasing (approx 330-600€/month). 3. Develop ROI logic. 4. Create "Financial Argumentation Guide" for each ICP.
{lang_instr}
Output JSON format ONLY: {{"businessCases": [{{"industry": "", "costDriver": "", "efficiencyGain": "", "riskArgument": ""}}]}}
"""
log_and_save(project_id, "phase8", "prompt", prompt)
@@ -284,11 +330,16 @@ def phase9(payload):
project_id = payload.get('projectId')
sys_instr = get_system_instruction(lang)
lang_instr = get_output_lang_instruction(lang)
prompt = f"""
PHASE 9: THE "FEATURE-TO-VALUE" TRANSLATOR
Input Features: {json.dumps(phase1_data.get('features'))}
Strategy Pains: {json.dumps([s.get('painPoint') for s in phase4_data.get('strategyMatrix', [])])}
TASK: 1. Take a tech feature. 2. Ask "So what?". 3. Ask "So what?" again. 4. Formulate benefit without jargon. Create a table.
{lang_instr}
Output JSON format ONLY: {{"techTranslations": [{{"feature": "", "story": "", "headline": ""}}]}}
"""
log_and_save(project_id, "phase9", "prompt", prompt)