Skip to content

Commit 5f80b5e

Browse files
authored
Merge pull request #301 from iceljc/features/save-conversation-log
add content log and state log
2 parents a6a717d + c1753b8 commit 5f80b5e

File tree

20 files changed

+377
-46
lines changed

20 files changed

+377
-46
lines changed

src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs

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

34
namespace BotSharp.Abstraction.Conversations;
@@ -14,6 +15,8 @@ public interface IConversationService
1415
Task<List<Conversation>> GetLastConversations();
1516
Task<bool> DeleteConversation(string id);
1617
Task<bool> TruncateConversation(string conversationId, string messageId);
18+
Task<List<ConversationContentLogModel>> GetConversationContentLogs(string conversationId);
19+
Task<List<ConversationStateLogModel>> GetConversationStateLogs(string conversationId);
1720

1821
/// <summary>
1922
/// Send message to LLM

src/Infrastructure/BotSharp.Abstraction/Conversations/Models/ConversationStateLogModel.cs

Lines changed: 0 additions & 11 deletions
This file was deleted.

src/Infrastructure/BotSharp.Abstraction/Conversations/Settings/ConversationSetting.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,6 @@ public class ConversationSetting
99
public int MaxRecursiveDepth { get; set; } = 3;
1010
public bool EnableLlmCompletionLog { get; set; }
1111
public bool EnableExecutionLog { get; set; }
12+
public bool EnableContentLog { get; set; }
13+
public bool EnableStateLog { get; set; }
1214
}
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
namespace BotSharp.Abstraction.Loggers.Models;
22

3-
public class StreamingLogModel
3+
public class ConversationContentLogModel
44
{
55
[JsonPropertyName("conversation_id")]
66
public string ConversationId { get; set; }
7+
[JsonPropertyName("message_id")]
8+
public string MessageId { get; set; }
79
[JsonPropertyName("name")]
810
public string? Name { get; set; }
911
[JsonPropertyName("role")]
@@ -13,5 +15,5 @@ public class StreamingLogModel
1315
public string Content { get; set; }
1416

1517
[JsonPropertyName("created_at")]
16-
public DateTime CreateTime { get; set; }
18+
public DateTime CreateTime { get; set; } = DateTime.UtcNow;
1719
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
namespace BotSharp.Abstraction.Loggers.Models;
2+
3+
public class ConversationStateLogModel
4+
{
5+
[JsonPropertyName("conversation_id")]
6+
public string ConversationId { get; set; }
7+
[JsonPropertyName("message_id")]
8+
public string MessageId { get; set; }
9+
[JsonPropertyName("states")]
10+
public Dictionary<string, string> States { get; set; }
11+
[JsonPropertyName("created_at")]
12+
public DateTime CreateTime { get; set; } = DateTime.UtcNow;
13+
}

src/Infrastructure/BotSharp.Abstraction/Conversations/Models/LlmCompletionLog.cs renamed to src/Infrastructure/BotSharp.Abstraction/Loggers/Models/LlmCompletionLog.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace BotSharp.Abstraction.Conversations.Models;
1+
namespace BotSharp.Abstraction.Loggers.Models;
22

33
public class LlmCompletionLog
44
{

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using BotSharp.Abstraction.Loggers.Models;
12
using BotSharp.Abstraction.Plugins.Models;
23
using BotSharp.Abstraction.Repositories.Filters;
34
using BotSharp.Abstraction.Repositories.Models;
@@ -70,6 +71,16 @@ public interface IBotSharpRepository
7071
void SaveLlmCompletionLog(LlmCompletionLog log);
7172
#endregion
7273

74+
#region Conversation Content Log
75+
void SaveConversationContentLog(ConversationContentLogModel log);
76+
List<ConversationContentLogModel> GetConversationContentLogs(string conversationId);
77+
#endregion
78+
79+
#region Conversation State Log
80+
void SaveConversationStateLog(ConversationStateLogModel log);
81+
List<ConversationStateLogModel> GetConversationStateLogs(string conversationId);
82+
#endregion
83+
7384
#region Statistics
7485
void IncrementConversationCount();
7586
#endregion
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using BotSharp.Abstraction.Loggers.Models;
2+
using BotSharp.Abstraction.Repositories;
3+
4+
namespace BotSharp.Core.Conversations.Services;
5+
6+
public partial class ConversationService
7+
{
8+
public async Task<List<ConversationContentLogModel>> GetConversationContentLogs(string conversationId)
9+
{
10+
var db = _services.GetRequiredService<IBotSharpRepository>();
11+
var logs = db.GetConversationContentLogs(conversationId);
12+
return await Task.FromResult(logs);
13+
}
14+
15+
16+
public async Task<List<ConversationStateLogModel>> GetConversationStateLogs(string conversationId)
17+
{
18+
var db = _services.GetRequiredService<IBotSharpRepository>();
19+
var logs = db.GetConversationStateLogs(conversationId);
20+
return await Task.FromResult(logs);
21+
}
22+
}

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using BotSharp.Abstraction.Agents.Models;
2+
using BotSharp.Abstraction.Loggers.Models;
23
using BotSharp.Abstraction.Plugins.Models;
34
using BotSharp.Abstraction.Repositories;
45
using BotSharp.Abstraction.Repositories.Filters;
@@ -255,6 +256,30 @@ public void SaveLlmCompletionLog(LlmCompletionLog log)
255256
}
256257
#endregion
257258

259+
#region Conversation Content Log
260+
public void SaveConversationContentLog(ConversationContentLogModel log)
261+
{
262+
throw new NotImplementedException();
263+
}
264+
265+
public List<ConversationContentLogModel> GetConversationContentLogs(string conversationId)
266+
{
267+
throw new NotImplementedException();
268+
}
269+
#endregion
270+
271+
#region Conversation State Log
272+
public void SaveConversationStateLog(ConversationStateLogModel log)
273+
{
274+
throw new NotImplementedException();
275+
}
276+
277+
public List<ConversationStateLogModel> GetConversationStateLogs(string conversationId)
278+
{
279+
throw new NotImplementedException();
280+
}
281+
#endregion
282+
258283
#region Stats
259284
public void IncrementConversationCount()
260285
{

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

Lines changed: 102 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using BotSharp.Abstraction.Loggers.Models;
2+
using Serilog;
13
using System.IO;
24

35
namespace BotSharp.Core.Repository
@@ -54,14 +56,112 @@ public void SaveLlmCompletionLog(LlmCompletionLog log)
5456
Directory.CreateDirectory(logDir);
5557
}
5658

57-
var index = GetNextLlmCompletionLogIndex(logDir, log.MessageId);
59+
var index = GetNextLogIndex(logDir, log.MessageId);
5860
var file = Path.Combine(logDir, $"{log.MessageId}.{index}.log");
5961
File.WriteAllText(file, JsonSerializer.Serialize(log, _options));
6062
}
6163
#endregion
6264

