darabos commited on
Commit
dc3ebef
·
1 Parent(s): 9b4d818

Start adding LLM logic boxes. Nicer tables.

Browse files
server/llm_ops.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ '''For specifying an LLM agent logic flow.'''
2
+ from . import ops
3
+ import json
4
+ import openai
5
+ import pandas as pd
6
+
7
+ client = openai.OpenAI(base_url="http://localhost:11434/v1")
8
+ CACHE = {}
9
+
10
+ def chat(*args, **kwargs):
11
+ key = json.dumps({'args': args, 'kwargs': kwargs})
12
+ if key not in CACHE:
13
+ completion = client.chat.completions.create(*args, **kwargs)
14
+ CACHE[key] = [c.message.content for c in completion.choices]
15
+ return CACHE[key]
16
+
17
+ @ops.op("Input")
18
+ def input(*, filename: str, key: str):
19
+ return pd.read_csv(filename).rename(columns={key: 'text'})
20
+
21
+ @ops.op("Create prompt")
22
+ def create_prompt(input, *, template: str):
23
+ assert template, 'Please specify the template. Refer to columns using their names in uppercase.'
24
+ df = input.copy()
25
+ prompts = []
26
+ for i, row in df.iterrows():
27
+ p = template
28
+ for c in df.columns:
29
+ p = p.replace(c.upper(), str(row[c]))
30
+ prompts.append(p)
31
+ df['prompt'] = p
32
+ return df
33
+
34
+
35
+ @ops.op("Ask LLM")
36
+ def ask_llm(input, *, model: str, choices: list = None, max_tokens: int = 100):
37
+ assert model, 'Please specify the model.'
38
+ assert 'prompt' in input.columns, 'Please create the prompt first.'
39
+ df = input.copy()
40
+ g = {}
41
+ if choices:
42
+ g['extra_body'] = {
43
+ "guided_choice": choices.split()
44
+ }
45
+ for i, row in df.iterrows():
46
+ [res] = chat(
47
+ model=model,
48
+ max_tokens=max_tokens,
49
+ messages=[
50
+ {"role": "user", "content": row['text']},
51
+ ],
52
+ **g,
53
+ )
54
+ df.loc[i, 'response'] = res
55
+ return df
56
+
57
+ @ops.op("View", view="table_view")
58
+ def view(input):
59
+ v = {
60
+ 'dataframes': { 'df': {
61
+ 'columns': [str(c) for c in input.columns],
62
+ 'data': input.values.tolist(),
63
+ }}
64
+ }
65
+ return v
server/main.py CHANGED
@@ -5,8 +5,9 @@ from . import ops
5
  from . import workspace
6
  from . import lynxkite_ops
7
  # from . import networkx_ops
8
- from . import pytorch_model_ops
9
  # from . import lynxscribe_ops
 
10
 
11
  app = fastapi.FastAPI()
12
 
 
5
  from . import workspace
6
  from . import lynxkite_ops
7
  # from . import networkx_ops
8
+ # from . import pytorch_model_ops
9
  # from . import lynxscribe_ops
10
+ from . import llm_ops
11
 
12
  app = fastapi.FastAPI()
13
 
web/src/NodeParameter.svelte CHANGED
@@ -38,9 +38,7 @@
38
  font-size: 10px;
39
  letter-spacing: 0.05em;
40
  margin-left: 10px;
41
- background: oklch(50% 0.13 230);
42
- background: oklch(95% 0.2 55);
43
- background:var(--bs-border-color);
44
  width: fit-content;
45
  padding: 2px 8px;
46
  border-radius: 4px 4px 0 0;
 
38
  font-size: 10px;
39
  letter-spacing: 0.05em;
40
  margin-left: 10px;
41
+ background: var(--bs-border-color);
 
 
42
  width: fit-content;
43
  padding: 2px 8px;
44
  border-radius: 4px 4px 0 0;
web/src/NodeSearch.svelte CHANGED
@@ -8,7 +8,7 @@
8
  let hits = Object.values(boxes).map(box => ({item: box}));
9
  let selectedIndex = 0;
10
  onMount(() => searchBox.focus());
11
- $: fuse = new Fuse(boxes, {
12
  keys: ['name']
13
  })
14
  function onInput() {
 
8
  let hits = Object.values(boxes).map(box => ({item: box}));
9
  let selectedIndex = 0;
10
  onMount(() => searchBox.focus());
11
+ $: fuse = new Fuse(Object.values(boxes), {
12
  keys: ['name']
13
  })
14
  function onInput() {
web/src/NodeWithTableView.svelte CHANGED
@@ -1,29 +1,35 @@
1
  <script lang="ts">
2
  import { type NodeProps } from '@xyflow/svelte';
 
3
  import LynxKiteNode from './LynxKiteNode.svelte';
4
  type $$Props = NodeProps;
5
  export let data: $$Props['data'];
6
  const open = {};
 
7
  </script>
8
 
9
  <LynxKiteNode {...$$props}>
10
  {#if data.view}
11
  {#each Object.entries(data.view.dataframes) as [name, df]}
12
- <div class="df-head" on:click={() => open[name] = !open[name]}>{name}</div>
13
- {#if open[name]}
14
- <table>
15
- <tr>
16
- {#each df.columns as column}
17
- <th>{column}</th>
18
- {/each}
19
- </tr>
20
- {#each df.data as row}
21
  <tr>
22
- {#each row as cell}
23
- <td>{cell}</td>
24
  {/each}
25
  </tr>
26
- {/each}
 
 
 
 
 
 
 
 
 
27
  </table>
28
  {/if}
29
  {/each}
@@ -43,7 +49,6 @@
43
  cursor: pointer;
44
  }
45
  table {
46
- margin: 8px;
47
- border-collapse: collapse;
48
  }
49
  </style>
 
1
  <script lang="ts">
2
  import { type NodeProps } from '@xyflow/svelte';
3
+ import { Tabulator } from 'tabulator-tables';
4
  import LynxKiteNode from './LynxKiteNode.svelte';
5
  type $$Props = NodeProps;
6
  export let data: $$Props['data'];
7
  const open = {};
8
+ $: single = data.view?.dataframes && Object.keys(data.view.dataframes).length === 1;
9
  </script>
10
 
11
  <LynxKiteNode {...$$props}>
12
  {#if data.view}
13
  {#each Object.entries(data.view.dataframes) as [name, df]}
14
+ {#if !single}<div class="df-head" on:click={() => open[name] = !open[name]}>{name}</div>{/if}
15
+ {#if single || open[name]}
16
+ <table class="table table-striped">
17
+ <thead>
 
 
 
 
 
18
  <tr>
19
+ {#each df.columns as column}
20
+ <th>{column}</th>
21
  {/each}
22
  </tr>
23
+ </thead>
24
+ <tbody>
25
+ {#each df.data as row}
26
+ <tr>
27
+ {#each row as cell}
28
+ <td><div class="text-truncate">{cell}</div></td>
29
+ {/each}
30
+ </tr>
31
+ {/each}
32
+ </tbody>
33
  </table>
34
  {/if}
35
  {/each}
 
49
  cursor: pointer;
50
  }
51
  table {
52
+ table-layout: fixed;
 
53
  }
54
  </style>