Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ To get started, follow this pattern:
```csharp
using LaunchDarkly.Sdk.Server.Ai;
using LaunchDarkly.Sdk.Server.Ai.Adapters;
using LaunchDarkly.Sdk.Server.Ai.Config;

// This is a standard LaunchDarkly server-side .NET client instance.
var baseClient = new LdClient(Configuration.Builder("sdk-key").Build());
Expand All @@ -17,5 +18,5 @@ var aiClient = new LdAiClient(new LdClientAdapter(baseClient));

// Pass in the key of the AI Config, a context, and a default value in case the config can't be
// retrieved from LaunchDarkly.
var myModelConfig = aiClient.Config("my-model-config", Context.New("user-key"), LdAiConfig.Disabled);
var myModelConfig = aiClient.CompletionConfig("my-model-config", Context.New("user-key"), LdAiCompletionConfigDefault.Disabled);
```
36 changes: 18 additions & 18 deletions pkgs/sdk/server-ai/src/Config/ConfigFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ private LdAiCompletionConfig BuildCompletionFromDefault(
string key,
LdAiCompletionConfigDefault defaultValue,
IReadOnlyDictionary<string, object> mergedVars,
Func<LdAiConfigBase, ILdAiConfigTracker> trackerFactory)
Func<LdAiConfig, ILdAiConfigTracker> trackerFactory)
{
// Caller-supplied default messages can contain Mustache templates too; interpolate
// with the same per-message fallback as server-returned configs.
Expand All @@ -93,16 +93,16 @@ private LdAiCompletionConfig BuildCompletionFromDefault(
trackerFactory);
}

private IReadOnlyList<Message> InterpolateMessages(
IReadOnlyList<Message> messages,
private IReadOnlyList<LdAiConfigTypes.Message> InterpolateMessages(
IReadOnlyList<LdAiConfigTypes.Message> messages,
IReadOnlyDictionary<string, object> mergedVars,
string key)
{
if (messages == null)
{
return new List<Message>();
return new List<LdAiConfigTypes.Message>();
}
var result = new List<Message>(messages.Count);
var result = new List<LdAiConfigTypes.Message>(messages.Count);
for (var i = 0; i < messages.Count; i++)
{
var msg = messages[i];
Expand All @@ -117,12 +117,12 @@ private IReadOnlyList<Message> InterpolateMessages(
$"AI Config '{key}': skipping interpolation of malformed template in message {i}: {ex.Message}");
interpolated = msg.Content;
}
result.Add(new Message(interpolated, msg.Role));
result.Add(new LdAiConfigTypes.Message(interpolated, msg.Role));
}
return result;
}

private Func<LdAiConfigBase, ILdAiConfigTracker> TrackerFactoryFor(Context context)
private Func<LdAiConfig, ILdAiConfigTracker> TrackerFactoryFor(Context context)
{
return cfg => new LdAiConfigTracker(
_client,
Expand All @@ -148,18 +148,18 @@ private static (bool Enabled, string VariationKey, int Version, string Mode) Par
return (enabled, variationKey, version, mode);
}

private static ModelConfig ParseModel(LdValue modelValue)
private static LdAiConfigTypes.ModelConfig ParseModel(LdValue modelValue)
{
var name = modelValue.Get("name").AsString ?? "";
var parameters = LdValueObjectToDictionary(modelValue.Get("parameters"));
var custom = LdValueObjectToDictionary(modelValue.Get("custom"));
return new ModelConfig(name, parameters, custom);
return new LdAiConfigTypes.ModelConfig(name, parameters, custom);
}

private static ProviderConfig ParseProvider(LdValue providerValue)
private static LdAiConfigTypes.ProviderConfig ParseProvider(LdValue providerValue)
{
var name = providerValue.Get("name").AsString ?? "";
return new ProviderConfig(name);
return new LdAiConfigTypes.ProviderConfig(name);
}

private static IReadOnlyDictionary<string, LdValue> LdValueObjectToDictionary(LdValue value)
Expand All @@ -173,14 +173,14 @@ private static IReadOnlyDictionary<string, LdValue> LdValueObjectToDictionary(Ld
return value.Dictionary.ToDictionary(kv => kv.Key, kv => kv.Value);
}

private static IReadOnlyList<Message> ParseMessages(LdValue messagesValue)
private static IReadOnlyList<LdAiConfigTypes.Message> ParseMessages(LdValue messagesValue)
{
if (messagesValue.Type != LdValueType.Array)
{
return new List<Message>();
return new List<LdAiConfigTypes.Message>();
}

var result = new List<Message>(messagesValue.Count);
var result = new List<LdAiConfigTypes.Message>(messagesValue.Count);
for (var i = 0; i < messagesValue.Count; i++)
{
var msg = messagesValue.Get(i);
Expand All @@ -190,20 +190,20 @@ private static IReadOnlyList<Message> ParseMessages(LdValue messagesValue)
}
var content = msg.Get("content").AsString ?? "";
var role = ParseRole(msg.Get("role").AsString);
result.Add(new Message(content, role));
result.Add(new LdAiConfigTypes.Message(content, role));
}
return result;
}

