fix(gtm): Ultimate prompt syntax robustness, add versions to logs, update migration docs
This commit is contained in:
@@ -60,13 +60,7 @@ Multi-Line Prompts können in Docker-Umgebungen zu **sehr hartnäckigen Syntaxfe
|
|||||||
2. **Nutze die `.format()` Methode** zur Variablen-Injektion. Dies trennt die String-Definition komplett von der Variablen-Interpolation und ist die robusteste Methode.
|
2. **Nutze die `.format()` Methode** zur Variablen-Injektion. Dies trennt die String-Definition komplett von der Variablen-Interpolation und ist die robusteste Methode.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
# Schlecht (fehleranfällig, auch wenn es manchmal funktioniert):
|
# Beispiel: So ist es maximal robust (bevorzugte Methode)
|
||||||
# prompt = f"""
|
|
||||||
# 1. Mache dies: {var1}
|
|
||||||
# 2. Mache das: {var2}
|
|
||||||
# """
|
|
||||||
|
|
||||||
# Gut (maximal robust):
|
|
||||||
prompt_template = """
|
prompt_template = """
|
||||||
1) Mache dies: {variable_1}
|
1) Mache dies: {variable_1}
|
||||||
2) Mache das: {variable_2}
|
2) Mache das: {variable_2}
|
||||||
@@ -76,6 +70,10 @@ Multi-Line Prompts können in Docker-Umgebungen zu **sehr hartnäckigen Syntaxfe
|
|||||||
full_prompt = sys_instr + "\n\n" + prompt
|
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.
|
||||||
|
* `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!
|
* **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`).
|
* Beispiel: `call_openai_chat` unterstützt oft kein `system_message` Argument. Stattdessen Prompt manuell zusammenbauen (`sys_instr + "\n\n" + prompt`).
|
||||||
|
|
||||||
|
|||||||
@@ -73,8 +73,10 @@ app.get('*', (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const VERSION = "1.1.1_Fix"; // Add a version for debugging
|
||||||
|
|
||||||
const server = app.listen(port, () => {
|
const server = app.listen(port, () => {
|
||||||
console.log(`GTM Architect server listening at http://localhost:${port} (Timeout: 600s)`);
|
console.log(`GTM Architect server listening at http://localhost:${port} (Version: ${VERSION})`);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Prevent 502 Bad Gateway by increasing Node.js server timeouts to match Nginx
|
// Prevent 502 Bad Gateway by increasing Node.js server timeouts to match Nginx
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ sys.path.append(str(project_root))
|
|||||||
from helpers import call_openai_chat
|
from helpers import call_openai_chat
|
||||||
import market_db_manager
|
import market_db_manager
|
||||||
|
|
||||||
|
__version__ = "1.3.0_SyntaxFix"
|
||||||
|
|
||||||
# Ensure DB is ready
|
# Ensure DB is ready
|
||||||
market_db_manager.init_db()
|
market_db_manager.init_db()
|
||||||
|
|
||||||
@@ -131,8 +133,9 @@ def analyze_product(data):
|
|||||||
lang = data.get('language', 'de')
|
lang = data.get('language', 'de')
|
||||||
sys_instr = get_system_instruction(lang)
|
sys_instr = get_system_instruction(lang)
|
||||||
|
|
||||||
|
# Statische Prompt-Teile (keine f-Strings)
|
||||||
if lang == 'en':
|
if lang == 'en':
|
||||||
extraction_prompt_template = """
|
extraction_prompt_static_part = """
|
||||||
PHASE 1-A: TECHNICAL EXTRACTION
|
PHASE 1-A: TECHNICAL EXTRACTION
|
||||||
Input Product Description: "{product_description}"
|
Input Product Description: "{product_description}"
|
||||||
|
|
||||||
@@ -143,9 +146,8 @@ Task:
|
|||||||
|
|
||||||
Output JSON format ONLY.
|
Output JSON format ONLY.
|
||||||
"""
|
"""
|
||||||
extraction_prompt = extraction_prompt_template.format(product_description=product_input[:25000])
|
|
||||||
else:
|
else:
|
||||||
extraction_prompt_template = """
|
extraction_prompt_static_part = """
|
||||||
PHASE 1-A: TECHNICAL EXTRACTION
|
PHASE 1-A: TECHNICAL EXTRACTION
|
||||||
Input Product Description: "{product_description}"
|
Input Product Description: "{product_description}"
|
||||||
|
|
||||||
@@ -156,7 +158,8 @@ Aufgabe:
|
|||||||
|
|
||||||
Output JSON format ONLY.
|
Output JSON format ONLY.
|
||||||
"""
|
"""
|
||||||
extraction_prompt = extraction_prompt_template.format(product_description=product_input[:25000])
|
# Variablen separat formatieren
|
||||||
|
extraction_prompt = extraction_prompt_static_part.format(product_description=product_input[:25000])
|
||||||
|
|
||||||
full_extraction_prompt = sys_instr + "\n\n" + extraction_prompt
|
full_extraction_prompt = sys_instr + "\n\n" + extraction_prompt
|
||||||
extraction_response = call_openai_chat(full_extraction_prompt, response_format_json=True)
|
extraction_response = call_openai_chat(full_extraction_prompt, response_format_json=True)
|
||||||
@@ -166,11 +169,11 @@ Output JSON format ONLY.
|
|||||||
constraints_json = json.dumps(extraction_data.get('constraints'))
|
constraints_json = json.dumps(extraction_data.get('constraints'))
|
||||||
|
|
||||||
if lang == 'en':
|
if lang == 'en':
|
||||||
conflict_prompt_template = """
|
conflict_prompt_static_part = """
|
||||||
PHASE 1-B: PORTFOLIO CONFLICT CHECK
|
PHASE 1-B: PORTFOLIO CONFLICT CHECK
|
||||||
|
|
||||||
New Product Features: {features_json}
|
New Product Features: {features_json_var}
|
||||||
New Product Constraints: {constraints_json}
|
New Product Constraints: {constraints_json_var}
|
||||||
|
|
||||||
Existing Portfolio:
|
Existing Portfolio:
|
||||||
1. "Indoor Scrubber 50": Indoor cleaning, hard floor, supermarkets.
|
1. "Indoor Scrubber 50": Indoor cleaning, hard floor, supermarkets.
|
||||||
@@ -181,13 +184,13 @@ Check if the new product overlaps significantly with existing ones (is it just a
|
|||||||
|
|
||||||
Output JSON format ONLY.
|
Output JSON format ONLY.
|
||||||
"""
|
"""
|
||||||
conflict_prompt = conflict_prompt_template.format(features_json=features_json, constraints_json=constraints_json)
|
conflict_prompt = conflict_prompt_static_part.format(features_json_var=features_json, constraints_json_var=constraints_json)
|
||||||
else:
|
else:
|
||||||
conflict_prompt_template = """
|
conflict_prompt_static_part = """
|
||||||
PHASE 1-B: PORTFOLIO CONFLICT CHECK
|
PHASE 1-B: PORTFOLIO CONFLICT CHECK
|
||||||
|
|
||||||
Neue Produkt-Features: {features_json}
|
Neue Produkt-Features: {features_json_var}
|
||||||
Neue Produkt-Constraints: {constraints_json}
|
Neue Produkt-Constraints: {constraints_json_var}
|
||||||
|
|
||||||
Existierendes Portfolio:
|
Existierendes Portfolio:
|
||||||
1. "Indoor Scrubber 50": Innenreinigung, Hartboden, Supermärkte.
|
1. "Indoor Scrubber 50": Innenreinigung, Hartboden, Supermärkte.
|
||||||
@@ -198,7 +201,7 @@ Prüfe, ob das neue Produkt signifikant mit bestehenden Produkten überlappt (Is
|
|||||||
|
|
||||||
Output JSON format ONLY.
|
Output JSON format ONLY.
|
||||||
"""
|
"""
|
||||||
conflict_prompt = conflict_prompt_template.format(features_json=features_json, constraints_json=constraints_json)
|
conflict_prompt = conflict_prompt_static_part.format(features_json_var=features_json, constraints_json_var=constraints_json)
|
||||||
|
|
||||||
full_conflict_prompt = sys_instr + "\n\n" + conflict_prompt
|
full_conflict_prompt = sys_instr + "\n\n" + conflict_prompt
|
||||||
conflict_response = call_openai_chat(full_conflict_prompt, response_format_json=True)
|
conflict_response = call_openai_chat(full_conflict_prompt, response_format_json=True)
|
||||||
@@ -218,8 +221,8 @@ def discover_icps(data):
|
|||||||
if lang == 'en':
|
if lang == 'en':
|
||||||
prompt_template = """
|
prompt_template = """
|
||||||
PHASE 2: ICP DISCOVERY & DATA PROXIES
|
PHASE 2: ICP DISCOVERY & DATA PROXIES
|
||||||
Based on the product features: {features_json}
|
Based on the product features: {features_json_var}
|
||||||
And constraints: {constraints_json}
|
And constraints: {constraints_json_var}
|
||||||
|
|
||||||
Output JSON format ONLY:
|
Output JSON format ONLY:
|
||||||
{{
|
{{
|
||||||
@@ -227,12 +230,12 @@ Output JSON format ONLY:
|
|||||||
"dataProxies": [ {{ "target": "Criteria", "method": "How" }} ]
|
"dataProxies": [ {{ "target": "Criteria", "method": "How" }} ]
|
||||||
}}
|
}}
|
||||||
"""
|
"""
|
||||||
prompt = prompt_template.format(features_json=features_json, constraints_json=constraints_json)
|
prompt = prompt_template.format(features_json_var=features_json, constraints_json_var=constraints_json)
|
||||||
else:
|
else:
|
||||||
prompt_template = """
|
prompt_template = """
|
||||||
PHASE 2: ICP DISCOVERY & DATA PROXIES
|
PHASE 2: ICP DISCOVERY & DATA PROXIES
|
||||||
Basierend auf Features: {features_json}
|
Basierend auf Features: {features_json_var}
|
||||||
Und Constraints: {constraints_json}
|
Und Constraints: {constraints_json_var}
|
||||||
|
|
||||||
Output JSON format ONLY:
|
Output JSON format ONLY:
|
||||||
{{
|
{{
|
||||||
@@ -240,7 +243,7 @@ Output JSON format ONLY:
|
|||||||
"dataProxies": [ {{ "target": "Kriterium", "method": "Methode" }} ]
|
"dataProxies": [ {{ "target": "Kriterium", "method": "Methode" }} ]
|
||||||
}}
|
}}
|
||||||
"""
|
"""
|
||||||
prompt = prompt_template.format(features_json=features_json, constraints_json=constraints_json)
|
prompt = prompt_template.format(features_json_var=features_json, constraints_json_var=constraints_json)
|
||||||
|
|
||||||
full_prompt = sys_instr + "\n\n" + prompt
|
full_prompt = sys_instr + "\n\n" + prompt
|
||||||
response = call_openai_chat(full_prompt, response_format_json=True)
|
response = call_openai_chat(full_prompt, response_format_json=True)
|
||||||
@@ -251,7 +254,10 @@ def hunt_whales(data):
|
|||||||
lang = data.get('language', 'de')
|
lang = data.get('language', 'de')
|
||||||
sys_instr = get_system_instruction(lang)
|
sys_instr = get_system_instruction(lang)
|
||||||
icps_json = json.dumps(phase2_result.get('icps'))
|
icps_json = json.dumps(phase2_result.get('icps'))
|
||||||
prompt = f"PHASE 3: WHALE HUNTING for {icps_json}. Identify 3-5 concrete DACH companies per industry and buying center roles. Output JSON ONLY."
|
prompt_template = """
|
||||||
|
PHASE 3: WHALE HUNTING for {icps_json_var}. Identify 3-5 concrete DACH companies per industry and buying center roles. Output JSON ONLY.
|
||||||
|
"""
|
||||||
|
prompt = prompt_template.format(icps_json_var=icps_json)
|
||||||
full_prompt = sys_instr + "\n\n" + prompt
|
full_prompt = sys_instr + "\n\n" + prompt
|
||||||
response = call_openai_chat(full_prompt, response_format_json=True)
|
response = call_openai_chat(full_prompt, response_format_json=True)
|
||||||
print(response)
|
print(response)
|
||||||
@@ -262,7 +268,10 @@ def develop_strategy(data):
|
|||||||
lang = data.get('language', 'de')
|
lang = data.get('language', 'de')
|
||||||
sys_instr = get_system_instruction(lang)
|
sys_instr = get_system_instruction(lang)
|
||||||
phase3_json = json.dumps(phase3_result)
|
phase3_json = json.dumps(phase3_result)
|
||||||
prompt = f"PHASE 4: STRATEGY Matrix for {phase3_json}. Apply Hybrid logic. Output JSON ONLY."
|
prompt_template = """
|
||||||
|
PHASE 4: STRATEGY Matrix for {phase3_json_var}. Apply Hybrid logic. Output JSON ONLY.
|
||||||
|
"""
|
||||||
|
prompt = prompt_template.format(phase3_json_var=phase3_json)
|
||||||
full_prompt = sys_instr + "\n\n" + prompt
|
full_prompt = sys_instr + "\n\n" + prompt
|
||||||
response = call_openai_chat(full_prompt, response_format_json=True)
|
response = call_openai_chat(full_prompt, response_format_json=True)
|
||||||
print(response)
|
print(response)
|
||||||
@@ -271,7 +280,10 @@ def generate_assets(data):
|
|||||||
lang = data.get('language', 'de')
|
lang = data.get('language', 'de')
|
||||||
sys_instr = get_system_instruction(lang)
|
sys_instr = get_system_instruction(lang)
|
||||||
data_json = json.dumps(data)
|
data_json = json.dumps(data)
|
||||||
prompt = f"PHASE 5: GTM STRATEGY REPORT Markdown. Use facts, TCO, ROI. Data: {data_json}"
|
prompt_template = """
|
||||||
|
PHASE 5: GTM STRATEGY REPORT Markdown. Use facts, TCO, ROI. Data: {data_json_var}
|
||||||
|
"""
|
||||||
|
prompt = prompt_template.format(data_json_var=data_json)
|
||||||
full_prompt = sys_instr + "\n\n" + prompt
|
full_prompt = sys_instr + "\n\n" + prompt
|
||||||
response = call_openai_chat(full_prompt)
|
response = call_openai_chat(full_prompt)
|
||||||
print(json.dumps(response))
|
print(json.dumps(response))
|
||||||
@@ -280,7 +292,10 @@ def generate_sales_enablement(data):
|
|||||||
lang = data.get('language', 'de')
|
lang = data.get('language', 'de')
|
||||||
sys_instr = get_system_instruction(lang)
|
sys_instr = get_system_instruction(lang)
|
||||||
data_json = json.dumps(data)
|
data_json = json.dumps(data)
|
||||||
prompt = f"PHASE 6: Battlecards and MJ Prompts. Data: {data_json}. Output JSON ONLY."
|
prompt_template = """
|
||||||
|
PHASE 6: Battlecards and MJ Prompts. Data: {data_json_var}. Output JSON ONLY.
|
||||||
|
"""
|
||||||
|
prompt = prompt_template.format(data_json_var=data_json)
|
||||||
full_prompt = sys_instr + "\n\n" + prompt
|
full_prompt = sys_instr + "\n\n" + prompt
|
||||||
response = call_openai_chat(full_prompt, response_format_json=True)
|
response = call_openai_chat(full_prompt, response_format_json=True)
|
||||||
print(response)
|
print(response)
|
||||||
@@ -290,7 +305,7 @@ def main():
|
|||||||
parser.add_argument("--mode", type=str, required=True, help="Execution mode")
|
parser.add_argument("--mode", type=str, required=True, help="Execution mode")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
print(f"DEBUG: Orchestrator v1.2 loaded (Mode: {args.mode})", file=sys.stderr)
|
print(f"DEBUG: Orchestrator v{__version__} loaded (Mode: {args.mode})", file=sys.stderr)
|
||||||
|
|
||||||
if not sys.stdin.isatty():
|
if not sys.stdin.isatty():
|
||||||
try:
|
try:
|
||||||
@@ -319,4 +334,4 @@ def main():
|
|||||||
print(json.dumps({"error": f"Unknown mode: {args.mode}"}))
|
print(json.dumps({"error": f"Unknown mode: {args.mode}"}))
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
Reference in New Issue
Block a user