Skip to content

Commit b1a3a8c

Browse files
authored
feat: update AI SDK with latest spec changes (#50)
* Updates `Model` config to contain `Id`, `Parameters` and `Custom`, which are both dictionaries from string -> `LdValue` * Adds `Provider` config which contains an `Id` * Renames `Prompt` -> `Messages`, update the getters There are no changes to the tracking methods.
1 parent 0396c4a commit b1a3a8c

File tree

11 files changed

+313
-79
lines changed

11 files changed

+313
-79
lines changed

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

Lines changed: 104 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -32,32 +32,81 @@ internal Message(string content, Role role)
3232
}
3333
}
3434

35+
36+
/// <summary>
37+
/// Information about the model provider.
38+
/// </summary>
39+
public record ModelProvider
40+
{
41+
/// <summary>
42+
/// The ID of the model provider.
43+
/// </summary>
44+
public readonly string Id;
45+
46+
internal ModelProvider(string id)
47+
{
48+
Id = id;
49+
}
50+
}
51+
52+
/// <summary>
53+
/// Information about the model.
54+
/// </summary>
55+
public record ModelConfiguration
56+
{
57+
/// <summary>
58+
/// The ID of the model.
59+
/// </summary>
60+
public readonly string Id;
61+
62+
/// <summary>
63+
/// The model's built-in parameters provided by LaunchDarkly.
64+
/// </summary>
65+
public readonly IReadOnlyDictionary<string, LdValue> Parameters;
66+
67+
/// <summary>
68+
/// The model's custom parameters provided by the user.
69+
/// </summary>
70+
public readonly IReadOnlyDictionary<string, LdValue> Custom;
71+
72+
internal ModelConfiguration(string id, IReadOnlyDictionary<string, LdValue> parameters, IReadOnlyDictionary<string, LdValue> custom)
73+
{
74+
Id = id;
75+
Parameters = parameters;
76+
Custom = custom;
77+
}
78+
}
79+
3580
/// <summary>
3681
/// Builder for constructing an LdAiConfig instance, which can be passed as the default
3782
/// value to the AI Client's <see cref="LdAiClient.ModelConfig"/> method.
3883
/// </summary>
3984
public class Builder
4085
{
4186
private bool _enabled;
42-
private readonly List<Message> _prompt;
43-
private readonly Dictionary<string, object> _modelParams;
87+
private readonly List<Message> _messages;
88+
private readonly Dictionary<string, LdValue> _modelParams;
89+
private readonly Dictionary<string, LdValue> _customModelParams;
90+
private string _providerId;
4491

4592
internal Builder()
4693
{
4794
_enabled = false;
48-
_prompt = new List<Message>();
49-
_modelParams = new Dictionary<string, object>();
95+
_messages = new List<Message>();
96+
_modelParams = new Dictionary<string, LdValue>();
97+
_customModelParams = new Dictionary<string, LdValue>();
98+
_providerId = "";
5099
}
51100

52101
/// <summary>
53-
/// Adds a prompt message with the given content and role. The default role is <see cref="Role.User"/>.
102+
/// Adds a message with the given content and role. The default role is <see cref="Role.User"/>.
54103
/// </summary>
55104
/// <param name="content">the content, which may contain Mustache templates</param>
56105
/// <param name="role">the role</param>
57106
/// <returns>a new builder</returns>
58-
public Builder AddPromptMessage(string content, Role role = Role.User)
107+
public Builder AddMessage(string content, Role role = Role.User)
59108
{
60-
_prompt.Add(new Message(content, role));
109+
_messages.Add(new Message(content, role));
61110
return this;
62111
}
63112

@@ -85,66 +134,74 @@ public Builder SetEnabled(bool enabled)
85134
}
86135

87136
/// <summary>
88-
/// Sets a parameter for the model. The value may be any object.
137+
/// Sets a parameter for the model.
89138
/// </summary>
90139
/// <param name="name">the parameter name</param>
91140
/// <param name="value">the parameter value</param>
92141
/// <returns>the builder</returns>
93-
public Builder SetModelParam(string name, object value)
142+
public Builder SetModelParam(string name, LdValue value)
94143
{
95144
_modelParams[name] = value;
96145
return this;
97146
}
98147

148+
/// <summary>
149+
/// Sets a custom parameter for the model.
150+
/// </summary>
151+
/// <param name="name">the custom parameter name</param>
152+
/// <param name="value">the custom parameter value</param>
153+
/// <returns>the builder</returns>
154+
public Builder SetCustomModelParam(string name, LdValue value)
155+
{
156+
_customModelParams[name] = value;
157+
return this;
158+
}
159+
160+
/// <summary>
161+
/// Sets the model provider's ID. By default, this will be the empty string.
162+
/// </summary>
163+
/// <param name="id">the ID</param>
164+
/// <returns></returns>
165+
public Builder SetModelProviderId(string id)
166+
{
167+
_providerId = id;
168+
return this;
169+
}
170+
99171
/// <summary>
100172
/// Builds the LdAiConfig instance.
101173
/// </summary>
102174
/// <returns>a new LdAiConfig</returns>
103175
public LdAiConfig Build()
104176
{
105-
return new LdAiConfig(_enabled, _prompt, new Meta(), _modelParams);
177+
return new LdAiConfig(_enabled, _messages, new Meta(), new Model {Parameters = _modelParams, Custom = _customModelParams}, new Provider{ Id = _providerId });
106178
}
107179
}
108180

109181
/// <summary>
110182
/// The prompts associated with the config.
111183
/// </summary>
112-
public readonly IReadOnlyList<Message> Prompt;
184+
public readonly IReadOnlyList<Message> Messages;
113185

114186
/// <summary>
115187
/// The model parameters associated with the config.
116188
/// </summary>
117-
public readonly IReadOnlyDictionary<string, object> Model;
118-
189+
public readonly ModelConfiguration Model;
119190

191+
/// <summary>
192+
/// Information about the model provider.
193+
/// </summary>
194+
public readonly ModelProvider Provider;
120195

121-
internal LdAiConfig(bool enabled, IEnumerable<Message> prompt, Meta meta, IReadOnlyDictionary<string, object> model)
196+
internal LdAiConfig(bool enabled, IEnumerable<Message> messages, Meta meta, Model model, Provider provider)
122197
{
123-
Model = model ?? new Dictionary<string, object>();
124-
Prompt = prompt?.ToList() ?? new List<Message>();
198+
Model = new ModelConfiguration(model?.Id ?? "", model?.Parameters ?? new Dictionary<string, LdValue>(),
199+
model?.Custom ?? new Dictionary<string, LdValue>());
200+
Messages = messages?.ToList() ?? new List<Message>();
125201
VersionKey = meta?.VersionKey ?? "";
126202
Enabled = enabled;
203+
Provider = new ModelProvider(provider?.Id ?? "");
127204
}
128-
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-
148205
internal LdValue ToLdValue()
149206
{
150207
return LdValue.ObjectFrom(new Dictionary<string, LdValue>
@@ -155,12 +212,20 @@ internal LdValue ToLdValue()
155212
{ "versionKey", LdValue.Of(VersionKey) },
156213
{ "enabled", LdValue.Of(Enabled) }
157214
}) },
158-
{ "prompt", LdValue.ArrayFrom(Prompt.Select(m => LdValue.ObjectFrom(new Dictionary<string, LdValue>
215+
{ "messages", LdValue.ArrayFrom(Messages.Select(m => LdValue.ObjectFrom(new Dictionary<string, LdValue>
159216
{
160217
{ "content", LdValue.Of(m.Content) },
161218
{ "role", LdValue.Of(m.Role.ToString()) }
162219
}))) },
163-
{ "model", ObjectToValue(Model) }
220+
{ "model", LdValue.ObjectFrom(new Dictionary<string, LdValue>
221+
{
222+
{ "parameters", LdValue.ObjectFrom(Model.Parameters) },
223+
{ "custom", LdValue.ObjectFrom(Model.Custom) }
224+
}) },
225+
{"provider", LdValue.ObjectFrom(new Dictionary<string, LdValue>
226+
{
227+
{"id", LdValue.Of(Provider.Id)}
228+
})}
164229
});
165230
}
166231

@@ -176,7 +241,6 @@ internal LdValue ToLdValue()
176241
/// <returns>true if enabled</returns>
177242
public bool Enabled { get; }
178243

179-
180244
/// <summary>
181245
/// This field meant for internal LaunchDarkly usage.
182246
/// </summary>
@@ -185,7 +249,5 @@ internal LdValue ToLdValue()
185249
/// <summary>
186250
/// Convenient helper that returns a disabled LdAiConfig.
187251
/// </summary>
188-
public static LdAiConfig Disabled = New().Disable().Build();
189-
190-
252+
public static LdAiConfig Disabled => New().Disable().Build();
191253
}

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

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ public class AiConfig
6969
/// <summary>
7070
/// The prompt.
7171
/// </summary>
72-
[JsonPropertyName("prompt")]
73-
public List<Message> Prompt { get; set; }
72+
[JsonPropertyName("messages")]
73+
public List<Message> Messages { get; set; }
7474

7575
/// <summary>
7676
/// LaunchDarkly metadata.
@@ -79,8 +79,50 @@ public class AiConfig
7979
public Meta Meta { get; set; }
8080

8181
/// <summary>
82-
/// The model params;
82+
/// The model configuration.
8383
/// </summary>
8484
[JsonPropertyName("model")]
85-
public Dictionary<string, object> Model { get; set; }
85+
public Model Model { get; set; }
86+
87+
/// <summary>
88+
/// The model provider.
89+
/// </summary>
90+
[JsonPropertyName("provider")]
91+
public Provider Provider { get; set; }
92+
}
93+
94+
/// <summary>
95+
/// Represents the JSON serialization of a model.
96+
/// </summary>
97+
public class Model
98+
{
99+
/// <summary>
100+
/// The model's ID.
101+
/// </summary>
102+
[JsonPropertyName("id")]
103+
public string Id { get; set; }
104+
105+
/// <summary>
106+
/// The model's parameters. These are provided by LaunchDarkly.
107+
/// </summary>
108+
[JsonPropertyName("parameters")]
109+
public Dictionary<string, LdValue> Parameters { get; set; }
110+
111+
/// <summary>
112+
/// The model's custom parameters. These are arbitrary and provided by the user.
113+
/// </summary>
114+
[JsonPropertyName("custom")]
115+
public Dictionary<string, LdValue> Custom { get; set; }
116+
}
117+
118+
/// <summary>
119+
/// Represents the JSON serialization of a model provider.
120+
/// </summary>
121+
public class Provider
122+
{
123+
/// <summary>
124+
/// The provider's ID.
125+
/// </summary>
126+
[JsonPropertyName("id")]
127+
public string Id { get; set; }
86128
}

pkgs/sdk/server-ai/src/Interfaces/ILdAiConfigTracker.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using System;
22
using System.Threading.Tasks;
33
using LaunchDarkly.Sdk.Server.Ai.Config;
4-
using LaunchDarkly.Sdk.Server.Ai.Provider;
4+
using LaunchDarkly.Sdk.Server.Ai.Tracking;
55

66
namespace LaunchDarkly.Sdk.Server.Ai.Interfaces;
77

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

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ public ILdAiConfigTracker ModelConfig(string key, Context context, LdAiConfig de
5757
return new LdAiConfigTracker(_client, key, defaultValue, context);
5858
}
5959

