@lmnr-ai/lmnr 0.2.3 → 0.2.5
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/README.md +20 -15
- package/package.json +1 -1
- package/src/index.ts +23 -10
- package/src/remote_debugger.ts +42 -12
- package/src/types.ts +15 -0
package/README.md
CHANGED
|
@@ -57,10 +57,16 @@ This only works in Node execution context; browser context is not supported.
|
|
|
57
57
|
|
|
58
58
|
Example use:
|
|
59
59
|
|
|
60
|
-
```
|
|
60
|
+
```js
|
|
61
61
|
import { Laminar, NodeInput } from '@lmnr-ai/lmnr';
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
// make sure to setup arguments as object
|
|
64
|
+
const myTool = ({
|
|
65
|
+
arg1, arg2
|
|
66
|
+
}: {
|
|
67
|
+
arg1: string,
|
|
68
|
+
arg2: number
|
|
69
|
+
}): NodeInput => {
|
|
64
70
|
// this tool teaches LLMs the beauty of JavaScript!
|
|
65
71
|
return arg1 + arg2;
|
|
66
72
|
}
|
|
@@ -83,7 +89,7 @@ If your pipeline contains tool call nodes, they will be able to call your local
|
|
|
83
89
|
If you want to test them from the Laminar workshop in your browser, you can attach to your
|
|
84
90
|
locally running debugger.
|
|
85
91
|
|
|
86
|
-
### Step
|
|
92
|
+
### Step-by-step instructions to use `LaminarRemoteDebugger`:
|
|
87
93
|
|
|
88
94
|
#### 1. Create your pipeline with tool call nodes
|
|
89
95
|
|
|
@@ -94,15 +100,21 @@ Add tool calls to your pipeline; node names must match the functions you want to
|
|
|
94
100
|
Example:
|
|
95
101
|
|
|
96
102
|
```js
|
|
97
|
-
import { LaminarRemoteDebugger } from '@lmnr-ai/lmnr';
|
|
98
|
-
|
|
99
|
-
|
|
103
|
+
import { LaminarRemoteDebugger, NodeInput } from '@lmnr-ai/lmnr';
|
|
104
|
+
|
|
105
|
+
// make sure to setup arguments as object
|
|
106
|
+
const myTool = ({
|
|
107
|
+
arg1, arg2
|
|
108
|
+
}: {
|
|
109
|
+
arg1: string,
|
|
110
|
+
arg2: number
|
|
111
|
+
}): NodeInput => {
|
|
100
112
|
// this tool teaches LLMs the beauty of JavaScript!
|
|
101
113
|
return arg1 + arg2;
|
|
102
114
|
}
|
|
103
115
|
|
|
104
|
-
|
|
105
|
-
|
|
116
|
+
const dbgr = new LaminarRemoteDebugger('<YOUR_PROJECT_API_KEY>', [myTool]);
|
|
117
|
+
dbgr.start();
|
|
106
118
|
// the session id will be printed to console.
|
|
107
119
|
// It is also returned from this promise, but you may not want to `await` it
|
|
108
120
|
```
|
|
@@ -118,10 +130,3 @@ Set up `DEBUGGER_SESSION_ID` environment variable in your pipeline.
|
|
|
118
130
|
|
|
119
131
|
You can run as many sessions as you need, experimenting with your flows.
|
|
120
132
|
|
|
121
|
-
#### 5. Stop the debugger
|
|
122
|
-
|
|
123
|
-
In order to stop the session, do
|
|
124
|
-
|
|
125
|
-
```js
|
|
126
|
-
debugger.stop()
|
|
127
|
-
```
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { EndpointRunResponse, EndpointRunRequest, NodeWebSocketMessage, WebSocketError, ToolCallRequest, ToolCallResponse, ToolCallError } from './types';
|
|
2
2
|
import { isBrowser, isNode } from 'browser-or-node';
|
|
3
3
|
import { WebSocket } from 'ws';
|
|
4
4
|
|
|
@@ -53,11 +53,10 @@ export class Laminar {
|
|
|
53
53
|
|
|
54
54
|
private async _ws_run(request: EndpointRunRequest): Promise<EndpointRunResponse> {
|
|
55
55
|
if (isBrowser) {
|
|
56
|
-
throw new Error('Running tools in the browser is not supported
|
|
56
|
+
throw new Error('Running tools in the browser is not supported. Please use the Node.js environment.');
|
|
57
57
|
} else if (isNode) {
|
|
58
58
|
return this._ws_run_node(request);
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
59
|
+
} else {
|
|
61
60
|
throw new Error('Unsupported environment');
|
|
62
61
|
}
|
|
63
62
|
}
|
|
@@ -71,6 +70,7 @@ export class Laminar {
|
|
|
71
70
|
}: EndpointRunRequest): Promise<EndpointRunResponse> {
|
|
72
71
|
const socket = new WebSocket(this.ws_url, [], {headers: {'Authorization': `Bearer ${this.projectApiKey}`}});
|
|
73
72
|
let response: EndpointRunResponse | null = null;
|
|
73
|
+
let reqId: string | null = null;
|
|
74
74
|
|
|
75
75
|
socket.on('open', () => {
|
|
76
76
|
socket.send(JSON.stringify({
|
|
@@ -83,19 +83,32 @@ export class Laminar {
|
|
|
83
83
|
});
|
|
84
84
|
socket.on('message', (data: NodeWebSocketMessage) => {
|
|
85
85
|
try {
|
|
86
|
-
const toolCall = JSON.parse(data.toString()) as
|
|
87
|
-
|
|
86
|
+
const toolCall = JSON.parse(data.toString()) as ToolCallRequest;
|
|
87
|
+
reqId = toolCall.reqId;
|
|
88
|
+
const matchingTool = tools.find(tool => tool.name === toolCall.toolCall.function.name);
|
|
88
89
|
if (!matchingTool) {
|
|
89
90
|
throw new WebSocketError(
|
|
90
|
-
`Tool ${toolCall.function.name} not found.
|
|
91
|
+
`Tool ${toolCall.toolCall.function.name} not found. ` +
|
|
92
|
+
`Registered tools: ${tools.map(tool => tool.name).join(', ')}`
|
|
91
93
|
);
|
|
92
94
|
}
|
|
93
95
|
let args = {}
|
|
94
96
|
try {
|
|
95
|
-
args = JSON.parse(toolCall.function.arguments);
|
|
97
|
+
args = JSON.parse(toolCall.toolCall.function.arguments);
|
|
96
98
|
} catch (e) {}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
+
try {
|
|
100
|
+
const result = matchingTool(args);
|
|
101
|
+
const toolResponse = {
|
|
102
|
+
reqId,
|
|
103
|
+
response: result
|
|
104
|
+
} as ToolCallResponse;
|
|
105
|
+
socket.send(JSON.stringify(toolResponse));
|
|
106
|
+
} catch (e) {
|
|
107
|
+
socket.send(JSON.stringify({
|
|
108
|
+
reqId,
|
|
109
|
+
error: (e as Error).message
|
|
110
|
+
} as ToolCallError));
|
|
111
|
+
}
|
|
99
112
|
} catch (e) {
|
|
100
113
|
if (e instanceof WebSocketError) {
|
|
101
114
|
throw e;
|
package/src/remote_debugger.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
DeregisterDebuggerRequest,
|
|
3
|
+
NodeWebSocketMessage,
|
|
4
|
+
RegisterDebuggerRequest,
|
|
5
|
+
Tool,
|
|
6
|
+
ToolCallRequest,
|
|
7
|
+
ToolCallError,
|
|
8
|
+
ToolCallResponse,
|
|
9
|
+
} from "./types";
|
|
2
10
|
import { v4 as uuidv4 } from 'uuid';
|
|
3
11
|
import { WebSocket } from 'ws';
|
|
4
12
|
|
|
@@ -18,7 +26,8 @@ export class RemoteDebugger {
|
|
|
18
26
|
|
|
19
27
|
public async start(): Promise<string> {
|
|
20
28
|
this.sessionId = this.generateSessionId();
|
|
21
|
-
console.log(this.
|
|
29
|
+
console.log(this.formatSessionIdAndRegisteredTools());
|
|
30
|
+
let reqId: string | null = null;
|
|
22
31
|
|
|
23
32
|
this.socket.on('open', () => {
|
|
24
33
|
this.socket.send(JSON.stringify({
|
|
@@ -28,21 +37,38 @@ export class RemoteDebugger {
|
|
|
28
37
|
|
|
29
38
|
this.socket.on('message', (data: NodeWebSocketMessage) => {
|
|
30
39
|
try {
|
|
31
|
-
const toolCall = JSON.parse(data.toString()) as
|
|
32
|
-
|
|
40
|
+
const toolCall = JSON.parse(data.toString()) as ToolCallRequest;
|
|
41
|
+
reqId = toolCall.reqId;
|
|
42
|
+
const matchingTool = this.tools.find(tool => tool.name === toolCall.toolCall.function.name);
|
|
33
43
|
if (!matchingTool) {
|
|
34
|
-
|
|
35
|
-
`
|
|
36
|
-
);
|
|
44
|
+
const errMsg = `Tool ${toolCall.toolCall.function.name} not found. ` +
|
|
45
|
+
`Registered tools: ${this.tools.map(tool => tool.name).join(', ')}`;
|
|
46
|
+
console.error(errMsg);
|
|
47
|
+
this.socket.send(JSON.stringify({
|
|
48
|
+
reqId,
|
|
49
|
+
error: errMsg
|
|
50
|
+
} as ToolCallError));
|
|
37
51
|
return;
|
|
38
52
|
}
|
|
39
53
|
let args = {}
|
|
40
54
|
try {
|
|
41
|
-
args = JSON.parse(toolCall.function.arguments);
|
|
55
|
+
args = JSON.parse(toolCall.toolCall.function.arguments);
|
|
42
56
|
} catch (e) {}
|
|
43
|
-
|
|
44
|
-
|
|
57
|
+
try {
|
|
58
|
+
const result = matchingTool(args); // NodeInput
|
|
59
|
+
const toolResponse = {
|
|
60
|
+
reqId,
|
|
61
|
+
response: result
|
|
62
|
+
} as ToolCallResponse;
|
|
63
|
+
this.socket.send(JSON.stringify(toolResponse));
|
|
64
|
+
} catch (e) {
|
|
65
|
+
this.socket.send(JSON.stringify({
|
|
66
|
+
reqId,
|
|
67
|
+
error: (e as Error).message
|
|
68
|
+
} as ToolCallError));
|
|
69
|
+
}
|
|
45
70
|
} catch (e) {
|
|
71
|
+
console.error(`Received invalid message: ${data.toString()}`);
|
|
46
72
|
this.socket.send(JSON.stringify({
|
|
47
73
|
deregister: true,
|
|
48
74
|
debuggerSessionId: this.sessionId
|
|
@@ -58,7 +84,7 @@ export class RemoteDebugger {
|
|
|
58
84
|
this.socket.send(JSON.stringify({
|
|
59
85
|
deregister: true,
|
|
60
86
|
debuggerSessionId: this.sessionId
|
|
61
|
-
} as
|
|
87
|
+
} as DeregisterDebuggerRequest));
|
|
62
88
|
this.socket.close();
|
|
63
89
|
}
|
|
64
90
|
|
|
@@ -70,12 +96,16 @@ export class RemoteDebugger {
|
|
|
70
96
|
return uuidv4();
|
|
71
97
|
}
|
|
72
98
|
|
|
73
|
-
private
|
|
99
|
+
private formatSessionIdAndRegisteredTools(): string {
|
|
74
100
|
return `
|
|
75
101
|
========================================
|
|
76
102
|
Debugger Session ID:
|
|
77
103
|
${this.sessionId}
|
|
78
104
|
========================================
|
|
105
|
+
|
|
106
|
+
Registered functions:
|
|
107
|
+
${this.tools.map(tool => '- ' + tool.name).join(',\n')}
|
|
108
|
+
========================================
|
|
79
109
|
`
|
|
80
110
|
}
|
|
81
111
|
}
|
package/src/types.ts
CHANGED
|
@@ -20,6 +20,11 @@ export type EndpointRunResponse = {
|
|
|
20
20
|
runId: string;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
export type ToolCallRequest = {
|
|
24
|
+
reqId: string;
|
|
25
|
+
toolCall: ToolCall;
|
|
26
|
+
}
|
|
27
|
+
|
|
23
28
|
export type ToolFunctionCall = {
|
|
24
29
|
name: string;
|
|
25
30
|
arguments: string;
|
|
@@ -31,6 +36,11 @@ export type ToolCall = {
|
|
|
31
36
|
function: ToolFunctionCall;
|
|
32
37
|
}
|
|
33
38
|
|
|
39
|
+
export type ToolCallResponse = {
|
|
40
|
+
reqId: string;
|
|
41
|
+
response: NodeInput;
|
|
42
|
+
}
|
|
43
|
+
|
|
34
44
|
export type NodeWebSocketMessage = {
|
|
35
45
|
type: 'utf8' | 'binary';
|
|
36
46
|
utf8Data?: string;
|
|
@@ -45,4 +55,9 @@ export type DeregisterDebuggerRequest = {
|
|
|
45
55
|
debuggerSessionId: string;
|
|
46
56
|
}
|
|
47
57
|
|
|
58
|
+
export type ToolCallError = {
|
|
59
|
+
reqId: string;
|
|
60
|
+
error: string;
|
|
61
|
+
}
|
|
62
|
+
|
|
48
63
|
export class WebSocketError extends Error {}
|