@lmnr-ai/lmnr 0.3.0 → 0.3.2
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/.eslintrc.json +2 -0
- package/README.md +79 -5
- package/dist/index.d.mts +136 -0
- package/dist/index.d.ts +136 -0
- package/dist/index.js +319 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +288 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +6 -4
- package/src/constants.ts +1 -0
- package/src/context.ts +0 -0
- package/src/index.ts +12 -1
- package/src/interface.ts +248 -0
- package/src/tracing.ts +84 -0
- package/src/types.ts +47 -2
- package/src/utils.ts +13 -0
package/.eslintrc.json
ADDED
package/README.md
CHANGED
|
@@ -8,11 +8,85 @@ npm install @lmnr-ai/lmnr
|
|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
11
|
+
- Instrumentation of your JS/TS code
|
|
12
|
+
- Events and semantic events right from the code
|
|
13
|
+
- Make Laminar pipeline calls from your JS code
|
|
14
14
|
|
|
15
|
-
##
|
|
15
|
+
## Prerequisite
|
|
16
|
+
|
|
17
|
+
- Laminar project created at https://lmnr.ai
|
|
18
|
+
- Export (or set using .env) a variable `LMNR_PROJECT_API_KEY` with the value from the project settings page
|
|
19
|
+
|
|
20
|
+
## Code instrumentation
|
|
21
|
+
|
|
22
|
+
For manual instrumetation you will need to import the following:
|
|
23
|
+
- `trace` - this is a function to start a trace. It returns a `TraceContext`
|
|
24
|
+
- `TraceContext` - a pointer to the current trace that you can pass around functions as you want.
|
|
25
|
+
- `SpanContext` - a pointer to the current span that you can pass around functions as you want
|
|
26
|
+
- `ObservationContext` – parent class of `TraceContext` and `SpanContext`. Useful, if you don't want to import the separate context types in TS.
|
|
27
|
+
|
|
28
|
+
Both `TraceContext` and `SpanContext` expose the following interfaces:
|
|
29
|
+
- `span(name: string, props: CreateSpanProps)` - create a child span within the current context. Returns `SpanContext`
|
|
30
|
+
- `update(props)` - update the current trace or span and return it. Returns `TraceContext` or `SpanContext`. Useful when some metadata becomes known later during the program execution
|
|
31
|
+
|
|
32
|
+
In addition, `SpanContext` allows you to:
|
|
33
|
+
- `event(templateName: string, props: SpanEventProps)` - emit a custom event at any point
|
|
34
|
+
- `evaluateEvent(templateName: string, data: str, props: SpanEvaluateEventProps)` - register a possible event for automatic checking by Laminar.
|
|
35
|
+
- `end(props: UpdateSpanProps)` – update the current span, and terminate it
|
|
36
|
+
|
|
37
|
+
### Example
|
|
38
|
+
|
|
39
|
+
```javascript
|
|
40
|
+
// `trace()` is the main entrypoint into the observation of your app
|
|
41
|
+
// `ObservationContext` is a parent class for `SpanContext` and `TraceContext`
|
|
42
|
+
import { trace, ObservationContext } from '@lmnr-ai/lmnr';
|
|
43
|
+
|
|
44
|
+
import OpenAI from 'openai';
|
|
45
|
+
|
|
46
|
+
const openai = new OpenAI({apiKey: process.env.OPENAI_API_KEY});
|
|
47
|
+
|
|
48
|
+
const getRandomCountry = (s: ObservationContext): string => {
|
|
49
|
+
// create the span without registering the input
|
|
50
|
+
const span = s.span('getRandomCountry');
|
|
51
|
+
const countries = ['United States', 'Canada', 'Australia', 'Germany', 'Japan'];
|
|
52
|
+
const country = countries[Math.floor(Math.random() * countries.length)];
|
|
53
|
+
|
|
54
|
+
// end the span and register the output
|
|
55
|
+
span.end({output: country});
|
|
56
|
+
|
|
57
|
+
return country;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const foo = (question: string, t: ObservationContext) => {
|
|
61
|
+
// create the span and register the input
|
|
62
|
+
const span = t.span('foo', {input: {question}});
|
|
63
|
+
|
|
64
|
+
// pass the span context down the function call if you want to trace it
|
|
65
|
+
const country = getRandomCountry(span);
|
|
66
|
+
question += country;
|
|
67
|
+
const result = openai.chat.completions.create({
|
|
68
|
+
model: 'gpt-4o-mini',
|
|
69
|
+
messages: [{role: 'system', content: 'You are a helpful assistant.'}, {role: 'user', content: question}],
|
|
70
|
+
}).then((response) => {
|
|
71
|
+
const output = response.choices[0].message.content;
|
|
72
|
+
|
|
73
|
+
// ask Laminar to check for a pre-defined event.
|
|
74
|
+
// In this example correctness is pre-defined in the UI as "The data is factually correct"
|
|
75
|
+
span.evalueateEvent('correctness', output ?? '');
|
|
76
|
+
// end the span and register the output
|
|
77
|
+
span.end({output});
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// Start the trace observation at the entry to your program
|
|
82
|
+
const t = trace();
|
|
83
|
+
|
|
84
|
+
// pass the trace context into the handler
|
|
85
|
+
foo("What is the capital of ", t);
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Making Laminar pipeline calls
|
|
16
90
|
|
|
17
91
|
After you are ready to use your pipeline in your code, deploy it in Laminar by selecting the target version for the pipeline.
|
|
18
92
|
|
|
@@ -21,7 +95,7 @@ Once your pipeline target is set, you can call it from JS in just a few lines.
|
|
|
21
95
|
Example use:
|
|
22
96
|
|
|
23
97
|
```typescript
|
|
24
|
-
import { Laminar
|
|
98
|
+
import { Laminar } from '@lmnr-ai/lmnr';
|
|
25
99
|
|
|
26
100
|
const l = new Laminar('<YOUR_PROJECT_API_KEY>');
|
|
27
101
|
const result = await l.run({
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
type ChatMessage = {
|
|
2
|
+
role: 'user' | 'assistant' | 'system';
|
|
3
|
+
content: string;
|
|
4
|
+
};
|
|
5
|
+
type NodeInput = ChatMessage[] | string;
|
|
6
|
+
type PipelineRunRequest = {
|
|
7
|
+
inputs: Record<string, NodeInput>;
|
|
8
|
+
pipeline: string;
|
|
9
|
+
env?: Record<string, string>;
|
|
10
|
+
metadata?: Record<string, string>;
|
|
11
|
+
};
|
|
12
|
+
type PipelineRunResponse = {
|
|
13
|
+
outputs: Record<string, Record<string, NodeInput>>;
|
|
14
|
+
runId: string;
|
|
15
|
+
};
|
|
16
|
+
type EvaluateEvent = {
|
|
17
|
+
name: string;
|
|
18
|
+
data: string;
|
|
19
|
+
timestamp?: Date;
|
|
20
|
+
};
|
|
21
|
+
type Event = {
|
|
22
|
+
id: string;
|
|
23
|
+
templateName: string;
|
|
24
|
+
timestamp: Date;
|
|
25
|
+
spanId: string;
|
|
26
|
+
value: number | string | null;
|
|
27
|
+
};
|
|
28
|
+
type SpanType = 'DEFAULT' | 'LLM';
|
|
29
|
+
type Span = {
|
|
30
|
+
version: string;
|
|
31
|
+
spanType: SpanType;
|
|
32
|
+
id: string;
|
|
33
|
+
parentSpanId: string | null;
|
|
34
|
+
traceId: string;
|
|
35
|
+
name: string;
|
|
36
|
+
startTime: Date;
|
|
37
|
+
endTime: Date | null;
|
|
38
|
+
attributes: Record<string, any>;
|
|
39
|
+
input: any | null;
|
|
40
|
+
output: any | null;
|
|
41
|
+
metadata: Record<string, any> | null;
|
|
42
|
+
evaluateEvents: EvaluateEvent[];
|
|
43
|
+
events: Event[];
|
|
44
|
+
};
|
|
45
|
+
type Trace = {
|
|
46
|
+
id: string;
|
|
47
|
+
version: string;
|
|
48
|
+
success: boolean;
|
|
49
|
+
startTime: Date | null;
|
|
50
|
+
endTime: Date | null;
|
|
51
|
+
userId: string | null;
|
|
52
|
+
sessionId: string | null;
|
|
53
|
+
release: string;
|
|
54
|
+
metadata: Record<string, any> | null;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
declare class Collector {
|
|
58
|
+
private readonly flushInterval;
|
|
59
|
+
private readonly client;
|
|
60
|
+
private readonly maxQueueSize;
|
|
61
|
+
private queue;
|
|
62
|
+
private flushTimeout;
|
|
63
|
+
constructor();
|
|
64
|
+
addTask(task: Span | Trace): void;
|
|
65
|
+
private flush;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
interface CreateSpanProps {
|
|
69
|
+
input?: any | null;
|
|
70
|
+
metadata?: Record<string, any> | null;
|
|
71
|
+
attributes?: Record<string, any>;
|
|
72
|
+
spanType?: SpanType;
|
|
73
|
+
}
|
|
74
|
+
declare class ObservationContext {
|
|
75
|
+
protected observation: Span | Trace;
|
|
76
|
+
parent: ObservationContext | null;
|
|
77
|
+
children: Record<string, SpanContext>;
|
|
78
|
+
protected collector: Collector;
|
|
79
|
+
constructor(observation: Span | Trace, parent: ObservationContext | null);
|
|
80
|
+
id(): string;
|
|
81
|
+
span(name: string, { input, metadata, attributes, spanType, }?: CreateSpanProps): SpanContext;
|
|
82
|
+
}
|
|
83
|
+
interface UpdateSpanProps {
|
|
84
|
+
input?: any | null;
|
|
85
|
+
output?: any | null;
|
|
86
|
+
metadata?: Record<string, any> | null;
|
|
87
|
+
attributes?: Record<string, any>;
|
|
88
|
+
evaluateEvents?: EvaluateEvent[];
|
|
89
|
+
override?: boolean;
|
|
90
|
+
}
|
|
91
|
+
interface SpanEventProps {
|
|
92
|
+
value?: string | number | boolean;
|
|
93
|
+
timestamp?: Date;
|
|
94
|
+
}
|
|
95
|
+
interface SpanEvaluateEventProps {
|
|
96
|
+
timestamp?: Date;
|
|
97
|
+
}
|
|
98
|
+
declare class SpanContext extends ObservationContext {
|
|
99
|
+
private inerSpan;
|
|
100
|
+
constructor(span: Span, parent: ObservationContext);
|
|
101
|
+
end({ input, output, metadata, attributes, evaluateEvents, override }?: UpdateSpanProps): SpanContext;
|
|
102
|
+
update({ input, output, metadata, attributes, evaluateEvents, override }: UpdateSpanProps): SpanContext;
|
|
103
|
+
event(templateName: string, { value, timestamp, }?: SpanEventProps): SpanContext;
|
|
104
|
+
evalueateEvent(templateName: string, data: string, { timestamp }?: SpanEvaluateEventProps): SpanContext;
|
|
105
|
+
private getParent;
|
|
106
|
+
private innerUpdate;
|
|
107
|
+
}
|
|
108
|
+
interface UpdateTraceProps {
|
|
109
|
+
success?: boolean;
|
|
110
|
+
userId?: string | null;
|
|
111
|
+
sessionId?: string | null;
|
|
112
|
+
release?: string;
|
|
113
|
+
metadata?: Record<string, any> | null;
|
|
114
|
+
}
|
|
115
|
+
declare class TraceContext extends ObservationContext {
|
|
116
|
+
private trace;
|
|
117
|
+
constructor(trace: Trace, parent: ObservationContext | null);
|
|
118
|
+
update({ success, userId, sessionId, release, metadata }?: UpdateTraceProps): TraceContext;
|
|
119
|
+
}
|
|
120
|
+
interface TraceProps {
|
|
121
|
+
userId?: string | null;
|
|
122
|
+
sessionId?: string | null;
|
|
123
|
+
release?: string;
|
|
124
|
+
metadata?: Record<string, any> | null;
|
|
125
|
+
}
|
|
126
|
+
declare const trace: ({ userId, sessionId, release, metadata, }?: TraceProps) => TraceContext;
|
|
127
|
+
|
|
128
|
+
declare class Laminar {
|
|
129
|
+
private readonly projectApiKey;
|
|
130
|
+
private readonly url;
|
|
131
|
+
private readonly response;
|
|
132
|
+
constructor(projectApiKey: string);
|
|
133
|
+
run({ pipeline, inputs, env, metadata, }: PipelineRunRequest): Promise<PipelineRunResponse>;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export { type ChatMessage, type EvaluateEvent, type Event, Laminar, type NodeInput, ObservationContext, type PipelineRunRequest, type PipelineRunResponse, type Span, SpanContext, type Trace, TraceContext, trace };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
type ChatMessage = {
|
|
2
|
+
role: 'user' | 'assistant' | 'system';
|
|
3
|
+
content: string;
|
|
4
|
+
};
|
|
5
|
+
type NodeInput = ChatMessage[] | string;
|
|
6
|
+
type PipelineRunRequest = {
|
|
7
|
+
inputs: Record<string, NodeInput>;
|
|
8
|
+
pipeline: string;
|
|
9
|
+
env?: Record<string, string>;
|
|
10
|
+
metadata?: Record<string, string>;
|
|
11
|
+
};
|
|
12
|
+
type PipelineRunResponse = {
|
|
13
|
+
outputs: Record<string, Record<string, NodeInput>>;
|
|
14
|
+
runId: string;
|
|
15
|
+
};
|
|
16
|
+
type EvaluateEvent = {
|
|
17
|
+
name: string;
|
|
18
|
+
data: string;
|
|
19
|
+
timestamp?: Date;
|
|
20
|
+
};
|
|
21
|
+
type Event = {
|
|
22
|
+
id: string;
|
|
23
|
+
templateName: string;
|
|
24
|
+
timestamp: Date;
|
|
25
|
+
spanId: string;
|
|
26
|
+
value: number | string | null;
|
|
27
|
+
};
|
|
28
|
+
type SpanType = 'DEFAULT' | 'LLM';
|
|
29
|
+
type Span = {
|
|
30
|
+
version: string;
|
|
31
|
+
spanType: SpanType;
|
|
32
|
+
id: string;
|
|
33
|
+
parentSpanId: string | null;
|
|
34
|
+
traceId: string;
|
|
35
|
+
name: string;
|
|
36
|
+
startTime: Date;
|
|
37
|
+
endTime: Date | null;
|
|
38
|
+
attributes: Record<string, any>;
|
|
39
|
+
input: any | null;
|
|
40
|
+
output: any | null;
|
|
41
|
+
metadata: Record<string, any> | null;
|
|
42
|
+
evaluateEvents: EvaluateEvent[];
|
|
43
|
+
events: Event[];
|
|
44
|
+
};
|
|
45
|
+
type Trace = {
|
|
46
|
+
id: string;
|
|
47
|
+
version: string;
|
|
48
|
+
success: boolean;
|
|
49
|
+
startTime: Date | null;
|
|
50
|
+
endTime: Date | null;
|
|
51
|
+
userId: string | null;
|
|
52
|
+
sessionId: string | null;
|
|
53
|
+
release: string;
|
|
54
|
+
metadata: Record<string, any> | null;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
declare class Collector {
|
|
58
|
+
private readonly flushInterval;
|
|
59
|
+
private readonly client;
|
|
60
|
+
private readonly maxQueueSize;
|
|
61
|
+
private queue;
|
|
62
|
+
private flushTimeout;
|
|
63
|
+
constructor();
|
|
64
|
+
addTask(task: Span | Trace): void;
|
|
65
|
+
private flush;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
interface CreateSpanProps {
|
|
69
|
+
input?: any | null;
|
|
70
|
+
metadata?: Record<string, any> | null;
|
|
71
|
+
attributes?: Record<string, any>;
|
|
72
|
+
spanType?: SpanType;
|
|
73
|
+
}
|
|
74
|
+
declare class ObservationContext {
|
|
75
|
+
protected observation: Span | Trace;
|
|
76
|
+
parent: ObservationContext | null;
|
|
77
|
+
children: Record<string, SpanContext>;
|
|
78
|
+
protected collector: Collector;
|
|
79
|
+
constructor(observation: Span | Trace, parent: ObservationContext | null);
|
|
80
|
+
id(): string;
|
|
81
|
+
span(name: string, { input, metadata, attributes, spanType, }?: CreateSpanProps): SpanContext;
|
|
82
|
+
}
|
|
83
|
+
interface UpdateSpanProps {
|
|
84
|
+
input?: any | null;
|
|
85
|
+
output?: any | null;
|
|
86
|
+
metadata?: Record<string, any> | null;
|
|
87
|
+
attributes?: Record<string, any>;
|
|
88
|
+
evaluateEvents?: EvaluateEvent[];
|
|
89
|
+
override?: boolean;
|
|
90
|
+
}
|
|
91
|
+
interface SpanEventProps {
|
|
92
|
+
value?: string | number | boolean;
|
|
93
|
+
timestamp?: Date;
|
|
94
|
+
}
|
|
95
|
+
interface SpanEvaluateEventProps {
|
|
96
|
+
timestamp?: Date;
|
|
97
|
+
}
|
|
98
|
+
declare class SpanContext extends ObservationContext {
|
|
99
|
+
private inerSpan;
|
|
100
|
+
constructor(span: Span, parent: ObservationContext);
|
|
101
|
+
end({ input, output, metadata, attributes, evaluateEvents, override }?: UpdateSpanProps): SpanContext;
|
|
102
|
+
update({ input, output, metadata, attributes, evaluateEvents, override }: UpdateSpanProps): SpanContext;
|
|
103
|
+
event(templateName: string, { value, timestamp, }?: SpanEventProps): SpanContext;
|
|
104
|
+
evalueateEvent(templateName: string, data: string, { timestamp }?: SpanEvaluateEventProps): SpanContext;
|
|
105
|
+
private getParent;
|
|
106
|
+
private innerUpdate;
|
|
107
|
+
}
|
|
108
|
+
interface UpdateTraceProps {
|
|
109
|
+
success?: boolean;
|
|
110
|
+
userId?: string | null;
|
|
111
|
+
sessionId?: string | null;
|
|
112
|
+
release?: string;
|
|
113
|
+
metadata?: Record<string, any> | null;
|
|
114
|
+
}
|
|
115
|
+
declare class TraceContext extends ObservationContext {
|
|
116
|
+
private trace;
|
|
117
|
+
constructor(trace: Trace, parent: ObservationContext | null);
|
|
118
|
+
update({ success, userId, sessionId, release, metadata }?: UpdateTraceProps): TraceContext;
|
|
119
|
+
}
|
|
120
|
+
interface TraceProps {
|
|
121
|
+
userId?: string | null;
|
|
122
|
+
sessionId?: string | null;
|
|
123
|
+
release?: string;
|
|
124
|
+
metadata?: Record<string, any> | null;
|
|
125
|
+
}
|
|
126
|
+
declare const trace: ({ userId, sessionId, release, metadata, }?: TraceProps) => TraceContext;
|
|
127
|
+
|
|
128
|
+
declare class Laminar {
|
|
129
|
+
private readonly projectApiKey;
|
|
130
|
+
private readonly url;
|
|
131
|
+
private readonly response;
|
|
132
|
+
constructor(projectApiKey: string);
|
|
133
|
+
run({ pipeline, inputs, env, metadata, }: PipelineRunRequest): Promise<PipelineRunResponse>;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export { type ChatMessage, type EvaluateEvent, type Event, Laminar, type NodeInput, ObservationContext, type PipelineRunRequest, type PipelineRunResponse, type Span, SpanContext, type Trace, TraceContext, trace };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
Laminar: () => Laminar,
|
|
24
|
+
ObservationContext: () => ObservationContext,
|
|
25
|
+
SpanContext: () => SpanContext,
|
|
26
|
+
TraceContext: () => TraceContext,
|
|
27
|
+
trace: () => trace
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(src_exports);
|
|
30
|
+
|
|
31
|
+
// src/types.ts
|
|
32
|
+
var DEFAULT_SPAN_TYPE = "DEFAULT";
|
|
33
|
+
|
|
34
|
+
// src/constants.ts
|
|
35
|
+
var CURRENT_TRACING_VERSION = "0.1.0";
|
|
36
|
+
|
|
37
|
+
// src/tracing.ts
|
|
38
|
+
var Collector = class {
|
|
39
|
+
constructor() {
|
|
40
|
+
this.flushInterval = 2;
|
|
41
|
+
// seconds
|
|
42
|
+
this.client = new Client(process.env.LMNR_PROJECT_API_KEY || "");
|
|
43
|
+
this.maxQueueSize = 1e3;
|
|
44
|
+
this.queue = [];
|
|
45
|
+
this.flushTimeout = setTimeout(this.flush.bind(this), this.flushInterval * 1e3);
|
|
46
|
+
}
|
|
47
|
+
addTask(task) {
|
|
48
|
+
this.queue.push(task);
|
|
49
|
+
if (this.queue.length >= this.maxQueueSize) {
|
|
50
|
+
this.flush();
|
|
51
|
+
}
|
|
52
|
+
if (!this.flushTimeout) {
|
|
53
|
+
this.flushTimeout = setTimeout(this.flush.bind(this), this.flushInterval * 1e3);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
flush() {
|
|
57
|
+
if (this.flushTimeout != null) {
|
|
58
|
+
clearTimeout(this.flushTimeout);
|
|
59
|
+
this.flushTimeout = null;
|
|
60
|
+
}
|
|
61
|
+
if (this.queue.length === 0) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
this.client.batchPost(this.queue);
|
|
65
|
+
this.queue = [];
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
var CollectorSingleton = class {
|
|
69
|
+
static getInstance() {
|
|
70
|
+
if (this.instance === null) {
|
|
71
|
+
this.instance = new Collector();
|
|
72
|
+
}
|
|
73
|
+
return this.instance;
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
CollectorSingleton.instance = null;
|
|
77
|
+
var Client = class {
|
|
78
|
+
constructor(projectApiKey) {
|
|
79
|
+
this.baseUrl = "https://api.lmnr.ai";
|
|
80
|
+
this.projectApiKey = projectApiKey;
|
|
81
|
+
}
|
|
82
|
+
getHeaders() {
|
|
83
|
+
return {
|
|
84
|
+
"Content-Type": "application/json",
|
|
85
|
+
"Authorization": `Bearer ${this.projectApiKey}`
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
batchPost(data) {
|
|
89
|
+
const body = JSON.stringify({
|
|
90
|
+
traces: data
|
|
91
|
+
});
|
|
92
|
+
const headers = this.getHeaders();
|
|
93
|
+
const url = `${this.baseUrl}/v1/traces`;
|
|
94
|
+
fetch(url, {
|
|
95
|
+
method: "POST",
|
|
96
|
+
headers,
|
|
97
|
+
body
|
|
98
|
+
}).then((response) => {
|
|
99
|
+
if (!response.ok) {
|
|
100
|
+
console.error("Failed to send traces. Response: ");
|
|
101
|
+
response.text().then((text) => console.error(text));
|
|
102
|
+
}
|
|
103
|
+
}).catch((error) => {
|
|
104
|
+
console.error("Failed to send traces. Error: ", error);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// src/utils.ts
|
|
110
|
+
var import_uuid = require("uuid");
|
|
111
|
+
var newUUID = () => {
|
|
112
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
113
|
+
return crypto.randomUUID();
|
|
114
|
+
} else {
|
|
115
|
+
return (0, import_uuid.v4)();
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// src/interface.ts
|
|
120
|
+
var ObservationContext = class {
|
|
121
|
+
constructor(observation, parent) {
|
|
122
|
+
this.observation = observation;
|
|
123
|
+
this.parent = parent;
|
|
124
|
+
this.children = {};
|
|
125
|
+
this.collector = CollectorSingleton.getInstance();
|
|
126
|
+
}
|
|
127
|
+
id() {
|
|
128
|
+
return this.observation.id;
|
|
129
|
+
}
|
|
130
|
+
span(name, {
|
|
131
|
+
input,
|
|
132
|
+
metadata,
|
|
133
|
+
attributes,
|
|
134
|
+
spanType
|
|
135
|
+
} = {}) {
|
|
136
|
+
const parent = this;
|
|
137
|
+
const parentSpanId = parent instanceof SpanContext ? parent.observation.id : null;
|
|
138
|
+
const traceId = parent instanceof TraceContext ? parent.observation.id : parent.observation.traceId;
|
|
139
|
+
const span = {
|
|
140
|
+
version: CURRENT_TRACING_VERSION,
|
|
141
|
+
spanType: spanType != null ? spanType : DEFAULT_SPAN_TYPE,
|
|
142
|
+
id: newUUID(),
|
|
143
|
+
parentSpanId,
|
|
144
|
+
traceId,
|
|
145
|
+
name,
|
|
146
|
+
startTime: /* @__PURE__ */ new Date(),
|
|
147
|
+
endTime: null,
|
|
148
|
+
attributes: attributes != null ? attributes : {},
|
|
149
|
+
input: input != null ? input : null,
|
|
150
|
+
output: null,
|
|
151
|
+
metadata: metadata != null ? metadata : null,
|
|
152
|
+
evaluateEvents: [],
|
|
153
|
+
events: []
|
|
154
|
+
};
|
|
155
|
+
const spanContext = new SpanContext(span, this);
|
|
156
|
+
this.children[span.id] = spanContext;
|
|
157
|
+
return spanContext;
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
var SpanContext = class extends ObservationContext {
|
|
161
|
+
constructor(span, parent) {
|
|
162
|
+
super(span, parent);
|
|
163
|
+
this.inerSpan = span;
|
|
164
|
+
}
|
|
165
|
+
end({
|
|
166
|
+
input,
|
|
167
|
+
output,
|
|
168
|
+
metadata,
|
|
169
|
+
attributes,
|
|
170
|
+
evaluateEvents,
|
|
171
|
+
override
|
|
172
|
+
} = {}) {
|
|
173
|
+
if (this.children && Object.keys(this.children).length > 0) {
|
|
174
|
+
console.warn(`Ending span ${this.observation.id}, but it has children that have not been finalized. Children: ${Object.values(this.children).map((child) => child.inerSpan.name)}`);
|
|
175
|
+
}
|
|
176
|
+
delete this.getParent().children[this.inerSpan.id];
|
|
177
|
+
this.innerUpdate(input, output, metadata, attributes, evaluateEvents, override, true);
|
|
178
|
+
return this;
|
|
179
|
+
}
|
|
180
|
+
update({
|
|
181
|
+
input,
|
|
182
|
+
output,
|
|
183
|
+
metadata,
|
|
184
|
+
attributes,
|
|
185
|
+
evaluateEvents,
|
|
186
|
+
override
|
|
187
|
+
}) {
|
|
188
|
+
return this.innerUpdate(input, output, metadata, attributes, evaluateEvents, override, false);
|
|
189
|
+
}
|
|
190
|
+
event(templateName, {
|
|
191
|
+
value,
|
|
192
|
+
timestamp
|
|
193
|
+
} = {}) {
|
|
194
|
+
const event = {
|
|
195
|
+
id: newUUID(),
|
|
196
|
+
templateName,
|
|
197
|
+
timestamp: timestamp != null ? timestamp : /* @__PURE__ */ new Date(),
|
|
198
|
+
spanId: this.inerSpan.id,
|
|
199
|
+
value: value != null ? value : null
|
|
200
|
+
};
|
|
201
|
+
this.inerSpan.events.push(event);
|
|
202
|
+
return this;
|
|
203
|
+
}
|
|
204
|
+
evalueateEvent(templateName, data, {
|
|
205
|
+
timestamp
|
|
206
|
+
} = {}) {
|
|
207
|
+
const event = {
|
|
208
|
+
name: templateName,
|
|
209
|
+
data,
|
|
210
|
+
timestamp: timestamp != null ? timestamp : /* @__PURE__ */ new Date()
|
|
211
|
+
};
|
|
212
|
+
this.inerSpan.evaluateEvents.push(event);
|
|
213
|
+
return this;
|
|
214
|
+
}
|
|
215
|
+
getParent() {
|
|
216
|
+
return this.parent;
|
|
217
|
+
}
|
|
218
|
+
innerUpdate(input, output, metadata, attributes, evaluateEvents, override, finalize) {
|
|
219
|
+
const newMetadata = override ? metadata : { ...this.observation.metadata, ...metadata != null ? metadata : {} };
|
|
220
|
+
const newAttributes = override ? attributes : { ...this.inerSpan.attributes, ...attributes != null ? attributes : {} };
|
|
221
|
+
const newEvaluateEvents = override ? evaluateEvents : [...this.inerSpan.evaluateEvents, ...evaluateEvents != null ? evaluateEvents : []];
|
|
222
|
+
this.inerSpan.input = input || this.inerSpan.input;
|
|
223
|
+
this.inerSpan.output = output || this.inerSpan.output;
|
|
224
|
+
this.inerSpan.metadata = newMetadata != null ? newMetadata : null;
|
|
225
|
+
this.inerSpan.attributes = newAttributes != null ? newAttributes : {};
|
|
226
|
+
this.inerSpan.evaluateEvents = newEvaluateEvents != null ? newEvaluateEvents : [];
|
|
227
|
+
if (finalize) {
|
|
228
|
+
this.inerSpan.endTime = /* @__PURE__ */ new Date();
|
|
229
|
+
this.collector.addTask(this.inerSpan);
|
|
230
|
+
}
|
|
231
|
+
return this;
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
var TraceContext = class extends ObservationContext {
|
|
235
|
+
constructor(trace2, parent) {
|
|
236
|
+
super(trace2, parent);
|
|
237
|
+
this.trace = trace2;
|
|
238
|
+
this.collector.addTask(this.trace);
|
|
239
|
+
}
|
|
240
|
+
update({
|
|
241
|
+
success,
|
|
242
|
+
userId,
|
|
243
|
+
sessionId,
|
|
244
|
+
release,
|
|
245
|
+
metadata
|
|
246
|
+
} = {}) {
|
|
247
|
+
const newMetadata = metadata ? { ...this.observation.metadata, ...metadata } : this.observation.metadata;
|
|
248
|
+
this.trace.success = success != null ? success : this.trace.success;
|
|
249
|
+
this.trace.userId = userId != null ? userId : this.trace.userId;
|
|
250
|
+
this.trace.sessionId = sessionId != null ? sessionId : this.trace.sessionId;
|
|
251
|
+
this.trace.release = release != null ? release : this.trace.release;
|
|
252
|
+
this.trace.metadata = newMetadata != null ? newMetadata : null;
|
|
253
|
+
this.collector.addTask(this.trace);
|
|
254
|
+
return this;
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
var trace = ({
|
|
258
|
+
userId,
|
|
259
|
+
sessionId,
|
|
260
|
+
release,
|
|
261
|
+
metadata
|
|
262
|
+
} = {}) => {
|
|
263
|
+
const trace2 = {
|
|
264
|
+
id: newUUID(),
|
|
265
|
+
version: CURRENT_TRACING_VERSION,
|
|
266
|
+
success: true,
|
|
267
|
+
startTime: /* @__PURE__ */ new Date(),
|
|
268
|
+
endTime: null,
|
|
269
|
+
userId: userId != null ? userId : null,
|
|
270
|
+
sessionId: sessionId != null ? sessionId : newUUID(),
|
|
271
|
+
release: release != null ? release : "v1",
|
|
272
|
+
metadata: metadata != null ? metadata : null
|
|
273
|
+
};
|
|
274
|
+
return new TraceContext(trace2, null);
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
// src/index.ts
|
|
278
|
+
var Laminar = class {
|
|
279
|
+
constructor(projectApiKey) {
|
|
280
|
+
this.response = null;
|
|
281
|
+
this.projectApiKey = projectApiKey != null ? projectApiKey : process.env.LMNR_PROJECT_API_KEY;
|
|
282
|
+
this.url = "https://api.lmnr.ai/v1/pipeline/run";
|
|
283
|
+
}
|
|
284
|
+
async run({
|
|
285
|
+
pipeline,
|
|
286
|
+
inputs,
|
|
287
|
+
env = {},
|
|
288
|
+
metadata = {}
|
|
289
|
+
}) {
|
|
290
|
+
if (this.projectApiKey === void 0) {
|
|
291
|
+
throw new Error(
|
|
292
|
+
"Please initialize the Laminar object with your project API key or set the LMNR_PROJECT_API_KEY environment variable"
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
const response = await fetch(this.url, {
|
|
296
|
+
method: "POST",
|
|
297
|
+
headers: {
|
|
298
|
+
"Content-Type": "application/json",
|
|
299
|
+
"Authorization": `Bearer ${this.projectApiKey}`
|
|
300
|
+
},
|
|
301
|
+
body: JSON.stringify({
|
|
302
|
+
inputs,
|
|
303
|
+
pipeline,
|
|
304
|
+
env,
|
|
305
|
+
metadata
|
|
306
|
+
})
|
|
307
|
+
});
|
|
308
|
+
return await response.json();
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
312
|
+
0 && (module.exports = {
|
|
313
|
+
Laminar,
|
|
314
|
+
ObservationContext,
|
|
315
|
+
SpanContext,
|
|
316
|
+
TraceContext,
|
|
317
|
+
trace
|
|
318
|
+
});
|
|
319
|
+
//# sourceMappingURL=index.js.map
|