From 4e32ae0f2b1b9c26af62fb9ddcdf11424b8b225c Mon Sep 17 00:00:00 2001 From: Casey Waldren <cwaldren@launchdarkly.com> Date: Tue, 12 Nov 2024 16:34:45 -0800 Subject: [PATCH] fix: catch exceptions thrown by template interpolation --- pkgs/sdk/server-ai/src/LdAiClient.cs | 21 ++++++++++-- pkgs/sdk/server-ai/test/InterpolationTests.cs | 32 +++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/pkgs/sdk/server-ai/src/LdAiClient.cs b/pkgs/sdk/server-ai/src/LdAiClient.cs index 928f2f63..5067af0b 100644 --- a/pkgs/sdk/server-ai/src/LdAiClient.cs +++ b/pkgs/sdk/server-ai/src/LdAiClient.cs @@ -73,10 +73,27 @@ public ILdAiConfigTracker ModelConfig(string key, Context context, LdAiConfig de } - var prompt = - parsed.Prompt?.Select(m => new LdAiConfig.Message(InterpolateTemplate(m.Content, mergedVariables), m.Role)); + var prompt = new List<LdAiConfig.Message>(); + + if (parsed.Prompt != null) + { + for (var i = 0; i < parsed.Prompt.Count; i++) + { + try + { + var content = InterpolateTemplate(parsed.Prompt[i].Content, mergedVariables); + prompt.Add(new LdAiConfig.Message(content, parsed.Prompt[i].Role)); + } + catch (Exception ex) + { + _logger.Error($"AI model config prompt has malformed message at index {i}: {ex.Message} (returning default config)"); + return new LdAiConfigTracker(_client, key, defaultValue, context); + } + } + } return new LdAiConfigTracker(_client, key, new LdAiConfig(parsed.Meta?.Enabled ?? false, prompt, parsed.Meta, parsed.Model), context); + } /// <summary> diff --git a/pkgs/sdk/server-ai/test/InterpolationTests.cs b/pkgs/sdk/server-ai/test/InterpolationTests.cs index d6256e9d..8635a390 100644 --- a/pkgs/sdk/server-ai/test/InterpolationTests.cs +++ b/pkgs/sdk/server-ai/test/InterpolationTests.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Text.Json; using System.Text.Json.Serialization; @@ -117,6 +118,37 @@ public void TestInterpolationWithArraySectionWorks() Assert.Equal("hello world ! ", result); } + [Fact] + public void TestInterpolationMalformed() + { + var mockClient = new Mock<ILaunchDarklyClient>(); + var mockLogger = new Mock<ILogger>(); + + + // The replacement is done this way because to use string.Format, we'd need to escape the curly braces. + var configJson = """ + { + "_ldMeta": {"versionKey": "1", "enabled": true}, + "model": {}, + "prompt": [ + { + "content": "This is a {{ malformed }]} prompt", + "role": "System" + } + ] + } + """; + + + mockClient.Setup(x => + x.JsonVariation("foo", It.IsAny<Context>(), It.IsAny<LdValue>())).Returns(LdValue.Parse(configJson)); + + mockClient.Setup(x => x.GetLogger()).Returns(mockLogger.Object); + + var client = new LdAiClient(mockClient.Object); + var tracker = client.ModelConfig("foo", Context.New("key"), LdAiConfig.Disabled, null); + Assert.False(tracker.Config.Enabled); + } [Fact] public void TestInterpolationWithBasicContext()