Skip to content
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

Aws bedrock llm support #1837

Merged
merged 76 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
67fb59d
WIP
jasonjkeller Feb 8, 2024
e2e6381
WIP
jasonjkeller Feb 15, 2024
3e08036
Report Llm errors
jasonjkeller Feb 15, 2024
5c994f3
Refactoring
jasonjkeller Feb 20, 2024
170b360
Refactoring
jasonjkeller Feb 21, 2024
db6b359
Refactoring
jasonjkeller Feb 21, 2024
dbdcaea
Merge branch 'main' of github.com:newrelic/newrelic-java-agent into a…
jasonjkeller Feb 21, 2024
443b600
Refactoring
jasonjkeller Feb 23, 2024
8087376
Merge branch 'main' of github.com:newrelic/newrelic-java-agent into a…
jasonjkeller Feb 23, 2024
a2ba5e1
Refactoring. Add llm custom attributes.
jasonjkeller Feb 24, 2024
a3c2f2a
Refactoring. Wire up async client.
jasonjkeller Feb 26, 2024
cfc5823
Add config. Some cleanup.
jasonjkeller Feb 27, 2024
78b9166
Cleanup
jasonjkeller Feb 27, 2024
a0ad252
Cleanup
jasonjkeller Feb 28, 2024
fe6268d
Cleanup logging around parsing errors
jasonjkeller Feb 28, 2024
7c09a4d
Fix some async client issues
jasonjkeller Feb 28, 2024
549692c
Add support for Jurassic and Titan models. Some refactoring.
jasonjkeller Mar 6, 2024
48fbd7d
Add support for Cohere models
jasonjkeller Mar 6, 2024
842bcc2
Add support for Meta Llama 2 models
jasonjkeller Mar 6, 2024
bafd7cf
Cleanup
jasonjkeller Mar 6, 2024
9160fff
Add readme for each model
jasonjkeller Mar 7, 2024
1c353e6
Cleanup
jasonjkeller Mar 7, 2024
100f047
Add ai_monitoring stanza to default yaml config file
jasonjkeller Mar 7, 2024
6b0b88c
Cleanup readme
jasonjkeller Mar 7, 2024
55b18ab
Remove logic for parsing input/output token counts
jasonjkeller Mar 7, 2024
60b520a
Cleanup readme
jasonjkeller Mar 7, 2024
7ac8568
Refactor to handle cases that should generate multiple events
jasonjkeller Mar 8, 2024
c601590
Remove role from interface
jasonjkeller Mar 8, 2024
3a8fb76
End segment in case of exception
jasonjkeller Mar 8, 2024
400b198
Add config supportability metrics
jasonjkeller Mar 12, 2024
eccec66
Add ModelInvocation tests
jasonjkeller Mar 13, 2024
3a86c87
Cleanup tests
jasonjkeller Mar 13, 2024
0a36968
Merge branch 'main' of github.com:newrelic/newrelic-java-agent into a…
jasonjkeller Mar 13, 2024
09a64a9
Add tests for async Bedrock client
jasonjkeller Mar 13, 2024
cb7753d
Add copyright header
jasonjkeller Mar 13, 2024
db637ec
add ai monitoring interface
deleonenriqueta Mar 15, 2024
b22730e
added ai monitoring implementation
deleonenriqueta Mar 15, 2024
440fce9
create builder class
deleonenriqueta Mar 15, 2024
cc31717
add test suite for builder class
deleonenriqueta Mar 15, 2024
8996831
start test suite for feedbackEvent recorder class
deleonenriqueta Mar 15, 2024
5391ed5
add getAiMonitoring to Agent interface
deleonenriqueta Mar 15, 2024
edec98e
update locations where Agent interface is implemented
deleonenriqueta Mar 15, 2024
f8e1853
Merge branch 'aws-bedrock-support' into aim-tokenCountCallback
deleonenriqueta Mar 18, 2024
40594b5
refactored naming of ai api implementation class
deleonenriqueta Mar 25, 2024
e2b3808
updated argument type for tokenCount
deleonenriqueta Mar 25, 2024
bc9d7ef
created callback interface
deleonenriqueta Mar 27, 2024
c68c478
created singleton holder class to store the users callback method
deleonenriqueta Mar 27, 2024
eb4d421
added example for setting a tokenCount callback
deleonenriqueta Mar 27, 2024
cd0926c
name refactoring
deleonenriqueta Mar 27, 2024
c6d39e4
created callback interface
deleonenriqueta Mar 27, 2024
cfa407b
added setLlmTokenCountCallback method and a supportability metric
deleonenriqueta Mar 27, 2024
f545f47
added setUp with LlmTokenCountCallback and updated tokenCount
deleonenriqueta Mar 28, 2024
a1cddff
added assertions for token_count value
deleonenriqueta Mar 28, 2024
bc01907
refactored builders to invoke getTokenCount
deleonenriqueta Mar 28, 2024
8ee1646
update tests to include callback setting
deleonenriqueta Mar 28, 2024
e9bdf5b
refactored AiMonitoringImplTest
deleonenriqueta Mar 28, 2024
1ba9614
added getTokenCount method
deleonenriqueta Mar 28, 2024
3ff383d
updates for class movement
deleonenriqueta Mar 28, 2024
c2722bf
moved LlmTokenCountCallbackHolder to agent-bridge and AiMonitoringImpl
deleonenriqueta Apr 1, 2024
6b9dabe
added supportability metric to track when tokenCountCallbacks are set
deleonenriqueta Apr 1, 2024
9e692ec
implemented getTokenCount method to check for nulls and return token
deleonenriqueta Apr 1, 2024
bee19fe
updated imports
deleonenriqueta Apr 1, 2024
1b4df47
updated return type and comments
deleonenriqueta Apr 1, 2024
51e1285
refactored class
deleonenriqueta Apr 1, 2024
18827a6
moved classes to update callback accessibility
deleonenriqueta Apr 1, 2024
9443c6b
refactored naming and initialized optional attrs to be null
deleonenriqueta Apr 1, 2024
088123d
moved the ai-monitoring implementation, refactored imports and updated
deleonenriqueta Apr 1, 2024
82fecfc
updated AiMonitoringImpl import
deleonenriqueta Apr 1, 2024
db09206
added NoOpAiMonitoring, updated implementations
deleonenriqueta Apr 1, 2024
89b4efe
Merge branch 'main' into aim-tokenCountCallback
deleonenriqueta Apr 1, 2024
387e32f
update naming for attributes
deleonenriqueta Apr 2, 2024
fd730a8
Merge branch 'main' of github.com:newrelic/newrelic-java-agent into a…
jasonjkeller Apr 2, 2024
c78d4fd
Merge branch 'aim-tokenCountCallback' of github.com:newrelic/newrelic…
jasonjkeller Apr 2, 2024
66fb720
update tests with refactored attribute names
deleonenriqueta Apr 2, 2024
434c355
Disable AIM if HSM is enabled
jasonjkeller Apr 2, 2024
70736f0
Merge branch 'aws-bedrock-llm-support' of github.com:newrelic/newreli…
jasonjkeller Apr 2, 2024
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 @@ -7,6 +7,7 @@

