diff --git a/lib/sdk/server-ai/src/main/java/com/launchdarkly/sdk/server/ai/LDAIClientImpl.java b/lib/sdk/server-ai/src/main/java/com/launchdarkly/sdk/server/ai/LDAIClientImpl.java index 140f7c7f..71569544 100644 --- a/lib/sdk/server-ai/src/main/java/com/launchdarkly/sdk/server/ai/LDAIClientImpl.java +++ b/lib/sdk/server-ai/src/main/java/com/launchdarkly/sdk/server/ai/LDAIClientImpl.java @@ -400,6 +400,8 @@ private Supplier trackerFactory( String graphKey) { String modelName = model != null && model.getName() != null ? model.getName() : ""; String providerName = provider != null && provider.getName() != null ? provider.getName() : ""; + String modelKey = model != null ? model.getModelKey() : null; + int modelVersion = model != null ? model.getModelVersion() : 1; int ver = version != null ? version : 1; return () -> new LDAIConfigTrackerImpl( client, @@ -409,6 +411,8 @@ private Supplier trackerFactory( ver, modelName, providerName, + modelKey, + modelVersion, context, graphKey, logger); diff --git a/lib/sdk/server-ai/src/main/java/com/launchdarkly/sdk/server/ai/datamodel/LDAIConfigTypes.java b/lib/sdk/server-ai/src/main/java/com/launchdarkly/sdk/server/ai/datamodel/LDAIConfigTypes.java index e6ccf122..d2ff9e1c 100644 --- a/lib/sdk/server-ai/src/main/java/com/launchdarkly/sdk/server/ai/datamodel/LDAIConfigTypes.java +++ b/lib/sdk/server-ai/src/main/java/com/launchdarkly/sdk/server/ai/datamodel/LDAIConfigTypes.java @@ -214,11 +214,20 @@ public String toString() { */ public static final class Model { private final String name; + private final String modelKey; + private final int modelVersion; private final Map parameters; private final Map custom; - private Model(String name, Map parameters, Map custom) { + private Model( + String name, + String modelKey, + int modelVersion, + Map parameters, + Map custom) { this.name = name; + this.modelKey = modelKey; + this.modelVersion = modelVersion; this.parameters = parameters; this.custom = custom; } @@ -232,6 +241,24 @@ public String getName() { return name; } + /** + * Returns the stable key of the model configuration. + * + * @return the model key, or {@code null} if none was specified + */ + public String getModelKey() { + return modelKey; + } + + /** + * Returns the version of the model configuration. + * + * @return the model version; defaults to {@code 1} + */ + public int getModelVersion() { + return modelVersion; + } + /** * Returns the model-specific parameters as an unmodifiable map. * @@ -290,18 +317,21 @@ public boolean equals(Object o) { } Model other = (Model) o; return Objects.equals(name, other.name) + && Objects.equals(modelKey, other.modelKey) + && modelVersion == other.modelVersion && parameters.equals(other.parameters) && custom.equals(other.custom); } @Override public int hashCode() { - return Objects.hash(name, parameters, custom); + return Objects.hash(name, modelKey, modelVersion, parameters, custom); } @Override public String toString() { - return "Model{name=" + name + ", parameters=" + parameters + ", custom=" + custom + '}'; + return "Model{name=" + name + ", modelKey=" + modelKey + ", modelVersion=" + modelVersion + + ", parameters=" + parameters + ", custom=" + custom + '}'; } /** @@ -309,6 +339,8 @@ public String toString() { */ public static final class Builder { private final String name; + private String modelKey; + private int modelVersion = 1; private Map parameters; private Map custom; @@ -316,6 +348,28 @@ private Builder(String name) { this.name = name; } + /** + * Sets the stable key of the model configuration. + * + * @param modelKey the model key; may be {@code null} + * @return this builder + */ + public Builder modelKey(String modelKey) { + this.modelKey = modelKey; + return this; + } + + /** + * Sets the version of the model configuration. + * + * @param modelVersion the model version + * @return this builder + */ + public Builder modelVersion(int modelVersion) { + this.modelVersion = modelVersion; + return this; + } + /** * Sets the model-specific parameters. The map is copied defensively. * @@ -350,7 +404,7 @@ public Model build() { Map cust = custom == null ? Collections.emptyMap() : Collections.unmodifiableMap(new HashMap<>(custom)); - return new Model(name, params, cust); + return new Model(name, modelKey, modelVersion, params, cust); } } } diff --git a/lib/sdk/server-ai/src/main/java/com/launchdarkly/sdk/server/ai/datamodel/LDAITrackingTypes.java b/lib/sdk/server-ai/src/main/java/com/launchdarkly/sdk/server/ai/datamodel/LDAITrackingTypes.java index fbae0264..95a07a9d 100644 --- a/lib/sdk/server-ai/src/main/java/com/launchdarkly/sdk/server/ai/datamodel/LDAITrackingTypes.java +++ b/lib/sdk/server-ai/src/main/java/com/launchdarkly/sdk/server/ai/datamodel/LDAITrackingTypes.java @@ -599,6 +599,8 @@ public static final class TrackData { private final int version; private final String modelName; private final String providerName; + private final String modelKey; + private final int modelVersion; private final String graphKey; /** @@ -610,6 +612,8 @@ public static final class TrackData { * @param version the config version * @param modelName the model name, or empty string when unknown * @param providerName the provider name, or empty string when unknown + * @param modelKey the stable model key, or {@code null} when unknown + * @param modelVersion the model version * @param graphKey the agent graph key, or {@code null} when not part of a graph */ public TrackData( @@ -619,6 +623,8 @@ public TrackData( int version, String modelName, String providerName, + String modelKey, + int modelVersion, String graphKey) { this.runId = Objects.requireNonNull(runId, "runId"); this.configKey = Objects.requireNonNull(configKey, "configKey"); @@ -626,6 +632,8 @@ public TrackData( this.version = version; this.modelName = modelName == null ? "" : modelName; this.providerName = providerName == null ? "" : providerName; + this.modelKey = modelKey == null || modelKey.trim().isEmpty() ? null : modelKey; + this.modelVersion = modelVersion; this.graphKey = graphKey; } @@ -683,6 +691,24 @@ public String getProviderName() { return providerName; } + /** + * Returns the stable model key. + * + * @return the model key, or {@code null} when unknown + */ + public String getModelKey() { + return modelKey; + } + + /** + * Returns the model version. + * + * @return the model version + */ + public int getModelVersion() { + return modelVersion; + } + /** * Returns the agent graph key. * @@ -695,7 +721,7 @@ public String getGraphKey() { /** * Builds an {@link LDValue} representation of this track data using camelCase keys. *

- * {@code variationKey} and {@code graphKey} are omitted when {@code null}. + * {@code variationKey}, {@code modelKey}, and {@code graphKey} are omitted when {@code null}. * * @return an {@link LDValue} object containing all non-null fields */ @@ -705,10 +731,14 @@ public LDValue toLDValue() { .put("configKey", configKey) .put("version", version) .put("modelName", modelName) - .put("providerName", providerName); + .put("providerName", providerName) + .put("modelVersion", modelVersion); if (variationKey != null) { b.put("variationKey", variationKey); } + if (modelKey != null) { + b.put("modelKey", modelKey); + } if (graphKey != null) { b.put("graphKey", graphKey); } diff --git a/lib/sdk/server-ai/src/main/java/com/launchdarkly/sdk/server/ai/internal/AIConfigParser.java b/lib/sdk/server-ai/src/main/java/com/launchdarkly/sdk/server/ai/internal/AIConfigParser.java index 40568454..9fbbf889 100644 --- a/lib/sdk/server-ai/src/main/java/com/launchdarkly/sdk/server/ai/internal/AIConfigParser.java +++ b/lib/sdk/server-ai/src/main/java/com/launchdarkly/sdk/server/ai/internal/AIConfigParser.java @@ -80,7 +80,11 @@ static Model parseModel(LDValue model) { if (model == null || model.getType() != LDValueType.OBJECT) { return null; } + LDValue modelVersion = model.get("modelVersion"); + int version = modelVersion.getType() == LDValueType.NUMBER ? modelVersion.intValue() : 1; return Model.builder(asStringOrNull(model.get("name"))) + .modelKey(trimToNull(asStringOrNull(model.get("modelKey")))) + .modelVersion(version) .parameters(LDValueConverter.toMap(model.get("parameters"))) .custom(LDValueConverter.toMap(model.get("custom"))) .build(); diff --git a/lib/sdk/server-ai/src/main/java/com/launchdarkly/sdk/server/ai/internal/LDAIConfigTrackerImpl.java b/lib/sdk/server-ai/src/main/java/com/launchdarkly/sdk/server/ai/internal/LDAIConfigTrackerImpl.java index 766d59e7..06f453fa 100644 --- a/lib/sdk/server-ai/src/main/java/com/launchdarkly/sdk/server/ai/internal/LDAIConfigTrackerImpl.java +++ b/lib/sdk/server-ai/src/main/java/com/launchdarkly/sdk/server/ai/internal/LDAIConfigTrackerImpl.java @@ -58,6 +58,8 @@ public final class LDAIConfigTrackerImpl implements LDAIConfigTracker { private final int version; private final String modelName; // empty string when unknown private final String providerName; // empty string when unknown + private final String modelKey; // nullable + private final int modelVersion; private final String graphKey; // nullable // Computed once at construction @@ -86,6 +88,8 @@ public final class LDAIConfigTrackerImpl implements LDAIConfigTracker { * @param version the config version * @param modelName the model name, or empty string when unknown * @param providerName the provider name, or empty string when unknown + * @param modelKey the stable model key, or {@code null} when unknown + * @param modelVersion the model version * @param context the evaluation context; must not be {@code null} * @param graphKey the agent graph key, or {@code null} when not part of a graph * @param logger the logger; must not be {@code null} @@ -98,6 +102,8 @@ public LDAIConfigTrackerImpl( int version, String modelName, String providerName, + String modelKey, + int modelVersion, LDContext context, String graphKey, LDLogger logger) { @@ -108,6 +114,8 @@ public LDAIConfigTrackerImpl( this.version = version; this.modelName = modelName == null ? "" : modelName; this.providerName = providerName == null ? "" : providerName; + this.modelKey = modelKey == null || modelKey.trim().isEmpty() ? null : modelKey; + this.modelVersion = modelVersion; this.context = Objects.requireNonNull(context, "context"); this.graphKey = graphKey; this.logger = Objects.requireNonNull(logger, "logger"); @@ -137,6 +145,8 @@ public static LDAIConfigTrackerImpl fromResumptionToken( d.getVersion(), "", // modelName not carried in token "", // providerName not carried in token + null, // modelKey not carried in token + 1, // modelVersion not carried in token context, d.getGraphKey(), logger); @@ -144,7 +154,16 @@ public static LDAIConfigTrackerImpl fromResumptionToken( @Override public TrackData getTrackData() { - return new TrackData(runId, configKey, variationKey, version, modelName, providerName, graphKey); + return new TrackData( + runId, + configKey, + variationKey, + version, + modelName, + providerName, + modelKey, + modelVersion, + graphKey); } @Override @@ -377,10 +396,14 @@ private ObjectBuilder baseData() { .put("configKey", configKey) .put("version", version) .put("modelName", modelName) - .put("providerName", providerName); + .put("providerName", providerName) + .put("modelVersion", modelVersion); if (variationKey != null) { b.put("variationKey", variationKey); } + if (modelKey != null) { + b.put("modelKey", modelKey); + } if (graphKey != null) { b.put("graphKey", graphKey); } diff --git a/lib/sdk/server-ai/src/test/java/com/launchdarkly/sdk/server/ai/LDAIClientImplTest.java b/lib/sdk/server-ai/src/test/java/com/launchdarkly/sdk/server/ai/LDAIClientImplTest.java index d2fa98cd..2840af00 100644 --- a/lib/sdk/server-ai/src/test/java/com/launchdarkly/sdk/server/ai/LDAIClientImplTest.java +++ b/lib/sdk/server-ai/src/test/java/com/launchdarkly/sdk/server/ai/LDAIClientImplTest.java @@ -134,6 +134,34 @@ public void completionConfigReturnsTypedConfigFromVariation() { assertThat(config.getMessages().get(0).getRole(), is(Message.Role.SYSTEM)); } + @Test + public void completionConfigPropagatesModelMetadataToTracker() { + String json = "{\"_ldMeta\":{\"enabled\":true,\"mode\":\"completion\"}," + + "\"model\":{\"name\":\"gpt-4\",\"modelKey\":\"custom-gpt\",\"modelVersion\":7}}"; + when(client.jsonValueVariation(anyString(), any(), any())).thenReturn(LDValue.parse(json)); + + AICompletionConfig config = ai.completionConfig("key", context, null, null); + + assertThat(config.getModel().getModelKey(), is("custom-gpt")); + assertThat(config.getModel().getModelVersion(), is(7)); + assertThat(config.createTracker().getTrackData().getModelKey(), is("custom-gpt")); + assertThat(config.createTracker().getTrackData().getModelVersion(), is(7)); + } + + @Test + public void completionConfigDefaultsMissingModelMetadata() { + String json = "{\"_ldMeta\":{\"enabled\":true,\"mode\":\"completion\"}," + + "\"model\":{\"name\":\"gpt-4\"}}"; + when(client.jsonValueVariation(anyString(), any(), any())).thenReturn(LDValue.parse(json)); + + AICompletionConfig config = ai.completionConfig("key", context, null, null); + + assertThat(config.getModel().getModelKey(), is(nullValue())); + assertThat(config.getModel().getModelVersion(), is(1)); + assertThat(config.createTracker().getTrackData().getModelKey(), is(nullValue())); + assertThat(config.createTracker().getTrackData().getModelVersion(), is(1)); + } + @Test public void interpolationExposesContextAsLdctx() { String json = "{\"_ldMeta\":{\"enabled\":true,\"mode\":\"completion\"}," diff --git a/lib/sdk/server-ai/src/test/java/com/launchdarkly/sdk/server/ai/internal/AIConfigParserTest.java b/lib/sdk/server-ai/src/test/java/com/launchdarkly/sdk/server/ai/internal/AIConfigParserTest.java index a38770a7..5459f586 100644 --- a/lib/sdk/server-ai/src/test/java/com/launchdarkly/sdk/server/ai/internal/AIConfigParserTest.java +++ b/lib/sdk/server-ai/src/test/java/com/launchdarkly/sdk/server/ai/internal/AIConfigParserTest.java @@ -22,7 +22,8 @@ public class AIConfigParserTest { public void parsesFullCompletionConfig() { LDValue value = LDValue.parse("{" + "\"_ldMeta\":{\"variationKey\":\"v1\",\"enabled\":true,\"version\":3,\"mode\":\"completion\"}," - + "\"model\":{\"name\":\"gpt-4\",\"parameters\":{\"temperature\":0.7,\"maxTokens\":100}," + + "\"model\":{\"name\":\"gpt-4\",\"modelKey\":\"custom-gpt\",\"modelVersion\":7," + + "\"parameters\":{\"temperature\":0.7,\"maxTokens\":100}," + "\"custom\":{\"team\":\"core\"}}," + "\"provider\":{\"name\":\"openai\"}," + "\"messages\":[{\"role\":\"system\",\"content\":\"You are {{persona}}.\"}," @@ -39,6 +40,8 @@ public void parsesFullCompletionConfig() { assertThat(parsed.getVersion(), is(3)); assertThat(parsed.getMode(), is(Mode.COMPLETION)); assertThat(parsed.getModel().getName(), is("gpt-4")); + assertThat(parsed.getModel().getModelKey(), is("custom-gpt")); + assertThat(parsed.getModel().getModelVersion(), is(7)); assertThat(parsed.getModel().getParameter("temperature"), is((Object) 0.7)); assertThat(parsed.getModel().getParameter("maxTokens"), is((Object) 100L)); assertThat(parsed.getModel().getCustom("team"), is((Object) "core")); @@ -53,6 +56,23 @@ public void parsesFullCompletionConfig() { assertThat(parsed.getTools().get("search").getType(), is("function")); } + @Test + public void modelMetadataDefaultsWhenMissingOrWrongType() { + AIConfigFlagValue missing = AIConfigParser.parse( + LDValue.parse("{\"model\":{\"name\":\"gpt-4\"}}")); + assertThat(missing.getModel().getModelKey(), is(nullValue())); + assertThat(missing.getModel().getModelVersion(), is(1)); + + AIConfigFlagValue wrongType = AIConfigParser.parse( + LDValue.parse("{\"model\":{\"modelKey\":3,\"modelVersion\":\"two\"}}")); + assertThat(wrongType.getModel().getModelKey(), is(nullValue())); + assertThat(wrongType.getModel().getModelVersion(), is(1)); + + AIConfigFlagValue blankKey = AIConfigParser.parse( + LDValue.parse("{\"model\":{\"modelKey\":\" \"}}")); + assertThat(blankKey.getModel().getModelKey(), is(nullValue())); + } + @Test public void parsesAgentInstructions() { LDValue value = LDValue.parse("{\"_ldMeta\":{\"enabled\":true,\"mode\":\"agent\"}," diff --git a/lib/sdk/server-ai/src/test/java/com/launchdarkly/sdk/server/ai/internal/LDAIConfigTrackerImplTest.java b/lib/sdk/server-ai/src/test/java/com/launchdarkly/sdk/server/ai/internal/LDAIConfigTrackerImplTest.java index ffcadaa9..02261893 100644 --- a/lib/sdk/server-ai/src/test/java/com/launchdarkly/sdk/server/ai/internal/LDAIConfigTrackerImplTest.java +++ b/lib/sdk/server-ai/src/test/java/com/launchdarkly/sdk/server/ai/internal/LDAIConfigTrackerImplTest.java @@ -6,6 +6,7 @@ import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.mockito.ArgumentMatchers.any; @@ -61,6 +62,8 @@ public class LDAIConfigTrackerImplTest { private static final int VERSION = 3; private static final String MODEL_NAME = "gpt-4"; private static final String PROVIDER_NAME = "openai"; + private static final String MODEL_KEY = "custom-gpt"; + private static final int MODEL_VERSION = 7; @Before public void setUp() { @@ -71,9 +74,14 @@ public void setUp() { } private LDAIConfigTrackerImpl makeTracker(String variationKey) { + return makeTracker(variationKey, MODEL_KEY, MODEL_VERSION); + } + + private LDAIConfigTrackerImpl makeTracker( + String variationKey, String modelKey, int modelVersion) { return new LDAIConfigTrackerImpl( client, RUN_ID, CONFIG_KEY, variationKey, VERSION, - MODEL_NAME, PROVIDER_NAME, CONTEXT, null, logger); + MODEL_NAME, PROVIDER_NAME, modelKey, modelVersion, CONTEXT, null, logger); } private List warnings() { @@ -98,6 +106,8 @@ private LDValue baseExpectedData() { .put("version", VERSION) .put("modelName", MODEL_NAME) .put("providerName", PROVIDER_NAME) + .put("modelKey", MODEL_KEY) + .put("modelVersion", MODEL_VERSION) .build(); } @@ -112,6 +122,8 @@ public void getTrackDataReturnsCorrectFields() { assertThat(data.getVersion(), is(VERSION)); assertThat(data.getModelName(), is(MODEL_NAME)); assertThat(data.getProviderName(), is(PROVIDER_NAME)); + assertThat(data.getModelKey(), is(MODEL_KEY)); + assertThat(data.getModelVersion(), is(MODEL_VERSION)); assertThat(data.getGraphKey(), is(nullValue())); } @@ -139,6 +151,20 @@ public void resumptionTokenRoundTrips() throws Exception { assertThat(d.getGraphKey(), is(nullValue())); } + @Test + public void resumptionTokenExcludesModelMetadata() { + String token = tracker.getResumptionToken(); + String decodedJson = new String( + java.util.Base64.getUrlDecoder().decode(token), java.nio.charset.StandardCharsets.UTF_8); + assertThat(decodedJson, not(containsString("modelKey"))); + assertThat(decodedJson, not(containsString("modelVersion"))); + + // Changing only model metadata must not change the encoded token, since decode() has no + // model fields to carry it and encode() never receives them. + LDAIConfigTrackerImpl other = makeTracker(VARIATION_KEY, "different-model", 99); + assertThat(other.getResumptionToken(), is(token)); + } + @Test public void fromResumptionTokenRestoresCorrectFields() { String token = tracker.getResumptionToken(); @@ -151,6 +177,8 @@ public void fromResumptionTokenRestoresCorrectFields() { assertThat(data.getVersion(), is(VERSION)); assertThat(data.getModelName(), is("")); // not in token assertThat(data.getProviderName(), is("")); // not in token + assertThat(data.getModelKey(), is(nullValue())); // not in token + assertThat(data.getModelVersion(), is(1)); // not in token } // ---- trackDuration -------------------------------------------------------- @@ -368,6 +396,7 @@ public void trackToolCallEmitsOnEveryCall() { .put("runId", RUN_ID).put("configKey", CONFIG_KEY) .put("variationKey", VARIATION_KEY).put("version", VERSION) .put("modelName", MODEL_NAME).put("providerName", PROVIDER_NAME) + .put("modelKey", MODEL_KEY).put("modelVersion", MODEL_VERSION) .put("toolKey", "search") .build(); @@ -381,6 +410,7 @@ public void trackToolCallEmitsOnEveryCall() { .put("runId", RUN_ID).put("configKey", CONFIG_KEY) .put("variationKey", VARIATION_KEY).put("version", VERSION) .put("modelName", MODEL_NAME).put("providerName", PROVIDER_NAME) + .put("modelKey", MODEL_KEY).put("modelVersion", MODEL_VERSION) .put("toolKey", "fetch") .build(); verify(client, times(1)).trackMetric( @@ -415,6 +445,7 @@ public void trackJudgeResultEmitsWhenSampledAndSucceeded() { .put("runId", RUN_ID).put("configKey", CONFIG_KEY) .put("variationKey", VARIATION_KEY).put("version", VERSION) .put("modelName", MODEL_NAME).put("providerName", PROVIDER_NAME) + .put("modelKey", MODEL_KEY).put("modelVersion", MODEL_VERSION) .put("judgeConfigKey", "my-judge") .build(); @@ -650,13 +681,41 @@ public void variationKeyIncludedInPayloadWhenPresent() { assertThat(dataCaptor.getValue().get("variationKey").stringValue(), is(VARIATION_KEY)); } + // ---- model metadata inclusion -------------------------------------------- + + @Test + public void modelMetadataIncludedInPayloadWhenPresent() { + tracker.trackSuccess(); + ArgumentCaptor dataCaptor = ArgumentCaptor.forClass(LDValue.class); + verify(client).trackMetric(eq("$ld:ai:generation:success"), any(), dataCaptor.capture(), anyDouble()); + assertThat(dataCaptor.getValue().get("modelKey").stringValue(), is(MODEL_KEY)); + assertThat(dataCaptor.getValue().get("modelVersion").intValue(), is(MODEL_VERSION)); + } + + @Test + public void blankModelKeyOmittedFromTrackDataAndPayload() { + for (String blankModelKey : Arrays.asList(null, "", " ")) { + LDAIConfigTrackerImpl blankTracker = + makeTracker(VARIATION_KEY, blankModelKey, MODEL_VERSION); + assertThat(blankTracker.getTrackData().getModelKey(), is(nullValue())); + assertThat(blankTracker.getTrackData().toLDValue().get("modelKey").isNull(), is(true)); + } + + LDAIConfigTrackerImpl t = makeTracker(VARIATION_KEY, " ", MODEL_VERSION); + t.trackSuccess(); + ArgumentCaptor dataCaptor = ArgumentCaptor.forClass(LDValue.class); + verify(client).trackMetric(eq("$ld:ai:generation:success"), any(), dataCaptor.capture(), anyDouble()); + assertThat(dataCaptor.getValue().get("modelKey").isNull(), is(true)); + assertThat(dataCaptor.getValue().get("modelVersion").intValue(), is(MODEL_VERSION)); + } + // ---- graphKey inclusion --------------------------------------------------- @Test public void graphKeyIncludedInPayloadWhenSet() { LDAIConfigTrackerImpl t = new LDAIConfigTrackerImpl( client, RUN_ID, CONFIG_KEY, VARIATION_KEY, VERSION, - MODEL_NAME, PROVIDER_NAME, CONTEXT, "my-graph", logger); + MODEL_NAME, PROVIDER_NAME, MODEL_KEY, MODEL_VERSION, CONTEXT, "my-graph", logger); t.trackSuccess(); ArgumentCaptor dataCaptor = ArgumentCaptor.forClass(LDValue.class); verify(client).trackMetric(eq("$ld:ai:generation:success"), any(), dataCaptor.capture(), anyDouble()); @@ -727,12 +786,12 @@ public void trackSuccessAtMostOnceUnderConcurrency() throws InterruptedException @Test(expected = NullPointerException.class) public void constructorRejectsNullClient() { new LDAIConfigTrackerImpl(null, RUN_ID, CONFIG_KEY, VARIATION_KEY, VERSION, - MODEL_NAME, PROVIDER_NAME, CONTEXT, null, logger); + MODEL_NAME, PROVIDER_NAME, MODEL_KEY, MODEL_VERSION, CONTEXT, null, logger); } @Test(expected = NullPointerException.class) public void constructorRejectsNullContext() { new LDAIConfigTrackerImpl(client, RUN_ID, CONFIG_KEY, VARIATION_KEY, VERSION, - MODEL_NAME, PROVIDER_NAME, null, null, logger); + MODEL_NAME, PROVIDER_NAME, MODEL_KEY, MODEL_VERSION, null, null, logger); } }