Skip to content

fix file selection #979

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,16 @@ namespace BotSharp.Abstraction.Agents.Models;

public class McpTool
{
[JsonPropertyName("name")]
public string Name { get; set; }

[JsonPropertyName("server_id")]
public string ServerId { get; set; }

[JsonPropertyName("disabled")]
public bool Disabled { get; set; }

[JsonPropertyName("functions")]
public IEnumerable<McpFunction> Functions { get; set; } = [];

public McpTool()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ public class SelectFileOptions
public string? Provider { get; set; }

/// <summary>
/// Llm model id
/// Llm model
/// </summary>
public string? ModelId { get; set; }
public string? Model { get; set; }

/// <summary>
/// Agent id
Expand Down
6 changes: 3 additions & 3 deletions src/Infrastructure/BotSharp.Core.MCP/BotSharpMCPExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ public static class BotSharpMcpExtensions
/// <returns></returns>
public static IServiceCollection AddBotSharpMCP(this IServiceCollection services, IConfiguration config)
{
var settings = config.GetSection("MCPSettings").Get<McpSettings>();
services.AddScoped<McpSettings>(provider => { return settings; });
if (settings != null && !settings.McpServerConfigs.IsNullOrEmpty())
var settings = config.GetSection("MCP").Get<McpSettings>();
services.AddScoped(provider => { return settings; });
if (settings != null && settings.Enabled && !settings.McpServerConfigs.IsNullOrEmpty())
{
var clientManager = new McpClientManager(settings);
services.AddSingleton(clientManager);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using BotSharp.Core.MCP.Helpers;
using BotSharp.Core.MCP.Managers;
using BotSharp.Core.MCP.Settings;
using ModelContextProtocol.Client;

namespace BotSharp.Core.MCP.Hooks;
Expand Down Expand Up @@ -39,6 +40,13 @@ public override void OnAgentMcpToolLoaded(Agent agent)
private async Task<IEnumerable<FunctionDef>> GetMcpContent(Agent agent)
{
var functionDefs = new List<FunctionDef>();

var settings = _services.GetRequiredService<McpSettings>();
if (settings?.Enabled != true)
{
return functionDefs;
}

var mcpClientManager = _services.GetRequiredService<McpClientManager>();
var mcps = agent.McpTools.Where(x => !x.Disabled);
foreach (var item in mcps)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,18 @@ namespace BotSharp.Core.MCP.Managers;

public class McpClientManager : IDisposable
{
private readonly McpSettings _mcpSettings;

private readonly McpSettings mcpSettings;

public McpClientManager(McpSettings settings)
public McpClientManager(McpSettings mcpSettings)
{
mcpSettings = settings;
_mcpSettings = mcpSettings;
}

public async Task<IMcpClient> GetMcpClientAsync(string serverId)
{
return await McpClientFactory.CreateAsync(
mcpSettings.McpServerConfigs.Where(x=> x.Name == serverId).First(),
mcpSettings.McpClientOptions);
_mcpSettings.McpServerConfigs.Where(x=> x.Name == serverId).First(),
_mcpSettings.McpClientOptions);
}

public void Dispose()
Expand Down
29 changes: 29 additions & 0 deletions src/Infrastructure/BotSharp.Core.MCP/McpPlugin.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using BotSharp.Abstraction.Plugins.Models;
using BotSharp.Abstraction.Plugins;
using BotSharp.Abstraction.Settings;
using BotSharp.Core.MCP.Settings;
using Microsoft.Extensions.Configuration;

namespace BotSharp.Core.MCP;

public class McpPlugin : IBotSharpPlugin
{
public string Id => "0cfb486a-229e-4470-a4c6-d2d4a5fdc727";
public string Name => "Model context protocol";
public string Description => "Model context protocol";

public SettingsMeta Settings =>
new SettingsMeta("MCP");

public object GetNewSettingsInstance() =>
new McpSettings();

public void RegisterDI(IServiceCollection services, IConfiguration config)
{
}

public bool AttachMenu(List<PluginMenuDef> menu)
{
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace BotSharp.Core.MCP.Settings;

public class McpSettings
{
public bool Enabled { get; set; } = true;
public McpClientOptions McpClientOptions { get; set; }
public List<McpServerConfig> McpServerConfigs { get; set; } = new();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public async Task<RoleDialogModel> GenerateImage(string text, InstructOptions? o
{
Id = innerAgentId,
Instruction = instruction
}, new RoleDialogModel(AgentRole.User, text));
}, new RoleDialogModel(AgentRole.User, instruction ?? text));

var hooks = _services.GetServices<IInstructHook>();
foreach (var hook in hooks)
Expand Down Expand Up @@ -90,8 +90,6 @@ public async Task<RoleDialogModel> VaryImage(InstructFileModel image, InstructOp
}

var innerAgentId = options?.AgentId ?? Guid.Empty.ToString();
var instruction = await GetAgentTemplate(innerAgentId, options?.TemplateName);

var completion = CompletionProvider.GetImageCompletion(_services, provider: options?.Provider ?? "openai", model: options?.Model ?? "dall-e-2");
var bytes = await DownloadFile(image);
using var stream = new MemoryStream();
Expand All @@ -101,8 +99,7 @@ public async Task<RoleDialogModel> VaryImage(InstructFileModel image, InstructOp
var fileName = $"{image.FileName ?? "image"}.{image.FileExtension ?? "png"}";
var message = await completion.GetImageVariation(new Agent()
{
Id = innerAgentId,
Instruction = instruction
Id = innerAgentId
}, new RoleDialogModel(AgentRole.User, string.Empty), stream, fileName);

stream.Close();
Expand All @@ -120,9 +117,7 @@ await hook.OnResponseGenerated(new InstructResponseModel
AgentId = innerAgentId,
Provider = completion.Provider,
Model = completion.Model,
TemplateName = options?.TemplateName,
UserMessage = string.Empty,
SystemInstruction = instruction,
CompletionText = message.Content
});
}
Expand All @@ -149,9 +144,8 @@ public async Task<RoleDialogModel> EditImage(string text, InstructFileModel imag
var fileName = $"{image.FileName ?? "image"}.{image.FileExtension ?? "png"}";
var message = await completion.GetImageEdits(new Agent()
{
Id = innerAgentId,
Instruction = instruction
}, new RoleDialogModel(AgentRole.User, text), stream, fileName);
Id = innerAgentId
}, new RoleDialogModel(AgentRole.User, instruction ?? text), stream, fileName);

stream.Close();

Expand Down Expand Up @@ -205,9 +199,8 @@ public async Task<RoleDialogModel> EditImage(string text, InstructFileModel imag
var maskName = $"{mask.FileName ?? "mask"}.{mask.FileExtension ?? "png"}";
var message = await completion.GetImageEdits(new Agent()
{
Id = innerAgentId,
Instruction = instruction
}, new RoleDialogModel(AgentRole.User, text), imageStream, imageName, maskStream, maskName);
Id = innerAgentId
}, new RoleDialogModel(AgentRole.User, instruction ?? text), imageStream, imageName, maskStream, maskName);

imageStream.Close();
maskStream.Close();
Expand All @@ -234,23 +227,4 @@ await hook.OnResponseGenerated(new InstructResponseModel

return message;
}

#region Private methods
private async Task<byte[]> DownloadFile(InstructFileModel file)
{
var bytes = new byte[0];
if (!string.IsNullOrEmpty(file.FileUrl))
{
var http = _services.GetRequiredService<IHttpClientFactory>();
using var client = http.CreateClient();
bytes = await client.GetByteArrayAsync(file.FileUrl);
}
else if (!string.IsNullOrEmpty(file.FileData))
{
(_, bytes) = FileUtility.GetFileInfoFromData(file.FileData);
}

return bytes;
}
#endregion
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,9 @@ private async Task<IEnumerable<MessageFileModel>> SelectFiles(IEnumerable<Messag
}

var providerName = options.Provider ?? "openai";
var modelId = options?.ModelId ?? "gpt-4o";
var model = options?.Model ?? "gpt-4o-mini";
var provider = llmProviderService.GetProviders().FirstOrDefault(x => x == providerName);
var model = llmProviderService.GetProviderModel(provider: provider, id: modelId);
var completion = CompletionProvider.GetChatCompletion(_services, provider: provider, model: model.Name);
var completion = CompletionProvider.GetChatCompletion(_services, provider: provider, model: model);

var response = await completion.GetChatCompletions(agent, new List<RoleDialogModel> { message });
var content = response?.Content ?? string.Empty;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public FileInstructService(
_services = services;
}

#region Private methods
private void DeleteIfExistDirectory(string? dir, bool createNew = false)
{
if (_fileStorage.ExistDirectory(dir))
Expand All @@ -31,6 +32,23 @@ private void DeleteIfExistDirectory(string? dir, bool createNew = false)
}
}

private async Task<byte[]> DownloadFile(InstructFileModel file)
{
var bytes = new byte[0];
if (!string.IsNullOrEmpty(file.FileUrl))
{
var http = _services.GetRequiredService<IHttpClientFactory>();
using var client = http.CreateClient();
bytes = await client.GetByteArrayAsync(file.FileUrl);
}
else if (!string.IsNullOrEmpty(file.FileData))
{
(_, bytes) = FileUtility.GetFileInfoFromData(file.FileData);
}

return bytes;
}

private async Task<string?> GetAgentTemplate(string agentId, string? templateName)
{
if (string.IsNullOrWhiteSpace(agentId) || string.IsNullOrWhiteSpace(templateName))
Expand All @@ -48,4 +66,5 @@ private void DeleteIfExistDirectory(string? dir, bool createNew = false)
var instruction = agentService.RenderedTemplate(agent, templateName);
return instruction;
}
#endregion
}
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,7 @@ public async Task<ImageGenerationViewModel> ImageVariation([FromBody] ImageVaria
{
Provider = input.Provider,
Model = input.Model,
AgentId = input.AgentId,
TemplateName = input.TemplateName
AgentId = input.AgentId
});
imageViewModel.Content = message.Content;
imageViewModel.Images = message.GeneratedImages.Select(x => ImageViewModel.ToViewModel(x)).ToList();
Expand All @@ -262,7 +261,7 @@ public async Task<ImageGenerationViewModel> ImageVariation([FromBody] ImageVaria
[HttpPost("/instruct/image-variation/upload")]
public async Task<ImageGenerationViewModel> ImageVariation(IFormFile file, [FromForm] string? provider = null,
[FromForm] string? model = null, [FromForm] List<MessageState>? states = null,
[FromForm] string? agentId = null, [FromForm] string? templateName = null)
[FromForm] string? agentId = null)
{
var state = _services.GetRequiredService<IConversationStateService>();
states?.ForEach(x => state.SetState(x.Key, x.Value, activeRounds: x.ActiveRounds, source: StateSource.External));
Expand All @@ -276,8 +275,7 @@ public async Task<ImageGenerationViewModel> ImageVariation(IFormFile file, [From
{
Provider = provider,
Model = model,
AgentId = agentId,
TemplateName = templateName
AgentId = agentId
});

imageViewModel.Content = message.Content;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using OpenAI.Images;
using static System.Net.Mime.MediaTypeNames;

namespace BotSharp.Plugin.OpenAI.Providers.Image;

Expand Down
3 changes: 2 additions & 1 deletion src/WebStarter/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,8 @@
}
},

"MCPSettings": {
"MCP": {
"Enabled": true,
"McpClientOptions": {
"ClientInfo": {
"Name": "SimpleToolsBotsharp",
Expand Down
Loading