diff --git a/morpheus/_lib/include/morpheus/llm/llm_context.hpp b/morpheus/_lib/include/morpheus/llm/llm_context.hpp index 1b113dad81..26aeaf4b61 100644 --- a/morpheus/_lib/include/morpheus/llm/llm_context.hpp +++ b/morpheus/_lib/include/morpheus/llm/llm_context.hpp @@ -124,7 +124,7 @@ class MORPHEUS_EXPORT LLMContext : public std::enable_shared_from_this(msg_config); + + llm::LLMContext ctx{llm::LLMTask{}, msg}; + ASSERT_EQ(ctx.message()->has_task("llm_engine"), true); +} + +TEST_F(TestLLMContext, InitWithLLMTaskAndControlMessageTask) +{ + nlohmann::json task_dict; + task_dict = { + {"task_type", "dictionary"}, + {"model_name", "test"}, + }; + + nlohmann::json msg_config; + msg_config["tasks"] = {{{"type", "llm_engine"}, {"properties", {{"type", "template"}, {"properties", task_dict}}}}}; + + auto msg = std::make_shared(msg_config); + + llm::LLMContext ctx{llm::LLMTask{"template", task_dict}, msg}; + ASSERT_EQ(ctx.message()->has_task("llm_engine"), true); + ASSERT_EQ(ctx.task().get("task_type"), "dictionary"); + ASSERT_EQ(ctx.task().get("model_name"), "test"); +} + +TEST_F(TestLLMContext, InitWithParentContext) +{ + nlohmann::json task_dict; + task_dict = { + {"task_type", "dictionary"}, + {"model_name", "test"}, + }; + + nlohmann::json msg_config; + msg_config["tasks"] = {{{"type", "llm_engine"}, {"properties", {{"type", "template"}, {"properties", task_dict}}}}}; + + auto msg = std::make_shared(msg_config); + + auto parent_ctx = std::make_shared(llm::LLMTask{"template", task_dict}, msg); + auto inputs = llm::input_mappings_t{{"/ext1", "input1"}}; + llm::LLMContext ctx{parent_ctx, "child", inputs}; + ASSERT_EQ(ctx.input_map()[0].external_name, "/ext1"); + ASSERT_EQ(ctx.input_map()[0].internal_name, "input1"); + ASSERT_EQ(ctx.parent()->message()->has_task("llm_engine"), true); + ASSERT_EQ(ctx.parent()->task().get("task_type"), "dictionary"); + ASSERT_EQ(ctx.parent()->task().get("model_name"), "test"); + ASSERT_EQ(ctx.name(), "child"); + ASSERT_EQ(ctx.full_name(), "/child"); +} + TEST_F(TestLLMContext, SetOutput) { - llm::LLMContext ctx_1{llm::LLMTask{}, nullptr}; + llm::LLMContext ctx{llm::LLMTask{}, nullptr}; nlohmann::json outputs; outputs = {{"key1", "val1"}, {"key2", "val2"}}; - ctx_1.set_output(outputs); + ctx.set_output(outputs); + + ASSERT_EQ(ctx.all_outputs().size(), 2); + ASSERT_EQ(ctx.all_outputs()["key1"], "val1"); + ASSERT_EQ(ctx.all_outputs()["key2"], "val2"); +} - ASSERT_EQ(ctx_1.all_outputs()["key1"], "val1"); - ASSERT_EQ(ctx_1.all_outputs()["key2"], "val2"); +TEST_F(TestLLMContext, SetOutputDict) +{ + llm::LLMContext ctx{llm::LLMTask{}, nullptr}; + nlohmann::json outputs; + outputs = {{"key1", "val1"}, {"key2", "val2"}}; - llm::LLMContext ctx_2{llm::LLMTask{}, nullptr}; - ctx_2.set_output("output", outputs); - ASSERT_EQ(ctx_2.all_outputs()["output"]["key1"], "val1"); - ASSERT_EQ(ctx_2.all_outputs()["output"]["key2"], "val2"); + ctx.set_output("output", outputs); + ASSERT_EQ(ctx.all_outputs()["output"]["key1"], "val1"); + ASSERT_EQ(ctx.all_outputs()["output"]["key2"], "val2"); } TEST_F(TestLLMContext, PushPop) @@ -188,51 +269,76 @@ TEST_F(TestLLMContext, PopSelectMultipleOutputs) ASSERT_EQ(child_ctx->parent()->all_outputs()["child"]["key3"], "val3"); } -TEST_F(TestLLMContext, SingleInputMapping) +TEST_F(TestLLMContext, SingleInputMappingValid) { auto parent_ctx = std::make_shared(llm::LLMTask{}, nullptr); nlohmann::json outputs; outputs = {{"parent_out", "val1"}}; parent_ctx->set_output(outputs); - auto inputs_1 = llm::input_mappings_t{{"/parent_out", "input1"}}; - llm::LLMContext child_ctx_1{parent_ctx, "child", inputs_1}; - ASSERT_EQ(child_ctx_1.get_input(), "val1"); - ASSERT_EQ(child_ctx_1.get_input("input1"), "val1"); - ASSERT_EQ(child_ctx_1.get_inputs()["input1"], "val1"); - ASSERT_THROW(child_ctx_1.get_input("input2"), std::runtime_error); - - auto inputs_2 = llm::input_mappings_t{{"/invalid", "input1"}}; - llm::LLMContext child_ctx_2{parent_ctx, "child", inputs_2}; - ASSERT_THROW(child_ctx_2.get_input(), std::runtime_error); - ASSERT_THROW(child_ctx_2.get_input("input1"), std::runtime_error); - ASSERT_THROW(child_ctx_2.get_inputs()["input1"], std::runtime_error); + auto inputs = llm::input_mappings_t{{"/parent_out", "input1"}}; + llm::LLMContext child_ctx{parent_ctx, "child", inputs}; + ASSERT_EQ(child_ctx.get_input(), "val1"); + ASSERT_EQ(child_ctx.get_input("input1"), "val1"); + ASSERT_EQ(child_ctx.get_inputs()["input1"], "val1"); + ASSERT_THROW(child_ctx.get_input("input2"), std::runtime_error); } -TEST_F(TestLLMContext, MultipleInputMappings) +TEST_F(TestLLMContext, SingleInputMappingInvalid) +{ + auto parent_ctx = std::make_shared(llm::LLMTask{}, nullptr); + nlohmann::json outputs; + outputs = {{"parent_out", "val1"}}; + parent_ctx->set_output(outputs); + + auto inputs = llm::input_mappings_t{{"/invalid", "input1"}}; + llm::LLMContext child_ctx{parent_ctx, "child", inputs}; + ASSERT_THROW(child_ctx.get_input(), std::runtime_error); + ASSERT_THROW(child_ctx.get_input("input1"), std::runtime_error); + ASSERT_THROW(child_ctx.get_inputs()["input1"], std::runtime_error); +} + +TEST_F(TestLLMContext, MultipleInputMappingsValid) { auto parent_ctx = std::make_shared(llm::LLMTask{}, nullptr); nlohmann::json outputs; outputs = {{"parent_out1", "val1"}, {"parent_out2", "val2"}}; parent_ctx->set_output(outputs); - auto inputs_1 = llm::input_mappings_t{{"/parent_out1", "input1"}, {"/parent_out2", "input2"}}; - llm::LLMContext child_ctx_1{parent_ctx, "child", inputs_1}; - ASSERT_EQ(child_ctx_1.get_input("input1"), "val1"); - ASSERT_EQ(child_ctx_1.get_input("input2"), "val2"); - ASSERT_EQ(child_ctx_1.get_inputs()["input1"], "val1"); - ASSERT_EQ(child_ctx_1.get_inputs()["input2"], "val2"); - ASSERT_THROW(child_ctx_1.get_input(), std::runtime_error); - ASSERT_THROW(child_ctx_1.get_input("input3"), std::runtime_error); - - auto inputs_2 = llm::input_mappings_t{{"/invalid", "input1"}}; - llm::LLMContext child_ctx_2{parent_ctx, "child", inputs_2}; - ASSERT_THROW(child_ctx_2.get_input(), std::runtime_error); - ASSERT_THROW(child_ctx_2.get_input("input1"), std::runtime_error); - ASSERT_THROW(child_ctx_2.get_inputs()["input1"], std::runtime_error); - - auto inputs_3 = llm::input_mappings_t{{"/parent_out1", "input1"}, {"/invalid", "input2"}}; - llm::LLMContext child_ctx_3{parent_ctx, "child", inputs_2}; - ASSERT_EQ(child_ctx_1.get_input("input1"), "val1"); - ASSERT_THROW(child_ctx_2.get_input("input2"), std::runtime_error); + auto inputs = llm::input_mappings_t{{"/parent_out1", "input1"}, {"/parent_out2", "input2"}}; + llm::LLMContext child_ctx{parent_ctx, "child", inputs}; + ASSERT_EQ(child_ctx.get_input("input1"), "val1"); + ASSERT_EQ(child_ctx.get_input("input2"), "val2"); + ASSERT_EQ(child_ctx.get_inputs()["input1"], "val1"); + ASSERT_EQ(child_ctx.get_inputs()["input2"], "val2"); + ASSERT_THROW(child_ctx.get_input(), std::runtime_error); + ASSERT_THROW(child_ctx.get_input("input3"), std::runtime_error); } + +TEST_F(TestLLMContext, MultipleInputMappingsSingleInvalid) +{ + auto parent_ctx = std::make_shared(llm::LLMTask{}, nullptr); + nlohmann::json outputs; + outputs = {{"parent_out1", "val1"}, {"parent_out2", "val2"}}; + parent_ctx->set_output(outputs); + + auto inputs = llm::input_mappings_t{{"/parent_out1", "input1"}, {"/invalid", "input2"}}; + llm::LLMContext child_ctx{parent_ctx, "child", inputs}; + ASSERT_EQ(child_ctx.get_input("input1"), "val1"); + ASSERT_THROW(child_ctx.get_input("input2"), std::runtime_error); + ASSERT_THROW(child_ctx.get_inputs(), std::runtime_error); +} + +TEST_F(TestLLMContext, MultipleInputMappingsBothInvalid) +{ + auto parent_ctx = std::make_shared(llm::LLMTask{}, nullptr); + nlohmann::json outputs; + outputs = {{"parent_out1", "val1"}, {"parent_out2", "val2"}}; + parent_ctx->set_output(outputs); + + auto inputs = llm::input_mappings_t{{"/invalid1", "input1"}, {"/invalid2", "input2"}}; + llm::LLMContext child_ctx{parent_ctx, "child", inputs}; + ASSERT_THROW(child_ctx.get_input("input1"), std::runtime_error); + ASSERT_THROW(child_ctx.get_input("input2"), std::runtime_error); + ASSERT_THROW(child_ctx.get_inputs(), std::runtime_error); +} \ No newline at end of file diff --git a/morpheus/_lib/tests/llm/test_utils.cpp b/morpheus/_lib/tests/llm/test_utils.cpp index 5cae320bd0..75003488bd 100644 --- a/morpheus/_lib/tests/llm/test_utils.cpp +++ b/morpheus/_lib/tests/llm/test_utils.cpp @@ -84,23 +84,17 @@ TEST_F(TestLLMUtils, ProcessInputNamesSingleMapping) TEST_F(TestLLMUtils, ProcessInputNamesSingleString) { - auto user_inputs_1 = llm::user_input_mappings_t{{"/ext1"}}; - auto input_names_1 = std::vector{"input1"}; - - auto returned_1 = llm::process_input_names(user_inputs_1, input_names_1); - - EXPECT_EQ(returned_1.size(), 1); - EXPECT_EQ(returned_1[0].external_name, "/ext1"); - EXPECT_EQ(returned_1[0].internal_name, "input1"); - - auto user_inputs_2 = llm::user_input_mappings_t{{"input1"}}; - auto input_names_2 = std::vector{"input1"}; - - auto returned_2 = llm::process_input_names(user_inputs_2, input_names_2); + std::vector> mappings{{"/ext1", "input1"}, {"input1", "input1"}}; + for (const auto& m : mappings) + { + auto user_inputs = llm::user_input_mappings_t{{m[0]}}; + auto input_names = std::vector{m[1]}; - EXPECT_EQ(returned_2.size(), 1); - EXPECT_EQ(returned_2[0].external_name, "input1"); - EXPECT_EQ(returned_2[0].internal_name, "input1"); + auto returned = llm::process_input_names(user_inputs, input_names); + EXPECT_EQ(returned.size(), 1); + EXPECT_EQ(returned[0].external_name, m[0]); + EXPECT_EQ(returned[0].internal_name, m[1]); + } } TEST_F(TestLLMUtils, ProcessInputNamesMultipleMappings) @@ -117,63 +111,63 @@ TEST_F(TestLLMUtils, ProcessInputNamesMultipleMappings) EXPECT_EQ(returned[1].internal_name, "input2"); } -TEST_F(TestLLMUtils, ProcessInputNamesMismatchInputNames) +TEST_F(TestLLMUtils, ProcessInputNamesMismatchSingleMapping) { - auto user_inputs_1 = llm::user_input_mappings_t{{"/ext1", "input2"}}; - auto input_names_1 = std::vector{"input1"}; + auto user_inputs = llm::user_input_mappings_t{{"/ext1", "input2"}}; + auto input_names = std::vector{"input1"}; - EXPECT_THROW(llm::process_input_names(user_inputs_1, input_names_1), std::invalid_argument); + EXPECT_THROW(llm::process_input_names(user_inputs, input_names), std::invalid_argument); +} - auto user_inputs_2 = llm::user_input_mappings_t{{"/ext1", "input1"}, {"/ext2", "input3"}}; - auto input_names_2 = std::vector{"input1", "input2"}; +TEST_F(TestLLMUtils, ProcessInputNamesMismatchMultipleMappings) +{ + auto user_inputs = llm::user_input_mappings_t{{"/ext1", "input1"}, {"/ext2", "input3"}}; + auto input_names = std::vector{"input1", "input2"}; - EXPECT_THROW(llm::process_input_names(user_inputs_2, input_names_2), std::invalid_argument); + EXPECT_THROW(llm::process_input_names(user_inputs, input_names), std::invalid_argument); } TEST_F(TestLLMUtils, ProcessInputNamesCountMismatch) { - auto user_inputs_1 = llm::user_input_mappings_t{{"/ext1", "input1"}, {"/ext2", "input1"}}; - auto input_names_1 = std::vector{"input1", "input2"}; + auto user_inputs = llm::user_input_mappings_t{{"/ext1", "input1"}, {"/ext2", "input1"}}; - EXPECT_THROW(llm::process_input_names(user_inputs_1, input_names_1), std::invalid_argument); - - auto input_names_2 = std::vector{"input1"}; - - EXPECT_THROW(llm::process_input_names(user_inputs_1, input_names_2), std::invalid_argument); + EXPECT_THROW(llm::process_input_names(user_inputs, std::vector{"input1", "input2"}), + std::invalid_argument); + EXPECT_THROW(llm::process_input_names(user_inputs, std::vector{"input1"}), std::invalid_argument); } -TEST_F(TestLLMUtils, ProcessInputNamesPlaceholderMappings) +TEST_F(TestLLMUtils, ProcessInputNamesPlaceholderSingleInput) { - auto user_inputs_1 = llm::user_input_mappings_t{{"/ext1/*", "*"}}; - auto input_names_1 = std::vector{"input1"}; + auto user_inputs = llm::user_input_mappings_t{{"/ext1/*", "*"}}; + auto input_names = std::vector{"input1"}; - auto returned_1 = llm::process_input_names(user_inputs_1, input_names_1); + auto returned = llm::process_input_names(user_inputs, input_names); - EXPECT_EQ(returned_1.size(), 1); - EXPECT_EQ(returned_1[0].external_name, "/ext1/input1"); - EXPECT_EQ(returned_1[0].internal_name, "input1"); + EXPECT_EQ(returned.size(), 1); + EXPECT_EQ(returned[0].external_name, "/ext1/input1"); + EXPECT_EQ(returned[0].internal_name, "input1"); +} - auto user_inputs_2 = llm::user_input_mappings_t{{"/ext1/*", "*"}}; - auto input_names_2 = std::vector{"input1, input2"}; +TEST_F(TestLLMUtils, ProcessInputNamesPlaceholderMultipleInputs) +{ + auto user_inputs = llm::user_input_mappings_t{{"/ext1/*", "*"}}; + auto input_names = std::vector{"input1, input2"}; - auto returned_2 = llm::process_input_names(user_inputs_2, input_names_2); + auto returned = llm::process_input_names(user_inputs, input_names); - EXPECT_EQ(returned_2.size(), 1); - EXPECT_EQ(returned_2[0].external_name, "/ext1/input1, input2"); - EXPECT_EQ(returned_2[0].internal_name, "input1, input2"); + EXPECT_EQ(returned.size(), 1); + EXPECT_EQ(returned[0].external_name, "/ext1/input1, input2"); + EXPECT_EQ(returned[0].internal_name, "input1, input2"); } TEST_F(TestLLMUtils, ProcessInputNamesPlaceholderMismatch) { - auto user_inputs_1 = llm::user_input_mappings_t{{"/ext1", "*"}}; - auto input_names_1 = std::vector{"input1"}; - - EXPECT_THROW(llm::process_input_names(user_inputs_1, input_names_1), std::invalid_argument); - - auto user_inputs_2 = llm::user_input_mappings_t{{"/ext1/*", "input1"}}; - auto input_names_2 = std::vector{"input1"}; + auto input_names = std::vector{"input1"}; - EXPECT_THROW(llm::process_input_names(user_inputs_2, input_names_2), std::invalid_argument); + EXPECT_THROW(llm::process_input_names(llm::user_input_mappings_t{{"/ext1", "*"}}, input_names), + std::invalid_argument); + EXPECT_THROW(llm::process_input_names(llm::user_input_mappings_t{{"/ext1/*", "input1"}}, input_names), + std::invalid_argument); } TEST_F(TestLLMUtils, ProcessInputNamesIndexMatching) @@ -226,13 +220,10 @@ TEST_F(TestLLMUtils, ProcessInputNamesSiblingWithInputNameMatching) TEST_F(TestLLMUtils, ProcessInputNamesMatchingIndexExceeded) { - auto user_inputs_1 = llm::user_input_mappings_t{{"/ext1"}, {"/ext2"}}; - auto input_names_1 = std::vector{"input1"}; - - EXPECT_THROW(llm::process_input_names(user_inputs_1, input_names_1), std::invalid_argument); - - auto user_inputs_2 = llm::user_input_mappings_t{{"input1"}, {"input2"}}; - auto input_names_2 = std::vector{"input1"}; + auto input_names = std::vector{"input1"}; - EXPECT_THROW(llm::process_input_names(user_inputs_2, input_names_2), std::invalid_argument); + EXPECT_THROW(llm::process_input_names(llm::user_input_mappings_t{{"/ext1"}, {"/ext2"}}, input_names), + std::invalid_argument); + EXPECT_THROW(llm::process_input_names(llm::user_input_mappings_t{{"input1"}, {"input2"}}, input_names), + std::invalid_argument); }