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
9 changes: 7 additions & 2 deletions AiAssistview/AiAssistview.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Syncfusion.Blazor.InteractiveChat" Version="31.1.23" />
<PackageReference Include="Syncfusion.Blazor.Themes" Version="31.1.23" />
<PackageReference Include="Azure.AI.OpenAI" Version="2.1.0" />
<PackageReference Include="Markdig" Version="0.44.0" />
<PackageReference Include="Microsoft.Extensions.AI" Version="10.0.1" />
<PackageReference Include="Mscc.GenerativeAI" Version="2.9.3" />
<PackageReference Include="OllamaSharp" Version="5.4.11" />
<PackageReference Include="Syncfusion.Blazor.InteractiveChat" Version="31.2.15" />
<PackageReference Include="Syncfusion.Blazor.Themes" Version="31.2.15" />
</ItemGroup>

</Project>
12 changes: 6 additions & 6 deletions AiAssistview/Components/App.razor
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@
display: flex;
}

.content table {
display: block;
margin: 50px 10px;
}
.content table {
display: block;
margin: 50px 10px;
}

.aiassist-container {
margin: 10% auto;
}
margin: 10% auto;
}
</style>
</head>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<table>
<tr>
<td>
<a href="geminiintegration">1.Gemini Integration</a>
<a href="openaiintegration">2.open AI Integration</a>
<a href="geminiintegration">1.Gemini Integration</a><br><br>
<a href="openaiintegration">2.open AI Integration</a><br><br>
<a href="ollamallmintegration">3.Ollama LLM Integration</a>
</td>
</tr>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@page "/openaiintegration"
@rendermode InteractiveServer

@using AIAssistView_AzureAI.Components.Services
@using AIAssistview.Components.Services
@using Syncfusion.Blazor.InteractiveChat
@using Syncfusion.Blazor.Navigations
@inject AzureOpenAIService OpenAIService
Expand Down
2 changes: 1 addition & 1 deletion AiAssistview/Components/Pages/Speech/SpeechNav.razor
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<table>
<tr>
<td>
<a href="speechtotext">1.SpeechToText</a>
<a href="speechtotext">1.SpeechToText</a><br><br>
<a href="texttospeech">2.TextToSpeech</a>
</td>
</tr>
Expand Down
4 changes: 2 additions & 2 deletions AiAssistview/Components/Pages/Speech/SpeechToText.razor
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
@rendermode InteractiveServer

@using Syncfusion.Blazor.InteractiveChat
@using AssistView_OpenAI.Components.Services
@using AIAssistview.Components.Services
@using Syncfusion.Blazor.Navigations
@using Syncfusion.Blazor.Inputs
@using Syncfusion.Blazor.Buttons
Expand Down Expand Up @@ -174,7 +174,7 @@
display: none;
}

