feat(gtm): Implement Meta-Framework for strategic analysis

Refactors the GTM orchestrator prompts (phases 2-9) to use a question-based strategic framework derived from the internal marketing blueprint. This new 'Meta-Framework' approach ensures strategic depth and prevents content pollution from irrelevant examples when analyzing new product categories.

- Updates orchestrator prompts in .
- Adds documentation in  explaining how to modify the new strategy logic.
- Includes minor fixes to the Node.js  and dependency updates in .
This commit is contained in:
2026-01-14 15:34:15 +00:00
parent 5a04fd6bf2
commit 2b7c072ddc
5 changed files with 4427 additions and 57 deletions

View File

@@ -433,33 +433,78 @@ def find_relevant_links(base_url):
logging.warning(f"Could not scrape base URL {base_url} for links: {e}") logging.warning(f"Could not scrape base URL {base_url} for links: {e}")
return [] return []
def clean_llm_response(text):
"""Sanitizes the LLM response to remove excessive whitespace and common artifacts."""
if not text: return ""
# 1. Replace multiple spaces/newlines with single ones (within a reasonable limit)
# But preserve single newlines for markdown structure
text = re.sub(r'[ \t]{5,}', ' ', text) # Replace 5+ spaces/tabs with 1 space
# 2. Remove non-printable characters (except common ones)
text = "".join(ch for ch in text if ch.isprintable() or ch in "\n\r\t")
# 3. Fix common table artifacts like empty pipes at the end of lines
text = re.sub(r'\|\s*$', '|', text, flags=re.MULTILINE)
return text.strip()
def parse_markdown_table(markdown_text): def parse_markdown_table(markdown_text):
lines = [line.strip() for line in markdown_text.strip().split('\n')] # Sanitize input first
markdown_text = clean_llm_response(markdown_text)
lines = [line.strip() for line in markdown_text.strip().split('\n') if line.strip()]
table_lines = [] table_lines = []
in_table_section = False
# 1. Identify all lines that look like table rows (start and end with |)
for line in lines: for line in lines:
if re.match(r'^\|.*\|$', line) and '---' not in line: if line.startswith('|') and line.endswith('|'):
in_table_section = True
table_lines.append(line) table_lines.append(line)
elif in_table_section and '---' in line and re.match(r'^\|(:?-+:?)\|', line.replace(' ', '')):
table_lines.append(line) if not table_lines:
elif in_table_section: return {"headers": [], "rows": []}
break
if not table_lines: return {"headers": [], "rows": []} # 2. Find the separator line (|---|---|...)
separator_index = -1 separator_index = -1
for i, line in enumerate(table_lines): for i, line in enumerate(table_lines):
if '---' in line and re.match(r'^\|(:?-+:?)\|', line.replace(' ', '')): # A separator line usually has at least one dash between pipes and no alphanumeric chars
if '---' in line and not re.search(r'[a-zA-Z0-9]', line.replace('|', '').replace('-', '').replace(' ', '').replace(':', '')):
separator_index = i separator_index = i
break break
if separator_index == -1 or separator_index == 0: return {"headers": [], "rows": []}
header_line = table_lines[0] if separator_index == -1:
# If no separator found, we might just have a list of rows where the first is the header
# but usually LLMs provide the separator. Let's assume the first is header.
header_line = table_lines[0]
data_start = 1
else:
# Separator found. Header is the line before it.
if separator_index == 0: return {"headers": [], "rows": []}
header_line = table_lines[separator_index - 1]
data_start = separator_index + 1
# 3. Extract and clean headers
headers = [re.sub(r'\*+([^*]+)\*+', r'\1', h.strip()).strip() for h in header_line.split('|') if h.strip()] headers = [re.sub(r'\*+([^*]+)\*+', r'\1', h.strip()).strip() for h in header_line.split('|') if h.strip()]
if not headers: return {"headers": [], "rows": []}
# 4. Extract and clean rows
rows = [] rows = []
for line in table_lines[separator_index + 1:]: for line in table_lines[data_start:]:
# Split by | and remove leading/trailing empty elements from the split result
raw_cells = line.split('|') raw_cells = line.split('|')
cells = [re.sub(r'\*+([^*]+)\*+', r'\1', c.strip()).strip() for c in raw_cells if c.strip()] # Handle the leading/trailing empty strings caused by the outer pipes
if len(cells) == len(headers): cells = [re.sub(r'\*+([^*]+)\*+', r'\1', c.strip()).strip() for c in raw_cells]
# If the line starts and ends with |, the first and last elements are empty strings
if line.startswith('|'): cells = cells[1:]
if line.endswith('|'): cells = cells[:-1]
# Pad or truncate row to match header length
if len(cells) < len(headers):
cells.extend([''] * (len(headers) - len(cells)))
elif len(cells) > len(headers):
cells = cells[:len(headers)]
# Only add row if it's not another separator or empty
if any(cells):
rows.append(cells) rows.append(cells)
return {"headers": headers, "rows": rows} return {"headers": headers, "rows": rows}
def format_context_for_prompt(analysis_data, language): def format_context_for_prompt(analysis_data, language):
@@ -521,7 +566,8 @@ def start_generation(url, language, regions, focus):
save_detailed_log("step1_offer", "response", response_text) save_detailed_log("step1_offer", "response", response_text)
step1_title = current_prompts['STEP_TITLES']['offer'] step1_title = current_prompts['STEP_TITLES']['offer']
title_match = re.search(rf'## {re.escape(step1_title)}\s*', response_text, re.IGNORECASE) # Flexible header matching
title_match = re.search(rf'^##\s*(?:Schritt|Step)\s*1.*$', response_text, re.IGNORECASE | re.MULTILINE)
content = response_text[title_match.end():].strip() if title_match else response_text content = response_text[title_match.end():].strip() if title_match else response_text
table_data = parse_markdown_table(content) table_data = parse_markdown_table(content)
@@ -566,7 +612,8 @@ def next_step(language, context_file, generation_step, channels, focus_industry=
step_key = ['offer', 'targetGroups', 'personas', 'painPoints', 'gains', 'messages', 'customerJourney'][generation_step - 1] step_key = ['offer', 'targetGroups', 'personas', 'painPoints', 'gains', 'messages', 'customerJourney'][generation_step - 1]
expected_title = current_prompts['STEP_TITLES'][step_key] expected_title = current_prompts['STEP_TITLES'][step_key]
title_match = re.search(rf'## {re.escape(expected_title)}\s*', response_text, re.IGNORECASE) # Flexible header matching
title_match = re.search(rf'^##\s*(?:Schritt|Step)\s*{generation_step}.*$', response_text, re.IGNORECASE | re.MULTILINE)
content = response_text[title_match.end():].strip() if title_match else response_text content = response_text[title_match.end():].strip() if title_match else response_text
table_data = parse_markdown_table(content) table_data = parse_markdown_table(content)

4174
gtm-architect/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -11,7 +11,7 @@ const port = 3005;
// --- DATABASE INITIALIZATION --- // --- DATABASE INITIALIZATION ---
// Initialize the SQLite database on startup to ensure the 'gtm_projects' table exists. // Initialize the SQLite database on startup to ensure the 'gtm_projects' table exists.
const dbScript = path.join(__dirname, 'gtm_db_manager.py'); const dbScript = path.join(__dirname, '../gtm_db_manager.py'); // CORRECTED PATH
console.log(`[Init] Initializing database via ${dbScript}...`); console.log(`[Init] Initializing database via ${dbScript}...`);
const initProcess = spawn('python3', [dbScript, 'init']); const initProcess = spawn('python3', [dbScript, 'init']);

View File

@@ -77,6 +77,54 @@ Die `call_gemini_image`-Funktion wählt automatisch die beste Methode basierend
| **8** | `phase8` | Phase 1, 2 | Business Case | CFO-Argumentation, ROI-Logik. | | **8** | `phase8` | Phase 1, 2 | Business Case | CFO-Argumentation, ROI-Logik. |
| **9** | `phase9` | Phase 1, 4 | Feature-to-Value | Übersetzung technischer Features in Nutzen. | | **9** | `phase9` | Phase 1, 4 | Feature-to-Value | Übersetzung technischer Features in Nutzen. |
### 4.1 Anleitung: Anpassung der Strategie-Logik (Meta-Framework)
Das Herzstück der strategischen Qualität der App ist nicht in einer externen Datei gespeichert, sondern wurde als "Meta-Framework" direkt in die Anweisungen (Prompts) für die KI einprogrammiert. Dieses Framework besteht aus den strategischen Schlüsselfragen, die die KI beantworten muss, um eine GTM-Strategie zu erstellen.
Wenn sich Ihre grundlegende Marketing-Strategie weiterentwickelt, können Sie diese Logik anpassen, indem Sie die Prompts im Code ändern.
**Wichtig:** Dieser Prozess erfordert ein Verständnis der Programm-Logik und sollte sorgfältig durchgeführt werden.
**Schritt-für-Schritt-Anleitung:**
1. **Quelldatei identifizieren:** Die gesamte Logik befindet sich in der Datei `gtm_architect_orchestrator.py`.
2. **Relevante Funktionen finden:** Jede Phase des GTM-Prozesses hat eine eigene Python-Funktion (z.B. `phase2`, `phase3`, `phase4` etc.). Innerhalb jeder dieser Funktionen gibt es eine Variable namens `prompt`. Das ist die Anweisung für die KI.
3. **Prompt-Struktur verstehen:** Die Prompts sind so aufgebaut, dass sie der KI strategische Leitplanken geben. Suchen Sie nach dem Abschnitt `**Strategic Questions:**` innerhalb des `prompt`-Blocks.
*Beispiel (Ausschnitt aus `phase2`):*
```python
prompt = f"""
PHASE 2: IDEAL CUSTOMER PROFILE (ICP) & DATA PROXIES - STRATEGIC ANALYSIS
**Your Task:**
Answer the following strategic questions to determine the Ideal Customer Profiles (ICPs).
**Strategic Questions:**
1. **ICP Identification:** Based on the product's core capabilities, which 3 industries face the most significant operational challenges...?
2. **Rationale:** For each identified ICP, provide a concise rationale...
3. **Data Proxies:** How can we find these companies online...?
{lang_instr}
**Output:**
Provide your analysis ONLY in the following JSON format:
{{"icps": [...], "dataProxies": [...]}}
"""
```
4. **Strategische Fragen anpassen:** Sie können die Fragen unter `**Strategic Questions:**` ändern, hinzufügen oder entfernen, um die Denkweise der KI zu steuern. Wenn Sie beispielsweise feststellen, dass die "Data Proxies" präziser sein müssen, könnten Sie die Frage 3 anpassen oder eine vierte Frage hinzufügen.
5. **Output-Struktur beibehalten (KRITISCH!):** Der Teil des Prompts, der mit `**Output:**` beginnt, definiert das JSON-Format, das die Funktion zurückgibt. **Ändern Sie dieses Format NICHT**, da sonst die nachfolgenden Phasen und das Frontend die Daten nicht mehr verarbeiten können. Die Anpassung erfolgt ausschließlich über die strategischen Fragen, die das Ergebnis inhaltlich beeinflussen.
6. **Änderungen bereitstellen:** Nachdem Sie die `gtm_architect_orchestrator.py` gespeichert haben, ist **kein** `docker build` notwendig. Ein einfacher Neustart des Containers aktiviert die neue Logik:
```bash
docker restart gtm-app
```
Durch das Befolgen dieser Schritte können Sie die Kernlogik des GTM Architect selbstständig an neue strategische Anforderungen anpassen.
## 5. Sitzungs-Management ## 5. Sitzungs-Management
Das System verwaltet persistente Sitzungen in der SQLite-Datenbank: Das System verwaltet persistente Sitzungen in der SQLite-Datenbank:

View File

@@ -143,6 +143,16 @@ def load_history(payload):
data = db_manager.get_project_data(project_id) data = db_manager.get_project_data(project_id)
if not data: if not data:
raise ValueError(f"Project {project_id} not found.") raise ValueError(f"Project {project_id} not found.")
# FIX: Check for and parse stringified JSON in phase results
if 'phases' in data and isinstance(data['phases'], dict):
for phase_name, phase_result in data['phases'].items():
if isinstance(phase_result, str):
try:
data['phases'][phase_name] = json.loads(phase_result)
except json.JSONDecodeError:
logging.warning(f"Could not decode JSON for {phase_name} in project {project_id}. Leaving as is.")
return data return data
def delete_session(payload): def delete_session(payload):
@@ -329,13 +339,27 @@ def phase2(payload):
lang_instr = get_output_lang_instruction(lang) lang_instr = get_output_lang_instruction(lang)
prompt = f""" prompt = f"""
PHASE 2: IDEAL CUSTOMER PROFILE (ICP) & DATA PROXIES PHASE 2: IDEAL CUSTOMER PROFILE (ICP) & DATA PROXIES - STRATEGIC ANALYSIS
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. **Product Context:**
{json.dumps(phase1_data)}
**Your Task:**
Answer the following strategic questions to determine the Ideal Customer Profiles (ICPs).
**Strategic Questions:**
1. **ICP Identification:** Based on the product's core capabilities, which 3 industries face the most significant operational challenges (e.g., safety, efficiency, high manual labor costs, security risks) that this product directly solves? Think about where the economic or safety impact is highest.
2. **Rationale:** For each identified ICP, provide a concise rationale. Why is this product a perfect fit for this specific industry? (e.g., "Reduces inspection costs by X%", "Improves safety in hazardous environments", "Automates a critical but repetitive task").
3. **Data Proxies:** How can we find these companies online? What specific digital footprints (data proxies) do they leave? Think about:
* Keywords on their websites (e.g., 'plant safety', 'autonomous inspection', 'logistics automation').
* Specific job titles on LinkedIn (e.g., 'Head of Security', 'Logistics Manager', 'Maintenance Lead').
* Their participation in specific industry trade shows or publications.
{lang_instr} {lang_instr}
Output JSON format ONLY: {{"icps": [{{"name": "", "rationale": ""}}], "dataProxies": [{{"target": "", "method": ""}}]}} **Output:**
Provide your analysis ONLY in the following JSON format:
{{"icps": [{{"name": "Industry Name", "rationale": "Why it's a fit."}}], "dataProxies": [{{"target": "e.g., Company Websites", "method": "How to find them."}}]}}
""" """
log_and_save(project_id, "phase2", "prompt", prompt) log_and_save(project_id, "phase2", "prompt", prompt)
response = call_gemini_flash(prompt, system_instruction=sys_instr, json_mode=True) response = call_gemini_flash(prompt, system_instruction=sys_instr, json_mode=True)
@@ -353,13 +377,28 @@ def phase3(payload):
lang_instr = get_output_lang_instruction(lang) lang_instr = get_output_lang_instruction(lang)
prompt = f""" prompt = f"""
PHASE 3: WHALE HUNTING PHASE 3: WHALE HUNTING & BUYING CENTER ANALYSIS - STRATEGIC ANALYSIS
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. **Target ICPs (Industries):**
{json.dumps(phase2_data.get('icps'))}
**Your Task:**
Answer the following strategic questions to identify key accounts and decision-makers.
**Strategic Questions:**
1. **Whale Identification:** For each ICP, identify 3-5 specific 'Whale' companies in the DACH market. These should be leaders, innovators, or companies with significant scale in that sector.
2. **Buying Center Roles:** For a technology investment of this scale, define the key roles within a typical customer's Buying Center. Use these specific archetypes and identify plausible job titles for each:
* **Decider:** The person with the final budget authority (e.g., Plant Manager, CEO, Head of Operations).
* **Evaluator:** The technical expert who vets the solution (e.g., Head of Engineering, IT Security Lead, Facility Manager).
* **User:** The person or team who will use the product day-to-day (e.g., Security Staff, Maintenance Crew).
* **Influencer:** A person with a strong opinion who can sway the decision (e.g., Head of Safety, Innovation Manager).
* **Gatekeeper:** A person who controls the flow of information (e.g., IT Administration, Purchasing Department).
{lang_instr} {lang_instr}
Output JSON format ONLY: {{"whales": [{{"industry": "", "accounts": []}}], "roles": []}} **Output:**
Provide your analysis ONLY in the following JSON format:
{{"whales": [{{"industry": "ICP Name", "accounts": ["Company A", "Company B"]}}], "roles": ["Role Archetype: Plausible Job Title 1, Plausible Job Title 2"]}}
""" """
log_and_save(project_id, "phase3", "prompt", prompt) log_and_save(project_id, "phase3", "prompt", prompt)
response = call_gemini_flash(prompt, system_instruction=sys_instr, json_mode=True) response = call_gemini_flash(prompt, system_instruction=sys_instr, json_mode=True)
@@ -382,15 +421,27 @@ def phase4(payload):
all_accounts.extend(w.get('accounts', [])) all_accounts.extend(w.get('accounts', []))
prompt = f""" prompt = f"""
PHASE 4: STRATEGY & ANGLE DEVELOPMENT PHASE 4: STRATEGY & ANGLE DEVELOPMENT - STRATEGIC ANALYSIS
Accounts: {json.dumps(all_accounts)}
Target Industries: {json.dumps([w.get('industry') for w in phase3_data.get('whales', [])])} **Target Industries & Companies:**
Product Features: {json.dumps(phase1_data.get('features'))} {json.dumps([w.get('industry') for w in phase3_data.get('whales', [])])}
Task: 1. Develop specific "Angle" per target/industry. 2. Consistency Check against Product Matrix. 3. **IMPORTANT:** Apply "Hybrid Service Logic" if constraints exist!
**Product Features:**
{json.dumps(phase1_data.get('features'))}
**Your Task:**
Answer the following strategic questions to build the core of our market approach.
**Strategic Questions:**
1. **Pain Point Analysis:** For each industry segment, what is the single most significant, measurable **Pain Point** this product solves? Frame it from the customer's operational perspective (e.g., "High rate of safety incidents during manual inspections", "Production downtime due to undetected equipment failure", "Inefficient inventory tracking").
2. **Develop the Angle:** What is our unique story or perspective for this segment? The "Angle" should directly connect a product capability to their primary pain point.
3. **Define Differentiation:** Why should they choose us over a competitor or simply doing nothing? You **must** connect this to our unique "Dynamic Hybrid Service" logic (the combination of robot capabilities and human expert services).
{lang_instr} {lang_instr}
Output JSON format ONLY: {{"strategyMatrix": [{{"segment": "", "painPoint": "", "angle": "", "differentiation": ""}}]}} **Output:**
Provide your analysis ONLY in the following JSON format:
{{"strategyMatrix": [{{"segment": "Target Industry", "painPoint": "The core problem.", "angle": "Our unique story.", "differentiation": "Why us (Hybrid Service)."}}]}}
""" """
log_and_save(project_id, "phase4", "prompt", prompt) log_and_save(project_id, "phase4", "prompt", prompt)
response = call_gemini_flash(prompt, system_instruction=sys_instr, json_mode=True) response = call_gemini_flash(prompt, system_instruction=sys_instr, json_mode=True)
@@ -489,13 +540,26 @@ def phase6(payload):
lang_instr = get_output_lang_instruction(lang) lang_instr = get_output_lang_instruction(lang)
prompt = f""" prompt = f"""
PHASE 6: SALES ENABLEMENT & VISUALS PHASE 6: SALES ENABLEMENT & VISUALS - STRATEGIC ANALYSIS
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. **Context:**
- Product Features: {json.dumps(phase1_data.get('features'))}
- Personas: {json.dumps(phase3_data.get('roles'))}
- Strategy: {json.dumps(phase4_data.get('strategyMatrix'))}
**Your Task:**
Answer the following strategic questions to create sales enablement materials.
**Strategic Questions:**
1. **Anticipate Objections:** For each key Buying Center persona, what is their most likely and critical **objection**? What is the core reason they would hesitate or say "no" to this investment?
2. **Formulate Battlecards:** For each objection, formulate a concise and powerful **response script**. The script should first acknowledge their concern, then reframe the issue, and finally present our solution as the clear, logical answer, quantifying the benefit where possible.
3. **Create Visual Prompts:** For the top 3 use cases, write a detailed **visual prompt** for an image generation AI. The prompt must describe a photorealistic scene that visually communicates the product's primary value proposition in that specific industry context. It should be clear what the robot is doing and what the positive outcome is.
{lang_instr} {lang_instr}
Output JSON format ONLY: {{"battlecards": [{{"persona": "", "objection": "", "responseScript": ""}}], "visualPrompts": [{{"title": "", "context": "", "prompt": ""}}]}} **Output:**
Provide your analysis ONLY in the following JSON format:
{{"battlecards": [{{"persona": "Buying Center Role", "objection": "The key objection.", "responseScript": "The compelling response."}}], "visualPrompts": [{{"title": "Image Title", "context": "Use case description.", "prompt": "Detailed photorealistic prompt."}}]}}
""" """
log_and_save(project_id, "phase6", "prompt", prompt) log_and_save(project_id, "phase6", "prompt", prompt)
response = call_gemini_flash(prompt, system_instruction=sys_instr, json_mode=True) response = call_gemini_flash(prompt, system_instruction=sys_instr, json_mode=True)
@@ -514,14 +578,27 @@ def phase7(payload):
lang_instr = get_output_lang_instruction(lang) lang_instr = get_output_lang_instruction(lang)
prompt = f""" prompt = f"""
PHASE 7: VERTICAL LANDING PAGE COPY (Conversion Optimization) PHASE 7: VERTICAL LANDING PAGE COPY - STRATEGIC ANALYSIS
ICPs: {json.dumps(phase2_data.get('icps'))}
Strategy: {json.dumps(phase4_data.get('strategyMatrix'))} **Context:**
TASK: 1. Transform generic features into specific benefits for the Top 2 ICPs. 2. Apply "Wackler Symbiosis". 3. Create Landing Page Drafts (Hero Section). - ICPs: {json.dumps(phase2_data.get('icps'))}
- Strategy: {json.dumps(phase4_data.get('strategyMatrix'))}
**Your Task:**
Create conversion-optimized landing page copy for the top 2 ICPs by answering the following questions.
**Strategic Questions:**
1. **Headline:** What is the most powerful **outcome** for this industry? The headline must grab the attention of a Decider and state this primary result.
2. **Subline:** How can you elaborate on the headline? Briefly mention the core problem this industry faces and introduce our solution as the answer.
3. **Benefit Bullets:** Transform 3-5 key technical features into tangible **benefit statements** for this specific industry. Each bullet point should answer the customer's question: "What's in it for me?".
4. **Call-to-Action (CTA):** What is the logical next step we want the user to take? The CTA should be clear, concise, and action-oriented.
5. **Apply Wackler Symbiosis:** Ensure the copy clearly communicates the value of the robot combined with the human expert service.
{lang_instr} {lang_instr}
Output JSON format ONLY: {{"landingPages": [{{"industry": "", "headline": "", "subline": "", "bullets": [], "cta": ""}}]}} **Output:**
Provide your analysis ONLY in the following JSON format:
{{"landingPages": [{{"industry": "ICP Name", "headline": "The compelling headline.", "subline": "The elaborating subline.", "bullets": ["Benefit 1", "Benefit 2"], "cta": "The call to action."}}]}}
""" """
log_and_save(project_id, "phase7", "prompt", prompt) log_and_save(project_id, "phase7", "prompt", prompt)
response = call_gemini_flash(prompt, system_instruction=sys_instr, json_mode=True) response = call_gemini_flash(prompt, system_instruction=sys_instr, json_mode=True)
@@ -540,13 +617,25 @@ def phase8(payload):
lang_instr = get_output_lang_instruction(lang) lang_instr = get_output_lang_instruction(lang)
prompt = f""" prompt = f"""
PHASE 8: BUSINESS CASE BUILDER (The CFO Pitch) PHASE 8: BUSINESS CASE BUILDER (THE CFO PITCH) - STRATEGIC ANALYSIS
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. **Context:**
- ICPs: {json.dumps(phase2_data.get('icps'))}
- Features: {json.dumps(phase1_data.get('features'))}
**Your Task:**
Develop the financial argumentation for each ICP by answering the following questions.
**Strategic Questions:**
1. **Identify the Cost Driver:** What is the primary, quantifiable **cost driver** that our product addresses in this industry? (e.g., "High labor costs for manual inspections", "Financial losses from production downtime", "Insurance premiums due to safety incidents").
2. **Quantify Efficiency Gains:** How, specifically, does our product create a positive financial impact? Estimate the **efficiency gain** in plausible percentages or saved hours/costs. (e.g., "Reduces manual inspection time by 50%", "Prevents costly downtime worth an estimated X€ per hour").
3. **Formulate the Risk Argument:** How does our solution mitigate significant operational, financial, or safety **risks**? Frame this as a form of financial protection or cost avoidance. (e.g., "Mitigates the multi-million dollar risk of an environmental incident by providing early leak detection.").
{lang_instr} {lang_instr}
Output JSON format ONLY: {{"businessCases": [{{"industry": "", "costDriver": "", "efficiencyGain": "", "riskArgument": ""}}]}} **Output:**
Provide your analysis ONLY in the following JSON format:
{{"businessCases": [{{"industry": "ICP Name", "costDriver": "The primary financial pain.", "efficiencyGain": "The quantifiable gain.", "riskArgument": "The cost of inaction."}}]}}
""" """
log_and_save(project_id, "phase8", "prompt", prompt) log_and_save(project_id, "phase8", "prompt", prompt)
response = call_gemini_flash(prompt, system_instruction=sys_instr, json_mode=True) response = call_gemini_flash(prompt, system_instruction=sys_instr, json_mode=True)
@@ -565,14 +654,26 @@ def phase9(payload):
lang_instr = get_output_lang_instruction(lang) lang_instr = get_output_lang_instruction(lang)
prompt = f""" prompt = f"""
PHASE 9: THE "FEATURE-TO-VALUE" TRANSLATOR PHASE 9: THE "FEATURE-TO-VALUE" TRANSLATOR - STRATEGIC ANALYSIS
Input Features: {json.dumps(phase1_data.get('features'))}
Strategy Pains: {json.dumps([s.get('painPoint') for s in phase4_data.get('strategyMatrix', [])])} **Context:**
TASK: 1. Take a tech feature. 2. Ask "So what?". 3. Ask "So what?" again. 4. Formulate benefit without jargon. Create a table. - Input Features: {json.dumps(phase1_data.get('features'))}
- Strategy Pains: {json.dumps([s.get('painPoint') for s in phase4_data.get('strategyMatrix', [])])}
**Your Task:**
Translate technical features into compelling, value-oriented benefits by following this structured process for each key feature.
**Structured Process:**
1. **State the Feature:** Pick a key technical feature.
2. **Ask "So what?" (The Consequence):** What is the immediate consequence or capability that this feature enables?
3. **Ask "So what?" again (The Value):** What is the ultimate, tangible **value** or **benefit** that the consequence delivers to the customer? How does it solve one of their core pain points? This is the "Story".
4. **Formulate Headline:** Create a short, powerful, jargon-free **headline** that encapsulates this final value.
{lang_instr} {lang_instr}
Output JSON format ONLY: {{"techTranslations": [{{"feature": "", "story": "", "headline": ""}}]}} **Output:**
Provide your analysis ONLY in the following JSON format:
{{"techTranslations": [{{"feature": "The technical feature.", "story": "The 'So what? So what?' analysis.", "headline": "The final value headline."}}]}}
""" """
log_and_save(project_id, "phase9", "prompt", prompt) log_and_save(project_id, "phase9", "prompt", prompt)
response = call_gemini_flash(prompt, system_instruction=sys_instr, json_mode=True) response = call_gemini_flash(prompt, system_instruction=sys_instr, json_mode=True)