node-red-contrib-ollama 0.2.6 → 0.3.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.
@@ -5,7 +5,12 @@
5
5
  defaults: {
6
6
  name: { value: 'Ollama Create' },
7
7
  server: { value: '', type: 'ollama-config-server', required: false },
8
- model: { value: '', type: 'ollama-config-model', required: false },
8
+ model: { value: '', required: false },
9
+ modelType: { value: 'str', required: false },
10
+ modelfile: { value: '', required: false },
11
+ stream: { value: false },
12
+ path: { value: '', required: false },
13
+ pathType: { value: 'str', required: false },
9
14
  },
10
15
  inputs: 1,
11
16
  outputs: 1,
@@ -13,6 +18,43 @@
13
18
  label: function() {
14
19
  return this.name || 'ollama-create';
15
20
  },
21
+ oneditprepare: function() {
22
+ if( !this.modelType ) {
23
+ this.modelType = 'str'
24
+ }
25
+
26
+ $( '#node-input-model' ).typedInput( {
27
+ type: 'str',
28
+ types: [ 'str', 'msg', 'flow', 'global' ],
29
+ typeField: '#node-input-modelType'
30
+ } )
31
+
32
+ this.editor = RED.editor.createEditor( {
33
+ id: 'node-input-modelfile-editor',
34
+ mode: 'yaml',
35
+ value: this.modelfile,
36
+ mode: 'ace/mode/text'
37
+ } )
38
+
39
+ if( !this.pathType ) {
40
+ this.pathType = 'str'
41
+ }
42
+
43
+ $( '#node-input-path' ).typedInput( {
44
+ type: 'str',
45
+ types: [ 'str', 'msg', 'flow', 'global' ],
46
+ typeField: '#node-input-pathType'
47
+ } )
48
+ },
49
+ oneditsave: function() {
50
+ this.modelfile = this.editor.getValue()
51
+ this.editor.destroy()
52
+ delete this.editor
53
+ },
54
+ oneditcancel: function() {
55
+ this.editor.destroy()
56
+ delete this.editor
57
+ }
16
58
  } )
17
59
  </script>
18
60
 
@@ -28,9 +70,24 @@
28
70
  </div>
29
71
 
30
72
  <div class="form-row">
31
- <label for="node-input-model"><i class="fa fa-bookmark"></i> Model</label>
73
+ <label for="node-input-model"><i class="fa fa-comment"></i> Model</label>
32
74
  <input type="text" id="node-input-model" />
75
+ <input type="hidden" id="node-input-modelType" />
33
76
  </div>
77
+
78
+ <div class="form-row">
79
+ <label for="node-input-stream"><i class="fa fa-cog"></i> Stream</label>
80
+ <input type="checkbox" id="node-input-stream" />
81
+ </div>
82
+
83
+ <div class="form-row">
84
+ <label for="node-input-path"><i class="fa fa-comment"></i> Path</label>
85
+ <input type="text" id="node-input-path" />
86
+ <input type="hidden" id="node-input-pathType" />
87
+ </div>
88
+
89
+ <label>Modelfile</label>
90
+ <div style="height: 250px; min-height:150px;" class="node-text-editor" id="node-input-modelfile-editor" />
34
91
  </script>
35
92
 
36
93
  <script type="text/html" data-help-name="ollama-create">
@@ -44,24 +101,19 @@
44
101
  </dt>
45
102
 
46
103
  <dd>
47
- The payload object.
104
+ The payload object is an alternative way to configure the node.<br />
105
+ Any properties in the payload object will override the node configuration.
48
106
 
49
107
  <dl class="message-properties">
50
108
  <dt class="optional">
51
109
  payload.host <span class="property-type">string</span>
52
110
  </dt>
53
- <dd>
54
- The host of the Ollama instance.<br />
55
- <em>Alternative to the <code>Server</code> field.</em>
56
- </dd>
111
+ <dd>The host of the Ollama instance.</dd>
57
112
 
58
113
  <dt class="optional">
59
114
  payload.model <span class="property-type">string</span>
60
115
  </dt>
61
- <dd>
62
- The name of the model to create.<br />
63
- <em>Alternative to the <code>Model</code> field.</em>
64
- </dd>
116
+ <dd>The name of the model to create.</dd>
65
117
 
66
118
  <dt class="optional">
67
119
  payload.path <span class="property-type">string</span>
@@ -3,34 +3,61 @@ module.exports = function( RED ) {
3
3
 
4
4
  function OllamaCreateNode( config ) {
5
5
  RED.nodes.createNode( this, config )
6
- const node = this
7
6
 
8
- node.on( 'input', async function( msg ) {
9
- const {
10
- host: payloadHost,
11
- model: payloadModel,
12
- modelfile,
13
- stream,
14
- path
15
- } = msg.payload
7
+ this.modelType = config.modelType || 'str'
8
+ this.stream = config.stream || false
9
+ this.pathType = config.pathType || 'str'
16
10
 
11
+ const node = this
12
+ node.on( 'input', async function( msg ) {
17
13
  const server = RED.nodes.getNode( config.server )
18
- const host = ( server ) ? server.host + ':' + server.port : payloadHost
14
+ const host = msg?.payload?.host || ( server ) ? server.host + ':' + server.port : null
19
15
 
20
16
  const ollama = new Ollama( { host } )
21
17
 
22
- const modelConfig = RED.nodes.getNode( config.model )
23
- const model = ( modelConfig ) ? modelConfig.name : payloadModel
18
+ let model = null
19
+ if( msg?.payload?.model ) {
20
+ model = msg?.payload?.model
21
+ } else if( !!config.model ) {
22
+ if( node.modelType === 'str' ) {
23
+ model = config.model
24
+ } else if( node.modelType === 'msg' ) {
25
+ model = msg[ config.model ]
26
+ } else if( node.modelType === 'flow' ) {
27
+ model = node.context().flow.get( config.model )
28
+ } else if( node.modelType === 'global' ) {
29
+ model = node.context().global.get( config.model )
30
+ }
31
+ }
32
+
33
+ const modelfile = msg?.payload?.modelfile || config.modelfile
34
+
35
+ const stream = ( msg?.payload?.stream !== undefined ) ? msg?.payload?.stream : node.stream
36
+
37
+ let path = null
38
+ if( msg?.payload?.path ) {
39
+ path = msg?.payload?.path
40
+ } else if( !!config.path ) {
41
+ if( node.pathType === 'str' ) {
42
+ path = config.path
43
+ } else if( node.pathType === 'msg' ) {
44
+ path = msg[ config.path ]
45
+ } else if( node.pathType === 'flow' ) {
46
+ path = node.context().flow.get( config.path )
47
+ } else if( node.pathType === 'global' ) {
48
+ path = node.context().global.get( config.path )
49
+ }
50
+ }
24
51
 
25
52
  const response = await ollama.create( {
26
- model,
27
- modelfile,
28
- stream,
29
- path
30
- } )
31
- .catch( error => {
32
- node.error( error )
33
- } )
53
+ model,
54
+ modelfile,
55
+ stream,
56
+ path
57
+ } )
58
+ .catch( error => {
59
+ node.error( error )
60
+ } )
34
61
 
35
62
  msg.payload = response
36
63
  node.send( msg )
@@ -5,7 +5,8 @@
5
5
  defaults: {
6
6
  name: { value: 'Ollama Delete' },
7
7
  server: { value: '', type: 'ollama-config-server', required: false },
8
- model: { value: '', type: 'ollama-config-model', required: false },
8
+ model: { value: '', required: false },
9
+ modelType: { value: 'str', required: false },
9
10
  },
10
11
  inputs: 1,
11
12
  outputs: 1,
@@ -13,6 +14,17 @@
13
14
  label: function() {
14
15
  return this.name || 'ollama-delete';
15
16
  },
17
+ oneditprepare: function() {
18
+ if( !this.modelType ) {
19
+ this.modelType = 'str'
20
+ }
21
+
22
+ $( '#node-input-model' ).typedInput( {
23
+ type: 'str',
24
+ types: [ 'str', 'msg', 'flow', 'global' ],
25
+ typeField: '#node-input-modelType'
26
+ } )
27
+ }
16
28
  } )
17
29
  </script>
18
30
 
@@ -28,8 +40,9 @@
28
40
  </div>
29
41
 
30
42
  <div class="form-row">
31
- <label for="node-input-model"><i class="fa fa-bookmark"></i> Model</label>
43
+ <label for="node-input-model"><i class="fa fa-comment"></i> Model</label>
32
44
  <input type="text" id="node-input-model" />
45
+ <input type="hidden" id="node-input-modelType" />
33
46
  </div>
34
47
  </script>
35
48
 
@@ -44,24 +57,19 @@
44
57
  </dt>
45
58
 
46
59
  <dd>
47
- The payload object.
60
+ The payload object is an alternative way to configure the node.<br />
61
+ Any properties in the payload object will override the node configuration.
48
62
 
49
63
  <dl class="message-properties">
50
64
  <dt class="optional">
51
65
  payload.host <span class="property-type">string</span>
52
66
  </dt>
53
- <dd>
54
- The host of the Ollama instance.<br />
55
- <em>Alternative to the <code>Server</code> field.</em>
56
- </dd>
67
+ <dd>The host of the Ollama instance.</dd>
57
68
 
58
69
  <dt class="optional">
59
70
  payload.model <span class="property-type">string</span>
60
71
  </dt>
61
- <dd>
62
- The name of the model to delete.<br />
63
- <em>Alternative to the <code>Model</code> field.</em>
64
- </dd>
72
+ <dd>The name of the model to delete.</dd>
65
73
  </dl>
66
74
  </dd>
67
75
  </dl>
@@ -3,21 +3,30 @@ module.exports = function( RED ) {
3
3
 
4
4
  function OllamaDeleteNode( config ) {
5
5
  RED.nodes.createNode( this, config )
6
- const node = this
7
6
 
8
- node.on( 'input', async function( msg ) {
9
- const {
10
- host: payloadHost,
11
- model: payloadModel
12
- } = msg.payload
7
+ this.modelType = config.modelType || 'str'
13
8
 
9
+ const node = this
10
+ node.on( 'input', async function( msg ) {
14
11
  const server = RED.nodes.getNode( config.server )
15
- const host = ( server ) ? server.host + ':' + server.port : payloadHost
12
+ const host = msg?.payload?.host || ( server ) ? server.host + ':' + server.port : null
16
13
 
17
14
  const ollama = new Ollama( { host } )
18
15
 
19
- const modelConfig = RED.nodes.getNode( config.model )
20
- const model = ( modelConfig ) ? modelConfig.name : payloadModel
16
+ let model = null
17
+ if( msg?.payload?.model ) {
18
+ model = msg?.payload?.model
19
+ } else if( !!config.model ) {
20
+ if( node.modelType === 'str' ) {
21
+ model = config.model
22
+ } else if( node.modelType === 'msg' ) {
23
+ model = msg[ config.model ]
24
+ } else if( node.modelType === 'flow' ) {
25
+ model = node.context().flow.get( config.model )
26
+ } else if( node.modelType === 'global' ) {
27
+ model = node.context().global.get( config.model )
28
+ }
29
+ }
21
30
 
22
31
  const response = await ollama.delete( { model } )
23
32
  .catch( error => {
@@ -5,7 +5,13 @@
5
5
  defaults: {
6
6
  name: { value: 'Ollama Embed' },
7
7
  server: { value: '', type: 'ollama-config-server', required: false },
8
- model: { value: '', type: 'ollama-config-model', required: false },
8
+ model: { value: '', required: false },
9
+ modelType: { value: 'str', required: false },
10
+ input: { value: '', required: false },
11
+ inputType: { value: 'str', required: false },
12
+ truncate: { value: false, required: false },
13
+ keepAlive: { value: '5m', required: false },
14
+ keepAliveType: { value: 'str', required: false },
9
15
  options: { value: '', type: 'ollama-config-options', required: false },
10
16
  },
11
17
  inputs: 1,
@@ -14,6 +20,37 @@
14
20
  label: function() {
15
21
  return this.name || 'ollama-embed';
16
22
  },
23
+ oneditprepare: function() {
24
+ if( !this.modelType ) {
25
+ this.modelType = 'str'
26
+ }
27
+
28
+ $( '#node-input-model' ).typedInput( {
29
+ type: 'str',
30
+ types: [ 'str', 'msg', 'flow', 'global' ],
31
+ typeField: '#node-input-modelType'
32
+ } )
33
+
34
+ if( !this.inputType ) {
35
+ this.inputType = 'str'
36
+ }
37
+
38
+ $( '#node-input-input' ).typedInput( {
39
+ type: 'str',
40
+ types: [ 'str', 'json', 'msg', 'flow', 'global' ],
41
+ typeField: '#node-input-inputType'
42
+ } )
43
+
44
+ if( !this.keepAliveType ) {
45
+ this.keepAliveType = 'str'
46
+ }
47
+
48
+ $( '#node-input-keepAlive' ).typedInput( {
49
+ type: 'str',
50
+ types: [ 'str', 'num' ],
51
+ typeField: '#node-input-keepAliveType'
52
+ } )
53
+ }
17
54
  } )
18
55
  </script>
19
56
 
@@ -29,8 +66,26 @@
29
66
  </div>
30
67
 
31
68
  <div class="form-row">
32
- <label for="node-input-model"><i class="fa fa-bookmark"></i> Model</label>
69
+ <label for="node-input-model"><i class="fa fa-comment"></i> Model</label>
33
70
  <input type="text" id="node-input-model" />
71
+ <input type="hidden" id="node-input-modelType" />
72
+ </div>
73
+
74
+ <div class="form-row">
75
+ <label for="node-input-input"><i class="fa fa-comment"></i> Input</label>
76
+ <input type="text" id="node-input-input" />
77
+ <input type="hidden" id="node-input-inputType" />
78
+ </div>
79
+
80
+ <div class="form-row">
81
+ <label for="node-input-truncate"><i class="fa fa-cog"></i> Truncate</label>
82
+ <input type="checkbox" id="node-input-truncate" />
83
+ </div>
84
+
85
+ <div class="form-row">
86
+ <label for="node-input-keepAlive"><i class="fa fa-cog"></i> Keep Alive</label>
87
+ <input type="text" id="node-input-keepAlive" />
88
+ <input type="hidden" id="node-input-keepAliveType" />
34
89
  </div>
35
90
 
36
91
  <div class="form-row">
@@ -50,28 +105,23 @@
50
105
  </dt>
51
106
 
52
107
  <dd>
53
- The payload object.
108
+ The payload object is an alternative way to configure the node.<br />
109
+ Any properties in the payload object will override the node configuration.
54
110
 
55
111
  <dl class="message-properties">
56
112
  <dt class="optional">
57
113
  payload.host <span class="property-type">string</span>
58
114
  </dt>
59
- <dd>
60
- The host of the Ollama instance.<br />
61
- <em>Alternative to the <code>Server</code> field.</em>
62
- </dd>
115
+ <dd>The host of the Ollama instance.</dd>
63
116
 
64
117
  <dt class="optional">
65
118
  payload.model <span class="property-type">string</span>
66
119
  </dt>
67
- <dd>
68
- The name of the model used to generate the embeddings.<br />
69
- <em>Alternative to the <code>Model</code> field.</em>
70
- </dd>
120
+ <dd>The name of the model used to generate the embeddings.</dd>
71
121
 
72
- <dt>
122
+ <dt class="optional">
73
123
  payload.input <span class="property-type">string | array[string]</span>
74
- </dt>
124
+ </d>
75
125
  <dd>The input used to generate the embeddings.</dd>
76
126
 
77
127
  <dt class="optional">
@@ -93,140 +143,140 @@
93
143
 
94
144
  <h4>Options</h4>
95
145
  <dl class="message-properties">
96
- <dt>
146
+ <dt class="optional">
97
147
  numa <span class="property-type">boolean</span>
98
148
  </dt>
99
149
  <dd>Use NUMA for the runtime.</dd>
100
150
 
101
- <dt>
151
+ <dt class="optional">
102
152
  num_ctx <span class="property-type">number</span>
103
153
  </dt>
104
154
  <dd>The number of contexts to use.</dd>
105
155
 
106
- <dt>
156
+ <dt class="optional">
107
157
  num_batch <span class="property-type">number</span>
108
158
  </dt>
109
159
  <dd>The number of batches to use.</dd>
110
160
 
111
- <dt>
161
+ <dt class="optional">
112
162
  main_gpu <span class="property-type">number</span>
113
163
  </dt>
114
164
  <dd>The main GPU to use.</dd>
115
165
 
116
- <dt>
166
+ <dt class="optional">
117
167
  low_vram <span class="property-type">boolean</span>
118
168
  </dt>
119
169
  <dd>Use low VRAM.</dd>
120
170
 
121
- <dt>
171
+ <dt class="optional">
122
172
  f16_kv <span class="property-type">boolean</span>
123
173
  </dt>
124
174
  <dd>Use f16 key-value.</dd>
125
175
 
126
- <dt>
176
+ <dt class="optional">
127
177
  logits_all <span class="property-type">boolean</span>
128
178
  </dt>
129
179
  <dd>Return all logits.</dd>
130
180
 
131
- <dt>
181
+ <dt class="optional">
132
182
  vocab_only <span class="property-type">boolean</span>
133
183
  </dt>
134
184
  <dd>Return only the vocabulary.</dd>
135
185
 
136
- <dt>
186
+ <dt class="optional">
137
187
  use_nmap <span class="property-type">boolean</span>
138
188
  </dt>
139
189
  <dd>Use NMAP.</dd>
140
190
 
141
- <dt>
191
+ <dt class="optional">
142
192
  use_mlock <span class="property-type">boolean</span>
143
193
  </dt>
144
194
  <dd>Use mlock.</dd>
145
195
 
146
- <dt>
196
+ <dt class="optional">
147
197
  embedding_only <span class="property-type">boolean</span>
148
198
  </dt>
149
199
  <dd>Return only the embeddings.</dd>
150
200
 
151
- <dt>
201
+ <dt class="optional">
152
202
  num_thread <span class="property-type">number</span>
153
203
  </dt>
154
204
  <dd>The number of threads to use.</dd>
155
205
 
156
- <dt>
206
+ <dt class="optional">
157
207
  num_keep <span class="property-type">number</span>
158
208
  </dt>
159
209
  <dd>The number of models to keep.</dd>
160
210
 
161
- <dt>
211
+ <dt class="optional">
162
212
  seed <span class="property-type">number</span>
163
213
  </dt>
164
214
  <dd>The seed to use.</dd>
165
215
 
166
- <dt>
216
+ <dt class="optional">
167
217
  num_predict <span class="property-type">number</span>
168
218
  </dt>
169
219
  <dd>The number of predictions to use.</dd>
170
220
 
171
- <dt>
221
+ <dt class="optional">
172
222
  top_k <span class="property-type">number</span>
173
223
  </dt>
174
224
  <dd>The top k to use.</dd>
175
225
 
176
- <dt>
226
+ <dt class="optional">
177
227
  top_p <span class="property-type">number</span>
178
228
  </dt>
179
229
  <dd>The top p to use.</dd>
180
230
 
181
- <dt>
231
+ <dt class="optional">
182
232
  typical_p <span class="property-type">number</span>
183
233
  </dt>
184
234
  <dd>The typical p to use.</dd>
185
235
 
186
- <dt>
236
+ <dt class="optional">
187
237
  repeat_last_n <span class="property-type">number</span>
188
238
  </dt>
189
239
  <dd>The repeat last n to use.</dd>
190
240
 
191
- <dt>
241
+ <dt class="optional">
192
242
  temperature <span class="property-type">number</span>
193
243
  </dt>
194
244
  <dd>The temperature to use.</dd>
195
245
 
196
- <dt>
246
+ <dt class="optional">
197
247
  repeat_pentalty <span class="property-type">number</span>
198
248
  </dt>
199
249
  <dd>The repeat pentalty to use.</dd>
200
250
 
201
- <dt>
251
+ <dt class="optional">
202
252
  presence_penalty <span class="property-type">number</span>
203
253
  </dt>
204
254
  <dd>The presence penalty to use.</dd>
205
255
 
206
- <dt>
256
+ <dt class="optional">
207
257
  frequency_penalty <span class="property-type">number</span>
208
258
  </dt>
209
259
  <dd>The frequency penalty to use.</dd>
210
260
 
211
- <dt>
261
+ <dt class="optional">
212
262
  mirostat <span class="property-type">boolean</span>
213
263
  </dt>
214
264
  <dd>Use mirostat.</dd>
215
265
 
216
- <dt>
266
+ <dt class="optional">
217
267
  mirostat_tau <span class="property-type">number</span>
218
268
  </dt>
219
269
 
220
- <dt>
270
+ <dt class="optional">
221
271
  mirostat_eta <span class="property-type">number</span>
222
272
  </dt>
223
273
 
224
- <dt>
274
+ <dt class="optional">
225
275
  penalize_newline <span class="property-type">boolean</span>
226
276
  </dt>
227
277
  <dd>Penalize newline.</dd>
228
278
 
229
- <dt>
279
+ <dt class="optional">
230
280
  stop <span class="property-type">array</span>
231
281
  </dt>
232
282
  <dd>The stop to use.</dd>
@@ -3,28 +3,66 @@ module.exports = function( RED ) {
3
3
 
4
4
  function OllamaEmbedNode( config ) {
5
5
  RED.nodes.createNode( this, config )
6
- const node = this
7
6
 
8
- node.on( 'input', async function( msg ) {
9
- const {
10
- host: payloadHost,
11
- model: payloadModel,
12
- input,
13
- truncate,
14
- keep_alive,
15
- options: payloadOptions
16
- } = msg.payload
7
+ this.modelType = config.modelType || 'str'
8
+ this.inputType = config.inputType || 'str'
9
+ this.thuncate = config.thuncate || false
10
+ this.keepAliveType = config.keepAliveType || 'str'
17
11
 
12
+ const node = this
13
+ node.on( 'input', async function( msg ) {
18
14
  const server = RED.nodes.getNode( config.server )
19
- const host = ( server ) ? server.host + ':' + server.port : payloadHost
15
+ const host = msg?.payload?.host || ( server ) ? server.host + ':' + server.port : null
20
16
 
21
17
  const ollama = new Ollama( { host } )
22
18
 
23
- const modelConfig = RED.nodes.getNode( config.model )
24
- const model = ( modelConfig ) ? modelConfig.name : payloadModel
19
+ let model = null
20
+ if( msg?.payload?.model ) {
21
+ model = msg?.payload?.model
22
+ } else if( !!config.model ) {
23
+ if( node.modelType === 'str' ) {
24
+ model = config.model
25
+ } else if( node.modelType === 'msg' ) {
26
+ model = msg[ config.model ]
27
+ } else if( node.modelType === 'flow' ) {
28
+ model = node.context().flow.get( config.model )
29
+ } else if( node.modelType === 'global' ) {
30
+ model = node.context().global.get( config.model )
31
+ }
32
+ }
33
+
34
+ let input = null
35
+ if( msg?.payload?.input ) {
36
+ input = msg?.payload?.input
37
+ } else if( !!config.input ) {
38
+ if( node.inputType === 'str' ) {
39
+ input = config.input
40
+ } else if( node.inputType === 'msg' ) {
41
+ input = msg[ config.input ]
42
+ } else if( node.inputType === 'flow' ) {
43
+ input = node.context().flow.get( config.input )
44
+ } else if( node.inputType === 'global' ) {
45
+ input = node.context().global.get( config.input )
46
+ } else if( node.inputType === 'json' ) {
47
+ input = JSON.parse( config.input )
48
+ }
49
+ }
50
+
51
+ const truncate = ( msg?.payload?.truncate !== undefined ) ? msg?.payload?.truncate : node.truncate
52
+
53
+ let keep_alive = null
54
+ if( msg?.payload?.keep_alive ) {
55
+ keep_alive = msg?.payload?.keep_alive
56
+ } else if( !!config.keepAlive ) {
57
+ if( node.keepAliveType === 'str' ) {
58
+ keep_alive = config.keepAlive
59
+ } else if( node.keepAliveType === 'num' ) {
60
+ keep_alive = Number( config.keepAlive )
61
+ }
62
+ }
25
63
 
26
64
  const optionsConfig = RED.nodes.getNode( config.options )
27
- const options = ( optionsConfig ) ? optionsConfig.json : payloadOptions
65
+ const options = msg?.payload?.options || ( optionsConfig ) ? JSON.parse( optionsConfig.json ) : null
28
66
 
29
67
  const response = await ollama.embed( {
30
68
  model,