65+
#region Conversation Content Log
66+
public void SaveConversationContentLog(ConversationContentLogModel log)
67+
{
68+
if (log == null) return;
69+
70+
log.ConversationId = log.ConversationId.IfNullOrEmptyAs(Guid.NewGuid().ToString());
71+
log.MessageId = log.MessageId.IfNullOrEmptyAs(Guid.NewGuid().ToString());
72+
73+
var convDir = FindConversationDirectory(log.ConversationId);
74+
if (string.IsNullOrEmpty(convDir))
75+
{
76+
convDir = Path.Combine(_dbSettings.FileRepository, _conversationSettings.DataDir, log.ConversationId);
77+
Directory.CreateDirectory(convDir);
78+
}
79+
80+
var logDir = Path.Combine(convDir, "content_log");
81+
if (!Directory.Exists(logDir))
82+
{
83+
Directory.CreateDirectory(logDir);
84+
}
85+
86+
var index = GetNextLogIndex(logDir, log.MessageId);
87+
var file = Path.Combine(logDir, $"{log.MessageId}.{index}.log");
88+
File.WriteAllText(file, JsonSerializer.Serialize(log, _options));
89+
}
90+
91+
public List<ConversationContentLogModel> GetConversationContentLogs(string conversationId)
92+
{
93+
var logs = new List<ConversationContentLogModel>();
94+
if (string.IsNullOrEmpty(conversationId)) return logs;
95+
96+
var convDir = FindConversationDirectory(conversationId);
97+
if (string.IsNullOrEmpty(convDir)) return logs;
98+
99+
var logDir = Path.Combine(convDir, "content_log");
100+
if (!Directory.Exists(logDir)) return logs;
101+
102+
foreach (var file in Directory.GetFiles(logDir))
103+
{
104+
var text = File.ReadAllText(file);
105+
var log = JsonSerializer.Deserialize<ConversationContentLogModel>(text);
106+
if (log == null) continue;
107+
108+
logs.Add(log);
109+
}
110+
return logs.OrderBy(x => x.CreateTime).ToList();
111+
}
112+
#endregion
113+
114+
#region Conversation State Log
115+
public void SaveConversationStateLog(ConversationStateLogModel log)
116+
{
117+
if (log == null) return;
118+
119+
log.ConversationId = log.ConversationId.IfNullOrEmptyAs(Guid.NewGuid().ToString());
120+
log.MessageId = log.MessageId.IfNullOrEmptyAs(Guid.NewGuid().ToString());
121+
122+
var convDir = FindConversationDirectory(log.ConversationId);
123+
if (string.IsNullOrEmpty(convDir))
124+
{
125+
convDir = Path.Combine(_dbSettings.FileRepository, _conversationSettings.DataDir, log.ConversationId);
126+
Directory.CreateDirectory(convDir);
127+
}
128+
129+
var logDir = Path.Combine(convDir, "state_log");
130+
if (!Directory.Exists(logDir))
131+
{
132+
Directory.CreateDirectory(logDir);
133+
}
134+
135+
var index = GetNextLogIndex(logDir, log.MessageId);
136+
var file = Path.Combine(logDir, $"{log.MessageId}.{index}.log");
137+
File.WriteAllText(file, JsonSerializer.Serialize(log, _options));
138+
}
139+
140+
public List<ConversationStateLogModel> GetConversationStateLogs(string conversationId)
141+
{
142+
var logs = new List<ConversationStateLogModel>();
143+
if (string.IsNullOrEmpty(conversationId)) return logs;
144+
145+
var convDir = FindConversationDirectory(conversationId);
146+
if (string.IsNullOrEmpty(convDir)) return logs;
147+
148+
var logDir = Path.Combine(convDir, "state_log");
149+
if (!Directory.Exists(logDir)) return logs;
150+
151+
foreach (var file in Directory.GetFiles(logDir))
152+
{
153+
var text = File.ReadAllText(file);
154+
var log = JsonSerializer.Deserialize<ConversationStateLogModel>(text);
155+
if (log == null) continue;
156+
157+
logs.Add(log);
158+
}
159+
return logs.OrderBy(x => x.CreateTime).ToList();
160+
}
161+
#endregion
162+
63163
#region Private methods
64-
private int GetNextLlmCompletionLogIndex(string logDir, string id)
164+
private int GetNextLogIndex(string logDir, string id)
65165
{
66166
var files = Directory.GetFiles(logDir);
67167
if (files.IsNullOrEmpty())

0 commit comments

Comments
 (0)