Skip to content

Commit 5bd15f7

Browse files
committed
Merge branch 'master' of https://github.com/SciSharp/BotSharp
2 parents fcc8ba6 + e8b654f commit 5bd15f7

16 files changed

Lines changed: 214 additions & 74 deletions

File tree

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
namespace BotSharp.Abstraction.Conversations.Models;
2+
3+
public class LlmCompletionLog
4+
{
5+
public string Id { get; set; } = string.Empty;
6+
public string ConversationId { get; set; } = string.Empty;
7+
public string MessageId { get; set; } = string.Empty;
8+
public string AgentId { get; set; } = string.Empty;
9+
public string Prompt { get; set; } = string.Empty;
10+
public string? Response { get; set; }
11+
public DateTime CreateDateTime { get; set; } = DateTime.UtcNow;
12+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace BotSharp.Abstraction.Repositories.Filters;
2+
3+
public class AgentFilter
4+
{
5+
public string? AgentName { get; set; }
6+
public bool? Disabled { get; set; }
7+
public bool? AllowRouting { get; set; }
8+
public bool? IsPublic { get; set; }
9+
public List<string>? AgentIds { get; set; }
10+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace BotSharp.Abstraction.Repositories.Filters;
2+
3+
public class ConversationFilter
4+
{
5+
public string? AgentId { get; set; }
6+
public string? Status { get; set; }
7+
public string? Channel { get; set; }
8+
public string? UserId { get; set; }
9+
}

src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using BotSharp.Abstraction.Repositories.Filters;
12
using BotSharp.Abstraction.Users.Models;
23

34
namespace BotSharp.Abstraction.Repositories;
@@ -16,8 +17,7 @@ public interface IBotSharpRepository
1617
#region Agent
1718
void UpdateAgent(Agent agent, AgentField field);
1819
Agent? GetAgent(string agentId);
19-
List<Agent> GetAgents(string? name = null, bool? disabled = null, bool? allowRouting = null,
20-
bool? isPublic = null, List<string>? agentIds = null);
20+
List<Agent> GetAgents(AgentFilter filter);
2121
List<Agent> GetAgentsByUser(string userId);
2222
void BulkInsertAgents(List<Agent> agents);
2323
void BulkInsertUserAgents(List<UserAgent> userAgents);
@@ -35,10 +35,14 @@ List<Agent> GetAgents(string? name = null, bool? disabled = null, bool? allowRou
3535
void UpdateConversationStates(string conversationId, List<StateKeyValue> states);
3636
void UpdateConversationStatus(string conversationId, string status);
3737
Conversation GetConversation(string conversationId);
38-
List<Conversation> GetConversations(string? agentId = null, string? status = null, string? channel = null, string? userId = null);
38+
List<Conversation> GetConversations(ConversationFilter filter);
3939
void UpdateConversationTitle(string conversationId, string title);
4040
List<Conversation> GetLastConversations();
4141
void AddExectionLogs(string conversationId, List<string> logs);
4242
List<string> GetExectionLogs(string conversationId);
4343
#endregion
44+
45+
#region LLM Completion Log
46+
void SaveLlmCompletionLog(LlmCompletionLog log);
47+
#endregion
4448
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using BotSharp.Abstraction.Agents.Models;
2+
using BotSharp.Abstraction.Repositories.Filters;
23

34
namespace BotSharp.Core.Agents.Services;
45

@@ -9,7 +10,8 @@ public partial class AgentService
910
#endif
1011
public async Task<List<Agent>> GetAgents(bool? allowRouting = null)
1112
{
12-
var agents = _db.GetAgents(allowRouting: allowRouting);
13+
var filter = new AgentFilter { AllowRouting = allowRouting };
14+
var agents = _db.GetAgents(filter);
1315
return await Task.FromResult(agents);
1416
}
1517

src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using BotSharp.Abstraction.Repositories;
2+
using BotSharp.Abstraction.Repositories.Filters;
23
using BotSharp.Abstraction.Users.Enums;
34

45
namespace BotSharp.Core.Conversations.Services;
@@ -57,8 +58,11 @@ public async Task<List<Conversation>> GetConversations()
5758
{
5859
var db = _services.GetRequiredService<IBotSharpRepository>();
5960
var user = db.GetUserById(_user.Id);
60-
var targetUserId = user.Role == UserRole.CSR ? null : user?.Id;
61-
var conversations = db.GetConversations(userId: targetUserId);
61+
var filter = new ConversationFilter
62+
{
63+
UserId = user.Role == UserRole.CSR ? string.Empty : user?.Id
64+
};
65+
var conversations = db.GetConversations(filter);
6266
return conversations.OrderByDescending(x => x.CreatedTime).ToList();
6367
}
6468

src/Infrastructure/BotSharp.Core/Planning/HFPlanner.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using BotSharp.Abstraction.Functions.Models;
33
using BotSharp.Abstraction.Planning;
44
using BotSharp.Abstraction.Repositories;
5+
using BotSharp.Abstraction.Repositories.Filters;
56
using BotSharp.Abstraction.Routing.Models;
67
using BotSharp.Abstraction.Routing.Settings;
78
using BotSharp.Abstraction.Templating;
@@ -72,7 +73,8 @@ public async Task<bool> AgentExecuting(FunctionCallFromLlm inst, RoleDialogModel
7273
if (!string.IsNullOrEmpty(inst.AgentName))
7374
{
7475
var db = _services.GetRequiredService<IBotSharpRepository>();
75-
var agent = db.GetAgents(inst.AgentName).FirstOrDefault();
76+
var filter = new AgentFilter { AgentName = inst.AgentName };
77+
var agent = db.GetAgents(filter).FirstOrDefault();
7678

7779
var context = _services.GetRequiredService<RoutingContext>();
7880
context.Push(agent.Id);

src/Infrastructure/BotSharp.Core/Repository/BotSharpDbContext.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using BotSharp.Abstraction.Agents.Models;
22
using BotSharp.Abstraction.Repositories;
3+
using BotSharp.Abstraction.Repositories.Filters;
34
using BotSharp.Abstraction.Users.Models;
45
using Microsoft.EntityFrameworkCore.Infrastructure;
56

@@ -72,8 +73,7 @@ public Agent GetAgent(string agentId)
7273
throw new NotImplementedException();
7374
}
7475

75-
public List<Agent> GetAgents(string? name = null, bool? disabled = null, bool? allowRouting = null,
76-
bool? isPublic = null, List<string>? agentIds = null)
76+
public List<Agent> GetAgents(AgentFilter filter)
7777
{
7878
throw new NotImplementedException();
7979
}
@@ -131,7 +131,7 @@ public Conversation GetConversation(string conversationId)
131131
throw new NotImplementedException();
132132
}
133133

134-
public List<Conversation> GetConversations(string? agentId = null, string? status = null, string? channel = null, string? userId = null)
134+
public List<Conversation> GetConversations(ConversationFilter filter)
135135
{
136136
throw new NotImplementedException();
137137
}
@@ -197,4 +197,11 @@ public void CreateUser(User user)
197197
throw new NotImplementedException();
198198
}
199199
#endregion
200+
201+
#region LLM Completion Log
202+
public void SaveLlmCompletionLog(LlmCompletionLog log)
203+
{
204+
throw new NotImplementedException();
205+
}
206+
#endregion
200207
}

src/Infrastructure/BotSharp.Core/Repository/FileRepository.cs

Lines changed: 77 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
using BotSharp.Abstraction.Agents.Models;
66
using MongoDB.Driver;
77
using BotSharp.Abstraction.Routing.Models;
8+
using BotSharp.Abstraction.Repositories.Filters;
9+
using BotSharp.Abstraction.Utilities;
10+
using BotSharp.Abstraction.Conversations.Models;
11+
812
namespace BotSharp.Core.Repository;
913

1014
public class FileRepository : IBotSharpRepository
@@ -500,33 +504,32 @@ public List<string> GetAgentResponses(string agentId, string prefix, string inte
500504
return null;
501505
}
502506

503-
public List<Agent> GetAgents(string? name = null, bool? disabled = null, bool? allowRouting = null,
504-
bool? isPublic = null, List<string>? agentIds = null)
507+
public List<Agent> GetAgents(AgentFilter filter)
505508
{
506509
var query = Agents;
507-
if (!string.IsNullOrEmpty(name))
510+
if (!string.IsNullOrEmpty(filter.AgentName))
508511
{
509-
query = query.Where(x => x.Name.ToLower() == name.ToLower());
512+
query = query.Where(x => x.Name.ToLower() == filter.AgentName.ToLower());
510513
}
511514

512-
if (disabled.HasValue)
515+
if (filter.Disabled.HasValue)
513516
{
514-
query = query.Where(x => x.Disabled == disabled);
517+
query = query.Where(x => x.Disabled == filter.Disabled);
515518
}
516519

517-
if (allowRouting.HasValue)
520+
if (filter.AllowRouting.HasValue)
518521
{
519-
query = query.Where(x => x.AllowRouting == allowRouting);
522+
query = query.Where(x => x.AllowRouting == filter.AllowRouting);
520523
}
521524

522-
if (isPublic.HasValue)
525+
if (filter.IsPublic.HasValue)
523526
{
524-
query = query.Where(x => x.IsPublic == isPublic);
527+
query = query.Where(x => x.IsPublic == filter.IsPublic);
525528
}
526529

527-
if (agentIds != null)
530+
if (filter.AgentIds != null)
528531
{
529-
query = query.Where(x => agentIds.Contains(x.Id));
532+
query = query.Where(x => filter.AgentIds.Contains(x.Id));
530533
}
531534

532535
return query.ToList();
@@ -539,7 +542,12 @@ join u in Users on ua.UserId equals u.Id
539542
where ua.UserId == userId || u.ExternalId == userId
540543
select ua.AgentId).ToList();
541544

542-
var agents = GetAgents(isPublic: true, agentIds: agentIds);
545+
var filter = new AgentFilter
546+
{
547+
IsPublic = true,
548+
AgentIds = agentIds
549+
};
550+
var agents = GetAgents(filter);
543551
return agents;
544552
}
545553

@@ -552,7 +560,7 @@ public string GetAgentTemplate(string agentId, string templateName)
552560
foreach (var file in Directory.GetFiles(dir))
553561
{
554562
var fileName = file.Split(Path.DirectorySeparatorChar).Last();
555-
var splits = fileName.ToLower().Split('.');
563+
var splits = ParseFileNameByPath(fileName.ToLower());
556564
var name = splits[0];
557565
var extension = splits[1];
558566
if (name.IsEqualTo(templateName) && extension.IsEqualTo(_agentSettings.TemplateFormat))
@@ -610,10 +618,10 @@ public bool DeleteConversation(string conversationId)
610618
{
611619
if (string.IsNullOrEmpty(conversationId)) return false;
612620

613-
var dir = Path.Combine(_dbSettings.FileRepository, _conversationSettings.DataDir, conversationId);
614-
if (!Directory.Exists(dir)) return false;
621+
var convDir = FindConversationDirectory(conversationId);
622+
if (string.IsNullOrEmpty(convDir)) return false;
615623

616-
Directory.Delete(dir, true);
624+
Directory.Delete(convDir, true);
617625
return true;
618626
}
619627

@@ -734,7 +742,7 @@ public Conversation GetConversation(string conversationId)
734742
return record;
735743
}
736744

