Skip to content

Commit 3e6394a

Browse files
authored
Merge pull request #805 from iceljc/features/refine-load-utility
Features/refine load utility
2 parents 4f08ca2 + ac72106 commit 3e6394a

File tree

14 files changed

+67
-35
lines changed

14 files changed

+67
-35
lines changed

src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public interface IAgentService
1818
/// </summary>
1919
/// <param name="id"></param>
2020
/// <returns></returns>
21-
Task<Agent> LoadAgent(string id);
21+
Task<Agent> LoadAgent(string id, bool loadUtility = true);
2222

2323
/// <summary>
2424
/// Inherit from an agent

src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,12 @@ public class Agent
118118
[JsonIgnore]
119119
public Dictionary<string, object> TemplateDict { get; set; } = new();
120120

121+
[JsonIgnore]
122+
public List<FunctionDef> SecondaryFunctions { get; set; } = [];
123+
124+
[JsonIgnore]
125+
public List<string> SecondaryInstructions { get; set; } = [];
126+
121127
public override string ToString()
122128
=> $"{Name} {Id}";
123129

src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ public class BasicAgentHook : AgentHookBase
44
{
55
public override string SelfId => string.Empty;
66

7+
private const string UTIL_PREFIX = "util-";
8+
79
public BasicAgentHook(IServiceProvider services, AgentSettings settings)
810
: base(services, settings)
911
{
@@ -17,22 +19,23 @@ public override void OnAgentUtilityLoaded(Agent agent)
1719
var isConvMode = conv.IsConversationMode();
1820
if (!isConvMode) return;
1921

20-
agent.Functions ??= [];
22+
agent.SecondaryFunctions ??= [];
23+
agent.SecondaryInstructions ??= [];
2124
agent.Utilities ??= [];
2225

2326
var (functions, templates) = GetUtilityContent(agent);
2427

2528
foreach (var fn in functions)
2629
{
27-
if (!agent.Functions.Any(x => x.Name.Equals(fn.Name, StringComparison.OrdinalIgnoreCase)))
30+
if (!agent.SecondaryFunctions.Any(x => x.Name.Equals(fn.Name, StringComparison.OrdinalIgnoreCase)))
2831
{
29-
agent.Functions.Add(fn);
32+
agent.SecondaryFunctions.Add(fn);
3033
}
3134
}
3235

3336
foreach (var prompt in templates)
3437
{
35-
agent.Instruction += $"\r\n\r\n{prompt}\r\n\r\n";
38+
agent.SecondaryInstructions.Add(prompt);
3639
}
3740
}
3841

@@ -67,14 +70,13 @@ public override void OnAgentUtilityLoaded(Agent agent)
6770
return ([], []);
6871
}
6972

70-
var prefix = "util-";
7173
utilities = utilities?.Where(x => !string.IsNullOrEmpty(x.Name) && !x.Disabled)?.ToList() ?? [];
7274
var functionNames = utilities.SelectMany(x => x.Functions)
73-
.Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(prefix))
75+
.Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(UTIL_PREFIX))
7476
.Select(x => x.Name)
7577
.Distinct().ToList();
7678
var templateNames = utilities.SelectMany(x => x.Templates)
77-
.Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(prefix))
79+
.Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(UTIL_PREFIX))
7880
.Select(x => x.Name)
7981
.Distinct().ToList();
8082

src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ public partial class AgentService
88
public static ConcurrentDictionary<string, Dictionary<string, string>> AgentParameterTypes = new();
99

1010
[MemoryCache(10 * 60, perInstanceCache: true)]
11-
public async Task<Agent> LoadAgent(string id)
11+
public async Task<Agent> LoadAgent(string id, bool loadUtility = true)
1212
{
1313
if (string.IsNullOrEmpty(id) || id == Guid.Empty.ToString())
1414
{
@@ -67,7 +67,11 @@ public async Task<Agent> LoadAgent(string id)
6767
hook.OnSamplesLoaded(agent.Samples);
6868
}
6969

70-
hook.OnAgentUtilityLoaded(agent);
70+
if (loadUtility)
71+
{
72+
hook.OnAgentUtilityLoaded(agent);
73+
}
74+
7175
hook.OnAgentLoaded(agent);
7276
}
7377

src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,18 @@ public string RenderedInstruction(Agent agent)
1111
var render = _services.GetRequiredService<ITemplateRender>();
1212
var conv = _services.GetRequiredService<IConversationService>();
1313

14+
// merge instructions
15+
var instructions = new List<string> { agent.Instruction };
16+
var secondaryInstructions = agent.SecondaryInstructions?.Where(x => !string.IsNullOrWhiteSpace(x)).ToList() ?? [];
17+
instructions.AddRange(secondaryInstructions);
18+
1419
// update states
1520
foreach (var t in conv.States.GetStates())
1621
{
1722
agent.TemplateDict[t.Key] = t.Value;
1823
}
1924

20-
var res = render.Render(agent.Instruction, agent.TemplateDict);
25+
var res = render.Render(string.Join("\r\n", instructions), agent.TemplateDict);
2126
return res;
2227
}
2328

