dd-trace 5.30.0 → 5.32.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/LICENSE-3rdparty.csv +1 -0
- package/README.md +9 -7
- package/package.json +7 -6
- package/packages/datadog-core/src/storage.js +11 -2
- package/packages/datadog-instrumentations/src/aerospike.js +1 -1
- package/packages/datadog-instrumentations/src/aws-sdk.js +2 -1
- package/packages/datadog-instrumentations/src/cucumber.js +14 -5
- package/packages/datadog-instrumentations/src/helpers/hooks.js +3 -0
- package/packages/datadog-instrumentations/src/jest.js +70 -36
- package/packages/datadog-instrumentations/src/mocha/utils.js +23 -7
- package/packages/datadog-instrumentations/src/node-serialize.js +22 -0
- package/packages/datadog-instrumentations/src/openai.js +2 -0
- package/packages/datadog-instrumentations/src/vitest.js +107 -59
- package/packages/datadog-instrumentations/src/vm.js +49 -0
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime.js +295 -0
- package/packages/datadog-plugin-aws-sdk/src/services/index.js +1 -0
- package/packages/datadog-plugin-cucumber/src/index.js +30 -32
- package/packages/datadog-plugin-jest/src/index.js +34 -37
- package/packages/datadog-plugin-langchain/src/index.js +12 -80
- package/packages/datadog-plugin-langchain/src/tracing.js +89 -0
- package/packages/datadog-plugin-mocha/src/index.js +18 -36
- package/packages/datadog-plugin-vitest/src/index.js +20 -34
- package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +1 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/code-injection-analyzer.js +2 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/untrusted-deserialization-analyzer.js +16 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +9 -8
- package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +1 -0
- package/packages/dd-trace/src/appsec/remote_config/manager.js +11 -1
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +37 -0
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +65 -28
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +57 -17
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +18 -3
- package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +20 -3
- package/packages/dd-trace/src/config.js +39 -3
- package/packages/dd-trace/src/crashtracking/crashtracker.js +9 -0
- package/packages/dd-trace/src/crashtracking/noop.js +3 -0
- package/packages/dd-trace/src/datastreams/fnv.js +1 -1
- package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +2 -2
- package/packages/dd-trace/src/debugger/devtools_client/config.js +3 -1
- package/packages/dd-trace/src/debugger/devtools_client/defaults.js +1 -0
- package/packages/dd-trace/src/debugger/devtools_client/index.js +32 -14
- package/packages/dd-trace/src/debugger/devtools_client/json-buffer.js +36 -0
- package/packages/dd-trace/src/debugger/devtools_client/send.js +29 -10
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +35 -1
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/redaction.js +112 -0
- package/packages/dd-trace/src/debugger/devtools_client/status.js +20 -11
- package/packages/dd-trace/src/debugger/index.js +2 -13
- package/packages/dd-trace/src/llmobs/plugins/base.js +40 -11
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chain.js +24 -0
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chat_model.js +111 -0
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/embedding.js +42 -0
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +102 -0
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/llm.js +32 -0
- package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +131 -0
- package/packages/dd-trace/src/llmobs/plugins/openai.js +1 -1
- package/packages/dd-trace/src/llmobs/sdk.js +90 -26
- package/packages/dd-trace/src/llmobs/tagger.js +11 -3
- package/packages/dd-trace/src/llmobs/util.js +7 -1
- package/packages/dd-trace/src/llmobs/writers/spans/agentProxy.js +3 -3
- package/packages/dd-trace/src/log/index.js +8 -9
- package/packages/dd-trace/src/noop/proxy.js +2 -2
- package/packages/dd-trace/src/noop/span.js +1 -1
- package/packages/dd-trace/src/opentelemetry/context_manager.js +43 -3
- package/packages/dd-trace/src/opentracing/span.js +11 -1
- package/packages/dd-trace/src/opentracing/span_context.js +12 -0
- package/packages/dd-trace/src/plugins/ci_plugin.js +57 -27
- package/packages/dd-trace/src/plugins/util/test.js +42 -12
- package/packages/dd-trace/src/priority_sampler.js +7 -2
- package/packages/dd-trace/src/profiling/exporters/event_serializer.js +21 -0
- package/packages/dd-trace/src/profiling/profiler.js +11 -8
- package/packages/dd-trace/src/profiling/profilers/events.js +17 -1
- package/packages/dd-trace/src/proxy.js +6 -3
- package/packages/dd-trace/src/scope.js +1 -1
- package/packages/dd-trace/src/telemetry/index.js +2 -0
|
@@ -28,6 +28,42 @@ const newTasks = new WeakSet()
|
|
|
28
28
|
const switchedStatuses = new WeakSet()
|
|
29
29
|
const sessionAsyncResource = new AsyncResource('bound-anonymous-fn')
|
|
30
30
|
|
|
31
|
+
const BREAKPOINT_HIT_GRACE_PERIOD_MS = 400
|
|
32
|
+
|
|
33
|
+
function waitForHitProbe () {
|
|
34
|
+
return new Promise(resolve => {
|
|
35
|
+
setTimeout(() => {
|
|
36
|
+
resolve()
|
|
37
|
+
}, BREAKPOINT_HIT_GRACE_PERIOD_MS)
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function getProvidedContext () {
|
|
42
|
+
try {
|
|
43
|
+
const {
|
|
44
|
+
_ddIsEarlyFlakeDetectionEnabled,
|
|
45
|
+
_ddIsDiEnabled,
|
|
46
|
+
_ddKnownTests: knownTests,
|
|
47
|
+
_ddEarlyFlakeDetectionNumRetries: numRepeats
|
|
48
|
+
} = globalThis.__vitest_worker__.providedContext
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
isDiEnabled: _ddIsDiEnabled,
|
|
52
|
+
isEarlyFlakeDetectionEnabled: _ddIsEarlyFlakeDetectionEnabled,
|
|
53
|
+
knownTests,
|
|
54
|
+
numRepeats
|
|
55
|
+
}
|
|
56
|
+
} catch (e) {
|
|
57
|
+
log.error('Vitest workers could not parse provided context, so some features will not work.')
|
|
58
|
+
return {
|
|
59
|
+
isDiEnabled: false,
|
|
60
|
+
isEarlyFlakeDetectionEnabled: false,
|
|
61
|
+
knownTests: {},
|
|
62
|
+
numRepeats: 0
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
31
67
|
function isReporterPackage (vitestPackage) {
|
|
32
68
|
return vitestPackage.B?.name === 'BaseSequencer'
|
|
33
69
|
}
|
|
@@ -143,7 +179,9 @@ function getSortWrapper (sort) {
|
|
|
143
179
|
const knownTestsResponse = await getChannelPromise(knownTestsCh)
|
|
144
180
|
if (!knownTestsResponse.err) {
|
|
145
181
|
knownTests = knownTestsResponse.knownTests
|
|
146
|
-
const
|
|
182
|
+
const getFilePaths = this.ctx.getTestFilepaths || this.ctx._globTestFilepaths
|
|
183
|
+
|
|
184
|
+
const testFilepaths = await getFilePaths.call(this.ctx)
|
|
147
185
|
|
|
148
186
|
isEarlyFlakeDetectionFaultyCh.publish({
|
|
149
187
|
knownTests: knownTests.vitest || {},
|
|
@@ -253,29 +291,26 @@ addHook({
|
|
|
253
291
|
// `onBeforeRunTask` is run before any repetition or attempt is run
|
|
254
292
|
shimmer.wrap(VitestTestRunner.prototype, 'onBeforeRunTask', onBeforeRunTask => async function (task) {
|
|
255
293
|
const testName = getTestName(task)
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
}
|
|
294
|
+
|
|
295
|
+
const {
|
|
296
|
+
knownTests,
|
|
297
|
+
isEarlyFlakeDetectionEnabled,
|
|
298
|
+
numRepeats
|
|
299
|
+
} = getProvidedContext()
|
|
300
|
+
|
|
301
|
+
if (isEarlyFlakeDetectionEnabled) {
|
|
302
|
+
isNewTestCh.publish({
|
|
303
|
+
knownTests,
|
|
304
|
+
testSuiteAbsolutePath: task.file.filepath,
|
|
305
|
+
testName,
|
|
306
|
+
onDone: (isNew) => {
|
|
307
|
+
if (isNew) {
|
|
308
|
+
task.repeats = numRepeats
|
|
309
|
+
newTasks.add(task)
|
|
310
|
+
taskToStatuses.set(task, [])
|
|
274
311
|
}
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
} catch (e) {
|
|
278
|
-
log.error('Vitest workers could not parse known tests, so Early Flake Detection will not work.')
|
|
312
|
+
}
|
|
313
|
+
})
|
|
279
314
|
}
|
|
280
315
|
|
|
281
316
|
return onBeforeRunTask.apply(this, arguments)
|
|
@@ -283,9 +318,7 @@ addHook({
|
|
|
283
318
|
|
|
284
319
|
// `onAfterRunTask` is run after all repetitions or attempts are run
|
|
285
320
|
shimmer.wrap(VitestTestRunner.prototype, 'onAfterRunTask', onAfterRunTask => async function (task) {
|
|
286
|
-
const {
|
|
287
|
-
_ddIsEarlyFlakeDetectionEnabled: isEarlyFlakeDetectionEnabled
|
|
288
|
-
} = globalThis.__vitest_worker__.providedContext
|
|
321
|
+
const { isEarlyFlakeDetectionEnabled } = getProvidedContext()
|
|
289
322
|
|
|
290
323
|
if (isEarlyFlakeDetectionEnabled && taskToStatuses.has(task)) {
|
|
291
324
|
const statuses = taskToStatuses.get(task)
|
|
@@ -309,43 +342,40 @@ addHook({
|
|
|
309
342
|
}
|
|
310
343
|
const testName = getTestName(task)
|
|
311
344
|
let isNew = false
|
|
312
|
-
let isEarlyFlakeDetectionEnabled = false
|
|
313
|
-
let isDiEnabled = false
|
|
314
|
-
|
|
315
|
-
try {
|
|
316
|
-
const {
|
|
317
|
-
_ddIsEarlyFlakeDetectionEnabled,
|
|
318
|
-
_ddIsDiEnabled
|
|
319
|
-
} = globalThis.__vitest_worker__.providedContext
|
|
320
345
|
|
|
321
|
-
|
|
322
|
-
|
|
346
|
+
const {
|
|
347
|
+
isEarlyFlakeDetectionEnabled,
|
|
348
|
+
isDiEnabled
|
|
349
|
+
} = getProvidedContext()
|
|
323
350
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
}
|
|
327
|
-
} catch (e) {
|
|
328
|
-
log.error('Vitest workers could not parse known tests, so Early Flake Detection will not work.')
|
|
351
|
+
if (isEarlyFlakeDetectionEnabled) {
|
|
352
|
+
isNew = newTasks.has(task)
|
|
329
353
|
}
|
|
354
|
+
|
|
330
355
|
const { retry: numAttempt, repeats: numRepetition } = retryInfo
|
|
331
356
|
|
|
332
357
|
// We finish the previous test here because we know it has failed already
|
|
333
358
|
if (numAttempt > 0) {
|
|
334
|
-
const
|
|
359
|
+
const shouldWaitForHitProbe = isDiEnabled && numAttempt > 1
|
|
360
|
+
if (shouldWaitForHitProbe) {
|
|
361
|
+
await waitForHitProbe()
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
const promises = {}
|
|
365
|
+
const shouldSetProbe = isDiEnabled && numAttempt === 1
|
|
335
366
|
const asyncResource = taskToAsync.get(task)
|
|
336
367
|
const testError = task.result?.errors?.[0]
|
|
337
368
|
if (asyncResource) {
|
|
338
369
|
asyncResource.runInAsyncScope(() => {
|
|
339
370
|
testErrorCh.publish({
|
|
340
371
|
error: testError,
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
isDiEnabled
|
|
372
|
+
shouldSetProbe,
|
|
373
|
+
promises
|
|
344
374
|
})
|
|
345
375
|
})
|
|
346
376
|
// We wait for the probe to be set
|
|
347
|
-
if (
|
|
348
|
-
await
|
|
377
|
+
if (promises.setProbePromise) {
|
|
378
|
+
await promises.setProbePromise
|
|
349
379
|
}
|
|
350
380
|
}
|
|
351
381
|
}
|
|
@@ -401,7 +431,8 @@ addHook({
|
|
|
401
431
|
testName,
|
|
402
432
|
testSuiteAbsolutePath: task.file.filepath,
|
|
403
433
|
isRetry: numAttempt > 0 || numRepetition > 0,
|
|
404
|
-
isNew
|
|
434
|
+
isNew,
|
|
435
|
+
mightHitProbe: isDiEnabled && numAttempt > 0
|
|
405
436
|
})
|
|
406
437
|
})
|
|
407
438
|
return onBeforeTryTask.apply(this, arguments)
|
|
@@ -418,6 +449,12 @@ addHook({
|
|
|
418
449
|
const status = getVitestTestStatus(task, retryCount)
|
|
419
450
|
const asyncResource = taskToAsync.get(task)
|
|
420
451
|
|
|
452
|
+
const { isDiEnabled } = getProvidedContext()
|
|
453
|
+
|
|
454
|
+
if (isDiEnabled && retryCount > 1) {
|
|
455
|
+
await waitForHitProbe()
|
|
456
|
+
}
|
|
457
|
+
|
|
421
458
|
if (asyncResource) {
|
|
422
459
|
// We don't finish here because the test might fail in a later hook (afterEach)
|
|
423
460
|
asyncResource.runInAsyncScope(() => {
|
|
@@ -457,15 +494,6 @@ addHook({
|
|
|
457
494
|
return vitestPackage
|
|
458
495
|
})
|
|
459
496
|
|
|
460
|
-
addHook({
|
|
461
|
-
name: 'vitest',
|
|
462
|
-
versions: ['>=2.1.0'],
|
|
463
|
-
filePattern: 'dist/chunks/RandomSequencer.*'
|
|
464
|
-
}, (randomSequencerPackage) => {
|
|
465
|
-
shimmer.wrap(randomSequencerPackage.B.prototype, 'sort', getSortWrapper)
|
|
466
|
-
return randomSequencerPackage
|
|
467
|
-
})
|
|
468
|
-
|
|
469
497
|
addHook({
|
|
470
498
|
name: 'vitest',
|
|
471
499
|
versions: ['>=2.0.5 <2.1.0'],
|
|
@@ -478,6 +506,24 @@ addHook({
|
|
|
478
506
|
return vitestPackage
|
|
479
507
|
})
|
|
480
508
|
|
|
509
|
+
addHook({
|
|
510
|
+
name: 'vitest',
|
|
511
|
+
versions: ['>=2.1.0 <3.0.0'],
|
|
512
|
+
filePattern: 'dist/chunks/RandomSequencer.*'
|
|
513
|
+
}, (randomSequencerPackage) => {
|
|
514
|
+
shimmer.wrap(randomSequencerPackage.B.prototype, 'sort', getSortWrapper)
|
|
515
|
+
return randomSequencerPackage
|
|
516
|
+
})
|
|
517
|
+
|
|
518
|
+
addHook({
|
|
519
|
+
name: 'vitest',
|
|
520
|
+
versions: ['>=3.0.0'],
|
|
521
|
+
filePattern: 'dist/chunks/resolveConfig.*'
|
|
522
|
+
}, (randomSequencerPackage) => {
|
|
523
|
+
shimmer.wrap(randomSequencerPackage.B.prototype, 'sort', getSortWrapper)
|
|
524
|
+
return randomSequencerPackage
|
|
525
|
+
})
|
|
526
|
+
|
|
481
527
|
// Can't specify file because compiled vitest includes hashes in their files
|
|
482
528
|
addHook({
|
|
483
529
|
name: 'vitest',
|
|
@@ -498,15 +544,17 @@ addHook({
|
|
|
498
544
|
versions: ['>=1.6.0'],
|
|
499
545
|
file: 'dist/index.js'
|
|
500
546
|
}, (vitestPackage, frameworkVersion) => {
|
|
501
|
-
shimmer.wrap(vitestPackage, 'startTests', startTests => async function (
|
|
547
|
+
shimmer.wrap(vitestPackage, 'startTests', startTests => async function (testPaths) {
|
|
502
548
|
let testSuiteError = null
|
|
503
549
|
if (!testSuiteStartCh.hasSubscribers) {
|
|
504
550
|
return startTests.apply(this, arguments)
|
|
505
551
|
}
|
|
552
|
+
// From >=3.0.1, the first arguments changes from a string to an object containing the filepath
|
|
553
|
+
const testSuiteAbsolutePath = testPaths[0]?.filepath || testPaths[0]
|
|
506
554
|
|
|
507
555
|
const testSuiteAsyncResource = new AsyncResource('bound-anonymous-fn')
|
|
508
556
|
testSuiteAsyncResource.runInAsyncScope(() => {
|
|
509
|
-
testSuiteStartCh.publish({ testSuiteAbsolutePath
|
|
557
|
+
testSuiteStartCh.publish({ testSuiteAbsolutePath, frameworkVersion })
|
|
510
558
|
})
|
|
511
559
|
const startTestsResponse = await startTests.apply(this, arguments)
|
|
512
560
|
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { channel, addHook } = require('./helpers/instrument')
|
|
4
|
+
const shimmer = require('../../datadog-shimmer')
|
|
5
|
+
const names = ['vm', 'node:vm']
|
|
6
|
+
|
|
7
|
+
const runScriptStartChannel = channel('datadog:vm:run-script:start')
|
|
8
|
+
const sourceTextModuleStartChannel = channel('datadog:vm:source-text-module:start')
|
|
9
|
+
|
|
10
|
+
addHook({ name: names }, function (vm) {
|
|
11
|
+
vm.Script = class extends vm.Script {
|
|
12
|
+
constructor (code) {
|
|
13
|
+
super(...arguments)
|
|
14
|
+
|
|
15
|
+
if (runScriptStartChannel.hasSubscribers && code) {
|
|
16
|
+
runScriptStartChannel.publish({ code })
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (vm.SourceTextModule && typeof vm.SourceTextModule === 'function') {
|
|
22
|
+
vm.SourceTextModule = class extends vm.SourceTextModule {
|
|
23
|
+
constructor (code) {
|
|
24
|
+
super(...arguments)
|
|
25
|
+
|
|
26
|
+
if (sourceTextModuleStartChannel.hasSubscribers && code) {
|
|
27
|
+
sourceTextModuleStartChannel.publish({ code })
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
shimmer.wrap(vm, 'runInContext', wrapVMMethod)
|
|
34
|
+
shimmer.wrap(vm, 'runInNewContext', wrapVMMethod)
|
|
35
|
+
shimmer.wrap(vm, 'runInThisContext', wrapVMMethod)
|
|
36
|
+
shimmer.wrap(vm, 'compileFunction', wrapVMMethod)
|
|
37
|
+
|
|
38
|
+
return vm
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
function wrapVMMethod (original) {
|
|
42
|
+
return function wrappedVMMethod (code) {
|
|
43
|
+
if (runScriptStartChannel.hasSubscribers && code) {
|
|
44
|
+
runScriptStartChannel.publish({ code })
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return original.apply(this, arguments)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const BaseAwsSdkPlugin = require('../base')
|
|
4
|
+
const log = require('../../../dd-trace/src/log')
|
|
5
|
+
|
|
6
|
+
const PROVIDER = {
|
|
7
|
+
AI21: 'AI21',
|
|
8
|
+
AMAZON: 'AMAZON',
|
|
9
|
+
ANTHROPIC: 'ANTHROPIC',
|
|
10
|
+
COHERE: 'COHERE',
|
|
11
|
+
META: 'META',
|
|
12
|
+
STABILITY: 'STABILITY',
|
|
13
|
+
MISTRAL: 'MISTRAL'
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const enabledOperations = ['invokeModel']
|
|
17
|
+
|
|
18
|
+
class BedrockRuntime extends BaseAwsSdkPlugin {
|
|
19
|
+
static get id () { return 'bedrock runtime' }
|
|
20
|
+
|
|
21
|
+
isEnabled (request) {
|
|
22
|
+
const operation = request.operation
|
|
23
|
+
if (!enabledOperations.includes(operation)) {
|
|
24
|
+
return false
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return super.isEnabled(request)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
generateTags (params, operation, response) {
|
|
31
|
+
let tags = {}
|
|
32
|
+
let modelName = ''
|
|
33
|
+
let modelProvider = ''
|
|
34
|
+
const modelMeta = params.modelId.split('.')
|
|
35
|
+
if (modelMeta.length === 2) {
|
|
36
|
+
[modelProvider, modelName] = modelMeta
|
|
37
|
+
modelProvider = modelProvider.toUpperCase()
|
|
38
|
+
} else {
|
|
39
|
+
[, modelProvider, modelName] = modelMeta
|
|
40
|
+
modelProvider = modelProvider.toUpperCase()
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const shouldSetChoiceIds = modelProvider === PROVIDER.COHERE && !modelName.includes('embed')
|
|
44
|
+
|
|
45
|
+
const requestParams = extractRequestParams(params, modelProvider)
|
|
46
|
+
const textAndResponseReason = extractTextAndResponseReason(response, modelProvider, modelName, shouldSetChoiceIds)
|
|
47
|
+
|
|
48
|
+
tags = buildTagsFromParams(requestParams, textAndResponseReason, modelProvider, modelName, operation)
|
|
49
|
+
|
|
50
|
+
return tags
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
class Generation {
|
|
55
|
+
constructor ({ message = '', finishReason = '', choiceId = '' } = {}) {
|
|
56
|
+
// stringify message as it could be a single generated message as well as a list of embeddings
|
|
57
|
+
this.message = typeof message === 'string' ? message : JSON.stringify(message) || ''
|
|
58
|
+
this.finishReason = finishReason || ''
|
|
59
|
+
this.choiceId = choiceId || undefined
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
class RequestParams {
|
|
64
|
+
constructor ({
|
|
65
|
+
prompt = '',
|
|
66
|
+
temperature = undefined,
|
|
67
|
+
topP = undefined,
|
|
68
|
+
maxTokens = undefined,
|
|
69
|
+
stopSequences = [],
|
|
70
|
+
inputType = '',
|
|
71
|
+
truncate = '',
|
|
72
|
+
stream = '',
|
|
73
|
+
n = undefined
|
|
74
|
+
} = {}) {
|
|
75
|
+
// TODO: set a truncation limit to prompt
|
|
76
|
+
// stringify prompt as it could be a single prompt as well as a list of message objects
|
|
77
|
+
this.prompt = typeof prompt === 'string' ? prompt : JSON.stringify(prompt) || ''
|
|
78
|
+
this.temperature = temperature !== undefined ? temperature : undefined
|
|
79
|
+
this.topP = topP !== undefined ? topP : undefined
|
|
80
|
+
this.maxTokens = maxTokens !== undefined ? maxTokens : undefined
|
|
81
|
+
this.stopSequences = stopSequences || []
|
|
82
|
+
this.inputType = inputType || ''
|
|
83
|
+
this.truncate = truncate || ''
|
|
84
|
+
this.stream = stream || ''
|
|
85
|
+
this.n = n !== undefined ? n : undefined
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function extractRequestParams (params, provider) {
|
|
90
|
+
const requestBody = JSON.parse(params.body)
|
|
91
|
+
const modelId = params.modelId
|
|
92
|
+
|
|
93
|
+
switch (provider) {
|
|
94
|
+
case PROVIDER.AI21: {
|
|
95
|
+
let userPrompt = requestBody.prompt
|
|
96
|
+
if (modelId.includes('jamba')) {
|
|
97
|
+
for (const message of requestBody.messages) {
|
|
98
|
+
if (message.role === 'user') {
|
|
99
|
+
userPrompt = message.content // Return the content of the most recent user message
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return new RequestParams({
|
|
104
|
+
prompt: userPrompt,
|
|
105
|
+
temperature: requestBody.temperature,
|
|
106
|
+
topP: requestBody.top_p,
|
|
107
|
+
maxTokens: requestBody.max_tokens,
|
|
108
|
+
stopSequences: requestBody.stop_sequences
|
|
109
|
+
})
|
|
110
|
+
}
|
|
111
|
+
case PROVIDER.AMAZON: {
|
|
112
|
+
if (modelId.includes('embed')) {
|
|
113
|
+
return new RequestParams({ prompt: requestBody.inputText })
|
|
114
|
+
}
|
|
115
|
+
const textGenerationConfig = requestBody.textGenerationConfig || {}
|
|
116
|
+
return new RequestParams({
|
|
117
|
+
prompt: requestBody.inputText,
|
|
118
|
+
temperature: textGenerationConfig.temperature,
|
|
119
|
+
topP: textGenerationConfig.topP,
|
|
120
|
+
maxTokens: textGenerationConfig.maxTokenCount,
|
|
121
|
+
stopSequences: textGenerationConfig.stopSequences
|
|
122
|
+
})
|
|
123
|
+
}
|
|
124
|
+
case PROVIDER.ANTHROPIC: {
|
|
125
|
+
const prompt = requestBody.prompt || requestBody.messages
|
|
126
|
+
return new RequestParams({
|
|
127
|
+
prompt,
|
|
128
|
+
temperature: requestBody.temperature,
|
|
129
|
+
topP: requestBody.top_p,
|
|
130
|
+
maxTokens: requestBody.max_tokens_to_sample,
|
|
131
|
+
stopSequences: requestBody.stop_sequences
|
|
132
|
+
})
|
|
133
|
+
}
|
|
134
|
+
case PROVIDER.COHERE: {
|
|
135
|
+
if (modelId.includes('embed')) {
|
|
136
|
+
return new RequestParams({
|
|
137
|
+
prompt: requestBody.texts,
|
|
138
|
+
inputType: requestBody.input_type,
|
|
139
|
+
truncate: requestBody.truncate
|
|
140
|
+
})
|
|
141
|
+
}
|
|
142
|
+
return new RequestParams({
|
|
143
|
+
prompt: requestBody.prompt,
|
|
144
|
+
temperature: requestBody.temperature,
|
|
145
|
+
topP: requestBody.p,
|
|
146
|
+
maxTokens: requestBody.max_tokens,
|
|
147
|
+
stopSequences: requestBody.stop_sequences,
|
|
148
|
+
stream: requestBody.stream,
|
|
149
|
+
n: requestBody.num_generations
|
|
150
|
+
})
|
|
151
|
+
}
|
|
152
|
+
case PROVIDER.META: {
|
|
153
|
+
return new RequestParams({
|
|
154
|
+
prompt: requestBody.prompt,
|
|
155
|
+
temperature: requestBody.temperature,
|
|
156
|
+
topP: requestBody.top_p,
|
|
157
|
+
maxTokens: requestBody.max_gen_len
|
|
158
|
+
})
|
|
159
|
+
}
|
|
160
|
+
case PROVIDER.MISTRAL: {
|
|
161
|
+
return new RequestParams({
|
|
162
|
+
prompt: requestBody.prompt,
|
|
163
|
+
temperature: requestBody.temperature,
|
|
164
|
+
topP: requestBody.top_p,
|
|
165
|
+
maxTokens: requestBody.max_tokens,
|
|
166
|
+
stopSequences: requestBody.stop,
|
|
167
|
+
topK: requestBody.top_k
|
|
168
|
+
})
|
|
169
|
+
}
|
|
170
|
+
case PROVIDER.STABILITY: {
|
|
171
|
+
return new RequestParams()
|
|
172
|
+
}
|
|
173
|
+
default: {
|
|
174
|
+
return new RequestParams()
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function extractTextAndResponseReason (response, provider, modelName, shouldSetChoiceIds) {
|
|
180
|
+
const body = JSON.parse(Buffer.from(response.body).toString('utf8'))
|
|
181
|
+
|
|
182
|
+
try {
|
|
183
|
+
switch (provider) {
|
|
184
|
+
case PROVIDER.AI21: {
|
|
185
|
+
if (modelName.includes('jamba')) {
|
|
186
|
+
const generations = body.choices || []
|
|
187
|
+
if (generations.length > 0) {
|
|
188
|
+
const generation = generations[0]
|
|
189
|
+
return new Generation({
|
|
190
|
+
message: generation.message,
|
|
191
|
+
finishReason: generation.finish_reason,
|
|
192
|
+
choiceId: shouldSetChoiceIds ? generation.id : undefined
|
|
193
|
+
})
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
const completions = body.completions || []
|
|
197
|
+
if (completions.length > 0) {
|
|
198
|
+
const completion = completions[0]
|
|
199
|
+
return new Generation({
|
|
200
|
+
message: completion.data?.text,
|
|
201
|
+
finishReason: completion?.finishReason,
|
|
202
|
+
choiceId: shouldSetChoiceIds ? completion?.id : undefined
|
|
203
|
+
})
|
|
204
|
+
}
|
|
205
|
+
return new Generation()
|
|
206
|
+
}
|
|
207
|
+
case PROVIDER.AMAZON: {
|
|
208
|
+
if (modelName.includes('embed')) {
|
|
209
|
+
return new Generation({ message: body.embedding })
|
|
210
|
+
}
|
|
211
|
+
const results = body.results || []
|
|
212
|
+
if (results.length > 0) {
|
|
213
|
+
const result = results[0]
|
|
214
|
+
return new Generation({ message: result.outputText, finishReason: result.completionReason })
|
|
215
|
+
}
|
|
216
|
+
break
|
|
217
|
+
}
|
|
218
|
+
case PROVIDER.ANTHROPIC: {
|
|
219
|
+
return new Generation({ message: body.completion || body.content, finishReason: body.stop_reason })
|
|
220
|
+
}
|
|
221
|
+
case PROVIDER.COHERE: {
|
|
222
|
+
if (modelName.includes('embed')) {
|
|
223
|
+
const embeddings = body.embeddings || [[]]
|
|
224
|
+
if (embeddings.length > 0) {
|
|
225
|
+
return new Generation({ message: embeddings[0] })
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
const generations = body.generations || []
|
|
229
|
+
if (generations.length > 0) {
|
|
230
|
+
const generation = generations[0]
|
|
231
|
+
return new Generation({
|
|
232
|
+
message: generation.text,
|
|
233
|
+
finishReason: generation.finish_reason,
|
|
234
|
+
choiceId: shouldSetChoiceIds ? generation.id : undefined
|
|
235
|
+
})
|
|
236
|
+
}
|
|
237
|
+
break
|
|
238
|
+
}
|
|
239
|
+
case PROVIDER.META: {
|
|
240
|
+
return new Generation({ message: body.generation, finishReason: body.stop_reason })
|
|
241
|
+
}
|
|
242
|
+
case PROVIDER.MISTRAL: {
|
|
243
|
+
const mistralGenerations = body.outputs || []
|
|
244
|
+
if (mistralGenerations.length > 0) {
|
|
245
|
+
const generation = mistralGenerations[0]
|
|
246
|
+
return new Generation({ message: generation.text, finishReason: generation.stop_reason })
|
|
247
|
+
}
|
|
248
|
+
break
|
|
249
|
+
}
|
|
250
|
+
case PROVIDER.STABILITY: {
|
|
251
|
+
return new Generation()
|
|
252
|
+
}
|
|
253
|
+
default: {
|
|
254
|
+
return new Generation()
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
} catch (error) {
|
|
258
|
+
log.warn('Unable to extract text/finishReason from response body. Defaulting to empty text/finishReason.')
|
|
259
|
+
return new Generation()
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return new Generation()
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function buildTagsFromParams (requestParams, textAndResponseReason, modelProvider, modelName, operation) {
|
|
266
|
+
const tags = {}
|
|
267
|
+
|
|
268
|
+
// add request tags
|
|
269
|
+
tags['resource.name'] = operation
|
|
270
|
+
tags['aws.bedrock.request.model'] = modelName
|
|
271
|
+
tags['aws.bedrock.request.model_provider'] = modelProvider
|
|
272
|
+
tags['aws.bedrock.request.prompt'] = requestParams.prompt
|
|
273
|
+
tags['aws.bedrock.request.temperature'] = requestParams.temperature
|
|
274
|
+
tags['aws.bedrock.request.top_p'] = requestParams.topP
|
|
275
|
+
tags['aws.bedrock.request.max_tokens'] = requestParams.maxTokens
|
|
276
|
+
tags['aws.bedrock.request.stop_sequences'] = requestParams.stopSequences
|
|
277
|
+
tags['aws.bedrock.request.input_type'] = requestParams.inputType
|
|
278
|
+
tags['aws.bedrock.request.truncate'] = requestParams.truncate
|
|
279
|
+
tags['aws.bedrock.request.stream'] = requestParams.stream
|
|
280
|
+
tags['aws.bedrock.request.n'] = requestParams.n
|
|
281
|
+
|
|
282
|
+
// add response tags
|
|
283
|
+
if (modelName.includes('embed')) {
|
|
284
|
+
tags['aws.bedrock.response.embedding_length'] = textAndResponseReason.message.length
|
|
285
|
+
}
|
|
286
|
+
if (textAndResponseReason.choiceId) {
|
|
287
|
+
tags['aws.bedrock.response.choices.id'] = textAndResponseReason.choiceId
|
|
288
|
+
}
|
|
289
|
+
tags['aws.bedrock.response.choices.text'] = textAndResponseReason.message
|
|
290
|
+
tags['aws.bedrock.response.choices.finish_reason'] = textAndResponseReason.finishReason
|
|
291
|
+
|
|
292
|
+
return tags
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
module.exports = BedrockRuntime
|