-
-
Notifications
You must be signed in to change notification settings - Fork 49
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3c0b4e4
commit 3641424
Showing
14 changed files
with
398 additions
and
98 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
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,5 @@ | ||
### Autocomplete | ||
The blog can utilize Microsofts **Semantic Kernel** to either generate or enhance the current blog post. | ||
There are toggles to provide the AI with the Title, Descritpion, Markdown Content and Tags. You can also instruct the AI only to append content and not rewrite the whole article. | ||
|
||
You can find the configuration in the `appsettings.json` file under the `AI` section. |
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,19 @@ | ||
namespace LinkDotNet.Blog.Domain; | ||
|
||
public class AiSettings | ||
{ | ||
public const string AiSettingsSection = "AI"; | ||
|
||
public string DeploymentName { get; set; } | ||
|
||
public string EndpointUrl { get; set; } | ||
|
||
public string ModelId { get; set; } | ||
|
||
public string ApiKey { get; set; } | ||
|
||
public bool IsEnabled => !string.IsNullOrEmpty(DeploymentName) | ||
&& !string.IsNullOrEmpty(EndpointUrl) | ||
&& !string.IsNullOrEmpty(ModelId) | ||
&& !string.IsNullOrEmpty(ApiKey); | ||
} |
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
115 changes: 115 additions & 0 deletions
115
src/LinkDotNet.Blog.Web/Features/Admin/BlogPostEditor/Components/CompletionDialog.razor
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,115 @@ | ||
@using LinkDotNet.Blog.Web.Features.Admin.BlogPostEditor.Services | ||
<ModalDialog @ref="Dialog" Title="AutoComplete Content"> | ||
<form> | ||
<div class="mb-3"> | ||
<label for="systemMessage" class="form-label">Message</label> | ||
<TextAreaWithShortcuts Class="form-control" Id="systemMessage" Rows="2" Placeholder="Enter message..." @bind-Value="@options.Prompt"></TextAreaWithShortcuts> | ||
</div> | ||
|
||
<div class="mb-3"> | ||
<small class="text-muted">Include the blog post's title in the AI input.</small> | ||
<div class="form-check form-switch"> | ||
<input class="form-check-input" type="checkbox" id="includeTitle" @bind-value="@options.IncludeTitle"> | ||
<label class="form-check-label" for="includeTitle">Include Title</label> | ||
</div> | ||
</div> | ||
|
||
<div class="mb-3"> | ||
<small class="text-muted">Include the blog post's short description in the AI input.</small> | ||
<div class="form-check form-switch"> | ||
<input class="form-check-input" type="checkbox" id="includeShortDescription" @bind-value="@options.IncludeShortDescription"> | ||
<label class="form-check-label" for="includeShortDescription">Include Short Description</label> | ||
</div> | ||
</div> | ||
|
||
<div class="mb-3"> | ||
<small class="text-muted">Include the blog post's tags in the AI input.</small> | ||
<div class="form-check form-switch"> | ||
<input class="form-check-input" type="checkbox" id="includeTags" @bind-value="@options.IncludeTags"> | ||
<label class="form-check-label" for="includeTags">Include Tags</label> | ||
</div> | ||
</div> | ||
|
||
<div class="mb-3"> | ||
<small class="text-muted">Include the blog post's content in the AI input.</small> | ||
<div class="form-check form-switch"> | ||
<input class="form-check-input" type="checkbox" id="includeContent" @bind-value="@options.IncludeContent"> | ||
<label class="form-check-label" for="includeContent">Include Content</label> | ||
</div> | ||
</div> | ||
|
||
<div class="mb-3"> | ||
<small class="text-muted">Keep original text and append AI-generated content, or allow AI to rewrite the content.</small> | ||
<div class="form-check form-switch"> | ||
<input class="form-check-input" type="checkbox" id="keepOriginalText" @bind-value="@options.KeepOriginalText"> | ||
<label class="form-check-label" for="keepOriginalText">Keep Original Text</label> | ||
</div> | ||
</div> | ||
|
||
<button type="button" class="btn btn-primary btn-sm" @onclick="Generate">Generate</button> | ||
|
||
<div class="mt-3"> | ||
<label for="outputField" class="form-label">Output</label> | ||
<textarea class="form-control" id="outputField" rows="6" readonly>@options.Content</textarea> | ||
</div> | ||
|
||
<div class="d-flex mt-3 justify-content-end gap-3"> | ||
<button type="button" class="btn btn-secondary" @onclick="Cancel">Cancel</button> | ||
<button type="button" class="btn btn-success" @onclick="Save" disabled="@(!options.AllowSave)">Save</button> | ||
</div> | ||
</form> | ||
</ModalDialog> | ||
|
||
@code { | ||
[Inject] private AutocompleteService AutocompleteService { get; set; } | ||
|
||
[Parameter] public CreateNewModel Model { get; set; } | ||
[Parameter] public EventCallback<string> ContentGenerated { get; set; } | ||
|
||
private ModalDialog Dialog { get; set; } | ||
private Options options = new (); | ||
|
||
public void Open() | ||
{ | ||
Dialog.Open(); | ||
StateHasChanged(); | ||
} | ||
|
||
private void Cancel() | ||
{ | ||
Dialog.Close(); | ||
} | ||
|
||
private async Task Generate() | ||
{ | ||
var completeOptions = new AutocompleteOptions( | ||
options.IncludeTitle ? Model.Title : string.Empty, | ||
options.IncludeShortDescription ? Model.ShortDescription : string.Empty, | ||
options.IncludeTags ? Model.Tags : string.Empty, | ||
options.IncludeContent ? Model.Content : string.Empty, | ||
options.Prompt, | ||
options.KeepOriginalText); | ||
options.Content = await AutocompleteService.GetAutocomplete(completeOptions); | ||
options.AllowSave = true; | ||
} | ||
|
||
private async Task Save() | ||
{ | ||
await ContentGenerated.InvokeAsync(options.Content); | ||
Dialog.Close(); | ||
options = new(); | ||
} | ||
|
||
private sealed class Options | ||
{ | ||
public string Prompt { get; set; } | ||
public bool IncludeTitle { get; set; } | ||
public bool IncludeShortDescription { get; set; } | ||
public bool IncludeTags { get; set; } | ||
public bool IncludeContent { get; set; } | ||
public bool KeepOriginalText { get; set; } | ||
public string Content { get; set; } | ||
|
||
public bool AllowSave { get; set; } | ||
} | ||
} |
Oops, something went wrong.