60-
6160
var mergedVariables = new Dictionary<string, object> { { LdContextVariable, GetAllAttributes(context) } };
6261
if (variables != null)
6362
{
@@ -75,14 +74,14 @@ public ILdAiConfigTracker ModelConfig(string key, Context context, LdAiConfig de
7574

7675
var prompt = new List<LdAiConfig.Message>();
7776

78-
if (parsed.Prompt != null)
77+
if (parsed.Messages != null)
7978
{
80-
for (var i = 0; i < parsed.Prompt.Count; i++)
79+
for (var i = 0; i < parsed.Messages.Count; i++)
8180
{
8281
try
8382
{
84-
var content = InterpolateTemplate(parsed.Prompt[i].Content, mergedVariables);
85-
prompt.Add(new LdAiConfig.Message(content, parsed.Prompt[i].Role));
83+
var content = InterpolateTemplate(parsed.Messages[i].Content, mergedVariables);
84+
prompt.Add(new LdAiConfig.Message(content, parsed.Messages[i].Role));
8685
}
8786
catch (Exception ex)
8887
{
@@ -93,7 +92,7 @@ public ILdAiConfigTracker ModelConfig(string key, Context context, LdAiConfig de
9392
}
9493
}
9594

96-
return new LdAiConfigTracker(_client, key, new LdAiConfig(parsed.Meta?.Enabled ?? false, prompt, parsed.Meta, parsed.Model), context);
95+
return new LdAiConfigTracker(_client, key, new LdAiConfig(parsed.Meta?.Enabled ?? false, prompt, parsed.Meta, parsed.Model, parsed.Provider), context);
9796

9897
}
9998

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
using System.Threading.Tasks;
55
using LaunchDarkly.Sdk.Server.Ai.Config;
66
using LaunchDarkly.Sdk.Server.Ai.Interfaces;
7-
using LaunchDarkly.Sdk.Server.Ai.Provider;
7+
using LaunchDarkly.Sdk.Server.Ai.Tracking;
88

99
namespace LaunchDarkly.Sdk.Server.Ai;
1010

pkgs/sdk/server-ai/src/Provider/Feedback.cs renamed to pkgs/sdk/server-ai/src/Tracking/Feedback.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace LaunchDarkly.Sdk.Server.Ai.Provider;
1+
namespace LaunchDarkly.Sdk.Server.Ai.Tracking;
22

33
/// <summary>
44
/// Feedback about the generated content.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace LaunchDarkly.Sdk.Server.Ai.Provider;
1+
namespace LaunchDarkly.Sdk.Server.Ai.Tracking;
22

33
/// <summary>
44
/// Represents metrics returned by a model provider.

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ private string Eval(string prompt, Context context, IReadOnlyDictionary<string,
2323
{
2424
"_ldMeta": {"versionKey": "1", "enabled": true},
2525
"model": {},
26-
"prompt": [
26+
"messages": [
2727
{
2828
"content": "<do-not-use-in-any-tests-prompt-placeholder>",
29-
"role": "System"
29+
"role": "system"
3030
}
3131
]
3232
}
@@ -41,7 +41,7 @@ private string Eval(string prompt, Context context, IReadOnlyDictionary<string,
4141
var client = new LdAiClient(mockClient.Object);
4242
var tracker = client.ModelConfig("foo", context, LdAiConfig.Disabled, variables);
4343

44-
return tracker.Config.Prompt[0].Content;
44+
return tracker.Config.Messages[0].Content;
4545
}
4646

4747
[Theory]
@@ -128,7 +128,7 @@ public void TestInterpolationMalformed()
128128
{
129129
"_ldMeta": {"versionKey": "1", "enabled": true},
130130
"model": {},
131-
"prompt": [
131+
"messages": [
132132
{
133133
"content": "This is a {{ malformed }]} prompt",
134134
"role": "System"

0 commit comments

Comments
 (0)