Merge pull request #86 from hchen2020/master

Some fixes.
This commit is contained in:
Haiping 2023-07-21 17:50:21 -05:00 committed by GitHub
commit 0989696d24
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 118 additions and 98 deletions

View file

@ -0,0 +1,6 @@
namespace BotSharp.Abstraction.Agents.Settings;
public class AgentSettings
{
public string DataDir { get; set; }
}

View file

@ -6,16 +6,16 @@ public class RoleDialogModel
/// user, system, assistant
/// </summary>
public string Role { get; set; }
public string Text { get; set; }
public string Content { get; set; }
public RoleDialogModel(string role, string text)
{
Role = role;
Text = text;
Content = text;
}
public override string ToString()
{
return $"{Role}: {Text}";
return $"{Role}: {Content}";
}
}

View file

@ -4,5 +4,6 @@ namespace BotSharp.Abstraction.MLTasks;
public interface IChatCompletion
{
Task<string> GetChatCompletionsAsync(Agent agent, List<RoleDialogModel> conversations);
string GetChatCompletions(Agent agent, List<RoleDialogModel> conversations);
Task<string> GetChatCompletionsStreamingAsync(Agent agent, List<RoleDialogModel> conversations);
}

View file

@ -6,7 +6,7 @@ public partial class AgentService
{
public async Task<Agent> CreateAgent(Agent agent)
{
var db = _services.GetRequiredService<AgentDbContext>();
var db = _services.GetRequiredService<BotSharpDbContext>();
var record = db.Agent.FirstOrDefault(x => x.OwnerId == _user.Id && x.Name == agent.Name);
if (record != null)
{
@ -19,9 +19,9 @@ public partial class AgentService
record.CreatedDateTime = DateTime.UtcNow;
record.UpdatedDateTime = DateTime.UtcNow;
db.Transaction<IAgentTable>(delegate
db.Transaction<IBotSharpTable>(delegate
{
db.Add<IAgentTable>(record);
db.Add<IBotSharpTable>(record);
});
return record.ToAgent();

View file

@ -7,7 +7,7 @@ public partial class AgentService
{
public async Task<List<Agent>> GetAgents()
{
var db = _services.GetRequiredService<AgentDbContext>();
var db = _services.GetRequiredService<BotSharpDbContext>();
var query = from agent in db.Agent
where agent.OwnerId == _user.Id
select agent.ToAgent();
@ -16,7 +16,7 @@ public partial class AgentService
public async Task<Agent> GetAgent(string id)
{
var db = _services.GetRequiredService<AgentDbContext>();
var db = _services.GetRequiredService<BotSharpDbContext>();
var query = from agent in db.Agent
where agent.Id == id
select agent.ToAgent();

View file

@ -7,9 +7,9 @@ public partial class AgentService
{
public async Task UpdateAgent(Agent agent)
{
var db = _services.GetRequiredService<AgentDbContext>();
var db = _services.GetRequiredService<BotSharpDbContext>();
db.Transaction<IAgentTable>(delegate
db.Transaction<IBotSharpTable>(delegate
{
var record = db.Agent.FirstOrDefault(x => x.OwnerId == agent.OwerId && x.Id == agent.Id);

View file

@ -6,16 +6,18 @@ public partial class AgentService : IAgentService
{
private readonly IServiceProvider _services;
private readonly IUserIdentity _user;
private readonly AgentSettings _settings;
public AgentService(IServiceProvider services, IUserIdentity user)
public AgentService(IServiceProvider services, IUserIdentity user, AgentSettings settings)
{
_services = services;
_user = user;
_settings = settings;
}
public string GetAgentDataDir(string agentId)
{
var dir = Path.Combine("data", agentId);
var dir = Path.Combine(_settings.DataDir, agentId);
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);

View file

@ -1,4 +1,3 @@
using BotSharp.Abstraction.Conversations.Settings;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
@ -13,6 +12,10 @@ public static class BotSharpServiceCollectionExtensions
services.AddScoped<IAgentService, AgentService>();
var agentSettings = new AgentSettings();
config.Bind("Agent", agentSettings);
services.AddSingleton((IServiceProvider x) => agentSettings);
var convsationSettings = new ConversationSetting();
config.Bind("Conversation", convsationSettings);
services.AddSingleton((IServiceProvider x) => convsationSettings);
@ -20,15 +23,29 @@ public static class BotSharpServiceCollectionExtensions
services.AddScoped<IConversationStorage, ConversationStorage>();
services.AddScoped<IConversationService, ConversationService>();
RegisterRepository(services, config);
RegisterPlugins(services, config);
return services;
}
public static void ConfigureBotSharp(this IServiceCollection services)
public static IServiceCollection ConfigureBotSharpRepository<Tdb>(this IServiceCollection services, IConfiguration config)
where Tdb : DataContext
{
var databaseSettings = new DatabaseSettings();
config.Bind("Database", databaseSettings);
services.AddSingleton((IServiceProvider x) => databaseSettings);
var myDatabaseSettings = new MyDatabaseSettings();
config.Bind("Database", myDatabaseSettings);
services.AddSingleton((IServiceProvider x) => databaseSettings);
services.AddScoped((IServiceProvider x)
=> DataContextHelper.GetDbContext<MongoDbContext, Tdb>(myDatabaseSettings, x));
services.AddScoped((IServiceProvider x)
=> DataContextHelper.GetDbContext<BotSharpDbContext, Tdb>(myDatabaseSettings, x));
return services;
}
public static IApplicationBuilder UseBotSharp(this IApplicationBuilder app)
@ -43,27 +60,6 @@ public static class BotSharpServiceCollectionExtensions
return app;
}
public static void RegisterRepository(IServiceCollection services, IConfiguration config)
{
var databaseSettings = new DatabaseSettings();
config.Bind("Database", databaseSettings);
services.AddSingleton((IServiceProvider x) => databaseSettings);
var myDatabaseSettings = new MyDatabaseSettings();
config.Bind("Database", myDatabaseSettings);
services.AddSingleton((IServiceProvider x) => databaseSettings);
services.AddScoped((IServiceProvider x) =>
{
return DataContextHelper.GetDbContext<MongoDbContext>(myDatabaseSettings, x);
});
services.AddScoped((IServiceProvider x) =>
{
return DataContextHelper.GetDbContext<AgentDbContext>(myDatabaseSettings, x);
});
}
public static void RegisterPlugins(IServiceCollection services, IConfiguration config)
{
var pluginSettings = new PluginLoaderSettings();

View file

@ -30,7 +30,7 @@ public class ConversationService : IConversationService
public async Task<Conversation> GetConversation(string id)
{
var db = _services.GetRequiredService<AgentDbContext>();
var db = _services.GetRequiredService<BotSharpDbContext>();
var query = from sess in db.Conversation
where sess.Id == id
orderby sess.CreatedTime descending
@ -40,7 +40,7 @@ public class ConversationService : IConversationService
public async Task<List<Conversation>> GetConversations()
{
var db = _services.GetRequiredService<AgentDbContext>();
var db = _services.GetRequiredService<BotSharpDbContext>();
var query = from sess in db.Conversation
where sess.UserId == _user.Id
orderby sess.CreatedTime descending
@ -50,16 +50,16 @@ public class ConversationService : IConversationService
public async Task<Conversation> NewConversation(Conversation sess)
{
var db = _services.GetRequiredService<AgentDbContext>();
var db = _services.GetRequiredService<BotSharpDbContext>();
var record = ConversationRecord.FromConversation(sess);
record.Id = sess.Id.IfNullOrEmptyAs(Guid.NewGuid().ToString());
record.UserId = sess.UserId.IfNullOrEmptyAs(_user.Id);
record.Title = "New Conversation";
db.Transaction<IAgentTable>(delegate
db.Transaction<IBotSharpTable>(delegate
{
db.Add<IAgentTable>(record);
db.Add<IBotSharpTable>(record);
});
_storage.InitStorage(sess.AgentId, record.Id);
@ -92,7 +92,7 @@ public class ConversationService : IConversationService
agent.Knowledges = await knowledge.GetKnowledges(new KnowledgeRetrievalModel
{
AgentId = agentId,
Question = string.Join("\n", wholeDialogs.Select(x => x.Text))
Question = string.Join("\n", wholeDialogs.Select(x => x.Content))
});
}
@ -110,7 +110,7 @@ public class ConversationService : IConversationService
.BeforeCompletion();
});
var response = await chatCompletion.GetChatCompletionsAsync(agent, wholeDialogs);
var response = await chatCompletion.GetChatCompletionsStreamingAsync(agent, wholeDialogs);
// After chat completion hook
hooks.ForEach(async hook =>

View file

@ -14,7 +14,7 @@ public class ConversationStorage : IConversationStorage
public void Append(string agentId, string conversationId, RoleDialogModel dialog)
{
var conversationFile = GetStorageFile(agentId, conversationId);
File.AppendAllText(conversationFile, $"{dialog.Role}: {dialog.Text}\n");
File.AppendAllText(conversationFile, $"{dialog.Role}: {dialog.Content}\n");
}
public List<RoleDialogModel> GetDialogs(string agentId, string conversationId)

View file

@ -14,10 +14,15 @@ public class ChatCompletionProvider : IChatCompletion
_services = services;
}
public Task<string> GetChatCompletionsAsync(Agent agent, List<RoleDialogModel> conversations)
public string GetChatCompletions(Agent agent, List<RoleDialogModel> conversations)
{
throw new NotImplementedException();
}
public Task<string> GetChatCompletionsStreamingAsync(Agent agent, List<RoleDialogModel> conversations)
{
string totalResponse = "";
var content = string.Join("\n", conversations.Select(x => $"{x.Role}: {x.Text.Replace("user:", "")}")).Trim();
var content = string.Join("\n", conversations.Select(x => $"{x.Role}: {x.Content.Replace("user:", "")}")).Trim();
content += "\nassistant: ";
var llama = _services.GetRequiredService<LlamaAiModel>();

View file

@ -1,5 +1,5 @@
namespace BotSharp.Core.Repository.Abstraction;
public interface IAgentTable
public interface IBotSharpTable
{
}

View file

@ -1,6 +1,6 @@
namespace BotSharp.Core.Repository;
public class AgentDbContext : Database
public class BotSharpDbContext : Database
{
public IQueryable<UserRecord> User => Table<UserRecord>();
public IQueryable<AgentRecord> Agent => Table<AgentRecord>();

View file

@ -1,14 +1,14 @@
using BotSharp.Core.Repository.Abstraction;
using EntityFrameworkCore.BootKit;
using Microsoft.Data.SqlClient;
using MySqlConnector;
using System.Data.Common;
namespace BotSharp.Core.Repository;
public static class DataContextHelper
{
public static T GetDbContext<T>(MyDatabaseSettings settings, IServiceProvider serviceProvider)
public static T GetDbContext<T, Tdb>(MyDatabaseSettings settings, IServiceProvider serviceProvider)
where T : Database, new()
where Tdb : DataContext
{
if (settings.Assemblies == null)
throw new Exception("Please set assemblies.");
@ -25,17 +25,33 @@ public static class DataContextHelper
IsRelational = false
});
}
else if (typeof(T) == typeof(AgentDbContext))
else if (typeof(T) == typeof(BotSharpDbContext))
{
dc.BindDbContext<IAgentTable, DbContext4SqlServer2>(new DatabaseBind
if (typeof(Tdb).Name.StartsWith("DbContext4SqlServer"))
{
ServiceProvider = serviceProvider,
MasterConnection = new SqlConnection(settings.BotSharp.Master),
SlaveConnections = settings.BotSharp.Slavers.Length == 0 ?
new List<DbConnection> { new SqlConnection(settings.BotSharp.Master) } :
settings.BotSharp.Slavers.Select(x => new SqlConnection(x) as DbConnection).ToList(),
CreateDbIfNotExist = true
});
dc.BindDbContext<IBotSharpTable, Tdb>(new DatabaseBind
{
ServiceProvider = serviceProvider,
MasterConnection = new SqlConnection(settings.BotSharp.Master),
SlaveConnections = settings.BotSharp.Slavers.Length == 0 ?
new List<DbConnection> { new SqlConnection(settings.BotSharp.Master) } :
settings.BotSharp.Slavers.Select(x => new SqlConnection(x) as DbConnection)
.ToList(),
CreateDbIfNotExist = true
});
}
else if (typeof(Tdb).Name.StartsWith("DbContext4Aurora") ||
typeof(Tdb).Name.StartsWith("DbContext4MySql"))
{
dc.BindDbContext<IBotSharpTable, Tdb>(new DatabaseBind
{
ServiceProvider = serviceProvider,
MasterConnection = new MySqlConnection(settings.BotSharp.Master),
SlaveConnections = settings.BotSharp.Slavers
.Select(x => new MySqlConnection(x) as DbConnection).ToList(),
CreateDbIfNotExist = true
});
}
}
return dc;
}

View file

@ -5,7 +5,7 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace BotSharp.Core.Repository.DbTables;
[Table("Agent")]
public class AgentRecord : DbRecord, IAgentTable
public class AgentRecord : DbRecord, IBotSharpTable
{
[Required]
[MaxLength(64)]

View file

@ -5,7 +5,7 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace BotSharp.Core.Repository.DbTables;
[Table("Conversation")]
public class ConversationRecord : DbRecord, IAgentTable
public class ConversationRecord : DbRecord, IBotSharpTable
{
[Required]
[MaxLength(36)]

View file

@ -5,7 +5,7 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace BotSharp.Core.Repository.DbTables;
[Table("User")]
public class UserRecord : DbRecord, IAgentTable
public class UserRecord : DbRecord, IBotSharpTable
{
[Required]
[MaxLength(64)]

View file

@ -23,7 +23,7 @@ public class UserService : IUserService
public async Task<User> CreateUser(User user)
{
var db = _services.GetRequiredService<AgentDbContext>();
var db = _services.GetRequiredService<BotSharpDbContext>();
var record = db.User.FirstOrDefault(x => x.Email == user.Email.ToLower());
if (record != null)
{
@ -36,9 +36,9 @@ public class UserService : IUserService
record.Salt = Guid.NewGuid().ToString("N");
record.Password = Utilities.HashText(user.Password, record.Salt);
db.Transaction<IAgentTable>(delegate
db.Transaction<IBotSharpTable>(delegate
{
db.Add<IAgentTable>(record);
db.Add<IBotSharpTable>(record);
});
return record.ToUser();
@ -49,7 +49,7 @@ public class UserService : IUserService
var base64 = Encoding.UTF8.GetString(Convert.FromBase64String(authorization));
var (userEmail, password) = base64.SplitAsTuple(":");
var db = _services.GetRequiredService<AgentDbContext>();
var db = _services.GetRequiredService<BotSharpDbContext>();
var record = db.User.FirstOrDefault(x => x.Email == userEmail);
if (record == null)
{
@ -104,7 +104,7 @@ public class UserService : IUserService
{
var userId = _user.Id;
var db = _services.GetRequiredService<AgentDbContext>();
var db = _services.GetRequiredService<BotSharpDbContext>();
var user = (from u in db.User
where u.Id == userId
select new User

View file

@ -18,4 +18,6 @@ global using BotSharp.Core.Agents.Services;
global using BotSharp.Core.Conversations.Services;
global using BotSharp.Core.Infrastructures;
global using BotSharp.Core.Plugins;
global using BotSharp.Core.Users.Services;
global using BotSharp.Core.Users.Services;
global using BotSharp.Abstraction.Agents.Settings;
global using BotSharp.Abstraction.Conversations.Settings;

View file

@ -8,7 +8,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Azure.AI.OpenAI" Version="1.0.0-beta.5" />
<PackageReference Include="Azure.AI.OpenAI" Version="1.0.0-beta.6" />
</ItemGroup>
<ItemGroup>

View file

@ -6,7 +6,6 @@ using BotSharp.Abstraction.MLTasks;
using BotSharp.Plugin.AzureOpenAI.Settings;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
namespace BotSharp.Plugin.AzureOpenAI.Providers;
@ -20,30 +19,25 @@ public class ChatCompletionProvider : IChatCompletion
_settings = settings;
}
/*public async Task GetChatCompletionsAsync(List<RoleDialogModel> conversations,
Func<string, Task> onChunkReceived)
public string GetChatCompletions(Agent agent, List<RoleDialogModel> conversations)
{
var client = new OpenAIClient(new Uri(_settings.Endpoint), new AzureKeyCredential(_settings.ApiKey));
var chatCompletionsOptions = PrepareOptions(conversations);
var chatCompletionsOptions = PrepareOptions(agent, conversations);
var response = await client.GetChatCompletionsStreamingAsync(_settings.DeploymentModel.ChatCompletionModel, chatCompletionsOptions);
using StreamingChatCompletions streaming = response.Value;
var response = client.GetChatCompletions(_settings.DeploymentModel.ChatCompletionModel, chatCompletionsOptions);
string content = "";
await foreach (var choice in streaming.GetChoicesStreaming())
string output = "";
foreach (var choice in response.Value.Choices)
{
await foreach (var message in choice.GetMessageStreaming())
{
if (message.Content == null)
continue;
Console.Write(message.Content);
content += message.Content;
await onChunkReceived(message.Content);
}
var message = choice.Message;
if (message.Content == null)
continue;
Console.Write(message.Content);
output += message.Content;
}
Console.WriteLine();
}*/
return output.Trim();
}
public List<RoleDialogModel> GetChatSamples(string sampleText)
{
@ -77,7 +71,7 @@ public class ChatCompletionProvider : IChatCompletion
}
public async Task<string> GetChatCompletionsAsync(Agent agent, List<RoleDialogModel> conversations)
public async Task<string> GetChatCompletionsStreamingAsync(Agent agent, List<RoleDialogModel> conversations)
{
var client = new OpenAIClient(new Uri(_settings.Endpoint), new AzureKeyCredential(_settings.ApiKey));
var chatCompletionsOptions = PrepareOptions(agent, conversations);
@ -117,12 +111,12 @@ public class ChatCompletionProvider : IChatCompletion
var samples = GetChatSamples(agent.Samples);
foreach (var message in samples)
{
chatCompletionsOptions.Messages.Add(new ChatMessage(message.Role, message.Text));
chatCompletionsOptions.Messages.Add(new ChatMessage(message.Role, message.Content));
}
foreach (var message in conversations)
{
chatCompletionsOptions.Messages.Add(new ChatMessage(message.Role, message.Text));
chatCompletionsOptions.Messages.Add(new ChatMessage(message.Role, message.Content));
}
return chatCompletionsOptions;

View file

@ -8,7 +8,6 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Azure.AI.OpenAI" Version="1.0.0-beta.5" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
<PackageReference Include="System.Text.Json" Version="7.0.2" />
</ItemGroup>

View file

@ -10,7 +10,6 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System;
using Azure.AI.OpenAI;
using BotSharp.Abstraction.ApiAdapters;
using BotSharp.Plugin.ChatbotUI.ViewModels;
using Microsoft.Extensions.DependencyInjection;
@ -94,7 +93,7 @@ public class ChatbotUiController : ControllerBase, IApiAdapter
{
new OpenAiChoice
{
Delta = new ChatMessage(ChatRole.Assistant, content)
Delta = new RoleDialogModel("assistant", content)
}
}
};

View file

@ -1,4 +1,4 @@
using Azure.AI.OpenAI;
using BotSharp.Abstraction.Conversations.Models;
using Newtonsoft.Json;
using System.Text.Json.Serialization;
@ -9,5 +9,5 @@ public class OpenAiChoice
[JsonPropertyName("finish_reason")]
[JsonProperty("finish_reason")]
public string FinishReason { get; set; }
public ChatMessage Delta { get; set; }
public RoleDialogModel Delta { get; set; }
}