Merge pull request #805 from iceljc/features/refine-load-utility
Features/refine load utility
This commit is contained in:
commit
3e6394a352
|
|
@ -18,7 +18,7 @@ public interface IAgentService
|
|||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
Task<Agent> LoadAgent(string id);
|
||||
Task<Agent> LoadAgent(string id, bool loadUtility = true);
|
||||
|
||||
/// <summary>
|
||||
/// Inherit from an agent
|
||||
|
|
|
|||
|
|
@ -118,6 +118,12 @@ public class Agent
|
|||
[JsonIgnore]
|
||||
public Dictionary<string, object> TemplateDict { get; set; } = new();
|
||||
|
||||
[JsonIgnore]
|
||||
public List<FunctionDef> SecondaryFunctions { get; set; } = [];
|
||||
|
||||
[JsonIgnore]
|
||||
public List<string> SecondaryInstructions { get; set; } = [];
|
||||
|
||||
public override string ToString()
|
||||
=> $"{Name} {Id}";
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ public class BasicAgentHook : AgentHookBase
|
|||
{
|
||||
public override string SelfId => string.Empty;
|
||||
|
||||
private const string UTIL_PREFIX = "util-";
|
||||
|
||||
public BasicAgentHook(IServiceProvider services, AgentSettings settings)
|
||||
: base(services, settings)
|
||||
{
|
||||
|
|
@ -17,22 +19,23 @@ public class BasicAgentHook : AgentHookBase
|
|||
var isConvMode = conv.IsConversationMode();
|
||||
if (!isConvMode) return;
|
||||
|
||||
agent.Functions ??= [];
|
||||
agent.SecondaryFunctions ??= [];
|
||||
agent.SecondaryInstructions ??= [];
|
||||
agent.Utilities ??= [];
|
||||
|
||||
var (functions, templates) = GetUtilityContent(agent);
|
||||
|
||||
foreach (var fn in functions)
|
||||
{
|
||||
if (!agent.Functions.Any(x => x.Name.Equals(fn.Name, StringComparison.OrdinalIgnoreCase)))
|
||||
if (!agent.SecondaryFunctions.Any(x => x.Name.Equals(fn.Name, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
agent.Functions.Add(fn);
|
||||
agent.SecondaryFunctions.Add(fn);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var prompt in templates)
|
||||
{
|
||||
agent.Instruction += $"\r\n\r\n{prompt}\r\n\r\n";
|
||||
agent.SecondaryInstructions.Add(prompt);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -67,14 +70,13 @@ public class BasicAgentHook : AgentHookBase
|
|||
return ([], []);
|
||||
}
|
||||
|
||||
var prefix = "util-";
|
||||
utilities = utilities?.Where(x => !string.IsNullOrEmpty(x.Name) && !x.Disabled)?.ToList() ?? [];
|
||||
var functionNames = utilities.SelectMany(x => x.Functions)
|
||||
.Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(prefix))
|
||||
.Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(UTIL_PREFIX))
|
||||
.Select(x => x.Name)
|
||||
.Distinct().ToList();
|
||||
var templateNames = utilities.SelectMany(x => x.Templates)
|
||||
.Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(prefix))
|
||||
.Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(UTIL_PREFIX))
|
||||
.Select(x => x.Name)
|
||||
.Distinct().ToList();
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ public partial class AgentService
|
|||
public static ConcurrentDictionary<string, Dictionary<string, string>> AgentParameterTypes = new();
|
||||
|
||||
[MemoryCache(10 * 60, perInstanceCache: true)]
|
||||
public async Task<Agent> LoadAgent(string id)
|
||||
public async Task<Agent> LoadAgent(string id, bool loadUtility = true)
|
||||
{
|
||||
if (string.IsNullOrEmpty(id) || id == Guid.Empty.ToString())
|
||||
{
|
||||
|
|
@ -67,7 +67,11 @@ public partial class AgentService
|
|||
hook.OnSamplesLoaded(agent.Samples);
|
||||
}
|
||||
|
||||
hook.OnAgentUtilityLoaded(agent);
|
||||
if (loadUtility)
|
||||
{
|
||||
hook.OnAgentUtilityLoaded(agent);
|
||||
}
|
||||
|
||||
hook.OnAgentLoaded(agent);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,13 +11,18 @@ public partial class AgentService
|
|||
var render = _services.GetRequiredService<ITemplateRender>();
|
||||
var conv = _services.GetRequiredService<IConversationService>();
|
||||
|
||||
// merge instructions
|
||||
var instructions = new List<string> { agent.Instruction };
|
||||
var secondaryInstructions = agent.SecondaryInstructions?.Where(x => !string.IsNullOrWhiteSpace(x)).ToList() ?? [];
|
||||
instructions.AddRange(secondaryInstructions);
|
||||
|
||||
// update states
|
||||
foreach (var t in conv.States.GetStates())
|
||||
{
|
||||
agent.TemplateDict[t.Key] = t.Value;
|
||||
}
|
||||
|
||||
var res = render.Render(agent.Instruction, agent.TemplateDict);
|
||||
var res = render.Render(string.Join("\r\n", instructions), agent.TemplateDict);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
|
||||
if (!string.IsNullOrEmpty(agent.Instruction))
|
||||
if (!string.IsNullOrEmpty(agent.Instruction) || !agent.SecondaryInstructions.IsNullOrEmpty())
|
||||
{
|
||||
instruction += agentService.RenderedInstruction(agent);
|
||||
}
|
||||
|
|
@ -197,7 +197,8 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
ReferenceHandler = ReferenceHandler.IgnoreCycles,
|
||||
};
|
||||
|
||||
foreach (var fn in agent.Functions)
|
||||
var functions = agent.Functions.Concat(agent.SecondaryFunctions ?? []);
|
||||
foreach (var fn in functions)
|
||||
{
|
||||
/*var inputschema = new InputSchema()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -230,7 +230,8 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
MaxOutputTokenCount = maxTokens
|
||||
};
|
||||
|
||||
foreach (var function in agent.Functions)
|
||||
var functions = agent.Functions.Concat(agent.SecondaryFunctions ?? []);
|
||||
foreach (var function in functions)
|
||||
{
|
||||
if (!agentService.RenderFunction(agent, function)) continue;
|
||||
|
||||
|
|
@ -242,7 +243,7 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
functionParameters: BinaryData.FromObjectAsJson(property)));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(agent.Instruction))
|
||||
if (!string.IsNullOrEmpty(agent.Instruction) || !agent.SecondaryInstructions.IsNullOrEmpty())
|
||||
{
|
||||
var instruction = agentService.RenderedInstruction(agent);
|
||||
messages.Add(new SystemChatMessage(instruction));
|
||||
|
|
|
|||
|
|
@ -24,17 +24,20 @@ public class ReadImageFn : IFunctionCallback
|
|||
|
||||
var wholeDialogs = conv.GetDialogHistory();
|
||||
var dialogs = AssembleFiles(conv.ConversationId, args?.ImageUrls, wholeDialogs);
|
||||
var agentId = !string.IsNullOrWhiteSpace(message.CurrentAgentId) ? message.CurrentAgentId : BuiltInAgentId.UtilityAssistant;
|
||||
var agent = await agentService.LoadAgent(agentId);
|
||||
var fileAgent = new Agent
|
||||
var agent = new Agent
|
||||
{
|
||||
Id = agent?.Id ?? Guid.Empty.ToString(),
|
||||
Name = agent?.Name ?? "Unkown",
|
||||
Id = BuiltInAgentId.UtilityAssistant,
|
||||
Name = "Utility Agent",
|
||||
Instruction = !string.IsNullOrWhiteSpace(args?.UserRequest) ? args.UserRequest : "Please describe the image(s).",
|
||||
TemplateDict = new Dictionary<string, object>()
|
||||
};
|
||||
|
||||
var response = await GetChatCompletion(fileAgent, dialogs);
|
||||
if (!string.IsNullOrEmpty(message.CurrentAgentId))
|
||||
{
|
||||
agent = await agentService.LoadAgent(message.CurrentAgentId, loadUtility: false);
|
||||
}
|
||||
|
||||
var response = await GetChatCompletion(agent, dialogs);
|
||||
message.Content = response;
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ public class GeminiChatCompletionProvider : IChatCompletion
|
|||
var funcDeclarations = new List<FunctionDeclaration>();
|
||||
|
||||
var systemPrompts = new List<string>();
|
||||
if (!string.IsNullOrEmpty(agent.Instruction))
|
||||
if (!string.IsNullOrEmpty(agent.Instruction) || !agent.SecondaryInstructions.IsNullOrEmpty())
|
||||
{
|
||||
var instruction = agentService.RenderedInstruction(agent);
|
||||
contents.Add(new Content(instruction)
|
||||
|
|
@ -119,7 +119,8 @@ public class GeminiChatCompletionProvider : IChatCompletion
|
|||
}
|
||||
|
||||
var funcPrompts = new List<string>();
|
||||
foreach (var function in agent.Functions)
|
||||
var functions = agent.Functions.Concat(agent.SecondaryFunctions ?? []);
|
||||
foreach (var function in functions)
|
||||
{
|
||||
if (!agentService.RenderFunction(agent, function)) continue;
|
||||
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ public class PalmChatCompletionProvider : IChatCompletion
|
|||
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
|
||||
if (!string.IsNullOrEmpty(agent.Instruction))
|
||||
if (!string.IsNullOrEmpty(agent.Instruction) || !agent.SecondaryInstructions.IsNullOrEmpty())
|
||||
{
|
||||
prompt += agentService.RenderedInstruction(agent);
|
||||
}
|
||||
|
|
@ -110,10 +110,11 @@ public class PalmChatCompletionProvider : IChatCompletion
|
|||
var messages = conversations.Select(c => new PalmChatMessage(c.Content, c.Role == AgentRole.User ? "user" : "AI"))
|
||||
.ToList();
|
||||
|
||||
if (agent.Functions != null && agent.Functions.Count > 0)
|
||||
var functions = agent.Functions.Concat(agent.SecondaryFunctions ?? []);
|
||||
if (!functions.IsNullOrEmpty())
|
||||
{
|
||||
prompt += "\r\n\r\n[Functions] defined in JSON Schema:\r\n";
|
||||
prompt += JsonSerializer.Serialize(agent.Functions, new JsonSerializerOptions
|
||||
prompt += JsonSerializer.Serialize(functions, new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
WriteIndented = true
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
using BotSharp.Abstraction.Utilities;
|
||||
|
||||
namespace BotSharp.Plugin.MetaGLM.Providers;
|
||||
|
||||
public class ChatCompletionProvider : IChatCompletion
|
||||
|
|
@ -86,7 +88,7 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
List<MessageItem> messages = new List<MessageItem>();
|
||||
List<FunctionTool> toolcalls = new List<FunctionTool>();
|
||||
|
||||
if (!string.IsNullOrEmpty(agent.Instruction))
|
||||
if (!string.IsNullOrEmpty(agent.Instruction) || !agent.SecondaryInstructions.IsNullOrEmpty())
|
||||
{
|
||||
var instruction = agentService.RenderedInstruction(agent);
|
||||
messages.Add(new MessageItem("system", instruction));
|
||||
|
|
@ -105,7 +107,8 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
new MessageItem("assistant", message.Content));
|
||||
}
|
||||
|
||||
foreach (var function in agent.Functions)
|
||||
var functions = agent.Functions.Concat(agent.SecondaryFunctions ?? []);
|
||||
foreach (var function in functions)
|
||||
{
|
||||
var functionTool = ConvertToFunctionTool(function);
|
||||
toolcalls.Add(functionTool);
|
||||
|
|
|
|||
|
|
@ -66,7 +66,8 @@ public sealed class MicrosoftExtensionsAIChatCompletionProvider : IChatCompletio
|
|||
|
||||
if (_services.GetService<IAgentService>() is { } agentService)
|
||||
{
|
||||
foreach (var function in agent.Functions)
|
||||
var functions = agent.Functions.Concat(agent.SecondaryFunctions ?? []);
|
||||
foreach (var function in functions)
|
||||
{
|
||||
if (agentService.RenderFunction(agent, function))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
using BotSharp.Abstraction.Files.Utilities;
|
||||
using BotSharp.Abstraction.Templating;
|
||||
using OpenAI.Chat;
|
||||
using static System.Net.Mime.MediaTypeNames;
|
||||
|
||||
namespace BotSharp.Plugin.OpenAI.Providers.Chat;
|
||||
|
||||
|
|
@ -208,7 +210,8 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
MaxOutputTokenCount = maxTokens
|
||||
};
|
||||
|
||||
foreach (var function in agent.Functions)
|
||||
var functions = agent.Functions.Concat(agent.SecondaryFunctions ?? []);
|
||||
foreach (var function in functions)
|
||||
{
|
||||
if (!agentService.RenderFunction(agent, function)) continue;
|
||||
|
||||
|
|
@ -220,10 +223,10 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
functionParameters: BinaryData.FromObjectAsJson(property)));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(agent.Instruction))
|
||||
if (!string.IsNullOrEmpty(agent.Instruction) || !agent.SecondaryInstructions.IsNullOrEmpty())
|
||||
{
|
||||
var instruction = agentService.RenderedInstruction(agent);
|
||||
messages.Add(new SystemChatMessage(instruction));
|
||||
var text = agentService.RenderedInstruction(agent);
|
||||
messages.Add(new SystemChatMessage(text));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(agent.Knowledges))
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var messages = new List<ChatMessage>();
|
||||
|
||||
if (!string.IsNullOrEmpty(agent.Instruction))
|
||||
if (!string.IsNullOrEmpty(agent.Instruction) || !agent.SecondaryInstructions.IsNullOrEmpty())
|
||||
{
|
||||
var instruction = agentService.RenderedInstruction(agent);
|
||||
messages.Add(ChatMessage.FromSystem(instruction));
|
||||
|
|
@ -193,7 +193,8 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
ChatMessage.FromAssistant(message.Content));
|
||||
}
|
||||
|
||||
foreach (var function in agent.Functions)
|
||||
var agentFuncs = agent.Functions.Concat(agent.SecondaryFunctions ?? []);
|
||||
foreach (var function in agentFuncs)
|
||||
{
|
||||
functions.Add(ConvertToFunctionDef(function));
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue