node-red-contrib-ollama 0.2.5 → 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.
@@ -3,25 +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
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
+ }
63
+
64
+ const optionsConfig = RED.nodes.getNode( config.options )
65
+ const options = msg?.payload?.options || ( optionsConfig ) ? JSON.parse( optionsConfig.json ) : null
25
66
 
26
67
  const response = await ollama.embed( {
27
68
  model,
@@ -6,7 +6,23 @@
6
6
  name: { value: 'Ollama Generate' },
7
7
  server: { value: '', type: 'ollama-config-server', required: false },
8
8
  format: { value: '', type: 'ollama-config-format', required: false },
9
- model: { value: '', type: 'ollama-config-model', required: false },
9
+ model: { value: '', required: false },
10
+ modelType: { value: 'str', required: false },
11
+ prompt: { value: '', required: true },
12
+ promptType: { value: 'str', required: false },
13
+ suffix: { value: '', required: false },
14
+ suffixType: { value: 'str', required: false },
15
+ system: { value: '', required: false },
16
+ systemType: { value: 'str', required: false },
17
+ template: { value: '', required: false },
18
+ templateType: { value: 'str', required: false },
19
+ raw: { value: false },
20
+ images: { value: '', required: false },
21
+ imagesType: { value: 'json', required: false },
22
+ stream: { value: false },
23
+ keepAlive: { value: '5m', required: false },
24
+ keepAliveType: { value: 'str', required: false },
25
+ options: { value: '', type: 'ollama-config-options', required: false },
10
26
  },
11
27
  inputs: 1,
12
28
  outputs: 1,
@@ -14,6 +30,77 @@
14
30
  label: function() {
15
31
  return this.name || 'ollama-generate';
16
32
  },
33
+ oneditprepare: function() {
34
+ if( !this.modelType ) {
35
+ this.modelType = 'str'
36
+ }
37
+
38
+ $( '#node-input-model' ).typedInput( {
39
+ type: 'str',
40
+ types: [ 'str', 'msg', 'flow', 'global' ],
41
+ typeField: '#node-input-modelType'
42
+ } )
43
+
44
+ if( !this.promptType ) {
45
+ this.promptType = 'str'
46
+ }
47
+
48
+ $( '#node-input-prompt' ).typedInput( {
49
+ type: 'str',
50
+ types: [ 'str', 'msg', 'flow', 'global' ],
51
+ typeField: '#node-input-promptType'
52
+ } )
53
+
54
+ if( !this.suffixType ) {
55
+ this.suffixType = 'str'
56
+ }
57
+
58
+ $( '#node-input-suffix' ).typedInput( {
59
+ type: 'str',
60
+ types: [ 'str', 'msg', 'flow', 'global' ],
61
+ typeField: '#node-input-suffixType'
62
+ } )
63
+
64
+ if( !this.systemType ) {
65
+ this.systemType = 'str'
66
+ }
67
+
68
+ $( '#node-input-system' ).typedInput( {
69
+ type: 'str',
70
+ types: [ 'str', 'msg', 'flow', 'global' ],
71
+ typeField: '#node-input-systemType'
72
+ } )
73
+
74
+ if( !this.templateType ) {
75
+ this.templateType = 'str'
76
+ }
77
+
78
+ $( '#node-input-template' ).typedInput( {
79
+ type: 'str',
80
+ types: [ 'str', 'msg', 'flow', 'global' ],
81
+ typeField: '#node-input-templateType'
82
+ } )
83
+
84
+ if( !this.imagesType ) {
85
+ this.imagesType = 'json'
86
+ }
87
+
88
+ $( '#node-input-images' ).typedInput( {
89
+ type: 'json',
90
+ types: [ 'json', 'msg', 'flow', 'global' ],
91
+ typeField: '#node-input-imagesType'
92
+ } )
93
+
94
+ if( !this.keepAliveType ) {
95
+ this.keepAliveType = 'str'
96
+ }
97
+
98
+ $( '#node-input-keepAlive' ).typedInput( {
99
+ type: 'str',
100
+ types: [ 'str', 'num' ],
101
+ typeField: '#node-input-keepAliveType'
102
+ } )
103
+ }
17
104
  } )
18
105
  </script>
19
106
 
@@ -34,8 +121,60 @@
34
121
  </div>
35
122
 
36
123
  <div class="form-row">
37
- <label for="node-input-model"><i class="fa fa-bookmark"></i> Model</label>
124
+ <label for="node-input-model"><i class="fa fa-comment"></i> Model</label>
38
125
  <input type="text" id="node-input-model" />
