SPA test
This commit is contained in:
parent
e7e092cadc
commit
24319f5213
|
|
@ -43,12 +43,14 @@ It's written in C# running on .Net Core that is full cross-platform framework, t
|
|||
```sh
|
||||
PS D:\> git clone https://github.com/SciSharp/BotSharp-UI
|
||||
PS D:\> cd BotSharp-UI
|
||||
PS D:\> npm install --force
|
||||
PS D:\> npm install
|
||||
PS D:\> npm run dev
|
||||
```
|
||||
|
||||
Access http://localhost:5015/
|
||||
|
||||
[Online Demo with UI](https://botsharp.azurewebsites.net/)
|
||||
|
||||
<img src="./docs/static/screenshots/agent-builder-agents.png" height="450px"/>
|
||||
|
||||
### Core Modules
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@
|
|||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0" />
|
||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||
<PackageReference Include="System.Text.Json" Version="8.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.25" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="6.0.26" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -1,26 +1,55 @@
|
|||
using BotSharp.Abstraction.Messaging.JsonConverters;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
|
||||
namespace BotSharp.OpenAPI;
|
||||
|
||||
public static class BotSharpOpenApiExtensions
|
||||
{
|
||||
public static IServiceCollection AddBotSharpOpenAPI(this IServiceCollection services, IConfiguration config)
|
||||
/// <summary>
|
||||
/// Use Swagger/OpenAPI
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
/// <param name="config"></param>
|
||||
/// <returns></returns>
|
||||
public static IApplicationBuilder UseBotSharpOpenAPI(this IApplicationBuilder app, bool isDevelopment = false)
|
||||
{
|
||||
// Add services to the container.
|
||||
services.AddControllers()
|
||||
.AddJsonOptions(options =>
|
||||
if (app == null)
|
||||
{
|
||||
options.JsonSerializerOptions.Converters.Add(new RichContentJsonConverter());
|
||||
options.JsonSerializerOptions.Converters.Add(new TemplateMessageJsonConverter());
|
||||
throw new ArgumentNullException(nameof(app));
|
||||
}
|
||||
|
||||
app.UseSwagger();
|
||||
if (isDevelopment)
|
||||
{
|
||||
app.UseSwaggerUI();
|
||||
}
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Host BotSharp UI built in adapter-static
|
||||
/// </summary>
|
||||
/// <param name="app"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
public static IApplicationBuilder UseBotSharpUI(this IApplicationBuilder app, bool isDevelopment = false)
|
||||
{
|
||||
if (app == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(app));
|
||||
}
|
||||
|
||||
// app.UseFileServer();
|
||||
app.UseDefaultFiles();
|
||||
app.UseStaticFiles();
|
||||
app.UseSpa(config =>
|
||||
{
|
||||
if (isDevelopment)
|
||||
{
|
||||
config.UseProxyToSpaDevelopmentServer("http://localhost:5015");
|
||||
}
|
||||
});
|
||||
|
||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||
services.AddEndpointsApiExplorer();
|
||||
services.AddSwaggerGen();
|
||||
|
||||
services.AddHttpContextAccessor();
|
||||
|
||||
return services;
|
||||
return app;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using BotSharp.Abstraction.Loggers;
|
||||
using BotSharp.Plugin.ChatHub.Hooks;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
|
|
@ -16,5 +17,6 @@ public class ChatHubPlugin : IBotSharpPlugin
|
|||
{
|
||||
// Register hooks
|
||||
services.AddScoped<IConversationHook, ChatHubConversationHook>();
|
||||
services.AddScoped<IContentGeneratingHook, StreamingLogHook>();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
using BotSharp.Abstraction.Messaging.JsonConverters;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace BotSharp.Plugin.ChatHub;
|
||||
|
||||
public static class ChatHubServiceExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Add Swagger/OpenAPI
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
/// <param name="config"></param>
|
||||
/// <returns></returns>
|
||||
public static IServiceCollection AddBotSharpOpenAPI(this IServiceCollection services, IConfiguration config)
|
||||
{
|
||||
// Add services to the container.
|
||||
services.AddControllers()
|
||||
.AddJsonOptions(options =>
|
||||
{
|
||||
options.JsonSerializerOptions.Converters.Add(new RichContentJsonConverter());
|
||||
options.JsonSerializerOptions.Converters.Add(new TemplateMessageJsonConverter());
|
||||
});
|
||||
|
||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||
services.AddEndpointsApiExplorer();
|
||||
services.AddSwaggerGen();
|
||||
|
||||
services.AddHttpContextAccessor();
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Host BotSharp UI built in adapter-static
|
||||
/// </summary>
|
||||
/// <param name="app"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
public static IApplicationBuilder UseChatHub(this IApplicationBuilder app)
|
||||
{
|
||||
if (app == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(app));
|
||||
}
|
||||
|
||||
app.UseMiddleware<WebSocketsMiddleware>();
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
using BotSharp.Abstraction.Loggers;
|
||||
using BotSharp.Abstraction.Users.Models;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
|
||||
namespace BotSharp.Plugin.ChatHub.Hooks;
|
||||
|
||||
public class StreamingLogHook : IContentGeneratingHook
|
||||
{
|
||||
private readonly ConversationSetting _convSettings;
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly IHubContext<SignalRHub> _chatHub;
|
||||
|
||||
public StreamingLogHook(
|
||||
ConversationSetting convSettings,
|
||||
IServiceProvider serivces,
|
||||
IHubContext<SignalRHub> chatHub)
|
||||
{
|
||||
_convSettings = convSettings;
|
||||
_services = serivces;
|
||||
_chatHub = chatHub;
|
||||
}
|
||||
|
||||
public async Task BeforeGenerating(Agent agent, List<RoleDialogModel> conversations)
|
||||
{
|
||||
if (!_convSettings.ShowVerboseLog) return;
|
||||
|
||||
var user = _services.GetRequiredService<IUserIdentity>();
|
||||
var dialog = conversations.Last();
|
||||
var log = $"{dialog.Role}: {dialog.Content} [msg_id: {dialog.MessageId}] ==>";
|
||||
await _chatHub.Clients.User(user.Id).SendAsync("OnContentLogGenerated", log);
|
||||
}
|
||||
|
||||
public async Task AfterGenerated(RoleDialogModel message, TokenStatsModel tokenStats)
|
||||
{
|
||||
if (!_convSettings.ShowVerboseLog) return;
|
||||
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var agent = await agentService.LoadAgent(message.CurrentAgentId);
|
||||
|
||||
var log = message.Role == AgentRole.Function ?
|
||||
$"[{agent?.Name}]: {message.FunctionName}({message.FunctionArgs})" :
|
||||
$"[{agent?.Name}]: {message.Content}" + $" <== [msg_id: {message.MessageId}]";
|
||||
|
||||
var user = _services.GetRequiredService<IUserIdentity>();
|
||||
await _chatHub.Clients.User(user.Id).SendAsync("OnContentLogGenerated", tokenStats.Prompt);
|
||||
await _chatHub.Clients.User(user.Id).SendAsync("OnContentLogGenerated", log);
|
||||
}
|
||||
}
|
||||
|
|
@ -49,4 +49,9 @@ public class SignalRHub : Hub
|
|||
|
||||
await base.OnConnectedAsync();
|
||||
}
|
||||
|
||||
public Task PushEventLog(string message)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using BotSharp.Abstraction.Functions;
|
||||
using BotSharp.Abstraction.Routing.Models;
|
||||
using BotSharp.Plugin.KnowledgeBase.LlmContexts;
|
||||
|
||||
namespace BotSharp.Plugin.KnowledgeBase.Functions;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
using BotSharp.Plugin.WebDriver.Services;
|
||||
|
||||
namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;
|
||||
|
||||
public partial class PlaywrightWebDriver
|
||||
{
|
||||
public async Task ChangeListValue(Agent agent, BrowsingContextIn context, string messageId)
|
||||
{
|
||||
// Retrieve the page raw html and infer the element path
|
||||
var body = await _instance.Page.QuerySelectorAsync("body");
|
||||
|
||||
var str = new List<string>();
|
||||
var inputs = await body.QuerySelectorAllAsync("input");
|
||||
foreach (var input in inputs)
|
||||
{
|
||||
var text = await input.TextContentAsync();
|
||||
var name = await input.GetAttributeAsync("name");
|
||||
var type = await input.GetAttributeAsync("type");
|
||||
str.Add($"<input name='{name}' type='{type}'>{text}</input>");
|
||||
}
|
||||
|
||||
inputs = await body.QuerySelectorAllAsync("textarea");
|
||||
foreach (var input in inputs)
|
||||
{
|
||||
var text = await input.TextContentAsync();
|
||||
var name = await input.GetAttributeAsync("name");
|
||||
var type = await input.GetAttributeAsync("type");
|
||||
str.Add($"<textarea name='{name}' type='{type}'>{text}</textarea>");
|
||||
}
|
||||
|
||||
var driverService = _services.GetRequiredService<WebDriverService>();
|
||||
var htmlElementContextOut = await driverService.LocateElement(agent, string.Join("", str), context.ElementName, messageId);
|
||||
|
||||
if (htmlElementContextOut.Index < 0)
|
||||
{
|
||||
throw new Exception($"Can't locate the web element {context.ElementName}.");
|
||||
}
|
||||
|
||||
var element = _instance.Page.Locator(htmlElementContextOut.TagName).Nth(htmlElementContextOut.Index);
|
||||
try
|
||||
{
|
||||
await element.FillAsync(context.InputText);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
using BotSharp.Abstraction.Agents;
|
||||
using BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;
|
||||
|
||||
namespace BotSharp.Plugin.WebDriver.Functions;
|
||||
|
||||
public class ChangeListValueFn : IFunctionCallback
|
||||
{
|
||||
public string Name => "change_list_value";
|
||||
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly PlaywrightWebDriver _driver;
|
||||
|
||||
public ChangeListValueFn(IServiceProvider services,
|
||||
PlaywrightWebDriver driver)
|
||||
{
|
||||
_services = services;
|
||||
_driver = driver;
|
||||
}
|
||||
|
||||
public async Task<bool> Execute(RoleDialogModel message)
|
||||
{
|
||||
var args = JsonSerializer.Deserialize<BrowsingContextIn>(message.FunctionArgs);
|
||||
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var agent = await agentService.LoadAgent(message.CurrentAgentId);
|
||||
await _driver.ChangeListValue(agent, args, message.MessageId);
|
||||
|
||||
message.Content = "Update successfully.";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -13,6 +13,9 @@ public class BrowsingContextIn
|
|||
[JsonPropertyName("input_text")]
|
||||
public string? InputText { get; set; }
|
||||
|
||||
[JsonPropertyName("update_value")]
|
||||
public string? UpdateValue { get; set; }
|
||||
|
||||
[JsonPropertyName("password")]
|
||||
public string? Password { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -11,13 +11,17 @@ using Serilog;
|
|||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
var loggerConfig = new LoggerConfiguration();
|
||||
Log.Logger = loggerConfig
|
||||
#if DEBUG
|
||||
.MinimumLevel.Debug()
|
||||
#else
|
||||
.MinimumLevel.Warning()
|
||||
#endif
|
||||
.WriteTo.Console()
|
||||
.WriteTo.File("logs/log-.txt", rollingInterval: RollingInterval.Day)
|
||||
.CreateLogger();
|
||||
|
||||
builder.Host.UseSerilog(Log.Logger);
|
||||
builder.Host.UseSerilog();
|
||||
|
||||
builder.Services.AddScoped<IUserIdentity, UserIdentity>();
|
||||
// Add bearer authentication
|
||||
|
|
@ -49,6 +53,7 @@ builder.Services.AddCors(options =>
|
|||
{
|
||||
options.AddPolicy("MyCorsPolicy",
|
||||
builder => builder.WithOrigins("http://localhost:5015",
|
||||
"http://localhost:5500",
|
||||
"https://botsharp.scisharpstack.org",
|
||||
"https://chat.scisharpstack.org")
|
||||
.AllowAnyMethod()
|
||||
|
|
@ -61,14 +66,8 @@ builder.Services.AddSignalR();
|
|||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
app.UseSwagger();
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseSwaggerUI();
|
||||
}
|
||||
|
||||
app.MapHub<SignalRHub>("/chatHub");
|
||||
app.UseMiddleware<WebSocketsMiddleware>();
|
||||
app.UseChatHub();
|
||||
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
|
@ -77,12 +76,9 @@ app.MapControllers();
|
|||
|
||||
// Use BotSharp
|
||||
app.UseBotSharp();
|
||||
app.UseBotSharpOpenAPI();
|
||||
app.UseBotSharpUI();
|
||||
|
||||
app.UseCors("MyCorsPolicy");
|
||||
|
||||
// Host BotSharp UI built in adapter-static
|
||||
app.UseFileServer();
|
||||
app.UseDefaultFiles();
|
||||
app.UseStaticFiles();
|
||||
|
||||
app.Run();
|
||||
|
|
|
|||
|
|
@ -30,17 +30,14 @@
|
|||
<None Remove="logs\**" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
<PackageReference Include="Serilog.Extensions.Hosting" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.5" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.6" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\tests\BotSharp.Plugin.PizzaBot\BotSharp.Plugin.PizzaBot.csproj" />
|
||||
<ProjectReference Include="..\Plugins\BotSharp.Plugin.WebDriver\BotSharp.Plugin.WebDriver.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="$(SolutionName)==BotSharp">
|
||||
|
|
|
|||
|
|
@ -155,7 +155,8 @@
|
|||
"BotSharp.Plugin.Qdrant",
|
||||
"BotSharp.Plugin.ChatHub",
|
||||
"BotSharp.Plugin.WeChat",
|
||||
"BotSharp.Plugin.PizzaBot"
|
||||
"BotSharp.Plugin.PizzaBot",
|
||||
"BotSharp.Plugin.WebDriver"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue