-
Notifications
You must be signed in to change notification settings - Fork 340
feat(ai): add vercel ai integration #5858
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
Open
sabrenner
wants to merge
56
commits into
master
Choose a base branch
from
sabrenner/vercel-ai-sdk-integration
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+4,099
−4
Open
Changes from 3 commits
Commits
Show all changes
56 commits
Select commit
Hold shift + click to select a range
94a2b68
add vercel ai integration with otel processing
sabrenner 0ed7d4c
add some typedocs and comments
sabrenner 233beb8
fix tagger test
sabrenner 90f4f13
rename to 'ai'
sabrenner a4014cc
try doing with a custom tracer
sabrenner 407d6dc
change up implementation slightly
sabrenner 16c3d28
codeowners
sabrenner fbff2a3
undo id changes
sabrenner d963226
get rid of otel span start/end publishes
sabrenner 067c596
revert llmobs tagger test change
sabrenner 24f37a8
add better noop default tracer and esm support
sabrenner 563d56f
delete util file
sabrenner 7e906a2
Merge branch 'master' of github.com:DataDog/dd-trace-js into sabrenne…
sabrenner 47056b9
add initial test skeleton
sabrenner 2da477f
fix duplicate wrapping
sabrenner a43db02
Merge branch 'master' of github.com:DataDog/dd-trace-js into sabrenne…
sabrenner cc9b031
simplify patching
sabrenner 2015808
apm tests
sabrenner 2ce1798
Merge branch 'master' of github.com:DataDog/dd-trace-js into sabrenne…
sabrenner 5a5a23c
Merge branch 'master' of github.com:DataDog/dd-trace-js into sabrenne…
sabrenner 16c5da4
write some tests
sabrenner 0c2df21
add rest of llmobs tests
sabrenner f47cc43
add ci job
sabrenner 85ec1c8
fix node version and import issue with check and externally defined v…
sabrenner 39f3eb9
fix metadata tagging
sabrenner c403681
handle tool rolls
sabrenner 15bcb79
remove import
sabrenner de7c0fa
add default return and docstring for formatMessage
sabrenner ffb75c1
Merge branch 'master' of github.com:DataDog/dd-trace-js into sabrenne…
sabrenner c60316b
fix tool message tests
sabrenner 1824313
add model name and provider tags to apm tracing
sabrenner 95ebae1
some self review
sabrenner d19e31b
address some review comments
sabrenner c03fc82
do not stub for tests, instead use dummy test agent
sabrenner 20c3c63
move cassettes to local directory to fix tests
sabrenner 0f1acf6
configurable flush interval for tests
sabrenner 72eca83
use separate image for ai tests that have local cassettes attached
sabrenner ac4071c
use different port
sabrenner 39ccf68
move test flush interval back local
sabrenner 32d75a6
change in esm test
sabrenner d1fbc64
Revert "move test flush interval back local"
sabrenner b705691
Revert "use different port"
sabrenner b28bd92
Revert "use separate image for ai tests that have local cassettes att…
sabrenner bec9312
Revert "move cassettes to local directory to fix tests"
sabrenner b642965
Revert "change in esm test"
sabrenner bbbfffb
remove env var from llmobs workflow
sabrenner 85abd5d
fix type hint for test util
sabrenner 8d1662e
Merge branch 'master' of github.com:DataDog/dd-trace-js into sabrenne…
sabrenner 2bd92ee
add test cassettes
sabrenner f9cfc5c
re-trigger ci
sabrenner 9fc3d13
more review fixes
sabrenner 5f6bc14
Merge branch 'master' into sabrenner/vercel-ai-sdk-integration
sabrenner 25a83e5
try removing configuration
sabrenner 8036e15
Merge branch 'sabrenner/vercel-ai-sdk-integration' of github.com:Data…
sabrenner 3d428da
revert supported config undoing
sabrenner 2938177
Merge branch 'master' into sabrenner/vercel-ai-sdk-integration
sabrenner File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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,70 @@ | ||
'use strict' | ||
|
||
const { addHook } = require('./helpers/instrument') | ||
const tracer = require('../../dd-trace') | ||
const shimmer = require('../../datadog-shimmer') | ||
|
||
const { TracerProvider } = tracer | ||
const provider = new TracerProvider() | ||
provider.register() | ||
|
||
const { channel } = require('dc-polyfill') | ||
const toolCreationChannel = channel('dd-trace:vercel-ai:tool') | ||
|
||
const TRACED_FUNCTIONS = { | ||
generateText: wrapWithTracer, | ||
streamText: wrapWithTracer, | ||
generateObject: wrapWithTracer, | ||
streamObject: wrapWithTracer, | ||
embed: wrapWithTracer, | ||
embedMany: wrapWithTracer, | ||
tool: wrapTool | ||
} | ||
|
||
function wrapWithTracer (fn) { | ||
return function () { | ||
const options = arguments[0] | ||
if (options.experimental_telemetry != null) return fn.apply(this, arguments) | ||
|
||
options.experimental_telemetry = { | ||
isEnabled: true, | ||
// TODO(sabrenner): need to figure out how a user can configure this tracer | ||
// maybe we advise they do this manually? | ||
tracer: provider.getTracer() | ||
sabrenner marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
return fn.apply(this, arguments) | ||
} | ||
} | ||
|
||
function wrapTool (tool) { | ||
return function () { | ||
const args = arguments[0] | ||
toolCreationChannel.publish(args) | ||
|
||
return tool.apply(this, arguments) | ||
} | ||
} | ||
|
||
addHook({ | ||
name: 'ai', | ||
versions: ['>=4.0.0'], | ||
}, exports => { | ||
// the exports from this package are not configurable | ||
// to return wrapped functions with the tracer provided above, | ||
// we need to copy the exports | ||
const wrappedExports = {} | ||
|
||
for (const [fnName, patchingFn] of Object.entries(TRACED_FUNCTIONS)) { | ||
const original = exports[fnName] | ||
wrappedExports[fnName] = shimmer.wrapFunction(original, patchingFn) | ||
} | ||
|
||
Object.getOwnPropertyNames(exports).forEach(prop => { | ||
if (!Object.keys(TRACED_FUNCTIONS).includes(prop)) { | ||
wrappedExports[prop] = exports[prop] | ||
} | ||
}) | ||
|
||
return wrappedExports | ||
}) |
This file contains hidden or 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,17 @@ | ||
'use strict' | ||
|
||
const CompositePlugin = require('../../dd-trace/src/plugins/composite') | ||
const VercelAILLMObsPlugin = require('../../dd-trace/src/llmobs/plugins/vercel-ai') | ||
const VercelAITracingPlugin = require('./tracing') | ||
|
||
class VercelAIPlugin extends CompositePlugin { | ||
static get id () { return 'vercel-ai' } | ||
static get plugins () { | ||
return { | ||
llmobs: VercelAILLMObsPlugin, | ||
tracing: VercelAITracingPlugin | ||
} | ||
} | ||
} | ||
|
||
module.exports = VercelAIPlugin |
This file contains hidden or 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,55 @@ | ||
'use strict' | ||
|
||
const Plugin = require('../../dd-trace/src/plugins/plugin') | ||
|
||
const { channel } = require('dc-polyfill') | ||
const spanFinishCh = channel('dd-trace:otel:span:finish') | ||
|
||
const { isVercelAISpan } = require('./util') | ||
|
||
// filter input/output based tags for APM spans | ||
// this is for data access controls and for sensitive data | ||
// the LLM Observability feature is recommended in its place for better | ||
// data access controls and sensitive data scrubbing | ||
const TAG_PATTERNS_TO_FILTER = [ | ||
'prompt', // TODO(sabrenner): we need to refine this so it doesn't filter out prompt tokens | ||
'messages', | ||
'response.text', | ||
'toolCalls', | ||
'toolCall.args', | ||
'toolCall.result', | ||
'values', | ||
'embedding' | ||
] | ||
|
||
/** | ||
* Determines if an OpenTelemetry span tag should be filtered out on the final DD span | ||
* | ||
* @param {String} key | ||
* @returns {Boolean} | ||
*/ | ||
function shouldFilterTag (key) { | ||
return TAG_PATTERNS_TO_FILTER.some(pattern => key.includes(pattern)) | ||
} | ||
|
||
class VercelAITracingPlugin extends Plugin { | ||
static get id () { return 'ai' } | ||
|
||
constructor (...args) { | ||
super(...args) | ||
|
||
spanFinishCh.subscribe(({ ddSpan }) => { | ||
if (!isVercelAISpan(ddSpan)) { | ||
return | ||
} | ||
|
||
for (const key of Object.keys(ddSpan.context()._tags)) { | ||
if (shouldFilterTag(key)) { | ||
ddSpan.setTag(key, undefined) | ||
} | ||
} | ||
}) | ||
} | ||
} | ||
|
||
module.exports = VercelAITracingPlugin |
This file contains hidden or 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,15 @@ | ||
'use strict' | ||
|
||
/** | ||
* Determines if an OpenTelemetry span is a Vercel AI span | ||
* | ||
* @param {import('../../dd-trace/src/opentracing/span') | null} span | ||
* @returns {Boolean} | ||
*/ | ||
function isVercelAISpan (span) { | ||
return span._name?.startsWith('ai') && span.context()._tags?.['resource.name']?.startsWith('ai') | ||
} | ||
|
||
module.exports = { | ||
isVercelAISpan | ||
} |
This file contains hidden or 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 hidden or 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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.