langwatch 0.1.0 → 0.1.3
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/copy-types.sh +17 -0
- package/dist/chunk-2I4YLOQY.mjs +736 -0
- package/dist/chunk-2I4YLOQY.mjs.map +1 -0
- package/dist/index.d.mts +352 -4
- package/dist/index.d.ts +352 -4
- package/dist/index.js +6505 -413
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +571 -359
- package/dist/index.mjs.map +1 -1
- package/dist/{utils-DDcm0z9v.d.mts → utils-CFtM8VVg.d.mts} +108 -31
- package/dist/{utils-DDcm0z9v.d.ts → utils-CFtM8VVg.d.ts} +108 -31
- package/dist/utils.d.mts +1 -2
- package/dist/utils.d.ts +1 -2
- package/dist/utils.js +437 -0
- package/dist/utils.js.map +1 -1
- package/dist/utils.mjs +3 -1
- package/example/README.md +3 -1
- package/example/app/(chat)/chat/[id]/page.tsx +1 -1
- package/example/app/(chat)/page.tsx +10 -5
- package/example/app/guardrails/page.tsx +26 -0
- package/example/app/langchain/page.tsx +27 -0
- package/example/app/langchain-rag/page.tsx +28 -0
- package/example/app/share/[id]/page.tsx +1 -1
- package/example/components/chat-list.tsx +1 -1
- package/example/components/chat-panel.tsx +1 -1
- package/example/components/header.tsx +39 -13
- package/example/components/prompt-form.tsx +1 -1
- package/example/components/stocks/stock-purchase.tsx +1 -1
- package/example/components/stocks/stocks.tsx +1 -1
- package/example/lib/chat/guardrails.tsx +181 -0
- package/example/lib/chat/langchain-rag.tsx +191 -0
- package/example/lib/chat/langchain.tsx +112 -0
- package/example/lib/chat/{actions.tsx → vercel-ai.tsx} +1 -1
- package/example/package-lock.json +289 -6
- package/example/package.json +1 -0
- package/package.json +13 -5
- package/src/evaluations.ts +219 -0
- package/src/index.test.ts +5 -0
- package/src/index.ts +190 -7
- package/src/langchain.ts +557 -0
- package/src/{helpers.ts → typeUtils.ts} +20 -2
- package/src/types.ts +7 -3
- package/src/utils.ts +25 -2
- package/ts-to-zod.config.js +2 -0
- package/dist/chunk-AP23NJ57.mjs +0 -296
- package/dist/chunk-AP23NJ57.mjs.map +0 -1
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { type LangWatchSpan, type LangWatchTrace } from "./index";
|
|
2
|
+
import { type Conversation } from "./server/types/evaluations";
|
|
3
|
+
import {
|
|
4
|
+
type Evaluators,
|
|
5
|
+
type EvaluatorTypes,
|
|
6
|
+
} from "./server/types/evaluators.generated";
|
|
7
|
+
import {
|
|
8
|
+
type RAGChunk,
|
|
9
|
+
type SpanTypes,
|
|
10
|
+
type TypedValueEvaluationResult,
|
|
11
|
+
type TypedValueGuardrailResult,
|
|
12
|
+
type TypedValueJson,
|
|
13
|
+
} from "./server/types/tracer";
|
|
14
|
+
|
|
15
|
+
type Money = {
|
|
16
|
+
currency: string;
|
|
17
|
+
amount: number;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type EvaluationResultModel = {
|
|
21
|
+
status: "processed" | "skipped" | "error";
|
|
22
|
+
passed?: boolean;
|
|
23
|
+
score?: number;
|
|
24
|
+
details?: string;
|
|
25
|
+
label?: string;
|
|
26
|
+
cost?: Money;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type CommonEvaluationParams = {
|
|
30
|
+
name?: string;
|
|
31
|
+
input?: string;
|
|
32
|
+
output?: string;
|
|
33
|
+
expectedOutput?: string;
|
|
34
|
+
contexts?: RAGChunk[] | string[];
|
|
35
|
+
conversation?: Conversation;
|
|
36
|
+
asGuardrail?: boolean;
|
|
37
|
+
trace?: LangWatchTrace;
|
|
38
|
+
span?: LangWatchSpan;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export type SavedEvaluationParams = {
|
|
42
|
+
slug: string;
|
|
43
|
+
settings?: Record<string, unknown>;
|
|
44
|
+
} & CommonEvaluationParams;
|
|
45
|
+
|
|
46
|
+
export type LangEvalsEvaluationParams<T extends EvaluatorTypes> = {
|
|
47
|
+
evaluator: T;
|
|
48
|
+
settings?: Evaluators[T]["settings"];
|
|
49
|
+
} & CommonEvaluationParams;
|
|
50
|
+
|
|
51
|
+
export type EvaluationParams =
|
|
52
|
+
| SavedEvaluationParams
|
|
53
|
+
| LangEvalsEvaluationParams<EvaluatorTypes>;
|
|
54
|
+
|
|
55
|
+
export const evaluate = async (
|
|
56
|
+
params: EvaluationParams
|
|
57
|
+
): Promise<EvaluationResultModel> => {
|
|
58
|
+
const slug = "slug" in params ? params.slug : params.evaluator;
|
|
59
|
+
const span = optionalCreateSpan({
|
|
60
|
+
trace: params.trace,
|
|
61
|
+
span: params.span,
|
|
62
|
+
name: params.name ? params.name : slug,
|
|
63
|
+
type: params.asGuardrail ? "guardrail" : "evaluation",
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
const requestParams = prepareData({
|
|
68
|
+
...params,
|
|
69
|
+
slug,
|
|
70
|
+
traceId: span?.trace.traceId,
|
|
71
|
+
spanId: span?.spanId,
|
|
72
|
+
span,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const response = await fetch(requestParams.url, {
|
|
76
|
+
method: "POST",
|
|
77
|
+
headers: requestParams.headers,
|
|
78
|
+
body: JSON.stringify(requestParams.json),
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
if (!response.ok) {
|
|
82
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const result = await response.json();
|
|
86
|
+
return handleResponse(result, span, params.asGuardrail);
|
|
87
|
+
} catch (e) {
|
|
88
|
+
return handleException(e as Error, span, params.asGuardrail);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const optionalCreateSpan = ({
|
|
93
|
+
trace,
|
|
94
|
+
span,
|
|
95
|
+
name,
|
|
96
|
+
type,
|
|
97
|
+
}: {
|
|
98
|
+
trace?: LangWatchTrace;
|
|
99
|
+
span?: LangWatchSpan;
|
|
100
|
+
name: string;
|
|
101
|
+
type: SpanTypes;
|
|
102
|
+
}): LangWatchSpan | undefined => {
|
|
103
|
+
if (span) {
|
|
104
|
+
return span.startSpan({ name, type });
|
|
105
|
+
} else if (trace) {
|
|
106
|
+
return trace.startSpan({ name, type });
|
|
107
|
+
}
|
|
108
|
+
return undefined;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const prepareData = (params: {
|
|
112
|
+
slug: string;
|
|
113
|
+
name?: string;
|
|
114
|
+
input?: string;
|
|
115
|
+
output?: string;
|
|
116
|
+
expectedOutput?: string;
|
|
117
|
+
contexts?: RAGChunk[] | string[];
|
|
118
|
+
conversation?: Conversation;
|
|
119
|
+
settings?: Record<string, unknown>;
|
|
120
|
+
traceId?: string;
|
|
121
|
+
spanId?: string;
|
|
122
|
+
span?: LangWatchSpan;
|
|
123
|
+
asGuardrail?: boolean;
|
|
124
|
+
}) => {
|
|
125
|
+
const data: Record<string, unknown> = {};
|
|
126
|
+
if (params.input) data.input = params.input;
|
|
127
|
+
if (params.output) data.output = params.output;
|
|
128
|
+
if (params.expectedOutput) data.expected_output = params.expectedOutput;
|
|
129
|
+
if (params.contexts && params.contexts.length > 0)
|
|
130
|
+
data.contexts = params.contexts;
|
|
131
|
+
if (params.conversation && params.conversation.length > 0)
|
|
132
|
+
data.conversation = params.conversation;
|
|
133
|
+
|
|
134
|
+
if (params.span) {
|
|
135
|
+
params.span.update({
|
|
136
|
+
input: { type: "json", value: data } as TypedValueJson,
|
|
137
|
+
params: params.settings,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
url: `${process.env.LANGWATCH_ENDPOINT}/api/evaluations/${params.slug}/evaluate`,
|
|
143
|
+
json: {
|
|
144
|
+
trace_id: params.traceId,
|
|
145
|
+
span_id: params.spanId,
|
|
146
|
+
name: params.name,
|
|
147
|
+
data,
|
|
148
|
+
settings: params.settings,
|
|
149
|
+
as_guardrail: params.asGuardrail,
|
|
150
|
+
},
|
|
151
|
+
headers: {
|
|
152
|
+
"X-Auth-Token": process.env.LANGWATCH_API_KEY ?? "",
|
|
153
|
+
"Content-Type": "application/json",
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
const handleResponse = (
|
|
159
|
+
response: EvaluationResultModel,
|
|
160
|
+
span?: LangWatchSpan,
|
|
161
|
+
asGuardrail = false
|
|
162
|
+
): EvaluationResultModel => {
|
|
163
|
+
if (response.status === "error") {
|
|
164
|
+
response.details = response.details ?? "";
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
for (const key of Object.keys(response)) {
|
|
168
|
+
if (
|
|
169
|
+
response[key as keyof EvaluationResultModel] === null ||
|
|
170
|
+
response[key as keyof EvaluationResultModel] === undefined
|
|
171
|
+
) {
|
|
172
|
+
delete response[key as keyof EvaluationResultModel];
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (span) {
|
|
177
|
+
const output: TypedValueGuardrailResult | TypedValueEvaluationResult =
|
|
178
|
+
asGuardrail
|
|
179
|
+
? {
|
|
180
|
+
type: "guardrail_result",
|
|
181
|
+
value: response,
|
|
182
|
+
}
|
|
183
|
+
: {
|
|
184
|
+
type: "evaluation_result",
|
|
185
|
+
value: response,
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
span.update({ output });
|
|
189
|
+
|
|
190
|
+
if (response.cost) {
|
|
191
|
+
span.update({
|
|
192
|
+
metrics: {
|
|
193
|
+
cost: response.cost.amount,
|
|
194
|
+
},
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
span.end();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return response;
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
const handleException = (
|
|
205
|
+
e: Error,
|
|
206
|
+
span?: LangWatchSpan,
|
|
207
|
+
asGuardrail = false
|
|
208
|
+
): EvaluationResultModel => {
|
|
209
|
+
const response: EvaluationResultModel = {
|
|
210
|
+
status: "error",
|
|
211
|
+
details: e.toString(),
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
if (asGuardrail) {
|
|
215
|
+
response.passed = true;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return handleResponse(response, span, asGuardrail);
|
|
219
|
+
};
|
package/src/index.test.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import { openai } from "@ai-sdk/openai";
|
|
12
12
|
import { generateText, type CoreMessage } from "ai";
|
|
13
13
|
import "dotenv/config";
|
|
14
|
+
import { version } from "../package.json";
|
|
14
15
|
|
|
15
16
|
describe("LangWatch tracer", () => {
|
|
16
17
|
let mockFetch: SpyInstanceFn;
|
|
@@ -65,6 +66,8 @@ describe("LangWatch tracer", () => {
|
|
|
65
66
|
threadId: "123",
|
|
66
67
|
userId: "456",
|
|
67
68
|
labels: ["foo", "bar"],
|
|
69
|
+
sdkLanguage: "typescript",
|
|
70
|
+
sdkVersion: version,
|
|
68
71
|
});
|
|
69
72
|
expect(span.timestamps.startedAt).toBeDefined();
|
|
70
73
|
expect(span.timestamps.finishedAt).toBeDefined();
|
|
@@ -133,6 +136,8 @@ describe("LangWatch tracer", () => {
|
|
|
133
136
|
thread_id: "123",
|
|
134
137
|
user_id: "456",
|
|
135
138
|
labels: ["foo", "bar"],
|
|
139
|
+
sdk_language: "typescript",
|
|
140
|
+
sdk_version: version,
|
|
136
141
|
});
|
|
137
142
|
expect(requestBody.spans.length).toBe(3);
|
|
138
143
|
});
|
package/src/index.ts
CHANGED
|
@@ -2,11 +2,19 @@ import EventEmitter from "events";
|
|
|
2
2
|
import { nanoid } from "nanoid";
|
|
3
3
|
import { ZodError } from "zod";
|
|
4
4
|
import { fromZodError } from "zod-validation-error";
|
|
5
|
-
import {
|
|
5
|
+
import { version } from "../package.json";
|
|
6
|
+
import {
|
|
7
|
+
evaluate,
|
|
8
|
+
type EvaluationParams,
|
|
9
|
+
type EvaluationResultModel,
|
|
10
|
+
} from "./evaluations";
|
|
11
|
+
import { LangWatchCallbackHandler } from "./langchain";
|
|
6
12
|
import {
|
|
7
13
|
type CollectorRESTParams,
|
|
14
|
+
type EvaluationResult,
|
|
8
15
|
type Span as ServerSpan,
|
|
9
16
|
type SpanTypes,
|
|
17
|
+
type TypedValueEvaluationResult,
|
|
10
18
|
} from "./server/types/tracer";
|
|
11
19
|
import {
|
|
12
20
|
collectorRESTParamsSchema,
|
|
@@ -22,9 +30,15 @@ import {
|
|
|
22
30
|
type PendingLLMSpan,
|
|
23
31
|
type PendingRAGSpan,
|
|
24
32
|
type RAGSpan,
|
|
33
|
+
type RESTEvaluation,
|
|
25
34
|
type SpanInputOutput,
|
|
26
35
|
} from "./types";
|
|
27
|
-
import {
|
|
36
|
+
import { camelToSnakeCaseNested, type Strict } from "./typeUtils";
|
|
37
|
+
import {
|
|
38
|
+
autoconvertTypedValues,
|
|
39
|
+
captureError,
|
|
40
|
+
convertFromVercelAIMessages,
|
|
41
|
+
} from "./utils";
|
|
28
42
|
|
|
29
43
|
export type {
|
|
30
44
|
BaseSpan,
|
|
@@ -39,7 +53,7 @@ export type {
|
|
|
39
53
|
SpanInputOutput,
|
|
40
54
|
};
|
|
41
55
|
|
|
42
|
-
export {
|
|
56
|
+
export { autoconvertTypedValues, captureError, convertFromVercelAIMessages };
|
|
43
57
|
|
|
44
58
|
export class LangWatch extends EventEmitter {
|
|
45
59
|
apiKey: string | undefined;
|
|
@@ -132,12 +146,35 @@ export class LangWatch extends EventEmitter {
|
|
|
132
146
|
}
|
|
133
147
|
}
|
|
134
148
|
|
|
149
|
+
type CurrentSpan = {
|
|
150
|
+
current: LangWatchSpan;
|
|
151
|
+
previous?: CurrentSpan;
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
type AddEvaluationParams = {
|
|
155
|
+
evaluationId?: string;
|
|
156
|
+
span?: LangWatchSpan;
|
|
157
|
+
name: string;
|
|
158
|
+
type?: string;
|
|
159
|
+
isGuardrail?: boolean;
|
|
160
|
+
status?: "processed" | "skipped" | "error";
|
|
161
|
+
passed?: boolean;
|
|
162
|
+
score?: number;
|
|
163
|
+
label?: string;
|
|
164
|
+
details?: string;
|
|
165
|
+
error?: Error;
|
|
166
|
+
timestamps?: RESTEvaluation["timestamps"];
|
|
167
|
+
};
|
|
168
|
+
|
|
135
169
|
export class LangWatchTrace {
|
|
136
170
|
client: LangWatch;
|
|
137
171
|
traceId: string;
|
|
138
172
|
metadata?: Metadata;
|
|
139
173
|
finishedSpans: Record<string, ServerSpan> = {};
|
|
140
|
-
|
|
174
|
+
langchainCallback?: LangWatchCallbackHandler;
|
|
175
|
+
evaluations: RESTEvaluation[] = [];
|
|
176
|
+
private currentSpan?: CurrentSpan;
|
|
177
|
+
private timeoutRef?: NodeJS.Timeout;
|
|
141
178
|
|
|
142
179
|
constructor({
|
|
143
180
|
client,
|
|
@@ -150,7 +187,11 @@ export class LangWatchTrace {
|
|
|
150
187
|
}) {
|
|
151
188
|
this.client = client;
|
|
152
189
|
this.traceId = traceId;
|
|
153
|
-
this.metadata =
|
|
190
|
+
this.metadata = {
|
|
191
|
+
...metadata,
|
|
192
|
+
sdkVersion: version,
|
|
193
|
+
sdkLanguage: "typescript",
|
|
194
|
+
};
|
|
154
195
|
}
|
|
155
196
|
|
|
156
197
|
update({ metadata }: { metadata: Metadata }) {
|
|
@@ -158,16 +199,37 @@ export class LangWatchTrace {
|
|
|
158
199
|
...this.metadata,
|
|
159
200
|
...metadata,
|
|
160
201
|
...(typeof metadata.labels !== "undefined"
|
|
161
|
-
? {
|
|
202
|
+
? {
|
|
203
|
+
labels: [
|
|
204
|
+
...(this.metadata?.labels ?? []),
|
|
205
|
+
...(metadata.labels ?? []),
|
|
206
|
+
],
|
|
207
|
+
}
|
|
162
208
|
: {}),
|
|
163
209
|
};
|
|
164
210
|
}
|
|
165
211
|
|
|
212
|
+
setCurrentSpan(span: LangWatchSpan) {
|
|
213
|
+
this.currentSpan = {
|
|
214
|
+
current: span,
|
|
215
|
+
previous: this.currentSpan,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
getCurrentSpan() {
|
|
220
|
+
return this.currentSpan?.current;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
resetCurrentSpan() {
|
|
224
|
+
this.currentSpan = this.currentSpan?.previous;
|
|
225
|
+
}
|
|
226
|
+
|
|
166
227
|
startSpan(params: Omit<Partial<PendingBaseSpan>, "parentId">) {
|
|
167
228
|
const span = new LangWatchSpan({
|
|
168
229
|
trace: this,
|
|
169
230
|
...params,
|
|
170
231
|
});
|
|
232
|
+
this.setCurrentSpan(span);
|
|
171
233
|
return span;
|
|
172
234
|
}
|
|
173
235
|
|
|
@@ -176,6 +238,7 @@ export class LangWatchTrace {
|
|
|
176
238
|
trace: this,
|
|
177
239
|
...params,
|
|
178
240
|
});
|
|
241
|
+
this.setCurrentSpan(span);
|
|
179
242
|
return span;
|
|
180
243
|
}
|
|
181
244
|
|
|
@@ -184,11 +247,113 @@ export class LangWatchTrace {
|
|
|
184
247
|
trace: this,
|
|
185
248
|
...params,
|
|
186
249
|
});
|
|
250
|
+
this.setCurrentSpan(span);
|
|
187
251
|
return span;
|
|
188
252
|
}
|
|
189
253
|
|
|
254
|
+
addEvaluation = ({
|
|
255
|
+
evaluationId,
|
|
256
|
+
span,
|
|
257
|
+
name,
|
|
258
|
+
type,
|
|
259
|
+
isGuardrail,
|
|
260
|
+
status = "processed",
|
|
261
|
+
passed,
|
|
262
|
+
score,
|
|
263
|
+
label,
|
|
264
|
+
details,
|
|
265
|
+
error,
|
|
266
|
+
timestamps,
|
|
267
|
+
}: AddEvaluationParams): void => {
|
|
268
|
+
const currentEvaluationIndex = this.evaluations.findIndex(
|
|
269
|
+
(e) =>
|
|
270
|
+
evaluationId && "evaluationId" in e && e.evaluationId === evaluationId
|
|
271
|
+
);
|
|
272
|
+
|
|
273
|
+
const currentEvaluation =
|
|
274
|
+
currentEvaluationIndex !== -1
|
|
275
|
+
? this.evaluations[currentEvaluationIndex]
|
|
276
|
+
: undefined;
|
|
277
|
+
|
|
278
|
+
const evaluationResult: EvaluationResult = {
|
|
279
|
+
status,
|
|
280
|
+
...(passed !== undefined && { passed }),
|
|
281
|
+
...(score !== undefined && { score }),
|
|
282
|
+
...(label !== undefined && { label }),
|
|
283
|
+
...(details !== undefined && { details }),
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
let span_ = span;
|
|
287
|
+
if (!span_) {
|
|
288
|
+
span_ = this.startSpan({
|
|
289
|
+
type: "evaluation",
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
if (span_.type !== "evaluation") {
|
|
293
|
+
span_ = span_.startSpan({ type: "evaluation" });
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
span_.update({
|
|
297
|
+
name,
|
|
298
|
+
output: {
|
|
299
|
+
type: "evaluation_result",
|
|
300
|
+
value: evaluationResult,
|
|
301
|
+
} as TypedValueEvaluationResult,
|
|
302
|
+
error,
|
|
303
|
+
timestamps: timestamps
|
|
304
|
+
? {
|
|
305
|
+
startedAt: timestamps.startedAt ?? span_.timestamps.startedAt,
|
|
306
|
+
finishedAt: timestamps.finishedAt ?? undefined,
|
|
307
|
+
}
|
|
308
|
+
: undefined,
|
|
309
|
+
});
|
|
310
|
+
span_.end();
|
|
311
|
+
|
|
312
|
+
const evaluation: RESTEvaluation = {
|
|
313
|
+
evaluationId: evaluationId ?? `eval_${nanoid()}`,
|
|
314
|
+
spanId: span_.spanId,
|
|
315
|
+
name,
|
|
316
|
+
type,
|
|
317
|
+
isGuardrail,
|
|
318
|
+
status,
|
|
319
|
+
passed,
|
|
320
|
+
score,
|
|
321
|
+
label,
|
|
322
|
+
details,
|
|
323
|
+
error: error ? captureError(error) : undefined,
|
|
324
|
+
timestamps: timestamps ?? {
|
|
325
|
+
startedAt: span_.timestamps.startedAt,
|
|
326
|
+
finishedAt: span_.timestamps.finishedAt,
|
|
327
|
+
},
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
if (currentEvaluation && currentEvaluationIndex !== -1) {
|
|
331
|
+
this.evaluations[currentEvaluationIndex] = {
|
|
332
|
+
...currentEvaluation,
|
|
333
|
+
...evaluation,
|
|
334
|
+
};
|
|
335
|
+
} else {
|
|
336
|
+
this.evaluations.push(evaluation);
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
async evaluate(params: EvaluationParams): Promise<EvaluationResultModel> {
|
|
341
|
+
return evaluate({
|
|
342
|
+
trace: this,
|
|
343
|
+
...params,
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
getLangChainCallback() {
|
|
348
|
+
if (!this.langchainCallback) {
|
|
349
|
+
this.langchainCallback = new LangWatchCallbackHandler({ trace: this });
|
|
350
|
+
}
|
|
351
|
+
return this.langchainCallback;
|
|
352
|
+
}
|
|
353
|
+
|
|
190
354
|
onEnd(span: ServerSpan) {
|
|
191
355
|
this.finishedSpans[span.span_id] = span;
|
|
356
|
+
this.resetCurrentSpan();
|
|
192
357
|
this.delayedSendSpans();
|
|
193
358
|
}
|
|
194
359
|
|
|
@@ -206,8 +371,9 @@ export class LangWatchTrace {
|
|
|
206
371
|
try {
|
|
207
372
|
trace = collectorRESTParamsSchema.parse({
|
|
208
373
|
trace_id: this.traceId,
|
|
209
|
-
metadata: camelToSnakeCaseNested(this.metadata),
|
|
374
|
+
metadata: camelToSnakeCaseNested(this.metadata, "metadata"),
|
|
210
375
|
spans: Object.values(this.finishedSpans),
|
|
376
|
+
evaluations: camelToSnakeCaseNested(this.evaluations),
|
|
211
377
|
} as Strict<CollectorRESTParams>);
|
|
212
378
|
} catch (error) {
|
|
213
379
|
if (error instanceof ZodError) {
|
|
@@ -300,6 +466,7 @@ export class LangWatchSpan implements PendingBaseSpan {
|
|
|
300
466
|
parentId: this.spanId,
|
|
301
467
|
...params,
|
|
302
468
|
});
|
|
469
|
+
this.trace.setCurrentSpan(span);
|
|
303
470
|
return span;
|
|
304
471
|
}
|
|
305
472
|
|
|
@@ -309,6 +476,7 @@ export class LangWatchSpan implements PendingBaseSpan {
|
|
|
309
476
|
parentId: this.spanId,
|
|
310
477
|
...params,
|
|
311
478
|
});
|
|
479
|
+
this.trace.setCurrentSpan(span);
|
|
312
480
|
return span;
|
|
313
481
|
}
|
|
314
482
|
|
|
@@ -318,9 +486,24 @@ export class LangWatchSpan implements PendingBaseSpan {
|
|
|
318
486
|
parentId: this.spanId,
|
|
319
487
|
...params,
|
|
320
488
|
});
|
|
489
|
+
this.trace.setCurrentSpan(span);
|
|
321
490
|
return span;
|
|
322
491
|
}
|
|
323
492
|
|
|
493
|
+
addEvaluation(params: AddEvaluationParams) {
|
|
494
|
+
this.trace.addEvaluation({
|
|
495
|
+
...params,
|
|
496
|
+
span: this,
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
async evaluate(params: EvaluationParams): Promise<EvaluationResultModel> {
|
|
501
|
+
return evaluate({
|
|
502
|
+
span: this,
|
|
503
|
+
...params,
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
|
|
324
507
|
end(params?: Partial<Omit<PendingBaseSpan, "spanId" | "parentId">>) {
|
|
325
508
|
this.timestamps.finishedAt = Date.now();
|
|
326
509
|
if (params) {
|