Merge branch 'SciSharp:master' into master

This commit is contained in:
Haiping 2024-12-14 03:27:00 +00:00 committed by GitHub
commit 88dcf07907
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 113 additions and 15 deletions

View file

@ -17,7 +17,8 @@ public enum AgentField
Response,
Sample,
LlmConfig,
Utility
Utility,
MaxMessageCount
}
public enum AgentTaskField

View file

@ -104,6 +104,12 @@ public class Agent
/// </summary>
public string? InheritAgentId { get; set; }
/// <summary>
/// Maximum message count when load conversation
/// </summary>
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public int? MaxMessageCount { get; set; }
public List<RoutingRule> RoutingRules { get; set; } = new();
/// <summary>
@ -133,6 +139,8 @@ public class Agent
Knowledges = agent.Knowledges,
IsPublic = agent.IsPublic,
Disabled = agent.Disabled,
MergeUtility = agent.MergeUtility,
MaxMessageCount = agent.MaxMessageCount,
Profiles = agent.Profiles,
RoutingRules = agent.RoutingRules,
LlmConfig = agent.LlmConfig,

View file

@ -53,7 +53,7 @@ public interface IBotSharpRepository : IHaveServiceProvider
#region Agent
void UpdateAgent(Agent agent, AgentField field);
Agent? GetAgent(string agentId);
Agent? GetAgent(string agentId, bool basicsOnly = false);
List<Agent> GetAgents(AgentFilter filter);
List<UserAgent> GetUserAgents(string userId);
void BulkInsertAgents(List<Agent> agents);

View file

@ -47,7 +47,7 @@ public class BasicAgentHook : AgentHookBase
var entryAgentId = routing.EntryAgentId;
if (!string.IsNullOrEmpty(entryAgentId))
{
var entryAgent = db.GetAgent(entryAgentId);
var entryAgent = db.GetAgent(entryAgentId, basicsOnly: true);
var (fns, tps) = GetUniqueContent(entryAgent?.Utilities);
functionNames = functionNames.Concat(fns).Distinct().ToList();
templateNames = templateNames.Concat(tps).Distinct().ToList();

View file

@ -28,6 +28,7 @@ public partial class AgentService
record.IsPublic = agent.IsPublic;
record.Disabled = agent.Disabled;
record.MergeUtility = agent.MergeUtility;
record.MaxMessageCount = agent.MaxMessageCount;
record.Type = agent.Type;
record.Profiles = agent.Profiles ?? [];
record.RoutingRules = agent.RoutingRules ?? [];

View file

@ -153,7 +153,10 @@ public partial class ConversationService : IConversationService
}
}
return dialogs.TakeLast(lastCount).ToList();
var agentMsgCount = GetAgentMessageCount();
var count = agentMsgCount.HasValue && agentMsgCount.Value > 0 ? agentMsgCount.Value : lastCount;
return dialogs.TakeLast(count).ToList();
}
public void SetConversationId(string conversationId, List<MessageState> states, bool isReadOnly = false)
@ -192,4 +195,16 @@ public partial class ConversationService : IConversationService
{
return !string.IsNullOrWhiteSpace(_conversationId);
}
private int? GetAgentMessageCount()
{
var db = _services.GetRequiredService<IBotSharpRepository>();
var routingCtx = _services.GetRequiredService<IRoutingContext>();
if (string.IsNullOrEmpty(routingCtx.EntryAgentId)) return null;
var agent = db.GetAgent(routingCtx.EntryAgentId, basicsOnly: true);
return agent?.MaxMessageCount;
}
}

View file

@ -16,7 +16,7 @@ public class BotSharpDbContext : Database, IBotSharpRepository
#endregion
#region Agent
public Agent GetAgent(string agentId)
public Agent GetAgent(string agentId, bool basicsOnly = false)
=> throw new NotImplementedException();
public List<Agent> GetAgents(AgentFilter filter)

View file

@ -57,6 +57,9 @@ namespace BotSharp.Core.Repository
case AgentField.Utility:
UpdateAgentUtilities(agent.Id, agent.MergeUtility, agent.Utilities);
break;
case AgentField.MaxMessageCount:
UpdateAgentMaxMessageCount(agent.Id, agent.MaxMessageCount);
break;
case AgentField.All:
UpdateAgentAllFields(agent);
break;
@ -283,6 +286,17 @@ namespace BotSharp.Core.Repository
File.WriteAllText(agentFile, json);
}
private void UpdateAgentMaxMessageCount(string agentId, int? maxMessageCount)
{
var (agent, agentFile) = GetAgentFromFile(agentId);
if (agent == null) return;
agent.MaxMessageCount = maxMessageCount;
agent.UpdatedDateTime = DateTime.UtcNow;
var json = JsonSerializer.Serialize(agent, _options);
File.WriteAllText(agentFile, json);
}
private void UpdateAgentAllFields(Agent inputAgent)
{
var (agent, agentFile) = GetAgentFromFile(inputAgent.Id);
@ -298,6 +312,7 @@ namespace BotSharp.Core.Repository
agent.Utilities = inputAgent.Utilities;
agent.RoutingRules = inputAgent.RoutingRules;
agent.LlmConfig = inputAgent.LlmConfig;
agent.MaxMessageCount = inputAgent.MaxMessageCount;
agent.UpdatedDateTime = DateTime.UtcNow;
var json = JsonSerializer.Serialize(agent, _options);
File.WriteAllText(agentFile, json);
@ -329,7 +344,7 @@ namespace BotSharp.Core.Repository
return responses;
}
public Agent? GetAgent(string agentId)
public Agent? GetAgent(string agentId, bool basicsOnly = false)
{
var agentDir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir);
var dir = Directory.GetDirectories(agentDir).FirstOrDefault(x => x.Split(Path.DirectorySeparatorChar).Last() == agentId);
@ -342,6 +357,8 @@ namespace BotSharp.Core.Repository
var record = JsonSerializer.Deserialize<Agent>(json, _options);
if (record == null) return null;
if (basicsOnly) return record;
var (defaultInstruction, channelInstructions) = FetchInstructions(dir);
var functions = FetchFunctions(dir);
var samples = FetchSamples(dir);