126
+ <input type="hidden" id="node-input-modelType" />
127
+ </div>
128
+
129
+ <div class="form-row">
130
+ <label for="node-input-prompt"><i class="fa fa-comment"></i> Prompt</label>
131
+ <input type="text" id="node-input-prompt" />
132
+ <input type="hidden" id="node-input-promptType" />
133
+ </div>
134
+
135
+ <div class="form-row">
136
+ <label for="node-input-suffix"><i class="fa fa-comment"></i> Suffix</label>
137
+ <input type="text" id="node-input-suffix" />
138
+ <input type="hidden" id="node-input-suffixType" />
139
+ </div>
140
+
141
+ <div class="form-row">
142
+ <label for="node-input-system"><i class="fa fa-cog"></i> System</label>
143
+ <input type="text" id="node-input-system" />
144
+ <input type="hidden" id="node-input-systemType" />
145
+ </div>
146
+
147
+ <div class="form-row">
148
+ <label for="node-input-template"><i class="fa fa-cog"></i> Template</label>
149
+ <input type="text" id="node-input-template" />
150
+ <input type="hidden" id="node-input-templateType" />
151
+ </div>
152
+
153
+ <div class="form-row">
154
+ <label for="node-input-raw"><i class="fa fa-cog"></i> Raw</label>
155
+ <input type="checkbox" id="node-input-raw" />
156
+ </div>
157
+
158
+ <div class="form-row">
159
+ <label for="node-input-images"><i class="fa fa-cog"></i> Images</label>
160
+ <input type="text" id="node-input-images" />
161
+ <input type="hidden" id="node-input-imagesType" />
162
+ </div>
163
+
164
+ <div class="form-row">
165
+ <label for="node-input-stream"><i class="fa fa-cog"></i> Stream</label>
166
+ <input type="checkbox" id="node-input-stream" />
167
+ </div>
168
+
169
+ <div class="form-row">
170
+ <label for="node-input-keepAlive"><i class="fa fa-cog"></i> Keep Alive</label>
171
+ <input type="text" id="node-input-keepAlive" />
172
+ <input type="hidden" id="node-input-keepAliveType" />
173
+ </div>
174
+
175
+ <div class="form-row">
176
+ <label for="node-input-options"><i class="fa fa-cog"></i> Options</label>
177
+ <input type="text" id="node-input-options" />
39
178
  </div>
40
179
  </script>
41
180
 
@@ -50,31 +189,26 @@
50
189
  </dt>
51
190
 
52
191
  <dd>
53
- The payload object.
192
+ The payload object is an alternative way to configure the node.<br />
193
+ Any properties in the payload object will override the node configuration.
54
194
 
55
195
  <dl class="message-properties">
56
196
  <dt class="optional">
57
197
  payload.host <span class="property-type">string</span>
58
198
  </dt>
59
- <dd>
60
- The host of the Ollama instance.<br />
61
- <em>Alternative to the <code>Server</code> field.</em>
62
- </dd>
199
+ <dd>The host of the Ollama instance.</dd>
63
200
 
64
201
  <dt class="optional">
65
202
  payload.model <span class="property-type">string</span>
66
203
  </dt>
67
- <dd>
68
- The model to use for generating the next message.<br />
69
- <em>Alternative to the <code>Model</code> field.</em>
70
- </dd>
204
+ <dd>The model to use for generating the next message.</dd>
71
205
 
72
- <dt>
206
+ <dt class="optional">
73
207
  payload.prompt <span class="property-type">string</span>
74
208
  </dt>
75
209
  <dd>The prompt to generate a response for.</dd>
76
210
 
77
- <dt>
211
+ <dt class="optional">
78
212
  payload.suffix <span class="property-type">string</span>
79
213
  </dt>
80
214
  <dd>The text after the model response.</dd>
@@ -87,17 +221,12 @@
87
221
  <dt class="optional">
88
222
  payload.format <span class="property-type">string</span>
89
223
  </dt>
90
- <dd>
91
- The format to return a response in. Currently the only accepted value is <code>json</code><br />
92
- <em>Alternative to the <code>Format</code> field.</em>
93
- </dd>
224
+ <dd>The format to return a response in. Currently the only accepted value is <code>json</code></dd>
94
225
 
95
226
  <dt class="optional">
96
227
  payload.options <span class="property-type">object</span>
97
228
  </dt>
98
- <dd>
99
- Additional model parameters listed in the documentation for the <a href="https://github.com/ollama/ollama/blob/main/docs/modelfile.md#valid-parameters-and-values">Modelfile</a>.
100
- </dd>
229
+ <dd>Additional model parameters listed in the documentation for the <a href="https://github.com/ollama/ollama/blob/main/docs/modelfile.md#valid-parameters-and-values">Modelfile</a>.</dd>
101
230
 
102
231
  <dt class="optional">
103
232
  payload.system <span class="property-type">string</span>
@@ -3,34 +3,134 @@ module.exports = function( RED ) {
3
3
 
4
4
  function OllamaGenerateNode( 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
- prompt,
13
- suffix,
14
- system,
15
- template,
16
- raw,
17
- images,
18
- format: payloadFormat,
19
- stream,
20
- keep_alive,
21
- options
22
- } = msg.payload
7
+ this.modelType = config.modelType || 'str'
8
+ this.promptType = config.promptType || 'str'
9
+ this.suffixType = config.suffixType || 'str'
10
+ this.systemType = config.systemType || 'str'
11
+ this.templateType = config.templateType || 'str'
12
+ this.raw = config.raw || false
13
+ this.imagesType = config.imagesType || 'json'
14
+ this.stream = config.stream || false
15
+ this.keepAliveType = config.keepAliveType || 'str'
23
16
 
17
+ const node = this
18
+ node.on( 'input', async function( msg ) {
24
19
  const server = RED.nodes.getNode( config.server )
25
- const host = ( server ) ? server.host + ':' + server.port : payloadHost
20
+ const host = msg?.payload?.host || ( server ) ? server.host + ':' + server.port : null
26
21
 
27
22
  const ollama = new Ollama( { host } )
28
23
 
29
- const modelConfig = RED.nodes.getNode( config.model )
30
- const model = ( modelConfig ) ? modelConfig.name : payloadModel
24
+ let model = null
25
+ if( msg?.payload?.model ) {
26
+ model = msg?.payload?.model
27
+ } else if( !!config.model ) {
28
+ if( node.modelType === 'str' ) {
29
+ model = config.model
30
+ } else if( node.modelType === 'msg' ) {
31
+ model = msg[ config.model ]
32
+ } else if( node.modelType === 'flow' ) {
33
+ model = node.context().flow.get( config.model )
34
+ } else if( node.modelType === 'global' ) {
35
+ model = node.context().global.get( config.model )
36
+ }
37
+ }
38
+
39
+ let prompt = null
40
+ if( msg?.payload?.prompt ) {
41
+ prompt = msg?.payload?.prompt
42
+ } else if( !!config.prompt ) {
43
+ if( node.promptType === 'str' ) {
44
+ prompt = config.prompt
45
+ } else if( node.promptType === 'msg' ) {
46
+ prompt = msg[ config.prompt ]
47
+ } else if( node.promptType === 'flow' ) {
48
+ prompt = node.context().flow.get( config.prompt )
49
+ } else if( node.promptType === 'global' ) {
50
+ prompt = node.context().global.get( config.prompt )
51
+ }
52
+ }
53
+
54
+ let suffix = null
55
+ if( msg?.payload?.suffix ) {
56
+ suffix = msg?.payload?.suffix
57
+ } else if( !!config.suffix ) {
58
+ if( node.suffixType === 'str' ) {
59
+ suffix = config.suffix
60
+ } else if( node.suffixType === 'msg' ) {
61
+ suffix = msg[ config.suffix ]
62
+ } else if( node.suffixType === 'flow' ) {
63
+ suffix = node.context().flow.get( config.suffix )
64
+ } else if( node.suffixType === 'global' ) {
65
+ suffix = node.context().global.get( config.suffix )
66
+ }
67
+ }
68
+
69
+ let system = null
70
+ if( msg?.payload?.system ) {
71
+ system = msg?.payload?.system
72
+ } else if( !!config.system ) {
73
+ if( node.systemType === 'str' ) {
74
+ system = config.system
75
+ } else if( node.systemType === 'msg' ) {
76
+ system = msg[ config.system ]
77
+ } else if( node.systemType === 'flow' ) {
78
+ system = node.context().flow.get( config.system )
79
+ } else if( node.systemType === 'global' ) {
80
+ system = node.context().global.get( config.system )
81
+ }
82
+ }
83
+
84
+ let template = null
85
+ if( msg?.payload?.template ) {
86
+ template = msg?.payload?.template
87
+ } else if( !!config.template ) {
88
+ if( node.templateType === 'str' ) {
89
+ template = config.template
90
+ } else if( node.templateType === 'msg' ) {
91
+ template = msg[ config.template ]
92
+ } else if( node.templateType === 'flow' ) {
93
+ template = node.context().flow.get( config.template )
94
+ } else if( node.templateType === 'global' ) {
95
+ template = node.context().global.get( config.template )
96
+ }
97
+ }
98
+
99
+ const raw = ( msg?.payload?.raw !== undefined ) ? msg?.payload?.raw : node.raw
100
+
101
+ let images = null
102
+ if( msg?.payload?.images ) {
103
+ images = msg?.payload?.images
104
+ } else if( !!config.images ) {
105
+ if( node.imagesType === 'json' ) {
106
+ images = JSON.parse( config.images )
107
+ } else if( node.imagesType === 'msg' ) {
108
+ images = msg[ config.images ]
109
+ } else if( node.imagesType === 'flow' ) {
110
+ images = node.context().flow.get( config.images )
111
+ } else if( node.imagesType === 'global' ) {
112
+ images = node.context().global.get( config.images )
113
+ }
114
+ }
31
115
 
32
116
  const formatConfig = RED.nodes.getNode( config.format )
33
- const format = ( formatConfig ) ? formatConfig.json : payloadFormat
117
+ const format = msg?.payload?.format || ( formatConfig ) ? formatConfig.json : null
118
+
119
+ const stream = ( msg?.payload?.stream !== undefined ) ? msg?.payload?.stream : node.stream
120
+
121
+ let keep_alive = null
122
+ if( msg?.payload?.keep_alive ) {
123
+ keep_alive = msg?.payload?.keep_alive
124
+ } else if( !!config.keepAlive ) {
125
+ if( node.keepAliveType === 'str' ) {
126
+ keep_alive = config.keepAlive
127
+ } else if( node.keepAliveType === 'num' ) {
128
+ keep_alive = Number( config.keepAlive )
129
+ }
130
+ }
131
+
132
+ const optionsConfig = RED.nodes.getNode( config.options )
133
+ const options = msg?.payload?.options || ( optionsConfig ) ? JSON.parse( optionsConfig.json ) : null
34
134
 
35
135
  const response = await ollama.generate( {
36
136
  model,
@@ -38,16 +38,14 @@
38
38
  </dt>
39
39
 
40
40
  <dd>
41
- The payload object.
41
+ The payload object is an alternative way to configure the node.<br />
42
+ Any properties in the payload object will override the node configuration.
42
43
 
43
44
  <dl class="message-properties">
44
45
  <dt class="optional">
45
46
  payload.host <span class="property-type">string</span>
46
47
  </dt>
47
- <dd>
48
- The host of the Ollama instance.<br />
49
- <em>Alternative to the <code>Server</code> field.</em>
50
- </dd>
48
+ <dd>The host of the Ollama instance.</dd>
51
49
  </dl>
52
50
  </dd>
53
51
  </dl>
@@ -6,13 +6,9 @@ module.exports = function( RED ) {
6
6
  const node = this
7
7
 
8
8
  node.on( 'input', async function( msg ) {
9
- const {
10
- host: payloadHost
11
- } = msg.payload
12
-
13
9
  const server = RED.nodes.getNode( config.server )
14
10
 
15
- const host = ( server ) ? server.host + ':' + server.port : payloadHost
11
+ const host = msg?.payload?.host || ( server ) ? server.host + ':' + server.port : null
16
12
 
17
13
  const ollama = new Ollama( { host } )
18
14
 
@@ -38,16 +38,14 @@
38
38
  </dt>
39
39
 
40
40
  <dd>
41
- The payload object.
41
+ The payload object is an alternative way to configure the node.<br />
42
+ Any properties in the payload object will override the node configuration.
42
43
 
43
44
  <dl class="message-properties">
44
45
  <dt class="optional">
45
46
  payload.host <span class="property-type">string</span>
46
47
  </dt>
47
- <dd>
48
- The host of the Ollama instance.<br />
49
- <em>Alternative to the <code>Server</code> field.</em>
50
- </dd>
48
+ <dd>The host of the Ollama instance.</dd>
51
49
  </dl>
52
50
  </dd>
53
51
  </dl>
@@ -6,13 +6,9 @@ module.exports = function( RED ) {
6
6
  const node = this
7
7
 
8
8
  node.on( 'input', async function( msg ) {
9
- const {
10
- host: payloadHost
11
- } = msg.payload
12
-
13
9
  const server = RED.nodes.getNode( config.server )
14
10
 
15
- const host = ( server ) ? server.host + ':' + server.port : payloadHost
11
+ const host = msg?.payload?.host || ( server ) ? server.host + ':' + server.port : null
16
12
 
17
13
  const ollama = new Ollama( { host } )
18
14
 
@@ -5,7 +5,10 @@
5
5
  defaults: {
6
6
  name: { value: 'Ollama Pull' },
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
+ insecure: { value: false },
11
+ stream: { value: false },
9
12
  },
10
13
  inputs: 1,
11
14
  outputs: 1,
@@ -13,6 +16,17 @@
13
16
  label: function() {
14
17
  return this.name || 'ollama-pull';
15
18
  },
19
+ oneditprepare: function() {
20
+ if( !this.modelType ) {
21
+ this.modelType = 'str'
22
+ }
23
+
24
+ $( '#node-input-model' ).typedInput( {
25
+ type: 'str',
26
+ types: [ 'str', 'msg', 'flow', 'global' ],
27
+ typeField: '#node-input-modelType'
28
+ } )
29
+ }
16
30
  } )
17
31
  </script>
18
32
 
@@ -28,8 +42,19 @@
28
42
  </div>
29
43
 
30
44
  <div class="form-row">
31
- <label for="node-input-model"><i class="fa fa-bookmark"></i> Model</label>
45
+ <label for="node-input-model"><i class="fa fa-comment"></i> Model</label>
32
46
  <input type="text" id="node-input-model" />
47
+ <input type="hidden" id="node-input-modelType" />
48
+ </div>
49
+
50
+ <div class="form-row">
51
+ <label for="node-input-insecure"><i class="fa fa-lock"></i> Insecure</label>
52
+ <input type="checkbox" id="node-input-insecure" />
53
+ </div>
54
+
55
+ <div class="form-row">
56
+ <label for="node-input-stream"><i class="fa fa-cog"></i> Stream</label>
57
+ <input type="checkbox" id="node-input-stream" />
33
58
  </div>
34
59
  </script>
35
60
 
@@ -44,31 +69,26 @@
44
69
  </dt>
45
70
 
46
71
  <dd>
47
- The payload object.
72
+ The payload object is an alternative way to configure the node.<br />
73
+ Any properties in the payload object will override the node configuration.
48
74
 
49
75
  <dl class="message-properties">
50
76
  <dt class="optional">
51
77
  payload.host <span class="property-type">string</span>
52
78
  </dt>
53
- <dd>
54
- The host of the Ollama instance.<br />
55
- <em>Alternative to the <code>Server</code> field.</em>
56
- </dd>
79
+ <dd>The host of the Ollama instance.</dd>
57
80
 
58
81
  <dt class="optional">
59
82
  payload.model <span class="property-type">string</span>
60
83
  </dt>
61
- <dd>
62
- The name of the model to download.<br />
63
- <em>Alternative to the <code>Model</code> field.</em>
64
- </dd>
84
+ <dd>The name of the model to download.</dd>
65
85
 
66
- <dt>
86
+ <dt class="optional">
67
87
  payload.insecure <span class="property-type">boolean</span>
68
88
  </dt>
69
89
  <dd>Pull from servers whose identity cannot be verified.</dd>
70
90
 
71
- <dt>
91
+ <dt class="optional">
72
92
  payload.stream <span class="property-type">boolean</span>
73
93
  </dt>
74
94
  <dd>When true an AsyncGenerator is returned.</dd>
@@ -3,23 +3,36 @@ module.exports = function( RED ) {
3
3
 
4
4
  function OllamaPulltNode( 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
- insecure,
13
- stream
14
- } = msg.payload
7
+ this.modelType = config.modelType || 'str'
8
+ this.insecure = config.insecure || false
9
+ this.stream = config.stream || false
15
10
 
11
+ const node = this
12
+ node.on( 'input', async function( msg ) {
16
13
  const server = RED.nodes.getNode( config.server )
17
- const host = ( server ) ? server.host + ':' + server.port : payloadHost
14
+ const host = msg?.payload?.host || ( server ) ? server.host + ':' + server.port : null
18
15
 
19
16
  const ollama = new Ollama( { host } )
20
17
 
21
- const modelConfig = RED.nodes.getNode( config.model )
22
- 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 insecure = ( msg?.payload?.insecure !== undefined ) ? msg?.payload?.insecure : node.insecure
34
+
35
+ const stream = ( msg?.payload?.stream !== undefined ) ? msg?.payload?.stream : node.stream
23
36
 
24
37
  const response = await ollama.pull( {
25
38
  model,