2023-05-27 01:58:31 +00:00
|
|
|
using BotSharp.Abstraction.Models;
|
|
|
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
|
using Microsoft.Net.Http.Headers;
|
|
|
|
|
using Newtonsoft.Json.Serialization;
|
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using System;
|
2023-06-07 00:59:32 +00:00
|
|
|
using BotSharp.Abstraction.ApiAdapters;
|
|
|
|
|
using BotSharp.Plugin.ChatbotUI.ViewModels;
|
2023-06-13 03:27:31 +00:00
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
2023-06-27 18:31:13 +00:00
|
|
|
using BotSharp.Abstraction.Conversations;
|
|
|
|
|
using BotSharp.Abstraction.Conversations.Models;
|
2023-07-21 15:15:30 +00:00
|
|
|
using Microsoft.AspNetCore.Authorization;
|
2023-08-15 15:41:34 +00:00
|
|
|
using BotSharp.Abstraction.Agents.Models;
|
|
|
|
|
using BotSharp.Abstraction.Agents.Enums;
|
2023-05-27 01:58:31 +00:00
|
|
|
|
2023-06-07 00:59:32 +00:00
|
|
|
namespace BotSharp.Plugin.ChatbotUI.Controllers;
|
2023-05-27 01:58:31 +00:00
|
|
|
|
2023-07-21 15:15:30 +00:00
|
|
|
[Authorize]
|
2023-05-27 01:58:31 +00:00
|
|
|
[ApiController]
|
2023-06-07 00:59:32 +00:00
|
|
|
public class ChatbotUiController : ControllerBase, IApiAdapter
|
2023-05-27 01:58:31 +00:00
|
|
|
{
|
2023-06-13 03:27:31 +00:00
|
|
|
private readonly IServiceProvider _services;
|
2023-05-27 01:58:31 +00:00
|
|
|
private readonly ILogger<ChatbotUiController> _logger;
|
|
|
|
|
|
2023-06-13 03:27:31 +00:00
|
|
|
public ChatbotUiController(ILogger<ChatbotUiController> logger, IServiceProvider services)
|
2023-05-27 01:58:31 +00:00
|
|
|
{
|
|
|
|
|
_logger = logger;
|
2023-06-13 03:27:31 +00:00
|
|
|
_services = services;
|
2023-05-27 01:58:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[HttpGet("/v1/models")]
|
|
|
|
|
public OpenAiModels GetOpenAiModels()
|
|
|
|
|
{
|
|
|
|
|
return new OpenAiModels
|
|
|
|
|
{
|
|
|
|
|
Data = new List<AiModel>
|
|
|
|
|
{
|
|
|
|
|
new AiModel
|
|
|
|
|
{
|
|
|
|
|
Id = "gpt-3.5-turbo",
|
|
|
|
|
Model = "gpt-3.5-turbo",
|
|
|
|
|
Name = "Default (GPT-3.5)",
|
|
|
|
|
MaxLength = 4000,
|
|
|
|
|
TokenLimit = 4000
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[HttpPost("/v1/chat/completions")]
|
2023-05-29 01:06:05 +00:00
|
|
|
public async Task SendMessage([FromBody] OpenAiMessageInput input)
|
2023-05-27 01:58:31 +00:00
|
|
|
{
|
|
|
|
|
Response.StatusCode = 200;
|
|
|
|
|
Response.Headers.Add(HeaderNames.ContentType, "text/event-stream");
|
|
|
|
|
Response.Headers.Add(HeaderNames.CacheControl, "no-cache");
|
|
|
|
|
Response.Headers.Add(HeaderNames.Connection, "keep-alive");
|
|
|
|
|
var outputStream = Response.Body;
|
|
|
|
|
|
2023-08-15 15:41:34 +00:00
|
|
|
var conversation = input.Messages
|
|
|
|
|
.Where(x => x.Role == AgentRole.User)
|
2023-07-21 01:55:40 +00:00
|
|
|
.Select(x => new RoleDialogModel(x.Role, x.Content))
|
2023-08-15 15:41:34 +00:00
|
|
|
.Last();
|
2023-05-29 01:06:05 +00:00
|
|
|
|
2023-07-21 01:55:40 +00:00
|
|
|
var conversationService = _services.GetRequiredService<IConversationService>();
|
2023-06-13 03:27:31 +00:00
|
|
|
|
2023-07-27 15:07:39 +00:00
|
|
|
var result = await conversationService.SendMessage(input.AgentId,
|
2023-08-15 15:41:34 +00:00
|
|
|
input.ConversationId,
|
|
|
|
|
conversation,
|
2023-07-27 15:07:39 +00:00
|
|
|
async msg =>
|
2023-08-14 22:14:05 +00:00
|
|
|
await OnChunkReceived(outputStream, msg),
|
|
|
|
|
async fn
|
|
|
|
|
=> await Task.CompletedTask);
|
2023-06-13 03:27:31 +00:00
|
|
|
|
2023-05-29 01:06:05 +00:00
|
|
|
await OnEventCompleted(outputStream);
|
2023-05-27 01:58:31 +00:00
|
|
|
}
|
|
|
|
|
|
2023-07-27 15:07:39 +00:00
|
|
|
private async Task OnChunkReceived(Stream outputStream, RoleDialogModel message)
|
2023-05-27 01:58:31 +00:00
|
|
|
{
|
|
|
|
|
var response = new OpenAiChatOutput
|
|
|
|
|
{
|
|
|
|
|
Choices = new List<OpenAiChoice>
|
|
|
|
|
{
|
|
|
|
|
new OpenAiChoice
|
|
|
|
|
{
|
2023-07-27 15:07:39 +00:00
|
|
|
Delta = new RoleDialogModel(message.Role, message.Content)
|
2023-05-27 01:58:31 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
var json = JsonConvert.SerializeObject(response, new JsonSerializerSettings
|
|
|
|
|
{
|
|
|
|
|
Formatting = Formatting.None,
|
|
|
|
|
ContractResolver = new CamelCasePropertyNamesContractResolver()
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var buffer = Encoding.UTF8.GetBytes($"data:{json}\n");
|
|
|
|
|
await outputStream.WriteAsync(buffer, 0, buffer.Length);
|
2023-07-27 15:07:39 +00:00
|
|
|
await Task.Delay(10);
|
2023-05-27 01:58:31 +00:00
|
|
|
|
|
|
|
|
buffer = Encoding.UTF8.GetBytes("\n");
|
|
|
|
|
await outputStream.WriteAsync(buffer, 0, buffer.Length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task OnEventCompleted(Stream outputStream)
|
|
|
|
|
{
|
|
|
|
|
var buffer = Encoding.UTF8.GetBytes("data:[DONE]\n");
|
|
|
|
|
await outputStream.WriteAsync(buffer, 0, buffer.Length);
|
|
|
|
|
|
|
|
|
|
buffer = Encoding.UTF8.GetBytes("\n");
|
|
|
|
|
await outputStream.WriteAsync(buffer, 0, buffer.Length);
|
|
|
|
|
|
|
|
|
|
await outputStream.FlushAsync();
|
|
|
|
|
}
|
|
|
|
|
}
|