-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
11 changed files
with
503 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
@using My1kWordsEe.Services; | ||
@using My1kWordsEe.Models; | ||
@using CSharpFunctionalExtensions; | ||
|
||
@inject OpenAiService OpenAiService; | ||
@inject TartuNlpService TartuNlpService; | ||
@inject StabilityAiService StabilityAiService; | ||
@inject IJSRuntime JS | ||
|
||
@code { | ||
[Parameter] | ||
public SampleSentence Sample { get; set; } | ||
|
||
protected override async Task OnInitializedAsync() | ||
{ | ||
} | ||
|
||
private async Task PlaySample(MouseEventArgs e) | ||
{ | ||
await JS.InvokeVoidAsync("playAudioSample", Sample.EeAudioUrl); | ||
} | ||
} | ||
|
||
<script> | ||
window.playAudioSample = async (audioId) => { | ||
const audio = document.getElementById(audioId); | ||
await audio.play(); | ||
}; | ||
</script> | ||
|
||
<div class="col-sm-6"> | ||
|
||
<ul class="list-group"> | ||
<li class="list-group-item"> | ||
@Sample.EeSentence | ||
<button type="button" class="btn btn-primary" @onclick="PlaySample"> | ||
<i class="bi bi-volume-down-fill"></i> | ||
<audio id="@Sample.EeAudioUrl" src="@Sample.EeAudioUrl"></audio> | ||
</button> | ||
</li> | ||
<li class="list-group-item"> | ||
@Sample.EnSentence | ||
</li> | ||
<li class="list-group-item"> | ||
<img id="sampleImage" width="256" height="256" src="@Sample.ImageUrl" /> | ||
</li> | ||
</ul> | ||
|
||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
@page "/word/{eeWord}" | ||
@rendermode InteractiveServer | ||
|
||
@using CSharpFunctionalExtensions | ||
@using My1kWordsEe.Services; | ||
@using My1kWordsEe.Models; | ||
@using My1kWordsEe.Components.Layout; | ||
@using My1kWordsEe.Services.Cqs; | ||
|
||
@inject IJSRuntime JS | ||
@inject EnsureWordCommand EnsureWordCommand | ||
@inject CreateSampleCommand CreateSampleCommand | ||
|
||
@code { | ||
[Parameter] | ||
public string EeWord { get; set; } | ||
|
||
private Result<SampleWord>? WordMetadata; | ||
|
||
protected override async Task OnInitializedAsync() | ||
{ | ||
WordMetadata = await this.EnsureWordCommand.Invoke(EeWord); | ||
} | ||
|
||
private bool isGenerationInProgress = false; | ||
|
||
private async Task GenerateSample(MouseEventArgs e) | ||
{ | ||
this.isGenerationInProgress = true; | ||
if (WordMetadata.HasValue) | ||
{ | ||
this.WordMetadata = await this.CreateSampleCommand.Invoke(WordMetadata.Value.Value); | ||
} | ||
this.isGenerationInProgress = false; | ||
} | ||
} | ||
|
||
<div class="text-left"> | ||
<div class="row"> | ||
<h1>@EeWord | ||
</h1> | ||
|
||
@if (WordMetadata.HasValue) | ||
{ | ||
if (WordMetadata.Value.IsSuccess) | ||
{ | ||
<h3>[@WordMetadata.Value.Value.EnWord]</h3> | ||
|
||
@if (WordMetadata.Value.Value.EnWords.Any()) | ||
{ | ||
<h4>[@string.Join(" / ", WordMetadata.Value.Value.EnWords)]</h4> | ||
} | ||
|
||
<h3>@WordMetadata.Value.Value.EnExplanation</h3> | ||
} | ||
else | ||
{ | ||
<h3>@WordMetadata.Value.Error</h3> | ||
} | ||
} | ||
else | ||
{ | ||
<div class="d-flex justify-content-center"> | ||
<div class="spinner-border" role="status"> | ||
<span class="visually-hidden">Loading...</span> | ||
</div> | ||
</div> | ||
} | ||
</div> | ||
|
||
@if (this.WordMetadata.HasValue && this.WordMetadata.Value.IsSuccess) | ||
{ | ||
<div class="row"> | ||
@foreach (var sample in this.WordMetadata.Value.Value.Samples) | ||
{ | ||
<SampleV2 Sample="@sample"> | ||
</SampleV2> | ||
} | ||
|
||
<div class="col-sm-6"> | ||
@if (this.isGenerationInProgress) | ||
{ | ||
<div class="d-flex justify-content-center"> | ||
<div class="spinner-border" role="status"> | ||
<span class="visually-hidden">Loading...</span> | ||
</div> | ||
</div> | ||
} | ||
else | ||
{ | ||
<button type="button" class="btn btn-primary" onclick="@GenerateSample"> | ||
<i class="bi bi-robot"></i> | ||
Generate sample sentence | ||
</button> | ||
} | ||
|
||
</div> | ||
</div> | ||
} | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
using System.Text.Json.Serialization; | ||
|
||
namespace My1kWordsEe.Models | ||
{ | ||
public class SampleSentence | ||
{ | ||
public string EeWord { get; set; } | ||
|
||
public string EeSentence { get; set; } | ||
|
||
public string EnSentence { get; set; } | ||
|
||
public Uri EeAudioUrl { get; set; } | ||
|
||
public Uri ImageUrl { get; set; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
namespace My1kWordsEe.Models | ||
{ | ||
public record SampleWord | ||
{ | ||
|
||
private string eeWord = ""; | ||
private string[] enWords = []; | ||
|
||
private SampleSentence[] samples = []; | ||
|
||
|
||
/// <summary> | ||
/// Estonian word | ||
/// </summary> | ||
public string EeWord | ||
{ | ||
get => this.eeWord; | ||
init => this.eeWord = value?.ToLower() ?? ""; | ||
} | ||
|
||
/// <summary> | ||
/// Default translation to English | ||
/// </summary> | ||
public string EnWord { get; init; } | ||
|
||
/// <summary> | ||
/// Alternatives to EnWord | ||
/// </summary> | ||
public string[] EnWords | ||
{ | ||
get => this.enWords; | ||
init => this.enWords = value ?? this.enWords; | ||
} | ||
|
||
public string EnExplanation { get; init; } | ||
|
||
public Uri EeAudioUrl { get; init; } | ||
|
||
public SampleSentence[] Samples | ||
{ | ||
get => this.samples; | ||
init => this.samples = value ?? this.samples; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
using CSharpFunctionalExtensions; | ||
|
||
using My1kWordsEe.Models; | ||
using My1kWordsEe.Services.Db; | ||
|
||
namespace My1kWordsEe.Services.Cqs | ||
{ | ||
public class CreateSampleCommand | ||
{ | ||
private readonly AzureBlobService azureBlobService; | ||
private readonly OpenAiService openAiService; | ||
private readonly TartuNlpService tartuNlpService; | ||
private readonly StabilityAiService stabilityAiService; | ||
|
||
public CreateSampleCommand( | ||
AzureBlobService azureBlobService, | ||
OpenAiService openAiService, | ||
TartuNlpService tartuNlpService, | ||
StabilityAiService stabilityAiService) | ||
{ | ||
this.azureBlobService = azureBlobService; | ||
this.openAiService = openAiService; | ||
this.tartuNlpService = tartuNlpService; | ||
this.stabilityAiService = stabilityAiService; | ||
} | ||
|
||
public async Task<Result<SampleWord>> Invoke(SampleWord word) | ||
{ | ||
var sentence = await this.openAiService.GetSampleSentence(word.EnWord); | ||
var imageGeneration = this.GenerateImage(sentence.Value); | ||
var speechGeneration = this.GenerateSpeech(sentence.Value); | ||
await Task.WhenAll(imageGeneration, speechGeneration); | ||
|
||
var updatedWordData = word with | ||
{ | ||
Samples = word.Samples.Append(new SampleSentence | ||
{ | ||
EeWord = word.EeWord, | ||
EeSentence = sentence.Value.Ee, | ||
EnSentence = sentence.Value.En, | ||
EeAudioUrl = speechGeneration.Result.Value, | ||
ImageUrl = imageGeneration.Result.Value, | ||
}).ToArray() | ||
}; | ||
|
||
await this.azureBlobService.SaveWordData(updatedWordData); | ||
|
||
return Result.Success(updatedWordData); | ||
} | ||
|
||
private async Task<Result<Uri>> GenerateImage(Sentence sentence) | ||
{ | ||
var prompt = await this.openAiService.GetDallEPrompt(sentence.En); | ||
var image = await this.stabilityAiService.GenerateImage(prompt.Value); | ||
var url = await this.azureBlobService.SaveImage(image.Value); | ||
return url; | ||
} | ||
|
||
private async Task<Result<Uri>> GenerateSpeech(Sentence sentence) | ||
{ | ||
var speech = await this.tartuNlpService.GetSpeech(sentence.Ee); | ||
var url = await this.azureBlobService.SaveAudio(speech); | ||
return url; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
using CSharpFunctionalExtensions; | ||
|
||
using My1kWordsEe.Models; | ||
using My1kWordsEe.Services.Db; | ||
|
||
namespace My1kWordsEe.Services.Cqs | ||
{ | ||
public class EnsureWordCommand | ||
{ | ||
private readonly AzureBlobService azureBlobService; | ||
private readonly OpenAiService openAiService; | ||
|
||
public EnsureWordCommand( | ||
AzureBlobService azureBlobService, | ||
OpenAiService openAiService) | ||
{ | ||
this.azureBlobService = azureBlobService; | ||
this.openAiService = openAiService; | ||
} | ||
|
||
public async Task<Result<SampleWord>> Invoke(string eeWord) | ||
{ | ||
var existingRecord = await azureBlobService.GetWordData(eeWord); | ||
|
||
if (existingRecord.IsSuccess) | ||
{ | ||
return existingRecord; | ||
} | ||
|
||
var sampleWord = await openAiService.GetWordMetadata(eeWord); | ||
|
||
if (sampleWord.IsSuccess) | ||
{ | ||
await azureBlobService.SaveWordData(sampleWord.Value); | ||
} | ||
|
||
return sampleWord; | ||
} | ||
} | ||
} |
Oops, something went wrong.