Skip to content

Commit 8d961ca

Browse files
committed
pass LdValue as default value
1 parent ce64ccf commit 8d961ca

File tree

4 files changed

+65
-45
lines changed

4 files changed

+65
-45
lines changed

pkgs/sdk/server-ai/src/Config/LdAiConfig.cs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,49 @@ internal LdAiConfig(bool enabled, IEnumerable<Message> prompt, Meta meta, IReadO
126126
Enabled = enabled;
127127
}
128128

129+
private static LdValue ObjectToValue(object obj)
130+
{
131+
if (obj == null)
132+
{
133+
return LdValue.Null;
134+
}
135+
136+
return obj switch
137+
{
138+
bool b => LdValue.Of(b),
139+
double d => LdValue.Of(d),
140+
string s => LdValue.Of(s),
141+
IEnumerable<object> list => LdValue.ArrayFrom(list.Select(ObjectToValue)),
142+
IDictionary<string, object> dict => LdValue.ObjectFrom(dict.ToDictionary(kv => kv.Key,
143+
kv => ObjectToValue(kv.Value))),
144+
_ => LdValue.Null
145+
};
146+
}
147+
148+
/// <summary>
149+
/// Converts the AI config to a compatible LdValue representation.
150+
/// Used internally.
151+
/// </summary>
152+
/// <returns>an LdValue</returns>
153+
public LdValue ToLdValue()
154+
{
155+
return LdValue.ObjectFrom(new Dictionary<string, LdValue>
156+
{
157+
{ "_ldMeta", LdValue.ObjectFrom(
158+
new Dictionary<string, LdValue>
159+
{
160+
{ "versionKey", LdValue.Of(VersionKey) },
161+
{ "enabled", LdValue.Of(Enabled) }
162+
}) },
163+
{ "prompt", LdValue.ArrayFrom(Prompt.Select(m => LdValue.ObjectFrom(new Dictionary<string, LdValue>
164+
{
165+
{ "content", LdValue.Of(m.Content) },
166+
{ "role", LdValue.Of(m.Role.ToString()) }
167+
}))) },
168+
{ "model", ObjectToValue(Model) }
169+
});
170+
}
171+
129172

130173
/// <summary>
131174
/// Creates a new LdAiConfig builder.

pkgs/sdk/server-ai/src/LdAiClient.cs

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,22 +47,14 @@ public ILdAiConfigTracker ModelConfig(string key, Context context, LdAiConfig de
4747
IReadOnlyDictionary<string, object> variables = null)
4848
{
4949

50-
var result = _client.JsonVariation(key, context, LdValue.Null);
51-
52-
var defaultTracker = new LdAiConfigTracker(_client, key, defaultValue, context);
53-
54-
if (result.IsNull)
55-
{
56-
_logger.Warn("Unable to retrieve AI model config for {0}, returning default config", key);
57-
return defaultTracker;
58-
}
59-
50+
var defaultValVal = defaultValue.ToLdValue();
51+
var result = _client.JsonVariation(key, context, defaultValVal);
6052

6153
var parsed = ParseConfig(result, key);
6254
if (parsed == null)
6355
{
6456
// ParseConfig already does logging.
65-
return defaultTracker;
57+
return new LdAiConfigTracker(_client, key, defaultValue, context);
6658
}
6759

6860

@@ -129,7 +121,6 @@ private static object ValueToObject(LdValue value)
129121
};
130122
}
131123