View file

@ -51,6 +51,8 @@ public class AgentCreationModel
public bool MergeUtility { get; set; }
public int? MaxMessageCount { get; set; }
public List<AgentUtility> Utilities { get; set; } = new();
public List<RoutingRuleUpdateModel> RoutingRules { get; set; } = new();
public AgentLlmConfig? LlmConfig { get; set; }
@ -72,6 +74,7 @@ public class AgentCreationModel
Type = Type,
Disabled = Disabled,
MergeUtility = MergeUtility,
MaxMessageCount = MaxMessageCount,
Profiles = Profiles,
RoutingRules = RoutingRules?.Select(x => RoutingRuleUpdateModel.ToDomainElement(x))?.ToList() ?? new List<RoutingRule>(),
LlmConfig = LlmConfig

View file

@ -57,6 +57,9 @@ public class AgentUpdateModel
public bool Disabled { get; set; }
[JsonPropertyName("max_message_count")]
public int? MaxMessageCount { get; set; }
/// <summary>
/// Profile by channel
/// </summary>
@ -77,6 +80,7 @@ public class AgentUpdateModel
IsPublic = IsPublic,
Disabled = Disabled,
MergeUtility = MergeUtility,
MaxMessageCount = MaxMessageCount,
Type = Type,
Profiles = Profiles ?? new List<string>(),
RoutingRules = RoutingRules?.Select(x => RoutingRuleUpdateModel.ToDomainElement(x))?.ToList() ?? new List<RoutingRule>(),

View file

@ -46,6 +46,10 @@ public class AgentViewModel
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public AgentLlmConfig? LlmConfig { get; set; }
[JsonPropertyName("max_message_count")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public int? MaxMessageCount { get; set; }
public PluginDef Plugin { get; set; }
public IEnumerable<string>? Actions { get; set; }
@ -75,6 +79,7 @@ public class AgentViewModel
Disabled = agent.Disabled,
MergeUtility = agent.MergeUtility,
IconUrl = agent.IconUrl,
MaxMessageCount = agent.MaxMessageCount,
Profiles = agent.Profiles ?? new List<string>(),
RoutingRules = agent.RoutingRules,
LlmConfig = agent.LlmConfig,

View file

@ -23,8 +23,9 @@ public class ReadImageFn : IFunctionCallback
var agentService = _services.GetRequiredService<IAgentService>();
var wholeDialogs = conv.GetDialogHistory();
var dialogs = AssembleFiles(conv.ConversationId, wholeDialogs);
var agent = await agentService.LoadAgent(BuiltInAgentId.UtilityAssistant);
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
{
Id = agent?.Id ?? Guid.Empty.ToString(),
@ -38,7 +39,7 @@ public class ReadImageFn : IFunctionCallback
return true;
}
private List<RoleDialogModel> AssembleFiles(string conversationId, List<RoleDialogModel> dialogs)
private List<RoleDialogModel> AssembleFiles(string conversationId, IEnumerable<string>? imageUrls, List<RoleDialogModel> dialogs)
{
if (dialogs.IsNullOrEmpty())
{
@ -66,6 +67,18 @@ public class ReadImageFn : IFunctionCallback
}).ToList();
}
if (!imageUrls.IsNullOrEmpty())
{
var lastDialog = dialogs.Last();
var files = lastDialog.Files ?? [];
var addnFiles = imageUrls.Select(x => x?.Trim())
.Where(x => !string.IsNullOrWhiteSpace(x))
.Select(x => new BotSharpFile { FileUrl = x }).ToList();
files.AddRange(addnFiles);
lastDialog.Files = files;
}
return dialogs;
}

View file

