Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Added instrumentation for langchain tools. (#2009)
- Loading branch information
Showing
23 changed files
with
599 additions
and
66 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/* | ||
* Copyright 2024 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
'use strict' | ||
const { langchainRunId } = require('../../symbols') | ||
|
||
module.exports = function initialize(shim, callbacks) { | ||
shim.wrap( | ||
callbacks.CallbackManager.prototype, | ||
['handleChainStart', 'handleToolStart'], | ||
function wrapStart(shim, orig) { | ||
return async function wrappedStart() { | ||
const result = await orig.apply(this, arguments) | ||
const segment = shim.getActiveSegment() | ||
if (segment) { | ||
segment[langchainRunId] = result?.runId | ||
} | ||
|
||
return result | ||
} | ||
} | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/* | ||
* Copyright 2024 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
'use strict' | ||
const { | ||
AI: { LANGCHAIN } | ||
} = require('../../metrics/names') | ||
|
||
const common = module.exports | ||
|
||
/** | ||
* Langchain allows you to define tags at the instance and call level | ||
* This helper merges the two into 1 array ensuring there are not duplicates | ||
* | ||
* @param {Array} localTags tags defined on instance of a langchain object | ||
* @param {Array} paramsTags tags defined on the method | ||
* @returns {Array} a merged array of unique tags | ||
*/ | ||
common.mergeTags = function mergeTags(localTags = [], paramsTags = []) { | ||
const tags = localTags.filter((tag) => !paramsTags.includes(tag)) | ||
tags.push(...paramsTags) | ||
return tags | ||
} | ||
|
||
/** | ||
* Langchain allows you to define metadata at the instance and call level | ||
* This helper merges the two into object favoring the call level metadata | ||
* values when duplicate keys exist. | ||
* | ||
* @param {object} localMeta metadata defined on instance of a langchain object | ||
* @param {object} paramsMeta metadata defined on the method | ||
* @returns {object} a merged object of metadata | ||
*/ | ||
common.mergeMetadata = function mergeMetadata(localMeta = {}, paramsMeta = {}) { | ||
return { ...localMeta, ...paramsMeta } | ||
} | ||
|
||
/** | ||
* Helper to enqueue a LLM event into the custom event aggregator. This will also | ||
* increment the Supportability metric that's used to derive a tag on the APM entity. | ||
* | ||
* @param {object} params function params | ||
* @param {Agent} params.agent NR agent | ||
* @param {string} params.type type of llm event(i.e.- LlmChatCompletionMessage, LlmTool, etc) | ||
* @param {object} params.msg the llm event getting enqueued | ||
* @param {string} params.pkgVersion version of langchain library instrumented | ||
*/ | ||
common.recordEvent = function recordEvent({ agent, type, msg, pkgVersion }) { | ||
agent.metrics.getOrCreateMetric(`${LANGCHAIN.TRACKING_PREFIX}/${pkgVersion}`).incrementCallCount() | ||
agent.customEventAggregator.add([{ type, timestamp: Date.now() }, msg]) | ||
} | ||
|
||
/** | ||
* Helper to decide if instrumentation should be registered. | ||
* | ||
* @param {object} config agent config | ||
* @returns {boolean} flag if we should skip instrumentation | ||
*/ | ||
common.shouldSkipInstrumentation = function shouldSkipInstrumentation(config) { | ||
return !( | ||
config.ai_monitoring.enabled === true && config.feature_flag.langchain_instrumentation === true | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/* | ||
* Copyright 2024 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
'use strict' | ||
const toolsInstrumentation = require('./tools') | ||
const cbManagerInstrumentation = require('./callback-manager') | ||
|
||
module.exports = [ | ||
{ | ||
type: 'generic', | ||
moduleName: '@langchain/core/tools', | ||
onRequire: toolsInstrumentation | ||
}, | ||
{ | ||
type: 'generic', | ||
moduleName: '@langchain/core/dist/callbacks/manager', | ||
onRequire: cbManagerInstrumentation | ||
} | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/* | ||
* Copyright 2024 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
'use strict' | ||
const { LangChainTool } = require('../../llm-events/langchain') | ||
const { mergeMetadata, mergeTags, recordEvent, shouldSkipInstrumentation } = require('./common') | ||
const { | ||
AI: { LANGCHAIN } | ||
} = require('../../metrics/names') | ||
const { langchainRunId } = require('../../symbols') | ||
const { DESTINATIONS } = require('../../config/attribute-filter') | ||
const { RecorderSpec } = require('../../shim/specs') | ||
|
||
module.exports = function initialize(shim, tools) { | ||
const { agent, pkgVersion } = shim | ||
|
||
if (shouldSkipInstrumentation(agent.config)) { | ||
shim.logger.debug( | ||
'langchain instrumentation is disabled. To enable set `config.ai_monitoring.enabled` to true' | ||
) | ||
return | ||
} | ||
|
||
shim.record(tools.StructuredTool.prototype, 'call', function wrapCall(shim, call, fnName, args) { | ||
const { name, metadata: instanceMeta, description, tags: instanceTags } = this | ||
const [request, params] = args | ||
const { metadata: paramsMeta, tags: paramsTags } = params || {} | ||
return new RecorderSpec({ | ||
name: `${LANGCHAIN.TOOL}/${name}`, | ||
promise: true, | ||
// eslint-disable-next-line max-params | ||
after(_shim, _fn, _name, _err, output, segment) { | ||
const metadata = mergeMetadata(instanceMeta, paramsMeta) | ||
const tags = mergeTags(instanceTags, paramsTags) | ||
segment.end() | ||
const toolEvent = new LangChainTool({ | ||
agent, | ||
description, | ||
name, | ||
runId: segment[langchainRunId], | ||
metadata, | ||
tags, | ||
input: request?.input, | ||
output, | ||
segment | ||
}) | ||
recordEvent({ agent, type: 'LlmTool', pkgVersion, msg: toolEvent }) | ||
segment.transaction.trace.attributes.addAttribute(DESTINATIONS.TRANS_EVENT, 'llm', true) | ||
} | ||
}) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/* | ||
* Copyright 2024 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
'use strict' | ||
const LangChainEvent = require('./event') | ||
|
||
class LangChainTool extends LangChainEvent { | ||
constructor(params) { | ||
super(params) | ||
this.input = params.input | ||
this.output = params.output | ||
this.name = params.name | ||
this.description = params.description | ||
this.duration = params?.segment?.getDurationInMillis() | ||
this.run_id = this.request_id | ||
delete this.request_id | ||
delete this.virtual_llm | ||
delete this.conversation_id | ||
} | ||
} | ||
|
||
module.exports = LangChainTool |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.