@media only screen and (max-width: 750px) {
@@media only screen and (max-width: 750px) {
.integration-speechtotext-section {
width: 100%;
}
Expand Down
6 changes: 3 additions & 3 deletions AiAssistview/Components/Pages/Speech/TextToSpeech.razor
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
@rendermode InteractiveServer

@using Syncfusion.Blazor.InteractiveChat
@using AssistView_OpenAI.Components.Services
@using AIAssistview.Components.Services
@using Syncfusion.Blazor.Navigations
@inject AzureOpenAIService OpenAIService
@inject IJSRuntime JSRuntime
Expand Down Expand Up @@ -42,7 +42,7 @@
private string audioTooltip = "Read Aloud";
private bool IsSpeaking = false;
// If component class name isn’t Home (file is not Home.razor), update DotNetObjectReference to match the actual component type.
private DotNetObjectReference<Home>? dotNetRef;
private DotNetObjectReference<TextToSpeech>? dotNetRef;

protected override void OnInitialized()
{
Expand Down Expand Up @@ -159,7 +159,7 @@
gap: 10px;
text-align: center;
}
@media only screen and (max-width: 750px) {
@@media only screen and (max-width: 750px) {
.integration-texttospeech-section {
width: 100%;
}
Expand Down
87 changes: 87 additions & 0 deletions AiAssistview/Components/Service/AzureOpenaiService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using System.Text.Json;
using Markdig;
using System.Text.RegularExpressions;

namespace AIAssistview.Components.Services
{
public class AzureOpenAIService
{
private readonly HttpClient _httpClient;
private readonly string _endpoint;
private readonly string _apiKey;
private readonly string _deploymentName;

public AzureOpenAIService(HttpClient httpClient, string endpoint, string apiKey, string deploymentName)
{
_httpClient = httpClient;
_endpoint = endpoint;
_apiKey = apiKey;
_deploymentName = deploymentName;
}

public async IAsyncEnumerable<string> GetChatResponseStreamAsync(string prompt)
{
var request = new
{
messages = new[] { new { role = "user", content = prompt } },
max_tokens = 500,
};

var url = $"{_endpoint}/openai/deployments/{_deploymentName}/chat/completions?api-version=2024-02-15-preview";
_httpClient.DefaultRequestHeaders.Add("api-key", _apiKey);

Stream responseStream = null;
List<string> results = new List<string>();

try
{
var response = await _httpClient.PostAsJsonAsync(url, request);

if (response.IsSuccessStatusCode)
{
responseStream = await response.Content.ReadAsStreamAsync();
using var jsonDocument = JsonDocument.Parse(responseStream);
var choices = jsonDocument.RootElement.GetProperty("choices");
if (choices.GetArrayLength() > 0)
{
var content = choices[0].GetProperty("message").GetProperty("content").GetString();
var htmlContent = Markdown.ToHtml(content);
htmlContent = Regex.Replace(htmlContent, @"\s+", " ").Trim();
// Collect each character to the results list before yielding
foreach (var chunk in htmlContent)
{
results.Add(chunk.ToString());
}
}
else
{
results.Add("Error: No choices returned in the response.");
}
}
else
{
var error = await response.Content.ReadAsStringAsync();
results.Add($"Error: {error}");
}
}
catch (Exception ex)
{
// Collect the error message to be yielded later
results.Add($"Error: {ex.Message}");
}
finally
{
if (responseStream != null)
{
responseStream.Dispose();
}
}

// Now yield each collected result
foreach (var result in results)
{
yield return result;
}
}
}
}
15 changes: 13 additions & 2 deletions AiAssistview/Program.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
using AiAssistview.Components;
using AIAssistView_AzureAI.Components.Services;
using Syncfusion.Blazor;
using AIAssistview.Components.Services;
using Microsoft.Extensions.AI;
using OllamaSharp;
using Azure.AI.OpenAI;
using Azure;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();
builder.Services.AddSyncfusionBlazor();

builder.Services.AddHttpClient();
builder.Services.AddScoped<AzureOpenAIService>(sp =>
{
var httpClientFactory = sp.GetRequiredService<IHttpClientFactory>();
Expand All @@ -21,6 +25,13 @@
return new AzureOpenAIService(httpClient, endpoint, apiKey, deploymentName);
});

builder.Services.AddDistributedMemoryCache();

// Ollama configuration
builder.Services.AddChatClient(new OllamaApiClient(new Uri("http://localhost:11434/"), "llama3.2"))
.UseDistributedCache()
.UseLogging();

var app = builder.Build();

// Configure the HTTP request pipeline.
Expand Down
32 changes: 32 additions & 0 deletions AiAssistview/wwwroot/Script/speechtotext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Checks if the contenteditable element contains meaningful text and cleans up.
window.isFooterContainsValue = function (elementref) {
if (!elementref) return "";

const text = (elementref.innerText || "").trim();

// If empty, normalize stray <br> or empty HTML to empty string
if (text === "") {
const html = (elementref.innerHTML || "").trim();
if (html === "<br>" || html === "") {
elementref.innerHTML = "";
}
return "";
}

return elementref.innerText || "";
};

// Clears the text content of a contenteditable element.
window.emptyFooterValue = function (elementref) {
if (elementref) {
elementref.innerText = "";
}
};

// Updates the text content of a contenteditable element with a specified value.
window.updateContentEditableDiv = function (element, value) {
if (element) {
// Using innerText preserves plain text; switch to innerHTML if you need HTML.
element.innerText = value || "";
}
};