newrelic 11.11.0 → 11.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NEWS.md +14 -0
- package/lib/config/default.js +16 -3
- package/lib/instrumentation/langchain/runnable.js +190 -38
- package/lib/instrumentations.js +3 -1
- package/lib/llm-events/langchain/chat-completion-message.js +5 -1
- package/lib/llm-events/langchain/event.js +1 -2
- package/lib/llm-events/langchain/tool.js +7 -2
- package/lib/llm-events/langchain/vector-search-result.js +5 -1
- package/lib/llm-events/langchain/vector-search.js +5 -2
- package/lib/llm-events/openai/chat-completion-message.js +5 -2
- package/lib/llm-events/openai/embedding.js +4 -1
- package/package.json +1 -1
package/NEWS.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
### v11.12.0 (2024-03-04)
|
|
2
|
+
|
|
3
|
+
#### Features
|
|
4
|
+
|
|
5
|
+
* Added instrumentation for `chain.stream` for langchain js. ([#2052](https://github.com/newrelic/node-newrelic/pull/2052)) ([03abfce](https://github.com/newrelic/node-newrelic/commit/03abfce666d3c48abd0994c44817bb5cbe8655a9))
|
|
6
|
+
|
|
7
|
+
#### Miscellaneous chores
|
|
8
|
+
|
|
9
|
+
* Added @azure/openai and @langchain/community/llms/bedrock as tracking packages so we can measure usage with angler ([#2053](https://github.com/newrelic/node-newrelic/pull/2053)) ([4830ea3](https://github.com/newrelic/node-newrelic/commit/4830ea3285726f8cc8fb60820c4cf2d3790e5250))
|
|
10
|
+
|
|
11
|
+
#### Tests
|
|
12
|
+
|
|
13
|
+
* Updated aws-sdk branch to main as the necessary code was merged. ([#2051](https://github.com/newrelic/node-newrelic/pull/2051)) ([1e52a5c](https://github.com/newrelic/node-newrelic/commit/1e52a5cd7a8acc8970dbdc6b1bf774c06aa6f5fb))
|
|
14
|
+
|
|
1
15
|
### v11.11.0 (2024-02-27)
|
|
2
16
|
|
|
3
17
|
#### Features
|
package/lib/config/default.js
CHANGED
|
@@ -1359,6 +1359,19 @@ defaultConfig.definition = () => ({
|
|
|
1359
1359
|
formatter: boolean,
|
|
1360
1360
|
default: false
|
|
1361
1361
|
},
|
|
1362
|
+
|
|
1363
|
+
/**
|
|
1364
|
+
* When enabled, the content of LLM messages will be included in the
|
|
1365
|
+
* recorded spans (i.e. delivered to the New Relic collector). This is
|
|
1366
|
+
* enabled by default.
|
|
1367
|
+
*/
|
|
1368
|
+
record_content: {
|
|
1369
|
+
enabled: {
|
|
1370
|
+
formatter: boolean,
|
|
1371
|
+
default: true
|
|
1372
|
+
}
|
|
1373
|
+
},
|
|
1374
|
+
|
|
1362
1375
|
/**
|
|
1363
1376
|
* Toggles the capturing of Llm events when using streaming
|
|
1364
1377
|
* based methods in AIM supported libraries(i.e.- openai, AWS bedrock, langchain)
|
|
@@ -1390,8 +1403,8 @@ defaultConfig.config = () => {
|
|
|
1390
1403
|
*
|
|
1391
1404
|
* @param {object} definition configuration definition for a given leaf node
|
|
1392
1405
|
* @param {object} config object that is used to construct the agent config
|
|
1393
|
-
* @param {Array} [paths
|
|
1394
|
-
* @param {int} [objectKeys
|
|
1406
|
+
* @param {Array} [paths] an array to capture the leaf node keys to properly assign defaults for nested objects
|
|
1407
|
+
* @param {int} [objectKeys] amount of keys in a given leaf node
|
|
1395
1408
|
*/
|
|
1396
1409
|
function buildConfig(definition, config, paths = [], objectKeys = 1) {
|
|
1397
1410
|
let keysSeen = 0
|
|
@@ -1429,7 +1442,7 @@ function buildConfig(definition, config, paths = [], objectKeys = 1) {
|
|
|
1429
1442
|
* @param {object} params.config object that is used to construct the agent config
|
|
1430
1443
|
* @param {string} params.key name of the configuration option
|
|
1431
1444
|
* @param {string} params.value value the configuration option
|
|
1432
|
-
* @param {Array} [params.paths
|
|
1445
|
+
* @param {Array} [params.paths] an array to capture the leaf node keys to properly assign defaults for nested objects
|
|
1433
1446
|
*/
|
|
1434
1447
|
function assignConfigValue({ config, key, value, paths }) {
|
|
1435
1448
|
if (paths.length) {
|
|
@@ -6,9 +6,8 @@
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
8
|
const common = require('./common')
|
|
9
|
-
const {
|
|
10
|
-
|
|
11
|
-
} = require('../../metrics/names')
|
|
9
|
+
const { AI } = require('../../metrics/names')
|
|
10
|
+
const { LANGCHAIN } = AI
|
|
12
11
|
const {
|
|
13
12
|
LangChainCompletionMessage,
|
|
14
13
|
LangChainCompletionSummary
|
|
@@ -28,10 +27,33 @@ module.exports = function initialize(shim, langchain) {
|
|
|
28
27
|
return
|
|
29
28
|
}
|
|
30
29
|
|
|
30
|
+
instrumentInvokeChain({ langchain, shim })
|
|
31
|
+
|
|
32
|
+
if (agent.config.ai_monitoring.streaming.enabled) {
|
|
33
|
+
instrumentStream({ langchain, shim })
|
|
34
|
+
} else {
|
|
35
|
+
shim.logger.warn(
|
|
36
|
+
'`ai_monitoring.streaming.enabled` is set to `false`, stream will not be instrumented.'
|
|
37
|
+
)
|
|
38
|
+
agent.metrics.getOrCreateMetric(AI.STREAMING_DISABLED).incrementCallCount()
|
|
39
|
+
agent.metrics
|
|
40
|
+
.getOrCreateMetric(`${LANGCHAIN.TRACKING_PREFIX}/${pkgVersion}`)
|
|
41
|
+
.incrementCallCount()
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Instruments and records span and relevant LLM events for `chain.invoke`
|
|
47
|
+
*
|
|
48
|
+
* @param {object} params function params
|
|
49
|
+
* @param {object} params.langchain `@langchain/core/runnables/base` export
|
|
50
|
+
* @param {Shim} params.shim instace of shim
|
|
51
|
+
*/
|
|
52
|
+
function instrumentInvokeChain({ langchain, shim }) {
|
|
31
53
|
shim.record(
|
|
32
54
|
langchain.RunnableSequence.prototype,
|
|
33
55
|
'invoke',
|
|
34
|
-
function wrapCall(shim,
|
|
56
|
+
function wrapCall(shim, _invoke, fnName, args) {
|
|
35
57
|
const [request, params] = args
|
|
36
58
|
const metadata = params?.metadata ?? {}
|
|
37
59
|
const tags = params?.tags ?? []
|
|
@@ -41,53 +63,183 @@ module.exports = function initialize(shim, langchain) {
|
|
|
41
63
|
promise: true,
|
|
42
64
|
// eslint-disable-next-line max-params
|
|
43
65
|
after(_shim, _fn, _name, err, output, segment) {
|
|
44
|
-
|
|
45
|
-
const completionSummary = new LangChainCompletionSummary({
|
|
46
|
-
agent,
|
|
47
|
-
messages: [{ output }],
|
|
48
|
-
metadata,
|
|
49
|
-
tags,
|
|
66
|
+
recordChatCompletionEvents({
|
|
50
67
|
segment,
|
|
51
|
-
|
|
52
|
-
runId: segment[langchainRunId]
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
common.recordEvent({
|
|
56
|
-
agent,
|
|
57
|
-
type: 'LlmChatCompletionSummary',
|
|
58
|
-
pkgVersion,
|
|
59
|
-
msg: completionSummary
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
// output can be BaseMessage with a content property https://js.langchain.com/docs/modules/model_io/concepts#messages
|
|
63
|
-
// or an output parser https://js.langchain.com/docs/modules/model_io/concepts#output-parsers
|
|
64
|
-
recordCompletions({
|
|
68
|
+
messages: [output],
|
|
65
69
|
events: [request, output],
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
70
|
+
metadata,
|
|
71
|
+
tags,
|
|
72
|
+
err,
|
|
69
73
|
shim
|
|
70
74
|
})
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Instruments and records span and relevant LLM events for `chain.stream`
|
|
83
|
+
*
|
|
84
|
+
* @param {object} params function params
|
|
85
|
+
* @param {object} params.langchain `@langchain/core/runnables/base` export
|
|
86
|
+
* @param {Shim} params.shim instace of shim
|
|
87
|
+
*/
|
|
88
|
+
function instrumentStream({ langchain, shim }) {
|
|
89
|
+
shim.record(
|
|
90
|
+
langchain.RunnableSequence.prototype,
|
|
91
|
+
'stream',
|
|
92
|
+
function wrapStream(shim, _stream, fnName, args) {
|
|
93
|
+
const [request, params] = args
|
|
94
|
+
const metadata = params?.metadata ?? {}
|
|
95
|
+
const tags = params?.tags ?? []
|
|
71
96
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
97
|
+
return new RecorderSpec({
|
|
98
|
+
name: `${LANGCHAIN.CHAIN}/${fnName}`,
|
|
99
|
+
promise: true,
|
|
100
|
+
// eslint-disable-next-line max-params
|
|
101
|
+
after(_shim, _fn, _name, err, output, segment) {
|
|
102
|
+
// Input error occurred which means a stream was not created.
|
|
103
|
+
// Skip instrumenting streaming and create Llm Events from
|
|
104
|
+
// the data we have
|
|
105
|
+
if (output?.next) {
|
|
106
|
+
wrapNextHandler({ shim, output, segment, request, metadata, tags })
|
|
107
|
+
} else {
|
|
108
|
+
recordChatCompletionEvents({
|
|
109
|
+
segment,
|
|
110
|
+
messages: [],
|
|
111
|
+
events: [request],
|
|
112
|
+
metadata,
|
|
113
|
+
tags,
|
|
75
114
|
err,
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
cause: err,
|
|
79
|
-
summary: completionSummary
|
|
80
|
-
})
|
|
81
|
-
)
|
|
115
|
+
shim
|
|
116
|
+
})
|
|
82
117
|
}
|
|
83
|
-
|
|
84
|
-
segment.transaction.trace.attributes.addAttribute(DESTINATIONS.TRANS_EVENT, 'llm', true)
|
|
85
118
|
}
|
|
86
119
|
})
|
|
87
120
|
}
|
|
88
121
|
)
|
|
89
122
|
}
|
|
90
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Wraps the next method on the IterableReadableStream. It will also record the Llm
|
|
126
|
+
* events when the stream is done processing.
|
|
127
|
+
*
|
|
128
|
+
* @param {object} params function params
|
|
129
|
+
* @param {Shim} params.shim shim instance
|
|
130
|
+
* @param {TraceSegment} params.segment active segment
|
|
131
|
+
* @param {function} params.output IterableReadableStream
|
|
132
|
+
* @param {string} params.request the prompt message
|
|
133
|
+
* @param {object} params.metadata metadata for the call
|
|
134
|
+
* @param {Array} params.tags tags for the call
|
|
135
|
+
*/
|
|
136
|
+
function wrapNextHandler({ shim, output, segment, request, metadata, tags }) {
|
|
137
|
+
shim.wrap(output, 'next', function wrapIterator(shim, orig) {
|
|
138
|
+
let content = ''
|
|
139
|
+
return async function wrappedIterator() {
|
|
140
|
+
try {
|
|
141
|
+
const result = await orig.apply(this, arguments)
|
|
142
|
+
// only create Llm events when stream iteration is done
|
|
143
|
+
if (result?.done) {
|
|
144
|
+
recordChatCompletionEvents({
|
|
145
|
+
segment,
|
|
146
|
+
messages: [content],
|
|
147
|
+
events: [request, content],
|
|
148
|
+
metadata,
|
|
149
|
+
tags,
|
|
150
|
+
shim
|
|
151
|
+
})
|
|
152
|
+
} else {
|
|
153
|
+
content += result.value
|
|
154
|
+
}
|
|
155
|
+
return result
|
|
156
|
+
} catch (error) {
|
|
157
|
+
recordChatCompletionEvents({
|
|
158
|
+
segment,
|
|
159
|
+
messages: [content],
|
|
160
|
+
events: [request, content],
|
|
161
|
+
metadata,
|
|
162
|
+
tags,
|
|
163
|
+
err: error,
|
|
164
|
+
shim
|
|
165
|
+
})
|
|
166
|
+
throw error
|
|
167
|
+
} finally {
|
|
168
|
+
// update segment duration on every stream iteration to extend
|
|
169
|
+
// the timer
|
|
170
|
+
segment.touch()
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
})
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Ends active segment, creates LlmChatCompletionSummary, and LlmChatCompletionMessage(s), and handles errors if they exists
|
|
178
|
+
*
|
|
179
|
+
* @param {object} params function params
|
|
180
|
+
* @param {TraceSegment} params.segment active segment
|
|
181
|
+
* @param {Array} params.messages response messages
|
|
182
|
+
* @param {Array} params.events prompt and response messages
|
|
183
|
+
* @param {object} params.metadata metadata for the call
|
|
184
|
+
* @param {Array} params.tags tags for the call
|
|
185
|
+
* @param {Error} params.err error object from call
|
|
186
|
+
* @param {Shim} params.shim shim instance
|
|
187
|
+
*/
|
|
188
|
+
function recordChatCompletionEvents({ segment, messages, events, metadata, tags, err, shim }) {
|
|
189
|
+
const { pkgVersion, agent } = shim
|
|
190
|
+
segment.end()
|
|
191
|
+
const completionSummary = new LangChainCompletionSummary({
|
|
192
|
+
agent,
|
|
193
|
+
messages,
|
|
194
|
+
metadata,
|
|
195
|
+
tags,
|
|
196
|
+
segment,
|
|
197
|
+
error: err != null,
|
|
198
|
+
runId: segment[langchainRunId]
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
common.recordEvent({
|
|
202
|
+
agent,
|
|
203
|
+
type: 'LlmChatCompletionSummary',
|
|
204
|
+
pkgVersion,
|
|
205
|
+
msg: completionSummary
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
// output can be BaseMessage with a content property https://js.langchain.com/docs/modules/model_io/concepts#messages
|
|
209
|
+
// or an output parser https://js.langchain.com/docs/modules/model_io/concepts#output-parsers
|
|
210
|
+
recordCompletions({
|
|
211
|
+
events,
|
|
212
|
+
completionSummary,
|
|
213
|
+
agent,
|
|
214
|
+
segment,
|
|
215
|
+
shim
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
if (err) {
|
|
219
|
+
agent.errors.add(
|
|
220
|
+
segment.transaction,
|
|
221
|
+
err,
|
|
222
|
+
new LlmErrorMessage({
|
|
223
|
+
response: {},
|
|
224
|
+
cause: err,
|
|
225
|
+
summary: completionSummary
|
|
226
|
+
})
|
|
227
|
+
)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
segment.transaction.trace.attributes.addAttribute(DESTINATIONS.TRANS_EVENT, 'llm', true)
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Records the LlmChatCompletionMessage(s)
|
|
235
|
+
*
|
|
236
|
+
* @param {object} params function params
|
|
237
|
+
* @param {Array} params.events prompt and response messages
|
|
238
|
+
* @param {LangChainCompletionSummary} params.completionSummary LlmChatCompletionSummary event
|
|
239
|
+
* @param {Agent} params.agent instance of agent
|
|
240
|
+
* @param {TraceSegment} params.segment active segment
|
|
241
|
+
* @param {Shim} params.shim shim instance
|
|
242
|
+
*/
|
|
91
243
|
function recordCompletions({ events, completionSummary, agent, segment, shim }) {
|
|
92
244
|
for (let i = 0; i < events.length; i += 1) {
|
|
93
245
|
let msg = events[i]
|
package/lib/instrumentations.js
CHANGED
|
@@ -55,6 +55,8 @@ module.exports = function instrumentations() {
|
|
|
55
55
|
'loglevel': { type: MODULE_TYPE.TRACKING },
|
|
56
56
|
'npmlog': { type: MODULE_TYPE.TRACKING },
|
|
57
57
|
'fancy-log': { type: MODULE_TYPE.TRACKING },
|
|
58
|
-
'knex': { type: MODULE_TYPE.TRACKING }
|
|
58
|
+
'knex': { type: MODULE_TYPE.TRACKING },
|
|
59
|
+
'@azure/openai': { type: MODULE_TYPE.TRACKING },
|
|
60
|
+
'@langchain/community/llms/bedrock': { type: MODULE_TYPE.TRACKING }
|
|
59
61
|
}
|
|
60
62
|
}
|
|
@@ -36,6 +36,7 @@ class LangChainCompletionMessage extends LangChainEvent {
|
|
|
36
36
|
constructor(params = defaultParams) {
|
|
37
37
|
params = Object.assign({}, defaultParams, params)
|
|
38
38
|
super(params)
|
|
39
|
+
const { agent } = params
|
|
39
40
|
|
|
40
41
|
if (params.runId) {
|
|
41
42
|
this.id = `${params.runId}-${params.sequence}`
|
|
@@ -43,10 +44,13 @@ class LangChainCompletionMessage extends LangChainEvent {
|
|
|
43
44
|
this.id = `${this.id}-${params.sequence}`
|
|
44
45
|
}
|
|
45
46
|
|
|
46
|
-
this.content = params.content
|
|
47
47
|
this.sequence = params.sequence
|
|
48
48
|
this.completion_id = params.completionId
|
|
49
49
|
this.is_response = params.isResponse ?? false
|
|
50
|
+
|
|
51
|
+
if (agent.config.ai_monitoring.record_content.enabled === true) {
|
|
52
|
+
this.content = params.content
|
|
53
|
+
}
|
|
50
54
|
}
|
|
51
55
|
}
|
|
52
56
|
|
|
@@ -51,7 +51,6 @@ class LangChainEvent extends BaseEvent {
|
|
|
51
51
|
ingest_source = 'Node'
|
|
52
52
|
vendor = 'langchain'
|
|
53
53
|
virtual_llm = true
|
|
54
|
-
error = false
|
|
55
54
|
|
|
56
55
|
constructor(params = defaultParams) {
|
|
57
56
|
params = Object.assign({}, defaultParams, params)
|
|
@@ -66,7 +65,7 @@ class LangChainEvent extends BaseEvent {
|
|
|
66
65
|
this.langchainMeta = params.metadata
|
|
67
66
|
this.metadata = agent
|
|
68
67
|
this.tags = Array.isArray(params.tags) ? params.tags.join(',') : params.tags
|
|
69
|
-
this.error = params.error ??
|
|
68
|
+
this.error = params.error ?? null
|
|
70
69
|
|
|
71
70
|
if (params.virtual !== undefined) {
|
|
72
71
|
if (params.virtual !== true && params.virtual !== false) {
|
|
@@ -9,8 +9,8 @@ const LangChainEvent = require('./event')
|
|
|
9
9
|
class LangChainTool extends LangChainEvent {
|
|
10
10
|
constructor(params) {
|
|
11
11
|
super(params)
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
const { agent } = params
|
|
13
|
+
|
|
14
14
|
this.name = params.name
|
|
15
15
|
this.description = params.description
|
|
16
16
|
this.duration = params?.segment?.getDurationInMillis()
|
|
@@ -18,6 +18,11 @@ class LangChainTool extends LangChainEvent {
|
|
|
18
18
|
delete this.request_id
|
|
19
19
|
delete this.virtual_llm
|
|
20
20
|
delete this.conversation_id
|
|
21
|
+
|
|
22
|
+
if (agent.config.ai_monitoring.record_content.enabled === true) {
|
|
23
|
+
this.input = params.input
|
|
24
|
+
this.output = params.output
|
|
25
|
+
}
|
|
21
26
|
}
|
|
22
27
|
}
|
|
23
28
|
|
|
@@ -28,9 +28,13 @@ class LangChainVectorSearchResult extends LangChainEvent {
|
|
|
28
28
|
constructor(params) {
|
|
29
29
|
params = Object.assign({}, defaultParams, params)
|
|
30
30
|
super(params)
|
|
31
|
+
const { agent } = params
|
|
31
32
|
|
|
32
|
-
this.page_content = params.pageContent
|
|
33
33
|
this.sequence = params.sequence
|
|
34
|
+
|
|
35
|
+
if (agent.config.ai_monitoring.record_content.enabled === true) {
|
|
36
|
+
this.page_content = params.pageContent
|
|
37
|
+
}
|
|
34
38
|
}
|
|
35
39
|
}
|
|
36
40
|
|
|
@@ -28,12 +28,15 @@ class LangChainVectorSearch extends LangChainEvent {
|
|
|
28
28
|
constructor(params) {
|
|
29
29
|
params = Object.assign({}, defaultParams, params)
|
|
30
30
|
super(params)
|
|
31
|
-
const { segment } = params
|
|
31
|
+
const { agent, segment } = params
|
|
32
32
|
|
|
33
33
|
this.duration = segment?.getDurationInMillis()
|
|
34
|
-
this['request.query'] = params.query
|
|
35
34
|
this['request.k'] = params.k
|
|
36
35
|
this['response.number_of_documents'] = params.documents?.length
|
|
36
|
+
|
|
37
|
+
if (agent.config.ai_monitoring.record_content.enabled === true) {
|
|
38
|
+
this['request.query'] = params.query
|
|
39
|
+
}
|
|
37
40
|
}
|
|
38
41
|
}
|
|
39
42
|
|
|
@@ -10,10 +10,13 @@ module.exports = class LlmChatCompletionMessage extends LlmEvent {
|
|
|
10
10
|
constructor({ agent, segment, request = {}, response = {}, index = 0, message, completionId }) {
|
|
11
11
|
super({ agent, segment, request, response })
|
|
12
12
|
this.id = `${response.id}-${index}`
|
|
13
|
-
this.content = message?.content
|
|
14
13
|
this.role = message?.role
|
|
15
14
|
this.sequence = index
|
|
16
15
|
this.completion_id = completionId
|
|
17
|
-
this.is_response = response?.choices?.[0]?.message?.content ===
|
|
16
|
+
this.is_response = response?.choices?.[0]?.message?.content === message?.content
|
|
17
|
+
|
|
18
|
+
if (agent.config.ai_monitoring.record_content.enabled === true) {
|
|
19
|
+
this.content = message?.content
|
|
20
|
+
}
|
|
18
21
|
}
|
|
19
22
|
}
|
|
@@ -10,6 +10,9 @@ module.exports = class LlmEmbedding extends LlmEvent {
|
|
|
10
10
|
constructor({ agent, segment, request = {}, response = {}, withError = false }) {
|
|
11
11
|
super({ agent, segment, request, response, responseAttrs: true })
|
|
12
12
|
this.error = withError
|
|
13
|
-
|
|
13
|
+
|
|
14
|
+
if (agent.config.ai_monitoring.record_content.enabled === true) {
|
|
15
|
+
this.input = request.input?.toString()
|
|
16
|
+
}
|
|
14
17
|
}
|
|
15
18
|
}
|