darabos commited on
Commit
57f808e
·
1 Parent(s): 956034e

ChatAPI and TaskSolver serving from LynxKite.

Browse files
examples/LynxScribe/ChatAPI/Demo.lynxkite.json ADDED
@@ -0,0 +1,1230 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "edges": [
3
+ {
4
+ "id": "MCP: Search web 1 output Agent 1 tools",
5
+ "source": "MCP: Search web 1",
6
+ "sourceHandle": "output",
7
+ "target": "Agent 1",
8
+ "targetHandle": "tools"
9
+ },
10
+ {
11
+ "id": "Agent 1 output Agent 2 tools",
12
+ "source": "Agent 1",
13
+ "sourceHandle": "output",
14
+ "target": "Agent 2",
15
+ "targetHandle": "tools"
16
+ },
17
+ {
18
+ "id": "Database 1 output MCP: Query database with SQL 2 db",
19
+ "source": "Database 1",
20
+ "sourceHandle": "output",
21
+ "target": "MCP: Query database with SQL 2",
22
+ "targetHandle": "db"
23
+ },
24
+ {
25
+ "id": "MCP: Query database with SQL 2 output Agent 1 tools",
26
+ "source": "MCP: Query database with SQL 2",
27
+ "sourceHandle": "output",
28
+ "target": "Agent 1",
29
+ "targetHandle": "tools"
30
+ },
31
+ {
32
+ "id": "Agent 3 output Agent 2 tools",
33
+ "source": "Agent 3",
34
+ "sourceHandle": "output",
35
+ "target": "Agent 2",
36
+ "targetHandle": "tools"
37
+ },
38
+ {
39
+ "id": "MCP: Calculator 1 output Agent 1 tools",
40
+ "source": "MCP: Calculator 1",
41
+ "sourceHandle": "output",
42
+ "target": "Agent 1",
43
+ "targetHandle": "tools"
44
+ },
45
+ {
46
+ "id": "Agent 2 output Chat frontend 1 agent",
47
+ "source": "Agent 2",
48
+ "sourceHandle": "output",
49
+ "target": "Chat frontend 1",
50
+ "targetHandle": "agent"
51
+ },
52
+ {
53
+ "id": "Ladder graph 1 output PageRank 1 G",
54
+ "source": "Ladder graph 1",
55
+ "sourceHandle": "output",
56
+ "target": "PageRank 1",
57
+ "targetHandle": "G"
58
+ },
59
+ {
60
+ "id": "PageRank 1 output Database 1 data_pipeline",
61
+ "source": "PageRank 1",
62
+ "sourceHandle": "output",
63
+ "target": "Database 1",
64
+ "targetHandle": "data_pipeline"
65
+ },
66
+ {
67
+ "id": "Karate club graph 1 output Common neighbor centrality 1 G",
68
+ "source": "Karate club graph 1",
69
+ "sourceHandle": "output",
70
+ "target": "Common neighbor centrality 1",
71
+ "targetHandle": "G"
72
+ },
73
+ {
74
+ "id": "Common neighbor centrality 1 output Database 1 data_pipeline",
75
+ "source": "Common neighbor centrality 1",
76
+ "sourceHandle": "output",
77
+ "target": "Database 1",
78
+ "targetHandle": "data_pipeline"
79
+ },
80
+ {
81
+ "id": "Import file 1 output SQL 1 bundle",
82
+ "source": "Import file 1",
83
+ "sourceHandle": "output",
84
+ "target": "SQL 1",
85
+ "targetHandle": "bundle"
86
+ },
87
+ {
88
+ "id": "SQL 1 output SQL 2 bundle",
89
+ "source": "SQL 1",
90
+ "sourceHandle": "output",
91
+ "target": "SQL 2",
92
+ "targetHandle": "bundle"
93
+ },
94
+ {
95
+ "id": "SQL 2 output Database 1 data_pipeline",
96
+ "source": "SQL 2",
97
+ "sourceHandle": "output",
98
+ "target": "Database 1",
99
+ "targetHandle": "data_pipeline"
100
+ },
101
+ {
102
+ "id": "MCP: Run ComfyUI workflow 1 output Agent 3 tools",
103
+ "source": "MCP: Run ComfyUI workflow 1",
104
+ "sourceHandle": "output",
105
+ "target": "Agent 3",
106
+ "targetHandle": "tools"
107
+ }
108
+ ],
109
+ "env": "LynxKite Graph Analytics",
110
+ "nodes": [
111
+ {
112
+ "data": {
113
+ "collapsed": true,
114
+ "display": null,
115
+ "error": null,
116
+ "input_metadata": [
117
+ {}
118
+ ],
119
+ "meta": {
120
+ "categories": [
121
+ "Data Science"
122
+ ],
123
+ "color": "orange",
124
+ "doc": null,
125
+ "id": "Data Science > Database",
126
+ "inputs": [
127
+ {
128
+ "name": "data_pipeline",
129
+ "position": "left",
130
+ "type": {
131
+ "type": "list[lynxkite_graph_analytics.core.Bundle]"
132
+ }
133
+ }
134
+ ],
135
+ "name": "Database",
136
+ "outputs": [
137
+ {
138
+ "name": "output",
139
+ "position": "top",
140
+ "type": {
141
+ "type": "None"
142
+ }
143
+ }
144
+ ],
145
+ "params": [],
146
+ "type": "basic"
147
+ },
148
+ "op_id": "Data Science > Database",
149
+ "params": {},
150
+ "status": "done",
151
+ "title": "Database"
152
+ },
153
+ "dragHandle": ".drag-handle",
154
+ "height": 200.0,
155
+ "id": "Database 1",
156
+ "position": {
157
+ "x": -175.8708861292469,
158
+ "y": 465.47762360072204
159
+ },
160
+ "type": "basic",
161
+ "width": 200.0
162
+ },
163
+ {
164
+ "data": {
165
+ "__execution_delay": 0.0,
166
+ "display": null,
167
+ "error": null,
168
+ "input_metadata": [],
169
+ "meta": {
170
+ "categories": [
171
+ "LynxScribe"
172
+ ],
173
+ "color": "green",
174
+ "doc": null,
175
+ "id": "LynxScribe > MCP: Search web",
176
+ "inputs": [],
177
+ "name": "MCP: Search web",
178
+ "outputs": [
179
+ {
180
+ "name": "output",
181
+ "position": "top",
182
+ "type": {
183
+ "type": "None"
184
+ }
185
+ }
186
+ ],
187
+ "params": [
188
+ {
189
+ "default": "Google",
190
+ "name": "engine",
191
+ "type": {
192
+ "enum": [
193
+ "Google",
194
+ "Bing",
195
+ "DuckDuckGo"
196
+ ]
197
+ }
198
+ }
199
+ ],
200
+ "type": "basic"
201
+ },
202
+ "op_id": "LynxScribe > MCP: Search web",
203
+ "params": {
204
+ "engine": "Google"
205
+ },
206
+ "status": "done",
207
+ "title": "MCP: Search web"
208
+ },
209
+ "dragHandle": ".drag-handle",
210
+ "height": 156.0,
211
+ "id": "MCP: Search web 1",
212
+ "position": {
213
+ "x": 183.63527583294598,
214
+ "y": 221.47335161357154
215
+ },
216
+ "type": "basic",
217
+ "width": 204.0
218
+ },
219
+ {
220
+ "data": {
221
+ "__execution_delay": 0.0,
222
+ "display": null,
223
+ "error": null,
224
+ "input_metadata": [
225
+ {}
226
+ ],
227
+ "meta": {
228
+ "categories": [
229
+ "LynxScribe"
230
+ ],
231
+ "color": "blue",
232
+ "doc": null,
233
+ "id": "LynxScribe > Agent",
234
+ "inputs": [
235
+ {
236
+ "name": "tools",
237
+ "position": "bottom",
238
+ "type": {
239
+ "type": "list[str]"
240
+ }
241
+ }
242
+ ],
243
+ "name": "Agent",
244
+ "outputs": [
245
+ {
246
+ "name": "output",
247
+ "position": "top",
248
+ "type": {
249
+ "type": "None"
250
+ }
251
+ }
252
+ ],
253
+ "params": [
254
+ {
255
+ "default": "",
256
+ "name": "purpose",
257
+ "type": {
258
+ "type": "<class 'str'>"
259
+ }
260
+ },
261
+ {
262
+ "default": "This agent help with various tasks.",
263
+ "name": "description",
264
+ "type": {
265
+ "format": "textarea"
266
+ }
267
+ },
268
+ {
269
+ "default": "You are a helpful assistant.",
270
+ "name": "system_prompt",
271
+ "type": {
272
+ "format": "textarea"
273
+ }
274
+ }
275
+ ],
276
+ "type": "basic"
277
+ },
278
+ "op_id": "LynxScribe > Agent",
279
+ "params": {
280
+ "description": "This agent can help with data science\nand analytics questions.",
281
+ "purpose": "Data assistant",
282
+ "system_prompt": "Using the tools at your disposal answer\nall questions in JSON format."
283
+ },
284
+ "status": "done",
285
+ "title": "Agent"
286
+ },
287
+ "dragHandle": ".drag-handle",
288
+ "height": 351.0,
289
+ "id": "Agent 1",
290
+ "position": {
291
+ "x": -55.2832056082014,
292
+ "y": -263.46066732045733
293
+ },
294
+ "type": "basic",
295
+ "width": 337.0
296
+ },
297
+ {
298
+ "data": {
299
+ "__execution_delay": 0.0,
300
+ "display": null,
301
+ "error": null,
302
+ "input_metadata": [
303
+ {}
304
+ ],
305
+ "meta": {
306
+ "categories": [
307
+ "LynxScribe"
308
+ ],
309
+ "color": "blue",
310
+ "doc": null,
311
+ "id": "LynxScribe > Agent",
312
+ "inputs": [
313
+ {
314
+ "name": "tools",
315
+ "position": "bottom",
316
+ "type": {
317
+ "type": "list[str]"
318
+ }
319
+ }
320
+ ],
321
+ "name": "Agent",
322
+ "outputs": [
323
+ {
324
+ "name": "output",
325
+ "position": "top",
326
+ "type": {
327
+ "type": "None"
328
+ }
329
+ }
330
+ ],
331
+ "params": [
332
+ {
333
+ "default": "",
334
+ "name": "purpose",
335
+ "type": {
336
+ "type": "<class 'str'>"
337
+ }
338
+ },
339
+ {
340
+ "default": "This agent help with various tasks.",
341
+ "name": "description",
342
+ "type": {
343
+ "format": "textarea"
344
+ }
345
+ },
346
+ {
347
+ "default": "You are a helpful assistant.",
348
+ "name": "system_prompt",
349
+ "type": {
350
+ "format": "textarea"
351
+ }
352
+ }
353
+ ],
354
+ "type": "basic"
355
+ },
356
+ "op_id": "LynxScribe > Agent",
357
+ "params": {
358
+ "description": "",
359
+ "purpose": "Main conversation",
360
+ "system_prompt": "You are a helpful assistant. Use the agents at your disposal\nto help the user."
361
+ },
362
+ "status": "done",
363
+ "title": "Agent"
364
+ },
365
+ "dragHandle": ".drag-handle",
366
+ "height": 326.0,
367
+ "id": "Agent 2",
368
+ "position": {
369
+ "x": 226.41731551276598,
370
+ "y": -695.7509243963451
371
+ },
372
+ "type": "basic",
373
+ "width": 457.0
374
+ },
375
+ {
376
+ "data": {
377
+ "__execution_delay": 0.0,
378
+ "collapsed": true,
379
+ "display": null,
380
+ "error": null,
381
+ "input_metadata": [],
382
+ "meta": {
383
+ "categories": [
384
+ "NetworkX",
385
+ "Generators",
386
+ "Classic"
387
+ ],
388
+ "color": "orange",
389
+ "doc": null,
390
+ "id": "NetworkX > Generators > Classic > Ladder graph",
391
+ "inputs": [],
392
+ "name": "Ladder graph",
393
+ "outputs": [
394
+ {
395
+ "name": "output",
396
+ "position": "right",
397
+ "type": {
398
+ "type": "<class 'networkx.classes.graph.Graph'>"
399
+ }
400
+ }
401
+ ],
402
+ "params": [
403
+ {
404
+ "default": null,
405
+ "name": "n",
406
+ "type": {
407
+ "type": "<class 'int'>"
408
+ }
409
+ }
410
+ ],
411
+ "type": "basic"
412
+ },
413
+ "op_id": "NetworkX > Generators > Classic > Ladder graph",
414
+ "params": {
415
+ "n": "11"
416
+ },
417
+ "status": "done",
418
+ "title": "Ladder graph"
419
+ },
420
+ "dragHandle": ".drag-handle",
421
+ "height": 200.0,
422
+ "id": "Ladder graph 1",
423
+ "position": {
424
+ "x": -1297.4471345569843,
425
+ "y": 364.99969784589774
426
+ },
427
+ "type": "basic",
428
+ "width": 200.0
429
+ },
430
+ {
431
+ "data": {
432
+ "collapsed": true,
433
+ "display": null,
434
+ "error": null,
435
+ "input_metadata": [
436
+ {}
437
+ ],
438
+ "meta": {
439
+ "categories": [
440
+ "LynxScribe"
441
+ ],
442
+ "color": "green",
443
+ "doc": null,
444
+ "id": "LynxScribe > MCP: Query database with SQL",
445
+ "inputs": [
446
+ {
447
+ "name": "db",
448
+ "position": "bottom",
449
+ "type": {
450
+ "type": "<class 'str'>"
451
+ }
452
+ }
453
+ ],
454
+ "name": "MCP: Query database with SQL",
455
+ "outputs": [
456
+ {
457
+ "name": "output",
458
+ "position": "top",
459
+ "type": {
460
+ "type": "None"
461
+ }
462
+ }
463
+ ],
464
+ "params": [],
465
+ "type": "basic"
466
+ },
467
+ "op_id": "LynxScribe > MCP: Query database with SQL",
468
+ "params": {},
469
+ "status": "done",
470
+ "title": "MCP: Query database with SQL"
471
+ },
472
+ "dragHandle": ".drag-handle",
473
+ "height": 152.0,
474
+ "id": "MCP: Query database with SQL 2",
475
+ "position": {
476
+ "x": -248.451978071668,
477
+ "y": 231.5655840074671
478
+ },
479
+ "type": "basic",
480
+ "width": 334.0
481
+ },
482
+ {
483
+ "data": {
484
+ "__execution_delay": 0.0,
485
+ "display": null,
486
+ "error": null,
487
+ "input_metadata": [
488
+ {}
489
+ ],
490
+ "meta": {
491
+ "categories": [
492
+ "LynxScribe"
493
+ ],
494
+ "color": "blue",
495
+ "doc": null,
496
+ "id": "LynxScribe > Agent",
497
+ "inputs": [
498
+ {
499
+ "name": "tools",
500
+ "position": "bottom",
501
+ "type": {
502
+ "type": "list[str]"
503
+ }
504
+ }
505
+ ],
506
+ "name": "Agent",
507
+ "outputs": [
508
+ {
509
+ "name": "output",
510
+ "position": "top",
511
+ "type": {
512
+ "type": "None"
513
+ }
514
+ }
515
+ ],
516
+ "params": [
517
+ {
518
+ "default": "",
519
+ "name": "purpose",
520
+ "type": {
521
+ "type": "<class 'str'>"
522
+ }
523
+ },
524
+ {
525
+ "default": "This agent help with various tasks.",
526
+ "name": "description",
527
+ "type": {
528
+ "format": "textarea"
529
+ }
530
+ },
531
+ {
532
+ "default": "You are a helpful assistant.",
533
+ "name": "system_prompt",
534
+ "type": {
535
+ "format": "textarea"
536
+ }
537
+ }
538
+ ],
539
+ "type": "basic"
540
+ },
541
+ "op_id": "LynxScribe > Agent",
542
+ "params": {
543
+ "description": "This agent can help with\nimage generation tasks.",
544
+ "purpose": "Generate image",
545
+ "system_prompt": "Formulate a good image generation prompt\nand use the ComfyUI tool to generate\nan image according to the user's wishes."
546
+ },
547
+ "status": "done",
548
+ "title": "Agent"
549
+ },
550
+ "dragHandle": ".drag-handle",
551
+ "height": 392.0,
552
+ "id": "Agent 3",
553
+ "position": {
554
+ "x": 511.2723643375159,
555
+ "y": -276.6461006767206
556
+ },
557
+ "type": "basic",
558
+ "width": 368.0
559
+ },
560
+ {
561
+ "data": {
562
+ "collapsed": true,
563
+ "display": null,
564
+ "error": null,
565
+ "input_metadata": [],
566
+ "meta": {
567
+ "categories": [
568
+ "LynxScribe"
569
+ ],
570
+ "color": "green",
571
+ "doc": null,
572
+ "id": "LynxScribe > MCP: Calculator",
573
+ "inputs": [],
574
+ "name": "MCP: Calculator",
575
+ "outputs": [
576
+ {
577
+ "name": "output",
578
+ "position": "top",
579
+ "type": {
580
+ "type": "None"
581
+ }
582
+ }
583
+ ],
584
+ "params": [],
585
+ "type": "basic"
586
+ },
587
+ "op_id": "LynxScribe > MCP: Calculator",
588
+ "params": {},
589
+ "status": "done",
590
+ "title": "MCP: Calculator"
591
+ },
592
+ "dragHandle": ".drag-handle",
593
+ "height": 200.0,
594
+ "id": "MCP: Calculator 1",
595
+ "position": {
596
+ "x": -527.6679408294542,
597
+ "y": 240.503939070944
598
+ },
599
+ "type": "basic",
600
+ "width": 200.0
601
+ },
602
+ {
603
+ "data": {
604
+ "collapsed": false,
605
+ "display": {
606
+ "dataframes": {
607
+ "service": {
608
+ "columns": [
609
+ "url"
610
+ ],
611
+ "data": [
612
+ [
613
+ "/api/service/lynxkite_graph_analytics/LynxScribe MCP/Demo.lynxkite.json/Chat frontend 1"
614
+ ]
615
+ ]
616
+ }
617
+ }
618
+ },
619
+ "error": null,
620
+ "input_metadata": [
621
+ {}
622
+ ],
623
+ "meta": {
624
+ "categories": [
625
+ "LynxScribe"
626
+ ],
627
+ "color": "gray",
628
+ "doc": null,
629
+ "id": "LynxScribe > Chat frontend",
630
+ "inputs": [
631
+ {
632
+ "name": "agent",
633
+ "position": "bottom",
634
+ "type": {
635
+ "type": "<class 'str'>"
636
+ }
637
+ }
638
+ ],
639
+ "name": "Chat frontend",
640
+ "outputs": [],
641
+ "params": [],
642
+ "type": "service"
643
+ },
644
+ "op_id": "LynxScribe > Chat frontend",
645
+ "params": {},
646
+ "status": "done",
647
+ "title": "Chat frontend"
648
+ },
649
+ "dragHandle": ".drag-handle",
650
+ "height": 362.0,
651
+ "id": "Chat frontend 1",
652
+ "position": {
653
+ "x": 237.184571561771,
654
+ "y": -1107.6739000139528
655
+ },
656
+ "type": "service",
657
+ "width": 428.0
658
+ },
659
+ {
660
+ "data": {
661
+ "collapsed": true,
662
+ "display": null,
663
+ "error": null,
664
+ "input_metadata": [
665
+ {}
666
+ ],
667
+ "meta": {
668
+ "categories": [
669
+ "NetworkX",
670
+ "Algorithms",
671
+ "Link analysis",
672
+ "PageRank alg"
673
+ ],
674
+ "color": "orange",
675
+ "doc": null,
676
+ "id": "NetworkX > Algorithms > Link analysis > PageRank alg > PageRank",
677
+ "inputs": [
678
+ {
679
+ "name": "G",
680
+ "position": "left",
681
+ "type": {
682
+ "type": "<class 'networkx.classes.graph.Graph'>"
683
+ }
684
+ }
685
+ ],
686
+ "name": "PageRank",
687
+ "outputs": [
688
+ {
689
+ "name": "output",
690
+ "position": "right",
691
+ "type": {
692
+ "type": "<class 'networkx.classes.graph.Graph'>"
693
+ }
694
+ }
695
+ ],
696
+ "params": [
697
+ {
698
+ "default": "0.85",
699
+ "name": "alpha",
700
+ "type": {
701
+ "type": "float | None"
702
+ }
703
+ },
704
+ {
705
+ "default": "100",
706
+ "name": "max_iter",
707
+ "type": {
708
+ "type": "int | None"
709
+ }
710
+ },
711
+ {
712
+ "default": "1e-06",
713
+ "name": "tol",
714
+ "type": {
715
+ "type": "float | None"
716
+ }
717
+ },
718
+ {
719
+ "default": "weight",
720
+ "name": "weight",
721
+ "type": {
722
+ "type": "str | None"
723
+ }
724
+ }
725
+ ],
726
+ "type": "basic"
727
+ },
728
+ "op_id": "NetworkX > Algorithms > Link analysis > PageRank alg > PageRank",
729
+ "params": {
730
+ "alpha": "0.85",
731
+ "max_iter": "100",
732
+ "tol": "1e-06",
733
+ "weight": "weight"
734
+ },
735
+ "status": "done",
736
+ "title": "PageRank"
737
+ },
738
+ "dragHandle": ".drag-handle",
739
+ "height": 200.0,
740
+ "id": "PageRank 1",
741
+ "position": {
742
+ "x": -878.5796659405156,
743
+ "y": 369.96445264090244
744
+ },
745
+ "type": "basic",
746
+ "width": 200.0
747
+ },
748
+ {
749
+ "data": {
750
+ "collapsed": true,
751
+ "display": null,
752
+ "error": null,
753
+ "input_metadata": [],
754
+ "meta": {
755
+ "categories": [
756
+ "NetworkX",
757
+ "Generators",
758
+ "Social"
759
+ ],
760
+ "color": "orange",
761
+ "doc": null,
762
+ "id": "NetworkX > Generators > Social > Karate club graph",
763
+ "inputs": [],
764
+ "name": "Karate club graph",
765
+ "outputs": [
766
+ {
767
+ "name": "output",
768
+ "position": "right",
769
+ "type": {
770
+ "type": "<class 'networkx.classes.graph.Graph'>"
771
+ }
772
+ }
773
+ ],
774
+ "params": [],
775
+ "type": "basic"
776
+ },
777
+ "op_id": "NetworkX > Generators > Social > Karate club graph",
778
+ "params": {},
779
+ "status": "done",
780
+ "title": "Karate club graph"
781
+ },
782
+ "dragHandle": ".drag-handle",
783
+ "height": 200.0,
784
+ "id": "Karate club graph 1",
785
+ "position": {
786
+ "x": -1304.6391517192224,
787
+ "y": 585.0242219568652
788
+ },
789
+ "type": "basic",
790
+ "width": 200.0
791
+ },
792
+ {
793
+ "data": {
794
+ "collapsed": true,
795
+ "display": null,
796
+ "error": null,
797
+ "input_metadata": [
798
+ {}
799
+ ],
800
+ "meta": {
801
+ "categories": [
802
+ "NetworkX",
803
+ "Algorithms",
804
+ "Link prediction"
805
+ ],
806
+ "color": "orange",
807
+ "doc": null,
808
+ "id": "NetworkX > Algorithms > Link prediction > Common neighbor centrality",
809
+ "inputs": [
810
+ {
811
+ "name": "G",
812
+ "position": "left",
813
+ "type": {
814
+ "type": "<class 'networkx.classes.graph.Graph'>"
815
+ }
816
+ }
817
+ ],
818
+ "name": "Common neighbor centrality",
819
+ "outputs": [
820
+ {
821
+ "name": "output",
822
+ "position": "right",
823
+ "type": {
824
+ "type": "<class 'networkx.classes.graph.Graph'>"
825
+ }
826
+ }
827
+ ],
828
+ "params": [],
829
+ "type": "basic"
830
+ },
831
+ "op_id": "NetworkX > Algorithms > Link prediction > Common neighbor centrality",
832
+ "params": {},
833
+ "status": "done",
834
+ "title": "Common neighbor centrality"
835
+ },
836
+ "dragHandle": ".drag-handle",
837
+ "height": 130.0,
838
+ "id": "Common neighbor centrality 1",
839
+ "position": {
840
+ "x": -990.2453153930347,
841
+ "y": 587.3192401780905
842
+ },
843
+ "type": "basic",
844
+ "width": 341.0
845
+ },
846
+ {
847
+ "data": {
848
+ "__execution_delay": 0.0,
849
+ "collapsed": true,
850
+ "display": null,
851
+ "error": null,
852
+ "input_metadata": [],
853
+ "meta": {
854
+ "categories": [],
855
+ "color": "orange",
856
+ "doc": [
857
+ {
858
+ "kind": "text",
859
+ "value": "Read the contents of the a file into a `Bundle`."
860
+ },
861
+ {
862
+ "kind": "parameters",
863
+ "value": [
864
+ {
865
+ "annotation": "str",
866
+ "description": "Path to the file to import.",
867
+ "name": "file_path"
868
+ },
869
+ {
870
+ "annotation": "str",
871
+ "description": "Name to use for identifying the table in the bundle.",
872
+ "name": "table_name"
873
+ },
874
+ {
875
+ "annotation": "FileFormat",
876
+ "description": "Format of the file. Has to be one of the values in the `FileFormat` enum.",
877
+ "name": "file_format"
878
+ }
879
+ ]
880
+ },
881
+ {
882
+ "kind": "returns",
883
+ "value": [
884
+ {
885
+ "annotation": "<class 'lynxkite_graph_analytics.core.Bundle'>",
886
+ "description": "Bundle with a single table with the contents of the file.",
887
+ "name": "Bundle"
888
+ }
889
+ ]
890
+ }
891
+ ],
892
+ "id": "Import file",
893
+ "inputs": [],
894
+ "name": "Import file",
895
+ "outputs": [
896
+ {
897
+ "name": "output",
898
+ "position": "right",
899
+ "type": {
900
+ "type": "None"
901
+ }
902
+ }
903
+ ],
904
+ "params": [
905
+ {
906
+ "default": null,
907
+ "name": "file_path",
908
+ "type": {
909
+ "type": "<class 'str'>"
910
+ }
911
+ },
912
+ {
913
+ "default": null,
914
+ "name": "table_name",
915
+ "type": {
916
+ "type": "<class 'str'>"
917
+ }
918
+ },
919
+ {
920
+ "default": "csv",
921
+ "name": "file_format",
922
+ "type": {
923
+ "enum": [
924
+ "csv",
925
+ "parquet",
926
+ "json",
927
+ "excel"
928
+ ]
929
+ }
930
+ },
931
+ {
932
+ "default": "csv",
933
+ "groups": {
934
+ "csv": [
935
+ {
936
+ "default": "<from file>",
937
+ "name": "columns",
938
+ "type": {
939
+ "type": "<class 'str'>"
940
+ }
941
+ },
942
+ {
943
+ "default": "<auto>",
944
+ "name": "separator",
945
+ "type": {
946
+ "type": "<class 'str'>"
947
+ }
948
+ }
949
+ ],
950
+ "excel": [
951
+ {
952
+ "default": "Sheet1",
953
+ "name": "sheet_name",
954
+ "type": {
955
+ "type": "<class 'str'>"
956
+ }
957
+ }
958
+ ],
959
+ "json": [],
960
+ "parquet": []
961
+ },
962
+ "name": "file_format_group",
963
+ "selector": {
964
+ "default": "csv",
965
+ "name": "file_format",
966
+ "type": {
967
+ "enum": [
968
+ "csv",
969
+ "parquet",
970
+ "json",
971
+ "excel"
972
+ ]
973
+ }
974
+ },
975
+ "type": "group"
976
+ }
977
+ ],
978
+ "type": "basic"
979
+ },
980
+ "op_id": "Import file",
981
+ "params": {
982
+ "file_format": "csv",
983
+ "file_format_group": "csv",
984
+ "file_path": "uploads/molecules2.csv",
985
+ "table_name": "molecules"
986
+ },
987
+ "status": "done",
988
+ "title": "Import file"
989
+ },
990
+ "dragHandle": ".drag-handle",
991
+ "height": 393.0,
992
+ "id": "Import file 1",
993
+ "position": {
994
+ "x": -1411.4491034838866,
995
+ "y": 772.1675932822765
996
+ },
997
+ "type": "basic",
998
+ "width": 369.0
999
+ },
1000
+ {
1001
+ "data": {
1002
+ "__execution_delay": 0.0,
1003
+ "collapsed": true,
1004
+ "display": null,
1005
+ "error": null,
1006
+ "input_metadata": [
1007
+ {
1008
+ "dataframes": {
1009
+ "molecules": {
1010
+ "columns": [
1011
+ "name",
1012
+ "smiles"
1013
+ ],
1014
+ "key": "molecules"
1015
+ }
1016
+ },
1017
+ "other": {},
1018
+ "relations": []
1019
+ }
1020
+ ],
1021
+ "meta": {
1022
+ "categories": [],
1023
+ "color": "orange",
1024
+ "doc": [
1025
+ {
1026
+ "kind": "text",
1027
+ "value": "Run a SQL query on the DataFrames in the bundle. Save the results as a new DataFrame."
1028
+ }
1029
+ ],
1030
+ "id": "SQL",
1031
+ "inputs": [
1032
+ {
1033
+ "name": "bundle",
1034
+ "position": "left",
1035
+ "type": {
1036
+ "type": "<class 'lynxkite_graph_analytics.core.Bundle'>"
1037
+ }
1038
+ }
1039
+ ],
1040
+ "name": "SQL",
1041
+ "outputs": [
1042
+ {
1043
+ "name": "output",
1044
+ "position": "right",
1045
+ "type": {
1046
+ "type": "None"
1047
+ }
1048
+ }
1049
+ ],
1050
+ "params": [
1051
+ {
1052
+ "default": null,
1053
+ "name": "query",
1054
+ "type": {
1055
+ "format": "textarea"
1056
+ }
1057
+ },
1058
+ {
1059
+ "default": "result",
1060
+ "name": "save_as",
1061
+ "type": {
1062
+ "type": "<class 'str'>"
1063
+ }
1064
+ }
1065
+ ],
1066
+ "type": "basic"
1067
+ },
1068
+ "op_id": "SQL",
1069
+ "params": {
1070
+ "query": "select *",
1071
+ "save_as": "result"
1072
+ },
1073
+ "status": "done",
1074
+ "title": "SQL"
1075
+ },
1076
+ "dragHandle": ".drag-handle",
1077
+ "height": 200.0,
1078
+ "id": "SQL 1",
1079
+ "position": {
1080
+ "x": -931.2061769202694,
1081
+ "y": 766.0054007337461
1082
+ },
1083
+ "type": "basic",
1084
+ "width": 200.0
1085
+ },
1086
+ {
1087
+ "data": {
1088
+ "__execution_delay": 0.0,
1089
+ "collapsed": true,
1090
+ "display": null,
1091
+ "error": null,
1092
+ "input_metadata": [
1093
+ {
1094
+ "dataframes": {
1095
+ "molecules": {
1096
+ "columns": [
1097
+ "name",
1098
+ "smiles"
1099
+ ],
1100
+ "key": "molecules"
1101
+ },
1102
+ "result": {
1103
+ "columns": [],
1104
+ "key": "result"
1105
+ }
1106
+ },
1107
+ "other": {},
1108
+ "relations": []
1109
+ }
1110
+ ],
1111
+ "meta": {
1112
+ "categories": [],
1113
+ "color": "orange",
1114
+ "doc": [
1115
+ {
1116
+ "kind": "text",
1117
+ "value": "Run a SQL query on the DataFrames in the bundle. Save the results as a new DataFrame."
1118
+ }
1119
+ ],
1120
+ "id": "SQL",
1121
+ "inputs": [
1122
+ {
1123
+ "name": "bundle",
1124
+ "position": "left",
1125
+ "type": {
1126
+ "type": "<class 'lynxkite_graph_analytics.core.Bundle'>"
1127
+ }
1128
+ }
1129
+ ],
1130
+ "name": "SQL",
1131
+ "outputs": [
1132
+ {
1133
+ "name": "output",
1134
+ "position": "right",
1135
+ "type": {
1136
+ "type": "None"
1137
+ }
1138
+ }
1139
+ ],
1140
+ "params": [
1141
+ {
1142
+ "default": null,
1143
+ "name": "query",
1144
+ "type": {
1145
+ "format": "textarea"
1146
+ }
1147
+ },
1148
+ {
1149
+ "default": "result",
1150
+ "name": "save_as",
1151
+ "type": {
1152
+ "type": "<class 'str'>"
1153
+ }
1154
+ }
1155
+ ],
1156
+ "type": "basic"
1157
+ },
1158
+ "op_id": "SQL",
1159
+ "params": {
1160
+ "query": "select *",
1161
+ "save_as": "result"
1162
+ },
1163
+ "status": "done",
1164
+ "title": "SQL"
1165
+ },
1166
+ "dragHandle": ".drag-handle",
1167
+ "height": 200.0,
1168
+ "id": "SQL 2",
1169
+ "position": {
1170
+ "x": -633.7783633982368,
1171
+ "y": 767.4541281209835
1172
+ },
1173
+ "type": "basic",
1174
+ "width": 200.0
1175
+ },
1176
+ {
1177
+ "data": {
1178
+ "__execution_delay": 0.0,
1179
+ "display": null,
1180
+ "error": null,
1181
+ "input_metadata": [],
1182
+ "meta": {
1183
+ "categories": [
1184
+ "LynxScribe"
1185
+ ],
1186
+ "color": "green",
1187
+ "doc": null,
1188
+ "id": "LynxScribe > MCP: Run ComfyUI workflow",
1189
+ "inputs": [],
1190
+ "name": "MCP: Run ComfyUI workflow",
1191
+ "outputs": [
1192
+ {
1193
+ "name": "output",
1194
+ "position": "top",
1195
+ "type": {
1196
+ "type": "None"
1197
+ }
1198
+ }
1199
+ ],
1200
+ "params": [
1201
+ {
1202
+ "default": null,
1203
+ "name": "workflow_name",
1204
+ "type": {
1205
+ "type": "<class 'str'>"
1206
+ }
1207
+ }
1208
+ ],
1209
+ "type": "basic"
1210
+ },
1211
+ "op_id": "LynxScribe > MCP: Run ComfyUI workflow",
1212
+ "params": {
1213
+ "workflow_name": "SDXL"
1214
+ },
1215
+ "status": "done",
1216
+ "title": "MCP: Run ComfyUI workflow"
1217
+ },
1218
+ "dragHandle": ".drag-handle",
1219
+ "height": 200.0,
1220
+ "id": "MCP: Run ComfyUI workflow 1",
1221
+ "position": {
1222
+ "x": 598.9560131686237,
1223
+ "y": 218.52928063566645
1224
+ },
1225
+ "type": "basic",
1226
+ "width": 200.0
1227
+ }
1228
+ ],
1229
+ "paused": false
1230
+ }
examples/LynxScribe/ChatAPI/demo.py ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import enum
2
+ from lynxkite_core import ops
3
+ from lynxkite_graph_analytics import core
4
+ import fastapi
5
+ from lynxscribe.components.chat.api import ChatAPI
6
+ from lynxscribe.components.rag.rag_chatbot import Mode, RAGChatbot, Scenario, ScenarioSelector
7
+ from lynxscribe.core.llm.base import get_llm_engine
8
+ from lynxscribe.core.models.prompts import ChatCompletionPrompt
9
+
10
+ lsop = ops.op_registration(
11
+ "LynxKite Graph Analytics", "LynxScribe", dir="bottom-to-top", color="blue"
12
+ )
13
+
14
+ dsop = ops.op_registration("LynxKite Graph Analytics", "Data Science")
15
+
16
+ Placeholder = str
17
+
18
+
19
+ @lsop("Chat frontend", color="gray", outputs=[], view="service")
20
+ def chat_frontend(agent: Placeholder):
21
+ return ChatAPIService(agent)
22
+
23
+
24
+ @lsop("Agent")
25
+ def agent(
26
+ tools: list[Placeholder],
27
+ *,
28
+ purpose: str = "",
29
+ description: ops.LongStr = "This agent helps with various tasks.",
30
+ system_prompt: ops.LongStr = "You are a helpful assistant.",
31
+ ):
32
+ ts = []
33
+ for t in tools:
34
+ t = "\n ".join(t.split("\n"))
35
+ ts.append(f"- {t}\n")
36
+ return f"Agent for {purpose} with {len(tools)} tools:\n{''.join(ts)}"
37
+
38
+
39
+ @lsop("MCP: Query database with SQL", color="green")
40
+ def sql_tool(db: Placeholder):
41
+ return f"SQL over {db}"
42
+
43
+
44
+ @ops.output_position(output="top")
45
+ @dsop("Database")
46
+ def db(data_pipeline: list[core.Bundle]):
47
+ return f"DB with {len(data_pipeline)} bundles"
48
+
49
+
50
+ class MCPSearchEngine(str, enum.Enum):
51
+ Google = "Google"
52
+ Bing = "Bing"
53
+ DuckDuckGo = "DuckDuckGo"
54
+
55
+
56
+ @lsop("MCP: Search web", color="green")
57
+ def web_search(*, engine: MCPSearchEngine = MCPSearchEngine.Google):
58
+ return f"Web search ({engine.name})"
59
+
60
+
61
+ @lsop("MCP: Run ComfyUI workflow", color="green")
62
+ def run_comfyui_workflow(*, workflow_name: str):
63
+ return f"Run comfyui workflow ({workflow_name})"
64
+
65
+
66
+ @lsop("MCP: Calculator", color="green")
67
+ def calculator():
68
+ return "Calculator"
69
+
70
+
71
+ class ChatAPIService:
72
+ def __init__(self, agent: str):
73
+ self.agent = agent
74
+ self.chat_api = ChatAPI(
75
+ chatbot=RAGChatbot(
76
+ None,
77
+ ScenarioSelector([Scenario(name="single", mode=Mode.LLM_ONLY)]),
78
+ llm=get_llm_engine(name="openai"),
79
+ ),
80
+ model="gpt-4o-mini",
81
+ )
82
+
83
+ async def get(self, request: fastapi.Request, path: str) -> dict:
84
+ if path == "models":
85
+ return {
86
+ "object": "list",
87
+ "data": [
88
+ {
89
+ "id": "LynxScribe",
90
+ "object": "model",
91
+ "created": 0,
92
+ "owned_by": "lynxkite",
93
+ "meta": {"profile_image_url": "https://lynxkite.com/favicon.png"},
94
+ }
95
+ ],
96
+ }
97
+ return {"error": "Not found"}
98
+
99
+ async def post(self, request: fastapi.Request, path: str) -> dict:
100
+ if path == "chat/completions":
101
+ request = await request.json()
102
+ if request["stream"]:
103
+ from sse_starlette.sse import EventSourceResponse
104
+
105
+ return EventSourceResponse(self.stream_chat_api_response(request))
106
+ else:
107
+ return await self.get_chat_api_response(request)
108
+ return {"error": "Not found"}
109
+
110
+ async def stream_chat_api_response(self, request):
111
+ request = ChatCompletionPrompt(**request)
112
+ async for chunk in await self.chat_api.answer(request, stream=True):
113
+ chunk.choices[0].delta.content += f"({self.agent})"
114
+ yield chunk.model_dump_json()
115
+
116
+ async def get_chat_api_response(self, request):
117
+ request = ChatCompletionPrompt(**request)
118
+ response = await self.chat_api.answer(request, stream=False)
119
+ return response.model_dump()
examples/LynxScribe/ChatAPI/demo.sh ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash -xue
2
+ # xh POST 'https://api.openai.com/v1/chat/completions' \
3
+ # Authorization:"Bearer $OPENAI_API_KEY" \
4
+ # model=gpt-4o-mini \
5
+ # stream:=false \
6
+ # messages:='[{"role": "user", "content": "what does the fox say"}]'
7
+
8
+ xh 'http://localhost:8000/api/service/lynxkite_graph_analytics/LynxScribe%20MCP/Demo.lynxkite.json/Chat%20frontend%201/models'
9
+
10
+ xh POST 'http://localhost:8000/api/service/lynxkite_graph_analytics/LynxScribe%20MCP/Demo.lynxkite.json/Chat%20frontend%201/chat/completions' \
11
+ model=LynxScribe \
12
+ stream:=false \
13
+ messages:='[{"role": "user", "content": "what does the fox say"}]'
examples/LynxScribe/ChatAPI/requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ ../../lynxscribe
examples/LynxScribe/MCP/Demo.lynxkite.json ADDED
@@ -0,0 +1,1050 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "edges": [
3
+ {
4
+ "id": "Database 1 output MCP: Query database with SQL 2 db",
5
+ "source": "Database 1",
6
+ "sourceHandle": "output",
7
+ "target": "MCP: Query database with SQL 2",
8
+ "targetHandle": "db"
9
+ },
10
+ {
11
+ "id": "Ladder graph 1 output PageRank 1 G",
12
+ "source": "Ladder graph 1",
13
+ "sourceHandle": "output",
14
+ "target": "PageRank 1",
15
+ "targetHandle": "G"
16
+ },
17
+ {
18
+ "id": "PageRank 1 output Database 1 data_pipeline",
19
+ "source": "PageRank 1",
20
+ "sourceHandle": "output",
21
+ "target": "Database 1",
22
+ "targetHandle": "data_pipeline"
23
+ },
24
+ {
25
+ "id": "Karate club graph 1 output Common neighbor centrality 1 G",
26
+ "source": "Karate club graph 1",
27
+ "sourceHandle": "output",
28
+ "target": "Common neighbor centrality 1",
29
+ "targetHandle": "G"
30
+ },
31
+ {
32
+ "id": "Common neighbor centrality 1 output Database 1 data_pipeline",
33
+ "source": "Common neighbor centrality 1",
34
+ "sourceHandle": "output",
35
+ "target": "Database 1",
36
+ "targetHandle": "data_pipeline"
37
+ },
38
+ {
39
+ "id": "Import file 1 output SQL 1 bundle",
40
+ "source": "Import file 1",
41
+ "sourceHandle": "output",
42
+ "target": "SQL 1",
43
+ "targetHandle": "bundle"
44
+ },
45
+ {
46
+ "id": "SQL 1 output SQL 2 bundle",
47
+ "source": "SQL 1",
48
+ "sourceHandle": "output",
49
+ "target": "SQL 2",
50
+ "targetHandle": "bundle"
51
+ },
52
+ {
53
+ "id": "SQL 2 output Database 1 data_pipeline",
54
+ "source": "SQL 2",
55
+ "sourceHandle": "output",
56
+ "target": "Database 1",
57
+ "targetHandle": "data_pipeline"
58
+ },
59
+ {
60
+ "id": "Agent 1 output Chat frontend 1 agent",
61
+ "source": "Agent 1",
62
+ "sourceHandle": "output",
63
+ "target": "Chat frontend 1",
64
+ "targetHandle": "agent"
65
+ },
66
+ {
67
+ "id": "MCP: Financial data 1 output Agent 1 tools",
68
+ "source": "MCP: Financial data 1",
69
+ "sourceHandle": "output",
70
+ "target": "Agent 1",
71
+ "targetHandle": "tools"
72
+ },
73
+ {
74
+ "id": "MCP: Query database with SQL 2 output Agent 1 tools",
75
+ "source": "MCP: Query database with SQL 2",
76
+ "sourceHandle": "output",
77
+ "target": "Agent 1",
78
+ "targetHandle": "tools"
79
+ },
80
+ {
81
+ "id": "MCP: Calculator 1 output Agent 1 tools",
82
+ "source": "MCP: Calculator 1",
83
+ "sourceHandle": "output",
84
+ "target": "Agent 1",
85
+ "targetHandle": "tools"
86
+ },
87
+ {
88
+ "id": "MCP: Search web 1 output Agent 1 tools",
89
+ "source": "MCP: Search web 1",
90
+ "sourceHandle": "output",
91
+ "target": "Agent 1",
92
+ "targetHandle": "tools"
93
+ }
94
+ ],
95
+ "env": "LynxKite Graph Analytics",
96
+ "nodes": [
97
+ {
98
+ "data": {
99
+ "collapsed": true,
100
+ "display": null,
101
+ "error": null,
102
+ "input_metadata": [
103
+ {}
104
+ ],
105
+ "meta": {
106
+ "categories": [
107
+ "Data Science"
108
+ ],
109
+ "color": "orange",
110
+ "doc": null,
111
+ "id": "Data Science > Database",
112
+ "inputs": [
113
+ {
114
+ "name": "data_pipeline",
115
+ "position": "left",
116
+ "type": {
117
+ "type": "list[lynxkite_graph_analytics.core.Bundle]"
118
+ }
119
+ }
120
+ ],
121
+ "name": "Database",
122
+ "outputs": [
123
+ {
124
+ "name": "output",
125
+ "position": "top",
126
+ "type": {
127
+ "type": "None"
128
+ }
129
+ }
130
+ ],
131
+ "params": [],
132
+ "type": "basic"
133
+ },
134
+ "op_id": "Data Science > Database",
135
+ "params": {},
136
+ "status": "done",
137
+ "title": "Database"
138
+ },
139
+ "dragHandle": ".drag-handle",
140
+ "height": 200.0,
141
+ "id": "Database 1",
142
+ "position": {
143
+ "x": -175.8708861292469,
144
+ "y": 465.47762360072204
145
+ },
146
+ "type": "basic",
147
+ "width": 200.0
148
+ },
149
+ {
150
+ "data": {
151
+ "__execution_delay": 0.0,
152
+ "display": null,
153
+ "error": null,
154
+ "input_metadata": [
155
+ {}
156
+ ],
157
+ "meta": {
158
+ "categories": [
159
+ "LynxScribe"
160
+ ],
161
+ "color": "blue",
162
+ "doc": null,
163
+ "id": "LynxScribe > Agent",
164
+ "inputs": [
165
+ {
166
+ "name": "tools",
167
+ "position": "bottom",
168
+ "type": {
169
+ "type": "list[dict]"
170
+ }
171
+ }
172
+ ],
173
+ "name": "Agent",
174
+ "outputs": [
175
+ {
176
+ "name": "output",
177
+ "position": "top",
178
+ "type": {
179
+ "type": "None"
180
+ }
181
+ }
182
+ ],
183
+ "params": [
184
+ {
185
+ "default": "",
186
+ "name": "purpose",
187
+ "type": {
188
+ "type": "<class 'str'>"
189
+ }
190
+ },
191
+ {
192
+ "default": "This agent helps with various tasks.",
193
+ "name": "description",
194
+ "type": {
195
+ "format": "textarea"
196
+ }
197
+ },
198
+ {
199
+ "default": "You are a helpful assistant.",
200
+ "name": "system_prompt",
201
+ "type": {
202
+ "format": "textarea"
203
+ }
204
+ }
205
+ ],
206
+ "type": "basic"
207
+ },
208
+ "op_id": "LynxScribe > Agent",
209
+ "params": {
210
+ "description": "This agent can help with data science\nand analytics questions.",
211
+ "purpose": "Data assistant",
212
+ "system_prompt": "Using the tools at your disposal answer all questions in JSON format. For queries about movies use the database, not web search. Always answer in JSON."
213
+ },
214
+ "status": "done",
215
+ "title": "Agent"
216
+ },
217
+ "dragHandle": ".drag-handle",
218
+ "height": 432.0,
219
+ "id": "Agent 1",
220
+ "position": {
221
+ "x": -162.02870375433838,
222
+ "y": -454.2852833821508
223
+ },
224
+ "type": "basic",
225
+ "width": 479.0
226
+ },
227
+ {
228
+ "data": {
229
+ "__execution_delay": 0.0,
230
+ "collapsed": true,
231
+ "display": null,
232
+ "error": null,
233
+ "input_metadata": [],
234
+ "meta": {
235
+ "categories": [
236
+ "NetworkX",
237
+ "Generators",
238
+ "Classic"
239
+ ],
240
+ "color": "orange",
241
+ "doc": null,
242
+ "id": "NetworkX > Generators > Classic > Ladder graph",
243
+ "inputs": [],
244
+ "name": "Ladder graph",
245
+ "outputs": [
246
+ {
247
+ "name": "output",
248
+ "position": "right",
249
+ "type": {
250
+ "type": "<class 'networkx.classes.graph.Graph'>"
251
+ }
252
+ }
253
+ ],
254
+ "params": [
255
+ {
256
+ "default": null,
257
+ "name": "n",
258
+ "type": {
259
+ "type": "<class 'int'>"
260
+ }
261
+ }
262
+ ],
263
+ "type": "basic"
264
+ },
265
+ "op_id": "NetworkX > Generators > Classic > Ladder graph",
266
+ "params": {
267
+ "n": "11"
268
+ },
269
+ "status": "done",
270
+ "title": "Ladder graph"
271
+ },
272
+ "dragHandle": ".drag-handle",
273
+ "height": 200.0,
274
+ "id": "Ladder graph 1",
275
+ "position": {
276
+ "x": -1297.4471345569843,
277
+ "y": 364.99969784589774
278
+ },
279
+ "type": "basic",
280
+ "width": 200.0
281
+ },
282
+ {
283
+ "data": {
284
+ "collapsed": true,
285
+ "display": null,
286
+ "error": null,
287
+ "input_metadata": [
288
+ {}
289
+ ],
290
+ "meta": {
291
+ "categories": [
292
+ "LynxScribe"
293
+ ],
294
+ "color": "green",
295
+ "doc": null,
296
+ "id": "LynxScribe > MCP: Query database with SQL",
297
+ "inputs": [
298
+ {
299
+ "name": "db",
300
+ "position": "bottom",
301
+ "type": {
302
+ "type": "<class 'str'>"
303
+ }
304
+ }
305
+ ],
306
+ "name": "MCP: Query database with SQL",
307
+ "outputs": [
308
+ {
309
+ "name": "output",
310
+ "position": "top",
311
+ "type": {
312
+ "type": "None"
313
+ }
314
+ }
315
+ ],
316
+ "params": [],
317
+ "type": "basic"
318
+ },
319
+ "op_id": "LynxScribe > MCP: Query database with SQL",
320
+ "params": {},
321
+ "status": "done",
322
+ "title": "MCP: Query database with SQL"
323
+ },
324
+ "dragHandle": ".drag-handle",
325
+ "height": 152.0,
326
+ "id": "MCP: Query database with SQL 2",
327
+ "position": {
328
+ "x": -248.451978071668,
329
+ "y": 231.5655840074671
330
+ },
331
+ "type": "basic",
332
+ "width": 334.0
333
+ },
334
+ {
335
+ "data": {
336
+ "collapsed": true,
337
+ "display": null,
338
+ "error": null,
339
+ "input_metadata": [],
340
+ "meta": {
341
+ "categories": [
342
+ "LynxScribe"
343
+ ],
344
+ "color": "green",
345
+ "doc": null,
346
+ "id": "LynxScribe > MCP: Calculator",
347
+ "inputs": [],
348
+ "name": "MCP: Calculator",
349
+ "outputs": [
350
+ {
351
+ "name": "output",
352
+ "position": "top",
353
+ "type": {
354
+ "type": "None"
355
+ }
356
+ }
357
+ ],
358
+ "params": [],
359
+ "type": "basic"
360
+ },
361
+ "op_id": "LynxScribe > MCP: Calculator",
362
+ "params": {},
363
+ "status": "done",
364
+ "title": "MCP: Calculator"
365
+ },
366
+ "dragHandle": ".drag-handle",
367
+ "height": 200.0,
368
+ "id": "MCP: Calculator 1",
369
+ "position": {
370
+ "x": -527.6679408294542,
371
+ "y": 240.503939070944
372
+ },
373
+ "type": "basic",
374
+ "width": 200.0
375
+ },
376
+ {
377
+ "data": {
378
+ "collapsed": true,
379
+ "display": {
380
+ "dataframes": {
381
+ "service": {
382
+ "columns": [
383
+ "url"
384
+ ],
385
+ "data": [
386
+ [
387
+ "/api/service/lynxkite_graph_analytics/LynxScribe Task Solver/Demo.lynxkite.json/Chat frontend 1"
388
+ ]
389
+ ]
390
+ }
391
+ }
392
+ },
393
+ "error": null,
394
+ "input_metadata": [
395
+ {}
396
+ ],
397
+ "meta": {
398
+ "categories": [
399
+ "LynxScribe"
400
+ ],
401
+ "color": "gray",
402
+ "doc": null,
403
+ "id": "LynxScribe > Chat frontend",
404
+ "inputs": [
405
+ {
406
+ "name": "agent",
407
+ "position": "bottom",
408
+ "type": {
409
+ "type": "<class 'dict'>"
410
+ }
411
+ }
412
+ ],
413
+ "name": "Chat frontend",
414
+ "outputs": [],
415
+ "params": [],
416
+ "type": "service"
417
+ },
418
+ "op_id": "LynxScribe > Chat frontend",
419
+ "params": {},
420
+ "status": "done",
421
+ "title": "Chat frontend"
422
+ },
423
+ "dragHandle": ".drag-handle",
424
+ "height": 362.0,
425
+ "id": "Chat frontend 1",
426
+ "position": {
427
+ "x": -138.70099552129096,
428
+ "y": -642.4401477213354
429
+ },
430
+ "type": "service",
431
+ "width": 428.0
432
+ },
433
+ {
434
+ "data": {
435
+ "collapsed": true,
436
+ "display": null,
437
+ "error": null,
438
+ "input_metadata": [
439
+ {}
440
+ ],
441
+ "meta": {
442
+ "categories": [
443
+ "NetworkX",
444
+ "Algorithms",
445
+ "Link analysis",
446
+ "PageRank alg"
447
+ ],
448
+ "color": "orange",
449
+ "doc": null,
450
+ "id": "NetworkX > Algorithms > Link analysis > PageRank alg > PageRank",
451
+ "inputs": [
452
+ {
453
+ "name": "G",
454
+ "position": "left",
455
+ "type": {
456
+ "type": "<class 'networkx.classes.graph.Graph'>"
457
+ }
458
+ }
459
+ ],
460
+ "name": "PageRank",
461
+ "outputs": [
462
+ {
463
+ "name": "output",
464
+ "position": "right",
465
+ "type": {
466
+ "type": "<class 'networkx.classes.graph.Graph'>"
467
+ }
468
+ }
469
+ ],
470
+ "params": [
471
+ {
472
+ "default": "0.85",
473
+ "name": "alpha",
474
+ "type": {
475
+ "type": "float | None"
476
+ }
477
+ },
478
+ {
479
+ "default": "100",
480
+ "name": "max_iter",
481
+ "type": {
482
+ "type": "int | None"
483
+ }
484
+ },
485
+ {
486
+ "default": "1e-06",
487
+ "name": "tol",
488
+ "type": {
489
+ "type": "float | None"
490
+ }
491
+ },
492
+ {
493
+ "default": "weight",
494
+ "name": "weight",
495
+ "type": {
496
+ "type": "str | None"
497
+ }
498
+ }
499
+ ],
500
+ "type": "basic"
501
+ },
502
+ "op_id": "NetworkX > Algorithms > Link analysis > PageRank alg > PageRank",
503
+ "params": {
504
+ "alpha": "0.85",
505
+ "max_iter": "100",
506
+ "tol": "1e-06",
507
+ "weight": "weight"
508
+ },
509
+ "status": "done",
510
+ "title": "PageRank"
511
+ },
512
+ "dragHandle": ".drag-handle",
513
+ "height": 200.0,
514
+ "id": "PageRank 1",
515
+ "position": {
516
+ "x": -878.5796659405156,
517
+ "y": 369.96445264090244
518
+ },
519
+ "type": "basic",
520
+ "width": 200.0
521
+ },
522
+ {
523
+ "data": {
524
+ "collapsed": true,
525
+ "display": null,
526
+ "error": null,
527
+ "input_metadata": [],
528
+ "meta": {
529
+ "categories": [
530
+ "NetworkX",
531
+ "Generators",
532
+ "Social"
533
+ ],
534
+ "color": "orange",
535
+ "doc": null,
536
+ "id": "NetworkX > Generators > Social > Karate club graph",
537
+ "inputs": [],
538
+ "name": "Karate club graph",
539
+ "outputs": [
540
+ {
541
+ "name": "output",
542
+ "position": "right",
543
+ "type": {
544
+ "type": "<class 'networkx.classes.graph.Graph'>"
545
+ }
546
+ }
547
+ ],
548
+ "params": [],
549
+ "type": "basic"
550
+ },
551
+ "op_id": "NetworkX > Generators > Social > Karate club graph",
552
+ "params": {},
553
+ "status": "done",
554
+ "title": "Karate club graph"
555
+ },
556
+ "dragHandle": ".drag-handle",
557
+ "height": 200.0,
558
+ "id": "Karate club graph 1",
559
+ "position": {
560
+ "x": -1304.6391517192224,
561
+ "y": 585.0242219568652
562
+ },
563
+ "type": "basic",
564
+ "width": 200.0
565
+ },
566
+ {
567
+ "data": {
568
+ "collapsed": true,
569
+ "display": null,
570
+ "error": null,
571
+ "input_metadata": [
572
+ {}
573
+ ],
574
+ "meta": {
575
+ "categories": [
576
+ "NetworkX",
577
+ "Algorithms",
578
+ "Link prediction"
579
+ ],
580
+ "color": "orange",
581
+ "doc": null,
582
+ "id": "NetworkX > Algorithms > Link prediction > Common neighbor centrality",
583
+ "inputs": [
584
+ {
585
+ "name": "G",
586
+ "position": "left",
587
+ "type": {
588
+ "type": "<class 'networkx.classes.graph.Graph'>"
589
+ }
590
+ }
591
+ ],
592
+ "name": "Common neighbor centrality",
593
+ "outputs": [
594
+ {
595
+ "name": "output",
596
+ "position": "right",
597
+ "type": {
598
+ "type": "<class 'networkx.classes.graph.Graph'>"
599
+ }
600
+ }
601
+ ],
602
+ "params": [],
603
+ "type": "basic"
604
+ },
605
+ "op_id": "NetworkX > Algorithms > Link prediction > Common neighbor centrality",
606
+ "params": {},
607
+ "status": "done",
608
+ "title": "Common neighbor centrality"
609
+ },
610
+ "dragHandle": ".drag-handle",
611
+ "height": 130.0,
612
+ "id": "Common neighbor centrality 1",
613
+ "position": {
614
+ "x": -990.2453153930347,
615
+ "y": 587.3192401780905
616
+ },
617
+ "type": "basic",
618
+ "width": 341.0
619
+ },
620
+ {
621
+ "data": {
622
+ "__execution_delay": 0.0,
623
+ "collapsed": true,
624
+ "display": null,
625
+ "error": null,
626
+ "input_metadata": [],
627
+ "meta": {
628
+ "categories": [],
629
+ "color": "orange",
630
+ "doc": [
631
+ {
632
+ "kind": "text",
633
+ "value": "Read the contents of the a file into a `Bundle`."
634
+ },
635
+ {
636
+ "kind": "parameters",
637
+ "value": [
638
+ {
639
+ "annotation": "str",
640
+ "description": "Path to the file to import.",
641
+ "name": "file_path"
642
+ },
643
+ {
644
+ "annotation": "str",
645
+ "description": "Name to use for identifying the table in the bundle.",
646
+ "name": "table_name"
647
+ },
648
+ {
649
+ "annotation": "FileFormat",
650
+ "description": "Format of the file. Has to be one of the values in the `FileFormat` enum.",
651
+ "name": "file_format"
652
+ }
653
+ ]
654
+ },
655
+ {
656
+ "kind": "returns",
657
+ "value": [
658
+ {
659
+ "annotation": "<class 'lynxkite_graph_analytics.core.Bundle'>",
660
+ "description": "Bundle with a single table with the contents of the file.",
661
+ "name": "Bundle"
662
+ }
663
+ ]
664
+ }
665
+ ],
666
+ "id": "Import file",
667
+ "inputs": [],
668
+ "name": "Import file",
669
+ "outputs": [
670
+ {
671
+ "name": "output",
672
+ "position": "right",
673
+ "type": {
674
+ "type": "None"
675
+ }
676
+ }
677
+ ],
678
+ "params": [
679
+ {
680
+ "default": null,
681
+ "name": "file_path",
682
+ "type": {
683
+ "type": "<class 'str'>"
684
+ }
685
+ },
686
+ {
687
+ "default": null,
688
+ "name": "table_name",
689
+ "type": {
690
+ "type": "<class 'str'>"
691
+ }
692
+ },
693
+ {
694
+ "default": "csv",
695
+ "name": "file_format",
696
+ "type": {
697
+ "enum": [
698
+ "csv",
699
+ "parquet",
700
+ "json",
701
+ "excel"
702
+ ]
703
+ }
704
+ },
705
+ {
706
+ "default": "csv",
707
+ "groups": {
708
+ "csv": [
709
+ {
710
+ "default": "<from file>",
711
+ "name": "columns",
712
+ "type": {
713
+ "type": "<class 'str'>"
714
+ }
715
+ },
716
+ {
717
+ "default": "<auto>",
718
+ "name": "separator",
719
+ "type": {
720
+ "type": "<class 'str'>"
721
+ }
722
+ }
723
+ ],
724
+ "excel": [
725
+ {
726
+ "default": "Sheet1",
727
+ "name": "sheet_name",
728
+ "type": {
729
+ "type": "<class 'str'>"
730
+ }
731
+ }
732
+ ],
733
+ "json": [],
734
+ "parquet": []
735
+ },
736
+ "name": "file_format_group",
737
+ "selector": {
738
+ "default": "csv",
739
+ "name": "file_format",
740
+ "type": {
741
+ "enum": [
742
+ "csv",
743
+ "parquet",
744
+ "json",
745
+ "excel"
746
+ ]
747
+ }
748
+ },
749
+ "type": "group"
750
+ }
751
+ ],
752
+ "type": "basic"
753
+ },
754
+ "op_id": "Import file",
755
+ "params": {
756
+ "file_format": "csv",
757
+ "file_format_group": "csv",
758
+ "file_path": "uploads/molecules2.csv",
759
+ "table_name": "molecules"
760
+ },
761
+ "status": "done",
762
+ "title": "Import file"
763
+ },
764
+ "dragHandle": ".drag-handle",
765
+ "height": 393.0,
766
+ "id": "Import file 1",
767
+ "position": {
768
+ "x": -1411.4491034838866,
769
+ "y": 772.1675932822765
770
+ },
771
+ "type": "basic",
772
+ "width": 369.0
773
+ },
774
+ {
775
+ "data": {
776
+ "__execution_delay": 0.0,
777
+ "collapsed": true,
778
+ "display": null,
779
+ "error": null,
780
+ "input_metadata": [
781
+ {
782
+ "dataframes": {
783
+ "molecules": {
784
+ "columns": [
785
+ "name",
786
+ "smiles"
787
+ ],
788
+ "key": "molecules"
789
+ }
790
+ },
791
+ "other": {},
792
+ "relations": []
793
+ }
794
+ ],
795
+ "meta": {
796
+ "categories": [],
797
+ "color": "orange",
798
+ "doc": [
799
+ {
800
+ "kind": "text",
801
+ "value": "Run a SQL query on the DataFrames in the bundle. Save the results as a new DataFrame."
802
+ }
803
+ ],
804
+ "id": "SQL",
805
+ "inputs": [
806
+ {
807
+ "name": "bundle",
808
+ "position": "left",
809
+ "type": {
810
+ "type": "<class 'lynxkite_graph_analytics.core.Bundle'>"
811
+ }
812
+ }
813
+ ],
814
+ "name": "SQL",
815
+ "outputs": [
816
+ {
817
+ "name": "output",
818
+ "position": "right",
819
+ "type": {
820
+ "type": "None"
821
+ }
822
+ }
823
+ ],
824
+ "params": [
825
+ {
826
+ "default": null,
827
+ "name": "query",
828
+ "type": {
829
+ "format": "textarea"
830
+ }
831
+ },
832
+ {
833
+ "default": "result",
834
+ "name": "save_as",
835
+ "type": {
836
+ "type": "<class 'str'>"
837
+ }
838
+ }
839
+ ],
840
+ "type": "basic"
841
+ },
842
+ "op_id": "SQL",
843
+ "params": {
844
+ "query": "select *",
845
+ "save_as": "result"
846
+ },
847
+ "status": "done",
848
+ "title": "SQL"
849
+ },
850
+ "dragHandle": ".drag-handle",
851
+ "height": 200.0,
852
+ "id": "SQL 1",
853
+ "position": {
854
+ "x": -931.2061769202694,
855
+ "y": 766.0054007337461
856
+ },
857
+ "type": "basic",
858
+ "width": 200.0
859
+ },
860
+ {
861
+ "data": {
862
+ "__execution_delay": 0.0,
863
+ "collapsed": true,
864
+ "display": null,
865
+ "error": null,
866
+ "input_metadata": [
867
+ {
868
+ "dataframes": {
869
+ "molecules": {
870
+ "columns": [
871
+ "name",
872
+ "smiles"
873
+ ],
874
+ "key": "molecules"
875
+ },
876
+ "result": {
877
+ "columns": [],
878
+ "key": "result"
879
+ }
880
+ },
881
+ "other": {},
882
+ "relations": []
883
+ }
884
+ ],
885
+ "meta": {
886
+ "categories": [],
887
+ "color": "orange",
888
+ "doc": [
889
+ {
890
+ "kind": "text",
891
+ "value": "Run a SQL query on the DataFrames in the bundle. Save the results as a new DataFrame."
892
+ }
893
+ ],
894
+ "id": "SQL",
895
+ "inputs": [
896
+ {
897
+ "name": "bundle",
898
+ "position": "left",
899
+ "type": {
900
+ "type": "<class 'lynxkite_graph_analytics.core.Bundle'>"
901
+ }
902
+ }
903
+ ],
904
+ "name": "SQL",
905
+ "outputs": [
906
+ {
907
+ "name": "output",
908
+ "position": "right",
909
+ "type": {
910
+ "type": "None"
911
+ }
912
+ }
913
+ ],
914
+ "params": [
915
+ {
916
+ "default": null,
917
+ "name": "query",
918
+ "type": {
919
+ "format": "textarea"
920
+ }
921
+ },
922
+ {
923
+ "default": "result",
924
+ "name": "save_as",
925
+ "type": {
926
+ "type": "<class 'str'>"
927
+ }
928
+ }
929
+ ],
930
+ "type": "basic"
931
+ },
932
+ "op_id": "SQL",
933
+ "params": {
934
+ "query": "select *",
935
+ "save_as": "result"
936
+ },
937
+ "status": "done",
938
+ "title": "SQL"
939
+ },
940
+ "dragHandle": ".drag-handle",
941
+ "height": 200.0,
942
+ "id": "SQL 2",
943
+ "position": {
944
+ "x": -633.7783633982368,
945
+ "y": 767.4541281209835
946
+ },
947
+ "type": "basic",
948
+ "width": 200.0
949
+ },
950
+ {
951
+ "data": {
952
+ "collapsed": true,
953
+ "display": null,
954
+ "error": null,
955
+ "input_metadata": [],
956
+ "meta": {
957
+ "categories": [
958
+ "LynxScribe"
959
+ ],
960
+ "color": "green",
961
+ "doc": null,
962
+ "id": "LynxScribe > MCP: Financial data",
963
+ "inputs": [],
964
+ "name": "MCP: Financial data",
965
+ "outputs": [
966
+ {
967
+ "name": "output",
968
+ "position": "top",
969
+ "type": {
970
+ "type": "None"
971
+ }
972
+ }
973
+ ],
974
+ "params": [],
975
+ "type": "basic"
976
+ },
977
+ "op_id": "LynxScribe > MCP: Financial data",
978
+ "params": {},
979
+ "status": "done",
980
+ "title": "MCP: Financial data"
981
+ },
982
+ "dragHandle": ".drag-handle",
983
+ "height": 175.0,
984
+ "id": "MCP: Financial data 1",
985
+ "position": {
986
+ "x": 158.4345441423415,
987
+ "y": 229.50555825204884
988
+ },
989
+ "type": "basic",
990
+ "width": 242.0
991
+ },
992
+ {
993
+ "data": {
994
+ "__execution_delay": 0.0,
995
+ "display": null,
996
+ "error": null,
997
+ "input_metadata": [],
998
+ "meta": {
999
+ "categories": [
1000
+ "LynxScribe"
1001
+ ],
1002
+ "color": "green",
1003
+ "doc": null,
1004
+ "id": "LynxScribe > MCP: Search web",
1005
+ "inputs": [],
1006
+ "name": "MCP: Search web",
1007
+ "outputs": [
1008
+ {
1009
+ "name": "output",
1010
+ "position": "top",
1011
+ "type": {
1012
+ "type": "None"
1013
+ }
1014
+ }
1015
+ ],
1016
+ "params": [
1017
+ {
1018
+ "default": "Google",
1019
+ "name": "engine",
1020
+ "type": {
1021
+ "enum": [
1022
+ "Google",
1023
+ "Bing",
1024
+ "DuckDuckGo"
1025
+ ]
1026
+ }
1027
+ }
1028
+ ],
1029
+ "type": "basic"
1030
+ },
1031
+ "op_id": "LynxScribe > MCP: Search web",
1032
+ "params": {
1033
+ "engine": "DuckDuckGo"
1034
+ },
1035
+ "status": "done",
1036
+ "title": "MCP: Search web"
1037
+ },
1038
+ "dragHandle": ".drag-handle",
1039
+ "height": 200.0,
1040
+ "id": "MCP: Search web 1",
1041
+ "position": {
1042
+ "x": 540.4008718602887,
1043
+ "y": 249.69009586836748
1044
+ },
1045
+ "type": "basic",
1046
+ "width": 200.0
1047
+ }
1048
+ ],
1049
+ "paused": false
1050
+ }
examples/LynxScribe/MCP/demo.py ADDED
@@ -0,0 +1,211 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import enum
2
+ from lynxkite_core import ops
3
+ from lynxkite_graph_analytics import core
4
+ import fastapi
5
+ from lynxscribe.core.llm.base import get_llm_engine
6
+ from lynxscribe.core.models.prompts import ChatCompletionPrompt
7
+ import contextlib
8
+ import mcp
9
+ from mcp.client.stdio import stdio_client
10
+ from lynxscribe.components.task_solver import TaskSolver
11
+ from lynxscribe.core.models.prompts import Function, Tool
12
+
13
+ lsop = ops.op_registration(
14
+ "LynxKite Graph Analytics", "LynxScribe", dir="bottom-to-top", color="blue"
15
+ )
16
+
17
+ dsop = ops.op_registration("LynxKite Graph Analytics", "Data Science")
18
+
19
+ Placeholder = str
20
+
21
+
22
+ @lsop("Chat frontend", color="gray", outputs=[], view="service")
23
+ def chat_frontend(agent: dict):
24
+ tools = [tool["command"] for tool in agent["agent"]["tools"] if tool]
25
+ return ChatAPIService(agent["agent"]["system_prompt"], tools)
26
+
27
+
28
+ @lsop("Agent")
29
+ def agent(
30
+ tools: list[dict],
31
+ *,
32
+ purpose: str = "",
33
+ description: ops.LongStr = "This agent helps with various tasks.",
34
+ system_prompt: ops.LongStr = "You are a helpful assistant.",
35
+ ):
36
+ prompt = [system_prompt]
37
+ for tool in tools:
38
+ if tool.get("extra_prompt"):
39
+ prompt.append(tool["extra_prompt"])
40
+ return {"agent": {"system_prompt": "\n".join(prompt), "tools": tools}}
41
+
42
+
43
+ @lsop("MCP: Custom", color="green")
44
+ def custom_mcp(*, command: str, extra_prompt: ops.LongStr):
45
+ if command.strip():
46
+ return {"command": command.strip().split(), "extra_prompt": extra_prompt}
47
+
48
+
49
+ @lsop("MCP: Query database with SQL", color="green")
50
+ def sql_tool(db: Placeholder):
51
+ return {
52
+ "command": ["npx", "-y", "mcp-sqlite", db],
53
+ "extra_prompt": """
54
+ When using the database, retrieve the list of tables, investigate the schema of the relevant tables
55
+ and use SQL queries. Always set a limit of 10 when using `read_records`. Unfortunately, `read_records`
56
+ is out of order currently. Please use `query` instead."
57
+ """.strip(),
58
+ }
59
+
60
+
61
+ @ops.output_position(output="top")
62
+ @dsop("Database")
63
+ def db(data_pipeline: list[core.Bundle]):
64
+ # The source of this file: https://github.com/biggraph/lynxscribe/pull/416
65
+ return "movie_data.sqlite.db"
66
+
67
+
68
+ class MCPSearchEngine(str, enum.Enum):
69
+ Google = "Google"
70
+ Bing = "Bing"
71
+ DuckDuckGo = "DuckDuckGo"
72
+
73
+
74
+ @lsop("MCP: Search web", color="green")
75
+ def web_search(*, engine: MCPSearchEngine = MCPSearchEngine.Google):
76
+ match engine:
77
+ case MCPSearchEngine.Google:
78
+ return {"command": ["npx", "-y", "https://github.com/pskill9/web-search"]}
79
+ case MCPSearchEngine.Bing:
80
+ return {"command": ["uvx", "bing-search-mcp"]}
81
+ case MCPSearchEngine.DuckDuckGo:
82
+ return {"command": ["uvx", "duckduckgo-mcp-server"]}
83
+
84
+
85
+ @lsop("MCP: Financial data", color="green")
86
+ def financial_data():
87
+ return {"command": ["uvx", "investor-agent"]}
88
+
89
+
90
+ @lsop("MCP: Calculator", color="green")
91
+ def calculator():
92
+ return {"command": ["uvx", "mcp-server-calculator"]}
93
+
94
+
95
+ class ChatAPIService:
96
+ def __init__(self, prompt: str, tools: list[list[str]]):
97
+ self.prompt = prompt
98
+ self.tools = tools
99
+ self.mcp_client = None
100
+ self.task_solver = None
101
+
102
+ async def init(self):
103
+ if self.task_solver is not None:
104
+ return
105
+ self.mcp_client = MultiMCPClient()
106
+ await self.mcp_client.connect(self.tools)
107
+ self.task_solver = TaskSolver(
108
+ llm=get_llm_engine(name="openai"),
109
+ model="gpt-4.1-nano",
110
+ initial_messages=[self.prompt],
111
+ functions=self.mcp_client.tools,
112
+ tool_choice="required",
113
+ temperature=0.0,
114
+ max_tool_call_steps=999,
115
+ )
116
+
117
+ async def get(self, request: fastapi.Request, path: str) -> dict:
118
+ if path == "models":
119
+ return {
120
+ "object": "list",
121
+ "data": [
122
+ {
123
+ "id": "LynxScribe",
124
+ "object": "model",
125
+ "created": 0,
126
+ "owned_by": "lynxkite",
127
+ "meta": {"profile_image_url": "https://lynxkite.com/favicon.png"},
128
+ }
129
+ ],
130
+ }
131
+ return {"error": "Not found"}
132
+
133
+ async def post(self, request: fastapi.Request, path: str) -> dict:
134
+ if path == "chat/completions":
135
+ request = await request.json()
136
+ assert not request["stream"]
137
+ await self.init()
138
+ res = await self.task_solver.solve(request["messages"][-1]["content"])
139
+ return {"choices": [{"message": {"role": "assistant", "content": res}}]}
140
+
141
+ return {"error": "Not found"}
142
+
143
+ async def get_chat_api_response(self, request):
144
+ request = ChatCompletionPrompt(**request)
145
+ response = await self.chat_api.answer(request, stream=False)
146
+ return response.model_dump()
147
+
148
+
149
+ class MCPClient:
150
+ def __init__(self):
151
+ self.session: mcp.ClientSession | None = None
152
+ self.exit_stack = contextlib.AsyncExitStack()
153
+
154
+ async def connect_to_server(self, config):
155
+ """Connect to an MCP server."""
156
+ server_params = mcp.StdioServerParameters(**config)
157
+ stdio_transport = await self.exit_stack.enter_async_context(stdio_client(server_params))
158
+ self.stdio, self.write = stdio_transport
159
+ self.session = await self.exit_stack.enter_async_context(
160
+ mcp.ClientSession(self.stdio, self.write)
161
+ )
162
+ await self.session.initialize()
163
+ self.connected = True
164
+ response = await self.session.list_tools()
165
+ self.tools = [self.to_func(tool) for tool in response.tools]
166
+
167
+ async def run_tool(self, tool_name: str, tool_args: dict):
168
+ print(f"Calling tool {tool_name} with args {tool_args}")
169
+ return await self.session.call_tool(tool_name, tool_args)
170
+
171
+ def to_func(self, tool):
172
+ """Convert a tool to a callable function."""
173
+
174
+ async def func(**kwargs):
175
+ res = await self.run_tool(tool.name, kwargs)
176
+ return res.content[0].text
177
+
178
+ func.__name__ = tool.name
179
+ func._tool = Tool(
180
+ type="function",
181
+ function=Function(
182
+ name=tool.name,
183
+ description=tool.description,
184
+ parameters=tool.inputSchema,
185
+ ),
186
+ )
187
+ return func
188
+
189
+ async def cleanup(self):
190
+ await self.exit_stack.aclose()
191
+
192
+
193
+ class MultiMCPClient:
194
+ """A client that can connect to multiple MCP servers."""
195
+
196
+ async def connect(self, servers: list[str]):
197
+ self.clients = []
198
+ for server in servers:
199
+ client = MCPClient()
200
+ [command, *args] = server
201
+ await client.connect_to_server({"command": command, "args": args})
202
+ self.clients.append(client)
203
+ tools = []
204
+ for client in self.clients:
205
+ tools.extend(client.tools)
206
+ self.tools = tools
207
+
208
+ async def cleanup(self):
209
+ # Reverse cleanup as in https://github.com/microsoft/semantic-kernel/issues/12627.
210
+ for client in reversed(self.clients):
211
+ await client.cleanup()
examples/LynxScribe/MCP/demo.sh ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ #!/bin/bash -xue
2
+ xh POST 'http://localhost:8000/api/service/lynxkite_graph_analytics/LynxScribe%20Task%20Solver/Demo.lynxkite.json/Chat%20frontend%201/chat/completions' \
3
+ model=LynxScribe \
4
+ stream:=false \
5
+ messages:='[{"role": "user", "content": "Investigate the database schema, then use a series of SQL queries to find movies featuring Bette Davis and Ann Sheridan together."}]'
examples/LynxScribe/MCP/requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ mcp
2
+ streamlit
3
+ ../../lynxscribe
examples/LynxScribe/MCP/ui/main.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import requests
3
+
4
+ API_URL = "http://localhost:8000/api/service/lynxkite_graph_analytics/LynxScribe%20Task%20Solver/Demo.lynxkite.json/Chat%20frontend%201/chat/completions"
5
+
6
+ st.title("LynxScribe Task Solver")
7
+
8
+ examples = [
9
+ "Which movies feature Bette Davis and Ann Sheridan together? Include the year of the movie's release.",
10
+ "Find the value of x given that 4*x^4 = 44.",
11
+ ]
12
+ question = st.text_area("Your question:", value=examples[0])
13
+ payload = {
14
+ "model": "LynxScribe",
15
+ "stream": False,
16
+ "messages": [{"role": "user", "content": question}],
17
+ }
18
+ response = requests.post(API_URL, json=payload)
19
+ if response.ok:
20
+ st.write("\n".join(c["message"]["content"] for c in response.json()["choices"]))
21
+ else:
22
+ st.error(f"Error: {response.status_code}")