using BLAIzor.Services; using System.Text; namespace BLAIzor.Models { public static class AiPrompts { public static class WelcomeContent { public static string GetSystemMessageForWelcomeMessage(string mood, string siteEntity, string extractedText, string selectedBrandName, string language, string menuList) { string systemMessage = "You are a helpful, " + mood + " assistant that welcomes the user speaking in the name of the " + siteEntity + " described by the content, on a website of " + selectedBrandName + " in " + language + ". Use the following content: `" + extractedText + "` " + //"and generate a short" +Mood+ "but kind marketing-oriented welcome message and introduction of the brand for the user, constructed as simple Bootstrap HTML codeblock with a

tagged title and a paragraph." + "and generate a" + mood + " marketing-oriented welcome message and a summary of the content and introduction " + "of the brand for the user in the name of " + siteEntity + " , aiming to explain clearly, what does the company/person offer, constructed " + "as simple Bootstrap HTML
codeblock with a

tagged title and a paragraph." + "If there is any logo, or not logo but main brand image in the document use that url, " + "and add that in a new container, as a bootstrap responsive ('img-fluid py-3') image, with the maximum height of 30vh." + "If there is anything marked important in the text, make sure to add that in your answer." + "If there are links to be displayed, make sure to display them as clickable links." + "After the welcome message, always add in a new div with container class: 'This website has a live, " + "AI interface: if you have any questions, you can simply ask either by typing in the message " + "box, or by clicking the microphone icon on the top of the page. '" + "Here is a list of topics " + menuList + ", make a new bootstrap clearfix and after that make a clickable bootstrap " + "styled (btn btn-primary) button from each of the determined topics, " + "that calls the javascript function 'callAI({the name of the topic})' on click. " + "Do not include anything else than the html title and text elements, no css, no scripts, no head or other tags." + "Do not mark your answer with ```html or any other mark."; return systemMessage; } } public static class UserIntention { } public static class ContentProcessing { public static string GetSystemMessageForJsonResultDecision(string language, string extractedText, string currentDom) { string systemMessage = $"You are a helpful assistant built in a website, trying to figure out what the User wants to do or know about.\r\n" + "Your job is to classify the user's request into one of the following categories:\r\n" + "1. **Ask about or search infromation in the website’s content** (Return a 'Text result')\r\n" + "2. **Analyze the currently displayed HTML content** (Return an 'Examination result')\r\n" + "3. **Initiate an action** (Return a 'Method result')\r\n" + "If none of the above applies, return an 'Error result'.\r\n\r\n" + "**Response format:**\r\n" + "Strictly respond in " + language + " as a JSON object, using one of the following formats:\r\n" + "1. **chatGPTMethodResult** (for initiating actions):\r\n" + " - `type`: \"methodresult\"\r\n" + " - `text`: A short explanation of what the user wants to do.\r\n" + " - `methodToCall`: One of: [openContactForm, openCalendar, openApplicationForm]\r\n" + " - `parameter`: [email address for openContactForm, calendlyUserName for openCalendar, empty string for openApplicationForm]\r\n\r\n" + "2. **chatGPTTextResult** (for general website content searches):\r\n" + " - `type`: \"textresult\"\r\n" + " - `text`: The user’s unmodified query.\r\n\r\n" + "3. **chatGPTExaminationResult** (for analyzing the currently displayed page only):\r\n" + " - `type`: \"examinationresult\"\r\n" + " - `text`: The user’s unmodified query.\r\n\r\n" + "4. **chatGPTErrorResult** (for errors):\r\n" + " - `type`: \"errorresult\"\r\n" + " - `text`: A description of the issue encountered.\r\n\r\n" + "**Decision Rules:**\r\n" + "- If the user is **searching for website content** beyond what is currently displayed (e.g., 'Find information about our services'), return a `textresult`.\r\n" + "- If the user is **asking about the currently visible content** (e.g., 'What is shown on the page?'), return an `examinationresult`.\r\n" + "- If the user wants to **perform an action**, return a `methodresult`.\r\n" + "- If the required parameter is missing, return an `errorresult`.\r\n\r\n" + "**Examples:**\r\n" + "- User asks: 'Show me information about pricing' → `textresult`\r\n" + "- User asks: 'What is displayed right now?' → `examinationresult`\r\n" + "- User asks: 'Open the contact form' → `methodresult`\r\n" + "- User asks: 'Contact support' but no email is found → `errorresult`\r\n\r\n" + "**Context:**\r\n" + "- Base responses on this initial document: {" + extractedText + "}\r\n" + "- Current displayed HTML: {" + currentDom + "}\r\n" + "**IMPORTANT:**\r\n" + "- If the request is about general content, **DO NOT use 'examinationresult'**.\r\n" + "- If the request is about the currently displayed page, **DO NOT use 'textresult'**.\r\n" + "- Do NOT format the response with markdown, code blocks, or `json` tags, do not add any title, or explanation besides the plain json object"; return systemMessage; } } public static class HtmlGeneration { public const string BootstrapCard = "Generate a Bootstrap 5 card layout using the following content:"; public const string SectionLayout = "Create a responsive HTML5 layout section for this text:"; } public static class LayoutPlanning { public static string GetLayoutPlanningSystemPrompt(List htmlToUse, Dictionary? photos, string[]? topics) { var sb = new StringBuilder(); // 📌 STRICT FORMAT INSTRUCTION sb.AppendLine("You are a helpful assistant whose ONLY task is to break down THE PROVIDED CONTENT into a structured JSON object for Bootstrap 5 pages, using \n" + "**layoutplan**:\r\n" + "- `title`: \"The title of the page\"\r\n" + "- `blocks`: \"an array of layoutblocks\"\r\n" + "."); if ((htmlToUse != null)) { sb.AppendLine("\n### You have these html snippets provided:"); foreach (var snippet in htmlToUse) { //no need to paste the html code //sb.AppendLine($"Snippet id: {snippet.Id}, Snippet name: {snippet.Name}, Snippet description: {snippet.Description}, Snippet type: {snippet.Type}, Snippet template code: {snippet.Html}"); sb.AppendLine($"Snippet id: {snippet.Id}, Snippet name: {snippet.Name}, Snippet description: {snippet.Description}, Snippet type: {snippet.Type}"); } sb.AppendLine("- Use them ONLY if relevant."); } if (photos != null && photos.Any()) { sb.AppendLine("\n### Photos to be used in the blocks:"); sb.AppendLine(string.Join(", ", photos.Select(kv => $"{kv.Key}: {kv.Value}"))); } if (topics != null && topics.Any()) { sb.AppendLine("\n### Topics:"); sb.AppendLine(string.Join(", ", topics)); } sb.AppendLine("### ⛔️ ABSOLUTELY DO NOT:"); sb.AppendLine("- ❌ Return HTML structure trees like `
`..."); sb.AppendLine("- ❌ Include keys like `src`, `alt`, `url`, `items`, or nested object lists."); sb.AppendLine("- ❌ Invent block types not on the list."); sb.AppendLine("- ❌ Return any explanation, markdown, prose, comments, or fallback formats."); sb.AppendLine("- ❌ Use any of these block types: `image`, `quote`, `list`, `layout`, `header`, `footer`, `sidebar`, etc."); sb.AppendLine("- ❌ Remove messages for AI marked with []"); sb.AppendLine("\n### ✅ REQUIRED OUTPUT FORMAT:"); sb.AppendLine("{"); sb.AppendLine(" \"title\": \"string\","); sb.AppendLine(" \"blocks\": ["); sb.AppendLine(" { \"type\": \"string\", \"rawcontent\": \"string (text)\", \"preferredsnippetid\" : an integer id of matching html snippet if one found., \"order\": an incremented integer to set the blocks in order }"); sb.AppendLine(" ]"); sb.AppendLine("}"); sb.AppendLine("\n### ✅ Allowed `type` values (only use these):"); sb.AppendLine("- hero"); sb.AppendLine("- text"); sb.AppendLine("- text-image"); sb.AppendLine("- features"); sb.AppendLine("- cta"); sb.AppendLine("- video"); sb.AppendLine("- icon-list"); sb.AppendLine("- event-list"); sb.AppendLine("- audio-player"); sb.AppendLine("- topic-buttons"); sb.AppendLine("\n### ❗ GOOD EXAMPLE:"); sb.AppendLine("{"); sb.AppendLine(" \"title\": \"Welcome to Our Product\","); sb.AppendLine(" \"blocks\": ["); sb.AppendLine(" { \"type\": \"hero\", \"rawcontent\": \"Example text\", \"preferredsnippetid\": 1, \"order\": 0 },"); sb.AppendLine(" { \"type\": \"features\", \"rawcontent\": \"Example features\", \"order\": 1 },"); sb.AppendLine(" { \"type\": \"cta\", \"rawcontent\": \"call to action content\", \"order\": 2 }"); sb.AppendLine(" ]"); sb.AppendLine("}"); sb.AppendLine("\n### ⛔ BAD EXAMPLES (DO NOT DO THIS):"); sb.AppendLine("- { \"type\": \"image\", \"src\": \"...\", \"alt\": \"...\" }"); sb.AppendLine("- { \"type\": \"list\", \"items\": [\"...\", \"...\"] }"); sb.AppendLine("- { \"layout\": { \"header\": ..., \"footer\": ... } }"); sb.AppendLine("\n### FINAL TASK:"); sb.AppendLine("Based on the following content, generate a JSON object following the exact format above. Output only the JSON. No markdown. No other marks. No explanation. ONLY the pure JSON."); return sb.ToString(); } public static string GetLayoutPlanningUserPrompt(string interMediateResult, string pageTitle, Dictionary? photos) { var userMessage = "Based on the following content:\n\n*** " + interMediateResult + " ***\n\n" + "and the available photos:"; if (photos != null && photos.Any()) { userMessage += "\n### Photo urls to be used WITHOUT ANY MODIFICATION in the blocks:"; userMessage += string.Join(", ", photos.Select(kv => $"{kv.Key}: {kv.Value}")); } userMessage += ", return ONLY a JSON object representing a structured content layout for a webpage with the title '" + pageTitle + "', with this exact shape:\n" + "{ \"title\": string, \"blocks\": [ { \"type\": \"string\", \"rawcontent\": \"string (text)\", \"preferredsnippetid\" : an integer id of matching html snippet if one found., \"order\": an incremented integer to set the blocks in order } ] }\n\n" + "⚠️ DO NOT use layout structures like 'header', 'sidebar', 'mainContent', or 'footer'.\n" + "⚠️ DO NOT explain anything. Just return the pure JSON. No markdown, no ``` markers.\n\n" + "🎯 OBJECTIVE:\n" + "1. Determine 1 to 5 major content blocks from the input, grouping full paragraphs or sections together.\n" + "Prefer **1 to 5 blocks max**, unless the content is extremely long. Each block should represent a semantically complete section.\r\n" + "Group related ideas into one block, even if they are multiple paragraphs. Do NOT break up content just because it is a new sentence. \r\n" + "2. Use meaningful, semantically grouped layout block types like: 'hero', 'features list', 'text with image', 'text', 'product list', 'call to action', 'videoplayer', 'audioplayer', etc.\n" + "3. Each block should contain **rich content** and related photo ['photo url': 'the url of the photo'], not just one or two sentences. Group related ideas into a single `rawcontent` field.\n\n" + "DO NOT REMOVE ANY URLS (photo, wen link, etc) from the section or paragraph that it follows. \n\n" + "📌 Examples of good block grouping:\n" + "- All introductory marketing text together in one 'hero' or 'text' block\n" + "- A group of benefits or features into a single 'features' block\n" + "- A pitch paragraph into a 'call to action' block\n\n" + "🎨 Naming:\n" + "- Try to find related type values in the available snippets list. If you find a relevant snippet for that block, use the name of that snippet for type, and add the id if the snippet as preferredsnippetid." + "- If there is no relevant snippet, use such layout `type` values: hero, text, features, text with image, call to action, product list, team members, testimonial, event list, blogpost, article, video player, audio player, etc\n" + "X Restrictions:" + "- DO **NOT** modify the photo urls in any way." + "- DO **NOT use the same text multiple times**" + "- Do **NOT** generate or assume new photo URLs.\n" + "- Do **NOT** modify photo URLs in any way.\n" + "- Do **NOT** skip or deny ANY part of the provided text. All of the provided text should be put in blocks \n" + "- Do **NOT** assume ANY content, like missing prices, missing links, etc. \n" + "✅ Final output: JSON only, well grouped, no extra explanation or formatting, no markdown, no ``` markers.\n"; return userMessage; } } public static class HtmlRendering { public static string GetHtmlRenderingSystemPromptForTextAndErrorResult(string language, string pageTitle, List htmlToUse, Dictionary? photos, string[]? topics) { var sb = new StringBuilder($"You are a helpful assistant generating HTML in {language} using Bootstrap 5.\n\n" + "### General Instructions:\n" + "- Output only the **HTML content** between the menu and footer.\n" + "- DO NOT include ``, ``, or markdown formatting.\n" + "- Use `

` for the title: " + pageTitle + ".\n" + "- Structure sections inside separate `
` or `
` blocks.\n" + "- Use Bootstrap spacing and layout classes:\n" + " - Use `row justify-content-center` for rows.\n" + " - Use `col-xx-x` only for multiple-column layouts.\n" + " - Always use `img-fluid` for images.\n" + "- Avoid: unnecessary paragraph classes, nesting `` inside `

`, or using `col` for single-column content.\n\n"); if (htmlToUse != null && htmlToUse.Any()) { sb.AppendLine("### Snippet Handling:\n" + "- You are provided with multiple HTML snippets:\n"); foreach (var snippet in htmlToUse) { sb.AppendLine($"{snippet.Id}: {snippet.Name}: {snippet.Html}\n"); sb.AppendLine($"Type: {snippet.Type}, Tags: {snippet.Tags}, Variant: {snippet.Variant}\n"); } sb.AppendLine( "- Use each snippet as a separate `

`.\n" + "- DO NOT merge snippets into one block.\n" + "- Use snippets only if they match the content block.\n" + "- Prefer variants with images if image content is present.\n" + "- Always use a short title in `` and place body text in a `

`.\n" + "- If snippet includes a button, wrap it in `

`.\n"); } if (photos != null && photos.Any()) { sb.AppendLine("### Photo Usage:\n" + "- Use ONLY the following image URLs as-is (no changes):\n" + string.Join(", ", photos.Select(kv => $"{kv.Key}: {kv.Value}")) + "\n" + "- Example:\n" + $" {photos.First().Key}\n" + "- DO NOT generate or modify photo URLs.\n"); } if (topics != null && topics.Any()) { sb.AppendLine("### Topic Buttons:\n" + "- Place this section last, titled `Related`.\n" + "- Generate a `btn btn-primary` for each topic, calling `callAI('{original_non_translated_topicName}')`.\n" + "- Translate topic names to " + language + " if needed.\n" + "- Example:\n" + $" \n"); } else { sb.AppendLine("- No topics provided → DO NOT generate topic buttons."); } sb.AppendLine("\n### DO NOT:\n" + "- DO **NOT** merge different content blocks.\n" + "- DO **NOT** remove javascript or