Merge branch 'SciSharp:master' into master
This commit is contained in:
commit
0cbb0183cf
|
|
@ -1,6 +1,6 @@
|
|||
# Messaging Components
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
|
||||
## Text Messages
|
||||
|
|
@ -75,7 +75,7 @@ Message templates are structured message formats used for various purposes to pr
|
|||
...
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,36 +1,9 @@
|
|||
using BotSharp.Abstraction.Models;
|
||||
|
||||
namespace BotSharp.Abstraction.Conversations.Models;
|
||||
|
||||
public class IncomingMessageModel
|
||||
public class IncomingMessageModel : MessageConfig
|
||||
{
|
||||
public string Text { get; set; } = string.Empty;
|
||||
|
||||
public virtual string Channel { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Completion Provider
|
||||
/// </summary>
|
||||
[JsonPropertyName("provider")]
|
||||
public virtual string? Provider { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Model name
|
||||
/// </summary>
|
||||
[JsonPropertyName("model")]
|
||||
public virtual string? Model { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// The sampling temperature to use that controls the apparent creativity of generated completions.
|
||||
/// </summary>
|
||||
public float Temperature { get; set; } = 0.5f;
|
||||
|
||||
/// <summary>
|
||||
/// An alternative value to Temperature, called nucleus sampling, that causes
|
||||
/// the model to consider the results of the tokens with probability mass.
|
||||
/// </summary>
|
||||
public float SamplingFactor { get; set; } = 0.5f;
|
||||
|
||||
/// <summary>
|
||||
/// Conversation states from input
|
||||
/// </summary>
|
||||
public List<string> States { get; set; } = new List<string>();
|
||||
public virtual string Channel { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
using BotSharp.Abstraction.Models;
|
||||
|
||||
namespace BotSharp.Abstraction.Conversations.Models;
|
||||
|
||||
public class RoleDialogModel
|
||||
public class RoleDialogModel : ITrackableMessage
|
||||
{
|
||||
public string MessageId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// user, system, assistant, function
|
||||
/// </summary>
|
||||
|
|
@ -34,10 +38,15 @@ public class RoleDialogModel
|
|||
[JsonIgnore(Condition = JsonIgnoreCondition.Always)]
|
||||
public bool StopCompletion { get; set; }
|
||||
|
||||
private RoleDialogModel()
|
||||
{
|
||||
}
|
||||
|
||||
public RoleDialogModel(string role, string text)
|
||||
{
|
||||
Role = role;
|
||||
Content = text;
|
||||
MessageId = Guid.NewGuid().ToString();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
using BotSharp.Abstraction.Models;
|
||||
|
||||
namespace BotSharp.Abstraction.Instructs.Models;
|
||||
|
||||
public class InstructResult
|
||||
public class InstructResult : ITrackableMessage
|
||||
{
|
||||
public string MessageId { get; set; }
|
||||
public string Text { get; set; }
|
||||
public object Data { get; set; }
|
||||
public ConversationState States { get; set; }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
namespace BotSharp.Abstraction.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Define a message ID to extend message-level applications, such as model fees, token usage, and data collection
|
||||
/// </summary>
|
||||
public interface ITrackableMessage
|
||||
{
|
||||
string MessageId { get; set; }
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
namespace BotSharp.Abstraction.Models;
|
||||
|
||||
public class MessageConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// Completion Provider
|
||||
/// </summary>
|
||||
[JsonPropertyName("provider")]
|
||||
public virtual string? Provider { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Model name
|
||||
/// </summary>
|
||||
[JsonPropertyName("model")]
|
||||
public virtual string? Model { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// The sampling temperature to use that controls the apparent creativity of generated completions.
|
||||
/// </summary>
|
||||
public float Temperature { get; set; } = 0.5f;
|
||||
|
||||
/// <summary>
|
||||
/// An alternative value to Temperature, called nucleus sampling, that causes
|
||||
/// the model to consider the results of the tokens with probability mass.
|
||||
/// </summary>
|
||||
public float SamplingFactor { get; set; } = 0.5f;
|
||||
|
||||
/// <summary>
|
||||
/// Conversation states from input
|
||||
/// </summary>
|
||||
public List<string> States { get; set; } = new List<string>();
|
||||
}
|
||||
|
|
@ -1,7 +1,10 @@
|
|||
namespace BotSharp.Abstraction.Routing.Models;
|
||||
|
||||
public class RoutingArgs
|
||||
public class RoutingArgs : ITrackableMessage
|
||||
{
|
||||
[JsonPropertyName("message_id")]
|
||||
public string MessageId { get; set; }
|
||||
|
||||
[JsonPropertyName("function")]
|
||||
public string Function { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -7,4 +7,5 @@ global using System.ComponentModel.DataAnnotations;
|
|||
global using System.Text.Json.Serialization;
|
||||
global using BotSharp.Abstraction.Agents.Models;
|
||||
global using BotSharp.Abstraction.Conversations.Models;
|
||||
global using BotSharp.Abstraction.Agents.Enums;
|
||||
global using BotSharp.Abstraction.Agents.Enums;
|
||||
global using BotSharp.Abstraction.Models;
|
||||
|
|
@ -78,11 +78,11 @@ public partial class ConversationService : IConversationService
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public List<RoleDialogModel> GetDialogHistory(int lastCount = 20)
|
||||
public List<RoleDialogModel> GetDialogHistory(int lastCount = 50)
|
||||
{
|
||||
var dialogs = _storage.GetDialogs(_conversationId);
|
||||
return dialogs
|
||||
.Where(x => x.CreatedAt > DateTime.UtcNow.AddHours(-8))
|
||||
.Where(x => x.CreatedAt > DateTime.UtcNow.AddHours(-24))
|
||||
.TakeLast(lastCount)
|
||||
.ToList();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,19 +6,13 @@ namespace BotSharp.Core.Conversations.Services;
|
|||
public class ConversationStorage : IConversationStorage
|
||||
{
|
||||
private readonly BotSharpDatabaseSettings _dbSettings;
|
||||
private readonly AgentSettings _agentSettings;
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly IUserIdentity _user;
|
||||
public ConversationStorage(
|
||||
BotSharpDatabaseSettings dbSettings,
|
||||
AgentSettings agentSettings,
|
||||
IServiceProvider services,
|
||||
IUserIdentity user)
|
||||
IServiceProvider services)
|
||||
{
|
||||
_dbSettings = dbSettings;
|
||||
_agentSettings = agentSettings;
|
||||
_services = services;
|
||||
_user = user;
|
||||
}
|
||||
|
||||
public void Append(string conversationId, RoleDialogModel dialog)
|
||||
|
|
@ -32,7 +26,7 @@ public class ConversationStorage : IConversationStorage
|
|||
{
|
||||
var args = dialog.FunctionArgs.Replace("\r", " ").Replace("\n", " ").Trim();
|
||||
|
||||
sb.AppendLine($"{dialog.CreatedAt}|{dialog.Role}|{agentId}|{dialog.FunctionName}|{args}");
|
||||
sb.AppendLine($"{dialog.CreatedAt}|{dialog.Role}|{agentId}|{dialog.MessageId}");
|
||||
|
||||
var content = dialog.Content;
|
||||
content = content.Replace("\r", " ").Replace("\n", " ").Trim();
|
||||
|
|
@ -44,9 +38,7 @@ public class ConversationStorage : IConversationStorage
|
|||
}
|
||||
else
|
||||
{
|
||||
var agentName = db.GetAgent(agentId)?.Name;
|
||||
|
||||
sb.AppendLine($"{dialog.CreatedAt}|{dialog.Role}|{agentId}|{agentName}|");
|
||||
sb.AppendLine($"{dialog.CreatedAt}|{dialog.Role}|{agentId}|{dialog.MessageId}");
|
||||
var content = dialog.Content.Replace("\r", " ").Replace("\n", " ").Trim();
|
||||
if (string.IsNullOrEmpty(content))
|
||||
{
|
||||
|
|
@ -73,15 +65,13 @@ public class ConversationStorage : IConversationStorage
|
|||
var createdAt = DateTime.Parse(meta.Split('|')[0]);
|
||||
var role = meta.Split('|')[1];
|
||||
var currentAgentId = meta.Split('|')[2];
|
||||
var funcName = meta.Split('|')[3];
|
||||
var funcArgs= meta.Split('|')[4];
|
||||
var messageId = meta.Split('|')[3];
|
||||
var text = dialog.Substring(4);
|
||||
|
||||
results.Add(new RoleDialogModel(role, text)
|
||||
{
|
||||
CurrentAgentId = currentAgentId,
|
||||
FunctionName = funcName,
|
||||
FunctionArgs = funcArgs,
|
||||
MessageId = messageId,
|
||||
Content = text,
|
||||
CreatedAt = createdAt
|
||||
});
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ public partial class InstructService : IInstructService
|
|||
{
|
||||
return new InstructResult
|
||||
{
|
||||
MessageId = message.MessageId,
|
||||
Text = message.Content
|
||||
};
|
||||
}
|
||||
|
|
@ -42,6 +43,7 @@ public partial class InstructService : IInstructService
|
|||
var result = await completer.GetCompletion(agent.Instruction);
|
||||
var response = new InstructResult
|
||||
{
|
||||
MessageId = message.MessageId,
|
||||
Text = result
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ public class ContinueExecuteTaskRoutingHandler : RoutingHandlerBase, IRoutingHan
|
|||
|
||||
var result = new RoleDialogModel(AgentRole.Function, inst.Question)
|
||||
{
|
||||
MessageId = inst.MessageId,
|
||||
FunctionName = inst.Function,
|
||||
FunctionArgs = JsonSerializer.Serialize(inst.Arguments),
|
||||
CurrentAgentId = record.Id
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ public class ConversationEndRoutingHandler : RoutingHandlerBase, IRoutingHandler
|
|||
{
|
||||
var result = new RoleDialogModel(AgentRole.Assistant, inst.Response)
|
||||
{
|
||||
MessageId = inst.MessageId,
|
||||
CurrentAgentId = _settings.RouterId,
|
||||
FunctionName = inst.Function,
|
||||
Data = inst
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ public class HumanInterventionNeededHandler : RoutingHandlerBase, IRoutingHandle
|
|||
{
|
||||
var result = new RoleDialogModel(AgentRole.Assistant, inst.Response)
|
||||
{
|
||||
MessageId = inst.MessageId,
|
||||
CurrentAgentId = _settings.RouterId,
|
||||
FunctionName = inst.Function,
|
||||
Data = inst
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ public class InterruptTaskExecutionRoutingHandler : RoutingHandlerBase, IRouting
|
|||
{
|
||||
var result = new RoleDialogModel(AgentRole.User, inst.Reason)
|
||||
{
|
||||
MessageId = inst.MessageId,
|
||||
FunctionName = inst.Function,
|
||||
StopCompletion = true
|
||||
};
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ public class ResponseToUserRoutingHandler : RoutingHandlerBase, IRoutingHandler
|
|||
{
|
||||
var result = new RoleDialogModel(AgentRole.Assistant, inst.Response)
|
||||
{
|
||||
MessageId = inst.MessageId,
|
||||
CurrentAgentId = _settings.RouterId,
|
||||
FunctionName = inst.Function,
|
||||
Data = inst,
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ public class RetrieveDataFromAgentRoutingHandler : RoutingHandlerBase, IRoutingH
|
|||
|
||||
/*_dialogs.Add(new RoleDialogModel(AgentRole.Function, inst.Parameters.Answer)
|
||||
{
|
||||
MessageId = inst.MessageId,
|
||||
FunctionName = inst.Function,
|
||||
FunctionArgs = JsonSerializer.Serialize(inst.Parameters.Arguments),
|
||||
ExecutionResult = inst.Parameters.Answer,
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ public class RouteToAgentRoutingHandler : RoutingHandlerBase, IRoutingHandler
|
|||
var function = _services.GetServices<IFunctionCallback>().FirstOrDefault(x => x.Name == inst.Function);
|
||||
var message = new RoleDialogModel(AgentRole.Function, inst.Question)
|
||||
{
|
||||
MessageId = inst.MessageId,
|
||||
FunctionName = inst.Function,
|
||||
FunctionArgs = JsonSerializer.Serialize(inst),
|
||||
CurrentAgentId = context.GetCurrentAgentId(),
|
||||
|
|
@ -46,6 +47,7 @@ public class RouteToAgentRoutingHandler : RoutingHandlerBase, IRoutingHandler
|
|||
// Keep last message data for debug
|
||||
result.Data = result.Data ?? message.Data;
|
||||
result.FunctionName = result.FunctionName ?? message.FunctionName;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ public class TaskEndRoutingHandler : RoutingHandlerBase, IRoutingHandler
|
|||
{
|
||||
var result = new RoleDialogModel(AgentRole.Assistant, inst.Response)
|
||||
{
|
||||
MessageId = inst.MessageId,
|
||||
CurrentAgentId = _settings.RouterId,
|
||||
FunctionName = inst.Function,
|
||||
Data = inst
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ public partial class RoutingService : IRoutingService
|
|||
CurrentAgentId = router.Id
|
||||
};
|
||||
|
||||
var message = Dialogs.Last().Content;
|
||||
var inputMsg = Dialogs.Last();
|
||||
|
||||
var handlers = _services.GetServices<IRoutingHandler>();
|
||||
|
||||
|
|
@ -87,7 +87,8 @@ public partial class RoutingService : IRoutingService
|
|||
loopCount++;
|
||||
|
||||
var inst = await GetNextInstruction();
|
||||
inst.Question = inst.Question ?? message;
|
||||
inst.MessageId = inputMsg.MessageId;
|
||||
inst.Question = inst.Question ?? inputMsg.Content;
|
||||
|
||||
var handler = handlers.FirstOrDefault(x => x.Name == inst.Function);
|
||||
if (handler == null)
|
||||
|
|
@ -99,6 +100,7 @@ public partial class RoutingService : IRoutingService
|
|||
handler.SetDialogs(Dialogs);
|
||||
|
||||
result = await handler.Handle(this, inst);
|
||||
result.MessageId = inputMsg.MessageId;
|
||||
|
||||
stop = !_settings.EnableReasoning;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using BotSharp.Abstraction.ApiAdapters;
|
||||
using BotSharp.Abstraction.Conversations.Models;
|
||||
using BotSharp.Abstraction.Models;
|
||||
using BotSharp.OpenAPI.ViewModels.Conversations;
|
||||
|
||||
namespace BotSharp.OpenAPI.Controllers;
|
||||
|
|
@ -19,15 +20,17 @@ public class ConversationController : ControllerBase, IApiAdapter
|
|||
}
|
||||
|
||||
[HttpPost("/conversation/{agentId}")]
|
||||
public async Task<ConversationViewModel> NewConversation([FromRoute] string agentId)
|
||||
public async Task<ConversationViewModel> NewConversation([FromRoute] string agentId, [FromBody] MessageConfig config)
|
||||
{
|
||||
var service = _services.GetRequiredService<IConversationService>();
|
||||
var sess = new Conversation
|
||||
var conv = new Conversation
|
||||
{
|
||||
AgentId = agentId
|
||||
};
|
||||
sess = await service.NewConversation(sess);
|
||||
return ConversationViewModel.FromSession(sess);
|
||||
conv = await service.NewConversation(conv);
|
||||
config.States.ForEach(x => conv.States[x.Split('=')[0]] = x.Split('=')[1]);
|
||||
|
||||
return ConversationViewModel.FromSession(conv);
|
||||
}
|
||||
|
||||
[HttpDelete("/conversation/{agentId}/{conversationId}")]
|
||||
|
|
@ -51,9 +54,8 @@ public class ConversationController : ControllerBase, IApiAdapter
|
|||
|
||||
var response = new MessageResponseModel();
|
||||
var stackMsg = new List<RoleDialogModel>();
|
||||
|
||||
await conv.SendMessage(agentId,
|
||||
new RoleDialogModel("user", input.Text),
|
||||
var inputMsg = new RoleDialogModel("user", input.Text);
|
||||
await conv.SendMessage(agentId, inputMsg,
|
||||
async msg =>
|
||||
{
|
||||
stackMsg.Add(msg);
|
||||
|
|
@ -71,6 +73,7 @@ public class ConversationController : ControllerBase, IApiAdapter
|
|||
response.Text = string.Join("\r\n", stackMsg.Select(x => x.Content));
|
||||
response.Data = response.Data ?? stackMsg.Last().Data;
|
||||
response.Function = stackMsg.Last().FunctionName;
|
||||
response.MessageId = inputMsg.MessageId;
|
||||
|
||||
return response;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
using BotSharp.Abstraction.Models;
|
||||
|
||||
namespace BotSharp.OpenAPI.ViewModels.Conversations;
|
||||
|
||||
public class MessageResponseModel
|
||||
public class MessageResponseModel : ITrackableMessage
|
||||
{
|
||||
public string MessageId { get; set; }
|
||||
public string Text { get; set; }
|
||||
public string Function { get; set; }
|
||||
public object Data { get; set; }
|
||||
|
|
|
|||
Loading…
Reference in a new issue