Merge pull request #403 from iceljc/features/add-visible-property
add visible property
This commit is contained in:
commit
ed7cabde4f
|
|
@ -26,6 +26,8 @@ public interface IAgentService
|
|||
|
||||
bool RenderFunction(Agent agent, FunctionDef def);
|
||||
|
||||
FunctionParametersDef? RenderFunctionProperty(Agent agent, FunctionDef def);
|
||||
|
||||
/// <summary>
|
||||
/// Get agent detail without trigger any hook.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace BotSharp.Abstraction.Conversations;
|
|||
public interface IConversationStateService
|
||||
{
|
||||
string GetConversationId();
|
||||
Dictionary<string, string> Load(string conversationId);
|
||||
Dictionary<string, string> Load(string conversationId, bool isReadOnly = false);
|
||||
string GetState(string name, string defaultValue = "");
|
||||
bool ContainsState(string name);
|
||||
Dictionary<string, string> GetStates();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using BotSharp.Abstraction.Loggers;
|
||||
using BotSharp.Abstraction.Templating;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BotSharp.Core.Agents.Services;
|
||||
|
||||
|
|
@ -32,6 +33,64 @@ public partial class AgentService
|
|||
return true;
|
||||
}
|
||||
|
||||
public FunctionParametersDef? RenderFunctionProperty(Agent agent, FunctionDef def)
|
||||
{
|
||||
var parameterDef = def?.Parameters;
|
||||
var propertyDef = parameterDef?.Properties;
|
||||
if (propertyDef == null) return null;
|
||||
|
||||
var visibleExpress = "visibility_expression";
|
||||
var root = propertyDef.RootElement;
|
||||
var iterator = root.EnumerateObject();
|
||||
var visibleProps = new List<string>();
|
||||
while (iterator.MoveNext())
|
||||
{
|
||||
var prop = iterator.Current;
|
||||
var name = prop.Name;
|
||||
var node = prop.Value;
|
||||
var matched = true;
|
||||
if (node.TryGetProperty(visibleExpress, out var element))
|
||||
{
|
||||
var expression = element.GetString();
|
||||
var render = _services.GetRequiredService<ITemplateRender>();
|
||||
var result = render.Render(expression, new Dictionary<string, object>
|
||||
{
|
||||
{ "states", agent.TemplateDict }
|
||||
});
|
||||
matched = result == "visible";
|
||||
}
|
||||
|
||||
if (matched)
|
||||
{
|
||||
visibleProps.Add(name);
|
||||
}
|
||||
}
|
||||
|
||||
var rootObject = JObject.Parse(root.GetRawText());
|
||||
var clonedRoot = rootObject.DeepClone() as JObject;
|
||||
var required = parameterDef?.Required ?? new List<string>();
|
||||
foreach (var property in rootObject.Properties())
|
||||
{
|
||||
if (visibleProps.Contains(property.Name))
|
||||
{
|
||||
var value = clonedRoot.GetValue(property.Name) as JObject;
|
||||
if (value != null && value.ContainsKey(visibleExpress))
|
||||
{
|
||||
value.Remove(visibleExpress);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
clonedRoot.Remove(property.Name);
|
||||
required.Remove(property.Name);
|
||||
}
|
||||
}
|
||||
|
||||
parameterDef.Properties = JsonSerializer.Deserialize<JsonDocument>(clonedRoot.ToString());
|
||||
parameterDef.Required = required;
|
||||
return parameterDef; ;
|
||||
}
|
||||
|
||||
public string RenderedTemplate(Agent agent, string templateName)
|
||||
{
|
||||
// render liquid template
|
||||
|
|
|
|||
|
|
@ -117,15 +117,15 @@ public class ConversationStateService : IConversationStateService, IDisposable
|
|||
return this;
|
||||
}
|
||||
|
||||
public Dictionary<string, string> Load(string conversationId)
|
||||
public Dictionary<string, string> Load(string conversationId, bool isReadOnly = false)
|
||||
{
|
||||
_conversationId = conversationId;
|
||||
_conversationId = !isReadOnly ? conversationId : null;
|
||||
|
||||
var routingCtx = _services.GetRequiredService<IRoutingContext>();
|
||||
var curMsgId = routingCtx.MessageId;
|
||||
|
||||
_historyStates = _db.GetConversationStates(_conversationId);
|
||||
var dialogs = _db.GetConversationDialogs(_conversationId);
|
||||
_historyStates = _db.GetConversationStates(conversationId);
|
||||
var dialogs = _db.GetConversationDialogs(conversationId);
|
||||
var userDialogs = dialogs.Where(x => x.MetaData?.Role == AgentRole.User || x.MetaData?.Role == UserRole.Client)
|
||||
.OrderBy(x => x.MetaData?.CreateTime)
|
||||
.ToList();
|
||||
|
|
@ -177,7 +177,7 @@ public class ConversationStateService : IConversationStateService, IDisposable
|
|||
_logger.LogInformation($"[STATE] {key} : {data}");
|
||||
}
|
||||
|
||||
_logger.LogInformation($"Loaded conversation states: {_conversationId}");
|
||||
_logger.LogInformation($"Loaded conversation states: {conversationId}");
|
||||
var hooks = _services.GetServices<IConversationHook>();
|
||||
foreach (var hook in hooks)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ public class ConversationController : ControllerBase
|
|||
var result = ConversationViewModel.FromSession(conversations.Items.First());
|
||||
|
||||
var state = _services.GetRequiredService<IConversationStateService>();
|
||||
result.States = state.Load(conversationId);
|
||||
result.States = state.Load(conversationId, isReadOnly: true);
|
||||
|
||||
var user = await userService.GetUser(result.User.Id);
|
||||
result.User = UserViewModel.FromUser(user);
|
||||
|
|
|
|||
|
|
@ -221,11 +221,12 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
{
|
||||
if (agentService.RenderFunction(agent, function))
|
||||
{
|
||||
var property = agentService.RenderFunctionProperty(agent, function);
|
||||
chatCompletionsOptions.Functions.Add(new FunctionDefinition
|
||||
{
|
||||
Name = function.Name,
|
||||
Description = function.Description,
|
||||
Parameters = BinaryData.FromObjectAsJson(function.Parameters)
|
||||
Parameters = BinaryData.FromObjectAsJson(property)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -191,14 +191,11 @@ public partial class MongoRepository
|
|||
{
|
||||
if (string.IsNullOrEmpty(conversationId) || states == null) return;
|
||||
|
||||
var filterConv = Builders<ConversationDocument>.Filter.Eq(x => x.Id, conversationId);
|
||||
var filterStates = Builders<ConversationStateDocument>.Filter.Eq(x => x.ConversationId, conversationId);
|
||||
var saveStates = states.Select(x => StateMongoElement.ToMongoElement(x)).ToList();
|
||||
var updateStates = Builders<ConversationStateDocument>.Update.Set(x => x.States, saveStates);
|
||||
var updateConv = Builders<ConversationDocument>.Update.Set(x => x.UpdatedTime, DateTime.UtcNow);
|
||||
|
||||
_dc.ConversationStates.UpdateOne(filterStates, updateStates);
|
||||
_dc.Conversations.UpdateOne(filterConv, updateConv);
|
||||
}
|
||||
|
||||
public void UpdateConversationStatus(string conversationId, string status)
|
||||
|
|
@ -391,7 +388,7 @@ public partial class MongoRepository
|
|||
{
|
||||
var skip = (page - 1) * batchSize;
|
||||
var candidates = _dc.Conversations.AsQueryable()
|
||||
.Where(x => (x.DialogCount <= messageLimit) && x.UpdatedTime <= utcNow.AddHours(-bufferHours))
|
||||
.Where(x => x.DialogCount <= messageLimit && x.UpdatedTime <= utcNow.AddHours(-bufferHours))
|
||||
.Skip(skip)
|
||||
.Take(batchSize)
|
||||
.Select(x => x.Id)
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
return (prompt, messages.ToArray(), functions.ToArray());
|
||||
}
|
||||
|
||||
private string GetPrompt(List<ChatMessage> messages,List<FunctionDef> functions)
|
||||
private string GetPrompt(List<ChatMessage> messages, List<FunctionDef> functions)
|
||||
{
|
||||
var prompt = string.Empty;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue