Skip to content

merge latest code #389

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 42 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
78ef7b6
refine rc options
Mar 28, 2024
bd7d3ff
add state change event
Mar 28, 2024
759f1f7
Merge pull request #371 from iceljc/features/add-state-change-log
Oceania2018 Mar 28, 2024
9f79dcf
Save function result to Storage
Mar 28, 2024
16e3a70
human_intervention_needed
Mar 28, 2024
25a4ec3
Merge branch 'master' of https://github.com/hchen2020/BotSharp
Mar 28, 2024
198ceb4
Merge pull request #372 from hchen2020/master
Oceania2018 Mar 28, 2024
3d7fb18
optimize naive.
Mar 28, 2024
6ecf249
Merge pull request #373 from hchen2020/master
Oceania2018 Mar 28, 2024
ffe9fb8
Update RoutingService.InvokeFunction.cs
Oceania2018 Mar 28, 2024
56e204c
expected_user_goal_agent
Mar 29, 2024
fcaf72a
Merge pull request #374 from hchen2020/master
Oceania2018 Mar 29, 2024
fd96a38
refine state node
Mar 29, 2024
14a0ea1
Merge pull request #375 from iceljc/features/refine-state-node
Oceania2018 Mar 29, 2024
fc7a82d
refine state node
Mar 29, 2024
e1e7f98
Merge pull request #376 from iceljc/features/refine-state-node
Oceania2018 Mar 29, 2024
d8368ef
Provide conversation_end flat in response_to_user
Mar 29, 2024
86f056b
Merge pull request #377 from hchen2020/master
Oceania2018 Mar 29, 2024
52d542c
response_to_user
Mar 30, 2024
91d2bb1
Merge branch 'SciSharp:master' into master
hchen2020 Mar 30, 2024
6e69412
Merge pull request #378 from hchen2020/master
Oceania2018 Mar 30, 2024
48cae89
OnConversationEnding
Oceania2018 Mar 30, 2024
bed33c8
Remove agent required args based on latest states.
Mar 30, 2024
f751d75
Merge pull request #379 from hchen2020/master
Oceania2018 Mar 30, 2024
8f9e2ad
Save to Storage as well
Mar 31, 2024
da9becb
Merge pull request #380 from hchen2020/master
Oceania2018 Mar 31, 2024
f61ee50
add active round log
iceljc Mar 31, 2024
a245d71
Merge pull request #381 from iceljc/features/refine-state-change
Oceania2018 Mar 31, 2024
15291fa
Fix OnRoutingInstructionRevised
Mar 31, 2024
3dd203f
Merge pull request #382 from hchen2020/master
Oceania2018 Mar 31, 2024
f5eaa71
Add featuer of VisibilityExpression
Mar 31, 2024
433d542
Merge pull request #383 from hchen2020/master
Oceania2018 Mar 31, 2024
f1999f3
GetProviders only when the setting has value.
Oceania2018 Mar 31, 2024
e3e769e
Release v1.2.
Oceania2018 Apr 1, 2024
a649b65
add agent queue changed event
iceljc Apr 1, 2024
8cc9776
Merge pull request #384 from iceljc/features/add-agent-queue-event
Oceania2018 Apr 1, 2024
601b64b
Prevent duplicate record to be inserted
Oceania2018 Apr 2, 2024
1f80192
refine json converter
Apr 2, 2024
6f93347
Merge pull request #385 from iceljc/features/refine-json-converter
Oceania2018 Apr 2, 2024
fcb7619
Handle output routing exception.
Apr 2, 2024
ff3f10f
Merge pull request #388 from hchen2020/master
Oceania2018 Apr 2, 2024
451ec99
Merge branch 'MetaGLM' into merge-code
geffzhang Apr 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<Project>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>12.0</LangVersion>
<BotSharpVersion>1.0.1</BotSharpVersion>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<LangVersion>10.0</LangVersion>
<BotSharpVersion>1.2.1</BotSharpVersion>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<GenerateDocumentationFile>false</GenerateDocumentationFile>
</PropertyGroup>
</Project>
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

