darabos commited on
Commit
a06b506
·
1 Parent(s): bc2b550

Flexible inputs!

Browse files
server/lynxscribe_ops.py CHANGED
@@ -11,4 +11,4 @@ register_passive_op('WhatsApp', inputs={})
11
  register_passive_op('PII removal')
12
  register_passive_op('Intent classification')
13
  register_passive_op('System prompt', inputs={}, params=[P('prompt', 'You are a heplful chatbot.')])
14
- register_passive_op('LLM', params=[P('model', 'gpt4')])
 
11
  register_passive_op('PII removal')
12
  register_passive_op('Intent classification')
13
  register_passive_op('System prompt', inputs={}, params=[P('prompt', 'You are a heplful chatbot.')])
14
+ register_passive_op('LLM', inputs={'multi': '*'}, params=[P('model', 'gpt4')])
server/main.py CHANGED
@@ -28,7 +28,7 @@ def save(req: SaveRequest):
28
  @app.post("/api/save")
29
  def save_and_execute(req: SaveRequest):
30
  save(req)
31
- execute(req.ws)
32
  save(req)
33
  return req.ws
34
 
 
28
  @app.post("/api/save")
29
  def save_and_execute(req: SaveRequest):
30
  save(req)
31
+ workspace.execute(req.ws)
32
  save(req)
33
  return req.ws
34
 
server/ops.py CHANGED
@@ -57,9 +57,12 @@ class Op:
57
  def to_json(self):
58
  return {
59
  'type': self.type,
60
- 'data': { 'title': self.name, 'params': [p.to_json() for p in self.params.values()] },
61
- 'targetPosition': 'left' if self.inputs else None,
62
- 'sourcePosition': 'right' if self.outputs else None,
 
 
 
63
  'sub_nodes': [sub.to_json() for sub in self.sub_nodes.values()] if self.sub_nodes else None,
64
  }
65
 
 
57
  def to_json(self):
58
  return {
59
  'type': self.type,
60
+ 'data': {
61
+ 'title': self.name,
62
+ 'inputs': {i: str(type) for i, type in self.inputs.items()},
63
+ 'outputs': {o: str(type) for o, type in self.outputs.items()},
64
+ 'params': [p.to_json() for p in self.params.values()],
65
+ },
66
  'sub_nodes': [sub.to_json() for sub in self.sub_nodes.values()] if self.sub_nodes else None,
67
  }
68
 
server/workspace.py CHANGED
@@ -71,6 +71,9 @@ def execute(ws):
71
  data.error = str(e)
72
  failed += 1
73
  continue
 
 
 
74
  data.error = None
75
  outputs[node.id] = output
76
  if op.type == 'graph_view' or op.type == 'table_view':
 
71
  data.error = str(e)
72
  failed += 1
73
  continue
74
+ if len(op.inputs) == 1 and op.inputs.get('multi') == '*':
75
+ # It's a flexible input. Create n+1 handles.
76
+ data.inputs = {f'input{i}': None for i in range(len(inputs) + 1)}
77
  data.error = None
78
  outputs[node.id] = output
79
  if op.type == 'graph_view' or op.type == 'table_view':
web/index.html CHANGED
@@ -2,7 +2,7 @@
2
  <html lang="en">
3
  <head>
4
  <meta charset="UTF-8" />
5
- <link rel="icon" type="image/png" href="/public/favicon.ico" />
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
  <title>LynxKite 2024</title>
8
  </head>
 
2
  <html lang="en">
3
  <head>
4
  <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/png" href="/favicon.ico" />
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
  <title>LynxKite 2024</title>
8
  </head>
web/src/LynxKiteFlow.svelte CHANGED
@@ -133,7 +133,10 @@
133
  function onconnect(connection: Connection) {
134
  edges.update((edges) => {
135
  // Only one source can connect to a given target.
136
- return edges.filter((e) => e.source === connection.source || e.target !== connection.target);
 
 
 
137
  });
138
  }
139
  function nodeClick(e) {
 
133
  function onconnect(connection: Connection) {
134
  edges.update((edges) => {
135
  // Only one source can connect to a given target.
136
+ return edges.filter((e) =>
137
+ e.source === connection.source
138
+ || e.target !== connection.target
139
+ || e.targetHandle !== connection.targetHandle);
140
  });
141
  }
142
  function nodeClick(e) {
web/src/LynxKiteNode.svelte CHANGED
@@ -29,6 +29,9 @@
29
  function asPx(n: number) {
30
  return n ? n + 'px' : undefined;
31
  }
 
 
 
32
  </script>
33
 
34
  <div class="node-container" style:width={asPx(width)} style:height={asPx(height)} style={containerStyle}>
@@ -43,12 +46,16 @@
43
  {/if}
44
  <slot />
45
  {/if}
46
- {#if sourcePosition}
47
- <Handle type="source" position={sourcePosition} />
48
- {/if}
49
- {#if targetPosition}
50
- <Handle type="target" position={targetPosition} />
51
- {/if}
 
 
 
 
52
  </div>
53
  </div>
54
 
 
29
  function asPx(n: number) {
30
  return n ? n + 'px' : undefined;
31
  }
32
+ $: inputs = Object.entries(data.inputs || {});
33
+ $: outputs = Object.entries(data.outputs || {});
34
+ const handleOffsetDirection = { top: 'left', bottom: 'left', left: 'top', right: 'top' };
35
  </script>
36
 
37
  <div class="node-container" style:width={asPx(width)} style:height={asPx(height)} style={containerStyle}>
 
46
  {/if}
47
  <slot />
48
  {/if}
49
+ {#each inputs as [name, input], i}
50
+ <Handle
51
+ id={name} type="target" position={targetPosition || 'left'}
52
+ style="{handleOffsetDirection[targetPosition || 'left']}: {100 * (i + 1) / (inputs.length + 1)}%" />
53
+ {/each}
54
+ {#each outputs as [name, output], i}
55
+ <Handle
56
+ id={name} type="source" position={sourcePosition || 'right'}
57
+ style="{handleOffsetDirection[sourcePosition || 'right']}: {100 * (i + 1) / (outputs.length + 1)}%" />
58
+ {/each}
59
  </div>
60
  </div>
61
 
web/src/Workspace.svelte CHANGED
@@ -52,7 +52,8 @@
52
  align-items: center;
53
  }
54
  .tools a {
55
- color: white;
56
  font-size: 1.5em;
 
57
  }
58
  </style>
 
52
  align-items: center;
53
  }
54
  .tools a {
55
+ color: #39bcf3;
56
  font-size: 1.5em;
57
+ padding: 0 10px;
58
  }
59
  </style>