737-
public List<Conversation> GetConversations(string? agentId = null, string? status = null, string? channel = null, string? userId = null)
745+
public List<Conversation> GetConversations(ConversationFilter filter)
738746
{
739747
var records = new List<Conversation>();
740748
var dir = Path.Combine(_dbSettings.FileRepository, _conversationSettings.DataDir);
@@ -749,10 +757,10 @@ public List<Conversation> GetConversations(string? agentId = null, string? statu
749757
if (record == null) continue;
750758

751759
var matched = true;
752-
if (!string.IsNullOrEmpty(agentId)) matched = matched && record.AgentId == agentId;
753-
if (!string.IsNullOrEmpty(status)) matched = matched && record.Status == status;
754-
if (!string.IsNullOrEmpty(channel)) matched = matched && record.Channel == channel;
755-
if (!string.IsNullOrEmpty(userId)) matched = matched && record.UserId == userId;
760+
if (!string.IsNullOrEmpty(filter.AgentId)) matched = matched && record.AgentId == filter.AgentId;
761+
if (!string.IsNullOrEmpty(filter.Status)) matched = matched && record.Status == filter.Status;
762+
if (!string.IsNullOrEmpty(filter.Channel)) matched = matched && record.Channel == filter.Channel;
763+
if (!string.IsNullOrEmpty(filter.UserId)) matched = matched && record.UserId == filter.UserId;
756764

757765
if (!matched) continue;
758766
records.Add(record);
@@ -835,6 +843,25 @@ public void CreateUser(User user)
835843
}
836844
#endregion
837845

846+
#region LLM Completion Log
847+
public void SaveLlmCompletionLog(LlmCompletionLog log)
848+
{
849+
var convDir = FindConversationDirectory(log.ConversationId);
850+
if (!Directory.Exists(convDir)) return;
851+
852+
var logDir = Path.Combine(convDir, "llm_prompt_log");
853+
if (!Directory.Exists(logDir))
854+
{
855+
Directory.CreateDirectory(logDir);
856+
}
857+
858+
var index = GetLlmCompletionLogIndex(logDir, log.MessageId);
859+
var file = Path.Combine(logDir, $"{log.MessageId}.{index}.log");
860+
File.WriteAllText(file, JsonSerializer.Serialize(log, _options));
861+
}
862+
#endregion
863+
864+
838865
#region Private methods
839866
private string GetAgentDataDir(string agentId)
840867
{
@@ -927,22 +954,10 @@ private List<AgentResponse> FetchResponses(string fileDir)
927954

928955
private string? FindConversationDirectory(string conversationId)
929956
{
930-
var dir = Path.Combine(_dbSettings.FileRepository, _conversationSettings.DataDir);
931-
932-
foreach (var d in Directory.GetDirectories(dir))
933-
{
934-
var path = Path.Combine(d, "conversation.json");
935-
if (!File.Exists(path)) continue;
936-
937-
var json = File.ReadAllText(path);
938-
var conv = JsonSerializer.Deserialize<Conversation>(json, _options);
939-
if (conv != null && conv.Id == conversationId)
940-
{
941-
return d;
942-
}
943-
}
957+
var dir = Path.Combine(_dbSettings.FileRepository, _conversationSettings.DataDir, conversationId);
958+
if (!Directory.Exists(dir)) return null;
944959

945-
return null;
960+
return dir;
946961
}
947962

948963
private List<DialogElement> CollectDialogElements(string dialogDir)
@@ -993,5 +1008,30 @@ private List<StateKeyValue> CollectConversationStates(string stateDir)
9931008
}
9941009
return states;
9951010
}
1011+
1012+
private int GetLlmCompletionLogIndex(string logDir, string id)
1013+
{
1014+
var files = Directory.GetFiles(logDir);
1015+
if (files.IsNullOrEmpty())
1016+
return 0;
1017+
1018+
var logIndexes = files.Where(file =>
1019+
{
1020+
var fileName = ParseFileNameByPath(file);
1021+
return fileName[0].IsEqualTo(id);
1022+
}).Select(file =>
1023+
{
1024+
var fileName = ParseFileNameByPath(file);
1025+
return int.Parse(fileName[1]);
1026+
}).ToList();
1027+
1028+
return logIndexes.IsNullOrEmpty() ? 0 : logIndexes.Max() + 1;
1029+
}
1030+
1031+
private string[] ParseFileNameByPath(string path, string separator = ".")
1032+
{
1033+
var name = path.Split(Path.DirectorySeparatorChar).Last();
1034+
return name.Split(separator);
1035+
}
9961036
#endregion
9971037
}

