add file llm processor

This commit is contained in:
Jicheng Lu 2025-10-14 13:52:01 -05:00
parent 32bea332f8
commit 9dab7c8343
7 changed files with 125 additions and 17 deletions

View file

@ -0,0 +1,34 @@
namespace BotSharp.Abstraction.Files.Models;
public class FileLlmProcessOptions
{
/// <summary>
/// Llm provider
/// </summary>
public string? LlmProvider { get; set; }
/// <summary>
/// llm model
/// </summary>
public string? LlModel { get; set; }
/// <summary>
/// Reasoning effort level
/// </summary>
public string? ReasoningEfforLevel { get; set; }
/// <summary>
/// Instruction
/// </summary>
public string? Instruction { get; set; }
/// <summary>
/// Template name in Agent
/// </summary>
public string? TemplateName { get; set; }
/// <summary>
/// Data that is used to render instruction
/// </summary>
public Dictionary<string, object>? Data { get; set; }
}

View file

@ -0,0 +1,9 @@
namespace BotSharp.Abstraction.Files.Proccessors;
public interface IFileLlmProcessor
{
public string Provider { get; }
Task<RoleDialogModel> GetFileLlmInferenceAsync(Agent agent, string text, IEnumerable<InstructFileModel> files, FileLlmProcessOptions? options = null)
=> throw new NotImplementedException();
}

View file

@ -13,10 +13,13 @@ public interface IInstructService
/// <param name="templateName"></param> /// <param name="templateName"></param>
/// <param name="files"></param> /// <param name="files"></param>
/// <param name="codeOptions"></param> /// <param name="codeOptions"></param>
/// <param name="fileOptions"></param>
/// <returns></returns> /// <returns></returns>
Task<InstructResult> Execute(string agentId, RoleDialogModel message, Task<InstructResult> Execute(string agentId, RoleDialogModel message,
string? instruction = null, string? templateName = null, string? instruction = null, string? templateName = null,
IEnumerable<InstructFileModel>? files = null, CodeInstructOptions? codeOptions = null); IEnumerable<InstructFileModel>? files = null,
CodeInstructOptions? codeOptions = null,
FileInstructOptions? fileOptions = null);
/// <summary> /// <summary>
/// A generic way to execute completion by using specified instruction or template /// A generic way to execute completion by using specified instruction or template

View file

@ -0,0 +1,6 @@
namespace BotSharp.Abstraction.Instructs.Models;
public class FileInstructOptions
{
public string? FileLlmProcessorProvider { get; set; }
}

View file

