Support User related functions.

This commit is contained in:
Haiping Chen 2023-06-11 18:46:02 -05:00
parent c03be389ca
commit 8046ddafe6
37 changed files with 619 additions and 40 deletions

View file

@ -24,7 +24,7 @@ BotSharp is in accordance with components principle strictly, decouples every pa
* Built-in multi-agents and conversation management.
* Support multiple LLM platforms.
* Support export/ import agent from other bot platforms directly.
* Support different open source UI [Chatbot UI](src\Plugins\BotSharp.Plugin.ChatbotUI\Chatbot-UI.md), [HuggingChat UI](src\Plugins\BotSharp.Plugin.HuggingFace\HuggingChat-UI.md).
* Support different open source UI [Chatbot UI](src/Plugins/BotSharp.Plugin.ChatbotUI/Chatbot-UI.md), [HuggingChat UI](src/Plugins/BotSharp.Plugin.HuggingFace/HuggingChat-UI.md).
* Integrate with popular message channels like Facebook Messenger, Slack and Telegram.
### Quick Started
@ -34,7 +34,7 @@ BotSharp is in accordance with components principle strictly, decouples every pa
PS D:\> cd BotSharp
PS D:\BotSharp\> dotnet run -p .\src\WebStarter
```
2. Run UI project, reference to [Chatbot UI](src\Plugins\BotSharp.Plugin.ChatbotUI\Chatbot-UI.md).
2. Run UI project, reference to [Chatbot UI](src/Plugins/BotSharp.Plugin.ChatbotUI/Chatbot-UI.md).
### Extension Libraries

View file

@ -1,3 +1,5 @@
using BotSharp.Abstraction.Agents.Models;
namespace BotSharp.Abstraction.Agents;
/// <summary>
@ -5,7 +7,7 @@ namespace BotSharp.Abstraction.Agents;
/// </summary>
public interface IAgentService
{
void NewAgent();
void DeleteAgent();
void UpdateAgent();
Task<string> CreateAgent(Agent agent);
Task<bool> DeleteAgent(string id);
Task UpdateAgent(Agent agent);
}

View file

@ -0,0 +1,9 @@
namespace BotSharp.Abstraction.Users;
public interface ICurrentUser
{
string Id { get; }
string Email { get; }
string FirstName { get; }
string LastName { get; }
}

View file

@ -0,0 +1,10 @@
using BotSharp.Abstraction.Users.Models;
namespace BotSharp.Abstraction.Users;
public interface IUserService
{
Task<User> CreateUser(User user);
Task<Token> GetToken(string authorization);
Task<User> GetMyProfile();
}

View file

@ -0,0 +1,10 @@
namespace BotSharp.Abstraction.Users.Models;
public class Token
{
public string AccessToken { get; set; } = string.Empty;
public string RefreshToken { get; set; } = string.Empty;
public string TokenType { get; set; } = string.Empty;
public int ExpireTime { get; set; }
public string Scope { get; set; } = string.Empty;
}

View file

@ -0,0 +1,13 @@
namespace BotSharp.Abstraction.Users.Models;
public class User
{
public string Id { get; set; } = string.Empty;
public string FirstName { get; set; } = string.Empty;
public string LastName { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public string Salt { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
public DateTime UpdatedTime { get; set; } = DateTime.UtcNow;
public DateTime CreatedTime { get; set; } = DateTime.UtcNow;
}

View file

@ -0,0 +1,24 @@
using BotSharp.Abstraction.Agents;
using BotSharp.Abstraction.ApiAdapters;
using BotSharp.Core.Agents.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace BotSharp.Core.Agents;
[Authorize]
[ApiController]
public class AgentController : ControllerBase, IApiAdapter
{
private readonly IAgentService _agentService;
public AgentController(IAgentService agentService)
{
_agentService = agentService;
}
[HttpPost("/agent")]
public async Task<string> CreateAgent(AgentCreationModel agent)
{
return await _agentService.CreateAgent(agent.ToAgent());
}
}

View file

@ -0,0 +1,41 @@
using BotSharp.Abstraction.Agents;
using BotSharp.Abstraction.Agents.Models;
using BotSharp.Core.Repository;
using BotSharp.Core.Repository.Abstraction;
using BotSharp.Core.Repository.DbTables;
using EntityFrameworkCore.BootKit;
using Microsoft.Extensions.DependencyInjection;
namespace BotSharp.Core.Agents.Services;
public class AgentService : IAgentService
{
private readonly IServiceProvider _services;
public AgentService(IServiceProvider services)
{
_services = services;
}
public async Task<string> CreateAgent(Agent agent)
{
var db = _services.GetRequiredService<AgentDbContext>();
var record = AgentRecord.FromAgent(agent);
db.Transaction<IAgentTable>(delegate
{
db.Add<IAgentTable>(record);
});
return record.Id;
}
public Task<bool> DeleteAgent(string id)
{
throw new NotImplementedException();
}
public Task UpdateAgent(Agent agent)
{
throw new NotImplementedException();
}
}

View file

@ -0,0 +1,18 @@
using BotSharp.Abstraction.Agents.Models;
namespace BotSharp.Core.Agents.ViewModels;
public class AgentCreationModel
{
public string Name { get; set; }
public string Description { get; set; }
public Agent ToAgent()
{
return new Agent
{
Name = Name,
Description = Description
};
}
}

View file

@ -0,0 +1,8 @@
namespace BotSharp.Core.Agents.ViewModels;
public class AgentUpdateModel
{
public string Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}

View file

@ -0,0 +1,8 @@
namespace BotSharp.Core.Agents.ViewModels;
public class AgentViewModel
{
public string Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}

View file

@ -67,14 +67,11 @@
<PackageReference Include="LLamaSharp" Version="0.3.0" />
<PackageReference Include="LLamaSharp.Backend.Cuda11" Version="0.3.0" />
<PackageReference Include="TensorFlow.Keras" Version="0.10.5" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BotSharp.Abstraction\BotSharp.Abstraction.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Infrastructures\" />
</ItemGroup>
</Project>

View file

@ -1,9 +1,10 @@
using BotSharp.Abstraction.Agents;
using BotSharp.Abstraction.Conversations;
using BotSharp.Abstraction.TextGeneratives;
using BotSharp.Abstraction.Users;
using BotSharp.Core.Agents.Services;
using BotSharp.Core.Conversations;
using BotSharp.Core.Plugins.TextGeneratives.LLamaSharp;
using BotSharp.Core.Repository;
using EntityFrameworkCore.BootKit;
using BotSharp.Core.Users.Services;
using BotSharp.Plugins.LLamaSharp;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
@ -14,6 +15,9 @@ public static class BotSharpServiceCollectionExtensions
{
public static IServiceCollection AddBotSharp(this IServiceCollection services, IConfiguration config)
{
services.AddScoped<ICurrentUser, CurrentUser>();
services.AddScoped<IUserService, UserService>();
services.AddScoped<IAgentService, AgentService>();
services.AddSingleton<ISessionService, SessionService>();
services.AddSingleton<IConversationService, ConversationService>();
@ -59,17 +63,22 @@ public static class BotSharpServiceCollectionExtensions
return DataContextHelper.GetDbContext<MongoDbContext>(myDatabaseSettings, x);
});
services.AddSingleton(x =>
services.AddScoped((IServiceProvider x) =>
{
var settings = new LlamaSharpSettings();
config.Bind("LlamaSharp", settings);
return settings;
return DataContextHelper.GetDbContext<AgentDbContext>(myDatabaseSettings, x);
});
services.AddSingleton<IChatCompletionProvider, ChatCompletionProvider>();
}
public static void RegisterPlugins(IServiceCollection services, IConfiguration config)
{
var settings = new LlamaSharpSettings();
config.Bind("LlamaSharp", settings);
services.AddSingleton(x =>
{
return settings;
});
// services.AddSingleton<IChatCompletionProvider, ChatCompletionProvider>();
}
}

View file

@ -0,0 +1,23 @@
namespace BotSharp.Core.Infrastructures;
public static class Utilities
{
public static string HashText(string password, string salt)
{
using var md5 = System.Security.Cryptography.MD5.Create();
var data = md5.ComputeHash(Encoding.UTF8.GetBytes(password + salt));
var sb = new StringBuilder();
foreach (var c in data)
{
sb.Append(c.ToString("x2"));
}
return sb.ToString();
}
public static (string, string) SplitAsTuple(this string str, string sep)
{
var splits = str.Split(sep);
return (splits[0], splits[1]);
}
}

View file

@ -1,10 +1,9 @@
using BotSharp.Abstraction.Models;
using BotSharp.Abstraction.Plugins;
using BotSharp.Abstraction.TextGeneratives;
using LLama;
using System.IO;
namespace BotSharp.Core.Plugins.TextGeneratives.LLamaSharp;
namespace BotSharp.Plugins.LLamaSharp;
public class ChatCompletionProvider : IChatCompletionProvider, IBotSharpPlugin
{

View file

@ -0,0 +1,6 @@
namespace BotSharp.Plugins.LLamaSharp;
public class LLamaSharpPlugin : IBotSharpPlugin
{
}

View file

@ -1,4 +1,4 @@
namespace BotSharp.Core.Plugins.TextGeneratives.LLamaSharp;
namespace BotSharp.Plugins.LLamaSharp;
public class LlamaSharpSettings
{

View file

@ -1,6 +0,0 @@
namespace BotSharp.Core.Plugins.TextGeneratives.LLamaSharp;
public class LLamaSharpPlugin : IBotSharpPlugin
{
}

View file

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

View file

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

View file

@ -1,4 +1,6 @@
using BotSharp.Core.Repository.Abstraction;
using EntityFrameworkCore.BootKit;
using Microsoft.Data.SqlClient;
using System.Data.Common;
namespace BotSharp.Core.Repository;
@ -23,6 +25,18 @@ public static class DataContextHelper
IsRelational = false
});
}
else if (typeof(T) == typeof(AgentDbContext))
{
dc.BindDbContext<IAgentTable, DbContext4SqlServer2>(new DatabaseBind
{
ServiceProvider = serviceProvider,
MasterConnection = new SqlConnection(settings.Agent.Master),
SlaveConnections = settings.Agent.Slavers.Length == 0 ?
new List<DbConnection> { new SqlConnection(settings.Agent.Master) } :
settings.Agent.Slavers.Select(x => new SqlConnection(x) as DbConnection).ToList(),
CreateDbIfNotExist = true
});
}
return dc;
}
}

View file

@ -0,0 +1,37 @@
using BotSharp.Abstraction.Agents.Models;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace BotSharp.Core.Repository.DbTables;
[Table("Agent")]
public class AgentRecord : DbRecord, IAgentTable
{
[Required]
[MaxLength(64)]
public string Name { get; set; } = string.Empty;
[MaxLength(512)]
public string? Description { get; set; }
[Required]
[MaxLength(36)]
public string OwnerId { get; set; } = string.Empty;
[Required]
public DateTime CreatedDateTime { get; set; }
[Required]
public DateTime UpdatedDateTime { get; set; }
public static AgentRecord FromAgent(Agent agent)
{
return new AgentRecord
{
Id = agent.Id,
Name = agent.Name,
Description = agent.Description,
OwnerId = agent.OwerId
};
}
}

View file

@ -0,0 +1,62 @@
using BotSharp.Abstraction.Users.Models;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace BotSharp.Core.Repository.DbTables;
[Table("User")]
public class UserRecord : DbRecord, IAgentTable
{
[Required]
[MaxLength(64)]
public string FirstName { get; set; } = string.Empty;
[Required]
[MaxLength(64)]
public string LastName { get; set; } = string.Empty;
[Required]
[MaxLength(64)]
public string Email { get; set; } = string.Empty;
[Required]
[StringLength(32)]
public string Salt { get; set; } = string.Empty;
[Required]
[MaxLength(256)]
public string Password { get; set; } = string.Empty;
[Required]
public DateTime UpdatedTime { get; set; } = DateTime.UtcNow;
[Required]
public DateTime CreatedTime { get; set; } = DateTime.UtcNow;
public static UserRecord FromUser(User user)
{
return new UserRecord
{
Id = user.Id,
FirstName = user.FirstName,
LastName = user.LastName,
Email = user.Email,
Password = user.Password
};
}
public User ToUser()
{
return new User
{
Id = Id,
FirstName = FirstName,
LastName = LastName,
Email = Email,
Salt = Salt,
Password = Password,
CreatedTime = CreatedTime,
UpdatedTime = UpdatedTime
};
}
}

View file

@ -6,4 +6,5 @@ public class MyDatabaseSettings : DatabaseSettings
{
public string[] Assemblies { get; set; }
public DbConnectionSetting MongoDb { get; set; }
public DbConnectionSetting Agent { get; set; }
}

View file

@ -0,0 +1,25 @@
using BotSharp.Abstraction.Users;
using Microsoft.AspNetCore.Http;
using System.Security.Claims;
namespace BotSharp.Core.Users.Services;
public class CurrentUser : ICurrentUser
{
private readonly IHttpContextAccessor _contextAccessor;
private IEnumerable<Claim> _claims => _contextAccessor.HttpContext.User.Claims;
public CurrentUser(IHttpContextAccessor contextAccessor)
{
_contextAccessor = contextAccessor;
}
public string Id => _claims.First(x => x.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier").Value;
public string Email => _claims.First(x => x.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress").Value;
public string FirstName => _claims.First(x => x.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname").Value;
public string LastName => _claims.First(x => x.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname").Value;
}

View file

@ -0,0 +1,123 @@
using BotSharp.Abstraction.Users;
using BotSharp.Abstraction.Users.Models;
using BotSharp.Core.Infrastructures;
using BotSharp.Core.Repository.DbTables;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
namespace BotSharp.Core.Users.Services;
public class UserService : IUserService
{
private readonly IServiceProvider _services;
private readonly ICurrentUser _user;
public UserService(IServiceProvider services, ICurrentUser user)
{
_services = services;
_user = user;
}
public async Task<User> CreateUser(User user)
{
var db = _services.GetRequiredService<AgentDbContext>();
var record = db.User.FirstOrDefault(x => x.Email == user.Email.ToLower());
if (record != null)
{
return record.ToUser();
}
record = UserRecord.FromUser(user);
record.Id = Guid.NewGuid().ToString();
record.Email = user.Email.ToLower();
record.Salt = Guid.NewGuid().ToString("N");
record.Password = Utilities.HashText(user.Password, record.Salt);
db.Transaction<IAgentTable>(delegate
{
db.Add<IAgentTable>(record);
});
return record.ToUser();
}
public async Task<Token> GetToken(string authorization)
{
var base64 = Encoding.UTF8.GetString(Convert.FromBase64String(authorization));
var (userEmail, password) = base64.SplitAsTuple(":");
var db = _services.GetRequiredService<AgentDbContext>();
var record = db.User.FirstOrDefault(x => x.Email == userEmail);
if (record == null)
{
return default;
}
if (Utilities.HashText(password, record.Salt) != record.Password)
{
return default;
}
var accessToken = GenerateJwtToken(record);
var jwt = new JwtSecurityTokenHandler().ReadJwtToken(accessToken);
return new Token
{
AccessToken = accessToken,
ExpireTime = jwt.Payload.Exp.Value,
TokenType = "Bearer",
Scope = "api"
};
}
private string GenerateJwtToken(UserRecord user)
{
var config = _services.GetRequiredService<IConfiguration>();
var issuer = config["Jwt:Issuer"];
var audience = config["Jwt:Audience"];
var key = Encoding.ASCII.GetBytes(config["Jwt:Key"]);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new Claim(JwtRegisteredClaimNames.NameId, user.Id),
new Claim(JwtRegisteredClaimNames.Email, user.Email),
new Claim(JwtRegisteredClaimNames.GivenName, user.FirstName),
new Claim(JwtRegisteredClaimNames.FamilyName, user.LastName),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
}),
Expires = DateTime.UtcNow.AddMinutes(5),
Issuer = issuer,
Audience = audience,
SigningCredentials = new SigningCredentials
(new SymmetricSecurityKey(key),
SecurityAlgorithms.HmacSha512Signature)
};
var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
public async Task<User> GetMyProfile()
{
var userId = _user.Id;
var db = _services.GetRequiredService<AgentDbContext>();
var user = (from u in db.User
where u.Id == userId
select new User
{
Id = u.Id,
Email = u.Email,
FirstName = u.FirstName,
LastName = u.LastName,
CreatedTime = u.CreatedTime,
UpdatedTime = u.UpdatedTime,
Password = u.Password,
}).FirstOrDefault();
return user;
}
}

View file

@ -0,0 +1,47 @@
using BotSharp.Abstraction.ApiAdapters;
using BotSharp.Abstraction.Users;
using BotSharp.Abstraction.Users.Models;
using BotSharp.Core.Users.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace BotSharp.Core.Users;
[Authorize]
[ApiController]
public class UserController : ControllerBase, IApiAdapter
{
private readonly IUserService _userService;
public UserController(IUserService userService)
{
_userService = userService;
}
[AllowAnonymous]
[HttpPost("/token")]
public async Task<ActionResult<Token>> GetToken()
{
var authcode = Request.Headers["Authorization"].ToString();
var token = await _userService.GetToken(authcode.Split(' ')[1]);
if (token == null)
{
return Unauthorized();
}
return Ok(token);
}
[AllowAnonymous]
[HttpPost("/user")]
public async Task<UserViewModel> CreateUser(UserCreationModel user)
{
var createdUser = await _userService.CreateUser(user.ToUser());
return UserViewModel.FromUser(createdUser);
}
[HttpGet("/user/my")]
public async Task<UserViewModel> GetMyUserProfile()
{
var user = await _userService.GetMyProfile();
return UserViewModel.FromUser(user);
}
}

View file

@ -0,0 +1,22 @@
using BotSharp.Abstraction.Users.Models;
namespace BotSharp.Core.Users.ViewModels;
public class UserCreationModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public User ToUser()
{
return new User
{
FirstName = FirstName,
LastName = LastName,
Email = Email,
Password = Password
};
}
}

View file

@ -0,0 +1,22 @@
using BotSharp.Abstraction.Users.Models;
namespace BotSharp.Core.Users.ViewModels;
public class UserViewModel
{
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public static UserViewModel FromUser(User user)
{
return new UserViewModel
{
Id = user.Id,
FirstName = user.FirstName,
LastName = user.LastName,
Email = user.Email
};
}
}

View file

@ -4,4 +4,7 @@ global using System.Text;
global using System.Threading.Tasks;
global using BotSharp.Abstraction;
global using System.Linq;
global using BotSharp.Abstraction.Plugins;
global using BotSharp.Abstraction.Plugins;
global using EntityFrameworkCore.BootKit;
global using BotSharp.Core.Repository;
global using BotSharp.Core.Repository.Abstraction;

View file

@ -11,7 +11,7 @@ public static class AzureOpenAiServiceCollectionExtensions
public static IServiceCollection AddAzureOpenAiPlatform(this IServiceCollection services, IConfiguration config)
{
var settings = new AzureOpenAiSettings();
config.Bind("AzureAi", settings);
config.Bind("AzureOpenAi", settings);
services.AddSingleton(x =>
{

View file

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

View file

@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
<PackageReference Include="System.Text.Json" Version="7.0.2" />
</ItemGroup>

View file

@ -1,18 +1,42 @@
using BotSharp.Core;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddHttpContextAccessor();
// Add bearer authentication
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(o =>
{
o.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = builder.Configuration["Jwt:Issuer"],
ValidAudience = builder.Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])),
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = false,
ValidateIssuerSigningKey = true
};
});
// Add BotSharp
builder.Services.AddBotSharp(builder.Configuration);
// builder.Services.AddAzureOpenAiPlatform(builder.Configuration);
builder.Services.AddAzureOpenAiPlatform(builder.Configuration);
builder.Services.AddCors(options =>
{
@ -34,6 +58,7 @@ if (app.Environment.IsDevelopment())
app.UseSwaggerUI();
}
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();

View file

@ -22,6 +22,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.16" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
</ItemGroup>

View file

@ -7,9 +7,10 @@
},
"AllowedHosts": "*",
"OpenAi": {
"userName": "",
"password": ""
"Jwt": {
"Issuer": "botsharp",
"Audience": "botsharp",
"Key": "31ba6052aa6f4569901facc3a41fcb4a"
},
"LlamaSharp": {
@ -33,7 +34,15 @@
"MongoDb": {
"Master": "mongodb://localhost:27017/chat-ui"
},
"Agent": {
"Master": "Data Source=(localdb)\\ProjectModels;Initial Catalog=Agent;Integrated Security=True;Connect Timeout=30;Encrypt=False;Trust Server Certificate=False;Application Intent=ReadWrite;Multi Subnet Failover=False",
"Slavers": []
},
"UseCamelCase": true,
"Assemblies": [ "BotSharp.Core" ]
},
"Providers": {
"ChatCompletionProvider": "BotSharp.Plugins.LLamaSharp.ChatCompletionProvider"
}
}

View file

@ -10,10 +10,13 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.10" />
<PackageReference Include="coverlet.collector" Version="3.2.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.2" />
<PackageReference Include="MSTest.TestAdapter" Version="3.0.4" />
<PackageReference Include="MSTest.TestFramework" Version="3.0.4" />
<PackageReference Include="coverlet.collector" Version="6.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>