This commit is contained in:
jx 2023-04-06 16:16:20 +08:00
parent fbc820208a
commit 7626775d4b
8 changed files with 82 additions and 16 deletions

10
GptBlazor/Constant.cs Normal file
View File

@ -0,0 +1,10 @@
namespace GptBlazor;
public class Constant
{
public static string? ResourceName;
public static string? DeploymentId;
public static string? ApiKey;
}

View File

@ -1,9 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>c76d0bd7-b6fa-4aaa-baeb-49ab35f36fc4</UserSecretsId>
</PropertyGroup>
<ItemGroup>
@ -12,6 +13,7 @@
<PackageReference Include="Furion" Version="4.8.7.35" />
<PackageReference Include="Markdig" Version="0.31.0" />
<PackageReference Include="OpenAI" Version="1.7.2" />
<PackageReference Include="Toolbelt.Blazor.HotKeys2" Version="1.0.0" />
</ItemGroup>
</Project>

View File

@ -14,7 +14,7 @@
<div class="card-header d-flex justify-content-between align-items-center p-3">
<h5 class="mb-0">Chat</h5>
</div>
<div class="card-body" style="overflow: auto; position: relative; height: calc(100vh - 196px)">
<div class="card-body" id="scroll" style="overflow: auto; position: relative; height: calc(100vh - 196px)">
@foreach (var message in _messages)
{
@ -57,8 +57,8 @@
<div class="card-footer text-muted d-flex justify-content-start align-items-center p-3">
<img src="https://mdbcdn.b-cdn.net/img/Photos/new-templates/bootstrap-chat/ava3-bg.webp"
alt="avatar 3" style="width: 40px; height: 100%;">
<Textarea rows="4" @bind-Value="@_userInput"></Textarea>
<Button Icon="fas fa-paper-plane" OnClick="@SendMessage"></Button>
<textarea @ref="Input" rows="4" @bind-value="@_userInput" @bind-value:event="onchange" class="form-control"></textarea>
<Button @ref="SubmitButton" Icon="fas fa-paper-plane" Text="发送[Ctrl+Enter]" OnClick="@SendMessage" IsDisabled="_isThinking"></Button>
</div>
</div>

View File

@ -1,35 +1,59 @@
using System.Diagnostics.CodeAnalysis;
using BootstrapBlazor.Components;
using Furion.LinqBuilder;
using GptBlazor.Entity;
using GptBlazor.Service;
using Markdig;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using Toolbelt.Blazor.HotKeys2;
using Message = GptBlazor.Entity.Message;
namespace GptBlazor.Pages;
public partial class Index
public partial class Index : IAsyncDisposable
{
private List<Message> _messages;
[Inject]
[NotNull]
private IJSRuntime? JsRuntime { get; set; }
[Inject]
[NotNull]
private OpenAiService? OpenAiService { get; set; }
[Inject]
[NotNull]
private HotKeys HotKeys { get; set; }
private ElementReference Input { get; set; }
private Button? SubmitButton { get; set; }
private string _userInput = string.Empty;
private string _response = string.Empty;
private bool _isThinking = false;
protected override async Task OnInitializedAsync()
private HotKeysContext HotKeysContext;
protected override void OnInitialized()
{
await base.OnInitializedAsync();
base.OnInitialized();
_messages = new List<Message>();
this.HotKeysContext = this.HotKeys.CreateContext()
.Add(ModCode.Ctrl, Code.Enter, async () =>
{
await SubmitButton.FocusAsync();
await SendMessage();
}, exclude: Exclude.None);
}
private async Task SendMessage()
{
if (_userInput.IsNullOrEmpty())
//await JsRuntime.InvokeVoidAsync("focusInput", SubmitButton);
if (_userInput.IsNullOrEmpty() || _isThinking)
{
return;
}
@ -44,10 +68,12 @@ public partial class Index
});
_isThinking = true;
StateHasChanged();
await JsRuntime.InvokeVoidAsync("scrollToBottom");
await foreach (var str in OpenAiService.StreamResponseEnumerableFromChatbotAsync(input))
{
_response += str;
StateHasChanged();
await JsRuntime.InvokeVoidAsync("scrollToBottom");
}
_messages.Add(new Message
@ -59,5 +85,12 @@ public partial class Index
_isThinking = false;
_response = string.Empty;
StateHasChanged();
await JsRuntime.InvokeVoidAsync("scrollToBottom");
await Input.FocusAsync();
}
public async ValueTask DisposeAsync()
{
await this.HotKeys.DisposeAsync();
}
}

View File

@ -34,5 +34,6 @@
<script src="_content/BootstrapBlazor/js/bootstrap.blazor.bundle.min.js"></script>
<script src="_framework/blazor.server.js"></script>
<script src="js/prism.js"></script>
<script src="js/site.js"></script>
</body>
</html>

View File

@ -1,6 +1,10 @@
using GptBlazor;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using GptBlazor.Data;
using Microsoft.Extensions.Primitives;
using Toolbelt.Blazor.Extensions.DependencyInjection;
using App = Furion.App;
var builder = WebApplication.CreateBuilder(args).Inject();
@ -9,6 +13,19 @@ builder.Services.AddRazorPages().AddInjectBase();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();
builder.Services.AddBootstrapBlazor();
builder.Services.AddHotKeys2();
var config = App.Configuration.GetSection("ChatGpt");
Constant.ResourceName = config["ResourceName"];
Constant.DeploymentId = config["DeploymentId"];
Constant.ApiKey = config["ApiKey"];
ChangeToken.OnChange(() => config.GetReloadToken(), () =>
{
Constant.ResourceName = config["ResourceName"];
Constant.DeploymentId = config["DeploymentId"];
Constant.ApiKey = config["ApiKey"];
});
var app = builder.Build();
// Configure the HTTP request pipeline.

View File

@ -6,17 +6,12 @@ namespace GptBlazor.Service;
public class OpenAiService : IScoped
{
private const string _resourceName = "jxgpt";
private const string _deploymentId = "gpt35test";
private const string _apiKey = "e97ae651d99945e2b3bb7e666442f5e9";
private readonly Conversation conversation;
public OpenAiService()
{
var api = OpenAIAPI.ForAzure(_resourceName, _deploymentId, _apiKey);
var api = OpenAIAPI.ForAzure(Constant.ResourceName, Constant.DeploymentId, Constant.ApiKey);
api.ApiVersion = "2023-03-15-preview";
conversation = api.Chat.CreateConversation();
}

View File

@ -0,0 +1,8 @@
function scrollToBottom() {
var element = document.getElementById("scroll");
element.scrollTop = element.scrollHeight;
}
function focusInput(element) {
element.focus();
}