commit
5189158d3f
|
|
@ -0,0 +1,9 @@
|
|||
using BotSharp.Abstraction.Knowledges.Models;
|
||||
|
||||
namespace BotSharp.Abstraction.Knowledges;
|
||||
|
||||
public interface IKnowledgeService
|
||||
{
|
||||
Task Feed(KnowledgeFeedModel knowledge);
|
||||
Task<string> GetAnswer(string question);
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
namespace BotSharp.Abstraction.Knowledges.Models;
|
||||
|
||||
public class KnowledgeFeedModel
|
||||
{
|
||||
public string AgentId { get; set; } = string.Empty;
|
||||
public string Content { get; set; } = string.Empty;
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
namespace BotSharp.Abstraction.MLTasks;
|
||||
|
||||
public interface ITextCompletion
|
||||
{
|
||||
Task<string> GetCompletion(string text);
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
namespace BotSharp.Abstraction.MLTasks;
|
||||
|
||||
public interface ITextEmbedding
|
||||
{
|
||||
float[] GetVector(string text);
|
||||
}
|
||||
|
|
@ -1,5 +1,9 @@
|
|||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace BotSharp.Abstraction.Plugins;
|
||||
|
||||
public interface IBotSharpPlugin
|
||||
{
|
||||
void RegisterDI(IServiceCollection services, IConfiguration config);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
namespace BotSharp.Abstraction.Plugins;
|
||||
|
||||
public class PluginLoaderSettings
|
||||
{
|
||||
public string[] Assemblies { get; set; }
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
namespace BotSharp.Abstraction.Users;
|
||||
|
||||
public interface IUserIdentity
|
||||
{
|
||||
string Id { get; }
|
||||
string Email { get; }
|
||||
string FirstName { get; }
|
||||
string LastName { get; }
|
||||
}
|
||||
|
|
@ -7,9 +7,9 @@ namespace BotSharp.Core.Agents.Services;
|
|||
public class AgentService : IAgentService
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly ICurrentUser _user;
|
||||
private readonly IUserIdentity _user;
|
||||
|
||||
public AgentService(IServiceProvider services, ICurrentUser user)
|
||||
public AgentService(IServiceProvider services, IUserIdentity user)
|
||||
{
|
||||
_services = services;
|
||||
_user = user;
|
||||
|
|
|
|||
|
|
@ -66,8 +66,11 @@
|
|||
<PackageReference Include="EntityFrameworkCore.BootKit" Version="6.2.1" />
|
||||
<PackageReference Include="LLamaSharp" Version="0.3.0" />
|
||||
<PackageReference Include="LLamaSharp.Backend.Cuda11" Version="0.3.0" />
|
||||
<PackageReference Include="PdfPig" Version="0.1.8" />
|
||||
<PackageReference Include="Qdrant.Client" Version="0.1.0" />
|
||||
<PackageReference Include="TensorFlow.Keras" Version="0.10.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
|
||||
<PackageReference Include="FastText.NetWrapper" Version="1.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
using BotSharp.Abstraction.Agents;
|
||||
using BotSharp.Abstraction.Conversations;
|
||||
using BotSharp.Abstraction.Infrastructures.ContentTransmitters;
|
||||
using BotSharp.Abstraction.Knowledges;
|
||||
using BotSharp.Abstraction.Users;
|
||||
using BotSharp.Core.Agents.Services;
|
||||
using BotSharp.Core.Conversations.Services;
|
||||
using BotSharp.Core.Infrastructures;
|
||||
using BotSharp.Core.Knowledges.Services;
|
||||
using BotSharp.Core.Plugins;
|
||||
using BotSharp.Core.Users.Services;
|
||||
using BotSharp.Plugins.LLamaSharp;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
|
|
@ -16,11 +19,12 @@ public static class BotSharpServiceCollectionExtensions
|
|||
{
|
||||
public static IServiceCollection AddBotSharp(this IServiceCollection services, IConfiguration config)
|
||||
{
|
||||
services.AddScoped<ICurrentUser, CurrentUser>();
|
||||
services.AddScoped<IUserIdentity, UserIdentity>();
|
||||
services.AddScoped<IUserService, UserService>();
|
||||
services.AddScoped<IAgentService, AgentService>();
|
||||
services.AddScoped<ISessionService, SessionService>();
|
||||
services.AddScoped<IConversationService, ConversationService>();
|
||||
services.AddScoped<IKnowledgeService, KnowledgeService>();
|
||||
|
||||
services.AddScoped<IContentTransfer, ContentTransfer>();
|
||||
|
||||
|
|
@ -74,14 +78,10 @@ public static class BotSharpServiceCollectionExtensions
|
|||
|
||||
public static void RegisterPlugins(IServiceCollection services, IConfiguration config)
|
||||
{
|
||||
var settings = new LlamaSharpSettings();
|
||||
config.Bind("LlamaSharp", settings);
|
||||
services.AddSingleton(x =>
|
||||
{
|
||||
var pluginSettings = new PluginLoaderSettings();
|
||||
config.Bind("PluginLoader", pluginSettings);
|
||||
|
||||
return settings;
|
||||
});
|
||||
|
||||
// services.AddScoped<IServiceZone, ChatCompletionProvider>();
|
||||
var loader = new PluginLoader(services, config, pluginSettings);
|
||||
loader.Load();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ namespace BotSharp.Core.Conversations.Services;
|
|||
public class SessionService : ISessionService
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly ICurrentUser _user;
|
||||
private readonly IUserIdentity _user;
|
||||
|
||||
public SessionService(IServiceProvider services, ICurrentUser user)
|
||||
public SessionService(IServiceProvider services, IUserIdentity user)
|
||||
{
|
||||
_services = services;
|
||||
_user = user;
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ namespace BotSharp.Core.Infrastructures;
|
|||
public class ContentTransfer : IContentTransfer
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly ICurrentUser _user;
|
||||
private readonly IUserIdentity _user;
|
||||
|
||||
public ContentTransfer(IServiceProvider services, ICurrentUser user)
|
||||
public ContentTransfer(IServiceProvider services, IUserIdentity user)
|
||||
{
|
||||
_services = services;
|
||||
_user = user;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
using BotSharp.Abstraction.ApiAdapters;
|
||||
using BotSharp.Abstraction.Knowledges;
|
||||
using BotSharp.Abstraction.Knowledges.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.IO;
|
||||
using UglyToad.PdfPig.Content;
|
||||
using UglyToad.PdfPig;
|
||||
|
||||
namespace BotSharp.Core.Knowledges;
|
||||
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
public class KnowledgeController : ControllerBase, IApiAdapter
|
||||
{
|
||||
private readonly IKnowledgeService _knowledgeService;
|
||||
public KnowledgeController(IKnowledgeService knowledgeService)
|
||||
{
|
||||
_knowledgeService = knowledgeService;
|
||||
}
|
||||
|
||||
[HttpGet("/knowledge")]
|
||||
public async Task<string> GetAnswer([FromQuery(Name = "q")] string question)
|
||||
{
|
||||
return await _knowledgeService.GetAnswer(question);
|
||||
}
|
||||
|
||||
[HttpPost("/knowledge/feed/{agentId}")]
|
||||
public async Task<IActionResult> FeedKnowledge([FromRoute] string agentId, List<IFormFile> files)
|
||||
{
|
||||
long size = files.Sum(f => f.Length);
|
||||
|
||||
foreach (var formFile in files)
|
||||
{
|
||||
if (formFile.Length <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var filePath = Path.GetTempFileName();
|
||||
|
||||
using (var stream = System.IO.File.Create(filePath))
|
||||
{
|
||||
await formFile.CopyToAsync(stream);
|
||||
}
|
||||
|
||||
var document = PdfDocument.Open(filePath);
|
||||
var content = "";
|
||||
foreach (Page page in document.GetPages())
|
||||
{
|
||||
content += page.Text;
|
||||
}
|
||||
|
||||
// Process uploaded files
|
||||
// Don't rely on or trust the FileName property without validation.
|
||||
|
||||
await _knowledgeService.Feed(new KnowledgeFeedModel
|
||||
{
|
||||
AgentId = agentId,
|
||||
Content = content
|
||||
});
|
||||
}
|
||||
|
||||
return Ok(new { count = files.Count, size });
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
using BotSharp.Abstraction.Knowledges;
|
||||
using BotSharp.Abstraction.Knowledges.Models;
|
||||
using QdrantCSharp.Enums;
|
||||
using QdrantCSharp.Models;
|
||||
using QdrantCSharp;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using BotSharp.Abstraction.MLTasks;
|
||||
|
||||
namespace BotSharp.Core.Knowledges.Services;
|
||||
|
||||
public class KnowledgeService : IKnowledgeService
|
||||
{
|
||||
private readonly ITextEmbedding _textEmbedding;
|
||||
private readonly ITextCompletion _textCompletion;
|
||||
string collectionName = "my_collection";
|
||||
public KnowledgeService(ITextEmbedding textEmbedding, ITextCompletion textCompletion)
|
||||
{
|
||||
_textEmbedding = textEmbedding;
|
||||
_textCompletion = textCompletion;
|
||||
}
|
||||
|
||||
public QdrantHttpClient GetClient()
|
||||
{
|
||||
var client = new QdrantHttpClient
|
||||
(
|
||||
url: "",
|
||||
apiKey: ""
|
||||
);
|
||||
return client;
|
||||
}
|
||||
|
||||
public async Task Feed(KnowledgeFeedModel knowledge)
|
||||
{
|
||||
var client = GetClient();
|
||||
|
||||
// List all the collections
|
||||
var collections = await client.GetCollections();
|
||||
if (!collections.Result.Collections.Select(x => x.Name).Contains(collectionName))
|
||||
{
|
||||
// Create a new collection
|
||||
await client.CreateCollection(collectionName, new VectorParams(size: 300, distance: Distance.COSINE));
|
||||
}
|
||||
|
||||
// Get collection info
|
||||
var collectionInfo = await client.GetCollection(collectionName);
|
||||
var idStart = 0;
|
||||
var lines = knowledge.Content.Split(". ");
|
||||
lines = lines.Select((x, i) => $"{i+1} {x}").ToArray();
|
||||
File.WriteAllLines(collectionName + ".txt", lines);
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
idStart++;
|
||||
|
||||
// Insert vectors
|
||||
/*await client.Upsert(collectionName, points: new List<PointStruct>
|
||||
{
|
||||
new PointStruct(id: idStart, vector: _textEmbedding.GetVector(line))
|
||||
});*/
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<string> GetAnswer(string question)
|
||||
{
|
||||
var client = GetClient();
|
||||
var vector = _textEmbedding.GetVector(question);
|
||||
|
||||
// Vector search
|
||||
var result = await client.Search
|
||||
(
|
||||
collectionName,
|
||||
vector,
|
||||
limit: 10
|
||||
);
|
||||
|
||||
var prompt = "";
|
||||
var lines = File.ReadAllLines(collectionName + ".txt");
|
||||
foreach (var r in result.Result)
|
||||
{
|
||||
prompt += lines[r.Id - 1] + "\n";
|
||||
}
|
||||
|
||||
prompt += "###\r\n";
|
||||
prompt += "Answer the user's question based on the content provided above, and your reply should be as concise and organized as possible.\r\n";
|
||||
prompt += "Q: how to turn on Hood Light? \r\nA: Press the Hood Light keypad to turn the light beneath the hood on or off.\r\n";
|
||||
prompt += $"Q: {question}\r\nA: ";
|
||||
|
||||
var completion = await _textCompletion.GetCompletion(prompt);
|
||||
return completion;
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ using System.IO;
|
|||
|
||||
namespace BotSharp.Plugins.LLamaSharp;
|
||||
|
||||
public class ChatCompletionProvider : IBotSharpPlugin, IServiceZone
|
||||
public class ChatCompletionProvider : IServiceZone
|
||||
{
|
||||
private readonly IChatModel _model;
|
||||
private readonly LlamaSharpSettings _settings;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,15 @@
|
|||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace BotSharp.Plugins.LLamaSharp;
|
||||
|
||||
public class LLamaSharpPlugin : IBotSharpPlugin
|
||||
{
|
||||
public void RegisterDI(IServiceCollection services, IConfiguration config)
|
||||
{
|
||||
var llamaSharpSettings = new LlamaSharpSettings();
|
||||
config.Bind("LlamaSharp", llamaSharpSettings);
|
||||
services.AddSingleton(x => llamaSharpSettings);
|
||||
|
||||
// services.AddScoped<IServiceZone, ChatCompletionProvider>();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
53
src/Infrastructure/BotSharp.Core/Plugins/PluginLoader.cs
Normal file
53
src/Infrastructure/BotSharp.Core/Plugins/PluginLoader.cs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
using Microsoft.Extensions.Configuration;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
namespace BotSharp.Core.Plugins;
|
||||
|
||||
public class PluginLoader
|
||||
{
|
||||
private readonly IServiceCollection _services;
|
||||
private readonly IConfiguration _config;
|
||||
private readonly PluginLoaderSettings _settings;
|
||||
private static List<IBotSharpPlugin> _modules = new List<IBotSharpPlugin>();
|
||||
|
||||
public PluginLoader(IServiceCollection services,
|
||||
IConfiguration config,
|
||||
PluginLoaderSettings settings)
|
||||
{
|
||||
_services = services;
|
||||
_config = config;
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public void Load()
|
||||
{
|
||||
var executingDir = Directory.GetParent(Assembly.GetEntryAssembly().Location).FullName;
|
||||
|
||||
_settings.Assemblies.ToList().ForEach(assemblyName =>
|
||||
{
|
||||
var assemblyPath = Path.Combine(executingDir, assemblyName + ".dll");
|
||||
if (File.Exists(assemblyPath))
|
||||
{
|
||||
var assembly = Assembly.Load(assemblyName);
|
||||
|
||||
var modules = assembly.GetTypes()
|
||||
.Where(x => x.GetInterface(nameof(IBotSharpPlugin)) != null)
|
||||
.Select(x => Activator.CreateInstance(x) as IBotSharpPlugin)
|
||||
.ToList();
|
||||
|
||||
foreach (var module in modules)
|
||||
{
|
||||
module.RegisterDI(_services, _config);
|
||||
Console.WriteLine($"Loaded plugin {module.GetType().Name} from {assemblyName}.");
|
||||
}
|
||||
|
||||
_modules.AddRange(modules);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Can't find assemble {assemblyPath}.");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
using BotSharp.Abstraction.MLTasks;
|
||||
using FastText.NetWrapper;
|
||||
|
||||
namespace BotSharp.Core.Plugins.fastText;
|
||||
|
||||
public class fastTextEmbeddingProvider : ITextEmbedding
|
||||
{
|
||||
FastTextWrapper fastText;
|
||||
public fastTextEmbeddingProvider()
|
||||
{
|
||||
fastText = new FastTextWrapper();
|
||||
|
||||
if (!fastText.IsModelReady())
|
||||
{
|
||||
fastText.LoadModel(@"D:\Service Mesh\prediction\WebStarter\tmp_data\models\crawl-300d-2M-subword.bin");
|
||||
}
|
||||
}
|
||||
|
||||
public float[] GetVector(string text)
|
||||
{
|
||||
return fastText.GetSentenceVector(text);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
using BotSharp.Abstraction.MLTasks;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace BotSharp.Core.Plugins.fastText;
|
||||
|
||||
public class fastTextPlugin : IBotSharpPlugin
|
||||
{
|
||||
public void RegisterDI(IServiceCollection services, IConfiguration config)
|
||||
{
|
||||
services.AddSingleton<ITextEmbedding, fastTextEmbeddingProvider>();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
using BotSharp.Abstraction.Users;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace BotSharp.Core.Users.Services;
|
||||
|
||||
public class UserIdentity : IUserIdentity
|
||||
{
|
||||
private readonly IHttpContextAccessor _contextAccessor;
|
||||
private IEnumerable<Claim> _claims => _contextAccessor.HttpContext.User.Claims;
|
||||
|
||||
public UserIdentity(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;
|
||||
}
|
||||
|
|
@ -13,9 +13,9 @@ namespace BotSharp.Core.Users.Services;
|
|||
public class UserService : IUserService
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly ICurrentUser _user;
|
||||
private readonly IUserIdentity _user;
|
||||
|
||||
public UserService(IServiceProvider services, ICurrentUser user)
|
||||
public UserService(IServiceProvider services, IUserIdentity user)
|
||||
{
|
||||
_services = services;
|
||||
_user = user;
|
||||
|
|
|
|||
22
src/Plugins/BotSharp.Plugin.AzureOpenAI/AzureOpenAiPlugin.cs
Normal file
22
src/Plugins/BotSharp.Plugin.AzureOpenAI/AzureOpenAiPlugin.cs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
using BotSharp.Abstraction.Infrastructures.ContentTransfers;
|
||||
using BotSharp.Abstraction.MLTasks;
|
||||
using BotSharp.Abstraction.Plugins;
|
||||
using BotSharp.Plugin.AzureOpenAI.TextGeneratives;
|
||||
using BotSharp.Plugin.AzureOpenAI.TextTasks;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace BotSharp.Platform.AzureAi;
|
||||
|
||||
public class AzureOpenAiPlugin : IBotSharpPlugin
|
||||
{
|
||||
public void RegisterDI(IServiceCollection services, IConfiguration config)
|
||||
{
|
||||
var settings = new AzureOpenAiSettings();
|
||||
config.Bind("AzureOpenAi", settings);
|
||||
services.AddSingleton(x => settings);
|
||||
|
||||
services.AddSingleton<ITextCompletion, TextCompletionProvider>();
|
||||
services.AddScoped<IServiceZone, ChatCompletionProvider>();
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ public class AzureOpenAiSettings
|
|||
{
|
||||
public string ApiKey { get; set; } = string.Empty;
|
||||
public string Endpoint { get; set; } = string.Empty;
|
||||
public string DeploymentModel { get; set; } = string.Empty;
|
||||
public string DeploymentName { get; set; } = string.Empty;
|
||||
public string InstructionFile { get; set; } = string.Empty;
|
||||
public string ChatSampleFile { get; set; } = string.Empty;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,130 @@
|
|||
using Azure;
|
||||
using Azure.AI.OpenAI;
|
||||
using BotSharp.Abstraction.Infrastructures.ContentTransfers;
|
||||
using BotSharp.Abstraction.Infrastructures.ContentTransmitters;
|
||||
using BotSharp.Abstraction.Models;
|
||||
using BotSharp.Platform.AzureAi;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BotSharp.Plugin.AzureOpenAI.TextGeneratives;
|
||||
|
||||
public class ChatCompletionProvider : IServiceZone
|
||||
{
|
||||
private readonly AzureOpenAiSettings _settings;
|
||||
|
||||
public ChatCompletionProvider(AzureOpenAiSettings settings)
|
||||
{
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public async Task GetChatCompletionsAsync(List<RoleDialogModel> conversations,
|
||||
Func<string, Task> onChunkReceived)
|
||||
{
|
||||
var client = new OpenAIClient(new Uri(_settings.Endpoint), new AzureKeyCredential(_settings.ApiKey));
|
||||
var chatCompletionsOptions = PrepareOptions(conversations);
|
||||
|
||||
var response = await client.GetChatCompletionsStreamingAsync(_settings.DeploymentName, chatCompletionsOptions);
|
||||
using StreamingChatCompletions streaming = response.Value;
|
||||
|
||||
string content = "";
|
||||
await foreach (var choice in streaming.GetChoicesStreaming())
|
||||
{
|
||||
await foreach (var message in choice.GetMessageStreaming())
|
||||
{
|
||||
if (message.Content == null)
|
||||
continue;
|
||||
Console.Write(message.Content);
|
||||
content += message.Content;
|
||||
await onChunkReceived(message.Content);
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
public List<RoleDialogModel> GetChatSamples()
|
||||
{
|
||||
var samples = new List<RoleDialogModel>();
|
||||
if (!string.IsNullOrEmpty(_settings.ChatSampleFile))
|
||||
{
|
||||
var lines = File.ReadAllLines(_settings.ChatSampleFile);
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
var line = lines[i];
|
||||
var role = line.Substring(0, line.IndexOf(' ') - 1);
|
||||
var content = line.Substring(line.IndexOf(' ') + 1);
|
||||
|
||||
samples.Add(new RoleDialogModel
|
||||
{
|
||||
Role = role,
|
||||
Content = content
|
||||
});
|
||||
}
|
||||
}
|
||||
return samples;
|
||||
}
|
||||
|
||||
public string GetInstruction()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_settings.InstructionFile))
|
||||
{
|
||||
return File.ReadAllText(_settings.InstructionFile);
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public async Task Serving(ContentContainer content)
|
||||
{
|
||||
var client = new OpenAIClient(new Uri(_settings.Endpoint), new AzureKeyCredential(_settings.ApiKey));
|
||||
var chatCompletionsOptions = PrepareOptions(content.Conversations);
|
||||
|
||||
var response = await client.GetChatCompletionsStreamingAsync(_settings.DeploymentName, chatCompletionsOptions);
|
||||
using StreamingChatCompletions streaming = response.Value;
|
||||
|
||||
string output = "";
|
||||
await foreach (var choice in streaming.GetChoicesStreaming())
|
||||
{
|
||||
await foreach (var message in choice.GetMessageStreaming())
|
||||
{
|
||||
if (message.Content == null)
|
||||
continue;
|
||||
Console.Write(message.Content);
|
||||
output += message.Content;
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
content.Output = new RoleDialogModel
|
||||
{
|
||||
Role = ChatRole.Assistant.ToString(),
|
||||
Content = output
|
||||
};
|
||||
}
|
||||
|
||||
private ChatCompletionsOptions PrepareOptions(List<RoleDialogModel> conversations)
|
||||
{
|
||||
var prompt = GetInstruction();
|
||||
var chatCompletionsOptions = new ChatCompletionsOptions()
|
||||
{
|
||||
Messages =
|
||||
{
|
||||
new ChatMessage(ChatRole.System, prompt)
|
||||
}
|
||||
};
|
||||
|
||||
foreach (var message in GetChatSamples())
|
||||
{
|
||||
chatCompletionsOptions.Messages.Add(new ChatMessage(message.Role, message.Content));
|
||||
}
|
||||
|
||||
foreach (var message in conversations)
|
||||
{
|
||||
chatCompletionsOptions.Messages.Add(new ChatMessage(message.Role, message.Content));
|
||||
}
|
||||
|
||||
return chatCompletionsOptions;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
using Azure.AI.OpenAI;
|
||||
using Azure;
|
||||
using BotSharp.Abstraction.MLTasks;
|
||||
using BotSharp.Platform.AzureAi;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BotSharp.Plugin.AzureOpenAI.TextTasks;
|
||||
|
||||
public class TextCompletionProvider : ITextCompletion
|
||||
{
|
||||
private readonly AzureOpenAiSettings _settings;
|
||||
bool _useAzureOpenAI = true;
|
||||
|
||||
public TextCompletionProvider(AzureOpenAiSettings settings)
|
||||
{
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public async Task<string> GetCompletion(string text)
|
||||
{
|
||||
var client = GetOpenAIClient();
|
||||
var completionsOptions = new CompletionsOptions()
|
||||
{
|
||||
Prompts =
|
||||
{
|
||||
text
|
||||
},
|
||||
Temperature = 0.5f,
|
||||
MaxTokens = 128
|
||||
};
|
||||
|
||||
var response = await client.GetCompletionsAsync(
|
||||
deploymentOrModelName: _settings.DeploymentName,
|
||||
completionsOptions);
|
||||
|
||||
// OpenAI
|
||||
var completion = "";
|
||||
foreach (var t in response.Value.Choices)
|
||||
{
|
||||
completion += t.Text;
|
||||
};
|
||||
|
||||
return completion;
|
||||
}
|
||||
|
||||
private OpenAIClient GetOpenAIClient()
|
||||
{
|
||||
OpenAIClient client = _useAzureOpenAI
|
||||
? new OpenAIClient(
|
||||
new Uri(_settings.Endpoint),
|
||||
new AzureKeyCredential(_settings.ApiKey))
|
||||
: new OpenAIClient("your-api-key-from-platform.openai.com");
|
||||
return client;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
using BotSharp.Abstraction.Users;
|
||||
using BotSharp.Core;
|
||||
using BotSharp.Core.Users.Services;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using System.Text;
|
||||
|
|
@ -36,7 +38,6 @@ builder.Services.AddAuthentication(options =>
|
|||
|
||||
// Add BotSharp
|
||||
builder.Services.AddBotSharp(builder.Configuration);
|
||||
builder.Services.AddAzureOpenAiPlatform(builder.Configuration);
|
||||
|
||||
builder.Services.AddCors(options =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -42,7 +42,10 @@
|
|||
"Assemblies": [ "BotSharp.Core" ]
|
||||
},
|
||||
|
||||
"Providers": {
|
||||
"ChatCompletionProvider": "BotSharp.Plugins.LLamaSharp.ChatCompletionProvider"
|
||||
"PluginLoader": {
|
||||
"Assemblies": [
|
||||
"BotSharp.Core",
|
||||
"BotSharp.Plugin.AzureOpenAI"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue