Skip to content

Commit 492a1d7

Browse files
committed
ITrackableMessage
1 parent 7ab383a commit 492a1d7

22 files changed

+103
-64
lines changed

docs/channels/components.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Messaging Components
22

3-
Conversations are a lot more than simple text messages when you are building a AI chatbot. In addition to text, the `BotSharp`` allows you to send rich-media, like audio, video, and images, and provides a set of structured messaging options in the form of message templates, quick replies, buttons and more. The UI rendering program can render components according to the returned data format.
3+
Conversations are a lot more than simple text messages when you are building a AI chatbot. In addition to text, the `BotSharp` allows you to send rich-media, like audio, video, and images, and provides a set of structured messaging options in the form of message templates, quick replies, buttons and more. The UI rendering program can render components according to the returned data format.
44

55

66
## Text Messages
@@ -75,7 +75,7 @@ Message templates are structured message formats used for various purposes to pr
7575
...
7676
}
7777
]
78-
}
78+
}
7979
}
8080
}
8181
}
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,9 @@
1+
using BotSharp.Abstraction.Models;
2+
13
namespace BotSharp.Abstraction.Conversations.Models;
24

3-
public class IncomingMessageModel
5+
public class IncomingMessageModel : MessageConfig
46
{
57
public string Text { get; set; } = string.Empty;
6-
7-
public virtual string Channel { get; set; } = string.Empty;
8-
9-
/// <summary>
10-
/// Completion Provider
11-
/// </summary>
12-
[JsonPropertyName("provider")]
13-
public virtual string? Provider { get; set; } = null;
14-
15-
/// <summary>
16-
/// Model name
17-
/// </summary>
18-
[JsonPropertyName("model")]
19-
public virtual string? Model { get; set; } = null;
20-
21-
/// <summary>
22-
/// The sampling temperature to use that controls the apparent creativity of generated completions.
23-
/// </summary>
24-
public float Temperature { get; set; } = 0.5f;
25-
26-
/// <summary>
27-
/// An alternative value to Temperature, called nucleus sampling, that causes
28-
/// the model to consider the results of the tokens with probability mass.
29-
/// </summary>
30-
public float SamplingFactor { get; set; } = 0.5f;
31-
32-
/// <summary>
33-
/// Conversation states from input
34-
/// </summary>
35-
public List<string> States { get; set; } = new List<string>();
8+
public virtual string Channel { get; set; }
369
}

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

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
using BotSharp.Abstraction.Models;
2+
13
namespace BotSharp.Abstraction.Conversations.Models;
24

3-
public class RoleDialogModel
5+
public class RoleDialogModel : ITrackableMessage
46
{
7+
public string MessageId { get; set; }
8+
59
/// <summary>
610
/// user, system, assistant, function
711
/// </summary>
@@ -34,10 +38,15 @@ public class RoleDialogModel
3438
[JsonIgnore(Condition = JsonIgnoreCondition.Always)]
3539
public bool StopCompletion { get; set; }
3640

41+
private RoleDialogModel()
42+
{
43+
}
44+
3745
public RoleDialogModel(string role, string text)
3846
{
3947
Role = role;
4048
Content = text;
49+
MessageId = Guid.NewGuid().ToString();
4150
}
4251

4352
public override string ToString()

src/Infrastructure/BotSharp.Abstraction/Instructs/Models/InstructResult.cs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
using BotSharp.Abstraction.Models;
2+
13
namespace BotSharp.Abstraction.Instructs.Models;
24

3-
public class InstructResult
5+
public class InstructResult : ITrackableMessage
46
{
7+
public string MessageId { get; set; }
58
public string Text { get; set; }
69
public object Data { get; set; }
710
public ConversationState States { get; set; }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace BotSharp.Abstraction.Models;
2+
3+
/// <summary>
4+
/// Define a message ID to extend message-level applications, such as model fees, token usage, and data collection
5+
/// </summary>
6+
public interface ITrackableMessage
7+
{
8+
string MessageId { get; set; }
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
namespace BotSharp.Abstraction.Models;
2+
3+
public class MessageConfig
4+
{
5+
/// <summary>
6+
/// Completion Provider
7+
/// </summary>
8+
[JsonPropertyName("provider")]
9+
public virtual string? Provider { get; set; } = null;
10+
11+
/// <summary>
12+
/// Model name
13+
/// </summary>
14+
[JsonPropertyName("model")]
15+
public virtual string? Model { get; set; } = null;
16+
17+
/// <summary>
18+
/// The sampling temperature to use that controls the apparent creativity of generated completions.
19+
/// </summary>
20+
public float Temperature { get; set; } = 0.5f;
21+
22+
/// <summary>
23+
/// An alternative value to Temperature, called nucleus sampling, that causes
24+
/// the model to consider the results of the tokens with probability mass.
25+
/// </summary>
26+
public float SamplingFactor { get; set; } = 0.5f;
27+
28+
/// <summary>
29+
/// Conversation states from input
30+
/// </summary>
31+
public List<string> States { get; set; } = new List<string>();
32+
}

src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
namespace BotSharp.Abstraction.Routing.Models;
22

3-
public class RoutingArgs
3+
public class RoutingArgs : ITrackableMessage
44
{
5+
[JsonPropertyName("message_id")]
6+
public string MessageId { get; set; }
7+
58
[JsonPropertyName("function")]
69
public string Function { get; set; }
710

src/Infrastructure/BotSharp.Abstraction/Using.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@
77
global using System.Text.Json.Serialization;
88
global using BotSharp.Abstraction.Agents.Models;
99
global using BotSharp.Abstraction.Conversations.Models;
10-
global using BotSharp.Abstraction.Agents.Enums;
10+
global using BotSharp.Abstraction.Agents.Enums;
11+
global using BotSharp.Abstraction.Models;

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,11 @@ public Task CleanHistory(string agentId)
7878
throw new NotImplementedException();
7979
}
8080

81-
public List<RoleDialogModel> GetDialogHistory(int lastCount = 20)
81+
public List<RoleDialogModel> GetDialogHistory(int lastCount = 50)
8282
{
8383
var dialogs = _storage.GetDialogs(_conversationId);
8484
return dialogs
85-
.Where(x => x.CreatedAt > DateTime.UtcNow.AddHours(-8))
85+
.Where(x => x.CreatedAt > DateTime.UtcNow.AddHours(-24))
8686
.TakeLast(lastCount)
8787
.ToList();
8888
}

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

+5-15
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,13 @@ namespace BotSharp.Core.Conversations.Services;
66
public class ConversationStorage : IConversationStorage
77
{
88
private readonly BotSharpDatabaseSettings _dbSettings;
9-
private readonly AgentSettings _agentSettings;
109
private readonly IServiceProvider _services;
11-
private readonly IUserIdentity _user;
1210
public ConversationStorage(
1311
BotSharpDatabaseSettings dbSettings,
14-
AgentSettings agentSettings,
15-
IServiceProvider services,
16-
IUserIdentity user)
12+
IServiceProvider services)
1713
{
1814
_dbSettings = dbSettings;
19-
_agentSettings = agentSettings;
2015
_services = services;
21-
_user = user;
2216
}
2317

2418
public void Append(string conversationId, RoleDialogModel dialog)
@@ -32,7 +26,7 @@ public void Append(string conversationId, RoleDialogModel dialog)
3226
{
3327
var args = dialog.FunctionArgs.Replace("\r", " ").Replace("\n", " ").Trim();
3428

35-
sb.AppendLine($"{dialog.CreatedAt}|{dialog.Role}|{agentId}|{dialog.FunctionName}|{args}");
29+
sb.AppendLine($"{dialog.CreatedAt}|{dialog.Role}|{agentId}|{dialog.MessageId}");
3630

3731
var content = dialog.Content;
3832
content = content.Replace("\r", " ").Replace("\n", " ").Trim();
@@ -44,9 +38,7 @@ public void Append(string conversationId, RoleDialogModel dialog)
4438
}
4539
else
4640
{
47-
var agentName = db.GetAgent(agentId)?.Name;
48-
49-
sb.AppendLine($"{dialog.CreatedAt}|{dialog.Role}|{agentId}|{agentName}|");
41+
sb.AppendLine($"{dialog.CreatedAt}|{dialog.Role}|{agentId}|{dialog.MessageId}");
5042
var content = dialog.Content.Replace("\r", " ").Replace("\n", " ").Trim();
5143
if (string.IsNullOrEmpty(content))
5244
{
@@ -73,15 +65,13 @@ public List<RoleDialogModel> GetDialogs(string conversationId)
7365
var createdAt = DateTime.Parse(meta.Split('|')[0]);
7466
var role = meta.Split('|')[1];
7567
var currentAgentId = meta.Split('|')[2];
76-
var funcName = meta.Split('|')[3];
77-
var funcArgs= meta.Split('|')[4];
68+
var messageId = meta.Split('|')[3];
7869
var text = dialog.Substring(4);
7970

8071
results.Add(new RoleDialogModel(role, text)
8172
{
8273
CurrentAgentId = currentAgentId,
83-
FunctionName = funcName,
84-
FunctionArgs = funcArgs,
74+
MessageId = messageId,
8575
Content = text,
8676
CreatedAt = createdAt
8777
});

src/Infrastructure/BotSharp.Core/Instructs/InstructService.cs

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public async Task<InstructResult> Execute(Agent agent, RoleDialogModel message)
3333
{
3434
return new InstructResult
3535
{
36+
MessageId = message.MessageId,
3637
Text = message.Content
3738
};
3839
}
@@ -42,6 +43,7 @@ public async Task<InstructResult> Execute(Agent agent, RoleDialogModel message)
4243
var result = await completer.GetCompletion(agent.Instruction);
4344
var response = new InstructResult
4445
{
46+
MessageId = message.MessageId,
4547
Text = result
4648
};
4749

src/Infrastructure/BotSharp.Core/Routing/Handlers/ContinueExecuteTaskRoutingHandler.cs

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public async Task<RoleDialogModel> Handle(IRoutingService routing, FunctionCallF
3333

3434
var result = new RoleDialogModel(AgentRole.Function, inst.Question)
3535
{
36+
MessageId = inst.MessageId,
3637
FunctionName = inst.Function,
3738
FunctionArgs = JsonSerializer.Serialize(inst.Arguments),
3839
CurrentAgentId = record.Id

src/Infrastructure/BotSharp.Core/Routing/Handlers/ConversationEndRoutingHandler.cs

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public async Task<RoleDialogModel> Handle(IRoutingService routing, FunctionCallF
2828
{
2929
var result = new RoleDialogModel(AgentRole.Assistant, inst.Response)
3030
{
31+
MessageId = inst.MessageId,
3132
CurrentAgentId = _settings.RouterId,
3233
FunctionName = inst.Function,
3334
Data = inst

src/Infrastructure/BotSharp.Core/Routing/Handlers/HumanInterventionNeededHandler.cs

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public async Task<RoleDialogModel> Handle(IRoutingService routing, FunctionCallF
2929
{
3030
var result = new RoleDialogModel(AgentRole.Assistant, inst.Response)
3131
{
32+
MessageId = inst.MessageId,
3233
CurrentAgentId = _settings.RouterId,
3334
FunctionName = inst.Function,
3435
Data = inst

src/Infrastructure/BotSharp.Core/Routing/Handlers/InterruptTaskExecutionRoutingHandler.cs

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public async Task<RoleDialogModel> Handle(IRoutingService routing, FunctionCallF
2828
{
2929
var result = new RoleDialogModel(AgentRole.User, inst.Reason)
3030
{
31+
MessageId = inst.MessageId,
3132
FunctionName = inst.Function,
3233
StopCompletion = true
3334
};

src/Infrastructure/BotSharp.Core/Routing/Handlers/ResponseToUserRoutingHandler.cs

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public async Task<RoleDialogModel> Handle(IRoutingService routing, FunctionCallF
2828
{
2929
var result = new RoleDialogModel(AgentRole.Assistant, inst.Response)
3030
{
31+
MessageId = inst.MessageId,
3132
CurrentAgentId = _settings.RouterId,
3233
FunctionName = inst.Function,
3334
Data = inst,

src/Infrastructure/BotSharp.Core/Routing/Handlers/RetrieveDataFromAgentRoutingHandler.cs

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public async Task<RoleDialogModel> Handle(IRoutingService routing, FunctionCallF
4545

4646
/*_dialogs.Add(new RoleDialogModel(AgentRole.Function, inst.Parameters.Answer)
4747
{
48+
MessageId = inst.MessageId,
4849
FunctionName = inst.Function,
4950
FunctionArgs = JsonSerializer.Serialize(inst.Parameters.Arguments),
5051
ExecutionResult = inst.Parameters.Answer,

src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public async Task<RoleDialogModel> Handle(IRoutingService routing, FunctionCallF
3535
var function = _services.GetServices<IFunctionCallback>().FirstOrDefault(x => x.Name == inst.Function);
3636
var message = new RoleDialogModel(AgentRole.Function, inst.Question)
3737
{
38+
MessageId = inst.MessageId,
3839
FunctionName = inst.Function,
3940
FunctionArgs = JsonSerializer.Serialize(inst),
4041
CurrentAgentId = context.GetCurrentAgentId(),
@@ -46,6 +47,7 @@ public async Task<RoleDialogModel> Handle(IRoutingService routing, FunctionCallF
4647
// Keep last message data for debug
4748
result.Data = result.Data ?? message.Data;
4849
result.FunctionName = result.FunctionName ?? message.FunctionName;
50+
4951
return result;
5052
}
5153
}

src/Infrastructure/BotSharp.Core/Routing/Handlers/TaskEndRoutingHandler.cs

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public async Task<RoleDialogModel> Handle(IRoutingService routing, FunctionCallF
2727
{
2828
var result = new RoleDialogModel(AgentRole.Assistant, inst.Response)
2929
{
30+
MessageId = inst.MessageId,
3031
CurrentAgentId = _settings.RouterId,
3132
FunctionName = inst.Function,
3233
Data = inst

src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs

+4-2
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public async Task<RoleDialogModel> InstructLoop()
7676
CurrentAgentId = router.Id
7777
};
7878

79-
var message = Dialogs.Last().Content;
79+
var inputMsg = Dialogs.Last();
8080

8181
var handlers = _services.GetServices<IRoutingHandler>();
8282

@@ -87,7 +87,8 @@ public async Task<RoleDialogModel> InstructLoop()
8787
loopCount++;
8888

8989
var inst = await GetNextInstruction();
90-
inst.Question = inst.Question ?? message;
90+
inst.MessageId = inputMsg.MessageId;
91+
inst.Question = inst.Question ?? inputMsg.Content;
9192

9293
var handler = handlers.FirstOrDefault(x => x.Name == inst.Function);
9394
if (handler == null)
@@ -99,6 +100,7 @@ public async Task<RoleDialogModel> InstructLoop()
99100
handler.SetDialogs(Dialogs);
100101

101102
result = await handler.Handle(this, inst);
103+
result.MessageId = inputMsg.MessageId;
102104

103105
stop = !_settings.EnableReasoning;
104106
}

src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs

+10-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using BotSharp.Abstraction.ApiAdapters;
22
using BotSharp.Abstraction.Conversations.Models;
3+
using BotSharp.Abstraction.Models;
34
using BotSharp.OpenAPI.ViewModels.Conversations;
45

56
namespace BotSharp.OpenAPI.Controllers;
@@ -19,15 +20,17 @@ public ConversationController(IServiceProvider services,
1920
}
2021

2122
[HttpPost("/conversation/{agentId}")]
22-
public async Task<ConversationViewModel> NewConversation([FromRoute] string agentId)
23+
public async Task<ConversationViewModel> NewConversation([FromRoute] string agentId, [FromBody] MessageConfig config)
2324
{
2425
var service = _services.GetRequiredService<IConversationService>();
25-
var sess = new Conversation
26+
var conv = new Conversation
2627
{
2728
AgentId = agentId
2829
};
29-
sess = await service.NewConversation(sess);
30-
return ConversationViewModel.FromSession(sess);
30+
conv = await service.NewConversation(conv);
31+
config.States.ForEach(x => conv.States[x.Split('=')[0]] = x.Split('=')[1]);
32+
33+
return ConversationViewModel.FromSession(conv);
3134
}
3235

3336
[HttpDelete("/conversation/{agentId}/{conversationId}")]
@@ -51,9 +54,8 @@ public async Task<MessageResponseModel> SendMessage([FromRoute] string agentId,
5154

5255
var response = new MessageResponseModel();
5356
var stackMsg = new List<RoleDialogModel>();
54-
55-
await conv.SendMessage(agentId,
56-
new RoleDialogModel("user", input.Text),
57+
var inputMsg = new RoleDialogModel("user", input.Text);
58+
await conv.SendMessage(agentId, inputMsg,
5759
async msg =>
5860
{
5961
stackMsg.Add(msg);
@@ -71,6 +73,7 @@ await conv.SendMessage(agentId,
7173
response.Text = string.Join("\r\n", stackMsg.Select(x => x.Content));
7274
response.Data = response.Data ?? stackMsg.Last().Data;
7375
response.Function = stackMsg.Last().FunctionName;
76+
response.MessageId = inputMsg.MessageId;
7477

7578
return response;
7679
}

0 commit comments

Comments
 (0)