display diagram
This commit is contained in:
parent
0b5f3d6ac9
commit
b07191224e
123
generate_diagram.php
Normal file
123
generate_diagram.php
Normal file
@ -0,0 +1,123 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
require_once 'db/config.php';
|
||||
|
||||
// --- OpenAI API Configuration ---
|
||||
// IMPORTANT: Do not hardcode API keys in production. Use environment variables.
|
||||
// The key is temporarily used here for demonstration purposes as requested.
|
||||
// You should revoke this key and use getenv('OPENAI_API_KEY') instead.
|
||||
$openai_api_key = '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';
|
||||
$openai_api_url = 'https://api.openai.com/v1/chat/completions';
|
||||
|
||||
$profile_id = $_GET['id'] ?? null;
|
||||
|
||||
if (!$profile_id) {
|
||||
echo json_encode(['error' => 'Profile ID is missing.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$profile = null;
|
||||
try {
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare("SELECT * FROM gtm_profiles WHERE id = ?");
|
||||
$stmt->execute([$profile_id]);
|
||||
$profile = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
} catch (PDOException $e) {
|
||||
error_log($e->getMessage());
|
||||
echo json_encode(['error' => 'Database error while fetching profile.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!$profile) {
|
||||
echo json_encode(['error' => 'Profile not found.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// --- Prompt Engineering ---
|
||||
$profile_details = "
|
||||
- Ideal Customer Profile (ICP): {$profile['icp']}
|
||||
- Market Size: {$profile['market_size']}
|
||||
- Sales Motions: {$profile['sales_motions']}
|
||||
- Organization Size: {$profile['org_size']}
|
||||
- Sells What: {$profile['sells_what']}
|
||||
- Business Name: {$profile['business_name']}
|
||||
";
|
||||
|
||||
$prompt = "You are an expert Go-To-Market strategist. Based on the following company profile, generate a clear, customized GTM process flow diagram using Mermaid.js syntax.
|
||||
|
||||
Company Profile:
|
||||
{$profile_details}
|
||||
|
||||
Instructions:
|
||||
1. The diagram should visualize the ideal GTM workflow from customer acquisition to retention/upselling.
|
||||
2. The output MUST be a valid Mermaid.js graph, starting with 'graph TD;'.
|
||||
3. Use the format: A[\"Step 1\"] --> B[\"Step 2\"] --> C[\"Step 3\"];
|
||||
4. **Crucially, node text MUST be enclosed in double quotes**, like A[\"This is a node\"];
|
||||
5. The steps should be logical and tailored to the company's profile (e.g., a product-led motion should have steps like 'Free Tier Signup', while an enterprise motion should have 'SDR Touchpoint').
|
||||
6. Make the flow concise, with 5 to 7 key steps.
|
||||
7. Do not include any explanation, just the Mermaid.js code.
|
||||
|
||||
Example:
|
||||
graph TD;
|
||||
A[\"Lead Gen via Social Media\"] --> B[\"Free Tier Signup (Product-Led)\"];
|
||||
B --> C[\"Auto-Onboarding Email\"];
|
||||
C --> D[\"SDR Touchpoint\"];
|
||||
D --> E[\"Upsell via Partner Integration\"];";
|
||||
|
||||
// --- API Call via cURL ---
|
||||
$payload = [
|
||||
'model' => 'gpt-4o',
|
||||
'messages' => [
|
||||
['role' => 'system', 'content' => 'You are a GTM strategy expert that only outputs Mermaid.js code.'],
|
||||
['role' => 'user', 'content' => $prompt]
|
||||
],
|
||||
'max_tokens' => 300,
|
||||
'temperature' => 0.5,
|
||||
];
|
||||
|
||||
$ch = curl_init($openai_api_url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'Content-Type: application/json',
|
||||
'Authorization: Bearer ' . $openai_api_key
|
||||
]);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
// --- Process Response ---
|
||||
if ($http_code !== 200 || $response === false) {
|
||||
error_log("OpenAI API Error: HTTP {$http_code} - " . $response);
|
||||
echo json_encode(['error' => 'Failed to generate diagram from AI. The API returned an error.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$result = json_decode($response, true);
|
||||
$diagram = $result['choices'][0]['message']['content'] ?? 'graph TD; A[Error: Could not parse AI response];';
|
||||
|
||||
// --- Log the raw AI response for debugging ---
|
||||
$log_file = __DIR__ . '/../ai_responses.log';
|
||||
$log_entry = "---" . date('Y-m-d H:i:s') . " ---
|
||||
" . $diagram . "\n\n";
|
||||
file_put_contents($log_file, $log_entry, FILE_APPEND);
|
||||
|
||||
// Clean up the response and extract the Mermaid code
|
||||
$diagram = trim($diagram);
|
||||
|
||||
// Regex to find Mermaid code block, with or without backticks and optional "mermaid" label
|
||||
if (preg_match('/```(?:mermaid)?\s*(graph\s(TD|LR|BT|RL);?[\s\S]*?)```|^(graph\s(TD|LR|BT|RL);?[\s\S]*)/', $diagram, $matches)) {
|
||||
// We have two possible capture groups for the main content
|
||||
$mermaid_code = !empty($matches[1]) ? $matches[1] : $matches[3];
|
||||
$diagram = trim($mermaid_code);
|
||||
} else {
|
||||
// If no match, log the bad response and set an error for the user
|
||||
error_log("Invalid AI response format: " . $diagram);
|
||||
$diagram = "graph TD; A[Error: Invalid AI response format.];";
|
||||
}
|
||||
|
||||
|
||||
|
||||
echo json_encode(['diagram' => $diagram]);
|
||||
51
profile.php
51
profile.php
@ -70,7 +70,11 @@ if ($profile_id) {
|
||||
<?php if ($profile): ?>
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Business Name: <?php echo htmlspecialchars($profile['business_name']); ?></h5>
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h5 class="card-title mb-0">Business Name: <?php echo htmlspecialchars($profile['business_name']); ?></h5>
|
||||
<button id="generate-diagram-btn" class="btn btn-primary" data-profile-id="<?php echo htmlspecialchars($profile_id); ?>">Generate GTM Process Flow Diagram</button>
|
||||
</div>
|
||||
<div id="diagram-container" class="mb-4"></div>
|
||||
<p class="card-text"><strong>Sells What:</strong> <?php echo htmlspecialchars($profile['sells_what']); ?></p>
|
||||
<hr>
|
||||
<h6 class="card-subtitle mb-2 text-muted">Market & Sales</h6>
|
||||
@ -86,7 +90,7 @@ if ($profile_id) {
|
||||
<p class="card-text"><strong>Growth Goals:</strong> <?php echo htmlspecialchars($profile['goals']); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<?php else: ?>
|
||||
<div class="alert alert-warning" role="alert">
|
||||
No GTM profile found. Please <a href="list_profiles.php">select one</a> or <a href="start.php">create a new one</a>.
|
||||
</div>
|
||||
@ -98,6 +102,49 @@ if ($profile_id) {
|
||||
</footer>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script>
|
||||
<script>mermaid.initialize({ startOnLoad: false });</script>
|
||||
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const generateBtn = document.getElementById('generate-diagram-btn');
|
||||
const diagramContainer = document.getElementById('diagram-container');
|
||||
|
||||
if (generateBtn) {
|
||||
generateBtn.addEventListener('click', function () {
|
||||
const profileId = this.dataset.profileId;
|
||||
diagramContainer.innerHTML = '<div class="text-center"><div class="spinner-border" role="status"><span class="visually-hidden">Loading...</span></div><p>Generating diagram...</p></div>';
|
||||
generateBtn.disabled = true;
|
||||
|
||||
fetch(`generate_diagram.php?id=${profileId}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.error) {
|
||||
diagramContainer.innerHTML = `<div class="alert alert-danger">${data.error}</div>`;
|
||||
} else {
|
||||
const mermaidCode = data.diagram;
|
||||
diagramContainer.innerHTML = `
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">GTM Process Flow Diagram</h5>
|
||||
<div class="mermaid text-center">
|
||||
${mermaidCode}
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
mermaid.run();
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error generating diagram:', error);
|
||||
diagramContainer.innerHTML = '<div class="alert alert-danger">An error occurred while generating the diagram.</div>';
|
||||
})
|
||||
.finally(() => {
|
||||
generateBtn.disabled = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
x
Reference in New Issue
Block a user