private static Role ParseRole(string roleString)
private static LdAiConfigTypes.Role ParseRole(string roleString)
{
// The wire format uses capitalized "User" / "System" / "Assistant"; Enum.TryParse with
// ignoreCase = true is tolerant of casing variants. Unknown / null roles fall back to User.
if (!string.IsNullOrEmpty(roleString) && Enum.TryParse<Role>(roleString, ignoreCase: true, out var parsed))
if (!string.IsNullOrEmpty(roleString) && Enum.TryParse<LdAiConfigTypes.Role>(roleString, ignoreCase: true, out var parsed))
{
return parsed;
}
return Role.User;
return LdAiConfigTypes.Role.User;
}

private IReadOnlyDictionary<string, object> MergeVariables(
Expand Down
10 changes: 5 additions & 5 deletions pkgs/sdk/server-ai/src/Config/LdAiCompletionConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace LaunchDarkly.Sdk.Server.Ai.Config;
/// they are not constructed directly by users. To supply a fallback default to the
/// client, use <see cref="LdAiCompletionConfigDefault"/>.
/// </summary>
public sealed class LdAiCompletionConfig : LdAiConfigBase
public sealed class LdAiCompletionConfig : LdAiConfig
{
/// <summary>
/// The mode tag emitted in <c>_ldMeta.mode</c> for this config type. Future agent and
Expand All @@ -25,13 +25,13 @@ public sealed class LdAiCompletionConfig : LdAiConfigBase
/// <summary>
/// The prompts associated with the config.
/// </summary>
public IReadOnlyList<Message> Messages { get; }
public IReadOnlyList<LdAiConfigTypes.Message> Messages { get; }

internal LdAiCompletionConfig(string key, bool enabled, string variationKey, int version,
IEnumerable<Message> messages, ModelConfig model, ProviderConfig provider,
Func<LdAiConfigBase, ILdAiConfigTracker> trackerFactory)
IEnumerable<LdAiConfigTypes.Message> messages, LdAiConfigTypes.ModelConfig model, LdAiConfigTypes.ProviderConfig provider,
Func<LdAiConfig, ILdAiConfigTracker> trackerFactory)
: base(key, enabled, variationKey, version, model, provider, trackerFactory)
{
Messages = messages?.ToList() ?? new List<Message>();
Messages = messages?.ToList() ?? new List<LdAiConfigTypes.Message>();
}
}
24 changes: 12 additions & 12 deletions pkgs/sdk/server-ai/src/Config/LdAiCompletionConfigDefault.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace LaunchDarkly.Sdk.Server.Ai.Config;
/// Construct an instance via <see cref="New"/> and the nested <see cref="Builder"/>,
/// or use <see cref="Disabled"/> for a disabled default.
/// </summary>
public sealed class LdAiCompletionConfigDefault : LdAiConfigDefaultBase
public sealed class LdAiCompletionConfigDefault : LdAiConfigDefault
{
/// <summary>
/// Builder for constructing an LdAiCompletionConfigDefault instance, which can be passed
Expand All @@ -21,7 +21,7 @@ public sealed class LdAiCompletionConfigDefault : LdAiConfigDefaultBase
public class Builder
{
private bool _enabled;
private readonly List<Message> _messages;
private readonly List<LdAiConfigTypes.Message> _messages;
private readonly Dictionary<string, LdValue> _modelParams;
private readonly Dictionary<string, LdValue> _customModelParams;
private string _providerName;
Expand All @@ -30,22 +30,22 @@ public class Builder
internal Builder()
{
_enabled = true;
_messages = new List<Message>();
_messages = new List<LdAiConfigTypes.Message>();
_modelParams = new Dictionary<string, LdValue>();
_customModelParams = new Dictionary<string, LdValue>();
_providerName = "";
_modelName = "";
}

/// <summary>
/// Adds a message with the given content and role. The default role is <see cref="Role.User"/>.
/// Adds a message with the given content and role. The default role is <see cref="LdAiConfigTypes.Role.User"/>.
/// </summary>
/// <param name="content">the content, which may contain Mustache templates</param>
/// <param name="role">the role</param>
/// <returns>a new builder</returns>
public Builder AddMessage(string content, Role role = Role.User)
public Builder AddMessage(string content, LdAiConfigTypes.Role role = LdAiConfigTypes.Role.User)
{
_messages.Add(new Message(content, role));
_messages.Add(new LdAiConfigTypes.Message(content, role));
return this;
}

Expand Down Expand Up @@ -124,25 +124,25 @@ public Builder SetModelProviderName(string name)
/// <returns>a new LdAiCompletionConfigDefault</returns>
public LdAiCompletionConfigDefault Build()
{
var model = new ModelConfig(
var model = new LdAiConfigTypes.ModelConfig(
_modelName,
new Dictionary<string, LdValue>(_modelParams),
new Dictionary<string, LdValue>(_customModelParams));
var provider = new ProviderConfig(_providerName);
var provider = new LdAiConfigTypes.ProviderConfig(_providerName);
return new LdAiCompletionConfigDefault(_enabled, _messages, model, provider);
}
}

/// <summary>
/// The prompts associated with the config.
/// </summary>
public IReadOnlyList<Message> Messages { get; }
public IReadOnlyList<LdAiConfigTypes.Message> Messages { get; }

internal LdAiCompletionConfigDefault(bool? enabled, IEnumerable<Message> messages,
ModelConfig model, ProviderConfig provider)
internal LdAiCompletionConfigDefault(bool? enabled, IEnumerable<LdAiConfigTypes.Message> messages,
LdAiConfigTypes.ModelConfig model, LdAiConfigTypes.ProviderConfig provider)
: base(enabled, model, provider)
{
Messages = messages?.ToList() ?? new List<Message>();
Messages = messages?.ToList() ?? new List<LdAiConfigTypes.Message>();
}

internal LdValue ToLdValue()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
namespace LaunchDarkly.Sdk.Server.Ai.Config;

/// <summary>
/// Base type for AI Configs returned by the SDK. Carries common fields and the
/// Shared type for AI Configs returned by the SDK. Carries common fields and the
/// <see cref="CreateTracker"/> factory. Cannot be constructed or subclassed outside the SDK.
/// </summary>
public abstract class LdAiConfigBase
public abstract class LdAiConfig
{
/// <summary>
/// The key of the AI Config that was evaluated.
Expand All @@ -18,12 +18,12 @@ public abstract class LdAiConfigBase
/// <summary>
/// Information about the model.
/// </summary>
public ModelConfig Model { get; }
public LdAiConfigTypes.ModelConfig Model { get; }

/// <summary>
/// Information about the model provider.
/// </summary>
public ProviderConfig Provider { get; }
public LdAiConfigTypes.ProviderConfig Provider { get; }

/// <summary>
/// Whether the config is enabled.
Expand All @@ -42,11 +42,11 @@ public abstract class LdAiConfigBase

/// <summary>
/// Factory that produces a tracker for the config. The factory is mode-agnostic — it
/// operates only on the shared base fields (<see cref="Key"/>, <see cref="Model"/>,
/// operates only on the shared fields (<see cref="Key"/>, <see cref="Model"/>,
/// <see cref="Provider"/>, <see cref="VariationKey"/>, <see cref="Version"/>), so the
/// same tracker class serves all config modes.
/// </summary>
private readonly Func<LdAiConfigBase, ILdAiConfigTracker> _trackerFactory;
private readonly Func<LdAiConfig, ILdAiConfigTracker> _trackerFactory;

/// <summary>
/// Creates a tracker that emits events related to this config. The returned tracker
Expand All @@ -56,24 +56,24 @@ public abstract class LdAiConfigBase
public ILdAiConfigTracker CreateTracker() => _trackerFactory(this);

/// <summary>
/// Constructs the base. Only public derived types in this assembly are intended
/// Constructs the config. Only public derived types in this assembly are intended
/// to extend this class.
/// </summary>
private protected LdAiConfigBase(
private protected LdAiConfig(
string key,
bool enabled,
string variationKey,
int version,
ModelConfig model,
ProviderConfig provider,
Func<LdAiConfigBase, ILdAiConfigTracker> trackerFactory)
LdAiConfigTypes.ModelConfig model,
LdAiConfigTypes.ProviderConfig provider,
Func<LdAiConfig, ILdAiConfigTracker> trackerFactory)
{
Key = key;
Enabled = enabled;
VariationKey = variationKey ?? "";
Version = version;
Model = model ?? new ModelConfig("", new Dictionary<string, LdValue>(), new Dictionary<string, LdValue>());
Provider = provider ?? new ProviderConfig("");
Model = model ?? new LdAiConfigTypes.ModelConfig("", new Dictionary<string, LdValue>(), new Dictionary<string, LdValue>());
Provider = provider ?? new LdAiConfigTypes.ProviderConfig("");
_trackerFactory = trackerFactory ?? throw new ArgumentNullException(nameof(trackerFactory));
}
}
36 changes: 36 additions & 0 deletions pkgs/sdk/server-ai/src/Config/LdAiConfigDefault.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System.Collections.Generic;

namespace LaunchDarkly.Sdk.Server.Ai.Config;

/// <summary>
/// Shared type for user-supplied default AI Configs. Carries the data fields common to
/// the mode-specific default config types. Cannot be constructed or subclassed outside the SDK.
/// </summary>
public abstract class LdAiConfigDefault
{
/// <summary>
/// Information about the model.
/// </summary>
public LdAiConfigTypes.ModelConfig Model { get; }

/// <summary>
/// Information about the model provider.
/// </summary>
public LdAiConfigTypes.ProviderConfig Provider { get; }

/// <summary>
/// Whether the config is enabled. Null indicates the user did not specify a value.
/// </summary>
public bool? Enabled { get; }

/// <summary>
/// Constructs the default config. Only public derived types in this assembly are intended
/// to extend this class.
/// </summary>
private protected LdAiConfigDefault(bool? enabled, LdAiConfigTypes.ModelConfig model, LdAiConfigTypes.ProviderConfig provider)
{
Enabled = enabled;
Model = model ?? new LdAiConfigTypes.ModelConfig("", new Dictionary<string, LdValue>(), new Dictionary<string, LdValue>());
Provider = provider ?? new LdAiConfigTypes.ProviderConfig("");
}
}
36 changes: 0 additions & 36 deletions pkgs/sdk/server-ai/src/Config/LdAiConfigDefaultBase.cs

This file was deleted.

Loading
Loading