src/Plugins/BotSharp.Plugin.AnthropicAI/Providers/ChatCompletionProvider.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ public Task<bool> GetChatCompletionsStreamingAsync(Agent agent, List<RoleDialogM
101101

102102
var agentService = _services.GetRequiredService<IAgentService>();
103103

104-
if (!string.IsNullOrEmpty(agent.Instruction))
104+
if (!string.IsNullOrEmpty(agent.Instruction) || !agent.SecondaryInstructions.IsNullOrEmpty())
105105
{
106106
instruction += agentService.RenderedInstruction(agent);
107107
}
@@ -197,7 +197,8 @@ public Task<bool> GetChatCompletionsStreamingAsync(Agent agent, List<RoleDialogM
197197
ReferenceHandler = ReferenceHandler.IgnoreCycles,
198198
};
199199

200-
foreach (var fn in agent.Functions)
200+
var functions = agent.Functions.Concat(agent.SecondaryFunctions ?? []);
201+
foreach (var fn in functions)
201202
{
202203
/*var inputschema = new InputSchema()
203204
{

src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/Chat/ChatCompletionProvider.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,8 @@ public async Task<bool> GetChatCompletionsStreamingAsync(Agent agent, List<RoleD
230230
MaxOutputTokenCount = maxTokens
231231
};
232232

233-
foreach (var function in agent.Functions)
233+
var functions = agent.Functions.Concat(agent.SecondaryFunctions ?? []);
234+
foreach (var function in functions)
234235
{
235236
if (!agentService.RenderFunction(agent, function)) continue;
236237

@@ -242,7 +243,7 @@ public async Task<bool> GetChatCompletionsStreamingAsync(Agent agent, List<RoleD
242243
functionParameters: BinaryData.FromObjectAsJson(property)));
243244
}
244245

245-
if (!string.IsNullOrEmpty(agent.Instruction))
246+
if (!string.IsNullOrEmpty(agent.Instruction) || !agent.SecondaryInstructions.IsNullOrEmpty())
246247
{
247248
var instruction = agentService.RenderedInstruction(agent);
248249
messages.Add(new SystemChatMessage(instruction));

src/Plugins/BotSharp.Plugin.FileHandler/Functions/ReadImageFn.cs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,20 @@ public async Task<bool> Execute(RoleDialogModel message)
2424

2525
var wholeDialogs = conv.GetDialogHistory();
2626
var dialogs = AssembleFiles(conv.ConversationId, args?.ImageUrls, wholeDialogs);
27-
var agentId = !string.IsNullOrWhiteSpace(message.CurrentAgentId) ? message.CurrentAgentId : BuiltInAgentId.UtilityAssistant;
28-
var agent = await agentService.LoadAgent(agentId);
29-
var fileAgent = new Agent
27+
var agent = new Agent
3028
{
31-
Id = agent?.Id ?? Guid.Empty.ToString(),
32-
Name = agent?.Name ?? "Unkown",
29+
Id = BuiltInAgentId.UtilityAssistant,
30+
Name = "Utility Agent",
3331
Instruction = !string.IsNullOrWhiteSpace(args?.UserRequest) ? args.UserRequest : "Please describe the image(s).",
3432
TemplateDict = new Dictionary<string, object>()
3533
};
3634

37-
var response = await GetChatCompletion(fileAgent, dialogs);
35+
if (!string.IsNullOrEmpty(message.CurrentAgentId))
36+
{
37+
agent = await agentService.LoadAgent(message.CurrentAgentId, loadUtility: false);
38+
}
39+
40+
var response = await GetChatCompletion(agent, dialogs);
3841
message.Content = response;
3942
return true;
4043
}

src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/GeminiChatCompletionProvider.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ public void SetModelName(string model)
107107
var funcDeclarations = new List<FunctionDeclaration>();
108108

109109
var systemPrompts = new List<string>();
110-
if (!string.IsNullOrEmpty(agent.Instruction))
110+
if (!string.IsNullOrEmpty(agent.Instruction) || !agent.SecondaryInstructions.IsNullOrEmpty())
111111
{
112112
var instruction = agentService.RenderedInstruction(agent);
113113
contents.Add(new Content(instruction)
@@ -119,7 +119,8 @@ public void SetModelName(string model)
119119
}
120120

121121
var funcPrompts = new List<string>();
122-
foreach (var function in agent.Functions)
122+
var functions = agent.Functions.Concat(agent.SecondaryFunctions ?? []);
123+
foreach (var function in functions)
123124
{
124125
if (!agentService.RenderFunction(agent, function)) continue;
125126

src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Chat/PalmChatCompletionProvider.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ public async Task<RoleDialogModel> GetChatCompletions(Agent agent, List<RoleDial
9999

100100
var agentService = _services.GetRequiredService<IAgentService>();
101101

102-
if (!string.IsNullOrEmpty(agent.Instruction))
102+
if (!string.IsNullOrEmpty(agent.Instruction) || !agent.SecondaryInstructions.IsNullOrEmpty())
103103
{
104104
prompt += agentService.RenderedInstruction(agent);
105105
}
@@ -110,10 +110,11 @@ public async Task<RoleDialogModel> GetChatCompletions(Agent agent, List<RoleDial
110110
var messages = conversations.Select(c => new PalmChatMessage(c.Content, c.Role == AgentRole.User ? "user" : "AI"))
111111
.ToList();
112112

113-
if (agent.Functions != null && agent.Functions.Count > 0)
113+
var functions = agent.Functions.Concat(agent.SecondaryFunctions ?? []);
114+
if (!functions.IsNullOrEmpty())
114115
{
115116
prompt += "\r\n\r\n[Functions] defined in JSON Schema:\r\n";
116-
prompt += JsonSerializer.Serialize(agent.Functions, new JsonSerializerOptions
117+
prompt += JsonSerializer.Serialize(functions, new JsonSerializerOptions
117118
{
118119
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
119120
WriteIndented = true

0 commit comments

Comments
 (0)