@arizeai/openinference-instrumentation-beeai 1.0.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 +201 -0
- package/README.md +80 -0
- package/dist/esm/config.d.ts +39 -0
- package/dist/esm/config.d.ts.map +1 -0
- package/dist/esm/config.js +39 -0
- package/dist/esm/config.js.map +1 -0
- package/dist/esm/helpers/buildTraceTree.d.ts +21 -0
- package/dist/esm/helpers/buildTraceTree.d.ts.map +1 -0
- package/dist/esm/helpers/buildTraceTree.js +71 -0
- package/dist/esm/helpers/buildTraceTree.js.map +1 -0
- package/dist/esm/helpers/create-span.d.ts +32 -0
- package/dist/esm/helpers/create-span.d.ts.map +1 -0
- package/dist/esm/helpers/create-span.js +42 -0
- package/dist/esm/helpers/create-span.js.map +1 -0
- package/dist/esm/helpers/getErrorSafe.d.ts +17 -0
- package/dist/esm/helpers/getErrorSafe.d.ts.map +1 -0
- package/dist/esm/helpers/getErrorSafe.js +24 -0
- package/dist/esm/helpers/getErrorSafe.js.map +1 -0
- package/dist/esm/helpers/getSerializedObjectSafe.d.ts +18 -0
- package/dist/esm/helpers/getSerializedObjectSafe.d.ts.map +1 -0
- package/dist/esm/helpers/getSerializedObjectSafe.js +217 -0
- package/dist/esm/helpers/getSerializedObjectSafe.js.map +1 -0
- package/dist/esm/helpers/idNameManager.d.ts +31 -0
- package/dist/esm/helpers/idNameManager.d.ts.map +1 -0
- package/dist/esm/helpers/idNameManager.js +50 -0
- package/dist/esm/helpers/idNameManager.js.map +1 -0
- package/dist/esm/helpers/traceSerializer.d.ts +19 -0
- package/dist/esm/helpers/traceSerializer.d.ts.map +1 -0
- package/dist/esm/helpers/traceSerializer.js +35 -0
- package/dist/esm/helpers/traceSerializer.js.map +1 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/instrumentation.d.ts +34 -0
- package/dist/esm/instrumentation.d.ts.map +1 -0
- package/dist/esm/instrumentation.js +71 -0
- package/dist/esm/instrumentation.js.map +1 -0
- package/dist/esm/middleware.d.ts +27 -0
- package/dist/esm/middleware.d.ts.map +1 -0
- package/dist/esm/middleware.js +247 -0
- package/dist/esm/middleware.js.map +1 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -0
- package/dist/esm/types.d.ts +36 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +17 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esnext/config.d.ts +39 -0
- package/dist/esnext/config.d.ts.map +1 -0
- package/dist/esnext/config.js +39 -0
- package/dist/esnext/config.js.map +1 -0
- package/dist/esnext/helpers/buildTraceTree.d.ts +21 -0
- package/dist/esnext/helpers/buildTraceTree.d.ts.map +1 -0
- package/dist/esnext/helpers/buildTraceTree.js +57 -0
- package/dist/esnext/helpers/buildTraceTree.js.map +1 -0
- package/dist/esnext/helpers/create-span.d.ts +32 -0
- package/dist/esnext/helpers/create-span.d.ts.map +1 -0
- package/dist/esnext/helpers/create-span.js +37 -0
- package/dist/esnext/helpers/create-span.js.map +1 -0
- package/dist/esnext/helpers/getErrorSafe.d.ts +17 -0
- package/dist/esnext/helpers/getErrorSafe.d.ts.map +1 -0
- package/dist/esnext/helpers/getErrorSafe.js +24 -0
- package/dist/esnext/helpers/getErrorSafe.js.map +1 -0
- package/dist/esnext/helpers/getSerializedObjectSafe.d.ts +18 -0
- package/dist/esnext/helpers/getSerializedObjectSafe.d.ts.map +1 -0
- package/dist/esnext/helpers/getSerializedObjectSafe.js +165 -0
- package/dist/esnext/helpers/getSerializedObjectSafe.js.map +1 -0
- package/dist/esnext/helpers/idNameManager.d.ts +31 -0
- package/dist/esnext/helpers/idNameManager.d.ts.map +1 -0
- package/dist/esnext/helpers/idNameManager.js +50 -0
- package/dist/esnext/helpers/idNameManager.js.map +1 -0
- package/dist/esnext/helpers/traceSerializer.d.ts +19 -0
- package/dist/esnext/helpers/traceSerializer.d.ts.map +1 -0
- package/dist/esnext/helpers/traceSerializer.js +35 -0
- package/dist/esnext/helpers/traceSerializer.js.map +1 -0
- package/dist/esnext/index.d.ts +2 -0
- package/dist/esnext/index.d.ts.map +1 -0
- package/dist/esnext/index.js +2 -0
- package/dist/esnext/index.js.map +1 -0
- package/dist/esnext/instrumentation.d.ts +34 -0
- package/dist/esnext/instrumentation.d.ts.map +1 -0
- package/dist/esnext/instrumentation.js +71 -0
- package/dist/esnext/instrumentation.js.map +1 -0
- package/dist/esnext/middleware.d.ts +27 -0
- package/dist/esnext/middleware.d.ts.map +1 -0
- package/dist/esnext/middleware.js +241 -0
- package/dist/esnext/middleware.js.map +1 -0
- package/dist/esnext/tsconfig.esnext.tsbuildinfo +1 -0
- package/dist/esnext/types.d.ts +36 -0
- package/dist/esnext/types.d.ts.map +1 -0
- package/dist/esnext/types.js +17 -0
- package/dist/esnext/types.js.map +1 -0
- package/dist/examples/bee.d.ts +2 -0
- package/dist/examples/bee.d.ts.map +1 -0
- package/dist/examples/bee.js +35 -0
- package/dist/examples/bee.js.map +1 -0
- package/dist/examples/instrumentation.d.ts +2 -0
- package/dist/examples/instrumentation.d.ts.map +1 -0
- package/dist/examples/instrumentation.js +54 -0
- package/dist/examples/instrumentation.js.map +1 -0
- package/dist/src/config.d.ts +39 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +42 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/helpers/buildTraceTree.d.ts +21 -0
- package/dist/src/helpers/buildTraceTree.d.ts.map +1 -0
- package/dist/src/helpers/buildTraceTree.js +60 -0
- package/dist/src/helpers/buildTraceTree.js.map +1 -0
- package/dist/src/helpers/create-span.d.ts +32 -0
- package/dist/src/helpers/create-span.d.ts.map +1 -0
- package/dist/src/helpers/create-span.js +40 -0
- package/dist/src/helpers/create-span.js.map +1 -0
- package/dist/src/helpers/getErrorSafe.d.ts +17 -0
- package/dist/src/helpers/getErrorSafe.d.ts.map +1 -0
- package/dist/src/helpers/getErrorSafe.js +27 -0
- package/dist/src/helpers/getErrorSafe.js.map +1 -0
- package/dist/src/helpers/getSerializedObjectSafe.d.ts +18 -0
- package/dist/src/helpers/getSerializedObjectSafe.d.ts.map +1 -0
- package/dist/src/helpers/getSerializedObjectSafe.js +168 -0
- package/dist/src/helpers/getSerializedObjectSafe.js.map +1 -0
- package/dist/src/helpers/idNameManager.d.ts +31 -0
- package/dist/src/helpers/idNameManager.d.ts.map +1 -0
- package/dist/src/helpers/idNameManager.js +54 -0
- package/dist/src/helpers/idNameManager.js.map +1 -0
- package/dist/src/helpers/traceSerializer.d.ts +19 -0
- package/dist/src/helpers/traceSerializer.d.ts.map +1 -0
- package/dist/src/helpers/traceSerializer.js +38 -0
- package/dist/src/helpers/traceSerializer.js.map +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +18 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/instrumentation.d.ts +34 -0
- package/dist/src/instrumentation.d.ts.map +1 -0
- package/dist/src/instrumentation.js +76 -0
- package/dist/src/instrumentation.js.map +1 -0
- package/dist/src/middleware.d.ts +27 -0
- package/dist/src/middleware.d.ts.map +1 -0
- package/dist/src/middleware.js +254 -0
- package/dist/src/middleware.js.map +1 -0
- package/dist/src/types.d.ts +36 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +18 -0
- package/dist/src/types.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +64 -0
- package/src/config.ts +48 -0
- package/src/helpers/buildTraceTree.ts +118 -0
- package/src/helpers/create-span.ts +66 -0
- package/src/helpers/getErrorSafe.ts +26 -0
- package/src/helpers/getSerializedObjectSafe.ts +325 -0
- package/src/helpers/idNameManager.ts +53 -0
- package/src/helpers/traceSerializer.ts +46 -0
- package/src/index.ts +1 -0
- package/src/instrumentation.ts +123 -0
- package/src/middleware.ts +318 -0
- package/src/types.ts +38 -0
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@arizeai/openinference-instrumentation-beeai",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "Apache-2.0",
|
|
5
|
+
"author": "gallas.milan@gmail.com",
|
|
6
|
+
"description": "OpenInference Instrumentation for BeeAI framework",
|
|
7
|
+
"private": false,
|
|
8
|
+
"main": "dist/src/index.js",
|
|
9
|
+
"module": "dist/esm/index.js",
|
|
10
|
+
"esnext": "dist/esnext/index.js",
|
|
11
|
+
"types": "dist/src/index.d.ts",
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "https://github.com/Arize-ai/openinference.git"
|
|
15
|
+
},
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"import": "./dist/esm/index.js",
|
|
19
|
+
"require": "./dist/src/index.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"src"
|
|
25
|
+
],
|
|
26
|
+
"keywords": [
|
|
27
|
+
"beeai",
|
|
28
|
+
"opentelemetry",
|
|
29
|
+
"tracing"
|
|
30
|
+
],
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@opentelemetry/api": "^1.9.0",
|
|
33
|
+
"@opentelemetry/instrumentation": "^0.57.1",
|
|
34
|
+
"remeda": "^2.20.2",
|
|
35
|
+
"@arizeai/openinference-core": "1.0.0",
|
|
36
|
+
"@arizeai/openinference-semantic-conventions": "1.0.0"
|
|
37
|
+
},
|
|
38
|
+
"peerDependencies": {
|
|
39
|
+
"beeai-framework": "^0.1.5"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/jest": "^29.5.12",
|
|
43
|
+
"@types/node": "^20.14.11",
|
|
44
|
+
"beeai-framework": "^0.1.5",
|
|
45
|
+
"import-in-the-middle": "^1.13.0",
|
|
46
|
+
"@opentelemetry/exporter-trace-otlp-proto": "^0.50.0",
|
|
47
|
+
"@opentelemetry/resources": "^1.30.1",
|
|
48
|
+
"@opentelemetry/sdk-node": "^0.57.1",
|
|
49
|
+
"@opentelemetry/sdk-trace-node": "^1.30.1",
|
|
50
|
+
"@opentelemetry/semantic-conventions": "^1.28.0",
|
|
51
|
+
"jest": "^29.7.0",
|
|
52
|
+
"ts-node": "^10.9.2"
|
|
53
|
+
},
|
|
54
|
+
"optionalDependencies": {
|
|
55
|
+
"ollama": "^0.5.12"
|
|
56
|
+
},
|
|
57
|
+
"scripts": {
|
|
58
|
+
"prebuild": "rimraf dist",
|
|
59
|
+
"build": "tsc --build tsconfig.json tsconfig.esm.json tsconfig.esnext.json && tsc-alias -p tsconfig.esm.json",
|
|
60
|
+
"postbuild": "echo '{\"type\": \"module\"}' > ./dist/esm/package.json && rimraf dist/test",
|
|
61
|
+
"type:check": "tsc --noEmit",
|
|
62
|
+
"test": "jest"
|
|
63
|
+
}
|
|
64
|
+
}
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2025 IBM Corp.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { BeeCallbacks } from "beeai-framework/agents/bee/types";
|
|
18
|
+
import { ChatModelEvents } from "beeai-framework/backend/chat";
|
|
19
|
+
import { ToolEvents } from "beeai-framework/tools/base";
|
|
20
|
+
|
|
21
|
+
export const INSTRUMENTATION_IGNORED_KEYS = process.env
|
|
22
|
+
.BEE_FRAMEWORK_INSTRUMENTATION_IGNORED_KEYS
|
|
23
|
+
? process.env.BEE_FRAMEWORK_INSTRUMENTATION_IGNORED_KEYS.split(",").filter(
|
|
24
|
+
Boolean,
|
|
25
|
+
)
|
|
26
|
+
: [];
|
|
27
|
+
|
|
28
|
+
export const partialUpdateEventName: keyof BeeCallbacks = "partialUpdate";
|
|
29
|
+
export const updateEventName: keyof BeeCallbacks = "update";
|
|
30
|
+
export const toolErrorEventName: keyof BeeCallbacks = "toolError";
|
|
31
|
+
export const toolStartEventName: keyof BeeCallbacks = "toolStart";
|
|
32
|
+
export const toolSuccessEventName: keyof BeeCallbacks = "toolSuccess";
|
|
33
|
+
export const startEventName: keyof BeeCallbacks = "start";
|
|
34
|
+
export const successEventName: keyof BeeCallbacks = "success";
|
|
35
|
+
export const errorEventName: keyof BeeCallbacks = "error";
|
|
36
|
+
export const retryEventName: keyof BeeCallbacks = "retry";
|
|
37
|
+
|
|
38
|
+
export const newTokenLLMEventName: keyof ChatModelEvents = `newToken`;
|
|
39
|
+
export const successLLMEventName: keyof ChatModelEvents = `success`;
|
|
40
|
+
export const startLLMEventName: keyof ChatModelEvents = `start`;
|
|
41
|
+
export const errorLLMEventName: keyof ChatModelEvents = `error`;
|
|
42
|
+
export const finishLLMEventName: keyof ChatModelEvents = `finish`;
|
|
43
|
+
|
|
44
|
+
export const startToolEventName: keyof ToolEvents = "start";
|
|
45
|
+
export const successToolEventName: keyof ToolEvents = "success";
|
|
46
|
+
export const finishToolEventName: keyof ToolEvents = "finish";
|
|
47
|
+
export const retryToolEventName: keyof ToolEvents = "retry";
|
|
48
|
+
export const errorToolEventName: keyof ToolEvents = "error";
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { OITracer } from "@arizeai/openinference-core";
|
|
2
|
+
import { FrameworkSpan, GeneratedResponse } from "../types";
|
|
3
|
+
import { SpanStatusCode, TimeInput } from "@opentelemetry/api";
|
|
4
|
+
import {
|
|
5
|
+
OpenInferenceSpanKind,
|
|
6
|
+
SemanticConventions,
|
|
7
|
+
} from "@arizeai/openinference-semantic-conventions";
|
|
8
|
+
|
|
9
|
+
interface BuiltTraceTreeProps {
|
|
10
|
+
tracer: OITracer;
|
|
11
|
+
data: {
|
|
12
|
+
prompt?: string | null;
|
|
13
|
+
history: GeneratedResponse[] | undefined;
|
|
14
|
+
generatedMessage: GeneratedResponse | undefined;
|
|
15
|
+
spans: FrameworkSpan[];
|
|
16
|
+
traceId: string;
|
|
17
|
+
version: string;
|
|
18
|
+
runErrorSpanKey: string;
|
|
19
|
+
startTime: TimeInput;
|
|
20
|
+
endTime: TimeInput;
|
|
21
|
+
source: string;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface BuildSpansForParentProps {
|
|
26
|
+
tracer: OITracer;
|
|
27
|
+
data: {
|
|
28
|
+
spans: FrameworkSpan[];
|
|
29
|
+
traceId: string;
|
|
30
|
+
parentId: string | undefined;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function buildSpansForParent({ tracer, data }: BuildSpansForParentProps) {
|
|
35
|
+
data.spans
|
|
36
|
+
.filter((beeaiSpan) => beeaiSpan.parent_id === data.parentId)
|
|
37
|
+
.forEach((beeaiSpan) => {
|
|
38
|
+
tracer.startActiveSpan(
|
|
39
|
+
beeaiSpan.context.span_id,
|
|
40
|
+
{
|
|
41
|
+
// custom start time
|
|
42
|
+
startTime: beeaiSpan.start_time,
|
|
43
|
+
// set span important attributes
|
|
44
|
+
attributes: {
|
|
45
|
+
target: beeaiSpan.attributes.target,
|
|
46
|
+
name: beeaiSpan.name,
|
|
47
|
+
traceId: data.traceId,
|
|
48
|
+
...(beeaiSpan.attributes.metadata && {
|
|
49
|
+
metadata: JSON.stringify(beeaiSpan.attributes.metadata),
|
|
50
|
+
}),
|
|
51
|
+
...(beeaiSpan.attributes.data && { ...beeaiSpan.attributes.data }),
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
(activeSpan) => {
|
|
55
|
+
// set status
|
|
56
|
+
activeSpan.setStatus(beeaiSpan.status);
|
|
57
|
+
|
|
58
|
+
// set nested spans
|
|
59
|
+
buildSpansForParent({
|
|
60
|
+
tracer,
|
|
61
|
+
data: {
|
|
62
|
+
spans: data.spans,
|
|
63
|
+
traceId: data.traceId,
|
|
64
|
+
parentId: beeaiSpan.context.span_id,
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// finish the span
|
|
69
|
+
activeSpan.end(beeaiSpan.end_time);
|
|
70
|
+
},
|
|
71
|
+
);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function buildTraceTree({ tracer, data }: BuiltTraceTreeProps) {
|
|
76
|
+
tracer.startActiveSpan(
|
|
77
|
+
`beeai-framework-main`,
|
|
78
|
+
{
|
|
79
|
+
// custom start time
|
|
80
|
+
startTime: data.startTime,
|
|
81
|
+
// set main span important attributes
|
|
82
|
+
attributes: {
|
|
83
|
+
source: data.source,
|
|
84
|
+
traceId: data.traceId,
|
|
85
|
+
[SemanticConventions.OPENINFERENCE_SPAN_KIND]:
|
|
86
|
+
OpenInferenceSpanKind.AGENT,
|
|
87
|
+
["beeai.version"]: data.version,
|
|
88
|
+
...(data.prompt && { [SemanticConventions.INPUT_VALUE]: data.prompt }),
|
|
89
|
+
...(data.generatedMessage !== undefined && {
|
|
90
|
+
[SemanticConventions.OUTPUT_VALUE]: JSON.stringify(
|
|
91
|
+
data.generatedMessage,
|
|
92
|
+
),
|
|
93
|
+
}),
|
|
94
|
+
...(data.history && { history: JSON.stringify(data.history) }),
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
(activeSpan) => {
|
|
98
|
+
// set status
|
|
99
|
+
const runErrorSpan = data.spans.find(
|
|
100
|
+
(span) => span.attributes.target === data.runErrorSpanKey,
|
|
101
|
+
);
|
|
102
|
+
if (runErrorSpan) {
|
|
103
|
+
activeSpan.setStatus(runErrorSpan.status);
|
|
104
|
+
} else {
|
|
105
|
+
activeSpan.setStatus({ code: SpanStatusCode.OK });
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// set nested spans
|
|
109
|
+
buildSpansForParent({
|
|
110
|
+
tracer,
|
|
111
|
+
data: { spans: data.spans, traceId: data.traceId, parentId: undefined },
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// finish the main span with custom end time
|
|
115
|
+
activeSpan.end(data.endTime);
|
|
116
|
+
},
|
|
117
|
+
);
|
|
118
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2025 IBM Corp.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { SpanStatusCode, TimeInput } from "@opentelemetry/api";
|
|
18
|
+
import { FrameworkSpan } from "../types";
|
|
19
|
+
import { isEmpty } from "remeda";
|
|
20
|
+
|
|
21
|
+
interface CreateSpanProps {
|
|
22
|
+
id: string;
|
|
23
|
+
name: string;
|
|
24
|
+
target: string;
|
|
25
|
+
startedAt: TimeInput;
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
27
|
+
ctx?: any;
|
|
28
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
29
|
+
data?: any;
|
|
30
|
+
error?: string;
|
|
31
|
+
parent?: { id: string };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function createSpan({
|
|
35
|
+
target,
|
|
36
|
+
name,
|
|
37
|
+
data,
|
|
38
|
+
error,
|
|
39
|
+
ctx,
|
|
40
|
+
parent,
|
|
41
|
+
id,
|
|
42
|
+
startedAt,
|
|
43
|
+
}: CreateSpanProps): FrameworkSpan {
|
|
44
|
+
return {
|
|
45
|
+
name: name,
|
|
46
|
+
attributes: {
|
|
47
|
+
target,
|
|
48
|
+
metadata: ctx && !isEmpty(ctx) ? { ...ctx } : undefined,
|
|
49
|
+
...(error && {
|
|
50
|
+
"exception.message": error,
|
|
51
|
+
"exception.type": "FrameworkError",
|
|
52
|
+
}),
|
|
53
|
+
data: data && !isEmpty(data) ? { ...data } : null,
|
|
54
|
+
},
|
|
55
|
+
context: {
|
|
56
|
+
span_id: id,
|
|
57
|
+
},
|
|
58
|
+
parent_id: parent?.id,
|
|
59
|
+
status: {
|
|
60
|
+
code: error ? SpanStatusCode.ERROR : SpanStatusCode.OK,
|
|
61
|
+
message: error ? error : "",
|
|
62
|
+
},
|
|
63
|
+
start_time: startedAt,
|
|
64
|
+
end_time: performance.now(),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2025 IBM Corp.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { FrameworkError } from "beeai-framework/errors";
|
|
18
|
+
import { getProp } from "beeai-framework/internals/helpers/object";
|
|
19
|
+
|
|
20
|
+
export function getErrorSafe(data: unknown): string | undefined {
|
|
21
|
+
const error = getProp(data, ["error"], data);
|
|
22
|
+
|
|
23
|
+
if (error instanceof FrameworkError) {
|
|
24
|
+
return FrameworkError.ensure(error).explain();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2025 IBM Corp.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { Serializable } from "beeai-framework/internals/serializable";
|
|
18
|
+
import { instrumentationLogger } from "beeai-framework/instrumentation/logger";
|
|
19
|
+
import { getProp } from "beeai-framework/internals/helpers/object";
|
|
20
|
+
import { EventMeta, InferCallbackValue } from "beeai-framework/emitter/types";
|
|
21
|
+
import { BeeCallbacks } from "beeai-framework/agents/bee/types";
|
|
22
|
+
import { ChatModel, ChatModelEvents } from "beeai-framework/backend/chat";
|
|
23
|
+
import { BaseAgent } from "beeai-framework/agents/base";
|
|
24
|
+
import { Message, MessageContentPart } from "beeai-framework/backend/message";
|
|
25
|
+
import {
|
|
26
|
+
errorEventName,
|
|
27
|
+
errorLLMEventName,
|
|
28
|
+
errorToolEventName,
|
|
29
|
+
finishLLMEventName,
|
|
30
|
+
finishToolEventName,
|
|
31
|
+
newTokenLLMEventName,
|
|
32
|
+
partialUpdateEventName,
|
|
33
|
+
retryEventName,
|
|
34
|
+
retryToolEventName,
|
|
35
|
+
startEventName,
|
|
36
|
+
startLLMEventName,
|
|
37
|
+
startToolEventName,
|
|
38
|
+
successEventName,
|
|
39
|
+
successLLMEventName,
|
|
40
|
+
successToolEventName,
|
|
41
|
+
toolErrorEventName,
|
|
42
|
+
toolStartEventName,
|
|
43
|
+
toolSuccessEventName,
|
|
44
|
+
updateEventName,
|
|
45
|
+
} from "../config";
|
|
46
|
+
import {
|
|
47
|
+
LLMAttributePostfixes,
|
|
48
|
+
MessageAttributePostfixes,
|
|
49
|
+
MimeType,
|
|
50
|
+
OpenInferenceSpanKind,
|
|
51
|
+
SemanticAttributePrefixes,
|
|
52
|
+
SemanticConventions,
|
|
53
|
+
} from "@arizeai/openinference-semantic-conventions";
|
|
54
|
+
import { Tool, ToolEvents } from "beeai-framework/tools/base";
|
|
55
|
+
|
|
56
|
+
function parserLLMInputMessages(
|
|
57
|
+
messages: readonly Message<MessageContentPart, string>[],
|
|
58
|
+
) {
|
|
59
|
+
return messages.reduce(
|
|
60
|
+
(acc, item, key) => ({
|
|
61
|
+
...acc,
|
|
62
|
+
[`${SemanticAttributePrefixes.llm}.${LLMAttributePostfixes.input_messages}.${key}.${SemanticAttributePrefixes.message}.${MessageAttributePostfixes.role}`]:
|
|
63
|
+
item.role,
|
|
64
|
+
[`${SemanticAttributePrefixes.llm}.${LLMAttributePostfixes.input_messages}.${key}.${SemanticAttributePrefixes.message}.${MessageAttributePostfixes.content}`]:
|
|
65
|
+
item.content
|
|
66
|
+
.filter((c) => c.type === "text")
|
|
67
|
+
.map((c) => c.text)
|
|
68
|
+
.join(""),
|
|
69
|
+
}),
|
|
70
|
+
{},
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function parseLLMOutputMessages(
|
|
75
|
+
messages: readonly Message<MessageContentPart, string>[],
|
|
76
|
+
) {
|
|
77
|
+
return messages.reduce(
|
|
78
|
+
(acc, item, key) => ({
|
|
79
|
+
...acc,
|
|
80
|
+
[`${SemanticAttributePrefixes.llm}.${LLMAttributePostfixes.output_messages}.${key}.${SemanticAttributePrefixes.message}.${MessageAttributePostfixes.role}`]:
|
|
81
|
+
item.role,
|
|
82
|
+
[`${SemanticAttributePrefixes.llm}.${LLMAttributePostfixes.output_messages}.${key}.${SemanticAttributePrefixes.message}.${MessageAttributePostfixes.content}`]:
|
|
83
|
+
item.content
|
|
84
|
+
.filter((c) => c.type === "text")
|
|
85
|
+
.map((c) => c.text)
|
|
86
|
+
.join(""),
|
|
87
|
+
}),
|
|
88
|
+
{},
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function getSerializedObjectSafe(
|
|
93
|
+
dataObject: unknown,
|
|
94
|
+
meta: EventMeta<unknown>,
|
|
95
|
+
) {
|
|
96
|
+
// agent events
|
|
97
|
+
if (
|
|
98
|
+
[startEventName, successEventName, errorEventName, retryEventName].includes(
|
|
99
|
+
meta.name as keyof BeeCallbacks,
|
|
100
|
+
) &&
|
|
101
|
+
meta.creator instanceof BaseAgent
|
|
102
|
+
) {
|
|
103
|
+
const { meta, tools, memory, error, data } =
|
|
104
|
+
dataObject as InferCallbackValue<
|
|
105
|
+
| BeeCallbacks["start"]
|
|
106
|
+
| BeeCallbacks["error"]
|
|
107
|
+
| BeeCallbacks["success"]
|
|
108
|
+
| BeeCallbacks["retry"]
|
|
109
|
+
>;
|
|
110
|
+
return {
|
|
111
|
+
[SemanticConventions.OPENINFERENCE_SPAN_KIND]:
|
|
112
|
+
OpenInferenceSpanKind.AGENT,
|
|
113
|
+
iteration: meta.iteration,
|
|
114
|
+
...(tools?.length > 0 && {
|
|
115
|
+
[SemanticConventions.LLM_TOOLS]: tools.map((tool) => ({
|
|
116
|
+
[SemanticConventions.TOOL_NAME]: tool.name,
|
|
117
|
+
[SemanticConventions.TOOL_DESCRIPTION]: tool.description,
|
|
118
|
+
"tool.options": tool.options,
|
|
119
|
+
})),
|
|
120
|
+
}),
|
|
121
|
+
...(memory.messages.length > 0 && {
|
|
122
|
+
[SemanticConventions.INPUT_MIME_TYPE]: MimeType.JSON,
|
|
123
|
+
[SemanticConventions.INPUT_VALUE]: JSON.stringify(memory.messages),
|
|
124
|
+
}),
|
|
125
|
+
...(error && {
|
|
126
|
+
"exception.message": error.message,
|
|
127
|
+
"exception.stacktrace": error.stack,
|
|
128
|
+
"exception.type": error.name,
|
|
129
|
+
}),
|
|
130
|
+
...(data && {
|
|
131
|
+
[SemanticConventions.OUTPUT_MIME_TYPE]: MimeType.JSON,
|
|
132
|
+
[SemanticConventions.OUTPUT_VALUE]: JSON.stringify(data),
|
|
133
|
+
}),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// update events
|
|
138
|
+
if (
|
|
139
|
+
[updateEventName, partialUpdateEventName].includes(
|
|
140
|
+
meta.name as keyof BeeCallbacks,
|
|
141
|
+
)
|
|
142
|
+
) {
|
|
143
|
+
const { data } = dataObject as InferCallbackValue<
|
|
144
|
+
BeeCallbacks["partialUpdate"] | BeeCallbacks["update"]
|
|
145
|
+
>;
|
|
146
|
+
|
|
147
|
+
const output = data.final_answer || data.tool_output;
|
|
148
|
+
return {
|
|
149
|
+
[SemanticConventions.OPENINFERENCE_SPAN_KIND]:
|
|
150
|
+
OpenInferenceSpanKind.AGENT,
|
|
151
|
+
thought: data.thought,
|
|
152
|
+
...(data.tool_name && {
|
|
153
|
+
[SemanticConventions.TOOL_NAME]: data.tool_name,
|
|
154
|
+
}),
|
|
155
|
+
...(data.tool_input && {
|
|
156
|
+
[SemanticConventions.TOOL_PARAMETERS]: JSON.stringify(data.tool_input),
|
|
157
|
+
}),
|
|
158
|
+
...(output && {
|
|
159
|
+
[SemanticConventions.OUTPUT_MIME_TYPE]: MimeType.JSON,
|
|
160
|
+
[SemanticConventions.OUTPUT_VALUE]: output,
|
|
161
|
+
}),
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// tool events (from agent)
|
|
166
|
+
if (
|
|
167
|
+
[toolErrorEventName, toolStartEventName, toolSuccessEventName].includes(
|
|
168
|
+
meta.name as keyof BeeCallbacks,
|
|
169
|
+
)
|
|
170
|
+
) {
|
|
171
|
+
const { data } = dataObject as InferCallbackValue<
|
|
172
|
+
| BeeCallbacks["toolError"]
|
|
173
|
+
| BeeCallbacks["toolStart"]
|
|
174
|
+
| BeeCallbacks["toolSuccess"]
|
|
175
|
+
>;
|
|
176
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
177
|
+
const output: any = data.result && data.result.createSnapshot();
|
|
178
|
+
|
|
179
|
+
return {
|
|
180
|
+
[SemanticConventions.OPENINFERENCE_SPAN_KIND]: OpenInferenceSpanKind.TOOL,
|
|
181
|
+
thought: data.iteration.thought,
|
|
182
|
+
...(data.input
|
|
183
|
+
? { [SemanticConventions.TOOL_PARAMETERS]: JSON.stringify(data.input) }
|
|
184
|
+
: {}),
|
|
185
|
+
...(data.tool.description && {
|
|
186
|
+
[SemanticConventions.TOOL_DESCRIPTION]: data.tool.description,
|
|
187
|
+
}),
|
|
188
|
+
...(data.tool.name && {
|
|
189
|
+
[SemanticConventions.TOOL_NAME]: data.tool.name,
|
|
190
|
+
}),
|
|
191
|
+
...(data.error && {
|
|
192
|
+
"exception.message": data.error.message,
|
|
193
|
+
"exception.stacktrace": data.error.stack,
|
|
194
|
+
"exception.type": data.error.name,
|
|
195
|
+
}),
|
|
196
|
+
...(output && {
|
|
197
|
+
[SemanticConventions.OUTPUT_VALUE]: JSON.stringify(output),
|
|
198
|
+
}),
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
// tool events native
|
|
202
|
+
if (
|
|
203
|
+
[
|
|
204
|
+
startToolEventName,
|
|
205
|
+
successToolEventName,
|
|
206
|
+
finishToolEventName,
|
|
207
|
+
errorToolEventName,
|
|
208
|
+
retryToolEventName,
|
|
209
|
+
].includes(meta.name as keyof ToolEvents) &&
|
|
210
|
+
meta.creator instanceof Tool
|
|
211
|
+
) {
|
|
212
|
+
if (!dataObject) {
|
|
213
|
+
return {
|
|
214
|
+
[SemanticConventions.OPENINFERENCE_SPAN_KIND]:
|
|
215
|
+
OpenInferenceSpanKind.TOOL,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
const { input, output, error } = dataObject as InferCallbackValue<
|
|
219
|
+
| ToolEvents["start"]
|
|
220
|
+
| ToolEvents["success"]
|
|
221
|
+
| ToolEvents["retry"]
|
|
222
|
+
| ToolEvents["error"]
|
|
223
|
+
>;
|
|
224
|
+
|
|
225
|
+
return {
|
|
226
|
+
[SemanticConventions.OPENINFERENCE_SPAN_KIND]: OpenInferenceSpanKind.TOOL,
|
|
227
|
+
...(input
|
|
228
|
+
? { [SemanticConventions.TOOL_PARAMETERS]: JSON.stringify(input) }
|
|
229
|
+
: {}),
|
|
230
|
+
...(output && {
|
|
231
|
+
[SemanticConventions.OUTPUT_VALUE]: JSON.stringify(output),
|
|
232
|
+
}),
|
|
233
|
+
...(error && {
|
|
234
|
+
"exception.message": error.message,
|
|
235
|
+
"exception.stacktrace": error.stack,
|
|
236
|
+
"exception.type": error.name,
|
|
237
|
+
}),
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// llm events
|
|
242
|
+
if (
|
|
243
|
+
[
|
|
244
|
+
successLLMEventName,
|
|
245
|
+
startLLMEventName,
|
|
246
|
+
errorLLMEventName,
|
|
247
|
+
newTokenLLMEventName,
|
|
248
|
+
].includes(meta.name as keyof ChatModelEvents) &&
|
|
249
|
+
meta.creator instanceof ChatModel
|
|
250
|
+
) {
|
|
251
|
+
const { value, input, error } = dataObject as InferCallbackValue<
|
|
252
|
+
| ChatModelEvents["success"]
|
|
253
|
+
| ChatModelEvents["start"]
|
|
254
|
+
| ChatModelEvents["error"]
|
|
255
|
+
| ChatModelEvents["newToken"]
|
|
256
|
+
>;
|
|
257
|
+
|
|
258
|
+
const creator = meta.creator.createSnapshot();
|
|
259
|
+
return {
|
|
260
|
+
[SemanticConventions.OPENINFERENCE_SPAN_KIND]: OpenInferenceSpanKind.LLM,
|
|
261
|
+
...(value?.usage?.completionTokens && {
|
|
262
|
+
[SemanticConventions.LLM_TOKEN_COUNT_COMPLETION]:
|
|
263
|
+
value?.usage?.completionTokens,
|
|
264
|
+
}),
|
|
265
|
+
...(value?.usage?.promptTokens && {
|
|
266
|
+
[SemanticConventions.LLM_TOKEN_COUNT_PROMPT]:
|
|
267
|
+
value?.usage?.promptTokens,
|
|
268
|
+
}),
|
|
269
|
+
...(value?.usage?.totalTokens && {
|
|
270
|
+
[SemanticConventions.LLM_TOKEN_COUNT_TOTAL]: value?.usage?.totalTokens,
|
|
271
|
+
}),
|
|
272
|
+
...(input?.messages.length > 0 && {
|
|
273
|
+
[SemanticConventions.INPUT_MIME_TYPE]: MimeType.JSON,
|
|
274
|
+
[SemanticConventions.INPUT_VALUE]: JSON.stringify(input.messages),
|
|
275
|
+
...parserLLMInputMessages(input.messages),
|
|
276
|
+
}),
|
|
277
|
+
...(value?.messages.length > 0 && {
|
|
278
|
+
[SemanticConventions.OUTPUT_MIME_TYPE]: MimeType.JSON,
|
|
279
|
+
[SemanticConventions.OUTPUT_VALUE]: JSON.stringify(value.messages),
|
|
280
|
+
...parseLLMOutputMessages(value.messages),
|
|
281
|
+
}),
|
|
282
|
+
...(error && {
|
|
283
|
+
"exception.message": error.message,
|
|
284
|
+
"exception.stacktrace": error.stack,
|
|
285
|
+
"exception.type": error.name,
|
|
286
|
+
}),
|
|
287
|
+
...("providerId" in creator && {
|
|
288
|
+
[SemanticConventions.LLM_PROVIDER]: creator.providerId,
|
|
289
|
+
[`${SemanticAttributePrefixes.metadata}.${LLMAttributePostfixes.provider}`]:
|
|
290
|
+
creator.providerId,
|
|
291
|
+
}),
|
|
292
|
+
...("modelId" in creator && {
|
|
293
|
+
[SemanticConventions.LLM_MODEL_NAME]: creator.modelId,
|
|
294
|
+
[`${SemanticAttributePrefixes.metadata}.${LLMAttributePostfixes.model_name}`]:
|
|
295
|
+
creator.modelId,
|
|
296
|
+
}),
|
|
297
|
+
...(creator.parameters && {
|
|
298
|
+
[SemanticConventions.LLM_INVOCATION_PARAMETERS]: JSON.stringify(
|
|
299
|
+
creator.parameters,
|
|
300
|
+
),
|
|
301
|
+
}),
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
if (meta.name === finishLLMEventName && meta.creator instanceof ChatModel) {
|
|
305
|
+
return {
|
|
306
|
+
[SemanticConventions.OPENINFERENCE_SPAN_KIND]: OpenInferenceSpanKind.LLM,
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// other events
|
|
311
|
+
const data = getProp(dataObject, ["data"], dataObject);
|
|
312
|
+
if (data instanceof Serializable) {
|
|
313
|
+
try {
|
|
314
|
+
return { data: JSON.stringify(data.createSnapshot()), test: "hallo" };
|
|
315
|
+
} catch (e) {
|
|
316
|
+
instrumentationLogger.warn(
|
|
317
|
+
e,
|
|
318
|
+
"Invalid createSnapshot method in the Serializable class",
|
|
319
|
+
);
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
return { data: JSON.stringify(data) };
|
|
325
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2025 IBM Corp.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
interface GetIdsProps {
|
|
18
|
+
path: string;
|
|
19
|
+
id: string;
|
|
20
|
+
runId: string;
|
|
21
|
+
parentRunId?: string;
|
|
22
|
+
groupId?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export class IdNameManager {
|
|
26
|
+
/** Current index for each event */
|
|
27
|
+
#idNamesCounter = new Map<string, number>();
|
|
28
|
+
/** The new span id names and the original framework emitter event ids dictionary */
|
|
29
|
+
#idNameMap = new Map<string, string>();
|
|
30
|
+
/** We need to map the run tree structure with duplicities to the event tree structure */
|
|
31
|
+
#runIdMap = new Map<string, string>();
|
|
32
|
+
|
|
33
|
+
#spanIdGenerator(name: string) {
|
|
34
|
+
const count = this.#idNamesCounter.get(name) || 0;
|
|
35
|
+
this.#idNamesCounter.set(name, count + 1);
|
|
36
|
+
return `${name}-${this.#idNamesCounter.get(name)}`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
getIds({ path, id, runId, parentRunId, groupId }: GetIdsProps) {
|
|
40
|
+
this.#runIdMap.set(runId, id);
|
|
41
|
+
const spanId = this.#spanIdGenerator(path);
|
|
42
|
+
|
|
43
|
+
this.#idNameMap.set(id, spanId);
|
|
44
|
+
const parentSpanId = parentRunId
|
|
45
|
+
? this.#idNameMap.get(this.#runIdMap.get(parentRunId) || "")
|
|
46
|
+
: groupId;
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
spanId,
|
|
50
|
+
parentSpanId,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|