package com.newrelic.agent.bridge;

import com.newrelic.api.agent.AiMonitoring;
import com.newrelic.api.agent.Config;
import com.newrelic.api.agent.ErrorApi;
import com.newrelic.api.agent.Insights;
Expand All @@ -18,6 +19,8 @@
import java.util.Collections;
import java.util.Map;

import static com.newrelic.agent.bridge.NoOpAiMonitoring.INSTANCE;

class NoOpAgent implements Agent {

static final Agent INSTANCE = new NoOpAgent();
Expand Down Expand Up @@ -65,6 +68,11 @@ public Insights getInsights() {
return NoOpInsights.INSTANCE;
}

@Override
public AiMonitoring getAiMonitoring() {
return NoOpAiMonitoring.INSTANCE;
}

@Override
public ErrorApi getErrorApi() {
return NoOpErrorApi.INSTANCE;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.newrelic.agent.bridge;

import com.newrelic.api.agent.AiMonitoring;
import com.newrelic.api.agent.LlmTokenCountCallback;

import java.util.Map;

public class NoOpAiMonitoring implements AiMonitoring {

static final AiMonitoring INSTANCE = new NoOpAiMonitoring();

private NoOpAiMonitoring() {}

@Override
public void recordLlmFeedbackEvent(Map<String, Object> llmFeedbackEventAttributes) {
}

@Override
public void setLlmTokenCountCallback(LlmTokenCountCallback llmTokenCountCallback) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
public class NoOpTransaction implements Transaction {
public static final Transaction INSTANCE = new NoOpTransaction();
public static final NoOpMap<String, Object> AGENT_ATTRIBUTES = new NoOpMap<>();
public static final NoOpMap<String, Object> USER_ATTRIBUTES = new NoOpMap<>();

@Override
public void beforeSendResponseHeaders() {
Expand Down Expand Up @@ -153,6 +154,11 @@ public Map<String, Object> getAgentAttributes() {
return AGENT_ATTRIBUTES;
}

@Override
public Map<String, Object> getUserAttributes() {
return USER_ATTRIBUTES;
}

@Override
public boolean registerAsyncActivity(Object activityContext) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
public interface Transaction extends com.newrelic.api.agent.Transaction {

Map<String, Object> getAgentAttributes();
Map<String, Object> getUserAttributes();

/**
* Sets the current transaction's name.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
*
* * Copyright 2024 New Relic Corporation. All rights reserved.
* * SPDX-License-Identifier: Apache-2.0
*
*/

package com.newrelic.agent.bridge.aimonitoring;

import com.newrelic.api.agent.Config;
import com.newrelic.api.agent.NewRelic;

import java.util.logging.Level;

public class AiMonitoringUtils {
// Enabled defaults
private static final boolean AI_MONITORING_ENABLED_DEFAULT = false;
private static final boolean AI_MONITORING_STREAMING_ENABLED_DEFAULT = true;
private static final boolean AI_MONITORING_RECORD_CONTENT_ENABLED_DEFAULT = true;
private static final boolean HIGH_SECURITY_ENABLED_DEFAULT = false;

/**
* Check if ai_monitoring features are enabled.
* Indicates whether LLM instrumentation will be registered. If this is set to False, no metrics, events, or spans are to be sent.
*
* @return true if AI monitoring is enabled, else false
*/
public static boolean isAiMonitoringEnabled() {
Config config = NewRelic.getAgent().getConfig();
Boolean aimEnabled = config.getValue("ai_monitoring.enabled", AI_MONITORING_ENABLED_DEFAULT);
Boolean highSecurity = config.getValue("high_security", HIGH_SECURITY_ENABLED_DEFAULT);

if (highSecurity || !aimEnabled) {
aimEnabled = false;
String disabledReason = highSecurity ? "High Security Mode." : "agent config.";
NewRelic.getAgent().getLogger().log(Level.FINE, "AIM: AI Monitoring is disabled due to " + disabledReason);
NewRelic.incrementCounter("Supportability/Java/ML/Disabled");
} else {
NewRelic.incrementCounter("Supportability/Java/ML/Enabled");
}

return aimEnabled;
}

/**
* Check if ai_monitoring.streaming features are enabled.
*
* @return true if streaming is enabled, else false
*/
public static boolean isAiMonitoringStreamingEnabled() {
Boolean enabled = NewRelic.getAgent().getConfig().getValue("ai_monitoring.streaming.enabled", AI_MONITORING_STREAMING_ENABLED_DEFAULT);

if (enabled) {
NewRelic.incrementCounter("Supportability/Java/ML/Streaming/Enabled");
} else {
NewRelic.incrementCounter("Supportability/Java/ML/Streaming/Disabled");
}

return enabled;
}

/**
* Check if the input and output content should be added to LLM events.
*
* @return true if adding content is enabled, else false
*/
public static boolean isAiMonitoringRecordContentEnabled() {
Boolean enabled = NewRelic.getAgent().getConfig().getValue("ai_monitoring.record_content.enabled", AI_MONITORING_RECORD_CONTENT_ENABLED_DEFAULT);

if (enabled) {
NewRelic.incrementCounter("Supportability/Java/ML/RecordContent/Enabled");
} else {
NewRelic.incrementCounter("Supportability/Java/ML/RecordContent/Disabled");
}

return enabled;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.newrelic.agent.bridge.aimonitoring;

import com.newrelic.api.agent.LlmTokenCountCallback;

/**
* A thread-safe holder for an instance of {@link LlmTokenCountCallback}.
* This class provides methods for setting and retrieving the callback instance.
*/
public class LlmTokenCountCallbackHolder {

private static volatile LlmTokenCountCallback llmTokenCountCallback = null;

/**
* Sets the {@link LlmTokenCountCallback} instance to be stored.
*
* @param newLlmTokenCountCallback the callback instance
*/
public static void setLlmTokenCountCallback(LlmTokenCountCallback newLlmTokenCountCallback) {
llmTokenCountCallback = newLlmTokenCountCallback;
}

/**
* Retrieves the stored {@link LlmTokenCountCallback} instance.
*
* @return stored callback instance
*/
public static LlmTokenCountCallback getLlmTokenCountCallback() {
return llmTokenCountCallback;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
*
* * Copyright 2024 New Relic Corporation. All rights reserved.
* * SPDX-License-Identifier: Apache-2.0
*
*/

package com.newrelic.agent.model;

/**
* Represents an internal subtype of a CustomInsightsEvent that is sent to the
* custom_event_data collector endpoint but potentially subject to different
* validation rules and agent configuration.
*/
public class LlmCustomInsightsEvent {
// LLM event types
private static final String LLM_EMBEDDING = "LlmEmbedding";
private static final String LLM_CHAT_COMPLETION_SUMMARY = "LlmChatCompletionSummary";
private static final String LLM_CHAT_COMPLETION_MESSAGE = "LlmChatCompletionMessage";

/**
* Determines if a CustomInsightsEvent should be treated as a LlmEvent
*
* @param eventType type of the current event
* @return true if eventType is an LlmEvent, else false
*/
public static boolean isLlmEvent(String eventType) {
return eventType.equals(LLM_EMBEDDING) || eventType.equals(LLM_CHAT_COMPLETION_MESSAGE) || eventType.equals(LLM_CHAT_COMPLETION_SUMMARY);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.newrelic.agent.bridge.Agent;
import com.newrelic.agent.bridge.TracedMethod;
import com.newrelic.agent.bridge.Transaction;
import com.newrelic.api.agent.AiMonitoring;
import com.newrelic.api.agent.Config;
import com.newrelic.api.agent.ErrorApi;
import com.newrelic.api.agent.Insights;
Expand Down Expand Up @@ -38,6 +39,11 @@ public Logger getLogger() {
@Override
public Insights getInsights() { throw new RuntimeException(); }

@Override
public AiMonitoring getAiMonitoring() {
return null;
}

@Override
public ErrorApi getErrorApi() { throw new RuntimeException(); }

Expand Down
Loading
Loading