[![Discord](https://img.shields.io/discord/1106946823282761851?label=Discord)](https://discord.com/channels/1106946823282761851/1106947212459642991)
[![QQ群聊](https://img.shields.io/static/v1?label=QQ&message=群聊&color=brightgreen)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=sN9VVMwbWjs5L0ATpizKKxOcZdEPMrp8&authKey=RLDw41bLTrEyEgZZi%2FzT4pYk%2BwmEFgFcrhs8ZbkiVY7a4JFckzJefaYNW6Lk4yPX&noverify=0&group_code=985366726)
[![Join the chat at https://gitter.im/publiclab/publiclab](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/sci-sharp/community)
[![Apache 2.0](https://img.shields.io/hexpm/l/plug.svg)](https://raw.githubusercontent.com/Oceania2018/BotSharp/master/LICENSE)
[![NuGet](https://img.shields.io/nuget/dt/BotSharp.Core.svg)](https://www.nuget.org/packages/BotSharp.Core)
[![Build status](https://ci.appveyor.com/api/projects/status/qx2dx5ca5hjqodm5?svg=true)](https://ci.appveyor.com/project/Haiping-Chen/botsharp)
Expand Down Expand Up @@ -88,6 +87,7 @@ BotSharp uses component design, the kernel is kept to a minimum, and business fu
- BotSharp.Plugin.HuggingFace
- BotSharp.Plugin.LLamaSharp
- BotSharp.Plugin.SemanticKernel
- BotSharp.Plugin.SparkDesk

#### Messaging / Channel
- BotSharp.OpenAPI
Expand Down
30 changes: 29 additions & 1 deletion docs/llm/function.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,32 @@

A **calling function** is a function that is passed as an argument to another function and is executed after a specific event or action occurs. In the context of **large language models (LLMs)**, calling functions can be used to hook into various stages of an LLM application. They are useful for tasks such as logging, monitoring, streaming, and more. For example, in the **BotSharp** framework, calling functions can be used to log information, monitor the progress of an LLM application, or perform other tasks. The BotSharp provides a `callbacks` argument that allows developers to interactive with external systems.

The use of calling functions in LLM applications provides flexibility and extensibility. Developers can customize the behavior of their applications by defining callback handlers that implement specific methods. These handlers can be used for tasks like logging, error handling, or interacting with external systems. The function will be triggered by LLM based on the conversation context.
The use of calling functions in LLM applications provides flexibility and extensibility. Developers can customize the behavior of their applications by defining callback handlers that implement specific methods. These handlers can be used for tasks like logging, error handling, or interacting with external systems. The function will be triggered by LLM based on the conversation context.

## Hide Function

In order to more flexibly control whether the Agent is allowed to use a certain function, there is a Visibility Expression property in the function definition that can be used to control display or hiding. When we input prompt into LLM, although we can use state variables in the system instruction file to control the rendering content, LLM will still take the definition of the function into consideration. If the related functions are not hidden at the same time, LLM will still be It is possible to call related functions, bringing unexpected results. Because we need to control system instruction and function definition at the same time to make them consistent.

```json
{
"name": "make_payment",
"description": "call this function to make payment",
"visibility_expression": "{% if states.order_number != empty %}visible{% endif %}",
"parameters": {
"type": "object",
"properties": {
"order_number": {
"type": "string",
"description": "order number."
},
"total_amount": {
"type": "string",
"description": "total amount."
}
},
"required": ["order_number", "total_amount"]
}
}
```

The above is an example. The system will parse the liquid template of Visibility Expression `{% if states.order_number != empty %}visible{% endif %}`. When "visible" is returned, the system will allow the Agent to use this function. In liquid In expressions, we can use `states.name` to reference the state value in the conversation.
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using BotSharp.Abstraction.Functions.Models;
using BotSharp.Abstraction.Plugins.Models;
using BotSharp.Abstraction.Repositories.Filters;

Expand All @@ -23,6 +24,8 @@ public interface IAgentService

string RenderedTemplate(Agent agent, string templateName);

bool RenderFunction(Agent agent, FunctionDef def);

/// <summary>
/// Get agent detail without trigger any hook.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public IConversationHook SetConversation(Conversation conversation)
public virtual Task OnStateLoaded(ConversationState state)
=> Task.CompletedTask;

public virtual Task OnStateChanged(string name, string preValue, string currentValue)
public virtual Task OnStateChanged(StateChangeModel stateChange)
=> Task.CompletedTask;

public virtual Task OnDialogRecordLoaded(RoleDialogModel dialog)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public interface IConversationHook
Task OnDialogRecordLoaded(RoleDialogModel dialog);

Task OnStateLoaded(ConversationState state);
Task OnStateChanged(string name, string preValue, string currentValue);
Task OnStateChanged(StateChangeModel stateChange);

Task OnMessageReceived(RoleDialogModel message);
Task OnPostbackMessageReceived(RoleDialogModel message, PostbackMessageModel replyMsg);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
namespace BotSharp.Abstraction.Conversations.Models;

public class StateChangeModel
{
[JsonPropertyName("conversation_id")]
public string ConversationId { get; set; }

[JsonPropertyName("message_id")]
public string MessageId { get; set; }

[JsonPropertyName("name")]
public string Name { get; set; }

[JsonPropertyName("before_value")]
public string BeforeValue { get; set; }

[JsonPropertyName("before_active_rounds")]
public int? BeforeActiveRounds { get; set; }

[JsonPropertyName("after_value")]
public string AfterValue { get; set; }

[JsonPropertyName("after_active_rounds")]
public int? AfterActiveRounds { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,9 @@ public class FunctionCallingResponse

[JsonPropertyName("args")]
public JsonDocument? Args { get; set; }

public override string ToString()
{
return $"{FunctionName}({JsonSerializer.Serialize(Args)}) => {Content}";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ public class FunctionDef
public string Name { get; set; }
public string Description { get; set; }

[JsonPropertyName("visibility_expression")]
public string? VisibilityExpression { get; set; }

[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Impact { get; set; }

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace BotSharp.Abstraction.Infrastructures.Enums;

public class StateConst
{
public const string EXPECTED_ACTION_AGENT = "expected_next_action_agent";
public const string EXPECTED_GOAL_AGENT = "expected_user_goal_agent";
public const string NEXT_ACTION_AGENT = "next_action_agent";
public const string USER_GOAL_AGENT = "user_goal_agent";
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,13 @@ public interface IContentGeneratingHook
/// </summary>
/// <returns></returns>
Task AfterGenerated(RoleDialogModel message, TokenStatsModel tokenStats) => Task.CompletedTask;

/// <summary>
/// Rdndering template
/// </summary>
/// <param name="agent"></param>
/// <param name="name"></param>
/// <param name="content"></param>
/// <returns></returns>
Task OnRenderingTemplate(Agent agent, string name, string content) => Task.CompletedTask;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace BotSharp.Abstraction.Loggers.Models;

public class AgentQueueChangedLogModel
{
[JsonPropertyName("conversation_id")]
public string ConversationId { get; set; }

[JsonPropertyName("log")]
public string Log { get; set; }

[JsonPropertyName("created_at")]
public DateTime CreateTime { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace BotSharp.Abstraction.Loggers.Models;

public class StateChangeOutputModel : StateChangeModel
{
[JsonPropertyName("created_at")]
public DateTime CreateTime { get; set; } = DateTime.UtcNow;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,7 @@ public class RichContentJsonConverter : JsonConverter<IRichMessage>
using var jsonDoc = JsonDocument.ParseValue(ref reader);
var root = jsonDoc.RootElement;
var jsonText = root.GetRawText();
IRichMessage? res = null;

var parser = new MessageParser();
if (root.TryGetProperty("rich_type", out JsonElement element))
{
var richType = element.GetString();
res = parser.ParseRichMessage(richType, jsonText, root, options);
}

var res = MessageParser.ParseRichMessage(root, options);
return res;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,7 @@ public class TemplateMessageJsonConverter : JsonConverter<ITemplateMessage>
using var jsonDoc = JsonDocument.ParseValue(ref reader);
var root = jsonDoc.RootElement;
var jsonText = root.GetRawText();
ITemplateMessage? res = null;

var parser = new MessageParser();
if (root.TryGetProperty("template_type", out JsonElement element))
{
var templateType = element.GetString();
res = parser.ParseTemplateMessage(templateType, jsonText, root, options);
}

var res = MessageParser.ParseTemplateMessage(root, options);
return res;
}

Expand Down
121 changes: 69 additions & 52 deletions src/Infrastructure/BotSharp.Abstraction/Messaging/MessageParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,79 +6,96 @@

namespace BotSharp.Core.Messaging;

public class MessageParser
public static class MessageParser
{
public MessageParser()
{
}

public IRichMessage? ParseRichMessage(string richType, string jsonText, JsonElement root, JsonSerializerOptions options)
public static IRichMessage? ParseRichMessage(JsonElement root, JsonSerializerOptions options)
{
IRichMessage? res = null;
JsonElement element;
var jsonText = root.GetRawText();

if (richType == RichTypeEnum.ButtonTemplate)
{
res = JsonSerializer.Deserialize<ButtonTemplateMessage>(jsonText, options);
}
else if (richType == RichTypeEnum.MultiSelectTemplate)
{
res = JsonSerializer.Deserialize<MultiSelectTemplateMessage>(jsonText, options);
}
else if (richType == RichTypeEnum.QuickReply)
{
res = JsonSerializer.Deserialize<QuickReplyMessage>(jsonText, options);
}
else if (richType == RichTypeEnum.CouponTemplate)
{
res = JsonSerializer.Deserialize<CouponTemplateMessage>(jsonText, options);
}
else if (richType == RichTypeEnum.Text)
if (root.TryGetProperty("rich_type", out element))
{
res = JsonSerializer.Deserialize<TextMessage>(jsonText, options);
}
else if (richType == RichTypeEnum.GenericTemplate)
{
if (root.TryGetProperty("element_type", out var element))
var richType = element.GetString();
if (richType == RichTypeEnum.ButtonTemplate)
{
res = JsonSerializer.Deserialize<ButtonTemplateMessage>(jsonText, options);
}
else if (richType == RichTypeEnum.MultiSelectTemplate)
{
res = JsonSerializer.Deserialize<MultiSelectTemplateMessage>(jsonText, options);
}
else if (richType == RichTypeEnum.QuickReply)
{
res = JsonSerializer.Deserialize<QuickReplyMessage>(jsonText, options);
}
else if (richType == RichTypeEnum.CouponTemplate)
{
res = JsonSerializer.Deserialize<CouponTemplateMessage>(jsonText, options);
}
else if (richType == RichTypeEnum.Text)
{
res = JsonSerializer.Deserialize<TextMessage>(jsonText, options);
}
else if (richType == RichTypeEnum.GenericTemplate)
{
var elementType = element.GetString();
if (elementType == typeof(GenericElement).Name)
if (root.TryGetProperty("element_type", out element))
{
res = JsonSerializer.Deserialize<GenericTemplateMessage<GenericElement>>(jsonText, options);
var elementType = element.GetString();
if (elementType == typeof(GenericElement).Name)
{
res = JsonSerializer.Deserialize<GenericTemplateMessage<GenericElement>>(jsonText, options);
}
else if (elementType == typeof(ButtonElement).Name)
{
res = JsonSerializer.Deserialize<GenericTemplateMessage<ButtonElement>>(jsonText, options);
}
}
}
}

return res;
}

public ITemplateMessage? ParseTemplateMessage(string templateType, string jsonText, JsonElement root, JsonSerializerOptions options)
public static ITemplateMessage? ParseTemplateMessage(JsonElement root, JsonSerializerOptions options)
{
ITemplateMessage? res = null;
JsonElement element;
var jsonText = root.GetRawText();

if (templateType == TemplateTypeEnum.Button)
{
res = JsonSerializer.Deserialize<ButtonTemplateMessage>(jsonText, options);
}
else if (templateType == TemplateTypeEnum.MultiSelect)
if (root.TryGetProperty("template_type", out element))
{
res = JsonSerializer.Deserialize<MultiSelectTemplateMessage>(jsonText, options);
}
else if (templateType == TemplateTypeEnum.Coupon)
{
res = JsonSerializer.Deserialize<CouponTemplateMessage>(jsonText, options);
}
else if (templateType == TemplateTypeEnum.Product)
{
res = JsonSerializer.Deserialize<ProductTemplateMessage>(jsonText, options);
}
else if (templateType == TemplateTypeEnum.Generic)
{
if (root.TryGetProperty("element_type", out var element))
var templateType = element.GetString();
if (templateType == TemplateTypeEnum.Button)
{
res = JsonSerializer.Deserialize<ButtonTemplateMessage>(jsonText, options);
}
else if (templateType == TemplateTypeEnum.MultiSelect)
{
res = JsonSerializer.Deserialize<MultiSelectTemplateMessage>(jsonText, options);
}
else if (templateType == TemplateTypeEnum.Coupon)
{
res = JsonSerializer.Deserialize<CouponTemplateMessage>(jsonText, options);
}
else if (templateType == TemplateTypeEnum.Product)
{
res = JsonSerializer.Deserialize<ProductTemplateMessage>(jsonText, options);
}
else if (templateType == TemplateTypeEnum.Generic)
{
var elementType = element.GetString();
if (elementType == typeof(GenericElement).Name)
if (root.TryGetProperty("element_type", out element))
{
res = JsonSerializer.Deserialize<GenericTemplateMessage<GenericElement>>(jsonText, options);
var elementType = element.GetString();
if (elementType == typeof(GenericElement).Name)
{
res = JsonSerializer.Deserialize<GenericTemplateMessage<GenericElement>>(jsonText, options);
}
else if (elementType == typeof(ButtonElement).Name)
{
res = JsonSerializer.Deserialize<GenericTemplateMessage<ButtonElement>>(jsonText, options);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using BotSharp.Abstraction.Messaging.JsonConverters;
using System.Text.Json;

namespace BotSharp.Abstraction.Options;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public class RoutingRule
/// <summary>
/// Field type: string, number, object
/// </summary>
[JsonPropertyName("field_type")]
public string FieldType { get; set; } = "string";

public bool Required { get; set; }
Expand Down
6 changes: 5 additions & 1 deletion src/Infrastructure/BotSharp.Abstraction/Using.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@
global using BotSharp.Abstraction.Utilities;
global using BotSharp.Abstraction.Conversations.Models;
global using BotSharp.Abstraction.Agents.Enums;
global using BotSharp.Abstraction.Models;
global using BotSharp.Abstraction.Infrastructures.Enums;
global using BotSharp.Abstraction.Models;
global using BotSharp.Abstraction.Routing.Models;
global using BotSharp.Abstraction.Routing.Planning;
global using BotSharp.Abstraction.Templating;
Loading