@ -1,4 +1,5 @@
using BotSharp.Abstraction.CodeInterpreter; using BotSharp.Abstraction.CodeInterpreter;
using BotSharp.Abstraction.Files.Proccessors;
using BotSharp.Abstraction.Instructs; using BotSharp.Abstraction.Instructs;
using BotSharp.Abstraction.Instructs.Models; using BotSharp.Abstraction.Instructs.Models;
using BotSharp.Abstraction.MLTasks; using BotSharp.Abstraction.MLTasks;
@ -14,9 +15,11 @@ public partial class InstructService
string? instruction = null, string? instruction = null,
string? templateName = null, string? templateName = null,
IEnumerable<InstructFileModel>? files = null, IEnumerable<InstructFileModel>? files = null,
CodeInstructOptions? codeOptions = null) CodeInstructOptions? codeOptions = null,
FileInstructOptions? fileOptions = null)
{ {
var agentService = _services.GetRequiredService<IAgentService>(); var agentService = _services.GetRequiredService<IAgentService>();
var state = _services.GetRequiredService<IConversationStateService>();
Agent agent = await agentService.LoadAgent(agentId); Agent agent = await agentService.LoadAgent(agentId);
var response = new InstructResult var response = new InstructResult
@ -68,6 +71,7 @@ public partial class InstructService
var provider = string.Empty; var provider = string.Empty;
var model = string.Empty; var model = string.Empty;
var result = string.Empty;
// Render prompt // Render prompt
var prompt = string.IsNullOrEmpty(templateName) ? var prompt = string.IsNullOrEmpty(templateName) ?
@ -83,13 +87,14 @@ public partial class InstructService
provider = textCompleter.Provider; provider = textCompleter.Provider;
model = textCompleter.Model; model = textCompleter.Model;
var result = await textCompleter.GetCompletion(prompt, agentId, message.MessageId); result = await GetTextCompletion(textCompleter, agent, prompt, message.MessageId);
response.Text = result; response.Text = result;
} }
else if (completer is IChatCompletion chatCompleter) else if (completer is IChatCompletion chatCompleter)
{ {
provider = chatCompleter.Provider; provider = chatCompleter.Provider;
model = chatCompleter.Model; model = chatCompleter.Model;
if (instruction == "#TEMPLATE#") if (instruction == "#TEMPLATE#")
{ {
@ -97,21 +102,30 @@ public partial class InstructService
prompt = message.Content; prompt = message.Content;
} }
var result = await chatCompleter.GetChatCompletions(new Agent IFileLlmProcessor? fileProcessor = null;
if (!files.IsNullOrEmpty() && !string.IsNullOrEmpty(fileOptions?.FileLlmProcessorProvider))
{ {
Id = agentId, fileProcessor = _services.GetServices<IFileLlmProcessor>()
Name = agent.Name, .FirstOrDefault(x => x.Provider.IsEqualTo(fileOptions?.FileLlmProcessorProvider));
Instruction = instruction }
}, new List<RoleDialogModel>
if (fileProcessor != null)
{ {
new RoleDialogModel(AgentRole.User, prompt) var inference = await fileProcessor.GetFileLlmInferenceAsync(agent, prompt, files, new FileLlmProcessOptions
{ {
CurrentAgentId = agentId, LlmProvider = provider,
MessageId = message.MessageId, LlModel = model,
Files = files?.Select(x => new BotSharpFile { FileUrl = x.FileUrl, FileData = x.FileData, ContentType = x.ContentType }).ToList() ?? [] Instruction = instruction,
} TemplateName = templateName,
}); Data = state.GetStates().ToDictionary(x => x.Key, x => (object)x.Value)
response.Text = result.Content; });
result = inference?.Content ?? string.Empty;
}
else
{
result = await GetChatCompletion(chatCompleter, agent, instruction, prompt, message.MessageId, files);
}
response.Text = result;
} }
// After completion hooks // After completion hooks
@ -141,7 +155,11 @@ public partial class InstructService
/// <param name="templateName"></param> /// <param name="templateName"></param>
/// <param name="codeOptions"></param> /// <param name="codeOptions"></param>
/// <returns></returns> /// <returns></returns>
private async Task<InstructResult?> GetCodeResponse(Agent agent, RoleDialogModel message, string templateName, CodeInstructOptions? codeOptions) private async Task<InstructResult?> GetCodeResponse(
Agent agent,
RoleDialogModel message,
string templateName,
CodeInstructOptions? codeOptions)
{ {
InstructResult? response = null; InstructResult? response = null;
@ -261,4 +279,40 @@ public partial class InstructService
return response; return response;
} }
private async Task<string> GetTextCompletion(
ITextCompletion textCompleter,
Agent agent,
string text,
string messageId)
{
var result = await textCompleter.GetCompletion(text, agent.Id, messageId);
return result;
}
private async Task<string> GetChatCompletion(
IChatCompletion chatCompleter,
Agent agent,
string instruction,
string text,
string messageId,
IEnumerable<InstructFileModel>? files = null)
{
var result = await chatCompleter.GetChatCompletions(new Agent
{
Id = agent.Id,
Name = agent.Name,
Instruction = instruction
}, new List<RoleDialogModel>
{
new RoleDialogModel(AgentRole.User, text)
{
CurrentAgentId = agent.Id,
MessageId = messageId,
Files = files?.Select(x => new BotSharpFile { FileUrl = x.FileUrl, FileData = x.FileData, ContentType = x.ContentType }).ToList() ?? []
}
});
return result.Content;
}
} }

View file

@ -39,7 +39,8 @@ public class InstructModeController : ControllerBase
instruction: input.Instruction, instruction: input.Instruction,
templateName: input.Template, templateName: input.Template,
files: input.Files, files: input.Files,
codeOptions: input.CodeOptions); codeOptions: input.CodeOptions,
fileOptions: input.FileOptions);
result.States = state.GetStates(); result.States = state.GetStates();
return result; return result;

View file

@ -12,6 +12,7 @@ public class InstructMessageModel : IncomingMessageModel
public string? Template { get; set; } public string? Template { get; set; }
public List<InstructFileModel> Files { get; set; } = []; public List<InstructFileModel> Files { get; set; } = [];
public CodeInstructOptions? CodeOptions { get; set; } public CodeInstructOptions? CodeOptions { get; set; }
public FileInstructOptions? FileOptions { get; set; }
} }