From e7bdeaaf1c4e037e1593158a5438d68035aa3ac2 Mon Sep 17 00:00:00 2001 From: Dimitri Glazkov Date: Mon, 17 Jun 2024 16:07:16 -0700 Subject: [PATCH] Document Joiner. (#2183) Fixes #2112. --- .../website/src/docs/kits/agents/index.md | 23 +- .../src/static/boards/joiner-example.bgl.json | 208 ++++++++++++++++++ .../static/boards/new-joiner-port.bgl.json | 59 +++++ .../static/images/agent-kit/joiner-merge.png | Bin 0 -> 6557 bytes 4 files changed, 287 insertions(+), 3 deletions(-) create mode 100644 packages/website/src/static/boards/joiner-example.bgl.json create mode 100644 packages/website/src/static/boards/new-joiner-port.bgl.json create mode 100644 packages/website/src/static/images/agent-kit/joiner-merge.png diff --git a/packages/website/src/docs/kits/agents/index.md b/packages/website/src/docs/kits/agents/index.md index e00eb0698c9..e7268593ba3 100644 --- a/packages/website/src/docs/kits/agents/index.md +++ b/packages/website/src/docs/kits/agents/index.md @@ -232,8 +232,25 @@ When placed into the flow of work, Human shows the intermediate output and asks ## Joiner -TO DO: +While not powered by an LLM or representing a real person, Joiner is an essential part of any team of workers. Depending on how it is configured, Joiner acts a helper that, respectively, joins or merges conversation contexts. -- Describe how joiner works +{{ "/breadboard/static/boards/joiner-example.bgl.json" | board }} -- Create a graph that joins contexts. +When the flow of work splits across multiple workers, we can rely on Joiner to bring it all together. + +When first added to the board, Joiner has no incoming ports: we have to explicitly inform it about all the context we'd like to join. To do so, use the "ad hoc" wiring technique in Breadboard. Drag a wire from each outgoing port we want to be joined into the center of the Joiner, then release. A small dialog box will pop up asking to name the port. Give it an informative name (can only contain lowercase alphanumeric characters, dashes, or numbers) and the wire will appear. + +{{ "/breadboard/static/boards/new-joiner-port.bgl.json" | board }} + +Joiner has one configuration option, a checkbox on whether or not to merge the last items of all incoming context into one. + +![Joiner Merge option](/breadboard/static/images/agent-kit/joiner-merge.png) + +When that checkbox is not checked, joiner will take all of the incoming conversation contexts and just string them together into one mega conversation context. + +When the checkbox is checked, it will only take the last item of each conversation context and turn them into a new conversation context that contains only one item, merging them as parts of that item. + +In either case, the order of items (or contexts) is determined by the alphabetical sort of the incoming ports for the Joiner. + +> [!TIP] +> It's a good practice to name ports in a way that makes the order evident. Like in the example above, the ports are named "a-picture", "b-voice", and "c-text" to ensure that the picture goes first, followed by voice and then text. diff --git a/packages/website/src/static/boards/joiner-example.bgl.json b/packages/website/src/static/boards/joiner-example.bgl.json new file mode 100644 index 00000000000..40e8054ddf3 --- /dev/null +++ b/packages/website/src/static/boards/joiner-example.bgl.json @@ -0,0 +1,208 @@ +{ + "title": "Card Maker", + "version": "0.0.1", + "metadata": { + "comments": [ + { + "id": "comment-571ff92f", + "text": "Writes contents of \na game card", + "metadata": { + "visual": { + "x": -129, + "y": 70, + "collapsed": false + } + } + }, + { + "id": "comment-6ce6abeb", + "text": "Uses the contents to craft a prompt and create picture.", + "metadata": { + "visual": { + "x": -77, + "y": -175, + "collapsed": false + } + } + }, + { + "id": "comment-b99d3821", + "text": "Narrates the text \nof the card", + "metadata": { + "visual": { + "x": 50, + "y": -29, + "collapsed": false + } + } + }, + { + "id": "comment-6907d9cd", + "text": "Joins picture, voice, and text into one card.", + "metadata": { + "visual": { + "x": 268, + "y": 113, + "collapsed": false + } + } + } + ] + }, + "edges": [ + { + "from": "input", + "to": "specialist-42832612", + "out": "context", + "in": "in" + }, + { + "from": "specialist-42832612", + "to": "specialist-5b7a9d43", + "out": "out", + "in": "in" + }, + { + "from": "specialist-42832612", + "to": "specialist-6a61c0b5", + "out": "out", + "in": "in" + }, + { + "from": "specialist-42832612", + "to": "joiner-22b013c9", + "out": "out", + "in": "c-text" + }, + { + "from": "specialist-5b7a9d43", + "to": "joiner-22b013c9", + "out": "out", + "in": "a-picture" + }, + { + "from": "specialist-6a61c0b5", + "to": "joiner-22b013c9", + "out": "out", + "in": "b-voice" + }, + { + "from": "joiner-22b013c9", + "to": "output", + "out": "context", + "in": "context" + } + ], + "nodes": [ + { + "type": "input", + "id": "input", + "configuration": { + "schema": { + "properties": { + "context": { + "type": "array", + "title": "Context", + "examples": [], + "items": { + "type": "object", + "behavior": ["llm-content"] + }, + "default": "[{\"role\":\"user\",\"parts\":[{\"text\":\"\"}]}]" + } + }, + "type": "object", + "required": [] + } + }, + "metadata": { + "visual": { + "x": -213, + "y": -127, + "collapsed": false + } + } + }, + { + "type": "output", + "id": "output", + "configuration": { + "schema": { + "properties": { + "context": { + "type": "array", + "title": "Context", + "examples": [], + "items": { + "type": "object", + "behavior": ["llm-content"] + }, + "default": "null" + } + }, + "type": "object", + "required": [] + } + }, + "metadata": { + "visual": { + "x": 369, + "y": -148, + "collapsed": false + } + } + }, + { + "id": "specialist-42832612", + "type": "specialist", + "metadata": { + "visual": { + "x": -167, + "y": 126, + "collapsed": false + }, + "title": "Writer", + "logLevel": "debug" + } + }, + { + "id": "specialist-5b7a9d43", + "type": "specialist", + "metadata": { + "visual": { + "x": 45, + "y": -123, + "collapsed": false + }, + "title": "Illustrator", + "logLevel": "debug" + } + }, + { + "id": "specialist-6a61c0b5", + "type": "specialist", + "metadata": { + "visual": { + "x": 90, + "y": 24, + "collapsed": false + }, + "title": "Narrator", + "logLevel": "debug" + } + }, + { + "id": "joiner-22b013c9", + "type": "joiner", + "metadata": { + "visual": { + "x": 354, + "y": 2, + "collapsed": false + }, + "title": "Card Maker", + "logLevel": "debug" + } + } + ] +} diff --git a/packages/website/src/static/boards/new-joiner-port.bgl.json b/packages/website/src/static/boards/new-joiner-port.bgl.json new file mode 100644 index 00000000000..046e0da6443 --- /dev/null +++ b/packages/website/src/static/boards/new-joiner-port.bgl.json @@ -0,0 +1,59 @@ +{ + "title": "Wiring Joiner ", + "version": "0.0.1", + "metadata": { + "comments": [ + { + "id": "comment-f59dbc67", + "text": "Drag a wire from \"Context Out\" ...", + "metadata": { + "visual": { + "x": 19, + "y": -46, + "collapsed": false + } + } + }, + { + "id": "comment-58b1c17b", + "text": "... to the center of Joiner and then let go. You will then be asked to name the incoming port for this wire.", + "metadata": { + "visual": { + "x": 259, + "y": -1, + "collapsed": false + } + } + } + ] + }, + "edges": [], + "nodes": [ + { + "id": "specialist-be4d952e", + "type": "specialist", + "metadata": { + "visual": { + "x": -39, + "y": 8, + "collapsed": false + }, + "title": "Illustrator", + "logLevel": "debug" + } + }, + { + "id": "joiner-ddb55d72", + "type": "joiner", + "metadata": { + "visual": { + "x": 221, + "y": -71, + "collapsed": false + }, + "title": "Card Maker", + "logLevel": "debug" + } + } + ] +} diff --git a/packages/website/src/static/images/agent-kit/joiner-merge.png b/packages/website/src/static/images/agent-kit/joiner-merge.png new file mode 100644 index 0000000000000000000000000000000000000000..bcc437912de42efdd63f883544d254bafbac761e GIT binary patch literal 6557 zcmcIIcRXBMx5Egd#Yoe_FeJLs1*7*|qDF{17@~I>y&JuSAWDcJ5{N~JAd+k;BDtqs>cZ|+GHEIe*3J?fHt)Z^02LcgE0gVOA@OZ2j9UZS{ z8Ql7@gSG2pujK&i(@ay-S$gO!*q{wmsM}iSNEOd|S|!j`=8X2ePZR6oWWPE2tK}rO zg1Ol5+Q;_`pG!9phS0ftNm;dPn@xK(EOM==W zdP7d`L0W|XjT3h>#Bj?Wf>}*C$u*G7F}d0Lh?T?fcg--1^8hs4ondQ*Bm29FS( zP`0$zh}P6rhu((sfCBRVKy0U`8;02}VVQTZdY`ejYmAjk3J6Th028 zi)^$s%-dzK)5;Z@nd=S$L*t20->djKp;G30E74VNu$6sAR@3` z30y50_S^MnBMnLrrQ2mcEO z8U7|z&{xvX0KWRx9%!_S=Ob6I&xT)s;1PYbH!$)t($bW&c6Am&*|=Jv1u)KTzga*? zj1&MmqrFh97-uIJPbrKH{7(ug0RD|ez*+w!@p6=b8)@mVD!F=~S;Yke1q9);6s)YQ zNDmuZDLrM?zuAG74E&Lomzxv<@%Zs$fyW{Ot{!#>AxTL|grG1&SePH6;P>=(@j_wv zT|C+U67nxO%4kn(4|_K+dsi3M-*Qn_uHIfUaQJUU|9<`&CmLh_A5AWvf13pui1^)u z5E2kX{987_iu{e0(y_;&os5<3odNd%I%MyNBmX4-A07Wu_zy;-|1gROiTsoEA3gt_ z^S&qAL&?<{(C8)mpTPXh{Ljw68Ig$JhX2D6e|h;&EZ}BY3MAs+A(N#rbFcOSfv#6; zC@UCXh&FP;X&f4Kk=8zT&Xcu&{oYDCn*7m?97demTzv{Cm|_Uk<2V|(dmhQ;iWAE5TPr=B%XEDEO&&TsE{YIc)di0m*$h12=_J&TrE|gp_jQe|6U5q%7m{F0nbwJdtt3|?m>+)^ zItMV!bPMq!0}wh>HwCp-)_~{S1qs@$$F0-5%74u9~xCceZP@WWdqXW7IbkmKqkYt$?{WSvEptH!G4kkod^?+2-uSwzCJeJ1Sjtl?BvutYYQ&G(Lvr@S*% zJ}e|kQxwWx950~8(HYcNwUO>dE+2k4C}Y}b)ku&ny#kGVnlc9?1r{wqa}Dd|l%D-! z8M%OqzW5M6E78373I@jOHXBM7#bBG+DvQ18p$<4n?jn8Jz9iR{1e@V|IBu6s_ITs{ zSd@Kn)@|fY`&HGR7Q%)9owZkmZBEtwwm;x}(=eZ2{yL-Pm({ajl+WxM`o$+B0Q30y znvdsiEKNP0c`x`p_`>&i@ria@2a~JQDm0IXMEZC(oS({fL7}{UJ{DD4^ps*b$MfEu z&H4qtJ|eQ4(0h00NSIg+O`OGgDRXMSd;Gy}L-|rpF+YR-vv_yY(X>A*mb>_v&dGGa z{Ehgqrik(9^@^71=B!<-C^EZ7$zU?WGP#fG?^ujjRhV>_GzCnmB}v0y-kBN*M?-y_vDBYfwROy-!Rz(oo&=% zOP&W!;O<5L0J4glJzg-(HxTpkO+|A<%96xPfc1%@Jf21lcgy|L^#>7?E{*-9#M++I zzRT3%m!%#Vd4Ij{yrvz5NilJ4^2ThplHngZzD2M81X2U_Jn)d5MrJ?RcL3w^MOCs>W!Sse0`Aj}hmvy0%Rz@P6rNpZMgZMmi!OMsoi+BC$Gg4?@-xVN}DV-&z)dSSScQ-fvkTM5ay z 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 N(NMXkT&`#t_Fs9Z0t5g6 literal 0 HcmV?d00001