Skip to content

Commit e7d8fc2

Browse files
committed
adding track methods
1 parent 949c635 commit e7d8fc2

File tree

6 files changed

+135
-9
lines changed

6 files changed

+135
-9
lines changed

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Generic;
33
using System.Collections.ObjectModel;
44
using System.Linq;
5+
using System.Runtime.InteropServices;
56
using LaunchDarkly.Sdk.Server.Ai.DataModel;
67

78
namespace LaunchDarkly.Sdk.Server.Ai.Config
@@ -65,7 +66,7 @@ public Builder()
6566
/// <param name="content"></param>
6667
/// <param name="role"></param>
6768
/// <returns></returns>
68-
public Builder AddPromptMessage(string content, Role role = Role.System)
69+
public Builder AddPromptMessage(string content, Role role = Role.User)
6970
{
7071
_prompt.Add(new Message(content, role));
7172
return this;
@@ -112,6 +113,8 @@ public LdAiConfig Build()
112113
public readonly IReadOnlyDictionary<string, object> Model;
113114

114115
private readonly string _versionKey;
116+
117+
115118
private readonly bool _enabled;
116119

117120
internal LdAiConfig(bool enabled, IEnumerable<Message> prompt, Meta meta, IReadOnlyDictionary<string, object> model)
@@ -135,6 +138,12 @@ internal LdAiConfig(bool enabled, IEnumerable<Message> prompt, Meta meta, IReadO
135138
/// <returns></returns>
136139
public bool IsEnabled() => _enabled;
137140

141+
142+
/// <summary>
143+
///
144+
/// </summary>
145+
public string VersionKey => _versionKey;
146+
138147
/// <summary>
139148
/// TBD
140149
/// </summary>

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

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@ public interface ILaunchDarklyClient
4444
/// <returns></returns>
4545
EvaluationDetail<LdValue> JsonVariationDetail(string key, Context context, LdValue defaultValue);
4646

47+
48+
/// <summary>
49+
/// TBD
50+
/// </summary>
51+
/// <param name="name"></param>
52+
/// <param name="context"></param>
53+
/// <param name="data"></param>
54+
/// <param name="metricValue"></param>
55+
void Track(string name, Context context, LdValue data, double metricValue);
56+
4757
/// <summary>
4858
/// TBD
4959
/// </summary>
@@ -127,18 +137,20 @@ public LdAiConfigTracker GetModelConfig(string key, Context context, LdAiConfig
127137

128138
var detail = _client.JsonVariationDetail(key, context, LdValue.Null);
129139

140+
var defaultTracker = new LdAiConfigTracker(_client, defaultValue, context, key);
141+
130142
if (detail.IsDefaultValue)
131143
{
132144
_client.GetLogger().Warn("No model config available for key {0}", key);
133-
return new LdAiConfigTracker(_client, defaultValue);
145+
return defaultTracker;
134146
}
135147

136148

137149
var parsed = ParseConfig(detail.Value, key);
138150
if (parsed == null)
139151
{
140152
// ParseConfig already does logging.
141-
return new LdAiConfigTracker(_client, defaultValue);
153+
return defaultTracker;
142154
}
143155

144156

@@ -160,7 +172,7 @@ public LdAiConfigTracker GetModelConfig(string key, Context context, LdAiConfig
160172
var prompt =
161173
parsed.Prompt?.Select(m => new LdAiConfig.Message(InterpolateTemplate(m.Content, mergedVariables), m.Role));
162174

163-
return new LdAiConfigTracker(_client, new LdAiConfig(parsed.Meta?.Enabled ?? false, prompt, parsed.Meta, parsed.Model));
175+
return new LdAiConfigTracker(_client, new LdAiConfig(parsed.Meta?.Enabled ?? false, prompt, parsed.Meta, parsed.Model), context, key);
164176
}
165177

166178

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

Lines changed: 82 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
using System;
2+
using System.Collections.Generic;
3+
using System.Diagnostics;
4+
using System.Threading.Tasks;
25
using LaunchDarkly.Sdk.Server.Ai.Config;
6+
using LaunchDarkly.Sdk.Server.Ai.Metrics;
37

48
namespace LaunchDarkly.Sdk.Server.Ai;
59

@@ -16,19 +20,94 @@ public class LdAiConfigTracker : IDisposable
1620
/// <summary>
1721
/// TBD
1822
/// </summary>
19-
private ILaunchDarklyClient _client;
23+
private readonly ILaunchDarklyClient _client;
24+
25+
private readonly Context _context;
26+
27+
private readonly string _key;
28+
29+
private const string Duration = "$ld:ai:duration:total";
30+
private const string FeedbackPositive = "$ld:ai:feedback:user:positive";
31+
private const string FeedbackNegative = "$ld:ai:feedback:user:negative";
32+
private const string Generation = "$ld:ai:generation";
2033

2134
/// <summary>
22-
/// TBD
35+
///
2336
/// </summary>
2437
/// <param name="client"></param>
2538
/// <param name="config"></param>
26-
public LdAiConfigTracker(ILaunchDarklyClient client, LdAiConfig config)
39+
/// <param name="context"></param>
40+
/// <param name="key"></param>
41+
/// <exception cref="ArgumentNullException"></exception>
42+
public LdAiConfigTracker(ILaunchDarklyClient client, LdAiConfig config, Context context, string key)
2743
{
2844
_client = client ?? throw new ArgumentNullException(nameof(client));
45+
_key = key ?? throw new ArgumentNullException(nameof(key));
46+
_context = context;
2947
Config = config ?? throw new ArgumentNullException(nameof(config));
3048
}
3149

50+
private LdValue GetTrackData()
51+
{
52+
return LdValue.ObjectFrom(new Dictionary<string, LdValue>
53+
{
54+
{ "versionKey", LdValue.Of(Config.VersionKey)},
55+
{ "configKey" , LdValue.Of(_key) }
56+
});
57+
}
58+
59+
/// <summary>
60+
///
61+
/// </summary>
62+
/// <param name="duration"></param>
63+
public void TrackDuration(float duration) =>
64+
_client.Track(Duration, _context, GetTrackData(), duration);
65+
66+
67+
/// <summary>
68+
///
69+
/// </summary>
70+
/// <param name="task"></param>
71+
/// <typeparam name="T"></typeparam>
72+
/// <returns></returns>
73+
public async Task<T> TrackDurationOfTask<T>(Task<T> task)
74+
{
75+
var sw = Stopwatch.StartNew();
76+
var result = await task;
77+
sw.Stop();
78+
TrackDuration(sw.ElapsedMilliseconds);
79+
return result;
80+
}
81+
82+
/// <summary>
83+
///
84+
/// </summary>
85+
/// <param name="feedback"></param>
86+
/// <exception cref="ArgumentOutOfRangeException"></exception>
87+
public void TrackFeedback(Feedback feedback)
88+
{
89+
switch (feedback)
90+
{
91+
case Feedback.Positive:
92+
_client.Track(FeedbackPositive, _context, GetTrackData(), 1);
93+
break;
94+
case Feedback.Negative:
95+
_client.Track(FeedbackNegative, _context, GetTrackData(), 1);
96+
break;
97+
default:
98+
throw new ArgumentOutOfRangeException(nameof(feedback), feedback, null);
99+
}
100+
}
101+
102+
/// <summary>
103+
///
104+
/// </summary>
105+
public void TrackSuccess()
106+
{
107+
_client.Track(Generation, _context, GetTrackData(), 1);
108+
}
109+
110+
32111
/// <summary>
33112
/// TBD
34113
/// </summary>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
namespace LaunchDarkly.Sdk.Server.Ai.Metrics;
2+
3+
/// <summary>
4+
/// Feedback about the generated content.
5+
/// </summary>
6+
public enum Feedback
7+
{
8+
/// <summary>
9+
/// The sentiment was positive.
10+
/// </summary>
11+
Positive,
12+
13+
/// <summary>
14+
/// The sentiment was negative.
15+
/// </summary>
16+
Negative,
17+
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ public void ConfigNotEnabledReturnsDisabledInstance(string json)
9797
var tracker = client.GetModelConfig("foo", Context.New(ContextKind.Default, "key"),
9898
LdAiConfig.New().AddPromptMessage("foo").Build());
9999

100+
101+
100102
Assert.False(tracker.Config.IsEnabled());
101103
}
102104

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,21 @@ public class LdAiTrackerTest
99
[Fact]
1010
public void ThrowsIfClientIsNull()
1111
{
12-
Assert.Throws<System.ArgumentNullException>(() => new LdAiConfigTracker(null, LdAiConfig.Disabled));
12+
Assert.Throws<System.ArgumentNullException>(() => new LdAiConfigTracker(null, LdAiConfig.Disabled, Context.New("key"), "key"));
1313
}
1414

1515
[Fact]
1616
public void ThrowsIfConfigIsNull()
1717
{
1818
var mockClient = new Mock<ILaunchDarklyClient>();
19-
Assert.Throws<System.ArgumentNullException>(() => new LdAiConfigTracker(mockClient.Object, null));
19+
Assert.Throws<System.ArgumentNullException>(() => new LdAiConfigTracker(mockClient.Object, null, Context.New("key"), "key"));
20+
}
21+
22+
[Fact]
23+
public void ThrowsIfKeyIsNull()
24+
{
25+
var mockClient = new Mock<ILaunchDarklyClient>();
26+
Assert.Throws<System.ArgumentNullException>(() => new LdAiConfigTracker(mockClient.Object, LdAiConfig.Disabled, Context.New("key"), null));
2027
}
2128
}
2229
}

0 commit comments

Comments
 (0)