Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MauiAppAISample"
x:Class="MauiAppAISample.App">
<Application.Resources>
<ResourceDictionary>

<!--
For information about styling .NET MAUI pages
please refer to the documentation:
https://go.microsoft.com/fwlink/?linkid=2282329
-->

</ResourceDictionary>
</Application.Resources>
</Application>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace MauiAppAISample
{
public partial class App : Application
{
public App()
{
InitializeComponent();
}

protected override Window CreateWindow(IActivationState? activationState)
{
return new Window(new MainPage()) { Title = "MauiAppAISample" };
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@inherits LayoutComponentBase

<div class="page">
<main>
@Body
</main>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
.page {
position: relative;
display: flex;
flex-direction: column;
}

main {
flex: 1;
}

.sidebar {
background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
}

.top-row {
background-color: #f7f7f7;
border-bottom: 1px solid #d6d5d5;
justify-content: flex-end;
height: 3.5rem;
display: flex;
align-items: center;
}

.top-row ::deep a, .top-row ::deep .btn-link {
white-space: nowrap;
margin-left: 1.5rem;
text-decoration: none;
}

.top-row ::deep a:hover, .top-row ::deep .btn-link:hover {
text-decoration: underline;
}

.top-row ::deep a:first-child {
overflow: hidden;
text-overflow: ellipsis;
}

@media (max-width: 640.98px) {
.top-row {
justify-content: space-between;
}

.top-row ::deep a, .top-row ::deep .btn-link {
margin-left: 0;
}
}

@media (min-width: 641px) {
.page {
flex-direction: row;
}

.sidebar {
width: 250px;
height: 100vh;
position: sticky;
top: 0;
}

.top-row {
position: sticky;
top: 0;
z-index: 1;
}

.top-row.auth ::deep a:first-child {
flex: 1;
text-align: right;
width: 0;
}

.top-row, article {
padding-left: 2rem !important;
padding-right: 1.5rem !important;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using Microsoft.Extensions.AI;
using Syncfusion.Blazor.AI;
using System;

namespace AIService
{
public class AzureAIService
{
private IChatClient _chatClient;

public AzureAIService(IChatClient client)
{
this._chatClient = client ?? throw new ArgumentNullException(nameof(client));
}

public async Task<string> GetCompletionAsync(string prompt, bool returnAsJson = true, string systemRole = null, int outputTokens = 2000)
{
string systemMessage = returnAsJson ? "You are a helpful assistant that only returns and replies with valid, iterable RFC8259 compliant JSON in your responses unless I ask for any other format. Do not provide introductory words such as 'Here is your result' or '```json', etc. in the response" : !string.IsNullOrEmpty(systemRole) ? systemRole : "You are a helpful assistant";
try
{
ChatParameters chatParameters = new ChatParameters();
chatParameters.Messages = new List<ChatMessage>(2) {
new ChatMessage (ChatRole.System, systemMessage),
new ChatMessage(ChatRole.User,prompt),
};
string completion = await GetChatResponseAsync(chatParameters);
return completion;
}
catch (Exception ex)
{
Console.WriteLine($"An exception has occurred: {ex.Message}");
return "";
}
}

public async Task<string> GetChatResponseAsync(ChatParameters options)
{
ChatOptions completionRequest = new ChatOptions
{
Temperature = options.Temperature ?? 0.5f,
TopP = options.TopP ?? 1.0f,
MaxOutputTokens = options.MaxTokens ?? 2000,
FrequencyPenalty = options.FrequencyPenalty ?? 0.0f,
PresencePenalty = options.PresencePenalty ?? 0.0f,
StopSequences = options.StopSequences
};
try
{
ChatResponse completion = await _chatClient.GetResponseAsync(options.Messages, completionRequest);
return completion.Text.ToString();
}
catch (Exception ex)
{
throw;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
@using Syncfusion.Blazor.Popups
@using Syncfusion.Blazor.Buttons
@using Syncfusion.Blazor.Inputs
@using AIService
@inject AzureAIService ChatGptService
@namespace TextToMindMapDiagram

<SfFab IconCss="e-icons e-ai-chat" Content="AI Assist" OnClick="OnFabClicked" Target="#diagram-area"></SfFab>
<SfDialog Width="570px" IsModal="true" ShowCloseIcon="true" CssClass="custom-dialog" Visible="@ShowAIAssistDialog">
<DialogTemplates>
<Header> <span class="e-icons e-ai-chat" style="color: black; font-size: 16px;"></span> AI Assist</Header>
<Content>
<p style="margin-bottom: 10px;">Suggested Prompts</p>
<SfButton style="flex: 1; overflow: visible; border-radius: 8px;margin-bottom: 10px;" @onclick="() => GenerateMindMap(MobileBankingPrompt)">Mindmap diagram for Mobile banking registration</SfButton>
<SfButton style="flex: 1; overflow: visible; border-radius: 8px;margin-bottom: 10px;" @onclick="() => GenerateMindMap(OrganizationalResearchPrompt)">Mindmap diagram for Organizational research</SfButton>
<SfButton style="flex: 1; overflow: visible; border-radius: 8px;margin-bottom: 10px;" @onclick="() => GenerateMindMap(MeetingAgendaPrompt)">Mindmap diagram for Meeting agenda</SfButton>

<div style="display: flex; flex: 95%; margin-top:20px;">
<SfTextBox @bind-Value="@OpenAIPrompt" CssClass="db-openai-textbox" Height="32px" Placeholder="Please enter your prompt for generating a mindmap diagram..." autofocus style="font-size: 14px;"></SfTextBox>
<SfButton @onclick="@GetResponseFromAI" CssClass="e-icons e-flat e-send" IsPrimary="true" style="height: 38px; width: 38px; margin-left: 5px; padding: 0;"></SfButton>
</div>
</Content>
</DialogTemplates>
<DialogEvents Closed="@DialogClose"></DialogEvents>
</SfDialog>
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
namespace TextToMindMapDiagram
{
public partial class DiagramOpenAI
{
public Home Parent;
public bool ShowAIAssistDialog = false;
public string OpenAIPrompt;
string MobileBankingPrompt = "Mindmap diagram for Mobile banking registration";
string OrganizationalResearchPrompt = "Mindmap diagram for Organizational research";
string MeetingAgendaPrompt = "Mindmap diagram for Meeting agenda";
public void OnFabClicked()
{
ShowAIAssistDialog = !ShowAIAssistDialog;
}
private void DialogClose(Object args)
{
ShowAIAssistDialog = false;
}

public async void GenerateMindMap(string value)
{
OpenAIPrompt = value;
await GetResponseFromAI();
StateHasChanged();
}

public async Task GetResponseFromAI()
{
Parent.IsGeneratingFromAI = true;
ShowAIAssistDialog = false;
if (!string.IsNullOrWhiteSpace(OpenAIPrompt))
{
await Parent.SpinnerRef!.ShowAsync();
string result = string.Empty;
string systemRole = "You are an expert in creating mind map diagram data sources. Generate a structured data source for a mind map based on the user's query, using tab indentation to indicate hierarchy. The root parent should have no indentation, while each subsequent child level should be indented by one tab space. Avoid using any symbols such as '+' or '-' before any level of data.";
string userPrompt = $"Based on the following input, create a mind map diagram data source: {OpenAIPrompt}.";
result = await ChatGptService.GetCompletionAsync(userPrompt, false, systemRole);
if (result != null)
{
List<string> filteredData = result
.Split(new[] { "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries)
.Where(line => !string.IsNullOrWhiteSpace(line))
.ToList();
if (filteredData[0].Trim() != "mindmap")
filteredData.Insert(0, "mindmap");
filteredData[1].TrimStart('-', '+');
result = string.Join("\n", filteredData);
Parent.Diagram!.BeginUpdate();
Parent.Diagram.StartGroupAction();
await Parent.Diagram.LoadDiagramFromMermaidAsync(result);
Parent.Diagram.EndGroupAction();
await Parent.Diagram.EndUpdateAsync();
StateHasChanged();
}
await Parent.SpinnerRef.HideAsync();
}
Parent.IsGeneratingFromAI = false;
}
}
}
Loading