Abastract chat service zone.
This commit is contained in:
parent
2c5fa98dfe
commit
e3c9d0632c
|
|
@ -2,13 +2,22 @@ namespace BotSharp.Abstraction.Agents.Models;
|
|||
|
||||
public class Agent
|
||||
{
|
||||
[StringLength(36)]
|
||||
public string Id { get; set; } = string.Empty;
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string? Description { get; set; }
|
||||
public DateTime CreatedDateTime { get; set; }
|
||||
public DateTime UpdatedDateTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Instruction
|
||||
/// </summary>
|
||||
public string Instruction { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Samples
|
||||
/// </summary>
|
||||
public string Samples { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Owner user id
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
using BotSharp.Abstraction.Infrastructures.ContentTransfers;
|
||||
|
||||
namespace BotSharp.Abstraction.Conversations;
|
||||
|
||||
/// <summary>
|
||||
/// IChatServiceZone is used to manage the chat function.
|
||||
/// When user send message to controller, all the registered service zone will process the message respectively.
|
||||
/// </summary>
|
||||
public interface IChatServiceZone : IServiceZone
|
||||
{
|
||||
}
|
||||
|
|
@ -4,5 +4,6 @@ namespace BotSharp.Abstraction.Infrastructures.ContentTransfers;
|
|||
|
||||
public interface IServiceZone
|
||||
{
|
||||
int Priority { get; }
|
||||
Task Serving(ContentContainer content);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,5 +3,5 @@ namespace BotSharp.Abstraction.Models;
|
|||
public class RoleDialogModel
|
||||
{
|
||||
public string Role { get; set; }
|
||||
public string Content { get; set; }
|
||||
public string Text { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
namespace BotSharp.Core.Agents.Services;
|
||||
|
||||
public partial class AgentService : IChatServiceZone
|
||||
{
|
||||
public int Priority => 10;
|
||||
|
||||
/// <summary>
|
||||
/// Prepare agent profile and configurations
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <returns></returns>
|
||||
public async Task Serving(ContentContainer content)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
|
||||
namespace BotSharp.Core.Agents.Services;
|
||||
|
||||
public partial class AgentService
|
||||
{
|
||||
public async Task<Agent> CreateAgent(Agent agent)
|
||||
{
|
||||
var db = _services.GetRequiredService<AgentDbContext>();
|
||||
var record = db.Agent.FirstOrDefault(x => x.OwnerId == _user.Id && x.Name == agent.Name);
|
||||
if (record != null)
|
||||
{
|
||||
return record.ToAgent();
|
||||
}
|
||||
|
||||
record = AgentRecord.FromAgent(agent);
|
||||
record.Id = Guid.NewGuid().ToString();
|
||||
record.OwnerId = _user.Id;
|
||||
record.CreatedDateTime = DateTime.UtcNow;
|
||||
record.UpdatedDateTime = DateTime.UtcNow;
|
||||
|
||||
db.Transaction<IAgentTable>(delegate
|
||||
{
|
||||
db.Add<IAgentTable>(record);
|
||||
});
|
||||
|
||||
return record.ToAgent();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
namespace BotSharp.Core.Agents.Services;
|
||||
|
||||
public partial class AgentService
|
||||
{
|
||||
public async Task<bool> DeleteAgent(string id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
|
||||
namespace BotSharp.Core.Agents.Services;
|
||||
|
||||
public partial class AgentService
|
||||
{
|
||||
public async Task<List<Agent>> GetAgents()
|
||||
{
|
||||
var db = _services.GetRequiredService<AgentDbContext>();
|
||||
var query = from agent in db.Agent
|
||||
where agent.OwnerId == _user.Id
|
||||
select agent.ToAgent();
|
||||
return query.ToList();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
|
||||
namespace BotSharp.Core.Agents.Services;
|
||||
|
||||
public partial class AgentService
|
||||
{
|
||||
public async Task UpdateAgent(Agent agent)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,6 @@
|
|||
using BotSharp.Abstraction.Agents;
|
||||
using BotSharp.Abstraction.Agents.Models;
|
||||
using BotSharp.Abstraction.Users;
|
||||
|
||||
namespace BotSharp.Core.Agents.Services;
|
||||
|
||||
public class AgentService : IAgentService
|
||||
public partial class AgentService : IAgentService
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly IUserIdentity _user;
|
||||
|
|
@ -14,46 +10,4 @@ public class AgentService : IAgentService
|
|||
_services = services;
|
||||
_user = user;
|
||||
}
|
||||
|
||||
public async Task<Agent> CreateAgent(Agent agent)
|
||||
{
|
||||
var db = _services.GetRequiredService<AgentDbContext>();
|
||||
var record = db.Agent.FirstOrDefault(x => x.OwnerId == _user.Id && x.Name == agent.Name);
|
||||
if (record != null)
|
||||
{
|
||||
return record.ToAgent();
|
||||
}
|
||||
|
||||
record = AgentRecord.FromAgent(agent);
|
||||
record.Id = Guid.NewGuid().ToString();
|
||||
record.OwnerId = _user.Id;
|
||||
record.CreatedDateTime = DateTime.UtcNow;
|
||||
record.UpdatedDateTime = DateTime.UtcNow;
|
||||
|
||||
db.Transaction<IAgentTable>(delegate
|
||||
{
|
||||
db.Add<IAgentTable>(record);
|
||||
});
|
||||
|
||||
return record.ToAgent();
|
||||
}
|
||||
|
||||
public Task<bool> DeleteAgent(string id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task<List<Agent>> GetAgents()
|
||||
{
|
||||
var db = _services.GetRequiredService<AgentDbContext>();
|
||||
var query = from agent in db.Agent
|
||||
where agent.OwnerId == _user.Id
|
||||
select agent.ToAgent();
|
||||
return query.ToList();
|
||||
}
|
||||
|
||||
public Task UpdateAgent(Agent agent)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,8 +9,12 @@ public static class BotSharpServiceCollectionExtensions
|
|||
{
|
||||
services.AddScoped<IUserIdentity, UserIdentity>();
|
||||
services.AddScoped<IUserService, UserService>();
|
||||
|
||||
services.AddScoped<IAgentService, AgentService>();
|
||||
services.AddScoped<IChatServiceZone, AgentService>();
|
||||
|
||||
services.AddScoped<ISessionService, SessionService>();
|
||||
|
||||
services.AddScoped<IConversationService, ConversationService>();
|
||||
|
||||
services.AddScoped<ITextChopper, TextChopperService>();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
using BotSharp.Abstraction.ApiAdapters;
|
||||
using BotSharp.Abstraction.Conversations;
|
||||
using BotSharp.Abstraction.Infrastructures.ContentTransmitters;
|
||||
using BotSharp.Abstraction.Models;
|
||||
using BotSharp.Abstraction.Conversations.Models;
|
||||
using BotSharp.Core.Conversations.ViewModels;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
|
@ -13,49 +11,60 @@ namespace BotSharp.Core.Conversations;
|
|||
public class ConversationController : ControllerBase, IApiAdapter
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly IUserIdentity _user;
|
||||
|
||||
public ConversationController(IServiceProvider services)
|
||||
public ConversationController(IServiceProvider services,
|
||||
IUserIdentity user)
|
||||
{
|
||||
_services = services;
|
||||
_user = user;
|
||||
}
|
||||
|
||||
[HttpPost("/conversation/session")]
|
||||
public async Task<SessionViewModel> NewSession([FromBody] SessionCreationModel session)
|
||||
[HttpPost("/conversation/{agentId}")]
|
||||
public async Task<SessionViewModel> NewSession([FromRoute] string agentId)
|
||||
{
|
||||
var service = _services.GetRequiredService<ISessionService>();
|
||||
var sess = session.ToSession();
|
||||
var sess = new Session
|
||||
{
|
||||
AgentId = agentId
|
||||
};
|
||||
sess = await service.NewSession(sess);
|
||||
return SessionViewModel.FromSession(sess);
|
||||
}
|
||||
|
||||
[HttpDelete("/conversation/session/{sessionId}")]
|
||||
public async Task DeleteSession([FromRoute] string sessionId)
|
||||
[HttpDelete("/conversation/{agentId}/{sessionId}")]
|
||||
public async Task DeleteSession([FromRoute] string agentId, [FromRoute] string sessionId)
|
||||
{
|
||||
var service = _services.GetRequiredService<ISessionService>();
|
||||
}
|
||||
|
||||
[HttpPost("/conversation/{sessionId}")]
|
||||
public async Task<MessageResponseModel> SendMessage([FromBody] NewMessageModel input)
|
||||
[HttpPost("/conversation/{agentId}/{sessionId}")]
|
||||
public async Task<MessageResponseModel> SendMessage([FromRoute] string agentId,
|
||||
[FromRoute] string sessionId,
|
||||
[FromBody] NewMessageModel input)
|
||||
{
|
||||
var transmitter = _services.GetRequiredService<IContentTransfer>();
|
||||
|
||||
var container = new ContentContainer
|
||||
{
|
||||
AgentId = agentId,
|
||||
SessionId = sessionId,
|
||||
Conversations = new List<RoleDialogModel>
|
||||
{
|
||||
new RoleDialogModel
|
||||
{
|
||||
Role = "user",
|
||||
Content = input.Content
|
||||
Text = input.Text
|
||||
}
|
||||
}
|
||||
},
|
||||
UserId = _user.Id
|
||||
};
|
||||
|
||||
var result = await transmitter.Transport(container);
|
||||
|
||||
return new MessageResponseModel
|
||||
{
|
||||
Content = result.IsSuccess ? container.Output.Content : result.Messages.First()
|
||||
Content = result.IsSuccess ? container.Output.Text : result.Messages.First()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace BotSharp.Core.Conversations.ViewModels;
|
||||
|
||||
public class NewMessageModel
|
||||
{
|
||||
public string Content { get; set; }
|
||||
public string Text { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,13 +4,5 @@ namespace BotSharp.Core.Conversations.ViewModels;
|
|||
|
||||
public class SessionCreationModel
|
||||
{
|
||||
public string AgentId { get; set; }
|
||||
|
||||
public Session ToSession()
|
||||
{
|
||||
return new Session
|
||||
{
|
||||
AgentId = AgentId
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,17 @@
|
|||
using BotSharp.Abstraction.Infrastructures.ContentTransfers;
|
||||
using BotSharp.Abstraction.Infrastructures.ContentTransmitters;
|
||||
using BotSharp.Abstraction.Users;
|
||||
|
||||
namespace BotSharp.Core.Infrastructures;
|
||||
|
||||
public class ContentTransfer : IContentTransfer
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly IUserIdentity _user;
|
||||
|
||||
public ContentTransfer(IServiceProvider services, IUserIdentity user)
|
||||
public ContentTransfer(IServiceProvider services)
|
||||
{
|
||||
_services = services;
|
||||
_user = user;
|
||||
}
|
||||
|
||||
public async Task<TransportResult> Transport(ContentContainer input)
|
||||
{
|
||||
input.UserId = _user.Id;
|
||||
input.Output = new RoleDialogModel();
|
||||
|
||||
var result = new TransportResult
|
||||
{
|
||||
|
|
@ -25,12 +19,12 @@ public class ContentTransfer : IContentTransfer
|
|||
Messages = new List<string>()
|
||||
};
|
||||
|
||||
var zones = _services.GetServices<IServiceZone>();
|
||||
var zones = _services.GetServices<IChatServiceZone>()
|
||||
.OrderBy(x => x.Priority)
|
||||
.ToList();
|
||||
|
||||
foreach (var zone in zones)
|
||||
{
|
||||
input.Output = null;
|
||||
|
||||
try
|
||||
{
|
||||
await zone.Serving(input);
|
||||
|
|
|
|||
|
|
@ -1,12 +1,9 @@
|
|||
using BotSharp.Abstraction.Infrastructures.ContentTransfers;
|
||||
using BotSharp.Abstraction.Models;
|
||||
using BotSharp.Core.Repository.Collections;
|
||||
using LLama;
|
||||
using System.IO;
|
||||
|
||||
namespace BotSharp.Plugins.LLamaSharp;
|
||||
|
||||
public class ChatCompletionProvider : IServiceZone
|
||||
public class ChatCompletionProvider : IChatServiceZone
|
||||
{
|
||||
private readonly IChatModel _model;
|
||||
private readonly LlamaSharpSettings _settings;
|
||||
|
|
@ -26,12 +23,14 @@ public class ChatCompletionProvider : IServiceZone
|
|||
_model.InitChatAntiprompt(new string[] { "user:" });
|
||||
}
|
||||
|
||||
public int Priority => 100;
|
||||
|
||||
public async Task GetChatCompletionsAsync(List<RoleDialogModel> conversations,
|
||||
Func<string, Task> onChunkReceived)
|
||||
{
|
||||
string totalResponse = "";
|
||||
var prompt = GetInstruction();
|
||||
var content = string.Join("\n ", conversations.Select(x => $"{x.Role}: {x.Content.Replace("user:", "")}")).Trim();
|
||||
var content = string.Join("\n ", conversations.Select(x => $"{x.Role}: {x.Text.Replace("user:", "")}")).Trim();
|
||||
content += "\n assistant: ";
|
||||
foreach (var response in _model.Chat(content, prompt, "UTF-8"))
|
||||
{
|
||||
|
|
@ -58,7 +57,7 @@ public class ChatCompletionProvider : IServiceZone
|
|||
samples.Add(new RoleDialogModel
|
||||
{
|
||||
Role = role,
|
||||
Content = content
|
||||
Text = content
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -76,7 +75,7 @@ public class ChatCompletionProvider : IServiceZone
|
|||
instruction += "\n";
|
||||
foreach (var message in GetChatSamples())
|
||||
{
|
||||
instruction += $"\n{message.Role}: {message.Content}";
|
||||
instruction += $"\n{message.Role}: {message.Text}";
|
||||
}
|
||||
|
||||
return instruction;
|
||||
|
|
@ -86,7 +85,7 @@ public class ChatCompletionProvider : IServiceZone
|
|||
{
|
||||
string output = "";
|
||||
var prompt = GetInstruction();
|
||||
var conversations = string.Join("\n ", content.Conversations.Select(x => $"{x.Role}: {x.Content.Replace("user:", "")}")).Trim();
|
||||
var conversations = string.Join("\n ", content.Conversations.Select(x => $"{x.Role}: {x.Text.Replace("user:", "")}")).Trim();
|
||||
conversations += "\n assistant: ";
|
||||
foreach (var response in _model.Chat(conversations, prompt, "UTF-8"))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ global using BotSharp.Abstraction.Infrastructures.ContentTransmitters;
|
|||
global using BotSharp.Abstraction.Infrastructures.ContentTransfers;
|
||||
global using BotSharp.Abstraction.Knowledges;
|
||||
global using BotSharp.Abstraction.Users;
|
||||
global using BotSharp.Abstraction.Models;
|
||||
global using BotSharp.Core.Repository;
|
||||
global using BotSharp.Core.Repository.Abstraction;
|
||||
global using BotSharp.Core.Repository.DbTables;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
using BotSharp.Abstraction.Infrastructures.ContentTransfers;
|
||||
using BotSharp.Abstraction.Conversations;
|
||||
using BotSharp.Abstraction.MLTasks;
|
||||
using BotSharp.Abstraction.Plugins;
|
||||
using BotSharp.Plugin.AzureOpenAI.Providers;
|
||||
|
|
@ -19,6 +19,6 @@ public class AzureOpenAiPlugin : IBotSharpPlugin
|
|||
|
||||
services.AddSingleton<ITextCompletion, TextCompletionProvider>();
|
||||
services.AddScoped<IChatCompletion, ChatCompletionProvider>();
|
||||
services.AddScoped<IServiceZone, ChatCompletionService>();
|
||||
services.AddScoped<IChatServiceZone, ChatCompletionService>();
|
||||
}
|
||||
}
|
||||
|
|
@ -61,7 +61,7 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
samples.Add(new RoleDialogModel
|
||||
{
|
||||
Role = role,
|
||||
Content = content
|
||||
Text = content
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -113,12 +113,12 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
|
||||
foreach (var message in GetChatSamples())
|
||||
{
|
||||
chatCompletionsOptions.Messages.Add(new ChatMessage(message.Role, message.Content));
|
||||
chatCompletionsOptions.Messages.Add(new ChatMessage(message.Role, message.Text));
|
||||
}
|
||||
|
||||
foreach (var message in conversations)
|
||||
{
|
||||
chatCompletionsOptions.Messages.Add(new ChatMessage(message.Role, message.Content));
|
||||
chatCompletionsOptions.Messages.Add(new ChatMessage(message.Role, message.Text));
|
||||
}
|
||||
|
||||
return chatCompletionsOptions;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
using Azure.AI.OpenAI;
|
||||
using BotSharp.Abstraction.Infrastructures.ContentTransfers;
|
||||
using BotSharp.Abstraction.Conversations;
|
||||
using BotSharp.Abstraction.Infrastructures.ContentTransmitters;
|
||||
using BotSharp.Abstraction.MLTasks;
|
||||
using BotSharp.Abstraction.Models;
|
||||
|
|
@ -7,7 +7,7 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace BotSharp.Plugin.AzureOpenAI.Services;
|
||||
|
||||
public class ChatCompletionService : IServiceZone
|
||||
public class ChatCompletionService : IChatServiceZone
|
||||
{
|
||||
private readonly IChatCompletion _chatCompletion;
|
||||
|
||||
|
|
@ -16,6 +16,8 @@ public class ChatCompletionService : IServiceZone
|
|||
_chatCompletion = chatCompletion;
|
||||
}
|
||||
|
||||
public int Priority => 100;
|
||||
|
||||
public async Task Serving(ContentContainer content)
|
||||
{
|
||||
var output = await _chatCompletion.GetChatCompletionsAsync(content.Conversations);
|
||||
|
|
@ -23,7 +25,7 @@ public class ChatCompletionService : IServiceZone
|
|||
content.Output = new RoleDialogModel
|
||||
{
|
||||
Role = ChatRole.Assistant.ToString(),
|
||||
Content = output
|
||||
Text = output
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ public class ChatbotUiController : ControllerBase, IApiAdapter
|
|||
var conversations = input.Messages.Skip(1).Select(x => new RoleDialogModel
|
||||
{
|
||||
Role = x.Role,
|
||||
Content = x.Content
|
||||
Text = x.Content
|
||||
}).ToList();
|
||||
|
||||
/*await _chatCompletionProvider.GetChatCompletionsAsync(conversations,
|
||||
|
|
@ -79,7 +79,7 @@ public class ChatbotUiController : ControllerBase, IApiAdapter
|
|||
|
||||
var result = await transmitter.Transport(container);
|
||||
|
||||
await OnChunkReceived(outputStream, container.Output.Content);
|
||||
await OnChunkReceived(outputStream, container.Output.Text);
|
||||
await OnEventCompleted(outputStream);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue