From 1a54f174404404ff9f35e2d0127413031771724b Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Fri, 13 Oct 2023 15:08:59 -0500 Subject: [PATCH] Auto test. --- BotSharp.sln | 13 +++- .../Routing/Models/RoutingArgs.cs | 8 +- .../BotSharp.Core/Evaluatings/Evaluater.cs | 9 +++ .../Handlers/ConversationEndRoutingHandler.cs | 18 ++--- .../Handlers/ResponseToUserRoutingHandler.cs | 8 +- .../Handlers/RouteToAgentRoutingHandler.cs | 5 +- .../RoutingService.GetNextInstruction.cs | 3 +- .../Controllers/InstructModeController.cs | 8 ++ .../Providers/TextCompletionProvider.cs | 4 +- src/WebStarter/WebStarter.csproj | 4 + .../instruction.liquid | 7 +- .../agent.json | 8 +- .../agent.json | 2 +- .../functions.json | 2 +- .../instruction.liquid | 4 +- .../responses/func.get_pizza_price.0.liquid | 11 ++- .../agent.json | 2 +- .../functions.json | 2 +- .../Functions/GetPizzaPricesFn.cs | 5 +- .../Functions/PlaceOrderFn.cs | 10 +++ .../BotSharp.TestingConsole.csproj | 19 +++++ .../IBotSharpOpenAPI.cs | 17 +++++ tests/BotSharp.TestingConsole/Program.cs | 74 +++++++++++++++++++ 23 files changed, 195 insertions(+), 48 deletions(-) create mode 100644 src/Infrastructure/BotSharp.Core/Evaluatings/Evaluater.cs create mode 100644 tests/BotSharp.TestingConsole/BotSharp.TestingConsole.csproj create mode 100644 tests/BotSharp.TestingConsole/IBotSharpOpenAPI.cs create mode 100644 tests/BotSharp.TestingConsole/Program.cs diff --git a/BotSharp.sln b/BotSharp.sln index 135e7de3..6313d06a 100644 --- a/BotSharp.sln +++ b/BotSharp.sln @@ -61,7 +61,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DataStorages", "DataStorage EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Plugin.MongoStorage", "src\Plugins\BotSharp.Plugin.MongoStorage\BotSharp.Plugin.MongoStorage.csproj", "{DB3DE37B-1208-4ED3-9615-A52AD0AAD69C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Plugin.GoogleAI", "src\Plugins\BotSharp.Plugin.GoogleAI\BotSharp.Plugin.GoogleAI.csproj", "{8BC29F8A-78D6-422C-B522-10687ADC38ED}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Plugin.GoogleAI", "src\Plugins\BotSharp.Plugin.GoogleAI\BotSharp.Plugin.GoogleAI.csproj", "{8BC29F8A-78D6-422C-B522-10687ADC38ED}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.TestingConsole", "tests\BotSharp.TestingConsole\BotSharp.TestingConsole.csproj", "{5E7EC98F-4A22-4D62-8FF6-746C497CF955}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -223,6 +225,14 @@ Global {8BC29F8A-78D6-422C-B522-10687ADC38ED}.Release|Any CPU.Build.0 = Release|Any CPU {8BC29F8A-78D6-422C-B522-10687ADC38ED}.Release|x64.ActiveCfg = Release|Any CPU {8BC29F8A-78D6-422C-B522-10687ADC38ED}.Release|x64.Build.0 = Release|Any CPU + {5E7EC98F-4A22-4D62-8FF6-746C497CF955}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5E7EC98F-4A22-4D62-8FF6-746C497CF955}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5E7EC98F-4A22-4D62-8FF6-746C497CF955}.Debug|x64.ActiveCfg = Debug|Any CPU + {5E7EC98F-4A22-4D62-8FF6-746C497CF955}.Debug|x64.Build.0 = Debug|Any CPU + {5E7EC98F-4A22-4D62-8FF6-746C497CF955}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5E7EC98F-4A22-4D62-8FF6-746C497CF955}.Release|Any CPU.Build.0 = Release|Any CPU + {5E7EC98F-4A22-4D62-8FF6-746C497CF955}.Release|x64.ActiveCfg = Release|Any CPU + {5E7EC98F-4A22-4D62-8FF6-746C497CF955}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -254,6 +264,7 @@ Global {5CD330E1-9E5A-4112-8346-6E31CA98EF78} = {2635EC9B-2E5F-4313-AC21-0B847F31F36C} {DB3DE37B-1208-4ED3-9615-A52AD0AAD69C} = {5CD330E1-9E5A-4112-8346-6E31CA98EF78} {8BC29F8A-78D6-422C-B522-10687ADC38ED} = {D5293208-2BEF-42FC-A64C-5954F61720BA} + {5E7EC98F-4A22-4D62-8FF6-746C497CF955} = {32FAFFFE-A4CB-4FEE-BF7C-84518BBC6DCC} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {A9969D89-C98B-40A5-A12B-FC87E55B3A19} diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs index 3499b6e9..0dfa5118 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs @@ -3,19 +3,19 @@ namespace BotSharp.Abstraction.Routing.Models; public class RoutingArgs { [JsonPropertyName("function")] - public string Function { get; set; } = string.Empty; + public string Function { get; set; } [JsonPropertyName("reason")] public string Reason { get; set; } = "the reason why you select this function or agent"; [JsonPropertyName("answer")] - public string Answer { get; set; } = string.Empty; + public string Answer { get; set; } = "the content of response to user"; [JsonPropertyName("next_action_agent")] - public string AgentName { get; set; } = "agent for next action based on user's latest response"; + public string AgentName { get; set; } = "agent for next action based on user latest response"; [JsonPropertyName("user_goal_agent")] - public string OriginalAgent { get; set; } = "agent who can achieve user's original goal"; + public string OriginalAgent { get; set; } = "agent who can achieve user original goal"; public override string ToString() { diff --git a/src/Infrastructure/BotSharp.Core/Evaluatings/Evaluater.cs b/src/Infrastructure/BotSharp.Core/Evaluatings/Evaluater.cs new file mode 100644 index 00000000..ebb4b5d2 --- /dev/null +++ b/src/Infrastructure/BotSharp.Core/Evaluatings/Evaluater.cs @@ -0,0 +1,9 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace BotSharp.Core.Evaluatings; + +public class Evaluater +{ +} diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ConversationEndRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ConversationEndRoutingHandler.cs index d3ad6bca..0ce49cd6 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ConversationEndRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ConversationEndRoutingHandler.cs @@ -1,5 +1,4 @@ using BotSharp.Abstraction.Functions.Models; -using BotSharp.Abstraction.Models; using BotSharp.Abstraction.Routing; using BotSharp.Abstraction.Routing.Settings; @@ -9,12 +8,7 @@ public class ConversationEndRoutingHandler : RoutingHandlerBase, IRoutingHandler { public string Name => "conversation_end"; - public string Description => "Call this function when user wants to end this conversation or all tasks have been completed."; - - public List Parameters => new List - { - new NameDesc("reason", "why this conversation is end") - }; + public string Description => "User wants to end the conversation."; public bool IsReasoning => false; @@ -23,8 +17,14 @@ public class ConversationEndRoutingHandler : RoutingHandlerBase, IRoutingHandler { } - public Task Handle(IRoutingService routing, FunctionCallFromLlm inst) + public async Task Handle(IRoutingService routing, FunctionCallFromLlm inst) { - throw new NotImplementedException(); + var result = new RoleDialogModel(AgentRole.Assistant, inst.Answer) + { + CurrentAgentId = _settings.RouterId, + FunctionName = inst.Function, + StopCompletion = true + }; + return result; } } diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ResponseToUserRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ResponseToUserRoutingHandler.cs index d2dd1809..4e021616 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ResponseToUserRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ResponseToUserRoutingHandler.cs @@ -9,13 +9,7 @@ public class ResponseToUserRoutingHandler : RoutingHandlerBase, IRoutingHandler { public string Name => "response_to_user"; - public string Description => "You know how to response according to the context without asking specific agent. For example user greeting."; - - public List Parameters => new List - { - new NameDesc("answer", "the content of response"), - new NameDesc("reason", "why response to user") - }; + public string Description => "You know how to response according to the context without asking specific agent."; public bool IsReasoning => false; diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs index cca712bc..d80dc143 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs @@ -15,10 +15,7 @@ public class RouteToAgentRoutingHandler : RoutingHandlerBase, IRoutingHandler public List Parameters => new List { - new NameDesc("next_action_agent", "the name of the next action's agent"), - new NameDesc("user_goal_agent", "the agent who can achieve user's original goal"), - new NameDesc("reason", "the reason why you select this function or agent"), - new NameDesc("args", "the agent required parameters") + new NameDesc("args", "useful parameters of next action agent") }; public bool IsReasoning => false; diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.GetNextInstruction.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.GetNextInstruction.cs index 1cf9b1d1..3a0d623a 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.GetNextInstruction.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.GetNextInstruction.cs @@ -16,7 +16,8 @@ public partial class RoutingService { Function = "route_to_agent" }); - var content = $"{prompt} Response must be in JSON format {responseFormat}"; + var content = $"{prompt} Response must be in JSON format {responseFormat}."; + content += " Set function as conversation_end with courtesy greeting if user is willing to end conversation"; var state = _services.GetRequiredService(); diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/InstructModeController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/InstructModeController.cs index d29fc4f2..d0f278bd 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/InstructModeController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/InstructModeController.cs @@ -4,6 +4,7 @@ using BotSharp.Abstraction.ApiAdapters; using BotSharp.Abstraction.Conversations.Models; using BotSharp.Abstraction.Instructs; using BotSharp.Abstraction.Instructs.Models; +using BotSharp.Core.Infrastructures; using BotSharp.OpenAPI.ViewModels.Instructs; namespace BotSharp.OpenAPI.Controllers; @@ -45,4 +46,11 @@ public class InstructModeController : ControllerBase, IApiAdapter fn => Task.CompletedTask, fn => Task.CompletedTask); } + + [HttpPost("/instruct/text-completion")] + public async Task TextCompletion([FromBody] IncomingMessageModel message) + { + var textCompletion = CompletionProvider.GetTextCompletion(_services); + return await textCompletion.GetCompletion(message.Text); + } } diff --git a/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/TextCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/TextCompletionProvider.cs index a6b037ce..9b74ce6e 100644 --- a/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/TextCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/TextCompletionProvider.cs @@ -7,6 +7,7 @@ using Microsoft.Extensions.Logging; using BotSharp.Abstraction.Conversations; using Microsoft.Extensions.DependencyInjection; using BotSharp.Abstraction.Conversations.Models; +using BotSharp.Abstraction.Agents.Enums; namespace BotSharp.Plugin.AzureOpenAI.Providers; @@ -40,8 +41,9 @@ public class TextCompletionProvider : ITextCompletion { text }, - MaxTokens = 256 + MaxTokens = 256, }; + completionsOptions.StopSequences.Add($"{AgentRole.Assistant}:"); var state = _services.GetRequiredService(); var temperature = float.Parse(state.GetState("temperature", "0.5")); diff --git a/src/WebStarter/WebStarter.csproj b/src/WebStarter/WebStarter.csproj index ba130a66..a26eb994 100644 --- a/src/WebStarter/WebStarter.csproj +++ b/src/WebStarter/WebStarter.csproj @@ -29,6 +29,8 @@ + + @@ -36,6 +38,8 @@ + + diff --git a/src/WebStarter/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/instruction.liquid b/src/WebStarter/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/instruction.liquid index 3dbcde84..9f9f8770 100644 --- a/src/WebStarter/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/instruction.liquid +++ b/src/WebStarter/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/instruction.liquid @@ -1,15 +1,14 @@ -You're {{router.name}} ({{router.description}}). Follow these steps to handle user's request: +You're {{router.name}} ({{router.description}}). Follow these steps to handle user request: 1. Read the CONVERSATION context. 2. Select a appropriate function from FUNCTIONS. -3. Determine which agent is suitable according to conversation context. +3. Determine which agent is suitable according to CONVERSATION context. 4. Re-think about selected function is from FUNCTIONS to handle the request. -5. Make sure agent is not in args. FUNCTIONS {% for handler in routing_handlers %} # {{ handler.name }} {{ handler.description}} -{% if handler.parameters -%} +{% if handler.parameters and handler.parameters != empty -%} Parameters: {% for p in handler.parameters -%} {{ p.name }}: {{ p.description }}{{ "\r\n " }} diff --git a/src/WebStarter/data/agents/b284db86-e9c2-4c25-a59e-4649797dd130/agent.json b/src/WebStarter/data/agents/b284db86-e9c2-4c25-a59e-4649797dd130/agent.json index b4ca558f..b9f4ca9c 100644 --- a/src/WebStarter/data/agents/b284db86-e9c2-4c25-a59e-4649797dd130/agent.json +++ b/src/WebStarter/data/agents/b284db86-e9c2-4c25-a59e-4649797dd130/agent.json @@ -4,11 +4,5 @@ "createdDateTime": "2023-08-18T14:39:32.2349685Z", "updatedDateTime": "2023-08-18T14:39:32.2349686Z", "id": "b284db86-e9c2-4c25-a59e-4649797dd130", - "allowRouting": true, - "routingRules": [ - { - "field": "order_number", - "required": true - } - ] + "allowRouting": true } \ No newline at end of file diff --git a/src/WebStarter/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/agent.json b/src/WebStarter/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/agent.json index ade357d0..a96cbf40 100644 --- a/src/WebStarter/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/agent.json +++ b/src/WebStarter/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/agent.json @@ -1,6 +1,6 @@ { "name": "Ordering", - "description": "Place new pizza order", + "description": "Provide types of pizza available, unit price and total cost. Place the order and returned the order number.", "createdDateTime": "2023-07-26T02:29:25.123224Z", "updatedDateTime": "2023-07-26T02:29:25.123274Z", "id": "c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd", diff --git a/src/WebStarter/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/functions.json b/src/WebStarter/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/functions.json index 2315c87a..140aec8a 100644 --- a/src/WebStarter/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/functions.json +++ b/src/WebStarter/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/functions.json @@ -19,7 +19,7 @@ }, { "name": "get_pizza_types", - "description": "get all pizza types.", + "description": "get all pizza types", "parameters": { "type": "object", "properties": {}, diff --git a/src/WebStarter/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/instruction.liquid b/src/WebStarter/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/instruction.liquid index eacd4dc1..19250653 100644 --- a/src/WebStarter/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/instruction.liquid +++ b/src/WebStarter/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/instruction.liquid @@ -1,10 +1,10 @@ You are now a Pizza Ordering agent, and you can help customers order a pizza according to the user's preferences. Follow below step to place order: -1: Ask user preferences. +1: Ask user preferences, call function get_pizza_types to provide the variety of pizza options. 2: Confirm with user the pizza type and quantity. 3: Call function place_an_order to purchase. -4: Proceed to make payment for this order. +4: Ask user how to pay for this order. Use below information to help ordering process: * Today is {{current_date}}, the time now is {{current_time}}, day of week is {{current_weekday}}. \ No newline at end of file diff --git a/src/WebStarter/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/responses/func.get_pizza_price.0.liquid b/src/WebStarter/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/responses/func.get_pizza_price.0.liquid index 2aa8f2bd..dec5c66b 100644 --- a/src/WebStarter/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/responses/func.get_pizza_price.0.liquid +++ b/src/WebStarter/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/responses/func.get_pizza_price.0.liquid @@ -1,5 +1,12 @@ -{% if pizza_type == "cheese" -%} - The price for a slice of cheese pizza is {{ cheese_unit_price }}. Would you like to proceed the order? +{% assign pizza_type = pizza_type | downcase %} +{% if pizza_type contains "cheese" -%} + The price for a slice of {{pizza_type}} pizza is {{ cheese_unit_price }}. Would you like to proceed the order? +{%- elsif pizza_type contains "pepperoni" -%} + The price for a slice of {{pizza_type}} pizza is {{ pepperoni_unit_price }}. Would you like to proceed the order? +{%- elsif pizza_type contains "margherita" -%} + The price for a slice of {{pizza_type}} pizza is {{ margherita_unit_price }}. Would you like to proceed the order? +{%- else -%} + We don't have {{pizza_type}} pizza, would you like something else? {%- endif %} {% if quantity == nil -%} How many slices would you like to order? diff --git a/src/WebStarter/data/agents/fe8c60aa-b114-4ef3-93cb-a8efeac80f75/agent.json b/src/WebStarter/data/agents/fe8c60aa-b114-4ef3-93cb-a8efeac80f75/agent.json index 72959d11..a69b758e 100644 --- a/src/WebStarter/data/agents/fe8c60aa-b114-4ef3-93cb-a8efeac80f75/agent.json +++ b/src/WebStarter/data/agents/fe8c60aa-b114-4ef3-93cb-a8efeac80f75/agent.json @@ -1,6 +1,6 @@ { "name": "Payment", - "description": "Make payment when user placed new order and system returned the order number.", + "description": "Make payment when user wants to pay for the order", "createdDateTime": "2023-07-26T02:29:25.123224Z", "updatedDateTime": "2023-07-26T02:29:25.123274Z", "id": "fe8c60aa-b114-4ef3-93cb-a8efeac80f75", diff --git a/src/WebStarter/data/agents/fe8c60aa-b114-4ef3-93cb-a8efeac80f75/functions.json b/src/WebStarter/data/agents/fe8c60aa-b114-4ef3-93cb-a8efeac80f75/functions.json index b9219dfe..13ed0ebd 100644 --- a/src/WebStarter/data/agents/fe8c60aa-b114-4ef3-93cb-a8efeac80f75/functions.json +++ b/src/WebStarter/data/agents/fe8c60aa-b114-4ef3-93cb-a8efeac80f75/functions.json @@ -1,7 +1,7 @@ [ { "name": "make_payment", - "description": "call this function to make payment after system returned the order number", + "description": "call this function to make payment", "parameters": { "type": "object", "properties": { diff --git a/tests/BotSharp.Plugin.PizzaBot/Functions/GetPizzaPricesFn.cs b/tests/BotSharp.Plugin.PizzaBot/Functions/GetPizzaPricesFn.cs index 86de63c8..071f9654 100644 --- a/tests/BotSharp.Plugin.PizzaBot/Functions/GetPizzaPricesFn.cs +++ b/tests/BotSharp.Plugin.PizzaBot/Functions/GetPizzaPricesFn.cs @@ -10,9 +10,10 @@ public class GetPizzaPricesFn : IFunctionCallback { message.ExecutionData = new { - cheese_unit_price = "$3.5" + pepperoni_unit_price = "$3.2", + cheese_unit_price = "$3.5", + margherita_unit_price = "$3.8", }; - message.ExecutionResult = "Pepperoni Pizza: $3.5/slice, Cheese Pizza: $2.5/slice, Margherita Pizza: $3.0/slice"; return true; } } diff --git a/tests/BotSharp.Plugin.PizzaBot/Functions/PlaceOrderFn.cs b/tests/BotSharp.Plugin.PizzaBot/Functions/PlaceOrderFn.cs index bc398dbd..b6faf05f 100644 --- a/tests/BotSharp.Plugin.PizzaBot/Functions/PlaceOrderFn.cs +++ b/tests/BotSharp.Plugin.PizzaBot/Functions/PlaceOrderFn.cs @@ -1,3 +1,4 @@ +using BotSharp.Abstraction.Conversations; using BotSharp.Abstraction.Conversations.Models; namespace BotSharp.Plugin.PizzaBot.Functions; @@ -6,9 +7,18 @@ public class PlaceOrderFn : IFunctionCallback { public string Name => "place_an_order"; + private readonly IServiceProvider _service; + public PlaceOrderFn(IServiceProvider service) + { + _service = service; + } + public async Task Execute(RoleDialogModel message) { message.ExecutionResult = "The order number is P123-01"; + var state = _service.GetRequiredService(); + state.SetState("order_number", "P123-01"); + return true; } } diff --git a/tests/BotSharp.TestingConsole/BotSharp.TestingConsole.csproj b/tests/BotSharp.TestingConsole/BotSharp.TestingConsole.csproj new file mode 100644 index 00000000..0bec8ecb --- /dev/null +++ b/tests/BotSharp.TestingConsole/BotSharp.TestingConsole.csproj @@ -0,0 +1,19 @@ + + + + Exe + net6.0 + enable + enable + + + + + + + + + + + + diff --git a/tests/BotSharp.TestingConsole/IBotSharpOpenAPI.cs b/tests/BotSharp.TestingConsole/IBotSharpOpenAPI.cs new file mode 100644 index 00000000..6844099f --- /dev/null +++ b/tests/BotSharp.TestingConsole/IBotSharpOpenAPI.cs @@ -0,0 +1,17 @@ +using BotSharp.Abstraction.Conversations.Models; +using BotSharp.OpenAPI.ViewModels.Conversations; +using Refit; + +namespace BotSharp.TestingConsole; + +public interface IBotSharpOpenAPI +{ + [Post("/conversation/{agentId}")] + Task NewConversation([Header("Authorization")] string authorization, string agentId); + + [Post("/conversation/{agentId}/{conversationId}")] + Task SendMessage([Header("Authorization")] string authorization, string agentId, string conversationId, [Body] NewMessageModel input); + + [Post("/instruct/text-completion")] + Task TextCompletion([Header("Authorization")] string authorization, [Body] IncomingMessageModel message); +} diff --git a/tests/BotSharp.TestingConsole/Program.cs b/tests/BotSharp.TestingConsole/Program.cs new file mode 100644 index 00000000..675198fd --- /dev/null +++ b/tests/BotSharp.TestingConsole/Program.cs @@ -0,0 +1,74 @@ +// See https://aka.ms/new-console-template for more information +using BotSharp.Abstraction.Agents.Enums; +using BotSharp.Abstraction.Conversations.Models; +using BotSharp.OpenAPI.ViewModels.Conversations; +using BotSharp.TestingConsole; +using Refit; +using System.Drawing; +using Console = Colorful.Console; + +var token = "Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiI0NTZlMzVjNS1jYWYwLTRkNDUtOTA4NC1iNDRhOGNhNzE3ZTQiLCJlbWFpbCI6ImJvdHNoYXJwQGdtYWlsLmNvbSIsImdpdmVuX25hbWUiOiJIYWlwaW5nIiwiZmFtaWx5X25hbWUiOiJDaGVuIiwianRpIjoiMTQ3MDkwMDQtNDM1Ny00NTFkLWExM2MtY2U1NDk5NWM0ZTJlIiwibmJmIjoxNjk3MTY0MzA4LCJleHAiOjE2OTcxNjQ2MDgsImlhdCI6MTY5NzE2NDMwOCwiaXNzIjoiYm90c2hhcnAiLCJhdWQiOiJib3RzaGFycCJ9.1UgOj5esNInTPiiy-_gLmcT2x8NtFswCUyePVHXa-4EeLCkA43nx0LOXPlzb_rmvUIg9bJSRZXbH2aBqtmiDYg"; +var agentId = "01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a"; + +// New conversation +var botsharp = RestService.For("http://localhost:5500"); +var conv = await botsharp.NewConversation(token, agentId); + +var instruction = @"You're a customer who is going to buy a pizza. + +Below are your requirments: +* You want to know what kind of pizza do they have. +* You want to buy three piece of pizza. +* Say Bye if the order is placed and payment is completed. + +Below are your profile: +* You like pepperoni flavor. +* You will pay the order in cash. +* Your address is 347 S Gladstone Ave, Aurora, IL 60506. +* Your phone number is +16308926431"; + +Action PrintDialog = message => +{ + Console.Write($"[{DateTime.Now:HH:mm:ss}] {message.Role}:\t"); + if (message.Role == AgentRole.User) + { + Console.WriteLine(message.Content); + } + else + { + Console.WriteLine(message.Content, Color.Yellow); + } +}; + +var dialogs = new List(); +dialogs.Add(new RoleDialogModel(AgentRole.User, "Good morning!")); +PrintDialog(dialogs.Last()); +dialogs.Add(new RoleDialogModel(AgentRole.Assistant, "Hi, How can I help you today?")); +PrintDialog(dialogs.Last()); + +var response = new MessageResponseModel(); + +while (response.Function != "conversation_end") +{ + var text = string.Join("\r\n", dialogs.Select(x => $"{x.Role}: {x.Content}")); + text = instruction + $"\r\n###\r\n{text}\r\n{AgentRole.User}: "; + var question = await botsharp.TextCompletion(token, new IncomingMessageModel + { + Text = text + }); + + dialogs.Add(new RoleDialogModel(AgentRole.User, question)); + PrintDialog(dialogs.Last()); + + response = await botsharp.SendMessage(token, agentId, conv.Id, new NewMessageModel + { + Text = question + }); + + dialogs.Add(new RoleDialogModel(AgentRole.Assistant, response.Text.Trim())); + PrintDialog(dialogs.Last()); +} + +Console.WriteLine(); +Console.WriteLine("Conversation End", Color.Green); +Console.ReadLine(); \ No newline at end of file