132-
133124
private static string InterpolateTemplate(string template, IReadOnlyDictionary<string, object> variables)
134125
{
135126
return Template.Compile(template).Render(variables);

pkgs/sdk/server-ai/test/InterpolationTests.cs

Lines changed: 13 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,37 +16,23 @@ private string Eval(string prompt, Context context, IReadOnlyDictionary<string,
1616
var mockClient = new Mock<ILaunchDarklyClient>();
1717
var mockLogger = new Mock<ILogger>();
1818

19-
var config = new AiConfig
20-
{
21-
Meta = new Meta
22-
{
23-
Enabled = true,
24-
VersionKey = "1"
25-
},
26-
Model = null,
27-
Prompt = new List<Message>
28-
{
29-
new()
30-
{
31-
Content = prompt,
32-
Role = Role.System
33-
}
34-
}
35-
};
3619

37-
var options = new JsonSerializerOptions
38-
{
39-
WriteIndented = true,
40-
Converters =
41-
{
42-
new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)
43-
}
44-
};
20+
var configJson = """
21+
{
22+
"_ldMeta": {"versionKey": "1", "enabled": true},
23+
"model": {},
24+
"prompt": [
25+
{
26+
"content": "<prompt>",
27+
"role": "System"
28+
}
29+
]
30+
}
31+
""".Replace("<prompt>", prompt);
4532

46-
var json = JsonSerializer.Serialize(config, options);
4733

4834
mockClient.Setup(x =>
49-
x.JsonVariation("foo", It.IsAny<Context>(), LdValue.Null)).Returns(LdValue.Parse(json));
35+
x.JsonVariation("foo", It.IsAny<Context>(), It.IsAny<LdValue>())).Returns(LdValue.Parse(configJson));
5036

5137
mockClient.Setup(x => x.GetLogger()).Returns(mockLogger.Object);
5238

pkgs/sdk/server-ai/test/LdAiClientTest.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public void CanInstantiateWithServerSideClient()
1717
var client = new LdClientAdapter(new LdClient(Configuration.Builder("key").Offline(true).Build()));
1818
var aiClient = new LdAiClient(client);
1919
var result= aiClient.ModelConfig("foo", Context.New("key"), LdAiConfig.Disabled);
20-
Assert.Equal(LdAiConfig.Disabled, result.Config);
20+
Assert.False(result.Config.Enabled);
2121
}
2222

2323
[Fact]
@@ -27,14 +27,14 @@ public void ThrowsIfClientIsNull()
2727
}
2828

2929
[Fact]
30-
public void ReturnsDefaultConfigWhenFlagNotFound()
30+
public void ReturnsDefaultConfigWhenGivenInvalidVariation()
3131
{
3232
var mockClient = new Mock<ILaunchDarklyClient>();
3333

3434
var mockLogger = new Mock<ILogger>();
3535

3636
mockClient.Setup(x =>
37-
x.JsonVariation("foo", It.IsAny<Context>(), LdValue.Null)).Returns(LdValue.Null);
37+
x.JsonVariation("foo", It.IsAny<Context>(), It.IsAny<LdValue>())).Returns(LdValue.Null);
3838

3939

4040
mockClient.Setup(x => x.GetLogger()).Returns(mockLogger.Object);
@@ -86,14 +86,14 @@ public void ConfigNotEnabledReturnsDisabledInstance(string json)
8686
var mockLogger = new Mock<ILogger>();
8787

8888
mockClient.Setup(x =>
89-
x.JsonVariation("foo", It.IsAny<Context>(), LdValue.Null)).Returns(LdValue.Parse(json));
89+
x.JsonVariation("foo", It.IsAny<Context>(), It.IsAny<LdValue>())).Returns(LdValue.Parse(json));
9090

9191
mockClient.Setup(x => x.GetLogger()).Returns(mockLogger.Object);
9292

9393
var client = new LdAiClient(mockClient.Object);
9494

9595
// All the JSON inputs here are considered disabled, either due to lack of the 'enabled' property,
96-
// or if present, it is set to false. Therefore if the default was returned, we'd see the assertion fail
96+
// or if present, it is set to false. Therefore, if the default was returned, we'd see the assertion fail
9797
// (since calling LdAiConfig.New() constructs an enabled config by default.)
9898
var tracker = client.ModelConfig("foo", Context.New(ContextKind.Default, "key"),
9999
LdAiConfig.New().AddPromptMessage("foo").Build());
@@ -117,7 +117,7 @@ public void ConfigEnabledReturnsInstance()
117117
""";
118118

119119
mockClient.Setup(x =>
120-
x.JsonVariation("foo", It.IsAny<Context>(), LdValue.Null)).Returns(LdValue.Parse(json));
120+
x.JsonVariation("foo", It.IsAny<Context>(), It.IsAny<LdValue>())).Returns(LdValue.Parse(json));
121121

122122
mockClient.Setup(x => x.GetLogger()).Returns(mockLogger.Object);
123123

0 commit comments

Comments
 (0)