-
Notifications
You must be signed in to change notification settings - Fork 8
refactor: implement AI Client #36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 22 commits
f25033c
ccdbada
8049816
8c34ad5
43aa7aa
25142ac
0d58582
37f395d
c74c9e3
7b0e446
44956bc
42a6b05
59dc7e7
949c635
e7d8fc2
36152b8
96b8fb0
3abb9e5
bdfe78a
dc4fe3d
796b85f
fa56649
aa1310a
b5a354d
e6e4ee7
d9b343b
6ec3f94
8c18ca5
ce64ccf
c513a2f
dd3492d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,159 @@ | ||
| using System.Collections.Generic; | ||
| using System.Linq; | ||
| using LaunchDarkly.Sdk.Server.Ai.DataModel; | ||
|
|
||
| namespace LaunchDarkly.Sdk.Server.Ai.Config; | ||
|
|
||
| /// <summary> | ||
| /// Represents an AI configuration, which contains model parameters and prompt messages. | ||
| /// </summary> | ||
| public record LdAiConfig | ||
| { | ||
|
|
||
| /// <summary> | ||
| /// Represents a single message, which is part of a prompt. | ||
| /// </summary> | ||
| public record Message | ||
| { | ||
| /// <summary> | ||
| /// The content of the message, which may contain Mustache templates. | ||
| /// </summary> | ||
| public readonly string Content; | ||
|
|
||
| /// <summary> | ||
| /// The role of the message. | ||
| /// </summary> | ||
| public readonly Role Role; | ||
|
|
||
| internal Message(string content, Role role) | ||
| { | ||
| Content = content; | ||
| Role = role; | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Builder for constructing an LdAiConfig instance, which can be passed as the default | ||
| /// value to the AI Client's <see cref="LdAiClient.ModelConfig"/> method. | ||
| /// </summary> | ||
| public class Builder | ||
| { | ||
| private readonly List<Message> _prompt; | ||
| private bool _enabled; | ||
| private readonly Dictionary<string, object> _modelParams; | ||
|
|
||
|
|
||
| /// <summary> | ||
| /// Constructs a new builder. By default, the config will be disabled, with no prompt | ||
| /// messages or model parameters. | ||
| /// </summary> | ||
| public Builder() | ||
| { | ||
| _enabled = false; | ||
| _prompt = new List<Message>(); | ||
| _modelParams = new Dictionary<string, object>(); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Adds a prompt message with the given content and role. The default role is <see cref="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 AddPromptMessage(string content, Role role = Role.User) | ||
| { | ||
| _prompt.Add(new Message(content, role)); | ||
| return this; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Disables the config. | ||
| /// </summary> | ||
| /// <returns>the builder</returns> | ||
| public Builder Disable() => SetEnabled(false); | ||
|
|
||
| /// <summary> | ||
| /// Enables the config. | ||
| /// </summary> | ||
| /// <returns>the builder</returns> | ||
| public Builder Enable() => SetEnabled(true); | ||
|
|
||
| /// <summary> | ||
| /// Sets the enabled state of the config based on a boolean. | ||
| /// </summary> | ||
| /// <param name="enabled">whether the config is enabled</param> | ||
| /// <returns>the builder</returns> | ||
| public Builder SetEnabled(bool enabled) | ||
| { | ||
| _enabled = enabled; | ||
| return this; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Sets a parameter for the model. The value may be any object. | ||
| /// </summary> | ||
| /// <param name="name">the parameter name</param> | ||
| /// <param name="value">the parameter value</param> | ||
| /// <returns>the builder</returns> | ||
| public Builder SetModelParam(string name, object value) | ||
| { | ||
| _modelParams[name] = value; | ||
| return this; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Builds the LdAiConfig instance. | ||
| /// </summary> | ||
| /// <returns>a new LdAiConfig</returns> | ||
| public LdAiConfig Build() | ||
| { | ||
| return new LdAiConfig(_enabled, _prompt, new Meta(), _modelParams); | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// The prompts associated with the config. | ||
| /// </summary> | ||
| public readonly IReadOnlyList<Message> Prompt; | ||
|
|
||
| /// <summary> | ||
| /// The model parameters associated with the config. | ||
| /// </summary> | ||
| public readonly IReadOnlyDictionary<string, object> Model; | ||
|
|
||
|
|
||
|
|
||
| internal LdAiConfig(bool enabled, IEnumerable<Message> prompt, Meta meta, IReadOnlyDictionary<string, object> model) | ||
| { | ||
| Model = model ?? new Dictionary<string, object>(); | ||
| Prompt = prompt?.ToList() ?? new List<Message>(); | ||
| VersionKey = meta?.VersionKey ?? ""; | ||
| Enabled = enabled; | ||
| } | ||
|
|
||
|
|
||
| /// <summary> | ||
| /// Creates a new LdAiConfig builder. | ||
| /// </summary> | ||
| /// <returns>a new builder</returns> | ||
| public static Builder New() => new(); | ||
cwaldren-ld marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| /// <summary> | ||
| /// Returns true if the config is enabled. | ||
| /// </summary> | ||
| /// <returns>true if enabled</returns> | ||
| public bool Enabled { get; } | ||
|
|
||
|
|
||
| /// <summary> | ||
| /// This field meant for internal LaunchDarkly usage. | ||
| /// </summary> | ||
| public string VersionKey { get; } | ||
|
|
||
| /// <summary> | ||
| /// Convenient helper that returns a disabled LdAiConfig. | ||
| /// </summary> | ||
| public static LdAiConfig Disabled = New().Disable().Build(); | ||
|
|
||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| using System.Collections.Generic; | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is some duplication here. This file is meant to contain classes that can be directly JSON deserialized, but this doesn't lend itself to the user-facing types. For instance, these fields have I can't make these internal (deserialization seems to fail) and I can't use I may be missing a more idiomatic way.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should be able to tell it to use a parameterized constructor |
||
| using System.Text.Json.Serialization; | ||
|
|
||
| namespace LaunchDarkly.Sdk.Server.Ai.DataModel; | ||
|
|
||
| /// <summary> | ||
| /// Represents the role of the prompt message. | ||
| /// </summary> | ||
| public enum Role | ||
| { | ||
| /// <summary> | ||
| /// User role. | ||
| /// </summary> | ||
| User, | ||
| /// <summary> | ||
| /// System role. | ||
| /// </summary> | ||
| System, | ||
| /// <summary> | ||
| /// Assistant role. | ||
| /// </summary> | ||
| Assistant | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Represents the JSON serialization of the Meta field. | ||
| /// </summary> | ||
| public class Meta | ||
| { | ||
| /// <summary> | ||
| /// The version key. | ||
| /// </summary> | ||
| [JsonPropertyName("versionKey")] | ||
| public string VersionKey { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// If the config is enabled. | ||
| /// </summary> | ||
|
|
||
cwaldren-ld marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| [JsonPropertyName("enabled")] | ||
| public bool Enabled { get; set; } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Represents the JSON serialization of a Message. | ||
| /// </summary> | ||
| public class Message | ||
| { | ||
| /// <summary> | ||
| /// The content. | ||
| /// </summary> | ||
| [JsonPropertyName("content")] | ||
| public string Content { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// The role. | ||
| /// </summary> | ||
| [JsonPropertyName("role")] | ||
| [JsonConverter(typeof(JsonStringEnumConverter))] | ||
| public Role Role { get; set; } | ||
| } | ||
|
|
||
|
|
||
| /// <summary> | ||
| /// Represents the JSON serialization of an AiConfig. | ||
| /// </summary> | ||
|
|
||
| public class AiConfig | ||
| { | ||
| /// <summary> | ||
| /// The prompt. | ||
| /// </summary> | ||
| [JsonPropertyName("prompt")] | ||
| public List<Message> Prompt { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// LaunchDarkly metadata. | ||
| /// </summary> | ||
|
|
||
| [JsonPropertyName("_ldMeta")] | ||
| public Meta Meta { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// The model params; | ||
| /// </summary> | ||
|
|
||
| [JsonPropertyName("model")] | ||
| public Dictionary<string, object> Model { get; set; } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| namespace LaunchDarkly.Sdk.Server.Ai.Interfaces; | ||
|
|
||
| /// <summary> | ||
| /// TBD | ||
| /// </summary> | ||
| public interface ILaunchDarklyClient | ||
| { | ||
| /// <summary> | ||
| /// TBD | ||
| /// </summary> | ||
| /// <param name="key"></param> | ||
| /// <param name="context"></param> | ||
| /// <param name="defaultValue"></param> | ||
| /// <returns></returns> | ||
| EvaluationDetail<LdValue> JsonVariationDetail(string key, Context context, LdValue defaultValue); | ||
cwaldren-ld marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
|
|
||
| /// <summary> | ||
| /// TBD | ||
| /// </summary> | ||
| /// <param name="name"></param> | ||
| /// <param name="context"></param> | ||
| /// <param name="data"></param> | ||
| /// <param name="metricValue"></param> | ||
| void Track(string name, Context context, LdValue data, double metricValue); | ||
|
|
||
| /// <summary> | ||
| /// TBD | ||
| /// </summary> | ||
| void Dispose(); | ||
|
|
||
| /// <summary> | ||
| /// TBD | ||
| /// </summary> | ||
| /// <returns></returns> | ||
| ILogger GetLogger(); | ||
|
|
||
cwaldren-ld marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| namespace LaunchDarkly.Sdk.Server.Ai.Interfaces; | ||
|
|
||
| /// <summary> | ||
| /// Log interface required by the AI Client. | ||
| /// </summary> | ||
| public interface ILogger | ||
| { | ||
|
|
||
cwaldren-ld marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| /// <summary> | ||
| /// Log an error. | ||
| /// </summary> | ||
| /// <param name="format">format string</param> | ||
| /// <param name="allParams">parameters</param> | ||
| void Error(string format, params object[] allParams); | ||
|
|
||
| /// <summary> | ||
| /// Log a warning. | ||
| /// </summary> | ||
| /// <param name="format">format string</param> | ||
| /// <param name="allParams">parameters</param> | ||
| void Warn(string format, params object[] allParams); | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.