@ -11,4 +11,12 @@ public class LlmContextIn
[JsonPropertyName("image_description")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? ImageDescription { get; set; }
//[JsonPropertyName("image_url")]
//[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
//public string? ImageUrl { get; set; }
[JsonPropertyName("image_urls")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public IEnumerable<string>? ImageUrls { get; set; }
}

View file

@ -7,6 +7,14 @@
"user_request": {
"type": "string",
"description": "The request posted by user, which is related to analyzing requested images. User can request for multiple images to process at one time."
},
"image_urls": {
"type": "array",
"description": "The image, photo or picture urls that user requests for analysis. They typically start with 'http' or 'https'. If user doesn't include any url, then leave this array empty. Please remove any duplicated urls",
"items": {
"type": "string",
"description": "The image, photo or picture url that user requests for analysis. It typically starts with http or https."
}
}
},
"required": [ "user_request" ]

View file

@ -11,6 +11,7 @@ public class AgentDocument : MongoBase
public bool IsPublic { get; set; }
public bool Disabled { get; set; }
public bool MergeUtility { get; set; }
public int? MaxMessageCount { get; set; }
public List<ChannelInstructionMongoElement> ChannelInstructions { get; set; }
public List<AgentTemplateMongoElement> Templates { get; set; }
public List<FunctionDefMongoElement> Functions { get; set; }

View file

@ -9,7 +9,7 @@ public partial class MongoRepository
{
public void UpdateAgent(Agent agent, AgentField field)
{
if (agent == null || string.IsNullOrEmpty(agent.Id)) return;
if (agent == null || string.IsNullOrWhiteSpace(agent.Id)) return;
switch (field)
{
@ -58,6 +58,9 @@ public partial class MongoRepository
case AgentField.Utility:
UpdateAgentUtilities(agent.Id, agent.MergeUtility, agent.Utilities);
break;
case AgentField.MaxMessageCount:
UpdateAgentMaxMessageCount(agent.Id, agent.MaxMessageCount);
break;
case AgentField.All:
UpdateAgentAllFields(agent);
break;
@ -158,10 +161,8 @@ public partial class MongoRepository
private void UpdateAgentInstructions(string agentId, string instruction, List<ChannelInstruction>? channelInstructions)
{
if (string.IsNullOrWhiteSpace(agentId)) return;
var instructionElements = channelInstructions?.Select(x => ChannelInstructionMongoElement.ToMongoElement(x))?
.ToList() ?? new List<ChannelInstructionMongoElement>();
.ToList() ?? [];
var filter = Builders<AgentDocument>.Filter.Eq(x => x.Id, agentId);
var update = Builders<AgentDocument>.Update
@ -200,7 +201,7 @@ public partial class MongoRepository
private void UpdateAgentResponses(string agentId, List<AgentResponse> responses)
{
if (responses == null) return;
if (responses == null || string.IsNullOrWhiteSpace(agentId)) return;
var responsesToUpdate = responses.Select(r => AgentResponseMongoElement.ToMongoElement(r)).ToList();
var filter = Builders<AgentDocument>.Filter.Eq(x => x.Id, agentId);
@ -249,6 +250,16 @@ public partial class MongoRepository
_dc.Agents.UpdateOne(filter, update);
}
private void UpdateAgentMaxMessageCount(string agentId, int? maxMessageCount)
{
var filter = Builders<AgentDocument>.Filter.Eq(x => x.Id, agentId);
var update = Builders<AgentDocument>.Update
.Set(x => x.MaxMessageCount, maxMessageCount)
.Set(x => x.UpdatedTime, DateTime.UtcNow);
_dc.Agents.UpdateOne(filter, update);
}
private void UpdateAgentAllFields(Agent agent)
{
var filter = Builders<AgentDocument>.Filter.Eq(x => x.Id, agent.Id);
@ -258,6 +269,7 @@ public partial class MongoRepository
.Set(x => x.Disabled, agent.Disabled)
.Set(x => x.MergeUtility, agent.MergeUtility)
.Set(x => x.Type, agent.Type)
.Set(x => x.MaxMessageCount, agent.MaxMessageCount)
.Set(x => x.Profiles, agent.Profiles)
.Set(x => x.RoutingRules, agent.RoutingRules.Select(r => RoutingRuleMongoElement.ToMongoElement(r)).ToList())
.Set(x => x.Instruction, agent.Instruction)
@ -277,7 +289,7 @@ public partial class MongoRepository
#endregion
public Agent? GetAgent(string agentId)
public Agent? GetAgent(string agentId, bool basicsOnly = false)
{
var agent = _dc.Agents.AsQueryable().FirstOrDefault(x => x.Id == agentId);
if (agent == null) return null;
@ -420,6 +432,7 @@ public partial class MongoRepository
InheritAgentId = x.InheritAgentId,
Disabled = x.Disabled,
MergeUtility = x.MergeUtility,
MaxMessageCount = x.MaxMessageCount,
Profiles = x.Profiles,
RoutingRules = x.RoutingRules?.Select(r => RoutingRuleMongoElement.ToMongoElement(r))?.ToList() ?? [],
LlmConfig = AgentLlmConfigMongoElement.ToMongoElement(x.LlmConfig),
@ -513,6 +526,7 @@ public partial class MongoRepository
Type = agentDoc.Type,
InheritAgentId = agentDoc.InheritAgentId,
Profiles = agentDoc.Profiles,
MaxMessageCount = agentDoc.MaxMessageCount
};
}
}