src/Infrastructure/BotSharp.Core/Routing/Functions/RouteToAgentFn.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using BotSharp.Abstraction.Functions;
22
using BotSharp.Abstraction.Repositories;
3+
using BotSharp.Abstraction.Repositories.Filters;
34
using BotSharp.Abstraction.Routing;
45
using BotSharp.Abstraction.Routing.Models;
56
using System.Drawing;
@@ -29,7 +30,8 @@ public async Task<bool> Execute(RoleDialogModel message)
2930
if (!string.IsNullOrEmpty(args.OriginalAgent) && args.OriginalAgent.Length < 32)
3031
{
3132
var db = _services.GetRequiredService<IBotSharpRepository>();
32-
var originalAgent = db.GetAgents(name: args.OriginalAgent).FirstOrDefault();
33+
var filter = new AgentFilter { AgentName = args.OriginalAgent };
34+
var originalAgent = db.GetAgents(filter).FirstOrDefault();
3335
if (originalAgent != null)
3436
{
3537
_context.Push(originalAgent.Id);
@@ -48,7 +50,8 @@ public async Task<bool> Execute(RoleDialogModel message)
4850
else
4951
{
5052
var db = _services.GetRequiredService<IBotSharpRepository>();
51-
var targetAgent = db.GetAgents(args.AgentName).FirstOrDefault();
53+
var filter = new AgentFilter { AgentName = args.AgentName };
54+
var targetAgent = db.GetAgents(filter).FirstOrDefault();
5255
if (targetAgent == null)
5356
{
5457
message.Data = JsonSerializer.Deserialize<JsonElement>(message.FunctionArgs);

0 commit comments

Comments
 (0)