From 2c47707b5d69df88f0e0d2e98765ed92b756446b Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Mon, 11 Nov 2024 13:01:58 -0800 Subject: [PATCH 01/11] Fix for environment detection in barebones environments. Missing import error catch in environment detection. --- guidance/visual/_environment.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/guidance/visual/_environment.py b/guidance/visual/_environment.py index ce35a70af..6edfbd680 100644 --- a/guidance/visual/_environment.py +++ b/guidance/visual/_environment.py @@ -104,6 +104,8 @@ def _detect_ipython(flags: EnvFlags) -> bool: found = get_ipython() is not None except NameError: # pragma: no cover pass + except ImportError: # pragma: no cover + pass return found @@ -131,6 +133,8 @@ def _detect_ipython_zmq(flags: EnvFlags) -> bool: found = False # Other type (?) except NameError: # pragma: no cover found = False # Probably standard Python interpreter + except ImportError: # pragma: no cover + found = False # Probably standard Python interpreter flags.is_notebook |= found return found \ No newline at end of file From 11c60b14f96a02bb1906fd54d1c88d0ac629e65a Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Mon, 11 Nov 2024 13:07:27 -0800 Subject: [PATCH 02/11] Minor clean-up of env detection. Moved exceptions catch into one line. --- guidance/visual/_environment.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/guidance/visual/_environment.py b/guidance/visual/_environment.py index 6edfbd680..fc10b35cc 100644 --- a/guidance/visual/_environment.py +++ b/guidance/visual/_environment.py @@ -102,9 +102,7 @@ def _detect_ipython(flags: EnvFlags) -> bool: try: from IPython import get_ipython found = get_ipython() is not None - except NameError: # pragma: no cover - pass - except ImportError: # pragma: no cover + except (NameError, ImportError): # pragma: no cover pass return found @@ -131,9 +129,7 @@ def _detect_ipython_zmq(flags: EnvFlags) -> bool: found = False # Terminal running IPython else: found = False # Other type (?) - except NameError: # pragma: no cover - found = False # Probably standard Python interpreter - except ImportError: # pragma: no cover + except (NameError, ImportError): # pragma: no cover found = False # Probably standard Python interpreter flags.is_notebook |= found From 29c1ac47dd1df5d8b1f9c7227f4acce371fe16ef Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Thu, 6 Feb 2025 13:54:21 -0800 Subject: [PATCH 03/11] Package rename for JS package in stitch. We need to deploy to NPM within @guidance-ai org. This requires some additional changes in the stitch package. --- packages/python/stitch/docs/source/installing.rst | 2 +- packages/python/stitch/package.json | 4 ++-- packages/python/stitch/pyproject.toml | 8 ++++---- packages/python/stitch/src/plugin.ts | 2 +- packages/python/stitch/stitch/_frontend.py | 4 ++-- packages/python/stitch/stitch/_version.py | 2 +- packages/python/stitch/stitch/nbextension/extension.js | 2 +- packages/python/stitch/webpack.config.js | 4 ++-- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/python/stitch/docs/source/installing.rst b/packages/python/stitch/docs/source/installing.rst index e5f8ad74f..b1e782f00 100644 --- a/packages/python/stitch/docs/source/installing.rst +++ b/packages/python/stitch/docs/source/installing.rst @@ -25,7 +25,7 @@ notebook (as opposed to Jupyterlab), run:: with the `appropriate flag`_. If you are using Jupyterlab, install the extension with:: - jupyter labextension install stitch + jupyter labextension install @guidance-ai/stitch If you are installing using conda, these commands should be unnecessary, but If you need to run them the commands should be the same (just make sure you choose the diff --git a/packages/python/stitch/package.json b/packages/python/stitch/package.json index b510ce5d5..0827aad9c 100644 --- a/packages/python/stitch/package.json +++ b/packages/python/stitch/package.json @@ -1,6 +1,6 @@ { - "name": "stitch", - "version": "0.1.0", + "name": "@guidance-ai/stitch", + "version": "0.1.1", "description": "Bidirectional comms for Jupyter and JavaScript.", "keywords": [ "jupyter", diff --git a/packages/python/stitch/pyproject.toml b/packages/python/stitch/pyproject.toml index 7712ab07f..2452e969c 100644 --- a/packages/python/stitch/pyproject.toml +++ b/packages/python/stitch/pyproject.toml @@ -37,7 +37,7 @@ classifiers = [ dependencies = [ "ipywidgets>=8.0.0", ] -version = "0.1.0" +version = "0.1.1" [project.optional-dependencies] docs = [ @@ -75,8 +75,8 @@ packages = ["stitch"] [tool.hatch.build.targets.wheel.shared-data] "stitch/nbextension" = "share/jupyter/nbextensions/stitch" -"stitch/labextension" = "share/jupyter/labextensions/stitch" -"./install.json" = "share/jupyter/labextensions/stitch/install.json" +"stitch/labextension" = "share/jupyter/labextensions/@guidance-ai/stitch" +"./install.json" = "share/jupyter/labextensions/@guidance-ai/stitch/install.json" "./stitch.json" = "etc/jupyter/nbconfig/notebook.d/stitch.json" [tool.hatch.build.targets.sdist] @@ -114,7 +114,7 @@ file = [ ] [tool.tbump.version] -current = "0.1.0.dev0" +current = "0.1.1" regex = "(?P\\d+)\\.(?P\\d+)\\.(?P\\d+)((?Pa|b|rc|.dev)(?P\\d+))?" [tool.tbump.git] diff --git a/packages/python/stitch/src/plugin.ts b/packages/python/stitch/src/plugin.ts index 49bea2f54..ff698e345 100644 --- a/packages/python/stitch/src/plugin.ts +++ b/packages/python/stitch/src/plugin.ts @@ -11,7 +11,7 @@ import * as widgetExports from './widget'; import { MODULE_NAME, MODULE_VERSION } from './version'; -const EXTENSION_ID = 'stitch:plugin'; +const EXTENSION_ID = '@guidance-ai/stitch:plugin'; /** * The example plugin. diff --git a/packages/python/stitch/stitch/_frontend.py b/packages/python/stitch/stitch/_frontend.py index 4dcf81718..3372665b9 100644 --- a/packages/python/stitch/stitch/_frontend.py +++ b/packages/python/stitch/stitch/_frontend.py @@ -8,5 +8,5 @@ Information about the frontend package of the widgets. """ -module_name = "stitch" -module_version = "^0.1.0" +module_name = "@guidance-ai/stitch" +module_version = "^0.1.1" diff --git a/packages/python/stitch/stitch/_version.py b/packages/python/stitch/stitch/_version.py index 37c53b133..e2228df08 100644 --- a/packages/python/stitch/stitch/_version.py +++ b/packages/python/stitch/stitch/_version.py @@ -4,5 +4,5 @@ # Copyright (c) Guidance Contributors. # Distributed under the terms of the Modified BSD License. -version_info = (0, 1, 0) +version_info = (0, 1, 1) __version__ = ".".join(map(str, version_info)) diff --git a/packages/python/stitch/stitch/nbextension/extension.js b/packages/python/stitch/stitch/nbextension/extension.js index a06baadcc..bd35fb097 100644 --- a/packages/python/stitch/stitch/nbextension/extension.js +++ b/packages/python/stitch/stitch/nbextension/extension.js @@ -6,7 +6,7 @@ define(function() { window['requirejs'].config({ map: { '*': { - 'stitch': 'nbextensions/stitch/index', + '@guidance-ai/stitch': 'nbextensions/stitch/index', }, } }); diff --git a/packages/python/stitch/webpack.config.js b/packages/python/stitch/webpack.config.js index 8faaf089b..327651651 100644 --- a/packages/python/stitch/webpack.config.js +++ b/packages/python/stitch/webpack.config.js @@ -55,8 +55,8 @@ module.exports = [ filename: 'index.js', path: path.resolve(__dirname, 'dist'), libraryTarget: 'amd', - library: "stitch", - publicPath: 'https://unpkg.com/stitch@' + version + '/dist/' + library: "@guidance-ai/stitch", + publicPath: 'https://unpkg.com/@guidance-ai/stitch@' + version + '/dist/' }, devtool: 'source-map', module: { From 50d0b52764873ee51a3b53fb486ad94806c51dde Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Fri, 7 Feb 2025 14:43:13 -0800 Subject: [PATCH 04/11] Missing name changes for stitch and yarn lock. Yarn lock updated, adjustments to package naming within stitch. --- packages/python/stitch/stitch/__init__.py | 2 +- packages/python/stitch/webpack.config.js | 2 +- packages/python/stitch/yarn.lock | 76 +++++++++++------------ 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/packages/python/stitch/stitch/__init__.py b/packages/python/stitch/stitch/__init__.py index e984ee173..bbed8bd61 100644 --- a/packages/python/stitch/stitch/__init__.py +++ b/packages/python/stitch/stitch/__init__.py @@ -21,7 +21,7 @@ def _jupyter_labextension_paths(): """ return [{ 'src': 'labextension', - 'dest': 'stitch', + 'dest': '@guidance-ai/stitch', }] diff --git a/packages/python/stitch/webpack.config.js b/packages/python/stitch/webpack.config.js index 327651651..c7e47b62e 100644 --- a/packages/python/stitch/webpack.config.js +++ b/packages/python/stitch/webpack.config.js @@ -40,7 +40,7 @@ module.exports = [ }, /** - * Embeddable stitch bundle + * Embeddable @guidance-ai/stitch bundle * * This bundle is almost identical to the notebook extension bundle. The only * difference is in the configuration of the webpack public path for the diff --git a/packages/python/stitch/yarn.lock b/packages/python/stitch/yarn.lock index b3e0c518f..3d520c641 100644 --- a/packages/python/stitch/yarn.lock +++ b/packages/python/stitch/yarn.lock @@ -1332,6 +1332,44 @@ __metadata: languageName: node linkType: hard +"@guidance-ai/stitch@workspace:.": + version: 0.0.0-use.local + resolution: "@guidance-ai/stitch@workspace:." + dependencies: + "@babel/core": ^7.23.7 + "@babel/preset-env": ^7.23.8 + "@jupyter-widgets/base": ^1.1.10 || ^2 || ^3 || ^4 || ^5 || ^6 + "@jupyter-widgets/base-manager": ^1.0.7 + "@jupyterlab/builder": ^4.0.11 + "@lumino/application": ^2.3.0 + "@lumino/widgets": ^2.3.1 + "@types/jest": ^29.5.11 + "@types/webpack-env": ^1.18.4 + "@typescript-eslint/eslint-plugin": ^6.19.1 + "@typescript-eslint/parser": ^6.19.1 + acorn: ^8.11.3 + css-loader: ^6.9.1 + eslint: ^8.56.0 + eslint-config-prettier: ^9.1.0 + eslint-plugin-prettier: ^5.1.3 + fs-extra: ^11.2.0 + identity-obj-proxy: ^3.0.0 + jest: ^29.7.0 + jest-environment-jsdom: ^29.7.0 + mkdirp: ^3.0.1 + npm-run-all: ^4.1.5 + prettier: ^3.2.4 + rimraf: ^5.0.5 + source-map-loader: ^5.0.0 + style-loader: ^3.3.4 + ts-jest: ^29.1.2 + ts-loader: ^9.5.1 + typescript: ~5.3.3 + webpack: ^5.90.0 + webpack-cli: ^5.1.4 + languageName: unknown + linkType: soft + "@humanwhocodes/config-array@npm:^0.13.0": version: 0.13.0 resolution: "@humanwhocodes/config-array@npm:0.13.0" @@ -7799,44 +7837,6 @@ __metadata: languageName: node linkType: hard -"stitch@workspace:.": - version: 0.0.0-use.local - resolution: "stitch@workspace:." - dependencies: - "@babel/core": ^7.23.7 - "@babel/preset-env": ^7.23.8 - "@jupyter-widgets/base": ^1.1.10 || ^2 || ^3 || ^4 || ^5 || ^6 - "@jupyter-widgets/base-manager": ^1.0.7 - "@jupyterlab/builder": ^4.0.11 - "@lumino/application": ^2.3.0 - "@lumino/widgets": ^2.3.1 - "@types/jest": ^29.5.11 - "@types/webpack-env": ^1.18.4 - "@typescript-eslint/eslint-plugin": ^6.19.1 - "@typescript-eslint/parser": ^6.19.1 - acorn: ^8.11.3 - css-loader: ^6.9.1 - eslint: ^8.56.0 - eslint-config-prettier: ^9.1.0 - eslint-plugin-prettier: ^5.1.3 - fs-extra: ^11.2.0 - identity-obj-proxy: ^3.0.0 - jest: ^29.7.0 - jest-environment-jsdom: ^29.7.0 - mkdirp: ^3.0.1 - npm-run-all: ^4.1.5 - prettier: ^3.2.4 - rimraf: ^5.0.5 - source-map-loader: ^5.0.0 - style-loader: ^3.3.4 - ts-jest: ^29.1.2 - ts-loader: ^9.5.1 - typescript: ~5.3.3 - webpack: ^5.90.0 - webpack-cli: ^5.1.4 - languageName: unknown - linkType: soft - "string-length@npm:^4.0.1": version: 4.0.2 resolution: "string-length@npm:4.0.2" From ee1d6d5e3bdc93dae1ea5d0c97293a68ed7015cf Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Sun, 9 Feb 2025 11:03:33 -0800 Subject: [PATCH 05/11] Bump to 0.1.2 Build not done correctly for 0.1.1 --- packages/python/stitch/README.md | 8 ++++---- packages/python/stitch/package.json | 2 +- packages/python/stitch/pyproject.toml | 2 +- packages/python/stitch/stitch/_version.py | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/python/stitch/README.md b/packages/python/stitch/README.md index 3267f1986..7bd63dc1f 100644 --- a/packages/python/stitch/README.md +++ b/packages/python/stitch/README.md @@ -12,13 +12,13 @@ Bidirectional comms for Jupyter and JavaScript. You can install using `pip`: ```bash -pip install stitch +pip install guidance-stitch ``` If you are using Jupyter Notebook 5.2 or earlier, you may also need to enable the nbextension: ```bash -jupyter nbextension enable --py [--sys-prefix|--user|--system] stitch +jupyter nbextension enable --py [--sys-prefix|--user|--system] guidance-stitch ``` ## Development Installation @@ -45,8 +45,8 @@ jlpm run build For classic notebook, you need to run: ``` -jupyter nbextension install --sys-prefix --symlink --overwrite --py stitch -jupyter nbextension enable --sys-prefix --py stitch +jupyter nbextension install --sys-prefix --symlink --overwrite --py guidance-stitch +jupyter nbextension enable --sys-prefix --py guidance-stitch ``` Note that the `--symlink` flag doesn't work on Windows, so you will here have to run diff --git a/packages/python/stitch/package.json b/packages/python/stitch/package.json index 0827aad9c..1302e5c7d 100644 --- a/packages/python/stitch/package.json +++ b/packages/python/stitch/package.json @@ -1,6 +1,6 @@ { "name": "@guidance-ai/stitch", - "version": "0.1.1", + "version": "0.1.2", "description": "Bidirectional comms for Jupyter and JavaScript.", "keywords": [ "jupyter", diff --git a/packages/python/stitch/pyproject.toml b/packages/python/stitch/pyproject.toml index 2452e969c..f80c30146 100644 --- a/packages/python/stitch/pyproject.toml +++ b/packages/python/stitch/pyproject.toml @@ -37,7 +37,7 @@ classifiers = [ dependencies = [ "ipywidgets>=8.0.0", ] -version = "0.1.1" +version = "0.1.2" [project.optional-dependencies] docs = [ diff --git a/packages/python/stitch/stitch/_version.py b/packages/python/stitch/stitch/_version.py index e2228df08..a1d2aa186 100644 --- a/packages/python/stitch/stitch/_version.py +++ b/packages/python/stitch/stitch/_version.py @@ -4,5 +4,5 @@ # Copyright (c) Guidance Contributors. # Distributed under the terms of the Modified BSD License. -version_info = (0, 1, 1) +version_info = (0, 1, 2) __version__ = ".".join(map(str, version_info)) From c1d56f25a761249818d3f9df95dc616eb443f098 Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Mon, 10 Feb 2025 12:58:46 -0800 Subject: [PATCH 06/11] Added state variables for stitch. State variables that are not synced now included in widget. --- .../python/stitch/examples/introduction.ipynb | 77 ++++++++++++++++--- packages/python/stitch/src/widget.ts | 29 ++++++- packages/python/stitch/stitch/stitch.py | 5 ++ 3 files changed, 98 insertions(+), 13 deletions(-) diff --git a/packages/python/stitch/examples/introduction.ipynb b/packages/python/stitch/examples/introduction.ipynb index b6e992f47..022cb274c 100644 --- a/packages/python/stitch/examples/introduction.ipynb +++ b/packages/python/stitch/examples/introduction.ipynb @@ -9,7 +9,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -18,18 +18,39 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "fd0586cd8d7e4bd39ef1decbf1e08262", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "StitchWidget(initial_height='auto', initial_width='100%', srcdoc='\\n\\n\n\n
\nMESSAGE: \n
\n\n\n" + } + } + }, + "version_major": 2, + "version_minor": 0 + } } }, "nbformat": 4, diff --git a/packages/python/stitch/src/widget.ts b/packages/python/stitch/src/widget.ts index 79922e720..33390c4cf 100644 --- a/packages/python/stitch/src/widget.ts +++ b/packages/python/stitch/src/widget.ts @@ -28,6 +28,8 @@ export class StitchModel extends DOMWidgetModel { initial_height: '1px', initial_width: '1px', initial_border: '0', + kernel_state: '', + client_state: '', }; } @@ -58,16 +60,20 @@ export class StitchView extends DOMWidgetView { iframe.style.display = 'block'; this._iframe = iframe; - // Send first kernelmsg on load. + // Initialization steps when model is ready. const refreshTimeMs = 100; - const sendKernelMsgOnReady = () => { + const initOnReady = () => { if (this.model.isNew()) { - window.setTimeout(sendKernelMsgOnReady, refreshTimeMs); + window.setTimeout(initOnReady, refreshTimeMs); } else { + // Send state to client if defined. + this.emit_state(); + + // Send first kernelmsg on load. this.kernelmsg_changed(); } }; - window.setTimeout(sendKernelMsgOnReady, refreshTimeMs); + window.setTimeout(initOnReady, refreshTimeMs); // Add callback for forwarding messages from client to kernel const model = this.model; @@ -79,6 +85,9 @@ export class StitchView extends DOMWidgetView { } else if (win === event.source && event.data.type === 'resize') { iframe.style.height = event.data.content.height; iframe.style.width = event.data.content.width; + } else if (win === event.source && event.data.type === 'client_state') { + model.set('client_state', event.data.content); + model.save_changes(); } }; window.addEventListener('message', recvFromClient); @@ -93,6 +102,18 @@ export class StitchView extends DOMWidgetView { this.model.on('change:srcdoc', this.srcdoc_changed, this); } + emit_state() { + const clientState = this.model.get('client_state'); + if (clientState === '') { + return; + } + const winmsg = { + type: 'client_state', + content: clientState, + }; + this._iframe.contentWindow?.postMessage(winmsg, '*'); + } + kernelmsg_changed() { // Forward message from kernel to client const kernelmsg = this.model.get('kernelmsg'); diff --git a/packages/python/stitch/stitch/stitch.py b/packages/python/stitch/stitch/stitch.py index 66ebc29ab..c75f894dc 100644 --- a/packages/python/stitch/stitch/stitch.py +++ b/packages/python/stitch/stitch/stitch.py @@ -29,3 +29,8 @@ class StitchWidget(DOMWidget): initial_height = Unicode("1px").tag(sync=True) initial_width = Unicode("1px").tag(sync=True) initial_border = Unicode("0").tag(sync=True) + + # State that should only be set in kernel, not shared with client. + kernel_state = Unicode("").tag(sync=False) + # State that should only be set in client, not shared with kernel. + client_state = Unicode("").tag(sync=False) \ No newline at end of file From 2e66e62b3483ef25cfa507bb5a7b0ba5ffd1cb38 Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Mon, 10 Feb 2025 13:11:13 -0800 Subject: [PATCH 07/11] Reformat App svelte. --- client/graphpaper-inline/src/App.svelte | 456 ++++++++++++------------ 1 file changed, 233 insertions(+), 223 deletions(-) diff --git a/client/graphpaper-inline/src/App.svelte b/client/graphpaper-inline/src/App.svelte index 7aee50b09..6c7712d98 100644 --- a/client/graphpaper-inline/src/App.svelte +++ b/client/graphpaper-inline/src/App.svelte @@ -4,248 +4,258 @@ This has bidirectional communication between the guidance server (usually Jupyte For upcoming features, we won't be able to send all details over the wire, and will need to operate on client request. --> - graphpaper - + graphpaper + - - + +
-
+ underlineField = selected.detail} /> + + + - -
- -
+ +
+ +
\ No newline at end of file From 8f6c564613659e9faf303c952d5ce9ae900564fa Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Tue, 11 Feb 2025 13:22:45 -0800 Subject: [PATCH 08/11] Stitch updates to store state. State can now be stored within stitch (needed for offline rendering or page refresh). --- .../python/stitch/examples/introduction.ipynb | 26 ++++++++--------- packages/python/stitch/src/widget.ts | 28 +++++++++++-------- packages/python/stitch/stitch/stitch.py | 6 ++-- 3 files changed, 31 insertions(+), 29 deletions(-) diff --git a/packages/python/stitch/examples/introduction.ipynb b/packages/python/stitch/examples/introduction.ipynb index 022cb274c..caadb476b 100644 --- a/packages/python/stitch/examples/introduction.ipynb +++ b/packages/python/stitch/examples/introduction.ipynb @@ -24,7 +24,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "fd0586cd8d7e4bd39ef1decbf1e08262", + "model_id": "b05706653924451ab8c6464f439f4a4e", "version_major": 2, "version_minor": 0 }, @@ -47,8 +47,8 @@ " document.getElementById(\"msgview\").innerHTML = event.data.content;\n", " window.parent.postMessage({type: \"clientmsg\", content: event.data.content}, \"*\");\n", " // Save state for offline render\n", - " window.parent.postMessage({type: \"client_state\", content: event.data.content}, \"*\");\n", - " } else if (event.data.type === \"client_state\") {\n", + " window.parent.postMessage({type: \"state\", content: event.data.content}, \"*\");\n", + " } else if (event.data.type === \"init_state\") {\n", " document.getElementById(\"msgview\").innerHTML = event.data.content;\n", " }\n", " }\n", @@ -149,27 +149,27 @@ "widgets": { "application/vnd.jupyter.widget-state+json": { "state": { - "087076260797479f884edd6546c5ccf9": { - "model_module": "@jupyter-widgets/base", - "model_module_version": "2.0.0", - "model_name": "LayoutModel", - "state": {} - }, - "fd0586cd8d7e4bd39ef1decbf1e08262": { + "b05706653924451ab8c6464f439f4a4e": { "model_module": "@guidance-ai/stitch", "model_module_version": "^0.1.1", "model_name": "StitchModel", "state": { "_model_module_version": "^0.1.1", "_view_module_version": "^0.1.1", - "client_state": "Wow, a change!", "clientmsg": "Wow, a change!", "initial_height": "auto", "initial_width": "100%", "kernelmsg": "Wow, a change!", - "layout": "IPY_MODEL_087076260797479f884edd6546c5ccf9", - "srcdoc": "\n\n\n\n
\nMESSAGE: \n
\n\n\n" + "layout": "IPY_MODEL_c8d8410bc496453882680ff0fb8f6d0d", + "srcdoc": "\n\n\n\n
\nMESSAGE: \n
\n\n\n", + "state": "Wow, a change!" } + }, + "c8d8410bc496453882680ff0fb8f6d0d": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "2.0.0", + "model_name": "LayoutModel", + "state": {} } }, "version_major": 2, diff --git a/packages/python/stitch/src/widget.ts b/packages/python/stitch/src/widget.ts index 33390c4cf..feab972bc 100644 --- a/packages/python/stitch/src/widget.ts +++ b/packages/python/stitch/src/widget.ts @@ -28,8 +28,7 @@ export class StitchModel extends DOMWidgetModel { initial_height: '1px', initial_width: '1px', initial_border: '0', - kernel_state: '', - client_state: '', + state: '', }; } @@ -50,6 +49,8 @@ export class StitchView extends DOMWidgetView { private _iframe: HTMLIFrameElement; render() { + // console.log('stitch:render'); + // Create sandboxed frame const iframe = document.createElement('iframe'); iframe.sandbox.add('allow-scripts'); @@ -66,11 +67,11 @@ export class StitchView extends DOMWidgetView { if (this.model.isNew()) { window.setTimeout(initOnReady, refreshTimeMs); } else { - // Send state to client if defined. - this.emit_state(); - + // Send init state if needed. + this.emit_init_state(); // Send first kernelmsg on load. this.kernelmsg_changed(); + // console.log('stitch:is_new'); } }; window.setTimeout(initOnReady, refreshTimeMs); @@ -85,8 +86,8 @@ export class StitchView extends DOMWidgetView { } else if (win === event.source && event.data.type === 'resize') { iframe.style.height = event.data.content.height; iframe.style.width = event.data.content.width; - } else if (win === event.source && event.data.type === 'client_state') { - model.set('client_state', event.data.content); + } else if (win === event.source && event.data.type === 'state') { + model.set('state', event.data.content); model.save_changes(); } }; @@ -102,15 +103,18 @@ export class StitchView extends DOMWidgetView { this.model.on('change:srcdoc', this.srcdoc_changed, this); } - emit_state() { - const clientState = this.model.get('client_state'); - if (clientState === '') { + emit_init_state() { + const state = this.model.get('state'); + if (state === '') { + // console.log('stitch:empty init state'); return; } const winmsg = { - type: 'client_state', - content: clientState, + type: 'init_state', + content: state, }; + + // console.log('stitch:state'); this._iframe.contentWindow?.postMessage(winmsg, '*'); } diff --git a/packages/python/stitch/stitch/stitch.py b/packages/python/stitch/stitch/stitch.py index c75f894dc..b69499191 100644 --- a/packages/python/stitch/stitch/stitch.py +++ b/packages/python/stitch/stitch/stitch.py @@ -30,7 +30,5 @@ class StitchWidget(DOMWidget): initial_width = Unicode("1px").tag(sync=True) initial_border = Unicode("0").tag(sync=True) - # State that should only be set in kernel, not shared with client. - kernel_state = Unicode("").tag(sync=False) - # State that should only be set in client, not shared with kernel. - client_state = Unicode("").tag(sync=False) \ No newline at end of file + # NOTE(nopdive): Should we sync or not? There are overheads when we deal with bandwidth on real time applications. + state = Unicode("").tag(sync=True) \ No newline at end of file From 161830fbd553b759f0773c5b0be770ae80d92a39 Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Tue, 11 Feb 2025 13:25:51 -0800 Subject: [PATCH 09/11] Stitch bump to 0.1.3 Updated for state exposure. --- packages/python/stitch/package.json | 2 +- packages/python/stitch/pyproject.toml | 2 +- packages/python/stitch/stitch/_version.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/python/stitch/package.json b/packages/python/stitch/package.json index 1302e5c7d..7b5f3a4a3 100644 --- a/packages/python/stitch/package.json +++ b/packages/python/stitch/package.json @@ -1,6 +1,6 @@ { "name": "@guidance-ai/stitch", - "version": "0.1.2", + "version": "0.1.3", "description": "Bidirectional comms for Jupyter and JavaScript.", "keywords": [ "jupyter", diff --git a/packages/python/stitch/pyproject.toml b/packages/python/stitch/pyproject.toml index f80c30146..82da0f584 100644 --- a/packages/python/stitch/pyproject.toml +++ b/packages/python/stitch/pyproject.toml @@ -37,7 +37,7 @@ classifiers = [ dependencies = [ "ipywidgets>=8.0.0", ] -version = "0.1.2" +version = "0.1.3" [project.optional-dependencies] docs = [ diff --git a/packages/python/stitch/stitch/_version.py b/packages/python/stitch/stitch/_version.py index a1d2aa186..abdaca827 100644 --- a/packages/python/stitch/stitch/_version.py +++ b/packages/python/stitch/stitch/_version.py @@ -4,5 +4,5 @@ # Copyright (c) Guidance Contributors. # Distributed under the terms of the Modified BSD License. -version_info = (0, 1, 2) +version_info = (0, 1, 3) __version__ = ".".join(map(str, version_info)) From 14fb501ada16a343085e05529a1b673be936b804 Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Tue, 11 Feb 2025 13:33:36 -0800 Subject: [PATCH 10/11] Updates to do offline rendering. This should enable offline rendering for guidance frontend. --- client/graphpaper-inline/src/App.svelte | 276 ++++++++---------- .../src/StitchHandler.svelte | 32 +- client/graphpaper-inline/src/metrics.ts | 69 +++++ client/graphpaper-inline/src/stitch.ts | 3 +- guidance/resources/graphpaper-inline.html | 4 +- 5 files changed, 213 insertions(+), 171 deletions(-) create mode 100644 client/graphpaper-inline/src/metrics.ts diff --git a/client/graphpaper-inline/src/App.svelte b/client/graphpaper-inline/src/App.svelte index 6c7712d98..8f1481e92 100644 --- a/client/graphpaper-inline/src/App.svelte +++ b/client/graphpaper-inline/src/App.svelte @@ -8,182 +8,139 @@ For upcoming features, we won't be able to send all details over the wire, and w import TokenGrid from './TokenGrid.svelte'; import ResizeListener from './ResizeListener.svelte'; import { - kernelmsg, clientmsg, - type StitchMessage, - type NodeAttr, + state, type GenTokenExtra, - isTraceMessage, - isTextOutput, - isRoleOpenerInput, - isRoleCloserInput, - isResetDisplayMessage, - isMetricMessage, + type GuidanceMessage, + isClientReadyAckMessage, isExecutionCompletedMessage, + isExecutionStartedMessage, + isMetricMessage, + isResetDisplayMessage, + isRoleCloserInput, + isRoleOpenerInput, + isTextOutput, isTokensMessage, - isClientReadyAckMessage, - isExecutionStartedMessage + isTraceMessage, + kernelmsg, + type NodeAttr, + type StitchMessage } from './stitch'; import StitchHandler from './StitchHandler.svelte'; import { onMount } from 'svelte'; - import { type MetricDef, type MetricVal } from './interfaces'; import MetricCard from './MetricCard.svelte'; - import { mockGenTokens, mockNodeAttrs } from './mocks'; import Select from './Select.svelte'; + import { metricDefs } from './metrics'; + import type { MetricVal } from './interfaces'; - let msg: any; - let textComponents: Array = []; - let tokenDetails: Array = []; - let isCompleted: boolean = false; - let isError: boolean = false; - let showMetrics: boolean = true; - let requireFullReplay: boolean = true; + interface AppState { + textComponents: Array, + tokenDetails: Array, + metrics: Record, + isCompleted: boolean, + isError: boolean, + requireFullReplay: boolean, + } + let appState: AppState = { + textComponents: [], + tokenDetails: [], + metrics: { + 'status': '⟳', + 'cpu': [0.0, 0.0, 0.0, 0.0, 0.0], + 'ram': 0, + 'wall time': 0, + 'avg latency': 0, + 'consumed': 0, + 'token reduction': 0 + }, + isCompleted: false, + isError: false, + requireFullReplay: false, + }; + // appState.textComponents = mockNodeAttrs; + // appState.tokenDetails = mockGenTokens; + let showMetrics: boolean = true; let bgField: string = 'Type'; let underlineField: string = 'Probability'; - // textComponents = mockNodeAttrs; - // tokenDetails = mockGenTokens; - - $: if ($kernelmsg !== undefined) { - if ($kernelmsg.content !== '') { - msg = JSON.parse($kernelmsg.content); - if (isTraceMessage(msg)) { - if (isTextOutput(msg.node_attr)) { - textComponents.push(msg.node_attr); - } else if (isRoleOpenerInput(msg.node_attr)) { - textComponents.push(msg.node_attr); - } else if (isRoleCloserInput(msg.node_attr)) { - textComponents.push(msg.node_attr); - } - } else if (isExecutionStartedMessage(msg)) { - requireFullReplay = false; - } else if (isClientReadyAckMessage(msg)) { - if (requireFullReplay) { - console.log('Require full replay and went past completion output message.'); - const msg: StitchMessage = { - type: 'clientmsg', - content: JSON.stringify({ 'class_name': 'OutputRequestMessage' }) - }; - clientmsg.set(msg); - } - } else if (isResetDisplayMessage(msg)) { - textComponents = []; - isCompleted = false; - } else if (isMetricMessage(msg)) { - const name = msg.name; - const value = msg.value; + const handleMessage = (msg: GuidanceMessage): void => { + if (isTraceMessage(msg)) { + if (isTextOutput(msg.node_attr)) { + appState.textComponents.push(msg.node_attr); + } else if (isRoleOpenerInput(msg.node_attr)) { + appState.textComponents.push(msg.node_attr); + } else if (isRoleCloserInput(msg.node_attr)) { + appState.textComponents.push(msg.node_attr); + } + } else if (isExecutionStartedMessage(msg)) { + appState.requireFullReplay = false; + } else if (isClientReadyAckMessage(msg)) { + if (appState.requireFullReplay) { + console.log('Require full replay and went past completion output message.'); + const msg: StitchMessage = { + type: 'clientmsg', + content: JSON.stringify({ 'class_name': 'OutputRequestMessage' }) + }; + clientmsg.set(msg); + } + } else if (isResetDisplayMessage(msg)) { + appState.textComponents = []; + appState.isCompleted = false; + } else if (isMetricMessage(msg)) { + const name = msg.name; + const value = msg.value; - if (name in metrics && name in metricDefs) { - let currVal = metrics[name]; - const metricDef = metricDefs[name]; - if (metricDef.isScalar === false) { - if (value.constructor === Array) { - metrics[name] = value; - } else { - currVal = currVal as Array; - metrics[name] = [...currVal.slice(1), value as string | number]; - } - } else if (metricDef.isScalar === true) { - metrics[name] = value; + if (name in appState.metrics && name in metricDefs) { + let currVal = appState.metrics[name]; + const metricDef = metricDefs[name]; + if (metricDef.isScalar === false) { + if (value.constructor === Array) { + appState.metrics[name] = value; } else { - console.log(`Cannot handle metric: ${name}: ${value}.`); - } - - if (name === 'status') { - isError = value === '⚠'; + currVal = currVal as Array; + appState.metrics[name] = [...currVal.slice(1), value as string | number]; } + } else if (metricDef.isScalar === true) { + appState.metrics[name] = value; + } else { + console.error(`Cannot handle metric: ${name}: ${value}.`); } - } else if (isExecutionCompletedMessage(msg)) { - isCompleted = true; - } else if (isTokensMessage(msg)) { - requireFullReplay = false; - isCompleted = true; - tokenDetails = msg.tokens; - console.log(textComponents); - console.log(msg.tokens); + if (name === 'status') { + appState.isError = value === '⚠'; + } } - textComponents = textComponents; - } - } + } else if (isExecutionCompletedMessage(msg)) { + appState.isCompleted = true; + } else if (isTokensMessage(msg)) { + appState.requireFullReplay = false; + appState.isCompleted = true; + appState.tokenDetails = msg.tokens; - const metricDefs: Record = { - 'status': { - name: 'status', - units: '', - description: 'Determines whether engine is running, completed or in error.', - isScalar: true, - precision: 0 - }, - 'cpu': { - name: 'cpu', - units: '%', - description: 'Average utilization across CPU cores.', - isScalar: false, - precision: 1 - }, - 'gpu': { - name: 'gpu', - units: '%', - description: 'Average utilization across GPUs.', - isScalar: false, - precision: 1 - }, - 'ram': { - name: 'ram', - units: 'GB', - description: 'Utilization of RAM.', - isScalar: true, - precision: 1 - }, - 'vram': { - name: 'vram', - units: 'GB', - description: 'Utilization of video RAM.', - isScalar: true, - precision: 1 - }, - 'wall time': { - name: 'wall time', - units: 's', - description: 'Time taken from initial display to engine completion.', - isScalar: true, - precision: 1 - }, - 'avg latency': { - name: 'avg latency', - units: 'ms', - description: 'Average roundtrip latency per token', - isScalar: true, - precision: 0 - }, - 'consumed': { - name: 'consumed', - units: 'tkn', - description: 'Total tokens consumed by language model.', - isScalar: true, - precision: 0 - }, - 'token reduction': { - name: 'token reduction', - units: '%', - description: 'Total tokens consumed by language model divided by total tokens.', - isScalar: true, - precision: 0 + // Good time to save state. + const savedState = JSON.stringify(appState); + const stateMessage: StitchMessage = { + type: 'state', + content: savedState, + }; + state.set(stateMessage); + + // console.log(appState.textComponents); + // console.log(appState.tokenDetails); } + + appState = appState; }; - const metrics: Record = { - 'status': '⟳', - // 'gpu': [0.0, 0.0, 0.0, 0.0, 0.0], - // 'vram': 0, - 'cpu': [0.0, 0.0, 0.0, 0.0, 0.0], - 'ram': 0, - 'wall time': 0, - 'avg latency': 0, - 'consumed': 0, - 'token reduction': 0 - }; + + $: if ($state !== undefined && $state.content !== '') { + // console.log("Client state received.") + appState = JSON.parse($state.content); + } + $: if ($kernelmsg !== undefined && $kernelmsg.content !== '') { + const msg = JSON.parse($kernelmsg.content); + handleMessage(msg); + } onMount(() => { const msg: StitchMessage = { @@ -213,7 +170,7 @@ For upcoming features, we won't be able to send all details over the wire, and w {#if showMetrics}
- {#each Object.entries(metrics) as [name, value]} + {#each Object.entries(appState.metrics) as [name, value]} {/each}
@@ -223,7 +180,8 @@ For upcoming features, we won't be able to send all details over the wire, and w
-
Metrics @@ -245,7 +203,8 @@ For upcoming features, we won't be able to send all details over the wire, and w {/if}
- underlineField = selected.detail} /> @@ -255,7 +214,8 @@ For upcoming features, we won't be able to send all details over the wire, and w
- +
\ No newline at end of file diff --git a/client/graphpaper-inline/src/StitchHandler.svelte b/client/graphpaper-inline/src/StitchHandler.svelte index fdc7058c4..dee57c3e1 100644 --- a/client/graphpaper-inline/src/StitchHandler.svelte +++ b/client/graphpaper-inline/src/StitchHandler.svelte @@ -1,29 +1,41 @@ diff --git a/client/graphpaper-inline/src/metrics.ts b/client/graphpaper-inline/src/metrics.ts new file mode 100644 index 000000000..7a8104dbf --- /dev/null +++ b/client/graphpaper-inline/src/metrics.ts @@ -0,0 +1,69 @@ +// Metrics and their definitions. + +import type { MetricDef } from './interfaces'; + +export const metricDefs: Record = { + 'status': { + name: 'status', + units: '', + description: 'Determines whether engine is running, completed or in error.', + isScalar: true, + precision: 0 + }, + 'cpu': { + name: 'cpu', + units: '%', + description: 'Average utilization across CPU cores.', + isScalar: false, + precision: 1 + }, + 'gpu': { + name: 'gpu', + units: '%', + description: 'Average utilization across GPUs.', + isScalar: false, + precision: 1 + }, + 'ram': { + name: 'ram', + units: 'GB', + description: 'Utilization of RAM.', + isScalar: true, + precision: 1 + }, + 'vram': { + name: 'vram', + units: 'GB', + description: 'Utilization of video RAM.', + isScalar: true, + precision: 1 + }, + 'wall time': { + name: 'wall time', + units: 's', + description: 'Time taken from initial display to engine completion.', + isScalar: true, + precision: 1 + }, + 'avg latency': { + name: 'avg latency', + units: 'ms', + description: 'Average roundtrip latency per token', + isScalar: true, + precision: 0 + }, + 'consumed': { + name: 'consumed', + units: 'tkn', + description: 'Total tokens consumed by language model.', + isScalar: true, + precision: 0 + }, + 'token reduction': { + name: 'token reduction', + units: '%', + description: 'Total tokens consumed by language model divided by total tokens.', + isScalar: true, + precision: 0 + } +}; diff --git a/client/graphpaper-inline/src/stitch.ts b/client/graphpaper-inline/src/stitch.ts index 3abcffe93..aec6d9c46 100644 --- a/client/graphpaper-inline/src/stitch.ts +++ b/client/graphpaper-inline/src/stitch.ts @@ -96,7 +96,7 @@ export interface MetricMessage extends GuidanceMessage { } export interface StitchMessage { - type: "resize" | "clientmsg" | "kernelmsg", + type: "resize" | "clientmsg" | "kernelmsg" | "state" | "init_state", content: any } @@ -157,4 +157,5 @@ export function isTokensMessage(o: GuidanceMessage | undefined | null): o is Tok export const kernelmsg = writable(undefined); export const clientmsg = writable(undefined); +export const state = writable(undefined); diff --git a/guidance/resources/graphpaper-inline.html b/guidance/resources/graphpaper-inline.html index 4d108f32c..5741e4055 100644 --- a/guidance/resources/graphpaper-inline.html +++ b/guidance/resources/graphpaper-inline.html @@ -9,8 +9,8 @@ From 0763992cb00e6e435b797caade60b801b64e70c7 Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Tue, 11 Feb 2025 13:58:33 -0800 Subject: [PATCH 11/11] Bump to 0.1.4 --- packages/python/stitch/package.json | 2 +- packages/python/stitch/pyproject.toml | 2 +- packages/python/stitch/stitch/_frontend.py | 2 +- packages/python/stitch/stitch/_version.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/python/stitch/package.json b/packages/python/stitch/package.json index 7b5f3a4a3..6593e60d6 100644 --- a/packages/python/stitch/package.json +++ b/packages/python/stitch/package.json @@ -1,6 +1,6 @@ { "name": "@guidance-ai/stitch", - "version": "0.1.3", + "version": "0.1.4", "description": "Bidirectional comms for Jupyter and JavaScript.", "keywords": [ "jupyter", diff --git a/packages/python/stitch/pyproject.toml b/packages/python/stitch/pyproject.toml index 82da0f584..b390b4747 100644 --- a/packages/python/stitch/pyproject.toml +++ b/packages/python/stitch/pyproject.toml @@ -37,7 +37,7 @@ classifiers = [ dependencies = [ "ipywidgets>=8.0.0", ] -version = "0.1.3" +version = "0.1.4" [project.optional-dependencies] docs = [ diff --git a/packages/python/stitch/stitch/_frontend.py b/packages/python/stitch/stitch/_frontend.py index 3372665b9..52c994ed3 100644 --- a/packages/python/stitch/stitch/_frontend.py +++ b/packages/python/stitch/stitch/_frontend.py @@ -9,4 +9,4 @@ """ module_name = "@guidance-ai/stitch" -module_version = "^0.1.1" +module_version = "^0.1.4" diff --git a/packages/python/stitch/stitch/_version.py b/packages/python/stitch/stitch/_version.py index abdaca827..a4cb6c21e 100644 --- a/packages/python/stitch/stitch/_version.py +++ b/packages/python/stitch/stitch/_version.py @@ -4,5 +4,5 @@ # Copyright (c) Guidance Contributors. # Distributed under the terms of the Modified BSD License. -version_info = (0, 1, 3) +version_info = (0, 1, 4) __version__ = ".".join(map(str, version_info))