From c84e33799634201a7a237f9e97fb241bebf7e0da Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Tue, 20 Aug 2024 15:41:14 -0400 Subject: [PATCH 01/84] split: errors into trace and legacy parts --- weave/clear_cache.py | 16 ------------ weave/errors.py | 8 ++---- weave/legacy/clear_cache.py | 1 - weave/legacy/errors.py | 32 ++++++++++++++++++++++++ weave/legacy/ops_primitives/weave_api.py | 2 +- weave/{ => legacy}/trace_legacy.py | 5 ++-- weave/tests/legacy/test_trace.py | 3 ++- 7 files changed, 40 insertions(+), 27 deletions(-) delete mode 100644 weave/clear_cache.py create mode 100644 weave/legacy/errors.py rename weave/{ => legacy}/trace_legacy.py (97%) diff --git a/weave/clear_cache.py b/weave/clear_cache.py deleted file mode 100644 index 2d7b9da1dcd..00000000000 --- a/weave/clear_cache.py +++ /dev/null @@ -1,16 +0,0 @@ -import os -import time - -from weave.legacy import cache - -# TODO: This should be split out into a scripts dir -# Script to run to delete expired caches -if __name__ == "__main__": - print("Starting clear cache job", flush=True) - hour_interval = int(os.getenv("WEAVE_CACHE_CLEAR_INTERVAL", 24)) - print("Clearing expired caches every " + str(hour_interval) + " hours", flush=True) - while True: - curTime = time.strftime("%x, %X", time.localtime()) - print("Clearing cache " + curTime, flush=True) - cache.clear_cache() - time.sleep(60 * 60 * hour_interval) diff --git a/weave/errors.py b/weave/errors.py index 5153972b272..be70b599141 100644 --- a/weave/errors.py +++ b/weave/errors.py @@ -1,10 +1,6 @@ from typing import Iterable, Optional -class WeaveUnmergableArtifactsError(Exception): - pass - - class WeaveFingerprintErrorMixin: fingerprint: Optional[Iterable] = None @@ -30,11 +26,11 @@ class WeaveInternalError(WeaveBaseError): pass -class WeaveConfigurationError(WeaveBaseError): +class WeaveSerializeError(WeaveBaseError): pass -class WeaveSerializeError(WeaveBaseError): +class WeaveConfigurationError(WeaveBaseError): pass diff --git a/weave/legacy/clear_cache.py b/weave/legacy/clear_cache.py index 2d7b9da1dcd..39a6186efef 100644 --- a/weave/legacy/clear_cache.py +++ b/weave/legacy/clear_cache.py @@ -3,7 +3,6 @@ from weave.legacy import cache -# TODO: This should be split out into a scripts dir # Script to run to delete expired caches if __name__ == "__main__": print("Starting clear cache job", flush=True) diff --git a/weave/legacy/errors.py b/weave/legacy/errors.py new file mode 100644 index 00000000000..f6b5fd477d3 --- /dev/null +++ b/weave/legacy/errors.py @@ -0,0 +1,32 @@ +from typing import Iterable, Optional + + +class WeaveUnmergableArtifactsError(Exception): + pass + + +class WeaveFingerprintErrorMixin: + fingerprint: Optional[Iterable] = None + + +class WeaveBaseError(Exception, WeaveFingerprintErrorMixin): + pass + + +class WeaveBaseWarning(Warning): + pass + +# Only use this if you actually want to return an Http 400 +# to the client. This should only happen in cases where the +# client is wrong. +class WeaveBadRequest(WeaveBaseError): + pass + + +class WeaveInternalError(WeaveBaseError): + """Internal Weave Error (a programming error)""" + + pass + +class WeaveSerializeError(WeaveBaseError): + pass diff --git a/weave/legacy/ops_primitives/weave_api.py b/weave/legacy/ops_primitives/weave_api.py index 4d95af0392c..5417cb96de7 100644 --- a/weave/legacy/ops_primitives/weave_api.py +++ b/weave/legacy/ops_primitives/weave_api.py @@ -7,7 +7,6 @@ ref_base, registry_mem, storage, - trace_legacy, weave_internal, ) from weave import weave_types as types @@ -20,6 +19,7 @@ graph, object_context, runs, + trace_legacy, uris, ) from weave.legacy.graph import Node diff --git a/weave/trace_legacy.py b/weave/legacy/trace_legacy.py similarity index 97% rename from weave/trace_legacy.py rename to weave/legacy/trace_legacy.py index 6a1b41fe69a..3264585672d 100644 --- a/weave/trace_legacy.py +++ b/weave/legacy/trace_legacy.py @@ -3,8 +3,9 @@ from weave.legacy import artifact_local, graph, runs -from . import errors, ref_base -from . import weave_types as types +from .. import ref_base +from . import errors +from .. import weave_types as types def get_obj_creator(ref: ref_base.Ref) -> typing.Optional[runs.Run]: diff --git a/weave/tests/legacy/test_trace.py b/weave/tests/legacy/test_trace.py index bd32cec3e01..e779f576e7e 100644 --- a/weave/tests/legacy/test_trace.py +++ b/weave/tests/legacy/test_trace.py @@ -3,7 +3,8 @@ from weave.legacy import graph from ... import api as weave -from ... import storage, trace_legacy +from ... import storage +from ...legacy import trace_legacy from ...weave_internal import make_const_node From 8ca0896e48b28ff05d9aafa8d1d1dbf50242c2ad Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Mon, 26 Aug 2024 19:20:48 -0400 Subject: [PATCH 02/84] move to scripts, legacy/scripts: scripts --- .github/workflows/test.yaml | 2 +- DEVELOPMENT.md | 3 +-- integration_test/README.md | 2 +- bisect_script.sh => scripts/bisect_script.sh | 0 build_frontend.sh => scripts/build_frontend.sh | 0 build_test_container.sh => scripts/build_test_container.sh | 0 dd_weave_server.sh => scripts/dd_weave_server.sh | 0 dd_weave_server_replay.sh => scripts/dd_weave_server_replay.sh | 0 weave_server.sh => scripts/weave_server.sh | 0 weave_server_replay.sh => scripts/weave_server_replay.sh | 0 weave_server_test.sh => scripts/weave_server_test.sh | 0 supervisord.conf | 2 +- weave-js/src/core/README.md | 2 +- weave/legacy/{ => scripts}/clear_cache.py | 0 jupyter_dev.sh => weave/legacy/scripts/jupyter_dev.sh | 0 weave/{ => scripts}/pytest_parallel.sh | 0 16 files changed, 5 insertions(+), 6 deletions(-) rename bisect_script.sh => scripts/bisect_script.sh (100%) rename build_frontend.sh => scripts/build_frontend.sh (100%) rename build_test_container.sh => scripts/build_test_container.sh (100%) rename dd_weave_server.sh => scripts/dd_weave_server.sh (100%) rename dd_weave_server_replay.sh => scripts/dd_weave_server_replay.sh (100%) rename weave_server.sh => scripts/weave_server.sh (100%) rename weave_server_replay.sh => scripts/weave_server_replay.sh (100%) rename weave_server_test.sh => scripts/weave_server_test.sh (100%) rename weave/legacy/{ => scripts}/clear_cache.py (100%) rename jupyter_dev.sh => weave/legacy/scripts/jupyter_dev.sh (100%) rename weave/{ => scripts}/pytest_parallel.sh (100%) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 38e0a8aef2e..f1b883498b1 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -186,7 +186,7 @@ jobs: # github actions does something funky with the std file descriptors, they end up # being closed. tqdm (for example) raises an exception when the descriptor it # wants to write to is closed. - run: nohup ./weave_server_test.sh < /dev/null &> /tmp/weave/log/stdout.log & + run: nohup ./scripts/weave_server_test.sh < /dev/null &> /tmp/weave/log/stdout.log & shell: bash - name: Cypress run # Use the following to run just a single test diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 86d52a80135..27f7ded1877 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -72,7 +72,7 @@ yarn dev Weave backend server. This does not currently auto-reload, so you need to restart it if you change stuff. ``` -sh weave_server.sh +sh scripts/weave_server.sh ``` Now you should be able to go to localhost:3000 to see the weave home page. @@ -92,7 +92,6 @@ You can tell everything is working if the weave UI renders and you see your serv Some ops require environment variables to be set, like OPENAI_API_KEY. You need to set these for the server environment and your Jupyter notebook. - ## Unit tests Some of the unit tests try to run a wandb server container, and will produce 403s if that container is out of date. The container is only accessible to wandb developers currently. diff --git a/integration_test/README.md b/integration_test/README.md index e97a5c5d65a..77c6eab53db 100644 --- a/integration_test/README.md +++ b/integration_test/README.md @@ -18,4 +18,4 @@ yarn && yarn run cypress open Start the weave server with -bash weave_server_test.sh +bash scripts/weave_server_test.sh diff --git a/bisect_script.sh b/scripts/bisect_script.sh similarity index 100% rename from bisect_script.sh rename to scripts/bisect_script.sh diff --git a/build_frontend.sh b/scripts/build_frontend.sh similarity index 100% rename from build_frontend.sh rename to scripts/build_frontend.sh diff --git a/build_test_container.sh b/scripts/build_test_container.sh similarity index 100% rename from build_test_container.sh rename to scripts/build_test_container.sh diff --git a/dd_weave_server.sh b/scripts/dd_weave_server.sh similarity index 100% rename from dd_weave_server.sh rename to scripts/dd_weave_server.sh diff --git a/dd_weave_server_replay.sh b/scripts/dd_weave_server_replay.sh similarity index 100% rename from dd_weave_server_replay.sh rename to scripts/dd_weave_server_replay.sh diff --git a/weave_server.sh b/scripts/weave_server.sh similarity index 100% rename from weave_server.sh rename to scripts/weave_server.sh diff --git a/weave_server_replay.sh b/scripts/weave_server_replay.sh similarity index 100% rename from weave_server_replay.sh rename to scripts/weave_server_replay.sh diff --git a/weave_server_test.sh b/scripts/weave_server_test.sh similarity index 100% rename from weave_server_test.sh rename to scripts/weave_server_test.sh diff --git a/supervisord.conf b/supervisord.conf index 39f470d7529..e5c0649f61a 100644 --- a/supervisord.conf +++ b/supervisord.conf @@ -27,7 +27,7 @@ stopasgroup = true killasgroup = true [program:weave-python-server] -command = bash ./weave_server_test.sh +command = bash ./scripts/weave_server_test.sh directory = . autostart = true autorestart = false diff --git a/weave-js/src/core/README.md b/weave-js/src/core/README.md index 0936c1535fa..b6ab48c56ba 100644 --- a/weave-js/src/core/README.md +++ b/weave-js/src/core/README.md @@ -424,5 +424,5 @@ See [generateDocs.ts](./generateDocs.ts) for implementation. # Testing Against Weave Python -1. Start a Weave Server using `./weave_server.sh` from the `weave/weave` directory +1. Start a Weave Server using `./scripts/weave_server.sh` from the `weave/weave` directory 2. Run `yarn test:python-backend` from this directory diff --git a/weave/legacy/clear_cache.py b/weave/legacy/scripts/clear_cache.py similarity index 100% rename from weave/legacy/clear_cache.py rename to weave/legacy/scripts/clear_cache.py diff --git a/jupyter_dev.sh b/weave/legacy/scripts/jupyter_dev.sh similarity index 100% rename from jupyter_dev.sh rename to weave/legacy/scripts/jupyter_dev.sh diff --git a/weave/pytest_parallel.sh b/weave/scripts/pytest_parallel.sh similarity index 100% rename from weave/pytest_parallel.sh rename to weave/scripts/pytest_parallel.sh From 4392bb6dab5ad98d29092c8ad935a6a291baa81e Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Sat, 24 Aug 2024 16:06:46 -0400 Subject: [PATCH 03/84] format: scripts --- scripts/build_test_container.sh | 6 +++++- scripts/dd_weave_server.sh | 19 +++++++++++-------- scripts/dd_weave_server_replay.sh | 11 ++++++++--- scripts/weave_server.sh | 12 ++++++++---- scripts/weave_server_replay.sh | 6 +++++- scripts/weave_server_test.sh | 9 ++++++++- 6 files changed, 45 insertions(+), 18 deletions(-) diff --git a/scripts/build_test_container.sh b/scripts/build_test_container.sh index d7a705eac39..7c02c00baec 100755 --- a/scripts/build_test_container.sh +++ b/scripts/build_test_container.sh @@ -1 +1,5 @@ -docker buildx build --platform linux/amd64 -t us-east4-docker.pkg.dev/weave-support-367421/weave-images/weave-test:latest . -f Dockerfile.test +docker buildx build \ + --platform linux/amd64 \ + -t us-east4-docker.pkg.dev/weave-support-367421/weave-images/weave-test:latest \ + -f Dockerfile.test \ + . diff --git a/scripts/dd_weave_server.sh b/scripts/dd_weave_server.sh index c1c12ea833a..7556d1bdb5e 100755 --- a/scripts/dd_weave_server.sh +++ b/scripts/dd_weave_server.sh @@ -1,13 +1,16 @@ #!/bin/sh -DD_SERVICE="weave-python" DD_ENV="dev-$(whoami)" DD_LOGS_INJECTION=true \ - DD_TRACE_PROPAGATION_STYLE_EXTRACT=b3,datadog \ - DD_TRACE_PROPAGATION_STYLE_INJECT=b3,datadog \ - WEAVE_DISABLE_ANALYTICS=true \ - WEAVE_SERVER_ENABLE_LOGGING=true \ - FLASK_ENV=development \ - FLASK_APP=weave.weave_server \ - ddtrace-run flask run --port 9994 +DD_SERVICE="weave-python" +DD_ENV="dev-$(whoami)" +DD_LOGS_INJECTION=true +DD_TRACE_PROPAGATION_STYLE_EXTRACT=b3,datadog +DD_TRACE_PROPAGATION_STYLE_INJECT=b3,datadog +WEAVE_DISABLE_ANALYTICS=true +WEAVE_SERVER_ENABLE_LOGGING=true +FLASK_ENV=development +FLASK_APP=weave.weave_server + +ddtrace-run flask run --port 9994 # This runs with the datadog profiler on, but it is expensive! # I noticed a 2x increase in query time for some queries diff --git a/scripts/dd_weave_server_replay.sh b/scripts/dd_weave_server_replay.sh index 34039457b21..590a0b38bd8 100755 --- a/scripts/dd_weave_server_replay.sh +++ b/scripts/dd_weave_server_replay.sh @@ -1,5 +1,10 @@ #!/bin/sh -WEAVE_SERVER_DEBUG=true \ -DD_SERVICE="weave-python" DD_ENV="dev-$(whoami)" DD_LOGS_INJECTION=true \ - WEAVE_SERVER_ENABLE_LOGGING=true FLASK_APP=weave.weave_server ddtrace-run flask run --port 9994 +WEAVE_SERVER_DEBUG=true +DD_SERVICE="weave-python" +DD_ENV="dev-$(whoami)" +DD_LOGS_INJECTION=true +WEAVE_SERVER_ENABLE_LOGGING=true +FLASK_APP=weave.weave_server + +ddtrace-run flask run --port 9994 diff --git a/scripts/weave_server.sh b/scripts/weave_server.sh index a2cebdd4134..91bc19fccd6 100755 --- a/scripts/weave_server.sh +++ b/scripts/weave_server.sh @@ -2,7 +2,11 @@ # We could set WEAVE_BACKEND_HOST=http://localhost:9994/__weave but the frontend dev server # automatically forwards so it shouldn't be necessary. -( - source ./config/auth_modes.sh - WEAVE_DISABLE_ANALYTICS=true WEAVE_SERVER_ENABLE_LOGGING=true FLASK_DEBUG=1 FLASK_APP=weave.weave_server flask run --port 9994 -) +source ./config/auth_modes.sh + +WEAVE_DISABLE_ANALYTICS=true +WEAVE_SERVER_ENABLE_LOGGING=true +FLASK_DEBUG=1 +FLASK_APP=weave.weave_server + +flask run --port 9994 diff --git a/scripts/weave_server_replay.sh b/scripts/weave_server_replay.sh index d8242a8841e..41814fb476d 100755 --- a/scripts/weave_server_replay.sh +++ b/scripts/weave_server_replay.sh @@ -1,3 +1,7 @@ #!/bin/sh -WEAVE_SERVER_DEBUG=true WEAVE_SERVER_ENABLE_LOGGING=true FLASK_APP=weave.weave_server flask run --port 9994 +export WEAVE_SERVER_DEBUG=true +export WEAVE_SERVER_ENABLE_LOGGING=true +export FLASK_APP=weave.weave_server + +flask run --port 9994 diff --git a/scripts/weave_server_test.sh b/scripts/weave_server_test.sh index 3f084bfcb63..366ad390ac9 100755 --- a/scripts/weave_server_test.sh +++ b/scripts/weave_server_test.sh @@ -1,3 +1,10 @@ #!/bin/sh -WEAVE_CI=true WEAVE_DISABLE_ANALYTICS=true WEAVE_SERVER_DEBUG=true WEAVE_SERVER_ENABLE_LOGGING=true WEAVE_WANDB_GQL_NUM_TIMEOUT_RETRIES=1 FLASK_APP=weave.weave_server flask run --port 9994 $@ +export WEAVE_CI=true +export WEAVE_DISABLE_ANALYTICS=true +export WEAVE_SERVER_DEBUG=true +export WEAVE_SERVER_ENABLE_LOGGING=true +export WEAVE_WANDB_GQL_NUM_TIMEOUT_RETRIES=1 +export FLASK_APP=weave.weave_server + +flask run --port 9994 "$@" From 68c9fe966673592dfd90249403d56046f9421573 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Wed, 21 Aug 2024 00:52:06 -0400 Subject: [PATCH 04/84] move to legacy: syndata --- examples/experimental/AutoBoard.ipynb | 4 ++-- examples/experimental/Monitor.ipynb | 8 ++++---- examples/experimental/MonitorPanelPlot.ipynb | 8 ++++---- .../ProductionMonitoring/MonitorPanelPlotGeneric.ipynb | 8 ++++---- examples/experimental/app/beautiful_runs.ipynb | 10 ++++------ examples/reference/layout/Each.ipynb | 4 ++-- examples/reference/panels/plot/synced_axes.ipynb | 2 +- pyrightconfig.json | 4 ++-- weave/{ => legacy/scripts}/syndata.py | 4 ++-- weave/{ => legacy/scripts}/syndata_mon.py | 2 +- 10 files changed, 26 insertions(+), 28 deletions(-) rename weave/{ => legacy/scripts}/syndata.py (98%) rename weave/{ => legacy/scripts}/syndata_mon.py (98%) diff --git a/examples/experimental/AutoBoard.ipynb b/examples/experimental/AutoBoard.ipynb index 0af2db14d81..2a75baac7b2 100644 --- a/examples/experimental/AutoBoard.ipynb +++ b/examples/experimental/AutoBoard.ipynb @@ -8,8 +8,8 @@ "outputs": [], "source": [ "import weave\n", - "from weave import syndata\n", - "from weave import syndata_mon\n", + "from weave.legacy.scripts import syndata\n", + "from weave.legacy.scripts import syndata_mon\n", "from weave.legacy.panels_py import panel_autoboard" ] }, diff --git a/examples/experimental/Monitor.ipynb b/examples/experimental/Monitor.ipynb index 0f1f560b371..fee2766ae24 100644 --- a/examples/experimental/Monitor.ipynb +++ b/examples/experimental/Monitor.ipynb @@ -7,7 +7,7 @@ "source": [ "# Model monitoring dashboard example\n", "\n", - "This notebook currently requires the plotly library to be installed." + "This notebook currently requires the plotly library to be installed.\n" ] }, { @@ -21,7 +21,7 @@ "import weave\n", "# Weave package now defaults to eager mode, but lazy mode required for this example notebook for now.\n", "weave.use_lazy_execution()\n", - "from weave import syndata_mon\n", + "from weave.legacy.scripts import syndata_mon\n", "from weave.legacy.arrow.list_ import dataframe_to_arrow\n", "from weave.legacy.ecosystem import wandb" ] @@ -31,7 +31,7 @@ "id": "8519889f", "metadata": {}, "source": [ - "## Create synthetic data" + "## Create synthetic data\n" ] }, { @@ -53,7 +53,7 @@ "id": "cdd59e39", "metadata": {}, "source": [ - "## Create a Weave Board for the data" + "## Create a Weave Board for the data\n" ] }, { diff --git a/examples/experimental/MonitorPanelPlot.ipynb b/examples/experimental/MonitorPanelPlot.ipynb index a819fb54f69..647bc0de53b 100644 --- a/examples/experimental/MonitorPanelPlot.ipynb +++ b/examples/experimental/MonitorPanelPlot.ipynb @@ -7,7 +7,7 @@ "source": [ "# Model monitoring dashboard example\n", "\n", - "This notebook currently requires the plotly library to be installed." + "This notebook currently requires the plotly library to be installed.\n" ] }, { @@ -20,7 +20,7 @@ "import weave\n", "import weave.legacy.panels\n", "weave.use_lazy_execution()\n", - "from weave import syndata_mon" + "from weave.legacy.scripts import syndata_mon" ] }, { @@ -28,7 +28,7 @@ "id": "8519889f", "metadata": {}, "source": [ - "## Create synthetic data" + "## Create synthetic data\n" ] }, { @@ -50,7 +50,7 @@ "id": "cdd59e39", "metadata": {}, "source": [ - "## Create a Weave Board for the data" + "## Create a Weave Board for the data\n" ] }, { diff --git a/examples/experimental/ProductionMonitoring/MonitorPanelPlotGeneric.ipynb b/examples/experimental/ProductionMonitoring/MonitorPanelPlotGeneric.ipynb index 77daeb4510c..ca7752dbebf 100644 --- a/examples/experimental/ProductionMonitoring/MonitorPanelPlotGeneric.ipynb +++ b/examples/experimental/ProductionMonitoring/MonitorPanelPlotGeneric.ipynb @@ -7,7 +7,7 @@ "source": [ "# Model monitoring dashboard example\n", "\n", - "This notebook currently requires the plotly library to be installed." + "This notebook currently requires the plotly library to be installed.\n" ] }, { @@ -18,7 +18,7 @@ "outputs": [], "source": [ "import weave\n", - "from weave import syndata_mon" + "from weave.legacy.scripts import syndata_mon" ] }, { @@ -26,7 +26,7 @@ "id": "8519889f", "metadata": {}, "source": [ - "## Create synthetic data" + "## Create synthetic data\n" ] }, { @@ -360,7 +360,7 @@ "id": "cdd59e39", "metadata": {}, "source": [ - "## Create a Weave Board for the data" + "## Create a Weave Board for the data\n" ] }, { diff --git a/examples/experimental/app/beautiful_runs.ipynb b/examples/experimental/app/beautiful_runs.ipynb index 772ac6e7d9a..a4d880471db 100644 --- a/examples/experimental/app/beautiful_runs.ipynb +++ b/examples/experimental/app/beautiful_runs.ipynb @@ -15,12 +15,10 @@ "\n", "We've also factored out a \"groupby\" variable so you can group by run parameters from the varbar. You can change it to 'id' or 'config.b' to try other groupings.\n", "\n", - "All of this behavior is complete defined by the code below. \n", + "All of this behavior is complete defined by the code below.\n", "\n", - "\n", - "\n", - "*TODO: There is one major outstanding issue here: we're using the start of the bucket for the x-coordinate\n", - "instead of the midpoint! Fix this!*\n" + "_TODO: There is one major outstanding issue here: we're using the start of the bucket for the x-coordinate\n", + "instead of the midpoint! Fix this!_\n" ] }, { @@ -31,7 +29,7 @@ "outputs": [], "source": [ "import weave\n", - "from weave import syndata" + "from weave.legacy.scripts import syndata" ] }, { diff --git a/examples/reference/layout/Each.ipynb b/examples/reference/layout/Each.ipynb index 4133a03dd4d..17248f033d2 100644 --- a/examples/reference/layout/Each.ipynb +++ b/examples/reference/layout/Each.ipynb @@ -9,7 +9,7 @@ "source": [ "from PIL import Image\n", "import weave\n", - "from weave import syndata\n", + "from weave.legacy.scripts import syndata\n", "from weave.legacy import panels" ] }, @@ -20,7 +20,7 @@ "source": [ "## PanelEach\n", "\n", - "PanelEach renders each item in a list." + "PanelEach renders each item in a list.\n" ] }, { diff --git a/examples/reference/panels/plot/synced_axes.ipynb b/examples/reference/panels/plot/synced_axes.ipynb index 9d227a2470b..4f39243c180 100644 --- a/examples/reference/panels/plot/synced_axes.ipynb +++ b/examples/reference/panels/plot/synced_axes.ipynb @@ -18,7 +18,7 @@ "metadata": {}, "outputs": [], "source": [ - "from weave import syndata" + "from weave.legacy.scripts import syndata" ] }, { diff --git a/pyrightconfig.json b/pyrightconfig.json index 84be57f4887..a42ea6cf76c 100644 --- a/pyrightconfig.json +++ b/pyrightconfig.json @@ -71,8 +71,8 @@ "weave/signal_handlers.py", "weave/stream_data_interfaces.py", "weave/storage.py", - "weave/syndata.py", - "weave/syndata_mon.py", + "weave/legacy/scripts/syndata.py", + "weave/legacy/scripts/syndata_mon.py", "weave/tests", "weave/types_numpy.py", "weave/usage_analytics.py", diff --git a/weave/syndata.py b/weave/legacy/scripts/syndata.py similarity index 98% rename from weave/syndata.py rename to weave/legacy/scripts/syndata.py index 0e6cb9fe684..9f7c697b556 100644 --- a/weave/syndata.py +++ b/weave/legacy/scripts/syndata.py @@ -5,8 +5,8 @@ import pyarrow as pa from scipy.signal import butter, filtfilt -from . import util -from .legacy.ops_arrow import ArrowWeaveList +from ... import util +from ..ops_arrow import ArrowWeaveList value_fns: list[typing.Any] = [ lambda steps: steps**2, diff --git a/weave/syndata_mon.py b/weave/legacy/scripts/syndata_mon.py similarity index 98% rename from weave/syndata_mon.py rename to weave/legacy/scripts/syndata_mon.py index a9838b99746..d93d7ccb64d 100644 --- a/weave/syndata_mon.py +++ b/weave/legacy/scripts/syndata_mon.py @@ -95,7 +95,7 @@ def random_predictions(n_users: int = 10) -> ArrowWeaveList: # Read the file and generate prompts with open( os.path.abspath( - os.path.join(os.path.dirname(__file__), "testdata/t8.shakespeare.txt") + os.path.join(os.path.dirname(__file__), "../..", "testdata/t8.shakespeare.txt") ), "r", ) as f: From 8531d881fc20f5ccc299e0d51e72ab1fb3d592c7 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Wed, 21 Aug 2024 00:38:26 -0400 Subject: [PATCH 05/84] move to legacy: usage_analytics, weave_inspector --- weave/legacy/context_state.py | 4 ++-- weave/legacy/graph.py | 4 ++-- weave/{ => legacy}/usage_analytics.py | 19 ++++++++++--------- weave/{ => legacy}/weave_inspector.py | 4 ++-- weave/query_api.py | 2 +- weave/weave_types.py | 4 ++-- 6 files changed, 19 insertions(+), 18 deletions(-) rename weave/{ => legacy}/usage_analytics.py (62%) rename weave/{ => legacy}/weave_inspector.py (99%) diff --git a/weave/legacy/context_state.py b/weave/legacy/context_state.py index 7ae2848dec3..15741b77987 100644 --- a/weave/legacy/context_state.py +++ b/weave/legacy/context_state.py @@ -218,11 +218,11 @@ def analytics_disabled(): _analytics_enabled.reset(analytics_token) -def analytics_enabled(): +def analytics_enabled() -> bool: return _analytics_enabled.get() -def disable_analytics(): +def disable_analytics() -> contextvars.Token: return _analytics_enabled.set(False) diff --git a/weave/legacy/graph.py b/weave/legacy/graph.py index 51353cd5bb2..cb05793a81d 100644 --- a/weave/legacy/graph.py +++ b/weave/legacy/graph.py @@ -6,7 +6,7 @@ from weave.legacy import uris if typing.TYPE_CHECKING: - from weave import weave_inspector + from weave.legacy import weave_inspector T = typing.TypeVar("T") @@ -39,7 +39,7 @@ def to_json(self) -> dict: def _inspect(self) -> "weave_inspector.NodeInspector": """Only intended to be used by developers to help debug the graph.""" # Circular import, so we do it here. - from weave import weave_inspector + from weave.legacy import weave_inspector return weave_inspector.NodeInspector(self) diff --git a/weave/usage_analytics.py b/weave/legacy/usage_analytics.py similarity index 62% rename from weave/usage_analytics.py rename to weave/legacy/usage_analytics.py index ce3d0aeb571..a9fe6866a58 100644 --- a/weave/usage_analytics.py +++ b/weave/legacy/usage_analytics.py @@ -1,22 +1,23 @@ import socket +from typing import Optional import analytics from weave.legacy import context_state -from . import environment +from .. import environment analytics.write_key = "uJ8vZgKqTBVH6ZdhD4GZGZYsR7ucfJmb" -def hostname(): +def hostname() -> str: return socket.gethostname() identify_called = False -def _identify(): +def _identify() -> None: global identify_called if not identify_called: host = hostname() @@ -24,14 +25,14 @@ def _identify(): identify_called = True -def analytics_enabled(): - context_enabled = context_state.analytics_enabled() - env_enabled = environment.usage_analytics_enabled() +def analytics_enabled() -> bool: + context_enabled: bool = context_state.analytics_enabled() + env_enabled: bool = environment.usage_analytics_enabled() return context_enabled and env_enabled -def track(action: str, info=None): +def track(action: str, info: Optional[dict] = None) -> None: if not analytics_enabled(): return try: @@ -43,9 +44,9 @@ def track(action: str, info=None): pass -def use_called(): +def use_called() -> None: track("called use") -def show_called(info=None): +def show_called(info: Optional[dict] = None) -> None: track("called show", info) diff --git a/weave/weave_inspector.py b/weave/legacy/weave_inspector.py similarity index 99% rename from weave/weave_inspector.py rename to weave/legacy/weave_inspector.py index b25a6c4ea21..15814ada84e 100644 --- a/weave/weave_inspector.py +++ b/weave/legacy/weave_inspector.py @@ -107,8 +107,8 @@ from weave.legacy import graph -from . import weave_types as types -from .legacy.partial_object import PartialObjectType +from .. import weave_types as types +from .partial_object import PartialObjectType def _trimmed_string(s: str, max_len: int = 20) -> str: diff --git a/weave/query_api.py b/weave/query_api.py index 626d5345eba..f457072c8e6 100644 --- a/weave/query_api.py +++ b/weave/query_api.py @@ -29,7 +29,7 @@ from . import errors from weave.legacy.decorators import weave_class, mutation, type -from . import usage_analytics +from weave.legacy import usage_analytics from weave.legacy.context import ( use_fixed_server_port, use_frontend_devmode, diff --git a/weave/weave_types.py b/weave/weave_types.py index e297bef18a3..9bc82f9039d 100644 --- a/weave/weave_types.py +++ b/weave/weave_types.py @@ -20,7 +20,7 @@ from weave.legacy import artifact_base from weave.legacy.artifact_fs import FilesystemArtifact - from . import weave_inspector + from .legacy import weave_inspector def to_weavejs_typekey(k: str) -> str: @@ -456,7 +456,7 @@ def _make(cls, kwargs={}): def _inspect(self) -> "weave_inspector.TypeInspector": """Only intended to be used by developers to help debug the graph.""" # Circular import, so we do it here. - from . import weave_inspector + from .legacy import weave_inspector return weave_inspector.TypeInspector(self) From 7a09f5bfd4c311742c9efd723e100db88a8cefdb Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Wed, 21 Aug 2024 11:55:22 -0400 Subject: [PATCH 06/84] move to legacy: stream_data_interfaces --- weave/engine_trace.py | 3 ++- weave/legacy/monitoring/langchain.py | 2 +- weave/legacy/monitoring/monitor.py | 3 ++- weave/legacy/ops_domain/trace_tree.py | 2 +- weave/legacy/run_streamtable_span.py | 2 +- weave/{ => legacy}/stream_data_interfaces.py | 0 6 files changed, 7 insertions(+), 5 deletions(-) rename weave/{ => legacy}/stream_data_interfaces.py (100%) diff --git a/weave/engine_trace.py b/weave/engine_trace.py index 2039c714473..7423b8048ca 100644 --- a/weave/engine_trace.py +++ b/weave/engine_trace.py @@ -18,7 +18,8 @@ import time import typing -from . import environment, logs, stream_data_interfaces +from . import environment, logs +from .legacy import stream_data_interfaces # Thanks co-pilot! diff --git a/weave/legacy/monitoring/langchain.py b/weave/legacy/monitoring/langchain.py index f5e50205cf7..8e3afddc148 100644 --- a/weave/legacy/monitoring/langchain.py +++ b/weave/legacy/monitoring/langchain.py @@ -11,7 +11,7 @@ from langchain.callbacks.tracers.schemas import Run from wandb.sdk.data_types import trace_tree -from weave import stream_data_interfaces +from weave.legacy import stream_data_interfaces from weave.legacy.monitoring import StreamTable diff --git a/weave/legacy/monitoring/monitor.py b/weave/legacy/monitoring/monitor.py index b586e0f4565..69fe290a023 100644 --- a/weave/legacy/monitoring/monitor.py +++ b/weave/legacy/monitoring/monitor.py @@ -11,10 +11,11 @@ import typing import uuid -from weave import call_context, errors, stream_data_interfaces +from weave import call_context, errors from weave.legacy import ( graph, run_streamtable_span, + stream_data_interfaces ) from weave.legacy.wandb_interface.wandb_stream_table import StreamTable from weave.trace import context as trace_context diff --git a/weave/legacy/ops_domain/trace_tree.py b/weave/legacy/ops_domain/trace_tree.py index d9c4ae5d3f3..e4f618eafa8 100644 --- a/weave/legacy/ops_domain/trace_tree.py +++ b/weave/legacy/ops_domain/trace_tree.py @@ -12,7 +12,7 @@ from wandb.sdk.data_types.trace_tree import Span as WBSpan from weave import query_api as weave -from weave import stream_data_interfaces +from weave.legacy import stream_data_interfaces from weave import weave_types as types from weave.legacy import op_def from weave.legacy.decorator_op import op diff --git a/weave/legacy/run_streamtable_span.py b/weave/legacy/run_streamtable_span.py index f59249fc0e7..269187d8b0b 100644 --- a/weave/legacy/run_streamtable_span.py +++ b/weave/legacy/run_streamtable_span.py @@ -1,7 +1,7 @@ import typing from typing import Iterable -from weave import stream_data_interfaces +from weave.legacy import stream_data_interfaces from weave.eager import WeaveIter from weave.legacy import artifact_wandb, uris from weave.legacy.run import Run diff --git a/weave/stream_data_interfaces.py b/weave/legacy/stream_data_interfaces.py similarity index 100% rename from weave/stream_data_interfaces.py rename to weave/legacy/stream_data_interfaces.py From bcf66704fe51eeba9f7cec0995f492a52622a3d4 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Wed, 21 Aug 2024 18:58:21 -0400 Subject: [PATCH 07/84] move to trace: autopatch,call_context --- weave/autopatch.py | 49 ----------------------- weave/conftest.py | 3 +- weave/integrations/langchain/langchain.py | 2 +- weave/legacy/monitoring/monitor.py | 4 +- weave/legacy/monitoring/openai/openai.py | 2 +- weave/parallelism.py | 2 +- weave/trace/autopatch.py | 49 +++++++++++++++++++++++ weave/{ => trace}/call_context.py | 2 +- weave/trace/op.py | 3 +- weave/trace_api.py | 2 +- weave/weave_client.py | 3 +- weave/weave_init.py | 3 +- 12 files changed, 63 insertions(+), 61 deletions(-) delete mode 100644 weave/autopatch.py create mode 100644 weave/trace/autopatch.py rename weave/{ => trace}/call_context.py (98%) diff --git a/weave/autopatch.py b/weave/autopatch.py deleted file mode 100644 index 2bd08db073b..00000000000 --- a/weave/autopatch.py +++ /dev/null @@ -1,49 +0,0 @@ -"""Basic autopatching of trackable libraries. - -This module should not require any dependencies beyond the standard library. It should -check if libraries are installed and imported and patch in the case that they are. -""" - - -def autopatch() -> None: - from .integrations.anthropic.anthropic_sdk import anthropic_patcher - from .integrations.cohere.cohere_sdk import cohere_patcher - from .integrations.dspy.dspy_sdk import dspy_patcher - from .integrations.groq.groq_sdk import groq_patcher - from .integrations.langchain.langchain import langchain_patcher - from .integrations.litellm.litellm import litellm_patcher - from .integrations.llamaindex.llamaindex import llamaindex_patcher - from .integrations.mistral.mistral import mistral_patcher - from .integrations.openai.openai_sdk import openai_patcher - - openai_patcher.attempt_patch() - mistral_patcher.attempt_patch() - litellm_patcher.attempt_patch() - llamaindex_patcher.attempt_patch() - langchain_patcher.attempt_patch() - anthropic_patcher.attempt_patch() - groq_patcher.attempt_patch() - dspy_patcher.attempt_patch() - cohere_patcher.attempt_patch() - - -def reset_autopatch() -> None: - from .integrations.anthropic.anthropic_sdk import anthropic_patcher - from .integrations.cohere.cohere_sdk import cohere_patcher - from .integrations.dspy.dspy_sdk import dspy_patcher - from .integrations.groq.groq_sdk import groq_patcher - from .integrations.langchain.langchain import langchain_patcher - from .integrations.litellm.litellm import litellm_patcher - from .integrations.llamaindex.llamaindex import llamaindex_patcher - from .integrations.mistral.mistral import mistral_patcher - from .integrations.openai.openai_sdk import openai_patcher - - openai_patcher.undo_patch() - mistral_patcher.undo_patch() - litellm_patcher.undo_patch() - llamaindex_patcher.undo_patch() - langchain_patcher.undo_patch() - anthropic_patcher.undo_patch() - groq_patcher.undo_patch() - dspy_patcher.undo_patch() - cohere_patcher.undo_patch() diff --git a/weave/conftest.py b/weave/conftest.py index b7b94fd2e70..0b401ce0ff4 100644 --- a/weave/conftest.py +++ b/weave/conftest.py @@ -26,10 +26,11 @@ trace_server_interface as tsi, ) -from . import autopatch, environment, logs +from . import environment, logs from .tests import fixture_fakewandb from .tests.trace.trace_server_clickhouse_conftest import * from .tests.wandb_system_tests_conftest import * +from .trace import autopatch logs.configure_logger() diff --git a/weave/integrations/langchain/langchain.py b/weave/integrations/langchain/langchain.py index 2c5fc3c2e03..52e7be8ac39 100644 --- a/weave/integrations/langchain/langchain.py +++ b/weave/integrations/langchain/langchain.py @@ -35,12 +35,12 @@ from contextvars import ContextVar from uuid import UUID -from weave import call_context from weave.client_context import weave_client as weave_client_context from weave.integrations.integration_utilities import ( make_pythonic_function_name, truncate_op_name, ) +from weave.trace import call_context from weave.trace.patcher import Patcher from weave.weave_client import Call diff --git a/weave/legacy/monitoring/monitor.py b/weave/legacy/monitoring/monitor.py index 69fe290a023..ff0e67ba359 100644 --- a/weave/legacy/monitoring/monitor.py +++ b/weave/legacy/monitoring/monitor.py @@ -11,14 +11,14 @@ import typing import uuid -from weave import call_context, errors +from weave import errors from weave.legacy import ( graph, run_streamtable_span, stream_data_interfaces ) from weave.legacy.wandb_interface.wandb_stream_table import StreamTable -from weave.trace import context as trace_context +from weave.trace import call_context, context as trace_context from weave.client_context import weave_client as weave_client_context logger = logging.getLogger(__name__) diff --git a/weave/legacy/monitoring/openai/openai.py b/weave/legacy/monitoring/openai/openai.py index 6e91314253d..c002ec85c4c 100644 --- a/weave/legacy/monitoring/openai/openai.py +++ b/weave/legacy/monitoring/openai/openai.py @@ -10,7 +10,7 @@ from openai import AsyncStream, Stream from openai.types.chat import ChatCompletion, ChatCompletionMessageParam from packaging import version -from weave import call_context +from weave.trace import call_context from weave.client_context import weave_client as weave_client_context from weave.legacy.monitoring.monitor import _get_global_monitor from weave.legacy.monitoring.openai.models import * diff --git a/weave/parallelism.py b/weave/parallelism.py index dab68b09e09..a11dcfeac76 100644 --- a/weave/parallelism.py +++ b/weave/parallelism.py @@ -3,7 +3,6 @@ from concurrent.futures import ThreadPoolExecutor from typing import Callable, Generator, Iterator, Optional, TypeVar -from weave import call_context from weave.legacy import ( cache, context, @@ -13,6 +12,7 @@ memo, wandb_api, ) +from weave.trace import call_context # Must be power of 2 MAX_PARALLELISM = 16 diff --git a/weave/trace/autopatch.py b/weave/trace/autopatch.py new file mode 100644 index 00000000000..d1a7bb07edb --- /dev/null +++ b/weave/trace/autopatch.py @@ -0,0 +1,49 @@ +"""Basic autopatching of trackable libraries. + +This module should not require any dependencies beyond the standard library. It should +check if libraries are installed and imported and patch in the case that they are. +""" + + +def autopatch() -> None: + from ..integrations.anthropic.anthropic_sdk import anthropic_patcher + from ..integrations.cohere.cohere_sdk import cohere_patcher + from ..integrations.dspy.dspy_sdk import dspy_patcher + from ..integrations.groq.groq_sdk import groq_patcher + from ..integrations.langchain.langchain import langchain_patcher + from ..integrations.litellm.litellm import litellm_patcher + from ..integrations.llamaindex.llamaindex import llamaindex_patcher + from ..integrations.mistral.mistral import mistral_patcher + from ..integrations.openai.openai_sdk import openai_patcher + + openai_patcher.attempt_patch() + mistral_patcher.attempt_patch() + litellm_patcher.attempt_patch() + llamaindex_patcher.attempt_patch() + langchain_patcher.attempt_patch() + anthropic_patcher.attempt_patch() + groq_patcher.attempt_patch() + dspy_patcher.attempt_patch() + cohere_patcher.attempt_patch() + + +def reset_autopatch() -> None: + from ..integrations.anthropic.anthropic_sdk import anthropic_patcher + from ..integrations.cohere.cohere_sdk import cohere_patcher + from ..integrations.dspy.dspy_sdk import dspy_patcher + from ..integrations.groq.groq_sdk import groq_patcher + from ..integrations.langchain.langchain import langchain_patcher + from ..integrations.litellm.litellm import litellm_patcher + from ..integrations.llamaindex.llamaindex import llamaindex_patcher + from ..integrations.mistral.mistral import mistral_patcher + from ..integrations.openai.openai_sdk import openai_patcher + + openai_patcher.undo_patch() + mistral_patcher.undo_patch() + litellm_patcher.undo_patch() + llamaindex_patcher.undo_patch() + langchain_patcher.undo_patch() + anthropic_patcher.undo_patch() + groq_patcher.undo_patch() + dspy_patcher.undo_patch() + cohere_patcher.undo_patch() diff --git a/weave/call_context.py b/weave/trace/call_context.py similarity index 98% rename from weave/call_context.py rename to weave/trace/call_context.py index 2c3860e80c3..74d9d9ed1e3 100644 --- a/weave/call_context.py +++ b/weave/trace/call_context.py @@ -6,7 +6,7 @@ if typing.TYPE_CHECKING: # from .run import Run - from .weave_client import Call + from ..weave_client import Call _call_stack: contextvars.ContextVar[list["Call"]] = contextvars.ContextVar( "call", default=[] diff --git a/weave/trace/op.py b/weave/trace/op.py index 8c81869f5a7..559cd0a4d45 100644 --- a/weave/trace/op.py +++ b/weave/trace/op.py @@ -17,10 +17,9 @@ runtime_checkable, ) -from weave import call_context from weave.client_context import weave_client as weave_client_context from weave.legacy import context_state -from weave.trace import box, settings +from weave.trace import box, call_context, settings from weave.trace.context import call_attributes from weave.trace.errors import OpCallError from weave.trace.refs import ObjectRef diff --git a/weave/trace_api.py b/weave/trace_api.py index 22a8b87af60..a586cfe4639 100644 --- a/weave/trace_api.py +++ b/weave/trace_api.py @@ -6,8 +6,8 @@ import time from typing import Any, Callable, Iterator, Optional, Union -from weave.call_context import get_current_call from weave.client_context import weave_client as weave_client_context +from weave.trace.call_context import get_current_call # TODO: type_serializers is imported here to trigger registration of the image serializer. # There is probably a better place for this, but including here for now to get the fix in. diff --git a/weave/weave_client.py b/weave/weave_client.py index d65275180d9..f2790e36f12 100644 --- a/weave/weave_client.py +++ b/weave/weave_client.py @@ -9,11 +9,12 @@ import pydantic from requests import HTTPError -from weave import call_context, trace_sentry, urls, version +from weave import trace_sentry, urls, version from weave.client_context import weave_client as weave_client_context from weave.exception import exception_to_json_str from weave.feedback import FeedbackQuery, RefFeedbackQuery from weave.table import Table +from weave.trace import call_context from weave.trace.object_record import ( ObjectRecord, dataclass_object_record, diff --git a/weave/weave_init.py b/weave/weave_init.py index d2af6bf5eb7..6febcbc3c88 100644 --- a/weave/weave_init.py +++ b/weave/weave_init.py @@ -2,7 +2,8 @@ from weave.client_context import weave_client as weave_client_context -from . import autopatch, errors, init_message, trace_sentry, weave_client +from . import errors, init_message, trace_sentry, weave_client +from .trace import autopatch from .trace_server import remote_http_trace_server, sqlite_trace_server _current_inited_client = None From ee001d643de69efb288d7a6a5109f7baceb90157 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Wed, 21 Aug 2024 19:02:21 -0400 Subject: [PATCH 08/84] move to trace: feedback --- weave/{ => trace}/feedback.py | 2 +- weave/weave_client.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename weave/{ => trace}/feedback.py (99%) diff --git a/weave/feedback.py b/weave/trace/feedback.py similarity index 99% rename from weave/feedback.py rename to weave/trace/feedback.py index feffab69234..5f911ed4e39 100644 --- a/weave/feedback.py +++ b/weave/trace/feedback.py @@ -13,7 +13,7 @@ from weave.trace_server import trace_server_interface as tsi from weave.trace_server.interface.query import Query -from . import util +from .. import util class Feedbacks(AbstractRichContainer[tsi.Feedback]): diff --git a/weave/weave_client.py b/weave/weave_client.py index f2790e36f12..1d136f7a994 100644 --- a/weave/weave_client.py +++ b/weave/weave_client.py @@ -12,9 +12,9 @@ from weave import trace_sentry, urls, version from weave.client_context import weave_client as weave_client_context from weave.exception import exception_to_json_str -from weave.feedback import FeedbackQuery, RefFeedbackQuery from weave.table import Table from weave.trace import call_context +from weave.trace.feedback import FeedbackQuery, RefFeedbackQuery from weave.trace.object_record import ( ObjectRecord, dataclass_object_record, From 07255036d436e9b27d5585d8df3ac053e3defd28 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Wed, 21 Aug 2024 20:08:17 -0400 Subject: [PATCH 09/84] move to trace: rich_* --- weave/trace/feedback.py | 6 +++--- weave/{ => trace}/rich_container.py | 2 +- weave/{ => trace}/rich_pydantic_util.py | 2 +- weave/{refs.py => trace/rich_refs.py} | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) rename weave/{ => trace}/rich_container.py (97%) rename weave/{ => trace}/rich_pydantic_util.py (98%) rename weave/{refs.py => trace/rich_refs.py} (95%) diff --git a/weave/trace/feedback.py b/weave/trace/feedback.py index 5f911ed4e39..01103f82d02 100644 --- a/weave/trace/feedback.py +++ b/weave/trace/feedback.py @@ -5,11 +5,11 @@ from rich.table import Table -from weave import rich_pydantic_util from weave.client_context import weave_client as weave_client_context -from weave.refs import Refs -from weave.rich_container import AbstractRichContainer +from weave.trace import rich_pydantic_util from weave.trace.refs import parse_uri +from weave.trace.rich_container import AbstractRichContainer +from weave.trace.rich_refs import Refs from weave.trace_server import trace_server_interface as tsi from weave.trace_server.interface.query import Query diff --git a/weave/rich_container.py b/weave/trace/rich_container.py similarity index 97% rename from weave/rich_container.py rename to weave/trace/rich_container.py index 626e290a449..a8a9565faf1 100644 --- a/weave/rich_container.py +++ b/weave/trace/rich_container.py @@ -3,7 +3,7 @@ from rich.table import Table -from weave import rich_pydantic_util +from weave.trace import rich_pydantic_util T = TypeVar("T") diff --git a/weave/rich_pydantic_util.py b/weave/trace/rich_pydantic_util.py similarity index 98% rename from weave/rich_pydantic_util.py rename to weave/trace/rich_pydantic_util.py index 33114d9b92a..1c2c1474ef7 100644 --- a/weave/rich_pydantic_util.py +++ b/weave/trace/rich_pydantic_util.py @@ -6,7 +6,7 @@ from rich.console import Console from rich.table import Table -from . import util +from .. import util def dict_to_table(d: dict[str, Any]) -> Table: diff --git a/weave/refs.py b/weave/trace/rich_refs.py similarity index 95% rename from weave/refs.py rename to weave/trace/rich_refs.py index af6e858ffe2..c72e07f4227 100644 --- a/weave/refs.py +++ b/weave/trace/rich_refs.py @@ -5,8 +5,8 @@ from rich.table import Table from weave.client_context import weave_client as weave_client_context -from weave.rich_container import AbstractRichContainer from weave.trace.refs import AnyRef, CallRef, parse_uri +from weave.trace.rich_container import AbstractRichContainer from weave.trace.vals import WeaveObject From 7c3a708466328b20cefc8dfc61abbcacd6c07b51 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Wed, 21 Aug 2024 19:26:44 -0400 Subject: [PATCH 10/84] move to legacy: weave_client --- docs/scripts/generate_python_sdk_docs.py | 2 +- weave/client_context/weave_client.py | 2 +- weave/conftest.py | 4 +-- weave/flow/eval.py | 2 +- weave/flow/obj.py | 2 +- .../integrations/anthropic/anthropic_test.py | 10 +++--- weave/integrations/cohere/cohere_test.py | 8 ++--- weave/integrations/dspy/dspy_test.py | 2 +- weave/integrations/groq/groq_test.py | 10 +++--- weave/integrations/langchain/langchain.py | 2 +- .../integrations/langchain/langchain_test.py | 2 +- weave/integrations/litellm/litellm_test.py | 10 +++--- weave/integrations/llamaindex/llamaindex.py | 2 +- .../llamaindex/llamaindex_test.py | 4 +-- weave/integrations/mistral/mistral_test.py | 12 ++++--- weave/integrations/openai/openai_test.py | 32 +++++++++++-------- weave/legacy/op_def.py | 2 +- weave/query_api.py | 2 +- weave/ref_base.py | 2 +- weave/tests/trace/test_anonymous_ops.py | 2 +- weave/tests/trace/test_client_trace.py | 3 +- weave/tests/trace/test_op_call_method.py | 2 +- .../trace/test_op_decorator_behaviour.py | 2 +- weave/tests/trace/test_weave_client.py | 4 +-- .../trace/trace_server_clickhouse_conftest.py | 2 +- weave/trace/call_context.py | 2 +- weave/trace/op.py | 2 +- weave/trace/tests/test_op_return_forms.py | 2 +- weave/{ => trace}/weave_client.py | 2 +- weave/trace_api.py | 3 +- weave/type_serializers/Image/image_test.py | 2 +- weave/weave_init.py | 4 +-- 32 files changed, 76 insertions(+), 68 deletions(-) rename weave/{ => trace}/weave_client.py (99%) diff --git a/docs/scripts/generate_python_sdk_docs.py b/docs/scripts/generate_python_sdk_docs.py index cbe040b9760..889091a6c2f 100644 --- a/docs/scripts/generate_python_sdk_docs.py +++ b/docs/scripts/generate_python_sdk_docs.py @@ -263,8 +263,8 @@ def doc_module(module, root_path="./docs/reference/python-sdk", module_root_path def main(): import weave from weave import feedback - from weave import weave_client as client from weave.trace import util + from weave.trace import weave_client as client from weave.trace_server import ( remote_http_trace_server, trace_server_interface, diff --git a/weave/client_context/weave_client.py b/weave/client_context/weave_client.py index ad0eb78b3dd..c0b3da823df 100644 --- a/weave/client_context/weave_client.py +++ b/weave/client_context/weave_client.py @@ -5,7 +5,7 @@ from weave.legacy import context_state if TYPE_CHECKING: - from weave.weave_client import WeaveClient + from weave.trace.weave_client import WeaveClient _global_weave_client: Optional["WeaveClient"] = None lock = threading.Lock() diff --git a/weave/conftest.py b/weave/conftest.py index 0b401ce0ff4..9ff85968cc8 100644 --- a/weave/conftest.py +++ b/weave/conftest.py @@ -22,9 +22,7 @@ remote_http_trace_server, sqlite_trace_server, ) -from weave.trace_server import ( - trace_server_interface as tsi, -) +from weave.trace_server import trace_server_interface as tsi from . import environment, logs from .tests import fixture_fakewandb diff --git a/weave/flow/eval.py b/weave/flow/eval.py index 49122b3d1d1..c69cd675925 100644 --- a/weave/flow/eval.py +++ b/weave/flow/eval.py @@ -24,7 +24,7 @@ from weave.trace.errors import OpCallError from weave.trace.op import Op from weave.trace.vals import WeaveObject -from weave.weave_client import get_ref +from weave.trace.weave_client import get_ref console = Console() diff --git a/weave/flow/obj.py b/weave/flow/obj.py index cdfda1899e1..07dc694d060 100644 --- a/weave/flow/obj.py +++ b/weave/flow/obj.py @@ -11,7 +11,7 @@ from weave.trace.op import ObjectRef, Op, call from weave.trace.vals import WeaveObject, pydantic_getattribute -from weave.weave_client import get_ref +from weave.trace.weave_client import get_ref class Object(BaseModel): diff --git a/weave/integrations/anthropic/anthropic_test.py b/weave/integrations/anthropic/anthropic_test.py index d028f61cc6e..1737b720231 100644 --- a/weave/integrations/anthropic/anthropic_test.py +++ b/weave/integrations/anthropic/anthropic_test.py @@ -28,7 +28,7 @@ def _get_call_output(call: tsi.CallSchema) -> Any: allowed_hosts=["api.wandb.ai", "localhost"], ) def test_anthropic( - client: weave.weave_client.WeaveClient, + client: weave.trace.weave_client.WeaveClient, ) -> None: api_key = os.environ.get("ANTHROPIC_API_KEY", "DUMMY_API_KEY") anthropic_client = Anthropic( @@ -67,7 +67,7 @@ def test_anthropic( allowed_hosts=["api.wandb.ai", "localhost"], ) def test_anthropic_stream( - client: weave.weave_client.WeaveClient, + client: weave.trace.weave_client.WeaveClient, ) -> None: api_key = os.environ.get("ANTHROPIC_API_KEY", "DUMMY_API_KEY") anthropic_client = Anthropic( @@ -115,7 +115,7 @@ def test_anthropic_stream( ) @pytest.mark.asyncio async def test_async_anthropic( - client: weave.weave_client.WeaveClient, + client: weave.trace.weave_client.WeaveClient, ) -> None: anthropic_client = AsyncAnthropic( # This is the default and can be omitted @@ -156,7 +156,7 @@ async def test_async_anthropic( ) @pytest.mark.asyncio async def test_async_anthropic_stream( - client: weave.weave_client.WeaveClient, + client: weave.trace.weave_client.WeaveClient, ) -> None: anthropic_client = AsyncAnthropic( # This is the default and can be omitted @@ -204,7 +204,7 @@ async def test_async_anthropic_stream( allowed_hosts=["api.wandb.ai", "localhost"], ) def test_tools_calling( - client: weave.weave_client.WeaveClient, + client: weave.trace.weave_client.WeaveClient, ) -> None: api_key = os.environ.get("ANTHROPIC_API_KEY", "DUMMY_API_KEY") anthropic_client = Anthropic( diff --git a/weave/integrations/cohere/cohere_test.py b/weave/integrations/cohere/cohere_test.py index db5dea50d7f..f1adecdf538 100644 --- a/weave/integrations/cohere/cohere_test.py +++ b/weave/integrations/cohere/cohere_test.py @@ -27,7 +27,7 @@ def op_name_from_ref(ref: str) -> str: allowed_hosts=["api.wandb.ai", "localhost"], ) def test_cohere( - client: weave.weave_client.WeaveClient, + client: weave.trace.weave_client.WeaveClient, ) -> None: api_key = os.environ.get("COHERE_API_KEY", "DUMMY_API_KEY") @@ -79,7 +79,7 @@ def test_cohere( allowed_hosts=["api.wandb.ai", "localhost"], ) def test_cohere_stream( - client: weave.weave_client.WeaveClient, + client: weave.trace.weave_client.WeaveClient, ) -> None: api_key = os.environ.get("COHERE_API_KEY", "DUMMY_API_KEY") cohere_client = cohere.Client(api_key=api_key) @@ -137,7 +137,7 @@ def test_cohere_stream( allowed_hosts=["api.wandb.ai", "localhost"], ) async def test_cohere_async( - client: weave.weave_client.WeaveClient, + client: weave.trace.weave_client.WeaveClient, ) -> None: api_key = os.environ.get("COHERE_API_KEY", "DUMMY_API_KEY") @@ -190,7 +190,7 @@ async def test_cohere_async( allowed_hosts=["api.wandb.ai", "localhost"], ) async def test_cohere_async_stream( - client: weave.weave_client.WeaveClient, + client: weave.trace.weave_client.WeaveClient, ) -> None: api_key = os.environ.get("COHERE_API_KEY", "DUMMY_API_KEY") cohere_client = cohere.AsyncClient(api_key=api_key) diff --git a/weave/integrations/dspy/dspy_test.py b/weave/integrations/dspy/dspy_test.py index 8bbb9514502..db2d1099dfa 100644 --- a/weave/integrations/dspy/dspy_test.py +++ b/weave/integrations/dspy/dspy_test.py @@ -4,8 +4,8 @@ import pytest import weave +from weave.trace.weave_client import WeaveClient from weave.trace_server import trace_server_interface as tsi -from weave.weave_client import WeaveClient def _get_call_output(call: tsi.CallSchema) -> Any: diff --git a/weave/integrations/groq/groq_test.py b/weave/integrations/groq/groq_test.py index 5292e55908e..6c6b1ca4deb 100644 --- a/weave/integrations/groq/groq_test.py +++ b/weave/integrations/groq/groq_test.py @@ -44,7 +44,7 @@ def op_name_from_ref(ref: str) -> str: allowed_hosts=["api.wandb.ai", "localhost", "trace.wandb.ai"], ) def test_groq_quickstart( - client: weave.weave_client.WeaveClient, + client: weave.trace.weave_client.WeaveClient, ) -> None: from groq import Groq @@ -97,7 +97,7 @@ def test_groq_quickstart( allowed_hosts=["api.wandb.ai", "localhost", "trace.wandb.ai"], ) def test_groq_async_chat_completion( - client: weave.weave_client.WeaveClient, + client: weave.trace.weave_client.WeaveClient, ) -> None: from groq import AsyncGroq @@ -165,7 +165,7 @@ async def complete_chat() -> None: allowed_hosts=["api.wandb.ai", "localhost", "trace.wandb.ai"], ) def test_groq_streaming_chat_completion( - client: weave.weave_client.WeaveClient, + client: weave.trace.weave_client.WeaveClient, ) -> None: from groq import Groq @@ -248,7 +248,7 @@ def test_groq_streaming_chat_completion( allowed_hosts=["api.wandb.ai", "localhost", "trace.wandb.ai"], ) def test_groq_async_streaming_chat_completion( - client: weave.weave_client.WeaveClient, + client: weave.trace.weave_client.WeaveClient, ) -> None: from groq import AsyncGroq @@ -327,7 +327,7 @@ async def generate_reponse() -> str: allowed_hosts=["api.wandb.ai", "localhost", "trace.wandb.ai"], ) def test_groq_tool_call( - client: weave.weave_client.WeaveClient, + client: weave.trace.weave_client.WeaveClient, ) -> None: import json diff --git a/weave/integrations/langchain/langchain.py b/weave/integrations/langchain/langchain.py index 52e7be8ac39..9d2ee657d9e 100644 --- a/weave/integrations/langchain/langchain.py +++ b/weave/integrations/langchain/langchain.py @@ -42,7 +42,7 @@ ) from weave.trace import call_context from weave.trace.patcher import Patcher -from weave.weave_client import Call +from weave.trace.weave_client import Call import_failed = False diff --git a/weave/integrations/langchain/langchain_test.py b/weave/integrations/langchain/langchain_test.py index 91e698ef98c..61decdb1819 100644 --- a/weave/integrations/langchain/langchain_test.py +++ b/weave/integrations/langchain/langchain_test.py @@ -4,8 +4,8 @@ import pytest import weave +from weave.trace.weave_client import WeaveClient from weave.trace_server import trace_server_interface as tsi -from weave.weave_client import WeaveClient def filter_body(r: Any) -> Any: diff --git a/weave/integrations/litellm/litellm_test.py b/weave/integrations/litellm/litellm_test.py index 8e404e5ee0f..2f901b52c82 100644 --- a/weave/integrations/litellm/litellm_test.py +++ b/weave/integrations/litellm/litellm_test.py @@ -60,7 +60,7 @@ def patch_litellm(request: Any) -> Generator[None, None, None]: filter_headers=["authorization"], allowed_hosts=["api.wandb.ai", "localhost"] ) def test_litellm_quickstart( - client: weave.weave_client.WeaveClient, patch_litellm: None + client: weave.trace.weave_client.WeaveClient, patch_litellm: None ) -> None: # This is taken directly from https://docs.litellm.ai/docs/ chat_response = litellm.completion( @@ -101,7 +101,7 @@ def test_litellm_quickstart( ) @pytest.mark.asyncio async def test_litellm_quickstart_async( - client: weave.weave_client.WeaveClient, patch_litellm: None + client: weave.trace.weave_client.WeaveClient, patch_litellm: None ) -> None: # This is taken directly from https://docs.litellm.ai/docs/ chat_response = await litellm.acompletion( @@ -144,7 +144,7 @@ async def test_litellm_quickstart_async( filter_headers=["authorization"], allowed_hosts=["api.wandb.ai", "localhost"] ) def test_litellm_quickstart_stream( - client: weave.weave_client.WeaveClient, patch_litellm: None + client: weave.trace.weave_client.WeaveClient, patch_litellm: None ) -> None: # This is taken directly from https://docs.litellm.ai/docs/ chat_response = litellm.completion( @@ -187,7 +187,7 @@ def test_litellm_quickstart_stream( ) @pytest.mark.asyncio async def test_litellm_quickstart_stream_async( - client: weave.weave_client.WeaveClient, patch_litellm: None + client: weave.trace.weave_client.WeaveClient, patch_litellm: None ) -> None: # This is taken directly from https://docs.litellm.ai/docs/ chat_response = await litellm.acompletion( @@ -231,7 +231,7 @@ async def test_litellm_quickstart_stream_async( ) @pytest.mark.asyncio def test_model_predict( - client: weave.weave_client.WeaveClient, patch_litellm: None + client: weave.trace.weave_client.WeaveClient, patch_litellm: None ) -> None: class TranslatorModel(weave.Model): model: str diff --git a/weave/integrations/llamaindex/llamaindex.py b/weave/integrations/llamaindex/llamaindex.py index b1abc37b8f4..acb22efb3c3 100644 --- a/weave/integrations/llamaindex/llamaindex.py +++ b/weave/integrations/llamaindex/llamaindex.py @@ -1,6 +1,6 @@ from weave.client_context import weave_client as weave_client_context from weave.trace.patcher import Patcher -from weave.weave_client import Call +from weave.trace.weave_client import Call TRANSFORM_EMBEDDINGS = False ALLOWED_ROOT_EVENT_TYPES = ("query",) diff --git a/weave/integrations/llamaindex/llamaindex_test.py b/weave/integrations/llamaindex/llamaindex_test.py index c47153efc53..3d119fbcc86 100644 --- a/weave/integrations/llamaindex/llamaindex_test.py +++ b/weave/integrations/llamaindex/llamaindex_test.py @@ -81,7 +81,7 @@ def fake_api_key() -> Generator[None, None, None]: before_record_request=filter_body, ) def test_llamaindex_quickstart( - client: weave.weave_client.WeaveClient, fake_api_key: None + client: weave.trace.weave_client.WeaveClient, fake_api_key: None ) -> None: # This is taken directly from https://docs.llamaindex.ai/en/stable/getting_started/starter_example/ from llama_index.core import SimpleDirectoryReader, VectorStoreIndex @@ -105,7 +105,7 @@ def test_llamaindex_quickstart( ) @pytest.mark.asyncio async def test_llamaindex_quickstart_async( - client: weave.weave_client.WeaveClient, fake_api_key: None + client: weave.trace.weave_client.WeaveClient, fake_api_key: None ) -> None: # This is taken directly from https://docs.llamaindex.ai/en/stable/getting_started/starter_example/ from llama_index.core import SimpleDirectoryReader, VectorStoreIndex diff --git a/weave/integrations/mistral/mistral_test.py b/weave/integrations/mistral/mistral_test.py index e4d92f0951b..73a2980961b 100644 --- a/weave/integrations/mistral/mistral_test.py +++ b/weave/integrations/mistral/mistral_test.py @@ -24,7 +24,7 @@ def _get_call_output(call: tsi.CallSchema) -> Any: @pytest.mark.vcr( filter_headers=["authorization"], allowed_hosts=["api.wandb.ai", "localhost"] ) -def test_mistral_quickstart(client: weave.weave_client.WeaveClient) -> None: +def test_mistral_quickstart(client: weave.trace.weave_client.WeaveClient) -> None: # This is taken directly from https://docs.mistral.ai/getting-started/quickstart/ api_key = os.environ.get("MISTRAL_API_KEY", "DUMMY_API_KEY") model = "mistral-large-latest" @@ -77,7 +77,9 @@ def test_mistral_quickstart(client: weave.weave_client.WeaveClient) -> None: filter_headers=["authorization"], allowed_hosts=["api.wandb.ai", "localhost"] ) @pytest.mark.asyncio -async def test_mistral_quickstart_async(client: weave.weave_client.WeaveClient) -> None: +async def test_mistral_quickstart_async( + client: weave.trace.weave_client.WeaveClient, +) -> None: # This is taken directly from https://docs.mistral.ai/getting-started/quickstart/ api_key = os.environ.get("MISTRAL_API_KEY", "DUMMY_API_KEY") model = "mistral-large-latest" @@ -125,7 +127,9 @@ async def test_mistral_quickstart_async(client: weave.weave_client.WeaveClient) @pytest.mark.vcr( filter_headers=["authorization"], allowed_hosts=["api.wandb.ai", "localhost"] ) -def test_mistral_quickstart_with_stream(client: weave.weave_client.WeaveClient) -> None: +def test_mistral_quickstart_with_stream( + client: weave.trace.weave_client.WeaveClient, +) -> None: # This is taken directly from https://docs.mistral.ai/getting-started/quickstart/ api_key = os.environ.get("MISTRAL_API_KEY", "DUMMY_API_KEY") model = "mistral-large-latest" @@ -182,7 +186,7 @@ def test_mistral_quickstart_with_stream(client: weave.weave_client.WeaveClient) ) @pytest.mark.asyncio async def test_mistral_quickstart_with_stream_async( - client: weave.weave_client.WeaveClient, + client: weave.trace.weave_client.WeaveClient, ) -> None: # This is taken directly from https://docs.mistral.ai/getting-started/quickstart/ api_key = os.environ.get("MISTRAL_API_KEY", "DUMMY_API_KEY") diff --git a/weave/integrations/openai/openai_test.py b/weave/integrations/openai/openai_test.py index 80e502694f5..9c9b4a3f5da 100644 --- a/weave/integrations/openai/openai_test.py +++ b/weave/integrations/openai/openai_test.py @@ -30,7 +30,7 @@ def op_name_from_ref(ref: str) -> str: filter_headers=["authorization"], allowed_hosts=["api.wandb.ai", "localhost"], ) -def test_openai_quickstart(client: weave.weave_client.WeaveClient) -> None: +def test_openai_quickstart(client: weave.trace.weave_client.WeaveClient) -> None: api_key = os.environ.get("OPENAI_API_KEY", "DUMMY_API_KEY") openai_client = OpenAI(api_key=api_key) @@ -77,7 +77,9 @@ def test_openai_quickstart(client: weave.weave_client.WeaveClient) -> None: filter_headers=["authorization"], allowed_hosts=["api.wandb.ai", "localhost"] ) @pytest.mark.asyncio -async def test_openai_async_quickstart(client: weave.weave_client.WeaveClient) -> None: +async def test_openai_async_quickstart( + client: weave.trace.weave_client.WeaveClient, +) -> None: api_key = os.environ.get("OPENAI_API_KEY", "DUMMY_API_KEY") openai_client = AsyncOpenAI(api_key=api_key) @@ -122,7 +124,7 @@ async def test_openai_async_quickstart(client: weave.weave_client.WeaveClient) - @pytest.mark.vcr( filter_headers=["authorization"], allowed_hosts=["api.wandb.ai", "localhost"] ) -def test_openai_stream_quickstart(client: weave.weave_client.WeaveClient) -> None: +def test_openai_stream_quickstart(client: weave.trace.weave_client.WeaveClient) -> None: api_key = os.environ.get("OPENAI_API_KEY", "DUMMY_API_KEY") openai_client = OpenAI(api_key=api_key) @@ -179,7 +181,7 @@ def test_openai_stream_quickstart(client: weave.weave_client.WeaveClient) -> Non ) @pytest.mark.asyncio async def test_openai_async_stream_quickstart( - client: weave.weave_client.WeaveClient, + client: weave.trace.weave_client.WeaveClient, ) -> None: api_key = os.environ.get("OPENAI_API_KEY", "DUMMY_API_KEY") @@ -231,7 +233,9 @@ async def test_openai_async_stream_quickstart( @pytest.mark.vcr( filter_headers=["authorization"], allowed_hosts=["api.wandb.ai", "localhost"] ) -def test_openai_stream_usage_quickstart(client: weave.weave_client.WeaveClient) -> None: +def test_openai_stream_usage_quickstart( + client: weave.trace.weave_client.WeaveClient, +) -> None: api_key = os.environ.get("OPENAI_API_KEY", "DUMMY_API_KEY") openai_client = OpenAI(api_key=api_key) @@ -268,7 +272,7 @@ def test_openai_stream_usage_quickstart(client: weave.weave_client.WeaveClient) @pytest.mark.vcr( filter_headers=["authorization"], allowed_hosts=["api.wandb.ai", "localhost"] ) -def test_openai_function_call(client: weave.weave_client.WeaveClient) -> None: +def test_openai_function_call(client: weave.trace.weave_client.WeaveClient) -> None: api_key = os.environ.get("OPENAI_API_KEY", "DUMMY_API_KEY") openai_client = OpenAI(api_key=api_key) @@ -354,7 +358,7 @@ def test_openai_function_call(client: weave.weave_client.WeaveClient) -> None: ) @pytest.mark.asyncio async def test_openai_function_call_async( - client: weave.weave_client.WeaveClient, + client: weave.trace.weave_client.WeaveClient, ) -> None: api_key = os.environ.get("OPENAI_API_KEY", "DUMMY_API_KEY") @@ -440,7 +444,7 @@ async def test_openai_function_call_async( ) @pytest.mark.asyncio async def test_openai_function_call_async_stream( - client: weave.weave_client.WeaveClient, + client: weave.trace.weave_client.WeaveClient, ) -> None: api_key = os.environ.get("OPENAI_API_KEY", "DUMMY_API_KEY") @@ -527,7 +531,7 @@ async def test_openai_function_call_async_stream( @pytest.mark.vcr( filter_headers=["authorization"], allowed_hosts=["api.wandb.ai", "localhost"] ) -def test_openai_tool_call(client: weave.weave_client.WeaveClient) -> None: +def test_openai_tool_call(client: weave.trace.weave_client.WeaveClient) -> None: api_key = os.environ.get("OPENAI_API_KEY", "DUMMY_API_KEY") openai_client = OpenAI(api_key=api_key) @@ -614,7 +618,9 @@ def test_openai_tool_call(client: weave.weave_client.WeaveClient) -> None: filter_headers=["authorization"], allowed_hosts=["api.wandb.ai", "localhost"] ) @pytest.mark.asyncio -async def test_openai_tool_call_async(client: weave.weave_client.WeaveClient) -> None: +async def test_openai_tool_call_async( + client: weave.trace.weave_client.WeaveClient, +) -> None: api_key = os.environ.get("OPENAI_API_KEY", "DUMMY_API_KEY") openai_client = AsyncOpenAI(api_key=api_key) @@ -700,7 +706,7 @@ async def test_openai_tool_call_async(client: weave.weave_client.WeaveClient) -> ) @pytest.mark.asyncio async def test_openai_tool_call_async_stream( - client: weave.weave_client.WeaveClient, + client: weave.trace.weave_client.WeaveClient, ) -> None: api_key = os.environ.get("OPENAI_API_KEY", "DUMMY_API_KEY") @@ -801,7 +807,7 @@ async def test_openai_tool_call_async_stream( filter_headers=["authorization"], allowed_hosts=["api.wandb.ai", "localhost"] ) def test_openai_as_context_manager( - client: weave.weave_client.WeaveClient, + client: weave.trace.weave_client.WeaveClient, ) -> None: api_key = os.environ.get("OPENAI_API_KEY", "DUMMY_API_KEY") @@ -854,7 +860,7 @@ def test_openai_as_context_manager( ) @pytest.mark.asyncio async def test_openai_as_context_manager_async( - client: weave.weave_client.WeaveClient, + client: weave.trace.weave_client.WeaveClient, ) -> None: api_key = os.environ.get("OPENAI_API_KEY", "DUMMY_API_KEY") diff --git a/weave/legacy/op_def.py b/weave/legacy/op_def.py index 614ec03ad44..0dff7ace695 100644 --- a/weave/legacy/op_def.py +++ b/weave/legacy/op_def.py @@ -34,7 +34,7 @@ from weave.weavejs_fixes import fixup_node if typing.TYPE_CHECKING: - from weave import weave_client + from weave.trace import weave_client from weave.legacy.run_streamtable_span import RunStreamTableSpan diff --git a/weave/query_api.py b/weave/query_api.py index f457072c8e6..03ff7562fdf 100644 --- a/weave/query_api.py +++ b/weave/query_api.py @@ -18,7 +18,7 @@ from weave.legacy import context as _context from . import weave_init as _weave_init -from . import weave_client as _weave_client +from .trace import weave_client as _weave_client # exposed as part of api from . import weave_types as types diff --git a/weave/ref_base.py b/weave/ref_base.py index e2bfa52add4..120ff9fed6d 100644 --- a/weave/ref_base.py +++ b/weave/ref_base.py @@ -17,8 +17,8 @@ REFS: weakref.WeakValueDictionary[int, "Ref"] = weakref.WeakValueDictionary() if typing.TYPE_CHECKING: - from . import weave_client from . import weave_types as types + from .trace import weave_client def _map_to_ref_strs(obj: typing.Any) -> typing.Any: diff --git a/weave/tests/trace/test_anonymous_ops.py b/weave/tests/trace/test_anonymous_ops.py index cd7a44ad02e..0b4502729b5 100644 --- a/weave/tests/trace/test_anonymous_ops.py +++ b/weave/tests/trace/test_anonymous_ops.py @@ -1,4 +1,4 @@ -from weave import weave_client +from weave.trace import weave_client from weave.trace_server.trace_server_interface import CallsQueryReq diff --git a/weave/tests/trace/test_client_trace.py b/weave/tests/trace/test_client_trace.py index 7d64c49e208..7fa79aa29d6 100644 --- a/weave/tests/trace/test_client_trace.py +++ b/weave/tests/trace/test_client_trace.py @@ -13,7 +13,8 @@ from pydantic import BaseModel, ValidationError import weave -from weave import Thread, ThreadPoolExecutor, weave_client +from weave import Thread, ThreadPoolExecutor +from weave.trace import weave_client from weave.trace.vals import MissingSelfInstanceError from weave.trace_server import trace_server_interface as tsi from weave.trace_server.ids import generate_id diff --git a/weave/tests/trace/test_op_call_method.py b/weave/tests/trace/test_op_call_method.py index 6bead7c2b65..c85d06cb1c6 100644 --- a/weave/tests/trace/test_op_call_method.py +++ b/weave/tests/trace/test_op_call_method.py @@ -13,7 +13,7 @@ def add(a, b): # call that returns a Call obj res2, call = add.call(1, 2) - assert isinstance(call, weave.weave_client.Call) + assert isinstance(call, weave.trace.weave_client.Call) assert call.inputs == {"a": 1, "b": 2} assert call.output == 3 assert res2 == 3 diff --git a/weave/tests/trace/test_op_decorator_behaviour.py b/weave/tests/trace/test_op_decorator_behaviour.py index 357bc142331..57ae0443be7 100644 --- a/weave/tests/trace/test_op_decorator_behaviour.py +++ b/weave/tests/trace/test_op_decorator_behaviour.py @@ -7,7 +7,7 @@ from weave.trace.op import Op, op from weave.trace.refs import ObjectRef from weave.trace.vals import MissingSelfInstanceError -from weave.weave_client import Call +from weave.trace.weave_client import Call @pytest.fixture diff --git a/weave/tests/trace/test_weave_client.py b/weave/tests/trace/test_weave_client.py index 7a065f243d2..b0bd9210ec5 100644 --- a/weave/tests/trace/test_weave_client.py +++ b/weave/tests/trace/test_weave_client.py @@ -11,9 +11,9 @@ import weave import weave.trace_server.trace_server_interface as tsi -from weave import Evaluation, weave_client +from weave import Evaluation from weave.legacy import op_def -from weave.trace import refs +from weave.trace import refs, weave_client from weave.trace.isinstance import weave_isinstance from weave.trace.op import Op from weave.trace.refs import ( diff --git a/weave/tests/trace/trace_server_clickhouse_conftest.py b/weave/tests/trace/trace_server_clickhouse_conftest.py index 23b4b6e0371..7d28d4506a9 100644 --- a/weave/tests/trace/trace_server_clickhouse_conftest.py +++ b/weave/tests/trace/trace_server_clickhouse_conftest.py @@ -9,7 +9,7 @@ import pytest import requests -from weave import weave_client +from weave.trace import weave_client from weave.trace_server import ( clickhouse_trace_server_batched, external_to_internal_trace_server_adapter, diff --git a/weave/trace/call_context.py b/weave/trace/call_context.py index 74d9d9ed1e3..2c3860e80c3 100644 --- a/weave/trace/call_context.py +++ b/weave/trace/call_context.py @@ -6,7 +6,7 @@ if typing.TYPE_CHECKING: # from .run import Run - from ..weave_client import Call + from .weave_client import Call _call_stack: contextvars.ContextVar[list["Call"]] = contextvars.ContextVar( "call", default=[] diff --git a/weave/trace/op.py b/weave/trace/op.py index 559cd0a4d45..29babb6b2d9 100644 --- a/weave/trace/op.py +++ b/weave/trace/op.py @@ -27,7 +27,7 @@ from .constants import TRACE_CALL_EMOJI if TYPE_CHECKING: - from weave.weave_client import Call, CallsIter + from weave.trace.weave_client import Call, CallsIter try: from openai._types import NOT_GIVEN as OPENAI_NOT_GIVEN diff --git a/weave/trace/tests/test_op_return_forms.py b/weave/trace/tests/test_op_return_forms.py index 2b5e6cff332..e441718eb7f 100644 --- a/weave/trace/tests/test_op_return_forms.py +++ b/weave/trace/tests/test_op_return_forms.py @@ -2,7 +2,7 @@ import weave from weave.trace.op_extensions.accumulator import add_accumulator -from weave.weave_client import get_ref +from weave.trace.weave_client import get_ref from ...trace_server import trace_server_interface as tsi diff --git a/weave/weave_client.py b/weave/trace/weave_client.py similarity index 99% rename from weave/weave_client.py rename to weave/trace/weave_client.py index 1d136f7a994..ce2ea38eea1 100644 --- a/weave/weave_client.py +++ b/weave/trace/weave_client.py @@ -51,7 +51,7 @@ ) if typing.TYPE_CHECKING: - from . import ref_base + from .. import ref_base # Controls if objects can have refs to projects not the WeaveClient project. diff --git a/weave/trace_api.py b/weave/trace_api.py index a586cfe4639..48a3b0a93af 100644 --- a/weave/trace_api.py +++ b/weave/trace_api.py @@ -15,11 +15,10 @@ type_serializers, # noqa: F401 urls, util, - weave_client, weave_init, ) from .table import Table -from .trace import context +from .trace import context, weave_client from .trace.constants import TRACE_OBJECT_EMOJI from .trace.op import Op, op from .trace.refs import ObjectRef, parse_uri diff --git a/weave/type_serializers/Image/image_test.py b/weave/type_serializers/Image/image_test.py index cf42c07c4d6..0e93201079f 100644 --- a/weave/type_serializers/Image/image_test.py +++ b/weave/type_serializers/Image/image_test.py @@ -1,7 +1,7 @@ from PIL import Image import weave -from weave.weave_client import WeaveClient, get_ref +from weave.trace.weave_client import WeaveClient, get_ref """When testing types, it is important to test: Objects: diff --git a/weave/weave_init.py b/weave/weave_init.py index 6febcbc3c88..b2ef6d98acd 100644 --- a/weave/weave_init.py +++ b/weave/weave_init.py @@ -2,8 +2,8 @@ from weave.client_context import weave_client as weave_client_context -from . import errors, init_message, trace_sentry, weave_client -from .trace import autopatch +from . import errors, init_message, trace_sentry +from .trace import autopatch, weave_client from .trace_server import remote_http_trace_server, sqlite_trace_server _current_inited_client = None From 9919f9a95079f44298d51a962e8af064cbe0526c Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Wed, 21 Aug 2024 19:18:30 -0400 Subject: [PATCH 11/84] move to legacy: notebooks --- Embeddings.ipynb => weave/legacy/notebooks/Embeddings.ipynb | 0 .../legacy/notebooks/Eval Board Syn.ipynb | 0 Eval Board.ipynb => weave/legacy/notebooks/Eval Board.ipynb | 0 .../legacy/notebooks/Text Extraction Eval.ipynb | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename Embeddings.ipynb => weave/legacy/notebooks/Embeddings.ipynb (100%) rename Eval Board Syn.ipynb => weave/legacy/notebooks/Eval Board Syn.ipynb (100%) rename Eval Board.ipynb => weave/legacy/notebooks/Eval Board.ipynb (100%) rename Text Extraction Eval.ipynb => weave/legacy/notebooks/Text Extraction Eval.ipynb (100%) diff --git a/Embeddings.ipynb b/weave/legacy/notebooks/Embeddings.ipynb similarity index 100% rename from Embeddings.ipynb rename to weave/legacy/notebooks/Embeddings.ipynb diff --git a/Eval Board Syn.ipynb b/weave/legacy/notebooks/Eval Board Syn.ipynb similarity index 100% rename from Eval Board Syn.ipynb rename to weave/legacy/notebooks/Eval Board Syn.ipynb diff --git a/Eval Board.ipynb b/weave/legacy/notebooks/Eval Board.ipynb similarity index 100% rename from Eval Board.ipynb rename to weave/legacy/notebooks/Eval Board.ipynb diff --git a/Text Extraction Eval.ipynb b/weave/legacy/notebooks/Text Extraction Eval.ipynb similarity index 100% rename from Text Extraction Eval.ipynb rename to weave/legacy/notebooks/Text Extraction Eval.ipynb From 653db7246f61530f14715fba92240fee2702448f Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Thu, 22 Aug 2024 00:28:52 -0400 Subject: [PATCH 12/84] move to legacy: weavify --- weave/legacy/decorator_op.py | 2 +- weave/legacy/ops_arrow/vectorize.py | 2 +- weave/{ => legacy}/weavify.py | 4 ++-- weave/tests/legacy/test_weavify.py | 3 ++- 4 files changed, 6 insertions(+), 5 deletions(-) rename weave/{ => legacy}/weavify.py (98%) diff --git a/weave/legacy/decorator_op.py b/weave/legacy/decorator_op.py index d00e7f46ab4..6f27dcb142b 100644 --- a/weave/legacy/decorator_op.py +++ b/weave/legacy/decorator_op.py @@ -105,7 +105,7 @@ def wrap(f: Callable[P, R]) -> Callable[P, R]: mutation=mutation, ) if weavify: - from weave.weavify import op_to_weave_fn + from weave.legacy.weavify import op_to_weave_fn op.weave_fn = op_to_weave_fn(op) diff --git a/weave/legacy/ops_arrow/vectorize.py b/weave/legacy/ops_arrow/vectorize.py index 17bf1115b05..f4123b18a54 100644 --- a/weave/legacy/ops_arrow/vectorize.py +++ b/weave/legacy/ops_arrow/vectorize.py @@ -10,8 +10,8 @@ errors, registry_mem, weave_internal, - weavify, ) +from weave.legacy import weavify from weave import weave_types as types from weave.query_api import op, use from weave.legacy import dispatch, graph, graph_debug, op_args, op_def diff --git a/weave/weavify.py b/weave/legacy/weavify.py similarity index 98% rename from weave/weavify.py rename to weave/legacy/weavify.py index 271a9672694..e739a308e92 100644 --- a/weave/weavify.py +++ b/weave/legacy/weavify.py @@ -2,8 +2,8 @@ from weave.legacy import graph, op_args, val_const -from . import errors, weave_internal -from . import weave_types as types +from .. import errors, weave_internal +from .. import weave_types as types if typing.TYPE_CHECKING: from weave.legacy import op_def diff --git a/weave/tests/legacy/test_weavify.py b/weave/tests/legacy/test_weavify.py index 5a2d0e5cda7..d869848d98d 100644 --- a/weave/tests/legacy/test_weavify.py +++ b/weave/tests/legacy/test_weavify.py @@ -2,8 +2,9 @@ from weave.legacy import graph, ops -from ... import weave_internal, weavify +from ... import weave_internal from ... import weave_types as types +from ...legacy import weavify from .. import geom From e317bded543c9236b7dbc9d6c0cf2750792c21a1 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Thu, 22 Aug 2024 00:47:59 -0400 Subject: [PATCH 13/84] move to legacy: weavejs_fixes --- weave/legacy/op_def.py | 2 +- weave/{ => legacy}/weavejs_fixes.py | 22 +++++++++++----------- weave/show.py | 2 +- weave/tests/legacy/test_js_compat.py | 3 +-- weave/tests/legacy/test_storage.py | 2 +- weave/tests/legacy/test_weavejs_fixes.py | 4 ++-- weave/weave_server.py | 3 +-- 7 files changed, 18 insertions(+), 20 deletions(-) rename weave/{ => legacy}/weavejs_fixes.py (93%) diff --git a/weave/legacy/op_def.py b/weave/legacy/op_def.py index 0dff7ace695..25438b8b24c 100644 --- a/weave/legacy/op_def.py +++ b/weave/legacy/op_def.py @@ -31,7 +31,7 @@ tagged_value_type, ) from weave.legacy.run import Run -from weave.weavejs_fixes import fixup_node +from weave.legacy.weavejs_fixes import fixup_node if typing.TYPE_CHECKING: from weave.trace import weave_client diff --git a/weave/weavejs_fixes.py b/weave/legacy/weavejs_fixes.py similarity index 93% rename from weave/weavejs_fixes.py rename to weave/legacy/weavejs_fixes.py index cc78520c0a0..d7d94c399f0 100644 --- a/weave/weavejs_fixes.py +++ b/weave/legacy/weavejs_fixes.py @@ -10,7 +10,7 @@ from weave.legacy import graph -from . import weave_types +from .. import weave_types def _convert_specific_opname_to_generic_opname( @@ -85,7 +85,7 @@ def convert_specific_opname_to_generic_opname( def convert_specific_ops_to_generic_ops_node(node: graph.Node) -> graph.Node: """Converts specific ops like typedDict-pick to generic ops like pick""" - def convert_specific_op_to_generic_op(node: graph.Node): + def convert_specific_op_to_generic_op(node: graph.Node): # type: ignore if isinstance(node, graph.ConstNode) and isinstance( node.type, weave_types.Function ): @@ -102,14 +102,14 @@ def convert_specific_op_to_generic_op(node: graph.Node): return graph.map_nodes_full([node], convert_specific_op_to_generic_op)[0] -def _obj_is_node_like(data: typing.Any): +def _obj_is_node_like(data: typing.Any): # type: ignore if not isinstance(data, dict): return False return data.get("nodeType") in ["const", "output", "var", "void"] # Non-perfect heuristic to determine if a serialized dict is likely an op -def _dict_is_op_like(data: dict): +def _dict_is_op_like(data: dict): # type: ignore # Firstly, ops will only have "name" and "input" keys if set(data.keys()) == set(["name", "inputs"]): # Those keys will be str and list respectively. @@ -121,7 +121,7 @@ def _dict_is_op_like(data: dict): return False -def convert_specific_ops_to_generic_ops_data(data): +def convert_specific_ops_to_generic_ops_data(data): # type: ignore """Fix op call names for serialized objects containing graphs""" if isinstance(data, list): return [convert_specific_ops_to_generic_ops_data(d) for d in data] @@ -138,7 +138,7 @@ def convert_specific_ops_to_generic_ops_data(data): def remove_opcall_versions_node(node: graph.Node) -> graph.Node: """Fix op call names""" - def remove_op_version(node: graph.Node): + def remove_op_version(node: graph.Node): # type: ignore if not isinstance(node, graph.OutputNode): return node return graph.OutputNode( @@ -150,7 +150,7 @@ def remove_op_version(node: graph.Node): return graph.map_nodes_full([node], remove_op_version)[0] -def remove_opcall_versions_data(data): +def remove_opcall_versions_data(data): # type: ignore """Fix op call names for serialized objects containing graphs""" if isinstance(data, list): return [remove_opcall_versions_data(d) for d in data] @@ -168,7 +168,7 @@ def fixup_node(node: graph.Node) -> graph.Node: return convert_specific_ops_to_generic_ops_node(node) -def recursively_unwrap_unions(obj): +def recursively_unwrap_unions(obj): # type: ignore if isinstance(obj, list): return [recursively_unwrap_unions(o) for o in obj] if isinstance(obj, dict): @@ -183,7 +183,7 @@ def recursively_unwrap_unions(obj): return obj -def remove_nan_and_inf(obj): +def remove_nan_and_inf(obj): # type: ignore if isinstance(obj, list): return [remove_nan_and_inf(o) for o in obj] if isinstance(obj, dict): @@ -194,7 +194,7 @@ def remove_nan_and_inf(obj): return obj -def remove_partialobject_from_types(data): +def remove_partialobject_from_types(data): # type: ignore """Convert weave-internal types like {"type":"PartialObject","keys":{"name":"string"},"keyless_weave_type_class":"project"} @@ -218,7 +218,7 @@ def remove_partialobject_from_types(data): return data -def fixup_data(data): +def fixup_data(data): # type: ignore data = recursively_unwrap_unions(data) data = remove_opcall_versions_data(data) # No good! We have to do this because remoteHttp doesn't handle NaN/inf in diff --git a/weave/show.py b/weave/show.py index cd55e63f087..5027cb8fa79 100644 --- a/weave/show.py +++ b/weave/show.py @@ -14,9 +14,9 @@ storage, usage_analytics, util, - weavejs_fixes, ) from . import weave_types as types +from .legacy import weavejs_fixes def make_varname_for_type(t: types.Type): diff --git a/weave/tests/legacy/test_js_compat.py b/weave/tests/legacy/test_js_compat.py index 190a7b747fb..87a7adb648c 100644 --- a/weave/tests/legacy/test_js_compat.py +++ b/weave/tests/legacy/test_js_compat.py @@ -8,8 +8,7 @@ # weave Python code that I haven't documented here. from weave import weave_types as types -from weave import weavejs_fixes -from weave.legacy import partial_object +from weave.legacy import partial_object, weavejs_fixes from weave.legacy.ops_domain import wb_domain_types diff --git a/weave/tests/legacy/test_storage.py b/weave/tests/legacy/test_storage.py index f1e7cb3f9e6..3821f662a26 100644 --- a/weave/tests/legacy/test_storage.py +++ b/weave/tests/legacy/test_storage.py @@ -13,8 +13,8 @@ from ... import api as weave from ... import storage from ... import weave_types as types +from ...legacy.weavejs_fixes import recursively_unwrap_unions from ...weave_internal import make_const_node -from ...weavejs_fixes import recursively_unwrap_unions from . import test_helpers diff --git a/weave/tests/legacy/test_weavejs_fixes.py b/weave/tests/legacy/test_weavejs_fixes.py index 32cff043df9..e654405a6bd 100644 --- a/weave/tests/legacy/test_weavejs_fixes.py +++ b/weave/tests/legacy/test_weavejs_fixes.py @@ -2,9 +2,9 @@ import pytest -from weave.legacy import context_state, mappers_python, ops +from weave.legacy import context_state, mappers_python, ops, weavejs_fixes -from ... import api, weave_internal, weavejs_fixes +from ... import api, weave_internal from ... import weave_types as types diff --git a/weave/weave_server.py b/weave/weave_server.py index 8d6134a128d..db96977c0a4 100644 --- a/weave/weave_server.py +++ b/weave/weave_server.py @@ -35,9 +35,8 @@ server, storage, util, - weavejs_fixes, ) -from weave.legacy import context_state, graph, value_or_error, wandb_api +from weave.legacy import context_state, graph, value_or_error, wandb_api, weavejs_fixes from weave.legacy.language_features.tagging import tag_store from weave.server_error_handling import client_safe_http_exceptions_as_werkzeug From 798ee7ca0532ef2ed317ff85bcaed17aa83e087e Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Thu, 22 Aug 2024 21:37:02 -0400 Subject: [PATCH 14/84] move to legacy: infer_types --- examples/experimental/app/scenario_compare.ipynb | 2 +- weave/legacy/decorator_type.py | 4 ++-- weave/legacy/ecosystem/torchvision/datasets.py | 2 +- weave/legacy/ecosystem/wandb/weave_plotly.py | 3 ++- weave/{ => legacy}/infer_types.py | 4 ++-- weave/legacy/op_def_type.py | 4 ++-- weave/pyfunc_type_util.py | 4 ++-- weave/tests/legacy/test_infer_types.py | 3 ++- weave/tests/legacy/test_typeddict_notrequired.py | 2 +- weave/weave_pydantic.py | 2 +- weave/weave_types.py | 2 +- 11 files changed, 17 insertions(+), 15 deletions(-) rename weave/{ => legacy}/infer_types.py (97%) diff --git a/examples/experimental/app/scenario_compare.ipynb b/examples/experimental/app/scenario_compare.ipynb index 4450f818b80..befb14b8f0a 100644 --- a/examples/experimental/app/scenario_compare.ipynb +++ b/examples/experimental/app/scenario_compare.ipynb @@ -95,7 +95,7 @@ "source": [ "# Ugly. We need to compute the Weave type right now.\n", "# TODO: Fix\n", - "from weave import infer_types\n", + "from weave.legacy import infer_types\n", "run_type = weave.types.List(infer_types.python_type_to_type(scenario.ScenarioResult))\n", "\n", "import time\n", diff --git a/weave/legacy/decorator_type.py b/weave/legacy/decorator_type.py index 97b3277d2b8..9568a906f48 100644 --- a/weave/legacy/decorator_type.py +++ b/weave/legacy/decorator_type.py @@ -2,9 +2,9 @@ import inspect import typing -from weave import errors, infer_types +from weave import errors from weave import weave_types as types -from weave.legacy import context_state, decorator_class, object_type_ref_util +from weave.legacy import context_state, decorator_class, object_type_ref_util, infer_types _py_type = type diff --git a/weave/legacy/ecosystem/torchvision/datasets.py b/weave/legacy/ecosystem/torchvision/datasets.py index 424f8d6fa05..46f74273f75 100644 --- a/weave/legacy/ecosystem/torchvision/datasets.py +++ b/weave/legacy/ecosystem/torchvision/datasets.py @@ -11,7 +11,7 @@ from torchvision import datasets import weave -from weave import infer_types +from weave.legacy import infer_types from weave.legacy import panels ExampleType = TypeVar("ExampleType") diff --git a/weave/legacy/ecosystem/wandb/weave_plotly.py b/weave/legacy/ecosystem/wandb/weave_plotly.py index bb6d4e58966..e5e9e85b983 100644 --- a/weave/legacy/ecosystem/wandb/weave_plotly.py +++ b/weave/legacy/ecosystem/wandb/weave_plotly.py @@ -9,7 +9,8 @@ from plotly import graph_objs as go import weave -from weave import infer_types, weave_internal +from weave import weave_internal +from weave.legacy import infer_types class PlotlyType(weave.types.Type): diff --git a/weave/infer_types.py b/weave/legacy/infer_types.py similarity index 97% rename from weave/infer_types.py rename to weave/legacy/infer_types.py index a9801677609..55d9988fb02 100644 --- a/weave/infer_types.py +++ b/weave/legacy/infer_types.py @@ -8,7 +8,7 @@ from weave.legacy import graph -from . import errors, weave_types +from .. import errors, weave_types class TypedDictLike: @@ -19,7 +19,7 @@ def is_typed_dict_like(t: type) -> typing_extensions.TypeGuard[TypedDictLike]: return hasattr(t, "__required_keys__") -def simple_python_type_to_type(py_type: type): +def simple_python_type_to_type(py_type: type): # type: ignore if isinstance(py_type, str): raise errors.WeaveTypeError( "Cannot yet detect Weave type from forward type references" diff --git a/weave/legacy/op_def_type.py b/weave/legacy/op_def_type.py index 4f2553cdc47..964aeb4cab9 100644 --- a/weave/legacy/op_def_type.py +++ b/weave/legacy/op_def_type.py @@ -11,9 +11,9 @@ from _ast import AsyncFunctionDef, ExceptHandler from typing import Any -from weave import environment, errors, infer_types, registry_mem, storage +from weave import environment, errors, registry_mem, storage from weave import weave_types as types -from weave.legacy import artifact_fs, artifact_local, context_state +from weave.legacy import artifact_fs, artifact_local, context_state, infer_types if typing.TYPE_CHECKING: from .op_def import OpDef diff --git a/weave/pyfunc_type_util.py b/weave/pyfunc_type_util.py index 0fdc94a11cd..4ae2943cc1f 100644 --- a/weave/pyfunc_type_util.py +++ b/weave/pyfunc_type_util.py @@ -1,9 +1,9 @@ import inspect import typing -from weave.legacy import op_args +from weave.legacy import infer_types, op_args -from . import errors, infer_types +from . import errors from . import weave_types as types InputTypeItemType = typing.Union[types.Type, typing.Callable[..., types.Type]] diff --git a/weave/tests/legacy/test_infer_types.py b/weave/tests/legacy/test_infer_types.py index e508dad0d49..5ddaf587ed1 100644 --- a/weave/tests/legacy/test_infer_types.py +++ b/weave/tests/legacy/test_infer_types.py @@ -2,7 +2,8 @@ from weave.legacy import graph -from ... import infer_types, weave_types +from ... import weave_types +from ...legacy import infer_types def test_node_with_generic(): diff --git a/weave/tests/legacy/test_typeddict_notrequired.py b/weave/tests/legacy/test_typeddict_notrequired.py index fc10cf75270..b58c53964f4 100644 --- a/weave/tests/legacy/test_typeddict_notrequired.py +++ b/weave/tests/legacy/test_typeddict_notrequired.py @@ -6,8 +6,8 @@ TypedDict, ) -from weave import infer_types from weave import weave_types as types +from weave.legacy import infer_types class _TestNotRequiredTypedDict(TypedDict): diff --git a/weave/weave_pydantic.py b/weave/weave_pydantic.py index 50e68a407de..19d200ad2fd 100644 --- a/weave/weave_pydantic.py +++ b/weave/weave_pydantic.py @@ -1,7 +1,7 @@ from pydantic import BaseModel, create_model -from . import infer_types from . import weave_types as types +from .legacy import infer_types def weave_type_to_pydantic( diff --git a/weave/weave_types.py b/weave/weave_types.py index 9bc82f9039d..990ec2586a8 100644 --- a/weave/weave_types.py +++ b/weave/weave_types.py @@ -1274,7 +1274,7 @@ def _hashable(self): @classmethod def type_of_instance(cls, obj): - from . import infer_types + from .legacy import infer_types attr_types = {} for field in dataclasses.fields(obj): From 718c33fcb09a55d4a3af74f5c673a092ab284e12 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Thu, 22 Aug 2024 21:58:20 -0400 Subject: [PATCH 15/84] move to legacy: show --- examples/get_started.ipynb | 44 +++++++++++-------- examples/reference/WB_API.ipynb | 2 +- .../reference/create_plots_ui_guide.ipynb | 2 +- examples/reference/vis/Scatter.ipynb | 2 +- .../cypress/e2e/interactive/blank.py | 2 +- .../cypress/e2e/interactive/distribution.py | 2 +- .../cypress/e2e/interactive/scatter.py | 2 +- weave/legacy/panel.py | 2 +- weave/{ => legacy}/show.py | 37 +++++++--------- .../wandb_interface/wandb_stream_table.py | 2 +- weave/tests/legacy/test_api.py | 2 +- weave/tests/legacy/test_show.py | 2 +- 12 files changed, 51 insertions(+), 50 deletions(-) rename weave/{ => legacy}/show.py (84%) diff --git a/examples/get_started.ipynb b/examples/get_started.ipynb index 151cc104979..b8b5a4f101a 100644 --- a/examples/get_started.ipynb +++ b/examples/get_started.ipynb @@ -6,9 +6,11 @@ "metadata": {}, "source": [ "# Get Started building with Weave\n", + "\n", "In this tutorial, you will learn how to use Weave to build an interactive dashboard to help you explore, understand, and evaluate machine learning models.\n", "\n", "After this tutorials, you'll know how to build a dashboard to:\n", + "\n", "- explore inputs, outputs & labels of your models\n", "- calculate and plot metrics about your models\n", "- interactively build live, connected plots to drill deeper into your data\n", @@ -16,7 +18,7 @@ "\n", "# Hello, World\n", "\n", - "First, install `weave`:" + "First, install `weave`:\n" ] }, { @@ -34,7 +36,7 @@ "id": "56c791d0", "metadata": {}, "source": [ - "Next, we'll use Weave to explore the Iris flower dataset." + "Next, we'll use Weave to explore the Iris flower dataset.\n" ] }, { @@ -65,7 +67,7 @@ "id": "ae1d5797", "metadata": {}, "source": [ - "Now that we have a dataframe, we can display it in an interactive table by calling `weave.show`." + "Now that we have a dataframe, we can display it in an interactive table by calling `weave.show`.\n" ] }, { @@ -76,7 +78,7 @@ "outputs": [], "source": [ "import weave\n", - "from weave.show import show\n", + "from weave.legacy.show import show\n", "show(iris_df)" ] }, @@ -96,7 +98,7 @@ "\n", "You should now see a plot of `sepal_width` versus `sepal_length`, colored by `target_name`. Weave's visualization engine uses the type of each column to choose a reasonable way to display your data. You can edit this plot by clicking the pencil icon ✏️ in the top right of the panel to open the panel editor.\n", "\n", - "Note: You can build these plots interactively using the UI or define them programmatically in Python. In this tutorial, we'll focus on building these dashboards using the UI and keep programmatic dashboard building for later tutorials. " + "Note: You can build these plots interactively using the UI or define them programmatically in Python. In this tutorial, we'll focus on building these dashboards using the UI and keep programmatic dashboard building for later tutorials.\n" ] }, { @@ -104,7 +106,7 @@ "id": "9866379b", "metadata": {}, "source": [ - "!['image'](https://raw.githubusercontent.com/wandb/weave/6936cd8233f382ae3fd165480dce5832c06c2453/docs/assets/get_started_0.png)" + "!['image'](https://raw.githubusercontent.com/wandb/weave/6936cd8233f382ae3fd165480dce5832c06c2453/docs/assets/get_started_0.png)\n" ] }, { @@ -113,14 +115,15 @@ "metadata": {}, "source": [ "## Exercise\n", + "\n", "- Try changing the X and Y axes\n", "- Try changing the color\n", "\n", - "Tip: `row[\"\"]` is a **Weave Expression**. You can edit the column name inside the quotes to show the relevant column from your data. \n", + "Tip: `row[\"\"]` is a **Weave Expression**. You can edit the column name inside the quotes to show the relevant column from your data.\n", "\n", "# Exploring Tables\n", "\n", - "Let's display our data as a `Table` again:" + "Let's display our data as a `Table` again:\n" ] }, { @@ -141,15 +144,17 @@ "You can add, remove and sort each column by using the three dots button ⋮ beside the column name.\n", "\n", "## Exercise\n", + "\n", "- Try sorting by the `sepal_length` column\n", "- Try removing the `target_id` column\n", "\n", "## Filtering\n", "\n", - "You can filter tables using the funnel icon ▼ on the top left. \n", + "You can filter tables using the funnel icon ▼ on the top left.\n", "\n", "For example, to filter the data to only display the `setosa` flowers:\n", - "- Click the filter icon \n", + "\n", + "- Click the filter icon\n", "- Add the expression `row[\"target_name\"] == \"setosa\"`\n", "\n", "# Transforming data\n", @@ -159,6 +164,7 @@ "To enable this, Weave has built-in operations, or **Weave Ops**, to transform data. You can also configure the data displayed in each column as we did with the plot.\n", "\n", "For example, to display the sum of each examples' `sepal_width` and `sepal_length`:\n", + "\n", "- Click a column to edit (e.g. `sepal_length`)\n", "- Change the Cell expression to `row[\"sepal_width\"] + row[\"sepal_length\"]`\n", "- Click anywhere outside the popover to apply the change\n", @@ -172,12 +178,13 @@ "- Click the three dots button ⋮ on the `target_name` column\n", "- Click `Group by`\n", "\n", - "We now see that Weave has grouped our data by the `target_name` and made plots for each column. We can now use different operations on these columns because they're now _lists_ rather than individual elements. \n", + "We now see that Weave has grouped our data by the `target_name` and made plots for each column. We can now use different operations on these columns because they're now _lists_ rather than individual elements.\n", "\n", "For example, we can calculate the average of each column by changing the cell expression to be `row[\"\"].avg` e.g. `row[\"sepal_length\"].avg`.\n", "\n", - "## Exercise \n", - "- Try calculating the maximum of each column" + "## Exercise\n", + "\n", + "- Try calculating the maximum of each column\n" ] }, { @@ -186,7 +193,7 @@ "id": "0954b735", "metadata": {}, "source": [ - "!['image'](https://raw.githubusercontent.com/wandb/weave/4885095070704922189ba4d761029821c4e5da42/docs/assets/get_started_1.png)" + "!['image'](https://raw.githubusercontent.com/wandb/weave/4885095070704922189ba4d761029821c4e5da42/docs/assets/get_started_1.png)\n" ] }, { @@ -196,7 +203,7 @@ "source": [ "## Drilldown with connected plots\n", "\n", - "Finally, once you have found a split of data that is interesting, you often want to view individual elements of that data to better understand it. Weave makes it easy to connect multiple visualizations so that you can drilldown into selected data. " + "Finally, once you have found a split of data that is interesting, you often want to view individual elements of that data to better understand it. Weave makes it easy to connect multiple visualizations so that you can drilldown into selected data.\n" ] }, { @@ -214,7 +221,7 @@ "id": "2519db1c", "metadata": {}, "source": [ - "!['image'](https://raw.githubusercontent.com/wandb/weave/4885095070704922189ba4d761029821c4e5da42/docs/assets/get_started_2.png)" + "!['image'](https://raw.githubusercontent.com/wandb/weave/4885095070704922189ba4d761029821c4e5da42/docs/assets/get_started_2.png)\n" ] }, { @@ -223,6 +230,7 @@ "metadata": {}, "source": [ "For example, to select data from a plot and display it in a table:\n", + "\n", "- Add a new panel from the drawer menu on the right (1)\n", "- Using the panel name (2), refer to the `.selected_data` from the first panel in the expression editor (3)\n", "- Use the selection tool (4) to display that data in the drilldown table\n", @@ -235,7 +243,7 @@ "\n", "# What's next?\n", "\n", - "With what you've learned, try build something on your own data. Weave works with lots of different types of data and is performant at large scales!" + "With what you've learned, try build something on your own data. Weave works with lots of different types of data and is performant at large scales!\n" ] }, { @@ -265,7 +273,7 @@ "\n", "## Not finished learning?\n", "\n", - "Check out our [examples](https://github.com/wandb/weave/tree/master/examples) to see more tutorials, a gallery of dashboards, and reference guides to different components." + "Check out our [examples](https://github.com/wandb/weave/tree/master/examples) to see more tutorials, a gallery of dashboards, and reference guides to different components.\n" ] } ], diff --git a/examples/reference/WB_API.ipynb b/examples/reference/WB_API.ipynb index 70aa036d4f3..04747e092f6 100644 --- a/examples/reference/WB_API.ipynb +++ b/examples/reference/WB_API.ipynb @@ -10,7 +10,7 @@ "import weave\n", "import weave.legacy.panels\n", "import weave.legacy.ops\n", - "from weave.show import show" + "from weave.legacy.show import show" ] }, { diff --git a/examples/reference/create_plots_ui_guide.ipynb b/examples/reference/create_plots_ui_guide.ipynb index dacecd97df9..468507e3b2e 100644 --- a/examples/reference/create_plots_ui_guide.ipynb +++ b/examples/reference/create_plots_ui_guide.ipynb @@ -39,7 +39,7 @@ "import wandb\n", "wandb.login()\n", "import weave\n", - "from weave.show import show" + "from weave.legacy.show import show" ] }, { diff --git a/examples/reference/vis/Scatter.ipynb b/examples/reference/vis/Scatter.ipynb index 35a1c5cdbe0..7584ee9b4cd 100644 --- a/examples/reference/vis/Scatter.ipynb +++ b/examples/reference/vis/Scatter.ipynb @@ -10,7 +10,7 @@ "import random\n", "import weave\n", "import weave.legacy.panels\n", - "from weave.show import show\n", + "from weave.legacy.show import show\n", "# Weave package now defaults to eager mode, but lazy mode required for this example notebook for now.\n", "weave.use_lazy_execution()\n", "from weave.legacy.ecosystem import wandb" diff --git a/integration_test/cypress/e2e/interactive/blank.py b/integration_test/cypress/e2e/interactive/blank.py index 6b92e6758f7..ef823b13559 100644 --- a/integration_test/cypress/e2e/interactive/blank.py +++ b/integration_test/cypress/e2e/interactive/blank.py @@ -1,5 +1,5 @@ import weave -from weave.show import show_url +from weave.legacy.show import show_url weave.use_fixed_server_port() obj = [ diff --git a/integration_test/cypress/e2e/interactive/distribution.py b/integration_test/cypress/e2e/interactive/distribution.py index 42c9006e5a0..e81e06a7c78 100644 --- a/integration_test/cypress/e2e/interactive/distribution.py +++ b/integration_test/cypress/e2e/interactive/distribution.py @@ -2,7 +2,7 @@ import weave from weave.legacy import panels -from weave.show import show_url +from weave.legacy.show import show_url # Weave package now defaults to eager mode, but lazy mode required for this example notebook for now. weave.use_lazy_execution() diff --git a/integration_test/cypress/e2e/interactive/scatter.py b/integration_test/cypress/e2e/interactive/scatter.py index 0a76b6201ee..0c0b117866d 100644 --- a/integration_test/cypress/e2e/interactive/scatter.py +++ b/integration_test/cypress/e2e/interactive/scatter.py @@ -2,7 +2,7 @@ import weave from weave.legacy.ecosystem import wandb -from weave.show import show_url +from weave.legacy.show import show_url weave.use_fixed_server_port() diff --git a/weave/legacy/panel.py b/weave/legacy/panel.py index d01d5159b25..094c90c9339 100644 --- a/weave/legacy/panel.py +++ b/weave/legacy/panel.py @@ -157,6 +157,6 @@ def to_json(self): } def _ipython_display_(self): - from weave import show + from weave.legacy import show show.show(self) diff --git a/weave/show.py b/weave/legacy/show.py similarity index 84% rename from weave/show.py rename to weave/legacy/show.py index 5027cb8fa79..4e6885795a0 100644 --- a/weave/show.py +++ b/weave/legacy/show.py @@ -6,20 +6,13 @@ from IPython.display import IFrame, display from weave.legacy import artifact_fs, context, graph, ops, panel +from weave import errors, node_ref, ref_base, storage, util +from . import usage_analytics +from .. import weave_types as types +from . import weavejs_fixes -from . import ( - errors, - node_ref, - ref_base, - storage, - usage_analytics, - util, -) -from . import weave_types as types -from .legacy import weavejs_fixes - -def make_varname_for_type(t: types.Type): +def make_varname_for_type(t: types.Type): # type: ignore if isinstance(t, types.List) and isinstance(t.object_type, types.TypedDict): return "table" return t.name @@ -64,10 +57,10 @@ def make_show_obj(obj: typing.Any) -> tuple[typing.Union[panel.Panel, graph.Node uri = obj.uri return ops.get(uri), name # type: ignore - if types.TypeRegistry.has_type(obj): - names = util.find_names(obj) + if types.TypeRegistry.has_type(obj): # type: ignore[no-untyped-call] + names = util.find_names(obj) # type: ignore[no-untyped-call] - ref = storage.save(obj, name=names[-1]) + ref = storage.save(obj, name=names[-1]) # type: ignore[arg-type] node = ops.get(ref.uri) # type: ignore return node, make_varname_for_type(ref.type) @@ -77,7 +70,7 @@ def make_show_obj(obj: typing.Any) -> tuple[typing.Union[panel.Panel, graph.Node # Broken out into to separate function for testing -def _show_params(obj): +def _show_params(obj): # type: ignore # Get a weave node (expression) that will return the object, and something to call it node, var_name = make_show_obj(obj) @@ -105,7 +98,7 @@ def _show_params(obj): return {"weave_node": weavejs_fixes.fixup_node(show_node)} -def show_url(obj=None): +def show_url(obj=None): # type: ignore if os.environ.get("WEAVE_FRONTEND_DEVMODE"): context.use_frontend_devmode() params = _show_params(obj) @@ -131,12 +124,12 @@ def show(obj: typing.Any = None, height: int = 400) -> typing.Any: "a weave node, try `weave.use()`." ) - if util.is_pandas_dataframe(obj): - obj = ops.dataframe_to_arrow(obj) + if util.is_pandas_dataframe(obj): # type: ignore[no-untyped-call] + obj = ops.dataframe_to_arrow(obj) # type: ignore[no-untyped-call] - panel_url = show_url(obj) + panel_url = show_url(obj) # type: ignore[no-untyped-call] - if util.is_colab(): + if util.is_colab(): # type: ignore[no-untyped-call] from google.colab.output import serve_kernel_port_as_iframe url = urllib.parse.urlparse(panel_url) @@ -148,7 +141,7 @@ def show(obj: typing.Any = None, height: int = 400) -> typing.Any: display(iframe) -def _ipython_display_method_(self): +def _ipython_display_method_(self): # type: ignore show(self) diff --git a/weave/legacy/wandb_interface/wandb_stream_table.py b/weave/legacy/wandb_interface/wandb_stream_table.py index bbe546253f0..31070b588c6 100644 --- a/weave/legacy/wandb_interface/wandb_stream_table.py +++ b/weave/legacy/wandb_interface/wandb_stream_table.py @@ -208,7 +208,7 @@ def rows(self) -> graph.Node: ) def _ipython_display_(self) -> graph.Node: - from weave import show + from weave.legacy import show return show.show(self.rows()) diff --git a/weave/tests/legacy/test_api.py b/weave/tests/legacy/test_api.py index c49db782e39..dce30746540 100644 --- a/weave/tests/legacy/test_api.py +++ b/weave/tests/legacy/test_api.py @@ -1,7 +1,7 @@ import shutil from ... import api as weave -from ...show import _show_params +from ...legacy.show import _show_params def test_print_save_val(): diff --git a/weave/tests/legacy/test_show.py b/weave/tests/legacy/test_show.py index 859309436e1..bee6ecd76dd 100644 --- a/weave/tests/legacy/test_show.py +++ b/weave/tests/legacy/test_show.py @@ -4,7 +4,7 @@ from weave.legacy import ops -from ...show import _show_params +from ...legacy.show import _show_params from . import test_helpers From f7a83100780b73f1d9068134dd3a5e0214d632e1 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Thu, 22 Aug 2024 21:52:48 -0400 Subject: [PATCH 16/84] move to legacy: eager --- weave/legacy/artifact_wandb.py | 2 +- weave/{ => legacy}/eager.py | 4 ++-- weave/legacy/execute.py | 2 +- weave/legacy/run_streamtable_span.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename weave/{ => legacy}/eager.py (98%) diff --git a/weave/legacy/artifact_wandb.py b/weave/legacy/artifact_wandb.py index 0d22e8b645a..527d3c3c3ab 100644 --- a/weave/legacy/artifact_wandb.py +++ b/weave/legacy/artifact_wandb.py @@ -14,7 +14,6 @@ from wandb.sdk.lib.hashutil import b64_to_hex_id, hex_to_b64_id from weave import ( - eager, engine_trace, errors, filesystem, @@ -24,6 +23,7 @@ from weave import weave_types as types from weave.legacy import ( artifact_fs, + eager, file_base, file_util, memo, diff --git a/weave/eager.py b/weave/legacy/eager.py similarity index 98% rename from weave/eager.py rename to weave/legacy/eager.py index 13c5ac76e85..5136297e7be 100644 --- a/weave/eager.py +++ b/weave/legacy/eager.py @@ -2,8 +2,8 @@ from weave.legacy import context_state, graph -from . import weave_internal -from . import weave_types as types +from .. import weave_internal +from .. import weave_types as types WeaveIterObjectType = typing.TypeVar("WeaveIterObjectType") diff --git a/weave/legacy/execute.py b/weave/legacy/execute.py index 909a052edaa..e05958a2f9c 100644 --- a/weave/legacy/execute.py +++ b/weave/legacy/execute.py @@ -10,7 +10,6 @@ from collections.abc import Mapping from weave import ( - eager, engine_trace, environment, errors, @@ -32,6 +31,7 @@ compile, context, context_state, + eager, forward_graph, graph, graph_debug, diff --git a/weave/legacy/run_streamtable_span.py b/weave/legacy/run_streamtable_span.py index 269187d8b0b..ae5f9225c22 100644 --- a/weave/legacy/run_streamtable_span.py +++ b/weave/legacy/run_streamtable_span.py @@ -2,7 +2,7 @@ from typing import Iterable from weave.legacy import stream_data_interfaces -from weave.eager import WeaveIter +from weave.legacy.eager import WeaveIter from weave.legacy import artifact_wandb, uris from weave.legacy.run import Run From c118c5b6111e9d3c50309b6b69b835fa502923b4 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Thu, 22 Aug 2024 22:10:53 -0400 Subject: [PATCH 17/84] move to legacy: stitch --- weave/legacy/compile.py | 2 +- weave/legacy/compile_domain.py | 4 ++-- weave/legacy/compile_table.py | 3 ++- weave/legacy/input_provider.py | 2 +- weave/{ => legacy}/stitch.py | 6 +++--- weave/tests/legacy/test_stitch.py | 3 ++- weave/tests/legacy/test_wb.py | 3 +-- 7 files changed, 12 insertions(+), 11 deletions(-) rename weave/{ => legacy}/stitch.py (99%) diff --git a/weave/legacy/compile.py b/weave/legacy/compile.py index 4a5c66b5d4c..cbe4293e893 100644 --- a/weave/legacy/compile.py +++ b/weave/legacy/compile.py @@ -9,7 +9,6 @@ engine_trace, errors, registry_mem, - stitch, weave_internal, ) from weave import weave_types as types @@ -28,6 +27,7 @@ partial_object, propagate_gql_keys, serialize, + stitch, value_or_error, ) from weave.legacy.language_features.tagging import tagged_value_type_helpers diff --git a/weave/legacy/compile_domain.py b/weave/legacy/compile_domain.py index 74ac5f63c56..7e04250e4f9 100644 --- a/weave/legacy/compile_domain.py +++ b/weave/legacy/compile_domain.py @@ -2,9 +2,9 @@ import graphql -from weave import errors, registry_mem, stitch +from weave import errors, registry_mem from weave import weave_types as types -from weave.legacy import gql_op_plugin, gql_to_weave, graph, op_args +from weave.legacy import gql_op_plugin, gql_to_weave, graph, op_args, stitch from weave.legacy.input_provider import InputAndStitchProvider if typing.TYPE_CHECKING: diff --git a/weave/legacy/compile_table.py b/weave/legacy/compile_table.py index 96f1c8d9815..59982717967 100644 --- a/weave/legacy/compile_table.py +++ b/weave/legacy/compile_table.py @@ -2,7 +2,8 @@ import typing -from weave import errors, stitch +from weave import errors +from weave.legacy import stitch KeyTree = typing.Dict[str, "KeyTree"] # type:ignore diff --git a/weave/legacy/input_provider.py b/weave/legacy/input_provider.py index c14e73680a3..a62a98d2fd1 100644 --- a/weave/legacy/input_provider.py +++ b/weave/legacy/input_provider.py @@ -2,7 +2,7 @@ import typing from dataclasses import dataclass, field -from .. import stitch +from . import stitch @dataclass diff --git a/weave/stitch.py b/weave/legacy/stitch.py similarity index 99% rename from weave/stitch.py rename to weave/legacy/stitch.py index 51a55c89f03..1fd73868f8a 100644 --- a/weave/stitch.py +++ b/weave/legacy/stitch.py @@ -25,9 +25,9 @@ from weave.legacy import graph, op_def from weave.legacy.language_features.tagging import opdef_util -from . import errors, registry_mem -from . import weave_types as types -from .legacy import _dict_utils +from .. import errors, registry_mem +from .. import weave_types as types +from . import _dict_utils @dataclasses.dataclass diff --git a/weave/tests/legacy/test_stitch.py b/weave/tests/legacy/test_stitch.py index ca205300d39..368f01ce553 100644 --- a/weave/tests/legacy/test_stitch.py +++ b/weave/tests/legacy/test_stitch.py @@ -8,7 +8,8 @@ from weave.legacy.language_features.tagging import make_tag_getter_op from weave.legacy.ops_domain import run_ops -from ... import stitch, weave_internal +from ... import weave_internal +from ...legacy import stitch from .. import fixture_fakewandb as fwb from . import test_wb diff --git a/weave/tests/legacy/test_wb.py b/weave/tests/legacy/test_wb.py index fd55c897b0b..20988988982 100644 --- a/weave/tests/legacy/test_wb.py +++ b/weave/tests/legacy/test_wb.py @@ -7,9 +7,8 @@ import wandb from weave import query_api as weave -from weave import stitch from weave import weave_types as types -from weave.legacy import artifact_fs, artifact_wandb, compile, graph, ops, uris +from weave.legacy import artifact_fs, artifact_wandb, compile, graph, ops, stitch, uris from weave.legacy import ops_arrow as arrow from weave.legacy.language_features.tagging.tagged_value_type import TaggedValueType from weave.legacy.ops_arrow import ArrowWeaveListType From a356e7adc3533c0085703278b56f919769abed39 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Thu, 22 Aug 2024 22:04:25 -0400 Subject: [PATCH 18/84] move to legacy: pyfunc_type_util.py --- weave/legacy/decorator_op.py | 4 ++-- weave/legacy/dispatch.py | 4 ++-- weave/legacy/op_def.py | 2 +- weave/{ => legacy}/pyfunc_type_util.py | 4 ++-- weave/serve_fastapi.py | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) rename weave/{ => legacy}/pyfunc_type_util.py (99%) diff --git a/weave/legacy/decorator_op.py b/weave/legacy/decorator_op.py index 6f27dcb142b..c7f0dc8b6cb 100644 --- a/weave/legacy/decorator_op.py +++ b/weave/legacy/decorator_op.py @@ -4,9 +4,9 @@ from typing_extensions import ParamSpec -from weave import pyfunc_type_util, registry_mem +from weave import registry_mem from weave import weave_types as types -from weave.legacy import context_state, derive_op, op_args, op_def +from weave.legacy import context_state, derive_op, op_args, op_def, pyfunc_type_util if typing.TYPE_CHECKING: from weave.legacy.gql_op_plugin import GqlOpPlugin diff --git a/weave/legacy/dispatch.py b/weave/legacy/dispatch.py index fef90cead41..b0af4369b9f 100644 --- a/weave/legacy/dispatch.py +++ b/weave/legacy/dispatch.py @@ -5,9 +5,9 @@ import typing from dataclasses import dataclass -from weave import errors, pyfunc_type_util, registry_mem, util +from weave import errors, registry_mem, util from weave import weave_types as types -from weave.legacy import graph, memo, op_args, op_def +from weave.legacy import graph, memo, op_args, op_def, pyfunc_type_util from weave.legacy.language_features.tagging.is_tag_getter import is_tag_getter from weave.legacy.language_features.tagging.tagged_value_type import TaggedValueType diff --git a/weave/legacy/op_def.py b/weave/legacy/op_def.py index 25438b8b24c..78d697e4e3c 100644 --- a/weave/legacy/op_def.py +++ b/weave/legacy/op_def.py @@ -9,7 +9,6 @@ from weave import ( engine_trace, errors, - pyfunc_type_util, weave_internal, ) from weave import weave_types as types @@ -22,6 +21,7 @@ op_args, op_def_type, op_execute, + pyfunc_type_util, uris, ) from weave.legacy.language_features.tagging import ( diff --git a/weave/pyfunc_type_util.py b/weave/legacy/pyfunc_type_util.py similarity index 99% rename from weave/pyfunc_type_util.py rename to weave/legacy/pyfunc_type_util.py index 4ae2943cc1f..bb544dfd2f4 100644 --- a/weave/pyfunc_type_util.py +++ b/weave/legacy/pyfunc_type_util.py @@ -3,8 +3,8 @@ from weave.legacy import infer_types, op_args -from . import errors -from . import weave_types as types +from .. import errors +from .. import weave_types as types InputTypeItemType = typing.Union[types.Type, typing.Callable[..., types.Type]] InputTypeType = typing.Union[op_args.OpArgs, typing.Mapping[str, InputTypeItemType]] diff --git a/weave/serve_fastapi.py b/weave/serve_fastapi.py index 584b9f1fc36..d6b23431349 100644 --- a/weave/serve_fastapi.py +++ b/weave/serve_fastapi.py @@ -12,12 +12,12 @@ except ImportError: from typing_extensions import Annotated # type: ignore -from weave.legacy import cache, op_args +from weave.legacy import cache, op_args, pyfunc_type_util from weave.legacy.wandb_api import WandbApiAsync from weave.trace.op import Op from weave.trace.refs import ObjectRef -from . import errors, pyfunc_type_util, weave_pydantic +from . import errors, weave_pydantic key_cache: cache.LruTimeWindowCache[str, typing.Optional[bool]] = ( cache.LruTimeWindowCache(datetime.timedelta(minutes=5)) From a026e4cfb3e205f065eb7f576c2b4db3dba29322 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Thu, 22 Aug 2024 22:41:27 -0400 Subject: [PATCH 19/84] move to legacy: node_ref --- weave/legacy/arrow/list_.py | 2 +- weave/legacy/graph_mapper.py | 4 ++-- weave/legacy/mappers_arrow.py | 3 ++- weave/legacy/mappers_publisher.py | 2 +- weave/{ => legacy}/node_ref.py | 2 +- weave/legacy/show.py | 4 ++-- weave/tests/legacy/test_node_ref.py | 2 +- 7 files changed, 10 insertions(+), 9 deletions(-) rename weave/{ => legacy}/node_ref.py (99%) diff --git a/weave/legacy/arrow/list_.py b/weave/legacy/arrow/list_.py index 85092b6230d..6db149220d5 100644 --- a/weave/legacy/arrow/list_.py +++ b/weave/legacy/arrow/list_.py @@ -12,7 +12,6 @@ from weave import ( errors, - node_ref, ref_base, ref_util, weave_internal, @@ -27,6 +26,7 @@ graph, op_def, op_def_type, + node_ref, ) from weave.legacy.arrow.arrow import ( ArrowWeaveListType, diff --git a/weave/legacy/graph_mapper.py b/weave/legacy/graph_mapper.py index a23acf156d4..8e0b6cce626 100644 --- a/weave/legacy/graph_mapper.py +++ b/weave/legacy/graph_mapper.py @@ -1,6 +1,6 @@ -from weave import node_ref, ref_base +from weave import ref_base from weave import weave_types as types -from weave.legacy import graph, mappers +from weave.legacy import graph, mappers, node_ref from weave.legacy import mappers_python_def as mappers_python diff --git a/weave/legacy/mappers_arrow.py b/weave/legacy/mappers_arrow.py index dfffef0f4e1..6b3ed376577 100644 --- a/weave/legacy/mappers_arrow.py +++ b/weave/legacy/mappers_arrow.py @@ -5,7 +5,7 @@ import pyarrow as pa -from weave import errors, node_ref, ref_base +from weave import errors, ref_base from weave import weave_types as types from weave.legacy import ( arrow_util, @@ -13,6 +13,7 @@ box, mappers, mappers_weave, + node_ref, partial_object, ) from weave.legacy import mappers_python_def as mappers_python diff --git a/weave/legacy/mappers_publisher.py b/weave/legacy/mappers_publisher.py index a6b622b5ded..f9facd494e7 100644 --- a/weave/legacy/mappers_publisher.py +++ b/weave/legacy/mappers_publisher.py @@ -4,7 +4,7 @@ from weave import errors, ref_base, storage, weave_internal from weave import weave_types as types -from weave.node_ref import ref_to_node +from weave.legacy.node_ref import ref_to_node # from weave.legacy.ops_primitives import weave_api from weave.legacy import ( diff --git a/weave/node_ref.py b/weave/legacy/node_ref.py similarity index 99% rename from weave/node_ref.py rename to weave/legacy/node_ref.py index 47edbc6804b..9c19030ba8f 100644 --- a/weave/node_ref.py +++ b/weave/legacy/node_ref.py @@ -3,7 +3,7 @@ from weave.legacy import graph -from . import ref_base +from .. import ref_base # Notes for the future: # - I added list.lookup to lookup rows in a list by ID. I think we probably should diff --git a/weave/legacy/show.py b/weave/legacy/show.py index 4e6885795a0..df57367e12f 100644 --- a/weave/legacy/show.py +++ b/weave/legacy/show.py @@ -5,8 +5,8 @@ from IPython.display import IFrame, display -from weave.legacy import artifact_fs, context, graph, ops, panel -from weave import errors, node_ref, ref_base, storage, util +from weave.legacy import artifact_fs, context, graph, ops, node_ref, panel +from weave import errors, ref_base, storage, util from . import usage_analytics from .. import weave_types as types from . import weavejs_fixes diff --git a/weave/tests/legacy/test_node_ref.py b/weave/tests/legacy/test_node_ref.py index 79af6d43a29..eaacc2c3190 100644 --- a/weave/tests/legacy/test_node_ref.py +++ b/weave/tests/legacy/test_node_ref.py @@ -1,7 +1,7 @@ from weave.legacy import graph from ... import api as weave -from ... import node_ref +from ...legacy import node_ref def test_node_to_ref(): From e8768a11d0ac11af6d8b34abd444374b3da3d156 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Thu, 22 Aug 2024 22:51:01 -0400 Subject: [PATCH 20/84] move to legacy: types_numpy --- weave/legacy/artifact_fs.py | 2 +- weave/{ => legacy}/types_numpy.py | 18 +++++++++--------- weave/query_api.py | 2 +- weave/tests/legacy/test_numpy.py | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) rename weave/{ => legacy}/types_numpy.py (68%) diff --git a/weave/legacy/artifact_fs.py b/weave/legacy/artifact_fs.py index 53e249e09de..b753b501974 100644 --- a/weave/legacy/artifact_fs.py +++ b/weave/legacy/artifact_fs.py @@ -266,7 +266,7 @@ def type(self) -> types.Type: ot = self._outer_type if self.extra is not None: - from weave import types_numpy + from weave.legacy import types_numpy if not types.is_list_like(ot) and isinstance( ot, types_numpy.NumpyArrayType diff --git a/weave/types_numpy.py b/weave/legacy/types_numpy.py similarity index 68% rename from weave/types_numpy.py rename to weave/legacy/types_numpy.py index 1d998500b9e..2577e1119a7 100644 --- a/weave/types_numpy.py +++ b/weave/legacy/types_numpy.py @@ -1,6 +1,6 @@ import numpy as np -from . import weave_types as types +from .. import weave_types as types # TODO: this doesn't match how extra works for list types... @@ -8,22 +8,22 @@ class NumpyArrayType(types.Type): instance_classes = np.ndarray name = "WeaveNDArray" - def __init__(self, dtype="x", shape=(0,)): + def __init__(self, dtype="x", shape=(0,)): # type: ignore self.dtype = dtype self.shape = shape @classmethod - def type_of_instance(cls, obj): + def type_of_instance(cls, obj): # type: ignore return cls(obj.dtype, obj.shape) - def _to_dict(self): + def _to_dict(self): # type: ignore return {"dtype": str(self.dtype), "shape": self.shape} @classmethod - def from_dict(cls, d): + def from_dict(cls, d): # type: ignore return cls(np.dtype(d.get("dtype", "object")), d["shape"]) - def _assign_type_inner(self, next_type): + def _assign_type_inner(self, next_type): # type: ignore if not isinstance(next_type, NumpyArrayType): return False if ( @@ -33,13 +33,13 @@ def _assign_type_inner(self, next_type): return False return True - def save_instance(self, obj, artifact, name): + def save_instance(self, obj, artifact, name): # type: ignore with artifact.new_file(f"{name}.npz", binary=True) as f: np.savez_compressed(f, arr=obj) - def load_instance(self, artifact, name, extra=None): + def load_instance(self, artifact, name, extra=None): # type: ignore with artifact.open(f"{name}.npz", binary=True) as f: return np.load(f)["arr"] - def __str__(self): + def __str__(self): # type: ignore return "" % (self.dtype, self.shape) diff --git a/weave/query_api.py b/weave/query_api.py index 03ff7562fdf..908c7e526fb 100644 --- a/weave/query_api.py +++ b/weave/query_api.py @@ -24,7 +24,7 @@ from . import weave_types as types # needed to enable automatic numpy serialization -from . import types_numpy as _types_numpy +from .legacy import types_numpy as _types_numpy from . import errors from weave.legacy.decorators import weave_class, mutation, type diff --git a/weave/tests/legacy/test_numpy.py b/weave/tests/legacy/test_numpy.py index cdb89250c9e..3ac8858e42c 100644 --- a/weave/tests/legacy/test_numpy.py +++ b/weave/tests/legacy/test_numpy.py @@ -3,8 +3,8 @@ from weave.legacy import artifact_fs, artifact_wandb from weave.legacy.ops_domain import table -from ... import types_numpy as numpy_types from ... import weave_types as types +from ...legacy import types_numpy as numpy_types def test_construct_numpy_type(): From 0d2467aa1d453e7b79875ffed37b03dd64f907b4 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Thu, 22 Aug 2024 22:50:02 -0400 Subject: [PATCH 21/84] move to legacy: registry_mem --- weave/legacy/codify.py | 4 ++-- weave/legacy/compile.py | 2 +- weave/legacy/compile_domain.py | 4 ++-- weave/legacy/decorator_class.py | 4 ++-- weave/legacy/decorator_op.py | 3 +-- weave/legacy/derive_op.py | 2 +- weave/legacy/dispatch.py | 4 ++-- weave/legacy/ecosystem/root.py | 4 ++-- weave/legacy/ecosystem/wandb/wandb_objs.py | 2 +- weave/legacy/execute.py | 2 +- weave/legacy/execute_fast.py | 2 +- .../tagging/process_opdef_output_type.py | 2 +- weave/legacy/op_def_type.py | 4 ++-- weave/legacy/ops_arrow/vectorize.py | 3 +-- .../run_history/history_op_common.py | 2 +- weave/legacy/ops_primitives/weave_api.py | 2 +- weave/legacy/panels_py/generator_templates.py | 4 ++-- weave/legacy/propagate_gql_keys.py | 4 ++-- weave/{ => legacy}/registry_mem.py | 18 +++++++++--------- weave/legacy/stitch.py | 4 ++-- weave/tests/legacy/test_derive_op.py | 2 +- weave/tests/legacy/test_mappability.py | 2 +- weave/tests/legacy/test_op_behaviors.py | 3 ++- weave/tests/legacy/test_op_coverage.py | 2 +- weave/tests/legacy/test_op_serialization.py | 3 ++- weave/tests/legacy/test_serialize.py | 4 ++-- weave/tests/legacy/test_wb_domain_ops.py | 2 +- weave/weave_internal.py | 2 +- weave/weave_server.py | 10 ++++++++-- 29 files changed, 56 insertions(+), 50 deletions(-) rename weave/{ => legacy}/registry_mem.py (92%) diff --git a/weave/legacy/codify.py b/weave/legacy/codify.py index 04fac73cb3c..0395775e034 100644 --- a/weave/legacy/codify.py +++ b/weave/legacy/codify.py @@ -6,8 +6,8 @@ import black -from weave import registry_mem, storage, weave_types -from weave.legacy import graph +from weave import storage, weave_types +from weave.legacy import graph, registry_mem from . import codifiable_value_mixin diff --git a/weave/legacy/compile.py b/weave/legacy/compile.py index cbe4293e893..30cbdf4d98f 100644 --- a/weave/legacy/compile.py +++ b/weave/legacy/compile.py @@ -8,7 +8,6 @@ from weave import ( engine_trace, errors, - registry_mem, weave_internal, ) from weave import weave_types as types @@ -26,6 +25,7 @@ op_args, partial_object, propagate_gql_keys, + registry_mem, serialize, stitch, value_or_error, diff --git a/weave/legacy/compile_domain.py b/weave/legacy/compile_domain.py index 7e04250e4f9..2a0f686d676 100644 --- a/weave/legacy/compile_domain.py +++ b/weave/legacy/compile_domain.py @@ -2,9 +2,9 @@ import graphql -from weave import errors, registry_mem +from weave import errors from weave import weave_types as types -from weave.legacy import gql_op_plugin, gql_to_weave, graph, op_args, stitch +from weave.legacy import gql_op_plugin, gql_to_weave, graph, op_args, stitch, registry_mem from weave.legacy.input_provider import InputAndStitchProvider if typing.TYPE_CHECKING: diff --git a/weave/legacy/decorator_class.py b/weave/legacy/decorator_class.py index 2e42b15b1be..99fadbcb16e 100644 --- a/weave/legacy/decorator_class.py +++ b/weave/legacy/decorator_class.py @@ -1,9 +1,9 @@ import inspect import typing -from weave import errors, registry_mem +from weave import errors from weave import weave_types as types -from weave.legacy import context_state, derive_op, op_def +from weave.legacy import context_state, derive_op, op_def, registry_mem # Contrary to the way it is read, the weave.class() decorator runs AFTER the # inner methods are defined. Therefore, this function runs after the ops are diff --git a/weave/legacy/decorator_op.py b/weave/legacy/decorator_op.py index c7f0dc8b6cb..e193e4b1e38 100644 --- a/weave/legacy/decorator_op.py +++ b/weave/legacy/decorator_op.py @@ -4,9 +4,8 @@ from typing_extensions import ParamSpec -from weave import registry_mem from weave import weave_types as types -from weave.legacy import context_state, derive_op, op_args, op_def, pyfunc_type_util +from weave.legacy import context_state, derive_op, op_args, op_def, pyfunc_type_util, registry_mem if typing.TYPE_CHECKING: from weave.legacy.gql_op_plugin import GqlOpPlugin diff --git a/weave/legacy/derive_op.py b/weave/legacy/derive_op.py index 13c0dcd35de..337bb66cccd 100644 --- a/weave/legacy/derive_op.py +++ b/weave/legacy/derive_op.py @@ -9,12 +9,12 @@ from weave import ( errors, parallelism, - registry_mem, storage, weave_internal, ) from weave import weave_types as types from weave.legacy import ( + registry_mem, box, context_state, execute_fast, diff --git a/weave/legacy/dispatch.py b/weave/legacy/dispatch.py index b0af4369b9f..4eaf2ca215f 100644 --- a/weave/legacy/dispatch.py +++ b/weave/legacy/dispatch.py @@ -5,9 +5,9 @@ import typing from dataclasses import dataclass -from weave import errors, registry_mem, util +from weave import errors, util from weave import weave_types as types -from weave.legacy import graph, memo, op_args, op_def, pyfunc_type_util +from weave.legacy import graph, memo, op_args, op_def, pyfunc_type_util, registry_mem from weave.legacy.language_features.tagging.is_tag_getter import is_tag_getter from weave.legacy.language_features.tagging.tagged_value_type import TaggedValueType diff --git a/weave/legacy/ecosystem/root.py b/weave/legacy/ecosystem/root.py index 0757c9b03d3..38cd09d3e7e 100644 --- a/weave/legacy/ecosystem/root.py +++ b/weave/legacy/ecosystem/root.py @@ -22,7 +22,7 @@ """ ) -from weave import registry_mem +from weave.legacy import registry_mem op_org_name = registry_mem.memory_registry.get_op("user-name") @@ -63,7 +63,7 @@ def ops(self) -> list[op_def.OpDef]: # objects. @weave.op(name="op-ecosystem", render_info={"type": "function"}) def ecosystem() -> Ecosystem: - from weave import registry_mem + from weave.legacy import registry_mem return Ecosystem( _orgs=[], diff --git a/weave/legacy/ecosystem/wandb/wandb_objs.py b/weave/legacy/ecosystem/wandb/wandb_objs.py index c57d8a296aa..449d82ed786 100644 --- a/weave/legacy/ecosystem/wandb/wandb_objs.py +++ b/weave/legacy/ecosystem/wandb/wandb_objs.py @@ -1,7 +1,7 @@ import typing import weave -from weave import registry_mem +from weave.legacy import registry_mem from weave.legacy.ops_domain import run_ops, wb_domain_types # We can't chain ops called .name() because of a weird bug :( [its a field on VarNode]. diff --git a/weave/legacy/execute.py b/weave/legacy/execute.py index e05958a2f9c..ccd0d67f101 100644 --- a/weave/legacy/execute.py +++ b/weave/legacy/execute.py @@ -15,7 +15,6 @@ errors, parallelism, ref_base, - registry_mem, trace_local, ) from weave import weave_types as types @@ -27,6 +26,7 @@ # Trace / cache # Language Features from weave.legacy import ( + registry_mem, box, compile, context, diff --git a/weave/legacy/execute_fast.py b/weave/legacy/execute_fast.py index 29488de46f2..dbf15feeadd 100644 --- a/weave/legacy/execute_fast.py +++ b/weave/legacy/execute_fast.py @@ -4,11 +4,11 @@ engine_trace, errors, ref_base, - registry_mem, weave_internal, ) from weave import weave_types as types from weave.legacy import ( + registry_mem, box, compile, forward_graph, diff --git a/weave/legacy/language_features/tagging/process_opdef_output_type.py b/weave/legacy/language_features/tagging/process_opdef_output_type.py index 7364ebcd409..a445e748527 100644 --- a/weave/legacy/language_features/tagging/process_opdef_output_type.py +++ b/weave/legacy/language_features/tagging/process_opdef_output_type.py @@ -5,7 +5,7 @@ import typing -from weave import registry_mem +from weave.legacy import registry_mem from weave import weave_types as types from weave.legacy import graph from weave.legacy.language_features.tagging.opdef_util import ( diff --git a/weave/legacy/op_def_type.py b/weave/legacy/op_def_type.py index 964aeb4cab9..bb5fccf4525 100644 --- a/weave/legacy/op_def_type.py +++ b/weave/legacy/op_def_type.py @@ -11,9 +11,9 @@ from _ast import AsyncFunctionDef, ExceptHandler from typing import Any -from weave import environment, errors, registry_mem, storage +from weave import environment, errors, storage from weave import weave_types as types -from weave.legacy import artifact_fs, artifact_local, context_state, infer_types +from weave.legacy import artifact_fs, artifact_local, context_state, infer_types, registry_mem if typing.TYPE_CHECKING: from .op_def import OpDef diff --git a/weave/legacy/ops_arrow/vectorize.py b/weave/legacy/ops_arrow/vectorize.py index f4123b18a54..8f3a11a2452 100644 --- a/weave/legacy/ops_arrow/vectorize.py +++ b/weave/legacy/ops_arrow/vectorize.py @@ -8,10 +8,9 @@ from weave import ( errors, - registry_mem, weave_internal, ) -from weave.legacy import weavify +from weave.legacy import weavify, registry_mem from weave import weave_types as types from weave.query_api import op, use from weave.legacy import dispatch, graph, graph_debug, op_args, op_def diff --git a/weave/legacy/ops_domain/run_history/history_op_common.py b/weave/legacy/ops_domain/run_history/history_op_common.py index 1987645a7c9..72d945d39f0 100644 --- a/weave/legacy/ops_domain/run_history/history_op_common.py +++ b/weave/legacy/ops_domain/run_history/history_op_common.py @@ -7,12 +7,12 @@ from weave import ( engine_trace, errors, - registry_mem, util, ) from weave import weave_types as types from weave.query_api import use from weave.legacy import ( + registry_mem, _dict_utils, artifact_base, artifact_fs, diff --git a/weave/legacy/ops_primitives/weave_api.py b/weave/legacy/ops_primitives/weave_api.py index 5417cb96de7..33ace6416b4 100644 --- a/weave/legacy/ops_primitives/weave_api.py +++ b/weave/legacy/ops_primitives/weave_api.py @@ -5,13 +5,13 @@ from weave import ( errors, ref_base, - registry_mem, storage, weave_internal, ) from weave import weave_types as types from weave.query_api import mutation, op, weave_class from weave.legacy import ( + registry_mem, artifact_fs, artifact_local, artifact_wandb, diff --git a/weave/legacy/panels_py/generator_templates.py b/weave/legacy/panels_py/generator_templates.py index 80bcccfb04f..b7fc045cb22 100644 --- a/weave/legacy/panels_py/generator_templates.py +++ b/weave/legacy/panels_py/generator_templates.py @@ -18,8 +18,8 @@ import dataclasses import typing -from weave import registry_mem, weave_types -from weave.legacy import decorator_op, graph +from weave import weave_types +from weave.legacy import decorator_op, graph, registry_mem @dataclasses.dataclass diff --git a/weave/legacy/propagate_gql_keys.py b/weave/legacy/propagate_gql_keys.py index 50f7d284acc..08aa87a1aff 100644 --- a/weave/legacy/propagate_gql_keys.py +++ b/weave/legacy/propagate_gql_keys.py @@ -1,8 +1,8 @@ import typing -from weave import registry_mem + from weave import weave_types as types -from weave.legacy import gql_op_plugin, graph, input_provider, op_def, partial_object +from weave.legacy import gql_op_plugin, graph, input_provider, op_def, partial_object, registry_mem def _propagate_gql_keys_for_node( diff --git a/weave/registry_mem.py b/weave/legacy/registry_mem.py similarity index 92% rename from weave/registry_mem.py rename to weave/legacy/registry_mem.py index 29061705502..62f4a42134f 100644 --- a/weave/registry_mem.py +++ b/weave/legacy/registry_mem.py @@ -28,7 +28,7 @@ class Registry: # the registry over HTTP. _updated_at: float - def __init__(self): + def __init__(self): # type: ignore self._types = {} self._ops = {} self._ops_by_common_name = {} @@ -41,8 +41,8 @@ def mark_updated(self) -> None: def updated_at(self) -> float: return self._updated_at - def register_op(self, op: "OpDef", location=None): - if context_state.get_no_op_register(): + def register_op(self, op: "OpDef", location=None): # type: ignore + if context_state.get_no_op_register(): # type: ignore[no-untyped-call] return op self.mark_updated() # do not save built-in ops today @@ -97,7 +97,7 @@ def get_op(self, uri: str) -> "OpDef": raise errors.WeaveMissingOpDefError("Op not registered: %s" % uri) return res - def find_op_by_fn(self, lazy_local_fn): + def find_op_by_fn(self, lazy_local_fn): # type: ignore for op_def in self._op_versions.values(): if op_def.call_fn == lazy_local_fn: return op_def @@ -111,7 +111,7 @@ def find_ops_by_common_name(self, common_name: str) -> typing.List["OpDef"]: return ops def find_chainable_ops(self, arg0_type: weave_types.Type) -> typing.List["OpDef"]: - def is_chainable(op): + def is_chainable(op): # type: ignore if not isinstance(op.input_type, op_args.OpNamedArgs): return False args = list(op.input_type.arg_types.values()) @@ -119,9 +119,9 @@ def is_chainable(op): return False return args[0].assign_type(arg0_type) - return [op for op in self._ops.values() if is_chainable(op)] + return [op for op in self._ops.values() if is_chainable(op)] # type: ignore[no-untyped-call] - def load_saved_ops(self): + def load_saved_ops(self): # type: ignore from weave.legacy import op_def_type for op_ref in storage.objects(op_def_type.OpDefType()): @@ -149,7 +149,7 @@ def list_packages(self) -> typing.List["OpDef"]: ] return packages - def rename_op(self, name, new_name): + def rename_op(self, name, new_name): # type: ignore """Internal use only, used during op bootstrapping at decorator time""" self.mark_updated() op = self._ops.pop(name) @@ -186,4 +186,4 @@ def rename_op(self, name, new_name): # Processes have a singleton MemoryRegistry -memory_registry = Registry() +memory_registry = Registry() # type: ignore[no-untyped-call] diff --git a/weave/legacy/stitch.py b/weave/legacy/stitch.py index 1fd73868f8a..3c2de9a04bc 100644 --- a/weave/legacy/stitch.py +++ b/weave/legacy/stitch.py @@ -22,10 +22,10 @@ import dataclasses import typing -from weave.legacy import graph, op_def +from weave.legacy import graph, op_def, registry_mem from weave.legacy.language_features.tagging import opdef_util -from .. import errors, registry_mem +from .. import errors from .. import weave_types as types from . import _dict_utils diff --git a/weave/tests/legacy/test_derive_op.py b/weave/tests/legacy/test_derive_op.py index c3bc56848be..85b86659543 100644 --- a/weave/tests/legacy/test_derive_op.py +++ b/weave/tests/legacy/test_derive_op.py @@ -1,5 +1,5 @@ from ... import api as weave -from ... import registry_mem +from ...legacy import registry_mem def test_mapped_add(): diff --git a/weave/tests/legacy/test_mappability.py b/weave/tests/legacy/test_mappability.py index 9beb8445a63..18822a65478 100644 --- a/weave/tests/legacy/test_mappability.py +++ b/weave/tests/legacy/test_mappability.py @@ -2,8 +2,8 @@ from weave.legacy import context_state as _context from weave.legacy import graph -from ... import registry_mem from ... import weave_types as types +from ...legacy import registry_mem from ...weave_internal import make_const_node _loading_builtins_token = _context.set_loading_built_ins() diff --git a/weave/tests/legacy/test_op_behaviors.py b/weave/tests/legacy/test_op_behaviors.py index 263f8541647..e49ff51c9c1 100644 --- a/weave/tests/legacy/test_op_behaviors.py +++ b/weave/tests/legacy/test_op_behaviors.py @@ -25,7 +25,8 @@ TaggedValueType, ) -from ... import registry_mem, storage, weave_internal +from ... import storage, weave_internal +from ...legacy import registry_mem from ..concrete_tagged_value import ( TaggedValue, concrete_from_tagstore, diff --git a/weave/tests/legacy/test_op_coverage.py b/weave/tests/legacy/test_op_coverage.py index 2eadbe3c55d..cede44a1109 100644 --- a/weave/tests/legacy/test_op_coverage.py +++ b/weave/tests/legacy/test_op_coverage.py @@ -1,4 +1,4 @@ -from ... import registry_mem +from ...legacy import registry_mem def make_error_message(missing_ops, section_name): diff --git a/weave/tests/legacy/test_op_serialization.py b/weave/tests/legacy/test_op_serialization.py index 66ad75c99d5..7c08a59b982 100644 --- a/weave/tests/legacy/test_op_serialization.py +++ b/weave/tests/legacy/test_op_serialization.py @@ -1,8 +1,9 @@ import pytest import weave +import weave.legacy -ops = weave.registry_mem.memory_registry.list_ops() +ops = weave.legacy.registry_mem.memory_registry.list_ops() def output_type_dict_is_const_function_node(output_type_dict): diff --git a/weave/tests/legacy/test_serialize.py b/weave/tests/legacy/test_serialize.py index 85b34ced7f9..3ce4594856f 100644 --- a/weave/tests/legacy/test_serialize.py +++ b/weave/tests/legacy/test_serialize.py @@ -2,9 +2,9 @@ import weave from weave import query_api as api -from weave import registry_mem, weave_internal +from weave import weave_internal from weave import weave_types as types -from weave.legacy import graph, op_args, ops, serialize +from weave.legacy import graph, op_args, ops, registry_mem, serialize from weave.legacy.ops_primitives import list_ from weave.weave_internal import make_const_node diff --git a/weave/tests/legacy/test_wb_domain_ops.py b/weave/tests/legacy/test_wb_domain_ops.py index ec2d5bb74bd..5674b65204e 100644 --- a/weave/tests/legacy/test_wb_domain_ops.py +++ b/weave/tests/legacy/test_wb_domain_ops.py @@ -9,7 +9,7 @@ from weave.legacy.ops_domain import wb_domain_types from weave.legacy.ops_primitives import _dict_utils -from ... import registry_mem +from ...legacy import registry_mem from .. import fixture_fakewandb as fwb """ diff --git a/weave/weave_internal.py b/weave/weave_internal.py index 68a7edbe53c..2b6e07b294b 100644 --- a/weave/weave_internal.py +++ b/weave/weave_internal.py @@ -150,7 +150,7 @@ def define_fn( # and the function doesn't explicitly operate on tagged values. this ensures that the input tags # are propagated appropriately to the output type of the function. def refine_graph(node: graph.Node) -> graph.Node: - from .registry_mem import memory_registry + from .legacy.registry_mem import memory_registry if isinstance(node, (graph.ConstNode, graph.VoidNode, graph.VarNode)): return node diff --git a/weave/weave_server.py b/weave/weave_server.py index db96977c0a4..461fe55989d 100644 --- a/weave/weave_server.py +++ b/weave/weave_server.py @@ -31,12 +31,18 @@ errors, filesystem, logs, - registry_mem, server, storage, util, ) -from weave.legacy import context_state, graph, value_or_error, wandb_api, weavejs_fixes +from weave.legacy import ( + context_state, + graph, + registry_mem, + value_or_error, + wandb_api, + weavejs_fixes, +) from weave.legacy.language_features.tagging import tag_store from weave.server_error_handling import client_safe_http_exceptions_as_werkzeug From 4bf0b5c932e5b2727ae0d7e644953eb47f483010 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Thu, 22 Aug 2024 22:59:52 -0400 Subject: [PATCH 22/84] move to legacy: weave_types --- weave/{ => legacy}/weave_pydantic.py | 4 ++-- weave/serve_fastapi.py | 3 ++- weave/weave_types.py | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) rename weave/{ => legacy}/weave_pydantic.py (93%) diff --git a/weave/weave_pydantic.py b/weave/legacy/weave_pydantic.py similarity index 93% rename from weave/weave_pydantic.py rename to weave/legacy/weave_pydantic.py index 19d200ad2fd..086feb8d2fa 100644 --- a/weave/weave_pydantic.py +++ b/weave/legacy/weave_pydantic.py @@ -1,7 +1,7 @@ from pydantic import BaseModel, create_model -from . import weave_types as types -from .legacy import infer_types +from .. import weave_types as types +from . import infer_types def weave_type_to_pydantic( diff --git a/weave/serve_fastapi.py b/weave/serve_fastapi.py index d6b23431349..ca63901d03b 100644 --- a/weave/serve_fastapi.py +++ b/weave/serve_fastapi.py @@ -17,7 +17,8 @@ from weave.trace.op import Op from weave.trace.refs import ObjectRef -from . import errors, weave_pydantic +from . import errors +from .legacy import weave_pydantic key_cache: cache.LruTimeWindowCache[str, typing.Optional[bool]] = ( cache.LruTimeWindowCache(datetime.timedelta(minutes=5)) diff --git a/weave/weave_types.py b/weave/weave_types.py index 990ec2586a8..bee5df4bd11 100644 --- a/weave/weave_types.py +++ b/weave/weave_types.py @@ -1057,7 +1057,7 @@ def property_types(self) -> dict[str, Type]: @classmethod def typeclass_of_class(cls, check_class): - from . import weave_pydantic + from .legacy import weave_pydantic if not issubclass(check_class, pydantic.BaseModel): return cls From c22b2fc366a2022c2fa143bbccdd7013559e07f8 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Thu, 22 Aug 2024 23:34:23 -0400 Subject: [PATCH 23/84] move to legacy: parallelism --- weave/legacy/derive_op.py | 2 +- weave/legacy/execute.py | 2 +- weave/{ => legacy}/parallelism.py | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename weave/{ => legacy}/parallelism.py (100%) diff --git a/weave/legacy/derive_op.py b/weave/legacy/derive_op.py index 337bb66cccd..255fe7c89aa 100644 --- a/weave/legacy/derive_op.py +++ b/weave/legacy/derive_op.py @@ -8,12 +8,12 @@ from weave import ( errors, - parallelism, storage, weave_internal, ) from weave import weave_types as types from weave.legacy import ( + parallelism, registry_mem, box, context_state, diff --git a/weave/legacy/execute.py b/weave/legacy/execute.py index ccd0d67f101..20937630e3e 100644 --- a/weave/legacy/execute.py +++ b/weave/legacy/execute.py @@ -13,7 +13,6 @@ engine_trace, environment, errors, - parallelism, ref_base, trace_local, ) @@ -26,6 +25,7 @@ # Trace / cache # Language Features from weave.legacy import ( + parallelism, registry_mem, box, compile, diff --git a/weave/parallelism.py b/weave/legacy/parallelism.py similarity index 100% rename from weave/parallelism.py rename to weave/legacy/parallelism.py From c52c644163cc11c2aae588bfb1743cb52ed2280b Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 01:21:34 -0400 Subject: [PATCH 24/84] move to legacy: server_error_handling --- weave/legacy/io_service.py | 2 +- weave/{ => legacy}/server_error_handling.py | 2 +- weave/weave_http.py | 2 +- weave/weave_server.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename weave/{ => legacy}/server_error_handling.py (99%) diff --git a/weave/legacy/io_service.py b/weave/legacy/io_service.py index 50502c700e4..a5e0c37f554 100644 --- a/weave/legacy/io_service.py +++ b/weave/legacy/io_service.py @@ -26,10 +26,10 @@ engine_trace, errors, filesystem, - server_error_handling, weave_http, ) from weave.legacy import ( + server_error_handling, artifact_wandb, async_queue, cache, diff --git a/weave/server_error_handling.py b/weave/legacy/server_error_handling.py similarity index 99% rename from weave/server_error_handling.py rename to weave/legacy/server_error_handling.py index 35f20ab7852..bdc5a46ee2b 100644 --- a/weave/server_error_handling.py +++ b/weave/legacy/server_error_handling.py @@ -27,7 +27,7 @@ from werkzeug import exceptions as werkzeug_exceptions from werkzeug import http as werkzeug_http -from . import errors, util +from .. import errors, util class WeaveInternalHttpException(werkzeug_exceptions.HTTPException): diff --git a/weave/weave_http.py b/weave/weave_http.py index 43e1d96116b..8d35a00b5c0 100644 --- a/weave/weave_http.py +++ b/weave/weave_http.py @@ -13,7 +13,7 @@ import requests.auth import yarl -from weave import server_error_handling +from weave.legacy import server_error_handling from . import engine_trace, filesystem diff --git a/weave/weave_server.py b/weave/weave_server.py index 461fe55989d..4ec00b16358 100644 --- a/weave/weave_server.py +++ b/weave/weave_server.py @@ -44,7 +44,7 @@ weavejs_fixes, ) from weave.legacy.language_features.tagging import tag_store -from weave.server_error_handling import client_safe_http_exceptions_as_werkzeug +from weave.legacy.server_error_handling import client_safe_http_exceptions_as_werkzeug logger = logging.getLogger(__name__) From 4bd456136f06c9d7f76089856226ee0bd8ac6042 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 01:24:51 -0400 Subject: [PATCH 25/84] move to legacy: engine_trace --- weave/filesystem.py | 4 +- weave/legacy/arrow/concat.py | 2 +- weave/legacy/artifact_wandb.py | 2 +- weave/legacy/cache.py | 4 +- weave/legacy/compile.py | 2 +- weave/{ => legacy}/engine_trace.py | 110 +++++++++--------- weave/legacy/execute.py | 2 +- weave/legacy/execute_fast.py | 2 +- weave/legacy/io_service.py | 2 +- .../language_features/tagging/tag_store.py | 4 +- weave/legacy/memo.py | 2 +- weave/legacy/op_def.py | 2 +- weave/legacy/ops_arrow/list_join.py | 2 +- .../run_history/history_op_common.py | 2 +- .../run_history/run_history_v1_legacy_ops.py | 2 +- .../run_history_v2_parquet_media.py | 2 +- ...run_history_v3_parquet_stream_optimized.py | 3 +- weave/legacy/ops_domain/run_ops.py | 2 +- weave/legacy/ops_domain/table.py | 3 +- weave/legacy/ops_domain/wbgqlquery_op.py | 4 +- weave/legacy/ops_domain/wbmedia.py | 4 +- weave/legacy/wandb_api.py | 4 +- weave/legacy/wandb_file_manager.py | 4 +- .../wandb_interface/wandb_artifact_pusher.py | 2 +- .../legacy/wandb_interface/wandb_lite_run.py | 4 +- weave/server.py | 3 +- weave/test_scripts/wandb_artifact_perf.py | 3 +- weave/weave_http.py | 4 +- weave/weave_server.py | 2 +- 29 files changed, 96 insertions(+), 92 deletions(-) rename weave/{ => legacy}/engine_trace.py (77%) diff --git a/weave/filesystem.py b/weave/filesystem.py index a3710b35165..8af0aac9bbb 100644 --- a/weave/filesystem.py +++ b/weave/filesystem.py @@ -20,9 +20,9 @@ from aiofiles.threadpool import binary as aiofiles_binary from aiofiles.threadpool import text as aiofiles_text -from weave.legacy import cache +from weave.legacy import cache, engine_trace -from . import engine_trace, environment, errors, util +from . import environment, errors, util tracer = engine_trace.tracer() # type: ignore async_utime = aiofiles_os.wrap(os.utime) # type: ignore diff --git a/weave/legacy/arrow/concat.py b/weave/legacy/arrow/concat.py index a22c5daf766..28198c3d339 100644 --- a/weave/legacy/arrow/concat.py +++ b/weave/legacy/arrow/concat.py @@ -30,7 +30,7 @@ DEBUG = False -from weave import engine_trace +from weave.legacy import engine_trace tracer = engine_trace.tracer() diff --git a/weave/legacy/artifact_wandb.py b/weave/legacy/artifact_wandb.py index 527d3c3c3ab..5a1378b8159 100644 --- a/weave/legacy/artifact_wandb.py +++ b/weave/legacy/artifact_wandb.py @@ -14,7 +14,6 @@ from wandb.sdk.lib.hashutil import b64_to_hex_id, hex_to_b64_id from weave import ( - engine_trace, errors, filesystem, urls, @@ -22,6 +21,7 @@ ) from weave import weave_types as types from weave.legacy import ( + engine_trace, artifact_fs, eager, file_base, diff --git a/weave/legacy/cache.py b/weave/legacy/cache.py index 2faefdde5bb..0bee0170fd3 100644 --- a/weave/legacy/cache.py +++ b/weave/legacy/cache.py @@ -6,8 +6,8 @@ import time import typing -from weave import engine_trace, environment, errors -from weave.legacy import context_state, wandb_api +from weave import environment, errors +from weave.legacy import context_state, wandb_api, engine_trace statsd = engine_trace.statsd() # type: ignore logger = logging.getLogger("root") diff --git a/weave/legacy/compile.py b/weave/legacy/compile.py index 30cbdf4d98f..eeec391beed 100644 --- a/weave/legacy/compile.py +++ b/weave/legacy/compile.py @@ -6,12 +6,12 @@ import typing from weave import ( - engine_trace, errors, weave_internal, ) from weave import weave_types as types from weave.legacy import ( + engine_trace, box, compile_domain, compile_table, diff --git a/weave/engine_trace.py b/weave/legacy/engine_trace.py similarity index 77% rename from weave/engine_trace.py rename to weave/legacy/engine_trace.py index 7423b8048ca..6a9284a2932 100644 --- a/weave/engine_trace.py +++ b/weave/legacy/engine_trace.py @@ -18,66 +18,66 @@ import time import typing -from . import environment, logs -from .legacy import stream_data_interfaces +from .. import environment, logs +from . import stream_data_interfaces # Thanks co-pilot! class DummySpan: - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs): # type: ignore self.args = args self.log_indent_token = None - def __enter__(self): + def __enter__(self): # type: ignore logging.debug("-> %s", self.args[0]) self.log_indent_token = logs.increment_indent() return self - def __exit__(self, *args, **kwargs): + def __exit__(self, *args, **kwargs): # type: ignore logs.reset_indent(self.log_indent_token) logging.debug("<- %s", self.args[0]) - def set_tag(self, key, unredacted_val, redacted_val=None): + def set_tag(self, key, unredacted_val, redacted_val=None): # type: ignore pass - def set_meta(self, *args, **kwargs): + def set_meta(self, *args, **kwargs): # type: ignore pass - def set_metric(self, *args, **kwargs): + def set_metric(self, *args, **kwargs): # type: ignore pass - def finish(self, *args, **kwargs): + def finish(self, *args, **kwargs): # type: ignore pass class TraceContext: - def __getstate__(self) -> dict: + def __getstate__(self) -> dict: # type: ignore return {} - def __setstate__(self, state: dict) -> None: + def __setstate__(self, state: dict) -> None: # type: ignore pass class ContextProvider: - def activate(self, context: TraceContext) -> None: + def activate(self, context: TraceContext) -> None: # type: ignore pass class DummyTrace: - def trace(self, *args, **kwargs): + def trace(self, *args, **kwargs): # type: ignore return DummySpan(*args) @property - def context_provider(self) -> ContextProvider: + def context_provider(self) -> ContextProvider: # type: ignore return ContextProvider() - def current_trace_context(self) -> typing.Optional[TraceContext]: + def current_trace_context(self) -> typing.Optional[TraceContext]: # type: ignore return None - def current_span(self): - return None + def current_span(self): # type: ignore + return None - def current_root_span(self): + def current_root_span(self): # type: ignore return None @@ -89,7 +89,7 @@ def current_root_span(self): _weave_trace_stream = None -def weave_trace_stream(): +def weave_trace_stream(): # type: ignore global _weave_trace_stream if _weave_trace_stream is None: from weave.legacy.wandb_interface.wandb_stream_table import StreamTable @@ -98,25 +98,25 @@ def weave_trace_stream(): return _weave_trace_stream -def span_count(span): +def span_count(span): # type: ignore if span.child_spans is None: return 1 return 1 + sum([span_count(child) for child in span.child_spans]) class WeaveTraceSpan: - def __init__(self, name): - from .legacy.ops_domain import trace_tree + def __init__(self, name): # type: ignore + from .ops_domain import trace_tree self.log_indent_token = None self._token = None self.span = trace_tree.Span(_name=name) self._parent = None - def total_span_count(self): + def total_span_count(self): # type: ignore return span_count(self.span) - def __enter__(self): + def __enter__(self): # type: ignore parent = _weave_trace_span.get() if parent is not None: if parent.span.child_spans is None: @@ -128,11 +128,11 @@ def __enter__(self): self.span.start_time_ms = int(time.time() * 1000) return self - def __exit__(self, *args, **kwargs): + def __exit__(self, *args, **kwargs): # type: ignore self.span.end_time_ms = int(time.time() * 1000) _weave_trace_span.reset(self._token) - from .legacy.ops_domain import trace_tree + from .ops_domain import trace_tree tt = trace_tree.WBTraceTree(json.dumps(dataclasses.asdict(self.span))) tags = self.attributes.get("tags", {}) @@ -147,12 +147,12 @@ def __exit__(self, *args, **kwargs): ) @property - def attributes(self): + def attributes(self): # type: ignore if self.span.attributes is None: self.span.attributes = {} return self.span.attributes - def set_tag(self, key, unredacted_val, redacted_val=None): + def set_tag(self, key, unredacted_val, redacted_val=None): # type: ignore if "tags" not in self.attributes: self.attributes["tags"] = {} if not environment.disable_weave_pii(): @@ -160,7 +160,7 @@ def set_tag(self, key, unredacted_val, redacted_val=None): elif redacted_val is not None: self.attributes["tags"][key] = redacted_val - def set_meta(self, key, unredacted_val, redacted_val=None): + def set_meta(self, key, unredacted_val, redacted_val=None): # type: ignore if "metadata" not in self.attributes: self.attributes["metadata"] = {} if not environment.disable_weave_pii(): @@ -168,7 +168,7 @@ def set_meta(self, key, unredacted_val, redacted_val=None): elif redacted_val is not None: self.attributes["metadata"][key] = redacted_val - def set_metric(self, key, unredacted_val, redacted_val=None): + def set_metric(self, key, unredacted_val, redacted_val=None): # type: ignore if "metrics" not in self.attributes: self.attributes["metrics"] = {} if not environment.disable_weave_pii(): @@ -176,15 +176,15 @@ def set_metric(self, key, unredacted_val, redacted_val=None): elif redacted_val is not None: self.attributes["metrics"][key] = redacted_val - def finish(self, *args, **kwargs): + def finish(self, *args, **kwargs): # type: ignore pass class WeaveTrace: - def __init__(self): + def __init__(self): # type: ignore self._stream_table = None - def trace(self, name, *args, **kwargs): + def trace(self, name, *args, **kwargs): # type: ignore return WeaveTraceSpan(name, *args) @property @@ -194,17 +194,17 @@ def context_provider(self) -> ContextProvider: def current_trace_context(self) -> typing.Optional[TraceContext]: return None - def current_span(self): + def current_span(self): # type: ignore return _weave_trace_span.get() - def current_root_span(self): + def current_root_span(self): # type: ignore cur_span = _weave_trace_span.get() while cur_span is not None and cur_span._parent is not None: cur_span = cur_span._parent return cur_span -def dd_span_to_weave_span(dd_span) -> stream_data_interfaces.TraceSpanDict: +def dd_span_to_weave_span(dd_span) -> stream_data_interfaces.TraceSpanDict: # type: ignore # Use '' for None, currently history2 doesn't read None columns from # the liveset correctly. parent_id = "" @@ -227,7 +227,7 @@ def dd_span_to_weave_span(dd_span) -> stream_data_interfaces.TraceSpanDict: } -def send_proc(queue): +def send_proc(queue): # type: ignore while True: spans = queue.get() if spans is None: @@ -244,35 +244,35 @@ def send_proc(queue): # by datadog, so we have some kind of re-entrancy/deadlock. Putting in a separate # process fixes. class WeaveWriter: - def __init__(self, orig_writer): + def __init__(self, orig_writer): # type: ignore self._orig_writer = orig_writer self._queue = multiprocessing.Queue() self._proc = multiprocessing.Process( target=send_proc, args=(self._queue,), daemon=True ) - def recreate(self): + def recreate(self): # type: ignore return WeaveWriter(self._orig_writer.recreate()) - def stop(self, timeout=None): + def stop(self, timeout=None): # type: ignore self._orig_writer.stop(timeout) - def _ensure_started(self): + def _ensure_started(self): # type: ignore if not self._proc.is_alive(): self._proc.start() - def write(self, spans): + def write(self, spans): # type: ignore if len(spans) == 1: return self._ensure_started() self._queue.put([dd_span_to_weave_span(s) for s in spans]) self._orig_writer.write(spans) - def flush_queue(self): + def flush_queue(self): # type: ignore self._orig_writer.flush_queue() -def patch_ddtrace_set_tag(): +def patch_ddtrace_set_tag(): # type: ignore from inspect import signature from ddtrace import span as ddtrace_span @@ -285,7 +285,7 @@ def patch_ddtrace_set_tag(): old_set_metric = ddtrace_span.Span.set_metric # Only logged redacted values if flag is on - def set_tag(self, key, unredacted_val=None, redacted_val=None): + def set_tag(self, key, unredacted_val=None, redacted_val=None): # type: ignore if redacted_val is not None and environment.disable_weave_pii(): old_set_tag(self, key, redacted_val) elif ( @@ -296,7 +296,7 @@ def set_tag(self, key, unredacted_val=None, redacted_val=None): old_set_tag(self, key, unredacted_val) # Log metric if flag is off or if flag is on and redacted - def set_metric(self, key, val, is_pii_redacted=False): + def set_metric(self, key, val, is_pii_redacted=False): # type: ignore if not environment.disable_weave_pii() or is_pii_redacted or "_dd." in key: old_set_metric(self, key, val) @@ -304,7 +304,7 @@ def set_metric(self, key, val, is_pii_redacted=False): ddtrace_span.Span.set_tag = set_tag -def tracer(): +def tracer(): # type: ignore if os.getenv("DD_ENV"): from ddtrace import tracer as ddtrace_tracer @@ -340,26 +340,26 @@ def new_trace_context() -> typing.Optional[TraceContext]: class DummyStatsd: - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs): # type: ignore pass - def increment(self, *args, **kwargs): + def increment(self, *args, **kwargs): # type: ignore pass - def decrement(self, *args, **kwargs): + def decrement(self, *args, **kwargs): # type: ignore pass - def gauge(self, *args, **kwargs): + def gauge(self, *args, **kwargs): # type: ignore pass - def flush(self, *args, **kwargs): + def flush(self, *args, **kwargs): # type: ignore pass _STATSD = None -def _initialize_statsd(): +def _initialize_statsd(): # type: ignore if os.getenv("DD_ENV"): from datadog import initialize, statsd @@ -369,7 +369,7 @@ def _initialize_statsd(): return DummyStatsd() -def statsd(): +def statsd(): # type: ignore global _STATSD if _STATSD is None: _STATSD = _initialize_statsd() @@ -377,5 +377,5 @@ def statsd(): return _STATSD -def datadog_is_enabled(): +def datadog_is_enabled(): # type: ignore return os.getenv("DD_ENV") diff --git a/weave/legacy/execute.py b/weave/legacy/execute.py index 20937630e3e..23176f1aaeb 100644 --- a/weave/legacy/execute.py +++ b/weave/legacy/execute.py @@ -10,7 +10,6 @@ from collections.abc import Mapping from weave import ( - engine_trace, environment, errors, ref_base, @@ -25,6 +24,7 @@ # Trace / cache # Language Features from weave.legacy import ( + engine_trace, parallelism, registry_mem, box, diff --git a/weave/legacy/execute_fast.py b/weave/legacy/execute_fast.py index dbf15feeadd..91a8e640b5b 100644 --- a/weave/legacy/execute_fast.py +++ b/weave/legacy/execute_fast.py @@ -1,13 +1,13 @@ import logging from weave import ( - engine_trace, errors, ref_base, weave_internal, ) from weave import weave_types as types from weave.legacy import ( + engine_trace, registry_mem, box, compile, diff --git a/weave/legacy/io_service.py b/weave/legacy/io_service.py index a5e0c37f554..4ef61c6218c 100644 --- a/weave/legacy/io_service.py +++ b/weave/legacy/io_service.py @@ -23,12 +23,12 @@ import aioprocessing from weave import ( - engine_trace, errors, filesystem, weave_http, ) from weave.legacy import ( + engine_trace, server_error_handling, artifact_wandb, async_queue, diff --git a/weave/legacy/language_features/tagging/tag_store.py b/weave/legacy/language_features/tagging/tag_store.py index 9a497cb5b4c..85a4c98de9f 100644 --- a/weave/legacy/language_features/tagging/tag_store.py +++ b/weave/legacy/language_features/tagging/tag_store.py @@ -22,9 +22,9 @@ from collections import defaultdict from contextlib import contextmanager -from weave import engine_trace, errors +from weave import errors from weave import weave_types as types -from weave.legacy import box +from weave.legacy import engine_trace, box statsd = engine_trace.statsd() # type: ignore diff --git a/weave/legacy/memo.py b/weave/legacy/memo.py index d18b3f2efd7..4928bb9b062 100644 --- a/weave/legacy/memo.py +++ b/weave/legacy/memo.py @@ -2,7 +2,7 @@ import contextvars import typing -from .. import engine_trace +from weave.legacy import engine_trace statsd = engine_trace.statsd() # type: ignore diff --git a/weave/legacy/op_def.py b/weave/legacy/op_def.py index 78d697e4e3c..0dba3ed28e3 100644 --- a/weave/legacy/op_def.py +++ b/weave/legacy/op_def.py @@ -7,13 +7,13 @@ from typing import Iterator, Sequence from weave import ( - engine_trace, errors, weave_internal, ) from weave import weave_types as types from weave.legacy import ( context_state, + engine_trace, graph, language_autocall, memo, diff --git a/weave/legacy/ops_arrow/list_join.py b/weave/legacy/ops_arrow/list_join.py index 270ca1c0a1d..6c7c34f7f1d 100644 --- a/weave/legacy/ops_arrow/list_join.py +++ b/weave/legacy/ops_arrow/list_join.py @@ -4,7 +4,7 @@ import pyarrow as pa import pyarrow.compute as pc -from weave import engine_trace +from weave.legacy import engine_trace from weave import weave_types as types from weave.query_api import op from weave.legacy import graph diff --git a/weave/legacy/ops_domain/run_history/history_op_common.py b/weave/legacy/ops_domain/run_history/history_op_common.py index 72d945d39f0..00821ae4d6f 100644 --- a/weave/legacy/ops_domain/run_history/history_op_common.py +++ b/weave/legacy/ops_domain/run_history/history_op_common.py @@ -5,13 +5,13 @@ from pyarrow import parquet as pq from weave import ( - engine_trace, errors, util, ) from weave import weave_types as types from weave.query_api import use from weave.legacy import ( + engine_trace, registry_mem, _dict_utils, artifact_base, diff --git a/weave/legacy/ops_domain/run_history/run_history_v1_legacy_ops.py b/weave/legacy/ops_domain/run_history/run_history_v1_legacy_ops.py index 14615652067..0b8e97f8787 100644 --- a/weave/legacy/ops_domain/run_history/run_history_v1_legacy_ops.py +++ b/weave/legacy/ops_domain/run_history/run_history_v1_legacy_ops.py @@ -2,7 +2,7 @@ import pyarrow as pa -from weave import engine_trace +from weave.legacy import engine_trace from weave import weave_types as types from weave.query_api import op from weave.legacy import gql_json_cache diff --git a/weave/legacy/ops_domain/run_history/run_history_v2_parquet_media.py b/weave/legacy/ops_domain/run_history/run_history_v2_parquet_media.py index f7f4c21db26..24afe60b728 100644 --- a/weave/legacy/ops_domain/run_history/run_history_v2_parquet_media.py +++ b/weave/legacy/ops_domain/run_history/run_history_v2_parquet_media.py @@ -6,7 +6,7 @@ import pyarrow as pa -from weave import engine_trace +from weave.legacy import engine_trace from weave import weave_types as types from weave.query_api import op, use from weave.legacy import artifact_mem, gql_json_cache diff --git a/weave/legacy/ops_domain/run_history/run_history_v3_parquet_stream_optimized.py b/weave/legacy/ops_domain/run_history/run_history_v3_parquet_stream_optimized.py index 3a767cce087..0412c764fdd 100644 --- a/weave/legacy/ops_domain/run_history/run_history_v3_parquet_stream_optimized.py +++ b/weave/legacy/ops_domain/run_history/run_history_v3_parquet_stream_optimized.py @@ -5,10 +5,11 @@ import pyarrow as pa -from weave import engine_trace, errors +from weave import errors from weave import weave_types as types from weave.query_api import op from weave.legacy import ( + engine_trace, artifact_base, artifact_fs, artifact_mem, diff --git a/weave/legacy/ops_domain/run_ops.py b/weave/legacy/ops_domain/run_ops.py index a9cd9df908c..1699c8d4e0b 100644 --- a/weave/legacy/ops_domain/run_ops.py +++ b/weave/legacy/ops_domain/run_ops.py @@ -37,7 +37,7 @@ import json import typing -from weave import engine_trace +from weave.legacy import engine_trace from weave import weave_types as types from weave.query_api import op from weave.legacy import compile_table diff --git a/weave/legacy/ops_domain/table.py b/weave/legacy/ops_domain/table.py index 651929a7f2e..d7c6b72e146 100644 --- a/weave/legacy/ops_domain/table.py +++ b/weave/legacy/ops_domain/table.py @@ -5,7 +5,7 @@ import logging import typing -from weave import engine_trace, errors, util, weave_internal +from weave import errors, util, weave_internal from weave import weave_types as types from weave.query_api import op, weave_class from weave.legacy import ( @@ -14,6 +14,7 @@ io_service, ops_arrow, wandb_util, + engine_trace, ) from weave.legacy import timestamp as weave_timestamp from weave.legacy.ops_domain import trace_tree, wbmedia diff --git a/weave/legacy/ops_domain/wbgqlquery_op.py b/weave/legacy/ops_domain/wbgqlquery_op.py index 1b78af45ae3..24dc73e3f8b 100644 --- a/weave/legacy/ops_domain/wbgqlquery_op.py +++ b/weave/legacy/ops_domain/wbgqlquery_op.py @@ -1,10 +1,10 @@ import logging import typing -from weave import engine_trace, environment, errors +from weave import environment, errors from weave import weave_types as types from weave.query_api import op -from weave.legacy import mappers_gql, partial_object +from weave.legacy import engine_trace, mappers_gql, partial_object from weave.legacy.language_features.tagging import tagged_value_type from weave.legacy.ops_domain import wb_domain_types as wdt from weave.legacy.wandb_client_api import wandb_gql_query diff --git a/weave/legacy/ops_domain/wbmedia.py b/weave/legacy/ops_domain/wbmedia.py index 20cccd808bd..34674731e97 100644 --- a/weave/legacy/ops_domain/wbmedia.py +++ b/weave/legacy/ops_domain/wbmedia.py @@ -5,8 +5,8 @@ import typing from weave import query_api as weave -from weave import engine_trace, errors, types -from weave.legacy import artifact_fs, file_base +from weave import errors, types +from weave.legacy import engine_trace, artifact_fs, file_base from weave.legacy.language_features.tagging.tag_store import isolated_tagging_context from weave.legacy.ops_primitives import html, markdown diff --git a/weave/legacy/wandb_api.py b/weave/legacy/wandb_api.py index cc26c0f7e66..b551538a6ae 100644 --- a/weave/legacy/wandb_api.py +++ b/weave/legacy/wandb_api.py @@ -14,9 +14,9 @@ from gql.transport.requests import RequestsHTTPTransport from requests.auth import HTTPBasicAuth -from weave import engine_trace, errors +from weave import errors from weave import environment as weave_env -from weave.legacy import wandb_client_api +from weave.legacy import wandb_client_api, engine_trace # Importing at the top-level namespace so other files can import from here. from weave.legacy.context_state import WandbApiContext, _wandb_api_context diff --git a/weave/legacy/wandb_file_manager.py b/weave/legacy/wandb_file_manager.py index d3868c29e8f..21c29a064af 100644 --- a/weave/legacy/wandb_file_manager.py +++ b/weave/legacy/wandb_file_manager.py @@ -12,9 +12,9 @@ from requests.auth import HTTPBasicAuth from wandb.sdk.lib import hashutil -from weave import engine_trace, errors, filesystem, weave_http +from weave import errors, filesystem, weave_http from weave import environment as weave_env -from weave.legacy import artifact_wandb, cache, wandb_api +from weave.legacy import artifact_wandb, cache, wandb_api, engine_trace tracer = engine_trace.tracer() # type: ignore diff --git a/weave/legacy/wandb_interface/wandb_artifact_pusher.py b/weave/legacy/wandb_interface/wandb_artifact_pusher.py index 8befef2c4e6..fa80c077c16 100644 --- a/weave/legacy/wandb_interface/wandb_artifact_pusher.py +++ b/weave/legacy/wandb_interface/wandb_artifact_pusher.py @@ -5,7 +5,7 @@ from wandb import Artifact from wandb.apis.public import api as wb_public -from weave import engine_trace +from weave.legacy import engine_trace from weave.legacy import wandb_client_api from weave.legacy.wandb_interface.wandb_lite_run import InMemoryLazyLiteRun diff --git a/weave/legacy/wandb_interface/wandb_lite_run.py b/weave/legacy/wandb_interface/wandb_lite_run.py index 4f565c527c2..95fa4c8e3f0 100644 --- a/weave/legacy/wandb_interface/wandb_lite_run.py +++ b/weave/legacy/wandb_interface/wandb_lite_run.py @@ -15,8 +15,8 @@ from wandb.sdk.internal.sender import _manifest_json_from_proto from wandb.sdk.lib import runid -from weave import engine_trace, errors -from weave.legacy import wandb_client_api +from weave import errors +from weave.legacy import engine_trace, wandb_client_api logger = logging.getLogger(__name__) diff --git a/weave/server.py b/weave/server.py index d620ef5167e..0792737639a 100644 --- a/weave/server.py +++ b/weave/server.py @@ -15,6 +15,7 @@ from weave.legacy import ( cache, context, + engine_trace, execute, gql_json_cache, graph, @@ -25,7 +26,7 @@ from weave.legacy.language_features.tagging import tag_store from weave.legacy.language_features.tagging.tag_store import isolated_tagging_context -from . import engine_trace, logs, storage, util, weave_types +from . import logs, storage, util, weave_types # A function to monkeypatch the request post method # def patch_request_post(): diff --git a/weave/test_scripts/wandb_artifact_perf.py b/weave/test_scripts/wandb_artifact_perf.py index 7452832dff3..0ba0b420b0a 100644 --- a/weave/test_scripts/wandb_artifact_perf.py +++ b/weave/test_scripts/wandb_artifact_perf.py @@ -16,11 +16,12 @@ from weave.legacy import ( artifact_wandb, async_map, + engine_trace, wandb_api, wandb_file_manager, ) -from .. import engine_trace, filesystem, weave_http +from .. import filesystem, weave_http tracer = engine_trace.tracer() # type: ignore diff --git a/weave/weave_http.py b/weave/weave_http.py index 8d35a00b5c0..075693b8edf 100644 --- a/weave/weave_http.py +++ b/weave/weave_http.py @@ -13,9 +13,9 @@ import requests.auth import yarl -from weave.legacy import server_error_handling +from weave.legacy import engine_trace, server_error_handling -from . import engine_trace, filesystem +from . import filesystem logging.getLogger("aiohttp.access").setLevel(logging.WARNING) logging.getLogger("aiohttp.client").setLevel(logging.WARNING) diff --git a/weave/weave_server.py b/weave/weave_server.py index 4ec00b16358..b9992991850 100644 --- a/weave/weave_server.py +++ b/weave/weave_server.py @@ -26,7 +26,6 @@ from werkzeug.exceptions import HTTPException from weave import ( - engine_trace, environment, errors, filesystem, @@ -37,6 +36,7 @@ ) from weave.legacy import ( context_state, + engine_trace, graph, registry_mem, value_or_error, From 4f07e89e00edf2fc68a59fe61625058885d96486 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 01:31:28 -0400 Subject: [PATCH 26/84] move to legacy: trace_local.py --- weave/legacy/execute.py | 2 +- weave/{ => legacy}/trace_local.py | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) rename weave/{ => legacy}/trace_local.py (92%) diff --git a/weave/legacy/execute.py b/weave/legacy/execute.py index 23176f1aaeb..916d9646f82 100644 --- a/weave/legacy/execute.py +++ b/weave/legacy/execute.py @@ -13,7 +13,6 @@ environment, errors, ref_base, - trace_local, ) from weave import weave_types as types @@ -41,6 +40,7 @@ op_def, op_execute, op_policy, + trace_local, value_or_error, wandb_api, ) diff --git a/weave/trace_local.py b/weave/legacy/trace_local.py similarity index 92% rename from weave/trace_local.py rename to weave/legacy/trace_local.py index 71b8dc32b9c..bc1376d5e35 100644 --- a/weave/trace_local.py +++ b/weave/legacy/trace_local.py @@ -7,12 +7,12 @@ from weave.legacy import artifact_local, graph, op_def, op_policy, runs -from . import ( +from .. import ( ref_base, storage, weave_internal, ) -from . import weave_types as types +from .. import weave_types as types @dataclasses.dataclass @@ -21,7 +21,7 @@ class RunKey: id: str -def _value_id(val): +def _value_id(val): # type: ignore # Important, do not include the type here, as it can change. # This happens because you can have a ref to an item that's in a list. # The list's object_type can change as items are appended to it. @@ -44,7 +44,7 @@ def make_run_key( else: hashable_inputs = {} for name, obj in inputs_refs.items(): - hashable_inputs[name] = _value_id(obj) + hashable_inputs[name] = _value_id(obj) # type: ignore[no-untyped-call] hash_val = { "op_name": op_def.name, "op_version": op_def.version, @@ -89,7 +89,7 @@ def _single_run(self, run_key: RunKey) -> graph.Node[runs.Run]: types.RunType(), ) - def _run_table(self, run_key: RunKey): + def _run_table(self, run_key: RunKey): # type: ignore table_uri = artifact_local.WeaveLocalArtifactURI( f"run-{run_key.op_simple_name}", "latest", "obj" ) @@ -99,7 +99,7 @@ def _run_table(self, run_key: RunKey): types.List(types.RunType()), ) - def _should_save_to_table(self, run_key: RunKey): + def _should_save_to_table(self, run_key: RunKey): # type: ignore # Restricted to just a couple ops for now. # A NOTE: for the future, async ops definitely can't be saved to # table (until we have safe table writes) @@ -120,10 +120,10 @@ def get_run(self, run_key: RunKey) -> graph.Node[runs.Run]: def get_run_val(self, run_key: RunKey) -> typing.Optional[runs.Run]: from weave.legacy import execute_fast - res = execute_fast._execute_fn_no_engine(None, None, self.get_run(run_key)) + res = execute_fast._execute_fn_no_engine(None, None, self.get_run(run_key)) # type: ignore[no-untyped-call] return res - def save_run(self, run: runs.Run): + def save_run(self, run: runs.Run): # type: ignore from weave.legacy.ops_primitives import weave_api run_key = RunKey(run.op_name, run.id) @@ -132,7 +132,7 @@ def save_run(self, run: runs.Run): else: weave_api.set(self._single_run(run_key), run, {}) - def save_run_output(self, od: op_def.OpDef, run_key: RunKey, output: typing.Any): + def save_run_output(self, od: op_def.OpDef, run_key: RunKey, output: typing.Any): # type: ignore if not od.pure: # If an op is impure, its output is saved to a name that does not # include run ID. This means consuming pure runs will hit cache if From 741808425062a38b29293b3809f2848ceffcbd8f Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 08:14:25 -0400 Subject: [PATCH 27/84] move to legacy: ref_base --- weave/legacy/arrow/list_.py | 2 +- weave/legacy/artifact_base.py | 2 +- weave/legacy/artifact_fs.py | 4 ++-- weave/legacy/artifact_mem.py | 2 +- weave/legacy/execute.py | 2 +- weave/legacy/execute_fast.py | 2 +- weave/legacy/graph_mapper.py | 2 +- weave/legacy/mappers_arrow.py | 3 ++- weave/legacy/mappers_publisher.py | 3 ++- weave/legacy/mappers_python_def.py | 3 ++- weave/legacy/node_ref.py | 2 +- weave/legacy/object_context.py | 2 +- weave/legacy/ops_primitives/artifacts.py | 4 ++-- weave/legacy/ops_primitives/weave_api.py | 2 +- weave/{ => legacy}/ref_base.py | 11 +++++------ weave/legacy/show.py | 4 ++-- weave/legacy/trace_legacy.py | 2 +- weave/legacy/trace_local.py | 2 +- weave/legacy/uris.py | 2 +- weave/query_api.py | 2 +- weave/ref_util.py | 2 +- weave/storage.py | 3 ++- weave/tests/legacy/test_mutation2.py | 3 +-- weave/tests/trace/test_evaluate.py | 2 +- weave/tests/trace/test_weaveflow.py | 2 +- weave/trace/box.py | 2 +- weave/trace/weave_client.py | 2 +- weave/weave_types.py | 4 ++-- 28 files changed, 40 insertions(+), 38 deletions(-) rename weave/{ => legacy}/ref_base.py (96%) diff --git a/weave/legacy/arrow/list_.py b/weave/legacy/arrow/list_.py index 6db149220d5..f8a7f09bbb3 100644 --- a/weave/legacy/arrow/list_.py +++ b/weave/legacy/arrow/list_.py @@ -12,7 +12,6 @@ from weave import ( errors, - ref_base, ref_util, weave_internal, ) @@ -27,6 +26,7 @@ op_def, op_def_type, node_ref, + ref_base, ) from weave.legacy.arrow.arrow import ( ArrowWeaveListType, diff --git a/weave/legacy/artifact_base.py b/weave/legacy/artifact_base.py index 9e62e34fa83..02b2e35d213 100644 --- a/weave/legacy/artifact_base.py +++ b/weave/legacy/artifact_base.py @@ -8,7 +8,7 @@ import typing from weave import weave_types as types -from weave import ref_base +from weave.legacy import ref_base class Artifact: diff --git a/weave/legacy/artifact_fs.py b/weave/legacy/artifact_fs.py index b753b501974..f09e110e612 100644 --- a/weave/legacy/artifact_fs.py +++ b/weave/legacy/artifact_fs.py @@ -6,9 +6,9 @@ import os import typing -from weave import errors, ref_base, ref_util +from weave import errors, ref_util from weave import weave_types as types -from weave.legacy import artifact_base, file_base, object_context, uris +from weave.legacy import artifact_base, file_base, object_context, ref_base, uris from weave.legacy.language_features.tagging import tag_store if typing.TYPE_CHECKING: diff --git a/weave/legacy/artifact_mem.py b/weave/legacy/artifact_mem.py index 5e6f63f9159..58471d6460f 100644 --- a/weave/legacy/artifact_mem.py +++ b/weave/legacy/artifact_mem.py @@ -3,7 +3,7 @@ from . import artifact_base from weave import weave_types as types from weave import errors -from weave import ref_base +from weave.legacy import ref_base class MemArtifact(artifact_base.Artifact): diff --git a/weave/legacy/execute.py b/weave/legacy/execute.py index 916d9646f82..8c9bb02475e 100644 --- a/weave/legacy/execute.py +++ b/weave/legacy/execute.py @@ -12,7 +12,6 @@ from weave import ( environment, errors, - ref_base, ) from weave import weave_types as types @@ -25,6 +24,7 @@ from weave.legacy import ( engine_trace, parallelism, + ref_base, registry_mem, box, compile, diff --git a/weave/legacy/execute_fast.py b/weave/legacy/execute_fast.py index 91a8e640b5b..f4b571c86ea 100644 --- a/weave/legacy/execute_fast.py +++ b/weave/legacy/execute_fast.py @@ -2,12 +2,12 @@ from weave import ( errors, - ref_base, weave_internal, ) from weave import weave_types as types from weave.legacy import ( engine_trace, + ref_base, registry_mem, box, compile, diff --git a/weave/legacy/graph_mapper.py b/weave/legacy/graph_mapper.py index 8e0b6cce626..f2c68399433 100644 --- a/weave/legacy/graph_mapper.py +++ b/weave/legacy/graph_mapper.py @@ -1,4 +1,4 @@ -from weave import ref_base +from weave.legacy import ref_base from weave import weave_types as types from weave.legacy import graph, mappers, node_ref from weave.legacy import mappers_python_def as mappers_python diff --git a/weave/legacy/mappers_arrow.py b/weave/legacy/mappers_arrow.py index 6b3ed376577..2f1ca904ef1 100644 --- a/weave/legacy/mappers_arrow.py +++ b/weave/legacy/mappers_arrow.py @@ -5,7 +5,7 @@ import pyarrow as pa -from weave import errors, ref_base +from weave import errors from weave import weave_types as types from weave.legacy import ( arrow_util, @@ -15,6 +15,7 @@ mappers_weave, node_ref, partial_object, + ref_base, ) from weave.legacy import mappers_python_def as mappers_python from weave.legacy.arrow import arrow diff --git a/weave/legacy/mappers_publisher.py b/weave/legacy/mappers_publisher.py index f9facd494e7..2e57541b60e 100644 --- a/weave/legacy/mappers_publisher.py +++ b/weave/legacy/mappers_publisher.py @@ -2,7 +2,7 @@ import dataclasses import typing -from weave import errors, ref_base, storage, weave_internal +from weave import errors, storage, weave_internal from weave import weave_types as types from weave.legacy.node_ref import ref_to_node @@ -15,6 +15,7 @@ graph, mappers, mappers_python_def, + ref_base, ) from weave.legacy.artifact_wandb import likely_commit_hash from weave.legacy.language_features.tagging import tag_store, tagged_value_type diff --git a/weave/legacy/mappers_python_def.py b/weave/legacy/mappers_python_def.py index 40359e01d8c..88a38b59af1 100644 --- a/weave/legacy/mappers_python_def.py +++ b/weave/legacy/mappers_python_def.py @@ -4,7 +4,7 @@ import math import typing -from weave import errors, ref_base, storage +from weave import errors, storage from weave import weave_types as types from weave.legacy import ( artifact_fs, @@ -12,6 +12,7 @@ mappers, mappers_python, mappers_weave, + ref_base, val_const, ) from weave.legacy import timestamp as weave_timestamp diff --git a/weave/legacy/node_ref.py b/weave/legacy/node_ref.py index 9c19030ba8f..47edbc6804b 100644 --- a/weave/legacy/node_ref.py +++ b/weave/legacy/node_ref.py @@ -3,7 +3,7 @@ from weave.legacy import graph -from .. import ref_base +from . import ref_base # Notes for the future: # - I added list.lookup to lookup rows in a list by ID. I think we probably should diff --git a/weave/legacy/object_context.py b/weave/legacy/object_context.py index 836fd054151..b8d916063e2 100644 --- a/weave/legacy/object_context.py +++ b/weave/legacy/object_context.py @@ -12,7 +12,7 @@ from typing import Any if typing.TYPE_CHECKING: - from weave import ref_base + from weave.legacy import ref_base from weave import weave_types as types from weave.legacy import box, uris diff --git a/weave/legacy/ops_primitives/artifacts.py b/weave/legacy/ops_primitives/artifacts.py index d48f86d9da2..d05c9223c8b 100644 --- a/weave/legacy/ops_primitives/artifacts.py +++ b/weave/legacy/ops_primitives/artifacts.py @@ -4,8 +4,8 @@ import typing from weave.query_api import op -from weave import ref_base, types -from weave.legacy import artifact_fs +from weave import types +from weave.legacy import artifact_fs, ref_base from weave.legacy.artifact_local import WORKING_DIR_PREFIX, LocalArtifact diff --git a/weave/legacy/ops_primitives/weave_api.py b/weave/legacy/ops_primitives/weave_api.py index 33ace6416b4..d59113a2997 100644 --- a/weave/legacy/ops_primitives/weave_api.py +++ b/weave/legacy/ops_primitives/weave_api.py @@ -4,13 +4,13 @@ from weave import ( errors, - ref_base, storage, weave_internal, ) from weave import weave_types as types from weave.query_api import mutation, op, weave_class from weave.legacy import ( + ref_base, registry_mem, artifact_fs, artifact_local, diff --git a/weave/ref_base.py b/weave/legacy/ref_base.py similarity index 96% rename from weave/ref_base.py rename to weave/legacy/ref_base.py index 120ff9fed6d..e7742d9eb65 100644 --- a/weave/ref_base.py +++ b/weave/legacy/ref_base.py @@ -6,19 +6,18 @@ from typing import Sequence from weave.client_context import weave_client as weave_client_context -from weave.legacy import box, context_state, object_context +from weave.legacy import box, context_state, object_context, uris from weave.legacy.language_features.tagging import tag_store -from . import errors -from . import weave_types as types -from .legacy import uris +from .. import errors +from .. import weave_types as types # We store Refs here if we can't attach them directly to the object REFS: weakref.WeakValueDictionary[int, "Ref"] = weakref.WeakValueDictionary() if typing.TYPE_CHECKING: - from . import weave_types as types - from .trace import weave_client + from .. import weave_types as types + from ..trace import weave_client def _map_to_ref_strs(obj: typing.Any) -> typing.Any: diff --git a/weave/legacy/show.py b/weave/legacy/show.py index df57367e12f..92ae3f7cf16 100644 --- a/weave/legacy/show.py +++ b/weave/legacy/show.py @@ -5,8 +5,8 @@ from IPython.display import IFrame, display -from weave.legacy import artifact_fs, context, graph, ops, node_ref, panel -from weave import errors, ref_base, storage, util +from weave.legacy import artifact_fs, context, graph, ops, node_ref, panel, ref_base +from weave import errors, storage, util from . import usage_analytics from .. import weave_types as types from . import weavejs_fixes diff --git a/weave/legacy/trace_legacy.py b/weave/legacy/trace_legacy.py index 3264585672d..3d9e6529cc4 100644 --- a/weave/legacy/trace_legacy.py +++ b/weave/legacy/trace_legacy.py @@ -3,7 +3,7 @@ from weave.legacy import artifact_local, graph, runs -from .. import ref_base +from . import ref_base from . import errors from .. import weave_types as types diff --git a/weave/legacy/trace_local.py b/weave/legacy/trace_local.py index bc1376d5e35..b210d313b09 100644 --- a/weave/legacy/trace_local.py +++ b/weave/legacy/trace_local.py @@ -6,9 +6,9 @@ from typing import Mapping from weave.legacy import artifact_local, graph, op_def, op_policy, runs +from . import ref_base from .. import ( - ref_base, storage, weave_internal, ) diff --git a/weave/legacy/uris.py b/weave/legacy/uris.py index dc1e562b80e..7ce5150f23b 100644 --- a/weave/legacy/uris.py +++ b/weave/legacy/uris.py @@ -5,7 +5,7 @@ from .. import errors if typing.TYPE_CHECKING: - from .. import ref_base + from . import ref_base @dataclasses.dataclass diff --git a/weave/query_api.py b/weave/query_api.py index 908c7e526fb..9f2140b8416 100644 --- a/weave/query_api.py +++ b/weave/query_api.py @@ -9,7 +9,7 @@ from weave.legacy import graph_mapper as _graph_mapper from . import storage as _storage -from . import ref_base as _ref_base +from .legacy import ref_base as _ref_base from weave.legacy import wandb_api as _wandb_api from . import weave_internal as _weave_internal diff --git a/weave/ref_util.py b/weave/ref_util.py index d2adf5a005f..968a584ca61 100644 --- a/weave/ref_util.py +++ b/weave/ref_util.py @@ -25,7 +25,7 @@ def val_with_relative_ref( ) -> typing.Any: from weave.legacy import context_state - from . import ref_base + from .legacy import ref_base # If we already have a ref, resolve it if isinstance(child_object, ref_base.Ref): diff --git a/weave/storage.py b/weave/storage.py index 8f0336d37c8..c87c1db4060 100644 --- a/weave/storage.py +++ b/weave/storage.py @@ -17,10 +17,11 @@ box, graph, mappers_python, + ref_base, timestamp, ) -from . import errors, ref_base +from . import errors from . import weave_types as types Ref = ref_base.Ref diff --git a/weave/tests/legacy/test_mutation2.py b/weave/tests/legacy/test_mutation2.py index 9fe786a3578..d344f10b0f9 100644 --- a/weave/tests/legacy/test_mutation2.py +++ b/weave/tests/legacy/test_mutation2.py @@ -1,6 +1,5 @@ import weave -from weave import ref_base -from weave.legacy import uris +from weave.legacy import ref_base, uris from ... import weave_internal diff --git a/weave/tests/trace/test_evaluate.py b/weave/tests/trace/test_evaluate.py index 0af269f1c88..b855eea3def 100644 --- a/weave/tests/trace/test_evaluate.py +++ b/weave/tests/trace/test_evaluate.py @@ -3,7 +3,7 @@ import pytest import weave -from weave import Dataset, Evaluation, Model, ref_base +from weave import Dataset, Evaluation, Model from weave.flow.scorer import MultiTaskBinaryClassificationF1 pytestmark = pytest.mark.webtest diff --git a/weave/tests/trace/test_weaveflow.py b/weave/tests/trace/test_weaveflow.py index ca3218dc98f..a41f4eba9d4 100644 --- a/weave/tests/trace/test_weaveflow.py +++ b/weave/tests/trace/test_weaveflow.py @@ -5,7 +5,7 @@ from pydantic import Field import weave -from weave import ref_base +from weave.legacy import ref_base pytestmark = pytest.mark.trace diff --git a/weave/trace/box.py b/weave/trace/box.py index 6662aedc113..1c39bf5e39f 100644 --- a/weave/trace/box.py +++ b/weave/trace/box.py @@ -10,7 +10,7 @@ import numpy as np -from weave.ref_base import Ref +from weave.legacy.ref_base import Ref T = TypeVar("T") diff --git a/weave/trace/weave_client.py b/weave/trace/weave_client.py index ce2ea38eea1..32a382f5999 100644 --- a/weave/trace/weave_client.py +++ b/weave/trace/weave_client.py @@ -51,7 +51,7 @@ ) if typing.TYPE_CHECKING: - from .. import ref_base + from ..legacy import ref_base # Controls if objects can have refs to projects not the WeaveClient project. diff --git a/weave/weave_types.py b/weave/weave_types.py index bee5df4bd11..039b7377c1a 100644 --- a/weave/weave_types.py +++ b/weave/weave_types.py @@ -122,7 +122,7 @@ def type_class_of(obj): @staticmethod def type_of(obj: typing.Any) -> "Type": - from . import ref_base + from weave.legacy import ref_base if ( context_state.ref_tracking_enabled() @@ -1381,7 +1381,7 @@ def _is_assignable_to(self, other_type) -> typing.Optional[bool]: return None def save_instance(self, obj, artifact, name): - from . import ref_base + from weave.legacy import ref_base obj_ref = ref_base.get_ref(obj) if obj_ref is None: From e5252bdff4c3fe512110513fbb12e7bbb953e0af Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Thu, 22 Aug 2024 22:08:16 -0400 Subject: [PATCH 28/84] move to trace: table --- weave/{ => trace}/table.py | 0 weave/trace/vals.py | 2 +- weave/trace/weave_client.py | 2 +- weave/trace_api.py | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename weave/{ => trace}/table.py (100%) diff --git a/weave/table.py b/weave/trace/table.py similarity index 100% rename from weave/table.py rename to weave/trace/table.py diff --git a/weave/trace/vals.py b/weave/trace/vals.py index 8933dcc201b..c92f9a024ec 100644 --- a/weave/trace/vals.py +++ b/weave/trace/vals.py @@ -9,7 +9,6 @@ from pydantic import v1 as pydantic_v1 from weave.client_context.weave_client import get_weave_client -from weave.table import Table from weave.trace import box from weave.trace.errors import InternalError from weave.trace.object_record import ObjectRecord @@ -24,6 +23,7 @@ TableRef, ) from weave.trace.serialize import from_json +from weave.trace.table import Table from weave.trace_server.trace_server_interface import ( ObjReadReq, TableQueryReq, diff --git a/weave/trace/weave_client.py b/weave/trace/weave_client.py index 32a382f5999..2a7f003a951 100644 --- a/weave/trace/weave_client.py +++ b/weave/trace/weave_client.py @@ -12,7 +12,6 @@ from weave import trace_sentry, urls, version from weave.client_context import weave_client as weave_client_context from weave.exception import exception_to_json_str -from weave.table import Table from weave.trace import call_context from weave.trace.feedback import FeedbackQuery, RefFeedbackQuery from weave.trace.object_record import ( @@ -25,6 +24,7 @@ from weave.trace.refs import CallRef, ObjectRef, OpRef, Ref, TableRef from weave.trace.serialize import from_json, isinstance_namedtuple, to_json from weave.trace.serializer import get_serializer_for_obj +from weave.trace.table import Table from weave.trace.vals import WeaveObject, WeaveTable, make_trace_obj from weave.trace_server.ids import generate_id from weave.trace_server.trace_server_interface import ( diff --git a/weave/trace_api.py b/weave/trace_api.py index 48a3b0a93af..f1c26b24284 100644 --- a/weave/trace_api.py +++ b/weave/trace_api.py @@ -17,12 +17,12 @@ util, weave_init, ) -from .table import Table from .trace import context, weave_client from .trace.constants import TRACE_OBJECT_EMOJI from .trace.op import Op, op from .trace.refs import ObjectRef, parse_uri from .trace.settings import UserSettings, parse_and_apply_settings +from .trace.table import Table def init( From bd8d34e76fe41b5199db4aa87756bfbb9d757048 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Thu, 22 Aug 2024 23:43:55 -0400 Subject: [PATCH 29/84] move to trace: trace_sentry --- weave/{ => trace}/trace_sentry.py | 2 +- weave/trace/weave_client.py | 4 ++-- weave/weave_init.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) rename weave/{ => trace}/trace_sentry.py (99%) diff --git a/weave/trace_sentry.py b/weave/trace/trace_sentry.py similarity index 99% rename from weave/trace_sentry.py rename to weave/trace/trace_sentry.py index 5e7e80d1a2f..38bd88b1e21 100644 --- a/weave/trace_sentry.py +++ b/weave/trace/trace_sentry.py @@ -90,7 +90,7 @@ def setup(self) -> None: to avoid the possibility of interfering with the user's own Sentry SDK setup. """ - from . import version + from .. import version client = sentry_sdk.Client( dsn=self.dsn, diff --git a/weave/trace/weave_client.py b/weave/trace/weave_client.py index 2a7f003a951..5062f5ecc1e 100644 --- a/weave/trace/weave_client.py +++ b/weave/trace/weave_client.py @@ -9,10 +9,10 @@ import pydantic from requests import HTTPError -from weave import trace_sentry, urls, version +from weave import urls, version from weave.client_context import weave_client as weave_client_context from weave.exception import exception_to_json_str -from weave.trace import call_context +from weave.trace import call_context, trace_sentry from weave.trace.feedback import FeedbackQuery, RefFeedbackQuery from weave.trace.object_record import ( ObjectRecord, diff --git a/weave/weave_init.py b/weave/weave_init.py index b2ef6d98acd..21d0e31ab6a 100644 --- a/weave/weave_init.py +++ b/weave/weave_init.py @@ -2,8 +2,8 @@ from weave.client_context import weave_client as weave_client_context -from . import errors, init_message, trace_sentry -from .trace import autopatch, weave_client +from . import errors, init_message +from .trace import autopatch, trace_sentry, weave_client from .trace_server import remote_http_trace_server, sqlite_trace_server _current_inited_client = None From 19a1530f27cb667741473b8c01a59098e4ad691b Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 01:08:41 -0400 Subject: [PATCH 30/84] move to trace: trace_api --- docs/docs/reference/python-sdk/weave/index.md | 191 +++++------------- weave/__init__.py | 4 +- weave/api.py | 2 +- weave/{trace_api.py => trace/api.py} | 16 +- 4 files changed, 66 insertions(+), 147 deletions(-) rename weave/{trace_api.py => trace/api.py} (96%) diff --git a/docs/docs/reference/python-sdk/weave/index.md b/docs/docs/reference/python-sdk/weave/index.md index 465b4cc22d4..7ea6afb28f1 100644 --- a/docs/docs/reference/python-sdk/weave/index.md +++ b/docs/docs/reference/python-sdk/weave/index.md @@ -1,7 +1,6 @@ --- sidebar_label: weave --- - # weave @@ -9,11 +8,8 @@ The top-level functions and classes for working with Weave. --- - # API Overview - - ## Classes - [`obj.Object`](#class-object) @@ -24,18 +20,16 @@ The top-level functions and classes for working with Weave. ## Functions -- [`trace_api.init`](#function-init): Initialize weave tracking, logging to a wandb project. -- [`trace_api.publish`](#function-publish): Save and version a python object. -- [`trace_api.ref`](#function-ref): Construct a Ref to a Weave object. +- [`trace.api.init`](#function-init): Initialize weave tracking, logging to a wandb project. +- [`trace.api.publish`](#function-publish): Save and version a python object. +- [`trace.api.ref`](#function-ref): Construct a Ref to a Weave object. - [`call_context.get_current_call`](#function-get_current_call): Get the Call object for the currently executing Op, within that Op. -- [`trace_api.finish`](#function-finish): Stops logging to weave. -- [`op.op`](#function-op): A decorator to weave op-ify a function or method. Works for both sync and async. - +- [`trace.api.finish`](#function-finish): Stops logging to weave. +- [`op.op`](#function-op): A decorator to weave op-ify a function or method. Works for both sync and async. --- - - + ### function `init` @@ -46,26 +40,22 @@ init( ) → WeaveClient ``` -Initialize weave tracking, logging to a wandb project. - -Logging is initialized globally, so you do not need to keep a reference to the return value of init. - -Following init, calls of weave.op() decorated functions will be logged to the specified project. +Initialize weave tracking, logging to a wandb project. +Logging is initialized globally, so you do not need to keep a reference to the return value of init. +Following init, calls of weave.op() decorated functions will be logged to the specified project. **Args:** - - - `project_name`: The name of the Weights & Biases project to log to. - +- `project_name`: The name of the Weights & Biases project to log to. **Returns:** - A Weave client. +A Weave client. --- - + ### function `publish` @@ -73,27 +63,23 @@ Following init, calls of weave.op() decorated functions will be logged to the sp publish(obj: Any, name: Optional[str] = None) → ObjectRef ``` -Save and version a python object. - -If an object with name already exists, and the content hash of obj does not match the latest version of that object, a new version will be created. - -TODO: Need to document how name works with this change. +Save and version a python object. +If an object with name already exists, and the content hash of obj does not match the latest version of that object, a new version will be created. +TODO: Need to document how name works with this change. **Args:** - - - `obj`: The object to save and version. - - `name`: The name to save the object under. - +- `obj`: The object to save and version. +- `name`: The name to save the object under. **Returns:** - A weave Ref to the saved object. +A weave Ref to the saved object. --- - + ### function `ref` @@ -101,22 +87,16 @@ TODO: Need to document how name works with this change. ref(location: str) → ObjectRef ``` -Construct a Ref to a Weave object. - -TODO: what happens if obj does not exist - +Construct a Ref to a Weave object. +TODO: what happens if obj does not exist **Args:** - - - `location`: A fully-qualified weave ref URI, or if weave.init() has been called, "name:version" or just "name" ("latest" will be used for version in this case). - - - +- `location`: A fully-qualified weave ref URI, or if weave.init() has been called, "name:version" or just "name" ("latest" will be used for version in this case). **Returns:** - A weave Ref to the object. +A weave Ref to the object. --- @@ -128,9 +108,9 @@ TODO: what happens if obj does not exist get_current_call() → Optional[ForwardRef('Call')] ``` -Get the Call object for the currently executing Op, within that Op. +Get the Call object for the currently executing Op, within that Op. -This allows you to access attributes of the Call such as its id or feedback while it is running. +This allows you to access attributes of the Call such as its id or feedback while it is running. ```python @weave.op @@ -138,18 +118,18 @@ def hello(name: str) -> None: print(f"Hello {name}!") current_call = weave.get_current_call() print(current_call.id) -``` +``` -It is also possible to access a Call after the Op has returned. +It is also possible to access a Call after the Op has returned. -If you have the Call's id, perhaps from the UI, you can use the `call` method on the `WeaveClient` returned from `weave.init` to retrieve the Call object. +If you have the Call's id, perhaps from the UI, you can use the `call` method on the `WeaveClient` returned from `weave.init` to retrieve the Call object. ```python client = weave.init("") mycall = client.call("") -``` +``` -Alternately, after defining your Op you can use its `call` method. For example: +Alternately, after defining your Op you can use its `call` method. For example: ```python @weave.op @@ -158,16 +138,14 @@ def hello(name: str) -> None: mycall = hello.call("world") print(mycall.id) -``` - - +``` **Returns:** - The Call object for the currently executing Op, or None if tracking has not been initialized or this method is invoked outside an Op. +The Call object for the currently executing Op, or None if tracking has not been initialized or this method is invoked outside an Op. --- - + ### function `finish` @@ -175,9 +153,9 @@ print(mycall.id) finish() → None ``` -Stops logging to weave. +Stops logging to weave. -Following finish, calls of weave.op() decorated functions will no longer be logged. You will need to run weave.init() again to resume logging. +Following finish, calls of weave.op() decorated functions will no longer be logged. You will need to run weave.init() again to resume logging. --- @@ -189,15 +167,13 @@ Following finish, calls of weave.op() decorated functions will no longer be logg op(*args: Any, **kwargs: Any) → Union[Callable[[Any], Op], Op] ``` -A decorator to weave op-ify a function or method. Works for both sync and async. - -Decorated functions and methods can be called as normal, but will also automatically track calls in the Weave UI. - -If you don't call `weave.init` then the function will behave as if it were not decorated. +A decorator to weave op-ify a function or method. Works for both sync and async. +Decorated functions and methods can be called as normal, but will also automatically track calls in the Weave UI. +If you don't call `weave.init` then the function will behave as if it were not decorated. -Example usage: +Example usage: ```python import weave @@ -213,7 +189,7 @@ async def extract(): ) await extract() # calls the function and tracks the call in the Weave UI -``` +``` --- @@ -221,14 +197,11 @@ await extract() # calls the function and tracks the call in the Weave UI ## class `Object` - - - - **Pydantic Fields:** - `name`: `typing.Optional[str]` - `description`: `typing.Optional[str]` + --- @@ -243,10 +216,6 @@ handle_relocatable_object( ) → Any ``` - - - - --- @@ -257,22 +226,15 @@ handle_relocatable_object( model_post_init(_Object__context: Any) → None ``` - - - - - --- ## class `Dataset` -Dataset object with easy saving and automatic versioning - +Dataset object with easy saving and automatic versioning **Examples:** - ```python # Create a dataset @@ -290,14 +252,14 @@ dataset_ref = weave.ref('grammar').get() # Access a specific example example_label = dataset_ref.rows[2]['sentence'] -``` - +``` **Pydantic Fields:** - `name`: `typing.Optional[str]` - `description`: `typing.Optional[str]` - `rows`: `` + --- @@ -308,24 +270,17 @@ example_label = dataset_ref.rows[2]['sentence'] convert_to_table(rows: Any) → Table ``` - - - - - --- ## class `Model` -Intended to capture a combination of code and data the operates on an input. For example it might call an LLM with a prompt to make a prediction or generate text. - -When you change the attributes or the code that defines your model, these changes will be logged and the version will be updated. This ensures that you can compare the predictions across different versions of your model. Use this to iterate on prompts or to try the latest LLM and compare predictions across different settings +Intended to capture a combination of code and data the operates on an input. For example it might call an LLM with a prompt to make a prediction or generate text. +When you change the attributes or the code that defines your model, these changes will be logged and the version will be updated. This ensures that you can compare the predictions across different versions of your model. Use this to iterate on prompts or to try the latest LLM and compare predictions across different settings **Examples:** - ```python class YourModel(Model): @@ -337,13 +292,13 @@ class YourModel(Model): # Model logic goes here prediction = self.attribute1 + ' ' + input_data return {'pred': prediction} -``` - +``` **Pydantic Fields:** - `name`: `typing.Optional[str]` - `description`: `typing.Optional[str]` + --- @@ -354,28 +309,21 @@ class YourModel(Model): get_infer_method() → Callable ``` - - - - - --- ## class `Evaluation` -Sets up an evaluation which includes a set of scorers and a dataset. - -Calling evaluation.evaluate(model) will pass in rows from a dataset into a model matching the names of the columns of the dataset to the argument names in model.predict. -Then it will call all of the scorers and save the results in weave. +Sets up an evaluation which includes a set of scorers and a dataset. -If you want to preprocess the rows from the dataset you can pass in a function to preprocess_model_input. +Calling evaluation.evaluate(model) will pass in rows from a dataset into a model matching the names of the columns of the dataset to the argument names in model.predict. +Then it will call all of the scorers and save the results in weave. +If you want to preprocess the rows from the dataset you can pass in a function to preprocess_model_input. **Examples:** - ```python # Collect your examples @@ -405,8 +353,7 @@ evaluation = Evaluation( weave.init('intro-example') # Run the evaluation asyncio.run(evaluation.evaluate(function_to_evaluate)) -``` - +``` **Pydantic Fields:** @@ -416,6 +363,7 @@ asyncio.run(evaluation.evaluate(function_to_evaluate)) - `scorers`: `typing.Optional[list[typing.Union[typing.Callable, trace.op.Op, flow.scorer.Scorer]]]` - `preprocess_model_input`: `typing.Optional[typing.Callable]` - `trials`: `` + --- @@ -426,10 +374,6 @@ asyncio.run(evaluation.evaluate(function_to_evaluate)) evaluate(model: Union[Callable, Model]) → dict ``` - - - - --- @@ -440,10 +384,6 @@ evaluate(model: Union[Callable, Model]) → dict model_post_init(_Evaluation__context: Any) → None ``` - - - - --- @@ -454,10 +394,6 @@ model_post_init(_Evaluation__context: Any) → None predict_and_score(model: Union[Callable, Model], example: dict) → dict ``` - - - - --- @@ -468,25 +404,17 @@ predict_and_score(model: Union[Callable, Model], example: dict) → dict summarize(eval_table: EvaluationResults) → dict ``` - - - - - --- ## class `Scorer` - - - - **Pydantic Fields:** - `name`: `typing.Optional[str]` - `description`: `typing.Optional[str]` + --- @@ -497,10 +425,6 @@ summarize(eval_table: EvaluationResults) → dict score(target: Any, model_output: Any) → Any ``` - - - - --- @@ -510,8 +434,3 @@ score(target: Any, model_output: Any) → Any ```python summarize(score_rows: list) → Optional[dict] ``` - - - - - diff --git a/weave/__init__.py b/weave/__init__.py index 97863a1d35f..207728c31fc 100644 --- a/weave/__init__.py +++ b/weave/__init__.py @@ -16,7 +16,7 @@ from . import storage from .query_api import * -from .trace_api import * +from .trace.api import * from .errors import * @@ -64,7 +64,7 @@ # Special object informing doc generation tooling which symbols # to document & to associate with this module. __docspec__ = [ - # Re-exported from trace_api + # Re-exported from trace.api init, publish, ref, diff --git a/weave/api.py b/weave/api.py index 17829d18092..6f00d422040 100644 --- a/weave/api.py +++ b/weave/api.py @@ -1,4 +1,4 @@ """These are the top-level functions in the `import weave` namespace.""" from .query_api import * -from .trace_api import * +from .trace.api import * diff --git a/weave/trace_api.py b/weave/trace/api.py similarity index 96% rename from weave/trace_api.py rename to weave/trace/api.py index f1c26b24284..5415d9abf60 100644 --- a/weave/trace_api.py +++ b/weave/trace/api.py @@ -11,18 +11,18 @@ # TODO: type_serializers is imported here to trigger registration of the image serializer. # There is probably a better place for this, but including here for now to get the fix in. -from . import ( +from .. import ( type_serializers, # noqa: F401 urls, util, weave_init, ) -from .trace import context, weave_client -from .trace.constants import TRACE_OBJECT_EMOJI -from .trace.op import Op, op -from .trace.refs import ObjectRef, parse_uri -from .trace.settings import UserSettings, parse_and_apply_settings -from .trace.table import Table +from . import context, weave_client +from .constants import TRACE_OBJECT_EMOJI +from .op import Op, op +from .refs import ObjectRef, parse_uri +from .settings import UserSettings, parse_and_apply_settings +from .table import Table def init( @@ -209,7 +209,7 @@ def serve( from weave.legacy import wandb_api - from .serve_fastapi import object_method_app + from ..serve_fastapi import object_method_app client = weave_client_context.require_weave_client() # if not isinstance( From b79ae8e6da44f33a1c98f3befd4aef561df66a2b Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 01:32:44 -0400 Subject: [PATCH 31/84] move to trace: serve_fastapi --- weave/deploy/modal/stub.py | 2 +- weave/trace/api.py | 2 +- weave/{ => trace}/serve_fastapi.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) rename weave/{ => trace}/serve_fastapi.py (98%) diff --git a/weave/deploy/modal/stub.py b/weave/deploy/modal/stub.py index cfd0bd08327..2dee6e838e6 100644 --- a/weave/deploy/modal/stub.py +++ b/weave/deploy/modal/stub.py @@ -27,7 +27,7 @@ @asgi_app(label=safe_name(uri.name)) def fastapi_app() -> FastAPI: from weave import api - from weave.serve_fastapi import object_method_app + from weave.trace.serve_fastapi import object_method_app uri_ref = parse_uri(os.environ["MODEL_REF"]) if not isinstance(uri_ref, ObjectRef): diff --git a/weave/trace/api.py b/weave/trace/api.py index 5415d9abf60..5fd03e25d67 100644 --- a/weave/trace/api.py +++ b/weave/trace/api.py @@ -209,7 +209,7 @@ def serve( from weave.legacy import wandb_api - from ..serve_fastapi import object_method_app + from .serve_fastapi import object_method_app client = weave_client_context.require_weave_client() # if not isinstance( diff --git a/weave/serve_fastapi.py b/weave/trace/serve_fastapi.py similarity index 98% rename from weave/serve_fastapi.py rename to weave/trace/serve_fastapi.py index ca63901d03b..3e3bc7b7286 100644 --- a/weave/serve_fastapi.py +++ b/weave/trace/serve_fastapi.py @@ -17,8 +17,8 @@ from weave.trace.op import Op from weave.trace.refs import ObjectRef -from . import errors -from .legacy import weave_pydantic +from .. import errors +from ..legacy import weave_pydantic key_cache: cache.LruTimeWindowCache[str, typing.Optional[bool]] = ( cache.LruTimeWindowCache(datetime.timedelta(minutes=5)) From a827541ab58ddfea5b7bc9811ae6d0703fa1db23 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 08:48:56 -0400 Subject: [PATCH 32/84] move to trace: ref_util --- weave/legacy/arrow/list_.py | 2 +- weave/legacy/artifact_fs.py | 3 ++- weave/legacy/box.py | 2 +- weave/legacy/object_type_ref_util.py | 2 +- weave/tests/legacy/test_refs.py | 3 ++- weave/tests/legacy/test_wb_end_to_end.py | 2 +- weave/{ => trace}/ref_util.py | 9 +++------ 7 files changed, 11 insertions(+), 12 deletions(-) rename weave/{ => trace}/ref_util.py (95%) diff --git a/weave/legacy/arrow/list_.py b/weave/legacy/arrow/list_.py index f8a7f09bbb3..7cc6e84ddba 100644 --- a/weave/legacy/arrow/list_.py +++ b/weave/legacy/arrow/list_.py @@ -12,7 +12,6 @@ from weave import ( errors, - ref_util, weave_internal, ) from weave import weave_types as types @@ -40,6 +39,7 @@ tag_store, tagged_value_type, ) +from weave.trace import ref_util def reverse_dict(d: dict) -> dict: diff --git a/weave/legacy/artifact_fs.py b/weave/legacy/artifact_fs.py index f09e110e612..d5c71f3c643 100644 --- a/weave/legacy/artifact_fs.py +++ b/weave/legacy/artifact_fs.py @@ -6,10 +6,11 @@ import os import typing -from weave import errors, ref_util +from weave import errors from weave import weave_types as types from weave.legacy import artifact_base, file_base, object_context, ref_base, uris from weave.legacy.language_features.tagging import tag_store +from weave.trace import ref_util if typing.TYPE_CHECKING: from weave.legacy import graph diff --git a/weave/legacy/box.py b/weave/legacy/box.py index f089e03acdc..b957fc6ba3f 100644 --- a/weave/legacy/box.py +++ b/weave/legacy/box.py @@ -4,7 +4,7 @@ import numpy as np -from weave import ref_util +from weave.trace import ref_util from weave.legacy import context_state diff --git a/weave/legacy/object_type_ref_util.py b/weave/legacy/object_type_ref_util.py index 40e70fff6fd..53787c4c454 100644 --- a/weave/legacy/object_type_ref_util.py +++ b/weave/legacy/object_type_ref_util.py @@ -1,6 +1,6 @@ import typing -from weave import ref_util +from weave.trace import ref_util from weave.legacy import context_state diff --git a/weave/tests/legacy/test_refs.py b/weave/tests/legacy/test_refs.py index a1cfd4ccca7..ac9923eaaad 100644 --- a/weave/tests/legacy/test_refs.py +++ b/weave/tests/legacy/test_refs.py @@ -4,13 +4,14 @@ from weave.flow.obj import Object from weave.legacy import artifact_local from weave.legacy import ops_arrow as arrow +from weave.trace import ref_util from weave.trace_server.refs_internal import ( DICT_KEY_EDGE_NAME, LIST_INDEX_EDGE_NAME, OBJECT_ATTR_EDGE_NAME, ) -from ... import ref_util, storage +from ... import storage def test_laref_artifact_version_1(): diff --git a/weave/tests/legacy/test_wb_end_to_end.py b/weave/tests/legacy/test_wb_end_to_end.py index 1529cfff655..2232079248d 100644 --- a/weave/tests/legacy/test_wb_end_to_end.py +++ b/weave/tests/legacy/test_wb_end_to_end.py @@ -60,7 +60,7 @@ def _test_basic_publish(user_fixture): uri == f"wandb-artifact:///{user_fixture.username}/weave/list:0cdf3358dc939f961ca9/obj" ) - assert weave.ref_base.Ref.from_str(uri).get() == [1, 2, 3] + assert weave.legacy.ref_base.Ref.from_str(uri).get() == [1, 2, 3] # Example of end to end integration test diff --git a/weave/ref_util.py b/weave/trace/ref_util.py similarity index 95% rename from weave/ref_util.py rename to weave/trace/ref_util.py index 968a584ca61..93ec19decd7 100644 --- a/weave/ref_util.py +++ b/weave/trace/ref_util.py @@ -3,8 +3,7 @@ from urllib import parse from weave.legacy import box - -from .trace_server import refs_internal +from weave.trace_server import refs_internal DICT_KEY_EDGE_NAME = refs_internal.DICT_KEY_EDGE_NAME LIST_INDEX_EDGE_NAME = refs_internal.LIST_INDEX_EDGE_NAME @@ -23,9 +22,7 @@ def parse_local_ref_str(s: str) -> typing.Tuple[str, typing.Optional[list[str]]] def val_with_relative_ref( parent_object: typing.Any, child_object: typing.Any, ref_extra_parts: list[str] ) -> typing.Any: - from weave.legacy import context_state - - from .legacy import ref_base + from weave.legacy import context_state, ref_base # If we already have a ref, resolve it if isinstance(child_object, ref_base.Ref): @@ -34,7 +31,7 @@ def val_with_relative_ref( # Only do this if ref_tracking_enabled right now. I just want to # avoid introducing new behavior into W&B prod for the moment. if context_state.ref_tracking_enabled(): - from . import storage + from .. import storage child_ref = storage.get_ref(child_object) parent_ref = ref_base.get_ref(parent_object) From 5d82861d81c648d709e59b726146435ced4a3a3e Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 10:05:27 -0400 Subject: [PATCH 33/84] move to trace: exception --- weave/{ => trace}/exception.py | 0 weave/trace/weave_client.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename weave/{ => trace}/exception.py (100%) diff --git a/weave/exception.py b/weave/trace/exception.py similarity index 100% rename from weave/exception.py rename to weave/trace/exception.py diff --git a/weave/trace/weave_client.py b/weave/trace/weave_client.py index 5062f5ecc1e..3a3af5e6166 100644 --- a/weave/trace/weave_client.py +++ b/weave/trace/weave_client.py @@ -11,8 +11,8 @@ from weave import urls, version from weave.client_context import weave_client as weave_client_context -from weave.exception import exception_to_json_str from weave.trace import call_context, trace_sentry +from weave.trace.exception import exception_to_json_str from weave.trace.feedback import FeedbackQuery, RefFeedbackQuery from weave.trace.object_record import ( ObjectRecord, From 65314dfef3c94de5c6c8126d99cd41944fc76c15 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 09:53:14 -0400 Subject: [PATCH 34/84] move to legacy: query_api --- weave/__init__.py | 2 +- weave/api.py | 2 +- weave/{query_api.py => legacy/api.py} | 34 +++++++++---------- weave/legacy/arrow/convert.py | 2 +- weave/legacy/ecosystem/root.py | 2 +- weave/legacy/op_def.py | 2 +- weave/legacy/ops_arrow/convert_ops.py | 2 +- weave/legacy/ops_arrow/date.py | 2 +- weave/legacy/ops_arrow/list_join.py | 2 +- weave/legacy/ops_arrow/list_ops.py | 2 +- weave/legacy/ops_arrow/list_range.py | 2 +- weave/legacy/ops_arrow/number.py | 2 +- weave/legacy/ops_arrow/string.py | 2 +- weave/legacy/ops_arrow/vectorize.py | 2 +- weave/legacy/ops_domain/artifact_alias_ops.py | 2 +- .../ops_domain/artifact_collection_ops.py | 2 +- .../ops_domain/artifact_membership_ops.py | 2 +- weave/legacy/ops_domain/artifact_type_ops.py | 2 +- .../legacy/ops_domain/artifact_version_ops.py | 2 +- weave/legacy/ops_domain/entity_ops.py | 2 +- weave/legacy/ops_domain/project_ops.py | 2 +- weave/legacy/ops_domain/repo_insight_ops.py | 2 +- weave/legacy/ops_domain/report_ops.py | 2 +- .../run_history/history_op_common.py | 2 +- .../run_history/run_history_v1_legacy_ops.py | 2 +- .../run_history_v2_parquet_media.py | 2 +- ...run_history_v3_parquet_stream_optimized.py | 2 +- weave/legacy/ops_domain/run_ops.py | 2 +- weave/legacy/ops_domain/run_queue_ops.py | 2 +- weave/legacy/ops_domain/run_segment.py | 2 +- weave/legacy/ops_domain/stream_table_ops.py | 2 +- weave/legacy/ops_domain/table.py | 2 +- weave/legacy/ops_domain/trace_tree.py | 2 +- weave/legacy/ops_domain/user_ops.py | 2 +- weave/legacy/ops_domain/wandb_domain_gql.py | 2 +- weave/legacy/ops_domain/wbgqlquery_op.py | 2 +- weave/legacy/ops_domain/wbmedia.py | 2 +- weave/legacy/ops_primitives/artifacts.py | 2 +- weave/legacy/ops_primitives/boolean.py | 2 +- weave/legacy/ops_primitives/csv_.py | 2 +- weave/legacy/ops_primitives/date.py | 2 +- weave/legacy/ops_primitives/file.py | 2 +- weave/legacy/ops_primitives/file_artifact.py | 2 +- weave/legacy/ops_primitives/file_local.py | 2 +- weave/legacy/ops_primitives/geom.py | 2 +- weave/legacy/ops_primitives/html.py | 2 +- weave/legacy/ops_primitives/image.py | 2 +- weave/legacy/ops_primitives/json_.py | 2 +- weave/legacy/ops_primitives/markdown.py | 2 +- weave/legacy/ops_primitives/number.py | 2 +- weave/legacy/ops_primitives/number_bin.py | 2 +- weave/legacy/ops_primitives/obj.py | 2 +- weave/legacy/ops_primitives/op_def.py | 2 +- weave/legacy/ops_primitives/pandas_.py | 2 +- weave/legacy/ops_primitives/random_junk.py | 4 +-- weave/legacy/ops_primitives/sql.py | 2 +- weave/legacy/ops_primitives/string.py | 2 +- weave/legacy/ops_primitives/test_any.py | 2 +- weave/legacy/ops_primitives/test_list.py | 2 +- weave/legacy/ops_primitives/test_pandas.py | 2 +- weave/legacy/ops_primitives/timestamp_bin.py | 2 +- weave/legacy/ops_primitives/type.py | 2 +- weave/legacy/ops_primitives/weave_api.py | 2 +- weave/legacy/panel.py | 2 +- weave/tests/legacy/test_mappers_python.py | 4 +-- weave/tests/legacy/test_op.py | 2 +- weave/tests/legacy/test_serialize.py | 2 +- weave/tests/legacy/test_wb.py | 2 +- 68 files changed, 86 insertions(+), 86 deletions(-) rename weave/{query_api.py => legacy/api.py} (83%) diff --git a/weave/__init__.py b/weave/__init__.py index 207728c31fc..67afd523607 100644 --- a/weave/__init__.py +++ b/weave/__init__.py @@ -15,7 +15,7 @@ from . import weave_types as types from . import storage -from .query_api import * +from .legacy.api import * from .trace.api import * from .errors import * diff --git a/weave/api.py b/weave/api.py index 6f00d422040..892dd0ec968 100644 --- a/weave/api.py +++ b/weave/api.py @@ -1,4 +1,4 @@ """These are the top-level functions in the `import weave` namespace.""" -from .query_api import * +from .legacy.api import * from .trace.api import * diff --git a/weave/query_api.py b/weave/legacy/api.py similarity index 83% rename from weave/query_api.py rename to weave/legacy/api.py index 9f2140b8416..5fec25de8a7 100644 --- a/weave/query_api.py +++ b/weave/legacy/api.py @@ -8,25 +8,25 @@ # If this is not imported, serialization of Weave Nodes is incorrect! from weave.legacy import graph_mapper as _graph_mapper -from . import storage as _storage -from .legacy import ref_base as _ref_base +from .. import storage as _storage +from . import ref_base as _ref_base from weave.legacy import wandb_api as _wandb_api -from . import weave_internal as _weave_internal +from .. import weave_internal as _weave_internal -from . import util as _util +from .. import util as _util from weave.legacy import context as _context -from . import weave_init as _weave_init -from .trace import weave_client as _weave_client +from .. import weave_init as _weave_init +from ..trace import weave_client as _weave_client # exposed as part of api -from . import weave_types as types +from .. import weave_types as types # needed to enable automatic numpy serialization -from .legacy import types_numpy as _types_numpy +from . import types_numpy as _types_numpy -from . import errors +from .. import errors from weave.legacy.decorators import weave_class, mutation, type from weave.legacy import usage_analytics @@ -44,7 +44,7 @@ # TODO: This is here because the op overloaded... from weave.trace.op import op # noqa: F401 -def save(node_or_obj, name=None): +def save(node_or_obj, name=None): # type: ignore from weave.legacy.ops_primitives.weave_api import get, save if isinstance(node_or_obj, _graph.Node): @@ -68,20 +68,20 @@ def save(node_or_obj, name=None): return get(str(uri)) -def get(ref_str): +def get(ref_str): # type: ignore obj = _storage.get(ref_str) ref = typing.cast(_ref_base.Ref, _storage._get_ref(obj)) return _weave_internal.make_const_node(ref.type, obj) -def use(nodes, client=None): +def use(nodes, client=None): # type: ignore usage_analytics.use_called() if client is None: client = _context.get_client() return _weave_internal.use(nodes, client) -def _get_ref(obj): +def _get_ref(obj): # type: ignore if isinstance(obj, _storage.Ref): return obj ref = _storage.get_ref(obj) @@ -90,7 +90,7 @@ def _get_ref(obj): return ref -def versions(obj): +def versions(obj): # type: ignore if isinstance(obj, _graph.ConstNode): obj = obj.val elif isinstance(obj, _graph.OutputNode): @@ -99,12 +99,12 @@ def versions(obj): return ref.versions() # type: ignore -def expr(obj): +def expr(obj): # type: ignore ref = _get_ref(obj) return _trace.get_obj_expr(ref) -def type_of(obj: typing.Any) -> types.Type: +def type_of(obj: typing.Any) -> types.Type: # type: ignore return types.TypeRegistry.type_of(obj) @@ -112,7 +112,7 @@ def type_of(obj: typing.Any) -> types.Type: # return _weave_internal.make_const_node(type_of(obj), obj) # type: ignore -def from_pandas(df): +def from_pandas(df): # type: ignore return _ops.pandas_to_awl(df) diff --git a/weave/legacy/arrow/convert.py b/weave/legacy/arrow/convert.py index ac88fae971c..d4e41d2e16b 100644 --- a/weave/legacy/arrow/convert.py +++ b/weave/legacy/arrow/convert.py @@ -3,7 +3,7 @@ import pyarrow as pa import pyarrow.compute as pc -from weave import query_api as api +from weave.legacy import api as api from weave import errors, weave_internal from weave import weave_types as types from weave.legacy import arrow_util, artifact_base, artifact_mem, box, mappers_arrow diff --git a/weave/legacy/ecosystem/root.py b/weave/legacy/ecosystem/root.py index 38cd09d3e7e..6e67b1e8413 100644 --- a/weave/legacy/ecosystem/root.py +++ b/weave/legacy/ecosystem/root.py @@ -1,6 +1,6 @@ import typing -from weave import query_api as weave +from weave.legacy import api as weave # TODO: Fix, these should be available from weave from weave.legacy import context_state, op_def, ops, panel, panels diff --git a/weave/legacy/op_def.py b/weave/legacy/op_def.py index 0dba3ed28e3..8784906cc06 100644 --- a/weave/legacy/op_def.py +++ b/weave/legacy/op_def.py @@ -358,7 +358,7 @@ def _replace_var_with_val(n): tracer = engine_trace.tracer() # type: ignore with tracer.trace("refine.%s" % _self.uri): # api's use auto-creates client. TODO: Fix inline import - from weave import query_api as api + from weave.legacy import api as api final_output_type = api.use(called_refine_output_type) # type: ignore if final_output_type == None: diff --git a/weave/legacy/ops_arrow/convert_ops.py b/weave/legacy/ops_arrow/convert_ops.py index 8f24c10321c..af7c3fc7273 100644 --- a/weave/legacy/ops_arrow/convert_ops.py +++ b/weave/legacy/ops_arrow/convert_ops.py @@ -1,5 +1,5 @@ from weave import weave_types as types -from weave.query_api import op +from weave.legacy.api import op from weave.legacy.arrow import convert from weave.legacy.arrow.arrow import ArrowWeaveListType diff --git a/weave/legacy/ops_arrow/date.py b/weave/legacy/ops_arrow/date.py index 54056ed82ec..f8b3d36c281 100644 --- a/weave/legacy/ops_arrow/date.py +++ b/weave/legacy/ops_arrow/date.py @@ -4,7 +4,7 @@ import pyarrow.compute as pc from weave import weave_types as types -from weave.query_api import op +from weave.legacy.api import op from weave.legacy import timestamp as weave_timestamp from weave.legacy.arrow.list_ import ArrowWeaveList, ArrowWeaveListType from weave.legacy.decorator_arrow_op import arrow_op diff --git a/weave/legacy/ops_arrow/list_join.py b/weave/legacy/ops_arrow/list_join.py index 6c7c34f7f1d..3fd533ed54e 100644 --- a/weave/legacy/ops_arrow/list_join.py +++ b/weave/legacy/ops_arrow/list_join.py @@ -6,7 +6,7 @@ from weave.legacy import engine_trace from weave import weave_types as types -from weave.query_api import op +from weave.legacy.api import op from weave.legacy import graph from weave.legacy.arrow import convert from weave.legacy.arrow.arrow import ( diff --git a/weave/legacy/ops_arrow/list_ops.py b/weave/legacy/ops_arrow/list_ops.py index 582658f8413..7e9308f3330 100644 --- a/weave/legacy/ops_arrow/list_ops.py +++ b/weave/legacy/ops_arrow/list_ops.py @@ -8,7 +8,7 @@ import pyarrow.compute as pc from weave import weave_types as types -from weave.query_api import op, type_of +from weave.legacy.api import op, type_of from weave.legacy import op_args, op_def from weave.legacy.arrow import arrow_tags, convert from weave.legacy.arrow.arrow import ( diff --git a/weave/legacy/ops_arrow/list_range.py b/weave/legacy/ops_arrow/list_range.py index c0b80e19b98..809faae2918 100644 --- a/weave/legacy/ops_arrow/list_range.py +++ b/weave/legacy/ops_arrow/list_range.py @@ -3,7 +3,7 @@ import pyarrow as pa from weave import weave_types as types -from weave.query_api import op +from weave.legacy.api import op from weave.legacy.arrow.list_ import ArrowWeaveList py_range = range diff --git a/weave/legacy/ops_arrow/number.py b/weave/legacy/ops_arrow/number.py index 383b3e456cc..3327c4222c3 100644 --- a/weave/legacy/ops_arrow/number.py +++ b/weave/legacy/ops_arrow/number.py @@ -5,7 +5,7 @@ import pyarrow.compute as pc from weave import weave_types as types -from weave.query_api import op +from weave.legacy.api import op from weave.legacy import timestamp as weave_timestamp from weave.legacy.arrow.list_ import ArrowWeaveList, ArrowWeaveListType from weave.legacy.decorator_arrow_op import arrow_op diff --git a/weave/legacy/ops_arrow/string.py b/weave/legacy/ops_arrow/string.py index 40eea66dfd7..a74db7d2550 100644 --- a/weave/legacy/ops_arrow/string.py +++ b/weave/legacy/ops_arrow/string.py @@ -4,7 +4,7 @@ import pyarrow.compute as pc from weave import weave_types as types -from weave.query_api import op +from weave.legacy.api import op from weave.legacy.arrow.arrow import ArrowWeaveListType, offsets_starting_at_zero from weave.legacy.arrow.list_ import ArrowWeaveList, ArrowWeaveListType from weave.legacy.decorator_arrow_op import arrow_op diff --git a/weave/legacy/ops_arrow/vectorize.py b/weave/legacy/ops_arrow/vectorize.py index 8f3a11a2452..0c9489397b8 100644 --- a/weave/legacy/ops_arrow/vectorize.py +++ b/weave/legacy/ops_arrow/vectorize.py @@ -12,7 +12,7 @@ ) from weave.legacy import weavify, registry_mem from weave import weave_types as types -from weave.query_api import op, use +from weave.legacy.api import op, use from weave.legacy import dispatch, graph, graph_debug, op_args, op_def from weave.legacy.arrow import convert from weave.legacy.arrow.arrow import ArrowWeaveListType diff --git a/weave/legacy/ops_domain/artifact_alias_ops.py b/weave/legacy/ops_domain/artifact_alias_ops.py index 7a65a5327eb..4d93dbfbc07 100644 --- a/weave/legacy/ops_domain/artifact_alias_ops.py +++ b/weave/legacy/ops_domain/artifact_alias_ops.py @@ -1,5 +1,5 @@ from weave import weave_types as types -from weave.query_api import op +from weave.legacy.api import op from weave.legacy.gql_op_plugin import wb_gql_op_plugin from weave.legacy.language_features.tagging.make_tag_getter_op import ( make_tag_getter_op, diff --git a/weave/legacy/ops_domain/artifact_collection_ops.py b/weave/legacy/ops_domain/artifact_collection_ops.py index 4e897eff4fa..2ca057618dc 100644 --- a/weave/legacy/ops_domain/artifact_collection_ops.py +++ b/weave/legacy/ops_domain/artifact_collection_ops.py @@ -3,7 +3,7 @@ from weave import errors from weave import weave_types as types -from weave.query_api import op +from weave.legacy.api import op from weave.legacy.gql_op_plugin import wb_gql_op_plugin from weave.legacy.ops_domain import wb_domain_types as wdt from weave.legacy.ops_domain.wandb_domain_gql import ( diff --git a/weave/legacy/ops_domain/artifact_membership_ops.py b/weave/legacy/ops_domain/artifact_membership_ops.py index 02127ed3bb0..ed17d75006c 100644 --- a/weave/legacy/ops_domain/artifact_membership_ops.py +++ b/weave/legacy/ops_domain/artifact_membership_ops.py @@ -1,7 +1,7 @@ import urllib from weave import weave_types as types -from weave.query_api import op +from weave.legacy.api import op from weave.legacy.gql_op_plugin import wb_gql_op_plugin from weave.legacy.ops_domain import wb_domain_types as wdt from weave.legacy.ops_domain.wandb_domain_gql import ( diff --git a/weave/legacy/ops_domain/artifact_type_ops.py b/weave/legacy/ops_domain/artifact_type_ops.py index 05260e6a034..d29445538d7 100644 --- a/weave/legacy/ops_domain/artifact_type_ops.py +++ b/weave/legacy/ops_domain/artifact_type_ops.py @@ -1,7 +1,7 @@ import typing from weave import weave_types as types -from weave.query_api import op +from weave.legacy.api import op from weave.legacy.gql_op_plugin import wb_gql_op_plugin from weave.legacy.ops_domain import wb_domain_types as wdt from weave.legacy.ops_domain.wandb_domain_gql import ( diff --git a/weave/legacy/ops_domain/artifact_version_ops.py b/weave/legacy/ops_domain/artifact_version_ops.py index 020cc3987ab..cc13aa5d84e 100644 --- a/weave/legacy/ops_domain/artifact_version_ops.py +++ b/weave/legacy/ops_domain/artifact_version_ops.py @@ -4,7 +4,7 @@ from weave import errors from weave import weave_types as types -from weave.query_api import op +from weave.legacy.api import op from weave.legacy import artifact_fs, artifact_wandb, input_provider from weave.legacy.gql_op_plugin import wb_gql_op_plugin from weave.legacy.ops_domain import wb_domain_types as wdt diff --git a/weave/legacy/ops_domain/entity_ops.py b/weave/legacy/ops_domain/entity_ops.py index a4cb6248734..8a6ff598622 100644 --- a/weave/legacy/ops_domain/entity_ops.py +++ b/weave/legacy/ops_domain/entity_ops.py @@ -1,5 +1,5 @@ from weave import weave_types as types -from weave.query_api import op +from weave.legacy.api import op from weave.legacy.gql_op_plugin import wb_gql_op_plugin from weave.legacy.language_features.tagging.make_tag_getter_op import ( make_tag_getter_op, diff --git a/weave/legacy/ops_domain/project_ops.py b/weave/legacy/ops_domain/project_ops.py index b7c9c8bd337..c8f13427a8a 100644 --- a/weave/legacy/ops_domain/project_ops.py +++ b/weave/legacy/ops_domain/project_ops.py @@ -3,7 +3,7 @@ from weave import errors from weave import weave_types as types -from weave.query_api import op +from weave.legacy.api import op from weave.legacy import input_provider from weave.legacy.gql_op_plugin import wb_gql_op_plugin from weave.legacy.language_features.tagging.make_tag_getter_op import ( diff --git a/weave/legacy/ops_domain/repo_insight_ops.py b/weave/legacy/ops_domain/repo_insight_ops.py index 45ed4be0d5b..486192281eb 100644 --- a/weave/legacy/ops_domain/repo_insight_ops.py +++ b/weave/legacy/ops_domain/repo_insight_ops.py @@ -3,7 +3,7 @@ from weave import errors from weave import weave_types as types -from weave.query_api import op +from weave.legacy.api import op from weave.legacy.gql_json_cache import use_json from weave.legacy.gql_op_plugin import wb_gql_op_plugin from weave.legacy.ops_domain.wandb_domain_gql import ( diff --git a/weave/legacy/ops_domain/report_ops.py b/weave/legacy/ops_domain/report_ops.py index a8ef162bc79..3173e4f8fa2 100644 --- a/weave/legacy/ops_domain/report_ops.py +++ b/weave/legacy/ops_domain/report_ops.py @@ -4,7 +4,7 @@ from weave import errors from weave import weave_types as types -from weave.query_api import op +from weave.legacy.api import op from weave.legacy.gql_op_plugin import wb_gql_op_plugin from weave.legacy.ops_domain import wb_domain_types as wdt from weave.legacy.ops_domain.wandb_domain_gql import ( diff --git a/weave/legacy/ops_domain/run_history/history_op_common.py b/weave/legacy/ops_domain/run_history/history_op_common.py index 00821ae4d6f..fbfab866db7 100644 --- a/weave/legacy/ops_domain/run_history/history_op_common.py +++ b/weave/legacy/ops_domain/run_history/history_op_common.py @@ -9,7 +9,7 @@ util, ) from weave import weave_types as types -from weave.query_api import use +from weave.legacy.api import use from weave.legacy import ( engine_trace, registry_mem, diff --git a/weave/legacy/ops_domain/run_history/run_history_v1_legacy_ops.py b/weave/legacy/ops_domain/run_history/run_history_v1_legacy_ops.py index 0b8e97f8787..782017fd1ea 100644 --- a/weave/legacy/ops_domain/run_history/run_history_v1_legacy_ops.py +++ b/weave/legacy/ops_domain/run_history/run_history_v1_legacy_ops.py @@ -4,7 +4,7 @@ from weave.legacy import engine_trace from weave import weave_types as types -from weave.query_api import op +from weave.legacy.api import op from weave.legacy import gql_json_cache from weave.legacy.gql_op_plugin import wb_gql_op_plugin from weave.legacy.ops_domain import wb_domain_types as wdt diff --git a/weave/legacy/ops_domain/run_history/run_history_v2_parquet_media.py b/weave/legacy/ops_domain/run_history/run_history_v2_parquet_media.py index 24afe60b728..540b068fa54 100644 --- a/weave/legacy/ops_domain/run_history/run_history_v2_parquet_media.py +++ b/weave/legacy/ops_domain/run_history/run_history_v2_parquet_media.py @@ -8,7 +8,7 @@ from weave.legacy import engine_trace from weave import weave_types as types -from weave.query_api import op, use +from weave.legacy.api import op, use from weave.legacy import artifact_mem, gql_json_cache from weave.legacy.arrow import convert from weave.legacy.arrow.list_ import ArrowWeaveList, ArrowWeaveListType diff --git a/weave/legacy/ops_domain/run_history/run_history_v3_parquet_stream_optimized.py b/weave/legacy/ops_domain/run_history/run_history_v3_parquet_stream_optimized.py index 0412c764fdd..6b61d141ac0 100644 --- a/weave/legacy/ops_domain/run_history/run_history_v3_parquet_stream_optimized.py +++ b/weave/legacy/ops_domain/run_history/run_history_v3_parquet_stream_optimized.py @@ -7,7 +7,7 @@ from weave import errors from weave import weave_types as types -from weave.query_api import op +from weave.legacy.api import op from weave.legacy import ( engine_trace, artifact_base, diff --git a/weave/legacy/ops_domain/run_ops.py b/weave/legacy/ops_domain/run_ops.py index 1699c8d4e0b..4c73766d9a4 100644 --- a/weave/legacy/ops_domain/run_ops.py +++ b/weave/legacy/ops_domain/run_ops.py @@ -39,7 +39,7 @@ from weave.legacy import engine_trace from weave import weave_types as types -from weave.query_api import op +from weave.legacy.api import op from weave.legacy import compile_table from weave.legacy.gql_op_plugin import wb_gql_op_plugin from weave.legacy.input_provider import InputAndStitchProvider diff --git a/weave/legacy/ops_domain/run_queue_ops.py b/weave/legacy/ops_domain/run_queue_ops.py index 4c5e51be661..d0f7c72d185 100644 --- a/weave/legacy/ops_domain/run_queue_ops.py +++ b/weave/legacy/ops_domain/run_queue_ops.py @@ -1,7 +1,7 @@ import json from weave import weave_types as types -from weave.query_api import op +from weave.legacy.api import op from weave.legacy.gql_op_plugin import wb_gql_op_plugin from weave.legacy.language_features.tagging.make_tag_getter_op import ( make_tag_getter_op, diff --git a/weave/legacy/ops_domain/run_segment.py b/weave/legacy/ops_domain/run_segment.py index d2382b95634..02d09567744 100644 --- a/weave/legacy/ops_domain/run_segment.py +++ b/weave/legacy/ops_domain/run_segment.py @@ -4,7 +4,7 @@ import weave from weave import weave_types as types -from weave.query_api import Node, get, use +from weave.legacy.api import Node, get, use from weave.legacy import context_state as _context from weave.legacy import panels from weave.legacy.ops_arrow import ArrowWeaveList, ArrowWeaveListType diff --git a/weave/legacy/ops_domain/stream_table_ops.py b/weave/legacy/ops_domain/stream_table_ops.py index 8b593d17c82..ca9c867ebd6 100644 --- a/weave/legacy/ops_domain/stream_table_ops.py +++ b/weave/legacy/ops_domain/stream_table_ops.py @@ -1,5 +1,5 @@ from weave import weave_types -from weave.query_api import op +from weave.legacy.api import op from weave.legacy import compile, op_def from weave.legacy.arrow.arrow import ArrowWeaveListType from weave.legacy.core_types import StreamTableType diff --git a/weave/legacy/ops_domain/table.py b/weave/legacy/ops_domain/table.py index d7c6b72e146..ba5dcddf7e0 100644 --- a/weave/legacy/ops_domain/table.py +++ b/weave/legacy/ops_domain/table.py @@ -7,7 +7,7 @@ from weave import errors, util, weave_internal from weave import weave_types as types -from weave.query_api import op, weave_class +from weave.legacy.api import op, weave_class from weave.legacy import ( artifact_fs, artifact_wandb, diff --git a/weave/legacy/ops_domain/trace_tree.py b/weave/legacy/ops_domain/trace_tree.py index e4f618eafa8..5a8487652f6 100644 --- a/weave/legacy/ops_domain/trace_tree.py +++ b/weave/legacy/ops_domain/trace_tree.py @@ -11,7 +11,7 @@ from wandb.sdk.data_types.trace_tree import Result as WBSpanResult from wandb.sdk.data_types.trace_tree import Span as WBSpan -from weave import query_api as weave +from weave.legacy import api as weave from weave.legacy import stream_data_interfaces from weave import weave_types as types from weave.legacy import op_def diff --git a/weave/legacy/ops_domain/user_ops.py b/weave/legacy/ops_domain/user_ops.py index 19a3f9c3dc6..f9b77f4f4f2 100644 --- a/weave/legacy/ops_domain/user_ops.py +++ b/weave/legacy/ops_domain/user_ops.py @@ -1,5 +1,5 @@ from weave import weave_types as types -from weave.query_api import op +from weave.legacy.api import op from weave.legacy.gql_op_plugin import wb_gql_op_plugin from weave.legacy.language_features.tagging.make_tag_getter_op import ( make_tag_getter_op, diff --git a/weave/legacy/ops_domain/wandb_domain_gql.py b/weave/legacy/ops_domain/wandb_domain_gql.py index 129d4047fa7..2f8601a2f32 100644 --- a/weave/legacy/ops_domain/wandb_domain_gql.py +++ b/weave/legacy/ops_domain/wandb_domain_gql.py @@ -5,7 +5,7 @@ import pyarrow as pa from weave import errors, weave_types -from weave.query_api import op +from weave.legacy.api import op from weave.legacy import gql_op_plugin, op_def, partial_object from weave.legacy.decorator_arrow_op import arrow_op from weave.legacy.gql_op_plugin import wb_gql_op_plugin diff --git a/weave/legacy/ops_domain/wbgqlquery_op.py b/weave/legacy/ops_domain/wbgqlquery_op.py index 24dc73e3f8b..662fbc339bc 100644 --- a/weave/legacy/ops_domain/wbgqlquery_op.py +++ b/weave/legacy/ops_domain/wbgqlquery_op.py @@ -3,7 +3,7 @@ from weave import environment, errors from weave import weave_types as types -from weave.query_api import op +from weave.legacy.api import op from weave.legacy import engine_trace, mappers_gql, partial_object from weave.legacy.language_features.tagging import tagged_value_type from weave.legacy.ops_domain import wb_domain_types as wdt diff --git a/weave/legacy/ops_domain/wbmedia.py b/weave/legacy/ops_domain/wbmedia.py index 34674731e97..12683e376e1 100644 --- a/weave/legacy/ops_domain/wbmedia.py +++ b/weave/legacy/ops_domain/wbmedia.py @@ -4,7 +4,7 @@ import json import typing -from weave import query_api as weave +from weave.legacy import api as weave from weave import errors, types from weave.legacy import engine_trace, artifact_fs, file_base from weave.legacy.language_features.tagging.tag_store import isolated_tagging_context diff --git a/weave/legacy/ops_primitives/artifacts.py b/weave/legacy/ops_primitives/artifacts.py index d05c9223c8b..de1e0e0ffa9 100644 --- a/weave/legacy/ops_primitives/artifacts.py +++ b/weave/legacy/ops_primitives/artifacts.py @@ -3,7 +3,7 @@ import pathlib import typing -from weave.query_api import op +from weave.legacy.api import op from weave import types from weave.legacy import artifact_fs, ref_base from weave.legacy.artifact_local import WORKING_DIR_PREFIX, LocalArtifact diff --git a/weave/legacy/ops_primitives/boolean.py b/weave/legacy/ops_primitives/boolean.py index 7325bbffb69..531faf43076 100644 --- a/weave/legacy/ops_primitives/boolean.py +++ b/weave/legacy/ops_primitives/boolean.py @@ -1,7 +1,7 @@ import typing from weave import weave_types as types -from weave.query_api import op, weave_class +from weave.legacy.api import op, weave_class from weave.legacy import dispatch from weave.legacy.ops_primitives.dict import dict_ diff --git a/weave/legacy/ops_primitives/csv_.py b/weave/legacy/ops_primitives/csv_.py index 046ecd20fbd..b5f4fe460fb 100644 --- a/weave/legacy/ops_primitives/csv_.py +++ b/weave/legacy/ops_primitives/csv_.py @@ -3,7 +3,7 @@ import pyarrow as pa import pyarrow.csv as pa_csv -from weave import query_api as weave +from weave.legacy import api as weave from weave.legacy import file_base diff --git a/weave/legacy/ops_primitives/date.py b/weave/legacy/ops_primitives/date.py index f564a0553d8..073014b593d 100644 --- a/weave/legacy/ops_primitives/date.py +++ b/weave/legacy/ops_primitives/date.py @@ -5,7 +5,7 @@ import dateutil.parser from weave import weave_types as types -from weave.query_api import op, type +from weave.legacy.api import op, type @op( diff --git a/weave/legacy/ops_primitives/file.py b/weave/legacy/ops_primitives/file.py index 8d891465390..fdc4ea7908e 100644 --- a/weave/legacy/ops_primitives/file.py +++ b/weave/legacy/ops_primitives/file.py @@ -4,7 +4,7 @@ from weave import environment as weave_env from weave import errors from weave import weave_types as types -from weave.query_api import op +from weave.legacy.api import op from weave.legacy import file_base, wandb_file_manager from weave.legacy.artifact_fs import FilesystemArtifactDir, FilesystemArtifactFile from weave.legacy.artifact_wandb import WandbArtifact, WandbArtifactManifest diff --git a/weave/legacy/ops_primitives/file_artifact.py b/weave/legacy/ops_primitives/file_artifact.py index 2f6ee716d23..203e2486241 100644 --- a/weave/legacy/ops_primitives/file_artifact.py +++ b/weave/legacy/ops_primitives/file_artifact.py @@ -1,6 +1,6 @@ import typing -from weave.query_api import op +from weave.legacy.api import op from weave.legacy import artifact_fs diff --git a/weave/legacy/ops_primitives/file_local.py b/weave/legacy/ops_primitives/file_local.py index a867967ba6f..45940d7500c 100644 --- a/weave/legacy/ops_primitives/file_local.py +++ b/weave/legacy/ops_primitives/file_local.py @@ -3,7 +3,7 @@ from weave import environment from weave import weave_types as types -from weave.query_api import op +from weave.legacy.api import op from weave.legacy import file_local diff --git a/weave/legacy/ops_primitives/geom.py b/weave/legacy/ops_primitives/geom.py index 4d209192b1c..e0931c1bd39 100644 --- a/weave/legacy/ops_primitives/geom.py +++ b/weave/legacy/ops_primitives/geom.py @@ -1,6 +1,6 @@ from PIL import Image -from weave import query_api as weave +from weave.legacy import api as weave @weave.type() diff --git a/weave/legacy/ops_primitives/html.py b/weave/legacy/ops_primitives/html.py index 4126d3dda33..358b9e7d0dd 100644 --- a/weave/legacy/ops_primitives/html.py +++ b/weave/legacy/ops_primitives/html.py @@ -1,6 +1,6 @@ import dataclasses -from weave import query_api as weave +from weave.legacy import api as weave from weave import weave_types as types diff --git a/weave/legacy/ops_primitives/image.py b/weave/legacy/ops_primitives/image.py index 5fb9eefcabb..64ea6ace2d5 100644 --- a/weave/legacy/ops_primitives/image.py +++ b/weave/legacy/ops_primitives/image.py @@ -5,7 +5,7 @@ import PIL import PIL.Image -from weave import query_api as weave +from weave.legacy import api as weave from weave import weave_types as types diff --git a/weave/legacy/ops_primitives/json_.py b/weave/legacy/ops_primitives/json_.py index 86cb21ea4e4..5cefb079741 100644 --- a/weave/legacy/ops_primitives/json_.py +++ b/weave/legacy/ops_primitives/json_.py @@ -1,7 +1,7 @@ import json import typing -from weave import query_api as weave +from weave.legacy import api as weave from weave.legacy import file_base diff --git a/weave/legacy/ops_primitives/markdown.py b/weave/legacy/ops_primitives/markdown.py index a7e7a601c10..1f685c65279 100644 --- a/weave/legacy/ops_primitives/markdown.py +++ b/weave/legacy/ops_primitives/markdown.py @@ -1,6 +1,6 @@ import dataclasses -from weave import query_api as weave +from weave.legacy import api as weave from weave import weave_types as types diff --git a/weave/legacy/ops_primitives/number.py b/weave/legacy/ops_primitives/number.py index 6b1889dff50..bddd25b7fca 100644 --- a/weave/legacy/ops_primitives/number.py +++ b/weave/legacy/ops_primitives/number.py @@ -5,7 +5,7 @@ import numpy as np from weave import weave_types as types -from weave.query_api import op, weave_class +from weave.legacy.api import op, weave_class from weave.legacy import timestamp as weave_timestamp binary_number_op_input_type = { diff --git a/weave/legacy/ops_primitives/number_bin.py b/weave/legacy/ops_primitives/number_bin.py index 3d5c82d4ef3..5213ce95d21 100644 --- a/weave/legacy/ops_primitives/number_bin.py +++ b/weave/legacy/ops_primitives/number_bin.py @@ -1,7 +1,7 @@ import math from weave import weave_types as types -from weave.query_api import op, use +from weave.legacy.api import op, use from weave.legacy import graph from weave.legacy.ops_primitives import date from weave.legacy.ops_primitives.dict import dict_ diff --git a/weave/legacy/ops_primitives/obj.py b/weave/legacy/ops_primitives/obj.py index 605d432f633..b05ae9a9d28 100644 --- a/weave/legacy/ops_primitives/obj.py +++ b/weave/legacy/ops_primitives/obj.py @@ -2,7 +2,7 @@ from weave.legacy import codify from weave import weave_types as types -from weave.query_api import op, weave_class +from weave.legacy.api import op, weave_class # This matches the output type logic of the frontend diff --git a/weave/legacy/ops_primitives/op_def.py b/weave/legacy/ops_primitives/op_def.py index 51d251543e7..48e4253c6dd 100644 --- a/weave/legacy/ops_primitives/op_def.py +++ b/weave/legacy/ops_primitives/op_def.py @@ -1,4 +1,4 @@ -from weave import query_api as weave +from weave.legacy import api as weave from weave import weave_types as types from weave.legacy.op_def import OpDef from weave.legacy.op_def_type import OpDefType diff --git a/weave/legacy/ops_primitives/pandas_.py b/weave/legacy/ops_primitives/pandas_.py index f85f0c0ff5c..3a0b5cad83b 100644 --- a/weave/legacy/ops_primitives/pandas_.py +++ b/weave/legacy/ops_primitives/pandas_.py @@ -10,7 +10,7 @@ from weave import errors from weave import weave_types as types -from weave.query_api import op, weave_class +from weave.legacy.api import op, weave_class from weave.legacy import box, file_base, graph, mappers_python from weave.legacy.language_features.tagging import tag_store, tagged_value_type from weave.legacy.ops_primitives import list_ diff --git a/weave/legacy/ops_primitives/random_junk.py b/weave/legacy/ops_primitives/random_junk.py index dabf751a7a6..b1bc875fd6a 100644 --- a/weave/legacy/ops_primitives/random_junk.py +++ b/weave/legacy/ops_primitives/random_junk.py @@ -1,8 +1,8 @@ # Ideas for ops, but not production ready. -from weave import query_api as api +from weave.legacy import api as api from weave import weave_types as types -from weave.query_api import op, weave_class +from weave.legacy.api import op, weave_class op( name="root-compare_versions", diff --git a/weave/legacy/ops_primitives/sql.py b/weave/legacy/ops_primitives/sql.py index 9d3d47caed2..3e179f727d2 100644 --- a/weave/legacy/ops_primitives/sql.py +++ b/weave/legacy/ops_primitives/sql.py @@ -3,7 +3,7 @@ import math from weave import weave_types as types -from weave.query_api import op, weave_class +from weave.legacy.api import op, weave_class from weave.legacy import decorator_type from weave.legacy.language_features.tagging import tagged_value_type from weave.legacy.ops_primitives import graph, list_ diff --git a/weave/legacy/ops_primitives/string.py b/weave/legacy/ops_primitives/string.py index 725412935a6..fbfa4aaec97 100644 --- a/weave/legacy/ops_primitives/string.py +++ b/weave/legacy/ops_primitives/string.py @@ -5,7 +5,7 @@ import numpy as np from weave import weave_types as types -from weave.query_api import op, weave_class +from weave.legacy.api import op, weave_class @op(name="root-string") diff --git a/weave/legacy/ops_primitives/test_any.py b/weave/legacy/ops_primitives/test_any.py index cf684080f8b..4fd7cd14952 100644 --- a/weave/legacy/ops_primitives/test_any.py +++ b/weave/legacy/ops_primitives/test_any.py @@ -2,7 +2,7 @@ import pytest -from weave import query_api as weave +from weave.legacy import api as weave from weave.legacy import box from weave.legacy.ops_primitives import any diff --git a/weave/legacy/ops_primitives/test_list.py b/weave/legacy/ops_primitives/test_list.py index 8112979d6f9..a2478617749 100644 --- a/weave/legacy/ops_primitives/test_list.py +++ b/weave/legacy/ops_primitives/test_list.py @@ -1,6 +1,6 @@ import pytest -from weave import query_api as weave +from weave.legacy import api as weave from weave import weave_internal from weave import weave_types as types from weave.legacy import box diff --git a/weave/legacy/ops_primitives/test_pandas.py b/weave/legacy/ops_primitives/test_pandas.py index 5b8afe76f49..2b0dc05a6b5 100644 --- a/weave/legacy/ops_primitives/test_pandas.py +++ b/weave/legacy/ops_primitives/test_pandas.py @@ -1,6 +1,6 @@ import pandas as pd -from weave import query_api as weave +from weave.legacy import api as weave from weave import weave_types as types from weave.legacy.ops_primitives import pandas_ as op_pandas diff --git a/weave/legacy/ops_primitives/timestamp_bin.py b/weave/legacy/ops_primitives/timestamp_bin.py index 9b0614d0019..55bd192de55 100644 --- a/weave/legacy/ops_primitives/timestamp_bin.py +++ b/weave/legacy/ops_primitives/timestamp_bin.py @@ -1,6 +1,6 @@ from weave import weave_internal from weave import weave_types as types -from weave.query_api import op, use +from weave.legacy.api import op, use from weave.legacy import graph from weave.legacy.ops_primitives.dict import dict_ from weave.weave_internal import call_fn, define_fn, make_const_node diff --git a/weave/legacy/ops_primitives/type.py b/weave/legacy/ops_primitives/type.py index 8fc1f311e5d..e4364746014 100644 --- a/weave/legacy/ops_primitives/type.py +++ b/weave/legacy/ops_primitives/type.py @@ -2,7 +2,7 @@ from weave import errors from weave import weave_types as types -from weave.query_api import op +from weave.legacy.api import op @op( diff --git a/weave/legacy/ops_primitives/weave_api.py b/weave/legacy/ops_primitives/weave_api.py index d59113a2997..fb66f04b55f 100644 --- a/weave/legacy/ops_primitives/weave_api.py +++ b/weave/legacy/ops_primitives/weave_api.py @@ -8,7 +8,7 @@ weave_internal, ) from weave import weave_types as types -from weave.query_api import mutation, op, weave_class +from weave.legacy.api import mutation, op, weave_class from weave.legacy import ( ref_base, registry_mem, diff --git a/weave/legacy/panel.py b/weave/legacy/panel.py index 094c90c9339..858bc39eeee 100644 --- a/weave/legacy/panel.py +++ b/weave/legacy/panel.py @@ -3,7 +3,7 @@ import typing from tarfile import DEFAULT_FORMAT -from weave import query_api as weave +from weave.legacy import api as weave from weave import errors, storage, weave_internal from weave import weave_types as types from weave.legacy import graph, panel_util diff --git a/weave/tests/legacy/test_mappers_python.py b/weave/tests/legacy/test_mappers_python.py index c343007453c..f614a147716 100644 --- a/weave/tests/legacy/test_mappers_python.py +++ b/weave/tests/legacy/test_mappers_python.py @@ -1,8 +1,8 @@ import math -from weave import query_api, weave_internal +from weave import weave_internal from weave import weave_types as types -from weave.legacy import context, mappers_python, val_const +from weave.legacy import api, context, mappers_python, val_const def test_map_typed_dict(): diff --git a/weave/tests/legacy/test_op.py b/weave/tests/legacy/test_op.py index bfa2271e8e5..855b6555b84 100644 --- a/weave/tests/legacy/test_op.py +++ b/weave/tests/legacy/test_op.py @@ -2,8 +2,8 @@ import pytest -from weave import query_api as weave from weave import storage, types, weave_internal +from weave.legacy import api as weave from weave.legacy import context_state, graph, uris from weave.legacy import context_state as _context_state diff --git a/weave/tests/legacy/test_serialize.py b/weave/tests/legacy/test_serialize.py index 3ce4594856f..7d86ec3b176 100644 --- a/weave/tests/legacy/test_serialize.py +++ b/weave/tests/legacy/test_serialize.py @@ -1,9 +1,9 @@ import pytest import weave -from weave import query_api as api from weave import weave_internal from weave import weave_types as types +from weave.legacy import api as api from weave.legacy import graph, op_args, ops, registry_mem, serialize from weave.legacy.ops_primitives import list_ from weave.weave_internal import make_const_node diff --git a/weave/tests/legacy/test_wb.py b/weave/tests/legacy/test_wb.py index 20988988982..9ac6a28f801 100644 --- a/weave/tests/legacy/test_wb.py +++ b/weave/tests/legacy/test_wb.py @@ -6,8 +6,8 @@ import pytest import wandb -from weave import query_api as weave from weave import weave_types as types +from weave.legacy import api as weave from weave.legacy import artifact_fs, artifact_wandb, compile, graph, ops, stitch, uris from weave.legacy import ops_arrow as arrow from weave.legacy.language_features.tagging.tagged_value_type import TaggedValueType From 462be706e38a7d4973625ea277dac255b250ce18 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 10:24:05 -0400 Subject: [PATCH 35/84] move to legacy: server --- weave/cli.py | 2 +- weave/legacy/context.py | 12 +++--- .../test_notebook_ecosystem_executions.py | 2 +- weave/{ => legacy}/server.py | 42 +++++++++---------- weave/tests/legacy/test_execution_graphs.py | 2 +- weave/tests/legacy/test_logging.py | 4 +- weave/tests/trace/test_server.py | 2 +- weave/weave_server.py | 2 +- 8 files changed, 34 insertions(+), 34 deletions(-) rename weave/{ => legacy}/server.py (88%) diff --git a/weave/cli.py b/weave/cli.py index 88681374dbc..8975d0da554 100644 --- a/weave/cli.py +++ b/weave/cli.py @@ -26,7 +26,7 @@ def cli() -> None: # def start_ui() -> None: # print("Starting server...") # try: -# from weave import server +# from weave.legacy import server # except ModuleNotFoundError: # print("Run 'pip install weave[engine]' to use the local server.") # sys.exit(1) diff --git a/weave/legacy/context.py b/weave/legacy/context.py index 679a6ad6b09..1dfb3fab302 100644 --- a/weave/legacy/context.py +++ b/weave/legacy/context.py @@ -12,7 +12,7 @@ @contextlib.contextmanager def execution_client(): """Returns a client for use by the execution engine and op resolvers.""" - from weave import server + from weave.legacy import server # Force in process execution with context_state.client(client.NonCachingClient(server.InProcessServer())): @@ -22,7 +22,7 @@ def execution_client(): @contextlib.contextmanager def local_http_client(): - from weave import server + from weave.legacy import server s = server.HttpServer() s.start() @@ -34,7 +34,7 @@ def local_http_client(): @contextlib.contextmanager def weavejs_client(): - from weave import server + from weave.legacy import server s = server.HttpServer() s.start() @@ -48,7 +48,7 @@ def use_fixed_server_port(): # s = server.HttpServer(port=9994) # s.start() # _weave_client.set(server.HttpServerClient(s.url)) - from weave import server + from weave.legacy import server context_state.set_client(server.HttpServerClient("http://localhost:9994")) @@ -70,7 +70,7 @@ def use_lazy_execution(): def _make_default_client(): - from weave import server + from weave.legacy import server if util.is_notebook(): serv = context_state.get_server() @@ -105,7 +105,7 @@ def get_client() -> typing.Optional[ClientInterface]: def get_frontend_url(): - from weave import server + from weave.legacy import server url = os.environ.get("WEAVE_FRONTEND_URL", context_state.get_frontend_url()) if url is None: diff --git a/weave/legacy/ecosystem/test_notebook_ecosystem_executions.py b/weave/legacy/ecosystem/test_notebook_ecosystem_executions.py index 60e8cada808..9d4e9bbfebb 100644 --- a/weave/legacy/ecosystem/test_notebook_ecosystem_executions.py +++ b/weave/legacy/ecosystem/test_notebook_ecosystem_executions.py @@ -1,4 +1,4 @@ -from weave.server import handle_request +from weave.legacy.server import handle_request def test_playback(): diff --git a/weave/server.py b/weave/legacy/server.py similarity index 88% rename from weave/server.py rename to weave/legacy/server.py index 0792737639a..2e6a90fb6e7 100644 --- a/weave/server.py +++ b/weave/legacy/server.py @@ -26,7 +26,7 @@ from weave.legacy.language_features.tagging import tag_store from weave.legacy.language_features.tagging.tag_store import isolated_tagging_context -from . import logs, storage, util, weave_types +from .. import logs, storage, util, weave_types # A function to monkeypatch the request post method # def patch_request_post(): @@ -59,14 +59,14 @@ class HandleRequestResponse: nodes: value_or_error.ValueOrErrors[graph.Node] -def handle_request( +def handle_request( # type: ignore request, deref=False, serialize_fn=storage.to_python ) -> HandleRequestResponse: # Stuff in the server path relies on lazy execution. Eager is now the default # in the weave package itself, so we need to switch to lazy mode here. with context.lazy_execution(): start_time = time.time() - tracer = engine_trace.tracer() + tracer = engine_trace.tracer() # type: ignore[no-untyped-call] # Need to add wandb_api.from_environment, which sets up the wandb api # The existing code only did this within the execute() function. But now # I'm hitting the need for this in deserialize, because node_id in deserialize @@ -90,7 +90,7 @@ def handle_request( result = result.zip(nodes).safe_map( lambda t: t[0] if isinstance(t[1].type, weave_types.RefType) - else storage.deref(t[0]) + else storage.deref(t[0]) # type: ignore[no-untyped-call] ) # print("Server request %s (%0.5fs): %s..." % (start_time, @@ -110,12 +110,12 @@ def handle_request( class SubprocessServer(multiprocessing.Process): - def __init__(self, req_queue, resp_queue): + def __init__(self, req_queue, resp_queue): # type: ignore multiprocessing.Process.__init__(self) self.req_queue = req_queue self.resp_queue = resp_queue - def run(self): + def run(self): # type: ignore while True: req = self.req_queue.get() try: @@ -127,21 +127,21 @@ def run(self): self.resp_queue.put(Exception("Caught exception in sub-process server")) break - def shutdown(self): + def shutdown(self): # type: ignore self.kill() class SubprocessServerClient: - def __init__(self): + def __init__(self): # type: ignore self.req_queue = multiprocessing.Queue() self.resp_queue = multiprocessing.Queue() self.server_proc = SubprocessServer(self.req_queue, self.resp_queue) self.server_proc.start() - def shutdown(self): + def shutdown(self): # type: ignore self.server_proc.shutdown() - def execute(self, nodes, no_cache=False): + def execute(self, nodes, no_cache=False): # type: ignore self.req_queue.put({"graphs": serialize.serialize(nodes)}) response = self.resp_queue.get() deserialized = [storage.from_python(r) for r in response] @@ -149,15 +149,15 @@ def execute(self, nodes, no_cache=False): class InProcessServer(object): - def __init__(self): + def __init__(self): # type: ignore pass - def execute(self, nodes, no_cache=False): + def execute(self, nodes, no_cache=False): # type: ignore return execute.execute_nodes(nodes, no_cache=no_cache).unwrap() class HttpServerClient(object): - def __init__(self, url, emulate_weavejs=False, auth: OptionalAuthType = None): + def __init__(self, url, emulate_weavejs=False, auth: OptionalAuthType = None): # type: ignore """Constructor. Args: @@ -172,7 +172,7 @@ def __init__(self, url, emulate_weavejs=False, auth: OptionalAuthType = None): if emulate_weavejs: self.execute_endpoint = "/__weave/execute" - def execute(self, nodes, no_cache=False): + def execute(self, nodes, no_cache=False): # type: ignore serialized = serialize.serialize(nodes) r = requests.post( self.url + self.execute_endpoint, @@ -195,8 +195,8 @@ def execute(self, nodes, no_cache=False): class HttpServer(threading.Thread): - def __init__(self, port=0, host="localhost"): - from . import weave_server + def __init__(self, port=0, host="localhost"): # type: ignore + from weave import weave_server self.host = host @@ -209,10 +209,10 @@ def __init__(self, port=0, host="localhost"): self.port = self.srv.socket.getsockname()[1] @property - def name(self): + def name(self): # type: ignore return f"Weave Port: {self.port}" - def run(self): + def run(self): # type: ignore if _REQUESTED_SERVER_LOG_LEVEL is None: capture_weave_server_logs(logging.ERROR) @@ -227,11 +227,11 @@ def run(self): self.srv.serve_forever() - def shutdown(self): + def shutdown(self): # type: ignore self.srv.shutdown() @property - def url(self): + def url(self): # type: ignore if util.is_colab(): url = f"https://{self.host}" else: @@ -241,7 +241,7 @@ def url(self): return url -def capture_weave_server_logs(log_level: int = logging.INFO): +def capture_weave_server_logs(log_level: int = logging.INFO): # type: ignore global _REQUESTED_SERVER_LOG_LEVEL _REQUESTED_SERVER_LOG_LEVEL = log_level diff --git a/weave/tests/legacy/test_execution_graphs.py b/weave/tests/legacy/test_execution_graphs.py index 920489aa992..78096f659a1 100644 --- a/weave/tests/legacy/test_execution_graphs.py +++ b/weave/tests/legacy/test_execution_graphs.py @@ -5,7 +5,7 @@ from weave import storage from weave.legacy import serialize -from weave.server import handle_request +from weave.legacy.server import handle_request def test_graph_playback(dev_only_admin_env_override): diff --git a/weave/tests/legacy/test_logging.py b/weave/tests/legacy/test_logging.py index 3be54e5940a..310c95d6cfb 100644 --- a/weave/tests/legacy/test_logging.py +++ b/weave/tests/legacy/test_logging.py @@ -4,9 +4,9 @@ import pytest import requests -from weave.legacy import context, ops +from weave.legacy import context, ops, server -from ... import api, logs, server, weave_server +from ... import api, logs, weave_server def test_logfile_created(fresh_server_logfile): diff --git a/weave/tests/trace/test_server.py b/weave/tests/trace/test_server.py index 4298adf0dea..0931eefda92 100644 --- a/weave/tests/trace/test_server.py +++ b/weave/tests/trace/test_server.py @@ -7,10 +7,10 @@ import requests from weave import api as weave -from weave import server as _server from weave import weave_types as types from weave.legacy import client as _client from weave.legacy import context_state, ops +from weave.legacy import server as _server from weave.legacy.decorator_op import op from weave.weave_internal import make_const_node diff --git a/weave/weave_server.py b/weave/weave_server.py index b9992991850..f76a27f7493 100644 --- a/weave/weave_server.py +++ b/weave/weave_server.py @@ -30,7 +30,6 @@ errors, filesystem, logs, - server, storage, util, ) @@ -39,6 +38,7 @@ engine_trace, graph, registry_mem, + server, value_or_error, wandb_api, weavejs_fixes, From e88c88b607e61105b1ee1036430c5ba8c139e7a0 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 10:04:13 -0400 Subject: [PATCH 36/84] move to legacy: environment --- weave/conftest.py | 4 ++-- weave/deploy/gcp/__init__.py | 3 ++- weave/deploy/modal/__init__.py | 2 +- weave/filesystem.py | 4 ++-- weave/legacy/artifact_local.py | 4 ++-- weave/legacy/cache.py | 4 ++-- weave/legacy/engine_trace.py | 4 ++-- weave/{ => legacy}/environment.py | 6 +++--- weave/legacy/execute.py | 2 +- weave/legacy/file_util.py | 4 ++-- weave/legacy/gql_schema.py | 2 +- weave/legacy/op_def_type.py | 4 ++-- weave/legacy/ops_domain/wbgqlquery_op.py | 4 ++-- weave/legacy/ops_primitives/file.py | 2 +- weave/legacy/ops_primitives/file_local.py | 2 +- weave/legacy/ops_primitives/projection_utils.py | 4 ++-- weave/legacy/runfiles_wandb.py | 2 +- weave/legacy/signal_handlers.py | 2 +- weave/legacy/usage_analytics.py | 2 +- weave/legacy/wandb_api.py | 2 +- weave/legacy/wandb_file_manager.py | 2 +- weave/legacy/wandb_interface/wandb_stream_table.py | 3 ++- weave/logs.py | 2 +- weave/tests/legacy/test_access.py | 4 ++-- weave/tests/legacy/test_cache.py | 3 +-- weave/tests/legacy/test_execute.py | 4 ++-- weave/tests/legacy/test_file.py | 4 ++-- weave/tests/legacy/test_filesystem.py | 4 +++- weave/trace/op_type.py | 3 ++- weave/trace_server/remote_http_trace_server.py | 2 +- weave/urls.py | 4 +--- weave/weave_server.py | 2 +- 32 files changed, 51 insertions(+), 49 deletions(-) rename weave/{ => legacy}/environment.py (99%) diff --git a/weave/conftest.py b/weave/conftest.py index 9ff85968cc8..c11f8c7a41e 100644 --- a/weave/conftest.py +++ b/weave/conftest.py @@ -15,7 +15,7 @@ import weave from weave import weave_init from weave.legacy import client as client_legacy -from weave.legacy import context_state, io_service, serialize +from weave.legacy import context_state, environment, io_service, serialize from weave.legacy.language_features.tagging.tag_store import isolated_tagging_context from weave.trace_server import ( clickhouse_trace_server_batched, @@ -24,7 +24,7 @@ ) from weave.trace_server import trace_server_interface as tsi -from . import environment, logs +from . import logs from .tests import fixture_fakewandb from .tests.trace.trace_server_clickhouse_conftest import * from .tests.wandb_system_tests_conftest import * diff --git a/weave/deploy/gcp/__init__.py b/weave/deploy/gcp/__init__.py index b827eca817a..3100723a4ce 100644 --- a/weave/deploy/gcp/__init__.py +++ b/weave/deploy/gcp/__init__.py @@ -7,7 +7,8 @@ import typing from pathlib import Path -from weave import __version__, environment +from weave import __version__ +from weave.legacy import environment from weave.legacy.artifact_wandb import WeaveWBArtifactURI as WeaveWBArtifactURI from weave.trace.refs import ObjectRef, parse_uri diff --git a/weave/deploy/modal/__init__.py b/weave/deploy/modal/__init__.py index 691e7903289..947cbb2f057 100644 --- a/weave/deploy/modal/__init__.py +++ b/weave/deploy/modal/__init__.py @@ -5,8 +5,8 @@ import typing from pathlib import Path -from weave import environment from weave.legacy import artifact_wandb as artifact_wandb +from weave.legacy import environment from weave.trace.refs import ObjectRef, parse_uri try: diff --git a/weave/filesystem.py b/weave/filesystem.py index 8af0aac9bbb..a3b03bee1ec 100644 --- a/weave/filesystem.py +++ b/weave/filesystem.py @@ -20,9 +20,9 @@ from aiofiles.threadpool import binary as aiofiles_binary from aiofiles.threadpool import text as aiofiles_text -from weave.legacy import cache, engine_trace +from weave.legacy import cache, engine_trace, environment -from . import environment, errors, util +from . import errors, util tracer = engine_trace.tracer() # type: ignore async_utime = aiofiles_os.wrap(os.utime) # type: ignore diff --git a/weave/legacy/artifact_local.py b/weave/legacy/artifact_local.py index f8854e5cc85..3bc114b8d96 100644 --- a/weave/legacy/artifact_local.py +++ b/weave/legacy/artifact_local.py @@ -9,9 +9,9 @@ import typing from datetime import datetime -from weave import environment, errors, filesystem, util +from weave import errors, filesystem, util from weave import weave_types as types -from weave.legacy import artifact_fs, artifact_wandb, file_base, file_util, uris +from weave.legacy import artifact_fs, artifact_wandb, environment, file_base, file_util, uris WORKING_DIR_PREFIX = "__working__" diff --git a/weave/legacy/cache.py b/weave/legacy/cache.py index 0bee0170fd3..7ebe820a715 100644 --- a/weave/legacy/cache.py +++ b/weave/legacy/cache.py @@ -6,8 +6,8 @@ import time import typing -from weave import environment, errors -from weave.legacy import context_state, wandb_api, engine_trace +from weave import errors +from weave.legacy import context_state, environment, wandb_api, engine_trace statsd = engine_trace.statsd() # type: ignore logger = logging.getLogger("root") diff --git a/weave/legacy/engine_trace.py b/weave/legacy/engine_trace.py index 6a9284a2932..c522afeefab 100644 --- a/weave/legacy/engine_trace.py +++ b/weave/legacy/engine_trace.py @@ -18,8 +18,8 @@ import time import typing -from .. import environment, logs -from . import stream_data_interfaces +from .. import logs +from . import environment, stream_data_interfaces # Thanks co-pilot! diff --git a/weave/environment.py b/weave/legacy/environment.py similarity index 99% rename from weave/environment.py rename to weave/legacy/environment.py index b54d1cfd7dc..eb5a5271ce5 100644 --- a/weave/environment.py +++ b/weave/legacy/environment.py @@ -11,10 +11,10 @@ from distutils.util import strtobool from urllib.parse import urlparse -from . import errors, util +from .. import errors, util if typing.TYPE_CHECKING: - from . import logs + from .. import logs WANDB_ERROR_REPORTING = "WANDB_ERROR_REPORTING" WEAVE_USAGE_ANALYTICS = "WEAVE_USAGE_ANALYTICS" @@ -105,7 +105,7 @@ def is_public() -> bool: def weave_log_format(default: "logs.LogFormat") -> "logs.LogFormat": - from .logs import LogFormat + from ..logs import LogFormat return LogFormat(os.getenv("WEAVE_LOG_FORMAT", default)) diff --git a/weave/legacy/execute.py b/weave/legacy/execute.py index 8c9bb02475e..4fe5da5e78c 100644 --- a/weave/legacy/execute.py +++ b/weave/legacy/execute.py @@ -10,7 +10,6 @@ from collections.abc import Mapping from weave import ( - environment, errors, ) from weave import weave_types as types @@ -23,6 +22,7 @@ # Language Features from weave.legacy import ( engine_trace, + environment, parallelism, ref_base, registry_mem, diff --git a/weave/legacy/file_util.py b/weave/legacy/file_util.py index b21f04bfc5e..b43c6dad627 100644 --- a/weave/legacy/file_util.py +++ b/weave/legacy/file_util.py @@ -2,8 +2,8 @@ import pathlib import typing -from weave import environment, filesystem -from weave.legacy import cache, path_util +from weave import filesystem +from weave.legacy import cache, environment, path_util def get_allowed_dir() -> pathlib.Path: diff --git a/weave/legacy/gql_schema.py b/weave/legacy/gql_schema.py index 5128d1eab50..6ee16b3cd7b 100644 --- a/weave/legacy/gql_schema.py +++ b/weave/legacy/gql_schema.py @@ -2,7 +2,7 @@ import graphql -from weave import environment +from weave.legacy import environment from weave.legacy import wandb_client_api _GQL_SCHEMA_CACHE: dict[typing.Optional[str], graphql.GraphQLSchema] = {} diff --git a/weave/legacy/op_def_type.py b/weave/legacy/op_def_type.py index bb5fccf4525..030ffad85c4 100644 --- a/weave/legacy/op_def_type.py +++ b/weave/legacy/op_def_type.py @@ -11,9 +11,9 @@ from _ast import AsyncFunctionDef, ExceptHandler from typing import Any -from weave import environment, errors, storage +from weave import errors, storage from weave import weave_types as types -from weave.legacy import artifact_fs, artifact_local, context_state, infer_types, registry_mem +from weave.legacy import artifact_fs, artifact_local, context_state, environment, infer_types, registry_mem if typing.TYPE_CHECKING: from .op_def import OpDef diff --git a/weave/legacy/ops_domain/wbgqlquery_op.py b/weave/legacy/ops_domain/wbgqlquery_op.py index 662fbc339bc..2ed399410b7 100644 --- a/weave/legacy/ops_domain/wbgqlquery_op.py +++ b/weave/legacy/ops_domain/wbgqlquery_op.py @@ -1,10 +1,10 @@ import logging import typing -from weave import environment, errors +from weave import errors from weave import weave_types as types from weave.legacy.api import op -from weave.legacy import engine_trace, mappers_gql, partial_object +from weave.legacy import engine_trace, environment, mappers_gql, partial_object from weave.legacy.language_features.tagging import tagged_value_type from weave.legacy.ops_domain import wb_domain_types as wdt from weave.legacy.wandb_client_api import wandb_gql_query diff --git a/weave/legacy/ops_primitives/file.py b/weave/legacy/ops_primitives/file.py index fdc4ea7908e..854da41e866 100644 --- a/weave/legacy/ops_primitives/file.py +++ b/weave/legacy/ops_primitives/file.py @@ -1,7 +1,7 @@ import json import typing -from weave import environment as weave_env +from weave.legacy import environment as weave_env from weave import errors from weave import weave_types as types from weave.legacy.api import op diff --git a/weave/legacy/ops_primitives/file_local.py b/weave/legacy/ops_primitives/file_local.py index 45940d7500c..f6e2a29f206 100644 --- a/weave/legacy/ops_primitives/file_local.py +++ b/weave/legacy/ops_primitives/file_local.py @@ -1,7 +1,7 @@ import os import typing -from weave import environment +from weave.legacy import environment from weave import weave_types as types from weave.legacy.api import op from weave.legacy import file_local diff --git a/weave/legacy/ops_primitives/projection_utils.py b/weave/legacy/ops_primitives/projection_utils.py index 250037323bd..8e05cf2753a 100644 --- a/weave/legacy/ops_primitives/projection_utils.py +++ b/weave/legacy/ops_primitives/projection_utils.py @@ -9,8 +9,8 @@ from sklearn.decomposition import PCA from sklearn.manifold import TSNE -from weave import environment, errors -from weave.legacy import context_state +from weave import errors +from weave.legacy import context_state, environment umap_lib = {} diff --git a/weave/legacy/runfiles_wandb.py b/weave/legacy/runfiles_wandb.py index bd5d0074c04..d61f91f4c53 100644 --- a/weave/legacy/runfiles_wandb.py +++ b/weave/legacy/runfiles_wandb.py @@ -6,7 +6,7 @@ import shutil import typing -from weave import environment as weave_env +from weave.legacy import environment as weave_env from weave import errors, filesystem from weave import weave_types as types from weave.legacy import artifact_fs, file_util, memo, uris, wandb_client_api diff --git a/weave/legacy/signal_handlers.py b/weave/legacy/signal_handlers.py index 0f74db86d5b..d9c1e89e683 100644 --- a/weave/legacy/signal_handlers.py +++ b/weave/legacy/signal_handlers.py @@ -10,7 +10,7 @@ import typing from types import FrameType -from weave import environment +from weave.legacy import environment def dump_folder() -> pathlib.Path: diff --git a/weave/legacy/usage_analytics.py b/weave/legacy/usage_analytics.py index a9fe6866a58..5fd8bddc571 100644 --- a/weave/legacy/usage_analytics.py +++ b/weave/legacy/usage_analytics.py @@ -5,7 +5,7 @@ from weave.legacy import context_state -from .. import environment +from . import environment analytics.write_key = "uJ8vZgKqTBVH6ZdhD4GZGZYsR7ucfJmb" diff --git a/weave/legacy/wandb_api.py b/weave/legacy/wandb_api.py index b551538a6ae..2ef082916f6 100644 --- a/weave/legacy/wandb_api.py +++ b/weave/legacy/wandb_api.py @@ -15,7 +15,7 @@ from requests.auth import HTTPBasicAuth from weave import errors -from weave import environment as weave_env +from weave.legacy import environment as weave_env from weave.legacy import wandb_client_api, engine_trace # Importing at the top-level namespace so other files can import from here. diff --git a/weave/legacy/wandb_file_manager.py b/weave/legacy/wandb_file_manager.py index 21c29a064af..6fd5a14a176 100644 --- a/weave/legacy/wandb_file_manager.py +++ b/weave/legacy/wandb_file_manager.py @@ -13,7 +13,7 @@ from wandb.sdk.lib import hashutil from weave import errors, filesystem, weave_http -from weave import environment as weave_env +from weave.legacy import environment as weave_env from weave.legacy import artifact_wandb, cache, wandb_api, engine_trace tracer = engine_trace.tracer() # type: ignore diff --git a/weave/legacy/wandb_interface/wandb_stream_table.py b/weave/legacy/wandb_interface/wandb_stream_table.py index 31070b588c6..4f69e6b7299 100644 --- a/weave/legacy/wandb_interface/wandb_stream_table.py +++ b/weave/legacy/wandb_interface/wandb_stream_table.py @@ -15,10 +15,11 @@ from wandb.sdk.lib.paths import LogicalPath from wandb.sdk.lib.printer import get_printer -from weave import environment, errors, storage, weave_types +from weave import errors, storage, weave_types from weave.legacy import ( artifact_base, box, + environment, file_util, graph, runfiles_wandb, diff --git a/weave/logs.py b/weave/logs.py index c9b039f6fc4..30c3127834b 100644 --- a/weave/logs.py +++ b/weave/logs.py @@ -12,7 +12,7 @@ from pythonjsonlogger import jsonlogger -from . import environment +from weave.legacy import environment try: from flask.logging import wsgi_errors_stream diff --git a/weave/tests/legacy/test_access.py b/weave/tests/legacy/test_access.py index d83a58491b3..1006a9e400b 100644 --- a/weave/tests/legacy/test_access.py +++ b/weave/tests/legacy/test_access.py @@ -1,9 +1,9 @@ import pytest import weave -from weave.legacy import artifact_fs, artifact_local, wandb_api +from weave.legacy import artifact_fs, artifact_local, environment, wandb_api -from ... import environment, errors, storage +from ... import errors, storage @pytest.fixture() diff --git a/weave/tests/legacy/test_cache.py b/weave/tests/legacy/test_cache.py index 9970efecda8..0fe6243504c 100644 --- a/weave/tests/legacy/test_cache.py +++ b/weave/tests/legacy/test_cache.py @@ -2,8 +2,7 @@ import os import time -from weave import environment -from weave.legacy import cache +from weave.legacy import cache, environment def test_lru_time_window_cache(): diff --git a/weave/tests/legacy/test_execute.py b/weave/tests/legacy/test_execute.py index c7a33bf1050..fc8cd413332 100644 --- a/weave/tests/legacy/test_execute.py +++ b/weave/tests/legacy/test_execute.py @@ -4,9 +4,9 @@ import pytest import weave -from weave.legacy import execute, ops +from weave.legacy import environment, execute, ops -from ... import api, environment, weave_internal +from ... import api, weave_internal from ... import weave_types as types from . import test_wb diff --git a/weave/tests/legacy/test_file.py b/weave/tests/legacy/test_file.py index b1bfd214f62..0fed90136c3 100644 --- a/weave/tests/legacy/test_file.py +++ b/weave/tests/legacy/test_file.py @@ -1,9 +1,9 @@ import pytest import weave -from weave.legacy import context_state, ops +from weave.legacy import context_state, environment, ops -from ... import api, environment, errors +from ... import api, errors def test_dir(): diff --git a/weave/tests/legacy/test_filesystem.py b/weave/tests/legacy/test_filesystem.py index c16d005d202..7faa4668230 100644 --- a/weave/tests/legacy/test_filesystem.py +++ b/weave/tests/legacy/test_filesystem.py @@ -2,7 +2,9 @@ import pytest -from ... import environment, errors, filesystem +from weave.legacy import environment + +from ... import errors, filesystem @pytest.fixture() diff --git a/weave/trace/op_type.py b/weave/trace/op_type.py index db3eaa25bae..c7566e07756 100644 --- a/weave/trace/op_type.py +++ b/weave/trace/op_type.py @@ -21,7 +21,8 @@ ) from weave.trace.refs import ObjectRef -from .. import environment, errors, storage +from .. import errors, storage +from ..legacy import environment from . import serializer from .op import Op diff --git a/weave/trace_server/remote_http_trace_server.py b/weave/trace_server/remote_http_trace_server.py index 145d2f50906..842e5c43893 100644 --- a/weave/trace_server/remote_http_trace_server.py +++ b/weave/trace_server/remote_http_trace_server.py @@ -6,7 +6,7 @@ import tenacity from pydantic import BaseModel, ValidationError -from weave.environment import weave_trace_server_url +from weave.legacy.environment import weave_trace_server_url from weave.legacy.wandb_interface import project_creator from . import requests diff --git a/weave/urls.py b/weave/urls.py index 6793462842b..cf7d53cbf38 100644 --- a/weave/urls.py +++ b/weave/urls.py @@ -2,9 +2,7 @@ from wandb import util as wb_util -from weave.legacy import context_state - -from . import environment +from weave.legacy import context_state, environment BROWSE3_PATH = "browse3" WEAVE_SLUG = "weave" diff --git a/weave/weave_server.py b/weave/weave_server.py index f76a27f7493..cb77de12faf 100644 --- a/weave/weave_server.py +++ b/weave/weave_server.py @@ -26,7 +26,6 @@ from werkzeug.exceptions import HTTPException from weave import ( - environment, errors, filesystem, logs, @@ -36,6 +35,7 @@ from weave.legacy import ( context_state, engine_trace, + environment, graph, registry_mem, server, From c189637dc011042560e32616efced67393c5f959 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 11:05:36 -0400 Subject: [PATCH 37/84] move to legacy: errors (and add relevant errors to trace) --- weave/__init__.py | 2 +- weave/client_context/weave_client.py | 2 +- weave/errors.py | 171 ------------------ weave/filesystem.py | 4 +- weave/legacy/_dict_utils.py | 2 +- weave/legacy/api.py | 2 +- weave/legacy/arrow/arrow.py | 2 +- weave/legacy/arrow/concat.py | 2 +- weave/legacy/arrow/constructors.py | 2 +- weave/legacy/arrow/convert.py | 4 +- weave/legacy/arrow/list_.py | 2 +- weave/legacy/artifact_fs.py | 2 +- weave/legacy/artifact_local.py | 12 +- weave/legacy/artifact_mem.py | 2 +- weave/legacy/artifact_wandb.py | 2 +- weave/legacy/cache.py | 2 +- weave/legacy/compile.py | 2 +- weave/legacy/compile_domain.py | 2 +- weave/legacy/compile_table.py | 2 +- weave/legacy/decorator_class.py | 2 +- weave/legacy/decorator_type.py | 2 +- weave/legacy/derive_op.py | 2 +- weave/legacy/dispatch.py | 4 +- weave/legacy/environment.py | 4 +- weave/legacy/errors.py | 143 +++++++++++++++ weave/legacy/execute.py | 4 +- weave/legacy/execute_fast.py | 2 +- weave/legacy/forward_graph.py | 2 +- weave/legacy/gql_to_weave.py | 2 +- weave/legacy/graph.py | 4 +- weave/legacy/infer_types.py | 4 +- weave/legacy/io_service.py | 2 +- .../language_features/tagging/tag_store.py | 2 +- .../tagging/tagged_value_type.py | 2 +- weave/legacy/mappers_arrow.py | 2 +- weave/legacy/mappers_gql.py | 2 +- weave/legacy/mappers_publisher.py | 3 +- weave/legacy/mappers_python_def.py | 3 +- weave/legacy/monitoring/monitor.py | 2 +- weave/legacy/op_def.py | 2 +- weave/legacy/op_def_type.py | 12 +- weave/legacy/ops_arrow/vectorize.py | 4 +- .../ops_domain/artifact_collection_ops.py | 2 +- .../legacy/ops_domain/artifact_version_ops.py | 2 +- weave/legacy/ops_domain/project_ops.py | 2 +- weave/legacy/ops_domain/repo_insight_ops.py | 2 +- weave/legacy/ops_domain/report_ops.py | 2 +- .../run_history/history_op_common.py | 2 +- ...run_history_v3_parquet_stream_optimized.py | 2 +- weave/legacy/ops_domain/table.py | 3 +- weave/legacy/ops_domain/wandb_domain_gql.py | 4 +- weave/legacy/ops_domain/wbgqlquery_op.py | 2 +- weave/legacy/ops_domain/wbmedia.py | 4 +- weave/legacy/ops_primitives/_dict_utils.py | 2 +- weave/legacy/ops_primitives/file.py | 2 +- weave/legacy/ops_primitives/list_.py | 4 +- weave/legacy/ops_primitives/pandas_.py | 2 +- .../legacy/ops_primitives/projection_utils.py | 2 +- weave/legacy/ops_primitives/type.py | 2 +- weave/legacy/ops_primitives/weave_api.py | 2 +- weave/legacy/panel.py | 4 +- weave/legacy/panels/panel_group.py | 3 +- weave/legacy/panels/panel_plot.py | 4 +- weave/legacy/path_util.py | 2 +- weave/legacy/pyfunc_type_util.py | 2 +- weave/legacy/ref_base.py | 2 +- weave/legacy/registry_mem.py | 4 +- weave/legacy/runfiles_wandb.py | 11 +- weave/legacy/serialize.py | 4 +- weave/legacy/server_error_handling.py | 3 +- weave/legacy/show.py | 4 +- weave/legacy/stitch.py | 2 +- weave/legacy/uris.py | 2 +- weave/legacy/wandb_api.py | 2 +- weave/legacy/wandb_client_api.py | 2 +- weave/legacy/wandb_file_manager.py | 4 +- .../legacy/wandb_interface/wandb_lite_run.py | 2 +- .../wandb_interface/wandb_stream_table.py | 3 +- weave/legacy/wandb_util.py | 2 +- weave/legacy/weavify.py | 4 +- weave/storage.py | 2 +- weave/tests/legacy/test_access.py | 4 +- weave/tests/legacy/test_arrow.py | 4 +- weave/tests/legacy/test_arrow_vectorizer.py | 4 +- weave/tests/legacy/test_filesystem.py | 4 +- weave/trace/op_type.py | 4 +- weave/trace/serve_fastapi.py | 3 +- weave/util.py | 2 +- weave/weave_init.py | 3 +- weave/weave_internal.py | 3 +- weave/weave_server.py | 2 +- weave/weave_types.py | 10 +- 92 files changed, 294 insertions(+), 292 deletions(-) delete mode 100644 weave/errors.py diff --git a/weave/__init__.py b/weave/__init__.py index 67afd523607..d6aca836e1c 100644 --- a/weave/__init__.py +++ b/weave/__init__.py @@ -18,7 +18,7 @@ from .legacy.api import * from .trace.api import * -from .errors import * +from .legacy.errors import * from weave.legacy import mappers_python_def diff --git a/weave/client_context/weave_client.py b/weave/client_context/weave_client.py index c0b3da823df..b80375adb56 100644 --- a/weave/client_context/weave_client.py +++ b/weave/client_context/weave_client.py @@ -1,8 +1,8 @@ import threading from typing import TYPE_CHECKING, Optional -from weave.errors import WeaveInitError from weave.legacy import context_state +from weave.legacy.errors import WeaveInitError if TYPE_CHECKING: from weave.trace.weave_client import WeaveClient diff --git a/weave/errors.py b/weave/errors.py deleted file mode 100644 index be70b599141..00000000000 --- a/weave/errors.py +++ /dev/null @@ -1,171 +0,0 @@ -from typing import Iterable, Optional - - -class WeaveFingerprintErrorMixin: - fingerprint: Optional[Iterable] = None - - -class WeaveBaseError(Exception, WeaveFingerprintErrorMixin): - pass - - -class WeaveBaseWarning(Warning): - pass - - -# Only use this if you actually want to return an Http 400 -# to the client. This should only happen in cases where the -# client is wrong. -class WeaveBadRequest(WeaveBaseError): - pass - - -class WeaveInternalError(WeaveBaseError): - """Internal Weave Error (a programming error)""" - - pass - - -class WeaveSerializeError(WeaveBaseError): - pass - - -class WeaveConfigurationError(WeaveBaseError): - pass - - -class WeaveApiError(WeaveBaseError): - pass - - -class WeaveTypeError(WeaveBaseError): - pass - - -class WeaveTypeWarning(WeaveBaseWarning): - pass - - -class WeaveDefinitionError(WeaveBaseError): - pass - - -class WeaveMakeFunctionError(Exception): - pass - - -class WeaveExpectedConstError(Exception): - pass - - -class WeaveInvalidURIError(Exception): - pass - - -class WeaveStorageError(Exception): - pass - - -class WeaveExecutionError(Exception): - pass - - -class WeavifyError(Exception): - pass - - -class WeaveDispatchError(WeaveBaseError): - pass - - -class WeaveArtifactFileNotFound(WeaveBaseError): - pass - - -class WeaveArtifactCollectionNotFound(WeaveBaseError): - pass - - -class WeaveArtifactVersionNotFound(WeaveBaseError): - pass - - -class WeaveVectorizationError(WeaveBaseError): - pass - - -class WeaveValueError(WeaveBaseError): - pass - - -class WeaveClientArtifactResolutionFailure(WeaveBaseError): - pass - - -class WeaveTableDeserializationError(WeaveBaseError): - pass - - -class WeaveStitchGraphMergeError(WeaveBaseError): - pass - - -class WeaveHashConstTypeError(WeaveBaseError): - """Raised if __hash__ is called on a Const Type. - - To hash a Const Type, we'd need to hash the value, which is unbounded. - """ - - pass - - -class WeaveGQLCompileError(WeaveBaseError): - pass - - -class WeaveGQLExecuteMissingAliasError(WeaveBaseError): - pass - - -class WeaveAccessDeniedError(WeaveBaseError): - pass - - -class WeaveWandbArtifactManagerError(WeaveBaseError): - pass - - -class WeaveArtifactMediaFileLookupError(WeaveBaseError): - pass - - -class WeaveClientRequestError(WeaveBaseError): - pass - - -class WeaveMissingVariableError(WeaveBaseError): - pass - - -class WeaveWBHistoryTranslationError(WeaveBaseError): - pass - - -class WeaveWandbAuthenticationException(Exception): - pass - - -class WeaveMissingOpDefError(WeaveBaseError): - pass - - -class WeaveMergeArtifactSpecError(WeaveBaseError): - pass - - -class WeaveOpSerializeError(WeaveBaseError): - pass - - -class WeaveInitError(WeaveBaseError): - pass diff --git a/weave/filesystem.py b/weave/filesystem.py index a3b03bee1ec..d46b06c6843 100644 --- a/weave/filesystem.py +++ b/weave/filesystem.py @@ -20,9 +20,9 @@ from aiofiles.threadpool import binary as aiofiles_binary from aiofiles.threadpool import text as aiofiles_text -from weave.legacy import cache, engine_trace, environment +from weave.legacy import cache, engine_trace, environment, errors -from . import errors, util +from . import util tracer = engine_trace.tracer() # type: ignore async_utime = aiofiles_os.wrap(os.utime) # type: ignore diff --git a/weave/legacy/_dict_utils.py b/weave/legacy/_dict_utils.py index ce3b41a9288..256a973fe98 100644 --- a/weave/legacy/_dict_utils.py +++ b/weave/legacy/_dict_utils.py @@ -3,7 +3,7 @@ from weave.legacy import box from weave.legacy.language_features.tagging import tag_store, tagged_value_type -from .. import errors +from weave.legacy import errors from .. import weave_types as types diff --git a/weave/legacy/api.py b/weave/legacy/api.py index 5fec25de8a7..177efdf3d20 100644 --- a/weave/legacy/api.py +++ b/weave/legacy/api.py @@ -26,7 +26,7 @@ # needed to enable automatic numpy serialization from . import types_numpy as _types_numpy -from .. import errors +from weave.legacy import errors from weave.legacy.decorators import weave_class, mutation, type from weave.legacy import usage_analytics diff --git a/weave/legacy/arrow/arrow.py b/weave/legacy/arrow/arrow.py index 2799fa249f6..d7f750f7caf 100644 --- a/weave/legacy/arrow/arrow.py +++ b/weave/legacy/arrow/arrow.py @@ -11,7 +11,7 @@ py_type = type -from weave import errors +from weave.legacy import errors from weave import weave_types as types from weave.legacy import artifact_fs, partial_object diff --git a/weave/legacy/arrow/concat.py b/weave/legacy/arrow/concat.py index 28198c3d339..4201da7d17d 100644 --- a/weave/legacy/arrow/concat.py +++ b/weave/legacy/arrow/concat.py @@ -12,7 +12,7 @@ import pyarrow as pa from pyarrow import compute as pc -from weave import errors +from weave.legacy import errors from weave import weave_types as types from weave.legacy.arrow.list_ import ( ArrowWeaveList, diff --git a/weave/legacy/arrow/constructors.py b/weave/legacy/arrow/constructors.py index ee0fe70318e..b7cab73103c 100644 --- a/weave/legacy/arrow/constructors.py +++ b/weave/legacy/arrow/constructors.py @@ -3,7 +3,7 @@ import pyarrow as pa -from weave import errors +from weave.legacy import errors from weave import weave_types as types from weave.legacy import artifact_base, box from weave.legacy.arrow import arrow_tags, convert diff --git a/weave/legacy/arrow/convert.py b/weave/legacy/arrow/convert.py index d4e41d2e16b..1b195a43283 100644 --- a/weave/legacy/arrow/convert.py +++ b/weave/legacy/arrow/convert.py @@ -4,9 +4,9 @@ import pyarrow.compute as pc from weave.legacy import api as api -from weave import errors, weave_internal +from weave import weave_internal from weave import weave_types as types -from weave.legacy import arrow_util, artifact_base, artifact_mem, box, mappers_arrow +from weave.legacy import errors, arrow_util, artifact_base, artifact_mem, box, mappers_arrow from weave.legacy.arrow.arrow import ( ArrowWeaveListType, ) diff --git a/weave/legacy/arrow/list_.py b/weave/legacy/arrow/list_.py index 7cc6e84ddba..cdd8dd1a5d7 100644 --- a/weave/legacy/arrow/list_.py +++ b/weave/legacy/arrow/list_.py @@ -11,11 +11,11 @@ import typing_extensions from weave import ( - errors, weave_internal, ) from weave import weave_types as types from weave.legacy import ( + errors, _dict_utils, artifact_base, box, diff --git a/weave/legacy/artifact_fs.py b/weave/legacy/artifact_fs.py index d5c71f3c643..9b5ca6a47a8 100644 --- a/weave/legacy/artifact_fs.py +++ b/weave/legacy/artifact_fs.py @@ -6,7 +6,7 @@ import os import typing -from weave import errors +from weave.legacy import errors from weave import weave_types as types from weave.legacy import artifact_base, file_base, object_context, ref_base, uris from weave.legacy.language_features.tagging import tag_store diff --git a/weave/legacy/artifact_local.py b/weave/legacy/artifact_local.py index 3bc114b8d96..498c3e5d2d5 100644 --- a/weave/legacy/artifact_local.py +++ b/weave/legacy/artifact_local.py @@ -9,9 +9,17 @@ import typing from datetime import datetime -from weave import errors, filesystem, util +from weave import filesystem, util from weave import weave_types as types -from weave.legacy import artifact_fs, artifact_wandb, environment, file_base, file_util, uris +from weave.legacy import ( + artifact_fs, + artifact_wandb, + environment, + errors, + file_base, + file_util, + uris, +) WORKING_DIR_PREFIX = "__working__" diff --git a/weave/legacy/artifact_mem.py b/weave/legacy/artifact_mem.py index 58471d6460f..bf8763b9da0 100644 --- a/weave/legacy/artifact_mem.py +++ b/weave/legacy/artifact_mem.py @@ -2,7 +2,7 @@ from . import artifact_base from weave import weave_types as types -from weave import errors +from weave.legacy import errors from weave.legacy import ref_base diff --git a/weave/legacy/artifact_wandb.py b/weave/legacy/artifact_wandb.py index 5a1378b8159..8f9a2fcfae1 100644 --- a/weave/legacy/artifact_wandb.py +++ b/weave/legacy/artifact_wandb.py @@ -14,13 +14,13 @@ from wandb.sdk.lib.hashutil import b64_to_hex_id, hex_to_b64_id from weave import ( - errors, filesystem, urls, util, ) from weave import weave_types as types from weave.legacy import ( + errors, engine_trace, artifact_fs, eager, diff --git a/weave/legacy/cache.py b/weave/legacy/cache.py index 7ebe820a715..bb254ca9473 100644 --- a/weave/legacy/cache.py +++ b/weave/legacy/cache.py @@ -6,7 +6,7 @@ import time import typing -from weave import errors +from weave.legacy import errors from weave.legacy import context_state, environment, wandb_api, engine_trace statsd = engine_trace.statsd() # type: ignore diff --git a/weave/legacy/compile.py b/weave/legacy/compile.py index eeec391beed..760a3527ff8 100644 --- a/weave/legacy/compile.py +++ b/weave/legacy/compile.py @@ -6,11 +6,11 @@ import typing from weave import ( - errors, weave_internal, ) from weave import weave_types as types from weave.legacy import ( + errors, engine_trace, box, compile_domain, diff --git a/weave/legacy/compile_domain.py b/weave/legacy/compile_domain.py index 2a0f686d676..3d9c6119220 100644 --- a/weave/legacy/compile_domain.py +++ b/weave/legacy/compile_domain.py @@ -2,7 +2,7 @@ import graphql -from weave import errors +from weave.legacy import errors from weave import weave_types as types from weave.legacy import gql_op_plugin, gql_to_weave, graph, op_args, stitch, registry_mem from weave.legacy.input_provider import InputAndStitchProvider diff --git a/weave/legacy/compile_table.py b/weave/legacy/compile_table.py index 59982717967..f0efcfc85ec 100644 --- a/weave/legacy/compile_table.py +++ b/weave/legacy/compile_table.py @@ -2,7 +2,7 @@ import typing -from weave import errors +from weave.legacy import errors from weave.legacy import stitch KeyTree = typing.Dict[str, "KeyTree"] # type:ignore diff --git a/weave/legacy/decorator_class.py b/weave/legacy/decorator_class.py index 99fadbcb16e..afcdc17690d 100644 --- a/weave/legacy/decorator_class.py +++ b/weave/legacy/decorator_class.py @@ -1,7 +1,7 @@ import inspect import typing -from weave import errors +from weave.legacy import errors from weave import weave_types as types from weave.legacy import context_state, derive_op, op_def, registry_mem diff --git a/weave/legacy/decorator_type.py b/weave/legacy/decorator_type.py index 9568a906f48..2f7ff2f0da9 100644 --- a/weave/legacy/decorator_type.py +++ b/weave/legacy/decorator_type.py @@ -2,7 +2,7 @@ import inspect import typing -from weave import errors +from weave.legacy import errors from weave import weave_types as types from weave.legacy import context_state, decorator_class, object_type_ref_util, infer_types diff --git a/weave/legacy/derive_op.py b/weave/legacy/derive_op.py index 255fe7c89aa..e591a652cc0 100644 --- a/weave/legacy/derive_op.py +++ b/weave/legacy/derive_op.py @@ -7,12 +7,12 @@ import typing from weave import ( - errors, storage, weave_internal, ) from weave import weave_types as types from weave.legacy import ( + errors, parallelism, registry_mem, box, diff --git a/weave/legacy/dispatch.py b/weave/legacy/dispatch.py index 4eaf2ca215f..872ad267e68 100644 --- a/weave/legacy/dispatch.py +++ b/weave/legacy/dispatch.py @@ -5,9 +5,9 @@ import typing from dataclasses import dataclass -from weave import errors, util +from weave import util from weave import weave_types as types -from weave.legacy import graph, memo, op_args, op_def, pyfunc_type_util, registry_mem +from weave.legacy import graph, memo, op_args, op_def, pyfunc_type_util, registry_mem, errors from weave.legacy.language_features.tagging.is_tag_getter import is_tag_getter from weave.legacy.language_features.tagging.tagged_value_type import TaggedValueType diff --git a/weave/legacy/environment.py b/weave/legacy/environment.py index eb5a5271ce5..1e22db8919f 100644 --- a/weave/legacy/environment.py +++ b/weave/legacy/environment.py @@ -10,8 +10,8 @@ import typing from distutils.util import strtobool from urllib.parse import urlparse - -from .. import errors, util +from weave.legacy import errors +from .. import util if typing.TYPE_CHECKING: from .. import logs diff --git a/weave/legacy/errors.py b/weave/legacy/errors.py index f6b5fd477d3..9bcba3faf94 100644 --- a/weave/legacy/errors.py +++ b/weave/legacy/errors.py @@ -16,6 +16,7 @@ class WeaveBaseError(Exception, WeaveFingerprintErrorMixin): class WeaveBaseWarning(Warning): pass + # Only use this if you actually want to return an Http 400 # to the client. This should only happen in cases where the # client is wrong. @@ -28,5 +29,147 @@ class WeaveInternalError(WeaveBaseError): pass + class WeaveSerializeError(WeaveBaseError): pass + + +class WeaveConfigurationError(WeaveBaseError): + pass + + +class WeaveApiError(WeaveBaseError): + pass + + +class WeaveTypeError(WeaveBaseError): + pass + + +class WeaveTypeWarning(WeaveBaseWarning): + pass + + +class WeaveDefinitionError(WeaveBaseError): + pass + + +class WeaveMakeFunctionError(Exception): + pass + + +class WeaveExpectedConstError(Exception): + pass + + +class WeaveInvalidURIError(Exception): + pass + + +class WeaveStorageError(Exception): + pass + + +class WeaveExecutionError(Exception): + pass + + +class WeavifyError(Exception): + pass + + +class WeaveDispatchError(WeaveBaseError): + pass + + +class WeaveArtifactFileNotFound(WeaveBaseError): + pass + + +class WeaveArtifactCollectionNotFound(WeaveBaseError): + pass + + +class WeaveArtifactVersionNotFound(WeaveBaseError): + pass + + +class WeaveVectorizationError(WeaveBaseError): + pass + + +class WeaveValueError(WeaveBaseError): + pass + + +class WeaveClientArtifactResolutionFailure(WeaveBaseError): + pass + + +class WeaveTableDeserializationError(WeaveBaseError): + pass + + +class WeaveStitchGraphMergeError(WeaveBaseError): + pass + + +class WeaveHashConstTypeError(WeaveBaseError): + """Raised if __hash__ is called on a Const Type. + + To hash a Const Type, we'd need to hash the value, which is unbounded. + """ + + pass + + +class WeaveGQLCompileError(WeaveBaseError): + pass + + +class WeaveGQLExecuteMissingAliasError(WeaveBaseError): + pass + + +class WeaveAccessDeniedError(WeaveBaseError): + pass + + +class WeaveWandbArtifactManagerError(WeaveBaseError): + pass + + +class WeaveArtifactMediaFileLookupError(WeaveBaseError): + pass + + +class WeaveClientRequestError(WeaveBaseError): + pass + + +class WeaveMissingVariableError(WeaveBaseError): + pass + + +class WeaveWBHistoryTranslationError(WeaveBaseError): + pass + + +class WeaveWandbAuthenticationException(Exception): + pass + + +class WeaveMissingOpDefError(WeaveBaseError): + pass + + +class WeaveMergeArtifactSpecError(WeaveBaseError): + pass + + +class WeaveOpSerializeError(WeaveBaseError): + pass + + +class WeaveInitError(WeaveBaseError): + pass diff --git a/weave/legacy/execute.py b/weave/legacy/execute.py index 4fe5da5e78c..72d7ecd9764 100644 --- a/weave/legacy/execute.py +++ b/weave/legacy/execute.py @@ -9,9 +9,6 @@ import typing from collections.abc import Mapping -from weave import ( - errors, -) from weave import weave_types as types # Configuration @@ -21,6 +18,7 @@ # Trace / cache # Language Features from weave.legacy import ( + errors, engine_trace, environment, parallelism, diff --git a/weave/legacy/execute_fast.py b/weave/legacy/execute_fast.py index f4b571c86ea..4bcb4e418fd 100644 --- a/weave/legacy/execute_fast.py +++ b/weave/legacy/execute_fast.py @@ -1,11 +1,11 @@ import logging from weave import ( - errors, weave_internal, ) from weave import weave_types as types from weave.legacy import ( + errors, engine_trace, ref_base, registry_mem, diff --git a/weave/legacy/forward_graph.py b/weave/legacy/forward_graph.py index 8a3048a281d..7f3801e3024 100644 --- a/weave/legacy/forward_graph.py +++ b/weave/legacy/forward_graph.py @@ -5,7 +5,7 @@ from weave.legacy import graph -from .. import errors +from weave.legacy import errors ExecutableNode = typing.Union[graph.OutputNode, graph.ConstNode] diff --git a/weave/legacy/gql_to_weave.py b/weave/legacy/gql_to_weave.py index 6216e5d93b6..51c78413868 100644 --- a/weave/legacy/gql_to_weave.py +++ b/weave/legacy/gql_to_weave.py @@ -17,7 +17,7 @@ parse, ) -from weave import errors +from weave.legacy import errors from weave import weave_types as types from weave.legacy import gql_schema diff --git a/weave/legacy/graph.py b/weave/legacy/graph.py index cb05793a81d..85aeecd13c1 100644 --- a/weave/legacy/graph.py +++ b/weave/legacy/graph.py @@ -2,8 +2,8 @@ import json import typing -from weave import errors, storage, weave_types -from weave.legacy import uris +from weave import storage, weave_types +from weave.legacy import uris, errors if typing.TYPE_CHECKING: from weave.legacy import weave_inspector diff --git a/weave/legacy/infer_types.py b/weave/legacy/infer_types.py index 55d9988fb02..8a70475c7de 100644 --- a/weave/legacy/infer_types.py +++ b/weave/legacy/infer_types.py @@ -6,9 +6,9 @@ import typing_extensions -from weave.legacy import graph +from weave.legacy import errors, graph -from .. import errors, weave_types +from .. import weave_types class TypedDictLike: diff --git a/weave/legacy/io_service.py b/weave/legacy/io_service.py index 4ef61c6218c..701363c0a36 100644 --- a/weave/legacy/io_service.py +++ b/weave/legacy/io_service.py @@ -23,11 +23,11 @@ import aioprocessing from weave import ( - errors, filesystem, weave_http, ) from weave.legacy import ( + errors, engine_trace, server_error_handling, artifact_wandb, diff --git a/weave/legacy/language_features/tagging/tag_store.py b/weave/legacy/language_features/tagging/tag_store.py index 85a4c98de9f..c39c404e35f 100644 --- a/weave/legacy/language_features/tagging/tag_store.py +++ b/weave/legacy/language_features/tagging/tag_store.py @@ -22,7 +22,7 @@ from collections import defaultdict from contextlib import contextmanager -from weave import errors +from weave.legacy import errors from weave import weave_types as types from weave.legacy import engine_trace, box diff --git a/weave/legacy/language_features/tagging/tagged_value_type.py b/weave/legacy/language_features/tagging/tagged_value_type.py index e9d44ae5977..533e0f4af38 100644 --- a/weave/legacy/language_features/tagging/tagged_value_type.py +++ b/weave/legacy/language_features/tagging/tagged_value_type.py @@ -30,7 +30,7 @@ import json import typing -from weave import errors +from weave.legacy import errors from weave import weave_types as types from weave.legacy import box, mappers, mappers_python from weave.legacy.language_features.tagging import tag_store diff --git a/weave/legacy/mappers_arrow.py b/weave/legacy/mappers_arrow.py index 2f1ca904ef1..7c47d34b568 100644 --- a/weave/legacy/mappers_arrow.py +++ b/weave/legacy/mappers_arrow.py @@ -5,7 +5,7 @@ import pyarrow as pa -from weave import errors +from weave.legacy import errors from weave import weave_types as types from weave.legacy import ( arrow_util, diff --git a/weave/legacy/mappers_gql.py b/weave/legacy/mappers_gql.py index 1dbde410384..4a4ce875af4 100644 --- a/weave/legacy/mappers_gql.py +++ b/weave/legacy/mappers_gql.py @@ -1,6 +1,6 @@ import json -from weave import errors +from weave.legacy import errors from weave import weave_types as types from weave.legacy import gql_json_cache, mappers from weave.legacy.mappers_weave import UnionMapper diff --git a/weave/legacy/mappers_publisher.py b/weave/legacy/mappers_publisher.py index 2e57541b60e..4118232aca3 100644 --- a/weave/legacy/mappers_publisher.py +++ b/weave/legacy/mappers_publisher.py @@ -2,7 +2,7 @@ import dataclasses import typing -from weave import errors, storage, weave_internal +from weave import storage, weave_internal from weave import weave_types as types from weave.legacy.node_ref import ref_to_node @@ -16,6 +16,7 @@ mappers, mappers_python_def, ref_base, + errors, ) from weave.legacy.artifact_wandb import likely_commit_hash from weave.legacy.language_features.tagging import tag_store, tagged_value_type diff --git a/weave/legacy/mappers_python_def.py b/weave/legacy/mappers_python_def.py index 88a38b59af1..4551d783803 100644 --- a/weave/legacy/mappers_python_def.py +++ b/weave/legacy/mappers_python_def.py @@ -4,7 +4,7 @@ import math import typing -from weave import errors, storage +from weave import storage from weave import weave_types as types from weave.legacy import ( artifact_fs, @@ -14,6 +14,7 @@ mappers_weave, ref_base, val_const, + errors, ) from weave.legacy import timestamp as weave_timestamp from weave.legacy.language_features.tagging import tagged_value_type diff --git a/weave/legacy/monitoring/monitor.py b/weave/legacy/monitoring/monitor.py index ff0e67ba359..5a707af576c 100644 --- a/weave/legacy/monitoring/monitor.py +++ b/weave/legacy/monitoring/monitor.py @@ -11,7 +11,7 @@ import typing import uuid -from weave import errors +from weave.legacy import errors from weave.legacy import ( graph, run_streamtable_span, diff --git a/weave/legacy/op_def.py b/weave/legacy/op_def.py index 8784906cc06..d38d208a4ba 100644 --- a/weave/legacy/op_def.py +++ b/weave/legacy/op_def.py @@ -7,11 +7,11 @@ from typing import Iterator, Sequence from weave import ( - errors, weave_internal, ) from weave import weave_types as types from weave.legacy import ( + errors, context_state, engine_trace, graph, diff --git a/weave/legacy/op_def_type.py b/weave/legacy/op_def_type.py index 030ffad85c4..040eeef1415 100644 --- a/weave/legacy/op_def_type.py +++ b/weave/legacy/op_def_type.py @@ -11,9 +11,17 @@ from _ast import AsyncFunctionDef, ExceptHandler from typing import Any -from weave import errors, storage +from weave import storage from weave import weave_types as types -from weave.legacy import artifact_fs, artifact_local, context_state, environment, infer_types, registry_mem +from weave.legacy import ( + artifact_fs, + artifact_local, + context_state, + environment, + errors, + infer_types, + registry_mem, +) if typing.TYPE_CHECKING: from .op_def import OpDef diff --git a/weave/legacy/ops_arrow/vectorize.py b/weave/legacy/ops_arrow/vectorize.py index 0c9489397b8..5974c3e1402 100644 --- a/weave/legacy/ops_arrow/vectorize.py +++ b/weave/legacy/ops_arrow/vectorize.py @@ -7,10 +7,10 @@ import pyarrow as pa from weave import ( - errors, + weave_internal, ) -from weave.legacy import weavify, registry_mem +from weave.legacy import errors,weavify, registry_mem from weave import weave_types as types from weave.legacy.api import op, use from weave.legacy import dispatch, graph, graph_debug, op_args, op_def diff --git a/weave/legacy/ops_domain/artifact_collection_ops.py b/weave/legacy/ops_domain/artifact_collection_ops.py index 2ca057618dc..ed3f2d705fd 100644 --- a/weave/legacy/ops_domain/artifact_collection_ops.py +++ b/weave/legacy/ops_domain/artifact_collection_ops.py @@ -1,7 +1,7 @@ import typing import urllib -from weave import errors +from weave.legacy import errors from weave import weave_types as types from weave.legacy.api import op from weave.legacy.gql_op_plugin import wb_gql_op_plugin diff --git a/weave/legacy/ops_domain/artifact_version_ops.py b/weave/legacy/ops_domain/artifact_version_ops.py index cc13aa5d84e..ada1ba79201 100644 --- a/weave/legacy/ops_domain/artifact_version_ops.py +++ b/weave/legacy/ops_domain/artifact_version_ops.py @@ -2,7 +2,7 @@ import typing from urllib.parse import quote -from weave import errors +from weave.legacy import errors from weave import weave_types as types from weave.legacy.api import op from weave.legacy import artifact_fs, artifact_wandb, input_provider diff --git a/weave/legacy/ops_domain/project_ops.py b/weave/legacy/ops_domain/project_ops.py index c8f13427a8a..22ebabcd6b7 100644 --- a/weave/legacy/ops_domain/project_ops.py +++ b/weave/legacy/ops_domain/project_ops.py @@ -1,7 +1,7 @@ import json import typing -from weave import errors +from weave.legacy import errors from weave import weave_types as types from weave.legacy.api import op from weave.legacy import input_provider diff --git a/weave/legacy/ops_domain/repo_insight_ops.py b/weave/legacy/ops_domain/repo_insight_ops.py index 486192281eb..d03aaa61cc6 100644 --- a/weave/legacy/ops_domain/repo_insight_ops.py +++ b/weave/legacy/ops_domain/repo_insight_ops.py @@ -1,7 +1,7 @@ import datetime import json -from weave import errors +from weave.legacy import errors from weave import weave_types as types from weave.legacy.api import op from weave.legacy.gql_json_cache import use_json diff --git a/weave/legacy/ops_domain/report_ops.py b/weave/legacy/ops_domain/report_ops.py index 3173e4f8fa2..fe3c39e80c5 100644 --- a/weave/legacy/ops_domain/report_ops.py +++ b/weave/legacy/ops_domain/report_ops.py @@ -2,7 +2,7 @@ import typing import urllib -from weave import errors +from weave.legacy import errors from weave import weave_types as types from weave.legacy.api import op from weave.legacy.gql_op_plugin import wb_gql_op_plugin diff --git a/weave/legacy/ops_domain/run_history/history_op_common.py b/weave/legacy/ops_domain/run_history/history_op_common.py index fbfab866db7..b95c1bf14b4 100644 --- a/weave/legacy/ops_domain/run_history/history_op_common.py +++ b/weave/legacy/ops_domain/run_history/history_op_common.py @@ -5,12 +5,12 @@ from pyarrow import parquet as pq from weave import ( - errors, util, ) from weave import weave_types as types from weave.legacy.api import use from weave.legacy import ( + errors, engine_trace, registry_mem, _dict_utils, diff --git a/weave/legacy/ops_domain/run_history/run_history_v3_parquet_stream_optimized.py b/weave/legacy/ops_domain/run_history/run_history_v3_parquet_stream_optimized.py index 6b61d141ac0..b39fce58054 100644 --- a/weave/legacy/ops_domain/run_history/run_history_v3_parquet_stream_optimized.py +++ b/weave/legacy/ops_domain/run_history/run_history_v3_parquet_stream_optimized.py @@ -5,7 +5,7 @@ import pyarrow as pa -from weave import errors +from weave.legacy import errors from weave import weave_types as types from weave.legacy.api import op from weave.legacy import ( diff --git a/weave/legacy/ops_domain/table.py b/weave/legacy/ops_domain/table.py index ba5dcddf7e0..1253293fe95 100644 --- a/weave/legacy/ops_domain/table.py +++ b/weave/legacy/ops_domain/table.py @@ -5,7 +5,7 @@ import logging import typing -from weave import errors, util, weave_internal +from weave import util, weave_internal from weave import weave_types as types from weave.legacy.api import op, weave_class from weave.legacy import ( @@ -15,6 +15,7 @@ ops_arrow, wandb_util, engine_trace, + errors, ) from weave.legacy import timestamp as weave_timestamp from weave.legacy.ops_domain import trace_tree, wbmedia diff --git a/weave/legacy/ops_domain/wandb_domain_gql.py b/weave/legacy/ops_domain/wandb_domain_gql.py index 2f8601a2f32..9cb25156608 100644 --- a/weave/legacy/ops_domain/wandb_domain_gql.py +++ b/weave/legacy/ops_domain/wandb_domain_gql.py @@ -4,9 +4,9 @@ import pyarrow as pa -from weave import errors, weave_types +from weave import weave_types from weave.legacy.api import op -from weave.legacy import gql_op_plugin, op_def, partial_object +from weave.legacy import errors, gql_op_plugin, op_def, partial_object from weave.legacy.decorator_arrow_op import arrow_op from weave.legacy.gql_op_plugin import wb_gql_op_plugin from weave.legacy.input_provider import InputProvider diff --git a/weave/legacy/ops_domain/wbgqlquery_op.py b/weave/legacy/ops_domain/wbgqlquery_op.py index 2ed399410b7..e16da74c830 100644 --- a/weave/legacy/ops_domain/wbgqlquery_op.py +++ b/weave/legacy/ops_domain/wbgqlquery_op.py @@ -1,7 +1,7 @@ import logging import typing -from weave import errors +from weave.legacy import errors from weave import weave_types as types from weave.legacy.api import op from weave.legacy import engine_trace, environment, mappers_gql, partial_object diff --git a/weave/legacy/ops_domain/wbmedia.py b/weave/legacy/ops_domain/wbmedia.py index 12683e376e1..72695599163 100644 --- a/weave/legacy/ops_domain/wbmedia.py +++ b/weave/legacy/ops_domain/wbmedia.py @@ -5,8 +5,8 @@ import typing from weave.legacy import api as weave -from weave import errors, types -from weave.legacy import engine_trace, artifact_fs, file_base +from weave import types +from weave.legacy import errors, engine_trace, artifact_fs, file_base from weave.legacy.language_features.tagging.tag_store import isolated_tagging_context from weave.legacy.ops_primitives import html, markdown diff --git a/weave/legacy/ops_primitives/_dict_utils.py b/weave/legacy/ops_primitives/_dict_utils.py index 06c0a9965ee..16b44d7b135 100644 --- a/weave/legacy/ops_primitives/_dict_utils.py +++ b/weave/legacy/ops_primitives/_dict_utils.py @@ -1,6 +1,6 @@ import typing -from weave import errors +from weave.legacy import errors from weave import weave_types as types from weave.legacy import box from weave.legacy.language_features.tagging import tag_store, tagged_value_type diff --git a/weave/legacy/ops_primitives/file.py b/weave/legacy/ops_primitives/file.py index 854da41e866..19d97a3b49a 100644 --- a/weave/legacy/ops_primitives/file.py +++ b/weave/legacy/ops_primitives/file.py @@ -2,7 +2,7 @@ import typing from weave.legacy import environment as weave_env -from weave import errors +from weave.legacy import errors from weave import weave_types as types from weave.legacy.api import op from weave.legacy import file_base, wandb_file_manager diff --git a/weave/legacy/ops_primitives/list_.py b/weave/legacy/ops_primitives/list_.py index 645a6e85a92..a58a2884955 100644 --- a/weave/legacy/ops_primitives/list_.py +++ b/weave/legacy/ops_primitives/list_.py @@ -6,9 +6,9 @@ import numpy as np import pandas as pd -from weave import errors, storage +from weave import storage from weave import weave_types as types -from weave.legacy import box, execute_fast +from weave.legacy import box, execute_fast, errors from weave.legacy._dict_utils import tag_aware_dict_val_for_escaped_key from weave.legacy.decorator_class import weave_class from weave.legacy.decorator_op import op diff --git a/weave/legacy/ops_primitives/pandas_.py b/weave/legacy/ops_primitives/pandas_.py index 3a0b5cad83b..70b15467e9d 100644 --- a/weave/legacy/ops_primitives/pandas_.py +++ b/weave/legacy/ops_primitives/pandas_.py @@ -8,7 +8,7 @@ import pyarrow as pa import pyarrow.parquet as pq -from weave import errors +from weave.legacy import errors from weave import weave_types as types from weave.legacy.api import op, weave_class from weave.legacy import box, file_base, graph, mappers_python diff --git a/weave/legacy/ops_primitives/projection_utils.py b/weave/legacy/ops_primitives/projection_utils.py index 8e05cf2753a..49e96d1e562 100644 --- a/weave/legacy/ops_primitives/projection_utils.py +++ b/weave/legacy/ops_primitives/projection_utils.py @@ -9,7 +9,7 @@ from sklearn.decomposition import PCA from sklearn.manifold import TSNE -from weave import errors +from weave.legacy import errors from weave.legacy import context_state, environment umap_lib = {} diff --git a/weave/legacy/ops_primitives/type.py b/weave/legacy/ops_primitives/type.py index e4364746014..46b7c987062 100644 --- a/weave/legacy/ops_primitives/type.py +++ b/weave/legacy/ops_primitives/type.py @@ -1,6 +1,6 @@ import typing -from weave import errors +from weave.legacy import errors from weave import weave_types as types from weave.legacy.api import op diff --git a/weave/legacy/ops_primitives/weave_api.py b/weave/legacy/ops_primitives/weave_api.py index fb66f04b55f..36295f3f69e 100644 --- a/weave/legacy/ops_primitives/weave_api.py +++ b/weave/legacy/ops_primitives/weave_api.py @@ -3,13 +3,13 @@ import typing from weave import ( - errors, storage, weave_internal, ) from weave import weave_types as types from weave.legacy.api import mutation, op, weave_class from weave.legacy import ( + errors, ref_base, registry_mem, artifact_fs, diff --git a/weave/legacy/panel.py b/weave/legacy/panel.py index 858bc39eeee..632a3d6e78a 100644 --- a/weave/legacy/panel.py +++ b/weave/legacy/panel.py @@ -4,9 +4,9 @@ from tarfile import DEFAULT_FORMAT from weave.legacy import api as weave -from weave import errors, storage, weave_internal +from weave import storage, weave_internal from weave import weave_types as types -from weave.legacy import graph, panel_util +from weave.legacy import graph, panel_util, errors def run_variable_lambdas( diff --git a/weave/legacy/panels/panel_group.py b/weave/legacy/panels/panel_group.py index 07b70604170..a7ea1847900 100644 --- a/weave/legacy/panels/panel_group.py +++ b/weave/legacy/panels/panel_group.py @@ -3,8 +3,9 @@ import typing import weave -from weave import errors, weave_internal +from weave import weave_internal from weave.legacy import ( + errors, codifiable_value_mixin, codify, dispatch, diff --git a/weave/legacy/panels/panel_plot.py b/weave/legacy/panels/panel_plot.py index ef6a606723b..3f3a2804988 100644 --- a/weave/legacy/panels/panel_plot.py +++ b/weave/legacy/panels/panel_plot.py @@ -4,9 +4,9 @@ import typing import weave -from weave import errors, weave_internal +from weave import weave_internal from weave import weave_types as types -from weave.legacy import codifiable_value_mixin, codify, graph, panel +from weave.legacy import errors, codifiable_value_mixin, codify, graph, panel from weave.legacy.ops_primitives import boolean, list_ from weave.legacy.ops_primitives import dict as dict_ from weave.legacy.panels import panel_table, table_state diff --git a/weave/legacy/path_util.py b/weave/legacy/path_util.py index 845bbc4aa9a..a6504697c37 100644 --- a/weave/legacy/path_util.py +++ b/weave/legacy/path_util.py @@ -1,7 +1,7 @@ import pathlib import typing -from .. import errors +from weave.legacy import errors def safe_join(*args: typing.Union[str, pathlib.Path]) -> str: diff --git a/weave/legacy/pyfunc_type_util.py b/weave/legacy/pyfunc_type_util.py index bb544dfd2f4..e327e18b4d5 100644 --- a/weave/legacy/pyfunc_type_util.py +++ b/weave/legacy/pyfunc_type_util.py @@ -3,7 +3,7 @@ from weave.legacy import infer_types, op_args -from .. import errors +from weave.legacy import errors from .. import weave_types as types InputTypeItemType = typing.Union[types.Type, typing.Callable[..., types.Type]] diff --git a/weave/legacy/ref_base.py b/weave/legacy/ref_base.py index e7742d9eb65..a085e044652 100644 --- a/weave/legacy/ref_base.py +++ b/weave/legacy/ref_base.py @@ -9,7 +9,7 @@ from weave.legacy import box, context_state, object_context, uris from weave.legacy.language_features.tagging import tag_store -from .. import errors +from weave.legacy import errors from .. import weave_types as types # We store Refs here if we can't attach them directly to the object diff --git a/weave/legacy/registry_mem.py b/weave/legacy/registry_mem.py index 62f4a42134f..6bfcb60d2ad 100644 --- a/weave/legacy/registry_mem.py +++ b/weave/legacy/registry_mem.py @@ -1,8 +1,8 @@ import datetime import typing -from weave import errors, storage, weave_types -from weave.legacy import context_state, op_aliases, op_args, uris +from weave import storage, weave_types +from weave.legacy import errors, context_state, op_aliases, op_args, uris from weave.legacy.op_args import OpNamedArgs if typing.TYPE_CHECKING: diff --git a/weave/legacy/runfiles_wandb.py b/weave/legacy/runfiles_wandb.py index d61f91f4c53..5aef4727961 100644 --- a/weave/legacy/runfiles_wandb.py +++ b/weave/legacy/runfiles_wandb.py @@ -7,9 +7,16 @@ import typing from weave.legacy import environment as weave_env -from weave import errors, filesystem +from weave import filesystem from weave import weave_types as types -from weave.legacy import artifact_fs, file_util, memo, uris, wandb_client_api +from weave.legacy import ( + artifact_fs, + errors, + file_util, + memo, + uris, + wandb_client_api, +) if typing.TYPE_CHECKING: from wandb.apis.public import Run as WBRun diff --git a/weave/legacy/serialize.py b/weave/legacy/serialize.py index 7a2b55d5e5c..f1b10819b29 100644 --- a/weave/legacy/serialize.py +++ b/weave/legacy/serialize.py @@ -7,9 +7,9 @@ import random import typing -from weave import errors, storage, weave_internal +from weave import storage, weave_internal from weave import weave_types as types -from weave.legacy import graph, memo, value_or_error +from weave.legacy import errors, graph, memo, value_or_error NodeOrOp = typing.Union[graph.Node, graph.Op] diff --git a/weave/legacy/server_error_handling.py b/weave/legacy/server_error_handling.py index bdc5a46ee2b..66c89590acc 100644 --- a/weave/legacy/server_error_handling.py +++ b/weave/legacy/server_error_handling.py @@ -26,8 +26,9 @@ from werkzeug import Response from werkzeug import exceptions as werkzeug_exceptions from werkzeug import http as werkzeug_http +from weave.legacy import errors -from .. import errors, util +from .. import util class WeaveInternalHttpException(werkzeug_exceptions.HTTPException): diff --git a/weave/legacy/show.py b/weave/legacy/show.py index 92ae3f7cf16..40543b67036 100644 --- a/weave/legacy/show.py +++ b/weave/legacy/show.py @@ -5,8 +5,8 @@ from IPython.display import IFrame, display -from weave.legacy import artifact_fs, context, graph, ops, node_ref, panel, ref_base -from weave import errors, storage, util +from weave.legacy import artifact_fs, context, errors, graph, ops, node_ref, panel, ref_base +from weave import storage, util from . import usage_analytics from .. import weave_types as types from . import weavejs_fixes diff --git a/weave/legacy/stitch.py b/weave/legacy/stitch.py index 3c2de9a04bc..878448292d5 100644 --- a/weave/legacy/stitch.py +++ b/weave/legacy/stitch.py @@ -25,7 +25,7 @@ from weave.legacy import graph, op_def, registry_mem from weave.legacy.language_features.tagging import opdef_util -from .. import errors +from weave.legacy import errors from .. import weave_types as types from . import _dict_utils diff --git a/weave/legacy/uris.py b/weave/legacy/uris.py index 7ce5150f23b..465dac98b9f 100644 --- a/weave/legacy/uris.py +++ b/weave/legacy/uris.py @@ -2,7 +2,7 @@ import typing from urllib import parse -from .. import errors +from weave.legacy import errors if typing.TYPE_CHECKING: from . import ref_base diff --git a/weave/legacy/wandb_api.py b/weave/legacy/wandb_api.py index 2ef082916f6..d93a11da936 100644 --- a/weave/legacy/wandb_api.py +++ b/weave/legacy/wandb_api.py @@ -14,7 +14,7 @@ from gql.transport.requests import RequestsHTTPTransport from requests.auth import HTTPBasicAuth -from weave import errors +from weave.legacy import errors from weave.legacy import environment as weave_env from weave.legacy import wandb_client_api, engine_trace diff --git a/weave/legacy/wandb_client_api.py b/weave/legacy/wandb_client_api.py index 524456e5d76..11bbff4e333 100644 --- a/weave/legacy/wandb_client_api.py +++ b/weave/legacy/wandb_client_api.py @@ -12,7 +12,7 @@ from wandb.errors import CommError as WandbCommError from wandb.sdk.internal.internal_api import _thread_local_api_settings -from weave import errors +from weave.legacy import errors def wandb_public_api() -> public.Api: diff --git a/weave/legacy/wandb_file_manager.py b/weave/legacy/wandb_file_manager.py index 6fd5a14a176..2e437c0021a 100644 --- a/weave/legacy/wandb_file_manager.py +++ b/weave/legacy/wandb_file_manager.py @@ -12,9 +12,9 @@ from requests.auth import HTTPBasicAuth from wandb.sdk.lib import hashutil -from weave import errors, filesystem, weave_http +from weave import filesystem, weave_http from weave.legacy import environment as weave_env -from weave.legacy import artifact_wandb, cache, wandb_api, engine_trace +from weave.legacy import artifact_wandb, cache, errors, wandb_api, engine_trace tracer = engine_trace.tracer() # type: ignore diff --git a/weave/legacy/wandb_interface/wandb_lite_run.py b/weave/legacy/wandb_interface/wandb_lite_run.py index 95fa4c8e3f0..4cd60b7452b 100644 --- a/weave/legacy/wandb_interface/wandb_lite_run.py +++ b/weave/legacy/wandb_interface/wandb_lite_run.py @@ -15,7 +15,7 @@ from wandb.sdk.internal.sender import _manifest_json_from_proto from wandb.sdk.lib import runid -from weave import errors +from weave.legacy import errors from weave.legacy import engine_trace, wandb_client_api logger = logging.getLogger(__name__) diff --git a/weave/legacy/wandb_interface/wandb_stream_table.py b/weave/legacy/wandb_interface/wandb_stream_table.py index 4f69e6b7299..4c8072a82f1 100644 --- a/weave/legacy/wandb_interface/wandb_stream_table.py +++ b/weave/legacy/wandb_interface/wandb_stream_table.py @@ -15,8 +15,9 @@ from wandb.sdk.lib.paths import LogicalPath from wandb.sdk.lib.printer import get_printer -from weave import errors, storage, weave_types +from weave import storage, weave_types from weave.legacy import ( + errors, artifact_base, box, environment, diff --git a/weave/legacy/wandb_util.py b/weave/legacy/wandb_util.py index b963eaed1c8..f160a46e2a0 100644 --- a/weave/legacy/wandb_util.py +++ b/weave/legacy/wandb_util.py @@ -1,6 +1,6 @@ import typing -from weave import errors +from weave.legacy import errors from weave import weave_types as types from weave.legacy import ops, ops_domain diff --git a/weave/legacy/weavify.py b/weave/legacy/weavify.py index e739a308e92..651cdc52b9d 100644 --- a/weave/legacy/weavify.py +++ b/weave/legacy/weavify.py @@ -1,8 +1,8 @@ import typing -from weave.legacy import graph, op_args, val_const +from weave.legacy import errors, graph, op_args, val_const -from .. import errors, weave_internal +from .. import weave_internal from .. import weave_types as types if typing.TYPE_CHECKING: diff --git a/weave/storage.py b/weave/storage.py index c87c1db4060..999f3ffd633 100644 --- a/weave/storage.py +++ b/weave/storage.py @@ -15,13 +15,13 @@ artifact_mem, artifact_wandb, box, + errors, graph, mappers_python, ref_base, timestamp, ) -from . import errors from . import weave_types as types Ref = ref_base.Ref diff --git a/weave/tests/legacy/test_access.py b/weave/tests/legacy/test_access.py index 1006a9e400b..cbcfbb6defe 100644 --- a/weave/tests/legacy/test_access.py +++ b/weave/tests/legacy/test_access.py @@ -1,9 +1,9 @@ import pytest import weave -from weave.legacy import artifact_fs, artifact_local, environment, wandb_api +from weave.legacy import artifact_fs, artifact_local, environment, errors, wandb_api -from ... import errors, storage +from ... import storage @pytest.fixture() diff --git a/weave/tests/legacy/test_arrow.py b/weave/tests/legacy/test_arrow.py index 6dc81439f05..87058e0e6ae 100644 --- a/weave/tests/legacy/test_arrow.py +++ b/weave/tests/legacy/test_arrow.py @@ -7,7 +7,7 @@ import pytest from PIL import Image -from weave.legacy import box, context_state, graph, mappers_arrow, ops +from weave.legacy import box, context_state, errors, graph, mappers_arrow, ops # If you're thinking of import vectorize here, don't! Put your # tests in test_arrow_vectorizer.py instead @@ -27,7 +27,7 @@ from weave.tests import list_arrow_test_helpers as lath from ... import api as weave -from ... import errors, storage, weave_internal +from ... import storage, weave_internal from ... import weave_types as types from ...tests import tag_test_util as ttu from ...tests import weavejs_ops diff --git a/weave/tests/legacy/test_arrow_vectorizer.py b/weave/tests/legacy/test_arrow_vectorizer.py index 51aeb512543..b5e38bf8286 100644 --- a/weave/tests/legacy/test_arrow_vectorizer.py +++ b/weave/tests/legacy/test_arrow_vectorizer.py @@ -5,7 +5,7 @@ import pytest from pyarrow import compute as pc -from weave.legacy import box, dispatch, ops +from weave.legacy import box, dispatch, errors, ops from weave.legacy import ops_arrow as arrow from weave.legacy.language_features.tagging import ( make_tag_getter_op, @@ -18,7 +18,7 @@ from weave.legacy.ops_primitives import Boolean, Number, date, dict_, list_ from ... import api as weave -from ... import errors, weave_internal +from ... import weave_internal from ... import weave_types as types string_ops_test_cases = [ diff --git a/weave/tests/legacy/test_filesystem.py b/weave/tests/legacy/test_filesystem.py index 7faa4668230..aaae05b21e9 100644 --- a/weave/tests/legacy/test_filesystem.py +++ b/weave/tests/legacy/test_filesystem.py @@ -2,9 +2,9 @@ import pytest -from weave.legacy import environment +from weave.legacy import environment, errors -from ... import errors, filesystem +from ... import filesystem @pytest.fixture() diff --git a/weave/trace/op_type.py b/weave/trace/op_type.py index c7566e07756..ad447c1c4d2 100644 --- a/weave/trace/op_type.py +++ b/weave/trace/op_type.py @@ -13,7 +13,7 @@ from _ast import AsyncFunctionDef, ExceptHandler from typing import Any, Callable, Optional, Union, get_args, get_origin -from weave.legacy import artifact_fs, context_state +from weave.legacy import artifact_fs, context_state, errors from weave.trace.ipython import ( ClassNotFoundError, get_class_source, @@ -21,7 +21,7 @@ ) from weave.trace.refs import ObjectRef -from .. import errors, storage +from .. import storage from ..legacy import environment from . import serializer from .op import Op diff --git a/weave/trace/serve_fastapi.py b/weave/trace/serve_fastapi.py index 3e3bc7b7286..89ef88b1d8c 100644 --- a/weave/trace/serve_fastapi.py +++ b/weave/trace/serve_fastapi.py @@ -17,8 +17,7 @@ from weave.trace.op import Op from weave.trace.refs import ObjectRef -from .. import errors -from ..legacy import weave_pydantic +from ..legacy import errors, weave_pydantic key_cache: cache.LruTimeWindowCache[str, typing.Optional[bool]] = ( cache.LruTimeWindowCache(datetime.timedelta(minutes=5)) diff --git a/weave/util.py b/weave/util.py index 81ce7070c89..1053f197c2b 100644 --- a/weave/util.py +++ b/weave/util.py @@ -8,7 +8,7 @@ # import ipynbname import typing -from .errors import WeaveFingerprintErrorMixin +from .legacy.errors import WeaveFingerprintErrorMixin sentry_inited = False diff --git a/weave/weave_init.py b/weave/weave_init.py index 21d0e31ab6a..3d0a0233aa5 100644 --- a/weave/weave_init.py +++ b/weave/weave_init.py @@ -1,8 +1,9 @@ import typing from weave.client_context import weave_client as weave_client_context +from weave.legacy import errors -from . import errors, init_message +from . import init_message from .trace import autopatch, trace_sentry, weave_client from .trace_server import remote_http_trace_server, sqlite_trace_server diff --git a/weave/weave_internal.py b/weave/weave_internal.py index 2b6e07b294b..3e6e82a7eb3 100644 --- a/weave/weave_internal.py +++ b/weave/weave_internal.py @@ -1,8 +1,7 @@ import typing -from weave.legacy import client_interface, context_state, graph +from weave.legacy import client_interface, context_state, errors, graph -from . import errors from . import weave_types as types diff --git a/weave/weave_server.py b/weave/weave_server.py index cb77de12faf..a2684fc0aa3 100644 --- a/weave/weave_server.py +++ b/weave/weave_server.py @@ -26,7 +26,6 @@ from werkzeug.exceptions import HTTPException from weave import ( - errors, filesystem, logs, storage, @@ -36,6 +35,7 @@ context_state, engine_trace, environment, + errors, graph, registry_mem, server, diff --git a/weave/weave_types.py b/weave/weave_types.py index 039b7377c1a..3621eaa0de4 100644 --- a/weave/weave_types.py +++ b/weave/weave_types.py @@ -11,11 +11,15 @@ import pydantic from dateutil.parser import isoparse -from weave.legacy import box, context_state, mappers_python, object_type_ref_util +from weave.legacy import ( + box, + context_state, + errors, + mappers_python, + object_type_ref_util, +) from weave.legacy import timestamp as weave_timestamp -from . import errors - if typing.TYPE_CHECKING: from weave.legacy import artifact_base from weave.legacy.artifact_fs import FilesystemArtifact From 97331259dd456864cc63ac0f355bd55d4691a4dd Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 10:47:52 -0400 Subject: [PATCH 38/84] move to legacy: storage --- .../skip_test/Confusion Matrix.ipynb | 4 +- .../skip_test/Performance profiling.ipynb | 2 +- .../experimental/skip_test/Vectorizing.ipynb | 4 +- .../skip_test/branching_runs.ipynb | 3 +- weave/__init__.py | 2 +- weave/legacy/client.py | 3 +- weave/legacy/codify.py | 4 +- weave/legacy/ecosystem/langchain/lc.py | 2 +- weave/legacy/ecosystem/wandb/weave_plotly.py | 2 +- weave/legacy/graph.py | 4 +- weave/legacy/mappers_publisher.py | 3 +- weave/legacy/mappers_python_def.py | 2 +- weave/legacy/op_def.py | 2 +- weave/legacy/op_def_type.py | 2 +- weave/legacy/ops_arrow/ref_ops.py | 2 +- weave/legacy/ops_domain/wbmedia.py | 4 +- weave/legacy/ops_primitives/list_.py | 2 +- weave/legacy/ops_primitives/test_image.py | 2 +- weave/legacy/panel.py | 4 +- weave/legacy/panel_util.py | 4 +- weave/legacy/registry_mem.py | 4 +- weave/legacy/serialize.py | 4 +- weave/legacy/show.py | 4 +- weave/{ => legacy}/storage.py | 42 +++++++++---------- .../wandb_interface/wandb_stream_table.py | 3 +- weave/tests/legacy/test_arrow_concat.py | 3 +- weave/tests/legacy/test_execution_graphs.py | 3 +- weave/tests/legacy/test_hypothesis.py | 3 +- weave/tests/legacy/test_op.py | 4 +- weave/tests/legacy/test_publish_flow.py | 3 +- weave/tests/legacy/test_ref_tracking.py | 2 +- weave/trace/op_type.py | 3 +- weave/trace/ref_util.py | 2 +- weave/weave_server.py | 2 +- 34 files changed, 69 insertions(+), 70 deletions(-) rename weave/{ => legacy}/storage.py (95%) diff --git a/examples/experimental/skip_test/Confusion Matrix.ipynb b/examples/experimental/skip_test/Confusion Matrix.ipynb index 31a3fd0bfa1..b357921adfa 100644 --- a/examples/experimental/skip_test/Confusion Matrix.ipynb +++ b/examples/experimental/skip_test/Confusion Matrix.ipynb @@ -12,7 +12,7 @@ "import itertools\n", "from PIL import Image\n", "import weave\n", - "from weave import storage\n", + "from weave.legacy import storage\n", "from weave import weave_internal\n", "#weave.use_frontend_devmode()" ] @@ -89,7 +89,7 @@ "id": "6583e01c", "metadata": {}, "source": [ - "## Facet is fun!" + "## Facet is fun!\n" ] }, { diff --git a/examples/experimental/skip_test/Performance profiling.ipynb b/examples/experimental/skip_test/Performance profiling.ipynb index a32cce4c8d9..d128c91d462 100644 --- a/examples/experimental/skip_test/Performance profiling.ipynb +++ b/examples/experimental/skip_test/Performance profiling.ipynb @@ -29,7 +29,7 @@ "import os\n", "import cProfile\n", "import weave\n", - "from weave import storage\n", + "from weave.legacy import storage\n", "import random\n", "import time\n", "import pyarrow as pa\n", diff --git a/examples/experimental/skip_test/Vectorizing.ipynb b/examples/experimental/skip_test/Vectorizing.ipynb index 705fb2d3d44..456c64262a8 100644 --- a/examples/experimental/skip_test/Vectorizing.ipynb +++ b/examples/experimental/skip_test/Vectorizing.ipynb @@ -9,8 +9,8 @@ "source": [ "import weave\n", "import time\n", - "from weave import storage\n", - "from weave import geom" + "from weave.legacy import storage\n", + "from weave.legacy.ops_primitives import geom" ] }, { diff --git a/examples/experimental/skip_test/branching_runs.ipynb b/examples/experimental/skip_test/branching_runs.ipynb index 77a28f9d385..bfad154cea7 100644 --- a/examples/experimental/skip_test/branching_runs.ipynb +++ b/examples/experimental/skip_test/branching_runs.ipynb @@ -11,7 +11,8 @@ "import weave\n", "from weave.legacy.ops_primitives import ArrowWeaveList\n", "from weave.legacy.ops_domain import RunSegment\n", - "from weave import storage, publish, type_of\n", + "from weave.legacy import storage\n", + "from weave import publish, type_of\n", "from weave.weave_types import List\n", "import typing\n", "import time\n", diff --git a/weave/__init__.py b/weave/__init__.py index d6aca836e1c..d75cd14713b 100644 --- a/weave/__init__.py +++ b/weave/__init__.py @@ -13,7 +13,7 @@ _loading_builtins_token = _context_state.set_loading_built_ins() from . import weave_types as types -from . import storage +from .legacy import storage from .legacy.api import * from .trace.api import * diff --git a/weave/legacy/client.py b/weave/legacy/client.py index 48590ec8c92..ab9ce10af25 100644 --- a/weave/legacy/client.py +++ b/weave/legacy/client.py @@ -1,4 +1,5 @@ -from weave import storage, weave_types +from weave import weave_types +from weave.legacy import storage class Client: diff --git a/weave/legacy/codify.py b/weave/legacy/codify.py index 0395775e034..e06006e936a 100644 --- a/weave/legacy/codify.py +++ b/weave/legacy/codify.py @@ -6,8 +6,8 @@ import black -from weave import storage, weave_types -from weave.legacy import graph, registry_mem +from weave import weave_types +from weave.legacy import storage, graph, registry_mem from . import codifiable_value_mixin diff --git a/weave/legacy/ecosystem/langchain/lc.py b/weave/legacy/ecosystem/langchain/lc.py index 533600319ea..54a5b870624 100644 --- a/weave/legacy/ecosystem/langchain/lc.py +++ b/weave/legacy/ecosystem/langchain/lc.py @@ -41,7 +41,7 @@ from langchain.vectorstores.base import VectorStoreRetriever import weave -from weave import storage +from weave.legacy import storage from weave.legacy import artifact_base from weave.legacy.artifact_fs import FilesystemArtifact from weave.legacy.ecosystem.langchain import util diff --git a/weave/legacy/ecosystem/wandb/weave_plotly.py b/weave/legacy/ecosystem/wandb/weave_plotly.py index e5e9e85b983..ab098cf4893 100644 --- a/weave/legacy/ecosystem/wandb/weave_plotly.py +++ b/weave/legacy/ecosystem/wandb/weave_plotly.py @@ -178,7 +178,7 @@ def bin_center(bin): @weave.op() def plotly_scatter(data: list[ScatterData]) -> plotly.graph_objs.Figure: - from weave import storage + from weave.legacy import storage data = storage.to_weavejs(data) color = None diff --git a/weave/legacy/graph.py b/weave/legacy/graph.py index 85aeecd13c1..b12d85dfdf9 100644 --- a/weave/legacy/graph.py +++ b/weave/legacy/graph.py @@ -2,8 +2,8 @@ import json import typing -from weave import storage, weave_types -from weave.legacy import uris, errors +from weave import weave_types +from weave.legacy import uris, errors, storage if typing.TYPE_CHECKING: from weave.legacy import weave_inspector diff --git a/weave/legacy/mappers_publisher.py b/weave/legacy/mappers_publisher.py index 4118232aca3..b80f2d1c357 100644 --- a/weave/legacy/mappers_publisher.py +++ b/weave/legacy/mappers_publisher.py @@ -2,7 +2,8 @@ import dataclasses import typing -from weave import storage, weave_internal +from weave.legacy import storage +from weave import weave_internal from weave import weave_types as types from weave.legacy.node_ref import ref_to_node diff --git a/weave/legacy/mappers_python_def.py b/weave/legacy/mappers_python_def.py index 4551d783803..b78e684ca31 100644 --- a/weave/legacy/mappers_python_def.py +++ b/weave/legacy/mappers_python_def.py @@ -4,7 +4,7 @@ import math import typing -from weave import storage +from weave.legacy import storage from weave import weave_types as types from weave.legacy import ( artifact_fs, diff --git a/weave/legacy/op_def.py b/weave/legacy/op_def.py index d38d208a4ba..8c63b15faaa 100644 --- a/weave/legacy/op_def.py +++ b/weave/legacy/op_def.py @@ -365,7 +365,7 @@ def _replace_var_with_val(n): # This can happen due to nullability. In that case, accept the output type is null final_output_type = types.NoneType() # Have to deref if in case a ref came back... - from weave import storage + from weave.legacy import storage final_output_type = storage.deref(final_output_type) diff --git a/weave/legacy/op_def_type.py b/weave/legacy/op_def_type.py index 040eeef1415..bb264899260 100644 --- a/weave/legacy/op_def_type.py +++ b/weave/legacy/op_def_type.py @@ -11,7 +11,7 @@ from _ast import AsyncFunctionDef, ExceptHandler from typing import Any -from weave import storage +from weave.legacy import storage from weave import weave_types as types from weave.legacy import ( artifact_fs, diff --git a/weave/legacy/ops_arrow/ref_ops.py b/weave/legacy/ops_arrow/ref_ops.py index 24fc3b23c3c..b5edd10d227 100644 --- a/weave/legacy/ops_arrow/ref_ops.py +++ b/weave/legacy/ops_arrow/ref_ops.py @@ -22,7 +22,7 @@ output_type=ArrowWeaveListType(types.Boolean()), ) def ref_equal(self, other): - from weave import storage + from weave.legacy import storage # Weave engine automatically derefs, so we need to undo that via # _get_ref here. diff --git a/weave/legacy/ops_domain/wbmedia.py b/weave/legacy/ops_domain/wbmedia.py index 72695599163..32e3fe4f937 100644 --- a/weave/legacy/ops_domain/wbmedia.py +++ b/weave/legacy/ops_domain/wbmedia.py @@ -283,7 +283,7 @@ class LegacyTableNDArrayType(types.Type): # code can work with it. @weave.op() def html_file(html: html.Html) -> HtmlArtifactFileRef: - from weave import storage + from weave.legacy import storage # This is a ref to the html object with isolated_tagging_context(): @@ -305,7 +305,7 @@ def html_file(html: html.Html) -> HtmlArtifactFileRef: ) ) def markdown_file(md: markdown.Markdown): - from weave import storage + from weave.legacy import storage with isolated_tagging_context(): ref = storage.save(md) diff --git a/weave/legacy/ops_primitives/list_.py b/weave/legacy/ops_primitives/list_.py index a58a2884955..d2aab966eef 100644 --- a/weave/legacy/ops_primitives/list_.py +++ b/weave/legacy/ops_primitives/list_.py @@ -6,7 +6,7 @@ import numpy as np import pandas as pd -from weave import storage +from weave.legacy import storage from weave import weave_types as types from weave.legacy import box, execute_fast, errors from weave.legacy._dict_utils import tag_aware_dict_val_for_escaped_key diff --git a/weave/legacy/ops_primitives/test_image.py b/weave/legacy/ops_primitives/test_image.py index 945c3865bb2..12c0e7868fe 100644 --- a/weave/legacy/ops_primitives/test_image.py +++ b/weave/legacy/ops_primitives/test_image.py @@ -2,7 +2,7 @@ import pytest from PIL import Image -from weave import storage +from weave.legacy import storage from weave.legacy.ops_primitives import api as weave diff --git a/weave/legacy/panel.py b/weave/legacy/panel.py index 632a3d6e78a..922023202fe 100644 --- a/weave/legacy/panel.py +++ b/weave/legacy/panel.py @@ -4,9 +4,9 @@ from tarfile import DEFAULT_FORMAT from weave.legacy import api as weave -from weave import storage, weave_internal +from weave import weave_internal from weave import weave_types as types -from weave.legacy import graph, panel_util, errors +from weave.legacy import graph, panel_util, errors, storage def run_variable_lambdas( diff --git a/weave/legacy/panel_util.py b/weave/legacy/panel_util.py index ae349f67a1c..3da288431dc 100644 --- a/weave/legacy/panel_util.py +++ b/weave/legacy/panel_util.py @@ -1,7 +1,7 @@ import typing -from weave import storage, weave_types -from weave.legacy import graph, panel +from weave import weave_types +from weave.legacy import storage, graph, panel def make_node(v: typing.Any) -> graph.Node: diff --git a/weave/legacy/registry_mem.py b/weave/legacy/registry_mem.py index 6bfcb60d2ad..cbc863f6d31 100644 --- a/weave/legacy/registry_mem.py +++ b/weave/legacy/registry_mem.py @@ -1,8 +1,8 @@ import datetime import typing -from weave import storage, weave_types -from weave.legacy import errors, context_state, op_aliases, op_args, uris +from weave import weave_types +from weave.legacy import storage, errors, context_state, op_aliases, op_args, uris from weave.legacy.op_args import OpNamedArgs if typing.TYPE_CHECKING: diff --git a/weave/legacy/serialize.py b/weave/legacy/serialize.py index f1b10819b29..b0d750f2902 100644 --- a/weave/legacy/serialize.py +++ b/weave/legacy/serialize.py @@ -7,9 +7,9 @@ import random import typing -from weave import storage, weave_internal +from weave import weave_internal from weave import weave_types as types -from weave.legacy import errors, graph, memo, value_or_error +from weave.legacy import storage, errors, graph, memo, value_or_error NodeOrOp = typing.Union[graph.Node, graph.Op] diff --git a/weave/legacy/show.py b/weave/legacy/show.py index 40543b67036..7091b2f8444 100644 --- a/weave/legacy/show.py +++ b/weave/legacy/show.py @@ -5,8 +5,8 @@ from IPython.display import IFrame, display -from weave.legacy import artifact_fs, context, errors, graph, ops, node_ref, panel, ref_base -from weave import storage, util +from weave.legacy import storage, artifact_fs, context, errors, graph, ops, node_ref, panel, ref_base +from weave import util from . import usage_analytics from .. import weave_types as types from . import weavejs_fixes diff --git a/weave/storage.py b/weave/legacy/storage.py similarity index 95% rename from weave/storage.py rename to weave/legacy/storage.py index 999f3ffd633..dce6b4d82f5 100644 --- a/weave/storage.py +++ b/weave/legacy/storage.py @@ -22,7 +22,7 @@ timestamp, ) -from . import weave_types as types +from weave import weave_types as types Ref = ref_base.Ref @@ -30,7 +30,7 @@ from weave.legacy.wandb_interface.wandb_lite_run import InMemoryLazyLiteRun -def split_path_dotfile(path, dotfile_name): +def split_path_dotfile(path, dotfile_name): # type: ignore while path != "/": path, tail = os.path.split(path) if os.path.exists(os.path.join(path, dotfile_name)): @@ -50,7 +50,7 @@ def _get_name(wb_type: types.Type, obj: typing.Any) -> str: # return f"{wb_type.name}-{obj_names[-1]}" -def _get_weave_type_with_refs(obj: typing.Any): +def _get_weave_type_with_refs(obj: typing.Any): # type: ignore try: return types.type_of_with_refs(obj) except errors.WeaveTypeError as e: @@ -60,7 +60,7 @@ def _get_weave_type_with_refs(obj: typing.Any): ) -def _ensure_object_components_are_published( +def _ensure_object_components_are_published( # type: ignore obj: typing.Any, wb_type: types.Type, artifact: artifact_wandb.WandbArtifact ): from weave.legacy.mappers_publisher import map_to_python_remote @@ -69,7 +69,7 @@ def _ensure_object_components_are_published( return mapper.apply(obj) -def _assert_valid_name_part(part: typing.Optional[str] = None): +def _assert_valid_name_part(part: typing.Optional[str] = None): # type: ignore if part is None: return if not re.match(r"^[a-zA-Z0-9_\-]+$", part): @@ -78,7 +78,7 @@ def _assert_valid_name_part(part: typing.Optional[str] = None): ) -def _assert_valid_entity_name(part: typing.Optional[str] = None): +def _assert_valid_entity_name(part: typing.Optional[str] = None): # type: ignore if part is None: return if not re.match(r"^[a-z0-9_\-]+$", part): @@ -88,7 +88,7 @@ def _assert_valid_entity_name(part: typing.Optional[str] = None): ) -def _assert_valid_project_name(part: typing.Optional[str] = None): +def _assert_valid_project_name(part: typing.Optional[str] = None): # type: ignore if part is None: return if len(part) > 128: @@ -99,7 +99,7 @@ def _assert_valid_project_name(part: typing.Optional[str] = None): ) -def _assert_valid_artifact_name(part: typing.Optional[str] = None): +def _assert_valid_artifact_name(part: typing.Optional[str] = None): # type: ignore if part is None: return if len(part) > 128: @@ -123,7 +123,7 @@ class PublishTargetProject(typing.TypedDict): @contextlib.contextmanager -def publish_target_project(project: PublishTargetProject): +def publish_target_project(project: PublishTargetProject): # type: ignore token = _pubish_target_project.set(project) yield _pubish_target_project.reset(token) @@ -243,12 +243,12 @@ def direct_save( # Only save if we have a ref into the artifact we created above. Otherwise # nothing new was created, so just return the existing ref. if ref.artifact == artifact: - artifact.save(branch=branch_name) + artifact.save(branch=branch_name) # type: ignore[no-untyped-call] return ref # type: ignore -def publish(obj, name=None, type=None): +def publish(obj, name=None, type=None): # type: ignore # We would probably refactor this method to be more like _direct_publish. This effectively # just a wrapper that let's the user specify project name with a slash. # TODO: should we only expose save for our API with a "remote" flag or something @@ -264,7 +264,7 @@ def publish(obj, name=None, type=None): ) -def save( +def save( # type: ignore obj, name=None, type=None, @@ -297,7 +297,7 @@ def get(uri_s: typing.Union[str, ref_base.Ref]) -> typing.Any: get_local_version = artifact_local.get_local_version -def deref(ref): +def deref(ref): # type: ignore if isinstance(ref, ref_base.Ref): return ref.get() return ref @@ -309,7 +309,7 @@ def _get_ref(obj: typing.Any) -> typing.Optional[ref_base.Ref]: return ref_base.get_ref(obj) -def clear_ref(obj): +def clear_ref(obj): # type: ignore ref_base.clear_ref(obj) @@ -330,7 +330,7 @@ def local_artifacts() -> typing.List[artifact_local.LocalArtifact]: return result -def all_objects(): +def all_objects(): # type: ignore result = [] obj_paths = sorted( pathlib.Path(artifact_local.local_artifact_dir()).iterdir(), @@ -365,7 +365,7 @@ def objects( return [r[1] for r in sorted(result)] -def recursively_unwrap_arrow(obj): +def recursively_unwrap_arrow(obj): # type: ignore if getattr(obj, "to_pylist_notags", None): return obj.to_pylist_notags() if getattr(obj, "as_py", None): @@ -387,7 +387,7 @@ def _default_ref_persister_artifact( for mem_ref in refs: if mem_ref.path is not None and mem_ref._type is not None: fs_art.set(mem_ref.path, mem_ref._type, mem_ref._obj) - fs_art.save() + fs_art.save() # type: ignore[no-untyped-call] return fs_art @@ -421,7 +421,7 @@ def to_python( return {"_type": wb_type.to_dict(), "_val": val} -def to_safe_const(obj): +def to_safe_const(obj): # type: ignore wb_type = types.TypeRegistry.type_of(obj) mapper = mappers_python.map_to_python(wb_type, artifact_mem.MemArtifact()) val = mapper.apply(obj) @@ -436,7 +436,7 @@ def from_python(obj: dict, wb_type: typing.Optional[types.Type] = None) -> typin return res -def to_json_with_refs( +def to_json_with_refs( # type: ignore obj: typing.Any, artifact: artifact_base.Artifact, path: typing.Optional[list[str]] = None, @@ -492,7 +492,7 @@ def to_json_with_refs( return res -def make_js_serializer(): +def make_js_serializer(): # type: ignore artifact = artifact_mem.MemArtifact() return functools.partial(to_weavejs, artifact=artifact) @@ -507,7 +507,7 @@ def convert_timestamps_to_epoch_ms(obj: typing.Any) -> typing.Any: return obj -def to_weavejs(obj, artifact: typing.Optional[artifact_base.Artifact] = None): +def to_weavejs(obj, artifact: typing.Optional[artifact_base.Artifact] = None): # type: ignore from weave.legacy.arrow import list_ as arrow_list obj = box.unbox(obj) diff --git a/weave/legacy/wandb_interface/wandb_stream_table.py b/weave/legacy/wandb_interface/wandb_stream_table.py index 4c8072a82f1..7d3e307cd7a 100644 --- a/weave/legacy/wandb_interface/wandb_stream_table.py +++ b/weave/legacy/wandb_interface/wandb_stream_table.py @@ -15,8 +15,9 @@ from wandb.sdk.lib.paths import LogicalPath from wandb.sdk.lib.printer import get_printer -from weave import storage, weave_types +from weave import weave_types from weave.legacy import ( + storage, errors, artifact_base, box, diff --git a/weave/tests/legacy/test_arrow_concat.py b/weave/tests/legacy/test_arrow_concat.py index 66e6bcf3d95..45317b3f39a 100644 --- a/weave/tests/legacy/test_arrow_concat.py +++ b/weave/tests/legacy/test_arrow_concat.py @@ -3,8 +3,7 @@ import pytest import weave -from weave import storage -from weave.legacy import artifact_local +from weave.legacy import artifact_local, storage from weave.legacy.ops_arrow import to_arrow from weave.legacy.ops_domain import wbmedia diff --git a/weave/tests/legacy/test_execution_graphs.py b/weave/tests/legacy/test_execution_graphs.py index 78096f659a1..37c6caee650 100644 --- a/weave/tests/legacy/test_execution_graphs.py +++ b/weave/tests/legacy/test_execution_graphs.py @@ -3,8 +3,7 @@ import os import zlib -from weave import storage -from weave.legacy import serialize +from weave.legacy import serialize, storage from weave.legacy.server import handle_request diff --git a/weave/tests/legacy/test_hypothesis.py b/weave/tests/legacy/test_hypothesis.py index 421c618ce54..915711acfac 100644 --- a/weave/tests/legacy/test_hypothesis.py +++ b/weave/tests/legacy/test_hypothesis.py @@ -44,8 +44,7 @@ from hypothesis.strategies import composite import weave -from weave import storage -from weave.legacy import artifact_local, ops_arrow, ops_primitives +from weave.legacy import artifact_local, ops_arrow, ops_primitives, storage from weave.legacy.arrow import convert from weave.legacy.language_features.tagging import tag_store diff --git a/weave/tests/legacy/test_op.py b/weave/tests/legacy/test_op.py index 855b6555b84..46cea2177cb 100644 --- a/weave/tests/legacy/test_op.py +++ b/weave/tests/legacy/test_op.py @@ -2,9 +2,9 @@ import pytest -from weave import storage, types, weave_internal +from weave import types, weave_internal from weave.legacy import api as weave -from weave.legacy import context_state, graph, uris +from weave.legacy import context_state, graph, storage, uris from weave.legacy import context_state as _context_state from . import test_helpers diff --git a/weave/tests/legacy/test_publish_flow.py b/weave/tests/legacy/test_publish_flow.py index f0a6a054ce5..228fdd200d0 100644 --- a/weave/tests/legacy/test_publish_flow.py +++ b/weave/tests/legacy/test_publish_flow.py @@ -3,8 +3,7 @@ import pytest import weave -from weave import storage -from weave.legacy import panels +from weave.legacy import panels, storage from weave.legacy.artifact_fs import BranchPointType, FilesystemArtifactRef from weave.legacy.artifact_local import ( LocalArtifact, diff --git a/weave/tests/legacy/test_ref_tracking.py b/weave/tests/legacy/test_ref_tracking.py index 8f6a830ab71..efd5d5a4895 100644 --- a/weave/tests/legacy/test_ref_tracking.py +++ b/weave/tests/legacy/test_ref_tracking.py @@ -1,6 +1,6 @@ import weave -from weave import storage from weave import weave_types as types +from weave.legacy import storage def test_reffed_type(ref_tracking): diff --git a/weave/trace/op_type.py b/weave/trace/op_type.py index ad447c1c4d2..90608f9c99b 100644 --- a/weave/trace/op_type.py +++ b/weave/trace/op_type.py @@ -13,7 +13,7 @@ from _ast import AsyncFunctionDef, ExceptHandler from typing import Any, Callable, Optional, Union, get_args, get_origin -from weave.legacy import artifact_fs, context_state, errors +from weave.legacy import artifact_fs, context_state, errors, storage from weave.trace.ipython import ( ClassNotFoundError, get_class_source, @@ -21,7 +21,6 @@ ) from weave.trace.refs import ObjectRef -from .. import storage from ..legacy import environment from . import serializer from .op import Op diff --git a/weave/trace/ref_util.py b/weave/trace/ref_util.py index 93ec19decd7..ebaec7dfe1e 100644 --- a/weave/trace/ref_util.py +++ b/weave/trace/ref_util.py @@ -31,7 +31,7 @@ def val_with_relative_ref( # Only do this if ref_tracking_enabled right now. I just want to # avoid introducing new behavior into W&B prod for the moment. if context_state.ref_tracking_enabled(): - from .. import storage + from weave.legacy import storage child_ref = storage.get_ref(child_object) parent_ref = ref_base.get_ref(parent_object) diff --git a/weave/weave_server.py b/weave/weave_server.py index a2684fc0aa3..a236262855e 100644 --- a/weave/weave_server.py +++ b/weave/weave_server.py @@ -28,7 +28,6 @@ from weave import ( filesystem, logs, - storage, util, ) from weave.legacy import ( @@ -39,6 +38,7 @@ graph, registry_mem, server, + storage, value_or_error, wandb_api, weavejs_fixes, From 9f2d0b9eb026ef1c20cc8544f26d8c1e2e71b7bd Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 11:25:03 -0400 Subject: [PATCH 39/84] move to legacy: logs --- weave/conftest.py | 2 +- weave/legacy/engine_trace.py | 3 +-- weave/legacy/environment.py | 4 ++-- weave/{ => legacy}/logs.py | 0 weave/legacy/server.py | 3 ++- weave/tests/legacy/test_logging.py | 4 ++-- weave/weave_server.py | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) rename weave/{ => legacy}/logs.py (100%) diff --git a/weave/conftest.py b/weave/conftest.py index c11f8c7a41e..f9916306774 100644 --- a/weave/conftest.py +++ b/weave/conftest.py @@ -24,7 +24,7 @@ ) from weave.trace_server import trace_server_interface as tsi -from . import logs +from .legacy import logs from .tests import fixture_fakewandb from .tests.trace.trace_server_clickhouse_conftest import * from .tests.wandb_system_tests_conftest import * diff --git a/weave/legacy/engine_trace.py b/weave/legacy/engine_trace.py index c522afeefab..20ce84169e7 100644 --- a/weave/legacy/engine_trace.py +++ b/weave/legacy/engine_trace.py @@ -18,8 +18,7 @@ import time import typing -from .. import logs -from . import environment, stream_data_interfaces +from weave.legacy import environment, logs, stream_data_interfaces # Thanks co-pilot! diff --git a/weave/legacy/environment.py b/weave/legacy/environment.py index 1e22db8919f..ed4a0ecd6d6 100644 --- a/weave/legacy/environment.py +++ b/weave/legacy/environment.py @@ -14,7 +14,7 @@ from .. import util if typing.TYPE_CHECKING: - from .. import logs + from weave.legacy import logs WANDB_ERROR_REPORTING = "WANDB_ERROR_REPORTING" WEAVE_USAGE_ANALYTICS = "WEAVE_USAGE_ANALYTICS" @@ -105,7 +105,7 @@ def is_public() -> bool: def weave_log_format(default: "logs.LogFormat") -> "logs.LogFormat": - from ..logs import LogFormat + from weave.legacy.logs import LogFormat return LogFormat(os.getenv("WEAVE_LOG_FORMAT", default)) diff --git a/weave/logs.py b/weave/legacy/logs.py similarity index 100% rename from weave/logs.py rename to weave/legacy/logs.py diff --git a/weave/legacy/server.py b/weave/legacy/server.py index 2e6a90fb6e7..d008f30e122 100644 --- a/weave/legacy/server.py +++ b/weave/legacy/server.py @@ -22,11 +22,12 @@ serialize, value_or_error, wandb_api, + logs, ) from weave.legacy.language_features.tagging import tag_store from weave.legacy.language_features.tagging.tag_store import isolated_tagging_context -from .. import logs, storage, util, weave_types +from .. import storage, util, weave_types # A function to monkeypatch the request post method # def patch_request_post(): diff --git a/weave/tests/legacy/test_logging.py b/weave/tests/legacy/test_logging.py index 310c95d6cfb..48463f5e49f 100644 --- a/weave/tests/legacy/test_logging.py +++ b/weave/tests/legacy/test_logging.py @@ -4,9 +4,9 @@ import pytest import requests -from weave.legacy import context, ops, server +from weave.legacy import context, logs, ops, server -from ... import api, logs, weave_server +from ... import api, weave_server def test_logfile_created(fresh_server_logfile): diff --git a/weave/weave_server.py b/weave/weave_server.py index a236262855e..509fea89cce 100644 --- a/weave/weave_server.py +++ b/weave/weave_server.py @@ -27,7 +27,6 @@ from weave import ( filesystem, - logs, util, ) from weave.legacy import ( @@ -36,6 +35,7 @@ environment, errors, graph, + logs, registry_mem, server, storage, From 1f5f4b30d36cc92af7eed716508b659ee1ef1f20 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 11:36:30 -0400 Subject: [PATCH 40/84] move to legacy: urls --- weave/init_message.py | 2 +- weave/legacy/artifact_wandb.py | 2 +- weave/legacy/context.py | 4 ++-- weave/{ => legacy}/urls.py | 0 weave/trace/api.py | 2 +- weave/trace/weave_client.py | 3 ++- 6 files changed, 7 insertions(+), 6 deletions(-) rename weave/{ => legacy}/urls.py (100%) diff --git a/weave/init_message.py b/weave/init_message.py index 34f107139dd..d76b8e963be 100644 --- a/weave/init_message.py +++ b/weave/init_message.py @@ -1,6 +1,6 @@ import typing -from weave import urls +from weave.legacy import urls if typing.TYPE_CHECKING: import packaging.version # type: ignore[import-not-found] diff --git a/weave/legacy/artifact_wandb.py b/weave/legacy/artifact_wandb.py index 8f9a2fcfae1..1b44de0bfe4 100644 --- a/weave/legacy/artifact_wandb.py +++ b/weave/legacy/artifact_wandb.py @@ -15,11 +15,11 @@ from weave import ( filesystem, - urls, util, ) from weave import weave_types as types from weave.legacy import ( + urls, errors, engine_trace, artifact_fs, diff --git a/weave/legacy/context.py b/weave/legacy/context.py index 1dfb3fab302..8333bcd9692 100644 --- a/weave/legacy/context.py +++ b/weave/legacy/context.py @@ -4,8 +4,8 @@ import typing from urllib.parse import urlparse -from weave import urls, util -from weave.legacy import client, context_state +from weave import util +from weave.legacy import urls, client, context_state from weave.legacy.client_interface import ClientInterface diff --git a/weave/urls.py b/weave/legacy/urls.py similarity index 100% rename from weave/urls.py rename to weave/legacy/urls.py diff --git a/weave/trace/api.py b/weave/trace/api.py index 5fd03e25d67..449c1b34758 100644 --- a/weave/trace/api.py +++ b/weave/trace/api.py @@ -7,13 +7,13 @@ from typing import Any, Callable, Iterator, Optional, Union from weave.client_context import weave_client as weave_client_context +from weave.legacy import urls from weave.trace.call_context import get_current_call # TODO: type_serializers is imported here to trigger registration of the image serializer. # There is probably a better place for this, but including here for now to get the fix in. from .. import ( type_serializers, # noqa: F401 - urls, util, weave_init, ) diff --git a/weave/trace/weave_client.py b/weave/trace/weave_client.py index 3a3af5e6166..b856c059df4 100644 --- a/weave/trace/weave_client.py +++ b/weave/trace/weave_client.py @@ -9,8 +9,9 @@ import pydantic from requests import HTTPError -from weave import urls, version +from weave import version from weave.client_context import weave_client as weave_client_context +from weave.legacy import urls from weave.trace import call_context, trace_sentry from weave.trace.exception import exception_to_json_str from weave.trace.feedback import FeedbackQuery, RefFeedbackQuery From 7205d9e5184263aeb036491132bb6c3ce3c482e6 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 11:50:09 -0400 Subject: [PATCH 41/84] move to legacy: util --- weave/filesystem.py | 4 +--- weave/legacy/api.py | 2 +- weave/legacy/artifact_local.py | 3 ++- weave/legacy/artifact_wandb.py | 2 +- weave/legacy/context.py | 2 +- weave/legacy/dispatch.py | 2 +- weave/legacy/environment.py | 2 +- .../ops_domain/run_history/history_op_common.py | 4 +--- weave/legacy/ops_domain/table.py | 3 ++- weave/legacy/panels_py/panel_autoboard.py | 3 ++- weave/legacy/panels_py/panel_llm_monitor.py | 4 ++-- weave/legacy/panels_py/panel_trace_monitor.py | 4 ++-- weave/legacy/scripts/syndata.py | 2 +- weave/legacy/server.py | 3 ++- weave/legacy/server_error_handling.py | 2 +- weave/legacy/show.py | 2 +- weave/{ => legacy}/util.py | 16 ++++++++-------- weave/tests/fixture_fakewandb.py | 3 +-- weave/tests/legacy/test_relpath_no_syscalls.py | 2 +- weave/trace/api.py | 3 +-- weave/trace/feedback.py | 3 +-- weave/trace/rich_pydantic_util.py | 2 +- weave/weave_server.py | 2 +- 23 files changed, 36 insertions(+), 39 deletions(-) rename weave/{ => legacy}/util.py (93%) diff --git a/weave/filesystem.py b/weave/filesystem.py index d46b06c6843..559ecaa1bd8 100644 --- a/weave/filesystem.py +++ b/weave/filesystem.py @@ -20,9 +20,7 @@ from aiofiles.threadpool import binary as aiofiles_binary from aiofiles.threadpool import text as aiofiles_text -from weave.legacy import cache, engine_trace, environment, errors - -from . import util +from weave.legacy import cache, engine_trace, environment, errors, util tracer = engine_trace.tracer() # type: ignore async_utime = aiofiles_os.wrap(os.utime) # type: ignore diff --git a/weave/legacy/api.py b/weave/legacy/api.py index 177efdf3d20..54ad4e2fcb5 100644 --- a/weave/legacy/api.py +++ b/weave/legacy/api.py @@ -14,7 +14,7 @@ from .. import weave_internal as _weave_internal -from .. import util as _util +from weave.legacy import util as _util from weave.legacy import context as _context from .. import weave_init as _weave_init diff --git a/weave/legacy/artifact_local.py b/weave/legacy/artifact_local.py index 498c3e5d2d5..ff271ae4c48 100644 --- a/weave/legacy/artifact_local.py +++ b/weave/legacy/artifact_local.py @@ -9,7 +9,7 @@ import typing from datetime import datetime -from weave import filesystem, util +from weave import filesystem from weave import weave_types as types from weave.legacy import ( artifact_fs, @@ -19,6 +19,7 @@ file_base, file_util, uris, + util, ) WORKING_DIR_PREFIX = "__working__" diff --git a/weave/legacy/artifact_wandb.py b/weave/legacy/artifact_wandb.py index 1b44de0bfe4..2c3173a3b8c 100644 --- a/weave/legacy/artifact_wandb.py +++ b/weave/legacy/artifact_wandb.py @@ -15,7 +15,6 @@ from weave import ( filesystem, - util, ) from weave import weave_types as types from weave.legacy import ( @@ -29,6 +28,7 @@ memo, uris, wandb_client_api, + util, ) from weave.legacy.wandb_interface import wandb_artifact_pusher diff --git a/weave/legacy/context.py b/weave/legacy/context.py index 8333bcd9692..ab01ec33727 100644 --- a/weave/legacy/context.py +++ b/weave/legacy/context.py @@ -4,7 +4,7 @@ import typing from urllib.parse import urlparse -from weave import util +from weave.legacy import util from weave.legacy import urls, client, context_state from weave.legacy.client_interface import ClientInterface diff --git a/weave/legacy/dispatch.py b/weave/legacy/dispatch.py index 872ad267e68..9ab44a17312 100644 --- a/weave/legacy/dispatch.py +++ b/weave/legacy/dispatch.py @@ -5,7 +5,7 @@ import typing from dataclasses import dataclass -from weave import util +from weave.legacy import util from weave import weave_types as types from weave.legacy import graph, memo, op_args, op_def, pyfunc_type_util, registry_mem, errors from weave.legacy.language_features.tagging.is_tag_getter import is_tag_getter diff --git a/weave/legacy/environment.py b/weave/legacy/environment.py index ed4a0ecd6d6..a2bc2d81852 100644 --- a/weave/legacy/environment.py +++ b/weave/legacy/environment.py @@ -11,7 +11,7 @@ from distutils.util import strtobool from urllib.parse import urlparse from weave.legacy import errors -from .. import util +from weave.legacy import util if typing.TYPE_CHECKING: from weave.legacy import logs diff --git a/weave/legacy/ops_domain/run_history/history_op_common.py b/weave/legacy/ops_domain/run_history/history_op_common.py index b95c1bf14b4..c1e6f7a1f0f 100644 --- a/weave/legacy/ops_domain/run_history/history_op_common.py +++ b/weave/legacy/ops_domain/run_history/history_op_common.py @@ -4,12 +4,10 @@ import pyarrow as pa from pyarrow import parquet as pq -from weave import ( - util, -) from weave import weave_types as types from weave.legacy.api import use from weave.legacy import ( + util, errors, engine_trace, registry_mem, diff --git a/weave/legacy/ops_domain/table.py b/weave/legacy/ops_domain/table.py index 1253293fe95..1f295cf62b5 100644 --- a/weave/legacy/ops_domain/table.py +++ b/weave/legacy/ops_domain/table.py @@ -5,7 +5,7 @@ import logging import typing -from weave import util, weave_internal +from weave import weave_internal from weave import weave_types as types from weave.legacy.api import op, weave_class from weave.legacy import ( @@ -16,6 +16,7 @@ wandb_util, engine_trace, errors, + util, ) from weave.legacy import timestamp as weave_timestamp from weave.legacy.ops_domain import trace_tree, wbmedia diff --git a/weave/legacy/panels_py/panel_autoboard.py b/weave/legacy/panels_py/panel_autoboard.py index b25c48c276c..ab37b9813ac 100644 --- a/weave/legacy/panels_py/panel_autoboard.py +++ b/weave/legacy/panels_py/panel_autoboard.py @@ -26,9 +26,10 @@ import typing import weave -from weave import util, weave_internal +from weave import weave_internal from weave.legacy.panels import panel_plot from weave.legacy.panels_py.generator_templates import template_registry +from weave.legacy import util @weave.type() diff --git a/weave/legacy/panels_py/panel_llm_monitor.py b/weave/legacy/panels_py/panel_llm_monitor.py index cdaa9cffd82..73cc9278e2b 100644 --- a/weave/legacy/panels_py/panel_llm_monitor.py +++ b/weave/legacy/panels_py/panel_llm_monitor.py @@ -2,10 +2,10 @@ import typing import weave -from weave import util, weave_internal +from weave import weave_internal from weave import weave_internal as internal from weave import weave_types as types -from weave.legacy import dispatch +from weave.legacy import util, dispatch from weave.legacy.panels import panel_board, panel_group from weave.legacy.panels_py import panel_autoboard from weave.legacy.panels_py.generator_templates import template_registry diff --git a/weave/legacy/panels_py/panel_trace_monitor.py b/weave/legacy/panels_py/panel_trace_monitor.py index d4fab19ccee..cb0a9a9e334 100644 --- a/weave/legacy/panels_py/panel_trace_monitor.py +++ b/weave/legacy/panels_py/panel_trace_monitor.py @@ -1,10 +1,10 @@ import os import weave -from weave import util, weave_internal +from weave import weave_internal from weave import weave_internal as internal from weave import weave_types as types -from weave.legacy import dispatch, graph +from weave.legacy import util, dispatch, graph from weave.legacy.panels import panel_board, panel_group, panel_trace from weave.legacy.panels.panel_trace_span import TraceSpanModelPanel, TraceSpanPanel from weave.legacy.panels_py import panel_autoboard diff --git a/weave/legacy/scripts/syndata.py b/weave/legacy/scripts/syndata.py index 9f7c697b556..c2436a7efd9 100644 --- a/weave/legacy/scripts/syndata.py +++ b/weave/legacy/scripts/syndata.py @@ -5,7 +5,7 @@ import pyarrow as pa from scipy.signal import butter, filtfilt -from ... import util +from weave.legacy import util from ..ops_arrow import ArrowWeaveList value_fns: list[typing.Any] = [ diff --git a/weave/legacy/server.py b/weave/legacy/server.py index d008f30e122..de94e6b17bb 100644 --- a/weave/legacy/server.py +++ b/weave/legacy/server.py @@ -23,11 +23,12 @@ value_or_error, wandb_api, logs, + util, ) from weave.legacy.language_features.tagging import tag_store from weave.legacy.language_features.tagging.tag_store import isolated_tagging_context -from .. import storage, util, weave_types +from .. import storage, weave_types # A function to monkeypatch the request post method # def patch_request_post(): diff --git a/weave/legacy/server_error_handling.py b/weave/legacy/server_error_handling.py index 66c89590acc..f7c262a24c0 100644 --- a/weave/legacy/server_error_handling.py +++ b/weave/legacy/server_error_handling.py @@ -28,7 +28,7 @@ from werkzeug import http as werkzeug_http from weave.legacy import errors -from .. import util +from weave.legacy import util class WeaveInternalHttpException(werkzeug_exceptions.HTTPException): diff --git a/weave/legacy/show.py b/weave/legacy/show.py index 7091b2f8444..0f03b3da900 100644 --- a/weave/legacy/show.py +++ b/weave/legacy/show.py @@ -6,7 +6,7 @@ from IPython.display import IFrame, display from weave.legacy import storage, artifact_fs, context, errors, graph, ops, node_ref, panel, ref_base -from weave import util +from weave.legacy import util from . import usage_analytics from .. import weave_types as types from . import weavejs_fixes diff --git a/weave/util.py b/weave/legacy/util.py similarity index 93% rename from weave/util.py rename to weave/legacy/util.py index 1053f197c2b..8027cf35a9d 100644 --- a/weave/util.py +++ b/weave/legacy/util.py @@ -8,12 +8,12 @@ # import ipynbname import typing -from .legacy.errors import WeaveFingerprintErrorMixin +from weave.legacy.errors import WeaveFingerprintErrorMixin sentry_inited = False -def init_sentry(): +def init_sentry(): # type: ignore global sentry_inited if sentry_inited: return @@ -59,11 +59,11 @@ def capture_exception_with_sentry_if_available( # return ipynbname.name() -def get_hostname(): +def get_hostname(): # type: ignore return socket.gethostname() -def get_pid(): +def get_pid(): # type: ignore return os.getpid() @@ -95,7 +95,7 @@ def parse_number_env_var(name: str) -> typing.Optional[typing.Union[int, float]] return float(raw_val) -def find_names(obj): +def find_names(obj): # type: ignore if hasattr(obj, "name"): return [obj.name] frame = inspect.currentframe() @@ -110,7 +110,7 @@ def find_names(obj): return obj_names -def is_colab(): +def is_colab(): # type: ignore import importlib spec = importlib.util.find_spec("google.colab") @@ -118,7 +118,7 @@ def is_colab(): def is_notebook() -> bool: - if is_colab(): + if is_colab(): # type: ignore[no-untyped-call] return True try: from IPython import get_ipython @@ -135,7 +135,7 @@ def is_notebook() -> bool: return True -def is_pandas_dataframe(obj): +def is_pandas_dataframe(obj): # type: ignore try: import pandas as pd except ImportError: diff --git a/weave/tests/fixture_fakewandb.py b/weave/tests/fixture_fakewandb.py index 764abac362e..bbce4d66b91 100644 --- a/weave/tests/fixture_fakewandb.py +++ b/weave/tests/fixture_fakewandb.py @@ -11,12 +11,11 @@ import wandb import weave -from weave import util # Note: We're mocking out the whole io_service right now. This is too # high level and doesn't test the actual io implementation. We should # mock wandb_api instead probably. -from weave.legacy import io_service, wandb_api, wandb_client_api +from weave.legacy import io_service, util, wandb_api, wandb_client_api from weave.legacy.artifact_wandb import ( WandbArtifact, WandbArtifactManifest, diff --git a/weave/tests/legacy/test_relpath_no_syscalls.py b/weave/tests/legacy/test_relpath_no_syscalls.py index 3138cabaabd..412aed2b06e 100644 --- a/weave/tests/legacy/test_relpath_no_syscalls.py +++ b/weave/tests/legacy/test_relpath_no_syscalls.py @@ -1,6 +1,6 @@ import pytest -from ...util import relpath_no_syscalls +from weave.legacy.util import relpath_no_syscalls @pytest.mark.parametrize( diff --git a/weave/trace/api.py b/weave/trace/api.py index 449c1b34758..e6615a7221a 100644 --- a/weave/trace/api.py +++ b/weave/trace/api.py @@ -7,14 +7,13 @@ from typing import Any, Callable, Iterator, Optional, Union from weave.client_context import weave_client as weave_client_context -from weave.legacy import urls +from weave.legacy import urls, util from weave.trace.call_context import get_current_call # TODO: type_serializers is imported here to trigger registration of the image serializer. # There is probably a better place for this, but including here for now to get the fix in. from .. import ( type_serializers, # noqa: F401 - util, weave_init, ) from . import context, weave_client diff --git a/weave/trace/feedback.py b/weave/trace/feedback.py index 01103f82d02..8f2eafd378f 100644 --- a/weave/trace/feedback.py +++ b/weave/trace/feedback.py @@ -6,6 +6,7 @@ from rich.table import Table from weave.client_context import weave_client as weave_client_context +from weave.legacy import util from weave.trace import rich_pydantic_util from weave.trace.refs import parse_uri from weave.trace.rich_container import AbstractRichContainer @@ -13,8 +14,6 @@ from weave.trace_server import trace_server_interface as tsi from weave.trace_server.interface.query import Query -from .. import util - class Feedbacks(AbstractRichContainer[tsi.Feedback]): """A collection of Feedback objects with utilities.""" diff --git a/weave/trace/rich_pydantic_util.py b/weave/trace/rich_pydantic_util.py index 1c2c1474ef7..2c5e21fa2ed 100644 --- a/weave/trace/rich_pydantic_util.py +++ b/weave/trace/rich_pydantic_util.py @@ -6,7 +6,7 @@ from rich.console import Console from rich.table import Table -from .. import util +from weave.legacy import util def dict_to_table(d: dict[str, Any]) -> Table: diff --git a/weave/weave_server.py b/weave/weave_server.py index 509fea89cce..edb84bef393 100644 --- a/weave/weave_server.py +++ b/weave/weave_server.py @@ -27,7 +27,6 @@ from weave import ( filesystem, - util, ) from weave.legacy import ( context_state, @@ -39,6 +38,7 @@ registry_mem, server, storage, + util, value_or_error, wandb_api, weavejs_fixes, From ee5858d3d0bf7ccf43822cb9c2bd24732f8297c0 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 12:02:06 -0400 Subject: [PATCH 42/84] move to legacy: filesystem --- weave/legacy/artifact_local.py | 2 +- weave/legacy/artifact_wandb.py | 4 +--- weave/legacy/file_util.py | 2 +- weave/{ => legacy}/filesystem.py | 0 weave/legacy/io_service.py | 2 +- weave/legacy/runfiles_wandb.py | 2 +- weave/legacy/wandb_file_manager.py | 4 ++-- weave/test_scripts/wandb_artifact_perf.py | 3 ++- weave/tests/legacy/test_filesystem.py | 4 +--- weave/tests/legacy/test_io_service.py | 4 +--- weave/weave_http.py | 4 +--- weave/weave_server.py | 4 +--- 12 files changed, 13 insertions(+), 22 deletions(-) rename weave/{ => legacy}/filesystem.py (100%) diff --git a/weave/legacy/artifact_local.py b/weave/legacy/artifact_local.py index ff271ae4c48..0a4e9f6ad00 100644 --- a/weave/legacy/artifact_local.py +++ b/weave/legacy/artifact_local.py @@ -9,7 +9,7 @@ import typing from datetime import datetime -from weave import filesystem +from weave.legacy import filesystem from weave import weave_types as types from weave.legacy import ( artifact_fs, diff --git a/weave/legacy/artifact_wandb.py b/weave/legacy/artifact_wandb.py index 2c3173a3b8c..575f2a3a14c 100644 --- a/weave/legacy/artifact_wandb.py +++ b/weave/legacy/artifact_wandb.py @@ -13,11 +13,9 @@ from wandb.apis.public import api as wb_public from wandb.sdk.lib.hashutil import b64_to_hex_id, hex_to_b64_id -from weave import ( - filesystem, -) from weave import weave_types as types from weave.legacy import ( + filesystem, urls, errors, engine_trace, diff --git a/weave/legacy/file_util.py b/weave/legacy/file_util.py index b43c6dad627..31da6fc6647 100644 --- a/weave/legacy/file_util.py +++ b/weave/legacy/file_util.py @@ -2,7 +2,7 @@ import pathlib import typing -from weave import filesystem +from weave.legacy import filesystem from weave.legacy import cache, environment, path_util diff --git a/weave/filesystem.py b/weave/legacy/filesystem.py similarity index 100% rename from weave/filesystem.py rename to weave/legacy/filesystem.py diff --git a/weave/legacy/io_service.py b/weave/legacy/io_service.py index 701363c0a36..448660c64f1 100644 --- a/weave/legacy/io_service.py +++ b/weave/legacy/io_service.py @@ -23,10 +23,10 @@ import aioprocessing from weave import ( - filesystem, weave_http, ) from weave.legacy import ( + filesystem, errors, engine_trace, server_error_handling, diff --git a/weave/legacy/runfiles_wandb.py b/weave/legacy/runfiles_wandb.py index 5aef4727961..819dc7696ea 100644 --- a/weave/legacy/runfiles_wandb.py +++ b/weave/legacy/runfiles_wandb.py @@ -7,7 +7,7 @@ import typing from weave.legacy import environment as weave_env -from weave import filesystem +from weave.legacy import filesystem from weave import weave_types as types from weave.legacy import ( artifact_fs, diff --git a/weave/legacy/wandb_file_manager.py b/weave/legacy/wandb_file_manager.py index 2e437c0021a..cd166240923 100644 --- a/weave/legacy/wandb_file_manager.py +++ b/weave/legacy/wandb_file_manager.py @@ -12,9 +12,9 @@ from requests.auth import HTTPBasicAuth from wandb.sdk.lib import hashutil -from weave import filesystem, weave_http +from weave import weave_http from weave.legacy import environment as weave_env -from weave.legacy import artifact_wandb, cache, errors, wandb_api, engine_trace +from weave.legacy import filesystem, artifact_wandb, cache, errors, wandb_api, engine_trace tracer = engine_trace.tracer() # type: ignore diff --git a/weave/test_scripts/wandb_artifact_perf.py b/weave/test_scripts/wandb_artifact_perf.py index 0ba0b420b0a..bfe7b3cc2ae 100644 --- a/weave/test_scripts/wandb_artifact_perf.py +++ b/weave/test_scripts/wandb_artifact_perf.py @@ -17,11 +17,12 @@ artifact_wandb, async_map, engine_trace, + filesystem, wandb_api, wandb_file_manager, ) -from .. import filesystem, weave_http +from .. import weave_http tracer = engine_trace.tracer() # type: ignore diff --git a/weave/tests/legacy/test_filesystem.py b/weave/tests/legacy/test_filesystem.py index aaae05b21e9..3fd8cde70cb 100644 --- a/weave/tests/legacy/test_filesystem.py +++ b/weave/tests/legacy/test_filesystem.py @@ -2,9 +2,7 @@ import pytest -from weave.legacy import environment, errors - -from ... import filesystem +from weave.legacy import environment, errors, filesystem @pytest.fixture() diff --git a/weave/tests/legacy/test_io_service.py b/weave/tests/legacy/test_io_service.py index 5f3f0103d2c..053ee5d19cd 100644 --- a/weave/tests/legacy/test_io_service.py +++ b/weave/tests/legacy/test_io_service.py @@ -2,9 +2,7 @@ import pytest -from weave.legacy import io_service - -from ... import filesystem +from weave.legacy import filesystem, io_service @pytest.mark.timeout(10) diff --git a/weave/weave_http.py b/weave/weave_http.py index 075693b8edf..773625fe9ec 100644 --- a/weave/weave_http.py +++ b/weave/weave_http.py @@ -13,9 +13,7 @@ import requests.auth import yarl -from weave.legacy import engine_trace, server_error_handling - -from . import filesystem +from weave.legacy import engine_trace, filesystem, server_error_handling logging.getLogger("aiohttp.access").setLevel(logging.WARNING) logging.getLogger("aiohttp.client").setLevel(logging.WARNING) diff --git a/weave/weave_server.py b/weave/weave_server.py index edb84bef393..b07886df75d 100644 --- a/weave/weave_server.py +++ b/weave/weave_server.py @@ -25,14 +25,12 @@ from flask_cors import CORS from werkzeug.exceptions import HTTPException -from weave import ( - filesystem, -) from weave.legacy import ( context_state, engine_trace, environment, errors, + filesystem, graph, logs, registry_mem, From 497ca05053ac3ee31c9da0cabded245d6c4315d5 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 12:16:26 -0400 Subject: [PATCH 43/84] move to legacy: weave_http --- weave/legacy/io_service.py | 4 +--- weave/legacy/wandb_file_manager.py | 3 +-- weave/{ => legacy}/weave_http.py | 0 weave/test_scripts/wandb_artifact_perf.py | 3 +-- 4 files changed, 3 insertions(+), 7 deletions(-) rename weave/{ => legacy}/weave_http.py (100%) diff --git a/weave/legacy/io_service.py b/weave/legacy/io_service.py index 448660c64f1..9091573a914 100644 --- a/weave/legacy/io_service.py +++ b/weave/legacy/io_service.py @@ -22,10 +22,8 @@ import aioprocessing -from weave import ( - weave_http, -) from weave.legacy import ( + weave_http, filesystem, errors, engine_trace, diff --git a/weave/legacy/wandb_file_manager.py b/weave/legacy/wandb_file_manager.py index cd166240923..ecce61b90d0 100644 --- a/weave/legacy/wandb_file_manager.py +++ b/weave/legacy/wandb_file_manager.py @@ -12,9 +12,8 @@ from requests.auth import HTTPBasicAuth from wandb.sdk.lib import hashutil -from weave import weave_http from weave.legacy import environment as weave_env -from weave.legacy import filesystem, artifact_wandb, cache, errors, wandb_api, engine_trace +from weave.legacy import filesystem, artifact_wandb, cache, errors, wandb_api, engine_trace, weave_http tracer = engine_trace.tracer() # type: ignore diff --git a/weave/weave_http.py b/weave/legacy/weave_http.py similarity index 100% rename from weave/weave_http.py rename to weave/legacy/weave_http.py diff --git a/weave/test_scripts/wandb_artifact_perf.py b/weave/test_scripts/wandb_artifact_perf.py index bfe7b3cc2ae..bc38aeb1d64 100644 --- a/weave/test_scripts/wandb_artifact_perf.py +++ b/weave/test_scripts/wandb_artifact_perf.py @@ -20,10 +20,9 @@ filesystem, wandb_api, wandb_file_manager, + weave_http, ) -from .. import weave_http - tracer = engine_trace.tracer() # type: ignore From 553b726e514947482f7f03f5458d6a30c254fc3d Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 15:12:08 -0400 Subject: [PATCH 44/84] move to legacy: weave_types --- .../skip_test/branching_runs.ipynb | 2 +- mypy.ini | 2 +- weave/__init__.py | 2 +- weave/legacy/_dict_utils.py | 2 +- weave/legacy/api.py | 2 +- weave/legacy/arrow/arrow.py | 2 +- weave/legacy/arrow/arrow_tags.py | 2 +- weave/legacy/arrow/concat.py | 2 +- weave/legacy/arrow/constructors.py | 2 +- weave/legacy/arrow/convert.py | 2 +- weave/legacy/arrow/list_.py | 2 +- weave/legacy/artifact_base.py | 2 +- weave/legacy/artifact_fs.py | 2 +- weave/legacy/artifact_local.py | 2 +- weave/legacy/artifact_mem.py | 2 +- weave/legacy/artifact_wandb.py | 2 +- weave/legacy/client.py | 2 +- weave/legacy/codify.py | 4 +- weave/legacy/compile.py | 2 +- weave/legacy/compile_domain.py | 2 +- weave/legacy/debug_types.py | 2 +- weave/legacy/decorator_arrow_op.py | 2 +- weave/legacy/decorator_class.py | 2 +- weave/legacy/decorator_op.py | 2 +- weave/legacy/decorator_type.py | 2 +- weave/legacy/derive_op.py | 2 +- weave/legacy/dispatch.py | 2 +- weave/legacy/eager.py | 2 +- weave/legacy/ecosystem/langchain/lc.py | 2 +- weave/legacy/execute.py | 2 +- weave/legacy/execute_fast.py | 2 +- weave/legacy/file_base.py | 2 +- weave/legacy/file_local.py | 2 +- weave/legacy/gql_op_plugin.py | 2 +- weave/legacy/gql_to_weave.py | 2 +- weave/legacy/graph.py | 2 +- weave/legacy/graph_debug.py | 2 +- weave/legacy/graph_mapper.py | 2 +- weave/legacy/infer_types.py | 2 +- weave/legacy/language_autocall.py | 2 +- .../tagging/is_tag_getter.py | 2 +- .../tagging/make_tag_getter_op.py | 2 +- .../language_features/tagging/opdef_util.py | 2 +- .../tagging/process_opdef_output_type.py | 2 +- .../tagging/process_opdef_resolve_fn.py | 2 +- .../language_features/tagging/tag_store.py | 2 +- .../tagging/tagged_value_type.py | 2 +- .../tagging/tagged_value_type_helpers.py | 2 +- .../tagging/tagging_op_logic.py | 2 +- .../language_features/tagging/tagging_ops.py | 2 +- weave/legacy/language_nullability.py | 2 +- weave/legacy/make_type.py | 2 +- weave/legacy/mappers.py | 2 +- weave/legacy/mappers_arrow.py | 2 +- weave/legacy/mappers_gql.py | 2 +- weave/legacy/mappers_publisher.py | 2 +- weave/legacy/mappers_python.py | 2 +- weave/legacy/mappers_python_def.py | 2 +- weave/legacy/mappers_weave.py | 2 +- weave/legacy/monitoring/openai/models.py | 2 +- weave/legacy/object_context.py | 2 +- weave/legacy/op_args.py | 2 +- weave/legacy/op_def.py | 2 +- weave/legacy/op_def_type.py | 2 +- weave/legacy/ops_arrow/arraylist_ops.py | 2 +- weave/legacy/ops_arrow/boolean.py | 2 +- weave/legacy/ops_arrow/convert_ops.py | 2 +- weave/legacy/ops_arrow/date.py | 2 +- weave/legacy/ops_arrow/dict.py | 2 +- weave/legacy/ops_arrow/list_join.py | 2 +- weave/legacy/ops_arrow/list_ops.py | 2 +- weave/legacy/ops_arrow/list_range.py | 2 +- weave/legacy/ops_arrow/number.py | 2 +- weave/legacy/ops_arrow/obj.py | 2 +- weave/legacy/ops_arrow/ref_ops.py | 2 +- weave/legacy/ops_arrow/string.py | 2 +- weave/legacy/ops_arrow/util.py | 2 +- weave/legacy/ops_arrow/vectorize.py | 2 +- weave/legacy/ops_domain/artifact_alias_ops.py | 2 +- .../ops_domain/artifact_collection_ops.py | 2 +- .../ops_domain/artifact_membership_ops.py | 2 +- weave/legacy/ops_domain/artifact_type_ops.py | 2 +- .../legacy/ops_domain/artifact_version_ops.py | 2 +- weave/legacy/ops_domain/entity_ops.py | 2 +- weave/legacy/ops_domain/org_ops.py | 2 +- weave/legacy/ops_domain/project_ops.py | 2 +- weave/legacy/ops_domain/repo_insight_ops.py | 2 +- weave/legacy/ops_domain/report_ops.py | 2 +- .../run_history/history_op_common.py | 2 +- .../run_history/run_history_v1_legacy_ops.py | 2 +- .../run_history_v2_parquet_media.py | 2 +- ...run_history_v3_parquet_stream_optimized.py | 2 +- weave/legacy/ops_domain/run_ops.py | 2 +- weave/legacy/ops_domain/run_queue_ops.py | 2 +- weave/legacy/ops_domain/run_segment.py | 2 +- weave/legacy/ops_domain/stream_table_ops.py | 2 +- weave/legacy/ops_domain/table.py | 2 +- weave/legacy/ops_domain/trace_tree.py | 2 +- weave/legacy/ops_domain/user_ops.py | 2 +- weave/legacy/ops_domain/wandb_domain_gql.py | 2 +- weave/legacy/ops_domain/wb_domain_types.py | 2 +- weave/legacy/ops_domain/wb_util.py | 2 +- weave/legacy/ops_domain/wbgqlquery_op.py | 2 +- weave/legacy/ops_primitives/_dict_utils.py | 2 +- weave/legacy/ops_primitives/any.py | 2 +- weave/legacy/ops_primitives/boolean.py | 2 +- weave/legacy/ops_primitives/date.py | 2 +- weave/legacy/ops_primitives/dict.py | 2 +- weave/legacy/ops_primitives/file.py | 2 +- weave/legacy/ops_primitives/file_local.py | 2 +- weave/legacy/ops_primitives/html.py | 2 +- weave/legacy/ops_primitives/image.py | 2 +- weave/legacy/ops_primitives/list_.py | 2 +- .../legacy/ops_primitives/list_tag_getters.py | 2 +- weave/legacy/ops_primitives/markdown.py | 2 +- weave/legacy/ops_primitives/number.py | 2 +- weave/legacy/ops_primitives/number_bin.py | 4 +- weave/legacy/ops_primitives/obj.py | 2 +- weave/legacy/ops_primitives/op_def.py | 2 +- weave/legacy/ops_primitives/pandas_.py | 2 +- weave/legacy/ops_primitives/random_junk.py | 2 +- weave/legacy/ops_primitives/set_.py | 2 +- weave/legacy/ops_primitives/sql.py | 2 +- weave/legacy/ops_primitives/string.py | 2 +- weave/legacy/ops_primitives/test_list.py | 2 +- weave/legacy/ops_primitives/test_pandas.py | 2 +- weave/legacy/ops_primitives/timestamp_bin.py | 4 +- weave/legacy/ops_primitives/type.py | 2 +- weave/legacy/ops_primitives/weave_api.py | 2 +- weave/legacy/panel.py | 2 +- weave/legacy/panel_util.py | 2 +- weave/legacy/panels/panel_facet.py | 2 +- weave/legacy/panels/panel_plot.py | 2 +- weave/legacy/panels/table_state.py | 4 +- weave/legacy/panels_py/generator_templates.py | 2 +- .../panels_py/panel_example_custom_board.py | 2 +- weave/legacy/panels_py/panel_llm_monitor.py | 2 +- weave/legacy/panels_py/panel_observability.py | 2 +- weave/legacy/panels_py/panel_trace_monitor.py | 2 +- weave/legacy/partial_object.py | 2 +- weave/legacy/propagate_gql_keys.py | 2 +- weave/legacy/pyfunc_type_util.py | 2 +- weave/legacy/ref_base.py | 4 +- weave/legacy/registry_mem.py | 2 +- weave/legacy/runfiles_wandb.py | 2 +- weave/legacy/runs.py | 2 +- weave/legacy/serialize.py | 2 +- weave/legacy/server.py | 4 +- weave/legacy/show.py | 2 +- weave/legacy/stitch.py | 2 +- weave/legacy/storage.py | 2 +- weave/legacy/trace_legacy.py | 2 +- weave/legacy/trace_local.py | 2 +- weave/legacy/types_numpy.py | 2 +- weave/legacy/val_const.py | 2 +- .../wandb_interface/wandb_stream_table.py | 2 +- weave/legacy/wandb_util.py | 2 +- weave/legacy/weave_inspector.py | 2 +- weave/legacy/weave_pydantic.py | 2 +- weave/{ => legacy}/weave_types.py | 292 +++++++++--------- weave/legacy/weavejs_fixes.py | 2 +- weave/legacy/weavify.py | 2 +- weave/tests/legacy/test_arrow.py | 2 +- weave/tests/legacy/test_arrow_awl.py | 2 +- weave/tests/legacy/test_arrow_vectorizer.py | 2 +- weave/tests/legacy/test_compile.py | 2 +- weave/tests/legacy/test_decorators.py | 2 +- weave/tests/legacy/test_execute.py | 2 +- weave/tests/legacy/test_execute_fast.py | 2 +- weave/tests/legacy/test_gql_to_weave.py | 2 +- weave/tests/legacy/test_graph.py | 2 +- weave/tests/legacy/test_infer_types.py | 5 +- weave/tests/legacy/test_js_compat.py | 2 +- weave/tests/legacy/test_list_arrow_compat.py | 2 +- weave/tests/legacy/test_mappability.py | 2 +- weave/tests/legacy/test_mappers_arrow.py | 2 +- weave/tests/legacy/test_mappers_python.py | 2 +- weave/tests/legacy/test_media.py | 3 +- weave/tests/legacy/test_numpy.py | 2 +- weave/tests/legacy/test_partial_object.py | 2 +- weave/tests/legacy/test_plot.py | 2 +- weave/tests/legacy/test_pydantic.py | 2 +- weave/tests/legacy/test_ref_tracking.py | 2 +- weave/tests/legacy/test_run_segment.py | 2 +- weave/tests/legacy/test_serialize.py | 2 +- weave/tests/legacy/test_storage.py | 2 +- weave/tests/legacy/test_table_ops.py | 2 +- weave/tests/legacy/test_tagging.py | 2 +- .../legacy/test_typeddict_notrequired.py | 2 +- weave/tests/legacy/test_wb.py | 2 +- weave/tests/legacy/test_wb_data_types.py | 2 +- weave/tests/legacy/test_wb_domain_types.py | 2 +- weave/tests/legacy/test_wb_stream_table.py | 3 +- weave/tests/legacy/test_weave_types.py | 112 +++---- weave/tests/legacy/test_weavejs_fixes.py | 2 +- weave/tests/legacy/test_weavify.py | 2 +- weave/tests/tag_test_util.py | 3 +- weave/tests/trace/test_server.py | 2 +- weave/tests/weavejs_ops.py | 2 +- weave/weave_internal.py | 3 +- 200 files changed, 408 insertions(+), 411 deletions(-) rename weave/{ => legacy}/weave_types.py (89%) diff --git a/examples/experimental/skip_test/branching_runs.ipynb b/examples/experimental/skip_test/branching_runs.ipynb index bfad154cea7..86b3c167e31 100644 --- a/examples/experimental/skip_test/branching_runs.ipynb +++ b/examples/experimental/skip_test/branching_runs.ipynb @@ -13,7 +13,7 @@ "from weave.legacy.ops_domain import RunSegment\n", "from weave.legacy import storage\n", "from weave import publish, type_of\n", - "from weave.weave_types import List\n", + "from weave.legacy.weave_types import List\n", "import typing\n", "import time\n", "import sys\n", diff --git a/mypy.ini b/mypy.ini index 3f47e1f0dd1..b8c601a669f 100644 --- a/mypy.ini +++ b/mypy.ini @@ -151,7 +151,7 @@ disallow_untyped_calls = False disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.weave_types] +[mypy-weave.legacy.weave_types] disallow_untyped_defs = False disallow_untyped_calls = False diff --git a/weave/__init__.py b/weave/__init__.py index d75cd14713b..0ed50283b77 100644 --- a/weave/__init__.py +++ b/weave/__init__.py @@ -12,7 +12,7 @@ _loading_builtins_token = _context_state.set_loading_built_ins() -from . import weave_types as types +from weave.legacy import weave_types as types from .legacy import storage from .legacy.api import * diff --git a/weave/legacy/_dict_utils.py b/weave/legacy/_dict_utils.py index 256a973fe98..744b62474ff 100644 --- a/weave/legacy/_dict_utils.py +++ b/weave/legacy/_dict_utils.py @@ -4,7 +4,7 @@ from weave.legacy.language_features.tagging import tag_store, tagged_value_type from weave.legacy import errors -from .. import weave_types as types +from weave.legacy import weave_types as types def typeddict_pick_output_type(input_types): diff --git a/weave/legacy/api.py b/weave/legacy/api.py index 54ad4e2fcb5..c310b40db08 100644 --- a/weave/legacy/api.py +++ b/weave/legacy/api.py @@ -21,7 +21,7 @@ from ..trace import weave_client as _weave_client # exposed as part of api -from .. import weave_types as types +from weave.legacy import weave_types as types # needed to enable automatic numpy serialization from . import types_numpy as _types_numpy diff --git a/weave/legacy/arrow/arrow.py b/weave/legacy/arrow/arrow.py index d7f750f7caf..0c5576eaa99 100644 --- a/weave/legacy/arrow/arrow.py +++ b/weave/legacy/arrow/arrow.py @@ -12,7 +12,7 @@ py_type = type from weave.legacy import errors -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import artifact_fs, partial_object diff --git a/weave/legacy/arrow/arrow_tags.py b/weave/legacy/arrow/arrow_tags.py index fc53c901f29..52ba674abca 100644 --- a/weave/legacy/arrow/arrow_tags.py +++ b/weave/legacy/arrow/arrow_tags.py @@ -3,7 +3,7 @@ import pyarrow as pa from pyarrow import compute as pc -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.arrow import convert from weave.legacy.arrow.arrow import offsets_starting_at_zero from weave.legacy.language_features.tagging import ( diff --git a/weave/legacy/arrow/concat.py b/weave/legacy/arrow/concat.py index 4201da7d17d..46453d7de70 100644 --- a/weave/legacy/arrow/concat.py +++ b/weave/legacy/arrow/concat.py @@ -13,7 +13,7 @@ from pyarrow import compute as pc from weave.legacy import errors -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.arrow.list_ import ( ArrowWeaveList, ArrowWeaveListGeneric, diff --git a/weave/legacy/arrow/constructors.py b/weave/legacy/arrow/constructors.py index b7cab73103c..578643160c8 100644 --- a/weave/legacy/arrow/constructors.py +++ b/weave/legacy/arrow/constructors.py @@ -4,7 +4,7 @@ import pyarrow as pa from weave.legacy import errors -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import artifact_base, box from weave.legacy.arrow import arrow_tags, convert from weave.legacy.arrow.arrow import ArrowWeaveListType, arrow_as_array diff --git a/weave/legacy/arrow/convert.py b/weave/legacy/arrow/convert.py index 1b195a43283..d76edeaef7b 100644 --- a/weave/legacy/arrow/convert.py +++ b/weave/legacy/arrow/convert.py @@ -5,7 +5,7 @@ from weave.legacy import api as api from weave import weave_internal -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import errors, arrow_util, artifact_base, artifact_mem, box, mappers_arrow from weave.legacy.arrow.arrow import ( ArrowWeaveListType, diff --git a/weave/legacy/arrow/list_.py b/weave/legacy/arrow/list_.py index cdd8dd1a5d7..e90c860fead 100644 --- a/weave/legacy/arrow/list_.py +++ b/weave/legacy/arrow/list_.py @@ -13,7 +13,7 @@ from weave import ( weave_internal, ) -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import ( errors, _dict_utils, diff --git a/weave/legacy/artifact_base.py b/weave/legacy/artifact_base.py index 02b2e35d213..ae98ed7bc84 100644 --- a/weave/legacy/artifact_base.py +++ b/weave/legacy/artifact_base.py @@ -7,7 +7,7 @@ import typing -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import ref_base diff --git a/weave/legacy/artifact_fs.py b/weave/legacy/artifact_fs.py index 9b5ca6a47a8..36ab31229a8 100644 --- a/weave/legacy/artifact_fs.py +++ b/weave/legacy/artifact_fs.py @@ -7,7 +7,7 @@ import typing from weave.legacy import errors -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import artifact_base, file_base, object_context, ref_base, uris from weave.legacy.language_features.tagging import tag_store from weave.trace import ref_util diff --git a/weave/legacy/artifact_local.py b/weave/legacy/artifact_local.py index 0a4e9f6ad00..a22b6ea30e9 100644 --- a/weave/legacy/artifact_local.py +++ b/weave/legacy/artifact_local.py @@ -10,7 +10,7 @@ from datetime import datetime from weave.legacy import filesystem -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import ( artifact_fs, artifact_wandb, diff --git a/weave/legacy/artifact_mem.py b/weave/legacy/artifact_mem.py index bf8763b9da0..3e01f70ccb3 100644 --- a/weave/legacy/artifact_mem.py +++ b/weave/legacy/artifact_mem.py @@ -1,7 +1,7 @@ import typing from . import artifact_base -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import errors from weave.legacy import ref_base diff --git a/weave/legacy/artifact_wandb.py b/weave/legacy/artifact_wandb.py index 575f2a3a14c..eff48f0519d 100644 --- a/weave/legacy/artifact_wandb.py +++ b/weave/legacy/artifact_wandb.py @@ -13,7 +13,7 @@ from wandb.apis.public import api as wb_public from wandb.sdk.lib.hashutil import b64_to_hex_id, hex_to_b64_id -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import ( filesystem, urls, diff --git a/weave/legacy/client.py b/weave/legacy/client.py index ab9ce10af25..e1a3a32ce0c 100644 --- a/weave/legacy/client.py +++ b/weave/legacy/client.py @@ -1,4 +1,4 @@ -from weave import weave_types +from weave.legacy import weave_types from weave.legacy import storage diff --git a/weave/legacy/codify.py b/weave/legacy/codify.py index e06006e936a..e1017261d77 100644 --- a/weave/legacy/codify.py +++ b/weave/legacy/codify.py @@ -6,7 +6,7 @@ import black -from weave import weave_types +from weave.legacy import weave_types from weave.legacy import storage, graph, registry_mem from . import codifiable_value_mixin @@ -128,7 +128,7 @@ def _try_otc_using_dataclasses(obj: typing.Any) -> typing.Optional[str]: if class_type.__module__.startswith("weave.decorator_type") and issubclass( class_type, weave_types.Type ): - qualified_classpath = "weave.weave_types" + qualified_classpath = "weave.legacy.weave_types" qualified_classname = f"type_name_to_type('{class_type.name}')" else: qualified_classpath = _module_name_corrections(class_type.__module__) diff --git a/weave/legacy/compile.py b/weave/legacy/compile.py index 760a3527ff8..1e307054bd0 100644 --- a/weave/legacy/compile.py +++ b/weave/legacy/compile.py @@ -8,7 +8,7 @@ from weave import ( weave_internal, ) -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import ( errors, engine_trace, diff --git a/weave/legacy/compile_domain.py b/weave/legacy/compile_domain.py index 3d9c6119220..65730e05ab3 100644 --- a/weave/legacy/compile_domain.py +++ b/weave/legacy/compile_domain.py @@ -3,7 +3,7 @@ import graphql from weave.legacy import errors -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import gql_op_plugin, gql_to_weave, graph, op_args, stitch, registry_mem from weave.legacy.input_provider import InputAndStitchProvider diff --git a/weave/legacy/debug_types.py b/weave/legacy/debug_types.py index d1b71dea419..c2a77b2c0cf 100644 --- a/weave/legacy/debug_types.py +++ b/weave/legacy/debug_types.py @@ -1,7 +1,7 @@ import textwrap from weave.legacy.language_features.tagging import tagged_value_type -from weave.weave_types import * +from weave.legacy.weave_types import * def short_type(type: Type) -> str: diff --git a/weave/legacy/decorator_arrow_op.py b/weave/legacy/decorator_arrow_op.py index cc8bea94e33..51869d03760 100644 --- a/weave/legacy/decorator_arrow_op.py +++ b/weave/legacy/decorator_arrow_op.py @@ -1,6 +1,6 @@ import typing -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import op_def from weave.legacy.arrow.arrow import ArrowWeaveListType from weave.legacy.language_features.tagging import tagged_value_type diff --git a/weave/legacy/decorator_class.py b/weave/legacy/decorator_class.py index afcdc17690d..c2b2d5314d2 100644 --- a/weave/legacy/decorator_class.py +++ b/weave/legacy/decorator_class.py @@ -2,7 +2,7 @@ import typing from weave.legacy import errors -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import context_state, derive_op, op_def, registry_mem # Contrary to the way it is read, the weave.class() decorator runs AFTER the diff --git a/weave/legacy/decorator_op.py b/weave/legacy/decorator_op.py index e193e4b1e38..d0081d8494a 100644 --- a/weave/legacy/decorator_op.py +++ b/weave/legacy/decorator_op.py @@ -4,7 +4,7 @@ from typing_extensions import ParamSpec -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import context_state, derive_op, op_args, op_def, pyfunc_type_util, registry_mem if typing.TYPE_CHECKING: diff --git a/weave/legacy/decorator_type.py b/weave/legacy/decorator_type.py index 2f7ff2f0da9..2b761f2838f 100644 --- a/weave/legacy/decorator_type.py +++ b/weave/legacy/decorator_type.py @@ -3,7 +3,7 @@ import typing from weave.legacy import errors -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import context_state, decorator_class, object_type_ref_util, infer_types _py_type = type diff --git a/weave/legacy/derive_op.py b/weave/legacy/derive_op.py index e591a652cc0..dcf1010b024 100644 --- a/weave/legacy/derive_op.py +++ b/weave/legacy/derive_op.py @@ -10,7 +10,7 @@ storage, weave_internal, ) -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import ( errors, parallelism, diff --git a/weave/legacy/dispatch.py b/weave/legacy/dispatch.py index 9ab44a17312..39baffd75a8 100644 --- a/weave/legacy/dispatch.py +++ b/weave/legacy/dispatch.py @@ -6,7 +6,7 @@ from dataclasses import dataclass from weave.legacy import util -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import graph, memo, op_args, op_def, pyfunc_type_util, registry_mem, errors from weave.legacy.language_features.tagging.is_tag_getter import is_tag_getter from weave.legacy.language_features.tagging.tagged_value_type import TaggedValueType diff --git a/weave/legacy/eager.py b/weave/legacy/eager.py index 5136297e7be..88ea1c453b6 100644 --- a/weave/legacy/eager.py +++ b/weave/legacy/eager.py @@ -3,7 +3,7 @@ from weave.legacy import context_state, graph from .. import weave_internal -from .. import weave_types as types +from weave.legacy import weave_types as types WeaveIterObjectType = typing.TypeVar("WeaveIterObjectType") diff --git a/weave/legacy/ecosystem/langchain/lc.py b/weave/legacy/ecosystem/langchain/lc.py index 54a5b870624..46fd02f6a65 100644 --- a/weave/legacy/ecosystem/langchain/lc.py +++ b/weave/legacy/ecosystem/langchain/lc.py @@ -46,7 +46,7 @@ from weave.legacy.artifact_fs import FilesystemArtifact from weave.legacy.ecosystem.langchain import util from weave.legacy.ops_domain import trace_tree -from weave.weave_types import Type +from weave.legacy.weave_types import Type class WeaveTracer(BaseTracer): diff --git a/weave/legacy/execute.py b/weave/legacy/execute.py index 72d7ecd9764..b4cc7a81570 100644 --- a/weave/legacy/execute.py +++ b/weave/legacy/execute.py @@ -9,7 +9,7 @@ import typing from collections.abc import Mapping -from weave import weave_types as types +from weave.legacy import weave_types as types # Configuration # Libraries diff --git a/weave/legacy/execute_fast.py b/weave/legacy/execute_fast.py index 4bcb4e418fd..b7331ded998 100644 --- a/weave/legacy/execute_fast.py +++ b/weave/legacy/execute_fast.py @@ -3,7 +3,7 @@ from weave import ( weave_internal, ) -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import ( errors, engine_trace, diff --git a/weave/legacy/file_base.py b/weave/legacy/file_base.py index 680208ab598..ff03c072471 100644 --- a/weave/legacy/file_base.py +++ b/weave/legacy/file_base.py @@ -2,7 +2,7 @@ import dataclasses import typing -from weave import weave_types as types +from weave.legacy import weave_types as types TRACE_EXT = "trace.json" diff --git a/weave/legacy/file_local.py b/weave/legacy/file_local.py index 07898c7152a..e20a0a2248b 100644 --- a/weave/legacy/file_local.py +++ b/weave/legacy/file_local.py @@ -2,7 +2,7 @@ import os import typing -from weave import weave_types as types +from weave.legacy import weave_types as types from . import file_base, file_util diff --git a/weave/legacy/gql_op_plugin.py b/weave/legacy/gql_op_plugin.py index 1068c7a8712..090a1536c40 100644 --- a/weave/legacy/gql_op_plugin.py +++ b/weave/legacy/gql_op_plugin.py @@ -1,7 +1,7 @@ import typing from dataclasses import dataclass -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import input_provider, op_args, op_def # A GQLOutputTypeFn is a function that is called during the refinement phase of the compile pass diff --git a/weave/legacy/gql_to_weave.py b/weave/legacy/gql_to_weave.py index 51c78413868..117e3511dea 100644 --- a/weave/legacy/gql_to_weave.py +++ b/weave/legacy/gql_to_weave.py @@ -18,7 +18,7 @@ ) from weave.legacy import errors -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import gql_schema diff --git a/weave/legacy/graph.py b/weave/legacy/graph.py index b12d85dfdf9..9517b687b34 100644 --- a/weave/legacy/graph.py +++ b/weave/legacy/graph.py @@ -2,7 +2,7 @@ import json import typing -from weave import weave_types +from weave.legacy import weave_types from weave.legacy import uris, errors, storage if typing.TYPE_CHECKING: diff --git a/weave/legacy/graph_debug.py b/weave/legacy/graph_debug.py index f9e5d96b4f2..d82a7353661 100644 --- a/weave/legacy/graph_debug.py +++ b/weave/legacy/graph_debug.py @@ -2,7 +2,7 @@ import textwrap import typing -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import forward_graph, graph diff --git a/weave/legacy/graph_mapper.py b/weave/legacy/graph_mapper.py index f2c68399433..1cf5a6c9e13 100644 --- a/weave/legacy/graph_mapper.py +++ b/weave/legacy/graph_mapper.py @@ -1,5 +1,5 @@ from weave.legacy import ref_base -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import graph, mappers, node_ref from weave.legacy import mappers_python_def as mappers_python diff --git a/weave/legacy/infer_types.py b/weave/legacy/infer_types.py index 8a70475c7de..9eedc3a4c03 100644 --- a/weave/legacy/infer_types.py +++ b/weave/legacy/infer_types.py @@ -8,7 +8,7 @@ from weave.legacy import errors, graph -from .. import weave_types +from weave.legacy import weave_types class TypedDictLike: diff --git a/weave/legacy/language_autocall.py b/weave/legacy/language_autocall.py index de830115435..73822279ed7 100644 --- a/weave/legacy/language_autocall.py +++ b/weave/legacy/language_autocall.py @@ -15,7 +15,7 @@ import typing -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import op_args diff --git a/weave/legacy/language_features/tagging/is_tag_getter.py b/weave/legacy/language_features/tagging/is_tag_getter.py index 5b387e7e684..d4d6b83c401 100644 --- a/weave/legacy/language_features/tagging/is_tag_getter.py +++ b/weave/legacy/language_features/tagging/is_tag_getter.py @@ -1,6 +1,6 @@ import typing -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import op_args from weave.legacy.language_features.tagging import tagged_value_type diff --git a/weave/legacy/language_features/tagging/make_tag_getter_op.py b/weave/legacy/language_features/tagging/make_tag_getter_op.py index decf0ae32eb..9cb06bd9f2f 100644 --- a/weave/legacy/language_features/tagging/make_tag_getter_op.py +++ b/weave/legacy/language_features/tagging/make_tag_getter_op.py @@ -1,6 +1,6 @@ import typing -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import context_state as _context_state from weave.legacy import decorator_op from weave.legacy.language_features.tagging import tag_store, tagged_value_type diff --git a/weave/legacy/language_features/tagging/opdef_util.py b/weave/legacy/language_features/tagging/opdef_util.py index f74d78956f0..f52a748414b 100644 --- a/weave/legacy/language_features/tagging/opdef_util.py +++ b/weave/legacy/language_features/tagging/opdef_util.py @@ -1,6 +1,6 @@ import typing -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.language_features.tagging import tagged_value_type if typing.TYPE_CHECKING: diff --git a/weave/legacy/language_features/tagging/process_opdef_output_type.py b/weave/legacy/language_features/tagging/process_opdef_output_type.py index a445e748527..b9e1a65b4cc 100644 --- a/weave/legacy/language_features/tagging/process_opdef_output_type.py +++ b/weave/legacy/language_features/tagging/process_opdef_output_type.py @@ -6,7 +6,7 @@ import typing from weave.legacy import registry_mem -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import graph from weave.legacy.language_features.tagging.opdef_util import ( should_flow_tags, diff --git a/weave/legacy/language_features/tagging/process_opdef_resolve_fn.py b/weave/legacy/language_features/tagging/process_opdef_resolve_fn.py index a4f474357ce..720c8db3931 100644 --- a/weave/legacy/language_features/tagging/process_opdef_resolve_fn.py +++ b/weave/legacy/language_features/tagging/process_opdef_resolve_fn.py @@ -11,7 +11,7 @@ import typing_extensions from pyarrow import compute as pc -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import box from weave.legacy.arrow.arrow_tags import awl_add_arrow_tags from weave.legacy.arrow.list_ import ArrowWeaveList diff --git a/weave/legacy/language_features/tagging/tag_store.py b/weave/legacy/language_features/tagging/tag_store.py index c39c404e35f..f6fea94eb79 100644 --- a/weave/legacy/language_features/tagging/tag_store.py +++ b/weave/legacy/language_features/tagging/tag_store.py @@ -23,7 +23,7 @@ from contextlib import contextmanager from weave.legacy import errors -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import engine_trace, box statsd = engine_trace.statsd() # type: ignore diff --git a/weave/legacy/language_features/tagging/tagged_value_type.py b/weave/legacy/language_features/tagging/tagged_value_type.py index 533e0f4af38..9ae900a2835 100644 --- a/weave/legacy/language_features/tagging/tagged_value_type.py +++ b/weave/legacy/language_features/tagging/tagged_value_type.py @@ -31,7 +31,7 @@ import typing from weave.legacy import errors -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import box, mappers, mappers_python from weave.legacy.language_features.tagging import tag_store diff --git a/weave/legacy/language_features/tagging/tagged_value_type_helpers.py b/weave/legacy/language_features/tagging/tagged_value_type_helpers.py index 72672f13115..a5b1a83f446 100644 --- a/weave/legacy/language_features/tagging/tagged_value_type_helpers.py +++ b/weave/legacy/language_features/tagging/tagged_value_type_helpers.py @@ -1,6 +1,6 @@ import typing -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.language_features.tagging import tagged_value_type diff --git a/weave/legacy/language_features/tagging/tagging_op_logic.py b/weave/legacy/language_features/tagging/tagging_op_logic.py index 7fc16b4fb3b..2c2bcc04138 100644 --- a/weave/legacy/language_features/tagging/tagging_op_logic.py +++ b/weave/legacy/language_features/tagging/tagging_op_logic.py @@ -1,4 +1,4 @@ -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.language_features.tagging.tagged_value_type import TaggedValueType diff --git a/weave/legacy/language_features/tagging/tagging_ops.py b/weave/legacy/language_features/tagging/tagging_ops.py index 9033b036123..abb6dfeb9aa 100644 --- a/weave/legacy/language_features/tagging/tagging_ops.py +++ b/weave/legacy/language_features/tagging/tagging_ops.py @@ -1,4 +1,4 @@ -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import decorator_op from weave.legacy.language_features.tagging import tagging_op_logic diff --git a/weave/legacy/language_nullability.py b/weave/legacy/language_nullability.py index 0cb5bbd9e9f..2541721b19a 100644 --- a/weave/legacy/language_nullability.py +++ b/weave/legacy/language_nullability.py @@ -1,6 +1,6 @@ import typing -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import box from weave.legacy.language_features.tagging import tagged_value_type diff --git a/weave/legacy/make_type.py b/weave/legacy/make_type.py index 3eb3a5f961b..765bc06636d 100644 --- a/weave/legacy/make_type.py +++ b/weave/legacy/make_type.py @@ -1,5 +1,5 @@ from .. import weave_internal -from .. import weave_types as types +from weave.legacy import weave_types as types # TODO: Consider if this should accept a *args, **kwargs? diff --git a/weave/legacy/mappers.py b/weave/legacy/mappers.py index 3ca05e17439..b7a25b0e605 100644 --- a/weave/legacy/mappers.py +++ b/weave/legacy/mappers.py @@ -1,7 +1,7 @@ import typing if typing.TYPE_CHECKING: - from weave import weave_types as types + from weave.legacy import weave_types as types from weave.legacy import artifact_local diff --git a/weave/legacy/mappers_arrow.py b/weave/legacy/mappers_arrow.py index 7c47d34b568..f74e1ca2ba5 100644 --- a/weave/legacy/mappers_arrow.py +++ b/weave/legacy/mappers_arrow.py @@ -6,7 +6,7 @@ import pyarrow as pa from weave.legacy import errors -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import ( arrow_util, artifact_base, diff --git a/weave/legacy/mappers_gql.py b/weave/legacy/mappers_gql.py index 4a4ce875af4..1f7da87687e 100644 --- a/weave/legacy/mappers_gql.py +++ b/weave/legacy/mappers_gql.py @@ -1,7 +1,7 @@ import json from weave.legacy import errors -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import gql_json_cache, mappers from weave.legacy.mappers_weave import UnionMapper from weave.legacy.partial_object import PartialObjectType diff --git a/weave/legacy/mappers_publisher.py b/weave/legacy/mappers_publisher.py index b80f2d1c357..667d47a5414 100644 --- a/weave/legacy/mappers_publisher.py +++ b/weave/legacy/mappers_publisher.py @@ -4,7 +4,7 @@ from weave.legacy import storage from weave import weave_internal -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.node_ref import ref_to_node # from weave.legacy.ops_primitives import weave_api diff --git a/weave/legacy/mappers_python.py b/weave/legacy/mappers_python.py index 53aec98ab8f..ad3f240eb35 100644 --- a/weave/legacy/mappers_python.py +++ b/weave/legacy/mappers_python.py @@ -3,7 +3,7 @@ import typing if typing.TYPE_CHECKING: - from weave import weave_types + from weave.legacy import weave_types from weave.legacy import artifact_base, mappers diff --git a/weave/legacy/mappers_python_def.py b/weave/legacy/mappers_python_def.py index b78e684ca31..5a1ee099220 100644 --- a/weave/legacy/mappers_python_def.py +++ b/weave/legacy/mappers_python_def.py @@ -5,7 +5,7 @@ import typing from weave.legacy import storage -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import ( artifact_fs, box, diff --git a/weave/legacy/mappers_weave.py b/weave/legacy/mappers_weave.py index 41c0fcbd2c9..133e1456cce 100644 --- a/weave/legacy/mappers_weave.py +++ b/weave/legacy/mappers_weave.py @@ -1,6 +1,6 @@ import typing -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import mappers from weave.legacy.partial_object import PartialObjectType diff --git a/weave/legacy/monitoring/openai/models.py b/weave/legacy/monitoring/openai/models.py index e5ab0196435..d9688f8b281 100644 --- a/weave/legacy/monitoring/openai/models.py +++ b/weave/legacy/monitoring/openai/models.py @@ -7,7 +7,7 @@ ) from pydantic import BaseModel, Field -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.monitoring import monitor diff --git a/weave/legacy/object_context.py b/weave/legacy/object_context.py index b8d916063e2..3ed119fa154 100644 --- a/weave/legacy/object_context.py +++ b/weave/legacy/object_context.py @@ -13,7 +13,7 @@ if typing.TYPE_CHECKING: from weave.legacy import ref_base -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import box, uris diff --git a/weave/legacy/op_args.py b/weave/legacy/op_args.py index 5487ed1f530..15fae9a443b 100644 --- a/weave/legacy/op_args.py +++ b/weave/legacy/op_args.py @@ -1,7 +1,7 @@ import typing from dataclasses import dataclass -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import debug_types BT = typing.TypeVar("BT") diff --git a/weave/legacy/op_def.py b/weave/legacy/op_def.py index 8c63b15faaa..7581773e09f 100644 --- a/weave/legacy/op_def.py +++ b/weave/legacy/op_def.py @@ -9,7 +9,7 @@ from weave import ( weave_internal, ) -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import ( errors, context_state, diff --git a/weave/legacy/op_def_type.py b/weave/legacy/op_def_type.py index bb264899260..8fd598aa0ca 100644 --- a/weave/legacy/op_def_type.py +++ b/weave/legacy/op_def_type.py @@ -12,7 +12,7 @@ from typing import Any from weave.legacy import storage -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import ( artifact_fs, artifact_local, diff --git a/weave/legacy/ops_arrow/arraylist_ops.py b/weave/legacy/ops_arrow/arraylist_ops.py index 02c519fc9e7..cd0d4752f94 100644 --- a/weave/legacy/ops_arrow/arraylist_ops.py +++ b/weave/legacy/ops_arrow/arraylist_ops.py @@ -3,7 +3,7 @@ import pyarrow as pa from pyarrow import compute as pc -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.arrow.arrow import ArrowWeaveListType, arrow_as_array from weave.legacy.arrow.list_ import ArrowWeaveList from weave.legacy.decorator_arrow_op import arrow_op diff --git a/weave/legacy/ops_arrow/boolean.py b/weave/legacy/ops_arrow/boolean.py index 3ad4caa354b..68b09327c61 100644 --- a/weave/legacy/ops_arrow/boolean.py +++ b/weave/legacy/ops_arrow/boolean.py @@ -1,7 +1,7 @@ import pyarrow as pa import pyarrow.compute as pc -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.arrow.list_ import ArrowWeaveList, ArrowWeaveListType from weave.legacy.decorator_arrow_op import arrow_op from weave.legacy.decorator_op import op diff --git a/weave/legacy/ops_arrow/convert_ops.py b/weave/legacy/ops_arrow/convert_ops.py index af7c3fc7273..b2538128b42 100644 --- a/weave/legacy/ops_arrow/convert_ops.py +++ b/weave/legacy/ops_arrow/convert_ops.py @@ -1,4 +1,4 @@ -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op from weave.legacy.arrow import convert from weave.legacy.arrow.arrow import ArrowWeaveListType diff --git a/weave/legacy/ops_arrow/date.py b/weave/legacy/ops_arrow/date.py index f8b3d36c281..9d93ee161d6 100644 --- a/weave/legacy/ops_arrow/date.py +++ b/weave/legacy/ops_arrow/date.py @@ -3,7 +3,7 @@ import pyarrow as pa import pyarrow.compute as pc -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op from weave.legacy import timestamp as weave_timestamp from weave.legacy.arrow.list_ import ArrowWeaveList, ArrowWeaveListType diff --git a/weave/legacy/ops_arrow/dict.py b/weave/legacy/ops_arrow/dict.py index ab3b90cb4b3..996ef2e4ffc 100644 --- a/weave/legacy/ops_arrow/dict.py +++ b/weave/legacy/ops_arrow/dict.py @@ -3,7 +3,7 @@ import numpy as np import pyarrow as pa -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import _dict_utils from weave.legacy.arrow import convert from weave.legacy.arrow.arrow import arrow_as_array, offsets_starting_at_zero diff --git a/weave/legacy/ops_arrow/list_join.py b/weave/legacy/ops_arrow/list_join.py index 3fd533ed54e..1f026ab61e9 100644 --- a/weave/legacy/ops_arrow/list_join.py +++ b/weave/legacy/ops_arrow/list_join.py @@ -5,7 +5,7 @@ import pyarrow.compute as pc from weave.legacy import engine_trace -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op from weave.legacy import graph from weave.legacy.arrow import convert diff --git a/weave/legacy/ops_arrow/list_ops.py b/weave/legacy/ops_arrow/list_ops.py index 7e9308f3330..1f034738bf9 100644 --- a/weave/legacy/ops_arrow/list_ops.py +++ b/weave/legacy/ops_arrow/list_ops.py @@ -7,7 +7,7 @@ import pyarrow as pa import pyarrow.compute as pc -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op, type_of from weave.legacy import op_args, op_def from weave.legacy.arrow import arrow_tags, convert diff --git a/weave/legacy/ops_arrow/list_range.py b/weave/legacy/ops_arrow/list_range.py index 809faae2918..064e8e29a22 100644 --- a/weave/legacy/ops_arrow/list_range.py +++ b/weave/legacy/ops_arrow/list_range.py @@ -2,7 +2,7 @@ import pyarrow as pa -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op from weave.legacy.arrow.list_ import ArrowWeaveList diff --git a/weave/legacy/ops_arrow/number.py b/weave/legacy/ops_arrow/number.py index 3327c4222c3..071b4d37ec9 100644 --- a/weave/legacy/ops_arrow/number.py +++ b/weave/legacy/ops_arrow/number.py @@ -4,7 +4,7 @@ import pyarrow as pa import pyarrow.compute as pc -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op from weave.legacy import timestamp as weave_timestamp from weave.legacy.arrow.list_ import ArrowWeaveList, ArrowWeaveListType diff --git a/weave/legacy/ops_arrow/obj.py b/weave/legacy/ops_arrow/obj.py index 103b3e0da52..7e38e90297b 100644 --- a/weave/legacy/ops_arrow/obj.py +++ b/weave/legacy/ops_arrow/obj.py @@ -1,4 +1,4 @@ -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.arrow.list_ import ArrowWeaveList, ArrowWeaveListType from weave.legacy.decorator_arrow_op import arrow_op from weave.legacy.ops_primitives import obj as primitives_obj diff --git a/weave/legacy/ops_arrow/ref_ops.py b/weave/legacy/ops_arrow/ref_ops.py index b5edd10d227..d40ee05949c 100644 --- a/weave/legacy/ops_arrow/ref_ops.py +++ b/weave/legacy/ops_arrow/ref_ops.py @@ -1,7 +1,7 @@ import pyarrow as pa import pyarrow.compute as pc -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.arrow.list_ import ArrowWeaveList, ArrowWeaveListType from weave.legacy.decorator_arrow_op import arrow_op from weave.legacy.decorator_op import op diff --git a/weave/legacy/ops_arrow/string.py b/weave/legacy/ops_arrow/string.py index a74db7d2550..491ad640a6e 100644 --- a/weave/legacy/ops_arrow/string.py +++ b/weave/legacy/ops_arrow/string.py @@ -3,7 +3,7 @@ import pyarrow as pa import pyarrow.compute as pc -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op from weave.legacy.arrow.arrow import ArrowWeaveListType, offsets_starting_at_zero from weave.legacy.arrow.list_ import ArrowWeaveList, ArrowWeaveListType diff --git a/weave/legacy/ops_arrow/util.py b/weave/legacy/ops_arrow/util.py index e31000a9fb0..5d515d9984a 100644 --- a/weave/legacy/ops_arrow/util.py +++ b/weave/legacy/ops_arrow/util.py @@ -3,7 +3,7 @@ import pyarrow as pa from pyarrow import compute as pc -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import graph diff --git a/weave/legacy/ops_arrow/vectorize.py b/weave/legacy/ops_arrow/vectorize.py index 5974c3e1402..107666929e1 100644 --- a/weave/legacy/ops_arrow/vectorize.py +++ b/weave/legacy/ops_arrow/vectorize.py @@ -11,7 +11,7 @@ weave_internal, ) from weave.legacy import errors,weavify, registry_mem -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op, use from weave.legacy import dispatch, graph, graph_debug, op_args, op_def from weave.legacy.arrow import convert diff --git a/weave/legacy/ops_domain/artifact_alias_ops.py b/weave/legacy/ops_domain/artifact_alias_ops.py index 4d93dbfbc07..140ffadfbaf 100644 --- a/weave/legacy/ops_domain/artifact_alias_ops.py +++ b/weave/legacy/ops_domain/artifact_alias_ops.py @@ -1,4 +1,4 @@ -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op from weave.legacy.gql_op_plugin import wb_gql_op_plugin from weave.legacy.language_features.tagging.make_tag_getter_op import ( diff --git a/weave/legacy/ops_domain/artifact_collection_ops.py b/weave/legacy/ops_domain/artifact_collection_ops.py index ed3f2d705fd..aaf6231a37e 100644 --- a/weave/legacy/ops_domain/artifact_collection_ops.py +++ b/weave/legacy/ops_domain/artifact_collection_ops.py @@ -2,7 +2,7 @@ import urllib from weave.legacy import errors -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op from weave.legacy.gql_op_plugin import wb_gql_op_plugin from weave.legacy.ops_domain import wb_domain_types as wdt diff --git a/weave/legacy/ops_domain/artifact_membership_ops.py b/weave/legacy/ops_domain/artifact_membership_ops.py index ed17d75006c..ab042265304 100644 --- a/weave/legacy/ops_domain/artifact_membership_ops.py +++ b/weave/legacy/ops_domain/artifact_membership_ops.py @@ -1,6 +1,6 @@ import urllib -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op from weave.legacy.gql_op_plugin import wb_gql_op_plugin from weave.legacy.ops_domain import wb_domain_types as wdt diff --git a/weave/legacy/ops_domain/artifact_type_ops.py b/weave/legacy/ops_domain/artifact_type_ops.py index d29445538d7..4b62b70929e 100644 --- a/weave/legacy/ops_domain/artifact_type_ops.py +++ b/weave/legacy/ops_domain/artifact_type_ops.py @@ -1,6 +1,6 @@ import typing -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op from weave.legacy.gql_op_plugin import wb_gql_op_plugin from weave.legacy.ops_domain import wb_domain_types as wdt diff --git a/weave/legacy/ops_domain/artifact_version_ops.py b/weave/legacy/ops_domain/artifact_version_ops.py index ada1ba79201..aa816e3f716 100644 --- a/weave/legacy/ops_domain/artifact_version_ops.py +++ b/weave/legacy/ops_domain/artifact_version_ops.py @@ -3,7 +3,7 @@ from urllib.parse import quote from weave.legacy import errors -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op from weave.legacy import artifact_fs, artifact_wandb, input_provider from weave.legacy.gql_op_plugin import wb_gql_op_plugin diff --git a/weave/legacy/ops_domain/entity_ops.py b/weave/legacy/ops_domain/entity_ops.py index 8a6ff598622..89b45216863 100644 --- a/weave/legacy/ops_domain/entity_ops.py +++ b/weave/legacy/ops_domain/entity_ops.py @@ -1,4 +1,4 @@ -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op from weave.legacy.gql_op_plugin import wb_gql_op_plugin from weave.legacy.language_features.tagging.make_tag_getter_op import ( diff --git a/weave/legacy/ops_domain/org_ops.py b/weave/legacy/ops_domain/org_ops.py index 1abeb1dfbdd..c0ce7588ba0 100644 --- a/weave/legacy/ops_domain/org_ops.py +++ b/weave/legacy/ops_domain/org_ops.py @@ -1,4 +1,4 @@ -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.ops_domain import wb_domain_types as wdt from weave.legacy.ops_domain.wandb_domain_gql import ( gql_connection_op, diff --git a/weave/legacy/ops_domain/project_ops.py b/weave/legacy/ops_domain/project_ops.py index 22ebabcd6b7..b4463818c8a 100644 --- a/weave/legacy/ops_domain/project_ops.py +++ b/weave/legacy/ops_domain/project_ops.py @@ -2,7 +2,7 @@ import typing from weave.legacy import errors -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op from weave.legacy import input_provider from weave.legacy.gql_op_plugin import wb_gql_op_plugin diff --git a/weave/legacy/ops_domain/repo_insight_ops.py b/weave/legacy/ops_domain/repo_insight_ops.py index d03aaa61cc6..5baa89dec29 100644 --- a/weave/legacy/ops_domain/repo_insight_ops.py +++ b/weave/legacy/ops_domain/repo_insight_ops.py @@ -2,7 +2,7 @@ import json from weave.legacy import errors -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op from weave.legacy.gql_json_cache import use_json from weave.legacy.gql_op_plugin import wb_gql_op_plugin diff --git a/weave/legacy/ops_domain/report_ops.py b/weave/legacy/ops_domain/report_ops.py index fe3c39e80c5..f0f0db1a61d 100644 --- a/weave/legacy/ops_domain/report_ops.py +++ b/weave/legacy/ops_domain/report_ops.py @@ -3,7 +3,7 @@ import urllib from weave.legacy import errors -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op from weave.legacy.gql_op_plugin import wb_gql_op_plugin from weave.legacy.ops_domain import wb_domain_types as wdt diff --git a/weave/legacy/ops_domain/run_history/history_op_common.py b/weave/legacy/ops_domain/run_history/history_op_common.py index c1e6f7a1f0f..3712e488bfc 100644 --- a/weave/legacy/ops_domain/run_history/history_op_common.py +++ b/weave/legacy/ops_domain/run_history/history_op_common.py @@ -4,7 +4,7 @@ import pyarrow as pa from pyarrow import parquet as pq -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import use from weave.legacy import ( util, diff --git a/weave/legacy/ops_domain/run_history/run_history_v1_legacy_ops.py b/weave/legacy/ops_domain/run_history/run_history_v1_legacy_ops.py index 782017fd1ea..d12822b462b 100644 --- a/weave/legacy/ops_domain/run_history/run_history_v1_legacy_ops.py +++ b/weave/legacy/ops_domain/run_history/run_history_v1_legacy_ops.py @@ -3,7 +3,7 @@ import pyarrow as pa from weave.legacy import engine_trace -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op from weave.legacy import gql_json_cache from weave.legacy.gql_op_plugin import wb_gql_op_plugin diff --git a/weave/legacy/ops_domain/run_history/run_history_v2_parquet_media.py b/weave/legacy/ops_domain/run_history/run_history_v2_parquet_media.py index 540b068fa54..db2c0a7a50f 100644 --- a/weave/legacy/ops_domain/run_history/run_history_v2_parquet_media.py +++ b/weave/legacy/ops_domain/run_history/run_history_v2_parquet_media.py @@ -7,7 +7,7 @@ import pyarrow as pa from weave.legacy import engine_trace -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op, use from weave.legacy import artifact_mem, gql_json_cache from weave.legacy.arrow import convert diff --git a/weave/legacy/ops_domain/run_history/run_history_v3_parquet_stream_optimized.py b/weave/legacy/ops_domain/run_history/run_history_v3_parquet_stream_optimized.py index b39fce58054..0b7750ddf1b 100644 --- a/weave/legacy/ops_domain/run_history/run_history_v3_parquet_stream_optimized.py +++ b/weave/legacy/ops_domain/run_history/run_history_v3_parquet_stream_optimized.py @@ -6,7 +6,7 @@ import pyarrow as pa from weave.legacy import errors -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op from weave.legacy import ( engine_trace, diff --git a/weave/legacy/ops_domain/run_ops.py b/weave/legacy/ops_domain/run_ops.py index 4c73766d9a4..542f21fb665 100644 --- a/weave/legacy/ops_domain/run_ops.py +++ b/weave/legacy/ops_domain/run_ops.py @@ -38,7 +38,7 @@ import typing from weave.legacy import engine_trace -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op from weave.legacy import compile_table from weave.legacy.gql_op_plugin import wb_gql_op_plugin diff --git a/weave/legacy/ops_domain/run_queue_ops.py b/weave/legacy/ops_domain/run_queue_ops.py index d0f7c72d185..4211cfdb5cd 100644 --- a/weave/legacy/ops_domain/run_queue_ops.py +++ b/weave/legacy/ops_domain/run_queue_ops.py @@ -1,6 +1,6 @@ import json -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op from weave.legacy.gql_op_plugin import wb_gql_op_plugin from weave.legacy.language_features.tagging.make_tag_getter_op import ( diff --git a/weave/legacy/ops_domain/run_segment.py b/weave/legacy/ops_domain/run_segment.py index 02d09567744..9dff1c01eaa 100644 --- a/weave/legacy/ops_domain/run_segment.py +++ b/weave/legacy/ops_domain/run_segment.py @@ -3,7 +3,7 @@ from typing import Optional, cast import weave -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import Node, get, use from weave.legacy import context_state as _context from weave.legacy import panels diff --git a/weave/legacy/ops_domain/stream_table_ops.py b/weave/legacy/ops_domain/stream_table_ops.py index ca9c867ebd6..bc750f574e5 100644 --- a/weave/legacy/ops_domain/stream_table_ops.py +++ b/weave/legacy/ops_domain/stream_table_ops.py @@ -1,4 +1,4 @@ -from weave import weave_types +from weave.legacy import weave_types from weave.legacy.api import op from weave.legacy import compile, op_def from weave.legacy.arrow.arrow import ArrowWeaveListType diff --git a/weave/legacy/ops_domain/table.py b/weave/legacy/ops_domain/table.py index 1f295cf62b5..7f4fbf91dae 100644 --- a/weave/legacy/ops_domain/table.py +++ b/weave/legacy/ops_domain/table.py @@ -6,7 +6,7 @@ import typing from weave import weave_internal -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op, weave_class from weave.legacy import ( artifact_fs, diff --git a/weave/legacy/ops_domain/trace_tree.py b/weave/legacy/ops_domain/trace_tree.py index 5a8487652f6..595916d1028 100644 --- a/weave/legacy/ops_domain/trace_tree.py +++ b/weave/legacy/ops_domain/trace_tree.py @@ -13,7 +13,7 @@ from weave.legacy import api as weave from weave.legacy import stream_data_interfaces -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import op_def from weave.legacy.decorator_op import op diff --git a/weave/legacy/ops_domain/user_ops.py b/weave/legacy/ops_domain/user_ops.py index f9b77f4f4f2..0c6527eea79 100644 --- a/weave/legacy/ops_domain/user_ops.py +++ b/weave/legacy/ops_domain/user_ops.py @@ -1,4 +1,4 @@ -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op from weave.legacy.gql_op_plugin import wb_gql_op_plugin from weave.legacy.language_features.tagging.make_tag_getter_op import ( diff --git a/weave/legacy/ops_domain/wandb_domain_gql.py b/weave/legacy/ops_domain/wandb_domain_gql.py index 9cb25156608..554e52f0651 100644 --- a/weave/legacy/ops_domain/wandb_domain_gql.py +++ b/weave/legacy/ops_domain/wandb_domain_gql.py @@ -4,7 +4,7 @@ import pyarrow as pa -from weave import weave_types +from weave.legacy import weave_types from weave.legacy.api import op from weave.legacy import errors, gql_op_plugin, op_def, partial_object from weave.legacy.decorator_arrow_op import arrow_op diff --git a/weave/legacy/ops_domain/wb_domain_types.py b/weave/legacy/ops_domain/wb_domain_types.py index df20f7a69bb..b1bf98bef0d 100644 --- a/weave/legacy/ops_domain/wb_domain_types.py +++ b/weave/legacy/ops_domain/wb_domain_types.py @@ -1,6 +1,6 @@ import typing -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.decorator_type import type as weave_type from weave.legacy.partial_object import ( PartialObject, diff --git a/weave/legacy/ops_domain/wb_util.py b/weave/legacy/ops_domain/wb_util.py index ccda04fdcb9..8ba2582a2ca 100644 --- a/weave/legacy/ops_domain/wb_util.py +++ b/weave/legacy/ops_domain/wb_util.py @@ -2,7 +2,7 @@ from dataclasses import dataclass from urllib import parse -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import artifact_fs, decorator_type from weave.legacy.artifact_wandb import ( WandbArtifact, diff --git a/weave/legacy/ops_domain/wbgqlquery_op.py b/weave/legacy/ops_domain/wbgqlquery_op.py index e16da74c830..4841ee249e3 100644 --- a/weave/legacy/ops_domain/wbgqlquery_op.py +++ b/weave/legacy/ops_domain/wbgqlquery_op.py @@ -2,7 +2,7 @@ import typing from weave.legacy import errors -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op from weave.legacy import engine_trace, environment, mappers_gql, partial_object from weave.legacy.language_features.tagging import tagged_value_type diff --git a/weave/legacy/ops_primitives/_dict_utils.py b/weave/legacy/ops_primitives/_dict_utils.py index 16b44d7b135..066c47b8616 100644 --- a/weave/legacy/ops_primitives/_dict_utils.py +++ b/weave/legacy/ops_primitives/_dict_utils.py @@ -1,7 +1,7 @@ import typing from weave.legacy import errors -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import box from weave.legacy.language_features.tagging import tag_store, tagged_value_type diff --git a/weave/legacy/ops_primitives/any.py b/weave/legacy/ops_primitives/any.py index c678d5eabb8..f1895ae6c2b 100644 --- a/weave/legacy/ops_primitives/any.py +++ b/weave/legacy/ops_primitives/any.py @@ -1,4 +1,4 @@ -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.decorator_op import op diff --git a/weave/legacy/ops_primitives/boolean.py b/weave/legacy/ops_primitives/boolean.py index 531faf43076..29c6d1ab283 100644 --- a/weave/legacy/ops_primitives/boolean.py +++ b/weave/legacy/ops_primitives/boolean.py @@ -1,6 +1,6 @@ import typing -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op, weave_class from weave.legacy import dispatch from weave.legacy.ops_primitives.dict import dict_ diff --git a/weave/legacy/ops_primitives/date.py b/weave/legacy/ops_primitives/date.py index 073014b593d..08a5083bfa8 100644 --- a/weave/legacy/ops_primitives/date.py +++ b/weave/legacy/ops_primitives/date.py @@ -4,7 +4,7 @@ import dateutil import dateutil.parser -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op, type diff --git a/weave/legacy/ops_primitives/dict.py b/weave/legacy/ops_primitives/dict.py index 9d6b76ebd98..cc6e2a25233 100644 --- a/weave/legacy/ops_primitives/dict.py +++ b/weave/legacy/ops_primitives/dict.py @@ -1,6 +1,6 @@ import typing -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy._dict_utils import typeddict_pick_output_type from weave.legacy.decorator_class import weave_class from weave.legacy.decorator_op import op diff --git a/weave/legacy/ops_primitives/file.py b/weave/legacy/ops_primitives/file.py index 19d97a3b49a..75d37ea08db 100644 --- a/weave/legacy/ops_primitives/file.py +++ b/weave/legacy/ops_primitives/file.py @@ -3,7 +3,7 @@ from weave.legacy import environment as weave_env from weave.legacy import errors -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op from weave.legacy import file_base, wandb_file_manager from weave.legacy.artifact_fs import FilesystemArtifactDir, FilesystemArtifactFile diff --git a/weave/legacy/ops_primitives/file_local.py b/weave/legacy/ops_primitives/file_local.py index f6e2a29f206..022bf141e19 100644 --- a/weave/legacy/ops_primitives/file_local.py +++ b/weave/legacy/ops_primitives/file_local.py @@ -2,7 +2,7 @@ import typing from weave.legacy import environment -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op from weave.legacy import file_local diff --git a/weave/legacy/ops_primitives/html.py b/weave/legacy/ops_primitives/html.py index 358b9e7d0dd..2103ff69428 100644 --- a/weave/legacy/ops_primitives/html.py +++ b/weave/legacy/ops_primitives/html.py @@ -1,7 +1,7 @@ import dataclasses from weave.legacy import api as weave -from weave import weave_types as types +from weave.legacy import weave_types as types class HtmlType(types.Type): diff --git a/weave/legacy/ops_primitives/image.py b/weave/legacy/ops_primitives/image.py index 64ea6ace2d5..f44f14357ad 100644 --- a/weave/legacy/ops_primitives/image.py +++ b/weave/legacy/ops_primitives/image.py @@ -6,7 +6,7 @@ import PIL.Image from weave.legacy import api as weave -from weave import weave_types as types +from weave.legacy import weave_types as types class ImageType(types.Type): diff --git a/weave/legacy/ops_primitives/list_.py b/weave/legacy/ops_primitives/list_.py index d2aab966eef..e61826f6003 100644 --- a/weave/legacy/ops_primitives/list_.py +++ b/weave/legacy/ops_primitives/list_.py @@ -7,7 +7,7 @@ import pandas as pd from weave.legacy import storage -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import box, execute_fast, errors from weave.legacy._dict_utils import tag_aware_dict_val_for_escaped_key from weave.legacy.decorator_class import weave_class diff --git a/weave/legacy/ops_primitives/list_tag_getters.py b/weave/legacy/ops_primitives/list_tag_getters.py index 7c91cd21f8c..61e57c3ae93 100644 --- a/weave/legacy/ops_primitives/list_tag_getters.py +++ b/weave/legacy/ops_primitives/list_tag_getters.py @@ -1,4 +1,4 @@ -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.language_features.tagging import make_tag_getter_op group_tag_getter_op = make_tag_getter_op.make_tag_getter_op( diff --git a/weave/legacy/ops_primitives/markdown.py b/weave/legacy/ops_primitives/markdown.py index 1f685c65279..ad3822dfdfc 100644 --- a/weave/legacy/ops_primitives/markdown.py +++ b/weave/legacy/ops_primitives/markdown.py @@ -1,7 +1,7 @@ import dataclasses from weave.legacy import api as weave -from weave import weave_types as types +from weave.legacy import weave_types as types class MarkdownType(types.Type): diff --git a/weave/legacy/ops_primitives/number.py b/weave/legacy/ops_primitives/number.py index bddd25b7fca..2cb4aec1254 100644 --- a/weave/legacy/ops_primitives/number.py +++ b/weave/legacy/ops_primitives/number.py @@ -4,7 +4,7 @@ import numpy as np -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op, weave_class from weave.legacy import timestamp as weave_timestamp diff --git a/weave/legacy/ops_primitives/number_bin.py b/weave/legacy/ops_primitives/number_bin.py index 5213ce95d21..c06de46703d 100644 --- a/weave/legacy/ops_primitives/number_bin.py +++ b/weave/legacy/ops_primitives/number_bin.py @@ -1,12 +1,12 @@ import math -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op, use from weave.legacy import graph from weave.legacy.ops_primitives import date from weave.legacy.ops_primitives.dict import dict_ from weave.weave_internal import call_fn, define_fn, make_const_node -from weave.weave_types import Function, NumberBinType +from weave.legacy.weave_types import Function, NumberBinType @op( diff --git a/weave/legacy/ops_primitives/obj.py b/weave/legacy/ops_primitives/obj.py index b05ae9a9d28..615fe8eea3f 100644 --- a/weave/legacy/ops_primitives/obj.py +++ b/weave/legacy/ops_primitives/obj.py @@ -1,7 +1,7 @@ import typing from weave.legacy import codify -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op, weave_class diff --git a/weave/legacy/ops_primitives/op_def.py b/weave/legacy/ops_primitives/op_def.py index 48e4253c6dd..81caf0be0e2 100644 --- a/weave/legacy/ops_primitives/op_def.py +++ b/weave/legacy/ops_primitives/op_def.py @@ -1,5 +1,5 @@ from weave.legacy import api as weave -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.op_def import OpDef from weave.legacy.op_def_type import OpDefType diff --git a/weave/legacy/ops_primitives/pandas_.py b/weave/legacy/ops_primitives/pandas_.py index 70b15467e9d..97a9f30c2db 100644 --- a/weave/legacy/ops_primitives/pandas_.py +++ b/weave/legacy/ops_primitives/pandas_.py @@ -9,7 +9,7 @@ import pyarrow.parquet as pq from weave.legacy import errors -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op, weave_class from weave.legacy import box, file_base, graph, mappers_python from weave.legacy.language_features.tagging import tag_store, tagged_value_type diff --git a/weave/legacy/ops_primitives/random_junk.py b/weave/legacy/ops_primitives/random_junk.py index b1bc875fd6a..e77ffe0a48b 100644 --- a/weave/legacy/ops_primitives/random_junk.py +++ b/weave/legacy/ops_primitives/random_junk.py @@ -1,7 +1,7 @@ # Ideas for ops, but not production ready. from weave.legacy import api as api -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op, weave_class op( diff --git a/weave/legacy/ops_primitives/set_.py b/weave/legacy/ops_primitives/set_.py index 6786c7c3f4f..d64e7e9f845 100644 --- a/weave/legacy/ops_primitives/set_.py +++ b/weave/legacy/ops_primitives/set_.py @@ -1,4 +1,4 @@ -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.decorators import op diff --git a/weave/legacy/ops_primitives/sql.py b/weave/legacy/ops_primitives/sql.py index 3e179f727d2..7c05a41a213 100644 --- a/weave/legacy/ops_primitives/sql.py +++ b/weave/legacy/ops_primitives/sql.py @@ -2,7 +2,7 @@ import functools import math -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op, weave_class from weave.legacy import decorator_type from weave.legacy.language_features.tagging import tagged_value_type diff --git a/weave/legacy/ops_primitives/string.py b/weave/legacy/ops_primitives/string.py index fbfa4aaec97..db86ae6d233 100644 --- a/weave/legacy/ops_primitives/string.py +++ b/weave/legacy/ops_primitives/string.py @@ -4,7 +4,7 @@ import numpy as np -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op, weave_class diff --git a/weave/legacy/ops_primitives/test_list.py b/weave/legacy/ops_primitives/test_list.py index a2478617749..2856054b5ab 100644 --- a/weave/legacy/ops_primitives/test_list.py +++ b/weave/legacy/ops_primitives/test_list.py @@ -2,7 +2,7 @@ from weave.legacy import api as weave from weave import weave_internal -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import box from weave.legacy.language_features.tagging import ( make_tag_getter_op, diff --git a/weave/legacy/ops_primitives/test_pandas.py b/weave/legacy/ops_primitives/test_pandas.py index 2b0dc05a6b5..835aeba71f8 100644 --- a/weave/legacy/ops_primitives/test_pandas.py +++ b/weave/legacy/ops_primitives/test_pandas.py @@ -1,7 +1,7 @@ import pandas as pd from weave.legacy import api as weave -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.ops_primitives import pandas_ as op_pandas diff --git a/weave/legacy/ops_primitives/timestamp_bin.py b/weave/legacy/ops_primitives/timestamp_bin.py index 55bd192de55..ef153be48da 100644 --- a/weave/legacy/ops_primitives/timestamp_bin.py +++ b/weave/legacy/ops_primitives/timestamp_bin.py @@ -1,10 +1,10 @@ from weave import weave_internal -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op, use from weave.legacy import graph from weave.legacy.ops_primitives.dict import dict_ from weave.weave_internal import call_fn, define_fn, make_const_node -from weave.weave_types import Function, TimestampBinType +from weave.legacy.weave_types import Function, TimestampBinType NICE_BIN_SIZES_SEC = [ # TODO: will need more steps along here for smooth zooming. diff --git a/weave/legacy/ops_primitives/type.py b/weave/legacy/ops_primitives/type.py index 46b7c987062..4b39df3143e 100644 --- a/weave/legacy/ops_primitives/type.py +++ b/weave/legacy/ops_primitives/type.py @@ -1,7 +1,7 @@ import typing from weave.legacy import errors -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import op diff --git a/weave/legacy/ops_primitives/weave_api.py b/weave/legacy/ops_primitives/weave_api.py index 36295f3f69e..680e21c5460 100644 --- a/weave/legacy/ops_primitives/weave_api.py +++ b/weave/legacy/ops_primitives/weave_api.py @@ -6,7 +6,7 @@ storage, weave_internal, ) -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.api import mutation, op, weave_class from weave.legacy import ( errors, diff --git a/weave/legacy/panel.py b/weave/legacy/panel.py index 922023202fe..7ec6daab4e0 100644 --- a/weave/legacy/panel.py +++ b/weave/legacy/panel.py @@ -5,7 +5,7 @@ from weave.legacy import api as weave from weave import weave_internal -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import graph, panel_util, errors, storage diff --git a/weave/legacy/panel_util.py b/weave/legacy/panel_util.py index 3da288431dc..5c86926c92e 100644 --- a/weave/legacy/panel_util.py +++ b/weave/legacy/panel_util.py @@ -1,6 +1,6 @@ import typing -from weave import weave_types +from weave.legacy import weave_types from weave.legacy import storage, graph, panel diff --git a/weave/legacy/panels/panel_facet.py b/weave/legacy/panels/panel_facet.py index 228f5c8b74b..54e079f333f 100644 --- a/weave/legacy/panels/panel_facet.py +++ b/weave/legacy/panels/panel_facet.py @@ -3,7 +3,7 @@ import weave from weave import weave_internal -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import graph, panel, panel_util from weave.legacy.arrow import list_ from weave.legacy.panels import table_state diff --git a/weave/legacy/panels/panel_plot.py b/weave/legacy/panels/panel_plot.py index 3f3a2804988..7210836b2d7 100644 --- a/weave/legacy/panels/panel_plot.py +++ b/weave/legacy/panels/panel_plot.py @@ -5,7 +5,7 @@ import weave from weave import weave_internal -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import errors, codifiable_value_mixin, codify, graph, panel from weave.legacy.ops_primitives import boolean, list_ from weave.legacy.ops_primitives import dict as dict_ diff --git a/weave/legacy/panels/table_state.py b/weave/legacy/panels/table_state.py index 0dcef9bda45..9415c814d7d 100644 --- a/weave/legacy/panels/table_state.py +++ b/weave/legacy/panels/table_state.py @@ -7,8 +7,8 @@ import string import typing -from weave import weave_internal, weave_types -from weave.legacy import decorator_type, graph, ops, panel +from weave import weave_internal +from weave.legacy import decorator_type, graph, ops, panel, weave_types from weave.legacy.language_features.tagging import tagged_value_type diff --git a/weave/legacy/panels_py/generator_templates.py b/weave/legacy/panels_py/generator_templates.py index b7fc045cb22..2aa6e524424 100644 --- a/weave/legacy/panels_py/generator_templates.py +++ b/weave/legacy/panels_py/generator_templates.py @@ -18,7 +18,7 @@ import dataclasses import typing -from weave import weave_types +from weave.legacy import weave_types from weave.legacy import decorator_op, graph, registry_mem diff --git a/weave/legacy/panels_py/panel_example_custom_board.py b/weave/legacy/panels_py/panel_example_custom_board.py index a514ddad03c..21ba4b37fdb 100644 --- a/weave/legacy/panels_py/panel_example_custom_board.py +++ b/weave/legacy/panels_py/panel_example_custom_board.py @@ -1,6 +1,6 @@ import weave from weave import weave_internal as internal -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.panels_py.generator_templates import template_registry # IMPORTANT: To enable this (or any template), it must be imported in diff --git a/weave/legacy/panels_py/panel_llm_monitor.py b/weave/legacy/panels_py/panel_llm_monitor.py index 73cc9278e2b..a14e0e804d5 100644 --- a/weave/legacy/panels_py/panel_llm_monitor.py +++ b/weave/legacy/panels_py/panel_llm_monitor.py @@ -4,7 +4,7 @@ import weave from weave import weave_internal from weave import weave_internal as internal -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import util, dispatch from weave.legacy.panels import panel_board, panel_group from weave.legacy.panels_py import panel_autoboard diff --git a/weave/legacy/panels_py/panel_observability.py b/weave/legacy/panels_py/panel_observability.py index 2dd3c574fd1..37a3d47d6bc 100644 --- a/weave/legacy/panels_py/panel_observability.py +++ b/weave/legacy/panels_py/panel_observability.py @@ -1,6 +1,6 @@ import weave from weave import weave_internal -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy.panels import panel_board from weave.legacy.panels_py.generator_templates import template_registry diff --git a/weave/legacy/panels_py/panel_trace_monitor.py b/weave/legacy/panels_py/panel_trace_monitor.py index cb0a9a9e334..7e228aeef01 100644 --- a/weave/legacy/panels_py/panel_trace_monitor.py +++ b/weave/legacy/panels_py/panel_trace_monitor.py @@ -3,7 +3,7 @@ import weave from weave import weave_internal from weave import weave_internal as internal -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import util, dispatch, graph from weave.legacy.panels import panel_board, panel_group, panel_trace from weave.legacy.panels.panel_trace_span import TraceSpanModelPanel, TraceSpanPanel diff --git a/weave/legacy/partial_object.py b/weave/legacy/partial_object.py index 8b504f882a5..306c12a2d73 100644 --- a/weave/legacy/partial_object.py +++ b/weave/legacy/partial_object.py @@ -2,7 +2,7 @@ import typing from dataclasses import dataclass, field -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import artifact_fs T = typing.TypeVar("T", bound="PartialObject") diff --git a/weave/legacy/propagate_gql_keys.py b/weave/legacy/propagate_gql_keys.py index 08aa87a1aff..b32fbd3ad32 100644 --- a/weave/legacy/propagate_gql_keys.py +++ b/weave/legacy/propagate_gql_keys.py @@ -1,7 +1,7 @@ import typing -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import gql_op_plugin, graph, input_provider, op_def, partial_object, registry_mem diff --git a/weave/legacy/pyfunc_type_util.py b/weave/legacy/pyfunc_type_util.py index e327e18b4d5..c72318e515d 100644 --- a/weave/legacy/pyfunc_type_util.py +++ b/weave/legacy/pyfunc_type_util.py @@ -4,7 +4,7 @@ from weave.legacy import infer_types, op_args from weave.legacy import errors -from .. import weave_types as types +from weave.legacy import weave_types as types InputTypeItemType = typing.Union[types.Type, typing.Callable[..., types.Type]] InputTypeType = typing.Union[op_args.OpArgs, typing.Mapping[str, InputTypeItemType]] diff --git a/weave/legacy/ref_base.py b/weave/legacy/ref_base.py index a085e044652..234b9f4aede 100644 --- a/weave/legacy/ref_base.py +++ b/weave/legacy/ref_base.py @@ -10,13 +10,13 @@ from weave.legacy.language_features.tagging import tag_store from weave.legacy import errors -from .. import weave_types as types +from weave.legacy import weave_types as types # We store Refs here if we can't attach them directly to the object REFS: weakref.WeakValueDictionary[int, "Ref"] = weakref.WeakValueDictionary() if typing.TYPE_CHECKING: - from .. import weave_types as types + from weave.legacy import weave_types as types from ..trace import weave_client diff --git a/weave/legacy/registry_mem.py b/weave/legacy/registry_mem.py index cbc863f6d31..625c18ca60e 100644 --- a/weave/legacy/registry_mem.py +++ b/weave/legacy/registry_mem.py @@ -1,7 +1,7 @@ import datetime import typing -from weave import weave_types +from weave.legacy import weave_types from weave.legacy import storage, errors, context_state, op_aliases, op_args, uris from weave.legacy.op_args import OpNamedArgs diff --git a/weave/legacy/runfiles_wandb.py b/weave/legacy/runfiles_wandb.py index 819dc7696ea..9353652927a 100644 --- a/weave/legacy/runfiles_wandb.py +++ b/weave/legacy/runfiles_wandb.py @@ -8,7 +8,7 @@ from weave.legacy import environment as weave_env from weave.legacy import filesystem -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import ( artifact_fs, errors, diff --git a/weave/legacy/runs.py b/weave/legacy/runs.py index ce26f5365a0..bb27e87b374 100644 --- a/weave/legacy/runs.py +++ b/weave/legacy/runs.py @@ -1,7 +1,7 @@ import dataclasses import typing -from weave import weave_types as types +from weave.legacy import weave_types as types @dataclasses.dataclass diff --git a/weave/legacy/serialize.py b/weave/legacy/serialize.py index b0d750f2902..ee83f9047cb 100644 --- a/weave/legacy/serialize.py +++ b/weave/legacy/serialize.py @@ -8,7 +8,7 @@ import typing from weave import weave_internal -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import storage, errors, graph, memo, value_or_error NodeOrOp = typing.Union[graph.Node, graph.Op] diff --git a/weave/legacy/server.py b/weave/legacy/server.py index de94e6b17bb..51f5f6bd6e4 100644 --- a/weave/legacy/server.py +++ b/weave/legacy/server.py @@ -24,12 +24,12 @@ wandb_api, logs, util, + storage, + weave_types, ) from weave.legacy.language_features.tagging import tag_store from weave.legacy.language_features.tagging.tag_store import isolated_tagging_context -from .. import storage, weave_types - # A function to monkeypatch the request post method # def patch_request_post(): # r_post = requests.post diff --git a/weave/legacy/show.py b/weave/legacy/show.py index 0f03b3da900..204e84d5b7f 100644 --- a/weave/legacy/show.py +++ b/weave/legacy/show.py @@ -8,7 +8,7 @@ from weave.legacy import storage, artifact_fs, context, errors, graph, ops, node_ref, panel, ref_base from weave.legacy import util from . import usage_analytics -from .. import weave_types as types +from weave.legacy import weave_types as types from . import weavejs_fixes diff --git a/weave/legacy/stitch.py b/weave/legacy/stitch.py index 878448292d5..9ba0145040b 100644 --- a/weave/legacy/stitch.py +++ b/weave/legacy/stitch.py @@ -26,7 +26,7 @@ from weave.legacy.language_features.tagging import opdef_util from weave.legacy import errors -from .. import weave_types as types +from weave.legacy import weave_types as types from . import _dict_utils diff --git a/weave/legacy/storage.py b/weave/legacy/storage.py index dce6b4d82f5..e13f102bb1b 100644 --- a/weave/legacy/storage.py +++ b/weave/legacy/storage.py @@ -22,7 +22,7 @@ timestamp, ) -from weave import weave_types as types +from weave.legacy import weave_types as types Ref = ref_base.Ref diff --git a/weave/legacy/trace_legacy.py b/weave/legacy/trace_legacy.py index 3d9e6529cc4..aefd89dc605 100644 --- a/weave/legacy/trace_legacy.py +++ b/weave/legacy/trace_legacy.py @@ -5,7 +5,7 @@ from . import ref_base from . import errors -from .. import weave_types as types +from weave.legacy import weave_types as types def get_obj_creator(ref: ref_base.Ref) -> typing.Optional[runs.Run]: diff --git a/weave/legacy/trace_local.py b/weave/legacy/trace_local.py index b210d313b09..05c6075b003 100644 --- a/weave/legacy/trace_local.py +++ b/weave/legacy/trace_local.py @@ -12,7 +12,7 @@ storage, weave_internal, ) -from .. import weave_types as types +from weave.legacy import weave_types as types @dataclasses.dataclass diff --git a/weave/legacy/types_numpy.py b/weave/legacy/types_numpy.py index 2577e1119a7..c7d661e8780 100644 --- a/weave/legacy/types_numpy.py +++ b/weave/legacy/types_numpy.py @@ -1,6 +1,6 @@ import numpy as np -from .. import weave_types as types +from weave.legacy import weave_types as types # TODO: this doesn't match how extra works for list types... diff --git a/weave/legacy/val_const.py b/weave/legacy/val_const.py index 212d5692d2b..c48e34e50cd 100644 --- a/weave/legacy/val_const.py +++ b/weave/legacy/val_const.py @@ -7,7 +7,7 @@ import typing -from weave import weave_types as types +from weave.legacy import weave_types as types class Const: diff --git a/weave/legacy/wandb_interface/wandb_stream_table.py b/weave/legacy/wandb_interface/wandb_stream_table.py index 7d3e307cd7a..63a05b9fb8b 100644 --- a/weave/legacy/wandb_interface/wandb_stream_table.py +++ b/weave/legacy/wandb_interface/wandb_stream_table.py @@ -15,7 +15,7 @@ from wandb.sdk.lib.paths import LogicalPath from wandb.sdk.lib.printer import get_printer -from weave import weave_types +from weave.legacy import weave_types from weave.legacy import ( storage, errors, diff --git a/weave/legacy/wandb_util.py b/weave/legacy/wandb_util.py index f160a46e2a0..be4161ff038 100644 --- a/weave/legacy/wandb_util.py +++ b/weave/legacy/wandb_util.py @@ -1,7 +1,7 @@ import typing from weave.legacy import errors -from weave import weave_types as types +from weave.legacy import weave_types as types from weave.legacy import ops, ops_domain diff --git a/weave/legacy/weave_inspector.py b/weave/legacy/weave_inspector.py index 15814ada84e..d878e4f8d4d 100644 --- a/weave/legacy/weave_inspector.py +++ b/weave/legacy/weave_inspector.py @@ -107,7 +107,7 @@ from weave.legacy import graph -from .. import weave_types as types +from weave.legacy import weave_types as types from .partial_object import PartialObjectType diff --git a/weave/legacy/weave_pydantic.py b/weave/legacy/weave_pydantic.py index 086feb8d2fa..870b2a83d61 100644 --- a/weave/legacy/weave_pydantic.py +++ b/weave/legacy/weave_pydantic.py @@ -1,6 +1,6 @@ from pydantic import BaseModel, create_model -from .. import weave_types as types +from weave.legacy import weave_types as types from . import infer_types diff --git a/weave/weave_types.py b/weave/legacy/weave_types.py similarity index 89% rename from weave/weave_types.py rename to weave/legacy/weave_types.py index 3621eaa0de4..2b1c45c3891 100644 --- a/weave/weave_types.py +++ b/weave/legacy/weave_types.py @@ -24,7 +24,7 @@ from weave.legacy import artifact_base from weave.legacy.artifact_fs import FilesystemArtifact - from .legacy import weave_inspector + from weave.legacy import weave_inspector def to_weavejs_typekey(k: str) -> str: @@ -46,7 +46,7 @@ def js_to_py_typename(typename: str) -> str: return typename -def all_subclasses(cls): +def all_subclasses(cls): # type: ignore # Note using a list here... this doesn't dedupe star pattern! # But it does preserve tree order. return list(cls.__subclasses__()) + [ @@ -54,11 +54,11 @@ def all_subclasses(cls): ] -def get_type_classes(): +def get_type_classes(): # type: ignore return all_subclasses(Type) -def instance_class_to_potential_type_map(): +def instance_class_to_potential_type_map(): # type: ignore res = {} type_classes = get_type_classes() for type_class in type_classes: @@ -74,7 +74,7 @@ def instance_class_to_potential_type_map(): @functools.cache -def instance_class_to_potential_type(cls): +def instance_class_to_potential_type(cls): # type: ignore mapping = instance_class_to_potential_type_map() exact_type_classes = mapping.get(cls) if exact_type_classes is not None: @@ -90,7 +90,7 @@ def instance_class_to_potential_type(cls): @functools.cache -def type_name_to_type_map(): +def type_name_to_type_map(): # type: ignore res = {} type_classes = get_type_classes() for type_class in type_classes: @@ -101,7 +101,7 @@ def type_name_to_type_map(): @functools.cache -def type_name_to_type(type_name): +def type_name_to_type(type_name): # type: ignore mapping = type_name_to_type_map() return mapping.get(js_to_py_typename(type_name)) @@ -113,11 +113,11 @@ def type_name_to_type(type_name): class TypeRegistry: @staticmethod - def has_type(obj): + def has_type(obj): # type: ignore return bool(instance_class_to_potential_type(type(obj))) @staticmethod - def type_class_of(obj): + def type_class_of(obj): # type: ignore type_classes = instance_class_to_potential_type(type(obj)) if not type_classes: # return UnknownType() @@ -125,7 +125,7 @@ def type_class_of(obj): return type_classes[-1] @staticmethod - def type_of(obj: typing.Any) -> "Type": + def type_of(obj: typing.Any) -> "Type": # type: ignore from weave.legacy import ref_base if ( @@ -169,7 +169,7 @@ def type_of(obj: typing.Any) -> "Type": return UnknownType() @staticmethod - def type_from_dict(d: typing.Union[str, dict]) -> "Type": + def type_from_dict(d: typing.Union[str, dict]) -> "Type": # type: ignore if is_relocatable_object_type(d): d = typing.cast(dict, d) return deserialize_relocatable_object_type(d) @@ -187,13 +187,13 @@ def type_from_dict(d: typing.Union[str, dict]) -> "Type": return type_.from_dict(d) -def _clear_global_type_class_cache(): +def _clear_global_type_class_cache(): # type: ignore instance_class_to_potential_type.cache_clear() type_name_to_type_map.cache_clear() type_name_to_type.cache_clear() -def _cached_hash(self): +def _cached_hash(self): # type: ignore try: return self.__dict__["_hash"] except KeyError: @@ -203,16 +203,16 @@ def _cached_hash(self): class classproperty(object): - def __init__(self, f): + def __init__(self, f): # type: ignore self.f = f - def __get__(self, obj, owner): + def __get__(self, obj, owner): # type: ignore return self.f(owner) # Addapted from https://stackoverflow.com/questions/18126552/how-to-run-code-when-a-class-is-subclassed class _TypeSubclassWatcher(type): - def __init__(cls, name, bases, clsdict): + def __init__(cls, name, bases, clsdict): # type: ignore # This code will run whenever `Type` is subclassed! # Bust the cache! _clear_global_type_class_cache() @@ -241,23 +241,23 @@ class Type(metaclass=_TypeSubclassWatcher): _type_attrs = None _hash = None - def _hashable(self): + def _hashable(self): # type: ignore return tuple((k, hash(t)) for k, t in self.type_vars_tuple) - def __lt__(self, other): + def __lt__(self, other): # type: ignore return hash(self) < hash(other) - def __repr__(self) -> str: + def __repr__(self) -> str: # type: ignore return f"{self.__class__.__name__}()" - def __name__(self) -> str: + def __name__(self) -> str: # type: ignore return self.__repr__() - def simple_str(self) -> str: + def simple_str(self) -> str: # type: ignore return str(self) @classmethod - def _instance_classes(cls) -> typing.Sequence[type]: + def _instance_classes(cls) -> typing.Sequence[type]: # type: ignore """Helper to get instance_classes as iterable.""" if cls.instance_classes is None: return () @@ -266,7 +266,7 @@ def _instance_classes(cls) -> typing.Sequence[type]: return (cls.instance_classes,) @classmethod - def type_attrs(cls): + def type_attrs(cls): # type: ignore type_attrs = [] for field in dataclasses.fields(cls): if (inspect.isclass(field.type) and issubclass(field.type, Type)) or ( @@ -277,18 +277,18 @@ def type_attrs(cls): return type_attrs @property - def type_vars_tuple(self): + def type_vars_tuple(self): # type: ignore type_vars = [] for field in self.type_attrs(): type_vars.append((field, getattr(self, field))) return tuple(type_vars) @property - def type_vars(self) -> dict[str, "Type"]: + def type_vars(self) -> dict[str, "Type"]: # type: ignore return dict(self.type_vars_tuple) @classmethod - def root_type_class(cls) -> type["Type"]: + def root_type_class(cls) -> type["Type"]: # type: ignore if cls._base_type is None: return cls base_type_class = cls._base_type.root_type_class() @@ -297,38 +297,38 @@ def root_type_class(cls) -> type["Type"]: return base_type_class @classmethod - def is_instance(cls, obj): + def is_instance(cls, obj): # type: ignore for ic in cls._instance_classes(): if isinstance(obj, ic): return ic return None @classmethod - def typeclass_of_class(cls, check_class): + def typeclass_of_class(cls, check_class): # type: ignore return cls @classmethod - def type_of(cls, obj) -> typing.Optional["Type"]: - if not cls.is_instance(obj): + def type_of(cls, obj) -> typing.Optional["Type"]: # type: ignore + if not cls.is_instance(obj): # type: ignore[no-untyped-call] return None - return cls.type_of_instance(obj) + return cls.type_of_instance(obj) # type: ignore[no-untyped-call] @classmethod - def type_of_instance(cls, obj): + def type_of_instance(cls, obj): # type: ignore # Default implementation for Types that take no arguments. return cls() @classproperty - def name(cls): + def name(cls): # type: ignore if cls == Type: return "type" return cls.__name__.removesuffix("Type") - @property # type: ignore - def instance_class(self): + @property # type: ignore[no-redef] + def instance_class(self): # type: ignore return self._instance_classes()[-1] - def assign_type(self, next_type: "Type") -> bool: + def assign_type(self, next_type: "Type") -> bool: # type: ignore # assign_type needs to be as fast as possible, so there are optimizations # throughout this code path, like checking for class equality instead of using isinstance @@ -348,10 +348,10 @@ def assign_type(self, next_type: "Type") -> bool: return self._assign_type_inner(next_type) - def _is_assignable_to(self, other_type) -> typing.Optional[bool]: + def _is_assignable_to(self, other_type) -> typing.Optional[bool]: # type: ignore return None - def _assign_type_inner(self, next_type: "Type") -> bool: + def _assign_type_inner(self, next_type: "Type") -> bool: # type: ignore # First check that we match next_type class or one of # its bases. next_type_class = next_type.__class__ @@ -377,18 +377,18 @@ def _assign_type_inner(self, next_type: "Type") -> bool: return True @classmethod - def class_to_dict(cls) -> dict[str, typing.Any]: + def class_to_dict(cls) -> dict[str, typing.Any]: # type: ignore d = {"type": cls.name} if cls._base_type is not None: d["_base_type"] = cls._base_type.class_to_dict() return d - def to_dict(self) -> typing.Union[dict, str]: + def to_dict(self) -> typing.Union[dict, str]: # type: ignore d = {"type": self.name} d.update(self._to_dict()) return d - def _to_dict(self) -> dict: + def _to_dict(self) -> dict: # type: ignore fields = dataclasses.fields(self.__class__) type_props = {} if self._base_type is not None: @@ -407,7 +407,7 @@ def _to_dict(self) -> dict: return type_props @classmethod - def from_dict(cls, d): + def from_dict(cls, d): # type: ignore fields = dataclasses.fields(cls) type_attrs = {} for field in fields: @@ -416,12 +416,12 @@ def from_dict(cls, d): type_attrs[field.name] = TypeRegistry.type_from_dict(d[field_name]) return cls(**type_attrs) - def save_instance( + def save_instance( # type: ignore self, obj, artifact, name ) -> typing.Optional[typing.Union[list[str], "artifact_base.ArtifactRef"]]: d = None try: - d = self.instance_to_dict(obj) + d = self.instance_to_dict(obj) # type: ignore[no-untyped-call] except NotImplementedError: pass if d is None: @@ -433,7 +433,7 @@ def save_instance( json.dump(d, f) return None - def load_instance( + def load_instance( # type: ignore self, artifact: "FilesystemArtifact", name: str, @@ -441,26 +441,26 @@ def load_instance( ) -> typing.Any: with artifact.open(f"{name}.object.json") as f: d = json.load(f) - return self.instance_from_dict(d) + return self.instance_from_dict(d) # type: ignore[no-untyped-call] - def instance_to_dict(self, obj): + def instance_to_dict(self, obj): # type: ignore raise NotImplementedError - def instance_from_dict(self, d): + def instance_from_dict(self, d): # type: ignore raise NotImplementedError @classmethod - def make(cls, kwargs={}): + def make(cls, kwargs={}): # type: ignore return cls._make(cls, kwargs) @staticmethod - def _make(cls, kwargs={}): + def _make(cls, kwargs={}): # type: ignore raise Exception("Please import `weave` to use `Type.make`.") - def _inspect(self) -> "weave_inspector.TypeInspector": + def _inspect(self) -> "weave_inspector.TypeInspector": # type: ignore """Only intended to be used by developers to help debug the graph.""" # Circular import, so we do it here. - from .legacy import weave_inspector + from weave.legacy import weave_inspector return weave_inspector.TypeInspector(self) @@ -468,13 +468,13 @@ def _inspect(self) -> "weave_inspector.TypeInspector": # _PlainStringNamedType should only be used for backward compatibility with # legacy WeaveJS code. class _PlainStringNamedType(Type): - def to_dict(self): + def to_dict(self): # type: ignore # A basic type is serialized as just its string name. return self.name class BasicType(_PlainStringNamedType): - def save_instance(self, obj, artifact, name): + def save_instance(self, obj, artifact, name): # type: ignore if artifact is None: raise errors.WeaveSerializeError( "save_instance invalid when artifact is None for type: %s" % self @@ -482,7 +482,7 @@ def save_instance(self, obj, artifact, name): with artifact.new_file(f"{name}.object.json") as f: json.dump(obj, f) - def load_instance(self, artifact, name, extra=None): + def load_instance(self, artifact, name, extra=None): # type: ignore with artifact.open(f"{name}.object.json") as f: return json.load(f) @@ -511,7 +511,7 @@ class UnknownType(BasicType): # # This change would need to be implemented in the core `Type.assign_type` # method - def _assign_type_inner(self, next_type): + def _assign_type_inner(self, next_type): # type: ignore return True @@ -525,10 +525,10 @@ class NoneType(BasicType): # If we're using NoneType in a place where we expect a list, the object_type # of that list is also NoneType, due to nullability. @property - def object_type(self): + def object_type(self): # type: ignore return NoneType() - def save_instance(self, obj, artifact, name): + def save_instance(self, obj, artifact, name): # type: ignore # BoxedNone is actually a box, not a subclass of bool, since # we can't subclass bool in Python. So we unbox it here. if isinstance(obj, box.BoxedNone): @@ -547,7 +547,7 @@ def save_instance(self, obj, artifact, name): class Any(BasicType): name = "any" - def _assign_type_inner(self, next_type): + def _assign_type_inner(self, next_type): # type: ignore return True @@ -557,14 +557,14 @@ class Const(Type): val_type: Type val: typing.Any - def __post_init__(self): + def __post_init__(self): # type: ignore if isinstance(self.val_type, UnionType): # Const Unions are invalid. If something is Const, that means we know what its value # is, which means it is definitely not a Union. Replace val_type with the actual type # here. self.__dict__["val_type"] = TypeRegistry.type_of(self.val) - def _hashable(self): + def _hashable(self): # type: ignore val_id = id(self.val) try: val_id = hash(self.val) @@ -572,19 +572,19 @@ def _hashable(self): pass return (hash(self.val_type), val_id) - def __getattr__(self, attr): + def __getattr__(self, attr): # type: ignore return getattr(self.val_type, attr) @classmethod - def type_of_instance(cls, obj): + def type_of_instance(cls, obj): # type: ignore return cls(TypeRegistry.type_of(obj.val), obj.val) - def _is_assignable_to(self, other_type) -> typing.Optional[bool]: + def _is_assignable_to(self, other_type) -> typing.Optional[bool]: # type: ignore if other_type.__class__ != Const: return other_type.assign_type(self.val_type) return None - def _assign_type_inner(self, next_type): + def _assign_type_inner(self, next_type): # type: ignore if isinstance(next_type, Const): # This does a check on class equality, so won't work for # fancier types. We can fix later if we need to. @@ -601,7 +601,7 @@ def _assign_type_inner(self, next_type): return self.val_type.assign_type(next_type) @classmethod - def from_dict(cls, d): + def from_dict(cls, d): # type: ignore w_type = TypeRegistry.type_from_dict(d["valType"]) val = d["val"] # try: @@ -610,7 +610,7 @@ def from_dict(cls, d): # pass return cls(w_type, val) - def _to_dict(self): + def _to_dict(self): # type: ignore val = self.val # try: # val = self.val_type.instance_to_dict(val) @@ -618,7 +618,7 @@ def _to_dict(self): # pass return {"valType": self.val_type.to_dict(), "val": val} - def __repr__(self): + def __repr__(self): # type: ignore return "Const(%s, %s)" % (self.val_type, self.val) @@ -648,7 +648,7 @@ class Float(Number): instance_classes = float name = "float" - def _assign_type_inner(self, other_type: Type): + def _assign_type_inner(self, other_type: Type): # type: ignore # Float if either side is a number return isinstance(other_type, Number) @@ -658,13 +658,13 @@ class Int(Number): instance_classes = int @classmethod - def is_instance(cls, obj): + def is_instance(cls, obj): # type: ignore # Special case, in Python bool isinstance of obj! if type(obj) == bool: return False return super().is_instance(obj) - def _assign_type_inner(self, other_type: Type): + def _assign_type_inner(self, other_type: Type): # type: ignore # Become Float if rhs is Float return isinstance(other_type, Number) and not isinstance(other_type, Float) @@ -673,7 +673,7 @@ class Boolean(BasicType): instance_classes = [bool, box.BoxedBool] name = "boolean" - def save_instance(self, obj, artifact, name): + def save_instance(self, obj, artifact, name): # type: ignore # BoxedBool is actually a box, not a subclass of bool, since # we can't subclass bool in Python. So we unbox it here. if isinstance(obj, box.BoxedBool): @@ -687,7 +687,7 @@ class LegacyDate(Type): # use "timestamp" but we need to keep this around for backwards compatibility. name = "date" - def save_instance(self, obj, artifact, name): + def save_instance(self, obj, artifact, name): # type: ignore if artifact is None: raise errors.WeaveSerializeError( "save_instance invalid when artifact is None for type: %s" % self @@ -696,7 +696,7 @@ def save_instance(self, obj, artifact, name): v = weave_timestamp.python_datetime_to_ms(obj) json.dump(v, f) - def load_instance(self, artifact, name, extra=None): + def load_instance(self, artifact, name, extra=None): # type: ignore with artifact.open(f"{name}.object.json") as f: v = json.load(f) return weave_timestamp.ms_to_python_datetime(v) @@ -706,7 +706,7 @@ class TimeDelta(Type): name = "timedelta" instance_classes = datetime.timedelta - def save_instance(self, obj: datetime.timedelta, artifact, name): + def save_instance(self, obj: datetime.timedelta, artifact, name): # type: ignore if artifact is None: raise errors.WeaveSerializeError( "save_instance invalid when artifact is None for type: %s" % self @@ -716,7 +716,7 @@ def save_instance(self, obj: datetime.timedelta, artifact, name): v = [obj.days, obj.seconds, obj.microseconds] json.dump(v, f) - def load_instance(self, artifact, name, extra=None): + def load_instance(self, artifact, name, extra=None): # type: ignore with artifact.open(f"{name}.object.json") as f: [days, seconds, microseconds] = json.load(f) return datetime.timedelta(days, seconds, microseconds) @@ -726,11 +726,11 @@ class Timestamp(Type): name = "timestamp" instance_classes = datetime.datetime - def from_isostring(self, iso: str) -> datetime.datetime: + def from_isostring(self, iso: str) -> datetime.datetime: # type: ignore tz_naive = isoparse(iso) return tz_naive.replace(tzinfo=datetime.timezone.utc) - def save_instance(self, obj, artifact, name): + def save_instance(self, obj, artifact, name): # type: ignore if artifact is None: raise errors.WeaveSerializeError( "save_instance invalid when artifact is None for type: %s" % self @@ -739,7 +739,7 @@ def save_instance(self, obj, artifact, name): v = weave_timestamp.python_datetime_to_ms(obj) json.dump(v, f) - def load_instance(self, artifact, name, extra=None): + def load_instance(self, artifact, name, extra=None): # type: ignore with artifact.open(f"{name}.object.json") as f: v = json.load(f) return weave_timestamp.ms_to_python_datetime(v) @@ -751,7 +751,7 @@ class UnionType(Type): members: list[Type] - def __init__(self, *members: Type) -> None: + def __init__(self, *members: Type) -> None: # type: ignore all_members = [] for mem in members: if isinstance(mem, UnionType): @@ -778,17 +778,17 @@ def __init__(self, *members: Type) -> None: # def __repr__(self): # return "UnionType(%s)" % ", ".join(repr(mem) for mem in self.members) - def __eq__(self, other): + def __eq__(self, other): # type: ignore if not isinstance(other, UnionType): return False # Order matters, it affects layout. # return self.members == other.members return set(self.members) == set(other.members) - def _hashable(self): + def _hashable(self): # type: ignore return tuple(hash(mem) for mem in sorted(self.members)) - def is_simple_nullable(self): + def is_simple_nullable(self): # type: ignore return len(set(self.members)) == 2 and none_type in set(self.members) # def instance_to_py(self, obj): @@ -799,15 +799,15 @@ def is_simple_nullable(self): # return member_type.instance_to_py(obj) # raise Exception('invalid') @classmethod - def from_dict(cls, d): + def from_dict(cls, d): # type: ignore return merge_many_types( [TypeRegistry.type_from_dict(mem) for mem in d["members"]] ) - def _to_dict(self): + def _to_dict(self): # type: ignore return {"members": [mem.to_dict() for mem in self.members]} - def __getattr__(self, attr): + def __getattr__(self, attr): # type: ignore has_none = False results = [] for mem in self.members: @@ -852,7 +852,7 @@ class List(Type): object_type: Type = dataclasses.field(default_factory=Any) @classmethod - def type_of_instance(cls, obj): + def type_of_instance(cls, obj): # type: ignore if not obj: return cls(UnknownType()) list_obj_type = TypeRegistry.type_of(obj[0]) @@ -863,18 +863,18 @@ def type_of_instance(cls, obj): list_obj_type = merge_types(list_obj_type, obj_type) return cls(list_obj_type) - def _assign_type_inner(self, next_type): + def _assign_type_inner(self, next_type): # type: ignore if isinstance(next_type, List) and next_type.object_type == UnknownType(): return True return super()._assign_type_inner(next_type) - def save_instance(self, obj, artifact, name): + def save_instance(self, obj, artifact, name): # type: ignore serializer = mappers_python.map_to_python(self, artifact) result = serializer.apply(obj) with artifact.new_file(f"{name}.list.json") as f: json.dump(result, f, allow_nan=False) - def load_instance(self, artifact, name, extra=None): + def load_instance(self, artifact, name, extra=None): # type: ignore with artifact.open(f"{name}.list.json") as f: result = json.load(f) mapper = mappers_python.map_from_python(self, artifact) @@ -898,16 +898,16 @@ class TypedDict(Type): # in Typescript this is like key?: value not_required_keys: set[str] = dataclasses.field(default_factory=set) - def _hashable(self): + def _hashable(self): # type: ignore return tuple( (k, hash(v), k in self.not_required_keys) for k, v in self.property_types.items() ) - def __getitem__(self, key: str) -> Type: + def __getitem__(self, key: str) -> Type: # type: ignore return self.property_types[key] - def _assign_type_inner(self, other_type): + def _assign_type_inner(self, other_type): # type: ignore if isinstance(other_type, Dict): for ptype in self.property_types.values(): if not ptype.assign_type(other_type.object_type): @@ -926,7 +926,7 @@ def _assign_type_inner(self, other_type): return False return True - def _to_dict(self): + def _to_dict(self): # type: ignore property_types = {} for key, type_ in self.property_types.items(): property_types[key] = type_.to_dict() @@ -936,7 +936,7 @@ def _to_dict(self): return result @classmethod - def from_dict(cls, d): + def from_dict(cls, d): # type: ignore property_types = {} for key, type_ in d["propertyTypes"].items(): property_types[key] = TypeRegistry.type_from_dict(type_) @@ -946,19 +946,19 @@ def from_dict(cls, d): return cls(property_types, not_required_keys) @classmethod - def type_of_instance(cls, obj): + def type_of_instance(cls, obj): # type: ignore property_types = {} for k, v in obj.items(): property_types[k] = TypeRegistry.type_of(v) return cls(property_types) - def save_instance(self, obj, artifact, name): + def save_instance(self, obj, artifact, name): # type: ignore serializer = mappers_python.map_to_python(self, artifact) result = serializer.apply(obj) with artifact.new_file(f"{name}.typedDict.json") as f: json.dump(result, f, allow_nan=False) - def load_instance(self, artifact, name, extra=None): + def load_instance(self, artifact, name, extra=None): # type: ignore # with artifact.open(f'{name}.type.json') as f: # obj_type = TypeRegistry.type_from_dict(json.load(f)) with artifact.open(f"{name}.typedDict.json") as f: @@ -976,27 +976,27 @@ class Dict(Type): object_type: Type = Any() @property - def property_types(self): + def property_types(self): # type: ignore class DictPropertyTypes: - def values(_self): + def values(_self): # type: ignore return [self.object_type] - def get(_self, _): + def get(_self, _): # type: ignore return self.object_type - def __getitem__(_self, _): + def __getitem__(_self, _): # type: ignore return self.object_type return DictPropertyTypes() - def __post_init__(self): + def __post_init__(self): # type: ignore # Note this differs from Python's Dict in that keys are always strings! # TODO: consider if we can / should accept key_type. Would make JS side # harder since js objects can only have string keys. if not String().assign_type(self.key_type): raise Exception("Dict only supports string keys!") - def _assign_type_inner(self, other_type): + def _assign_type_inner(self, other_type): # type: ignore if isinstance(other_type, TypedDict): return all( self.object_type.assign_type(t) @@ -1005,7 +1005,7 @@ def _assign_type_inner(self, other_type): return super()._assign_type_inner(other_type) @classmethod - def type_of_instance(cls, obj): + def type_of_instance(cls, obj): # type: ignore value_type = UnknownType() for k, v in obj.items(): if not isinstance(k, str): @@ -1032,7 +1032,7 @@ class ObjectType(Type): # base. All interactions with types go through methods here, so # fixups can be contained. - def __init__(self, **attr_types: Type): + def __init__(self, **attr_types: Type): # type: ignore fixed_attr_types = {} for k, v in attr_types.items(): if k == "name": @@ -1044,7 +1044,7 @@ def __init__(self, **attr_types: Type): self.__dict__[k] = v @property - def type_vars(self): + def type_vars(self): # type: ignore if hasattr(self, "attr_types"): tv = self.attr_types else: @@ -1056,12 +1056,12 @@ def type_vars(self): result[k] = v return result - def property_types(self) -> dict[str, Type]: + def property_types(self) -> dict[str, Type]: # type: ignore return self.type_vars @classmethod - def typeclass_of_class(cls, check_class): - from .legacy import weave_pydantic + def typeclass_of_class(cls, check_class): # type: ignore + from weave.legacy import weave_pydantic if not issubclass(check_class, pydantic.BaseModel): return cls @@ -1097,7 +1097,7 @@ def typeclass_of_class(cls, check_class): return dataclasses.dataclass(frozen=True)(new_cls) @classmethod - def type_of_instance(cls, obj): + def type_of_instance(cls, obj): # type: ignore if isinstance(obj, pydantic.BaseModel): type_class = cls.typeclass_of_class(obj.__class__) attr_types = {} @@ -1118,7 +1118,7 @@ def type_of_instance(cls, obj): variable_prop_types[prop_name] = prop_type return cls(**variable_prop_types) - def _to_dict(self) -> dict: + def _to_dict(self) -> dict: # type: ignore d = self.class_to_dict() if self._relocatable: @@ -1131,7 +1131,7 @@ def _to_dict(self) -> dict: d[to_weavejs_typekey(k)] = prop_type.to_dict() return d - def save_instance(self, obj, artifact, name): + def save_instance(self, obj, artifact, name): # type: ignore serializer = mappers_python.map_to_python(self, artifact) result = serializer.apply(obj) @@ -1140,20 +1140,20 @@ def save_instance(self, obj, artifact, name): with artifact.new_file(f"{name}.object.json") as f: json.dump(result, f, allow_nan=False) - def load_instance(self, artifact, name, extra=None): + def load_instance(self, artifact, name, extra=None): # type: ignore with artifact.open(f"{name}.object.json") as f: result = json.load(f) mapper = mappers_python.map_from_python(self, artifact) return mapper.apply(result) - def __eq__(self, other) -> bool: + def __eq__(self, other) -> bool: # type: ignore return ( type(self) == type(other) and self.property_types() == other.property_types() ) -def is_serialized_object_type(t: dict) -> bool: +def is_serialized_object_type(t: dict) -> bool: # type: ignore if "_base_type" not in t: return False if t["_base_type"]["type"] == "Object": @@ -1161,7 +1161,7 @@ def is_serialized_object_type(t: dict) -> bool: return is_serialized_object_type(t["_base_type"]) -def is_relocatable_object_type(t: typing.Union[str, dict]) -> bool: +def is_relocatable_object_type(t: typing.Union[str, dict]) -> bool: # type: ignore if not isinstance(t, dict): return False if not t.get("_relocatable"): @@ -1178,7 +1178,7 @@ def is_relocatable_object_type(t: typing.Union[str, dict]) -> bool: DESERIALIZED_OBJECT_TYPE_CLASSES: dict[str, type[ObjectType]] = {} -def validate_kwarg_name(name: str) -> bool: +def validate_kwarg_name(name: str) -> bool: # type: ignore """Return True if name is a valid python kwarg name""" if name in keyword.kwlist: raise ValueError( @@ -1191,7 +1191,7 @@ def validate_kwarg_name(name: str) -> bool: return True -def deserialize_relocatable_object_type(t: dict) -> ObjectType: +def deserialize_relocatable_object_type(t: dict) -> ObjectType: # type: ignore key = json.dumps(t) if key in DESERIALIZED_OBJECT_TYPE_CLASSES: return DESERIALIZED_OBJECT_TYPE_CLASSES[key]() @@ -1270,22 +1270,22 @@ class TypeType(ObjectType): instance_classes = [Type] attr_types: dict[str, Type] = dataclasses.field(default_factory=dict) - def property_types(self) -> dict[str, Type]: + def property_types(self) -> dict[str, Type]: # type: ignore return self.attr_types - def _hashable(self): + def _hashable(self): # type: ignore return tuple((k, hash(v)) for k, v in self.property_types().items()) @classmethod - def type_of_instance(cls, obj): - from .legacy import infer_types + def type_of_instance(cls, obj): # type: ignore + from weave.legacy import infer_types attr_types = {} for field in dataclasses.fields(obj): attr_types[field.name] = infer_types.python_type_to_type(field.type) return cls(attr_types) - def _to_dict(self): + def _to_dict(self): # type: ignore # we ensure we match the layout of ObjectType, so WeaveJS # can handle it the same way. d = {"_is_object": True} @@ -1294,7 +1294,7 @@ def _to_dict(self): return d @classmethod - def from_dict(cls, d): + def from_dict(cls, d): # type: ignore # weavejs fix: weavejs uses the plain string 'type' for now. if d == "type": return cls() @@ -1314,18 +1314,18 @@ class Function(Type): input_types: dict[str, Type] = dataclasses.field(default_factory=dict) output_type: Type = dataclasses.field(default_factory=lambda: UnknownType()) - def _hashable(self): + def _hashable(self): # type: ignore return ( tuple((k, hash(v)) for k, v in self.input_types.items()), hash(self.output_type), ) - def _is_assignable_to(self, other_type) -> typing.Optional[bool]: + def _is_assignable_to(self, other_type) -> typing.Optional[bool]: # type: ignore if other_type.__class__ != Function: return other_type.assign_type(self.output_type) return None - def assign_type(self, next_type: Type) -> bool: + def assign_type(self, next_type: Type) -> bool: # type: ignore if not self.input_types and not isinstance(next_type, Function): # Allow assignment of T to () -> T. # Compile handles this in the compile_quote pass. @@ -1333,7 +1333,7 @@ def assign_type(self, next_type: Type) -> bool: return super().assign_type(next_type) @classmethod - def type_of_instance(cls, obj): + def type_of_instance(cls, obj): # type: ignore if isinstance(obj.type, Function): # Its already a Function type, so just return it. # TODO: I'm not sure if this is right, this makes FunctionType @@ -1343,22 +1343,22 @@ def type_of_instance(cls, obj): return cls({}, obj.type) @classmethod - def from_dict(cls, json): + def from_dict(cls, json): # type: ignore input_types = { pname: TypeRegistry.type_from_dict(ptype) for (pname, ptype) in json["inputTypes"].items() } return cls(input_types, TypeRegistry.type_from_dict(json["outputType"])) - def _to_dict(self): + def _to_dict(self): # type: ignore input_types = {k: v.to_dict() for (k, v) in self.input_types.items()} return {"inputTypes": input_types, "outputType": self.output_type.to_dict()} - def save_instance(self, obj, artifact, name): + def save_instance(self, obj, artifact, name): # type: ignore with artifact.new_file(f"{name}.object.json") as f: json.dump(obj.to_json(), f) - def load_instance(self, artifact, name, extra=None): + def load_instance(self, artifact, name, extra=None): # type: ignore with artifact.open(f"{name}.object.json") as f: # TODO: no circular imports! from weave.legacy import graph @@ -1371,10 +1371,10 @@ class RefType(Type): object_type: Type = Any() @classmethod - def type_of_instance(cls, obj): + def type_of_instance(cls, obj): # type: ignore return cls(obj.type) - def _is_assignable_to(self, other_type) -> typing.Optional[bool]: + def _is_assignable_to(self, other_type) -> typing.Optional[bool]: # type: ignore # Use issubclass, we have RunLocalType defined as a subclass of RunType if not issubclass(other_type.__class__, RefType): if self.object_type == NoneType(): @@ -1384,7 +1384,7 @@ def _is_assignable_to(self, other_type) -> typing.Optional[bool]: return other_type.assign_type(self.object_type) return None - def save_instance(self, obj, artifact, name): + def save_instance(self, obj, artifact, name): # type: ignore from weave.legacy import ref_base obj_ref = ref_base.get_ref(obj) @@ -1418,7 +1418,7 @@ class LocalArtifactRefType(FilesystemArtifactRefType): @dataclasses.dataclass(frozen=True) class WandbArtifactRefType(FilesystemArtifactRefType): - def load_instance(self, artifact, name, extra=None): + def load_instance(self, artifact, name, extra=None): # type: ignore from weave.legacy import artifact_wandb return artifact_wandb.WandbArtifactRef(artifact, name) @@ -1428,7 +1428,7 @@ class WBTable(Type): name = "wbtable" -def is_json_compatible(type_): +def is_json_compatible(type_): # type: ignore if isinstance(type_, List): return is_json_compatible(type_.object_type) elif isinstance(type_, Dict): @@ -1498,15 +1498,15 @@ def non_none(type_: Type) -> Type: return type_ -def string_enum_type(*vals): +def string_enum_type(*vals): # type: ignore return UnionType(*[Const(String(), v) for v in vals]) -def literal(val: typing.Any) -> Const: +def literal(val: typing.Any) -> Const: # type: ignore return Const(TypeRegistry.type_of(val), val) -RUN_STATE_TYPE = string_enum_type("pending", "running", "finished", "failed") +RUN_STATE_TYPE = string_enum_type("pending", "running", "finished", "failed") # type: ignore[no-untyped-call] # TODO: get rid of all the underscores. This is another @@ -1518,7 +1518,7 @@ class RunType(ObjectType): history: Type = List(TypedDict({})) output: Type = Any() - def property_types(self): + def property_types(self): # type: ignore return { "id": String(), "op_name": String(), @@ -1529,7 +1529,7 @@ def property_types(self): "output": self.output, } - def _is_assignable_to(self, other_type) -> typing.Optional[bool]: + def _is_assignable_to(self, other_type) -> typing.Optional[bool]: # type: ignore # Use issubclass, we have RunLocalType defined as a subclass of RunType if not issubclass(other_type.__class__, RunType): if self.output == NoneType(): @@ -1601,9 +1601,9 @@ def merge_types(a: Type, b: Type) -> Type: next_prop_types[key] = merge_types(self_prop_type, other_prop_type) return TypedDict(next_prop_types) if isinstance(a, ObjectType) and isinstance(b, ObjectType): - if a.name == b.name and not set(a.type_attrs()).difference(b.type_attrs()): + if a.name == b.name and not set(a.type_attrs()).difference(b.type_attrs()): # type: ignore[no-untyped-call] next_type_attrs = {} - for key in a.type_attrs(): + for key in a.type_attrs(): # type: ignore[no-untyped-call] next_type_attrs[key] = merge_types(getattr(a, key), getattr(b, key)) return type(a)(**next_type_attrs) @@ -1737,7 +1737,7 @@ def _unknown_coalesce_on_union(u_type: UnionType) -> Type: return union(*final_types) -def _merge_unknowns_of_type_with_types(of_type: Type, with_types: list[Type]): +def _merge_unknowns_of_type_with_types(of_type: Type, with_types: list[Type]): # type: ignore # At this stage, we have a starting type and a list of peer candidate types. # These types have already been coalesced individually. This step is similar to # the outer `unknown_coalesce` function, except that rather than operating on the diff --git a/weave/legacy/weavejs_fixes.py b/weave/legacy/weavejs_fixes.py index d7d94c399f0..23c97ee64c7 100644 --- a/weave/legacy/weavejs_fixes.py +++ b/weave/legacy/weavejs_fixes.py @@ -10,7 +10,7 @@ from weave.legacy import graph -from .. import weave_types +from weave.legacy import weave_types def _convert_specific_opname_to_generic_opname( diff --git a/weave/legacy/weavify.py b/weave/legacy/weavify.py index 651cdc52b9d..6714d6676f8 100644 --- a/weave/legacy/weavify.py +++ b/weave/legacy/weavify.py @@ -3,7 +3,7 @@ from weave.legacy import errors, graph, op_args, val_const from .. import weave_internal -from .. import weave_types as types +from weave.legacy import weave_types as types if typing.TYPE_CHECKING: from weave.legacy import op_def diff --git a/weave/tests/legacy/test_arrow.py b/weave/tests/legacy/test_arrow.py index 87058e0e6ae..889835c9588 100644 --- a/weave/tests/legacy/test_arrow.py +++ b/weave/tests/legacy/test_arrow.py @@ -12,6 +12,7 @@ # If you're thinking of import vectorize here, don't! Put your # tests in test_arrow_vectorizer.py instead from weave.legacy import ops_arrow as arrow +from weave.legacy import weave_types as types from weave.legacy.arrow import constructors from weave.legacy.arrow.arrow_tags import ( recursively_encode_pyarrow_strings_as_dictionaries, @@ -28,7 +29,6 @@ from ... import api as weave from ... import storage, weave_internal -from ... import weave_types as types from ...tests import tag_test_util as ttu from ...tests import weavejs_ops from ...tests.legacy import test_wb diff --git a/weave/tests/legacy/test_arrow_awl.py b/weave/tests/legacy/test_arrow_awl.py index 974de06afc7..c1949a9cb97 100644 --- a/weave/tests/legacy/test_arrow_awl.py +++ b/weave/tests/legacy/test_arrow_awl.py @@ -3,7 +3,7 @@ import pytest import weave -import weave.weave_types as types +import weave.legacy.weave_types as types from weave.legacy import box, ops_arrow from weave.legacy.arrow.convert import to_arrow from weave.legacy.language_features.tagging import tag_store, tagged_value_type diff --git a/weave/tests/legacy/test_arrow_vectorizer.py b/weave/tests/legacy/test_arrow_vectorizer.py index b5e38bf8286..04e1b0f9862 100644 --- a/weave/tests/legacy/test_arrow_vectorizer.py +++ b/weave/tests/legacy/test_arrow_vectorizer.py @@ -7,6 +7,7 @@ from weave.legacy import box, dispatch, errors, ops from weave.legacy import ops_arrow as arrow +from weave.legacy import weave_types as types from weave.legacy.language_features.tagging import ( make_tag_getter_op, tag_store, @@ -19,7 +20,6 @@ from ... import api as weave from ... import weave_internal -from ... import weave_types as types string_ops_test_cases = [ ("eq-scalar", lambda x: x == "bc", [True, False, False]), diff --git a/weave/tests/legacy/test_compile.py b/weave/tests/legacy/test_compile.py index c2ab8544bf7..ef0ec1014bd 100644 --- a/weave/tests/legacy/test_compile.py +++ b/weave/tests/legacy/test_compile.py @@ -3,13 +3,13 @@ import weave from weave.legacy import async_demo, compile, graph +from weave.legacy import weave_types as types from weave.legacy.dispatch import RuntimeOutputNode from weave.legacy.ops_arrow import to_arrow from weave.legacy.ops_arrow.vectorize import raise_on_python_bailout from weave.legacy.wandb_interface.wandb_stream_table import StreamTable from weave.weave_internal import const, define_fn, make_const_node -from ... import weave_types as types from ...api import use diff --git a/weave/tests/legacy/test_decorators.py b/weave/tests/legacy/test_decorators.py index 1690899112b..e47c79db7a9 100644 --- a/weave/tests/legacy/test_decorators.py +++ b/weave/tests/legacy/test_decorators.py @@ -1,8 +1,8 @@ +from weave.legacy import weave_types as types from weave.legacy.decorator_op import op from ... import api as weave from ... import storage -from ... import weave_types as types def test_function_op_name(): diff --git a/weave/tests/legacy/test_execute.py b/weave/tests/legacy/test_execute.py index fc8cd413332..29a8a93191f 100644 --- a/weave/tests/legacy/test_execute.py +++ b/weave/tests/legacy/test_execute.py @@ -5,9 +5,9 @@ import weave from weave.legacy import environment, execute, ops +from weave.legacy import weave_types as types from ... import api, weave_internal -from ... import weave_types as types from . import test_wb execute_test_count_op_run_count = 0 diff --git a/weave/tests/legacy/test_execute_fast.py b/weave/tests/legacy/test_execute_fast.py index c196dac3a86..716651dd943 100644 --- a/weave/tests/legacy/test_execute_fast.py +++ b/weave/tests/legacy/test_execute_fast.py @@ -1,8 +1,8 @@ import weave from weave.legacy import dispatch +from weave.legacy import weave_types as types from ... import weave_internal -from ... import weave_types as types from .. import weavejs_ops diff --git a/weave/tests/legacy/test_gql_to_weave.py b/weave/tests/legacy/test_gql_to_weave.py index 088cfda7a19..e3dc869d9bf 100644 --- a/weave/tests/legacy/test_gql_to_weave.py +++ b/weave/tests/legacy/test_gql_to_weave.py @@ -1,5 +1,5 @@ -from weave import weave_types as types from weave.legacy import gql_to_weave +from weave.legacy import weave_types as types def test_simple_query(): diff --git a/weave/tests/legacy/test_graph.py b/weave/tests/legacy/test_graph.py index 0f09e1338a6..70051c60a17 100644 --- a/weave/tests/legacy/test_graph.py +++ b/weave/tests/legacy/test_graph.py @@ -1,8 +1,8 @@ import weave from weave.legacy import graph +from weave.legacy import weave_types as types from ... import weave_internal -from ... import weave_types as types def test_map_dag_produces_same_len(): diff --git a/weave/tests/legacy/test_infer_types.py b/weave/tests/legacy/test_infer_types.py index 5ddaf587ed1..137af307186 100644 --- a/weave/tests/legacy/test_infer_types.py +++ b/weave/tests/legacy/test_infer_types.py @@ -1,9 +1,6 @@ import typing -from weave.legacy import graph - -from ... import weave_types -from ...legacy import infer_types +from weave.legacy import graph, infer_types, weave_types def test_node_with_generic(): diff --git a/weave/tests/legacy/test_js_compat.py b/weave/tests/legacy/test_js_compat.py index 87a7adb648c..ba37ee1f65e 100644 --- a/weave/tests/legacy/test_js_compat.py +++ b/weave/tests/legacy/test_js_compat.py @@ -7,8 +7,8 @@ # Note: This file is not yet complete, there are existing fixups in the # weave Python code that I haven't documented here. -from weave import weave_types as types from weave.legacy import partial_object, weavejs_fixes +from weave.legacy import weave_types as types from weave.legacy.ops_domain import wb_domain_types diff --git a/weave/tests/legacy/test_list_arrow_compat.py b/weave/tests/legacy/test_list_arrow_compat.py index 46eb15f38fd..a38a409ae23 100644 --- a/weave/tests/legacy/test_list_arrow_compat.py +++ b/weave/tests/legacy/test_list_arrow_compat.py @@ -4,9 +4,9 @@ import pytest from weave import weave_internal -from weave import weave_types as types from weave.legacy import box, ops from weave.legacy import ops_arrow as arrow +from weave.legacy import weave_types as types from weave.legacy.language_features.tagging import ( make_tag_getter_op, tag_store, diff --git a/weave/tests/legacy/test_mappability.py b/weave/tests/legacy/test_mappability.py index 18822a65478..e7bbcfb79ca 100644 --- a/weave/tests/legacy/test_mappability.py +++ b/weave/tests/legacy/test_mappability.py @@ -1,8 +1,8 @@ import weave from weave.legacy import context_state as _context from weave.legacy import graph +from weave.legacy import weave_types as types -from ... import weave_types as types from ...legacy import registry_mem from ...weave_internal import make_const_node diff --git a/weave/tests/legacy/test_mappers_arrow.py b/weave/tests/legacy/test_mappers_arrow.py index cc2d9f9b258..ff380abdf19 100644 --- a/weave/tests/legacy/test_mappers_arrow.py +++ b/weave/tests/legacy/test_mappers_arrow.py @@ -2,8 +2,8 @@ import pyarrow as pa -from weave import weave_types as types from weave.legacy import mappers_arrow +from weave.legacy import weave_types as types def test_map_list(): diff --git a/weave/tests/legacy/test_mappers_python.py b/weave/tests/legacy/test_mappers_python.py index f614a147716..192fdefb041 100644 --- a/weave/tests/legacy/test_mappers_python.py +++ b/weave/tests/legacy/test_mappers_python.py @@ -1,8 +1,8 @@ import math from weave import weave_internal -from weave import weave_types as types from weave.legacy import api, context, mappers_python, val_const +from weave.legacy import weave_types as types def test_map_typed_dict(): diff --git a/weave/tests/legacy/test_media.py b/weave/tests/legacy/test_media.py index ef35626c307..175f4ad38cf 100644 --- a/weave/tests/legacy/test_media.py +++ b/weave/tests/legacy/test_media.py @@ -3,8 +3,9 @@ import numpy as np import pytest +from weave.legacy import weave_types as types + from ... import storage -from ... import weave_types as types def test_nparray(): diff --git a/weave/tests/legacy/test_numpy.py b/weave/tests/legacy/test_numpy.py index 3ac8858e42c..99275de1e7d 100644 --- a/weave/tests/legacy/test_numpy.py +++ b/weave/tests/legacy/test_numpy.py @@ -1,9 +1,9 @@ import numpy as np from weave.legacy import artifact_fs, artifact_wandb +from weave.legacy import weave_types as types from weave.legacy.ops_domain import table -from ... import weave_types as types from ...legacy import types_numpy as numpy_types diff --git a/weave/tests/legacy/test_partial_object.py b/weave/tests/legacy/test_partial_object.py index 20ed18e55b1..8096e6061b5 100644 --- a/weave/tests/legacy/test_partial_object.py +++ b/weave/tests/legacy/test_partial_object.py @@ -1,11 +1,11 @@ from weave.legacy import compile, ops +from weave.legacy import weave_types as types from weave.legacy.language_features.tagging.tagged_value_type import TaggedValueType from weave.legacy.ops_domain import wb_domain_types as wdt from weave.legacy.ops_domain.project_ops import root_all_projects from weave.legacy.ops_domain.report_ops import root_all_reports from ... import api as weave -from ... import weave_types as types from .test_wb import table_mock1_no_display_name diff --git a/weave/tests/legacy/test_plot.py b/weave/tests/legacy/test_plot.py index 768667e3bd2..7f0658d2529 100644 --- a/weave/tests/legacy/test_plot.py +++ b/weave/tests/legacy/test_plot.py @@ -4,8 +4,8 @@ import pytest import weave -from weave import weave_types as types from weave.legacy import graph +from weave.legacy import weave_types as types from weave.legacy.panels.panel_plot import Plot, PlotConstants, Series from ... import storage diff --git a/weave/tests/legacy/test_pydantic.py b/weave/tests/legacy/test_pydantic.py index d29a016ff01..1a57eda18cb 100644 --- a/weave/tests/legacy/test_pydantic.py +++ b/weave/tests/legacy/test_pydantic.py @@ -3,7 +3,7 @@ import pydantic import weave -from weave import weave_types as types +from weave.legacy import weave_types as types def test_pydantic_type_inference(): diff --git a/weave/tests/legacy/test_ref_tracking.py b/weave/tests/legacy/test_ref_tracking.py index efd5d5a4895..47d8ca60408 100644 --- a/weave/tests/legacy/test_ref_tracking.py +++ b/weave/tests/legacy/test_ref_tracking.py @@ -1,6 +1,6 @@ import weave -from weave import weave_types as types from weave.legacy import storage +from weave.legacy import weave_types as types def test_reffed_type(ref_tracking): diff --git a/weave/tests/legacy/test_run_segment.py b/weave/tests/legacy/test_run_segment.py index 3e78e3614ff..eb0f36f81c6 100644 --- a/weave/tests/legacy/test_run_segment.py +++ b/weave/tests/legacy/test_run_segment.py @@ -7,11 +7,11 @@ import weave from weave.legacy import ops +from weave.legacy import weave_types as types from weave.legacy.ops_arrow import ArrowWeaveList, arrow_as_array from weave.legacy.ops_domain.run_segment import RunSegment from ... import api, storage, weave_internal -from ... import weave_types as types N_NUMERIC_METRICS = 99 # number of numerical columns in the metrics table diff --git a/weave/tests/legacy/test_serialize.py b/weave/tests/legacy/test_serialize.py index 7d86ec3b176..030ddb13465 100644 --- a/weave/tests/legacy/test_serialize.py +++ b/weave/tests/legacy/test_serialize.py @@ -2,9 +2,9 @@ import weave from weave import weave_internal -from weave import weave_types as types from weave.legacy import api as api from weave.legacy import graph, op_args, ops, registry_mem, serialize +from weave.legacy import weave_types as types from weave.legacy.ops_primitives import list_ from weave.weave_internal import make_const_node diff --git a/weave/tests/legacy/test_storage.py b/weave/tests/legacy/test_storage.py index 3821f662a26..4c31c43f9b7 100644 --- a/weave/tests/legacy/test_storage.py +++ b/weave/tests/legacy/test_storage.py @@ -8,11 +8,11 @@ import wandb from weave.legacy import artifact_mem, artifact_wandb, mappers_python, ops_arrow +from weave.legacy import weave_types as types from weave.legacy.arrow import list_ as arrow from ... import api as weave from ... import storage -from ... import weave_types as types from ...legacy.weavejs_fixes import recursively_unwrap_unions from ...weave_internal import make_const_node from . import test_helpers diff --git a/weave/tests/legacy/test_table_ops.py b/weave/tests/legacy/test_table_ops.py index 10af48c5289..9296cb2e235 100644 --- a/weave/tests/legacy/test_table_ops.py +++ b/weave/tests/legacy/test_table_ops.py @@ -4,11 +4,11 @@ import pytest from weave.legacy import box, context, context_state, graph, ops +from weave.legacy import weave_types as types from weave.legacy.ops_domain import table as table_ops from ... import api as weave from ... import storage, weave_internal -from ... import weave_types as types from .. import weavejs_ops TABLE_TYPES = ["list", "pandas", "sql"] diff --git a/weave/tests/legacy/test_tagging.py b/weave/tests/legacy/test_tagging.py index 96bf56ba747..fa691cdd77a 100644 --- a/weave/tests/legacy/test_tagging.py +++ b/weave/tests/legacy/test_tagging.py @@ -2,6 +2,7 @@ import weave from weave.legacy import box +from weave.legacy import weave_types as types from weave.legacy.artifact_fs import FilesystemArtifactFileType from weave.legacy.language_features.tagging import ( make_tag_getter_op, @@ -15,7 +16,6 @@ from weave.legacy.ops_primitives import list_ as list_ops from ... import weave_internal -from ... import weave_types as types def test_tagged_value(): diff --git a/weave/tests/legacy/test_typeddict_notrequired.py b/weave/tests/legacy/test_typeddict_notrequired.py index b58c53964f4..0625b430aad 100644 --- a/weave/tests/legacy/test_typeddict_notrequired.py +++ b/weave/tests/legacy/test_typeddict_notrequired.py @@ -6,8 +6,8 @@ TypedDict, ) -from weave import weave_types as types from weave.legacy import infer_types +from weave.legacy import weave_types as types class _TestNotRequiredTypedDict(TypedDict): diff --git a/weave/tests/legacy/test_wb.py b/weave/tests/legacy/test_wb.py index 9ac6a28f801..065e4b0dc09 100644 --- a/weave/tests/legacy/test_wb.py +++ b/weave/tests/legacy/test_wb.py @@ -6,10 +6,10 @@ import pytest import wandb -from weave import weave_types as types from weave.legacy import api as weave from weave.legacy import artifact_fs, artifact_wandb, compile, graph, ops, stitch, uris from weave.legacy import ops_arrow as arrow +from weave.legacy import weave_types as types from weave.legacy.language_features.tagging.tagged_value_type import TaggedValueType from weave.legacy.ops_arrow import ArrowWeaveListType from weave.legacy.ops_domain import artifact_membership_ops as amo diff --git a/weave/tests/legacy/test_wb_data_types.py b/weave/tests/legacy/test_wb_data_types.py index 5e3ac21c54c..7f4c7fd66f1 100644 --- a/weave/tests/legacy/test_wb_data_types.py +++ b/weave/tests/legacy/test_wb_data_types.py @@ -12,8 +12,8 @@ from wandb.sdk.data_types._dtypes import TypeRegistry as SDKTypeRegistry import weave -from weave import weave_types as types from weave.legacy import artifact_fs +from weave.legacy import weave_types as types from weave.legacy.artifact_wandb import WandbArtifact, WeaveWBArtifactURI from weave.legacy.language_features.tagging.tagged_value_type import TaggedValueType from weave.legacy.ops_domain.wbmedia import ImageArtifactFileRefType diff --git a/weave/tests/legacy/test_wb_domain_types.py b/weave/tests/legacy/test_wb_domain_types.py index d41f3ea469a..e2a131a57f2 100644 --- a/weave/tests/legacy/test_wb_domain_types.py +++ b/weave/tests/legacy/test_wb_domain_types.py @@ -1,8 +1,8 @@ +from weave.legacy import weave_types as types from weave.legacy.ops_domain import wb_domain_types as wdt from ... import api as weave from ... import storage -from ... import weave_types as types def test_with_keys_assignability(): diff --git a/weave/tests/legacy/test_wb_stream_table.py b/weave/tests/legacy/test_wb_stream_table.py index 47cda086956..68301ad4dde 100644 --- a/weave/tests/legacy/test_wb_stream_table.py +++ b/weave/tests/legacy/test_wb_stream_table.py @@ -5,8 +5,7 @@ from PIL import Image import weave -from weave import weave_types -from weave.legacy import context, execute, gql_json_cache, wandb_api +from weave.legacy import context, execute, gql_json_cache, wandb_api, weave_types from weave.legacy.wandb_interface.wandb_stream_table import StreamTable diff --git a/weave/tests/legacy/test_weave_types.py b/weave/tests/legacy/test_weave_types.py index f19c8097114..1c88c49d14f 100644 --- a/weave/tests/legacy/test_weave_types.py +++ b/weave/tests/legacy/test_weave_types.py @@ -4,13 +4,13 @@ import weave import weave.legacy -import weave.weave_types +import weave.legacy.weave_types from weave.legacy import _dict_utils, runs +from weave.legacy import weave_types as types from weave.legacy.language_features.tagging.tagged_value_type import TaggedValueType from weave.legacy.ops_domain import wbmedia from ... import errors -from ... import weave_types as types def test_typeof_string(): @@ -155,23 +155,23 @@ def test_typeof_list_dict_merge(): def test_typeof_nested_dict_merge(): """Tests that nested merging is disabled.""" - t1 = weave.weave_types.TypedDict( - {"a": weave.weave_types.TypedDict({"b": types.Int()})} + t1 = weave.legacy.weave_types.TypedDict( + {"a": weave.legacy.weave_types.TypedDict({"b": types.Int()})} ) - t2 = weave.weave_types.TypedDict( - {"a": weave.weave_types.TypedDict({"c": types.String()})} + t2 = weave.legacy.weave_types.TypedDict( + {"a": weave.legacy.weave_types.TypedDict({"c": types.String()})} ) merged_type = _dict_utils.typeddict_merge_output_type({"self": t1, "other": t2}) - assert merged_type == weave.weave_types.TypedDict( - {"a": weave.weave_types.TypedDict({"c": types.String()})} + assert merged_type == weave.legacy.weave_types.TypedDict( + {"a": weave.legacy.weave_types.TypedDict({"c": types.String()})} ) def test_dict_without_key_type(): - fully_typed = weave.weave_types.TypeRegistry.type_from_dict( + fully_typed = weave.legacy.weave_types.TypeRegistry.type_from_dict( {"type": "dict", "keyType": "string", "objectType": "number"} ) - partial_typed = weave.weave_types.TypeRegistry.type_from_dict( + partial_typed = weave.legacy.weave_types.TypeRegistry.type_from_dict( {"type": "dict", "objectType": "number"} ) assert fully_typed.assign_type(partial_typed) @@ -179,24 +179,24 @@ def test_dict_without_key_type(): # def test_union_unknown(): # assert ( -# weave.weave_types.union( -# weave.weave_types.String(), weave.weave_types.UnknownType() +# weave.legacy.weave_types.union( +# weave.legacy.weave_types.String(), weave.legacy.weave_types.UnknownType() # ) -# == weave.weave_types.String() +# == weave.legacy.weave_types.String() # ) # assert ( -# weave.weave_types.union( -# weave.weave_types.UnknownType(), weave.weave_types.UnknownType() +# weave.legacy.weave_types.union( +# weave.legacy.weave_types.UnknownType(), weave.legacy.weave_types.UnknownType() # ) -# == weave.weave_types.UnknownType() +# == weave.legacy.weave_types.UnknownType() # ) # assert ( -# weave.weave_types.union( -# weave.weave_types.UnknownType(), -# weave.weave_types.UnknownType(), +# weave.legacy.weave_types.union( +# weave.legacy.weave_types.UnknownType(), +# weave.legacy.weave_types.UnknownType(), # weave.types.String(), # ) -# == weave.weave_types.String() +# == weave.legacy.weave_types.String() # ) @@ -204,76 +204,78 @@ def test_union_access(): ### Type return # Not all members have props - unioned = weave.weave_types.union( - weave.weave_types.String(), weave.weave_types.List(weave.weave_types.String()) + unioned = weave.legacy.weave_types.union( + weave.legacy.weave_types.String(), + weave.legacy.weave_types.List(weave.legacy.weave_types.String()), ) with pytest.raises(AttributeError): unioned.object_type # Combined dicts - unioned = weave.weave_types.union( - weave.weave_types.List(weave.weave_types.String()), - weave.weave_types.List(weave.weave_types.Number()), + unioned = weave.legacy.weave_types.union( + weave.legacy.weave_types.List(weave.legacy.weave_types.String()), + weave.legacy.weave_types.List(weave.legacy.weave_types.Number()), ) - assert unioned.object_type == weave.weave_types.union( - weave.weave_types.String(), weave.weave_types.Number() + assert unioned.object_type == weave.legacy.weave_types.union( + weave.legacy.weave_types.String(), weave.legacy.weave_types.Number() ) # Nullable type - unioned = weave.weave_types.union( - weave.weave_types.NoneType(), weave.weave_types.List(weave.weave_types.String()) + unioned = weave.legacy.weave_types.union( + weave.legacy.weave_types.NoneType(), + weave.legacy.weave_types.List(weave.legacy.weave_types.String()), ) - assert unioned.object_type == weave.weave_types.union( - weave.weave_types.String(), weave.weave_types.NoneType() + assert unioned.object_type == weave.legacy.weave_types.union( + weave.legacy.weave_types.String(), weave.legacy.weave_types.NoneType() ) ### Dict Return # Not all members have props - unioned = weave.weave_types.union( - weave.weave_types.String(), - weave.weave_types.TypedDict({"a": weave.weave_types.String()}), + unioned = weave.legacy.weave_types.union( + weave.legacy.weave_types.String(), + weave.legacy.weave_types.TypedDict({"a": weave.legacy.weave_types.String()}), ) with pytest.raises(AttributeError): unioned.property_types # Combined dicts - unioned = weave.weave_types.union( - weave.weave_types.TypedDict( + unioned = weave.legacy.weave_types.union( + weave.legacy.weave_types.TypedDict( { - "same": weave.weave_types.Number(), - "solo_a": weave.weave_types.Number(), - "differ": weave.weave_types.Number(), + "same": weave.legacy.weave_types.Number(), + "solo_a": weave.legacy.weave_types.Number(), + "differ": weave.legacy.weave_types.Number(), } ), - weave.weave_types.TypedDict( + weave.legacy.weave_types.TypedDict( { - "same": weave.weave_types.Number(), - "solo_b": weave.weave_types.String(), - "differ": weave.weave_types.String(), + "same": weave.legacy.weave_types.Number(), + "solo_b": weave.legacy.weave_types.String(), + "differ": weave.legacy.weave_types.String(), } ), ) assert unioned.property_types == { - "same": weave.weave_types.Number(), - "solo_a": weave.weave_types.union( - weave.weave_types.Number(), weave.weave_types.NoneType() + "same": weave.legacy.weave_types.Number(), + "solo_a": weave.legacy.weave_types.union( + weave.legacy.weave_types.Number(), weave.legacy.weave_types.NoneType() ), - "solo_b": weave.weave_types.union( - weave.weave_types.String(), weave.weave_types.NoneType() + "solo_b": weave.legacy.weave_types.union( + weave.legacy.weave_types.String(), weave.legacy.weave_types.NoneType() ), - "differ": weave.weave_types.union( - weave.weave_types.Number(), weave.weave_types.String() + "differ": weave.legacy.weave_types.union( + weave.legacy.weave_types.Number(), weave.legacy.weave_types.String() ), } # Nullable type - unioned = weave.weave_types.union( - weave.weave_types.NoneType(), - weave.weave_types.TypedDict({"a": weave.weave_types.String()}), + unioned = weave.legacy.weave_types.union( + weave.legacy.weave_types.NoneType(), + weave.legacy.weave_types.TypedDict({"a": weave.legacy.weave_types.String()}), ) assert unioned.property_types == { - "a": weave.weave_types.union( - weave.weave_types.String(), weave.weave_types.NoneType() + "a": weave.legacy.weave_types.union( + weave.legacy.weave_types.String(), weave.legacy.weave_types.NoneType() ) } diff --git a/weave/tests/legacy/test_weavejs_fixes.py b/weave/tests/legacy/test_weavejs_fixes.py index e654405a6bd..4488b4314ef 100644 --- a/weave/tests/legacy/test_weavejs_fixes.py +++ b/weave/tests/legacy/test_weavejs_fixes.py @@ -3,9 +3,9 @@ import pytest from weave.legacy import context_state, mappers_python, ops, weavejs_fixes +from weave.legacy import weave_types as types from ... import api, weave_internal -from ... import weave_types as types @pytest.mark.skip( diff --git a/weave/tests/legacy/test_weavify.py b/weave/tests/legacy/test_weavify.py index d869848d98d..f5971099b43 100644 --- a/weave/tests/legacy/test_weavify.py +++ b/weave/tests/legacy/test_weavify.py @@ -1,9 +1,9 @@ import pytest from weave.legacy import graph, ops +from weave.legacy import weave_types as types from ... import weave_internal -from ... import weave_types as types from ...legacy import weavify from .. import geom diff --git a/weave/tests/tag_test_util.py b/weave/tests/tag_test_util.py index 9c2a6540604..a444466c413 100644 --- a/weave/tests/tag_test_util.py +++ b/weave/tests/tag_test_util.py @@ -1,11 +1,10 @@ import weave from weave.legacy import box, graph from weave.legacy import context_state as _context_state +from weave.legacy import weave_types as types from weave.legacy.language_features.tagging import tag_store from weave.legacy.language_features.tagging.tagged_value_type import TaggedValueType -from .. import weave_types as types - tag_adders = 0 diff --git a/weave/tests/trace/test_server.py b/weave/tests/trace/test_server.py index 0931eefda92..1be4acbb3cc 100644 --- a/weave/tests/trace/test_server.py +++ b/weave/tests/trace/test_server.py @@ -7,10 +7,10 @@ import requests from weave import api as weave -from weave import weave_types as types from weave.legacy import client as _client from weave.legacy import context_state, ops from weave.legacy import server as _server +from weave.legacy import weave_types as types from weave.legacy.decorator_op import op from weave.weave_internal import make_const_node diff --git a/weave/tests/weavejs_ops.py b/weave/tests/weavejs_ops.py index e1b22cf4694..2d4764e3f58 100644 --- a/weave/tests/weavejs_ops.py +++ b/weave/tests/weavejs_ops.py @@ -1,6 +1,7 @@ # WeaveJS ops used for testing. These are not used in production. from weave.legacy import graph +from weave.legacy import weave_types as types from weave.legacy._dict_utils import typeddict_pick_output_type from weave.legacy.language_features.tagging import tagged_value_type from weave.legacy.language_features.tagging.tagging_op_logic import ( @@ -9,7 +10,6 @@ ) from .. import weave_internal -from .. import weave_types as types def ensure_node(v): diff --git a/weave/weave_internal.py b/weave/weave_internal.py index 3e6e82a7eb3..014ab621db6 100644 --- a/weave/weave_internal.py +++ b/weave/weave_internal.py @@ -1,8 +1,7 @@ import typing from weave.legacy import client_interface, context_state, errors, graph - -from . import weave_types as types +from weave.legacy import weave_types as types def dereference_variables( From b9ab50068ac5e8abb20f501768efbf500d60f1db Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 17:55:30 -0400 Subject: [PATCH 45/84] move to legacy: weave_internal --- .../skip_test/Confusion Matrix.ipynb | 2 +- .../skip_test/Diffusion explore 2.ipynb | 2 +- .../skip_test/Diffusion explore.ipynb | 2 +- .../skip_test/Diffusion story.ipynb | 2 +- .../experimental/skip_test/art_explore.ipynb | 2 +- .../experimental/skip_test/weave_scifi.ipynb | 2 +- examples/experimental/tag_search.ipynb | 2 +- .../reference/panels/plot/synced_axes.ipynb | 2 +- examples/reference/vis/Distribution.ipynb | 2 +- weave/legacy/api.py | 2 +- weave/legacy/arrow/convert.py | 2 +- weave/legacy/arrow/list_.py | 4 +- weave/legacy/codify.py | 4 +- weave/legacy/compile.py | 4 +- weave/legacy/derive_op.py | 6 +- weave/legacy/eager.py | 2 +- .../ecosystem/wandb/panel_distribution.py | 2 +- weave/legacy/ecosystem/wandb/panel_geo.py | 2 +- weave/legacy/ecosystem/wandb/panel_scatter.py | 2 +- .../ecosystem/wandb/panel_time_series.py | 2 +- .../wandb/test_panel_distribution.py | 2 +- weave/legacy/ecosystem/wandb/weave_plotly.py | 2 +- weave/legacy/execute_fast.py | 4 +- weave/legacy/make_type.py | 2 +- weave/legacy/mappers_publisher.py | 2 +- weave/legacy/notebooks/Eval Board.ipynb | 308 +++++++++--------- weave/legacy/op_def.py | 4 +- weave/legacy/ops_arrow/vectorize.py | 5 +- .../legacy/ops_domain/artifact_version_ops.py | 2 +- weave/legacy/ops_domain/table.py | 2 +- weave/legacy/ops_primitives/number_bin.py | 2 +- weave/legacy/ops_primitives/test_dict.py | 2 +- weave/legacy/ops_primitives/test_list.py | 2 +- weave/legacy/ops_primitives/test_typeddict.py | 2 +- weave/legacy/ops_primitives/timestamp_bin.py | 4 +- weave/legacy/ops_primitives/weave_api.py | 6 +- weave/legacy/panel.py | 2 +- weave/legacy/panels/panel_board.py | 2 +- weave/legacy/panels/panel_facet.py | 2 +- weave/legacy/panels/panel_group.py | 2 +- weave/legacy/panels/panel_object_picker.py | 2 +- weave/legacy/panels/panel_plot.py | 2 +- weave/legacy/panels/panel_query.py | 2 +- weave/legacy/panels/panel_select.py | 2 +- weave/legacy/panels/panel_slider.py | 2 +- weave/legacy/panels/panel_table.py | 2 +- weave/legacy/panels/panel_weavelink.py | 2 +- weave/legacy/panels/table_state.py | 2 +- weave/legacy/panels_py/panel_autoboard.py | 2 +- .../panels_py/panel_example_custom_board.py | 2 +- weave/legacy/panels_py/panel_llm_monitor.py | 4 +- weave/legacy/panels_py/panel_observability.py | 2 +- weave/legacy/panels_py/panel_seedboard.py | 2 +- weave/legacy/panels_py/panel_trace_monitor.py | 4 +- weave/legacy/serialize.py | 2 +- weave/legacy/trace_local.py | 2 +- weave/{ => legacy}/weave_internal.py | 2 +- weave/legacy/weavify.py | 2 +- weave/tests/legacy/test_access.py | 11 +- weave/tests/legacy/test_arrow.py | 12 +- weave/tests/legacy/test_arrow_vectorizer.py | 3 +- weave/tests/legacy/test_artifact.py | 4 +- weave/tests/legacy/test_basic_ops.py | 2 +- weave/tests/legacy/test_compile.py | 2 +- weave/tests/legacy/test_complex_calls.py | 3 +- weave/tests/legacy/test_const_type_mapper.py | 4 +- weave/tests/legacy/test_decorators.py | 2 +- weave/tests/legacy/test_execute.py | 4 +- weave/tests/legacy/test_execute_fast.py | 3 +- weave/tests/legacy/test_graph.py | 4 +- weave/tests/legacy/test_list_arrow_compat.py | 3 +- weave/tests/legacy/test_logging.py | 5 +- weave/tests/legacy/test_mappability.py | 8 +- weave/tests/legacy/test_mappers_python.py | 3 +- weave/tests/legacy/test_media.py | 3 +- weave/tests/legacy/test_mutation2.py | 4 +- weave/tests/legacy/test_mutations.py | 3 +- weave/tests/legacy/test_nullability.py | 2 +- weave/tests/legacy/test_op.py | 4 +- weave/tests/legacy/test_op_behaviors.py | 3 +- weave/tests/legacy/test_op_dispatching.py | 4 +- weave/tests/legacy/test_panels.py | 2 +- weave/tests/legacy/test_plot.py | 3 +- weave/tests/legacy/test_refs.py | 4 +- weave/tests/legacy/test_run_segment.py | 4 +- weave/tests/legacy/test_serialize.py | 5 +- weave/tests/legacy/test_stitch.py | 3 +- weave/tests/legacy/test_storage.py | 11 +- weave/tests/legacy/test_table_ops.py | 11 +- weave/tests/legacy/test_tagging.py | 4 +- weave/tests/legacy/test_trace.py | 5 +- weave/tests/legacy/test_wb_domain_types.py | 2 +- weave/tests/legacy/test_wb_tables.py | 2 +- weave/tests/legacy/test_weavejs_fixes.py | 10 +- weave/tests/legacy/test_weavify.py | 3 +- weave/tests/trace/test_server.py | 2 +- weave/tests/weavejs_ops.py | 4 +- 97 files changed, 304 insertions(+), 316 deletions(-) rename weave/{ => legacy}/weave_internal.py (99%) diff --git a/examples/experimental/skip_test/Confusion Matrix.ipynb b/examples/experimental/skip_test/Confusion Matrix.ipynb index b357921adfa..02e964017eb 100644 --- a/examples/experimental/skip_test/Confusion Matrix.ipynb +++ b/examples/experimental/skip_test/Confusion Matrix.ipynb @@ -13,7 +13,7 @@ "from PIL import Image\n", "import weave\n", "from weave.legacy import storage\n", - "from weave import weave_internal\n", + "from weave.legacy import weave_internal\n", "#weave.use_frontend_devmode()" ] }, diff --git a/examples/experimental/skip_test/Diffusion explore 2.ipynb b/examples/experimental/skip_test/Diffusion explore 2.ipynb index 1e3dfee050e..3337cda943e 100644 --- a/examples/experimental/skip_test/Diffusion explore 2.ipynb +++ b/examples/experimental/skip_test/Diffusion explore 2.ipynb @@ -8,7 +8,7 @@ "outputs": [], "source": [ "import weave\n", - "from weave import weave_internal\n", + "from weave.legacy import weave_internal\n", "from weave.legacy.ecosystem.all import langchain\n", "weave.use_frontend_devmode()" ] diff --git a/examples/experimental/skip_test/Diffusion explore.ipynb b/examples/experimental/skip_test/Diffusion explore.ipynb index 0d3365f2f25..a253ccdaae5 100644 --- a/examples/experimental/skip_test/Diffusion explore.ipynb +++ b/examples/experimental/skip_test/Diffusion explore.ipynb @@ -25,7 +25,7 @@ "outputs": [], "source": [ "import weave\n", - "from weave import weave_internal\n", + "from weave.legacy import weave_internal\n", "from weave.legacy.ecosystem.all import langchain" ] }, diff --git a/examples/experimental/skip_test/Diffusion story.ipynb b/examples/experimental/skip_test/Diffusion story.ipynb index 8a9f8b6771d..93844909d88 100644 --- a/examples/experimental/skip_test/Diffusion story.ipynb +++ b/examples/experimental/skip_test/Diffusion story.ipynb @@ -8,7 +8,7 @@ "outputs": [], "source": [ "import weave\n", - "from weave import weave_internal\n", + "from weave.legacy import weave_internal\n", "from weave.legacy.ecosystem.all import langchain\n", "weave.use_frontend_devmode()" ] diff --git a/examples/experimental/skip_test/art_explore.ipynb b/examples/experimental/skip_test/art_explore.ipynb index 2b3ae1221c6..b591b5a163e 100644 --- a/examples/experimental/skip_test/art_explore.ipynb +++ b/examples/experimental/skip_test/art_explore.ipynb @@ -32,7 +32,7 @@ "outputs": [], "source": [ "import weave\n", - "from weave import weave_internal\n", + "from weave.legacy import weave_internal\n", "from weave.legacy.ecosystem.all import langchain" ] }, diff --git a/examples/experimental/skip_test/weave_scifi.ipynb b/examples/experimental/skip_test/weave_scifi.ipynb index d6144ba3fff..e08c7cc5ed2 100644 --- a/examples/experimental/skip_test/weave_scifi.ipynb +++ b/examples/experimental/skip_test/weave_scifi.ipynb @@ -8,7 +8,7 @@ "outputs": [], "source": [ "import weave\n", - "from weave import weave_internal\n", + "from weave.legacy import weave_internal\n", "from weave.legacy.ecosystem.all import langchain\n", "weave.use_frontend_devmode()" ] diff --git a/examples/experimental/tag_search.ipynb b/examples/experimental/tag_search.ipynb index edd83696e7e..d28245ee8ad 100644 --- a/examples/experimental/tag_search.ipynb +++ b/examples/experimental/tag_search.ipynb @@ -30,7 +30,7 @@ "outputs": [], "source": [ "import weave\n", - "from weave import weave_internal" + "from weave.legacy import weave_internal" ] }, { diff --git a/examples/reference/panels/plot/synced_axes.ipynb b/examples/reference/panels/plot/synced_axes.ipynb index 4f39243c180..6db386cf402 100644 --- a/examples/reference/panels/plot/synced_axes.ipynb +++ b/examples/reference/panels/plot/synced_axes.ipynb @@ -89,7 +89,7 @@ "outputs": [], "source": [ "from weave.legacy.panels.panel_plot import Signals, AxisSelections, Plot\n", - "from weave import weave_internal\n", + "from weave.legacy import weave_internal\n", "\n", "\n", "domain_node = weave_internal.const(None)\n", diff --git a/examples/reference/vis/Distribution.ipynb b/examples/reference/vis/Distribution.ipynb index 726c4a8f99e..3248599762f 100644 --- a/examples/reference/vis/Distribution.ipynb +++ b/examples/reference/vis/Distribution.ipynb @@ -41,7 +41,7 @@ "metadata": {}, "outputs": [], "source": [ - "from weave import weave_internal\n", + "from weave.legacy import weave_internal\n", "# Numeric distribution\n", "dist = wandb.Distribution(\n", " items,\n", diff --git a/weave/legacy/api.py b/weave/legacy/api.py index c310b40db08..853d7cd37ce 100644 --- a/weave/legacy/api.py +++ b/weave/legacy/api.py @@ -12,7 +12,7 @@ from . import ref_base as _ref_base from weave.legacy import wandb_api as _wandb_api -from .. import weave_internal as _weave_internal +from weave.legacy import weave_internal as _weave_internal from weave.legacy import util as _util diff --git a/weave/legacy/arrow/convert.py b/weave/legacy/arrow/convert.py index d76edeaef7b..95c22eb4f3d 100644 --- a/weave/legacy/arrow/convert.py +++ b/weave/legacy/arrow/convert.py @@ -4,7 +4,7 @@ import pyarrow.compute as pc from weave.legacy import api as api -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy import weave_types as types from weave.legacy import errors, arrow_util, artifact_base, artifact_mem, box, mappers_arrow from weave.legacy.arrow.arrow import ( diff --git a/weave/legacy/arrow/list_.py b/weave/legacy/arrow/list_.py index e90c860fead..f0855545fb5 100644 --- a/weave/legacy/arrow/list_.py +++ b/weave/legacy/arrow/list_.py @@ -10,11 +10,9 @@ import pyarrow.compute as pc import typing_extensions -from weave import ( - weave_internal, -) from weave.legacy import weave_types as types from weave.legacy import ( + weave_internal, errors, _dict_utils, artifact_base, diff --git a/weave/legacy/codify.py b/weave/legacy/codify.py index e1017261d77..ca1036dd826 100644 --- a/weave/legacy/codify.py +++ b/weave/legacy/codify.py @@ -201,7 +201,7 @@ def _node_to_code(node: graph.Node, wrap_const_node: bool = True) -> str: if current_frame is not None and node.name in current_frame: return node.name - return f"weave.weave_internal.make_var_node({_type_to_code(node.type)}, '{node.name}')" + return f"weave.legacy.weave_internal.make_var_node({_type_to_code(node.type)}, '{node.name}')" elif isinstance(node, graph.ConstNode): if isinstance(node.type, weave_types.Function): vars = list(node.type.input_types.keys()) @@ -209,7 +209,7 @@ def _node_to_code(node: graph.Node, wrap_const_node: bool = True) -> str: else: val_as_code = object_to_code_no_format(node.val) if wrap_const_node: - return f"weave.weave_internal.const({val_as_code})" + return f"weave.legacy.weave_internal.const({val_as_code})" else: return val_as_code elif isinstance(node, graph.OutputNode): diff --git a/weave/legacy/compile.py b/weave/legacy/compile.py index 1e307054bd0..e55d66daf9b 100644 --- a/weave/legacy/compile.py +++ b/weave/legacy/compile.py @@ -5,11 +5,9 @@ import re import typing -from weave import ( - weave_internal, -) from weave.legacy import weave_types as types from weave.legacy import ( + weave_internal, errors, engine_trace, box, diff --git a/weave/legacy/derive_op.py b/weave/legacy/derive_op.py index dcf1010b024..797d16af9fa 100644 --- a/weave/legacy/derive_op.py +++ b/weave/legacy/derive_op.py @@ -6,12 +6,10 @@ import inspect import typing -from weave import ( - storage, - weave_internal, -) from weave.legacy import weave_types as types from weave.legacy import ( + storage, + weave_internal, errors, parallelism, registry_mem, diff --git a/weave/legacy/eager.py b/weave/legacy/eager.py index 88ea1c453b6..7b1b1935ffc 100644 --- a/weave/legacy/eager.py +++ b/weave/legacy/eager.py @@ -2,7 +2,7 @@ from weave.legacy import context_state, graph -from .. import weave_internal +from weave.legacy import weave_internal from weave.legacy import weave_types as types WeaveIterObjectType = typing.TypeVar("WeaveIterObjectType") diff --git a/weave/legacy/ecosystem/wandb/panel_distribution.py b/weave/legacy/ecosystem/wandb/panel_distribution.py index 3ed85e247e3..b7d53699e4a 100644 --- a/weave/legacy/ecosystem/wandb/panel_distribution.py +++ b/weave/legacy/ecosystem/wandb/panel_distribution.py @@ -2,7 +2,7 @@ import typing import weave -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy import panel_util from weave.legacy.ecosystem.wandb import weave_plotly diff --git a/weave/legacy/ecosystem/wandb/panel_geo.py b/weave/legacy/ecosystem/wandb/panel_geo.py index be1baff8a1f..f0be1990357 100644 --- a/weave/legacy/ecosystem/wandb/panel_geo.py +++ b/weave/legacy/ecosystem/wandb/panel_geo.py @@ -3,7 +3,7 @@ import typing import weave -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy.ecosystem.wandb import weave_plotly diff --git a/weave/legacy/ecosystem/wandb/panel_scatter.py b/weave/legacy/ecosystem/wandb/panel_scatter.py index 4b86e22edb1..9794d847313 100644 --- a/weave/legacy/ecosystem/wandb/panel_scatter.py +++ b/weave/legacy/ecosystem/wandb/panel_scatter.py @@ -3,7 +3,7 @@ import typing import weave -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy.ecosystem.wandb import weave_plotly diff --git a/weave/legacy/ecosystem/wandb/panel_time_series.py b/weave/legacy/ecosystem/wandb/panel_time_series.py index a95069bc279..5d793f3152d 100644 --- a/weave/legacy/ecosystem/wandb/panel_time_series.py +++ b/weave/legacy/ecosystem/wandb/panel_time_series.py @@ -2,7 +2,7 @@ import typing import weave -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy.ecosystem.wandb import weave_plotly from weave.legacy.language_features.tagging import tagged_value_type from weave.legacy.panel_util import make_node diff --git a/weave/legacy/ecosystem/wandb/test_panel_distribution.py b/weave/legacy/ecosystem/wandb/test_panel_distribution.py index 71090b2d59c..a75a862649c 100644 --- a/weave/legacy/ecosystem/wandb/test_panel_distribution.py +++ b/weave/legacy/ecosystem/wandb/test_panel_distribution.py @@ -1,7 +1,7 @@ import random import weave -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy.ecosystem.wandb import panel_distribution diff --git a/weave/legacy/ecosystem/wandb/weave_plotly.py b/weave/legacy/ecosystem/wandb/weave_plotly.py index ab098cf4893..0450a9dbd64 100644 --- a/weave/legacy/ecosystem/wandb/weave_plotly.py +++ b/weave/legacy/ecosystem/wandb/weave_plotly.py @@ -9,7 +9,7 @@ from plotly import graph_objs as go import weave -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy import infer_types diff --git a/weave/legacy/execute_fast.py b/weave/legacy/execute_fast.py index b7331ded998..f3069ffa886 100644 --- a/weave/legacy/execute_fast.py +++ b/weave/legacy/execute_fast.py @@ -1,10 +1,8 @@ import logging -from weave import ( - weave_internal, -) from weave.legacy import weave_types as types from weave.legacy import ( + weave_internal, errors, engine_trace, ref_base, diff --git a/weave/legacy/make_type.py b/weave/legacy/make_type.py index 765bc06636d..3a39f8aa14d 100644 --- a/weave/legacy/make_type.py +++ b/weave/legacy/make_type.py @@ -1,4 +1,4 @@ -from .. import weave_internal +from weave.legacy import weave_internal from weave.legacy import weave_types as types diff --git a/weave/legacy/mappers_publisher.py b/weave/legacy/mappers_publisher.py index 667d47a5414..7332f22c16a 100644 --- a/weave/legacy/mappers_publisher.py +++ b/weave/legacy/mappers_publisher.py @@ -3,7 +3,7 @@ import typing from weave.legacy import storage -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy import weave_types as types from weave.legacy.node_ref import ref_to_node diff --git a/weave/legacy/notebooks/Eval Board.ipynb b/weave/legacy/notebooks/Eval Board.ipynb index 6c64694dc68..be2baf592eb 100644 --- a/weave/legacy/notebooks/Eval Board.ipynb +++ b/weave/legacy/notebooks/Eval Board.ipynb @@ -1,161 +1,161 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": 61, - "id": "314bb6b4", - "metadata": {}, - "outputs": [], - "source": [ - "import typing\n", - "\n", - "import weave\n", - "from weave import weave_internal\n", - "\n", - "weave.use_frontend_devmode()\n", - "from weave.legacy import ops_domain\n", - "from weave.legacy.panels import panel_board" - ] - }, - { - "cell_type": "code", - "execution_count": 62, - "id": "550daef6", - "metadata": {}, - "outputs": [], - "source": [ - "@weave.type()\n", - "class Dataset:\n", - " rows: list[typing.Any]" - ] - }, - { - "cell_type": "code", - "execution_count": 64, - "id": "e8065ad6", - "metadata": {}, - "outputs": [ + "cells": [ + { + "cell_type": "code", + "execution_count": 61, + "id": "314bb6b4", + "metadata": {}, + "outputs": [], + "source": [ + "import typing\n", + "\n", + "import weave\n", + "from weave.legacy import weave_internal\n", + "\n", + "weave.use_frontend_devmode()\n", + "from weave.legacy import ops_domain\n", + "from weave.legacy.panels import panel_board" + ] + }, { - "data": { - "text/html": [ - "\n", - " \n", - " " + "cell_type": "code", + "execution_count": 62, + "id": "550daef6", + "metadata": {}, + "outputs": [], + "source": [ + "@weave.type()\n", + "class Dataset:\n", + " rows: list[typing.Any]" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "id": "e8065ad6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } ], - "text/plain": [ - "" + "source": [ + "varbar = panel_board.varbar()\n", + "\n", + "entity_name_val = varbar.add(\"entity_name_val\", \"shawn\", hidden=True)\n", + "entity = ops_domain.entity(entity_name_val)\n", + "entity_name = varbar.add(\n", + " \"entity_name\",\n", + " weave.legacy.panels.Dropdown(\n", + " entity_name_val, choices=ops_domain.viewer().entities().name()\n", + " ),\n", + ")\n", + "\n", + "project_name_val = varbar.add(\"project_name_val\", \"weave-flow1\", hidden=True)\n", + "project = ops_domain.project(entity_name_val, project_name_val)\n", + "project_name = varbar.add(\n", + " \"project_name\",\n", + " weave.legacy.panels.Dropdown(project_name_val, choices=entity.projects().name()),\n", + ")\n", + "\n", + "dataset_name_val = varbar.add(\"dataset_name_val\", \"my_dataset1\", hidden=True)\n", + "dataset = varbar.add(\n", + " \"dataset\",\n", + " weave.legacy.ops.get(\n", + " weave_internal.const(\"wandb-artifact:///\")\n", + " + entity_name_val\n", + " + \"/\"\n", + " + project_name_val\n", + " + \"/\"\n", + " + dataset_name_val\n", + " + \":latest/obj\"\n", + " ),\n", + " hidden=True,\n", + ")\n", + "dataset_ref = varbar.add(\n", + " \"dataset_ref\",\n", + " weave.legacy.ops.ref(\n", + " weave_internal.const(\"wandb-artifact:///\")\n", + " + entity_name_val\n", + " + \"/\"\n", + " + project_name_val\n", + " + \"/\"\n", + " + dataset_name_val\n", + " + \":latest/obj\"\n", + " ),\n", + ")\n", + "dataset_name = varbar.add(\n", + " \"dataset_name\",\n", + " weave.legacy.panels.Dropdown(\n", + " dataset_name_val, choices=project.artifactType(\"Dataset\").artifacts().name()\n", + " ),\n", + ")\n", + "\n", + "# Now here I want to pick model A and model B\n", + "# I need to a way to get to artifact from an object, like get_ref.artifact ?\n", + "# like dataset_ref.artifact().usedBy().filter(lambda row: row.jobName() == 'eval')\n", + "# then from there find consuming runs of a given job_type (\"eval\")\n", + "# let the user pick two of those\n", + "\n", + "# want a really nice data grid of the table metric comparsion per row\n", + "\n", + "main = weave.legacy.panels.Group(\n", + " layoutMode=\"grid\",\n", + " showExpressions=True,\n", + " enableAddPanel=True,\n", + ")\n", + "\n", + "main.add(\"ename\", entity_name_val)\n", + "main.add(\"pname\", project_name_val)\n", + "main.add(\"dsrows\", weave.legacy.ops.obj_getattr(dataset, \"rows\"))\n", + "# main.add(\"artifact\", dataset_ref.artifact())\n", + "\n", + "# I Need a programmable Table. One that's columns are defined by Nodes\n", + "# Same for panels, I want to be able to generate a bunch of panels\n", + "# Can I do this with Weaveify?\n", + "# Like I can pass a function in in the Board that returns the panel I want maybe?\n", + "\n", + "weave.legacy.panels.Board(vars=varbar, panels=main)" ] - }, - "metadata": {}, - "output_type": "display_data" } - ], - "source": [ - "varbar = panel_board.varbar()\n", - "\n", - "entity_name_val = varbar.add(\"entity_name_val\", \"shawn\", hidden=True)\n", - "entity = ops_domain.entity(entity_name_val)\n", - "entity_name = varbar.add(\n", - " \"entity_name\",\n", - " weave.legacy.panels.Dropdown(\n", - " entity_name_val, choices=ops_domain.viewer().entities().name()\n", - " ),\n", - ")\n", - "\n", - "project_name_val = varbar.add(\"project_name_val\", \"weave-flow1\", hidden=True)\n", - "project = ops_domain.project(entity_name_val, project_name_val)\n", - "project_name = varbar.add(\n", - " \"project_name\",\n", - " weave.legacy.panels.Dropdown(project_name_val, choices=entity.projects().name()),\n", - ")\n", - "\n", - "dataset_name_val = varbar.add(\"dataset_name_val\", \"my_dataset1\", hidden=True)\n", - "dataset = varbar.add(\n", - " \"dataset\",\n", - " weave.legacy.ops.get(\n", - " weave_internal.const(\"wandb-artifact:///\")\n", - " + entity_name_val\n", - " + \"/\"\n", - " + project_name_val\n", - " + \"/\"\n", - " + dataset_name_val\n", - " + \":latest/obj\"\n", - " ),\n", - " hidden=True,\n", - ")\n", - "dataset_ref = varbar.add(\n", - " \"dataset_ref\",\n", - " weave.legacy.ops.ref(\n", - " weave_internal.const(\"wandb-artifact:///\")\n", - " + entity_name_val\n", - " + \"/\"\n", - " + project_name_val\n", - " + \"/\"\n", - " + dataset_name_val\n", - " + \":latest/obj\"\n", - " ),\n", - ")\n", - "dataset_name = varbar.add(\n", - " \"dataset_name\",\n", - " weave.legacy.panels.Dropdown(\n", - " dataset_name_val, choices=project.artifactType(\"Dataset\").artifacts().name()\n", - " ),\n", - ")\n", - "\n", - "# Now here I want to pick model A and model B\n", - "# I need to a way to get to artifact from an object, like get_ref.artifact ?\n", - "# like dataset_ref.artifact().usedBy().filter(lambda row: row.jobName() == 'eval')\n", - "# then from there find consuming runs of a given job_type (\"eval\")\n", - "# let the user pick two of those\n", - "\n", - "# want a really nice data grid of the table metric comparsion per row\n", - "\n", - "main = weave.legacy.panels.Group(\n", - " layoutMode=\"grid\",\n", - " showExpressions=True,\n", - " enableAddPanel=True,\n", - ")\n", - "\n", - "main.add(\"ename\", entity_name_val)\n", - "main.add(\"pname\", project_name_val)\n", - "main.add(\"dsrows\", weave.legacy.ops.obj_getattr(dataset, \"rows\"))\n", - "# main.add(\"artifact\", dataset_ref.artifact())\n", - "\n", - "# I Need a programmable Table. One that's columns are defined by Nodes\n", - "# Same for panels, I want to be able to generate a bunch of panels\n", - "# Can I do this with Weaveify?\n", - "# Like I can pass a function in in the Board that returns the panel I want maybe?\n", - "\n", - "weave.legacy.panels.Board(vars=varbar, panels=main)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/op_def.py b/weave/legacy/op_def.py index 7581773e09f..8fdfd881513 100644 --- a/weave/legacy/op_def.py +++ b/weave/legacy/op_def.py @@ -6,11 +6,9 @@ import typing from typing import Iterator, Sequence -from weave import ( - weave_internal, -) from weave.legacy import weave_types as types from weave.legacy import ( + weave_internal, errors, context_state, engine_trace, diff --git a/weave/legacy/ops_arrow/vectorize.py b/weave/legacy/ops_arrow/vectorize.py index 107666929e1..002d8c1d86d 100644 --- a/weave/legacy/ops_arrow/vectorize.py +++ b/weave/legacy/ops_arrow/vectorize.py @@ -6,10 +6,7 @@ import numpy as np import pyarrow as pa -from weave import ( - - weave_internal, -) +from weave.legacy import weave_internal from weave.legacy import errors,weavify, registry_mem from weave.legacy import weave_types as types from weave.legacy.api import op, use diff --git a/weave/legacy/ops_domain/artifact_version_ops.py b/weave/legacy/ops_domain/artifact_version_ops.py index aa816e3f716..8203e289189 100644 --- a/weave/legacy/ops_domain/artifact_version_ops.py +++ b/weave/legacy/ops_domain/artifact_version_ops.py @@ -460,7 +460,7 @@ def artifact_version_weave_type( def _get_history_metrics( artifactVersion: wdt.ArtifactVersion, ) -> dict[str, typing.Any]: - from weave import weave_internal + from weave.legacy import weave_internal from weave.legacy.compile import enable_compile from weave.legacy.graph import ConstNode, OutputNode from weave.legacy.ops_domain import wb_domain_types diff --git a/weave/legacy/ops_domain/table.py b/weave/legacy/ops_domain/table.py index 7f4fbf91dae..bef6805ad1d 100644 --- a/weave/legacy/ops_domain/table.py +++ b/weave/legacy/ops_domain/table.py @@ -5,7 +5,7 @@ import logging import typing -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy import weave_types as types from weave.legacy.api import op, weave_class from weave.legacy import ( diff --git a/weave/legacy/ops_primitives/number_bin.py b/weave/legacy/ops_primitives/number_bin.py index c06de46703d..97b799fcd3d 100644 --- a/weave/legacy/ops_primitives/number_bin.py +++ b/weave/legacy/ops_primitives/number_bin.py @@ -5,7 +5,7 @@ from weave.legacy import graph from weave.legacy.ops_primitives import date from weave.legacy.ops_primitives.dict import dict_ -from weave.weave_internal import call_fn, define_fn, make_const_node +from weave.legacy.weave_internal import call_fn, define_fn, make_const_node from weave.legacy.weave_types import Function, NumberBinType diff --git a/weave/legacy/ops_primitives/test_dict.py b/weave/legacy/ops_primitives/test_dict.py index 33508af74e2..165a714a3ee 100644 --- a/weave/legacy/ops_primitives/test_dict.py +++ b/weave/legacy/ops_primitives/test_dict.py @@ -1,5 +1,5 @@ import weave -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy.language_features.tagging import tagged_value_type diff --git a/weave/legacy/ops_primitives/test_list.py b/weave/legacy/ops_primitives/test_list.py index 2856054b5ab..6507ead3b4a 100644 --- a/weave/legacy/ops_primitives/test_list.py +++ b/weave/legacy/ops_primitives/test_list.py @@ -1,7 +1,7 @@ import pytest from weave.legacy import api as weave -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy import weave_types as types from weave.legacy import box from weave.legacy.language_features.tagging import ( diff --git a/weave/legacy/ops_primitives/test_typeddict.py b/weave/legacy/ops_primitives/test_typeddict.py index 94644dae54e..6f85584df4d 100644 --- a/weave/legacy/ops_primitives/test_typeddict.py +++ b/weave/legacy/ops_primitives/test_typeddict.py @@ -1,7 +1,7 @@ import pytest import weave -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy import box from weave.legacy.arrow.arrow import ArrowWeaveListType from weave.legacy.language_features.tagging import tag_store, tagged_value_type diff --git a/weave/legacy/ops_primitives/timestamp_bin.py b/weave/legacy/ops_primitives/timestamp_bin.py index ef153be48da..ce5b3e1097b 100644 --- a/weave/legacy/ops_primitives/timestamp_bin.py +++ b/weave/legacy/ops_primitives/timestamp_bin.py @@ -1,9 +1,9 @@ -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy import weave_types as types from weave.legacy.api import op, use from weave.legacy import graph from weave.legacy.ops_primitives.dict import dict_ -from weave.weave_internal import call_fn, define_fn, make_const_node +from weave.legacy.weave_internal import call_fn, define_fn, make_const_node from weave.legacy.weave_types import Function, TimestampBinType NICE_BIN_SIZES_SEC = [ diff --git a/weave/legacy/ops_primitives/weave_api.py b/weave/legacy/ops_primitives/weave_api.py index 680e21c5460..1b760c9b5dc 100644 --- a/weave/legacy/ops_primitives/weave_api.py +++ b/weave/legacy/ops_primitives/weave_api.py @@ -2,13 +2,11 @@ import time import typing -from weave import ( - storage, - weave_internal, -) from weave.legacy import weave_types as types from weave.legacy.api import mutation, op, weave_class from weave.legacy import ( + storage, + weave_internal, errors, ref_base, registry_mem, diff --git a/weave/legacy/panel.py b/weave/legacy/panel.py index 7ec6daab4e0..87af22bca47 100644 --- a/weave/legacy/panel.py +++ b/weave/legacy/panel.py @@ -4,7 +4,7 @@ from tarfile import DEFAULT_FORMAT from weave.legacy import api as weave -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy import weave_types as types from weave.legacy import graph, panel_util, errors, storage diff --git a/weave/legacy/panels/panel_board.py b/weave/legacy/panels/panel_board.py index 6f3ac7e94dd..0db30de2a27 100644 --- a/weave/legacy/panels/panel_board.py +++ b/weave/legacy/panels/panel_board.py @@ -2,7 +2,7 @@ import typing import weave -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy import panel from weave.legacy.panels import panel_group diff --git a/weave/legacy/panels/panel_facet.py b/weave/legacy/panels/panel_facet.py index 54e079f333f..24c4b42d663 100644 --- a/weave/legacy/panels/panel_facet.py +++ b/weave/legacy/panels/panel_facet.py @@ -2,7 +2,7 @@ import typing import weave -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy import weave_types as types from weave.legacy import graph, panel, panel_util from weave.legacy.arrow import list_ diff --git a/weave/legacy/panels/panel_group.py b/weave/legacy/panels/panel_group.py index a7ea1847900..3c4046c7410 100644 --- a/weave/legacy/panels/panel_group.py +++ b/weave/legacy/panels/panel_group.py @@ -3,7 +3,7 @@ import typing import weave -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy import ( errors, codifiable_value_mixin, diff --git a/weave/legacy/panels/panel_object_picker.py b/weave/legacy/panels/panel_object_picker.py index 802afc109a2..c3ca313c4cc 100644 --- a/weave/legacy/panels/panel_object_picker.py +++ b/weave/legacy/panels/panel_object_picker.py @@ -2,7 +2,7 @@ import typing import weave -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy import graph, panel ChoiceType = typing.TypeVar("ChoiceType") diff --git a/weave/legacy/panels/panel_plot.py b/weave/legacy/panels/panel_plot.py index 7210836b2d7..6386d26e719 100644 --- a/weave/legacy/panels/panel_plot.py +++ b/weave/legacy/panels/panel_plot.py @@ -4,7 +4,7 @@ import typing import weave -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy import weave_types as types from weave.legacy import errors, codifiable_value_mixin, codify, graph, panel from weave.legacy.ops_primitives import boolean, list_ diff --git a/weave/legacy/panels/panel_query.py b/weave/legacy/panels/panel_query.py index 1ca55a02828..e59d4b666e8 100644 --- a/weave/legacy/panels/panel_query.py +++ b/weave/legacy/panels/panel_query.py @@ -2,7 +2,7 @@ import typing import weave -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy import graph, panel from weave.legacy.panels import table_state diff --git a/weave/legacy/panels/panel_select.py b/weave/legacy/panels/panel_select.py index b62334154da..3ab67039bae 100644 --- a/weave/legacy/panels/panel_select.py +++ b/weave/legacy/panels/panel_select.py @@ -2,7 +2,7 @@ import typing import weave -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy import graph, panel diff --git a/weave/legacy/panels/panel_slider.py b/weave/legacy/panels/panel_slider.py index 130407577d1..cbe568a4876 100644 --- a/weave/legacy/panels/panel_slider.py +++ b/weave/legacy/panels/panel_slider.py @@ -2,7 +2,7 @@ import typing import weave -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy import panel diff --git a/weave/legacy/panels/panel_table.py b/weave/legacy/panels/panel_table.py index 4cce8bfb05c..a359e7b01c1 100644 --- a/weave/legacy/panels/panel_table.py +++ b/weave/legacy/panels/panel_table.py @@ -2,7 +2,7 @@ import typing import weave -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy import codifiable_value_mixin, codify, panel from weave.legacy.graph import ConstNode, Node, OutputNode, VoidNode from weave.legacy.panels import table_state diff --git a/weave/legacy/panels/panel_weavelink.py b/weave/legacy/panels/panel_weavelink.py index ac1bb125869..095926dd167 100644 --- a/weave/legacy/panels/panel_weavelink.py +++ b/weave/legacy/panels/panel_weavelink.py @@ -2,7 +2,7 @@ import typing import weave -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy import graph, ops, panel, panel_util diff --git a/weave/legacy/panels/table_state.py b/weave/legacy/panels/table_state.py index 9415c814d7d..460585136b8 100644 --- a/weave/legacy/panels/table_state.py +++ b/weave/legacy/panels/table_state.py @@ -7,7 +7,7 @@ import string import typing -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy import decorator_type, graph, ops, panel, weave_types from weave.legacy.language_features.tagging import tagged_value_type diff --git a/weave/legacy/panels_py/panel_autoboard.py b/weave/legacy/panels_py/panel_autoboard.py index ab37b9813ac..26ea6c6c468 100644 --- a/weave/legacy/panels_py/panel_autoboard.py +++ b/weave/legacy/panels_py/panel_autoboard.py @@ -26,7 +26,7 @@ import typing import weave -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy.panels import panel_plot from weave.legacy.panels_py.generator_templates import template_registry from weave.legacy import util diff --git a/weave/legacy/panels_py/panel_example_custom_board.py b/weave/legacy/panels_py/panel_example_custom_board.py index 21ba4b37fdb..fa3bd6641df 100644 --- a/weave/legacy/panels_py/panel_example_custom_board.py +++ b/weave/legacy/panels_py/panel_example_custom_board.py @@ -1,5 +1,5 @@ import weave -from weave import weave_internal as internal +from weave.legacy import weave_internal as internal from weave.legacy import weave_types as types from weave.legacy.panels_py.generator_templates import template_registry diff --git a/weave/legacy/panels_py/panel_llm_monitor.py b/weave/legacy/panels_py/panel_llm_monitor.py index a14e0e804d5..d51810eb0a5 100644 --- a/weave/legacy/panels_py/panel_llm_monitor.py +++ b/weave/legacy/panels_py/panel_llm_monitor.py @@ -2,8 +2,8 @@ import typing import weave -from weave import weave_internal -from weave import weave_internal as internal +from weave.legacy import weave_internal +from weave.legacy import weave_internal as internal from weave.legacy import weave_types as types from weave.legacy import util, dispatch from weave.legacy.panels import panel_board, panel_group diff --git a/weave/legacy/panels_py/panel_observability.py b/weave/legacy/panels_py/panel_observability.py index 37a3d47d6bc..a6ea920d2f4 100644 --- a/weave/legacy/panels_py/panel_observability.py +++ b/weave/legacy/panels_py/panel_observability.py @@ -1,5 +1,5 @@ import weave -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy import weave_types as types from weave.legacy.panels import panel_board from weave.legacy.panels_py.generator_templates import template_registry diff --git a/weave/legacy/panels_py/panel_seedboard.py b/weave/legacy/panels_py/panel_seedboard.py index a8ffbc5b2c1..4887f66f854 100644 --- a/weave/legacy/panels_py/panel_seedboard.py +++ b/weave/legacy/panels_py/panel_seedboard.py @@ -1,7 +1,7 @@ import typing import weave -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy.panels_py.generator_templates import template_registry diff --git a/weave/legacy/panels_py/panel_trace_monitor.py b/weave/legacy/panels_py/panel_trace_monitor.py index 7e228aeef01..9bd91d96090 100644 --- a/weave/legacy/panels_py/panel_trace_monitor.py +++ b/weave/legacy/panels_py/panel_trace_monitor.py @@ -1,8 +1,8 @@ import os import weave -from weave import weave_internal -from weave import weave_internal as internal +from weave.legacy import weave_internal +from weave.legacy import weave_internal as internal from weave.legacy import weave_types as types from weave.legacy import util, dispatch, graph from weave.legacy.panels import panel_board, panel_group, panel_trace diff --git a/weave/legacy/serialize.py b/weave/legacy/serialize.py index ee83f9047cb..396a1b956be 100644 --- a/weave/legacy/serialize.py +++ b/weave/legacy/serialize.py @@ -7,7 +7,7 @@ import random import typing -from weave import weave_internal +from weave.legacy import weave_internal from weave.legacy import weave_types as types from weave.legacy import storage, errors, graph, memo, value_or_error diff --git a/weave/legacy/trace_local.py b/weave/legacy/trace_local.py index 05c6075b003..b38d0df657d 100644 --- a/weave/legacy/trace_local.py +++ b/weave/legacy/trace_local.py @@ -8,7 +8,7 @@ from weave.legacy import artifact_local, graph, op_def, op_policy, runs from . import ref_base -from .. import ( +from weave.legacy import ( storage, weave_internal, ) diff --git a/weave/weave_internal.py b/weave/legacy/weave_internal.py similarity index 99% rename from weave/weave_internal.py rename to weave/legacy/weave_internal.py index 014ab621db6..e26bcd526c2 100644 --- a/weave/weave_internal.py +++ b/weave/legacy/weave_internal.py @@ -148,7 +148,7 @@ def define_fn( # and the function doesn't explicitly operate on tagged values. this ensures that the input tags # are propagated appropriately to the output type of the function. def refine_graph(node: graph.Node) -> graph.Node: - from .legacy.registry_mem import memory_registry + from weave.legacy.registry_mem import memory_registry if isinstance(node, (graph.ConstNode, graph.VoidNode, graph.VarNode)): return node diff --git a/weave/legacy/weavify.py b/weave/legacy/weavify.py index 6714d6676f8..a85567a1e53 100644 --- a/weave/legacy/weavify.py +++ b/weave/legacy/weavify.py @@ -2,7 +2,7 @@ from weave.legacy import errors, graph, op_args, val_const -from .. import weave_internal +from weave.legacy import weave_internal from weave.legacy import weave_types as types if typing.TYPE_CHECKING: diff --git a/weave/tests/legacy/test_access.py b/weave/tests/legacy/test_access.py index cbcfbb6defe..15b1157581d 100644 --- a/weave/tests/legacy/test_access.py +++ b/weave/tests/legacy/test_access.py @@ -1,9 +1,14 @@ import pytest import weave -from weave.legacy import artifact_fs, artifact_local, environment, errors, wandb_api - -from ... import storage +from weave.legacy import ( + artifact_fs, + artifact_local, + environment, + errors, + storage, + wandb_api, +) @pytest.fixture() diff --git a/weave/tests/legacy/test_arrow.py b/weave/tests/legacy/test_arrow.py index 889835c9588..7e8a7703e64 100644 --- a/weave/tests/legacy/test_arrow.py +++ b/weave/tests/legacy/test_arrow.py @@ -7,7 +7,16 @@ import pytest from PIL import Image -from weave.legacy import box, context_state, errors, graph, mappers_arrow, ops +from weave.legacy import ( + box, + context_state, + errors, + graph, + mappers_arrow, + ops, + storage, + weave_internal, +) # If you're thinking of import vectorize here, don't! Put your # tests in test_arrow_vectorizer.py instead @@ -28,7 +37,6 @@ from weave.tests import list_arrow_test_helpers as lath from ... import api as weave -from ... import storage, weave_internal from ...tests import tag_test_util as ttu from ...tests import weavejs_ops from ...tests.legacy import test_wb diff --git a/weave/tests/legacy/test_arrow_vectorizer.py b/weave/tests/legacy/test_arrow_vectorizer.py index 04e1b0f9862..8f41805c840 100644 --- a/weave/tests/legacy/test_arrow_vectorizer.py +++ b/weave/tests/legacy/test_arrow_vectorizer.py @@ -5,7 +5,7 @@ import pytest from pyarrow import compute as pc -from weave.legacy import box, dispatch, errors, ops +from weave.legacy import box, dispatch, errors, ops, weave_internal from weave.legacy import ops_arrow as arrow from weave.legacy import weave_types as types from weave.legacy.language_features.tagging import ( @@ -19,7 +19,6 @@ from weave.legacy.ops_primitives import Boolean, Number, date, dict_, list_ from ... import api as weave -from ... import weave_internal string_ops_test_cases = [ ("eq-scalar", lambda x: x == "bc", [True, False, False]), diff --git a/weave/tests/legacy/test_artifact.py b/weave/tests/legacy/test_artifact.py index 27cde9e1e1b..2c62094c36e 100644 --- a/weave/tests/legacy/test_artifact.py +++ b/weave/tests/legacy/test_artifact.py @@ -1,11 +1,9 @@ import pytest import weave -from weave.legacy import artifact_fs, artifact_local +from weave.legacy import artifact_fs, artifact_local, storage from weave.legacy import ops_arrow as arrow -from ... import storage - def test_artifact(): data = arrow.to_arrow([{"a": 5}]) diff --git a/weave/tests/legacy/test_basic_ops.py b/weave/tests/legacy/test_basic_ops.py index c957d907e0e..19c2d3020b8 100644 --- a/weave/tests/legacy/test_basic_ops.py +++ b/weave/tests/legacy/test_basic_ops.py @@ -1,9 +1,9 @@ from weave.legacy import box, ops from weave.legacy.ops_primitives import number from weave.legacy.ops_primitives.string import * +from weave.legacy.weave_internal import make_const_node from ... import api as weave -from ...weave_internal import make_const_node def test_number_ops(): diff --git a/weave/tests/legacy/test_compile.py b/weave/tests/legacy/test_compile.py index ef0ec1014bd..2bdde6920af 100644 --- a/weave/tests/legacy/test_compile.py +++ b/weave/tests/legacy/test_compile.py @@ -8,7 +8,7 @@ from weave.legacy.ops_arrow import to_arrow from weave.legacy.ops_arrow.vectorize import raise_on_python_bailout from weave.legacy.wandb_interface.wandb_stream_table import StreamTable -from weave.weave_internal import const, define_fn, make_const_node +from weave.legacy.weave_internal import const, define_fn, make_const_node from ...api import use diff --git a/weave/tests/legacy/test_complex_calls.py b/weave/tests/legacy/test_complex_calls.py index 07fe79a5f01..bb480e1b800 100644 --- a/weave/tests/legacy/test_complex_calls.py +++ b/weave/tests/legacy/test_complex_calls.py @@ -1,6 +1,5 @@ import weave - -from ... import weave_internal +from weave.legacy import weave_internal def test_weave_fn_in_data(): diff --git a/weave/tests/legacy/test_const_type_mapper.py b/weave/tests/legacy/test_const_type_mapper.py index c6143cdc278..792294572d0 100644 --- a/weave/tests/legacy/test_const_type_mapper.py +++ b/weave/tests/legacy/test_const_type_mapper.py @@ -1,9 +1,7 @@ import typing import weave -from weave.legacy import context_state - -from ... import weave_internal +from weave.legacy import context_state, weave_internal _loading_builtins_token = context_state.set_loading_built_ins() diff --git a/weave/tests/legacy/test_decorators.py b/weave/tests/legacy/test_decorators.py index e47c79db7a9..cc1a2e1846b 100644 --- a/weave/tests/legacy/test_decorators.py +++ b/weave/tests/legacy/test_decorators.py @@ -1,8 +1,8 @@ +from weave.legacy import storage from weave.legacy import weave_types as types from weave.legacy.decorator_op import op from ... import api as weave -from ... import storage def test_function_op_name(): diff --git a/weave/tests/legacy/test_execute.py b/weave/tests/legacy/test_execute.py index 29a8a93191f..a36eec66b6b 100644 --- a/weave/tests/legacy/test_execute.py +++ b/weave/tests/legacy/test_execute.py @@ -4,10 +4,10 @@ import pytest import weave -from weave.legacy import environment, execute, ops +from weave.legacy import environment, execute, ops, weave_internal from weave.legacy import weave_types as types -from ... import api, weave_internal +from ... import api from . import test_wb execute_test_count_op_run_count = 0 diff --git a/weave/tests/legacy/test_execute_fast.py b/weave/tests/legacy/test_execute_fast.py index 716651dd943..af8c94b7b5e 100644 --- a/weave/tests/legacy/test_execute_fast.py +++ b/weave/tests/legacy/test_execute_fast.py @@ -1,8 +1,7 @@ import weave -from weave.legacy import dispatch +from weave.legacy import dispatch, weave_internal from weave.legacy import weave_types as types -from ... import weave_internal from .. import weavejs_ops diff --git a/weave/tests/legacy/test_graph.py b/weave/tests/legacy/test_graph.py index 70051c60a17..ca04c2722d5 100644 --- a/weave/tests/legacy/test_graph.py +++ b/weave/tests/legacy/test_graph.py @@ -1,9 +1,7 @@ import weave -from weave.legacy import graph +from weave.legacy import graph, weave_internal from weave.legacy import weave_types as types -from ... import weave_internal - def test_map_dag_produces_same_len(): # 3 diff --git a/weave/tests/legacy/test_list_arrow_compat.py b/weave/tests/legacy/test_list_arrow_compat.py index a38a409ae23..08287ed6da9 100644 --- a/weave/tests/legacy/test_list_arrow_compat.py +++ b/weave/tests/legacy/test_list_arrow_compat.py @@ -3,8 +3,7 @@ import numpy as np import pytest -from weave import weave_internal -from weave.legacy import box, ops +from weave.legacy import box, ops, weave_internal from weave.legacy import ops_arrow as arrow from weave.legacy import weave_types as types from weave.legacy.language_features.tagging import ( diff --git a/weave/tests/legacy/test_logging.py b/weave/tests/legacy/test_logging.py index 48463f5e49f..6ef1abea8b5 100644 --- a/weave/tests/legacy/test_logging.py +++ b/weave/tests/legacy/test_logging.py @@ -4,9 +4,8 @@ import pytest import requests -from weave.legacy import context, logs, ops, server - -from ... import api, weave_server +from weave import weave_server +from weave.legacy import api, context, logs, ops, server def test_logfile_created(fresh_server_logfile): diff --git a/weave/tests/legacy/test_mappability.py b/weave/tests/legacy/test_mappability.py index e7bbcfb79ca..335eff5722e 100644 --- a/weave/tests/legacy/test_mappability.py +++ b/weave/tests/legacy/test_mappability.py @@ -2,9 +2,9 @@ from weave.legacy import context_state as _context from weave.legacy import graph from weave.legacy import weave_types as types +from weave.legacy.weave_internal import make_const_node from ...legacy import registry_mem -from ...weave_internal import make_const_node _loading_builtins_token = _context.set_loading_built_ins() @@ -61,7 +61,7 @@ def test_non_mapped_use(): def test_non_mapped_serialized(): - node = weave.weave_internal.make_output_node( + node = weave.legacy.weave_internal.make_output_node( weave.types.Int(), _test_add_one.name, {"x": weave.legacy.graph.ConstNode(weave.types.Int(), 1)}, @@ -82,7 +82,7 @@ def test_mapped_nullable_use(): def test_mapped_serialized(): - node = weave.weave_internal.make_output_node( + node = weave.legacy.weave_internal.make_output_node( weave.types.Int(), _test_add_one.name, { @@ -101,7 +101,7 @@ def test_mapped_empty_use(): def test_mapped_empty_serialized(): - node = weave.weave_internal.make_output_node( + node = weave.legacy.weave_internal.make_output_node( weave.types.Int(), _test_add_one.name, {"x": weave.legacy.graph.ConstNode(weave.types.List(weave.types.Int()), [])}, diff --git a/weave/tests/legacy/test_mappers_python.py b/weave/tests/legacy/test_mappers_python.py index 192fdefb041..61cd78e0c81 100644 --- a/weave/tests/legacy/test_mappers_python.py +++ b/weave/tests/legacy/test_mappers_python.py @@ -1,7 +1,6 @@ import math -from weave import weave_internal -from weave.legacy import api, context, mappers_python, val_const +from weave.legacy import api, context, mappers_python, val_const, weave_internal from weave.legacy import weave_types as types diff --git a/weave/tests/legacy/test_media.py b/weave/tests/legacy/test_media.py index 175f4ad38cf..502679692c1 100644 --- a/weave/tests/legacy/test_media.py +++ b/weave/tests/legacy/test_media.py @@ -3,10 +3,9 @@ import numpy as np import pytest +from weave.legacy import storage from weave.legacy import weave_types as types -from ... import storage - def test_nparray(): arr = np.array([[1, 2], [3, 4]]) diff --git a/weave/tests/legacy/test_mutation2.py b/weave/tests/legacy/test_mutation2.py index d344f10b0f9..00f5619423d 100644 --- a/weave/tests/legacy/test_mutation2.py +++ b/weave/tests/legacy/test_mutation2.py @@ -1,7 +1,5 @@ import weave -from weave.legacy import ref_base, uris - -from ... import weave_internal +from weave.legacy import ref_base, uris, weave_internal def test_mutation_set_direct_call(): diff --git a/weave/tests/legacy/test_mutations.py b/weave/tests/legacy/test_mutations.py index 983b777ee05..a83ff5a0272 100644 --- a/weave/tests/legacy/test_mutations.py +++ b/weave/tests/legacy/test_mutations.py @@ -1,7 +1,6 @@ -from weave.legacy import ops +from weave.legacy import ops, storage, weave_internal from ... import api as weave -from ... import storage, weave_internal def test_autocommit(cereal_csv): diff --git a/weave/tests/legacy/test_nullability.py b/weave/tests/legacy/test_nullability.py index 41ab3fd24e8..df8b08be96a 100644 --- a/weave/tests/legacy/test_nullability.py +++ b/weave/tests/legacy/test_nullability.py @@ -4,7 +4,7 @@ import weave from weave.legacy import context_state as _context -from weave.weave_internal import make_const_node, make_output_node +from weave.legacy.weave_internal import make_const_node, make_output_node _loading_builtins_token = _context.set_loading_built_ins() diff --git a/weave/tests/legacy/test_op.py b/weave/tests/legacy/test_op.py index 46cea2177cb..dfd0636c0c9 100644 --- a/weave/tests/legacy/test_op.py +++ b/weave/tests/legacy/test_op.py @@ -2,10 +2,10 @@ import pytest -from weave import types, weave_internal from weave.legacy import api as weave -from weave.legacy import context_state, graph, storage, uris +from weave.legacy import context_state, graph, storage, uris, weave_internal from weave.legacy import context_state as _context_state +from weave.legacy import weave_types as types from . import test_helpers diff --git a/weave/tests/legacy/test_op_behaviors.py b/weave/tests/legacy/test_op_behaviors.py index e49ff51c9c1..6a9f207acd9 100644 --- a/weave/tests/legacy/test_op_behaviors.py +++ b/weave/tests/legacy/test_op_behaviors.py @@ -19,13 +19,14 @@ op_def, ops_arrow, ops_primitives, + storage, + weave_internal, ) from weave.legacy.language_features.tagging import make_tag_getter_op from weave.legacy.language_features.tagging.tagged_value_type import ( TaggedValueType, ) -from ... import storage, weave_internal from ...legacy import registry_mem from ..concrete_tagged_value import ( TaggedValue, diff --git a/weave/tests/legacy/test_op_dispatching.py b/weave/tests/legacy/test_op_dispatching.py index fbd1d51df36..7123a19e553 100644 --- a/weave/tests/legacy/test_op_dispatching.py +++ b/weave/tests/legacy/test_op_dispatching.py @@ -2,13 +2,11 @@ import weave from weave.legacy import context_state as _context -from weave.legacy import graph +from weave.legacy import graph, weave_internal from weave.legacy.dispatch import _dispatch_first_arg, _resolve_op_ambiguity from weave.legacy.language_features.tagging.tagged_value_type import TaggedValueType from weave.legacy.ops_domain import wb_domain_types -from ... import weave_internal - _loading_builtins_token = _context.set_loading_built_ins() diff --git a/weave/tests/legacy/test_panels.py b/weave/tests/legacy/test_panels.py index 867f9842c0f..14f162987d1 100644 --- a/weave/tests/legacy/test_panels.py +++ b/weave/tests/legacy/test_panels.py @@ -1,9 +1,9 @@ import pytest import weave +from weave.legacy import storage, weave_internal from weave.legacy.panels import panel_plot -from ... import storage, weave_internal from ...legacy.panels.panel_group import Group from ...legacy.panels.panel_slider import Slider diff --git a/weave/tests/legacy/test_plot.py b/weave/tests/legacy/test_plot.py index 7f0658d2529..f124eabf81d 100644 --- a/weave/tests/legacy/test_plot.py +++ b/weave/tests/legacy/test_plot.py @@ -4,11 +4,10 @@ import pytest import weave -from weave.legacy import graph +from weave.legacy import graph, storage from weave.legacy import weave_types as types from weave.legacy.panels.panel_plot import Plot, PlotConstants, Series -from ... import storage from .test_run_segment import create_experiment diff --git a/weave/tests/legacy/test_refs.py b/weave/tests/legacy/test_refs.py index ac9923eaaad..e890134d0ff 100644 --- a/weave/tests/legacy/test_refs.py +++ b/weave/tests/legacy/test_refs.py @@ -2,7 +2,7 @@ import weave from weave.flow.obj import Object -from weave.legacy import artifact_local +from weave.legacy import artifact_local, storage from weave.legacy import ops_arrow as arrow from weave.trace import ref_util from weave.trace_server.refs_internal import ( @@ -11,8 +11,6 @@ OBJECT_ATTR_EDGE_NAME, ) -from ... import storage - def test_laref_artifact_version_1(): art = artifact_local.LocalArtifact("my-art", "v19") diff --git a/weave/tests/legacy/test_run_segment.py b/weave/tests/legacy/test_run_segment.py index eb0f36f81c6..6ab3815c200 100644 --- a/weave/tests/legacy/test_run_segment.py +++ b/weave/tests/legacy/test_run_segment.py @@ -6,12 +6,12 @@ import pytest import weave -from weave.legacy import ops +from weave.legacy import ops, storage, weave_internal from weave.legacy import weave_types as types from weave.legacy.ops_arrow import ArrowWeaveList, arrow_as_array from weave.legacy.ops_domain.run_segment import RunSegment -from ... import api, storage, weave_internal +from ... import api N_NUMERIC_METRICS = 99 # number of numerical columns in the metrics table diff --git a/weave/tests/legacy/test_serialize.py b/weave/tests/legacy/test_serialize.py index 030ddb13465..dc430c95cd1 100644 --- a/weave/tests/legacy/test_serialize.py +++ b/weave/tests/legacy/test_serialize.py @@ -1,12 +1,11 @@ import pytest import weave -from weave import weave_internal from weave.legacy import api as api -from weave.legacy import graph, op_args, ops, registry_mem, serialize +from weave.legacy import graph, op_args, ops, registry_mem, serialize, weave_internal from weave.legacy import weave_types as types from weave.legacy.ops_primitives import list_ -from weave.weave_internal import make_const_node +from weave.legacy.weave_internal import make_const_node from .. import fixture_fakewandb as fwb diff --git a/weave/tests/legacy/test_stitch.py b/weave/tests/legacy/test_stitch.py index 368f01ce553..54accda3ebd 100644 --- a/weave/tests/legacy/test_stitch.py +++ b/weave/tests/legacy/test_stitch.py @@ -3,12 +3,11 @@ import pytest import weave -from weave.legacy import compile_domain, compile_table +from weave.legacy import compile_domain, compile_table, weave_internal from weave.legacy import context_state as _context from weave.legacy.language_features.tagging import make_tag_getter_op from weave.legacy.ops_domain import run_ops -from ... import weave_internal from ...legacy import stitch from .. import fixture_fakewandb as fwb from . import test_wb diff --git a/weave/tests/legacy/test_storage.py b/weave/tests/legacy/test_storage.py index 4c31c43f9b7..ab91835e742 100644 --- a/weave/tests/legacy/test_storage.py +++ b/weave/tests/legacy/test_storage.py @@ -7,14 +7,19 @@ import pytest import wandb -from weave.legacy import artifact_mem, artifact_wandb, mappers_python, ops_arrow +from weave.legacy import ( + artifact_mem, + artifact_wandb, + mappers_python, + ops_arrow, + storage, +) from weave.legacy import weave_types as types from weave.legacy.arrow import list_ as arrow +from weave.legacy.weave_internal import make_const_node from ... import api as weave -from ... import storage from ...legacy.weavejs_fixes import recursively_unwrap_unions -from ...weave_internal import make_const_node from . import test_helpers diff --git a/weave/tests/legacy/test_table_ops.py b/weave/tests/legacy/test_table_ops.py index 9296cb2e235..c5ece54c3ab 100644 --- a/weave/tests/legacy/test_table_ops.py +++ b/weave/tests/legacy/test_table_ops.py @@ -3,12 +3,19 @@ import pytest -from weave.legacy import box, context, context_state, graph, ops +from weave.legacy import ( + box, + context, + context_state, + graph, + ops, + storage, + weave_internal, +) from weave.legacy import weave_types as types from weave.legacy.ops_domain import table as table_ops from ... import api as weave -from ... import storage, weave_internal from .. import weavejs_ops TABLE_TYPES = ["list", "pandas", "sql"] diff --git a/weave/tests/legacy/test_tagging.py b/weave/tests/legacy/test_tagging.py index fa691cdd77a..da17be75408 100644 --- a/weave/tests/legacy/test_tagging.py +++ b/weave/tests/legacy/test_tagging.py @@ -1,7 +1,7 @@ import pytest import weave -from weave.legacy import box +from weave.legacy import box, weave_internal from weave.legacy import weave_types as types from weave.legacy.artifact_fs import FilesystemArtifactFileType from weave.legacy.language_features.tagging import ( @@ -15,8 +15,6 @@ from weave.legacy.ops_primitives import dict as dict_ops from weave.legacy.ops_primitives import list_ as list_ops -from ... import weave_internal - def test_tagged_value(): tv = tagged_value_type.TaggedValueType( diff --git a/weave/tests/legacy/test_trace.py b/weave/tests/legacy/test_trace.py index e779f576e7e..629ca15a4c3 100644 --- a/weave/tests/legacy/test_trace.py +++ b/weave/tests/legacy/test_trace.py @@ -1,11 +1,10 @@ import re -from weave.legacy import graph +from weave.legacy import graph, storage +from weave.legacy.weave_internal import make_const_node from ... import api as weave -from ... import storage from ...legacy import trace_legacy -from ...weave_internal import make_const_node def test_node_expr(): diff --git a/weave/tests/legacy/test_wb_domain_types.py b/weave/tests/legacy/test_wb_domain_types.py index e2a131a57f2..b035ebd3b7a 100644 --- a/weave/tests/legacy/test_wb_domain_types.py +++ b/weave/tests/legacy/test_wb_domain_types.py @@ -1,8 +1,8 @@ +from weave.legacy import storage from weave.legacy import weave_types as types from weave.legacy.ops_domain import wb_domain_types as wdt from ... import api as weave -from ... import storage def test_with_keys_assignability(): diff --git a/weave/tests/legacy/test_wb_tables.py b/weave/tests/legacy/test_wb_tables.py index 98ccb6ed076..0c89d128d29 100644 --- a/weave/tests/legacy/test_wb_tables.py +++ b/weave/tests/legacy/test_wb_tables.py @@ -9,7 +9,7 @@ from weave.legacy.ops_arrow.list_ops import filter from weave.legacy.ops_domain import wbmedia from weave.legacy.ops_domain.wandb_domain_gql import _make_alias -from weave.weave_internal import make_const_node +from weave.legacy.weave_internal import make_const_node def use_static_artifact_node( diff --git a/weave/tests/legacy/test_weavejs_fixes.py b/weave/tests/legacy/test_weavejs_fixes.py index 4488b4314ef..c40a9d3145f 100644 --- a/weave/tests/legacy/test_weavejs_fixes.py +++ b/weave/tests/legacy/test_weavejs_fixes.py @@ -2,10 +2,16 @@ import pytest -from weave.legacy import context_state, mappers_python, ops, weavejs_fixes +from weave.legacy import ( + context_state, + mappers_python, + ops, + weave_internal, + weavejs_fixes, +) from weave.legacy import weave_types as types -from ... import api, weave_internal +from ... import api @pytest.mark.skip( diff --git a/weave/tests/legacy/test_weavify.py b/weave/tests/legacy/test_weavify.py index f5971099b43..3e6a845b517 100644 --- a/weave/tests/legacy/test_weavify.py +++ b/weave/tests/legacy/test_weavify.py @@ -1,9 +1,8 @@ import pytest -from weave.legacy import graph, ops +from weave.legacy import graph, ops, weave_internal from weave.legacy import weave_types as types -from ... import weave_internal from ...legacy import weavify from .. import geom diff --git a/weave/tests/trace/test_server.py b/weave/tests/trace/test_server.py index 1be4acbb3cc..aaaf1f08ff7 100644 --- a/weave/tests/trace/test_server.py +++ b/weave/tests/trace/test_server.py @@ -12,7 +12,7 @@ from weave.legacy import server as _server from weave.legacy import weave_types as types from weave.legacy.decorator_op import op -from weave.weave_internal import make_const_node +from weave.legacy.weave_internal import make_const_node SERVER_TYPES = ["inprocess", "subprocess", "http"] diff --git a/weave/tests/weavejs_ops.py b/weave/tests/weavejs_ops.py index 2d4764e3f58..82bceb9fba8 100644 --- a/weave/tests/weavejs_ops.py +++ b/weave/tests/weavejs_ops.py @@ -1,6 +1,6 @@ # WeaveJS ops used for testing. These are not used in production. -from weave.legacy import graph +from weave.legacy import graph, weave_internal from weave.legacy import weave_types as types from weave.legacy._dict_utils import typeddict_pick_output_type from weave.legacy.language_features.tagging import tagged_value_type @@ -9,8 +9,6 @@ op_make_type_tagged_resolver, ) -from .. import weave_internal - def ensure_node(v): if isinstance(v, graph.Node): From 8f9963a5bc1596273c0e46d9c3053946f227aa19 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 16:52:31 -0400 Subject: [PATCH 46/84] move to legacy: test_stream_table --- weave/tests/{stream_table => legacy}/test_stream_table.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename weave/tests/{stream_table => legacy}/test_stream_table.py (100%) diff --git a/weave/tests/stream_table/test_stream_table.py b/weave/tests/legacy/test_stream_table.py similarity index 100% rename from weave/tests/stream_table/test_stream_table.py rename to weave/tests/legacy/test_stream_table.py From fc555d82dc3e9fb4523d6322de8590b78e224b93 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 16:57:34 -0400 Subject: [PATCH 47/84] move to legacy: perf_notebooks --- .../legacy/perf_notebooks}/case_when v if_then_else.ipynb | 0 .../legacy/perf_notebooks}/pyarrow joinall.ipynb | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {perf_notebooks => weave/legacy/perf_notebooks}/case_when v if_then_else.ipynb (100%) rename {perf_notebooks => weave/legacy/perf_notebooks}/pyarrow joinall.ipynb (100%) diff --git a/perf_notebooks/case_when v if_then_else.ipynb b/weave/legacy/perf_notebooks/case_when v if_then_else.ipynb similarity index 100% rename from perf_notebooks/case_when v if_then_else.ipynb rename to weave/legacy/perf_notebooks/case_when v if_then_else.ipynb diff --git a/perf_notebooks/pyarrow joinall.ipynb b/weave/legacy/perf_notebooks/pyarrow joinall.ipynb similarity index 100% rename from perf_notebooks/pyarrow joinall.ipynb rename to weave/legacy/perf_notebooks/pyarrow joinall.ipynb From 9af69767e8fec3c34b3941c52e9bc47f24f1ac4b Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 17:17:27 -0400 Subject: [PATCH 48/84] move to legacy: internal_tools --- .../legacy/internal_tools}/Module deps viz.ipynb | 0 .../legacy/internal_tools}/generate_notebook_tests.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {internal_tools => weave/legacy/internal_tools}/Module deps viz.ipynb (100%) rename {internal_tools => weave/legacy/internal_tools}/generate_notebook_tests.py (100%) diff --git a/internal_tools/Module deps viz.ipynb b/weave/legacy/internal_tools/Module deps viz.ipynb similarity index 100% rename from internal_tools/Module deps viz.ipynb rename to weave/legacy/internal_tools/Module deps viz.ipynb diff --git a/internal_tools/generate_notebook_tests.py b/weave/legacy/internal_tools/generate_notebook_tests.py similarity index 100% rename from internal_tools/generate_notebook_tests.py rename to weave/legacy/internal_tools/generate_notebook_tests.py From d7354a430c509004f83324c6d8771b5b9e61539f Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 17:19:31 -0400 Subject: [PATCH 49/84] move to legacy: dispatching_and_resolution --- weave/{ => legacy}/docs/dispatching_and_resolution.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename weave/{ => legacy}/docs/dispatching_and_resolution.md (100%) diff --git a/weave/docs/dispatching_and_resolution.md b/weave/legacy/docs/dispatching_and_resolution.md similarity index 100% rename from weave/docs/dispatching_and_resolution.md rename to weave/legacy/docs/dispatching_and_resolution.md From 749c6ae7b636e01cb35add5e079acae7886cd9b4 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 11:44:48 -0400 Subject: [PATCH 50/84] move to trace: init_message --- weave/{ => trace}/init_message.py | 0 weave/weave_init.py | 6 ++---- 2 files changed, 2 insertions(+), 4 deletions(-) rename weave/{ => trace}/init_message.py (100%) diff --git a/weave/init_message.py b/weave/trace/init_message.py similarity index 100% rename from weave/init_message.py rename to weave/trace/init_message.py diff --git a/weave/weave_init.py b/weave/weave_init.py index 3d0a0233aa5..2bf83c97080 100644 --- a/weave/weave_init.py +++ b/weave/weave_init.py @@ -2,10 +2,8 @@ from weave.client_context import weave_client as weave_client_context from weave.legacy import errors - -from . import init_message -from .trace import autopatch, trace_sentry, weave_client -from .trace_server import remote_http_trace_server, sqlite_trace_server +from weave.trace import autopatch, init_message, trace_sentry, weave_client +from weave.trace_server import remote_http_trace_server, sqlite_trace_server _current_inited_client = None From cc5f285c67a42cce55f8c8d358cda81632dd2b08 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 12:25:51 -0400 Subject: [PATCH 51/84] move to trace: weave_init --- weave/conftest.py | 2 +- weave/legacy/api.py | 2 +- weave/tests/legacy/test_weave_api.py | 12 +++++++----- weave/tests/trace/test_client_trace.py | 2 +- .../tests/trace/trace_server_clickhouse_conftest.py | 2 +- weave/trace/api.py | 6 +----- weave/trace/refs.py | 2 +- weave/{ => trace}/weave_init.py | 0 8 files changed, 13 insertions(+), 15 deletions(-) rename weave/{ => trace}/weave_init.py (100%) diff --git a/weave/conftest.py b/weave/conftest.py index f9916306774..a18d90ad4e2 100644 --- a/weave/conftest.py +++ b/weave/conftest.py @@ -13,10 +13,10 @@ from flask.testing import FlaskClient import weave -from weave import weave_init from weave.legacy import client as client_legacy from weave.legacy import context_state, environment, io_service, serialize from weave.legacy.language_features.tagging.tag_store import isolated_tagging_context +from weave.trace import weave_init from weave.trace_server import ( clickhouse_trace_server_batched, remote_http_trace_server, diff --git a/weave/legacy/api.py b/weave/legacy/api.py index 853d7cd37ce..ba13f7e09f8 100644 --- a/weave/legacy/api.py +++ b/weave/legacy/api.py @@ -17,7 +17,7 @@ from weave.legacy import util as _util from weave.legacy import context as _context -from .. import weave_init as _weave_init +from ..trace import weave_init as _weave_init from ..trace import weave_client as _weave_client # exposed as part of api diff --git a/weave/tests/legacy/test_weave_api.py b/weave/tests/legacy/test_weave_api.py index 8f389d26a2f..ad1996ccc97 100644 --- a/weave/tests/legacy/test_weave_api.py +++ b/weave/tests/legacy/test_weave_api.py @@ -5,7 +5,7 @@ import weave import weave.legacy.context_state import weave.legacy.wandb_api -import weave.weave_init +import weave.trace.weave_init def test_create_list_rename_delete(): @@ -40,9 +40,11 @@ def foo(): return 1 weave.client_context.weave_client.set_weave_client_global(None) - weave.weave_init._current_inited_client = weave.weave_init.InitializedClient(client) - weave_client = weave.weave_init._current_inited_client.client - assert weave.weave_init._current_inited_client is not None + weave.trace.weave_init._current_inited_client = ( + weave.trace.weave_init.InitializedClient(client) + ) + weave_client = weave.trace.weave_init._current_inited_client.client + assert weave.trace.weave_init._current_inited_client is not None foo() assert len(list(weave_client.calls())) == 1 @@ -51,4 +53,4 @@ def foo(): foo() assert len(list(weave_client.calls())) == 1 - assert weave.weave_init._current_inited_client is None + assert weave.trace.weave_init._current_inited_client is None diff --git a/weave/tests/trace/test_client_trace.py b/weave/tests/trace/test_client_trace.py index 7fa79aa29d6..57b7e697fe5 100644 --- a/weave/tests/trace/test_client_trace.py +++ b/weave/tests/trace/test_client_trace.py @@ -1568,7 +1568,7 @@ def _no_graph_client(): @contextmanager def _patched_default_initializer(trace_client: weave_client.WeaveClient): - from weave import weave_init + from weave.trace import weave_init def init_weave_get_server_patched(api_key): return trace_client.server diff --git a/weave/tests/trace/trace_server_clickhouse_conftest.py b/weave/tests/trace/trace_server_clickhouse_conftest.py index 7d28d4506a9..14a6b0d9fcb 100644 --- a/weave/tests/trace/trace_server_clickhouse_conftest.py +++ b/weave/tests/trace/trace_server_clickhouse_conftest.py @@ -10,13 +10,13 @@ import requests from weave.trace import weave_client +from weave.trace.weave_init import InitializedClient from weave.trace_server import ( clickhouse_trace_server_batched, external_to_internal_trace_server_adapter, ) from weave.trace_server import environment as wf_env from weave.trace_server import trace_server_interface as tsi -from weave.weave_init import InitializedClient @pytest.fixture(scope="session") diff --git a/weave/trace/api.py b/weave/trace/api.py index e6615a7221a..4b1929770ab 100644 --- a/weave/trace/api.py +++ b/weave/trace/api.py @@ -12,11 +12,7 @@ # TODO: type_serializers is imported here to trigger registration of the image serializer. # There is probably a better place for this, but including here for now to get the fix in. -from .. import ( - type_serializers, # noqa: F401 - weave_init, -) -from . import context, weave_client +from . import context, weave_client, weave_init from .constants import TRACE_OBJECT_EMOJI from .op import Op, op from .refs import ObjectRef, parse_uri diff --git a/weave/trace/refs.py b/weave/trace/refs.py index cfffe99436c..0df24902462 100644 --- a/weave/trace/refs.py +++ b/weave/trace/refs.py @@ -64,7 +64,7 @@ def get(self) -> Any: # This import is invalid in the trace server and represents a dependency # that should be removed. from weave.client_context.weave_client import get_weave_client - from weave.weave_init import init_weave + from weave.trace.weave_init import init_weave gc = get_weave_client() if gc is not None: diff --git a/weave/weave_init.py b/weave/trace/weave_init.py similarity index 100% rename from weave/weave_init.py rename to weave/trace/weave_init.py From c018cd3e227e2bd4f0da63247171a5846384dc73 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 13:02:58 -0400 Subject: [PATCH 52/84] move to trace: cli --- weave/tests/{legacy => trace}/test_cli.py | 2 +- weave/{ => trace}/cli.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename weave/tests/{legacy => trace}/test_cli.py (88%) rename weave/{ => trace}/cli.py (99%) diff --git a/weave/tests/legacy/test_cli.py b/weave/tests/trace/test_cli.py similarity index 88% rename from weave/tests/legacy/test_cli.py rename to weave/tests/trace/test_cli.py index 71e0391632c..9710611e85e 100644 --- a/weave/tests/legacy/test_cli.py +++ b/weave/tests/trace/test_cli.py @@ -1,6 +1,6 @@ from click.testing import CliRunner -from weave.cli import cli +from weave.trace.cli import cli from weave.version import VERSION diff --git a/weave/cli.py b/weave/trace/cli.py similarity index 99% rename from weave/cli.py rename to weave/trace/cli.py index 8975d0da554..97aa7aad635 100644 --- a/weave/cli.py +++ b/weave/trace/cli.py @@ -4,10 +4,10 @@ import click from weave import __version__ +from weave.deploy import gcp as google from weave.trace.refs import ObjectRef, parse_uri from . import api -from .deploy import gcp as google # from .model_server import app From 7c2c2fdd68ff20511c27fd7c9cf064031ad69cf6 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Sat, 24 Aug 2024 11:46:46 -0400 Subject: [PATCH 53/84] move to trace: client_context --- weave/integrations/langchain/langchain.py | 2 +- weave/integrations/llamaindex/llamaindex.py | 2 +- weave/legacy/mappers_python_def.py | 2 +- weave/legacy/monitoring/monitor.py | 2 +- weave/legacy/monitoring/openai/openai.py | 2 +- weave/legacy/ref_base.py | 2 +- weave/legacy/storage.py | 2 +- weave/tests/legacy/test_weave_api.py | 2 +- weave/tests/trace/test_client_trace.py | 6 +++--- weave/trace/api.py | 2 +- weave/trace/cli.py | 2 +- weave/{ => trace}/client_context/weave_client.py | 0 weave/trace/custom_objs.py | 2 +- weave/trace/feedback.py | 2 +- weave/trace/op.py | 2 +- weave/trace/refs.py | 2 +- weave/trace/rich_refs.py | 2 +- weave/trace/tests/test_vals.py | 2 +- weave/trace/vals.py | 2 +- weave/trace/weave_client.py | 2 +- weave/trace/weave_init.py | 2 +- 21 files changed, 22 insertions(+), 22 deletions(-) rename weave/{ => trace}/client_context/weave_client.py (100%) diff --git a/weave/integrations/langchain/langchain.py b/weave/integrations/langchain/langchain.py index 9d2ee657d9e..0b974312390 100644 --- a/weave/integrations/langchain/langchain.py +++ b/weave/integrations/langchain/langchain.py @@ -35,12 +35,12 @@ from contextvars import ContextVar from uuid import UUID -from weave.client_context import weave_client as weave_client_context from weave.integrations.integration_utilities import ( make_pythonic_function_name, truncate_op_name, ) from weave.trace import call_context +from weave.trace.client_context import weave_client as weave_client_context from weave.trace.patcher import Patcher from weave.trace.weave_client import Call diff --git a/weave/integrations/llamaindex/llamaindex.py b/weave/integrations/llamaindex/llamaindex.py index acb22efb3c3..df30a6b6abb 100644 --- a/weave/integrations/llamaindex/llamaindex.py +++ b/weave/integrations/llamaindex/llamaindex.py @@ -1,4 +1,4 @@ -from weave.client_context import weave_client as weave_client_context +from weave.trace.client_context import weave_client as weave_client_context from weave.trace.patcher import Patcher from weave.trace.weave_client import Call diff --git a/weave/legacy/mappers_python_def.py b/weave/legacy/mappers_python_def.py index 5a1ee099220..c50bdc648ac 100644 --- a/weave/legacy/mappers_python_def.py +++ b/weave/legacy/mappers_python_def.py @@ -19,7 +19,7 @@ from weave.legacy import timestamp as weave_timestamp from weave.legacy.language_features.tagging import tagged_value_type from weave.legacy.partial_object import PartialObject, PartialObjectType -from weave.client_context import weave_client as weave_client_context +from weave.trace.client_context import weave_client as weave_client_context class TypedDictToPyDict(mappers_weave.TypedDictMapper): diff --git a/weave/legacy/monitoring/monitor.py b/weave/legacy/monitoring/monitor.py index 5a707af576c..518383ab59f 100644 --- a/weave/legacy/monitoring/monitor.py +++ b/weave/legacy/monitoring/monitor.py @@ -19,7 +19,7 @@ ) from weave.legacy.wandb_interface.wandb_stream_table import StreamTable from weave.trace import call_context, context as trace_context -from weave.client_context import weave_client as weave_client_context +from weave.trace.client_context import weave_client as weave_client_context logger = logging.getLogger(__name__) diff --git a/weave/legacy/monitoring/openai/openai.py b/weave/legacy/monitoring/openai/openai.py index c002ec85c4c..f41f551d994 100644 --- a/weave/legacy/monitoring/openai/openai.py +++ b/weave/legacy/monitoring/openai/openai.py @@ -11,7 +11,7 @@ from openai.types.chat import ChatCompletion, ChatCompletionMessageParam from packaging import version from weave.trace import call_context -from weave.client_context import weave_client as weave_client_context +from weave.trace.client_context import weave_client as weave_client_context from weave.legacy.monitoring.monitor import _get_global_monitor from weave.legacy.monitoring.openai.models import * from weave.legacy.monitoring.openai.util import * diff --git a/weave/legacy/ref_base.py b/weave/legacy/ref_base.py index 234b9f4aede..107ca9ca6c1 100644 --- a/weave/legacy/ref_base.py +++ b/weave/legacy/ref_base.py @@ -5,7 +5,7 @@ import weakref from typing import Sequence -from weave.client_context import weave_client as weave_client_context +from weave.trace.client_context import weave_client as weave_client_context from weave.legacy import box, context_state, object_context, uris from weave.legacy.language_features.tagging import tag_store diff --git a/weave/legacy/storage.py b/weave/legacy/storage.py index e13f102bb1b..cd14615af6c 100644 --- a/weave/legacy/storage.py +++ b/weave/legacy/storage.py @@ -7,7 +7,7 @@ import re import typing -from weave.client_context import weave_client as weave_client_context +from weave.trace.client_context import weave_client as weave_client_context from weave.legacy import ( artifact_base, artifact_fs, diff --git a/weave/tests/legacy/test_weave_api.py b/weave/tests/legacy/test_weave_api.py index ad1996ccc97..90fd26ebb24 100644 --- a/weave/tests/legacy/test_weave_api.py +++ b/weave/tests/legacy/test_weave_api.py @@ -39,7 +39,7 @@ def test_weave_finish_unsets_client(client): def foo(): return 1 - weave.client_context.weave_client.set_weave_client_global(None) + weave.trace.client_context.weave_client.set_weave_client_global(None) weave.trace.weave_init._current_inited_client = ( weave.trace.weave_init.InitializedClient(client) ) diff --git a/weave/tests/trace/test_client_trace.py b/weave/tests/trace/test_client_trace.py index 57b7e697fe5..dd638e7fbe4 100644 --- a/weave/tests/trace/test_client_trace.py +++ b/weave/tests/trace/test_client_trace.py @@ -1558,12 +1558,12 @@ def test_ref_get_no_client(trace_init_client): @contextmanager def _no_graph_client(): - client = weave.client_context.weave_client.get_weave_client() - weave.client_context.weave_client.set_weave_client_global(None) + client = weave.trace.client_context.weave_client.get_weave_client() + weave.trace.client_context.weave_client.set_weave_client_global(None) try: yield finally: - weave.client_context.weave_client.set_weave_client_global(client) + weave.trace.client_context.weave_client.set_weave_client_global(client) @contextmanager diff --git a/weave/trace/api.py b/weave/trace/api.py index 4b1929770ab..916d27c2841 100644 --- a/weave/trace/api.py +++ b/weave/trace/api.py @@ -6,9 +6,9 @@ import time from typing import Any, Callable, Iterator, Optional, Union -from weave.client_context import weave_client as weave_client_context from weave.legacy import urls, util from weave.trace.call_context import get_current_call +from weave.trace.client_context import weave_client as weave_client_context # TODO: type_serializers is imported here to trigger registration of the image serializer. # There is probably a better place for this, but including here for now to get the fix in. diff --git a/weave/trace/cli.py b/weave/trace/cli.py index 97aa7aad635..59a6118d12c 100644 --- a/weave/trace/cli.py +++ b/weave/trace/cli.py @@ -134,7 +134,7 @@ def gcp( ) @click.option("--dev", is_flag=True, help="Run the function locally.") def modal(model_ref: str, project: str, auth_entity: str, dev: bool = False) -> None: - from .deploy import modal as mdp + from weave.deploy import modal as mdp if dev: print(f"Developing model {model_ref}...") diff --git a/weave/client_context/weave_client.py b/weave/trace/client_context/weave_client.py similarity index 100% rename from weave/client_context/weave_client.py rename to weave/trace/client_context/weave_client.py diff --git a/weave/trace/custom_objs.py b/weave/trace/custom_objs.py index 6a8c0022d3e..99b7d41eb60 100644 --- a/weave/trace/custom_objs.py +++ b/weave/trace/custom_objs.py @@ -4,9 +4,9 @@ import tempfile from typing import Any, Dict, Generator, Iterator, Mapping, Optional, Union -from weave.client_context.weave_client import require_weave_client from weave.legacy import artifact_fs from weave.trace import op_type # noqa: F401, Must import this to register op save/load +from weave.trace.client_context.weave_client import require_weave_client from weave.trace.op import Op, op from weave.trace.refs import ObjectRef, parse_uri from weave.trace.serializer import get_serializer_by_id, get_serializer_for_obj diff --git a/weave/trace/feedback.py b/weave/trace/feedback.py index 8f2eafd378f..a9a386aa002 100644 --- a/weave/trace/feedback.py +++ b/weave/trace/feedback.py @@ -5,9 +5,9 @@ from rich.table import Table -from weave.client_context import weave_client as weave_client_context from weave.legacy import util from weave.trace import rich_pydantic_util +from weave.trace.client_context import weave_client as weave_client_context from weave.trace.refs import parse_uri from weave.trace.rich_container import AbstractRichContainer from weave.trace.rich_refs import Refs diff --git a/weave/trace/op.py b/weave/trace/op.py index 29babb6b2d9..3dca692b28d 100644 --- a/weave/trace/op.py +++ b/weave/trace/op.py @@ -17,9 +17,9 @@ runtime_checkable, ) -from weave.client_context import weave_client as weave_client_context from weave.legacy import context_state from weave.trace import box, call_context, settings +from weave.trace.client_context import weave_client as weave_client_context from weave.trace.context import call_attributes from weave.trace.errors import OpCallError from weave.trace.refs import ObjectRef diff --git a/weave/trace/refs.py b/weave/trace/refs.py index 0df24902462..0634de90a80 100644 --- a/weave/trace/refs.py +++ b/weave/trace/refs.py @@ -63,7 +63,7 @@ def get(self) -> Any: # Move import here so that it only happens when the function is called. # This import is invalid in the trace server and represents a dependency # that should be removed. - from weave.client_context.weave_client import get_weave_client + from weave.trace.client_context.weave_client import get_weave_client from weave.trace.weave_init import init_weave gc = get_weave_client() diff --git a/weave/trace/rich_refs.py b/weave/trace/rich_refs.py index c72e07f4227..aab9f11d7f8 100644 --- a/weave/trace/rich_refs.py +++ b/weave/trace/rich_refs.py @@ -4,7 +4,7 @@ from rich.table import Table -from weave.client_context import weave_client as weave_client_context +from weave.trace.client_context import weave_client as weave_client_context from weave.trace.refs import AnyRef, CallRef, parse_uri from weave.trace.rich_container import AbstractRichContainer from weave.trace.vals import WeaveObject diff --git a/weave/trace/tests/test_vals.py b/weave/trace/tests/test_vals.py index 37a3f9c75d4..32e1b815fed 100644 --- a/weave/trace/tests/test_vals.py +++ b/weave/trace/tests/test_vals.py @@ -31,6 +31,6 @@ def my_op(obj: MyObj) -> None: # simulate a situation where the client is closed # but a reference to a trace object still exists. - weave.client_context.weave_client.set_weave_client_global(None) + weave.trace.client_context.weave_client.set_weave_client_global(None) assert my_obj.val == 1 diff --git a/weave/trace/vals.py b/weave/trace/vals.py index c92f9a024ec..a54d01b0626 100644 --- a/weave/trace/vals.py +++ b/weave/trace/vals.py @@ -8,8 +8,8 @@ from pydantic import BaseModel from pydantic import v1 as pydantic_v1 -from weave.client_context.weave_client import get_weave_client from weave.trace import box +from weave.trace.client_context.weave_client import get_weave_client from weave.trace.errors import InternalError from weave.trace.object_record import ObjectRecord from weave.trace.op import Op, call, maybe_bind_method diff --git a/weave/trace/weave_client.py b/weave/trace/weave_client.py index b856c059df4..11029cc64fd 100644 --- a/weave/trace/weave_client.py +++ b/weave/trace/weave_client.py @@ -10,9 +10,9 @@ from requests import HTTPError from weave import version -from weave.client_context import weave_client as weave_client_context from weave.legacy import urls from weave.trace import call_context, trace_sentry +from weave.trace.client_context import weave_client as weave_client_context from weave.trace.exception import exception_to_json_str from weave.trace.feedback import FeedbackQuery, RefFeedbackQuery from weave.trace.object_record import ( diff --git a/weave/trace/weave_init.py b/weave/trace/weave_init.py index 2bf83c97080..07de4b40045 100644 --- a/weave/trace/weave_init.py +++ b/weave/trace/weave_init.py @@ -1,8 +1,8 @@ import typing -from weave.client_context import weave_client as weave_client_context from weave.legacy import errors from weave.trace import autopatch, init_message, trace_sentry, weave_client +from weave.trace.client_context import weave_client as weave_client_context from weave.trace_server import remote_http_trace_server, sqlite_trace_server _current_inited_client = None From 8825fa6efe002f74d6084662a43d72a934afe724 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Wed, 21 Aug 2024 20:15:23 -0400 Subject: [PATCH 54/84] delete: extraneous files --- data/paul_graham/paul_graham_essay.txt | 353 ------------------------- my_patch.patch | 13 - 2 files changed, 366 deletions(-) delete mode 100644 data/paul_graham/paul_graham_essay.txt delete mode 100644 my_patch.patch diff --git a/data/paul_graham/paul_graham_essay.txt b/data/paul_graham/paul_graham_essay.txt deleted file mode 100644 index 6ebd8587939..00000000000 --- a/data/paul_graham/paul_graham_essay.txt +++ /dev/null @@ -1,353 +0,0 @@ - - -What I Worked On - -February 2021 - -Before college the two main things I worked on, outside of school, were writing and programming. I didn't write essays. I wrote what beginning writers were supposed to write then, and probably still are: short stories. My stories were awful. They had hardly any plot, just characters with strong feelings, which I imagined made them deep. - -The first programs I tried writing were on the IBM 1401 that our school district used for what was then called "data processing." This was in 9th grade, so I was 13 or 14. The school district's 1401 happened to be in the basement of our junior high school, and my friend Rich Draves and I got permission to use it. It was like a mini Bond villain's lair down there, with all these alien-looking machines — CPU, disk drives, printer, card reader — sitting up on a raised floor under bright fluorescent lights. - -The language we used was an early version of Fortran. You had to type programs on punch cards, then stack them in the card reader and press a button to load the program into memory and run it. The result would ordinarily be to print something on the spectacularly loud printer. - -I was puzzled by the 1401. I couldn't figure out what to do with it. And in retrospect there's not much I could have done with it. The only form of input to programs was data stored on punched cards, and I didn't have any data stored on punched cards. The only other option was to do things that didn't rely on any input, like calculate approximations of pi, but I didn't know enough math to do anything interesting of that type. So I'm not surprised I can't remember any programs I wrote, because they can't have done much. My clearest memory is of the moment I learned it was possible for programs not to terminate, when one of mine didn't. On a machine without time-sharing, this was a social as well as a technical error, as the data center manager's expression made clear. - -With microcomputers, everything changed. Now you could have a computer sitting right in front of you, on a desk, that could respond to your keystrokes as it was running instead of just churning through a stack of punch cards and then stopping. [1] - -The first of my friends to get a microcomputer built it himself. It was sold as a kit by Heathkit. I remember vividly how impressed and envious I felt watching him sitting in front of it, typing programs right into the computer. - -Computers were expensive in those days and it took me years of nagging before I convinced my father to buy one, a TRS-80, in about 1980. The gold standard then was the Apple II, but a TRS-80 was good enough. This was when I really started programming. I wrote simple games, a program to predict how high my model rockets would fly, and a word processor that my father used to write at least one book. There was only room in memory for about 2 pages of text, so he'd write 2 pages at a time and then print them out, but it was a lot better than a typewriter. - -Though I liked programming, I didn't plan to study it in college. In college I was going to study philosophy, which sounded much more powerful. It seemed, to my naive high school self, to be the study of the ultimate truths, compared to which the things studied in other fields would be mere domain knowledge. What I discovered when I got to college was that the other fields took up so much of the space of ideas that there wasn't much left for these supposed ultimate truths. All that seemed left for philosophy were edge cases that people in other fields felt could safely be ignored. - -I couldn't have put this into words when I was 18. All I knew at the time was that I kept taking philosophy courses and they kept being boring. So I decided to switch to AI. - -AI was in the air in the mid 1980s, but there were two things especially that made me want to work on it: a novel by Heinlein called The Moon is a Harsh Mistress, which featured an intelligent computer called Mike, and a PBS documentary that showed Terry Winograd using SHRDLU. I haven't tried rereading The Moon is a Harsh Mistress, so I don't know how well it has aged, but when I read it I was drawn entirely into its world. It seemed only a matter of time before we'd have Mike, and when I saw Winograd using SHRDLU, it seemed like that time would be a few years at most. All you had to do was teach SHRDLU more words. - -There weren't any classes in AI at Cornell then, not even graduate classes, so I started trying to teach myself. Which meant learning Lisp, since in those days Lisp was regarded as the language of AI. The commonly used programming languages then were pretty primitive, and programmers' ideas correspondingly so. The default language at Cornell was a Pascal-like language called PL/I, and the situation was similar elsewhere. Learning Lisp expanded my concept of a program so fast that it was years before I started to have a sense of where the new limits were. This was more like it; this was what I had expected college to do. It wasn't happening in a class, like it was supposed to, but that was ok. For the next couple years I was on a roll. I knew what I was going to do. - -For my undergraduate thesis, I reverse-engineered SHRDLU. My God did I love working on that program. It was a pleasing bit of code, but what made it even more exciting was my belief — hard to imagine now, but not unique in 1985 — that it was already climbing the lower slopes of intelligence. - -I had gotten into a program at Cornell that didn't make you choose a major. You could take whatever classes you liked, and choose whatever you liked to put on your degree. I of course chose "Artificial Intelligence." When I got the actual physical diploma, I was dismayed to find that the quotes had been included, which made them read as scare-quotes. At the time this bothered me, but now it seems amusingly accurate, for reasons I was about to discover. - -I applied to 3 grad schools: MIT and Yale, which were renowned for AI at the time, and Harvard, which I'd visited because Rich Draves went there, and was also home to Bill Woods, who'd invented the type of parser I used in my SHRDLU clone. Only Harvard accepted me, so that was where I went. - -I don't remember the moment it happened, or if there even was a specific moment, but during the first year of grad school I realized that AI, as practiced at the time, was a hoax. By which I mean the sort of AI in which a program that's told "the dog is sitting on the chair" translates this into some formal representation and adds it to the list of things it knows. - -What these programs really showed was that there's a subset of natural language that's a formal language. But a very proper subset. It was clear that there was an unbridgeable gap between what they could do and actually understanding natural language. It was not, in fact, simply a matter of teaching SHRDLU more words. That whole way of doing AI, with explicit data structures representing concepts, was not going to work. Its brokenness did, as so often happens, generate a lot of opportunities to write papers about various band-aids that could be applied to it, but it was never going to get us Mike. - -So I looked around to see what I could salvage from the wreckage of my plans, and there was Lisp. I knew from experience that Lisp was interesting for its own sake and not just for its association with AI, even though that was the main reason people cared about it at the time. So I decided to focus on Lisp. In fact, I decided to write a book about Lisp hacking. It's scary to think how little I knew about Lisp hacking when I started writing that book. But there's nothing like writing a book about something to help you learn it. The book, On Lisp, wasn't published till 1993, but I wrote much of it in grad school. - -Computer Science is an uneasy alliance between two halves, theory and systems. The theory people prove things, and the systems people build things. I wanted to build things. I had plenty of respect for theory — indeed, a sneaking suspicion that it was the more admirable of the two halves — but building things seemed so much more exciting. - -The problem with systems work, though, was that it didn't last. Any program you wrote today, no matter how good, would be obsolete in a couple decades at best. People might mention your software in footnotes, but no one would actually use it. And indeed, it would seem very feeble work. Only people with a sense of the history of the field would even realize that, in its time, it had been good. - -There were some surplus Xerox Dandelions floating around the computer lab at one point. Anyone who wanted one to play around with could have one. I was briefly tempted, but they were so slow by present standards; what was the point? No one else wanted one either, so off they went. That was what happened to systems work. - -I wanted not just to build things, but to build things that would last. - -In this dissatisfied state I went in 1988 to visit Rich Draves at CMU, where he was in grad school. One day I went to visit the Carnegie Institute, where I'd spent a lot of time as a kid. While looking at a painting there I realized something that might seem obvious, but was a big surprise to me. There, right on the wall, was something you could make that would last. Paintings didn't become obsolete. Some of the best ones were hundreds of years old. - -And moreover this was something you could make a living doing. Not as easily as you could by writing software, of course, but I thought if you were really industrious and lived really cheaply, it had to be possible to make enough to survive. And as an artist you could be truly independent. You wouldn't have a boss, or even need to get research funding. - -I had always liked looking at paintings. Could I make them? I had no idea. I'd never imagined it was even possible. I knew intellectually that people made art — that it didn't just appear spontaneously — but it was as if the people who made it were a different species. They either lived long ago or were mysterious geniuses doing strange things in profiles in Life magazine. The idea of actually being able to make art, to put that verb before that noun, seemed almost miraculous. - -That fall I started taking art classes at Harvard. Grad students could take classes in any department, and my advisor, Tom Cheatham, was very easy going. If he even knew about the strange classes I was taking, he never said anything. - -So now I was in a PhD program in computer science, yet planning to be an artist, yet also genuinely in love with Lisp hacking and working away at On Lisp. In other words, like many a grad student, I was working energetically on multiple projects that were not my thesis. - -I didn't see a way out of this situation. I didn't want to drop out of grad school, but how else was I going to get out? I remember when my friend Robert Morris got kicked out of Cornell for writing the internet worm of 1988, I was envious that he'd found such a spectacular way to get out of grad school. - -Then one day in April 1990 a crack appeared in the wall. I ran into professor Cheatham and he asked if I was far enough along to graduate that June. I didn't have a word of my dissertation written, but in what must have been the quickest bit of thinking in my life, I decided to take a shot at writing one in the 5 weeks or so that remained before the deadline, reusing parts of On Lisp where I could, and I was able to respond, with no perceptible delay "Yes, I think so. I'll give you something to read in a few days." - -I picked applications of continuations as the topic. In retrospect I should have written about macros and embedded languages. There's a whole world there that's barely been explored. But all I wanted was to get out of grad school, and my rapidly written dissertation sufficed, just barely. - -Meanwhile I was applying to art schools. I applied to two: RISD in the US, and the Accademia di Belli Arti in Florence, which, because it was the oldest art school, I imagined would be good. RISD accepted me, and I never heard back from the Accademia, so off to Providence I went. - -I'd applied for the BFA program at RISD, which meant in effect that I had to go to college again. This was not as strange as it sounds, because I was only 25, and art schools are full of people of different ages. RISD counted me as a transfer sophomore and said I had to do the foundation that summer. The foundation means the classes that everyone has to take in fundamental subjects like drawing, color, and design. - -Toward the end of the summer I got a big surprise: a letter from the Accademia, which had been delayed because they'd sent it to Cambridge England instead of Cambridge Massachusetts, inviting me to take the entrance exam in Florence that fall. This was now only weeks away. My nice landlady let me leave my stuff in her attic. I had some money saved from consulting work I'd done in grad school; there was probably enough to last a year if I lived cheaply. Now all I had to do was learn Italian. - -Only stranieri (foreigners) had to take this entrance exam. In retrospect it may well have been a way of excluding them, because there were so many stranieri attracted by the idea of studying art in Florence that the Italian students would otherwise have been outnumbered. I was in decent shape at painting and drawing from the RISD foundation that summer, but I still don't know how I managed to pass the written exam. I remember that I answered the essay question by writing about Cezanne, and that I cranked up the intellectual level as high as I could to make the most of my limited vocabulary. [2] - -I'm only up to age 25 and already there are such conspicuous patterns. Here I was, yet again about to attend some august institution in the hopes of learning about some prestigious subject, and yet again about to be disappointed. The students and faculty in the painting department at the Accademia were the nicest people you could imagine, but they had long since arrived at an arrangement whereby the students wouldn't require the faculty to teach anything, and in return the faculty wouldn't require the students to learn anything. And at the same time all involved would adhere outwardly to the conventions of a 19th century atelier. We actually had one of those little stoves, fed with kindling, that you see in 19th century studio paintings, and a nude model sitting as close to it as possible without getting burned. Except hardly anyone else painted her besides me. The rest of the students spent their time chatting or occasionally trying to imitate things they'd seen in American art magazines. - -Our model turned out to live just down the street from me. She made a living from a combination of modelling and making fakes for a local antique dealer. She'd copy an obscure old painting out of a book, and then he'd take the copy and maltreat it to make it look old. [3] - -While I was a student at the Accademia I started painting still lives in my bedroom at night. These paintings were tiny, because the room was, and because I painted them on leftover scraps of canvas, which was all I could afford at the time. Painting still lives is different from painting people, because the subject, as its name suggests, can't move. People can't sit for more than about 15 minutes at a time, and when they do they don't sit very still. So the traditional m.o. for painting people is to know how to paint a generic person, which you then modify to match the specific person you're painting. Whereas a still life you can, if you want, copy pixel by pixel from what you're seeing. You don't want to stop there, of course, or you get merely photographic accuracy, and what makes a still life interesting is that it's been through a head. You want to emphasize the visual cues that tell you, for example, that the reason the color changes suddenly at a certain point is that it's the edge of an object. By subtly emphasizing such things you can make paintings that are more realistic than photographs not just in some metaphorical sense, but in the strict information-theoretic sense. [4] - -I liked painting still lives because I was curious about what I was seeing. In everyday life, we aren't consciously aware of much we're seeing. Most visual perception is handled by low-level processes that merely tell your brain "that's a water droplet" without telling you details like where the lightest and darkest points are, or "that's a bush" without telling you the shape and position of every leaf. This is a feature of brains, not a bug. In everyday life it would be distracting to notice every leaf on every bush. But when you have to paint something, you have to look more closely, and when you do there's a lot to see. You can still be noticing new things after days of trying to paint something people usually take for granted, just as you can after days of trying to write an essay about something people usually take for granted. - -This is not the only way to paint. I'm not 100% sure it's even a good way to paint. But it seemed a good enough bet to be worth trying. - -Our teacher, professor Ulivi, was a nice guy. He could see I worked hard, and gave me a good grade, which he wrote down in a sort of passport each student had. But the Accademia wasn't teaching me anything except Italian, and my money was running out, so at the end of the first year I went back to the US. - -I wanted to go back to RISD, but I was now broke and RISD was very expensive, so I decided to get a job for a year and then return to RISD the next fall. I got one at a company called Interleaf, which made software for creating documents. You mean like Microsoft Word? Exactly. That was how I learned that low end software tends to eat high end software. But Interleaf still had a few years to live yet. [5] - -Interleaf had done something pretty bold. Inspired by Emacs, they'd added a scripting language, and even made the scripting language a dialect of Lisp. Now they wanted a Lisp hacker to write things in it. This was the closest thing I've had to a normal job, and I hereby apologize to my boss and coworkers, because I was a bad employee. Their Lisp was the thinnest icing on a giant C cake, and since I didn't know C and didn't want to learn it, I never understood most of the software. Plus I was terribly irresponsible. This was back when a programming job meant showing up every day during certain working hours. That seemed unnatural to me, and on this point the rest of the world is coming around to my way of thinking, but at the time it caused a lot of friction. Toward the end of the year I spent much of my time surreptitiously working on On Lisp, which I had by this time gotten a contract to publish. - -The good part was that I got paid huge amounts of money, especially by art student standards. In Florence, after paying my part of the rent, my budget for everything else had been $7 a day. Now I was getting paid more than 4 times that every hour, even when I was just sitting in a meeting. By living cheaply I not only managed to save enough to go back to RISD, but also paid off my college loans. - -I learned some useful things at Interleaf, though they were mostly about what not to do. I learned that it's better for technology companies to be run by product people than sales people (though sales is a real skill and people who are good at it are really good at it), that it leads to bugs when code is edited by too many people, that cheap office space is no bargain if it's depressing, that planned meetings are inferior to corridor conversations, that big, bureaucratic customers are a dangerous source of money, and that there's not much overlap between conventional office hours and the optimal time for hacking, or conventional offices and the optimal place for it. - -But the most important thing I learned, and which I used in both Viaweb and Y Combinator, is that the low end eats the high end: that it's good to be the "entry level" option, even though that will be less prestigious, because if you're not, someone else will be, and will squash you against the ceiling. Which in turn means that prestige is a danger sign. - -When I left to go back to RISD the next fall, I arranged to do freelance work for the group that did projects for customers, and this was how I survived for the next several years. When I came back to visit for a project later on, someone told me about a new thing called HTML, which was, as he described it, a derivative of SGML. Markup language enthusiasts were an occupational hazard at Interleaf and I ignored him, but this HTML thing later became a big part of my life. - -In the fall of 1992 I moved back to Providence to continue at RISD. The foundation had merely been intro stuff, and the Accademia had been a (very civilized) joke. Now I was going to see what real art school was like. But alas it was more like the Accademia than not. Better organized, certainly, and a lot more expensive, but it was now becoming clear that art school did not bear the same relationship to art that medical school bore to medicine. At least not the painting department. The textile department, which my next door neighbor belonged to, seemed to be pretty rigorous. No doubt illustration and architecture were too. But painting was post-rigorous. Painting students were supposed to express themselves, which to the more worldly ones meant to try to cook up some sort of distinctive signature style. - -A signature style is the visual equivalent of what in show business is known as a "schtick": something that immediately identifies the work as yours and no one else's. For example, when you see a painting that looks like a certain kind of cartoon, you know it's by Roy Lichtenstein. So if you see a big painting of this type hanging in the apartment of a hedge fund manager, you know he paid millions of dollars for it. That's not always why artists have a signature style, but it's usually why buyers pay a lot for such work. [6] - -There were plenty of earnest students too: kids who "could draw" in high school, and now had come to what was supposed to be the best art school in the country, to learn to draw even better. They tended to be confused and demoralized by what they found at RISD, but they kept going, because painting was what they did. I was not one of the kids who could draw in high school, but at RISD I was definitely closer to their tribe than the tribe of signature style seekers. - -I learned a lot in the color class I took at RISD, but otherwise I was basically teaching myself to paint, and I could do that for free. So in 1993 I dropped out. I hung around Providence for a bit, and then my college friend Nancy Parmet did me a big favor. A rent-controlled apartment in a building her mother owned in New York was becoming vacant. Did I want it? It wasn't much more than my current place, and New York was supposed to be where the artists were. So yes, I wanted it! [7] - -Asterix comics begin by zooming in on a tiny corner of Roman Gaul that turns out not to be controlled by the Romans. You can do something similar on a map of New York City: if you zoom in on the Upper East Side, there's a tiny corner that's not rich, or at least wasn't in 1993. It's called Yorkville, and that was my new home. Now I was a New York artist — in the strictly technical sense of making paintings and living in New York. - -I was nervous about money, because I could sense that Interleaf was on the way down. Freelance Lisp hacking work was very rare, and I didn't want to have to program in another language, which in those days would have meant C++ if I was lucky. So with my unerring nose for financial opportunity, I decided to write another book on Lisp. This would be a popular book, the sort of book that could be used as a textbook. I imagined myself living frugally off the royalties and spending all my time painting. (The painting on the cover of this book, ANSI Common Lisp, is one that I painted around this time.) - -The best thing about New York for me was the presence of Idelle and Julian Weber. Idelle Weber was a painter, one of the early photorealists, and I'd taken her painting class at Harvard. I've never known a teacher more beloved by her students. Large numbers of former students kept in touch with her, including me. After I moved to New York I became her de facto studio assistant. - -She liked to paint on big, square canvases, 4 to 5 feet on a side. One day in late 1994 as I was stretching one of these monsters there was something on the radio about a famous fund manager. He wasn't that much older than me, and was super rich. The thought suddenly occurred to me: why don't I become rich? Then I'll be able to work on whatever I want. - -Meanwhile I'd been hearing more and more about this new thing called the World Wide Web. Robert Morris showed it to me when I visited him in Cambridge, where he was now in grad school at Harvard. It seemed to me that the web would be a big deal. I'd seen what graphical user interfaces had done for the popularity of microcomputers. It seemed like the web would do the same for the internet. - -If I wanted to get rich, here was the next train leaving the station. I was right about that part. What I got wrong was the idea. I decided we should start a company to put art galleries online. I can't honestly say, after reading so many Y Combinator applications, that this was the worst startup idea ever, but it was up there. Art galleries didn't want to be online, and still don't, not the fancy ones. That's not how they sell. I wrote some software to generate web sites for galleries, and Robert wrote some to resize images and set up an http server to serve the pages. Then we tried to sign up galleries. To call this a difficult sale would be an understatement. It was difficult to give away. A few galleries let us make sites for them for free, but none paid us. - -Then some online stores started to appear, and I realized that except for the order buttons they were identical to the sites we'd been generating for galleries. This impressive-sounding thing called an "internet storefront" was something we already knew how to build. - -So in the summer of 1995, after I submitted the camera-ready copy of ANSI Common Lisp to the publishers, we started trying to write software to build online stores. At first this was going to be normal desktop software, which in those days meant Windows software. That was an alarming prospect, because neither of us knew how to write Windows software or wanted to learn. We lived in the Unix world. But we decided we'd at least try writing a prototype store builder on Unix. Robert wrote a shopping cart, and I wrote a new site generator for stores — in Lisp, of course. - -We were working out of Robert's apartment in Cambridge. His roommate was away for big chunks of time, during which I got to sleep in his room. For some reason there was no bed frame or sheets, just a mattress on the floor. One morning as I was lying on this mattress I had an idea that made me sit up like a capital L. What if we ran the software on the server, and let users control it by clicking on links? Then we'd never have to write anything to run on users' computers. We could generate the sites on the same server we'd serve them from. Users wouldn't need anything more than a browser. - -This kind of software, known as a web app, is common now, but at the time it wasn't clear that it was even possible. To find out, we decided to try making a version of our store builder that you could control through the browser. A couple days later, on August 12, we had one that worked. The UI was horrible, but it proved you could build a whole store through the browser, without any client software or typing anything into the command line on the server. - -Now we felt like we were really onto something. I had visions of a whole new generation of software working this way. You wouldn't need versions, or ports, or any of that crap. At Interleaf there had been a whole group called Release Engineering that seemed to be at least as big as the group that actually wrote the software. Now you could just update the software right on the server. - -We started a new company we called Viaweb, after the fact that our software worked via the web, and we got $10,000 in seed funding from Idelle's husband Julian. In return for that and doing the initial legal work and giving us business advice, we gave him 10% of the company. Ten years later this deal became the model for Y Combinator's. We knew founders needed something like this, because we'd needed it ourselves. - -At this stage I had a negative net worth, because the thousand dollars or so I had in the bank was more than counterbalanced by what I owed the government in taxes. (Had I diligently set aside the proper proportion of the money I'd made consulting for Interleaf? No, I had not.) So although Robert had his graduate student stipend, I needed that seed funding to live on. - -We originally hoped to launch in September, but we got more ambitious about the software as we worked on it. Eventually we managed to build a WYSIWYG site builder, in the sense that as you were creating pages, they looked exactly like the static ones that would be generated later, except that instead of leading to static pages, the links all referred to closures stored in a hash table on the server. - -It helped to have studied art, because the main goal of an online store builder is to make users look legit, and the key to looking legit is high production values. If you get page layouts and fonts and colors right, you can make a guy running a store out of his bedroom look more legit than a big company. - -(If you're curious why my site looks so old-fashioned, it's because it's still made with this software. It may look clunky today, but in 1996 it was the last word in slick.) - -In September, Robert rebelled. "We've been working on this for a month," he said, "and it's still not done." This is funny in retrospect, because he would still be working on it almost 3 years later. But I decided it might be prudent to recruit more programmers, and I asked Robert who else in grad school with him was really good. He recommended Trevor Blackwell, which surprised me at first, because at that point I knew Trevor mainly for his plan to reduce everything in his life to a stack of notecards, which he carried around with him. But Rtm was right, as usual. Trevor turned out to be a frighteningly effective hacker. - -It was a lot of fun working with Robert and Trevor. They're the two most independent-minded people I know, and in completely different ways. If you could see inside Rtm's brain it would look like a colonial New England church, and if you could see inside Trevor's it would look like the worst excesses of Austrian Rococo. - -We opened for business, with 6 stores, in January 1996. It was just as well we waited a few months, because although we worried we were late, we were actually almost fatally early. There was a lot of talk in the press then about ecommerce, but not many people actually wanted online stores. [8] - -There were three main parts to the software: the editor, which people used to build sites and which I wrote, the shopping cart, which Robert wrote, and the manager, which kept track of orders and statistics, and which Trevor wrote. In its time, the editor was one of the best general-purpose site builders. I kept the code tight and didn't have to integrate with any other software except Robert's and Trevor's, so it was quite fun to work on. If all I'd had to do was work on this software, the next 3 years would have been the easiest of my life. Unfortunately I had to do a lot more, all of it stuff I was worse at than programming, and the next 3 years were instead the most stressful. - -There were a lot of startups making ecommerce software in the second half of the 90s. We were determined to be the Microsoft Word, not the Interleaf. Which meant being easy to use and inexpensive. It was lucky for us that we were poor, because that caused us to make Viaweb even more inexpensive than we realized. We charged $100 a month for a small store and $300 a month for a big one. This low price was a big attraction, and a constant thorn in the sides of competitors, but it wasn't because of some clever insight that we set the price low. We had no idea what businesses paid for things. $300 a month seemed like a lot of money to us. - -We did a lot of things right by accident like that. For example, we did what's now called "doing things that don't scale," although at the time we would have described it as "being so lame that we're driven to the most desperate measures to get users." The most common of which was building stores for them. This seemed particularly humiliating, since the whole raison d'etre of our software was that people could use it to make their own stores. But anything to get users. - -We learned a lot more about retail than we wanted to know. For example, that if you could only have a small image of a man's shirt (and all images were small then by present standards), it was better to have a closeup of the collar than a picture of the whole shirt. The reason I remember learning this was that it meant I had to rescan about 30 images of men's shirts. My first set of scans were so beautiful too. - -Though this felt wrong, it was exactly the right thing to be doing. Building stores for users taught us about retail, and about how it felt to use our software. I was initially both mystified and repelled by "business" and thought we needed a "business person" to be in charge of it, but once we started to get users, I was converted, in much the same way I was converted to fatherhood once I had kids. Whatever users wanted, I was all theirs. Maybe one day we'd have so many users that I couldn't scan their images for them, but in the meantime there was nothing more important to do. - -Another thing I didn't get at the time is that growth rate is the ultimate test of a startup. Our growth rate was fine. We had about 70 stores at the end of 1996 and about 500 at the end of 1997. I mistakenly thought the thing that mattered was the absolute number of users. And that is the thing that matters in the sense that that's how much money you're making, and if you're not making enough, you might go out of business. But in the long term the growth rate takes care of the absolute number. If we'd been a startup I was advising at Y Combinator, I would have said: Stop being so stressed out, because you're doing fine. You're growing 7x a year. Just don't hire too many more people and you'll soon be profitable, and then you'll control your own destiny. - -Alas I hired lots more people, partly because our investors wanted me to, and partly because that's what startups did during the Internet Bubble. A company with just a handful of employees would have seemed amateurish. So we didn't reach breakeven until about when Yahoo bought us in the summer of 1998. Which in turn meant we were at the mercy of investors for the entire life of the company. And since both we and our investors were noobs at startups, the result was a mess even by startup standards. - -It was a huge relief when Yahoo bought us. In principle our Viaweb stock was valuable. It was a share in a business that was profitable and growing rapidly. But it didn't feel very valuable to me; I had no idea how to value a business, but I was all too keenly aware of the near-death experiences we seemed to have every few months. Nor had I changed my grad student lifestyle significantly since we started. So when Yahoo bought us it felt like going from rags to riches. Since we were going to California, I bought a car, a yellow 1998 VW GTI. I remember thinking that its leather seats alone were by far the most luxurious thing I owned. - -The next year, from the summer of 1998 to the summer of 1999, must have been the least productive of my life. I didn't realize it at the time, but I was worn out from the effort and stress of running Viaweb. For a while after I got to California I tried to continue my usual m.o. of programming till 3 in the morning, but fatigue combined with Yahoo's prematurely aged culture and grim cube farm in Santa Clara gradually dragged me down. After a few months it felt disconcertingly like working at Interleaf. - -Yahoo had given us a lot of options when they bought us. At the time I thought Yahoo was so overvalued that they'd never be worth anything, but to my astonishment the stock went up 5x in the next year. I hung on till the first chunk of options vested, then in the summer of 1999 I left. It had been so long since I'd painted anything that I'd half forgotten why I was doing this. My brain had been entirely full of software and men's shirts for 4 years. But I had done this to get rich so I could paint, I reminded myself, and now I was rich, so I should go paint. - -When I said I was leaving, my boss at Yahoo had a long conversation with me about my plans. I told him all about the kinds of pictures I wanted to paint. At the time I was touched that he took such an interest in me. Now I realize it was because he thought I was lying. My options at that point were worth about $2 million a month. If I was leaving that kind of money on the table, it could only be to go and start some new startup, and if I did, I might take people with me. This was the height of the Internet Bubble, and Yahoo was ground zero of it. My boss was at that moment a billionaire. Leaving then to start a new startup must have seemed to him an insanely, and yet also plausibly, ambitious plan. - -But I really was quitting to paint, and I started immediately. There was no time to lose. I'd already burned 4 years getting rich. Now when I talk to founders who are leaving after selling their companies, my advice is always the same: take a vacation. That's what I should have done, just gone off somewhere and done nothing for a month or two, but the idea never occurred to me. - -So I tried to paint, but I just didn't seem to have any energy or ambition. Part of the problem was that I didn't know many people in California. I'd compounded this problem by buying a house up in the Santa Cruz Mountains, with a beautiful view but miles from anywhere. I stuck it out for a few more months, then in desperation I went back to New York, where unless you understand about rent control you'll be surprised to hear I still had my apartment, sealed up like a tomb of my old life. Idelle was in New York at least, and there were other people trying to paint there, even though I didn't know any of them. - -When I got back to New York I resumed my old life, except now I was rich. It was as weird as it sounds. I resumed all my old patterns, except now there were doors where there hadn't been. Now when I was tired of walking, all I had to do was raise my hand, and (unless it was raining) a taxi would stop to pick me up. Now when I walked past charming little restaurants I could go in and order lunch. It was exciting for a while. Painting started to go better. I experimented with a new kind of still life where I'd paint one painting in the old way, then photograph it and print it, blown up, on canvas, and then use that as the underpainting for a second still life, painted from the same objects (which hopefully hadn't rotted yet). - -Meanwhile I looked for an apartment to buy. Now I could actually choose what neighborhood to live in. Where, I asked myself and various real estate agents, is the Cambridge of New York? Aided by occasional visits to actual Cambridge, I gradually realized there wasn't one. Huh. - -Around this time, in the spring of 2000, I had an idea. It was clear from our experience with Viaweb that web apps were the future. Why not build a web app for making web apps? Why not let people edit code on our server through the browser, and then host the resulting applications for them? [9] You could run all sorts of services on the servers that these applications could use just by making an API call: making and receiving phone calls, manipulating images, taking credit card payments, etc. - -I got so excited about this idea that I couldn't think about anything else. It seemed obvious that this was the future. I didn't particularly want to start another company, but it was clear that this idea would have to be embodied as one, so I decided to move to Cambridge and start it. I hoped to lure Robert into working on it with me, but there I ran into a hitch. Robert was now a postdoc at MIT, and though he'd made a lot of money the last time I'd lured him into working on one of my schemes, it had also been a huge time sink. So while he agreed that it sounded like a plausible idea, he firmly refused to work on it. - -Hmph. Well, I'd do it myself then. I recruited Dan Giffin, who had worked for Viaweb, and two undergrads who wanted summer jobs, and we got to work trying to build what it's now clear is about twenty companies and several open source projects worth of software. The language for defining applications would of course be a dialect of Lisp. But I wasn't so naive as to assume I could spring an overt Lisp on a general audience; we'd hide the parentheses, like Dylan did. - -By then there was a name for the kind of company Viaweb was, an "application service provider," or ASP. This name didn't last long before it was replaced by "software as a service," but it was current for long enough that I named this new company after it: it was going to be called Aspra. - -I started working on the application builder, Dan worked on network infrastructure, and the two undergrads worked on the first two services (images and phone calls). But about halfway through the summer I realized I really didn't want to run a company — especially not a big one, which it was looking like this would have to be. I'd only started Viaweb because I needed the money. Now that I didn't need money anymore, why was I doing this? If this vision had to be realized as a company, then screw the vision. I'd build a subset that could be done as an open source project. - -Much to my surprise, the time I spent working on this stuff was not wasted after all. After we started Y Combinator, I would often encounter startups working on parts of this new architecture, and it was very useful to have spent so much time thinking about it and even trying to write some of it. - -The subset I would build as an open source project was the new Lisp, whose parentheses I now wouldn't even have to hide. A lot of Lisp hackers dream of building a new Lisp, partly because one of the distinctive features of the language is that it has dialects, and partly, I think, because we have in our minds a Platonic form of Lisp that all existing dialects fall short of. I certainly did. So at the end of the summer Dan and I switched to working on this new dialect of Lisp, which I called Arc, in a house I bought in Cambridge. - -The following spring, lightning struck. I was invited to give a talk at a Lisp conference, so I gave one about how we'd used Lisp at Viaweb. Afterward I put a postscript file of this talk online, on paulgraham.com, which I'd created years before using Viaweb but had never used for anything. In one day it got 30,000 page views. What on earth had happened? The referring urls showed that someone had posted it on Slashdot. [10] - -Wow, I thought, there's an audience. If I write something and put it on the web, anyone can read it. That may seem obvious now, but it was surprising then. In the print era there was a narrow channel to readers, guarded by fierce monsters known as editors. The only way to get an audience for anything you wrote was to get it published as a book, or in a newspaper or magazine. Now anyone could publish anything. - -This had been possible in principle since 1993, but not many people had realized it yet. I had been intimately involved with building the infrastructure of the web for most of that time, and a writer as well, and it had taken me 8 years to realize it. Even then it took me several years to understand the implications. It meant there would be a whole new generation of essays. [11] - -In the print era, the channel for publishing essays had been vanishingly small. Except for a few officially anointed thinkers who went to the right parties in New York, the only people allowed to publish essays were specialists writing about their specialties. There were so many essays that had never been written, because there had been no way to publish them. Now they could be, and I was going to write them. [12] - -I've worked on several different things, but to the extent there was a turning point where I figured out what to work on, it was when I started publishing essays online. From then on I knew that whatever else I did, I'd always write essays too. - -I knew that online essays would be a marginal medium at first. Socially they'd seem more like rants posted by nutjobs on their GeoCities sites than the genteel and beautifully typeset compositions published in The New Yorker. But by this point I knew enough to find that encouraging instead of discouraging. - -One of the most conspicuous patterns I've noticed in my life is how well it has worked, for me at least, to work on things that weren't prestigious. Still life has always been the least prestigious form of painting. Viaweb and Y Combinator both seemed lame when we started them. I still get the glassy eye from strangers when they ask what I'm writing, and I explain that it's an essay I'm going to publish on my web site. Even Lisp, though prestigious intellectually in something like the way Latin is, also seems about as hip. - -It's not that unprestigious types of work are good per se. But when you find yourself drawn to some kind of work despite its current lack of prestige, it's a sign both that there's something real to be discovered there, and that you have the right kind of motives. Impure motives are a big danger for the ambitious. If anything is going to lead you astray, it will be the desire to impress people. So while working on things that aren't prestigious doesn't guarantee you're on the right track, it at least guarantees you're not on the most common type of wrong one. - -Over the next several years I wrote lots of essays about all kinds of different topics. O'Reilly reprinted a collection of them as a book, called Hackers & Painters after one of the essays in it. I also worked on spam filters, and did some more painting. I used to have dinners for a group of friends every thursday night, which taught me how to cook for groups. And I bought another building in Cambridge, a former candy factory (and later, twas said, porn studio), to use as an office. - -One night in October 2003 there was a big party at my house. It was a clever idea of my friend Maria Daniels, who was one of the thursday diners. Three separate hosts would all invite their friends to one party. So for every guest, two thirds of the other guests would be people they didn't know but would probably like. One of the guests was someone I didn't know but would turn out to like a lot: a woman called Jessica Livingston. A couple days later I asked her out. - -Jessica was in charge of marketing at a Boston investment bank. This bank thought it understood startups, but over the next year, as she met friends of mine from the startup world, she was surprised how different reality was. And how colorful their stories were. So she decided to compile a book of interviews with startup founders. - -When the bank had financial problems and she had to fire half her staff, she started looking for a new job. In early 2005 she interviewed for a marketing job at a Boston VC firm. It took them weeks to make up their minds, and during this time I started telling her about all the things that needed to be fixed about venture capital. They should make a larger number of smaller investments instead of a handful of giant ones, they should be funding younger, more technical founders instead of MBAs, they should let the founders remain as CEO, and so on. - -One of my tricks for writing essays had always been to give talks. The prospect of having to stand up in front of a group of people and tell them something that won't waste their time is a great spur to the imagination. When the Harvard Computer Society, the undergrad computer club, asked me to give a talk, I decided I would tell them how to start a startup. Maybe they'd be able to avoid the worst of the mistakes we'd made. - -So I gave this talk, in the course of which I told them that the best sources of seed funding were successful startup founders, because then they'd be sources of advice too. Whereupon it seemed they were all looking expectantly at me. Horrified at the prospect of having my inbox flooded by business plans (if I'd only known), I blurted out "But not me!" and went on with the talk. But afterward it occurred to me that I should really stop procrastinating about angel investing. I'd been meaning to since Yahoo bought us, and now it was 7 years later and I still hadn't done one angel investment. - -Meanwhile I had been scheming with Robert and Trevor about projects we could work on together. I missed working with them, and it seemed like there had to be something we could collaborate on. - -As Jessica and I were walking home from dinner on March 11, at the corner of Garden and Walker streets, these three threads converged. Screw the VCs who were taking so long to make up their minds. We'd start our own investment firm and actually implement the ideas we'd been talking about. I'd fund it, and Jessica could quit her job and work for it, and we'd get Robert and Trevor as partners too. [13] - -Once again, ignorance worked in our favor. We had no idea how to be angel investors, and in Boston in 2005 there were no Ron Conways to learn from. So we just made what seemed like the obvious choices, and some of the things we did turned out to be novel. - -There are multiple components to Y Combinator, and we didn't figure them all out at once. The part we got first was to be an angel firm. In those days, those two words didn't go together. There were VC firms, which were organized companies with people whose job it was to make investments, but they only did big, million dollar investments. And there were angels, who did smaller investments, but these were individuals who were usually focused on other things and made investments on the side. And neither of them helped founders enough in the beginning. We knew how helpless founders were in some respects, because we remembered how helpless we'd been. For example, one thing Julian had done for us that seemed to us like magic was to get us set up as a company. We were fine writing fairly difficult software, but actually getting incorporated, with bylaws and stock and all that stuff, how on earth did you do that? Our plan was not only to make seed investments, but to do for startups everything Julian had done for us. - -YC was not organized as a fund. It was cheap enough to run that we funded it with our own money. That went right by 99% of readers, but professional investors are thinking "Wow, that means they got all the returns." But once again, this was not due to any particular insight on our part. We didn't know how VC firms were organized. It never occurred to us to try to raise a fund, and if it had, we wouldn't have known where to start. [14] - -The most distinctive thing about YC is the batch model: to fund a bunch of startups all at once, twice a year, and then to spend three months focusing intensively on trying to help them. That part we discovered by accident, not merely implicitly but explicitly due to our ignorance about investing. We needed to get experience as investors. What better way, we thought, than to fund a whole bunch of startups at once? We knew undergrads got temporary jobs at tech companies during the summer. Why not organize a summer program where they'd start startups instead? We wouldn't feel guilty for being in a sense fake investors, because they would in a similar sense be fake founders. So while we probably wouldn't make much money out of it, we'd at least get to practice being investors on them, and they for their part would probably have a more interesting summer than they would working at Microsoft. - -We'd use the building I owned in Cambridge as our headquarters. We'd all have dinner there once a week — on tuesdays, since I was already cooking for the thursday diners on thursdays — and after dinner we'd bring in experts on startups to give talks. - -We knew undergrads were deciding then about summer jobs, so in a matter of days we cooked up something we called the Summer Founders Program, and I posted an announcement on my site, inviting undergrads to apply. I had never imagined that writing essays would be a way to get "deal flow," as investors call it, but it turned out to be the perfect source. [15] We got 225 applications for the Summer Founders Program, and we were surprised to find that a lot of them were from people who'd already graduated, or were about to that spring. Already this SFP thing was starting to feel more serious than we'd intended. - -We invited about 20 of the 225 groups to interview in person, and from those we picked 8 to fund. They were an impressive group. That first batch included reddit, Justin Kan and Emmett Shear, who went on to found Twitch, Aaron Swartz, who had already helped write the RSS spec and would a few years later become a martyr for open access, and Sam Altman, who would later become the second president of YC. I don't think it was entirely luck that the first batch was so good. You had to be pretty bold to sign up for a weird thing like the Summer Founders Program instead of a summer job at a legit place like Microsoft or Goldman Sachs. - -The deal for startups was based on a combination of the deal we did with Julian ($10k for 10%) and what Robert said MIT grad students got for the summer ($6k). We invested $6k per founder, which in the typical two-founder case was $12k, in return for 6%. That had to be fair, because it was twice as good as the deal we ourselves had taken. Plus that first summer, which was really hot, Jessica brought the founders free air conditioners. [16] - -Fairly quickly I realized that we had stumbled upon the way to scale startup funding. Funding startups in batches was more convenient for us, because it meant we could do things for a lot of startups at once, but being part of a batch was better for the startups too. It solved one of the biggest problems faced by founders: the isolation. Now you not only had colleagues, but colleagues who understood the problems you were facing and could tell you how they were solving them. - -As YC grew, we started to notice other advantages of scale. The alumni became a tight community, dedicated to helping one another, and especially the current batch, whose shoes they remembered being in. We also noticed that the startups were becoming one another's customers. We used to refer jokingly to the "YC GDP," but as YC grows this becomes less and less of a joke. Now lots of startups get their initial set of customers almost entirely from among their batchmates. - -I had not originally intended YC to be a full-time job. I was going to do three things: hack, write essays, and work on YC. As YC grew, and I grew more excited about it, it started to take up a lot more than a third of my attention. But for the first few years I was still able to work on other things. - -In the summer of 2006, Robert and I started working on a new version of Arc. This one was reasonably fast, because it was compiled into Scheme. To test this new Arc, I wrote Hacker News in it. It was originally meant to be a news aggregator for startup founders and was called Startup News, but after a few months I got tired of reading about nothing but startups. Plus it wasn't startup founders we wanted to reach. It was future startup founders. So I changed the name to Hacker News and the topic to whatever engaged one's intellectual curiosity. - -HN was no doubt good for YC, but it was also by far the biggest source of stress for me. If all I'd had to do was select and help founders, life would have been so easy. And that implies that HN was a mistake. Surely the biggest source of stress in one's work should at least be something close to the core of the work. Whereas I was like someone who was in pain while running a marathon not from the exertion of running, but because I had a blister from an ill-fitting shoe. When I was dealing with some urgent problem during YC, there was about a 60% chance it had to do with HN, and a 40% chance it had do with everything else combined. [17] - -As well as HN, I wrote all of YC's internal software in Arc. But while I continued to work a good deal in Arc, I gradually stopped working on Arc, partly because I didn't have time to, and partly because it was a lot less attractive to mess around with the language now that we had all this infrastructure depending on it. So now my three projects were reduced to two: writing essays and working on YC. - -YC was different from other kinds of work I've done. Instead of deciding for myself what to work on, the problems came to me. Every 6 months there was a new batch of startups, and their problems, whatever they were, became our problems. It was very engaging work, because their problems were quite varied, and the good founders were very effective. If you were trying to learn the most you could about startups in the shortest possible time, you couldn't have picked a better way to do it. - -There were parts of the job I didn't like. Disputes between cofounders, figuring out when people were lying to us, fighting with people who maltreated the startups, and so on. But I worked hard even at the parts I didn't like. I was haunted by something Kevin Hale once said about companies: "No one works harder than the boss." He meant it both descriptively and prescriptively, and it was the second part that scared me. I wanted YC to be good, so if how hard I worked set the upper bound on how hard everyone else worked, I'd better work very hard. - -One day in 2010, when he was visiting California for interviews, Robert Morris did something astonishing: he offered me unsolicited advice. I can only remember him doing that once before. One day at Viaweb, when I was bent over double from a kidney stone, he suggested that it would be a good idea for him to take me to the hospital. That was what it took for Rtm to offer unsolicited advice. So I remember his exact words very clearly. "You know," he said, "you should make sure Y Combinator isn't the last cool thing you do." - -At the time I didn't understand what he meant, but gradually it dawned on me that he was saying I should quit. This seemed strange advice, because YC was doing great. But if there was one thing rarer than Rtm offering advice, it was Rtm being wrong. So this set me thinking. It was true that on my current trajectory, YC would be the last thing I did, because it was only taking up more of my attention. It had already eaten Arc, and was in the process of eating essays too. Either YC was my life's work or I'd have to leave eventually. And it wasn't, so I would. - -In the summer of 2012 my mother had a stroke, and the cause turned out to be a blood clot caused by colon cancer. The stroke destroyed her balance, and she was put in a nursing home, but she really wanted to get out of it and back to her house, and my sister and I were determined to help her do it. I used to fly up to Oregon to visit her regularly, and I had a lot of time to think on those flights. On one of them I realized I was ready to hand YC over to someone else. - -I asked Jessica if she wanted to be president, but she didn't, so we decided we'd try to recruit Sam Altman. We talked to Robert and Trevor and we agreed to make it a complete changing of the guard. Up till that point YC had been controlled by the original LLC we four had started. But we wanted YC to last for a long time, and to do that it couldn't be controlled by the founders. So if Sam said yes, we'd let him reorganize YC. Robert and I would retire, and Jessica and Trevor would become ordinary partners. - -When we asked Sam if he wanted to be president of YC, initially he said no. He wanted to start a startup to make nuclear reactors. But I kept at it, and in October 2013 he finally agreed. We decided he'd take over starting with the winter 2014 batch. For the rest of 2013 I left running YC more and more to Sam, partly so he could learn the job, and partly because I was focused on my mother, whose cancer had returned. - -She died on January 15, 2014. We knew this was coming, but it was still hard when it did. - -I kept working on YC till March, to help get that batch of startups through Demo Day, then I checked out pretty completely. (I still talk to alumni and to new startups working on things I'm interested in, but that only takes a few hours a week.) - -What should I do next? Rtm's advice hadn't included anything about that. I wanted to do something completely different, so I decided I'd paint. I wanted to see how good I could get if I really focused on it. So the day after I stopped working on YC, I started painting. I was rusty and it took a while to get back into shape, but it was at least completely engaging. [18] - -I spent most of the rest of 2014 painting. I'd never been able to work so uninterruptedly before, and I got to be better than I had been. Not good enough, but better. Then in November, right in the middle of a painting, I ran out of steam. Up till that point I'd always been curious to see how the painting I was working on would turn out, but suddenly finishing this one seemed like a chore. So I stopped working on it and cleaned my brushes and haven't painted since. So far anyway. - -I realize that sounds rather wimpy. But attention is a zero sum game. If you can choose what to work on, and you choose a project that's not the best one (or at least a good one) for you, then it's getting in the way of another project that is. And at 50 there was some opportunity cost to screwing around. - -I started writing essays again, and wrote a bunch of new ones over the next few months. I even wrote a couple that weren't about startups. Then in March 2015 I started working on Lisp again. - -The distinctive thing about Lisp is that its core is a language defined by writing an interpreter in itself. It wasn't originally intended as a programming language in the ordinary sense. It was meant to be a formal model of computation, an alternative to the Turing machine. If you want to write an interpreter for a language in itself, what's the minimum set of predefined operators you need? The Lisp that John McCarthy invented, or more accurately discovered, is an answer to that question. [19] - -McCarthy didn't realize this Lisp could even be used to program computers till his grad student Steve Russell suggested it. Russell translated McCarthy's interpreter into IBM 704 machine language, and from that point Lisp started also to be a programming language in the ordinary sense. But its origins as a model of computation gave it a power and elegance that other languages couldn't match. It was this that attracted me in college, though I didn't understand why at the time. - -McCarthy's 1960 Lisp did nothing more than interpret Lisp expressions. It was missing a lot of things you'd want in a programming language. So these had to be added, and when they were, they weren't defined using McCarthy's original axiomatic approach. That wouldn't have been feasible at the time. McCarthy tested his interpreter by hand-simulating the execution of programs. But it was already getting close to the limit of interpreters you could test that way — indeed, there was a bug in it that McCarthy had overlooked. To test a more complicated interpreter, you'd have had to run it, and computers then weren't powerful enough. - -Now they are, though. Now you could continue using McCarthy's axiomatic approach till you'd defined a complete programming language. And as long as every change you made to McCarthy's Lisp was a discoveredness-preserving transformation, you could, in principle, end up with a complete language that had this quality. Harder to do than to talk about, of course, but if it was possible in principle, why not try? So I decided to take a shot at it. It took 4 years, from March 26, 2015 to October 12, 2019. It was fortunate that I had a precisely defined goal, or it would have been hard to keep at it for so long. - -I wrote this new Lisp, called Bel, in itself in Arc. That may sound like a contradiction, but it's an indication of the sort of trickery I had to engage in to make this work. By means of an egregious collection of hacks I managed to make something close enough to an interpreter written in itself that could actually run. Not fast, but fast enough to test. - -I had to ban myself from writing essays during most of this time, or I'd never have finished. In late 2015 I spent 3 months writing essays, and when I went back to working on Bel I could barely understand the code. Not so much because it was badly written as because the problem is so convoluted. When you're working on an interpreter written in itself, it's hard to keep track of what's happening at what level, and errors can be practically encrypted by the time you get them. - -So I said no more essays till Bel was done. But I told few people about Bel while I was working on it. So for years it must have seemed that I was doing nothing, when in fact I was working harder than I'd ever worked on anything. Occasionally after wrestling for hours with some gruesome bug I'd check Twitter or HN and see someone asking "Does Paul Graham still code?" - -Working on Bel was hard but satisfying. I worked on it so intensively that at any given time I had a decent chunk of the code in my head and could write more there. I remember taking the boys to the coast on a sunny day in 2015 and figuring out how to deal with some problem involving continuations while I watched them play in the tide pools. It felt like I was doing life right. I remember that because I was slightly dismayed at how novel it felt. The good news is that I had more moments like this over the next few years. - -In the summer of 2016 we moved to England. We wanted our kids to see what it was like living in another country, and since I was a British citizen by birth, that seemed the obvious choice. We only meant to stay for a year, but we liked it so much that we still live there. So most of Bel was written in England. - -In the fall of 2019, Bel was finally finished. Like McCarthy's original Lisp, it's a spec rather than an implementation, although like McCarthy's Lisp it's a spec expressed as code. - -Now that I could write essays again, I wrote a bunch about topics I'd had stacked up. I kept writing essays through 2020, but I also started to think about other things I could work on. How should I choose what to do? Well, how had I chosen what to work on in the past? I wrote an essay for myself to answer that question, and I was surprised how long and messy the answer turned out to be. If this surprised me, who'd lived it, then I thought perhaps it would be interesting to other people, and encouraging to those with similarly messy lives. So I wrote a more detailed version for others to read, and this is the last sentence of it. - - - - - - - - - -Notes - -[1] My experience skipped a step in the evolution of computers: time-sharing machines with interactive OSes. I went straight from batch processing to microcomputers, which made microcomputers seem all the more exciting. - -[2] Italian words for abstract concepts can nearly always be predicted from their English cognates (except for occasional traps like polluzione). It's the everyday words that differ. So if you string together a lot of abstract concepts with a few simple verbs, you can make a little Italian go a long way. - -[3] I lived at Piazza San Felice 4, so my walk to the Accademia went straight down the spine of old Florence: past the Pitti, across the bridge, past Orsanmichele, between the Duomo and the Baptistery, and then up Via Ricasoli to Piazza San Marco. I saw Florence at street level in every possible condition, from empty dark winter evenings to sweltering summer days when the streets were packed with tourists. - -[4] You can of course paint people like still lives if you want to, and they're willing. That sort of portrait is arguably the apex of still life painting, though the long sitting does tend to produce pained expressions in the sitters. - -[5] Interleaf was one of many companies that had smart people and built impressive technology, and yet got crushed by Moore's Law. In the 1990s the exponential growth in the power of commodity (i.e. Intel) processors rolled up high-end, special-purpose hardware and software companies like a bulldozer. - -[6] The signature style seekers at RISD weren't specifically mercenary. In the art world, money and coolness are tightly coupled. Anything expensive comes to be seen as cool, and anything seen as cool will soon become equally expensive. - -[7] Technically the apartment wasn't rent-controlled but rent-stabilized, but this is a refinement only New Yorkers would know or care about. The point is that it was really cheap, less than half market price. - -[8] Most software you can launch as soon as it's done. But when the software is an online store builder and you're hosting the stores, if you don't have any users yet, that fact will be painfully obvious. So before we could launch publicly we had to launch privately, in the sense of recruiting an initial set of users and making sure they had decent-looking stores. - -[9] We'd had a code editor in Viaweb for users to define their own page styles. They didn't know it, but they were editing Lisp expressions underneath. But this wasn't an app editor, because the code ran when the merchants' sites were generated, not when shoppers visited them. - -[10] This was the first instance of what is now a familiar experience, and so was what happened next, when I read the comments and found they were full of angry people. How could I claim that Lisp was better than other languages? Weren't they all Turing complete? People who see the responses to essays I write sometimes tell me how sorry they feel for me, but I'm not exaggerating when I reply that it has always been like this, since the very beginning. It comes with the territory. An essay must tell readers things they don't already know, and some people dislike being told such things. - -[11] People put plenty of stuff on the internet in the 90s of course, but putting something online is not the same as publishing it online. Publishing online means you treat the online version as the (or at least a) primary version. - -[12] There is a general lesson here that our experience with Y Combinator also teaches: Customs continue to constrain you long after the restrictions that caused them have disappeared. Customary VC practice had once, like the customs about publishing essays, been based on real constraints. Startups had once been much more expensive to start, and proportionally rare. Now they could be cheap and common, but the VCs' customs still reflected the old world, just as customs about writing essays still reflected the constraints of the print era. - -Which in turn implies that people who are independent-minded (i.e. less influenced by custom) will have an advantage in fields affected by rapid change (where customs are more likely to be obsolete). - -Here's an interesting point, though: you can't always predict which fields will be affected by rapid change. Obviously software and venture capital will be, but who would have predicted that essay writing would be? - -[13] Y Combinator was not the original name. At first we were called Cambridge Seed. But we didn't want a regional name, in case someone copied us in Silicon Valley, so we renamed ourselves after one of the coolest tricks in the lambda calculus, the Y combinator. - -I picked orange as our color partly because it's the warmest, and partly because no VC used it. In 2005 all the VCs used staid colors like maroon, navy blue, and forest green, because they were trying to appeal to LPs, not founders. The YC logo itself is an inside joke: the Viaweb logo had been a white V on a red circle, so I made the YC logo a white Y on an orange square. - -[14] YC did become a fund for a couple years starting in 2009, because it was getting so big I could no longer afford to fund it personally. But after Heroku got bought we had enough money to go back to being self-funded. - -[15] I've never liked the term "deal flow," because it implies that the number of new startups at any given time is fixed. This is not only false, but it's the purpose of YC to falsify it, by causing startups to be founded that would not otherwise have existed. - -[16] She reports that they were all different shapes and sizes, because there was a run on air conditioners and she had to get whatever she could, but that they were all heavier than she could carry now. - -[17] Another problem with HN was a bizarre edge case that occurs when you both write essays and run a forum. When you run a forum, you're assumed to see if not every conversation, at least every conversation involving you. And when you write essays, people post highly imaginative misinterpretations of them on forums. Individually these two phenomena are tedious but bearable, but the combination is disastrous. You actually have to respond to the misinterpretations, because the assumption that you're present in the conversation means that not responding to any sufficiently upvoted misinterpretation reads as a tacit admission that it's correct. But that in turn encourages more; anyone who wants to pick a fight with you senses that now is their chance. - -[18] The worst thing about leaving YC was not working with Jessica anymore. We'd been working on YC almost the whole time we'd known each other, and we'd neither tried nor wanted to separate it from our personal lives, so leaving was like pulling up a deeply rooted tree. - -[19] One way to get more precise about the concept of invented vs discovered is to talk about space aliens. Any sufficiently advanced alien civilization would certainly know about the Pythagorean theorem, for example. I believe, though with less certainty, that they would also know about the Lisp in McCarthy's 1960 paper. - -But if so there's no reason to suppose that this is the limit of the language that might be known to them. Presumably aliens need numbers and errors and I/O too. So it seems likely there exists at least one path out of McCarthy's Lisp along which discoveredness is preserved. - - - -Thanks to Trevor Blackwell, John Collison, Patrick Collison, Daniel Gackle, Ralph Hazell, Jessica Livingston, Robert Morris, and Harj Taggar for reading drafts of this. diff --git a/my_patch.patch b/my_patch.patch deleted file mode 100644 index 04b01bb37f6..00000000000 --- a/my_patch.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/weave/__init__.py b/weave/__init__.py -index b77fa857..a45a1532 100644 ---- a/weave/__init__.py -+++ b/weave/__init__.py -@@ -12,8 +12,6 @@ from .graph import Node # used as a type in op definitions - from .show import show, show_url - from .api import * - --use_frontend_devmode() -- - from . import panels - from .panel import Panel - From 2243f97d3bdfc86773c75363246fbe9bcd937aa5 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Fri, 23 Aug 2024 18:20:23 -0400 Subject: [PATCH 55/84] delete: api; split out trace and query api from single api file --- weave/__init__.py | 16 ++++++---------- weave/api.py | 4 ---- weave/deploy/modal/stub.py | 2 +- weave/tests/legacy/test_api.py | 3 ++- weave/tests/legacy/test_arrow.py | 2 +- weave/tests/legacy/test_arrow_vectorizer.py | 3 +-- weave/tests/legacy/test_async.py | 4 +--- weave/tests/legacy/test_basic_ops.py | 3 +-- weave/tests/legacy/test_compile.py | 3 +-- weave/tests/legacy/test_custom_types.py | 2 +- weave/tests/legacy/test_decorators.py | 3 +-- weave/tests/legacy/test_derive_op.py | 3 ++- weave/tests/legacy/test_examples.py | 3 +-- weave/tests/legacy/test_execute.py | 3 +-- weave/tests/legacy/test_file.py | 4 +--- weave/tests/legacy/test_list_arrow_compat.py | 2 +- weave/tests/legacy/test_media_user.py | 3 +-- weave/tests/legacy/test_mutations.py | 3 +-- weave/tests/legacy/test_node_ref.py | 2 +- weave/tests/legacy/test_op_def.py | 3 +-- weave/tests/legacy/test_partial_object.py | 2 +- weave/tests/legacy/test_run_segment.py | 4 +--- weave/tests/legacy/test_storage.py | 2 +- weave/tests/legacy/test_table_ops.py | 2 +- weave/tests/legacy/test_trace.py | 2 +- weave/tests/legacy/test_wb_domain_types.py | 3 +-- weave/tests/legacy/test_weavejs_fixes.py | 3 +-- weave/tests/list_arrow_test_helpers.py | 3 +-- weave/tests/trace/test_server.py | 2 +- weave/trace/cli.py | 3 +-- 30 files changed, 36 insertions(+), 61 deletions(-) delete mode 100644 weave/api.py diff --git a/weave/__init__.py b/weave/__init__.py index 0ed50283b77..9ea806d2e21 100644 --- a/weave/__init__.py +++ b/weave/__init__.py @@ -13,25 +13,21 @@ _loading_builtins_token = _context_state.set_loading_built_ins() from weave.legacy import weave_types as types -from .legacy import storage - -from .legacy.api import * -from .trace.api import * - -from .legacy.errors import * - +from weave.legacy import storage +from weave.legacy.api import * +from weave.legacy.errors import * from weave.legacy import mappers_python_def - from weave.legacy import wandb_api as _wandb_api +from weave.legacy import context as _context -from . import version +from weave import version _wandb_api.init() # Ensure there is a client available for eager mode -from weave.legacy import context as _context +from weave.trace.api import * _context_state.clear_loading_built_ins(_loading_builtins_token) __version__ = version.VERSION diff --git a/weave/api.py b/weave/api.py deleted file mode 100644 index 892dd0ec968..00000000000 --- a/weave/api.py +++ /dev/null @@ -1,4 +0,0 @@ -"""These are the top-level functions in the `import weave` namespace.""" - -from .legacy.api import * -from .trace.api import * diff --git a/weave/deploy/modal/stub.py b/weave/deploy/modal/stub.py index 2dee6e838e6..89eeff34bcc 100644 --- a/weave/deploy/modal/stub.py +++ b/weave/deploy/modal/stub.py @@ -26,7 +26,7 @@ @stub.function(image=image, secret=Secret.from_dotenv(__file__)) @asgi_app(label=safe_name(uri.name)) def fastapi_app() -> FastAPI: - from weave import api + from weave.trace import api from weave.trace.serve_fastapi import object_method_app uri_ref = parse_uri(os.environ["MODEL_REF"]) diff --git a/weave/tests/legacy/test_api.py b/weave/tests/legacy/test_api.py index dce30746540..75111a6fc8c 100644 --- a/weave/tests/legacy/test_api.py +++ b/weave/tests/legacy/test_api.py @@ -1,6 +1,7 @@ import shutil -from ... import api as weave +from weave.legacy import api as weave + from ...legacy.show import _show_params diff --git a/weave/tests/legacy/test_arrow.py b/weave/tests/legacy/test_arrow.py index 7e8a7703e64..e5554ab165c 100644 --- a/weave/tests/legacy/test_arrow.py +++ b/weave/tests/legacy/test_arrow.py @@ -7,6 +7,7 @@ import pytest from PIL import Image +from weave.legacy import api as weave from weave.legacy import ( box, context_state, @@ -36,7 +37,6 @@ from weave.legacy.ops_primitives import list_, make_list from weave.tests import list_arrow_test_helpers as lath -from ... import api as weave from ...tests import tag_test_util as ttu from ...tests import weavejs_ops from ...tests.legacy import test_wb diff --git a/weave/tests/legacy/test_arrow_vectorizer.py b/weave/tests/legacy/test_arrow_vectorizer.py index 8f41805c840..1bb224fdb4f 100644 --- a/weave/tests/legacy/test_arrow_vectorizer.py +++ b/weave/tests/legacy/test_arrow_vectorizer.py @@ -5,6 +5,7 @@ import pytest from pyarrow import compute as pc +from weave.legacy import api as weave from weave.legacy import box, dispatch, errors, ops, weave_internal from weave.legacy import ops_arrow as arrow from weave.legacy import weave_types as types @@ -18,8 +19,6 @@ from weave.legacy.ops_domain import wb_domain_types as wdt from weave.legacy.ops_primitives import Boolean, Number, date, dict_, list_ -from ... import api as weave - string_ops_test_cases = [ ("eq-scalar", lambda x: x == "bc", [True, False, False]), ("ne-scalar", lambda x: x != "bc", [False, True, True]), diff --git a/weave/tests/legacy/test_async.py b/weave/tests/legacy/test_async.py index 976e7e9398d..e0a9632154e 100644 --- a/weave/tests/legacy/test_async.py +++ b/weave/tests/legacy/test_async.py @@ -1,8 +1,6 @@ import pytest -from weave.legacy import async_demo, ops, runs - -from ... import api, storage +from weave.legacy import api, async_demo, ops, runs, storage def test_run_basic(): diff --git a/weave/tests/legacy/test_basic_ops.py b/weave/tests/legacy/test_basic_ops.py index 19c2d3020b8..e8868da0e03 100644 --- a/weave/tests/legacy/test_basic_ops.py +++ b/weave/tests/legacy/test_basic_ops.py @@ -1,10 +1,9 @@ +from weave.legacy import api as weave from weave.legacy import box, ops from weave.legacy.ops_primitives import number from weave.legacy.ops_primitives.string import * from weave.legacy.weave_internal import make_const_node -from ... import api as weave - def test_number_ops(): nine = make_const_node(weave.types.Number(), 9) diff --git a/weave/tests/legacy/test_compile.py b/weave/tests/legacy/test_compile.py index 2bdde6920af..dc5679d769d 100644 --- a/weave/tests/legacy/test_compile.py +++ b/weave/tests/legacy/test_compile.py @@ -4,14 +4,13 @@ import weave from weave.legacy import async_demo, compile, graph from weave.legacy import weave_types as types +from weave.legacy.api import use from weave.legacy.dispatch import RuntimeOutputNode from weave.legacy.ops_arrow import to_arrow from weave.legacy.ops_arrow.vectorize import raise_on_python_bailout from weave.legacy.wandb_interface.wandb_stream_table import StreamTable from weave.legacy.weave_internal import const, define_fn, make_const_node -from ...api import use - def test_automatic_await_compile(): twelve = async_demo.slowmult(3, 4, 0.01) diff --git a/weave/tests/legacy/test_custom_types.py b/weave/tests/legacy/test_custom_types.py index 5f8940785fa..f5b15ff28ba 100644 --- a/weave/tests/legacy/test_custom_types.py +++ b/weave/tests/legacy/test_custom_types.py @@ -1,10 +1,10 @@ import pytest from PIL import Image +from weave.legacy import api as weave from weave.legacy import context_state as _context from weave.legacy import ops_arrow -from ... import api as weave from ... import errors from .. import geom diff --git a/weave/tests/legacy/test_decorators.py b/weave/tests/legacy/test_decorators.py index cc1a2e1846b..7682136833f 100644 --- a/weave/tests/legacy/test_decorators.py +++ b/weave/tests/legacy/test_decorators.py @@ -1,9 +1,8 @@ +from weave.legacy import api as weave from weave.legacy import storage from weave.legacy import weave_types as types from weave.legacy.decorator_op import op -from ... import api as weave - def test_function_op_name(): @op() diff --git a/weave/tests/legacy/test_derive_op.py b/weave/tests/legacy/test_derive_op.py index 85b86659543..637255a8ca7 100644 --- a/weave/tests/legacy/test_derive_op.py +++ b/weave/tests/legacy/test_derive_op.py @@ -1,4 +1,5 @@ -from ... import api as weave +from weave.legacy import api as weave + from ...legacy import registry_mem diff --git a/weave/tests/legacy/test_examples.py b/weave/tests/legacy/test_examples.py index b9324c781f8..1fc1a60d773 100644 --- a/weave/tests/legacy/test_examples.py +++ b/weave/tests/legacy/test_examples.py @@ -1,10 +1,9 @@ import math import typing +from weave.legacy import api as weave from weave.legacy import context, context_state -from ... import api as weave - class XOnly(typing.TypedDict): x: float diff --git a/weave/tests/legacy/test_execute.py b/weave/tests/legacy/test_execute.py index a36eec66b6b..8c77e72a21e 100644 --- a/weave/tests/legacy/test_execute.py +++ b/weave/tests/legacy/test_execute.py @@ -4,10 +4,9 @@ import pytest import weave -from weave.legacy import environment, execute, ops, weave_internal +from weave.legacy import api, environment, execute, ops, weave_internal from weave.legacy import weave_types as types -from ... import api from . import test_wb execute_test_count_op_run_count = 0 diff --git a/weave/tests/legacy/test_file.py b/weave/tests/legacy/test_file.py index 0fed90136c3..d8561dae6a0 100644 --- a/weave/tests/legacy/test_file.py +++ b/weave/tests/legacy/test_file.py @@ -1,9 +1,7 @@ import pytest import weave -from weave.legacy import context_state, environment, ops - -from ... import api, errors +from weave.legacy import api, context_state, environment, errors, ops def test_dir(): diff --git a/weave/tests/legacy/test_list_arrow_compat.py b/weave/tests/legacy/test_list_arrow_compat.py index 08287ed6da9..37680040db3 100644 --- a/weave/tests/legacy/test_list_arrow_compat.py +++ b/weave/tests/legacy/test_list_arrow_compat.py @@ -3,6 +3,7 @@ import numpy as np import pytest +from weave.legacy import api as weave from weave.legacy import box, ops, weave_internal from weave.legacy import ops_arrow as arrow from weave.legacy import weave_types as types @@ -13,7 +14,6 @@ ) from weave.legacy.ops_primitives import dict_, list_ -from ... import api as weave from ...tests import tag_test_util as ttu from .. import list_arrow_test_helpers as lath diff --git a/weave/tests/legacy/test_media_user.py b/weave/tests/legacy/test_media_user.py index edbceb07217..8bb37deb4f4 100644 --- a/weave/tests/legacy/test_media_user.py +++ b/weave/tests/legacy/test_media_user.py @@ -1,10 +1,9 @@ from PIL import Image +from weave.legacy import api as weave from weave.legacy import context_state from weave.legacy.ops_primitives import geom as media_user -from ... import api as weave - def test_im_with_metadata(): base_im = Image.linear_gradient("L").resize((32, 32)) diff --git a/weave/tests/legacy/test_mutations.py b/weave/tests/legacy/test_mutations.py index a83ff5a0272..453d8af7ec5 100644 --- a/weave/tests/legacy/test_mutations.py +++ b/weave/tests/legacy/test_mutations.py @@ -1,7 +1,6 @@ +from weave.legacy import api as weave from weave.legacy import ops, storage, weave_internal -from ... import api as weave - def test_autocommit(cereal_csv): csv = ops.local_path(cereal_csv).readcsv() diff --git a/weave/tests/legacy/test_node_ref.py b/weave/tests/legacy/test_node_ref.py index eaacc2c3190..0a8d56f1e7e 100644 --- a/weave/tests/legacy/test_node_ref.py +++ b/weave/tests/legacy/test_node_ref.py @@ -1,6 +1,6 @@ +from weave.legacy import api as weave from weave.legacy import graph -from ... import api as weave from ...legacy import node_ref diff --git a/weave/tests/legacy/test_op_def.py b/weave/tests/legacy/test_op_def.py index aa24f185282..cb05fe0135c 100644 --- a/weave/tests/legacy/test_op_def.py +++ b/weave/tests/legacy/test_op_def.py @@ -5,10 +5,9 @@ import pytest +from weave.legacy import api as weave from weave.legacy import context_state -from ... import api as weave - _loading_builtins_token = context_state.set_loading_built_ins() diff --git a/weave/tests/legacy/test_partial_object.py b/weave/tests/legacy/test_partial_object.py index 8096e6061b5..22eac741e3b 100644 --- a/weave/tests/legacy/test_partial_object.py +++ b/weave/tests/legacy/test_partial_object.py @@ -1,3 +1,4 @@ +from weave.legacy import api as weave from weave.legacy import compile, ops from weave.legacy import weave_types as types from weave.legacy.language_features.tagging.tagged_value_type import TaggedValueType @@ -5,7 +6,6 @@ from weave.legacy.ops_domain.project_ops import root_all_projects from weave.legacy.ops_domain.report_ops import root_all_reports -from ... import api as weave from .test_wb import table_mock1_no_display_name diff --git a/weave/tests/legacy/test_run_segment.py b/weave/tests/legacy/test_run_segment.py index 6ab3815c200..fd92b66c552 100644 --- a/weave/tests/legacy/test_run_segment.py +++ b/weave/tests/legacy/test_run_segment.py @@ -6,13 +6,11 @@ import pytest import weave -from weave.legacy import ops, storage, weave_internal +from weave.legacy import api, ops, storage, weave_internal from weave.legacy import weave_types as types from weave.legacy.ops_arrow import ArrowWeaveList, arrow_as_array from weave.legacy.ops_domain.run_segment import RunSegment -from ... import api - N_NUMERIC_METRICS = 99 # number of numerical columns in the metrics table diff --git a/weave/tests/legacy/test_storage.py b/weave/tests/legacy/test_storage.py index ab91835e742..29dda1e8963 100644 --- a/weave/tests/legacy/test_storage.py +++ b/weave/tests/legacy/test_storage.py @@ -7,6 +7,7 @@ import pytest import wandb +from weave.legacy import api as weave from weave.legacy import ( artifact_mem, artifact_wandb, @@ -18,7 +19,6 @@ from weave.legacy.arrow import list_ as arrow from weave.legacy.weave_internal import make_const_node -from ... import api as weave from ...legacy.weavejs_fixes import recursively_unwrap_unions from . import test_helpers diff --git a/weave/tests/legacy/test_table_ops.py b/weave/tests/legacy/test_table_ops.py index c5ece54c3ab..46f4af2e436 100644 --- a/weave/tests/legacy/test_table_ops.py +++ b/weave/tests/legacy/test_table_ops.py @@ -3,6 +3,7 @@ import pytest +from weave.legacy import api as weave from weave.legacy import ( box, context, @@ -15,7 +16,6 @@ from weave.legacy import weave_types as types from weave.legacy.ops_domain import table as table_ops -from ... import api as weave from .. import weavejs_ops TABLE_TYPES = ["list", "pandas", "sql"] diff --git a/weave/tests/legacy/test_trace.py b/weave/tests/legacy/test_trace.py index 629ca15a4c3..a0c308aab12 100644 --- a/weave/tests/legacy/test_trace.py +++ b/weave/tests/legacy/test_trace.py @@ -1,9 +1,9 @@ import re +from weave.legacy import api as weave from weave.legacy import graph, storage from weave.legacy.weave_internal import make_const_node -from ... import api as weave from ...legacy import trace_legacy diff --git a/weave/tests/legacy/test_wb_domain_types.py b/weave/tests/legacy/test_wb_domain_types.py index b035ebd3b7a..ed550677062 100644 --- a/weave/tests/legacy/test_wb_domain_types.py +++ b/weave/tests/legacy/test_wb_domain_types.py @@ -1,9 +1,8 @@ +from weave.legacy import api as weave from weave.legacy import storage from weave.legacy import weave_types as types from weave.legacy.ops_domain import wb_domain_types as wdt -from ... import api as weave - def test_with_keys_assignability(): org_type = wdt.OrgType diff --git a/weave/tests/legacy/test_weavejs_fixes.py b/weave/tests/legacy/test_weavejs_fixes.py index c40a9d3145f..94bc36039a8 100644 --- a/weave/tests/legacy/test_weavejs_fixes.py +++ b/weave/tests/legacy/test_weavejs_fixes.py @@ -3,6 +3,7 @@ import pytest from weave.legacy import ( + api, context_state, mappers_python, ops, @@ -11,8 +12,6 @@ ) from weave.legacy import weave_types as types -from ... import api - @pytest.mark.skip( "calling custom ops with graph engine is broken right now. Not needed for weaveflow" diff --git a/weave/tests/list_arrow_test_helpers.py b/weave/tests/list_arrow_test_helpers.py index 8c2fedcd4a9..ab7e19d8eb1 100644 --- a/weave/tests/list_arrow_test_helpers.py +++ b/weave/tests/list_arrow_test_helpers.py @@ -1,8 +1,7 @@ +from weave.legacy import api as weave from weave.legacy import ops_arrow as arrow from weave.legacy.ops_primitives import list_ -from .. import api as weave - class ListLikeNodeInterface: @staticmethod diff --git a/weave/tests/trace/test_server.py b/weave/tests/trace/test_server.py index aaaf1f08ff7..936eb7aa360 100644 --- a/weave/tests/trace/test_server.py +++ b/weave/tests/trace/test_server.py @@ -6,7 +6,7 @@ import pytest import requests -from weave import api as weave +from weave.legacy import api as weave from weave.legacy import client as _client from weave.legacy import context_state, ops from weave.legacy import server as _server diff --git a/weave/trace/cli.py b/weave/trace/cli.py index 59a6118d12c..2204e2c4c76 100644 --- a/weave/trace/cli.py +++ b/weave/trace/cli.py @@ -5,10 +5,9 @@ from weave import __version__ from weave.deploy import gcp as google +from weave.trace import api from weave.trace.refs import ObjectRef, parse_uri -from . import api - # from .model_server import app # TODO: does this work? From 678fc70418d439a625eb0c0d3b75cbcd4626c8dd Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Sat, 24 Aug 2024 13:54:03 -0400 Subject: [PATCH 56/84] move to legacy: legacy tests --- .github/workflows/test.yaml | 4 ++-- weave/{tests => }/legacy/__init__.py | 0 weave/legacy/tests/__init__.py | 0 weave/{ => legacy}/tests/example_wb_unit_test.py | 0 weave/{tests/legacy => legacy/tests}/test_access.py | 0 weave/{tests/legacy => legacy/tests}/test_api.py | 0 weave/{tests/legacy => legacy/tests}/test_arrow.py | 2 +- weave/{tests/legacy => legacy/tests}/test_arrow_awl.py | 2 +- weave/{tests/legacy => legacy/tests}/test_arrow_concat.py | 0 weave/{tests/legacy => legacy/tests}/test_arrow_perf.py | 0 weave/{tests/legacy => legacy/tests}/test_arrow_topy.py | 2 +- .../{tests/legacy => legacy/tests}/test_arrow_vectorizer.py | 0 weave/{tests/legacy => legacy/tests}/test_artifact.py | 0 .../legacy => legacy/tests}/test_artifact_metadata.py | 0 weave/{tests/legacy => legacy/tests}/test_assign_perf.py | 0 weave/{tests/legacy => legacy/tests}/test_assignment.py | 0 weave/{tests/legacy => legacy/tests}/test_async.py | 0 weave/{tests/legacy => legacy/tests}/test_async_queue.py | 0 weave/{tests/legacy => legacy/tests}/test_basic_ops.py | 0 weave/{tests/legacy => legacy/tests}/test_box.py | 0 weave/{tests/legacy => legacy/tests}/test_cache.py | 0 weave/{tests/legacy => legacy/tests}/test_codify.py | 0 weave/{tests/legacy => legacy/tests}/test_compile.py | 0 weave/{tests/legacy => legacy/tests}/test_complex_calls.py | 0 weave/{tests/legacy => legacy/tests}/test_cond.py | 0 .../legacy => legacy/tests}/test_const_type_mapper.py | 0 weave/{tests/legacy => legacy/tests}/test_custom_types.py | 2 +- .../legacy => legacy/tests}/test_datetime_timestamp.py | 0 weave/{tests/legacy => legacy/tests}/test_decorator_type.py | 0 weave/{tests/legacy => legacy/tests}/test_decorators.py | 0 weave/{tests/legacy => legacy/tests}/test_derive_op.py | 0 weave/{tests/legacy => legacy/tests}/test_dispatch.py | 0 weave/{tests/legacy => legacy/tests}/test_examples.py | 0 weave/{tests/legacy => legacy/tests}/test_execute.py | 0 weave/{tests/legacy => legacy/tests}/test_execute_fast.py | 2 +- .../{tests/legacy => legacy/tests}/test_execution_graphs.py | 0 weave/{tests/legacy => legacy/tests}/test_file.py | 0 weave/{tests/legacy => legacy/tests}/test_filesystem.py | 0 weave/{tests/legacy => legacy/tests}/test_gql_to_weave.py | 0 weave/{tests/legacy => legacy/tests}/test_graph.py | 0 weave/{tests/legacy => legacy/tests}/test_graph_debug.py | 0 weave/{tests/legacy => legacy/tests}/test_helpers.py | 0 weave/{tests/legacy => legacy/tests}/test_hypothesis.py | 0 weave/{tests/legacy => legacy/tests}/test_index.py | 0 weave/{tests/legacy => legacy/tests}/test_infer_types.py | 0 weave/{tests/legacy => legacy/tests}/test_io_service.py | 0 weave/{tests/legacy => legacy/tests}/test_join.py | 0 weave/{tests/legacy => legacy/tests}/test_js_compat.py | 0 weave/{tests/legacy => legacy/tests}/test_language.py | 0 .../legacy => legacy/tests}/test_language_autocall.py | 0 weave/{tests/legacy => legacy/tests}/test_levenshtein.py | 0 .../legacy => legacy/tests}/test_list_arrow_compat.py | 2 +- weave/{tests/legacy => legacy/tests}/test_list_indexing.py | 0 weave/{tests/legacy => legacy/tests}/test_logging.py | 0 weave/{tests/legacy => legacy/tests}/test_mappability.py | 0 weave/{tests/legacy => legacy/tests}/test_mappers_arrow.py | 0 weave/{tests/legacy => legacy/tests}/test_mappers_python.py | 0 weave/{tests/legacy => legacy/tests}/test_media.py | 0 weave/{tests/legacy => legacy/tests}/test_media_user.py | 0 weave/{tests/legacy => legacy/tests}/test_monitoring.py | 0 .../legacy => legacy/tests}/test_monitoring_openai.py | 0 weave/{tests/legacy => legacy/tests}/test_mutation2.py | 0 weave/{tests/legacy => legacy/tests}/test_mutations.py | 0 weave/{tests/legacy => legacy/tests}/test_node_ref.py | 0 weave/{tests/legacy => legacy/tests}/test_nullability.py | 0 weave/{tests/legacy => legacy/tests}/test_number_bin.py | 0 weave/{tests/legacy => legacy/tests}/test_numpy.py | 0 weave/{tests/legacy => legacy/tests}/test_op.py | 0 weave/{tests/legacy => legacy/tests}/test_op_behaviors.py | 4 ++-- weave/{tests/legacy => legacy/tests}/test_op_coverage.py | 0 weave/{tests/legacy => legacy/tests}/test_op_def.py | 3 +-- weave/{tests/legacy => legacy/tests}/test_op_def_data.json | 0 weave/{tests/legacy => legacy/tests}/test_op_def_type.py | 0 weave/{tests/legacy => legacy/tests}/test_op_dispatching.py | 0 .../{tests/legacy => legacy/tests}/test_op_serialization.py | 0 weave/{tests/legacy => legacy/tests}/test_panel_coverage.py | 0 .../legacy => legacy/tests}/test_panel_time_series.py | 0 weave/{tests/legacy => legacy/tests}/test_panels.py | 0 weave/{tests/legacy => legacy/tests}/test_partial_object.py | 0 weave/{tests/legacy => legacy/tests}/test_plot.py | 0 .../legacy => legacy/tests}/test_projection_timeout.py | 0 weave/{tests/legacy => legacy/tests}/test_publish_flow.py | 0 weave/{tests/legacy => legacy/tests}/test_pydantic.py | 0 weave/{tests/legacy => legacy/tests}/test_ref_tracking.py | 0 weave/{tests/legacy => legacy/tests}/test_refs.py | 0 .../legacy => legacy/tests}/test_relpath_no_syscalls.py | 0 weave/{tests/legacy => legacy/tests}/test_run_segment.py | 0 weave/{tests/legacy => legacy/tests}/test_serialize.py | 2 +- weave/{tests/legacy => legacy/tests}/test_show.py | 0 weave/{tests/legacy => legacy/tests}/test_stitch.py | 2 +- weave/{tests/legacy => legacy/tests}/test_storage.py | 0 weave/{tests/legacy => legacy/tests}/test_stream_table.py | 0 weave/{tests/legacy => legacy/tests}/test_table_ops.py | 2 +- weave/{tests/legacy => legacy/tests}/test_tagging.py | 0 weave/{tests/legacy => legacy/tests}/test_templates.py | 0 weave/{tests/legacy => legacy/tests}/test_timestamp_bin.py | 0 weave/{tests/legacy => legacy/tests}/test_trace.py | 0 .../legacy => legacy/tests}/test_typeddict_notrequired.py | 0 weave/{tests/legacy => legacy/tests}/test_uris.py | 0 weave/{tests/legacy => legacy/tests}/test_wb.py | 6 +++--- weave/{tests/legacy => legacy/tests}/test_wb_data_types.py | 2 +- weave/{tests/legacy => legacy/tests}/test_wb_domain_ops.py | 2 +- .../{tests/legacy => legacy/tests}/test_wb_domain_types.py | 0 weave/{tests/legacy => legacy/tests}/test_wb_end_to_end.py | 0 .../tests}/test_wb_history_loading_compatability.py | 0 .../{tests/legacy => legacy/tests}/test_wb_stream_table.py | 0 weave/{tests/legacy => legacy/tests}/test_wb_tables.py | 0 weave/{tests/legacy => legacy/tests}/test_weave_api.py | 0 weave/{tests/legacy => legacy/tests}/test_weave_types.py | 0 weave/{tests/legacy => legacy/tests}/test_weavejs_fixes.py | 0 weave/{tests/legacy => legacy/tests}/test_weavify.py | 2 +- weave/{tests/legacy => legacy/tests}/test_with_columns.py | 0 112 files changed, 20 insertions(+), 21 deletions(-) rename weave/{tests => }/legacy/__init__.py (100%) create mode 100644 weave/legacy/tests/__init__.py rename weave/{ => legacy}/tests/example_wb_unit_test.py (100%) rename weave/{tests/legacy => legacy/tests}/test_access.py (100%) rename weave/{tests/legacy => legacy/tests}/test_api.py (100%) rename weave/{tests/legacy => legacy/tests}/test_arrow.py (99%) rename weave/{tests/legacy => legacy/tests}/test_arrow_awl.py (98%) rename weave/{tests/legacy => legacy/tests}/test_arrow_concat.py (100%) rename weave/{tests/legacy => legacy/tests}/test_arrow_perf.py (100%) rename weave/{tests/legacy => legacy/tests}/test_arrow_topy.py (99%) rename weave/{tests/legacy => legacy/tests}/test_arrow_vectorizer.py (100%) rename weave/{tests/legacy => legacy/tests}/test_artifact.py (100%) rename weave/{tests/legacy => legacy/tests}/test_artifact_metadata.py (100%) rename weave/{tests/legacy => legacy/tests}/test_assign_perf.py (100%) rename weave/{tests/legacy => legacy/tests}/test_assignment.py (100%) rename weave/{tests/legacy => legacy/tests}/test_async.py (100%) rename weave/{tests/legacy => legacy/tests}/test_async_queue.py (100%) rename weave/{tests/legacy => legacy/tests}/test_basic_ops.py (100%) rename weave/{tests/legacy => legacy/tests}/test_box.py (100%) rename weave/{tests/legacy => legacy/tests}/test_cache.py (100%) rename weave/{tests/legacy => legacy/tests}/test_codify.py (100%) rename weave/{tests/legacy => legacy/tests}/test_compile.py (100%) rename weave/{tests/legacy => legacy/tests}/test_complex_calls.py (100%) rename weave/{tests/legacy => legacy/tests}/test_cond.py (100%) rename weave/{tests/legacy => legacy/tests}/test_const_type_mapper.py (100%) rename weave/{tests/legacy => legacy/tests}/test_custom_types.py (98%) rename weave/{tests/legacy => legacy/tests}/test_datetime_timestamp.py (100%) rename weave/{tests/legacy => legacy/tests}/test_decorator_type.py (100%) rename weave/{tests/legacy => legacy/tests}/test_decorators.py (100%) rename weave/{tests/legacy => legacy/tests}/test_derive_op.py (100%) rename weave/{tests/legacy => legacy/tests}/test_dispatch.py (100%) rename weave/{tests/legacy => legacy/tests}/test_examples.py (100%) rename weave/{tests/legacy => legacy/tests}/test_execute.py (100%) rename weave/{tests/legacy => legacy/tests}/test_execute_fast.py (97%) rename weave/{tests/legacy => legacy/tests}/test_execution_graphs.py (100%) rename weave/{tests/legacy => legacy/tests}/test_file.py (100%) rename weave/{tests/legacy => legacy/tests}/test_filesystem.py (100%) rename weave/{tests/legacy => legacy/tests}/test_gql_to_weave.py (100%) rename weave/{tests/legacy => legacy/tests}/test_graph.py (100%) rename weave/{tests/legacy => legacy/tests}/test_graph_debug.py (100%) rename weave/{tests/legacy => legacy/tests}/test_helpers.py (100%) rename weave/{tests/legacy => legacy/tests}/test_hypothesis.py (100%) rename weave/{tests/legacy => legacy/tests}/test_index.py (100%) rename weave/{tests/legacy => legacy/tests}/test_infer_types.py (100%) rename weave/{tests/legacy => legacy/tests}/test_io_service.py (100%) rename weave/{tests/legacy => legacy/tests}/test_join.py (100%) rename weave/{tests/legacy => legacy/tests}/test_js_compat.py (100%) rename weave/{tests/legacy => legacy/tests}/test_language.py (100%) rename weave/{tests/legacy => legacy/tests}/test_language_autocall.py (100%) rename weave/{tests/legacy => legacy/tests}/test_levenshtein.py (100%) rename weave/{tests/legacy => legacy/tests}/test_list_arrow_compat.py (99%) rename weave/{tests/legacy => legacy/tests}/test_list_indexing.py (100%) rename weave/{tests/legacy => legacy/tests}/test_logging.py (100%) rename weave/{tests/legacy => legacy/tests}/test_mappability.py (100%) rename weave/{tests/legacy => legacy/tests}/test_mappers_arrow.py (100%) rename weave/{tests/legacy => legacy/tests}/test_mappers_python.py (100%) rename weave/{tests/legacy => legacy/tests}/test_media.py (100%) rename weave/{tests/legacy => legacy/tests}/test_media_user.py (100%) rename weave/{tests/legacy => legacy/tests}/test_monitoring.py (100%) rename weave/{tests/legacy => legacy/tests}/test_monitoring_openai.py (100%) rename weave/{tests/legacy => legacy/tests}/test_mutation2.py (100%) rename weave/{tests/legacy => legacy/tests}/test_mutations.py (100%) rename weave/{tests/legacy => legacy/tests}/test_node_ref.py (100%) rename weave/{tests/legacy => legacy/tests}/test_nullability.py (100%) rename weave/{tests/legacy => legacy/tests}/test_number_bin.py (100%) rename weave/{tests/legacy => legacy/tests}/test_numpy.py (100%) rename weave/{tests/legacy => legacy/tests}/test_op.py (100%) rename weave/{tests/legacy => legacy/tests}/test_op_behaviors.py (99%) rename weave/{tests/legacy => legacy/tests}/test_op_coverage.py (100%) rename weave/{tests/legacy => legacy/tests}/test_op_def.py (97%) rename weave/{tests/legacy => legacy/tests}/test_op_def_data.json (100%) rename weave/{tests/legacy => legacy/tests}/test_op_def_type.py (100%) rename weave/{tests/legacy => legacy/tests}/test_op_dispatching.py (100%) rename weave/{tests/legacy => legacy/tests}/test_op_serialization.py (100%) rename weave/{tests/legacy => legacy/tests}/test_panel_coverage.py (100%) rename weave/{tests/legacy => legacy/tests}/test_panel_time_series.py (100%) rename weave/{tests/legacy => legacy/tests}/test_panels.py (100%) rename weave/{tests/legacy => legacy/tests}/test_partial_object.py (100%) rename weave/{tests/legacy => legacy/tests}/test_plot.py (100%) rename weave/{tests/legacy => legacy/tests}/test_projection_timeout.py (100%) rename weave/{tests/legacy => legacy/tests}/test_publish_flow.py (100%) rename weave/{tests/legacy => legacy/tests}/test_pydantic.py (100%) rename weave/{tests/legacy => legacy/tests}/test_ref_tracking.py (100%) rename weave/{tests/legacy => legacy/tests}/test_refs.py (100%) rename weave/{tests/legacy => legacy/tests}/test_relpath_no_syscalls.py (100%) rename weave/{tests/legacy => legacy/tests}/test_run_segment.py (100%) rename weave/{tests/legacy => legacy/tests}/test_serialize.py (99%) rename weave/{tests/legacy => legacy/tests}/test_show.py (100%) rename weave/{tests/legacy => legacy/tests}/test_stitch.py (99%) rename weave/{tests/legacy => legacy/tests}/test_storage.py (100%) rename weave/{tests/legacy => legacy/tests}/test_stream_table.py (100%) rename weave/{tests/legacy => legacy/tests}/test_table_ops.py (99%) rename weave/{tests/legacy => legacy/tests}/test_tagging.py (100%) rename weave/{tests/legacy => legacy/tests}/test_templates.py (100%) rename weave/{tests/legacy => legacy/tests}/test_timestamp_bin.py (100%) rename weave/{tests/legacy => legacy/tests}/test_trace.py (100%) rename weave/{tests/legacy => legacy/tests}/test_typeddict_notrequired.py (100%) rename weave/{tests/legacy => legacy/tests}/test_uris.py (100%) rename weave/{tests/legacy => legacy/tests}/test_wb.py (99%) rename weave/{tests/legacy => legacy/tests}/test_wb_data_types.py (99%) rename weave/{tests/legacy => legacy/tests}/test_wb_domain_ops.py (99%) rename weave/{tests/legacy => legacy/tests}/test_wb_domain_types.py (100%) rename weave/{tests/legacy => legacy/tests}/test_wb_end_to_end.py (100%) rename weave/{tests/legacy => legacy/tests}/test_wb_history_loading_compatability.py (100%) rename weave/{tests/legacy => legacy/tests}/test_wb_stream_table.py (100%) rename weave/{tests/legacy => legacy/tests}/test_wb_tables.py (100%) rename weave/{tests/legacy => legacy/tests}/test_weave_api.py (100%) rename weave/{tests/legacy => legacy/tests}/test_weave_types.py (100%) rename weave/{tests/legacy => legacy/tests}/test_weavejs_fixes.py (100%) rename weave/{tests/legacy => legacy/tests}/test_weavify.py (98%) rename weave/{tests/legacy => legacy/tests}/test_with_columns.py (100%) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index f1b883498b1..4ebd119ef67 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -127,13 +127,13 @@ jobs: WEAVE_SENTRY_ENV: ci # This runner specifically runs the tests that use the `client` fixture (those that support clickhouse client tests) # However, we skip tests marked with `skip_clickhouse_client`. These should be considered TODOs and an exception - run: CI=1 WB_SERVER_HOST=http://wandbservice WF_CLICKHOUSE_HOST=weave_clickhouse WEAVE_SERVER_DISABLE_ECOSYSTEM=1 source /root/venv/bin/activate && cd weave && pytest -m "weave_client and not skip_clickhouse_client" --weave-server=clickhouse --job-num=${{ matrix.job_num }} --timeout=90 ./flow ./integrations ./tests ./legacy/ops_arrow ./legacy/ecosystem ./trace_server ./trace --ddtrace --durations=5 + run: CI=1 WB_SERVER_HOST=http://wandbservice WF_CLICKHOUSE_HOST=weave_clickhouse WEAVE_SERVER_DISABLE_ECOSYSTEM=1 source /root/venv/bin/activate && cd weave && pytest -m "weave_client and not skip_clickhouse_client" --weave-server=clickhouse --job-num=${{ matrix.job_num }} --timeout=90 ./flow ./integrations ./legacy/tests ./tests ./legacy/ops_arrow ./legacy/ecosystem ./trace_server ./trace --ddtrace --durations=5 - name: Run Python Unit Tests env: DD_SERVICE: weave-python DD_ENV: ci WEAVE_SENTRY_ENV: ci - run: CI=1 WB_SERVER_HOST=http://wandbservice WF_CLICKHOUSE_HOST=weave_clickhouse WEAVE_SERVER_DISABLE_ECOSYSTEM=1 source /root/venv/bin/activate && pip install 'dspy-ai>=0.1.5' && pip install pydantic -U && cd weave && pytest --job-num=${{ matrix.job_num }} --timeout=90 ./flow ./integrations ./tests ./legacy/ops_arrow ./legacy/ecosystem ./trace_server ./trace --ddtrace --durations=5 + run: CI=1 WB_SERVER_HOST=http://wandbservice WF_CLICKHOUSE_HOST=weave_clickhouse WEAVE_SERVER_DISABLE_ECOSYSTEM=1 source /root/venv/bin/activate && pip install 'dspy-ai>=0.1.5' && pip install pydantic -U && cd weave && pytest --job-num=${{ matrix.job_num }} --timeout=90 ./flow ./integrations ./legacy/tests ./tests ./legacy/ops_arrow ./legacy/ecosystem ./trace_server ./trace --ddtrace --durations=5 # nbmake: # name: Run notebooks with nbmake diff --git a/weave/tests/legacy/__init__.py b/weave/legacy/__init__.py similarity index 100% rename from weave/tests/legacy/__init__.py rename to weave/legacy/__init__.py diff --git a/weave/legacy/tests/__init__.py b/weave/legacy/tests/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/weave/tests/example_wb_unit_test.py b/weave/legacy/tests/example_wb_unit_test.py similarity index 100% rename from weave/tests/example_wb_unit_test.py rename to weave/legacy/tests/example_wb_unit_test.py diff --git a/weave/tests/legacy/test_access.py b/weave/legacy/tests/test_access.py similarity index 100% rename from weave/tests/legacy/test_access.py rename to weave/legacy/tests/test_access.py diff --git a/weave/tests/legacy/test_api.py b/weave/legacy/tests/test_api.py similarity index 100% rename from weave/tests/legacy/test_api.py rename to weave/legacy/tests/test_api.py diff --git a/weave/tests/legacy/test_arrow.py b/weave/legacy/tests/test_arrow.py similarity index 99% rename from weave/tests/legacy/test_arrow.py rename to weave/legacy/tests/test_arrow.py index e5554ab165c..2f0a0b71c3c 100644 --- a/weave/tests/legacy/test_arrow.py +++ b/weave/legacy/tests/test_arrow.py @@ -39,7 +39,7 @@ from ...tests import tag_test_util as ttu from ...tests import weavejs_ops -from ...tests.legacy import test_wb +from . import test_wb _loading_builtins_token = context_state.set_loading_built_ins() # T in `conftest::pre_post_each_test` we set a custom artifact directory for each test for isolation diff --git a/weave/tests/legacy/test_arrow_awl.py b/weave/legacy/tests/test_arrow_awl.py similarity index 98% rename from weave/tests/legacy/test_arrow_awl.py rename to weave/legacy/tests/test_arrow_awl.py index c1949a9cb97..c870484343d 100644 --- a/weave/tests/legacy/test_arrow_awl.py +++ b/weave/legacy/tests/test_arrow_awl.py @@ -8,7 +8,7 @@ from weave.legacy.arrow.convert import to_arrow from weave.legacy.language_features.tagging import tag_store, tagged_value_type -from ..concrete_tagged_value import ( +from ...tests.concrete_tagged_value import ( TaggedValue, concrete_from_tagstore, concrete_to_tagstore, diff --git a/weave/tests/legacy/test_arrow_concat.py b/weave/legacy/tests/test_arrow_concat.py similarity index 100% rename from weave/tests/legacy/test_arrow_concat.py rename to weave/legacy/tests/test_arrow_concat.py diff --git a/weave/tests/legacy/test_arrow_perf.py b/weave/legacy/tests/test_arrow_perf.py similarity index 100% rename from weave/tests/legacy/test_arrow_perf.py rename to weave/legacy/tests/test_arrow_perf.py diff --git a/weave/tests/legacy/test_arrow_topy.py b/weave/legacy/tests/test_arrow_topy.py similarity index 99% rename from weave/tests/legacy/test_arrow_topy.py rename to weave/legacy/tests/test_arrow_topy.py index 6f5b2839cf8..fba5f9d9b18 100644 --- a/weave/tests/legacy/test_arrow_topy.py +++ b/weave/legacy/tests/test_arrow_topy.py @@ -6,7 +6,7 @@ import weave from weave.legacy import ops_arrow -from ..concrete_tagged_value import ( +from ...tests.concrete_tagged_value import ( TaggedValue, concrete_from_tagstore, concrete_to_tagstore, diff --git a/weave/tests/legacy/test_arrow_vectorizer.py b/weave/legacy/tests/test_arrow_vectorizer.py similarity index 100% rename from weave/tests/legacy/test_arrow_vectorizer.py rename to weave/legacy/tests/test_arrow_vectorizer.py diff --git a/weave/tests/legacy/test_artifact.py b/weave/legacy/tests/test_artifact.py similarity index 100% rename from weave/tests/legacy/test_artifact.py rename to weave/legacy/tests/test_artifact.py diff --git a/weave/tests/legacy/test_artifact_metadata.py b/weave/legacy/tests/test_artifact_metadata.py similarity index 100% rename from weave/tests/legacy/test_artifact_metadata.py rename to weave/legacy/tests/test_artifact_metadata.py diff --git a/weave/tests/legacy/test_assign_perf.py b/weave/legacy/tests/test_assign_perf.py similarity index 100% rename from weave/tests/legacy/test_assign_perf.py rename to weave/legacy/tests/test_assign_perf.py diff --git a/weave/tests/legacy/test_assignment.py b/weave/legacy/tests/test_assignment.py similarity index 100% rename from weave/tests/legacy/test_assignment.py rename to weave/legacy/tests/test_assignment.py diff --git a/weave/tests/legacy/test_async.py b/weave/legacy/tests/test_async.py similarity index 100% rename from weave/tests/legacy/test_async.py rename to weave/legacy/tests/test_async.py diff --git a/weave/tests/legacy/test_async_queue.py b/weave/legacy/tests/test_async_queue.py similarity index 100% rename from weave/tests/legacy/test_async_queue.py rename to weave/legacy/tests/test_async_queue.py diff --git a/weave/tests/legacy/test_basic_ops.py b/weave/legacy/tests/test_basic_ops.py similarity index 100% rename from weave/tests/legacy/test_basic_ops.py rename to weave/legacy/tests/test_basic_ops.py diff --git a/weave/tests/legacy/test_box.py b/weave/legacy/tests/test_box.py similarity index 100% rename from weave/tests/legacy/test_box.py rename to weave/legacy/tests/test_box.py diff --git a/weave/tests/legacy/test_cache.py b/weave/legacy/tests/test_cache.py similarity index 100% rename from weave/tests/legacy/test_cache.py rename to weave/legacy/tests/test_cache.py diff --git a/weave/tests/legacy/test_codify.py b/weave/legacy/tests/test_codify.py similarity index 100% rename from weave/tests/legacy/test_codify.py rename to weave/legacy/tests/test_codify.py diff --git a/weave/tests/legacy/test_compile.py b/weave/legacy/tests/test_compile.py similarity index 100% rename from weave/tests/legacy/test_compile.py rename to weave/legacy/tests/test_compile.py diff --git a/weave/tests/legacy/test_complex_calls.py b/weave/legacy/tests/test_complex_calls.py similarity index 100% rename from weave/tests/legacy/test_complex_calls.py rename to weave/legacy/tests/test_complex_calls.py diff --git a/weave/tests/legacy/test_cond.py b/weave/legacy/tests/test_cond.py similarity index 100% rename from weave/tests/legacy/test_cond.py rename to weave/legacy/tests/test_cond.py diff --git a/weave/tests/legacy/test_const_type_mapper.py b/weave/legacy/tests/test_const_type_mapper.py similarity index 100% rename from weave/tests/legacy/test_const_type_mapper.py rename to weave/legacy/tests/test_const_type_mapper.py diff --git a/weave/tests/legacy/test_custom_types.py b/weave/legacy/tests/test_custom_types.py similarity index 98% rename from weave/tests/legacy/test_custom_types.py rename to weave/legacy/tests/test_custom_types.py index f5b15ff28ba..6d47d4c8054 100644 --- a/weave/tests/legacy/test_custom_types.py +++ b/weave/legacy/tests/test_custom_types.py @@ -6,7 +6,7 @@ from weave.legacy import ops_arrow from ... import errors -from .. import geom +from ...tests import geom def test_mapped_method_on_custom_type(): diff --git a/weave/tests/legacy/test_datetime_timestamp.py b/weave/legacy/tests/test_datetime_timestamp.py similarity index 100% rename from weave/tests/legacy/test_datetime_timestamp.py rename to weave/legacy/tests/test_datetime_timestamp.py diff --git a/weave/tests/legacy/test_decorator_type.py b/weave/legacy/tests/test_decorator_type.py similarity index 100% rename from weave/tests/legacy/test_decorator_type.py rename to weave/legacy/tests/test_decorator_type.py diff --git a/weave/tests/legacy/test_decorators.py b/weave/legacy/tests/test_decorators.py similarity index 100% rename from weave/tests/legacy/test_decorators.py rename to weave/legacy/tests/test_decorators.py diff --git a/weave/tests/legacy/test_derive_op.py b/weave/legacy/tests/test_derive_op.py similarity index 100% rename from weave/tests/legacy/test_derive_op.py rename to weave/legacy/tests/test_derive_op.py diff --git a/weave/tests/legacy/test_dispatch.py b/weave/legacy/tests/test_dispatch.py similarity index 100% rename from weave/tests/legacy/test_dispatch.py rename to weave/legacy/tests/test_dispatch.py diff --git a/weave/tests/legacy/test_examples.py b/weave/legacy/tests/test_examples.py similarity index 100% rename from weave/tests/legacy/test_examples.py rename to weave/legacy/tests/test_examples.py diff --git a/weave/tests/legacy/test_execute.py b/weave/legacy/tests/test_execute.py similarity index 100% rename from weave/tests/legacy/test_execute.py rename to weave/legacy/tests/test_execute.py diff --git a/weave/tests/legacy/test_execute_fast.py b/weave/legacy/tests/test_execute_fast.py similarity index 97% rename from weave/tests/legacy/test_execute_fast.py rename to weave/legacy/tests/test_execute_fast.py index af8c94b7b5e..663140be8d9 100644 --- a/weave/tests/legacy/test_execute_fast.py +++ b/weave/legacy/tests/test_execute_fast.py @@ -2,7 +2,7 @@ from weave.legacy import dispatch, weave_internal from weave.legacy import weave_types as types -from .. import weavejs_ops +from ...tests import weavejs_ops def test_nested_weavejs_call(): diff --git a/weave/tests/legacy/test_execution_graphs.py b/weave/legacy/tests/test_execution_graphs.py similarity index 100% rename from weave/tests/legacy/test_execution_graphs.py rename to weave/legacy/tests/test_execution_graphs.py diff --git a/weave/tests/legacy/test_file.py b/weave/legacy/tests/test_file.py similarity index 100% rename from weave/tests/legacy/test_file.py rename to weave/legacy/tests/test_file.py diff --git a/weave/tests/legacy/test_filesystem.py b/weave/legacy/tests/test_filesystem.py similarity index 100% rename from weave/tests/legacy/test_filesystem.py rename to weave/legacy/tests/test_filesystem.py diff --git a/weave/tests/legacy/test_gql_to_weave.py b/weave/legacy/tests/test_gql_to_weave.py similarity index 100% rename from weave/tests/legacy/test_gql_to_weave.py rename to weave/legacy/tests/test_gql_to_weave.py diff --git a/weave/tests/legacy/test_graph.py b/weave/legacy/tests/test_graph.py similarity index 100% rename from weave/tests/legacy/test_graph.py rename to weave/legacy/tests/test_graph.py diff --git a/weave/tests/legacy/test_graph_debug.py b/weave/legacy/tests/test_graph_debug.py similarity index 100% rename from weave/tests/legacy/test_graph_debug.py rename to weave/legacy/tests/test_graph_debug.py diff --git a/weave/tests/legacy/test_helpers.py b/weave/legacy/tests/test_helpers.py similarity index 100% rename from weave/tests/legacy/test_helpers.py rename to weave/legacy/tests/test_helpers.py diff --git a/weave/tests/legacy/test_hypothesis.py b/weave/legacy/tests/test_hypothesis.py similarity index 100% rename from weave/tests/legacy/test_hypothesis.py rename to weave/legacy/tests/test_hypothesis.py diff --git a/weave/tests/legacy/test_index.py b/weave/legacy/tests/test_index.py similarity index 100% rename from weave/tests/legacy/test_index.py rename to weave/legacy/tests/test_index.py diff --git a/weave/tests/legacy/test_infer_types.py b/weave/legacy/tests/test_infer_types.py similarity index 100% rename from weave/tests/legacy/test_infer_types.py rename to weave/legacy/tests/test_infer_types.py diff --git a/weave/tests/legacy/test_io_service.py b/weave/legacy/tests/test_io_service.py similarity index 100% rename from weave/tests/legacy/test_io_service.py rename to weave/legacy/tests/test_io_service.py diff --git a/weave/tests/legacy/test_join.py b/weave/legacy/tests/test_join.py similarity index 100% rename from weave/tests/legacy/test_join.py rename to weave/legacy/tests/test_join.py diff --git a/weave/tests/legacy/test_js_compat.py b/weave/legacy/tests/test_js_compat.py similarity index 100% rename from weave/tests/legacy/test_js_compat.py rename to weave/legacy/tests/test_js_compat.py diff --git a/weave/tests/legacy/test_language.py b/weave/legacy/tests/test_language.py similarity index 100% rename from weave/tests/legacy/test_language.py rename to weave/legacy/tests/test_language.py diff --git a/weave/tests/legacy/test_language_autocall.py b/weave/legacy/tests/test_language_autocall.py similarity index 100% rename from weave/tests/legacy/test_language_autocall.py rename to weave/legacy/tests/test_language_autocall.py diff --git a/weave/tests/legacy/test_levenshtein.py b/weave/legacy/tests/test_levenshtein.py similarity index 100% rename from weave/tests/legacy/test_levenshtein.py rename to weave/legacy/tests/test_levenshtein.py diff --git a/weave/tests/legacy/test_list_arrow_compat.py b/weave/legacy/tests/test_list_arrow_compat.py similarity index 99% rename from weave/tests/legacy/test_list_arrow_compat.py rename to weave/legacy/tests/test_list_arrow_compat.py index 37680040db3..2cc3663ae2d 100644 --- a/weave/tests/legacy/test_list_arrow_compat.py +++ b/weave/legacy/tests/test_list_arrow_compat.py @@ -15,7 +15,7 @@ from weave.legacy.ops_primitives import dict_, list_ from ...tests import tag_test_util as ttu -from .. import list_arrow_test_helpers as lath +from ...tests import list_arrow_test_helpers as lath def filter_fn(row) -> bool: diff --git a/weave/tests/legacy/test_list_indexing.py b/weave/legacy/tests/test_list_indexing.py similarity index 100% rename from weave/tests/legacy/test_list_indexing.py rename to weave/legacy/tests/test_list_indexing.py diff --git a/weave/tests/legacy/test_logging.py b/weave/legacy/tests/test_logging.py similarity index 100% rename from weave/tests/legacy/test_logging.py rename to weave/legacy/tests/test_logging.py diff --git a/weave/tests/legacy/test_mappability.py b/weave/legacy/tests/test_mappability.py similarity index 100% rename from weave/tests/legacy/test_mappability.py rename to weave/legacy/tests/test_mappability.py diff --git a/weave/tests/legacy/test_mappers_arrow.py b/weave/legacy/tests/test_mappers_arrow.py similarity index 100% rename from weave/tests/legacy/test_mappers_arrow.py rename to weave/legacy/tests/test_mappers_arrow.py diff --git a/weave/tests/legacy/test_mappers_python.py b/weave/legacy/tests/test_mappers_python.py similarity index 100% rename from weave/tests/legacy/test_mappers_python.py rename to weave/legacy/tests/test_mappers_python.py diff --git a/weave/tests/legacy/test_media.py b/weave/legacy/tests/test_media.py similarity index 100% rename from weave/tests/legacy/test_media.py rename to weave/legacy/tests/test_media.py diff --git a/weave/tests/legacy/test_media_user.py b/weave/legacy/tests/test_media_user.py similarity index 100% rename from weave/tests/legacy/test_media_user.py rename to weave/legacy/tests/test_media_user.py diff --git a/weave/tests/legacy/test_monitoring.py b/weave/legacy/tests/test_monitoring.py similarity index 100% rename from weave/tests/legacy/test_monitoring.py rename to weave/legacy/tests/test_monitoring.py diff --git a/weave/tests/legacy/test_monitoring_openai.py b/weave/legacy/tests/test_monitoring_openai.py similarity index 100% rename from weave/tests/legacy/test_monitoring_openai.py rename to weave/legacy/tests/test_monitoring_openai.py diff --git a/weave/tests/legacy/test_mutation2.py b/weave/legacy/tests/test_mutation2.py similarity index 100% rename from weave/tests/legacy/test_mutation2.py rename to weave/legacy/tests/test_mutation2.py diff --git a/weave/tests/legacy/test_mutations.py b/weave/legacy/tests/test_mutations.py similarity index 100% rename from weave/tests/legacy/test_mutations.py rename to weave/legacy/tests/test_mutations.py diff --git a/weave/tests/legacy/test_node_ref.py b/weave/legacy/tests/test_node_ref.py similarity index 100% rename from weave/tests/legacy/test_node_ref.py rename to weave/legacy/tests/test_node_ref.py diff --git a/weave/tests/legacy/test_nullability.py b/weave/legacy/tests/test_nullability.py similarity index 100% rename from weave/tests/legacy/test_nullability.py rename to weave/legacy/tests/test_nullability.py diff --git a/weave/tests/legacy/test_number_bin.py b/weave/legacy/tests/test_number_bin.py similarity index 100% rename from weave/tests/legacy/test_number_bin.py rename to weave/legacy/tests/test_number_bin.py diff --git a/weave/tests/legacy/test_numpy.py b/weave/legacy/tests/test_numpy.py similarity index 100% rename from weave/tests/legacy/test_numpy.py rename to weave/legacy/tests/test_numpy.py diff --git a/weave/tests/legacy/test_op.py b/weave/legacy/tests/test_op.py similarity index 100% rename from weave/tests/legacy/test_op.py rename to weave/legacy/tests/test_op.py diff --git a/weave/tests/legacy/test_op_behaviors.py b/weave/legacy/tests/test_op_behaviors.py similarity index 99% rename from weave/tests/legacy/test_op_behaviors.py rename to weave/legacy/tests/test_op_behaviors.py index 6a9f207acd9..73f9e786885 100644 --- a/weave/tests/legacy/test_op_behaviors.py +++ b/weave/legacy/tests/test_op_behaviors.py @@ -28,12 +28,12 @@ ) from ...legacy import registry_mem -from ..concrete_tagged_value import ( +from ...tests.concrete_tagged_value import ( TaggedValue, concrete_from_tagstore, concrete_to_tagstore, ) -from ..op_specs import OP_TEST_SPECS, OpSpec, OpSpecTestCase +from ...tests.op_specs import OP_TEST_SPECS, OpSpec, OpSpecTestCase def assert_equal_with_tags(node: graph.Node, v: typing.Any, expected: typing.Any): diff --git a/weave/tests/legacy/test_op_coverage.py b/weave/legacy/tests/test_op_coverage.py similarity index 100% rename from weave/tests/legacy/test_op_coverage.py rename to weave/legacy/tests/test_op_coverage.py diff --git a/weave/tests/legacy/test_op_def.py b/weave/legacy/tests/test_op_def.py similarity index 97% rename from weave/tests/legacy/test_op_def.py rename to weave/legacy/tests/test_op_def.py index cb05fe0135c..343452305e8 100644 --- a/weave/tests/legacy/test_op_def.py +++ b/weave/legacy/tests/test_op_def.py @@ -55,8 +55,7 @@ def wrap(obj: typing.Any): context_state.clear_loading_built_ins(_loading_builtins_token) - -test_data = json.load(open("./tests/legacy/test_op_def_data.json")) +test_data = json.load(open("./legacy/tests/test_op_def_data.json")) def test_op_def_to_dict(): diff --git a/weave/tests/legacy/test_op_def_data.json b/weave/legacy/tests/test_op_def_data.json similarity index 100% rename from weave/tests/legacy/test_op_def_data.json rename to weave/legacy/tests/test_op_def_data.json diff --git a/weave/tests/legacy/test_op_def_type.py b/weave/legacy/tests/test_op_def_type.py similarity index 100% rename from weave/tests/legacy/test_op_def_type.py rename to weave/legacy/tests/test_op_def_type.py diff --git a/weave/tests/legacy/test_op_dispatching.py b/weave/legacy/tests/test_op_dispatching.py similarity index 100% rename from weave/tests/legacy/test_op_dispatching.py rename to weave/legacy/tests/test_op_dispatching.py diff --git a/weave/tests/legacy/test_op_serialization.py b/weave/legacy/tests/test_op_serialization.py similarity index 100% rename from weave/tests/legacy/test_op_serialization.py rename to weave/legacy/tests/test_op_serialization.py diff --git a/weave/tests/legacy/test_panel_coverage.py b/weave/legacy/tests/test_panel_coverage.py similarity index 100% rename from weave/tests/legacy/test_panel_coverage.py rename to weave/legacy/tests/test_panel_coverage.py diff --git a/weave/tests/legacy/test_panel_time_series.py b/weave/legacy/tests/test_panel_time_series.py similarity index 100% rename from weave/tests/legacy/test_panel_time_series.py rename to weave/legacy/tests/test_panel_time_series.py diff --git a/weave/tests/legacy/test_panels.py b/weave/legacy/tests/test_panels.py similarity index 100% rename from weave/tests/legacy/test_panels.py rename to weave/legacy/tests/test_panels.py diff --git a/weave/tests/legacy/test_partial_object.py b/weave/legacy/tests/test_partial_object.py similarity index 100% rename from weave/tests/legacy/test_partial_object.py rename to weave/legacy/tests/test_partial_object.py diff --git a/weave/tests/legacy/test_plot.py b/weave/legacy/tests/test_plot.py similarity index 100% rename from weave/tests/legacy/test_plot.py rename to weave/legacy/tests/test_plot.py diff --git a/weave/tests/legacy/test_projection_timeout.py b/weave/legacy/tests/test_projection_timeout.py similarity index 100% rename from weave/tests/legacy/test_projection_timeout.py rename to weave/legacy/tests/test_projection_timeout.py diff --git a/weave/tests/legacy/test_publish_flow.py b/weave/legacy/tests/test_publish_flow.py similarity index 100% rename from weave/tests/legacy/test_publish_flow.py rename to weave/legacy/tests/test_publish_flow.py diff --git a/weave/tests/legacy/test_pydantic.py b/weave/legacy/tests/test_pydantic.py similarity index 100% rename from weave/tests/legacy/test_pydantic.py rename to weave/legacy/tests/test_pydantic.py diff --git a/weave/tests/legacy/test_ref_tracking.py b/weave/legacy/tests/test_ref_tracking.py similarity index 100% rename from weave/tests/legacy/test_ref_tracking.py rename to weave/legacy/tests/test_ref_tracking.py diff --git a/weave/tests/legacy/test_refs.py b/weave/legacy/tests/test_refs.py similarity index 100% rename from weave/tests/legacy/test_refs.py rename to weave/legacy/tests/test_refs.py diff --git a/weave/tests/legacy/test_relpath_no_syscalls.py b/weave/legacy/tests/test_relpath_no_syscalls.py similarity index 100% rename from weave/tests/legacy/test_relpath_no_syscalls.py rename to weave/legacy/tests/test_relpath_no_syscalls.py diff --git a/weave/tests/legacy/test_run_segment.py b/weave/legacy/tests/test_run_segment.py similarity index 100% rename from weave/tests/legacy/test_run_segment.py rename to weave/legacy/tests/test_run_segment.py diff --git a/weave/tests/legacy/test_serialize.py b/weave/legacy/tests/test_serialize.py similarity index 99% rename from weave/tests/legacy/test_serialize.py rename to weave/legacy/tests/test_serialize.py index dc430c95cd1..94251cd1dd4 100644 --- a/weave/tests/legacy/test_serialize.py +++ b/weave/legacy/tests/test_serialize.py @@ -7,7 +7,7 @@ from weave.legacy.ops_primitives import list_ from weave.legacy.weave_internal import make_const_node -from .. import fixture_fakewandb as fwb +from ...tests import fixture_fakewandb as fwb response = { "project_518fa79465d8ffaeb91015dce87e092f": { diff --git a/weave/tests/legacy/test_show.py b/weave/legacy/tests/test_show.py similarity index 100% rename from weave/tests/legacy/test_show.py rename to weave/legacy/tests/test_show.py diff --git a/weave/tests/legacy/test_stitch.py b/weave/legacy/tests/test_stitch.py similarity index 99% rename from weave/tests/legacy/test_stitch.py rename to weave/legacy/tests/test_stitch.py index 54accda3ebd..0c34a27aacd 100644 --- a/weave/tests/legacy/test_stitch.py +++ b/weave/legacy/tests/test_stitch.py @@ -9,7 +9,7 @@ from weave.legacy.ops_domain import run_ops from ...legacy import stitch -from .. import fixture_fakewandb as fwb +from ...tests import fixture_fakewandb as fwb from . import test_wb _loading_builtins_token = _context.set_loading_built_ins() diff --git a/weave/tests/legacy/test_storage.py b/weave/legacy/tests/test_storage.py similarity index 100% rename from weave/tests/legacy/test_storage.py rename to weave/legacy/tests/test_storage.py diff --git a/weave/tests/legacy/test_stream_table.py b/weave/legacy/tests/test_stream_table.py similarity index 100% rename from weave/tests/legacy/test_stream_table.py rename to weave/legacy/tests/test_stream_table.py diff --git a/weave/tests/legacy/test_table_ops.py b/weave/legacy/tests/test_table_ops.py similarity index 99% rename from weave/tests/legacy/test_table_ops.py rename to weave/legacy/tests/test_table_ops.py index 46f4af2e436..f445e71164c 100644 --- a/weave/tests/legacy/test_table_ops.py +++ b/weave/legacy/tests/test_table_ops.py @@ -16,7 +16,7 @@ from weave.legacy import weave_types as types from weave.legacy.ops_domain import table as table_ops -from .. import weavejs_ops +from ...tests import weavejs_ops TABLE_TYPES = ["list", "pandas", "sql"] diff --git a/weave/tests/legacy/test_tagging.py b/weave/legacy/tests/test_tagging.py similarity index 100% rename from weave/tests/legacy/test_tagging.py rename to weave/legacy/tests/test_tagging.py diff --git a/weave/tests/legacy/test_templates.py b/weave/legacy/tests/test_templates.py similarity index 100% rename from weave/tests/legacy/test_templates.py rename to weave/legacy/tests/test_templates.py diff --git a/weave/tests/legacy/test_timestamp_bin.py b/weave/legacy/tests/test_timestamp_bin.py similarity index 100% rename from weave/tests/legacy/test_timestamp_bin.py rename to weave/legacy/tests/test_timestamp_bin.py diff --git a/weave/tests/legacy/test_trace.py b/weave/legacy/tests/test_trace.py similarity index 100% rename from weave/tests/legacy/test_trace.py rename to weave/legacy/tests/test_trace.py diff --git a/weave/tests/legacy/test_typeddict_notrequired.py b/weave/legacy/tests/test_typeddict_notrequired.py similarity index 100% rename from weave/tests/legacy/test_typeddict_notrequired.py rename to weave/legacy/tests/test_typeddict_notrequired.py diff --git a/weave/tests/legacy/test_uris.py b/weave/legacy/tests/test_uris.py similarity index 100% rename from weave/tests/legacy/test_uris.py rename to weave/legacy/tests/test_uris.py diff --git a/weave/tests/legacy/test_wb.py b/weave/legacy/tests/test_wb.py similarity index 99% rename from weave/tests/legacy/test_wb.py rename to weave/legacy/tests/test_wb.py index 065e4b0dc09..db11383c181 100644 --- a/weave/tests/legacy/test_wb.py +++ b/weave/legacy/tests/test_wb.py @@ -17,10 +17,10 @@ from weave.legacy.ops_domain import wb_domain_types as wdt from weave.legacy.ops_primitives import dict_, list_ from weave.legacy.ops_primitives.file import _as_w0_dict_ -from weave.tests.legacy.test_wb_domain_ops import assert_gql_str_equal +from .test_wb_domain_ops import assert_gql_str_equal -from .. import fixture_fakewandb as fwb -from .. import weavejs_ops +from ...tests import fixture_fakewandb as fwb +from ...tests import weavejs_ops file_path_response = { "project_518fa79465d8ffaeb91015dce87e092f": { diff --git a/weave/tests/legacy/test_wb_data_types.py b/weave/legacy/tests/test_wb_data_types.py similarity index 99% rename from weave/tests/legacy/test_wb_data_types.py rename to weave/legacy/tests/test_wb_data_types.py index 7f4c7fd66f1..ea41588b6c3 100644 --- a/weave/tests/legacy/test_wb_data_types.py +++ b/weave/legacy/tests/test_wb_data_types.py @@ -21,7 +21,7 @@ from weave.legacy.wandb_client_api import wandb_gql_query from weave.legacy.wandb_util import weave0_type_json_to_weave1_type -from ..fixture_fakewandb import FakeApi +from ...tests.fixture_fakewandb import FakeApi class RandomClass: diff --git a/weave/tests/legacy/test_wb_domain_ops.py b/weave/legacy/tests/test_wb_domain_ops.py similarity index 99% rename from weave/tests/legacy/test_wb_domain_ops.py rename to weave/legacy/tests/test_wb_domain_ops.py index 5674b65204e..aefaa47c94c 100644 --- a/weave/tests/legacy/test_wb_domain_ops.py +++ b/weave/legacy/tests/test_wb_domain_ops.py @@ -10,7 +10,7 @@ from weave.legacy.ops_primitives import _dict_utils from ...legacy import registry_mem -from .. import fixture_fakewandb as fwb +from ...tests import fixture_fakewandb as fwb """ Tests in this file whould be used to test the graphs that can be constructed diff --git a/weave/tests/legacy/test_wb_domain_types.py b/weave/legacy/tests/test_wb_domain_types.py similarity index 100% rename from weave/tests/legacy/test_wb_domain_types.py rename to weave/legacy/tests/test_wb_domain_types.py diff --git a/weave/tests/legacy/test_wb_end_to_end.py b/weave/legacy/tests/test_wb_end_to_end.py similarity index 100% rename from weave/tests/legacy/test_wb_end_to_end.py rename to weave/legacy/tests/test_wb_end_to_end.py diff --git a/weave/tests/legacy/test_wb_history_loading_compatability.py b/weave/legacy/tests/test_wb_history_loading_compatability.py similarity index 100% rename from weave/tests/legacy/test_wb_history_loading_compatability.py rename to weave/legacy/tests/test_wb_history_loading_compatability.py diff --git a/weave/tests/legacy/test_wb_stream_table.py b/weave/legacy/tests/test_wb_stream_table.py similarity index 100% rename from weave/tests/legacy/test_wb_stream_table.py rename to weave/legacy/tests/test_wb_stream_table.py diff --git a/weave/tests/legacy/test_wb_tables.py b/weave/legacy/tests/test_wb_tables.py similarity index 100% rename from weave/tests/legacy/test_wb_tables.py rename to weave/legacy/tests/test_wb_tables.py diff --git a/weave/tests/legacy/test_weave_api.py b/weave/legacy/tests/test_weave_api.py similarity index 100% rename from weave/tests/legacy/test_weave_api.py rename to weave/legacy/tests/test_weave_api.py diff --git a/weave/tests/legacy/test_weave_types.py b/weave/legacy/tests/test_weave_types.py similarity index 100% rename from weave/tests/legacy/test_weave_types.py rename to weave/legacy/tests/test_weave_types.py diff --git a/weave/tests/legacy/test_weavejs_fixes.py b/weave/legacy/tests/test_weavejs_fixes.py similarity index 100% rename from weave/tests/legacy/test_weavejs_fixes.py rename to weave/legacy/tests/test_weavejs_fixes.py diff --git a/weave/tests/legacy/test_weavify.py b/weave/legacy/tests/test_weavify.py similarity index 98% rename from weave/tests/legacy/test_weavify.py rename to weave/legacy/tests/test_weavify.py index 3e6a845b517..fb67f606c13 100644 --- a/weave/tests/legacy/test_weavify.py +++ b/weave/legacy/tests/test_weavify.py @@ -4,7 +4,7 @@ from weave.legacy import weave_types as types from ...legacy import weavify -from .. import geom +from ...tests import geom @pytest.mark.parametrize( diff --git a/weave/tests/legacy/test_with_columns.py b/weave/legacy/tests/test_with_columns.py similarity index 100% rename from weave/tests/legacy/test_with_columns.py rename to weave/legacy/tests/test_with_columns.py From 54793f25d85e45e0da7cca507c382b4992135b0c Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Sat, 24 Aug 2024 12:31:53 -0400 Subject: [PATCH 57/84] move to legacy: legacy test_utils --- weave/legacy/ops_primitives/test_list.py | 2 +- weave/legacy/ops_primitives/test_typeddict.py | 2 +- weave/legacy/tests/test_arrow.py | 6 +++--- weave/legacy/tests/test_arrow_awl.py | 2 +- weave/legacy/tests/test_arrow_topy.py | 2 +- weave/legacy/tests/test_custom_types.py | 2 +- weave/legacy/tests/test_execute_fast.py | 2 +- weave/legacy/tests/test_list_arrow_compat.py | 4 ++-- weave/legacy/tests/test_op_behaviors.py | 4 ++-- weave/legacy/tests/test_table_ops.py | 2 +- weave/legacy/tests/test_wb.py | 2 +- weave/legacy/tests/test_weavify.py | 2 +- weave/legacy/tests/util/__init__.py | 0 weave/{tests => legacy/tests/util}/concrete_tagged_value.py | 0 weave/{tests => legacy/tests/util}/geom.py | 0 .../{tests => legacy/tests/util}/list_arrow_test_helpers.py | 0 weave/{tests => legacy/tests/util}/op_specs.py | 4 +--- weave/{tests => legacy/tests/util}/tag_test_util.py | 6 +++--- weave/{tests => legacy/tests/util}/weavejs_ops.py | 0 weave/tests/fixture_fakewandb.py | 3 +-- 20 files changed, 21 insertions(+), 24 deletions(-) create mode 100644 weave/legacy/tests/util/__init__.py rename weave/{tests => legacy/tests/util}/concrete_tagged_value.py (100%) rename weave/{tests => legacy/tests/util}/geom.py (100%) rename weave/{tests => legacy/tests/util}/list_arrow_test_helpers.py (100%) rename weave/{tests => legacy/tests/util}/op_specs.py (99%) rename weave/{tests => legacy/tests/util}/tag_test_util.py (83%) rename weave/{tests => legacy/tests/util}/weavejs_ops.py (100%) diff --git a/weave/legacy/ops_primitives/test_list.py b/weave/legacy/ops_primitives/test_list.py index 6507ead3b4a..e9e99073bb0 100644 --- a/weave/legacy/ops_primitives/test_list.py +++ b/weave/legacy/ops_primitives/test_list.py @@ -10,7 +10,7 @@ tagged_value_type, ) from weave.legacy.ops_primitives import dict, errors, list_, number, runs -from weave.tests import geom, weavejs_ops +from weave.legacy.tests.util import geom, weavejs_ops def test_unnest(): diff --git a/weave/legacy/ops_primitives/test_typeddict.py b/weave/legacy/ops_primitives/test_typeddict.py index 6f85584df4d..2818487c9fb 100644 --- a/weave/legacy/ops_primitives/test_typeddict.py +++ b/weave/legacy/ops_primitives/test_typeddict.py @@ -5,7 +5,7 @@ from weave.legacy import box from weave.legacy.arrow.arrow import ArrowWeaveListType from weave.legacy.language_features.tagging import tag_store, tagged_value_type -from weave.tests.list_arrow_test_helpers import ArrowNode +from weave.legacy.tests.util.list_arrow_test_helpers import ArrowNode pick_options = [ # Basic Pick diff --git a/weave/legacy/tests/test_arrow.py b/weave/legacy/tests/test_arrow.py index 2f0a0b71c3c..afad3e65b2d 100644 --- a/weave/legacy/tests/test_arrow.py +++ b/weave/legacy/tests/test_arrow.py @@ -35,10 +35,10 @@ from weave.legacy.op_def import map_type from weave.legacy.ops_domain import project_ops from weave.legacy.ops_primitives import list_, make_list -from weave.tests import list_arrow_test_helpers as lath +from .util import list_arrow_test_helpers as lath -from ...tests import tag_test_util as ttu -from ...tests import weavejs_ops +from weave.legacy.tests.util import tag_test_util as ttu +from weave.legacy.tests.util import weavejs_ops from . import test_wb _loading_builtins_token = context_state.set_loading_built_ins() diff --git a/weave/legacy/tests/test_arrow_awl.py b/weave/legacy/tests/test_arrow_awl.py index c870484343d..62babfc75bd 100644 --- a/weave/legacy/tests/test_arrow_awl.py +++ b/weave/legacy/tests/test_arrow_awl.py @@ -8,7 +8,7 @@ from weave.legacy.arrow.convert import to_arrow from weave.legacy.language_features.tagging import tag_store, tagged_value_type -from ...tests.concrete_tagged_value import ( +from weave.legacy.tests.util.concrete_tagged_value import ( TaggedValue, concrete_from_tagstore, concrete_to_tagstore, diff --git a/weave/legacy/tests/test_arrow_topy.py b/weave/legacy/tests/test_arrow_topy.py index fba5f9d9b18..8e6d87e5c70 100644 --- a/weave/legacy/tests/test_arrow_topy.py +++ b/weave/legacy/tests/test_arrow_topy.py @@ -6,7 +6,7 @@ import weave from weave.legacy import ops_arrow -from ...tests.concrete_tagged_value import ( +from weave.legacy.tests.util.concrete_tagged_value import ( TaggedValue, concrete_from_tagstore, concrete_to_tagstore, diff --git a/weave/legacy/tests/test_custom_types.py b/weave/legacy/tests/test_custom_types.py index 6d47d4c8054..4ee201e8071 100644 --- a/weave/legacy/tests/test_custom_types.py +++ b/weave/legacy/tests/test_custom_types.py @@ -6,7 +6,7 @@ from weave.legacy import ops_arrow from ... import errors -from ...tests import geom +from weave.legacy.tests.util import geom def test_mapped_method_on_custom_type(): diff --git a/weave/legacy/tests/test_execute_fast.py b/weave/legacy/tests/test_execute_fast.py index 663140be8d9..0208f29e662 100644 --- a/weave/legacy/tests/test_execute_fast.py +++ b/weave/legacy/tests/test_execute_fast.py @@ -2,7 +2,7 @@ from weave.legacy import dispatch, weave_internal from weave.legacy import weave_types as types -from ...tests import weavejs_ops +from weave.legacy.tests.util import weavejs_ops def test_nested_weavejs_call(): diff --git a/weave/legacy/tests/test_list_arrow_compat.py b/weave/legacy/tests/test_list_arrow_compat.py index 2cc3663ae2d..d689161abe2 100644 --- a/weave/legacy/tests/test_list_arrow_compat.py +++ b/weave/legacy/tests/test_list_arrow_compat.py @@ -14,8 +14,8 @@ ) from weave.legacy.ops_primitives import dict_, list_ -from ...tests import tag_test_util as ttu -from ...tests import list_arrow_test_helpers as lath +from weave.legacy.tests.util import tag_test_util as ttu +from weave.legacy.tests.util import list_arrow_test_helpers as lath def filter_fn(row) -> bool: diff --git a/weave/legacy/tests/test_op_behaviors.py b/weave/legacy/tests/test_op_behaviors.py index 73f9e786885..4da75809cac 100644 --- a/weave/legacy/tests/test_op_behaviors.py +++ b/weave/legacy/tests/test_op_behaviors.py @@ -28,12 +28,12 @@ ) from ...legacy import registry_mem -from ...tests.concrete_tagged_value import ( +from weave.legacy.tests.util.concrete_tagged_value import ( TaggedValue, concrete_from_tagstore, concrete_to_tagstore, ) -from ...tests.op_specs import OP_TEST_SPECS, OpSpec, OpSpecTestCase +from weave.legacy.tests.util.op_specs import OP_TEST_SPECS, OpSpec, OpSpecTestCase def assert_equal_with_tags(node: graph.Node, v: typing.Any, expected: typing.Any): diff --git a/weave/legacy/tests/test_table_ops.py b/weave/legacy/tests/test_table_ops.py index f445e71164c..83e526edd03 100644 --- a/weave/legacy/tests/test_table_ops.py +++ b/weave/legacy/tests/test_table_ops.py @@ -16,7 +16,7 @@ from weave.legacy import weave_types as types from weave.legacy.ops_domain import table as table_ops -from ...tests import weavejs_ops +from weave.legacy.tests.util import weavejs_ops TABLE_TYPES = ["list", "pandas", "sql"] diff --git a/weave/legacy/tests/test_wb.py b/weave/legacy/tests/test_wb.py index db11383c181..e3f3e96892d 100644 --- a/weave/legacy/tests/test_wb.py +++ b/weave/legacy/tests/test_wb.py @@ -20,7 +20,7 @@ from .test_wb_domain_ops import assert_gql_str_equal from ...tests import fixture_fakewandb as fwb -from ...tests import weavejs_ops +from weave.legacy.tests.util import weavejs_ops file_path_response = { "project_518fa79465d8ffaeb91015dce87e092f": { diff --git a/weave/legacy/tests/test_weavify.py b/weave/legacy/tests/test_weavify.py index fb67f606c13..d92fa838759 100644 --- a/weave/legacy/tests/test_weavify.py +++ b/weave/legacy/tests/test_weavify.py @@ -4,7 +4,7 @@ from weave.legacy import weave_types as types from ...legacy import weavify -from ...tests import geom +from weave.legacy.tests.util import geom @pytest.mark.parametrize( diff --git a/weave/legacy/tests/util/__init__.py b/weave/legacy/tests/util/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/weave/tests/concrete_tagged_value.py b/weave/legacy/tests/util/concrete_tagged_value.py similarity index 100% rename from weave/tests/concrete_tagged_value.py rename to weave/legacy/tests/util/concrete_tagged_value.py diff --git a/weave/tests/geom.py b/weave/legacy/tests/util/geom.py similarity index 100% rename from weave/tests/geom.py rename to weave/legacy/tests/util/geom.py diff --git a/weave/tests/list_arrow_test_helpers.py b/weave/legacy/tests/util/list_arrow_test_helpers.py similarity index 100% rename from weave/tests/list_arrow_test_helpers.py rename to weave/legacy/tests/util/list_arrow_test_helpers.py diff --git a/weave/tests/op_specs.py b/weave/legacy/tests/util/op_specs.py similarity index 99% rename from weave/tests/op_specs.py rename to weave/legacy/tests/util/op_specs.py index cf10582a1b8..5e586cdd983 100644 --- a/weave/tests/op_specs.py +++ b/weave/legacy/tests/util/op_specs.py @@ -7,9 +7,7 @@ from weave.legacy.language_features.tagging import tagged_value_type from weave.legacy.timestamp import PY_DATETIME_MAX_MS, PY_DATETIME_MIN_MS -from .concrete_tagged_value import ( - TaggedValue, -) +from .concrete_tagged_value import TaggedValue @dataclasses.dataclass diff --git a/weave/tests/tag_test_util.py b/weave/legacy/tests/util/tag_test_util.py similarity index 83% rename from weave/tests/tag_test_util.py rename to weave/legacy/tests/util/tag_test_util.py index a444466c413..b83074d0d71 100644 --- a/weave/tests/tag_test_util.py +++ b/weave/legacy/tests/util/tag_test_util.py @@ -8,7 +8,7 @@ tag_adders = 0 -def op_add_tag(obj_node: graph.Node, tags: dict[str, str]): +def op_add_tag(obj_node: graph.Node, tags: dict[str, str]): # type: ignore[no-untyped-def] global tag_adders tag_adders += 1 name = f"_custom_tagger_{tag_adders}" @@ -23,7 +23,7 @@ def op_add_tag(obj_node: graph.Node, tags: dict[str, str]): input_types["obj"], ), ) - def custom_tagger(obj): + def custom_tagger(obj): # type: ignore[no-untyped-def] return tag_store.add_tags( box.box(obj), {f"_ct_{k}": v for k, v in tags.items()} ) @@ -33,7 +33,7 @@ def custom_tagger(obj): return custom_tagger(obj_node) -def make_get_tag(tag_name: str): +def make_get_tag(tag_name: str): # type: ignore[no-untyped-def] from weave.legacy.language_features.tagging import make_tag_getter_op return make_tag_getter_op.make_tag_getter_op(f"_ct_{tag_name}", types.String()) diff --git a/weave/tests/weavejs_ops.py b/weave/legacy/tests/util/weavejs_ops.py similarity index 100% rename from weave/tests/weavejs_ops.py rename to weave/legacy/tests/util/weavejs_ops.py diff --git a/weave/tests/fixture_fakewandb.py b/weave/tests/fixture_fakewandb.py index bbce4d66b91..c5ea0e69773 100644 --- a/weave/tests/fixture_fakewandb.py +++ b/weave/tests/fixture_fakewandb.py @@ -22,8 +22,7 @@ WeaveWBArtifactByIDURI, WeaveWBArtifactURI, ) - -from .tag_test_util import op_add_tag +from weave.legacy.tests.util.tag_test_util import op_add_tag TEST_TABLE_ARTIFACT_PATH = "testdata/wb_artifacits/test_res_1fwmcd3q:v0" ABS_TEST_TABLE_ARTIFACT_PATH = os.path.abspath(TEST_TABLE_ARTIFACT_PATH) From ecf615d1151322e5d5d11bb2595d00aa17f6404c Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Sat, 24 Aug 2024 16:01:02 -0400 Subject: [PATCH 58/84] move to legacy: old query panel examples and notebooks --- .../e2e/notebooks/experimental/AutoBoard.cy.ts | 11 ++++++----- .../e2e/notebooks/experimental/Monitor.cy.ts | 11 ++++++----- .../notebooks/experimental/MonitorPanelPlot.cy.ts | 11 ++++++----- .../e2e/notebooks/experimental/Mutations.cy.ts | 11 ++++++----- .../e2e/notebooks/experimental/app/RunChain.cy.ts | 4 ++-- .../notebooks/experimental/app/beautiful_runs.cy.ts | 11 ++++++----- .../experimental/app/scenario_compare.cy.ts | 11 ++++++----- .../e2e/notebooks/experimental/dir_browsing.cy.ts | 11 ++++++----- .../e2e/notebooks/experimental/ecosystem.cy.ts | 11 ++++++----- .../notebooks/experimental/image_gen_craiyon.cy.ts | 11 ++++++----- .../e2e/notebooks/experimental/layout_panels.cy.ts | 11 ++++++----- .../e2e/notebooks/experimental/spacy_demo.cy.ts | 11 ++++++----- .../notebooks/experimental/table_data_passing.cy.ts | 11 ++++++----- .../e2e/notebooks/experimental/tag_search.cy.ts | 11 ++++++----- .../cypress/e2e/notebooks/get_started.cy.ts | 8 ++++---- .../cypress/e2e/notebooks/reference/WB_API.cy.ts | 11 ++++++----- .../e2e/notebooks/reference/basic_weave_types.cy.ts | 11 ++++++----- .../e2e/notebooks/reference/confusion_matrix.cy.ts | 11 ++++++----- .../notebooks/reference/control/Object Picker.cy.ts | 11 ++++++----- .../e2e/notebooks/reference/control/Slider.cy.ts | 11 ++++++----- .../notebooks/reference/create_plots_ui_guide.cy.ts | 11 ++++++----- .../e2e/notebooks/reference/layout/Each.cy.ts | 11 ++++++----- .../reference/layout/Group & LabeledItem.cy.ts | 11 ++++++----- .../reference/panels/plot/synced_axes.cy.ts | 11 ++++++----- .../e2e/notebooks/reference/vis/Distribution.cy.ts | 11 ++++++----- .../e2e/notebooks/reference/vis/Scatter.cy.ts | 11 ++++++----- .../reference/vis/derived_plots_from_tables.cy.ts | 11 ++++++----- .../legacy/examples}/apps/explore_embeddings.ipynb | 0 .../legacy/examples}/experimental/AutoBoard.ipynb | 0 .../legacy/examples}/experimental/Closures.ipynb | 0 .../legacy/examples}/experimental/Monitor.ipynb | 0 .../examples}/experimental/MonitorPanelPlot.ipynb | 0 .../legacy/examples}/experimental/Mutations.ipynb | 0 .../MonitorPanelPlotGeneric.ipynb | 0 .../ProductionMonitoringConceptualOverview.ipynb | 0 .../ProductionMonitoring/StreamTable.md | 0 .../experimental/ProductionMonitoring/app_util.py | 0 .../experimental/ProductionMonitoring/model_util.py | 0 .../ProductionMonitoring/stream_table_api.ipynb | 0 .../experimental/Table Summary Panel.ipynb | 0 .../examples}/experimental/app/Embeddings.ipynb | 0 .../examples}/experimental/app/RunChain.ipynb | 0 .../examples}/experimental/app/beautiful_runs.ipynb | 0 .../experimental/app/scenario_compare.ipynb | 0 .../legacy/examples}/experimental/bert_viz.ipynb | 0 .../experimental/composite_histograms.ipynb | 0 .../examples}/experimental/dir_browsing.ipynb | 0 .../legacy/examples}/experimental/ecosystem.ipynb | 0 .../experimental/huggingface_datasets.ipynb | 0 .../examples}/experimental/huggingface_models.ipynb | 0 .../examples}/experimental/image_gen_craiyon.ipynb | 0 .../examples}/experimental/image_gen_ops.ipynb | 0 .../examples}/experimental/layout_panels.ipynb | 0 .../examples}/experimental/llm_monitor_helper.ipynb | 0 .../legacy/examples}/experimental/mnist_train.ipynb | 0 .../experimental/object_version_compare.ipynb | 0 .../experimental/old_openai_monitoring.ipynb | 0 .../examples}/experimental/openai_monitoring.ipynb | 0 .../prompts_dev/generate_synth_mon_board.ipynb | 0 .../prompts_dev/synthetic_openai_data.ipynb | 0 .../skip_test/00 Tutorial - Data versioning.ipynb | 0 .../04 Tutorial - Publishing Data and Ops.ipynb | 0 .../skip_test/Composable Python panels.ipynb | 0 .../experimental/skip_test/Confusion Matrix.ipynb | 0 .../experimental/skip_test/Custom ops.ipynb | 0 .../skip_test/Diffusion explore 2.ipynb | 0 .../experimental/skip_test/Diffusion explore.ipynb | 0 .../experimental/skip_test/Diffusion story.ipynb | 0 .../examples}/experimental/skip_test/Docbot.ipynb | 0 .../experimental/skip_test/Hack demo.ipynb | 0 .../experimental/skip_test/KerasModel.ipynb | 0 .../experimental/skip_test/LLMs Via Weave.ipynb | 0 .../experimental/skip_test/Model Cards.ipynb | 0 .../examples}/experimental/skip_test/Models.ipynb | 0 .../examples}/experimental/skip_test/Monitor2.ipynb | 0 .../examples}/experimental/skip_test/Monitor3.ipynb | 0 .../experimental/skip_test/Multiple Y Axes.ipynb | 0 .../skip_test/Mutation - Code Editor.ipynb | 0 .../examples}/experimental/skip_test/Mutation.ipynb | 0 .../experimental/skip_test/Object browsing.ipynb | 0 .../examples}/experimental/skip_test/OpenAI.ipynb | 0 .../skip_test/Oxford-IIIT Pet Dataset.ipynb | 0 .../skip_test/Performance profiling.ipynb | 0 .../skip_test/ProdMonStreamTableIntro.ipynb | 0 .../examples}/experimental/skip_test/Shap.ipynb | 0 .../experimental/skip_test/StreamTables.ipynb | 0 .../experimental/skip_test/TimeSeries.ipynb | 0 .../examples}/experimental/skip_test/Untitled.ipynb | 0 .../experimental/skip_test/Vectorizing.ipynb | 0 .../examples}/experimental/skip_test/WB data.ipynb | 0 .../experimental/skip_test/Weave geo data.ipynb | 0 .../experimental/skip_test/art_explore.ipynb | 0 .../skip_test/assets/op_preview_via_cursor.png | Bin .../experimental/skip_test/branching_runs.ipynb | 0 .../skip_test/evaluation notebook.ipynb | 0 .../skip_test/image_gen_replicate.ipynb | 0 .../experimental/skip_test/langchain docbot.ipynb | 0 .../experimental/skip_test/plot_selection.ipynb | 0 .../examples}/experimental/skip_test/slurm.ipynb | 0 .../skip_test/wandbot from scratch.ipynb | 0 .../skip_test/weave_engine_tracing.ipynb | 0 .../experimental/skip_test/weave_scifi.ipynb | 0 .../experimental/skip_test/weave_walkthrough.ipynb | 0 .../legacy/examples}/experimental/spacy_demo.ipynb | 0 .../examples}/experimental/table_data_passing.ipynb | 0 .../legacy/examples}/experimental/tag_search.ipynb | 0 .../legacy/examples}/get_started.ipynb | 0 .../legacy/examples}/reference/WB_API.ipynb | 0 .../examples}/reference/basic_weave_types.ipynb | 0 .../examples}/reference/confusion_matrix.ipynb | 0 .../examples}/reference/control/Object Picker.ipynb | 0 .../legacy/examples}/reference/control/Slider.ipynb | 0 .../legacy/examples}/reference/create_ops.ipynb | 0 .../examples}/reference/create_plots_ui_guide.ipynb | 0 .../legacy/examples}/reference/layout/Each.ipynb | 0 .../reference/layout/Group & LabeledItem.ipynb | 0 .../legacy/examples}/reference/markdown.ipynb | 0 .../reference/panels/plot/synced_axes.ipynb | 0 .../examples}/reference/vis/Distribution.ipynb | 0 .../legacy/examples}/reference/vis/Scatter.ipynb | 0 .../reference/vis/derived_plots_from_tables.ipynb | 0 121 files changed, 156 insertions(+), 131 deletions(-) rename {examples => weave/legacy/examples}/apps/explore_embeddings.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/AutoBoard.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/Closures.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/Monitor.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/MonitorPanelPlot.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/Mutations.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/ProductionMonitoring/MonitorPanelPlotGeneric.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/ProductionMonitoring/ProductionMonitoringConceptualOverview.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/ProductionMonitoring/StreamTable.md (100%) rename {examples => weave/legacy/examples}/experimental/ProductionMonitoring/app_util.py (100%) rename {examples => weave/legacy/examples}/experimental/ProductionMonitoring/model_util.py (100%) rename {examples => weave/legacy/examples}/experimental/ProductionMonitoring/stream_table_api.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/Table Summary Panel.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/app/Embeddings.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/app/RunChain.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/app/beautiful_runs.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/app/scenario_compare.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/bert_viz.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/composite_histograms.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/dir_browsing.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/ecosystem.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/huggingface_datasets.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/huggingface_models.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/image_gen_craiyon.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/image_gen_ops.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/layout_panels.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/llm_monitor_helper.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/mnist_train.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/object_version_compare.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/old_openai_monitoring.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/openai_monitoring.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/prompts_dev/generate_synth_mon_board.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/prompts_dev/synthetic_openai_data.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/00 Tutorial - Data versioning.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/04 Tutorial - Publishing Data and Ops.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/Composable Python panels.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/Confusion Matrix.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/Custom ops.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/Diffusion explore 2.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/Diffusion explore.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/Diffusion story.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/Docbot.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/Hack demo.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/KerasModel.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/LLMs Via Weave.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/Model Cards.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/Models.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/Monitor2.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/Monitor3.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/Multiple Y Axes.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/Mutation - Code Editor.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/Mutation.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/Object browsing.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/OpenAI.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/Oxford-IIIT Pet Dataset.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/Performance profiling.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/ProdMonStreamTableIntro.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/Shap.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/StreamTables.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/TimeSeries.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/Untitled.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/Vectorizing.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/WB data.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/Weave geo data.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/art_explore.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/assets/op_preview_via_cursor.png (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/branching_runs.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/evaluation notebook.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/image_gen_replicate.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/langchain docbot.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/plot_selection.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/slurm.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/wandbot from scratch.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/weave_engine_tracing.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/weave_scifi.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/skip_test/weave_walkthrough.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/spacy_demo.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/table_data_passing.ipynb (100%) rename {examples => weave/legacy/examples}/experimental/tag_search.ipynb (100%) rename {examples => weave/legacy/examples}/get_started.ipynb (100%) rename {examples => weave/legacy/examples}/reference/WB_API.ipynb (100%) rename {examples => weave/legacy/examples}/reference/basic_weave_types.ipynb (100%) rename {examples => weave/legacy/examples}/reference/confusion_matrix.ipynb (100%) rename {examples => weave/legacy/examples}/reference/control/Object Picker.ipynb (100%) rename {examples => weave/legacy/examples}/reference/control/Slider.ipynb (100%) rename {examples => weave/legacy/examples}/reference/create_ops.ipynb (100%) rename {examples => weave/legacy/examples}/reference/create_plots_ui_guide.ipynb (100%) rename {examples => weave/legacy/examples}/reference/layout/Each.ipynb (100%) rename {examples => weave/legacy/examples}/reference/layout/Group & LabeledItem.ipynb (100%) rename {examples => weave/legacy/examples}/reference/markdown.ipynb (100%) rename {examples => weave/legacy/examples}/reference/panels/plot/synced_axes.ipynb (100%) rename {examples => weave/legacy/examples}/reference/vis/Distribution.ipynb (100%) rename {examples => weave/legacy/examples}/reference/vis/Scatter.ipynb (100%) rename {examples => weave/legacy/examples}/reference/vis/derived_plots_from_tables.ipynb (100%) diff --git a/integration_test/cypress/e2e/notebooks/experimental/AutoBoard.cy.ts b/integration_test/cypress/e2e/notebooks/experimental/AutoBoard.cy.ts index 846e7a7aaf5..dff3492376a 100644 --- a/integration_test/cypress/e2e/notebooks/experimental/AutoBoard.cy.ts +++ b/integration_test/cypress/e2e/notebooks/experimental/AutoBoard.cy.ts @@ -1,7 +1,8 @@ import {checkWeaveNotebookOutputs} from '../notebooks'; -describe('../examples/experimental/AutoBoard.ipynb notebook test', () => { - it('passes', () => - checkWeaveNotebookOutputs('../examples/experimental/AutoBoard.ipynb') - ); -}); \ No newline at end of file +describe('../weave/legacy/examples/experimental/AutoBoard.ipynb notebook test', () => { + it('passes', () => + checkWeaveNotebookOutputs( + '../weave/legacy/examples/experimental/AutoBoard.ipynb' + )); +}); diff --git a/integration_test/cypress/e2e/notebooks/experimental/Monitor.cy.ts b/integration_test/cypress/e2e/notebooks/experimental/Monitor.cy.ts index c7386eea2ec..2a54869af2f 100644 --- a/integration_test/cypress/e2e/notebooks/experimental/Monitor.cy.ts +++ b/integration_test/cypress/e2e/notebooks/experimental/Monitor.cy.ts @@ -1,7 +1,8 @@ import {checkWeaveNotebookOutputs} from '../notebooks'; -describe('../examples/experimental/Monitor.ipynb notebook test', () => { - it('passes', () => - checkWeaveNotebookOutputs('../examples/experimental/Monitor.ipynb') - ); -}); \ No newline at end of file +describe('../weave/legacy/examples/experimental/Monitor.ipynb notebook test', () => { + it('passes', () => + checkWeaveNotebookOutputs( + '../weave/legacy/examples/experimental/Monitor.ipynb' + )); +}); diff --git a/integration_test/cypress/e2e/notebooks/experimental/MonitorPanelPlot.cy.ts b/integration_test/cypress/e2e/notebooks/experimental/MonitorPanelPlot.cy.ts index 149bae1d569..e8f2bfa5958 100644 --- a/integration_test/cypress/e2e/notebooks/experimental/MonitorPanelPlot.cy.ts +++ b/integration_test/cypress/e2e/notebooks/experimental/MonitorPanelPlot.cy.ts @@ -1,7 +1,8 @@ import {checkWeaveNotebookOutputs} from '../notebooks'; -describe('../examples/experimental/MonitorPanelPlot.ipynb notebook test', () => { - it('passes', () => - checkWeaveNotebookOutputs('../examples/experimental/MonitorPanelPlot.ipynb') - ); -}); \ No newline at end of file +describe('../weave/legacy/examples/experimental/MonitorPanelPlot.ipynb notebook test', () => { + it('passes', () => + checkWeaveNotebookOutputs( + '../weave/legacy/examples/experimental/MonitorPanelPlot.ipynb' + )); +}); diff --git a/integration_test/cypress/e2e/notebooks/experimental/Mutations.cy.ts b/integration_test/cypress/e2e/notebooks/experimental/Mutations.cy.ts index 7caa04330d0..7da28147003 100644 --- a/integration_test/cypress/e2e/notebooks/experimental/Mutations.cy.ts +++ b/integration_test/cypress/e2e/notebooks/experimental/Mutations.cy.ts @@ -1,7 +1,8 @@ import {checkWeaveNotebookOutputs} from '../notebooks'; -describe('../examples/experimental/Mutations.ipynb notebook test', () => { - it('passes', () => - checkWeaveNotebookOutputs('../examples/experimental/Mutations.ipynb') - ); -}); \ No newline at end of file +describe('../weave/legacy/examples/experimental/Mutations.ipynb notebook test', () => { + it('passes', () => + checkWeaveNotebookOutputs( + '../weave/legacy/examples/experimental/Mutations.ipynb' + )); +}); diff --git a/integration_test/cypress/e2e/notebooks/experimental/app/RunChain.cy.ts b/integration_test/cypress/e2e/notebooks/experimental/app/RunChain.cy.ts index 38be88c7892..418dc2ff776 100644 --- a/integration_test/cypress/e2e/notebooks/experimental/app/RunChain.cy.ts +++ b/integration_test/cypress/e2e/notebooks/experimental/app/RunChain.cy.ts @@ -1,10 +1,10 @@ import {checkWeaveNotebookOutputs} from '../../notebooks'; -describe('../examples/experimental/app/RunChain.ipynb notebook test', () => { +describe('../weave/legacy/examples/experimental/app/RunChain.ipynb notebook test', () => { // Skipping until this is stable it.skip('passes', () => { return checkWeaveNotebookOutputs( - '../examples/experimental/app/RunChain.ipynb' + '../weave/legacy/examples/experimental/app/RunChain.ipynb' ); }); }); diff --git a/integration_test/cypress/e2e/notebooks/experimental/app/beautiful_runs.cy.ts b/integration_test/cypress/e2e/notebooks/experimental/app/beautiful_runs.cy.ts index 3a817c65bdf..5b25ef8202e 100644 --- a/integration_test/cypress/e2e/notebooks/experimental/app/beautiful_runs.cy.ts +++ b/integration_test/cypress/e2e/notebooks/experimental/app/beautiful_runs.cy.ts @@ -1,7 +1,8 @@ import {checkWeaveNotebookOutputs} from '../../notebooks'; -describe('../examples/experimental/app/beautiful_runs.ipynb notebook test', () => { - it('passes', () => - checkWeaveNotebookOutputs('../examples/experimental/app/beautiful_runs.ipynb') - ); -}); \ No newline at end of file +describe('../weave/legacy/examples/experimental/app/beautiful_runs.ipynb notebook test', () => { + it('passes', () => + checkWeaveNotebookOutputs( + '../weave/legacy/examples/experimental/app/beautiful_runs.ipynb' + )); +}); diff --git a/integration_test/cypress/e2e/notebooks/experimental/app/scenario_compare.cy.ts b/integration_test/cypress/e2e/notebooks/experimental/app/scenario_compare.cy.ts index d15058f6d8e..ec4ab75457b 100644 --- a/integration_test/cypress/e2e/notebooks/experimental/app/scenario_compare.cy.ts +++ b/integration_test/cypress/e2e/notebooks/experimental/app/scenario_compare.cy.ts @@ -1,7 +1,8 @@ import {checkWeaveNotebookOutputs} from '../../notebooks'; -describe('../examples/experimental/app/scenario_compare.ipynb notebook test', () => { - it('passes', () => - checkWeaveNotebookOutputs('../examples/experimental/app/scenario_compare.ipynb') - ); -}); \ No newline at end of file +describe('../weave/legacy/examples/experimental/app/scenario_compare.ipynb notebook test', () => { + it('passes', () => + checkWeaveNotebookOutputs( + '../weave/legacy/examples/experimental/app/scenario_compare.ipynb' + )); +}); diff --git a/integration_test/cypress/e2e/notebooks/experimental/dir_browsing.cy.ts b/integration_test/cypress/e2e/notebooks/experimental/dir_browsing.cy.ts index 27eb8ac7c90..33b8eb15f85 100644 --- a/integration_test/cypress/e2e/notebooks/experimental/dir_browsing.cy.ts +++ b/integration_test/cypress/e2e/notebooks/experimental/dir_browsing.cy.ts @@ -1,7 +1,8 @@ import {checkWeaveNotebookOutputs} from '../notebooks'; -describe('../examples/experimental/dir_browsing.ipynb notebook test', () => { - it('passes', () => - checkWeaveNotebookOutputs('../examples/experimental/dir_browsing.ipynb') - ); -}); \ No newline at end of file +describe('../weave/legacy/examples/experimental/dir_browsing.ipynb notebook test', () => { + it('passes', () => + checkWeaveNotebookOutputs( + '../weave/legacy/examples/experimental/dir_browsing.ipynb' + )); +}); diff --git a/integration_test/cypress/e2e/notebooks/experimental/ecosystem.cy.ts b/integration_test/cypress/e2e/notebooks/experimental/ecosystem.cy.ts index 51f591f77b2..45b124b806d 100644 --- a/integration_test/cypress/e2e/notebooks/experimental/ecosystem.cy.ts +++ b/integration_test/cypress/e2e/notebooks/experimental/ecosystem.cy.ts @@ -1,7 +1,8 @@ import {checkWeaveNotebookOutputs} from '../notebooks'; -describe('../examples/experimental/ecosystem.ipynb notebook test', () => { - it('passes', () => - checkWeaveNotebookOutputs('../examples/experimental/ecosystem.ipynb') - ); -}); \ No newline at end of file +describe('../weave/legacy/examples/experimental/ecosystem.ipynb notebook test', () => { + it('passes', () => + checkWeaveNotebookOutputs( + '../weave/legacy/examples/experimental/ecosystem.ipynb' + )); +}); diff --git a/integration_test/cypress/e2e/notebooks/experimental/image_gen_craiyon.cy.ts b/integration_test/cypress/e2e/notebooks/experimental/image_gen_craiyon.cy.ts index d9427192dd8..ce8e9acb66f 100644 --- a/integration_test/cypress/e2e/notebooks/experimental/image_gen_craiyon.cy.ts +++ b/integration_test/cypress/e2e/notebooks/experimental/image_gen_craiyon.cy.ts @@ -1,7 +1,8 @@ import {checkWeaveNotebookOutputs} from '../notebooks'; -describe('../examples/experimental/image_gen_craiyon.ipynb notebook test', () => { - it('passes', () => - checkWeaveNotebookOutputs('../examples/experimental/image_gen_craiyon.ipynb') - ); -}); \ No newline at end of file +describe('../weave/legacy/examples/experimental/image_gen_craiyon.ipynb notebook test', () => { + it('passes', () => + checkWeaveNotebookOutputs( + '../weave/legacy/examples/experimental/image_gen_craiyon.ipynb' + )); +}); diff --git a/integration_test/cypress/e2e/notebooks/experimental/layout_panels.cy.ts b/integration_test/cypress/e2e/notebooks/experimental/layout_panels.cy.ts index 5b41c7b27ab..536aa496cd4 100644 --- a/integration_test/cypress/e2e/notebooks/experimental/layout_panels.cy.ts +++ b/integration_test/cypress/e2e/notebooks/experimental/layout_panels.cy.ts @@ -1,7 +1,8 @@ import {checkWeaveNotebookOutputs} from '../notebooks'; -describe('../examples/experimental/layout_panels.ipynb notebook test', () => { - it('passes', () => - checkWeaveNotebookOutputs('../examples/experimental/layout_panels.ipynb') - ); -}); \ No newline at end of file +describe('../weave/legacy/examples/experimental/layout_panels.ipynb notebook test', () => { + it('passes', () => + checkWeaveNotebookOutputs( + '../weave/legacy/examples/experimental/layout_panels.ipynb' + )); +}); diff --git a/integration_test/cypress/e2e/notebooks/experimental/spacy_demo.cy.ts b/integration_test/cypress/e2e/notebooks/experimental/spacy_demo.cy.ts index e1808d5b81a..81563c82ba1 100644 --- a/integration_test/cypress/e2e/notebooks/experimental/spacy_demo.cy.ts +++ b/integration_test/cypress/e2e/notebooks/experimental/spacy_demo.cy.ts @@ -1,7 +1,8 @@ import {checkWeaveNotebookOutputs} from '../notebooks'; -describe('../examples/experimental/spacy_demo.ipynb notebook test', () => { - it('passes', () => - checkWeaveNotebookOutputs('../examples/experimental/spacy_demo.ipynb') - ); -}); \ No newline at end of file +describe('../weave/legacy/examples/experimental/spacy_demo.ipynb notebook test', () => { + it('passes', () => + checkWeaveNotebookOutputs( + '../weave/legacy/examples/experimental/spacy_demo.ipynb' + )); +}); diff --git a/integration_test/cypress/e2e/notebooks/experimental/table_data_passing.cy.ts b/integration_test/cypress/e2e/notebooks/experimental/table_data_passing.cy.ts index 1cec68fa389..dda193c3bda 100644 --- a/integration_test/cypress/e2e/notebooks/experimental/table_data_passing.cy.ts +++ b/integration_test/cypress/e2e/notebooks/experimental/table_data_passing.cy.ts @@ -1,7 +1,8 @@ import {checkWeaveNotebookOutputs} from '../notebooks'; -describe('../examples/experimental/table_data_passing.ipynb notebook test', () => { - it('passes', () => - checkWeaveNotebookOutputs('../examples/experimental/table_data_passing.ipynb') - ); -}); \ No newline at end of file +describe('../weave/legacy/examples/experimental/table_data_passing.ipynb notebook test', () => { + it('passes', () => + checkWeaveNotebookOutputs( + '../weave/legacy/examples/experimental/table_data_passing.ipynb' + )); +}); diff --git a/integration_test/cypress/e2e/notebooks/experimental/tag_search.cy.ts b/integration_test/cypress/e2e/notebooks/experimental/tag_search.cy.ts index 8a0a590a263..ed077f50955 100644 --- a/integration_test/cypress/e2e/notebooks/experimental/tag_search.cy.ts +++ b/integration_test/cypress/e2e/notebooks/experimental/tag_search.cy.ts @@ -1,7 +1,8 @@ import {checkWeaveNotebookOutputs} from '../notebooks'; -describe('../examples/experimental/tag_search.ipynb notebook test', () => { - it('passes', () => - checkWeaveNotebookOutputs('../examples/experimental/tag_search.ipynb') - ); -}); \ No newline at end of file +describe('../weave/legacy/examples/experimental/tag_search.ipynb notebook test', () => { + it('passes', () => + checkWeaveNotebookOutputs( + '../weave/legacy/examples/experimental/tag_search.ipynb' + )); +}); diff --git a/integration_test/cypress/e2e/notebooks/get_started.cy.ts b/integration_test/cypress/e2e/notebooks/get_started.cy.ts index d5a5864ed38..edc71adaa1a 100644 --- a/integration_test/cypress/e2e/notebooks/get_started.cy.ts +++ b/integration_test/cypress/e2e/notebooks/get_started.cy.ts @@ -1,7 +1,7 @@ -import {checkWeaveNotebookOutputs} from './notebooks'; +import { checkWeaveNotebookOutputs } from './notebooks'; -describe('../examples/get_started.ipynb notebook test', () => { +describe('../weave/legacy/examples/get_started.ipynb notebook test', () => { it('passes', () => - checkWeaveNotebookOutputs('../examples/get_started.ipynb') + checkWeaveNotebookOutputs('../weave/legacy/examples/get_started.ipynb') ); -}); \ No newline at end of file +}); diff --git a/integration_test/cypress/e2e/notebooks/reference/WB_API.cy.ts b/integration_test/cypress/e2e/notebooks/reference/WB_API.cy.ts index ee5392842b8..95b70e8b197 100644 --- a/integration_test/cypress/e2e/notebooks/reference/WB_API.cy.ts +++ b/integration_test/cypress/e2e/notebooks/reference/WB_API.cy.ts @@ -1,7 +1,8 @@ import {checkWeaveNotebookOutputs} from '../notebooks'; -describe('../examples/reference/WB_API.ipynb notebook test', () => { - it('passes', () => - checkWeaveNotebookOutputs('../examples/reference/WB_API.ipynb') - ); -}); \ No newline at end of file +describe('../weave/legacy/examples/reference/WB_API.ipynb notebook test', () => { + it('passes', () => + checkWeaveNotebookOutputs( + '../weave/legacy/examples/reference/WB_API.ipynb' + )); +}); diff --git a/integration_test/cypress/e2e/notebooks/reference/basic_weave_types.cy.ts b/integration_test/cypress/e2e/notebooks/reference/basic_weave_types.cy.ts index ffc884c3b6a..1d5b0f2db26 100644 --- a/integration_test/cypress/e2e/notebooks/reference/basic_weave_types.cy.ts +++ b/integration_test/cypress/e2e/notebooks/reference/basic_weave_types.cy.ts @@ -1,7 +1,8 @@ import {checkWeaveNotebookOutputs} from '../notebooks'; -describe('../examples/reference/basic_weave_types.ipynb notebook test', () => { - it('passes', () => - checkWeaveNotebookOutputs('../examples/reference/basic_weave_types.ipynb') - ); -}); \ No newline at end of file +describe('../weave/legacy/examples/reference/basic_weave_types.ipynb notebook test', () => { + it('passes', () => + checkWeaveNotebookOutputs( + '../weave/legacy/examples/reference/basic_weave_types.ipynb' + )); +}); diff --git a/integration_test/cypress/e2e/notebooks/reference/confusion_matrix.cy.ts b/integration_test/cypress/e2e/notebooks/reference/confusion_matrix.cy.ts index 76b05398ce1..3be38b4eb2e 100644 --- a/integration_test/cypress/e2e/notebooks/reference/confusion_matrix.cy.ts +++ b/integration_test/cypress/e2e/notebooks/reference/confusion_matrix.cy.ts @@ -1,7 +1,8 @@ import {checkWeaveNotebookOutputs} from '../notebooks'; -describe('../examples/reference/confusion_matrix.ipynb notebook test', () => { - it('passes', () => - checkWeaveNotebookOutputs('../examples/reference/confusion_matrix.ipynb') - ); -}); \ No newline at end of file +describe('../weave/legacy/examples/reference/confusion_matrix.ipynb notebook test', () => { + it('passes', () => + checkWeaveNotebookOutputs( + '../weave/legacy/examples/reference/confusion_matrix.ipynb' + )); +}); diff --git a/integration_test/cypress/e2e/notebooks/reference/control/Object Picker.cy.ts b/integration_test/cypress/e2e/notebooks/reference/control/Object Picker.cy.ts index 125ff013a01..58a8525d577 100644 --- a/integration_test/cypress/e2e/notebooks/reference/control/Object Picker.cy.ts +++ b/integration_test/cypress/e2e/notebooks/reference/control/Object Picker.cy.ts @@ -1,7 +1,8 @@ import {checkWeaveNotebookOutputs} from '../../notebooks'; -describe('../examples/reference/control/Object Picker.ipynb notebook test', () => { - it('passes', () => - checkWeaveNotebookOutputs('../examples/reference/control/Object Picker.ipynb') - ); -}); \ No newline at end of file +describe('../weave/legacy/examples/reference/control/Object Picker.ipynb notebook test', () => { + it('passes', () => + checkWeaveNotebookOutputs( + '../weave/legacy/examples/reference/control/Object Picker.ipynb' + )); +}); diff --git a/integration_test/cypress/e2e/notebooks/reference/control/Slider.cy.ts b/integration_test/cypress/e2e/notebooks/reference/control/Slider.cy.ts index 742dd891f77..b1413fd62b1 100644 --- a/integration_test/cypress/e2e/notebooks/reference/control/Slider.cy.ts +++ b/integration_test/cypress/e2e/notebooks/reference/control/Slider.cy.ts @@ -1,7 +1,8 @@ import {checkWeaveNotebookOutputs} from '../../notebooks'; -describe('../examples/reference/control/Slider.ipynb notebook test', () => { - it('passes', () => - checkWeaveNotebookOutputs('../examples/reference/control/Slider.ipynb') - ); -}); \ No newline at end of file +describe('../weave/legacy/examples/reference/control/Slider.ipynb notebook test', () => { + it('passes', () => + checkWeaveNotebookOutputs( + '../weave/legacy/examples/reference/control/Slider.ipynb' + )); +}); diff --git a/integration_test/cypress/e2e/notebooks/reference/create_plots_ui_guide.cy.ts b/integration_test/cypress/e2e/notebooks/reference/create_plots_ui_guide.cy.ts index 7b8e106b9ea..dac28852865 100644 --- a/integration_test/cypress/e2e/notebooks/reference/create_plots_ui_guide.cy.ts +++ b/integration_test/cypress/e2e/notebooks/reference/create_plots_ui_guide.cy.ts @@ -1,7 +1,8 @@ import {checkWeaveNotebookOutputs} from '../notebooks'; -describe('../examples/reference/create_plots_ui_guide.ipynb notebook test', () => { - it('passes', () => - checkWeaveNotebookOutputs('../examples/reference/create_plots_ui_guide.ipynb') - ); -}); \ No newline at end of file +describe('../weave/legacy/examples/reference/create_plots_ui_guide.ipynb notebook test', () => { + it('passes', () => + checkWeaveNotebookOutputs( + '../weave/legacy/examples/reference/create_plots_ui_guide.ipynb' + )); +}); diff --git a/integration_test/cypress/e2e/notebooks/reference/layout/Each.cy.ts b/integration_test/cypress/e2e/notebooks/reference/layout/Each.cy.ts index bedfb78564e..2979cd6496b 100644 --- a/integration_test/cypress/e2e/notebooks/reference/layout/Each.cy.ts +++ b/integration_test/cypress/e2e/notebooks/reference/layout/Each.cy.ts @@ -1,7 +1,8 @@ import {checkWeaveNotebookOutputs} from '../../notebooks'; -describe('../examples/reference/layout/Each.ipynb notebook test', () => { - it('passes', () => - checkWeaveNotebookOutputs('../examples/reference/layout/Each.ipynb') - ); -}); \ No newline at end of file +describe('../weave/legacy/examples/reference/layout/Each.ipynb notebook test', () => { + it('passes', () => + checkWeaveNotebookOutputs( + '../weave/legacy/examples/reference/layout/Each.ipynb' + )); +}); diff --git a/integration_test/cypress/e2e/notebooks/reference/layout/Group & LabeledItem.cy.ts b/integration_test/cypress/e2e/notebooks/reference/layout/Group & LabeledItem.cy.ts index 418b2e46deb..1dc98c1a348 100644 --- a/integration_test/cypress/e2e/notebooks/reference/layout/Group & LabeledItem.cy.ts +++ b/integration_test/cypress/e2e/notebooks/reference/layout/Group & LabeledItem.cy.ts @@ -1,7 +1,8 @@ import {checkWeaveNotebookOutputs} from '../../notebooks'; -describe('../examples/reference/layout/Group & LabeledItem.ipynb notebook test', () => { - it('passes', () => - checkWeaveNotebookOutputs('../examples/reference/layout/Group & LabeledItem.ipynb') - ); -}); \ No newline at end of file +describe('../weave/legacy/examples/reference/layout/Group & LabeledItem.ipynb notebook test', () => { + it('passes', () => + checkWeaveNotebookOutputs( + '../weave/legacy/examples/reference/layout/Group & LabeledItem.ipynb' + )); +}); diff --git a/integration_test/cypress/e2e/notebooks/reference/panels/plot/synced_axes.cy.ts b/integration_test/cypress/e2e/notebooks/reference/panels/plot/synced_axes.cy.ts index 07cdc0e2c74..bdf79decb3f 100644 --- a/integration_test/cypress/e2e/notebooks/reference/panels/plot/synced_axes.cy.ts +++ b/integration_test/cypress/e2e/notebooks/reference/panels/plot/synced_axes.cy.ts @@ -1,7 +1,8 @@ import {checkWeaveNotebookOutputs} from '../../../notebooks'; -describe('../examples/reference/panels/plot/synced_axes.ipynb notebook test', () => { - it('passes', () => - checkWeaveNotebookOutputs('../examples/reference/panels/plot/synced_axes.ipynb') - ); -}); \ No newline at end of file +describe('../weave/legacy/examples/reference/panels/plot/synced_axes.ipynb notebook test', () => { + it('passes', () => + checkWeaveNotebookOutputs( + '../weave/legacy/examples/reference/panels/plot/synced_axes.ipynb' + )); +}); diff --git a/integration_test/cypress/e2e/notebooks/reference/vis/Distribution.cy.ts b/integration_test/cypress/e2e/notebooks/reference/vis/Distribution.cy.ts index d4c1a853819..5acc7678425 100644 --- a/integration_test/cypress/e2e/notebooks/reference/vis/Distribution.cy.ts +++ b/integration_test/cypress/e2e/notebooks/reference/vis/Distribution.cy.ts @@ -1,7 +1,8 @@ import {checkWeaveNotebookOutputs} from '../../notebooks'; -describe('../examples/reference/vis/Distribution.ipynb notebook test', () => { - it('passes', () => - checkWeaveNotebookOutputs('../examples/reference/vis/Distribution.ipynb') - ); -}); \ No newline at end of file +describe('../weave/legacy/examples/reference/vis/Distribution.ipynb notebook test', () => { + it('passes', () => + checkWeaveNotebookOutputs( + '../weave/legacy/examples/reference/vis/Distribution.ipynb' + )); +}); diff --git a/integration_test/cypress/e2e/notebooks/reference/vis/Scatter.cy.ts b/integration_test/cypress/e2e/notebooks/reference/vis/Scatter.cy.ts index f50850fd37b..9b39b237944 100644 --- a/integration_test/cypress/e2e/notebooks/reference/vis/Scatter.cy.ts +++ b/integration_test/cypress/e2e/notebooks/reference/vis/Scatter.cy.ts @@ -1,7 +1,8 @@ import {checkWeaveNotebookOutputs} from '../../notebooks'; -describe('../examples/reference/vis/Scatter.ipynb notebook test', () => { - it('passes', () => - checkWeaveNotebookOutputs('../examples/reference/vis/Scatter.ipynb') - ); -}); \ No newline at end of file +describe('../weave/legacy/examples/reference/vis/Scatter.ipynb notebook test', () => { + it('passes', () => + checkWeaveNotebookOutputs( + '../weave/legacy/examples/reference/vis/Scatter.ipynb' + )); +}); diff --git a/integration_test/cypress/e2e/notebooks/reference/vis/derived_plots_from_tables.cy.ts b/integration_test/cypress/e2e/notebooks/reference/vis/derived_plots_from_tables.cy.ts index f701fc88836..072da256384 100644 --- a/integration_test/cypress/e2e/notebooks/reference/vis/derived_plots_from_tables.cy.ts +++ b/integration_test/cypress/e2e/notebooks/reference/vis/derived_plots_from_tables.cy.ts @@ -1,7 +1,8 @@ import {checkWeaveNotebookOutputs} from '../../notebooks'; -describe('../examples/reference/vis/derived_plots_from_tables.ipynb notebook test', () => { - it('passes', () => - checkWeaveNotebookOutputs('../examples/reference/vis/derived_plots_from_tables.ipynb') - ); -}); \ No newline at end of file +describe('../weave/legacy/examples/reference/vis/derived_plots_from_tables.ipynb notebook test', () => { + it('passes', () => + checkWeaveNotebookOutputs( + '../weave/legacy/examples/reference/vis/derived_plots_from_tables.ipynb' + )); +}); diff --git a/examples/apps/explore_embeddings.ipynb b/weave/legacy/examples/apps/explore_embeddings.ipynb similarity index 100% rename from examples/apps/explore_embeddings.ipynb rename to weave/legacy/examples/apps/explore_embeddings.ipynb diff --git a/examples/experimental/AutoBoard.ipynb b/weave/legacy/examples/experimental/AutoBoard.ipynb similarity index 100% rename from examples/experimental/AutoBoard.ipynb rename to weave/legacy/examples/experimental/AutoBoard.ipynb diff --git a/examples/experimental/Closures.ipynb b/weave/legacy/examples/experimental/Closures.ipynb similarity index 100% rename from examples/experimental/Closures.ipynb rename to weave/legacy/examples/experimental/Closures.ipynb diff --git a/examples/experimental/Monitor.ipynb b/weave/legacy/examples/experimental/Monitor.ipynb similarity index 100% rename from examples/experimental/Monitor.ipynb rename to weave/legacy/examples/experimental/Monitor.ipynb diff --git a/examples/experimental/MonitorPanelPlot.ipynb b/weave/legacy/examples/experimental/MonitorPanelPlot.ipynb similarity index 100% rename from examples/experimental/MonitorPanelPlot.ipynb rename to weave/legacy/examples/experimental/MonitorPanelPlot.ipynb diff --git a/examples/experimental/Mutations.ipynb b/weave/legacy/examples/experimental/Mutations.ipynb similarity index 100% rename from examples/experimental/Mutations.ipynb rename to weave/legacy/examples/experimental/Mutations.ipynb diff --git a/examples/experimental/ProductionMonitoring/MonitorPanelPlotGeneric.ipynb b/weave/legacy/examples/experimental/ProductionMonitoring/MonitorPanelPlotGeneric.ipynb similarity index 100% rename from examples/experimental/ProductionMonitoring/MonitorPanelPlotGeneric.ipynb rename to weave/legacy/examples/experimental/ProductionMonitoring/MonitorPanelPlotGeneric.ipynb diff --git a/examples/experimental/ProductionMonitoring/ProductionMonitoringConceptualOverview.ipynb b/weave/legacy/examples/experimental/ProductionMonitoring/ProductionMonitoringConceptualOverview.ipynb similarity index 100% rename from examples/experimental/ProductionMonitoring/ProductionMonitoringConceptualOverview.ipynb rename to weave/legacy/examples/experimental/ProductionMonitoring/ProductionMonitoringConceptualOverview.ipynb diff --git a/examples/experimental/ProductionMonitoring/StreamTable.md b/weave/legacy/examples/experimental/ProductionMonitoring/StreamTable.md similarity index 100% rename from examples/experimental/ProductionMonitoring/StreamTable.md rename to weave/legacy/examples/experimental/ProductionMonitoring/StreamTable.md diff --git a/examples/experimental/ProductionMonitoring/app_util.py b/weave/legacy/examples/experimental/ProductionMonitoring/app_util.py similarity index 100% rename from examples/experimental/ProductionMonitoring/app_util.py rename to weave/legacy/examples/experimental/ProductionMonitoring/app_util.py diff --git a/examples/experimental/ProductionMonitoring/model_util.py b/weave/legacy/examples/experimental/ProductionMonitoring/model_util.py similarity index 100% rename from examples/experimental/ProductionMonitoring/model_util.py rename to weave/legacy/examples/experimental/ProductionMonitoring/model_util.py diff --git a/examples/experimental/ProductionMonitoring/stream_table_api.ipynb b/weave/legacy/examples/experimental/ProductionMonitoring/stream_table_api.ipynb similarity index 100% rename from examples/experimental/ProductionMonitoring/stream_table_api.ipynb rename to weave/legacy/examples/experimental/ProductionMonitoring/stream_table_api.ipynb diff --git a/examples/experimental/Table Summary Panel.ipynb b/weave/legacy/examples/experimental/Table Summary Panel.ipynb similarity index 100% rename from examples/experimental/Table Summary Panel.ipynb rename to weave/legacy/examples/experimental/Table Summary Panel.ipynb diff --git a/examples/experimental/app/Embeddings.ipynb b/weave/legacy/examples/experimental/app/Embeddings.ipynb similarity index 100% rename from examples/experimental/app/Embeddings.ipynb rename to weave/legacy/examples/experimental/app/Embeddings.ipynb diff --git a/examples/experimental/app/RunChain.ipynb b/weave/legacy/examples/experimental/app/RunChain.ipynb similarity index 100% rename from examples/experimental/app/RunChain.ipynb rename to weave/legacy/examples/experimental/app/RunChain.ipynb diff --git a/examples/experimental/app/beautiful_runs.ipynb b/weave/legacy/examples/experimental/app/beautiful_runs.ipynb similarity index 100% rename from examples/experimental/app/beautiful_runs.ipynb rename to weave/legacy/examples/experimental/app/beautiful_runs.ipynb diff --git a/examples/experimental/app/scenario_compare.ipynb b/weave/legacy/examples/experimental/app/scenario_compare.ipynb similarity index 100% rename from examples/experimental/app/scenario_compare.ipynb rename to weave/legacy/examples/experimental/app/scenario_compare.ipynb diff --git a/examples/experimental/bert_viz.ipynb b/weave/legacy/examples/experimental/bert_viz.ipynb similarity index 100% rename from examples/experimental/bert_viz.ipynb rename to weave/legacy/examples/experimental/bert_viz.ipynb diff --git a/examples/experimental/composite_histograms.ipynb b/weave/legacy/examples/experimental/composite_histograms.ipynb similarity index 100% rename from examples/experimental/composite_histograms.ipynb rename to weave/legacy/examples/experimental/composite_histograms.ipynb diff --git a/examples/experimental/dir_browsing.ipynb b/weave/legacy/examples/experimental/dir_browsing.ipynb similarity index 100% rename from examples/experimental/dir_browsing.ipynb rename to weave/legacy/examples/experimental/dir_browsing.ipynb diff --git a/examples/experimental/ecosystem.ipynb b/weave/legacy/examples/experimental/ecosystem.ipynb similarity index 100% rename from examples/experimental/ecosystem.ipynb rename to weave/legacy/examples/experimental/ecosystem.ipynb diff --git a/examples/experimental/huggingface_datasets.ipynb b/weave/legacy/examples/experimental/huggingface_datasets.ipynb similarity index 100% rename from examples/experimental/huggingface_datasets.ipynb rename to weave/legacy/examples/experimental/huggingface_datasets.ipynb diff --git a/examples/experimental/huggingface_models.ipynb b/weave/legacy/examples/experimental/huggingface_models.ipynb similarity index 100% rename from examples/experimental/huggingface_models.ipynb rename to weave/legacy/examples/experimental/huggingface_models.ipynb diff --git a/examples/experimental/image_gen_craiyon.ipynb b/weave/legacy/examples/experimental/image_gen_craiyon.ipynb similarity index 100% rename from examples/experimental/image_gen_craiyon.ipynb rename to weave/legacy/examples/experimental/image_gen_craiyon.ipynb diff --git a/examples/experimental/image_gen_ops.ipynb b/weave/legacy/examples/experimental/image_gen_ops.ipynb similarity index 100% rename from examples/experimental/image_gen_ops.ipynb rename to weave/legacy/examples/experimental/image_gen_ops.ipynb diff --git a/examples/experimental/layout_panels.ipynb b/weave/legacy/examples/experimental/layout_panels.ipynb similarity index 100% rename from examples/experimental/layout_panels.ipynb rename to weave/legacy/examples/experimental/layout_panels.ipynb diff --git a/examples/experimental/llm_monitor_helper.ipynb b/weave/legacy/examples/experimental/llm_monitor_helper.ipynb similarity index 100% rename from examples/experimental/llm_monitor_helper.ipynb rename to weave/legacy/examples/experimental/llm_monitor_helper.ipynb diff --git a/examples/experimental/mnist_train.ipynb b/weave/legacy/examples/experimental/mnist_train.ipynb similarity index 100% rename from examples/experimental/mnist_train.ipynb rename to weave/legacy/examples/experimental/mnist_train.ipynb diff --git a/examples/experimental/object_version_compare.ipynb b/weave/legacy/examples/experimental/object_version_compare.ipynb similarity index 100% rename from examples/experimental/object_version_compare.ipynb rename to weave/legacy/examples/experimental/object_version_compare.ipynb diff --git a/examples/experimental/old_openai_monitoring.ipynb b/weave/legacy/examples/experimental/old_openai_monitoring.ipynb similarity index 100% rename from examples/experimental/old_openai_monitoring.ipynb rename to weave/legacy/examples/experimental/old_openai_monitoring.ipynb diff --git a/examples/experimental/openai_monitoring.ipynb b/weave/legacy/examples/experimental/openai_monitoring.ipynb similarity index 100% rename from examples/experimental/openai_monitoring.ipynb rename to weave/legacy/examples/experimental/openai_monitoring.ipynb diff --git a/examples/experimental/prompts_dev/generate_synth_mon_board.ipynb b/weave/legacy/examples/experimental/prompts_dev/generate_synth_mon_board.ipynb similarity index 100% rename from examples/experimental/prompts_dev/generate_synth_mon_board.ipynb rename to weave/legacy/examples/experimental/prompts_dev/generate_synth_mon_board.ipynb diff --git a/examples/experimental/prompts_dev/synthetic_openai_data.ipynb b/weave/legacy/examples/experimental/prompts_dev/synthetic_openai_data.ipynb similarity index 100% rename from examples/experimental/prompts_dev/synthetic_openai_data.ipynb rename to weave/legacy/examples/experimental/prompts_dev/synthetic_openai_data.ipynb diff --git a/examples/experimental/skip_test/00 Tutorial - Data versioning.ipynb b/weave/legacy/examples/experimental/skip_test/00 Tutorial - Data versioning.ipynb similarity index 100% rename from examples/experimental/skip_test/00 Tutorial - Data versioning.ipynb rename to weave/legacy/examples/experimental/skip_test/00 Tutorial - Data versioning.ipynb diff --git a/examples/experimental/skip_test/04 Tutorial - Publishing Data and Ops.ipynb b/weave/legacy/examples/experimental/skip_test/04 Tutorial - Publishing Data and Ops.ipynb similarity index 100% rename from examples/experimental/skip_test/04 Tutorial - Publishing Data and Ops.ipynb rename to weave/legacy/examples/experimental/skip_test/04 Tutorial - Publishing Data and Ops.ipynb diff --git a/examples/experimental/skip_test/Composable Python panels.ipynb b/weave/legacy/examples/experimental/skip_test/Composable Python panels.ipynb similarity index 100% rename from examples/experimental/skip_test/Composable Python panels.ipynb rename to weave/legacy/examples/experimental/skip_test/Composable Python panels.ipynb diff --git a/examples/experimental/skip_test/Confusion Matrix.ipynb b/weave/legacy/examples/experimental/skip_test/Confusion Matrix.ipynb similarity index 100% rename from examples/experimental/skip_test/Confusion Matrix.ipynb rename to weave/legacy/examples/experimental/skip_test/Confusion Matrix.ipynb diff --git a/examples/experimental/skip_test/Custom ops.ipynb b/weave/legacy/examples/experimental/skip_test/Custom ops.ipynb similarity index 100% rename from examples/experimental/skip_test/Custom ops.ipynb rename to weave/legacy/examples/experimental/skip_test/Custom ops.ipynb diff --git a/examples/experimental/skip_test/Diffusion explore 2.ipynb b/weave/legacy/examples/experimental/skip_test/Diffusion explore 2.ipynb similarity index 100% rename from examples/experimental/skip_test/Diffusion explore 2.ipynb rename to weave/legacy/examples/experimental/skip_test/Diffusion explore 2.ipynb diff --git a/examples/experimental/skip_test/Diffusion explore.ipynb b/weave/legacy/examples/experimental/skip_test/Diffusion explore.ipynb similarity index 100% rename from examples/experimental/skip_test/Diffusion explore.ipynb rename to weave/legacy/examples/experimental/skip_test/Diffusion explore.ipynb diff --git a/examples/experimental/skip_test/Diffusion story.ipynb b/weave/legacy/examples/experimental/skip_test/Diffusion story.ipynb similarity index 100% rename from examples/experimental/skip_test/Diffusion story.ipynb rename to weave/legacy/examples/experimental/skip_test/Diffusion story.ipynb diff --git a/examples/experimental/skip_test/Docbot.ipynb b/weave/legacy/examples/experimental/skip_test/Docbot.ipynb similarity index 100% rename from examples/experimental/skip_test/Docbot.ipynb rename to weave/legacy/examples/experimental/skip_test/Docbot.ipynb diff --git a/examples/experimental/skip_test/Hack demo.ipynb b/weave/legacy/examples/experimental/skip_test/Hack demo.ipynb similarity index 100% rename from examples/experimental/skip_test/Hack demo.ipynb rename to weave/legacy/examples/experimental/skip_test/Hack demo.ipynb diff --git a/examples/experimental/skip_test/KerasModel.ipynb b/weave/legacy/examples/experimental/skip_test/KerasModel.ipynb similarity index 100% rename from examples/experimental/skip_test/KerasModel.ipynb rename to weave/legacy/examples/experimental/skip_test/KerasModel.ipynb diff --git a/examples/experimental/skip_test/LLMs Via Weave.ipynb b/weave/legacy/examples/experimental/skip_test/LLMs Via Weave.ipynb similarity index 100% rename from examples/experimental/skip_test/LLMs Via Weave.ipynb rename to weave/legacy/examples/experimental/skip_test/LLMs Via Weave.ipynb diff --git a/examples/experimental/skip_test/Model Cards.ipynb b/weave/legacy/examples/experimental/skip_test/Model Cards.ipynb similarity index 100% rename from examples/experimental/skip_test/Model Cards.ipynb rename to weave/legacy/examples/experimental/skip_test/Model Cards.ipynb diff --git a/examples/experimental/skip_test/Models.ipynb b/weave/legacy/examples/experimental/skip_test/Models.ipynb similarity index 100% rename from examples/experimental/skip_test/Models.ipynb rename to weave/legacy/examples/experimental/skip_test/Models.ipynb diff --git a/examples/experimental/skip_test/Monitor2.ipynb b/weave/legacy/examples/experimental/skip_test/Monitor2.ipynb similarity index 100% rename from examples/experimental/skip_test/Monitor2.ipynb rename to weave/legacy/examples/experimental/skip_test/Monitor2.ipynb diff --git a/examples/experimental/skip_test/Monitor3.ipynb b/weave/legacy/examples/experimental/skip_test/Monitor3.ipynb similarity index 100% rename from examples/experimental/skip_test/Monitor3.ipynb rename to weave/legacy/examples/experimental/skip_test/Monitor3.ipynb diff --git a/examples/experimental/skip_test/Multiple Y Axes.ipynb b/weave/legacy/examples/experimental/skip_test/Multiple Y Axes.ipynb similarity index 100% rename from examples/experimental/skip_test/Multiple Y Axes.ipynb rename to weave/legacy/examples/experimental/skip_test/Multiple Y Axes.ipynb diff --git a/examples/experimental/skip_test/Mutation - Code Editor.ipynb b/weave/legacy/examples/experimental/skip_test/Mutation - Code Editor.ipynb similarity index 100% rename from examples/experimental/skip_test/Mutation - Code Editor.ipynb rename to weave/legacy/examples/experimental/skip_test/Mutation - Code Editor.ipynb diff --git a/examples/experimental/skip_test/Mutation.ipynb b/weave/legacy/examples/experimental/skip_test/Mutation.ipynb similarity index 100% rename from examples/experimental/skip_test/Mutation.ipynb rename to weave/legacy/examples/experimental/skip_test/Mutation.ipynb diff --git a/examples/experimental/skip_test/Object browsing.ipynb b/weave/legacy/examples/experimental/skip_test/Object browsing.ipynb similarity index 100% rename from examples/experimental/skip_test/Object browsing.ipynb rename to weave/legacy/examples/experimental/skip_test/Object browsing.ipynb diff --git a/examples/experimental/skip_test/OpenAI.ipynb b/weave/legacy/examples/experimental/skip_test/OpenAI.ipynb similarity index 100% rename from examples/experimental/skip_test/OpenAI.ipynb rename to weave/legacy/examples/experimental/skip_test/OpenAI.ipynb diff --git a/examples/experimental/skip_test/Oxford-IIIT Pet Dataset.ipynb b/weave/legacy/examples/experimental/skip_test/Oxford-IIIT Pet Dataset.ipynb similarity index 100% rename from examples/experimental/skip_test/Oxford-IIIT Pet Dataset.ipynb rename to weave/legacy/examples/experimental/skip_test/Oxford-IIIT Pet Dataset.ipynb diff --git a/examples/experimental/skip_test/Performance profiling.ipynb b/weave/legacy/examples/experimental/skip_test/Performance profiling.ipynb similarity index 100% rename from examples/experimental/skip_test/Performance profiling.ipynb rename to weave/legacy/examples/experimental/skip_test/Performance profiling.ipynb diff --git a/examples/experimental/skip_test/ProdMonStreamTableIntro.ipynb b/weave/legacy/examples/experimental/skip_test/ProdMonStreamTableIntro.ipynb similarity index 100% rename from examples/experimental/skip_test/ProdMonStreamTableIntro.ipynb rename to weave/legacy/examples/experimental/skip_test/ProdMonStreamTableIntro.ipynb diff --git a/examples/experimental/skip_test/Shap.ipynb b/weave/legacy/examples/experimental/skip_test/Shap.ipynb similarity index 100% rename from examples/experimental/skip_test/Shap.ipynb rename to weave/legacy/examples/experimental/skip_test/Shap.ipynb diff --git a/examples/experimental/skip_test/StreamTables.ipynb b/weave/legacy/examples/experimental/skip_test/StreamTables.ipynb similarity index 100% rename from examples/experimental/skip_test/StreamTables.ipynb rename to weave/legacy/examples/experimental/skip_test/StreamTables.ipynb diff --git a/examples/experimental/skip_test/TimeSeries.ipynb b/weave/legacy/examples/experimental/skip_test/TimeSeries.ipynb similarity index 100% rename from examples/experimental/skip_test/TimeSeries.ipynb rename to weave/legacy/examples/experimental/skip_test/TimeSeries.ipynb diff --git a/examples/experimental/skip_test/Untitled.ipynb b/weave/legacy/examples/experimental/skip_test/Untitled.ipynb similarity index 100% rename from examples/experimental/skip_test/Untitled.ipynb rename to weave/legacy/examples/experimental/skip_test/Untitled.ipynb diff --git a/examples/experimental/skip_test/Vectorizing.ipynb b/weave/legacy/examples/experimental/skip_test/Vectorizing.ipynb similarity index 100% rename from examples/experimental/skip_test/Vectorizing.ipynb rename to weave/legacy/examples/experimental/skip_test/Vectorizing.ipynb diff --git a/examples/experimental/skip_test/WB data.ipynb b/weave/legacy/examples/experimental/skip_test/WB data.ipynb similarity index 100% rename from examples/experimental/skip_test/WB data.ipynb rename to weave/legacy/examples/experimental/skip_test/WB data.ipynb diff --git a/examples/experimental/skip_test/Weave geo data.ipynb b/weave/legacy/examples/experimental/skip_test/Weave geo data.ipynb similarity index 100% rename from examples/experimental/skip_test/Weave geo data.ipynb rename to weave/legacy/examples/experimental/skip_test/Weave geo data.ipynb diff --git a/examples/experimental/skip_test/art_explore.ipynb b/weave/legacy/examples/experimental/skip_test/art_explore.ipynb similarity index 100% rename from examples/experimental/skip_test/art_explore.ipynb rename to weave/legacy/examples/experimental/skip_test/art_explore.ipynb diff --git a/examples/experimental/skip_test/assets/op_preview_via_cursor.png b/weave/legacy/examples/experimental/skip_test/assets/op_preview_via_cursor.png similarity index 100% rename from examples/experimental/skip_test/assets/op_preview_via_cursor.png rename to weave/legacy/examples/experimental/skip_test/assets/op_preview_via_cursor.png diff --git a/examples/experimental/skip_test/branching_runs.ipynb b/weave/legacy/examples/experimental/skip_test/branching_runs.ipynb similarity index 100% rename from examples/experimental/skip_test/branching_runs.ipynb rename to weave/legacy/examples/experimental/skip_test/branching_runs.ipynb diff --git a/examples/experimental/skip_test/evaluation notebook.ipynb b/weave/legacy/examples/experimental/skip_test/evaluation notebook.ipynb similarity index 100% rename from examples/experimental/skip_test/evaluation notebook.ipynb rename to weave/legacy/examples/experimental/skip_test/evaluation notebook.ipynb diff --git a/examples/experimental/skip_test/image_gen_replicate.ipynb b/weave/legacy/examples/experimental/skip_test/image_gen_replicate.ipynb similarity index 100% rename from examples/experimental/skip_test/image_gen_replicate.ipynb rename to weave/legacy/examples/experimental/skip_test/image_gen_replicate.ipynb diff --git a/examples/experimental/skip_test/langchain docbot.ipynb b/weave/legacy/examples/experimental/skip_test/langchain docbot.ipynb similarity index 100% rename from examples/experimental/skip_test/langchain docbot.ipynb rename to weave/legacy/examples/experimental/skip_test/langchain docbot.ipynb diff --git a/examples/experimental/skip_test/plot_selection.ipynb b/weave/legacy/examples/experimental/skip_test/plot_selection.ipynb similarity index 100% rename from examples/experimental/skip_test/plot_selection.ipynb rename to weave/legacy/examples/experimental/skip_test/plot_selection.ipynb diff --git a/examples/experimental/skip_test/slurm.ipynb b/weave/legacy/examples/experimental/skip_test/slurm.ipynb similarity index 100% rename from examples/experimental/skip_test/slurm.ipynb rename to weave/legacy/examples/experimental/skip_test/slurm.ipynb diff --git a/examples/experimental/skip_test/wandbot from scratch.ipynb b/weave/legacy/examples/experimental/skip_test/wandbot from scratch.ipynb similarity index 100% rename from examples/experimental/skip_test/wandbot from scratch.ipynb rename to weave/legacy/examples/experimental/skip_test/wandbot from scratch.ipynb diff --git a/examples/experimental/skip_test/weave_engine_tracing.ipynb b/weave/legacy/examples/experimental/skip_test/weave_engine_tracing.ipynb similarity index 100% rename from examples/experimental/skip_test/weave_engine_tracing.ipynb rename to weave/legacy/examples/experimental/skip_test/weave_engine_tracing.ipynb diff --git a/examples/experimental/skip_test/weave_scifi.ipynb b/weave/legacy/examples/experimental/skip_test/weave_scifi.ipynb similarity index 100% rename from examples/experimental/skip_test/weave_scifi.ipynb rename to weave/legacy/examples/experimental/skip_test/weave_scifi.ipynb diff --git a/examples/experimental/skip_test/weave_walkthrough.ipynb b/weave/legacy/examples/experimental/skip_test/weave_walkthrough.ipynb similarity index 100% rename from examples/experimental/skip_test/weave_walkthrough.ipynb rename to weave/legacy/examples/experimental/skip_test/weave_walkthrough.ipynb diff --git a/examples/experimental/spacy_demo.ipynb b/weave/legacy/examples/experimental/spacy_demo.ipynb similarity index 100% rename from examples/experimental/spacy_demo.ipynb rename to weave/legacy/examples/experimental/spacy_demo.ipynb diff --git a/examples/experimental/table_data_passing.ipynb b/weave/legacy/examples/experimental/table_data_passing.ipynb similarity index 100% rename from examples/experimental/table_data_passing.ipynb rename to weave/legacy/examples/experimental/table_data_passing.ipynb diff --git a/examples/experimental/tag_search.ipynb b/weave/legacy/examples/experimental/tag_search.ipynb similarity index 100% rename from examples/experimental/tag_search.ipynb rename to weave/legacy/examples/experimental/tag_search.ipynb diff --git a/examples/get_started.ipynb b/weave/legacy/examples/get_started.ipynb similarity index 100% rename from examples/get_started.ipynb rename to weave/legacy/examples/get_started.ipynb diff --git a/examples/reference/WB_API.ipynb b/weave/legacy/examples/reference/WB_API.ipynb similarity index 100% rename from examples/reference/WB_API.ipynb rename to weave/legacy/examples/reference/WB_API.ipynb diff --git a/examples/reference/basic_weave_types.ipynb b/weave/legacy/examples/reference/basic_weave_types.ipynb similarity index 100% rename from examples/reference/basic_weave_types.ipynb rename to weave/legacy/examples/reference/basic_weave_types.ipynb diff --git a/examples/reference/confusion_matrix.ipynb b/weave/legacy/examples/reference/confusion_matrix.ipynb similarity index 100% rename from examples/reference/confusion_matrix.ipynb rename to weave/legacy/examples/reference/confusion_matrix.ipynb diff --git a/examples/reference/control/Object Picker.ipynb b/weave/legacy/examples/reference/control/Object Picker.ipynb similarity index 100% rename from examples/reference/control/Object Picker.ipynb rename to weave/legacy/examples/reference/control/Object Picker.ipynb diff --git a/examples/reference/control/Slider.ipynb b/weave/legacy/examples/reference/control/Slider.ipynb similarity index 100% rename from examples/reference/control/Slider.ipynb rename to weave/legacy/examples/reference/control/Slider.ipynb diff --git a/examples/reference/create_ops.ipynb b/weave/legacy/examples/reference/create_ops.ipynb similarity index 100% rename from examples/reference/create_ops.ipynb rename to weave/legacy/examples/reference/create_ops.ipynb diff --git a/examples/reference/create_plots_ui_guide.ipynb b/weave/legacy/examples/reference/create_plots_ui_guide.ipynb similarity index 100% rename from examples/reference/create_plots_ui_guide.ipynb rename to weave/legacy/examples/reference/create_plots_ui_guide.ipynb diff --git a/examples/reference/layout/Each.ipynb b/weave/legacy/examples/reference/layout/Each.ipynb similarity index 100% rename from examples/reference/layout/Each.ipynb rename to weave/legacy/examples/reference/layout/Each.ipynb diff --git a/examples/reference/layout/Group & LabeledItem.ipynb b/weave/legacy/examples/reference/layout/Group & LabeledItem.ipynb similarity index 100% rename from examples/reference/layout/Group & LabeledItem.ipynb rename to weave/legacy/examples/reference/layout/Group & LabeledItem.ipynb diff --git a/examples/reference/markdown.ipynb b/weave/legacy/examples/reference/markdown.ipynb similarity index 100% rename from examples/reference/markdown.ipynb rename to weave/legacy/examples/reference/markdown.ipynb diff --git a/examples/reference/panels/plot/synced_axes.ipynb b/weave/legacy/examples/reference/panels/plot/synced_axes.ipynb similarity index 100% rename from examples/reference/panels/plot/synced_axes.ipynb rename to weave/legacy/examples/reference/panels/plot/synced_axes.ipynb diff --git a/examples/reference/vis/Distribution.ipynb b/weave/legacy/examples/reference/vis/Distribution.ipynb similarity index 100% rename from examples/reference/vis/Distribution.ipynb rename to weave/legacy/examples/reference/vis/Distribution.ipynb diff --git a/examples/reference/vis/Scatter.ipynb b/weave/legacy/examples/reference/vis/Scatter.ipynb similarity index 100% rename from examples/reference/vis/Scatter.ipynb rename to weave/legacy/examples/reference/vis/Scatter.ipynb diff --git a/examples/reference/vis/derived_plots_from_tables.ipynb b/weave/legacy/examples/reference/vis/derived_plots_from_tables.ipynb similarity index 100% rename from examples/reference/vis/derived_plots_from_tables.ipynb rename to weave/legacy/examples/reference/vis/derived_plots_from_tables.ipynb From cb4fd965f5dc9d90bde99804f01add798e3217d8 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Sat, 24 Aug 2024 16:08:45 -0400 Subject: [PATCH 59/84] move to legacy: makefile --- Makefile => weave/legacy/Makefile | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Makefile => weave/legacy/Makefile (100%) diff --git a/Makefile b/weave/legacy/Makefile similarity index 100% rename from Makefile rename to weave/legacy/Makefile From dd06747ef03476a24be4fcdb9c484efb48a7a2f4 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Sun, 25 Aug 2024 12:01:11 -0400 Subject: [PATCH 60/84] !!! move files from weave/legacy -> weave/legacy/weave to match new repo --- .github/workflows/test.yaml | 31 +- examples/prompts/llm_monitoring/README.md | 2 +- .../openai_client_quickstart.ipynb | 4 +- ...nai_proxy_quickstart_enterprise_mode.ipynb | 4 +- .../dev/synthetic_trace_data.ipynb | 2 +- .../trace_quickstart_decorator.ipynb | 2 +- .../trace_quickstart_langchain.ipynb | 2 +- .../cypress/e2e/interactive/blank.py | 4 +- .../cypress/e2e/interactive/distribution.py | 9 +- .../cypress/e2e/interactive/scatter.py | 10 +- mypy.ini | 90 +- pyrightconfig.json | 2 +- weave/__init__.py | 26 +- weave/conftest.py | 14 +- weave/deploy/gcp/__init__.py | 4 +- weave/deploy/modal/__init__.py | 4 +- weave/deploy/modal/stub.py | 2 +- weave/legacy/Dockerfile | 51 + weave/legacy/core_types/__init__.py | 1 - weave/legacy/ecosystem/__init__.py | 1 - weave/legacy/ecosystem/bertviz/__init__.py | 1 - weave/legacy/ecosystem/craiyon/__init__.py | 1 - .../legacy/ecosystem/huggingface/__init__.py | 12 - weave/legacy/ecosystem/keras/__init__.py | 6 - weave/legacy/ecosystem/lens/__init__.py | 1 - weave/legacy/ecosystem/py/__init__.py | 1 - weave/legacy/ecosystem/pytorch/__init__.py | 1 - weave/legacy/ecosystem/sklearn/__init__.py | 1 - weave/legacy/ecosystem/slack/__init__.py | 2 - weave/legacy/ecosystem/slurm/__init__.py | 1 - .../legacy/ecosystem/torchvision/__init__.py | 1 - weave/legacy/ecosystem/wandb/__init__.py | 13 - .../examples/apps/explore_embeddings.ipynb | 756 +++++++-------- .../examples/experimental/AutoBoard.ipynb | 176 ++-- .../examples/experimental/Monitor.ipynb | 432 ++++----- .../experimental/MonitorPanelPlot.ipynb | 498 +++++----- .../examples/experimental/Mutations.ipynb | 134 +-- .../MonitorPanelPlotGeneric.ipynb | 794 ++++++++-------- ...oductionMonitoringConceptualOverview.ipynb | 710 +++++++------- .../ProductionMonitoring/StreamTable.md | 2 +- .../stream_table_api.ipynb | 314 +++---- .../experimental/Table Summary Panel.ipynb | 184 ++-- .../experimental/app/Embeddings.ipynb | 240 ++--- .../examples/experimental/app/RunChain.ipynb | 348 +++---- .../experimental/app/beautiful_runs.ipynb | 316 +++---- .../experimental/app/scenario_compare.ipynb | 346 +++---- .../examples/experimental/bert_viz.ipynb | 134 +-- .../experimental/composite_histograms.ipynb | 266 +++--- .../examples/experimental/dir_browsing.ipynb | 48 +- .../examples/experimental/ecosystem.ipynb | 46 +- .../experimental/huggingface_datasets.ipynb | 172 ++-- .../experimental/huggingface_models.ipynb | 256 ++--- .../experimental/image_gen_craiyon.ipynb | 98 +- .../examples/experimental/image_gen_ops.ipynb | 246 ++--- .../examples/experimental/layout_panels.ipynb | 406 ++++---- .../experimental/llm_monitor_helper.ipynb | 390 ++++---- .../examples/experimental/mnist_train.ipynb | 158 ++-- .../experimental/object_version_compare.ipynb | 226 ++--- .../experimental/old_openai_monitoring.ipynb | 446 ++++----- .../experimental/openai_monitoring.ipynb | 474 +++++----- .../generate_synth_mon_board.ipynb | 378 ++++---- .../prompts_dev/synthetic_openai_data.ipynb | 328 +++---- ...4 Tutorial - Publishing Data and Ops.ipynb | 244 ++--- .../skip_test/Composable Python panels.ipynb | 152 +-- .../skip_test/Confusion Matrix.ipynb | 570 +++++------ .../experimental/skip_test/Custom ops.ipynb | 292 +++--- .../skip_test/Diffusion explore 2.ipynb | 196 ++-- .../skip_test/Diffusion explore.ipynb | 332 +++---- .../skip_test/Diffusion story.ipynb | 238 ++--- .../experimental/skip_test/Docbot.ipynb | 652 ++++++------- .../experimental/skip_test/Hack demo.ipynb | 228 ++--- .../experimental/skip_test/KerasModel.ipynb | 604 ++++++------ .../skip_test/LLMs Via Weave.ipynb | 216 ++--- .../experimental/skip_test/Model Cards.ipynb | 152 +-- .../experimental/skip_test/Models.ipynb | 200 ++-- .../experimental/skip_test/Monitor2.ipynb | 614 ++++++------ .../experimental/skip_test/Monitor3.ipynb | 634 ++++++------- .../skip_test/Multiple Y Axes.ipynb | 362 +++---- .../skip_test/Mutation - Code Editor.ipynb | 104 +-- .../experimental/skip_test/Mutation.ipynb | 102 +- .../experimental/skip_test/OpenAI.ipynb | 206 ++-- .../skip_test/Oxford-IIIT Pet Dataset.ipynb | 224 ++--- .../skip_test/Performance profiling.ipynb | 300 +++--- .../skip_test/ProdMonStreamTableIntro.ipynb | 264 +++--- .../experimental/skip_test/Shap.ipynb | 114 +-- .../experimental/skip_test/StreamTables.ipynb | 178 ++-- .../experimental/skip_test/TimeSeries.ipynb | 290 +++--- .../experimental/skip_test/Untitled.ipynb | 96 +- .../experimental/skip_test/Vectorizing.ipynb | 176 ++-- .../experimental/skip_test/WB data.ipynb | 154 +-- .../skip_test/Weave geo data.ipynb | 206 ++-- .../experimental/skip_test/art_explore.ipynb | 276 +++--- .../skip_test/branching_runs.ipynb | 424 ++++----- .../skip_test/image_gen_replicate.ipynb | 148 +-- .../skip_test/langchain docbot.ipynb | 172 ++-- .../skip_test/plot_selection.ipynb | 120 +-- .../experimental/skip_test/slurm.ipynb | 126 +-- .../skip_test/weave_engine_tracing.ipynb | 246 ++--- .../experimental/skip_test/weave_scifi.ipynb | 154 +-- .../examples/experimental/spacy_demo.ipynb | 98 +- .../experimental/table_data_passing.ipynb | 158 ++-- .../examples/experimental/tag_search.ipynb | 214 ++--- weave/legacy/examples/get_started.ipynb | 596 ++++++------ weave/legacy/examples/reference/WB_API.ipynb | 172 ++-- .../examples/reference/confusion_matrix.ipynb | 462 ++++----- .../reference/control/Object Picker.ipynb | 236 ++--- .../examples/reference/control/Slider.ipynb | 144 +-- .../reference/create_plots_ui_guide.ipynb | 654 ++++++------- .../examples/reference/layout/Each.ipynb | 134 +-- .../layout/Group & LabeledItem.ipynb | 90 +- .../legacy/examples/reference/markdown.ipynb | 94 +- .../reference/panels/plot/synced_axes.ipynb | 300 +++--- .../examples/reference/vis/Distribution.ipynb | 270 +++--- .../examples/reference/vis/Scatter.ipynb | 196 ++-- .../vis/derived_plots_from_tables.ipynb | 216 ++--- weave/legacy/notebooks/Eval Board Syn.ipynb | 630 ++++++------- weave/legacy/notebooks/Eval Board.ipynb | 310 +++--- .../notebooks/Text Extraction Eval.ipynb | 884 +++++++++--------- weave/legacy/ops_arrow/__init__.py | 12 - weave/legacy/ops_arrow/ops.py | 11 - .../legacy/ops_primitives/test_list_range.py | 7 - weave/legacy/panels/__init__.py | 70 -- weave/legacy/scripts/clear_cache.py | 2 +- weave/legacy/scripts/syndata.py | 4 +- weave/legacy/scripts/syndata_mon.py | 2 +- weave/legacy/tests/test_access.py | 4 +- weave/legacy/tests/test_api.py | 4 +- weave/legacy/tests/test_arrow.py | 22 +- weave/legacy/tests/test_arrow_awl.py | 8 +- weave/legacy/tests/test_arrow_concat.py | 6 +- weave/legacy/tests/test_arrow_perf.py | 2 +- weave/legacy/tests/test_arrow_topy.py | 2 +- weave/legacy/tests/test_arrow_vectorizer.py | 18 +- weave/legacy/tests/test_artifact.py | 4 +- weave/legacy/tests/test_artifact_metadata.py | 10 +- weave/legacy/tests/test_assignment.py | 2 +- weave/legacy/tests/test_async.py | 2 +- weave/legacy/tests/test_async_queue.py | 2 +- weave/legacy/tests/test_basic_ops.py | 10 +- weave/legacy/tests/test_box.py | 2 +- weave/legacy/tests/test_cache.py | 2 +- weave/legacy/tests/test_codify.py | 70 +- weave/legacy/tests/test_compile.py | 40 +- weave/legacy/tests/test_complex_calls.py | 2 +- weave/legacy/tests/test_cond.py | 32 +- weave/legacy/tests/test_const_type_mapper.py | 2 +- weave/legacy/tests/test_custom_types.py | 6 +- weave/legacy/tests/test_datetime_timestamp.py | 2 +- weave/legacy/tests/test_decorators.py | 8 +- weave/legacy/tests/test_derive_op.py | 4 +- weave/legacy/tests/test_dispatch.py | 2 +- weave/legacy/tests/test_examples.py | 4 +- weave/legacy/tests/test_execute.py | 12 +- weave/legacy/tests/test_execute_fast.py | 6 +- weave/legacy/tests/test_execution_graphs.py | 4 +- weave/legacy/tests/test_file.py | 2 +- weave/legacy/tests/test_filesystem.py | 2 +- weave/legacy/tests/test_gql_to_weave.py | 4 +- weave/legacy/tests/test_graph.py | 4 +- weave/legacy/tests/test_graph_debug.py | 2 +- weave/legacy/tests/test_hypothesis.py | 6 +- weave/legacy/tests/test_infer_types.py | 2 +- weave/legacy/tests/test_io_service.py | 2 +- weave/legacy/tests/test_join.py | 6 +- weave/legacy/tests/test_js_compat.py | 6 +- weave/legacy/tests/test_language.py | 4 +- weave/legacy/tests/test_levenshtein.py | 2 +- weave/legacy/tests/test_list_arrow_compat.py | 14 +- weave/legacy/tests/test_list_indexing.py | 2 +- weave/legacy/tests/test_logging.py | 2 +- weave/legacy/tests/test_mappability.py | 24 +- weave/legacy/tests/test_mappers_arrow.py | 4 +- weave/legacy/tests/test_mappers_python.py | 4 +- weave/legacy/tests/test_media.py | 4 +- weave/legacy/tests/test_media_user.py | 6 +- weave/legacy/tests/test_monitoring.py | 2 +- weave/legacy/tests/test_monitoring_openai.py | 20 +- weave/legacy/tests/test_mutation2.py | 76 +- weave/legacy/tests/test_mutations.py | 4 +- weave/legacy/tests/test_node_ref.py | 6 +- weave/legacy/tests/test_nullability.py | 6 +- weave/legacy/tests/test_number_bin.py | 4 +- weave/legacy/tests/test_numpy.py | 8 +- weave/legacy/tests/test_op.py | 8 +- weave/legacy/tests/test_op_behaviors.py | 10 +- weave/legacy/tests/test_op_coverage.py | 2 +- weave/legacy/tests/test_op_def.py | 4 +- weave/legacy/tests/test_op_def_type.py | 2 +- weave/legacy/tests/test_op_dispatching.py | 14 +- weave/legacy/tests/test_op_serialization.py | 4 +- weave/legacy/tests/test_panel_coverage.py | 2 +- weave/legacy/tests/test_panel_time_series.py | 4 +- weave/legacy/tests/test_panels.py | 28 +- weave/legacy/tests/test_partial_object.py | 14 +- weave/legacy/tests/test_plot.py | 42 +- weave/legacy/tests/test_projection_timeout.py | 2 +- weave/legacy/tests/test_publish_flow.py | 100 +- weave/legacy/tests/test_pydantic.py | 2 +- weave/legacy/tests/test_ref_tracking.py | 4 +- weave/legacy/tests/test_refs.py | 4 +- .../legacy/tests/test_relpath_no_syscalls.py | 2 +- weave/legacy/tests/test_run_segment.py | 8 +- weave/legacy/tests/test_serialize.py | 10 +- weave/legacy/tests/test_show.py | 4 +- weave/legacy/tests/test_stitch.py | 42 +- weave/legacy/tests/test_storage.py | 12 +- weave/legacy/tests/test_stream_table.py | 2 +- weave/legacy/tests/test_table_ops.py | 8 +- weave/legacy/tests/test_tagging.py | 18 +- weave/legacy/tests/test_templates.py | 24 +- weave/legacy/tests/test_timestamp_bin.py | 10 +- weave/legacy/tests/test_trace.py | 8 +- .../tests/test_typeddict_notrequired.py | 4 +- weave/legacy/tests/test_uris.py | 4 +- weave/legacy/tests/test_wb.py | 22 +- weave/legacy/tests/test_wb_data_types.py | 38 +- weave/legacy/tests/test_wb_domain_ops.py | 10 +- weave/legacy/tests/test_wb_domain_types.py | 8 +- weave/legacy/tests/test_wb_end_to_end.py | 14 +- .../test_wb_history_loading_compatability.py | 14 +- weave/legacy/tests/test_wb_stream_table.py | 14 +- weave/legacy/tests/test_wb_tables.py | 48 +- weave/legacy/tests/test_weave_api.py | 18 +- weave/legacy/tests/test_weave_types.py | 124 +-- weave/legacy/tests/test_weavejs_fixes.py | 4 +- weave/legacy/tests/test_weavify.py | 6 +- weave/legacy/tests/test_with_columns.py | 2 +- .../tests/util/concrete_tagged_value.py | 4 +- weave/legacy/tests/util/geom.py | 4 +- .../tests/util/list_arrow_test_helpers.py | 6 +- weave/legacy/tests/util/op_specs.py | 6 +- weave/legacy/tests/util/tag_test_util.py | 12 +- weave/legacy/tests/util/weavejs_ops.py | 10 +- weave/legacy/{arrow => weave}/__init__.py | 0 weave/legacy/{ => weave}/_dict_utils.py | 8 +- weave/legacy/{ => weave}/api.py | 36 +- .../twitter => weave/arrow}/__init__.py | 0 weave/legacy/{ => weave}/arrow/arrow.py | 16 +- weave/legacy/{ => weave}/arrow/arrow_tags.py | 10 +- weave/legacy/{ => weave}/arrow/concat.py | 10 +- .../legacy/{ => weave}/arrow/constructors.py | 14 +- weave/legacy/{ => weave}/arrow/convert.py | 16 +- weave/legacy/{ => weave}/arrow/list_.py | 24 +- weave/legacy/{ => weave}/arrow_util.py | 0 weave/legacy/{ => weave}/artifact_base.py | 4 +- weave/legacy/{ => weave}/artifact_fs.py | 16 +- weave/legacy/{ => weave}/artifact_local.py | 6 +- weave/legacy/{ => weave}/artifact_mem.py | 6 +- weave/legacy/{ => weave}/artifact_wandb.py | 12 +- weave/legacy/{ => weave}/async_demo.py | 2 +- weave/legacy/{ => weave}/async_map.py | 0 weave/legacy/{ => weave}/async_queue.py | 0 weave/legacy/{ => weave}/box.py | 2 +- weave/legacy/{ => weave}/cache.py | 4 +- weave/legacy/{ => weave}/client.py | 4 +- weave/legacy/{ => weave}/client_interface.py | 0 .../{ => weave}/codifiable_value_mixin.py | 0 weave/legacy/{ => weave}/codify.py | 22 +- weave/legacy/{ => weave}/compile.py | 16 +- weave/legacy/{ => weave}/compile_domain.py | 10 +- weave/legacy/{ => weave}/compile_table.py | 6 +- weave/legacy/{ => weave}/context.py | 18 +- weave/legacy/{ => weave}/context_state.py | 6 +- weave/legacy/weave/core_types/__init__.py | 1 + .../core_types/stream_table_type.py | 2 +- weave/legacy/{ => weave}/debug.py | 0 weave/legacy/{ => weave}/debug_compile.py | 2 +- weave/legacy/{ => weave}/debug_types.py | 4 +- .../legacy/{ => weave}/decorator_arrow_op.py | 8 +- weave/legacy/{ => weave}/decorator_class.py | 6 +- .../legacy/{ => weave}/decorator_mutation.py | 0 weave/legacy/{ => weave}/decorator_op.py | 8 +- weave/legacy/{ => weave}/decorator_type.py | 8 +- weave/legacy/{ => weave}/decorator_type.pyi | 0 weave/legacy/{ => weave}/decorators.py | 0 weave/legacy/{ => weave}/derive_op.py | 8 +- weave/legacy/{ => weave}/dispatch.py | 10 +- weave/legacy/{ => weave}/eager.py | 8 +- weave/legacy/weave/ecosystem/__init__.py | 1 + weave/legacy/{ => weave}/ecosystem/all.py | 6 +- .../weave/ecosystem/bertviz/__init__.py | 1 + .../{ => weave}/ecosystem/bertviz/panels.py | 18 +- .../weave/ecosystem/craiyon/__init__.py | 1 + .../{ => weave}/ecosystem/craiyon/ops.py | 0 .../ecosystem/example}/__init__.py | 4 +- .../{ => weave}/ecosystem/example/ops.py | 0 .../ecosystem/hdbscan}/__init__.py | 4 +- .../{ => weave}/ecosystem/hdbscan/ops.py | 2 +- .../weave/ecosystem/huggingface/__init__.py | 12 + .../ecosystem/huggingface/hfmodel.py | 8 +- .../huggingface/huggingface_datasets.py | 2 +- .../huggingface/huggingface_models.py | 38 +- .../huggingface/model_textclassification.py | 20 +- .../huggingface/model_textgeneration.py | 10 +- .../ecosystem/keras}/__init__.py | 5 +- .../{ => weave}/ecosystem/keras/model.py | 0 .../ecosystem/langchain/__init__.py | 4 +- .../{ => weave}/ecosystem/langchain/lc.py | 12 +- .../{ => weave}/ecosystem/langchain/util.py | 2 +- weave/legacy/weave/ecosystem/lens/__init__.py | 1 + .../legacy/{ => weave}/ecosystem/lens/lens.py | 0 weave/legacy/weave/ecosystem/py/__init__.py | 1 + .../legacy/{ => weave}/ecosystem/py/pydoc.py | 54 +- .../weave/ecosystem/pytorch/__init__.py | 1 + .../{ => weave}/ecosystem/pytorch/model.py | 0 .../ecosystem/replicate/__init__.py | 4 +- .../{ => weave}/ecosystem/replicate/rep.py | 0 weave/legacy/{ => weave}/ecosystem/root.py | 8 +- .../ecosystem/scenario/__init__.py | 18 +- .../{ => weave}/ecosystem/shap/__init__.py | 4 +- .../legacy/{ => weave}/ecosystem/shap/shap.py | 14 +- .../legacy/weave/ecosystem/shawn/__init__.py | 7 + .../{ => weave}/ecosystem/shawn/petdataset.py | 4 +- .../{ => weave}/ecosystem/shawn/scratch.py | 24 +- .../weave/ecosystem/sklearn/__init__.py | 1 + .../{ => weave}/ecosystem/sklearn/datasets.py | 2 +- .../legacy/weave/ecosystem/slack/__init__.py | 2 + .../{ => weave}/ecosystem/slack/panels.py | 22 +- .../{ => weave}/ecosystem/slack/slack.py | 2 +- .../{ => weave}/ecosystem/slack/slackapi.py | 0 .../ecosystem/slack/slackapi_readexport.py | 0 .../legacy/weave/ecosystem/slurm/__init__.py | 1 + .../legacy/{ => weave}/ecosystem/slurm/ops.py | 24 +- .../ecosystem/spacy}/__init__.py | 4 +- .../{ => weave}/ecosystem/spacy/spacy.py | 20 +- .../test_notebook_ecosystem_executions.py | 4 +- .../ecosystem/torch_mnist_model_example.py | 8 +- .../weave/ecosystem/torchvision/__init__.py | 1 + .../ecosystem/torchvision/datasets.py | 4 +- .../ecosystem/twitter}/__init__.py | 0 .../{ => weave}/ecosystem/twitter/tweet.py | 0 .../ecosystem/umap}/__init__.py | 4 +- .../legacy/{ => weave}/ecosystem/umap/ops.py | 2 +- .../legacy/weave/ecosystem/wandb/__init__.py | 13 + .../ecosystem/wandb/gql_artifact_dag.py | 2 +- .../ecosystem/wandb/panel_distribution.py | 50 +- .../{ => weave}/ecosystem/wandb/panel_geo.py | 56 +- .../ecosystem/wandb/panel_scatter.py | 52 +- .../ecosystem/wandb/panel_time_series.py | 80 +- .../{ => weave}/ecosystem/wandb/run_chain.py | 12 +- .../wandb/test_panel_distribution.py | 4 +- .../{ => weave}/ecosystem/wandb/wandb_objs.py | 56 +- .../ecosystem/wandb/weave_plotly.py | 6 +- .../{ => weave}/ecosystem/xgboost/__init__.py | 4 +- .../{ => weave}/ecosystem/xgboost/model.py | 0 weave/legacy/{ => weave}/engine_trace.py | 4 +- weave/legacy/{ => weave}/environment.py | 8 +- weave/legacy/{ => weave}/errors.py | 0 weave/legacy/{ => weave}/execute.py | 6 +- weave/legacy/{ => weave}/execute_fast.py | 6 +- weave/legacy/{ => weave}/file_base.py | 2 +- weave/legacy/{ => weave}/file_local.py | 2 +- weave/legacy/{ => weave}/file_util.py | 4 +- weave/legacy/{ => weave}/filesystem.py | 2 +- weave/legacy/{ => weave}/forward_graph.py | 4 +- weave/legacy/{ => weave}/gql_json_cache.py | 0 weave/legacy/{ => weave}/gql_op_plugin.py | 4 +- weave/legacy/{ => weave}/gql_schema.py | 4 +- weave/legacy/{ => weave}/gql_to_weave.py | 6 +- weave/legacy/{ => weave}/graph.py | 12 +- weave/legacy/{ => weave}/graph_debug.py | 6 +- weave/legacy/{ => weave}/graph_mapper.py | 8 +- weave/legacy/{ => weave}/infer_types.py | 4 +- weave/legacy/{ => weave}/input_provider.py | 0 weave/legacy/{ => weave}/io_service.py | 2 +- weave/legacy/{ => weave}/language_autocall.py | 4 +- .../language_features}/__init__.py | 0 .../language_features/tagging}/__init__.py | 0 .../tagging/is_tag_getter.py | 8 +- .../tagging/make_tag_getter_op.py | 12 +- .../language_features/tagging/opdef_util.py | 6 +- .../tagging/process_opdef_output_type.py | 12 +- .../tagging/process_opdef_resolve_fn.py | 18 +- .../language_features/tagging/tag_store.py | 6 +- .../tagging/tagged_value_type.py | 10 +- .../tagging/tagged_value_type_helpers.py | 4 +- .../tagging/tagging_op_logic.py | 4 +- .../language_features/tagging/tagging_ops.py | 6 +- .../{ => weave}/language_nullability.py | 8 +- weave/legacy/{ => weave}/logs.py | 2 +- weave/legacy/{ => weave}/make_type.py | 4 +- weave/legacy/{ => weave}/mappers.py | 4 +- weave/legacy/{ => weave}/mappers_arrow.py | 12 +- weave/legacy/{ => weave}/mappers_gql.py | 10 +- weave/legacy/{ => weave}/mappers_publisher.py | 20 +- weave/legacy/{ => weave}/mappers_python.py | 4 +- .../legacy/{ => weave}/mappers_python_def.py | 16 +- weave/legacy/{ => weave}/mappers_weave.py | 6 +- weave/legacy/{ => weave}/memo.py | 2 +- .../legacy/{ => weave}/monitoring/__init__.py | 4 +- .../{ => weave}/monitoring/langchain.py | 4 +- .../legacy/{ => weave}/monitoring/monitor.py | 6 +- .../{ => weave}/monitoring/openai/__init__.py | 0 .../{ => weave}/monitoring/openai/models.py | 4 +- .../{ => weave}/monitoring/openai/openai.py | 6 +- .../{ => weave}/monitoring/openai/util.py | 2 +- weave/legacy/{ => weave}/node_ref.py | 4 +- weave/legacy/{ => weave}/object_context.py | 10 +- .../{ => weave}/object_type_ref_util.py | 2 +- weave/legacy/{ => weave}/op_aliases.py | 0 weave/legacy/{ => weave}/op_args.py | 4 +- weave/legacy/{ => weave}/op_def.py | 22 +- weave/legacy/{ => weave}/op_def_type.py | 8 +- weave/legacy/{ => weave}/op_execute.py | 0 weave/legacy/{ => weave}/op_policy.py | 0 weave/legacy/{ => weave}/ops.py | 0 weave/legacy/weave/ops_arrow/__init__.py | 12 + .../{ => weave}/ops_arrow/arraylist_ops.py | 12 +- weave/legacy/{ => weave}/ops_arrow/boolean.py | 10 +- .../{ => weave}/ops_arrow/convert_ops.py | 8 +- weave/legacy/{ => weave}/ops_arrow/date.py | 12 +- weave/legacy/{ => weave}/ops_arrow/dict.py | 24 +- .../legacy/{ => weave}/ops_arrow/list_join.py | 20 +- .../legacy/{ => weave}/ops_arrow/list_ops.py | 28 +- .../{ => weave}/ops_arrow/list_range.py | 6 +- weave/legacy/{ => weave}/ops_arrow/number.py | 12 +- weave/legacy/{ => weave}/ops_arrow/obj.py | 8 +- weave/legacy/weave/ops_arrow/ops.py | 11 + weave/legacy/{ => weave}/ops_arrow/ref_ops.py | 12 +- weave/legacy/{ => weave}/ops_arrow/string.py | 12 +- weave/legacy/{ => weave}/ops_arrow/util.py | 8 +- .../legacy/{ => weave}/ops_arrow/vectorize.py | 30 +- .../legacy/{ => weave}/ops_domain/__init__.py | 2 +- .../ops_domain/artifact_alias_ops.py | 12 +- .../ops_domain/artifact_collection_ops.py | 12 +- .../ops_domain/artifact_membership_ops.py | 10 +- .../ops_domain/artifact_type_ops.py | 10 +- .../ops_domain/artifact_version_ops.py | 24 +- .../{ => weave}/ops_domain/entity_ops.py | 12 +- .../legacy/{ => weave}/ops_domain/org_ops.py | 6 +- .../{ => weave}/ops_domain/project_ops.py | 16 +- .../ops_domain/repo_insight_ops.py | 12 +- .../{ => weave}/ops_domain/report_ops.py | 12 +- .../weave/ops_domain/run_history/__init__.py | 0 .../ops_domain/run_history/context.py | 0 .../run_history/history_op_common.py | 32 +- .../run_history/run_history_v1_legacy_ops.py | 16 +- .../run_history_v2_parquet_media.py | 22 +- ...run_history_v3_parquet_stream_optimized.py | 28 +- .../legacy/{ => weave}/ops_domain/run_ops.py | 22 +- .../{ => weave}/ops_domain/run_queue_ops.py | 12 +- .../{ => weave}/ops_domain/run_segment.py | 10 +- .../ops_domain/stream_table_ops.py | 12 +- weave/legacy/{ => weave}/ops_domain/table.py | 12 +- .../{ => weave}/ops_domain/trace_tree.py | 10 +- .../legacy/{ => weave}/ops_domain/user_ops.py | 12 +- .../ops_domain/wandb_domain_gql.py | 16 +- .../{ => weave}/ops_domain/wb_domain_types.py | 6 +- .../legacy/{ => weave}/ops_domain/wb_util.py | 30 +- .../{ => weave}/ops_domain/wbgqlquery_op.py | 14 +- .../legacy/{ => weave}/ops_domain/wbmedia.py | 12 +- .../{ => weave}/ops_primitives/__init__.py | 2 +- .../{ => weave}/ops_primitives/_dict_utils.py | 8 +- .../legacy/{ => weave}/ops_primitives/any.py | 4 +- .../{ => weave}/ops_primitives/artifacts.py | 6 +- .../{ => weave}/ops_primitives/boolean.py | 8 +- .../legacy/{ => weave}/ops_primitives/csv_.py | 4 +- .../legacy/{ => weave}/ops_primitives/date.py | 4 +- .../legacy/{ => weave}/ops_primitives/dict.py | 14 +- .../legacy/{ => weave}/ops_primitives/file.py | 14 +- .../ops_primitives/file_artifact.py | 4 +- .../{ => weave}/ops_primitives/file_local.py | 8 +- .../legacy/{ => weave}/ops_primitives/geom.py | 2 +- .../legacy/{ => weave}/ops_primitives/html.py | 4 +- .../{ => weave}/ops_primitives/image.py | 4 +- .../{ => weave}/ops_primitives/json_.py | 4 +- .../{ => weave}/ops_primitives/list_.py | 24 +- .../ops_primitives/list_tag_getters.py | 4 +- .../{ => weave}/ops_primitives/markdown.py | 4 +- .../{ => weave}/ops_primitives/number.py | 6 +- .../{ => weave}/ops_primitives/number_bin.py | 14 +- .../legacy/{ => weave}/ops_primitives/obj.py | 6 +- .../{ => weave}/ops_primitives/op_def.py | 8 +- .../{ => weave}/ops_primitives/pandas_.py | 12 +- .../ops_primitives/projection_utils.py | 4 +- .../{ => weave}/ops_primitives/random_junk.py | 6 +- .../{ => weave}/ops_primitives/server.py | 2 +- .../legacy/{ => weave}/ops_primitives/set_.py | 4 +- .../legacy/{ => weave}/ops_primitives/sql.py | 10 +- .../{ => weave}/ops_primitives/string.py | 4 +- .../{ => weave}/ops_primitives/test_any.py | 6 +- .../{ => weave}/ops_primitives/test_dict.py | 6 +- .../{ => weave}/ops_primitives/test_file.py | 4 +- .../{ => weave}/ops_primitives/test_image.py | 4 +- .../{ => weave}/ops_primitives/test_list.py | 12 +- .../weave/ops_primitives/test_list_range.py | 7 + .../{ => weave}/ops_primitives/test_pandas.py | 6 +- .../{ => weave}/ops_primitives/test_set.py | 2 +- .../{ => weave}/ops_primitives/test_type.py | 4 +- .../ops_primitives/test_typeddict.py | 8 +- .../ops_primitives/timestamp_bin.py | 14 +- .../legacy/{ => weave}/ops_primitives/type.py | 6 +- .../{ => weave}/ops_primitives/weave_api.py | 10 +- weave/legacy/{ => weave}/panel.py | 10 +- weave/legacy/{ => weave}/panel_util.py | 6 +- weave/legacy/weave/panels/__init__.py | 70 ++ weave/legacy/{ => weave}/panels/bank.py | 2 +- weave/legacy/{ => weave}/panels/panel_auto.py | 2 +- .../legacy/{ => weave}/panels/panel_basic.py | 2 +- .../legacy/{ => weave}/panels/panel_board.py | 12 +- weave/legacy/{ => weave}/panels/panel_card.py | 2 +- .../legacy/{ => weave}/panels/panel_color.py | 2 +- .../{ => weave}/panels/panel_daterange.py | 2 +- .../legacy/{ => weave}/panels/panel_domain.py | 2 +- .../{ => weave}/panels/panel_dropdown.py | 4 +- weave/legacy/{ => weave}/panels/panel_each.py | 6 +- .../{ => weave}/panels/panel_each_column.py | 4 +- .../{ => weave}/panels/panel_expression.py | 2 +- .../legacy/{ => weave}/panels/panel_facet.py | 22 +- .../{ => weave}/panels/panel_facet_tabs.py | 6 +- .../{ => weave}/panels/panel_filter_editor.py | 2 +- .../panels/panel_function_editor.py | 2 +- .../legacy/{ => weave}/panels/panel_group.py | 10 +- .../panels/panel_group_panel_info.py | 0 .../panels/panel_grouping_editor.py | 2 +- .../{ => weave}/panels/panel_histogram.py | 2 +- weave/legacy/{ => weave}/panels/panel_html.py | 2 +- .../{ => weave}/panels/panel_labeled_item.py | 2 +- .../legacy/{ => weave}/panels/panel_legacy.py | 2 +- .../{ => weave}/panels/panel_markdown.py | 2 +- .../{ => weave}/panels/panel_object_picker.py | 4 +- weave/legacy/{ => weave}/panels/panel_plot.py | 14 +- .../legacy/{ => weave}/panels/panel_query.py | 10 +- .../{ => weave}/panels/panel_sections.py | 6 +- .../legacy/{ => weave}/panels/panel_select.py | 6 +- .../panels/panel_sidebarcontainer.py | 4 +- .../legacy/{ => weave}/panels/panel_slider.py | 6 +- .../legacy/{ => weave}/panels/panel_string.py | 2 +- .../{ => weave}/panels/panel_string_editor.py | 2 +- .../legacy/{ => weave}/panels/panel_table.py | 34 +- .../legacy/{ => weave}/panels/panel_trace.py | 4 +- .../{ => weave}/panels/panel_trace_span.py | 2 +- .../{ => weave}/panels/panel_weavelink.py | 6 +- .../legacy/{ => weave}/panels/table_state.py | 6 +- .../legacy/{ => weave}/panels_py/__init__.py | 6 +- .../panels_py/generator_templates.py | 4 +- .../panels_py/instructions/panel_autoboard.md | 0 .../instructions/panel_llm_monitor.md | 0 .../instructions/panel_trace_monitor.md | 6 +- .../{ => weave}/panels_py/panel_autoboard.py | 84 +- .../{ => weave}/panels_py/panel_eval.py | 92 +- .../panels_py/panel_example_custom_board.py | 20 +- .../panels_py/panel_llm_monitor.py | 66 +- .../panels_py/panel_observability.py | 174 ++-- .../{ => weave}/panels_py/panel_seedboard.py | 14 +- .../panels_py/panel_trace_monitor.py | 50 +- weave/legacy/{ => weave}/parallelism.py | 2 +- weave/legacy/{ => weave}/partial_object.py | 8 +- weave/legacy/{ => weave}/path_util.py | 2 +- .../legacy/{ => weave}/propagate_gql_keys.py | 6 +- weave/legacy/{ => weave}/pyfunc_type_util.py | 6 +- weave/legacy/{ => weave}/ref_base.py | 10 +- weave/legacy/{ => weave}/registry_mem.py | 10 +- weave/legacy/{ => weave}/run.py | 0 .../{ => weave}/run_streamtable_span.py | 8 +- weave/legacy/{ => weave}/runfiles_wandb.py | 8 +- weave/legacy/{ => weave}/runs.py | 2 +- weave/legacy/{ => weave}/serialize.py | 6 +- weave/legacy/{ => weave}/server.py | 6 +- .../{ => weave}/server_error_handling.py | 4 +- weave/legacy/{ => weave}/server_interface.py | 0 weave/legacy/{ => weave}/show.py | 8 +- weave/legacy/{ => weave}/signal_handlers.py | 2 +- weave/legacy/{ => weave}/stitch.py | 8 +- weave/legacy/{ => weave}/storage.py | 12 +- .../{ => weave}/stream_data_interfaces.py | 0 weave/legacy/{ => weave}/timestamp.py | 0 weave/legacy/{ => weave}/trace_legacy.py | 4 +- weave/legacy/{ => weave}/trace_local.py | 10 +- weave/legacy/{ => weave}/types_numpy.py | 2 +- weave/legacy/{ => weave}/uris.py | 2 +- weave/legacy/{ => weave}/urls.py | 2 +- weave/legacy/{ => weave}/usage_analytics.py | 2 +- weave/legacy/{ => weave}/util.py | 2 +- weave/legacy/{ => weave}/val_const.py | 2 +- weave/legacy/{ => weave}/value_or_error.py | 0 weave/legacy/{ => weave}/wandb_api.py | 8 +- weave/legacy/{ => weave}/wandb_client_api.py | 2 +- .../legacy/{ => weave}/wandb_file_manager.py | 4 +- .../wandb_interface/project_creator.py | 0 .../wandb_interface/wandb_artifact_pusher.py | 6 +- .../wandb_interface/wandb_lite_run.py | 4 +- .../wandb_interface/wandb_stream_table.py | 14 +- weave/legacy/{ => weave}/wandb_util.py | 6 +- weave/legacy/{ => weave}/weave_http.py | 2 +- weave/legacy/{ => weave}/weave_inspector.py | 6 +- weave/legacy/{ => weave}/weave_internal.py | 16 +- weave/legacy/{ => weave}/weave_pydantic.py | 2 +- weave/legacy/{ => weave}/weave_types.py | 26 +- weave/legacy/{ => weave}/weavejs_fixes.py | 4 +- weave/legacy/{ => weave}/weavify.py | 10 +- weave/test_scripts/wandb_artifact_perf.py | 2 +- weave/tests/fixture_fakewandb.py | 6 +- weave/tests/trace/op_versioning_solo.py | 2 +- weave/tests/trace/test_op_versioning.py | 2 +- weave/tests/trace/test_server.py | 14 +- weave/tests/trace/test_weave_client.py | 2 +- weave/tests/trace/test_weaveflow.py | 2 +- weave/tests/wandb_system_tests_conftest.py | 2 +- weave/trace/api.py | 4 +- weave/trace/box.py | 2 +- weave/trace/cli.py | 2 +- weave/trace/client_context/weave_client.py | 4 +- weave/trace/custom_objs.py | 4 +- weave/trace/feedback.py | 2 +- weave/trace/init_message.py | 2 +- weave/trace/op.py | 4 +- weave/trace/op_type.py | 4 +- weave/trace/ref_util.py | 6 +- weave/trace/rich_pydantic_util.py | 2 +- weave/trace/serve_fastapi.py | 6 +- weave/trace/weave_client.py | 4 +- weave/trace/weave_init.py | 8 +- .../trace_server/remote_http_trace_server.py | 4 +- weave/weave_server.py | 16 +- 615 files changed, 15095 insertions(+), 15010 deletions(-) create mode 100644 weave/legacy/Dockerfile delete mode 100644 weave/legacy/core_types/__init__.py delete mode 100644 weave/legacy/ecosystem/__init__.py delete mode 100644 weave/legacy/ecosystem/bertviz/__init__.py delete mode 100644 weave/legacy/ecosystem/craiyon/__init__.py delete mode 100644 weave/legacy/ecosystem/huggingface/__init__.py delete mode 100644 weave/legacy/ecosystem/keras/__init__.py delete mode 100644 weave/legacy/ecosystem/lens/__init__.py delete mode 100644 weave/legacy/ecosystem/py/__init__.py delete mode 100644 weave/legacy/ecosystem/pytorch/__init__.py delete mode 100644 weave/legacy/ecosystem/sklearn/__init__.py delete mode 100644 weave/legacy/ecosystem/slack/__init__.py delete mode 100644 weave/legacy/ecosystem/slurm/__init__.py delete mode 100644 weave/legacy/ecosystem/torchvision/__init__.py delete mode 100644 weave/legacy/ecosystem/wandb/__init__.py delete mode 100644 weave/legacy/ops_arrow/__init__.py delete mode 100644 weave/legacy/ops_arrow/ops.py delete mode 100644 weave/legacy/ops_primitives/test_list_range.py delete mode 100644 weave/legacy/panels/__init__.py rename weave/legacy/{arrow => weave}/__init__.py (100%) rename weave/legacy/{ => weave}/_dict_utils.py (97%) rename weave/legacy/{ => weave}/api.py (78%) rename weave/legacy/{ecosystem/twitter => weave/arrow}/__init__.py (100%) rename weave/legacy/{ => weave}/arrow/arrow.py (97%) rename weave/legacy/{ => weave}/arrow/arrow_tags.py (93%) rename weave/legacy/{ => weave}/arrow/concat.py (98%) rename weave/legacy/{ => weave}/arrow/constructors.py (90%) rename weave/legacy/{ => weave}/arrow/convert.py (98%) rename weave/legacy/{ => weave}/arrow/list_.py (98%) rename weave/legacy/{ => weave}/arrow_util.py (100%) rename weave/legacy/{ => weave}/artifact_base.py (95%) rename weave/legacy/{ => weave}/artifact_fs.py (97%) rename weave/legacy/{ => weave}/artifact_local.py (99%) rename weave/legacy/{ => weave}/artifact_mem.py (90%) rename weave/legacy/{ => weave}/artifact_wandb.py (99%) rename weave/legacy/{ => weave}/async_demo.py (97%) rename weave/legacy/{ => weave}/async_map.py (100%) rename weave/legacy/{ => weave}/async_queue.py (100%) rename weave/legacy/{ => weave}/box.py (99%) rename weave/legacy/{ => weave}/cache.py (98%) rename weave/legacy/{ => weave}/client.py (91%) rename weave/legacy/{ => weave}/client_interface.py (100%) rename weave/legacy/{ => weave}/codifiable_value_mixin.py (100%) rename weave/legacy/{ => weave}/codify.py (91%) rename weave/legacy/{ => weave}/compile.py (99%) rename weave/legacy/{ => weave}/compile_domain.py (97%) rename weave/legacy/{ => weave}/compile_table.py (92%) rename weave/legacy/{ => weave}/context.py (88%) rename weave/legacy/{ => weave}/context_state.py (98%) create mode 100644 weave/legacy/weave/core_types/__init__.py rename weave/legacy/{ => weave}/core_types/stream_table_type.py (78%) rename weave/legacy/{ => weave}/debug.py (100%) rename weave/legacy/{ => weave}/debug_compile.py (97%) rename weave/legacy/{ => weave}/debug_types.py (97%) rename weave/legacy/{ => weave}/decorator_arrow_op.py (96%) rename weave/legacy/{ => weave}/decorator_class.py (93%) rename weave/legacy/{ => weave}/decorator_mutation.py (100%) rename weave/legacy/{ => weave}/decorator_op.py (93%) rename weave/legacy/{ => weave}/decorator_type.py (95%) rename weave/legacy/{ => weave}/decorator_type.pyi (100%) rename weave/legacy/{ => weave}/decorators.py (100%) rename weave/legacy/{ => weave}/derive_op.py (98%) rename weave/legacy/{ => weave}/dispatch.py (98%) rename weave/legacy/{ => weave}/eager.py (93%) create mode 100644 weave/legacy/weave/ecosystem/__init__.py rename weave/legacy/{ => weave}/ecosystem/all.py (90%) create mode 100644 weave/legacy/weave/ecosystem/bertviz/__init__.py rename weave/legacy/{ => weave}/ecosystem/bertviz/panels.py (83%) create mode 100644 weave/legacy/weave/ecosystem/craiyon/__init__.py rename weave/legacy/{ => weave}/ecosystem/craiyon/ops.py (100%) rename weave/legacy/{ecosystem/hdbscan => weave/ecosystem/example}/__init__.py (73%) rename weave/legacy/{ => weave}/ecosystem/example/ops.py (100%) rename weave/legacy/{ecosystem/umap => weave/ecosystem/hdbscan}/__init__.py (73%) rename weave/legacy/{ => weave}/ecosystem/hdbscan/ops.py (95%) create mode 100644 weave/legacy/weave/ecosystem/huggingface/__init__.py rename weave/legacy/{ => weave}/ecosystem/huggingface/hfmodel.py (96%) rename weave/legacy/{ => weave}/ecosystem/huggingface/huggingface_datasets.py (98%) rename weave/legacy/{ => weave}/ecosystem/huggingface/huggingface_models.py (78%) rename weave/legacy/{ => weave}/ecosystem/huggingface/model_textclassification.py (89%) rename weave/legacy/{ => weave}/ecosystem/huggingface/model_textgeneration.py (91%) rename weave/legacy/{ecosystem/spacy => weave/ecosystem/keras}/__init__.py (51%) rename weave/legacy/{ => weave}/ecosystem/keras/model.py (100%) rename weave/legacy/{ => weave}/ecosystem/langchain/__init__.py (67%) rename weave/legacy/{ => weave}/ecosystem/langchain/lc.py (98%) rename weave/legacy/{ => weave}/ecosystem/langchain/util.py (99%) create mode 100644 weave/legacy/weave/ecosystem/lens/__init__.py rename weave/legacy/{ => weave}/ecosystem/lens/lens.py (100%) create mode 100644 weave/legacy/weave/ecosystem/py/__init__.py rename weave/legacy/{ => weave}/ecosystem/py/pydoc.py (76%) create mode 100644 weave/legacy/weave/ecosystem/pytorch/__init__.py rename weave/legacy/{ => weave}/ecosystem/pytorch/model.py (100%) rename weave/legacy/{ => weave}/ecosystem/replicate/__init__.py (57%) rename weave/legacy/{ => weave}/ecosystem/replicate/rep.py (100%) rename weave/legacy/{ => weave}/ecosystem/root.py (96%) rename weave/legacy/{ => weave}/ecosystem/scenario/__init__.py (79%) rename weave/legacy/{ => weave}/ecosystem/shap/__init__.py (52%) rename weave/legacy/{ => weave}/ecosystem/shap/shap.py (85%) create mode 100644 weave/legacy/weave/ecosystem/shawn/__init__.py rename weave/legacy/{ => weave}/ecosystem/shawn/petdataset.py (96%) rename weave/legacy/{ => weave}/ecosystem/shawn/scratch.py (69%) create mode 100644 weave/legacy/weave/ecosystem/sklearn/__init__.py rename weave/legacy/{ => weave}/ecosystem/sklearn/datasets.py (81%) create mode 100644 weave/legacy/weave/ecosystem/slack/__init__.py rename weave/legacy/{ => weave}/ecosystem/slack/panels.py (73%) rename weave/legacy/{ => weave}/ecosystem/slack/slack.py (97%) rename weave/legacy/{ => weave}/ecosystem/slack/slackapi.py (100%) rename weave/legacy/{ => weave}/ecosystem/slack/slackapi_readexport.py (100%) create mode 100644 weave/legacy/weave/ecosystem/slurm/__init__.py rename weave/legacy/{ => weave}/ecosystem/slurm/ops.py (79%) rename weave/legacy/{ecosystem/shawn => weave/ecosystem/spacy}/__init__.py (51%) rename weave/legacy/{ => weave}/ecosystem/spacy/spacy.py (72%) rename weave/legacy/{ => weave}/ecosystem/test_notebook_ecosystem_executions.py (98%) rename weave/legacy/{ => weave}/ecosystem/torch_mnist_model_example.py (93%) create mode 100644 weave/legacy/weave/ecosystem/torchvision/__init__.py rename weave/legacy/{ => weave}/ecosystem/torchvision/datasets.py (98%) rename weave/legacy/{language_features => weave/ecosystem/twitter}/__init__.py (100%) rename weave/legacy/{ => weave}/ecosystem/twitter/tweet.py (100%) rename weave/legacy/{ecosystem/example => weave/ecosystem/umap}/__init__.py (74%) rename weave/legacy/{ => weave}/ecosystem/umap/ops.py (96%) create mode 100644 weave/legacy/weave/ecosystem/wandb/__init__.py rename weave/legacy/{ => weave}/ecosystem/wandb/gql_artifact_dag.py (98%) rename weave/legacy/{ => weave}/ecosystem/wandb/panel_distribution.py (75%) rename weave/legacy/{ => weave}/ecosystem/wandb/panel_geo.py (77%) rename weave/legacy/{ => weave}/ecosystem/wandb/panel_scatter.py (65%) rename weave/legacy/{ => weave}/ecosystem/wandb/panel_time_series.py (80%) rename weave/legacy/{ => weave}/ecosystem/wandb/run_chain.py (91%) rename weave/legacy/{ => weave}/ecosystem/wandb/test_panel_distribution.py (93%) rename weave/legacy/{ => weave}/ecosystem/wandb/wandb_objs.py (73%) rename weave/legacy/{ => weave}/ecosystem/wandb/weave_plotly.py (97%) rename weave/legacy/{ => weave}/ecosystem/xgboost/__init__.py (51%) rename weave/legacy/{ => weave}/ecosystem/xgboost/model.py (100%) rename weave/legacy/{ => weave}/engine_trace.py (98%) rename weave/legacy/{ => weave}/environment.py (98%) rename weave/legacy/{ => weave}/errors.py (100%) rename weave/legacy/{ => weave}/execute.py (99%) rename weave/legacy/{ => weave}/execute_fast.py (97%) rename weave/legacy/{ => weave}/file_base.py (98%) rename weave/legacy/{ => weave}/file_local.py (98%) rename weave/legacy/{ => weave}/file_util.py (88%) rename weave/legacy/{ => weave}/filesystem.py (98%) rename weave/legacy/{ => weave}/forward_graph.py (98%) rename weave/legacy/{ => weave}/gql_json_cache.py (100%) rename weave/legacy/{ => weave}/gql_op_plugin.py (95%) rename weave/legacy/{ => weave}/gql_schema.py (87%) rename weave/legacy/{ => weave}/gql_to_weave.py (97%) rename weave/legacy/{ => weave}/graph.py (98%) rename weave/legacy/{ => weave}/graph_debug.py (98%) rename weave/legacy/{ => weave}/graph_mapper.py (75%) rename weave/legacy/{ => weave}/infer_types.py (97%) rename weave/legacy/{ => weave}/input_provider.py (100%) rename weave/legacy/{ => weave}/io_service.py (99%) rename weave/legacy/{ => weave}/language_autocall.py (93%) rename weave/legacy/{language_features/tagging => weave/language_features}/__init__.py (100%) rename weave/legacy/{ops_domain/run_history => weave/language_features/tagging}/__init__.py (100%) rename weave/legacy/{ => weave}/language_features/tagging/is_tag_getter.py (84%) rename weave/legacy/{ => weave}/language_features/tagging/make_tag_getter_op.py (87%) rename weave/legacy/{ => weave}/language_features/tagging/opdef_util.py (91%) rename weave/legacy/{ => weave}/language_features/tagging/process_opdef_output_type.py (85%) rename weave/legacy/{ => weave}/language_features/tagging/process_opdef_resolve_fn.py (91%) rename weave/legacy/{ => weave}/language_features/tagging/tag_store.py (98%) rename weave/legacy/{ => weave}/language_features/tagging/tagged_value_type.py (98%) rename weave/legacy/{ => weave}/language_features/tagging/tagged_value_type_helpers.py (94%) rename weave/legacy/{ => weave}/language_features/tagging/tagging_op_logic.py (86%) rename weave/legacy/{ => weave}/language_features/tagging/tagging_ops.py (84%) rename weave/legacy/{ => weave}/language_nullability.py (83%) rename weave/legacy/{ => weave}/logs.py (99%) rename weave/legacy/{ => weave}/make_type.py (81%) rename weave/legacy/{ => weave}/mappers.py (81%) rename weave/legacy/{ => weave}/mappers_arrow.py (98%) rename weave/legacy/{ => weave}/mappers_gql.py (93%) rename weave/legacy/{ => weave}/mappers_publisher.py (92%) rename weave/legacy/{ => weave}/mappers_python.py (85%) rename weave/legacy/{ => weave}/mappers_python_def.py (97%) rename weave/legacy/{ => weave}/mappers_weave.py (95%) rename weave/legacy/{ => weave}/memo.py (97%) rename weave/legacy/{ => weave}/monitoring/__init__.py (58%) rename weave/legacy/{ => weave}/monitoring/langchain.py (94%) rename weave/legacy/{ => weave}/monitoring/monitor.py (98%) rename weave/legacy/{ => weave}/monitoring/openai/__init__.py (100%) rename weave/legacy/{ => weave}/monitoring/openai/models.py (90%) rename weave/legacy/{ => weave}/monitoring/openai/openai.py (98%) rename weave/legacy/{ => weave}/monitoring/openai/util.py (98%) rename weave/legacy/{ => weave}/node_ref.py (97%) rename weave/legacy/{ => weave}/object_context.py (95%) rename weave/legacy/{ => weave}/object_type_ref_util.py (97%) rename weave/legacy/{ => weave}/op_aliases.py (100%) rename weave/legacy/{ => weave}/op_args.py (98%) rename weave/legacy/{ => weave}/op_def.py (97%) rename weave/legacy/{ => weave}/op_def_type.py (99%) rename weave/legacy/{ => weave}/op_execute.py (100%) rename weave/legacy/{ => weave}/op_policy.py (100%) rename weave/legacy/{ => weave}/ops.py (100%) create mode 100644 weave/legacy/weave/ops_arrow/__init__.py rename weave/legacy/{ => weave}/ops_arrow/arraylist_ops.py (96%) rename weave/legacy/{ => weave}/ops_arrow/boolean.py (93%) rename weave/legacy/{ => weave}/ops_arrow/convert_ops.py (71%) rename weave/legacy/{ => weave}/ops_arrow/date.py (94%) rename weave/legacy/{ => weave}/ops_arrow/dict.py (96%) rename weave/legacy/{ => weave}/ops_arrow/list_join.py (93%) rename weave/legacy/{ => weave}/ops_arrow/list_ops.py (97%) rename weave/legacy/{ => weave}/ops_arrow/list_range.py (61%) rename weave/legacy/{ => weave}/ops_arrow/number.py (97%) rename weave/legacy/{ => weave}/ops_arrow/obj.py (72%) create mode 100644 weave/legacy/weave/ops_arrow/ops.py rename weave/legacy/{ => weave}/ops_arrow/ref_ops.py (83%) rename weave/legacy/{ => weave}/ops_arrow/string.py (97%) rename weave/legacy/{ => weave}/ops_arrow/util.py (91%) rename weave/legacy/{ => weave}/ops_arrow/vectorize.py (97%) rename weave/legacy/{ => weave}/ops_domain/__init__.py (93%) rename weave/legacy/{ => weave}/ops_domain/artifact_alias_ops.py (61%) rename weave/legacy/{ => weave}/ops_domain/artifact_collection_ops.py (94%) rename weave/legacy/{ => weave}/ops_domain/artifact_membership_ops.py (89%) rename weave/legacy/{ => weave}/ops_domain/artifact_type_ops.py (89%) rename weave/legacy/{ => weave}/ops_domain/artifact_version_ops.py (96%) rename weave/legacy/{ => weave}/ops_domain/entity_ops.py (82%) rename weave/legacy/{ => weave}/ops_domain/org_ops.py (85%) rename weave/legacy/{ => weave}/ops_domain/project_ops.py (93%) rename weave/legacy/{ => weave}/ops_domain/repo_insight_ops.py (94%) rename weave/legacy/{ => weave}/ops_domain/report_ops.py (91%) create mode 100644 weave/legacy/weave/ops_domain/run_history/__init__.py rename weave/legacy/{ => weave}/ops_domain/run_history/context.py (100%) rename weave/legacy/{ => weave}/ops_domain/run_history/history_op_common.py (94%) rename weave/legacy/{ => weave}/ops_domain/run_history/run_history_v1_legacy_ops.py (89%) rename weave/legacy/{ => weave}/ops_domain/run_history/run_history_v2_parquet_media.py (90%) rename weave/legacy/{ => weave}/ops_domain/run_history/run_history_v3_parquet_stream_optimized.py (98%) rename weave/legacy/{ => weave}/ops_domain/run_ops.py (95%) rename weave/legacy/{ => weave}/ops_domain/run_queue_ops.py (51%) rename weave/legacy/{ => weave}/ops_domain/run_segment.py (91%) rename weave/legacy/{ => weave}/ops_domain/stream_table_ops.py (68%) rename weave/legacy/{ => weave}/ops_domain/table.py (99%) rename weave/legacy/{ => weave}/ops_domain/trace_tree.py (97%) rename weave/legacy/{ => weave}/ops_domain/user_ops.py (77%) rename weave/legacy/{ => weave}/ops_domain/wandb_domain_gql.py (96%) rename weave/legacy/{ => weave}/ops_domain/wb_domain_types.py (97%) rename weave/legacy/{ => weave}/ops_domain/wb_util.py (87%) rename weave/legacy/{ => weave}/ops_domain/wbgqlquery_op.py (87%) rename weave/legacy/{ => weave}/ops_domain/wbmedia.py (97%) rename weave/legacy/{ => weave}/ops_primitives/__init__.py (92%) rename weave/legacy/{ => weave}/ops_primitives/_dict_utils.py (97%) rename weave/legacy/{ => weave}/ops_primitives/any.py (61%) rename weave/legacy/{ => weave}/ops_primitives/artifacts.py (96%) rename weave/legacy/{ => weave}/ops_primitives/boolean.py (92%) rename weave/legacy/{ => weave}/ops_primitives/csv_.py (97%) rename weave/legacy/{ => weave}/ops_primitives/date.py (98%) rename weave/legacy/{ => weave}/ops_primitives/dict.py (92%) rename weave/legacy/{ => weave}/ops_primitives/file.py (90%) rename weave/legacy/{ => weave}/ops_primitives/file_artifact.py (87%) rename weave/legacy/{ => weave}/ops_primitives/file_local.py (83%) rename weave/legacy/{ => weave}/ops_primitives/geom.py (93%) rename weave/legacy/{ => weave}/ops_primitives/html.py (82%) rename weave/legacy/{ => weave}/ops_primitives/image.py (93%) rename weave/legacy/{ => weave}/ops_primitives/json_.py (90%) rename weave/legacy/{ => weave}/ops_primitives/list_.py (97%) rename weave/legacy/{ => weave}/ops_primitives/list_tag_getters.py (74%) rename weave/legacy/{ => weave}/ops_primitives/markdown.py (82%) rename weave/legacy/{ => weave}/ops_primitives/number.py (98%) rename weave/legacy/{ => weave}/ops_primitives/number_bin.py (81%) rename weave/legacy/{ => weave}/ops_primitives/obj.py (93%) rename weave/legacy/{ => weave}/ops_primitives/op_def.py (68%) rename weave/legacy/{ => weave}/ops_primitives/pandas_.py (97%) rename weave/legacy/{ => weave}/ops_primitives/projection_utils.py (98%) rename weave/legacy/{ => weave}/ops_primitives/random_junk.py (82%) rename weave/legacy/{ => weave}/ops_primitives/server.py (76%) rename weave/legacy/{ => weave}/ops_primitives/set_.py (94%) rename weave/legacy/{ => weave}/ops_primitives/sql.py (97%) rename weave/legacy/{ => weave}/ops_primitives/string.py (98%) rename weave/legacy/{ => weave}/ops_primitives/test_any.py (73%) rename weave/legacy/{ => weave}/ops_primitives/test_dict.py (80%) rename weave/legacy/{ => weave}/ops_primitives/test_file.py (54%) rename weave/legacy/{ => weave}/ops_primitives/test_image.py (89%) rename weave/legacy/{ => weave}/ops_primitives/test_list.py (96%) create mode 100644 weave/legacy/weave/ops_primitives/test_list_range.py rename weave/legacy/{ => weave}/ops_primitives/test_pandas.py (85%) rename weave/legacy/{ => weave}/ops_primitives/test_set.py (89%) rename weave/legacy/{ => weave}/ops_primitives/test_type.py (79%) rename weave/legacy/{ => weave}/ops_primitives/test_typeddict.py (96%) rename weave/legacy/{ => weave}/ops_primitives/timestamp_bin.py (86%) rename weave/legacy/{ => weave}/ops_primitives/type.py (85%) rename weave/legacy/{ => weave}/ops_primitives/weave_api.py (99%) rename weave/legacy/{ => weave}/panel.py (95%) rename weave/legacy/{ => weave}/panel_util.py (80%) create mode 100644 weave/legacy/weave/panels/__init__.py rename weave/legacy/{ => weave}/panels/bank.py (93%) rename weave/legacy/{ => weave}/panels/panel_auto.py (77%) rename weave/legacy/{ => weave}/panels/panel_basic.py (84%) rename weave/legacy/{ => weave}/panels/panel_board.py (92%) rename weave/legacy/{ => weave}/panels/panel_card.py (93%) rename weave/legacy/{ => weave}/panels/panel_color.py (81%) rename weave/legacy/{ => weave}/panels/panel_daterange.py (93%) rename weave/legacy/{ => weave}/panels/panel_domain.py (90%) rename weave/legacy/{ => weave}/panels/panel_dropdown.py (88%) rename weave/legacy/{ => weave}/panels/panel_each.py (82%) rename weave/legacy/{ => weave}/panels/panel_each_column.py (84%) rename weave/legacy/{ => weave}/panels/panel_expression.py (68%) rename weave/legacy/{ => weave}/panels/panel_facet.py (86%) rename weave/legacy/{ => weave}/panels/panel_facet_tabs.py (73%) rename weave/legacy/{ => weave}/panels/panel_filter_editor.py (94%) rename weave/legacy/{ => weave}/panels/panel_function_editor.py (91%) rename weave/legacy/{ => weave}/panels/panel_group.py (97%) rename weave/legacy/{ => weave}/panels/panel_group_panel_info.py (100%) rename weave/legacy/{ => weave}/panels/panel_grouping_editor.py (94%) rename weave/legacy/{ => weave}/panels/panel_histogram.py (86%) rename weave/legacy/{ => weave}/panels/panel_html.py (90%) rename weave/legacy/{ => weave}/panels/panel_labeled_item.py (93%) rename weave/legacy/{ => weave}/panels/panel_legacy.py (98%) rename weave/legacy/{ => weave}/panels/panel_markdown.py (90%) rename weave/legacy/{ => weave}/panels/panel_object_picker.py (95%) rename weave/legacy/{ => weave}/panels/panel_plot.py (98%) rename weave/legacy/{ => weave}/panels/panel_query.py (89%) rename weave/legacy/{ => weave}/panels/panel_sections.py (73%) rename weave/legacy/{ => weave}/panels/panel_select.py (85%) rename weave/legacy/{ => weave}/panels/panel_sidebarcontainer.py (89%) rename weave/legacy/{ => weave}/panels/panel_slider.py (85%) rename weave/legacy/{ => weave}/panels/panel_string.py (94%) rename weave/legacy/{ => weave}/panels/panel_string_editor.py (82%) rename weave/legacy/{ => weave}/panels/panel_table.py (93%) rename weave/legacy/{ => weave}/panels/panel_trace.py (94%) rename weave/legacy/{ => weave}/panels/panel_trace_span.py (85%) rename weave/legacy/{ => weave}/panels/panel_weavelink.py (89%) rename weave/legacy/{ => weave}/panels/table_state.py (97%) rename weave/legacy/{ => weave}/panels_py/__init__.py (64%) rename weave/legacy/{ => weave}/panels_py/generator_templates.py (97%) rename weave/legacy/{ => weave}/panels_py/instructions/panel_autoboard.md (100%) rename weave/legacy/{ => weave}/panels_py/instructions/panel_llm_monitor.md (100%) rename weave/legacy/{ => weave}/panels_py/instructions/panel_trace_monitor.md (93%) rename weave/legacy/{ => weave}/panels_py/panel_autoboard.py (84%) rename weave/legacy/{ => weave}/panels_py/panel_eval.py (67%) rename weave/legacy/{ => weave}/panels_py/panel_example_custom_board.py (76%) rename weave/legacy/{ => weave}/panels_py/panel_llm_monitor.py (85%) rename weave/legacy/{ => weave}/panels_py/panel_observability.py (81%) rename weave/legacy/{ => weave}/panels_py/panel_seedboard.py (60%) rename weave/legacy/{ => weave}/panels_py/panel_trace_monitor.py (81%) rename weave/legacy/{ => weave}/parallelism.py (99%) rename weave/legacy/{ => weave}/partial_object.py (96%) rename weave/legacy/{ => weave}/path_util.py (90%) rename weave/legacy/{ => weave}/propagate_gql_keys.py (93%) rename weave/legacy/{ => weave}/pyfunc_type_util.py (98%) rename weave/legacy/{ => weave}/ref_base.py (95%) rename weave/legacy/{ => weave}/registry_mem.py (95%) rename weave/legacy/{ => weave}/run.py (100%) rename weave/legacy/{ => weave}/run_streamtable_span.py (93%) rename weave/legacy/{ => weave}/runfiles_wandb.py (97%) rename weave/legacy/{ => weave}/runs.py (92%) rename weave/legacy/{ => weave}/serialize.py (97%) rename weave/legacy/{ => weave}/server.py (97%) rename weave/legacy/{ => weave}/server_error_handling.py (98%) rename weave/legacy/{ => weave}/server_interface.py (100%) rename weave/legacy/{ => weave}/show.py (95%) rename weave/legacy/{ => weave}/signal_handlers.py (99%) rename weave/legacy/{ => weave}/stitch.py (98%) rename weave/legacy/{ => weave}/storage.py (98%) rename weave/legacy/{ => weave}/stream_data_interfaces.py (100%) rename weave/legacy/{ => weave}/timestamp.py (100%) rename weave/legacy/{ => weave}/trace_legacy.py (96%) rename weave/legacy/{ => weave}/trace_local.py (95%) rename weave/legacy/{ => weave}/types_numpy.py (96%) rename weave/legacy/{ => weave}/uris.py (98%) rename weave/legacy/{ => weave}/urls.py (96%) rename weave/legacy/{ => weave}/usage_analytics.py (95%) rename weave/legacy/{ => weave}/util.py (98%) rename weave/legacy/{ => weave}/val_const.py (90%) rename weave/legacy/{ => weave}/value_or_error.py (100%) rename weave/legacy/{ => weave}/wandb_api.py (98%) rename weave/legacy/{ => weave}/wandb_client_api.py (98%) rename weave/legacy/{ => weave}/wandb_file_manager.py (99%) rename weave/legacy/{ => weave}/wandb_interface/project_creator.py (100%) rename weave/legacy/{ => weave}/wandb_interface/wandb_artifact_pusher.py (95%) rename weave/legacy/{ => weave}/wandb_interface/wandb_lite_run.py (98%) rename weave/legacy/{ => weave}/wandb_interface/wandb_stream_table.py (97%) rename weave/legacy/{ => weave}/wandb_util.py (98%) rename weave/legacy/{ => weave}/weave_http.py (98%) rename weave/legacy/{ => weave}/weave_inspector.py (99%) rename weave/legacy/{ => weave}/weave_internal.py (93%) rename weave/legacy/{ => weave}/weave_pydantic.py (95%) rename weave/legacy/{ => weave}/weave_types.py (99%) rename weave/legacy/{ => weave}/weavejs_fixes.py (99%) rename weave/legacy/{ => weave}/weavify.py (93%) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 4ebd119ef67..7023d1a87e5 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -125,15 +125,42 @@ jobs: DD_SERVICE: weave-python DD_ENV: ci WEAVE_SENTRY_ENV: ci + CI: 1 + WB_SERVER_HOST: http://wandbservice + WF_CLICKHOUSE_HOST: weave_clickhouse + WEAVE_SERVER_DISABLE_ECOSYSTEM: 1 # This runner specifically runs the tests that use the `client` fixture (those that support clickhouse client tests) # However, we skip tests marked with `skip_clickhouse_client`. These should be considered TODOs and an exception - run: CI=1 WB_SERVER_HOST=http://wandbservice WF_CLICKHOUSE_HOST=weave_clickhouse WEAVE_SERVER_DISABLE_ECOSYSTEM=1 source /root/venv/bin/activate && cd weave && pytest -m "weave_client and not skip_clickhouse_client" --weave-server=clickhouse --job-num=${{ matrix.job_num }} --timeout=90 ./flow ./integrations ./legacy/tests ./tests ./legacy/ops_arrow ./legacy/ecosystem ./trace_server ./trace --ddtrace --durations=5 + run: | + source /root/venv/bin/activate && \ + cd weave && \ + pytest -m "weave_client and not skip_clickhouse_client" \ + --weave-server=clickhouse \ + --job-num=${{ matrix.job_num }} \ + --timeout=90 \ + --ddtrace \ + --durations=5 \ + ./integrations ./legacy ./trace_server ./trace ./tests - name: Run Python Unit Tests env: DD_SERVICE: weave-python DD_ENV: ci WEAVE_SENTRY_ENV: ci - run: CI=1 WB_SERVER_HOST=http://wandbservice WF_CLICKHOUSE_HOST=weave_clickhouse WEAVE_SERVER_DISABLE_ECOSYSTEM=1 source /root/venv/bin/activate && pip install 'dspy-ai>=0.1.5' && pip install pydantic -U && cd weave && pytest --job-num=${{ matrix.job_num }} --timeout=90 ./flow ./integrations ./legacy/tests ./tests ./legacy/ops_arrow ./legacy/ecosystem ./trace_server ./trace --ddtrace --durations=5 + CI: 1 + WB_SERVER_HOST: http://wandbservice + WF_CLICKHOUSE_HOST: weave_clickhouse + WEAVE_SERVER_DISABLE_ECOSYSTEM: 1 + run: | + source /root/venv/bin/activate && \ + pip install 'dspy-ai>=0.1.5' && \ + pip install pydantic -U && \ + cd weave && \ + pytest \ + --job-num=${{ matrix.job_num }} \ + --timeout=90 \ + --ddtrace \ + --durations=5 \ + ./integrations ./legacy ./trace_server ./trace ./tests # nbmake: # name: Run notebooks with nbmake diff --git a/examples/prompts/llm_monitoring/README.md b/examples/prompts/llm_monitoring/README.md index fcb12dd331b..7636594f80f 100644 --- a/examples/prompts/llm_monitoring/README.md +++ b/examples/prompts/llm_monitoring/README.md @@ -20,7 +20,7 @@ There are two main ways to authenticate OpenAI API calls so you can view them in ### OpenAI API 1. Set your OPENAI_API_KEY in your environment/script/notebook (e.g. via `os.environ["OPENAI_API_KEY"]`). -2. Import openai as follows: `from weave.legacy.monitoring import openai`. +2. Import openai as follows: `from weave.legacy.weave.monitoring import openai`. 3. Make calls via the OpenAI SDK as usual. See details and create an interactive board in the [OpenAI monitoring notebook](./openai_client_quickstart.ipynb). diff --git a/examples/prompts/llm_monitoring/openai_client_quickstart.ipynb b/examples/prompts/llm_monitoring/openai_client_quickstart.ipynb index f9b39f1af13..f0fc64bdceb 100644 --- a/examples/prompts/llm_monitoring/openai_client_quickstart.ipynb +++ b/examples/prompts/llm_monitoring/openai_client_quickstart.ipynb @@ -135,7 +135,7 @@ "metadata": {}, "outputs": [], "source": [ - "from weave.legacy.monitoring import openai, init_monitor\n", + "from weave.legacy.weave.monitoring import openai, init_monitor\n", "m = init_monitor(f\"{WB_ENTITY}/{WB_PROJECT}/{STREAM_NAME}\")\n", "\n", "# specifying a single model for simplicity\n", @@ -245,7 +245,7 @@ "metadata": {}, "outputs": [], "source": [ - "from weave.legacy.monitoring.openai import message_from_stream\n", + "from weave.legacy.weave.monitoring.openai import message_from_stream\n", "r = openai.ChatCompletion.create(model=OPENAI_MODEL, messages=[\n", " {\"role\": \"system\", \"content\": \"You are a robot and only speak in robot, like beep bloop bop.\"},\n", " {\"role\": \"user\", \"content\": \"Tell me a 50-word story.\"},\n", diff --git a/examples/prompts/llm_monitoring/openai_proxy_quickstart_enterprise_mode.ipynb b/examples/prompts/llm_monitoring/openai_proxy_quickstart_enterprise_mode.ipynb index 57d8c1eaa96..b2c1cda36cb 100644 --- a/examples/prompts/llm_monitoring/openai_proxy_quickstart_enterprise_mode.ipynb +++ b/examples/prompts/llm_monitoring/openai_proxy_quickstart_enterprise_mode.ipynb @@ -251,8 +251,8 @@ "outputs": [], "source": [ "import openai\n", - "from weave.legacy.monitoring import openai as openaimon\n", - "from weave.legacy.monitoring import init_monitor\n", + "from weave.legacy.weave.monitoring import openai as openaimon\n", + "from weave.legacy.weave.monitoring import init_monitor\n", "\n", "m = init_monitor(f\"{WB_ENTITY}/{WB_PROJECT}/{STREAM_NAME}\")\n", "\n", diff --git a/examples/prompts/trace_debugging/dev/synthetic_trace_data.ipynb b/examples/prompts/trace_debugging/dev/synthetic_trace_data.ipynb index 3834e6ea2a5..be0eae16ac5 100644 --- a/examples/prompts/trace_debugging/dev/synthetic_trace_data.ipynb +++ b/examples/prompts/trace_debugging/dev/synthetic_trace_data.ipynb @@ -39,7 +39,7 @@ "outputs": [], "source": [ "import weave\n", - "from weave.legacy.monitoring import StreamTable\n", + "from weave.legacy.weave.monitoring import StreamTable\n", "from weave.stream_data_interfaces import TraceSpanDict" ] }, diff --git a/examples/prompts/trace_debugging/trace_quickstart_decorator.ipynb b/examples/prompts/trace_debugging/trace_quickstart_decorator.ipynb index d692e72734b..bc0dd40d255 100644 --- a/examples/prompts/trace_debugging/trace_quickstart_decorator.ipynb +++ b/examples/prompts/trace_debugging/trace_quickstart_decorator.ipynb @@ -46,7 +46,7 @@ "source": [ "import weave\n", "import time\n", - "from weave.legacy.monitoring import init_monitor" + "from weave.legacy.weave.monitoring import init_monitor" ] }, { diff --git a/examples/prompts/trace_debugging/trace_quickstart_langchain.ipynb b/examples/prompts/trace_debugging/trace_quickstart_langchain.ipynb index 4e5080d95a1..72c3257f562 100644 --- a/examples/prompts/trace_debugging/trace_quickstart_langchain.ipynb +++ b/examples/prompts/trace_debugging/trace_quickstart_langchain.ipynb @@ -75,7 +75,7 @@ "source": [ "import langchain\n", "import weave\n", - "from weave.legacy.monitoring.langchain import WeaveTracer" + "from weave.legacy.weave.monitoring.langchain import WeaveTracer" ] }, { diff --git a/integration_test/cypress/e2e/interactive/blank.py b/integration_test/cypress/e2e/interactive/blank.py index ef823b13559..0dc51529825 100644 --- a/integration_test/cypress/e2e/interactive/blank.py +++ b/integration_test/cypress/e2e/interactive/blank.py @@ -1,12 +1,12 @@ import weave -from weave.legacy.show import show_url +from weave.legacy.weave.show import show_url weave.use_fixed_server_port() obj = [ 1, 2, 3, -] # weave.legacy.panels.Board({}, [weave.legacy.panels.BoardPanel(weave.legacy.panels.Table([1, 2, 3]))]) +] # weave.legacy.weave.panels.Board({}, [weave.legacy.weave.panels.BoardPanel(weave.legacy.weave.panels.Table([1, 2, 3]))]) blank = weave.save(obj) print(show_url(obj)) diff --git a/integration_test/cypress/e2e/interactive/distribution.py b/integration_test/cypress/e2e/interactive/distribution.py index e81e06a7c78..f516a04364c 100644 --- a/integration_test/cypress/e2e/interactive/distribution.py +++ b/integration_test/cypress/e2e/interactive/distribution.py @@ -1,12 +1,12 @@ import random import weave -from weave.legacy import panels -from weave.legacy.show import show_url +from weave.legacy.weave import panels +from weave.legacy.weave.show import show_url # Weave package now defaults to eager mode, but lazy mode required for this example notebook for now. weave.use_lazy_execution() -from weave.legacy.ecosystem import wandb +from weave.legacy.weave.ecosystem import wandb weave.use_fixed_server_port() @@ -38,7 +38,8 @@ {}, [ panels.BoardPanel( - panel, layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=24, h=12) + panel, + layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=24, h=12), ) ], ) diff --git a/integration_test/cypress/e2e/interactive/scatter.py b/integration_test/cypress/e2e/interactive/scatter.py index 0c0b117866d..b0e170fcc56 100644 --- a/integration_test/cypress/e2e/interactive/scatter.py +++ b/integration_test/cypress/e2e/interactive/scatter.py @@ -1,8 +1,8 @@ import random import weave -from weave.legacy.ecosystem import wandb -from weave.legacy.show import show_url +from weave.legacy.weave.ecosystem import wandb +from weave.legacy.weave.show import show_url weave.use_fixed_server_port() @@ -19,14 +19,14 @@ ] ) -panel: weave.legacy.panels.Group = weave.legacy.panels.Group( +panel: weave.legacy.weave.panels.Group = weave.legacy.weave.panels.Group( items={ "scatter": wandb.Scatter( # type: ignore data, x_fn=lambda item: item["a"], y_fn=lambda item: item["b"] ), - "table": lambda scatter: weave.legacy.panels.LabeledItem( + "table": lambda scatter: weave.legacy.weave.panels.LabeledItem( label="Selected items", - item=weave.legacy.panels.Group( + item=weave.legacy.weave.panels.Group( style="height: 400px;", preferHorizontal=True, items={"table": scatter.selected()}, diff --git a/mypy.ini b/mypy.ini index b8c601a669f..8793034417e 100644 --- a/mypy.ini +++ b/mypy.ini @@ -7,19 +7,19 @@ exclude = (.*pyi$)|(weave/ecosystem)|(weave/tests)|(weave/panel)|(weave/ops)|(we ;; 1. put in exclude above ;; 2. put in follow_imports = skip below ;; 3. put in exclude in .pre-commit-config.yaml -[mypy-weave.legacy.ecosystem.*] +[mypy-weave.legacy.weave.ecosystem.*] follow_imports = skip -[mypy-weave.legacy.panels_py.*] +[mypy-weave.legacy.weave.panels_py.*] follow_imports = skip -[mypy-weave.legacy.panels.*] +[mypy-weave.legacy.weave.panels.*] follow_imports = skip -[mypy-weave.legacy.ops_primitives.*] +[mypy-weave.legacy.weave.ops_primitives.*] follow_imports = skip -[mypy-weave.legacy.ops_domain.*] +[mypy-weave.legacy.weave.ops_domain.*] follow_imports = skip [mypy-pyarrow.*] @@ -95,15 +95,15 @@ disallow_untyped_calls = True ; show_error_codes = True -[mypy-weave.legacy._dict_utils] +[mypy-weave.legacy.weave._dict_utils] disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.arrow.*] +[mypy-weave.legacy.weave.arrow.*] disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.ops_arrow.*] +[mypy-weave.legacy.weave.ops_arrow.*] disallow_untyped_defs = False disallow_untyped_calls = False @@ -131,19 +131,19 @@ disallow_untyped_calls = False disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.arrow_util] +[mypy-weave.legacy.weave.arrow_util] disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.box] +[mypy-weave.legacy.weave.box] disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.mappers] +[mypy-weave.legacy.weave.mappers] disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.client_interface] +[mypy-weave.legacy.weave.client_interface] disallow_untyped_defs = False disallow_untyped_calls = False @@ -151,11 +151,11 @@ disallow_untyped_calls = False disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.weave_types] +[mypy-weave.legacy.weave.weave_types] disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.uris] +[mypy-weave.legacy.weave.uris] disallow_untyped_defs = False disallow_untyped_calls = False @@ -163,15 +163,15 @@ disallow_untyped_calls = False disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.op_args] +[mypy-weave.legacy.weave.op_args] disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.context_state] +[mypy-weave.legacy.weave.context_state] disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.mappers_weave] +[mypy-weave.legacy.weave.mappers_weave] disallow_untyped_defs = False disallow_untyped_calls = False @@ -183,15 +183,15 @@ disallow_untyped_calls = False disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.artifact_base] +[mypy-weave.legacy.weave.artifact_base] disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.artifact_local] +[mypy-weave.legacy.weave.artifact_local] disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.artifact_wandb] +[mypy-weave.legacy.weave.artifact_wandb] disallow_untyped_defs = False disallow_untyped_calls = False @@ -199,19 +199,19 @@ disallow_untyped_calls = False disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.client] +[mypy-weave.legacy.weave.client] disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.mappers_python_def] +[mypy-weave.legacy.weave.mappers_python_def] disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.mappers_gql] +[mypy-weave.legacy.weave.mappers_gql] disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.mappers_publisher] +[mypy-weave.legacy.weave.mappers_publisher] disallow_untyped_defs = False disallow_untyped_calls = False @@ -227,7 +227,7 @@ disallow_untyped_calls = False disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.forward_graph] +[mypy-weave.legacy.weave.forward_graph] disallow_untyped_defs = False disallow_untyped_calls = False @@ -235,15 +235,15 @@ disallow_untyped_calls = False disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.make_type] +[mypy-weave.legacy.weave.make_type] disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.serialize] +[mypy-weave.legacy.weave.serialize] disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.op_def] +[mypy-weave.legacy.weave.op_def] disallow_untyped_defs = False disallow_untyped_calls = False @@ -255,19 +255,19 @@ disallow_untyped_calls = False disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.execute_fast] +[mypy-weave.legacy.weave.execute_fast] disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.op_def_type] +[mypy-weave.legacy.weave.op_def_type] disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.op_execute] +[mypy-weave.legacy.weave.op_execute] disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.execute] +[mypy-weave.legacy.weave.execute] disallow_untyped_defs = False disallow_untyped_calls = False @@ -275,19 +275,19 @@ disallow_untyped_calls = False disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.graph_mapper] +[mypy-weave.legacy.weave.graph_mapper] disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.context] +[mypy-weave.legacy.weave.context] disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.decorator_class] +[mypy-weave.legacy.weave.decorator_class] disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.mappers_arrow] +[mypy-weave.legacy.weave.mappers_arrow] disallow_untyped_defs = False disallow_untyped_calls = False @@ -295,11 +295,11 @@ disallow_untyped_calls = False disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.decorator_op] +[mypy-weave.legacy.weave.decorator_op] disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.decorator_arrow_op] +[mypy-weave.legacy.weave.decorator_arrow_op] disallow_untyped_defs = False disallow_untyped_calls = False @@ -307,15 +307,15 @@ disallow_untyped_calls = False disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.decorator_type] +[mypy-weave.legacy.weave.decorator_type] disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.panel_util] +[mypy-weave.legacy.weave.panel_util] disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.compile] +[mypy-weave.legacy.weave.compile] disallow_untyped_defs = False disallow_untyped_calls = False @@ -327,7 +327,7 @@ disallow_untyped_calls = False disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.panel] +[mypy-weave.legacy.weave.panel] disallow_untyped_defs = False disallow_untyped_calls = False @@ -335,15 +335,15 @@ disallow_untyped_calls = False disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.derive_op] +[mypy-weave.legacy.weave.derive_op] disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.async_demo] +[mypy-weave.legacy.weave.async_demo] disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.legacy.runs] +[mypy-weave.legacy.weave.runs] disallow_untyped_defs = False disallow_untyped_calls = False diff --git a/pyrightconfig.json b/pyrightconfig.json index a42ea6cf76c..0ad38dc42a1 100644 --- a/pyrightconfig.json +++ b/pyrightconfig.json @@ -19,7 +19,7 @@ "weave/box.py", "weave/cli.py", "weave/client_interface.py", - "weave.legacy.codify.py", + "weave.legacy.weave.codify.py", "weave/compile_domain.py", "weave/conftest.py", "weave/context.py", diff --git a/weave/__init__.py b/weave/__init__.py index 9ea806d2e21..4a92a3147a7 100644 --- a/weave/__init__.py +++ b/weave/__init__.py @@ -3,22 +3,22 @@ import sys # We track what modules were loaded before importing weave, so we can ensure -# that someone doesn't introduce auto-importing loading weave.legacy.ops or weave.legacy.panels +# that someone doesn't introduce auto-importing loading weave.legacy.weave.ops or weave.legacy.weave.panels # (because they are slow to import and have more dependencies, and they are part of # the engine and UI layers which should be kept separate from the core layer). pre_init_modules = set(sys.modules.keys()) -from weave.legacy import context_state as _context_state +from weave.legacy.weave import context_state as _context_state _loading_builtins_token = _context_state.set_loading_built_ins() -from weave.legacy import weave_types as types -from weave.legacy import storage -from weave.legacy.api import * -from weave.legacy.errors import * -from weave.legacy import mappers_python_def -from weave.legacy import wandb_api as _wandb_api -from weave.legacy import context as _context +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import storage +from weave.legacy.weave.api import * +from weave.legacy.weave.errors import * +from weave.legacy.weave import mappers_python_def +from weave.legacy.weave import wandb_api as _wandb_api +from weave.legacy.weave import context as _context from weave import version @@ -40,20 +40,20 @@ from weave.trace.util import ThreadPoolExecutor, Thread # See the comment above pre_init_modules above. This is check to ensure we don't accidentally -# introduce loading weave.legacy.ops or weave.legacy.panels when importing weave. +# introduce loading weave.legacy.weave.ops or weave.legacy.weave.panels when importing weave. newly_added_modules = set(sys.modules.keys()) - pre_init_modules ops_modules = [] panels_modules = [] for module_name in newly_added_modules: - if module_name.startswith("weave.legacy.ops"): + if module_name.startswith("weave.legacy.weave.ops"): ops_modules.append(module_name) - if module_name.startswith("weave.legacy.panels"): + if module_name.startswith("weave.legacy.weave.panels"): panels_modules.append(module_name) if ops_modules or panels_modules: all_invalid_modules = ops_modules + panels_modules invalid_submodules = set([".".join(m.split(".")[:2]) for m in all_invalid_modules]) raise errors.WeaveInternalError( - "importing weave should not import weave.legacy.ops or weave.legacy.panels, but the following modules were imported: " + "importing weave should not import weave.legacy.weave.ops or weave.legacy.weave.panels, but the following modules were imported: " + ", ".join(invalid_submodules) ) diff --git a/weave/conftest.py b/weave/conftest.py index a18d90ad4e2..a33d2ac523c 100644 --- a/weave/conftest.py +++ b/weave/conftest.py @@ -13,9 +13,11 @@ from flask.testing import FlaskClient import weave -from weave.legacy import client as client_legacy -from weave.legacy import context_state, environment, io_service, serialize -from weave.legacy.language_features.tagging.tag_store import isolated_tagging_context +from weave.legacy.weave import client as client_legacy +from weave.legacy.weave import context_state, environment, io_service, serialize +from weave.legacy.weave.language_features.tagging.tag_store import ( + isolated_tagging_context, +) from weave.trace import weave_init from weave.trace_server import ( clickhouse_trace_server_batched, @@ -24,7 +26,7 @@ ) from weave.trace_server import trace_server_interface as tsi -from .legacy import logs +from .legacy.weave import logs from .tests import fixture_fakewandb from .tests.trace.trace_server_clickhouse_conftest import * from .tests.wandb_system_tests_conftest import * @@ -37,7 +39,7 @@ # tests. context_state._eager_mode.set(False) -# A lot of tests rely on weave.legacy.ops.* being in scope. Importing this here +# A lot of tests rely on weave.legacy.weave.ops.* being in scope. Importing this here # makes that work... ### Disable datadog engine tracing @@ -269,7 +271,7 @@ def factory(process=False): @pytest.fixture() def consistent_table_col_ids(): - from weave.legacy.panels import table_state + from weave.legacy.weave.panels import table_state with table_state.use_consistent_col_ids(): yield diff --git a/weave/deploy/gcp/__init__.py b/weave/deploy/gcp/__init__.py index 3100723a4ce..dfe8947be6c 100644 --- a/weave/deploy/gcp/__init__.py +++ b/weave/deploy/gcp/__init__.py @@ -8,8 +8,8 @@ from pathlib import Path from weave import __version__ -from weave.legacy import environment -from weave.legacy.artifact_wandb import WeaveWBArtifactURI as WeaveWBArtifactURI +from weave.legacy.weave import environment +from weave.legacy.weave.artifact_wandb import WeaveWBArtifactURI as WeaveWBArtifactURI from weave.trace.refs import ObjectRef, parse_uri from ..util import execute, safe_name diff --git a/weave/deploy/modal/__init__.py b/weave/deploy/modal/__init__.py index 947cbb2f057..6972f32ce7f 100644 --- a/weave/deploy/modal/__init__.py +++ b/weave/deploy/modal/__init__.py @@ -5,8 +5,8 @@ import typing from pathlib import Path -from weave.legacy import artifact_wandb as artifact_wandb -from weave.legacy import environment +from weave.legacy.weave import artifact_wandb as artifact_wandb +from weave.legacy.weave import environment from weave.trace.refs import ObjectRef, parse_uri try: diff --git a/weave/deploy/modal/stub.py b/weave/deploy/modal/stub.py index 89eeff34bcc..29242192fde 100644 --- a/weave/deploy/modal/stub.py +++ b/weave/deploy/modal/stub.py @@ -4,7 +4,7 @@ from modal import Image, Secret, Stub, asgi_app from weave.deploy.util import safe_name -from weave.legacy.uris import WeaveURI +from weave.legacy.weave.uris import WeaveURI from weave.trace.refs import ObjectRef, parse_uri image = ( diff --git a/weave/legacy/Dockerfile b/weave/legacy/Dockerfile new file mode 100644 index 00000000000..e1d677577ff --- /dev/null +++ b/weave/legacy/Dockerfile @@ -0,0 +1,51 @@ +FROM frolvlad/alpine-glibc:alpine-3.17_glibc-2.34 +LABEL MAINTAINER="danny goldstein " + +ENV CONDA_VERSION=4.9.2 \ + CONDA_MD5=b4e46fcc8029e2cfa731b788f25b1d36 \ + PYTHON_VERSION=39 \ + PYTHONDONTWRITEBYTECODE=true \ + PATH=/opt/conda/bin/:/opt/conda/envs/base/:$PATH \ + WEAVE_LOCAL_ARTIFACT_DIR=/local-artifacts + +# We do the following all in one block: +# - Create user and group weave +# - Install miniconda install dependencies +# - Download miniconda and check the md5sum +# - Install miniconda +# - Install tini +# - Remove all conda managed static libraries +# - Remove all conda managed *.pyc files +# - Cleanup conda files +# - Uninstall miniconda install dependencies +RUN mkdir /weave && + apk add --no-cache wget bzip2 && + wget --quiet https://repo.continuum.io/miniconda/Miniconda3-py${PYTHON_VERSION}_$CONDA_VERSION-Linux-x86_64.sh && + echo "${CONDA_MD5} Miniconda3-py${PYTHON_VERSION}_$CONDA_VERSION-Linux-x86_64.sh" >miniconda.md5 && + if [ $(md5sum -c miniconda.md5 | awk '{print $2}') != "OK" ]; then exit 1; fi && + mv Miniconda3-py${PYTHON_VERSION}_$CONDA_VERSION-Linux-x86_64.sh miniconda.sh && + sh ./miniconda.sh -b -p /opt/conda && + rm miniconda.sh miniconda.md5 && + ln -s /opt/conda/etc/profile.d/conda.sh /etc/profile.d/conda.sh && + echo ". /opt/conda/etc/profile.d/conda.sh" >>/weave/.profile && + echo "conda activate base" >>/weave/.profile && + /opt/conda/bin/conda install conda==$CONDA_VERSION && + echo "conda == $CONDA_VERSION" >>/opt/conda/conda-meta/pinned && + /opt/conda/bin/conda install --freeze-installed tini pip gunicorn python=3.9.7 -y && + find /opt/conda/ -follow -type f -name '*.a' -delete && + find /opt/conda/ -follow -type f -name '*.pyc' -delete && + /opt/conda/bin/conda clean -afy && + apk del wget bzip2 + +ENV PORT 9239 + +WORKDIR /weave +ADD . . + +RUN pip install -r requirements.engine.txt +RUN mkdir /local-artifacts + +EXPOSE 9239 + +ENTRYPOINT [ "tini", "-g", "--" ] +CMD ["gunicorn", "weave.legacy.weave.weave_server:app"] diff --git a/weave/legacy/core_types/__init__.py b/weave/legacy/core_types/__init__.py deleted file mode 100644 index 9b2fa51859e..00000000000 --- a/weave/legacy/core_types/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from weave.legacy.core_types.stream_table_type import StreamTableType diff --git a/weave/legacy/ecosystem/__init__.py b/weave/legacy/ecosystem/__init__.py deleted file mode 100644 index 265d3d5e9bb..00000000000 --- a/weave/legacy/ecosystem/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from weave.legacy.ecosystem.root import * diff --git a/weave/legacy/ecosystem/bertviz/__init__.py b/weave/legacy/ecosystem/bertviz/__init__.py deleted file mode 100644 index 87a014869a2..00000000000 --- a/weave/legacy/ecosystem/bertviz/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from weave.legacy.ecosystem.bertviz.panels import * diff --git a/weave/legacy/ecosystem/craiyon/__init__.py b/weave/legacy/ecosystem/craiyon/__init__.py deleted file mode 100644 index b007a23646e..00000000000 --- a/weave/legacy/ecosystem/craiyon/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from weave.legacy.ecosystem.craiyon.ops import * diff --git a/weave/legacy/ecosystem/huggingface/__init__.py b/weave/legacy/ecosystem/huggingface/__init__.py deleted file mode 100644 index 2f42a92960c..00000000000 --- a/weave/legacy/ecosystem/huggingface/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from weave.legacy import context_state as _context - -_loading_builtins_token = _context.set_loading_built_ins() - -from weave.legacy.ecosystem.huggingface.hfmodel import ModelOutputAttention -from weave.legacy.ecosystem.huggingface.huggingface_datasets import * -from weave.legacy.ecosystem.huggingface.huggingface_models import * -from weave.legacy.ecosystem.huggingface.model_textclassification import ( - FullTextClassificationPipelineOutput, -) - -_context.clear_loading_built_ins(_loading_builtins_token) diff --git a/weave/legacy/ecosystem/keras/__init__.py b/weave/legacy/ecosystem/keras/__init__.py deleted file mode 100644 index 7e87b9429a8..00000000000 --- a/weave/legacy/ecosystem/keras/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -from weave.legacy import context_state as _context - -_loading_builtins_token = _context.set_loading_built_ins() -from weave.legacy.ecosystem.keras.model import * - -_context.clear_loading_built_ins(_loading_builtins_token) diff --git a/weave/legacy/ecosystem/lens/__init__.py b/weave/legacy/ecosystem/lens/__init__.py deleted file mode 100644 index 68f024d1abb..00000000000 --- a/weave/legacy/ecosystem/lens/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from weave.legacy.ecosystem.lens.lens import * diff --git a/weave/legacy/ecosystem/py/__init__.py b/weave/legacy/ecosystem/py/__init__.py deleted file mode 100644 index a6167c9b4cf..00000000000 --- a/weave/legacy/ecosystem/py/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from weave.legacy.ecosystem.py import pydoc diff --git a/weave/legacy/ecosystem/pytorch/__init__.py b/weave/legacy/ecosystem/pytorch/__init__.py deleted file mode 100644 index 6e0da8b69d5..00000000000 --- a/weave/legacy/ecosystem/pytorch/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from weave.legacy.ecosystem.pytorch.model import * diff --git a/weave/legacy/ecosystem/sklearn/__init__.py b/weave/legacy/ecosystem/sklearn/__init__.py deleted file mode 100644 index 6c3b24135bb..00000000000 --- a/weave/legacy/ecosystem/sklearn/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from weave.legacy.ecosystem.sklearn.datasets import * diff --git a/weave/legacy/ecosystem/slack/__init__.py b/weave/legacy/ecosystem/slack/__init__.py deleted file mode 100644 index 24421beadde..00000000000 --- a/weave/legacy/ecosystem/slack/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from weave.legacy.ecosystem.slack.panels import * -from weave.legacy.ecosystem.slack.slack import * diff --git a/weave/legacy/ecosystem/slurm/__init__.py b/weave/legacy/ecosystem/slurm/__init__.py deleted file mode 100644 index 208a2d8e6c9..00000000000 --- a/weave/legacy/ecosystem/slurm/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from weave.legacy.ecosystem.slurm.ops import * diff --git a/weave/legacy/ecosystem/torchvision/__init__.py b/weave/legacy/ecosystem/torchvision/__init__.py deleted file mode 100644 index f875c477039..00000000000 --- a/weave/legacy/ecosystem/torchvision/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from weave.legacy.ecosystem.torchvision.datasets import * diff --git a/weave/legacy/ecosystem/wandb/__init__.py b/weave/legacy/ecosystem/wandb/__init__.py deleted file mode 100644 index 709aa0d4414..00000000000 --- a/weave/legacy/ecosystem/wandb/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -from weave.legacy import context_state as _context - -_loading_builtins_token = _context.set_loading_built_ins() - -from weave.legacy.ecosystem.wandb import wandb_objs -from weave.legacy.ecosystem.wandb.panel_distribution import * -from weave.legacy.ecosystem.wandb.panel_geo import * -from weave.legacy.ecosystem.wandb.panel_scatter import * -from weave.legacy.ecosystem.wandb.panel_time_series import * -from weave.legacy.ecosystem.wandb.run_chain import * -from weave.legacy.ecosystem.wandb.weave_plotly import * - -_context.clear_loading_built_ins(_loading_builtins_token) diff --git a/weave/legacy/examples/apps/explore_embeddings.ipynb b/weave/legacy/examples/apps/explore_embeddings.ipynb index cb8a21a4a36..a5e820dc9d7 100644 --- a/weave/legacy/examples/apps/explore_embeddings.ipynb +++ b/weave/legacy/examples/apps/explore_embeddings.ipynb @@ -1,383 +1,383 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "d3f10990", - "metadata": {}, - "source": [ - "# Embedding explorer\n", - "\n", - "In this tutorial, we'll create a notebook-based Embeddings explorer. We will use functions, or **Weave Ops**, defined in the Weave ecosystem so that they're available to compatible types in the Weave UI.\n", - "\n", - "You'll learn how to:\n", - "- Save and version embeddings\n", - "- Build an interactive embeddings explorer using Weave\n", - "- Use the Weave ecosystem to: \n", - " - Embed a string column using OpenAI Embeddings\n", - " - Cluster & project the embeddings using umap\n", - "\n", - "Note: we will follow the clustering / projection approach from here: https://umap-learn.readthedocs.io/en/latest/clustering.html" - ] - }, - { - "cell_type": "markdown", - "id": "dd81428f", - "metadata": {}, - "source": [ - "## Import Dependencies\n", - "\n", - "Make sure you have weave installed." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "cb252cdb", - "metadata": {}, - "outputs": [], - "source": [ - "!pip install weave openai tiktoken tenacity hdbscan" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "13a3497f", - "metadata": {}, - "outputs": [], - "source": [ - "import pandas\n", - "import weave\n", - "from weave.legacy.ecosystem import openai\n", - "from weave.legacy.ecosystem import umap\n", - "from weave.legacy.ecosystem import hdbscan" - ] - }, - { - "cell_type": "markdown", - "id": "43771ee8", - "metadata": {}, - "source": [ - "## Download the data" - ] - }, - { - "cell_type": "markdown", - "id": "2c74303f", - "metadata": {}, - "source": [ - "We'll use a pokemon dataset from https://calmcode.io/datasets/pokemon.json." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a297c756", - "metadata": {}, - "outputs": [], - "source": [ - "!curl -O https://calmcode.io/datasets/pokemon.json" - ] - }, - { - "cell_type": "markdown", - "id": "81a36bc4", - "metadata": {}, - "source": [ - "## Read the data and save it to Weave" - ] - }, - { - "cell_type": "markdown", - "id": "a7b73421", - "metadata": {}, - "source": [ - "Weave will store and version the data locally under the name you pass as the second argument to `weave.save`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e68f6c86", - "metadata": {}, - "outputs": [], - "source": [ - "raw_data = pandas.read_json('./pokemon.json')\n", - "data = weave.save(weave.legacy.ops.dataframe_to_arrow(raw_data), 'pokemon_data')" - ] - }, - { - "cell_type": "markdown", - "id": "8352ddb9", - "metadata": {}, - "source": [ - "We can show the data by executing it in a notebook, this will call `weave.show` on it." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "614f551d", - "metadata": {}, - "outputs": [], - "source": [ - "data # or weave.show(data)" - ] - }, - { - "attachments": { - "image.png": { - "image/png": "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" + "cells": [ + { + "cell_type": "markdown", + "id": "d3f10990", + "metadata": {}, + "source": [ + "# Embedding explorer\n", + "\n", + "In this tutorial, we'll create a notebook-based Embeddings explorer. We will use functions, or **Weave Ops**, defined in the Weave ecosystem so that they're available to compatible types in the Weave UI.\n", + "\n", + "You'll learn how to:\n", + "- Save and version embeddings\n", + "- Build an interactive embeddings explorer using Weave\n", + "- Use the Weave ecosystem to: \n", + " - Embed a string column using OpenAI Embeddings\n", + " - Cluster & project the embeddings using umap\n", + "\n", + "Note: we will follow the clustering / projection approach from here: https://umap-learn.readthedocs.io/en/latest/clustering.html" + ] + }, + { + "cell_type": "markdown", + "id": "dd81428f", + "metadata": {}, + "source": [ + "## Import Dependencies\n", + "\n", + "Make sure you have weave installed." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cb252cdb", + "metadata": {}, + "outputs": [], + "source": [ + "!pip install weave openai tiktoken tenacity hdbscan" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "13a3497f", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas\n", + "import weave\n", + "from weave.legacy.weave.ecosystem import openai\n", + "from weave.legacy.weave.ecosystem import umap\n", + "from weave.legacy.weave.ecosystem import hdbscan" + ] + }, + { + "cell_type": "markdown", + "id": "43771ee8", + "metadata": {}, + "source": [ + "## Download the data" + ] + }, + { + "cell_type": "markdown", + "id": "2c74303f", + "metadata": {}, + "source": [ + "We'll use a pokemon dataset from https://calmcode.io/datasets/pokemon.json." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a297c756", + "metadata": {}, + "outputs": [], + "source": [ + "!curl -O https://calmcode.io/datasets/pokemon.json" + ] + }, + { + "cell_type": "markdown", + "id": "81a36bc4", + "metadata": {}, + "source": [ + "## Read the data and save it to Weave" + ] + }, + { + "cell_type": "markdown", + "id": "a7b73421", + "metadata": {}, + "source": [ + "Weave will store and version the data locally under the name you pass as the second argument to `weave.save`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e68f6c86", + "metadata": {}, + "outputs": [], + "source": [ + "raw_data = pandas.read_json('./pokemon.json')\n", + "data = weave.save(weave.legacy.weave.ops.dataframe_to_arrow(raw_data), 'pokemon_data')" + ] + }, + { + "cell_type": "markdown", + "id": "8352ddb9", + "metadata": {}, + "source": [ + "We can show the data by executing it in a notebook, this will call `weave.show` on it." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "614f551d", + "metadata": {}, + "outputs": [], + "source": [ + "data # or weave.show(data)" + ] + }, + { + "attachments": { + "image.png": { + "image/png": "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" + } + }, + "cell_type": "markdown", + "id": "7619577f", + "metadata": {}, + "source": [ + "You can change the type of the displayed weave panel by changing `Table` to `Plot` and it will intelligently change to display a plot of the data.\n", + "![image.png](attachment:image.png)\n", + "\n", + "You've now created a Weave `Plot` Panel, or **Weave PanelPlot**. The default PanelPlot will show the HP (hit points or health points) of all the Pokemon versus their total stats. From the resulting PanelPlot, you can \n", + "* hover your mouse over a point to see the full data for it in the tooltip\n", + "* click on the magnifuing glass in the bottom right corner, then click and drag over a region of the plot to rescale and zoom to the selected region\n", + "* double-click on the plot area to reset to the original zoom level" + ] + }, + { + "cell_type": "markdown", + "id": "356dc2a9", + "metadata": {}, + "source": [ + "## Embed and cluster the data" + ] + }, + { + "cell_type": "markdown", + "id": "4fd47c57", + "metadata": {}, + "source": [ + "Now we can pass a column from this data to another Weave Op to embed it. This will turn each row in the column `name` into a vector." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "43cec2d8", + "metadata": {}, + "outputs": [], + "source": [ + "embeddings = openai.openai_embed(data['name'], {\"model\": \"text-embedding-ada-002\"})" + ] + }, + { + "cell_type": "markdown", + "id": "6715de4a", + "metadata": {}, + "source": [ + "Now, we'll project this to 2 dimensions for clustering, and then we'll cluster this projection using `hdbscan`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5eff5bca", + "metadata": {}, + "outputs": [], + "source": [ + "clusterable_projection = umap.umap_project(\n", + " embeddings, {\n", + " 'n_neighbors': 30,\n", + " 'min_dist': 0,\n", + " 'n_components': 2,\n", + " }\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "583830d0", + "metadata": {}, + "outputs": [], + "source": [ + "clusters = hdbscan.hdbscan_cluster(clusterable_projection, {\n", + " 'min_samples': 10,\n", + " 'min_cluster_size': 60\n", + " })" + ] + }, + { + "cell_type": "markdown", + "id": "87c4ad19", + "metadata": {}, + "source": [ + "Then, we'll project the embeddings again for plotting. For efficient computation, Weave isn't actually executing anything until we call `weave.use` or `weave.show` on the built-up computation (or \"compute graph\")." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "21f5917b", + "metadata": {}, + "outputs": [], + "source": [ + "projection = umap.umap_project(embeddings, {})" + ] + }, + { + "cell_type": "markdown", + "id": "e3b7f76c", + "metadata": {}, + "source": [ + "## Combine data for plotting" + ] + }, + { + "cell_type": "markdown", + "id": "1d017836", + "metadata": {}, + "source": [ + "Finally, we'll combine our data into one big table so we can display the Pokemon name and types alongside our embedding. Here, we're calling `weave.use` on each weave object to execute the computation, and then we're merging them into a new list of dictionaries. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d642110d", + "metadata": {}, + "outputs": [], + "source": [ + "weave.show([{'x': x, 'y': y, 'k':k, 'd':d} for (x,y),k,d in \n", + " zip(weave.use(projection),\n", + " weave.use(clusters),\n", + " weave.use(data))])" + ] + }, + { + "cell_type": "markdown", + "id": "1cf9b267", + "metadata": {}, + "source": [ + "## Build and publish an interactive dashboard" + ] + }, + { + "cell_type": "markdown", + "id": "202f5f66-a3c4-41ea-b1ca-cef26f98f26b", + "metadata": {}, + "source": [ + "Some Weave UI tips to build an interactive dashboard in-line to explore and get insights into your embeddings:\n", + "* **add new panels**: click the + button on the drawer that pops out on the right hand side of the cell\n", + "* **change panel types**: as we did above to change the `Table` panel named `pokemon_data` into a `Plot` panel\n", + "* **refer to other panels by their name**: add a new `plot` panel that uses `table.selected_data` from the first panel. You can click the pencil to edit the configuration of your `plot`. " + ] + }, + { + "attachments": { + "image.png": { + "image/png": "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Y29tL2V4aWYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iPgogICAgICAgICA8ZXhpZjpVc2VyQ29tbWVudD5TY3JlZW5zaG90PC9leGlmOlVzZXJDb21tZW50PgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+MTY3MDwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgICAgICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj43MDQ8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8dGlmZjpYUmVzb2x1dGlvbj4xNDQvMTwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+MTQ0LzE8L3RpZmY6WVJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgpZQ7xWAABAAElEQVR4AeydB2BUVfbGT3ovkEoJhN57B1FAEHsHe/evrrqra9t1177uuuvaXdvae1lRERRBivTeewuhJZDee8L/fDe8YZJMwkxISPuODvPmlfvu+81M5r77neJ2TE1oJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACzZ6Ae7O/Ql4gCZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZCAIUBhiB8EEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEmghBCgMtZA3mpdJAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAhSG+BkgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIggRZCgMJQC3mjeZkkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQGGInwESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESaCEEKAy1kDeal0kCJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACnq4gSE9Pl7y8PFcO4b4kQAIkQAIkQAIkcMoEMo+5ya4St1Nuhw2QAAmQAAmQAAmQgKsEov19pKt7mTksPDzc1cO5PwmQAAmQAAmQAAk0OgIuCUMlJSVSWFjY6C6CHSIBEiABEiABEmjeBHLK3CSpmMJQ836XeXUkQAIkQAIk0DgJ+Hl4SJFHSePsHHtFAiRAAiRAAiRAArUg4JIwZLXfuXNna5HPJEACJEACJEACJFCvBOLi4uq1fTZOAiRAAiRAAiRAAiRAAiRAAiRAAiRAAi2JQK2EoZYEiNdKAiRAAiRAAiTQuAh0DPSXyTGRjatT7A0JkAAJkAAJkECzIrA/J09mH0xqVtfEiyEBEiABEiABEiABi4C7tcBnEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiCB5k2AwlDzfn95dSRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRgI0BhyIaCCyRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiTQvAlQGGre7y+vjgRIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARsBCgM2VBwgQRIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgASaNwEKQ837/eXVkQAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkICNAIUhGwoukAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkEDzJkBhqHm/v7w6EiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABErARoDBkQ8EFEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEmjeBCgMNe/3l1dHAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAjYCFIZsKLhAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAs2bAIWh5v3+8upIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIwEaAwpANBRdIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIoHkToDDUvN9fXh0JkAAJkAAJkAAJkAAJ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t1Xtd333i+2TAAmQAAnULQFXRCHrzJY4hHRyR5OSTHo5pJlraGuyNYYaGhzPTwIkQAIkQAIkcHoINKYaQ6gT+Mgjj8jdd999ei6eZyEBEiABEiABEmgQAo2lxlDli7evOXTu5EmCYtsNaaaOYWamoHZQeFiYSZvjbH+Q7i1dRZtQFYVQm8cVQ72htLQ0KTtWJiHBIZri90ThcrRToBNuqamp4u3lrXWjWzlVM9qV89e0L5hkKhPUTEINxqAg1iCuiRe3kQAJkEBTIXBEU6b+oLXwkF5+zOhRMnBAf5e6bl9zKDoq0jhRIOq0oaxiTG9D9YLnJQESIAESIAESIIFGTCBYvV+HDRsmGRkZ0r59+0bcU3aNBEiABEiABEigOROwTyu3cuWqBheGMKGFaB88XDVTD6idn6uHmf0RhdOmTXS1x/pqXYd2bdtWu70+N4AJxC48aCRAAiRAAs2HAKJ9ykrLaiUKgYIVOTRj5s+SkpIqRUVFLjlU1DVJCkN1TZTtkQAJkAAJkAAJNDsCPXv2lDfffLPZXRcviARIgARIgARIoOkRgDgUGBQknh4eTa/z7DEJkAAJkAAJNFEC/bXOXdcunTXKtWKUqiuXA3EI6VYLCgoaVBRCnykMufLOcV8SIAESIAESIAESIAESIAESIAESIAESaGACsR07NHAPeHoSIAESIAESaFkEEBF6KqKQRcvd3V38/V1LoWodW5fP7nXZGNsiARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARJovAQoDDXe94Y9IwESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIIE6JUBhqE5xsjESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESaLwEKAw13veGPSMBEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiCBOiVAYahOcbIxEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEmi8BCgMNd73hj0jARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIggTolQGGoTnGyMRIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARJovAQoDDXe94Y9IwESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIIE6JUBhqE5xsjESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESaLwEPBtv19gzEiABEiABEiABEjhBINz9mAz0OiZSnCNxcTknNnCJBEiABEiABEiABOqBwEAvN9lQ7FYPLbNJEiABEiABEiABEmhYArUShuLi4hq21zw7CZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZCAywRqJQy5fBYeQAIkQAIkQAIkQAKnSCClzE3mFrpJx0B/mRwTeYqt8XASIAESIAESIAESqJ7A/pw82XAwqfoduIUESIAESIAESIAEmjCBWglDnTt3bsKXzK6TAAmQAAmQAAk0JQKMVG5K7xb7SgIkQAIkQAIkQAIkQAIkQAIkQAIk0NgJuDf2DrJ/JEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACdUOAwlDdcGQrJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJNDoCVAYavRvETtIAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAnVDgMJQ3XBkKyRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiTQ6AlQGGr0bxE7SAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAJ1Q4DCUN1wZCskQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIk0OgJUBhq9G8RO0gCJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACdUOAwlDdcGQrJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJNDoCVAYavRvETtIAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAnVDgMJQ3XBkKyRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiTQ6Al4NvoesoMkQAIkQAIkQAIk0EwIlJaWSkpKiqxdu17mzp0r/v7+8uCDf5RWrVqZKywsLJStW7fJ9z9Mly1btkhOTo4MGjRQrpo6RQYMGCCenhy6NZOPAi+DBEiABEiABEiABEiABEiABEiABBqMQIufXTh27JgUl5RImU7U+Pj4iJubm8M3o6ysTEp0P5i3t7fDfbiSBEiABEiABEiABGoikJubKytWrpJv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AZg7Z9bgHfQgGllwcGsOqMLCImRkZEouzqo+HZ32p/1q/2pBQUF92j87IwESIAESaEuAHkNtefAVCZAACZAACZAACRgCgQEBWH7DjTh65Bj+z//8D15fuw6JiWPgMGoU0tIvIj09HeMkhvyKW26Gu4R5oZEACZAACZAACZAACQxeArm5eWi5PLxRcj+XOCYBixYugKOj4+Ad9CAamYYcDA0NRZ54XZWXl5tHfw0vNDSkxyEO+2ss7JcESIAEhisBCkPD9cryvEiABEiABEiABK6JgE4YjBfh579++J9Yu+4NvPHGG9i2fbvpU8PG3Xbbajzx+GNISkq6puOwMQmQAAmQAAmQAAkMZwKLFi3EgvnzzSk6Og5c4Jro6Cjcv+YeaLhgf3+/fs2TM1yvZ1BQINzd3SScXImEWq5BfX1Dn52qi4sz3NzcobmiPD09+6xfdkQCJEACJGCfAIUh+1xYSgIkQAIkQAIkQAKGgK5Y/PKXnsEXPv8USkpKoHmF/P39oYmXVTyikQAJkAAJkAAJkAAJdE7A0cEB+hhoc5AxBAUGDvQwhvzxVbShcDPkLyNPgARIgARAYYhvAhIgARIgARIgARK4CgEVgDQpcVhY2FVqcjcJkAAJkAAJkAAJkAAJkAAJkAAJkAAJDG4CA79kY3Dz4ehIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIYNgQoDA0bC4lT4QESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAEuiZAYahrPtxLAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAsOGAIWhYXMpeSIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIk0DUBCkNd8+FeEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEhg2BCgMDZtLyRMhARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgga4JOHW9m3ubm5uxb/9+bNr0ESoqKjFmzGg8+MD98PX1JRwSIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESGFIE6DF0lcv17ob38M1vfgtZmVnw8fHGu+9uwP/89OdXacXdJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJDD4CNBjqItrUlZWju/927/j0YcfFnHoOTg4OKCktBROTsTWBTbuIgESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESGKQEqHB0cWH+8corcHJ0wuOPf86IQlrV38+vixbcRQIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAKDlwCFoS6uzeHDhzFp4kQ4Ojpg9+49qG+oR1xsHKJjouEwalQXLbmLBEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABAYfAQpDXVyTjIwshIQE49e//i0qKiuQmZkNV1cXfO2rX8GMGdPbtNy9ezcqKyvblFleNDU1mc2amhoUFhZaivncTQIWfsq3vr6+m61YrT2BhoYGU8T3YHsy3Xvd3NxMft1D1Wkty99yVVXVgPwt19XVdTo27iABEiABEiABEiABEiABEiABEiABEiABEiCBkUKAwlAnV7qlpcWIQaWlJbj33nswcUKyCD9V+I/v/wA/+e//g3VrX2vT8vTp0ygoKGhT1v6Fihrl5eXti/m6mwRqa2uhD9q1EeB7kPyujcC1t1aRXB8DYZorjkYCJEACJEACJEACJEACJEACJEACJEACJEACI5kAhaFOrv4oCRUXEhyMuLg4rFp5q4STczQ1ly1dip//8pcyqVkLd3c3a+uHH34YKibZM12l/uKLL8LHx8f0Z68OyzonoGJQbm4uAgICDMPOa3JPVwSUobLU9zSt5wQyMjKgf+Ex0dE9b8wWhoDlbzkwMBDe3t7XnYqK9wMlSF33k+UBSYAESIAESIAESIAESIAESIAESIAESIAESKATAhSGOgGjxYljEnHy1Mk2gk+wiEWODo5obNSwXFeEIVdX1y56at2lYhNXq18VU4cKFmb6bNnuUIkF3SZAht1G1aGiZhYjvw5Yul2gn4FqA/VZaDl+twfMiiRAAiRAAiRAAiRAAiRAAiRAAoaAJTw9cZAACZDA9STg7Ox8PQ83oo7FmDpdXO41a+5FRkYmPtq82YSAy8/Px85duzBlypQBWe3exVC5iwRIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgASuSoAeQ10gmj59Gp584nH88Y9/ws6du1FRUQ4Vh55//htdtOIuEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEhicBCgMdXFdNGTUF7/4eUyeMgkXL16Ck+QZmjhpIiZPmtRFK+4iARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIggcFJgMLQVa6Lu7s7li1diqamJlPTyYnIroKMu0mABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABAYpAaoc3bgwmrCcglA3QLEKCZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZDAoCbgMKhHx8GRAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAn0GQEKQ32Gkh2RAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQwOAmQGFocF8fjo4ESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAE+owAhaE+Q8mOSIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESGBwE6AwNLivD0dHAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAn1GgMJQn6FkRyRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiQwuAlQGBrc14ejIwESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIIE+I+DUZz2xIxIgARIgARIgARIggT4j0NzcjIqKShQUFMDNzRVhYWFwcuKtW58BZkckQAIkQAIkQAIkQAIkQAIkQAIkMEIJ0GNohF54njYJkAAJkAAJkMDgJlBRUYHNmzfjP77/A7y+dp2IRBWDe8AcHQmQAAmQAAmQAAmQAAmQAAmQAAmQwJAgwGWnQ+IycZAkQAIkQAIkQAIjiUBjYyNSU1Px4aaPkJmZhcTEMWhqahpJCHiuJEACJEACJEACJEACJDDgBGpr6/D+xg86HcecObMQFRnZYf/uPfvQ0tKCWTNnmH37DxzEqFGjMG/u7A51r1Zw7P+zdx/gcV3ngfdfYDAVvTcWgL03sVMkJVnNkizJjiXHJYos2/LGibNer+PYcZyN7c9Z50m8jr2bxLHTY8exZMmSVaguqrCKvYkNBEACRCF6H9TvvBecwQCYIQpnQGDwP88znDvnnnvuPb87AMl55z2noka8XT2yMj9THDa+4x/MazzeR48el/NFRcG6k/j4eLn7rjuC7qMSgWgRIDAULXeScSCAAAIIIIBA1AhU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JEACJEACJEACJEACJEACJEACJEACJEACJEAC3kaANYa87Yhyf0iABEiABEiABEiABEiABEiABEiABEjAwwj07t1LevboYXrt7884Zg87fOwuCZAACZCAhxGgY8jDDhi7SwIkQAIkQAIkQAIkQAIkQAIkQAIkQALeRsDfz0/wopEACZAACZAACbieAK+4rmfMFkiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEjALQjQMeQWh4GdIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAHXE6BjyPWM2QIJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJuAUBOobc4jCwEyRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiTgegIBrm+CLZAACZAACZAACZCA8wicSM+Qj/Yfd94GuSUSIAESIAESIAESIAESIAESIAESIAES8CECt+QYiouL8yFE3FUSIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAES8A4ClJLzjuPIvSABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiCBYglU+EGt2KW4AAmQAAmQAAmQAAmQAAmQAAmQAAmQAAn4KIH4+Hiz5+Hh4T5KgLvt6wSys7N9HQH3nwRI4DYQqFix4m1o1TeavCUpOd9Aw70kARIgARIgARIgARIgARIgARIgARIgARIgARLg4Cx/AyRAAiTgXQSYMeRdx5N7QwIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIOCbDGkEM0nEECJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEAC3kWAjiHvOp7cGxIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARJwSICOIYdoOIMESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAEvIsAHUPedTy5NyRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiTgkAAdQw7RcAYJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJeBcBOoa863hyb0iABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEjAIQE6hhyi4QwSIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAES8C4CdAx51/Hk3pAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZCAQwJ0DDlEwxkkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIk4F0E6BjyruPJvSEBEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABhwToGHKIhjNIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIwLsI0DHkXceTe0MCJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACDgnQMeQQDWeQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQgHcRoGPIu44n94YESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAEHBKgY8ghGs4gARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgAe8i8P/kFu9JFZ12fgAAAABJRU5ErkJggg==" + } + }, + "cell_type": "markdown", + "id": "0cf240cf", + "metadata": {}, + "source": [ + "![image.png](attachment:image.png)" + ] + }, + { + "cell_type": "markdown", + "id": "4b9fc573", + "metadata": {}, + "source": [ + "To share your creation, you can click \"open in new tab\" in the right-hand drawer, and then click \"Publish\" to save it to wandb." + ] + }, + { + "cell_type": "markdown", + "id": "9a4092e3", + "metadata": {}, + "source": [ + "### Bonus: Weaving everything together" + ] + }, + { + "cell_type": "markdown", + "id": "4f211f9e", + "metadata": {}, + "source": [ + "Here's a **Weave Board** for all these panels, defined in code. We're actively working on additional examples and tutorials to explain these concepts in more detail. To inspire some initial exploration, you can:\n", + "* **open the panel in a new window** from the right-hand drawer on hover, to view a full-page Weave Board\n", + "* **see the details of selected data** by clicking the mouse button in the bottom right of the PanelPlot, then clicking and dragging to select a subregion of points\n", + "* **customize the Board** by adding, changing, and interconnecting panels\n", + "* **save and share your work** by renaming the Board and publishing it to W&B" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e194b3ce", + "metadata": {}, + "outputs": [], + "source": [ + "weave.legacy.weave.panels.Board(\n", + " vars={\n", + " 'data': data,\n", + " 'limit': 1005,\n", + " 'limited_data': lambda data, limit: data.limit(limit),\n", + " 'embeddings': lambda limited_data: openai.openai_embed(limited_data['name'], {\"model\": \"text-embedding-ada-002\"}),\n", + " 'clusterable_projection': lambda embeddings: umap.umap_project(\n", + " embeddings, {\n", + " 'n_neighbors': 30,\n", + " 'min_dist': 0,\n", + " 'n_components': 2,\n", + " }\n", + " ),\n", + " 'clusters': lambda clusterable_projection: hdbscan.hdbscan_cluster(clusterable_projection, {\n", + " 'min_samples': 10,\n", + " 'min_cluster_size': 50\n", + " }),\n", + " 'projection': lambda embeddings: umap.umap_project(embeddings, {})\n", + " },\n", + " panels=[\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda limited_data, projection, clusters: weave.legacy.weave.panels.Plot(\n", + " limited_data,\n", + " x=lambda row, index: projection[index][0],\n", + " y=lambda row, index: projection[index][1],\n", + " label=lambda row, index: clusters[index],\n", + " ),\n", + " id='projection_plot',\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=24, h=12)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda projection_plot: projection_plot.selected_data(),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=24, h=12)\n", + " )\n", + " ]\n", + ")" + ] } - }, - "cell_type": "markdown", - "id": "7619577f", - "metadata": {}, - "source": [ - "You can change the type of the displayed weave panel by changing `Table` to `Plot` and it will intelligently change to display a plot of the data.\n", - "![image.png](attachment:image.png)\n", - "\n", - "You've now created a Weave `Plot` Panel, or **Weave PanelPlot**. The default PanelPlot will show the HP (hit points or health points) of all the Pokemon versus their total stats. From the resulting PanelPlot, you can \n", - "* hover your mouse over a point to see the full data for it in the tooltip\n", - "* click on the magnifuing glass in the bottom right corner, then click and drag over a region of the plot to rescale and zoom to the selected region\n", - "* double-click on the plot area to reset to the original zoom level" - ] - }, - { - "cell_type": "markdown", - "id": "356dc2a9", - "metadata": {}, - "source": [ - "## Embed and cluster the data" - ] - }, - { - "cell_type": "markdown", - "id": "4fd47c57", - "metadata": {}, - "source": [ - "Now we can pass a column from this data to another Weave Op to embed it. This will turn each row in the column `name` into a vector." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "43cec2d8", - "metadata": {}, - "outputs": [], - "source": [ - "embeddings = openai.openai_embed(data['name'], {\"model\": \"text-embedding-ada-002\"})" - ] - }, - { - "cell_type": "markdown", - "id": "6715de4a", - "metadata": {}, - "source": [ - "Now, we'll project this to 2 dimensions for clustering, and then we'll cluster this projection using `hdbscan`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5eff5bca", - "metadata": {}, - "outputs": [], - "source": [ - "clusterable_projection = umap.umap_project(\n", - " embeddings, {\n", - " 'n_neighbors': 30,\n", - " 'min_dist': 0,\n", - " 'n_components': 2,\n", - " }\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "583830d0", - "metadata": {}, - "outputs": [], - "source": [ - "clusters = hdbscan.hdbscan_cluster(clusterable_projection, {\n", - " 'min_samples': 10,\n", - " 'min_cluster_size': 60\n", - " })" - ] - }, - { - "cell_type": "markdown", - "id": "87c4ad19", - "metadata": {}, - "source": [ - "Then, we'll project the embeddings again for plotting. For efficient computation, Weave isn't actually executing anything until we call `weave.use` or `weave.show` on the built-up computation (or \"compute graph\")." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "21f5917b", - "metadata": {}, - "outputs": [], - "source": [ - "projection = umap.umap_project(embeddings, {})" - ] - }, - { - "cell_type": "markdown", - "id": "e3b7f76c", - "metadata": {}, - "source": [ - "## Combine data for plotting" - ] - }, - { - "cell_type": "markdown", - "id": "1d017836", - "metadata": {}, - "source": [ - "Finally, we'll combine our data into one big table so we can display the Pokemon name and types alongside our embedding. Here, we're calling `weave.use` on each weave object to execute the computation, and then we're merging them into a new list of dictionaries. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d642110d", - "metadata": {}, - "outputs": [], - "source": [ - "weave.show([{'x': x, 'y': y, 'k':k, 'd':d} for (x,y),k,d in \n", - " zip(weave.use(projection),\n", - " weave.use(clusters),\n", - " weave.use(data))])" - ] - }, - { - "cell_type": "markdown", - "id": "1cf9b267", - "metadata": {}, - "source": [ - "## Build and publish an interactive dashboard" - ] - }, - { - "cell_type": "markdown", - "id": "202f5f66-a3c4-41ea-b1ca-cef26f98f26b", - "metadata": {}, - "source": [ - "Some Weave UI tips to build an interactive dashboard in-line to explore and get insights into your embeddings:\n", - "* **add new panels**: click the + button on the drawer that pops out on the right hand side of the cell\n", - "* **change panel types**: as we did above to change the `Table` panel named `pokemon_data` into a `Plot` panel\n", - "* **refer to other panels by their name**: add a new `plot` panel that uses `table.selected_data` from the first panel. You can click the pencil to edit the configuration of your `plot`. " - ] - }, - { - "attachments": { - "image.png": { - "image/png": "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Y29tL2V4aWYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iPgogICAgICAgICA8ZXhpZjpVc2VyQ29tbWVudD5TY3JlZW5zaG90PC9leGlmOlVzZXJDb21tZW50PgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+MTY3MDwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgICAgICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj43MDQ8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8dGlmZjpYUmVzb2x1dGlvbj4xNDQvMTwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+MTQ0LzE8L3RpZmY6WVJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgpZQ7xWAABAAElEQVR4AeydB2BUVfbGT3ovkEoJhN57B1FAEHsHe/evrrqra9t1177uuuvaXdvae1lRERRBivTeewuhJZDee8L/fDe8YZJMwkxISPuODvPmlfvu+81M5r77neJ2TE1oJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACzZ6Ae7O/Ql4gCZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZCAIUBhiB8EEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEmghBCgMtZA3mpdJAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAhSG+BkgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIggRZCgMJQC3mjeZkkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQGGInwESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESaCEEKAy1kDeal0kCJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACnq4gSE9Pl7y8PFcO4b4kQAIkQAIkQAIkcMoEMo+5ya4St1Nuhw2QAAmQAAmQAAmQgKsEov19pKt7mTksPDzc1cO5PwmQAAmQAAmQAAk0OgIuCUMlJSVSWFjY6C6CHSIBEiABEiABEmjeBHLK3CSpmMJQ836XeXUkQAIkQAIk0DgJ+Hl4SJFHSePsHHtFAiRAAiRAAiRAArUg4JIwZLXfuXNna5HPJEACJEACJEACJFCvBOLi4uq1fTZOAiRAAiRAAiRAAiRAAiRAAiRAAiRAAi2JQK2EoZYEiNdKAiRAAiRAAiTQuAh0DPSXyTGRjatT7A0JkAAJkAAJkECzIrA/J09mH0xqVtfEiyEBEiABEiABEiABi4C7tcBnEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiCB5k2AwlDzfn95dSRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRgI0BhyIaCCyRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiTQvAlQGGre7y+vjgRIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARsBCgM2VBwgQRIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgASaNwEKQ837/eXVkQAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkICNAIUhGwoukAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkEDzJkBhqHm/v7w6EiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABErARoDBkQ8EFEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEmjeBCgMNe/3l1dHAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAjYCFIZsKLhAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAs2bAIWh5v3+8upIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIwEaAwpANBRdIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIoHkToDDUvN9fXh0JkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJ2AhQGLKh4AIJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJNG8CFIaa9/vLqyMBEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABGwEKQzYUXCABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiCB5k2AwlDzfn95dSTgkEBOTq5s3rzF4TauJAESIAESIAESqB2B3Nxc+Xba9zJh4vnyyJ8ek+ycnNo1xKNIgARIgARIgARIgARIgARIgARIoB4JeNZj22yaBJwm8JfHnpIVK1bJxRedL/ffd6/Tx3FH1wls3LRZHnviGYnt2EFef/VF1xvgESRAAiRAAiTQjAkkJSXLmrXr5NixY7ardHd3F39/fwkPC5OIyHDzjHWVDccUFRWpIJQt+QV5oo1U3qVFvs4+XCT7fs0UTx83aT8mWII7eDvNIS+lRA4tyZKsg0UVjgmJ9ZGuF4SKm7tbhfUt5UVZaYlk7NslB5fPq3DJPkEhEtlvmLTu0qvCer4gARIgARIgARIgARIgARIgAXsCFIbsaXC51gT27I2TnTt3VTjezc1NgoODJSIiXKKjIiUkJKTCdvsX+fn5ZhKloKDQfjWX65BAWVmZvP/Bx/KePvStkaumXlFt6198+Y3s2btXzjxjjIwbd6Ys+G2hLF6yTLp26SLXXjPV4XGztu+TLYkpVbb9cdwQ8XQweVZlx0a+IqugSN5ZtrFKL4d3aCNndW1fZT1XkAAJkAAJNE0Cu3bvkWeefU5KS0sdXoC3t7f07NlDrrz8Uhl31ljx8/NzuF9dr8zNzZMdO3dKcnKK9O7dUzrExNT1KeqtvcKMEklYli2+YV7S/oxgl85TlF0qR9fnSdJGFdrsLHpIgHQ5D8KQ3coWtHhMx3W5SQkqDM2tcNUBEW0kIKo9haEKVPiCBEiABEiABEiABEiABEigMgEKQ5WJ8HWtCCxevFTefPu/1R7rpnftZ4wZJddcPVWGDR1c7X71sWH6jzOlqLjYTOBArGqp9qdHH5ffFi6Stm3byt//9qT07dO7WhSrVq+RpcuWS2RkpBGGdu7aIzNm/ixjRo+qVhiCKPTL9vgqbf7hzMEqDFVZ3eRWFBSXOLy+EF8fCkNN7t1kh0mABEjg5AQQHTRixHCJjo4yIhHSxCUkJMrOXbtlk0bf7tsXr0LNLvn9PXeJp2f9D6lT01IFY5qtW7fL7bfdXGfC0LGSY1KQUSr5aSXi5ecuQTHOR/OcnGLVPVwVckI7+cjYp084YCSsypXl/zhcteEWtsbDy1tiRk80D1x6ztHDsmvml5J5YE+jJlFSWCB5KUekTMfmgdHtxNPXv1H3l50jARIgARIgARIgARIggeZKoP7vYpsIuQ0bNsj48eNNb3eqNyYmxF2xq6++WmbPni233nqrvPhiy03PhaigK6+4zKBDhEpGRoYcOXJUVmtKlsVLlsqSpcvk+eeeNWKDK3xruy9Sujz3rxfMhM4Vl12ikTJNUxhCJprcxGLJSy4WpE7xCfFwCcms2b8aUahVq1by37delyiN4KrJrPQ4Hscjfaxna72jYx+eMEzwgIH7xDe/dbRbk10XGeQv8+6ZYuv/Ryu3yqdrttleN6cFvH8JmblyNDtXOoeHSqifT3O6PF4LCZBADQSysrLk888/l7/85S9mXPThhx/WGPFbQ1NNflN4eJhccvEFMmjggArXkpaWpnWEfpAPPvpUFi5cLJ1iO8qll1xUYZ/6eFGiDgq5eRWjZuriPJkHimTj+0lSqOJQr6vD6l0Yqos+s42mSaBURaHDqxbKlq/flqh+I2TI7Q83zQthr0mABEiABEiABEiABEigGRCgMHT8TSwp0TzdKmLAMCnqquVocWEcn1cPN+yu9qUh9w9VYeiuO26r0oXMzEx56pl/GGHo8aeelWn/+1wiIyKq7FfXK5B2pbpUMHV9rvpsLzexSGbfHS/u3m5yyeddXTpVRkamvPTya8ab+V/P/e2kohAa9/Ep9xb2rvRsrXepA9y5yRE4nJkjN33+i3h7eMiP/3dpk+s/O0wCJFB7AnDqKCgoMGMaRMjUNCbCNox/8IiOjm6yzheu0mrdurWcO3mSHDh4UBAxjaih02HFOlbN03FNXduxsmMavXFMIzfcxC+MtwZ1zZftnSBw7FiZlJUUC6KdfII1DaCOM2gkQAIkQAIkQAIkQAIkQAINQ6DJ3f1t2rRJlixZIkOHDpXhw4c3DDWe1WUCiCT6x7NPyeTzL5X8/DzZuHGzTJo4weV2XD0AglRzsNKicrEyINJL3L1ci3p68eVXzQTfHbffWsXruTo2AQGBZlNgpWdrfXXHcX3zIFBYUl5XIyrYX7w8mkEewObxtvAqSKDREIAQhCjp559/XjZv3ixwronRejeInr7//vu1tmDtHT/gzAFBqrCoyKnr9dSJ5YCAAEHdn9NpQUFBEtuxo8yeM89ERhdpf13pQ2pqmixctFiWL18p+w8cVIcMH+nXt4+MHTtGRo4YVkFkS0w8IvPm/ybbNaJ9r6avKyoslB80pdzadRvMJXfsECMXX3R+rSO7dK5eSjWdnIeOL7wCXP+bj+MhLrl7ujY+gR9WmZ4XqeXcPVw7trbv9bFSFcH0J85DHW1Oh5WVlkhpUaF4evu6JIKgftAxPdbN06vCZ6E++3xMv3vHFI67ijYuG95MJ6LycV0QhnBdnn61SyHXEGxc5sEDSIAESIAESIAESIAESKAJEGhywtCPP/4ojz/+uDz22GMUho5/wOCxm5Ka6vTHzU3cBOlRTrehOHPXrp11EmmL8a51VRhC5MsXX30j27ZtlzidGGnXto0p/jxFU9d10EkRe4vfv19+njVHDh06kYP+H//8t+5SPhHQs2d3U3PI/hhXl4tydPLqaHlqt8oTGiV5ZXrDqzMd1c076P1zSaHu4+vcBAz2hXkHu+ZZuW3bDvlF08hhwmnqlMudvkTr8xERUf45OfEc7nQbtd2xRCcNYJ7H09i50g7ks+qQ19QOhBAfT9fY1tRefW0DGw+deDmVlIi5RcUS4O1VYxctYShU6yfRSIAESMCeQHZ2tnz11Vfy8MMPq6NHvhGEwrQWz9atW+WVV17Rujv75OWXX9bo1Cj7w5xehkjy1tvvmvSnzhzUKTZW7rrzdpkw/ixndq+zffB32N0I58cE/yHSyhmD8LV16zZ56533ZI2m2bUM7e1Q4WfO3HlywXmT5Zabb5TQ0BCzOUGFoW/+N00Sjxyxdpd169abB1YMHjRQzj57nEvCEMYvcb9kSPLmPCnOLZMcTVeLH9BFjx8UOKHAMOaIOSNYOk4INq/t/8lLKpH4eZmSuEYjxhKKTcSRr0YbRfb3l67nh0qI1gWqzjB+ip+XJbump0n2oSJT1yisp690mhQqbUeoY0ptfsirO5muL0gvkQO/ZcmBhdna13LBMbijj3QcHyyxE0PqXCTKT0uW/Utmy5ENK7RuU5IRhjy8fSS4XSdpP2KctBt+lsO6OmXIXhC/S+LmT5eMfbukMDtTvAODJaLXIOk04SIJielcw1XWblNhZrocWvWbSe+Wm1Q+Zg5q21Haj5wgMaMmKhvHIhEEpKzD++WAXmd63E7JT00S76AQadW5p0T1HybR/UfYhDDcp6Tt3Czbf/hYivNzJTc50XT2wOJfJHXHRlvHQzp0ke4XXKPpklvZ1lkLDcHGOjefSYAESIAESIAESIAESKC5EmhywlCqCwJIc33TKl8XUr6cf2F5XZ/K2xy9hkiwZOFcR5vqfZ3H8ZQRpXrz64rBo/bpZ58T6/3HBEpycrJs2LhJfpg+Q+7/w71yxeWX2JqMi4uXDz/6xPYaCyjYbFlm1pm1FoaSt2jE0/vJkrm/UF1d1etUU69gImTIPdGy56d02Tc7UwozS2XyW50ksE3FCfjDy7Jl98wMydxXKCX5ZeIX4SlthgVKvxvCy4Ukq4P6XKppXRY+esCsSd+j51JL3ZYv8x/ab5atf0Y81FYCoiuex9r2m3ojwy48/zyXJoxQaBtmTeydeI406+v6HwgR0zbull+275OErFzTfNvgADm3Vye5YkC3GkWbPK258OXaHbI5IVn2pGSYCJfe0WHSv22EXN6/m8OIFwhIP22Nk/m7D8i+1EzJKiiSEBVBOrYOlhuG9pLBMbWb0KxrLmjviNb5+VjrGe1I0smbjGxx189+lNY7Gt2prdwwrHe1Is+7yzfLukNH5apBPWRgu0j5YMUWc735yqu1v6+M6dRO7hjTX/y9yn8GinSy8r7vFphL2KXngm1OTJHf/a/i34rHzxkpbUPKI8rMTvyHBEigxRDABO+KFSuMc46/v7/8+c9/lkceecSI1UuXLpV7771Xfv75Z/PbAXGoNhYUGChDhwzSKCDnognCw8M1jd3p/5udo1FNhw8niK+vr0RpXUo8O2O7d++V1998RzZt2mycW2695UYZ0K+fqR0065fZ8uVX/5PpM36SYv1dfOiBPwhq+3Xr1kWeefpx4xjz6WdfmnXnqXg0fNgQc8pgjV4KV3HOFUOAB5xOilQUKi3Ar6KaPpXqcAPrYG4aAYSxiL0h4iZ5a76pSZRzuFj8Iz0lQsdAiBjKjC+U+LmZkrI1T3pNDZMO46oKSkVZpRI3K1MOLslW0cNdwnv7SYHWNjq6Pk8y9hZK5oFC6TVFr6WOxKH0uELZ/GGypO8ukNDOPtL1wlApUuedlM35svnjZEnblS8D74gSL3/nHHXsWThazjocL9u//1jSdm+RwOgY6TB6khFMshMOSNqerbL12/fk6Ja10ufK21SAa2NrojgvWw6t/E12/fS1Rhf5SGTfoea4rINxkrhuiWTs3yU9LrxO2gwebTvmVBcyte3t0z6UdG07JKaLdBp3oRQX5EnqLhVxvvtI0vftlL5X3anCXcXvYnFejhGSds/6RrDs1ypcQjp2lSIVso6sX6bXt9qIRT1U5PE4/r0oUyEJohCipyxDNBXWWVai9Ycgsla2hmBTuQ98TQIkQAIkQAIkQAIkQALNkQCFIQfv6ql44ztort5XeXh6ygXnn+v0eTw1fUNDGLxk9+6NM6fu0bOH013Yo8f88aE/mVpBQ4cOkXt+d4d0795NDqpX8edffi0zZv4s/3z+BRU+gmXi2eNNuwMH9pc3Xn/ZpKz773sfmHWvv/qSTqaUzzS0alXVG9GZDqXuyJelzx7WtCdu6tkaosKPt/G2TVyVKzNX7TVNxJwZJH6tPStk1MAEzJrXjsiBBVkS2NZLOk8OMfWCkjbmSdzPGXJEPW4n/LujeklWjFqxJmfs+1Z5HVK4VGfLlq0wm846a2x1uzhc36dXT1NIu61GZcHwjMLaWF/XVqZwnp2zQpbtSzCTi31U1IFtPZIq76/QyYmjqfL0eaONIFL53FtUuHhu7io5omJSsK+34NgCnUzbnJAiK+ITZbm2+bcLxkjQ8VpJOB5C0mMzl8hGFZJC/XykV1SYBPp4yZ7kDCOEPPzjIrluSC+5dWTfyqc77a8hXL04f61AtOkcFiITu3eQ5Nx82a19/d+GXfLrzv3y36smSViAX5W+JWblCAQesHlAvYEPad2g7hGhEhHoLzuT0mTG1r1SrBM1D08YZjs2t1A9xitZ5XX4LNNIgARaJgE4ZCxbtkyysrLkyiuvlAceeMCIFKAxYsQIIxjdcMMNsnbtWtmzZ49GCXd1GVRERLhcNfVKl487nQcUaiq3TZu2yNx5CwS1Fbt06ezU6dO1FuVS5bdhw0aTNu7RPz2kok85o9atW8mN118rbaKi5Z//flEZrpNFWr9onP5+Q/gZOKC/RiUdEx91YvBw95AunTupMDTUqfM62ilQHUoGqSACg8PL6leOSECUlwy7L1rFnurHiW6a8s1HI4ki+vhJj8tbS8zYIDMmQjvFKrgcWJglmz9Klvj5WRLex1/81QHG3rI1YqdQI4a6qUDTU8UjCDKIINqv+2/7MlUSVuZo2/56bNXfNft2nFnOSyqW+DkZJiqpx5WtpPtlrW0p67LUuWfzpymSsqVA9uvYrOsFoc40WeM+SHGWp9Ewabu3SmSfoTLw5vs14uZ45JT+eOYmJ8jeOd9LQWaaeNiNxVF3J10jhPbMnqZRRR2l79V3SVCb8kh4iCWJa5fItmkfyIFlv0rrLr0cRtTU2DEHG/M0wufAkjmSc/SQdJs8RbpMuswW4ZOtkUDbf/zUXMfhlQskdtwFthaQBi552zrZMf1T8Q0Nk95X3Cpth51pxm9IRZdxYI+KW18ZcSikYxdpN7R8W0TvQTL+6bfVcSpN9i2YIQdXLJBO4y+UrpNr/q43BBvbxXKBBEigyRJAits4jWCGeenf206dYnXphMHRJSEh0dTVhYMJjQRIgARIgARaKoGKd2uNmMLbb78tu3bt0iK/5REQM2fO1JzuR2w9fvLJJ6V9+/a21xs3bhSknduwYYN5IEqmf//+ct9998moUaNs+zla8PLyMm2/9dZbsnDhQpMWZdCgQTJhwgTjDQvvzdrY0aNHTXoVeNtiwqR3794ycuRI420bqB6ytTVv7e9TT/y1toeftuP+ox6ySEHjqf0d0M+5SXcM2v75rxdsotDrr7wgniqEwTAR88Rjj5qc/tO++0FefPk1GT1qhMCLubUKP5gwyc8vsF0fPGtr+95ZjWz9PEW9YkXO/Ft7ad3N16zufmkrwfod/0uT3teESa+rqnrtIl0LRKF2owNl2B/bmDz+OLjPNSIb3kuSvT9lyBadoBhy7wmvZ+T6P1ejjmCHlmbLyn8nStuRgTLqz23NOmf+OZyQYHbrEHPiu+HMcZio+uujj9h2hQe3/WvbhjpYeG3heiMKdQkPlecuHKsiRznXtLwCeXTGYrMN+9w/bnCFs2H7X39aIrlFJSZy5kaNnkE0DQzp0t5ZtslEBX2nkUg3De9jOxYRMm004qV/uwi5XqOD7FPWIeLofo2a+WrdDpmgIkysRhA1pHVqHSKdw0PkvjMHS1cVdSyDNvO8CmJzVBh6e+km+es5I6xNVZ4RiRWsE4nvTJ0onVRcgkGM+/uclXL14BNCn7dG831y/Xlm+8I9h+SZ2cvljM7tjChnVvIfEmjhBJAi7YsvvhBEvt54441mIvT77783tXYwPmnXrp1MnDhRpk6dKp07VxUKkGosPj5eZsyYIatXrzap11BLB2OTSy+91NTnsX7fLNTWObEe50RKVoxLML5Zs2aN6cvkyZPljjvu0EmP8t8L61j758TERPnuu+9MNA/GH6gBdNZZZ8mUKVNk4MCB9rvWuHzgwAFzvdHR0TJmzJgKNXUwdkIfhgwZIthvzpw5tRKGauzAad5YWFhkUtIGag2j0tIyydbaSgcPHpTlK1epQLZS+btrWuNhcslFJybOa+oi0tvOnb9QWoWGygg9Dr+19oaooz59e8vokSNk6fIVMl/3hTBU34ZxTZkGciMtrrvXyce4IbE+Jsqmcr8g8rTTcUp+aokcXJRtnF46n3fitwv7Q1gK76Wi0hWtbVE63oEeJoVc9sEiObg420QTnaowdExrFyHa+qCOn6IGBEi3i06IQuhHUIyPOumEyqpXEuXI2hyTVu5Uo4YgDJUWF8uxY1qrx0S+lI9JcD54CwVEtpNeV9xiImt8W5+YiMxLOiKHNVrIyy9AYs863yYK4TBPH18J695XogeOMpE8Rzatko5jJ2NTrQ21izJVwEnQSKSIngNNmjq34xH9aDRQRamOY86RDR+/Iklb1mhaufG21HeIfIpf9ItGMwVL54mXmLR4VkfQRqtOPaSfClvZCfslqt8JxxNrn/IaQ1o7Se+l3O3EMWt75efTzaby+fmaBBozgWL9ezPn13kSoPe+48ad2aBdxT07nB/y8/IlLKy101G09dVp/H7/OneBaR6/4Z06xZpl659Fi5fIlq3bzUv8zvbp3cvaxGcSIAESIAESqJEAatnv2LlbHff6mbIdNe5cw0Y4KBxRnQBpwRvSmoww9MYbb8iWLVtsrCzBx1rx+9//3ghDmHRB3vtp06bpjVm5azvEAEzIbN++3UyMfPzxx3LNNTojX419++23Jj1KWlqabQ9MckyfPl1++eUXk1s/ONi1CWMUab7pppsE4hAM+fh//fVX8/jmm2/khx9+0JQiJyZpbSduYgtFOkDdvXuP6TUmn9O0uDJy4yOqZ+u2bWb9g3/8g4lAcebSkCpuo6Zbgf3ujtttopD9sXf8360y86dZkpKSIj/Nmi2oOVQfhgLJqTsLJHKACk/HRSHrPPBC3TFNc+Ufz11vrcdzcU6ZEY68NRpoyL3RNlHI7KNzBv1ujDCTIPHzM6WvppSrHDWE/UqLyj/Lnpq2zllDIWwUCMeEYps20c4edlr3Q1QQIldQ8+bJc0fZRCF0AunOsO6ub+aafSb17GgigqwOvrF4g+RohAvSxd1sJ/xgO9p7YNwQiW0VLJdpKrrK9vCEoZVXmdddVZz608Th8tSsZfLDpj1VxCiHBzmxcuX+RPlm/a5q97y4bxc5q2tV8Q5CzutXTKhyHD4FD+o1xKdlmfRwd58xQFopL0cGAe2ly8ZJTGiQbTMENIhJlpBm23B8waox5KsiGo0ESKCcAKJl8Fudl5cnGAziNxyRMZbt2LFDfvvtN4HjyvPPPy+jR59I+YQxxOuvvy4ffvhhhZSoGKfs3r1b5s2bZ4Sef/7znxUmU6xzIpIZzi/YD2MY+3o2mzZtMkLTm2++qdG03a3umGd4zK5atUr++te/mr5B1IKjDMZKSP2G8Q7qNl5//fUVjqvuBX5nN2/eLH369JFhw6pO+iLt6PDhw41DDvrV1G2fcnpG09g6statW8tFF54vV0+9ssJ75mhfax2EQIh0iMIdoBFAjiwiPEwGaNQzUsGmpeu4Qh1qgjRiqD7NCEPFZTpZr+JQ9cFCTnXBJ9RTwnr4mpo++Vrbp7IhojpKx1HeQRUjpBFZFDnIX/ZpKjpE+pRpCjt3dZCprSG6GmnpPH3cTX88fCq2hWv1CfVQEcZbSvKOGTHLy99xPR1n++Cu462AiGgJahcrKds3yMbPXpNu507Rc3QwwhDagfiDh70V5mRqpM1ejTYPl7BuVR2nvAKCBHV/jm5epfWSku0PrdVycV6uZCceMCnrIOTYopqOtwbRxic4VCPH2mhquXzJT0/Va0C6QK2tqRFR6Xu3m1R37Yad5fD8/uFRgocjQwRQqUYduWnUm4fnyXmfbjaO+sx1JNAYCUAUwv114pGj4qoDYF1ez9GjSbJMHRmSk1M0BeqJv/lBQYEmsnXkiOHGiaUuz4m20tMzJC8/z9znIp2rq3ZEuVkGZ2MKQxYNPpMACZAACZyMwN64faZW7MGDh/R+8LxaiUMHNAPWz5pGHPf1vTUzk7NpyU/Wt9psbzKzfu+++66Z5L7rrrs0Hdleue666+Tmm2+2XbPlnYtJ8J9++slMWiDFCSJykMoEEzY4FilQsP6yyy6rFjw8bzHh8f777xuPWog5n332mfz973+XWbNmmVQpr732mu3cJ1tAQeYLL7zQvOEPPfSQPProo4IJBUz44PUnn3wit956q+nbydpq7Nsx4XHtDbc47CbEsJtvut6l2j579pSnZ4N3c//+VW+WcSJEB0FhXb5ipUZile/vsAOnuLKkoMxMVCCFSmXz9HU3xYuRO7+ypWr+eohDKN7syBsVkxUQmo6s0Rv1w0UqDPlVbkJz/qs7r5qHTnA4a9bEIVIHnmqklLPndHW/bSoMwc7s0l7aOahbg1o22DZLaw9hXyvNXJ5GBP2256AgyuXmESeigSqf/3IHolDlfSq/HhXbRnz178hhTb1WV5aaWyAbDidV29xIPaerhkinscpmV3K66Wt1wtC4rjEVRCHrPNWJQtheePzGztez6mfdOp7PJNBSCWxTJweMKXr06CFwWpk0aZIgWgYROS+99JIsX75cnn32Wfn000+NEwg4IfXazp07zW8/xiDnnHOOGZscPnxYEJ2MqOi5c+eaKJuLL764Clo4xtx///0mYugvf/mLXHDBBYJIY0Qwvfrqqyb6CCIPttkbxBmMOSBgIfXbE088YcZHSUlJRqT617/+Jf/5z39MBPPgwRWjMu3bwTJ+UyCKweEAkUuRDiZirPVItZaenl65CadeQ8yC8Jav9ROdMYz7QjSdm59G29S1BaiXcWxsRyPM4G8mXrdpEyWdNTJq0MABTju5oF+YxEtTJhCHfFWcC9PUcY4MNwVIKwcDb0xe1b8wdEwjho6ZlHAe3s6PMzC2Sd2Zr7WBCiRPo4SQSg5iDsZCRdllUqi1gyqbp5+71lesqj4hRa+Xv4d4B3jomOeYplsrVXGh9rcpGLMhcqlE+4So6xSt0VjZ0N+85BLxbe0hBbpvcMzJhYrKbVR+HdKhi/S54jbZ/sMnkrBmsRzVCJ+QDl0lZuQEieo/XOsqVXUsK1HxpSAzVceYmt7uq7crN6mCjF5LeorWhCqQ/Iy0KttdXWHaSdNJXJ1URdRQ2t5yxy37drCtQPfxCWml7yOEoRhBP/M1BZ2nfkYh/FQWlOyPr24ZtajK9DtuIob07+bJ7HSzOVl/uJ0EGgMBe1EoXKNzJk08+7R3C44t6zUt6spVq3V8UO7AaN+J7OwcrQW8WQ5qpOw52j/rd81+n1NZXrpsuezXSbVQTSV/3bVXu9wUMotA0IKzzID+/Vw+ngeQAAmQAAm0XAJwJkBd+6N6Tz1j5iyXxSFLFEK5lTGjR1WrTZwuwrW/4zpdPTx+Hgg8MOvmGOlKkLKlssGjdsmSJSY1iv1keD8t7ItJm5iYGJMmDmlYkO7FkT344IPy3HPPmYkebEc9GkzyoL2//e1v8t577xkPW4gVztjdd98tmOhAkWa0axmOh+cvhCNMJKFg8/nnn29tdvoZAzMrZZgzB7mJm6a8aevMri7v4+vrp+zLvWDhmxmq6VLaarRKx44dZML4s1xWUqHEwtqpd21NBu9bWNzx/Wvat7bbkOokqL23oC4QJhwgBlmWtFEL6mrx5jAtolzZsg8VmVUZ+wplxb8SKm82r7MOlO+ToxFHKMRc2U5EDJ04Z+V9Kr/G5BImsTAJlZKSKuHqhdzYzBKGutmlSavcR2ybpZH+1r7YHpeaaXbr0CrIRAdVPsbZ12gTUUtHs3IlPb9Q6za4ab0hb61TVCKo0VNXNq5bjAxqX703G+oj1WRIjbc0LkESVKw6mp2rNYfKxNfLQ7Yklgtridr/vm3CHTbRsRbp8Bgx5BAlV5KAIYB0pfitxu+5fQ2de++914wxbrvtNiMCIboIyzCISHBwwe810rBZht9IOK3s37/fRPQgKtmRMAShBVE6EHKQ1tYyOJVAXIIIhfR0aN+qk4joHjizYHwB55R33nnHCFM4Fn3AsRAeIAx9/vnncjJhCH3I0DQxMG9vb3EUOY31GKdhzAMBCcdg0sUVO6CeV2+9/a78tnCRU4d1io2Vu+683YwxnDrAhZ1i2reT+35/txGBXDjM4a5gghQ7MA8Pz2pvABDVBeEIhmPy8qsKGmZjXf6jc3r60dFwIf3fiTuDouxSI7bs+kGFriMa/eHpphFA7mZcBFGnWGsGQWhC7aDKhshn/zDHJ0EKXa9Ad03HVibFuXrsKQpDBWkqDGnEdXZiseQmnfBkt++Tm/o/YHxXdVrTfi/nlxEJ07prbxl256NyZNNKOaQp4tLjdhjxxWdGqLQfPt6kbvMNaW0ahUhSnJulkeGFUqRvAvatznwCQzTqvObxQnXH2q8vLSrQWj/pKkQVSd7RRCP22G+3liHeePkH2thAUCpQkcjdy8dEFFn7ufZc/mFD2276PajJGoJNTf3hNhJoDAQqi0KXXHyR/p649jtbF9exeYvOX6xYZWsK9/sddJ7FP8BfkpKSTdr8Ak3nlqrZQ6b/OMOINxgj1JXl6P3tqVinTrFV0sudSns8lgRIgARIoOUQwP0tIoUgCrkqDlUWhVBHtqGt5hF5Q/euluevbnIDKU6QSx+TJ0jdUp0hFR28fysb0tVhUiZfb9IhLFkTPpX3s3+NVC2LFi0y4tJTTz1lv8m2jAilO++803gL10YYKlCv2suucN5TBh/iJQvn2s5flwtRkRGCOkB1ZfA2gkHgqMmQOxiWpSlX6tM6jAuWrVoLaOmzh6XPdeGah91bkjfnyfq3j2o0jwpuIwKrnD5HJyRgeSnFeiNedZLEOsBX06uYiRlrhd0z0rzAXE2r0kYn//ZohN3BQ4capTBkCTz2ac7Kr/TEv9Y2a19sOZhR/j5HB9f8uTjRSsWlzQkp8uaSDSbaBluCVAyCOFOqHm+ZBYVmZ6RgqytDXSM8XLUS9RJ+R2sIIWIqv7hEvLSeRaifr0ZKuZvXVh+tZ0ftRwb6O1pd4zqkgYQhIotGAiRQkQCcOsaPH19BFMIemPBA7UBsQ30dOKlY4wSMKTAGcWSIvEFdHjiHIOrWXtyx9ofTC9LR2otC2IZIXNQowjFWijuITTDUEkIUEcQrRFkjUtne0J8zzzxTkIIOqXZxPESv6gxjDSvFLsYRlqOO/f6WMIR12B9RQ/ZCmP2+1S0Hq7A0cuRwp72Lw5VBfTm7VNfH2qyHswY+OxCFCnWCPTUtXYXE9lWaKjDRVuUCHN6P2qTIqdLoSVYgrZrO06vbkJpGRtVkEIX2zc2S7V+nSEhHrd95a4RE9vMXRAJZdnR9rqx4IdF6WeEZ45lSTRPnyEpVTCrWFHD+GlHkE+T6b6Z9m0ZkCnDXtG7eJk1vm6G1Gy/Yt+nKsndQiHTQOj3tNVIo58hhFYjmmwiiffN/lJyEA9Jn6u16nW20rpOHqd8DwSd64EgZdPMDrpymVvuito+Xf4AERGnNo0tu1PdvqFPtoI9eGvEEEaswq/wz6tSBFXZS9zQVz2An+ag1CJsKXeULEmhkBBqLKIT6PavXrLXRGaROoaNHjbS97tWzh0bh9DUTZrg3z9Oav+vWbTC/7badTnEhN+fUhKHanh7e3XDgcNYQbQ2HHctpx9njuB8JkAAJkEDjJlAbcagxikKgfGp3XY37fTK9w2RJXFycqU+EvPjIIQtD8WBXDTf0yN+PlC7x8fFOHb5x40azH4o844PjyLp06WJWI0VebcxD06hcftklTh+KtCtNxTppChdYgk6W1WSoYwSD53B9Wk8tlgxhKGVLvix89MRnCN6yY/7aVoI7VH2PfTWHPazPNeHS5fzyCTtX+2h58GLyxhUbMWKYEYbWrd9QJx7PrpzbmX2RPu6QijwJGvFSXRIjbIPZp5qLOC52IFLGVdt4OFkenblYkIrt/rMGa22fGCMK2bdz6XvTNSqnehHPft/6WoZI9fQvy2XZvgQZ3amtXD24p/SODiufuDt+0u+1DtJ/Fq+vsQsnm3hxdLCnCk8wDaCikQAJuEAA4gvEoRkzZphaQtVNICASBGlqETGMNG8LFiwwqdoQ4YmoHEQq2xsmFOyjoK1tGFcgjRrMiuixhCGkr9u3b59xiKnOYQbCA4QbnBfjIystr9V+bZ7tJz8wBnPVEN16hQtjGlfbb6j9wQVOLJGR4ZKt0VRw2EDB0sqWow4xiJpy0x98pAuMiHAcDVr5uFN6jUkrDzfjnILaPh7e1f/xz9Io6P1aByg01kcG/S7KiEP25z5WioghrSOTf9yjxX6jLiOiqNBB2l18VEo1Grsor1Q8/d3Ep1X52KnS4U6/RFS3n0YcIYVc7hFEZZ9eYcjqqLsKgcHtOkrvy26WdkPHyvbvPpKsxP2StHWdxI67wKgjnr7+4hUQbMSWouxMjb4q/05bbdT1s6ePr/i1CpO0PVslN6V8/OzMOTw1K4B/WKS+h5o6MOWoefbQtlwxfA/cdIyB9HhlpY6juGzt6b6nm43t3FwggUZGoLGIQsCyXu8rC4470sEp1F4UsrBhLDJ+3JkyfcZPZhVqBvft20d/18r/FiOSaKHW0oOFh4fLmWPHmGXrn71742x1hrt27SL9+5WnlJ/z6zzjeAInCliOCkTffT/dOkzOP29ytRG5tp10Yf36jYI6grDBgwdJrGY3sczahjHWBeefq+mAswX30ojQzszMMo4x/fr10d/w6r28t2hE1S6tu5ys0dv6V8848vTo3tUwsM7DZxIgARIggaZNwBVxqLGKQngHmo5C4OLnBSIQUr6hNpDl4YpJFUsUwQRKbQwTKK4IQ9gXhtoB7dq1c3hKDPRgtRGrcJy3eiI/+qeHsNjsrEuXTuaaDh1KMDUaHKWuQV7j7Tt2mv26dC7fv75AxM/TFGY6XzLozkjN9X7MTDaE9fCTCPWW9asmNQrSz8HSNQd/bc1dhSeYlVLO2XbOGnuGfP7FV/LttB/kxuuvdRgJ52xb9bEfhI6V+xNlb0r1nqfWNuxrWeew8kmTg+nZkq1ea4j4cdbeXb5Ja+iUynOXjpUB7SKqHJZTWGza9Gng+jrrDh01otDAdpHyzHmjHXqaIbVcfRhEM5iVUq4+zsE2SaA5EsDgEKIOBBGILaglaEXMQCSCUPPll1/KV199ZaJ0sJ/92ASepdaYwBk+9seiLau2HMY4qCOEWj0rV66UMWPGOPwbgnNhH0Tloq81CUPWtaFfRUVF5voqRw1hffbxyN3yWjkVo5ScuabmvE9rrQXRV4XD+b8tlMWLl8rEs8dXqY10UEWhBQsWav3EUOnVq2cFz2QvRJ/6+Uu6iodI1VNXBucTL42uQZrcwowS8Y+sGjWPc0H0QXq2nKNF0rZjoNbOqeoMk3O0WBJWV//bVJBeYsSayhE8qPGTrE43XiroBGk0tmoCp2ReWqsosK2mhtVIbbTbYXyI1i9y0bvG1R7ge5+k49XD+6XN4NEVj9YL8g+LkojegyRr7g9SqAKQZYjeCdTonfy0JEnatl7ajxhnbaqXZ0+/AH2P25o+pO7eoucbbyKITnYyRBpBGMIjO2G/HFq9UDqeMdnxYcrC0ZtoopX0/M5GHZ1uNo4vhmtJoGEJNCZRCCQOqUBi2UCtt1edtdd0rBHq7JGsKc1LdAwEBxSIPLAiTWWZqDX0YPYOJWaF/pOrUczWdvvI2bi4fZrh4YTjAdq19sOxGGs5Y5lZmbbj8vVc9mZtw8/QHhWokNoWUVKWIQpq6bIV5mVlcQjjL4hXcPCwtyPqDITH4YREmXzORPtNXCYBEiCBFkvApB/Xe+aQ4GCHvwUAg99AZLbAXLCj3wvsg3tQ1KdFO6fbnBGHGrMoBF7NUhhC8WWrlg9qEyGFytChQwV1hq6++mqZOXNmrT8r+ODCnM2Ra4lS+BDb1yKo3IFevXoZL+PK61v660Ga+i8oMEi9a7Ply6+/lTv/79YqSBboBMsh9byFd+0ZZ1S8EQ/RgpSWxcfv10mvTtbLWj3vX5CledU9pNPkUD2fc0206qrelDoXkbAyRwpuKBUrgsi5o8v38gkp/6oil78rNmjQAA3bHyErVqyUX+fON15Urhxf3/v2jiqfNFwSd1huGt5H06RVnGTK0Lo/2Aaz9sVya39f6RoeKntUUPp45Va598xBWF3F4Ktu/zblaTq2nUnp4qeTa/0diEJoYNrGXVXaaYgV6w8lmdMO7xjt8AcQgticnfvrpWvW+1CbiKx66RAbJYEmQgDijDUpAdHGSjcCkQh1Dh944AEjxHTr1s3UKkQ0MdLE/fTTT2ZbXV0mBtCWQOPn5yedOnWyOcY4OgeinCpHKVXeD0KPtQ8G34hIqiwMWeeFEw6iXTBQbmmGa7dS8pVqPbgirRFnWQdNHXfBBefKGvU8Xrtuvbz99rtyx//dpsKcvxETt23fIe++/5HJVT1Kf7svu+Qi61DzjNpDrcNaSbzWpIInMtL14X05VfMO8pDgGG/JOlgsR9bnSefJx6PQNLInfXeBigbuEtbLT1OAuR2PJnKT4jy9Nq0hhGMtK9L9E1bkyGF9VGdIRYdUc1ED/CVSHzAIUkmalvfAQv1MqTMN0vaeqiG9b1h3P4keHCCp2/Nl9/Q06XlFmEn7a7Wdn6IilW4LbOslrbo45pienmEm+dasXSfnTDpbi7xPsA6v8pyXelT2/PqdZMTv1qgYD4nuP7yCOIL6PKm7t2lNoxAJbn9iPApRKEbFmU1fvikHFv8iQdHtNRKrq6191NrJPLhXayUdMCIOopBOxTy8VcDu1ENFqsHqtLRd4uZNl66Tr9D39sT3tSA9RdLitkuAprsL6XCiL0HtYqWjRjptn/ah7Js/w0T0tB1yhm2cUpiVbuoq5acmSa9LbxKPSp9Pr4AgTcMcI0XZGRqxtE2KxmaLt3+QRhCVqqAWr4LTAWk3/Cwzpsc11oYNbr6//maaThDky9VTr5Su3bpq3bdd8sWX3+jfsFC59uqp6r3fWjZs3CzTvvtBkJ3g6qunNMhkwqm8jzy2ZRDA7+qMmZpqVkWUcP3cNlRNIXvaGRknhG2rzq/9dvvlNm3aGGEI6zLUEeVUDQ4T+O2DYAPz9vaSbpoy1zJPFbDrynAfOXvOXDOW69ghxvxW796zVycpy+eDNm7cpCnz+tn+/uG8EIwsUQh1CntrgXJ3nTSAE2v8/gOm3120DUsgq6u+sh0SIAESaEoEStRRG5GY+DtapL9zQRpNOmLEcOnRvZvtMnAPtUbTlqKmHZwAQkNDZJSmG++s97WW4fdg5arV6nC50zgN4HcSUayO0nVbx9THc03iUGMXhcDj1O4s6oPoKbb5wgsvGFEIqVVQ+HncuHGn2GLFw+HtC0MhaWcMgg9swIABpn6AM8e0xH2Cg4PMZeMmzt7w5b/77jvkX8+/KB998pm0b9fWhHRb+6zfsFGe+1d5TaPLL7tYkNPY3trqYNSyJUuXn7IwhEkR1Ala/OQhaTMsQHPge5gJEwg3vq09NGrISydOrDOWPwdEeUnXC1vJnh/TZe3rR2T4g23MMfZ7GcEpRCcRdALDkYX39jOrE9eouKTeuqhHBCvRiZkd36VpmjpNMaZpYBwZosmuuuZGef2Nt2X4sKGNqtbQAI2GGdGxjYkaenbOCvnnRWNNijdzbeoN9o9fVwrq52Af7GtvD4wfKvd8O09+2LJXglVQumFor4oDcxWUPl2zXf59yZm2iCIf5PLXydoCHdCn5uZLeEA5V6vdDYeT5Jv1jUMYCvApv7E5nFF1gg39f/m3tZJj571mXUNdPPdvWx5JtTw+0XAKO84pT3+cv1y3U25WEc9Dvwuw93QSc8XKVfJ/t98iI4YPMz/sz//7ZeMV+MD9vzffOUysPf/Cy6aQ+iMP/1G9B8ProptsgwQaHQF4MyFFHAQhjEOQHgUOJYgavv/++wUizTPPPGNEIMvBBBE71Xk/1fYCEQHUtm1b048+ffrI+++/b1Lh1rY9HAehC4IH2sYgPEXTo1SOhMb1I1LJPrroVM7ZFI+FUNNGi3DDIQgTSB9+/Jlcd81Usw4M++r7ceP118i7730o33z7nfy2aIl07dLJeLnt2LHLpMXp2bO7XKvHtG7dqgIC1IUaMWyYRoGtlnnzF5iJpt69ehjBDiJSbZ1ffFt5qvDjr6JQiqkdlLwpV0UCd0nbVaBjnhKJnRRihCF4WmBMEzXQX1K25svq145IhzODVRxwl6xDGqWmolL24SJp3c3XiDEVOo8XejzGSh4aBb3yxURt01cCwr3MsSnbC8yYqv2YIAnRNHX2lpNQJIjYLkgv9wSHoAPLjC+UtW8cMd8fCEHhffwl5ozy8SS2B7Xzki7nhkiW7rfr+3Q5ui5PEKnkq2nq4GhzZF2u5GmkEq4vtLOvtoOjKlqcjvs//fwL/V4nmSg5ONygrpUjO6Y3rWWImlNxY8PHr6j401lCVeDx1ro8eZqyLXX3VuWZptFEZ0h4jxNpBN21dk/r7n1NTaL4hT/Lqrf+pqLNEAk5Lh5BvEnevt4IKsEqzIR2LL9pLinIk5Sdm+XoxpWmO8X5ecoyTopys+Tgsl8lTaOBYP7hUVoDc7yJ9DEr9B8ILrFnniebNfJnr4pZyZraLkprDXkHtzJ9Tdq2VnmnSszoSSoadrH9jfLSaJ/o/iMkJ/GgnmOubPrsdYnTCCj0C6nhMvbtVKZJEta1t6apS6wggOHc7iqcBoRH67V0UB5bZPUbf9NjO0lOsqZo2r9Xo8ViJKhtRwmJ6Wy66iobn8j2AhHvm2+nmb9Vfhphd8tN18nceQvkl9lzNJVjhERHRWraqjPk51m/mO9RB53w7dixo5w7eaI5J/8hgcZCoDGKQqi1XKh/52AY6/jruKYmCwo6UX/XXlCq6Ziatp115hkmatYShnD+cWeNremQU9oWqI4b52l6usiI8nujkSNGyCeffa5ju1LJydXfvOwc/b0v/91J1NT2O1QAgiFS6uKLNF3occPv80c6HkAk1Bp1DKEwZJHhMwmQQEsksHzFCtm0eavOKbkbp4eU1FQzVvPScaJ1P4NoTdxLeWomHzj0IAXpL7/8KpfqPY/llADnd4jxyKKFoIAU3WfmT7NkypTLqx2v1xdvR+LQAE0bjns2OI6OGT2qxhSk9dUvZ9ptdsIQ0rPA/v73v8u4OhaFEJVipXtzVhjChAxs9erVZnLISmVnVvIfGwGEYf88a7Ys0tQqH370qdxy8w22bZdfeokqxevMF+qpZ/4un372pWDSZL963cD7Bl+y3irA3Xv3XbZjrAXcAI5U5RkT16+/8ZbM1S9lzx7djafPk48/au3m9HPvq8Nk4aY8ST7+qHygf6Sn9LsxQtrbTUxgHwg3yeoNe2Rtrsy5J146nBVkvGJRZBliT/LmfGnd01eiBgU4nJjwUdEovK+fqW204M8Hpc1wnZjTdCw4Dh66EX21QLVO1DiytjpBdfddt8tLr7wujzz6mLzz5mv1klLu09XbxIowgYeVZS+pgOFxfLalTXCA3DCst7XJiAtPTB4pf/zhN0GEzBUfzJAxWk8Huy+NSzAp3XpEthbsYwkR1sE9IlvJ78YMkHeWbpSPV22VOTvipU+bcAlSz7GtR1Nl1/HIoN36PDimvOg72ji/dyf5YfMeeWT6IpkysLtEaZ+OaK2izYkp8qu2MaF7B5m364B1GttzXGqmfLvhhGiEaCXYyv1HBJFNll2pbVqp7qx1tXme0K2DfK0izM/b4sRbfwyH6jWUaTTCPu3HbO2nLkovjbjafjStNs3XeAwihpBmD/WY/jBtgYzS9yQtL182HEqWTM0pPlC3DdH+wPvhnXffN2298tqb8uVnH8qiRUtk+o8zzLqPP/1cnn7yMePpOHfefLMON0KOIv9q7BA3kkATIZCenq6TAjvMhCREEwg+qTrQRR0hRA2df/758qc//ck2yVpfl4XzQphCH6w+oUbiqVqYToj37dvXiF8Y18Dpxd4gCq1Zs8bk0rfGP/bbW8oynFJQLwGexquVx/Chg40whOvHTcvUKy83Nz3//e/7sk093BISEgwaRGBhIunWW24Qe8cWixsmn86eMM6k8Zn+40wzJsW4tFNsrKkjaN1IWfs7+4xI6A5nBZsIoPhfM+XQ0hzjbAJhpaeOezraRfAExfhI3+vDZds3qZK4SmtTrc41p0GtxVZdfKTPDeEmHR2idCqbT6incappOyxQtn2dqpHUuSY9HRxqQjr5SM8pYSpgnJhEtI5HOrjDK3IlR0Une8tXUefAgmyzCqnwPHzcKwhDcJiJGhggY55oJ7t+0EiWpdmS/lV5Wl+cE6nm+lwXLrFnhzgce6FhpKQAV0xoRkdHSSutm1GdBajY0ueqOyS810A5sHSOpGvETdqecnEGgoh/eBvpdu4UiR1/YYXoHLTn1ypcelx0nbSK7S57Zn8rh1cukEMr5plTQYyJ7DdMOk+8RAWT8jRM2FCqHpYQgg4e38/sfPyftL3bBA9YqLYZ2XeIiKaAs8zN3UMitJ8j7nlChaHvJWHdUsn4abfZ7KY36QERbU1/YkZNrPL3CkJT78tv0fe7l+ydPU0jzeIk88Ae3c9dI8hCpdP4i6TLpEs1wr6isGmdG2JZ78tv1XpLH5roqvT4XWKusc8Qc6wlCln7u8IG4ySk70R9E0wYd+4ca6IX4e3vhUkDfT87dYo10Y6dVAwyIn5wSIX6ItZ5+UwCDUkA97dWpBD6AaeDRYuX1LpLmIMYpr9FlSN9XW0w6AuoEwAAQABJREFUV8UQy3x9K4r41nr7Z/uoVogiTc2GqVOlJQqh735+vjrZGG7SwuE1xnaWMLQ3bp/o7ZmxyinmsBIe7Ds0ejEtLd14tmNClEYCJEACLY0AnCa3bdthxBzc90Spww6igpBmG/XoMO7O07mnPSoKYSx3ycUXqLNca+P4s3LVGhWUthhhCM7HEIWC1QHhEhWLgjRbxdJly7WNLbJZRSfUuTvdVlkcQmpRTcbdqEUhMGpywhAmJWCYeKlsyK2/ceNGsxqpWSobtmOCpLb273//2+TvRx+cFZ2QJgaTM/Csfemll+SRRx6p7emb9XFImYJUe3v27DHCj70w5K6T+f/8xzNmcIyol71xceYBIPBevu7aq+S2WzRdhXotObLH/vIn+dOjj8vWbds0xHCHeSDFzV8ffbjG1DqV28pJKJbl/0yQdmMCpfslrdVbskgnUbQehBZKLszQFBgHCo1Qs+qVRPU89TETDlYbnn7ucvYLHWSneqzu1sghTFBY5uHrJl0uCDUTLcf1E2tThedRf25rzo/Jlr0zVZTQsWSoTqQMuTuqWlHIauCqqVN0gmqe/oHcIo8/+TeBKAbP9bq0FRpdsiOpqkgx1y7dWU8VeeyFIZzf18tTnrtwrPx32SYjyED0gCGyZ3LPWLljdH+zj1lZ6Z8rBnSTfioGvbZonRGCErP2mz1w7OD2UfLA+CECMcrefnfGAPHSwsfTN++VFxassW0K1DpF94wdJBCcHAlDKTn5RpCxHXB8IT4tU/CwbFzXmDoRhtDvf1x4hry+aL18v2m3eVjngCjzx3FD5BUV3erLnta6Rk/+vEy2qGCG8yMNQhdN3wemOD8sWkVHeLAjQmLQwP5mHaL28IOIHNvWTVE/LTaL7yfErP66TCOB5kgAn/lNmzbJ/PnzdUDbWUaPHm0uExFBcfq7he8FBrWVo4OstGx1zQSToyPUs3XGjBny9ddfy8SJE20pzmp7rg4dOsikSZPMeGb58uVyyy232H57MYkFkQLC0ODBg81+tT1PQx93xphRsmLpb7XuBiZ//vroI3L7rTdJEmo32aU8QKOIFhut456RGmWZofWCDh1OEB9d11GLX9tPojnqADzkHnnoj9r2zZpG97D5POF88KQ7FfOP0BSrN0dIn2vDNc1XqUm55h1YdVyFcQoiekZq9HNhdpnkJRVrzcUyFT00EkSjiRBZDet+acX+IJpn/L862Lo4Qo9HBBAidnzV+QWONdaxtp2OL4T38pPJb8RWXu3ca+1OUDtvGXJPlKkPCTEJkd9wuPHT6Gt3r/L+VtcYnBn+8ezT5v6hjX6nqhtrWsd7a6q0mFFnm5RvxXka5a1RN8eOgU+URotXFb2s4/Ds6esnbYedqVFNY6UkP1eQjg2/m36tIzTq6EQklHWMT1CIdL/gGvOw1rn0rG8mxKz+198rfa++S5DqrlBTvKFd39Awje6pPiWTp0bixIycUH6dOVkmSgi1iwIiovR9rPq5se+Xm6bCi+g9UAW0V/Q686S0MN+ISEi/V505ywZjlZEjhsn/vlLPfJ2wbaeZBmAoSD9Gv9elOhkRGVkukCF93LnnnWPuBVprbTgaCTQmAohEOXK8Bg/6hd+JUzX8fvTsUfVviSvt2kcAIXoIKXQrj2vs28P30DJM2jU1c/QLYS+IoVaSZalpJ+6DD6vDR6LWVLI3jAdhYJat6XghYNNIgARIoKURQOYJpIZrExFuRCFcP+aQFi9ZamoJ4TWyUEBoh6M/7p9hvXr21LRxa0x2Bby2fl/gCBmsznUwtANhCMc3lOGeH5FC5aKQ3odo3ypntmqovlV33iYnDMXGxpprWbx4sclvj1QdliFFByYtMAHzwQcfqGp4ibXJpDW6/vrrZenSpbZ11S1ceeWVmvf9bbH3dv3Pf/4jb7zxhjnkiSeeMGKP/fHWh9X6cFrbIjTsGPWO7r77bnnqqaeMF+1tt91mbTbPBw4ckPXr11fob4UdmsALCDn2Yo6rXYYXJqINoBRjkszRIPOiC88XPDBI3rcv3qjEMTExmt7G0ZDtRA+gQH/4/tta7DFB4uMPqLdgkKbU6eaSKITWNn2cZCZLhtwTbVLBte5eNR/9ure0b7MzNSUHctZ7n+iELsFzteeVrc0DkxJIt+IdqF6ZUd4Vct5XOMjuBSZozno2Rj1Ej0l+crH4R3iddELDOhyMXnnpeXnm2edM5NXOXbvl2WeekD6a97iu7I0pZ9e6KUSoPHL2MLl/3GCN3in/Ix4d7C/eNUwSWCfrrkLOf648W4r0xyUupTwlU5fwEFtKOms/6xmi0V0aaXSjpkNLyMyRdE1VF6IebxA9rKikefdMsXa3PaPWj6P1th3qYaGvil5vXzVJjmarV7ZGNWGCqGPrYFNjCaf718XVe0H8ddJIeXTiMeVQ8/ejum4HqVD20mXjDNek7DyJCgowgpr9/gjZ/e5/X8i++P22fLCYhJk183vBzVGseuPCkHpnxvRvTdQkJtZoJNCUCSB6+N133zWTi5dddpmZKMYA95dffpEnn3zSvB4+fLhceuml5jLhwICJSNTk2bBhgxmjQDiCQUh55ZVX5M033zSv6/If1DG6+eabZeHChTJnzhxT0+jRRx816e1wHvzOHtYC0jt37pRhmp7MGk9BtLA8iuHRhWuzDNcxZswYMx6aN2+eGSvdc889ZjOuDel8MXHev39/jeztaR3WIp/hnY0bFTyqM4xbMX60xpDV7Vd5PRhH6M0UHnVtHt5umhb35LcHGNOgZmJt6iaizzjeT8UkPE6XuWtUE8QrPFyxQE2fiIcrhqgbpJDDw1XDJCtEpJMJSa62W9P+5RFNUUbAqmm/ytvQV28VkvBw1cqvU8cW/s6zdYYNvldIRY2HZfg+hh2fWLDW4W+dfSSAtZ7PJNAYCODzi8hTZNPA5NiAfn1NtFtt+4bvAO6JT9Uw4eWn0Uso8l1WdkzTqeUaL+3q2oXAZZn9d9Ja1xSf8XfIkWWo97pliAauyay61TXtw20kQAIk0BwJIC05hBykaV7w2yKtE9fFRANhrgt16WAQziHCIyJoydJl0lHn+VFLCIaU3TDcB3lqZh2km/P317qi6rC8otI+ZsfT/A+y6iB9HCKFcE+N38EZM2fpXPZ5xlH0NHfHqdOdvrsxp7pz8p0gqiBXPjzUcbN9+eWXazhumonEGTt2rPFeffzxx+XHH3/UYn+9Zfz48WbSY9myZSaVwHnnnSezZs2q9kS4Od+9e7cMHDjQeLxi8gber4hkgZ1zzjnyu9/9rsrxZ5xxhnz66afmvP/4xz/kL3/5i22fO++8U8PiFsuXX34pt99+u7z66qsydOhQ47m7TaNYlixZYtIb7N2716Q/sB3YAhcQWXAyg4iEhyuGAVx7/bzgUVvL3FdkhJiavEuRpx+GfPs1GTxVfUJqF7Hjod6tlUWnms5lbcNg/KUX/inf/O87efX1N+Se3/9R5s356aTer9bxp+MZQlCHVrXzZMOxPTW1mrPmr5FKXVUMauyGW49oFWXwcMUgcnmgoMMpGri2D63+PcHEin2RQJwOP4DWxLJ1etYVskjwuTkQQNQynE0wRujSpYtJBbZ1qxbGVCEFwskf/vAH28DPElM+/PBD45wyYcIEgXAEJ4iVK1ea2j14vUJzLdelQTwYOXKk/PnPf5ann35aXnvtNfnuu+/MuRH5DCcaiDkYnGPMYjmtQMhCvY1W6kGPCCg4tzzwwANmHX5L0dfHHnvMPHDct99+a4Qv9P+IesdOnjxZHn744bq8FLZFAiRAAiRAAi2OQN/j98UQhzZv3SZt27WpEoHaEFCQDQXCEAwTYNU5GsIBBc40loXqcc3ZArQeEYQy2PBhQ0wkcHXXC4Y0EiABEmiJBHA/OWb0SJk1+1dNqb3DPMDBW0tCDBuqqY/VIPggqxSEI0QA4QFDarnBgwaaZTgqDB0yWMuGrJa16zaYdfgHabtR07UhDL+JP/8y21ZTCJFCEIWOarr1xiwONTlhaNSoUWZy48EHH9QQshz55JNPzPsNUQgPeMMma9oORPds377dPDBBOWXKFHnxxRcFHq41CUNIuwKB57777jOpV1atWmXax8TJQw89JIgWgidaZTv33HONhywmUZByzl4Ywv5ffPGF8R5GKrnNmzebh9UGUq5gf6RkojVeAogQOrQkW9ZrVFA/TbeCnPz2lrwlz0QLefq7a82f2ok+9u3V1/JULcQ2ePBALcL7a6MSherretkuCZAACdQlAYgmN910k9aqK5a33nrLjDPQPm7yEXGMqCFEs1oG8RRiEASWZ599Vuvj7TcPpDRFejeIKEhDd+ONN1qH1NkznF0Q0QNnl6eeekqQ/u2bb74x7cN7GFFFd911ly26yTpxbGysiWLG2AXjprPPPtsIQ9iONpFCDulI4Qjz22+/mcNw/ddcc405D46nkQAJkAAJkAAJnBoBe3EIacEnn3N2g4tDsbEdbDV2Nm7cXK0whAwfmVnZBgAm/JDKzjJPTSlpWVFRsbXo1LO92xuilhqLYXx0NCnZdKc8erpfY+ka+0ECJEACjYoA6ghdPfVK2aPBEcnJKRoRpOUYdB3m3S2DqBKuqbJRvw212WJjO+rvX6yp9WbtA5EIvy1798RJVna2aaOT7offnNNtlUUhq6wCIoUauzjkpp4cTv+aQnDJNrDLU6CcbtD250M/ILAgNQsKKltpWax9EFG0ZcsWE4KGCRH8OLtqSAsHYQg/8ii27Ewb8JhF2hXUFqouzBgc4aULwQpRTVb6Flf7x/1PLwHkpV/67GHJ3Fdo6vsEx3hrChVPKS06JrlHi6UgrURQ/HjYfdHSZnjTy6F8emnybCRAAiTgPAFEt6SUucmG4vLpgI6B/jI55tRTojjfAzHjAYgsqBmIKBxEA8NBBRHFiP5B6rSafs8x3EI9mV27dpl6hfj9P50eo9b5ERUNIQqiEBxSqhurQPhCqlukm0NqXavGoz0ztAOhC/Ubcf2n83rs+8FlEiABEiABEqgPAvtz8mT2wSTTNMYe/TxKzHLbtuX1q+rjnI7a3KLp1hE5hDSVDS0OITr68y++0uiY8vTfmLxDkW/78QTGSjNm/ix5+eWRRaj9NWTwINulof7Dhx9/Zl57aRaHW266UTOolItFOTm5Mv3HGZKRmWW2D+zfz9QIsw4uLCyS9z74yLzEqPDWW26sUp8vT+sfffjRp2YfpAK96cbrzLL1z28LF2n94R3m5QTte69eJ9Lf1rQNB/w8a7ZJo43lCy8416Q4wvKOnbs0fdBvWNTJTX+54fprNU15VYdiswP/IQESIAESaDYEqhOFrAvEPbMlDkVpavbGllbuhKuG1eMm8gxRxSrs7KjLmOw41QgcqJVIReeKIW3LyQx1h1C8mda0CCDn/tkvdJCkzfmSuDpH8rTOD2oFIR9/1CB/Ce7gI50mhZj6Q03rythbEiABEiABZwlAYCnVmmYwRP3A+cQZw4QJ0rMhMrkhzDo/UsE5Y15aQwxp8vCozhDCD+ccGgmQAAmQAAmQQP0RaEyRQ4g4Hj58mMxfsNBc8PYdOyU1VWuLaiQRRJhErQe8d2+cFKmDCSwoMEAGqLhjb4g6tmoVFReXyPfTf5R+fXqrkJSvgs12U5PBfn/7ZR+tg+rv52tEJ3g4L122XAYNHKCR3CWmUDnGO0g3hAfay1UR6og6DaP+RH0aUmtv3brdnCtXRbOZP82SEcOGqmNNa3UcLpTExETZruLR+edOtolg9dkftk0CJEACJFD/BE4mCqEHuGduzJFDTVYYqv+3l2cggaoEUCw5aqC/eVTdyjUkQAIkQAIkQAIkQAIkQAIkQAIkULcEGpM4hCihUo0cWrJshXGWSdKMKHhUtqjICDln0kStF1Fx2gniTZ8+vbTg+HpzCFIJzddaEjB3rZM6auRwWb6iPKW/WVnpn379+moh8jVm7Y6duzVaZ7dZRmoiCDEwpBfaowIVHHqmfTddbrz+mio1UM2OdfQPrmnC+LPkxxk/mVpDhw4d1hpLh6u0vlFLD6AuBo0ESIAESKBpE3BGFLKusDGLQ4xttd4lPpMACZAACZAACZAACZAACZAACZAACZBAIyQAcejMsWPkWFmZoOZQ3L59DdZL9OXKyy+R9u3aVomACQkOliFa++Hyyy7RNLtBDvuI1HI9unWtsK1VaKicf965pri4t0YuV2eDtO1+fXtX2YwUdpb11QgkKz0d1qVqjYr6tlatQuWaq6eYuktelcQwRDoNHjRAt1Xtd333i+2TAAmQAAnULQFXRCHrzJY4hHRyR5OSTHo5pJlraGuyNYYaGhzPTwIkQAIkQAIkcHoINKYaQ6gT+Mgjj8jdd999ei6eZyEBEiABEiABEmgQAo2lxlDli7evOXTu5EmCYtsNaaaOYWamoHZQeFiYSZvjbH+Q7i1dRZtQFYVQm8cVQ72htLQ0KTtWJiHBIZri90ThcrRToBNuqamp4u3lrXWjWzlVM9qV89e0L5hkKhPUTEINxqAg1iCuiRe3kQAJkEBTIXBEU6b+oLXwkF5+zOhRMnBAf5e6bl9zKDoq0jhRIOq0oaxiTG9D9YLnJQESIAESIAESIIFGTCBYvV+HDRsmGRkZ0r59+0bcU3aNBEiABEiABEigOROwTyu3cuWqBheGMKGFaB88XDVTD6idn6uHmf0RhdOmTXS1x/pqXYd2bdtWu70+N4AJxC48aCRAAiRAAs2HAKJ9ykrLaiUKgYIVOTRj5s+SkpIqRUVFLjlU1DVJCkN1TZTtkQAJkAAJkAAJNDsCPXv2lDfffLPZXRcviARIgARIgARIoOkRgDgUGBQknh4eTa/z7DEJkAAJkAAJNFEC/bXOXdcunTXKtWKUqiuXA3EI6VYLCgoaVBRCnykMufLOcV8SIAESIAESIAESIAESIAESIAESIAESaGACsR07NHAPeHoSIAESIAESaFkEEBF6KqKQRcvd3V38/V1LoWodW5fP7nXZGNsiARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARJovAQoDDXe94Y9IwESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIIE6JUBhqE5xsjESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESaLwEKAw13veGPSMBEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiCBOiVAYahOcbIxEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEmi8BCgMNd73hj0jARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIggTolQGGoTnGyMRIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARJovAQoDDXe94Y9IwESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIIE6JUBhqE5xsjESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESaLwEPBtv19gzEiABEiABEiABEjhBINz9mAz0OiZSnCNxcTknNnCJBEiABEiABEiABOqBwEAvN9lQ7FYPLbNJEiABEiABEiABEmhYArUShuLi4hq21zw7CZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZCAywRqJQy5fBYeQAIkQAIkQAIkQAKnSCClzE3mFrpJx0B/mRwTeYqt8XASIAESIAESIAESqJ7A/pw82XAwqfoduIUESIAESIAESIAEmjCBWglDnTt3bsKXzK6TAAmQAAmQAAk0JQKMVG5K7xb7SgIkQAIkQAIkQAIkQAIkQAIkQAIk0NgJuDf2DrJ/JEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACdUOAwlDdcGQrJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJNDoCVAYavRvETtIAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAnVDgMJQ3XBkKyRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiTQ6AlQGGr0bxE7SAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAJ1Q4DCUN1wZCskQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIk0OgJUBhq9G8RO0gCJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACdUOAwlDdcGQrJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJNDoCVAYavRvETtIAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAnVDgMJQ3XBkKyRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiTQ6Al4NvoesoMkQAIkQAIkQAIk0EwIlJaWSkpKiqxdu17mzp0r/v7+8uCDf5RWrVqZKywsLJStW7fJ9z9Mly1btkhOTo4MGjRQrpo6RQYMGCCenhy6NZOPAi+DBEiABEiABEiABEiABEiABEiABBqMQIufXTh27JgUl5RImU7U+Pj4iJubm8M3o6ysTEp0P5i3t7fDfbiSBEiABEiABEiABGoikJubKytWrpJv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AZg7Z9bgHfQgGllwcGsOqMLCImRkZEouzqo+HZ32p/1q/2pBQUF92j87IwESIAESaEuAHkNtefAVCZAACZAACZAACRgCgQEBWH7DjTh65Bj+z//8D15fuw6JiWPgMGoU0tIvIj09HeMkhvyKW26Gu4R5oZEACZAACZAACZAACQxeArm5eWi5PLxRcj+XOCYBixYugKOj4+Ad9CAamYYcDA0NRZ54XZWXl5tHfw0vNDSkxyEO+2ss7JcESIAEhisBCkPD9cryvEiABEiABEiABK6JgE4YjBfh579++J9Yu+4NvPHGG9i2fbvpU8PG3Xbbajzx+GNISkq6puOwMQmQAAmQAAmQAAkMZwKLFi3EgvnzzSk6Og5c4Jro6Cjcv+YeaLhgf3+/fs2TM1yvZ1BQINzd3SScXImEWq5BfX1Dn52qi4sz3NzcobmiPD09+6xfdkQCJEACJGCfAIUh+1xYSgIkQAIkQAIkQAKGgK5Y/PKXnsEXPv8USkpKoHmF/P39oYmXVTyikQAJkAAJkAAJkAAJdE7A0cEB+hhoc5AxBAUGDvQwhvzxVbShcDPkLyNPgARIgARAYYhvAhIgARIgARIgARK4CgEVgDQpcVhY2FVqcjcJkAAJkAAJkAAJkAAJkAAJkAAJkAAJDG4CA79kY3Dz4ehIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIYNgQoDA0bC4lT4QESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAEuiZAYahrPtxLAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAsOGAIWhYXMpeSIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIk0DUBCkNd8+FeEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEhg2BCgMDZtLyRMhARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgga4JOHW9m3ubm5uxb/9+bNr0ESoqKjFmzGg8+MD98PX1JRwSIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESGFIE6DF0lcv17ob38M1vfgtZmVnw8fHGu+9uwP/89OdXacXdJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJDD4CNBjqItrUlZWju/927/j0YcfFnHoOTg4OKCktBROTsTWBTbuIgESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESGKQEqHB0cWH+8corcHJ0wuOPf86IQlrV38+vixbcRQIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAKDlwCFoS6uzeHDhzFp4kQ4Ojpg9+49qG+oR1xsHKJjouEwalQXLbmLBEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABAYfAQpDXVyTjIwshIQE49e//i0qKiuQmZkNV1cXfO2rX8GMGdPbtNy9ezcqKyvblFleNDU1mc2amhoUFhZaivncTQIWfsq3vr6+m61YrT2BhoYGU8T3YHsy3Xvd3NxMft1D1Wkty99yVVXVgPwt19XVdTo27iABEiABEiABEiABEiABEiABEiABEiABEiCBkUKAwlAnV7qlpcWIQaWlJbj33nswcUKyCD9V+I/v/wA/+e//g3VrX2vT8vTp0ygoKGhT1v6Fihrl5eXti/m6mwRqa2uhD9q1EeB7kPyujcC1t1aRXB8DYZorjkYCJEACJEACJEACJEACJEACJEACJEACJEACI5kAhaFOrv4oCRUXEhyMuLg4rFp5q4STczQ1ly1dip//8pcyqVkLd3c3a+uHH34YKibZM12l/uKLL8LHx8f0Z68OyzonoGJQbm4uAgICDMPOa3JPVwSUobLU9zSt5wQyMjKgf+Ex0dE9b8wWhoDlbzkwMBDe3t7XnYqK9wMlSF33k+UBSYAESIAESIAESIAESIAESIAESIAESIAESKATAhSGOgGjxYljEnHy1Mk2gk+wiEWODo5obNSwXFeEIVdX1y56at2lYhNXq18VU4cKFmb6bNnuUIkF3SZAht1G1aGiZhYjvw5Yul2gn4FqA/VZaDl+twfMiiRAAiRAAiRAAiRAAiRAAiRAAoaAJTw9cZAACZDA9STg7Ox8PQ83oo7FmDpdXO41a+5FRkYmPtq82YSAy8/Px85duzBlypQBWe3exVC5iwRIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgASuSoAeQ10gmj59Gp584nH88Y9/ws6du1FRUQ4Vh55//htdtOIuEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEhicBCgMdXFdNGTUF7/4eUyeMgkXL16Ck+QZmjhpIiZPmtRFK+4iARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIggcFJgMLQVa6Lu7s7li1diqamJlPTyYnIroKMu0mABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABAYpAaoc3bgwmrCcglA3QLEKCZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZDAoCbgMKhHx8GRAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAn0GQEKQ32Gkh2RAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQwOAmQGFocF8fjo4ESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAE+owAhaE+Q8mOSIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESGBwE6AwNLivD0dHAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAn1GgMJQn6FkRyRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiQwuAlQGBrc14ejIwESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIIE+I+DUZz2xIxIgARIgARIgARIggT4j0NzcjIqKShQUFMDNzRVhYWFwcuKtW58BZkckQAIkQAIkQAIkQAIkQAIkQAIkMEIJ0GNohF54njYJkAAJkAAJkMDgJlBRUYHNmzfjP77/A7y+dp2IRBWDe8AcHQmQAAmQAAmQAAmQAAmQAAmQAAmQwJAgwGWnQ+IycZAkQAIkQAIkQAIjiUBjYyNSU1Px4aaPkJmZhcTEMWhqahpJCHiuJEACJEACJEACJEACJDDgBGpr6/D+xg86HcecObMQFRnZYf/uPfvQ0tKCWTNnmH37DxzEqFGjMG/u7A51r1Zw7P+zdx/gcV3ngfdfYDAVvTcWgL03sVMkJVnNkizJjiXHJYos2/LGibNer+PYcZyN7c9Z50m8jr2bxLHTY8exZMmSVaguqrCKvYkNBEACRCF6H9TvvBecwQCYIQpnQGDwP88znDvnnnvuPb87AMl55z2noka8XT2yMj9THDa+4x/MazzeR48el/NFRcG6k/j4eLn7rjuC7qMSgWgRIDAULXeScSCAAAIIIIBA1AhU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JEACJEACJEACJEACJEACJEACJEACJEACJEAC3kaANYa87Yhyf0iABEiABEiABEiABEiABEiABEiABEjAwwj07t1LevboYXrt7884Zg87fOwuCZAACZCAhxGgY8jDDhi7SwIkQAIkQAIkQAIkQAIkQAIkQAIkQALeRsDfz0/wopEACZAACZAACbieAK+4rmfMFkiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEjALQjQMeQWh4GdIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAHXE6BjyPWM2QIJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJuAUBOobc4jCwEyRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiTgegIBrm+CLZAACZAACZAACZCA8wicSM+Qj/Yfd94GuSUSIAESIAESIAESIAESIAESIAESIAES8CECt+QYiouL8yFE3FUSIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAES8A4ClJLzjuPIvSABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiCBYglU+EGt2KW4AAmQAAmQAAmQAAmQAAmQAAmQAAmQAAn4KIH4+Hiz5+Hh4T5KgLvt6wSys7N9HQH3nwRI4DYQqFix4m1o1TeavCUpOd9Aw70kARIgARIgARIgARIgARIgARIgARIgARIgARLg4Cx/AyRAAiTgXQSYMeRdx5N7QwIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIOCbDGkEM0nEECJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEAC3kWAjiHvOp7cGxIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARJwSICOIYdoOIMESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAEvIsAHUPedTy5NyRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiTgkAAdQw7RcAYJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJeBcBOoa863hyb0iABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEjAIQE6hhyi4QwSIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAES8C4CdAx51/Hk3pAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZCAQwJ0DDlEwxkkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIk4F0E6BjyruPJvSEBEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABhwToGHKIhjNIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIwLsI0DHkXceTe0MCJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACDgnQMeQQDWeQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQgHcRoGPIu44n94YESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAEHBKgY8ghGs4gARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgAe8i8P/kFu9JFZ12fgAAAABJRU5ErkJggg==" + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" } - }, - "cell_type": "markdown", - "id": "0cf240cf", - "metadata": {}, - "source": [ - "![image.png](attachment:image.png)" - ] - }, - { - "cell_type": "markdown", - "id": "4b9fc573", - "metadata": {}, - "source": [ - "To share your creation, you can click \"open in new tab\" in the right-hand drawer, and then click \"Publish\" to save it to wandb." - ] - }, - { - "cell_type": "markdown", - "id": "9a4092e3", - "metadata": {}, - "source": [ - "### Bonus: Weaving everything together" - ] - }, - { - "cell_type": "markdown", - "id": "4f211f9e", - "metadata": {}, - "source": [ - "Here's a **Weave Board** for all these panels, defined in code. We're actively working on additional examples and tutorials to explain these concepts in more detail. To inspire some initial exploration, you can:\n", - "* **open the panel in a new window** from the right-hand drawer on hover, to view a full-page Weave Board\n", - "* **see the details of selected data** by clicking the mouse button in the bottom right of the PanelPlot, then clicking and dragging to select a subregion of points\n", - "* **customize the Board** by adding, changing, and interconnecting panels\n", - "* **save and share your work** by renaming the Board and publishing it to W&B" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e194b3ce", - "metadata": {}, - "outputs": [], - "source": [ - "weave.legacy.panels.Board(\n", - " vars={\n", - " 'data': data,\n", - " 'limit': 1005,\n", - " 'limited_data': lambda data, limit: data.limit(limit),\n", - " 'embeddings': lambda limited_data: openai.openai_embed(limited_data['name'], {\"model\": \"text-embedding-ada-002\"}),\n", - " 'clusterable_projection': lambda embeddings: umap.umap_project(\n", - " embeddings, {\n", - " 'n_neighbors': 30,\n", - " 'min_dist': 0,\n", - " 'n_components': 2,\n", - " }\n", - " ),\n", - " 'clusters': lambda clusterable_projection: hdbscan.hdbscan_cluster(clusterable_projection, {\n", - " 'min_samples': 10,\n", - " 'min_cluster_size': 50\n", - " }),\n", - " 'projection': lambda embeddings: umap.umap_project(embeddings, {})\n", - " },\n", - " panels=[\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda limited_data, projection, clusters: weave.legacy.panels.Plot(\n", - " limited_data,\n", - " x=lambda row, index: projection[index][0],\n", - " y=lambda row, index: projection[index][1],\n", - " label=lambda row, index: clusters[index],\n", - " ),\n", - " id='projection_plot',\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=24, h=12)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda projection_plot: projection_plot.selected_data(),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=24, h=12)\n", - " )\n", - " ]\n", - ")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/AutoBoard.ipynb b/weave/legacy/examples/experimental/AutoBoard.ipynb index 2a75baac7b2..264a035b27e 100644 --- a/weave/legacy/examples/experimental/AutoBoard.ipynb +++ b/weave/legacy/examples/experimental/AutoBoard.ipynb @@ -1,91 +1,91 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "315969ff", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "from weave.legacy.scripts import syndata\n", - "from weave.legacy.scripts import syndata_mon\n", - "from weave.legacy.panels_py import panel_autoboard" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "315969ff", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "from weave.legacy.scripts import syndata\n", + "from weave.legacy.scripts import syndata_mon\n", + "from weave.legacy.weave.panels_py import panel_autoboard" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a6b988de", + "metadata": {}, + "outputs": [], + "source": [ + "predictions = weave.save(syndata_mon.random_predictions(10), 'predictions')\n", + "#predictions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "64aef598", + "metadata": {}, + "outputs": [], + "source": [ + "panel_autoboard.auto_panels(predictions)\n", + "#weave.legacy.weave.ops.project('shawn', 'fasion-sweep').runs().history().concat()['_step'].type" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "78a3a155", + "metadata": {}, + "outputs": [], + "source": [ + "metrics = weave.save(syndata.random_metrics(10000, 10), 'syndata')\n", + "#metrics" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "77e03fd6", + "metadata": {}, + "outputs": [], + "source": [ + "#panel_autoboard.auto_panels(metrics)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8b417fd2", + "metadata": {}, + "outputs": [], + "source": [ + "#panel_autoboard.auto_panels(weave.legacy.weave.ops.project('shawn', 'oai-api5').run('test4').history2())" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "a6b988de", - "metadata": {}, - "outputs": [], - "source": [ - "predictions = weave.save(syndata_mon.random_predictions(10), 'predictions')\n", - "#predictions" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "64aef598", - "metadata": {}, - "outputs": [], - "source": [ - "panel_autoboard.auto_panels(predictions)\n", - "#weave.legacy.ops.project('shawn', 'fasion-sweep').runs().history().concat()['_step'].type" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "78a3a155", - "metadata": {}, - "outputs": [], - "source": [ - "metrics = weave.save(syndata.random_metrics(10000, 10), 'syndata')\n", - "#metrics" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "77e03fd6", - "metadata": {}, - "outputs": [], - "source": [ - "#panel_autoboard.auto_panels(metrics)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8b417fd2", - "metadata": {}, - "outputs": [], - "source": [ - "#panel_autoboard.auto_panels(weave.legacy.ops.project('shawn', 'oai-api5').run('test4').history2())" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/Monitor.ipynb b/weave/legacy/examples/experimental/Monitor.ipynb index fee2766ae24..4f6ac6046aa 100644 --- a/weave/legacy/examples/experimental/Monitor.ipynb +++ b/weave/legacy/examples/experimental/Monitor.ipynb @@ -1,219 +1,219 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "f7512dfa", - "metadata": {}, - "source": [ - "# Model monitoring dashboard example\n", - "\n", - "This notebook currently requires the plotly library to be installed.\n" - ] + "cells": [ + { + "cell_type": "markdown", + "id": "f7512dfa", + "metadata": {}, + "source": [ + "# Model monitoring dashboard example\n", + "\n", + "This notebook currently requires the plotly library to be installed.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "039f298a", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import weave\n", + "# Weave package now defaults to eager mode, but lazy mode required for this example notebook for now.\n", + "weave.use_lazy_execution()\n", + "from weave.legacy.scripts import syndata_mon\n", + "from weave.legacy.weave.arrow.list_ import dataframe_to_arrow\n", + "from weave.legacy.weave.ecosystem import wandb" + ] + }, + { + "cell_type": "markdown", + "id": "8519889f", + "metadata": {}, + "source": [ + "## Create synthetic data\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "29f45c3d", + "metadata": {}, + "outputs": [], + "source": [ + "data = syndata_mon.random_predictions(10)\n", + "timestamps = data._arrow_data.field('timestamp')\n", + "start_date = timestamps[0].as_py().to_pydatetime()\n", + "end_date = timestamps[-1].as_py().to_pydatetime()\n", + "predictions = weave.save(data, 'predictions')" + ] + }, + { + "cell_type": "markdown", + "id": "cdd59e39", + "metadata": {}, + "source": [ + "## Create a Weave Board for the data\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8049b6dd", + "metadata": {}, + "outputs": [], + "source": [ + "# Create a dashboard for our data\n", + "board = weave.legacy.weave.panels.Board(\n", + " vars={\n", + " 'x_max': weave.legacy.weave.ops.date_parse(str(end_date)),\n", + " 'x_min': lambda x_max: x_max - weave.legacy.weave.ops.days(5),\n", + " 'predictions_query': weave.legacy.weave.panels.Query(\n", + " predictions,\n", + " conditions=[\n", + " lambda query_input: weave.legacy.weave.panels.QueryCondition(\n", + " expression=query_input['model_version'],\n", + " editor=weave.legacy.weave.panels.SelectEditor(\n", + " choices=query_input['model_version']\n", + " )\n", + " ),\n", + " lambda query_input: weave.legacy.weave.panels.QueryCondition(\n", + " expression=query_input['username'],\n", + " editor=weave.legacy.weave.panels.SelectEditor(\n", + " choices=query_input['username']\n", + " )\n", + " ),\n", + " ]),\n", + " 'predictions': lambda predictions_query: predictions_query.selected()\n", + " },\n", + " panels=[\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", + " predictions,\n", + " x=lambda item: item[\"timestamp\"],\n", + " label=lambda item: item[\"model_version\"],\n", + " agg=lambda preds: preds.count(),\n", + " min_x=x_min,\n", + " max_x=x_max,\n", + " mark=\"bar\",\n", + " axis_labels={\"y\": \"num_preds\"},\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=12, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", + " predictions,\n", + " x=lambda item: item[\"timestamp\"],\n", + " label=lambda item: item[\"username\"],\n", + " agg=lambda preds: preds.count(),\n", + " min_x=x_min,\n", + " max_x=x_max,\n", + " mark=\"bar\",\n", + " axis_labels={\"y\": \"num_preds\"},\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=12, y=0, w=12, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", + " predictions,\n", + " x=lambda item: item[\"timestamp\"],\n", + " #label=lambda item: item[\"model_version\"],\n", + " agg=lambda preds: preds[\"api_cost\"].sum(),\n", + " min_x=x_min,\n", + " max_x=x_max,\n", + " mark=\"line\",\n", + " axis_labels={\"y\": \"api_cost\"},\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=6, w=8, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", + " predictions,\n", + " x=lambda item: item[\"timestamp\"],\n", + " #label=lambda item: item[\"model_version\"],\n", + " agg=lambda preds: preds[\"prompt_tokens\"].sum() + preds['completion_tokens'].sum(),\n", + " min_x=x_min,\n", + " max_x=x_max,\n", + " mark=\"line\",\n", + " axis_labels={\"y\": \"total_tokens\"},\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=8, y=6, w=8, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", + " predictions,\n", + " x=lambda item: item[\"timestamp\"],\n", + " #label=lambda item: item[\"model_version\"],\n", + " agg=lambda preds: preds[\"latency\"].avg(),\n", + " min_x=x_min,\n", + " max_x=x_max,\n", + " mark=\"line\",\n", + " axis_labels={\"y\": \"avg_latency\"},\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=16, y=6, w=8, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, x_min, x_max: wandb.Distribution(\n", + " predictions,\n", + " value_fn=lambda pred: pred['api_cost'],\n", + " bin_size=0.2\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=12, w=8, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, x_min, x_max: wandb.Distribution(\n", + " predictions,\n", + " value_fn=lambda pred: pred['prompt_tokens'] + pred['completion_tokens'],\n", + " bin_size=25\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=8, y=12, w=8, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, x_min, x_max: wandb.Distribution(\n", + " predictions,\n", + " value_fn=lambda pred: pred['latency'],\n", + " bin_size=0.05\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=16, y=12, w=8, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions: predictions,\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=18, w=24, h=12)\n", + " )\n", + " ]\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1d8bafc9", + "metadata": {}, + "outputs": [], + "source": [ + "board" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "039f298a", - "metadata": {}, - "outputs": [], - "source": [ - "import pandas as pd\n", - "import weave\n", - "# Weave package now defaults to eager mode, but lazy mode required for this example notebook for now.\n", - "weave.use_lazy_execution()\n", - "from weave.legacy.scripts import syndata_mon\n", - "from weave.legacy.arrow.list_ import dataframe_to_arrow\n", - "from weave.legacy.ecosystem import wandb" - ] - }, - { - "cell_type": "markdown", - "id": "8519889f", - "metadata": {}, - "source": [ - "## Create synthetic data\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "29f45c3d", - "metadata": {}, - "outputs": [], - "source": [ - "data = syndata_mon.random_predictions(10)\n", - "timestamps = data._arrow_data.field('timestamp')\n", - "start_date = timestamps[0].as_py().to_pydatetime()\n", - "end_date = timestamps[-1].as_py().to_pydatetime()\n", - "predictions = weave.save(data, 'predictions')" - ] - }, - { - "cell_type": "markdown", - "id": "cdd59e39", - "metadata": {}, - "source": [ - "## Create a Weave Board for the data\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8049b6dd", - "metadata": {}, - "outputs": [], - "source": [ - "# Create a dashboard for our data\n", - "board = weave.legacy.panels.Board(\n", - " vars={\n", - " 'x_max': weave.legacy.ops.date_parse(str(end_date)),\n", - " 'x_min': lambda x_max: x_max - weave.legacy.ops.days(5),\n", - " 'predictions_query': weave.legacy.panels.Query(\n", - " predictions,\n", - " conditions=[\n", - " lambda query_input: weave.legacy.panels.QueryCondition(\n", - " expression=query_input['model_version'],\n", - " editor=weave.legacy.panels.SelectEditor(\n", - " choices=query_input['model_version']\n", - " )\n", - " ),\n", - " lambda query_input: weave.legacy.panels.QueryCondition(\n", - " expression=query_input['username'],\n", - " editor=weave.legacy.panels.SelectEditor(\n", - " choices=query_input['username']\n", - " )\n", - " ),\n", - " ]),\n", - " 'predictions': lambda predictions_query: predictions_query.selected()\n", - " },\n", - " panels=[\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", - " predictions,\n", - " x=lambda item: item[\"timestamp\"],\n", - " label=lambda item: item[\"model_version\"],\n", - " agg=lambda preds: preds.count(),\n", - " min_x=x_min,\n", - " max_x=x_max,\n", - " mark=\"bar\",\n", - " axis_labels={\"y\": \"num_preds\"},\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=12, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", - " predictions,\n", - " x=lambda item: item[\"timestamp\"],\n", - " label=lambda item: item[\"username\"],\n", - " agg=lambda preds: preds.count(),\n", - " min_x=x_min,\n", - " max_x=x_max,\n", - " mark=\"bar\",\n", - " axis_labels={\"y\": \"num_preds\"},\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=12, y=0, w=12, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", - " predictions,\n", - " x=lambda item: item[\"timestamp\"],\n", - " #label=lambda item: item[\"model_version\"],\n", - " agg=lambda preds: preds[\"api_cost\"].sum(),\n", - " min_x=x_min,\n", - " max_x=x_max,\n", - " mark=\"line\",\n", - " axis_labels={\"y\": \"api_cost\"},\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=6, w=8, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", - " predictions,\n", - " x=lambda item: item[\"timestamp\"],\n", - " #label=lambda item: item[\"model_version\"],\n", - " agg=lambda preds: preds[\"prompt_tokens\"].sum() + preds['completion_tokens'].sum(),\n", - " min_x=x_min,\n", - " max_x=x_max,\n", - " mark=\"line\",\n", - " axis_labels={\"y\": \"total_tokens\"},\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=8, y=6, w=8, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", - " predictions,\n", - " x=lambda item: item[\"timestamp\"],\n", - " #label=lambda item: item[\"model_version\"],\n", - " agg=lambda preds: preds[\"latency\"].avg(),\n", - " min_x=x_min,\n", - " max_x=x_max,\n", - " mark=\"line\",\n", - " axis_labels={\"y\": \"avg_latency\"},\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=16, y=6, w=8, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, x_min, x_max: wandb.Distribution(\n", - " predictions,\n", - " value_fn=lambda pred: pred['api_cost'],\n", - " bin_size=0.2\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=12, w=8, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, x_min, x_max: wandb.Distribution(\n", - " predictions,\n", - " value_fn=lambda pred: pred['prompt_tokens'] + pred['completion_tokens'],\n", - " bin_size=25\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=8, y=12, w=8, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, x_min, x_max: wandb.Distribution(\n", - " predictions,\n", - " value_fn=lambda pred: pred['latency'],\n", - " bin_size=0.05\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=16, y=12, w=8, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions: predictions,\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=18, w=24, h=12)\n", - " )\n", - " ]\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1d8bafc9", - "metadata": {}, - "outputs": [], - "source": [ - "board" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/MonitorPanelPlot.ipynb b/weave/legacy/examples/experimental/MonitorPanelPlot.ipynb index 647bc0de53b..31b6a8de189 100644 --- a/weave/legacy/examples/experimental/MonitorPanelPlot.ipynb +++ b/weave/legacy/examples/experimental/MonitorPanelPlot.ipynb @@ -1,252 +1,252 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "f7512dfa", - "metadata": {}, - "source": [ - "# Model monitoring dashboard example\n", - "\n", - "This notebook currently requires the plotly library to be installed.\n" - ] + "cells": [ + { + "cell_type": "markdown", + "id": "f7512dfa", + "metadata": {}, + "source": [ + "# Model monitoring dashboard example\n", + "\n", + "This notebook currently requires the plotly library to be installed.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3e7d3247", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "import weave.legacy.weave.panels\n", + "weave.use_lazy_execution()\n", + "from weave.legacy.scripts import syndata_mon" + ] + }, + { + "cell_type": "markdown", + "id": "8519889f", + "metadata": {}, + "source": [ + "## Create synthetic data\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d6a3a6f1", + "metadata": {}, + "outputs": [], + "source": [ + "data = syndata_mon.random_predictions(10)\n", + "timestamps = data._arrow_data.field('timestamp')\n", + "start_date = timestamps[0].as_py().to_pydatetime()\n", + "end_date = timestamps[-1].as_py().to_pydatetime()\n", + "predictions = weave.save(data, 'predictions')" + ] + }, + { + "cell_type": "markdown", + "id": "cdd59e39", + "metadata": {}, + "source": [ + "## Create a Weave Board for the data\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "57fc86e0", + "metadata": {}, + "outputs": [], + "source": [ + "# Fetch the data by the latest alias instead of its version hash.\n", + "# TODO: change weave.save to do this automatically\n", + "predictions = weave.legacy.weave.ops.get(\"local-artifact:///predictions:latest/obj\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "25c63bf1-10f4-4a9b-b5f3-01361126bc2c", + "metadata": {}, + "outputs": [], + "source": [ + "# from weave.legacy.weave import context_state\n", + "# context_state._eager_mode.get()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8049b6dd", + "metadata": {}, + "outputs": [], + "source": [ + "# Create a dashboard for our data\n", + "board = weave.legacy.weave.panels.Board(\n", + " vars={\n", + " 'data': predictions,\n", + " 'zoom_range': weave.legacy.weave.ops.make_list(\n", + " a=weave.legacy.weave.ops.date_parse(str(start_date)),\n", + " b=weave.legacy.weave.ops.date_parse(str(end_date))),\n", + " 'data_range': lambda data: weave.legacy.weave.ops.make_list(\n", + " a=data['timestamp'].min(),\n", + " b=data['timestamp'].max()\n", + " ),\n", + " 'bin_range': lambda zoom_range, data_range: zoom_range.coalesce(data_range),\n", + " 'predictions_query': weave.legacy.weave.panels.Query(\n", + " predictions,\n", + " conditions=[\n", + " lambda query_input: weave.legacy.weave.panels.QueryCondition(\n", + " expression=query_input['model_version'],\n", + " editor=weave.legacy.weave.panels.SelectEditor(\n", + " choices=query_input['model_version']\n", + " )\n", + " ),\n", + " lambda query_input: weave.legacy.weave.panels.QueryCondition(\n", + " expression=query_input['username'],\n", + " editor=weave.legacy.weave.panels.SelectEditor(\n", + " choices=query_input['username']\n", + " )\n", + " ),\n", + " ]),\n", + " 'predictions': lambda predictions_query: predictions_query.selected()\n", + " },\n", + " panels=[\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, zoom_range, bin_range: weave.legacy.weave.panels.Plot(\n", + " predictions,\n", + " x=lambda item: item[\"timestamp\"].bin(\n", + " weave.legacy.weave.ops.timestamp_bins_nice(bin_range, 30)),\n", + " label=lambda item: item[\"model_version\"],\n", + " y=lambda preds: preds.count(),\n", + " groupby_dims=['x', 'label'],\n", + " domain_x=zoom_range,\n", + " mark=\"bar\",\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=12, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, zoom_range, bin_range: weave.legacy.weave.panels.Plot(\n", + " predictions,\n", + " x=lambda item: item[\"timestamp\"].bin(\n", + " weave.legacy.weave.ops.timestamp_bins_nice(bin_range, 100)),\n", + " label=lambda item: item[\"username\"],\n", + " y=lambda preds: preds.count(),\n", + " groupby_dims=['x', 'label'],\n", + " domain_x=zoom_range,\n", + " mark=\"bar\",\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=12, y=0, w=12, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, zoom_range, bin_range: weave.legacy.weave.panels.Plot(\n", + " predictions,\n", + " x=lambda item: item[\"timestamp\"].bin(\n", + " weave.legacy.weave.ops.timestamp_bins_nice(bin_range, 100))['start'],\n", + " y=lambda preds: preds[\"api_cost\"].sum(),\n", + " groupby_dims=['x'],\n", + " domain_x=zoom_range,\n", + " mark=\"line\",\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=6, w=8, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, zoom_range, bin_range: weave.legacy.weave.panels.Plot(\n", + " predictions,\n", + " x=lambda item: item[\"timestamp\"].bin(\n", + " weave.legacy.weave.ops.timestamp_bins_nice(bin_range, 100))['start'],\n", + " y=lambda preds: preds[\"prompt_tokens\"].sum() + preds['completion_tokens'].sum(),\n", + " groupby_dims=['x'],\n", + " domain_x=zoom_range,\n", + " mark=\"line\",\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=8, y=6, w=8, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, zoom_range, bin_range: weave.legacy.weave.panels.Plot(\n", + " predictions,\n", + " x=lambda item: item[\"timestamp\"].bin(\n", + " weave.legacy.weave.ops.timestamp_bins_nice(bin_range, 100))['start'],\n", + " y=lambda preds: preds[\"latency\"].avg(),\n", + " groupby_dims=['x'],\n", + " domain_x=zoom_range,\n", + " mark=\"line\",\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=16, y=6, w=8, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions: weave.legacy.weave.panels.Plot(\n", + " predictions,\n", + " x=lambda item: item[\"api_cost\"].bin(\n", + " weave.legacy.weave.ops.numbers_bins_equal(predictions['api_cost'], 50)),\n", + " y=lambda preds: preds.count(),\n", + " groupby_dims=['x'],\n", + " mark=\"bar\",\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=12, w=8, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions: weave.legacy.weave.panels.Plot(\n", + " predictions,\n", + " x=lambda item: (item['prompt_tokens'] + item['completion_tokens']).bin(\n", + " weave.legacy.weave.ops.number_bins_fixed(25)),\n", + " y=lambda preds: preds.count(),\n", + " groupby_dims=['x'],\n", + " mark=\"bar\",\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=8, y=12, w=8, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions: weave.legacy.weave.panels.Plot(\n", + " predictions,\n", + " x=lambda item: item['latency'].bin(\n", + " weave.legacy.weave.ops.numbers_bins_equal(predictions['latency'], 50)),\n", + " y=lambda preds: preds.count(),\n", + " groupby_dims=['x'],\n", + " mark=\"bar\",\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=16, y=12, w=8, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions: predictions,\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=18, w=24, h=12)\n", + " )\n", + " ]\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1d8bafc9", + "metadata": {}, + "outputs": [], + "source": [ + "board" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "3e7d3247", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "import weave.legacy.panels\n", - "weave.use_lazy_execution()\n", - "from weave.legacy.scripts import syndata_mon" - ] - }, - { - "cell_type": "markdown", - "id": "8519889f", - "metadata": {}, - "source": [ - "## Create synthetic data\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d6a3a6f1", - "metadata": {}, - "outputs": [], - "source": [ - "data = syndata_mon.random_predictions(10)\n", - "timestamps = data._arrow_data.field('timestamp')\n", - "start_date = timestamps[0].as_py().to_pydatetime()\n", - "end_date = timestamps[-1].as_py().to_pydatetime()\n", - "predictions = weave.save(data, 'predictions')" - ] - }, - { - "cell_type": "markdown", - "id": "cdd59e39", - "metadata": {}, - "source": [ - "## Create a Weave Board for the data\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "57fc86e0", - "metadata": {}, - "outputs": [], - "source": [ - "# Fetch the data by the latest alias instead of its version hash.\n", - "# TODO: change weave.save to do this automatically\n", - "predictions = weave.legacy.ops.get(\"local-artifact:///predictions:latest/obj\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "25c63bf1-10f4-4a9b-b5f3-01361126bc2c", - "metadata": {}, - "outputs": [], - "source": [ - "# from weave.legacy import context_state\n", - "# context_state._eager_mode.get()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8049b6dd", - "metadata": {}, - "outputs": [], - "source": [ - "# Create a dashboard for our data\n", - "board = weave.legacy.panels.Board(\n", - " vars={\n", - " 'data': predictions,\n", - " 'zoom_range': weave.legacy.ops.make_list(\n", - " a=weave.legacy.ops.date_parse(str(start_date)),\n", - " b=weave.legacy.ops.date_parse(str(end_date))),\n", - " 'data_range': lambda data: weave.legacy.ops.make_list(\n", - " a=data['timestamp'].min(),\n", - " b=data['timestamp'].max()\n", - " ),\n", - " 'bin_range': lambda zoom_range, data_range: zoom_range.coalesce(data_range),\n", - " 'predictions_query': weave.legacy.panels.Query(\n", - " predictions,\n", - " conditions=[\n", - " lambda query_input: weave.legacy.panels.QueryCondition(\n", - " expression=query_input['model_version'],\n", - " editor=weave.legacy.panels.SelectEditor(\n", - " choices=query_input['model_version']\n", - " )\n", - " ),\n", - " lambda query_input: weave.legacy.panels.QueryCondition(\n", - " expression=query_input['username'],\n", - " editor=weave.legacy.panels.SelectEditor(\n", - " choices=query_input['username']\n", - " )\n", - " ),\n", - " ]),\n", - " 'predictions': lambda predictions_query: predictions_query.selected()\n", - " },\n", - " panels=[\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, zoom_range, bin_range: weave.legacy.panels.Plot(\n", - " predictions,\n", - " x=lambda item: item[\"timestamp\"].bin(\n", - " weave.legacy.ops.timestamp_bins_nice(bin_range, 30)),\n", - " label=lambda item: item[\"model_version\"],\n", - " y=lambda preds: preds.count(),\n", - " groupby_dims=['x', 'label'],\n", - " domain_x=zoom_range,\n", - " mark=\"bar\",\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=12, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, zoom_range, bin_range: weave.legacy.panels.Plot(\n", - " predictions,\n", - " x=lambda item: item[\"timestamp\"].bin(\n", - " weave.legacy.ops.timestamp_bins_nice(bin_range, 100)),\n", - " label=lambda item: item[\"username\"],\n", - " y=lambda preds: preds.count(),\n", - " groupby_dims=['x', 'label'],\n", - " domain_x=zoom_range,\n", - " mark=\"bar\",\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=12, y=0, w=12, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, zoom_range, bin_range: weave.legacy.panels.Plot(\n", - " predictions,\n", - " x=lambda item: item[\"timestamp\"].bin(\n", - " weave.legacy.ops.timestamp_bins_nice(bin_range, 100))['start'],\n", - " y=lambda preds: preds[\"api_cost\"].sum(),\n", - " groupby_dims=['x'],\n", - " domain_x=zoom_range,\n", - " mark=\"line\",\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=6, w=8, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, zoom_range, bin_range: weave.legacy.panels.Plot(\n", - " predictions,\n", - " x=lambda item: item[\"timestamp\"].bin(\n", - " weave.legacy.ops.timestamp_bins_nice(bin_range, 100))['start'],\n", - " y=lambda preds: preds[\"prompt_tokens\"].sum() + preds['completion_tokens'].sum(),\n", - " groupby_dims=['x'],\n", - " domain_x=zoom_range,\n", - " mark=\"line\",\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=8, y=6, w=8, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, zoom_range, bin_range: weave.legacy.panels.Plot(\n", - " predictions,\n", - " x=lambda item: item[\"timestamp\"].bin(\n", - " weave.legacy.ops.timestamp_bins_nice(bin_range, 100))['start'],\n", - " y=lambda preds: preds[\"latency\"].avg(),\n", - " groupby_dims=['x'],\n", - " domain_x=zoom_range,\n", - " mark=\"line\",\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=16, y=6, w=8, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions: weave.legacy.panels.Plot(\n", - " predictions,\n", - " x=lambda item: item[\"api_cost\"].bin(\n", - " weave.legacy.ops.numbers_bins_equal(predictions['api_cost'], 50)),\n", - " y=lambda preds: preds.count(),\n", - " groupby_dims=['x'],\n", - " mark=\"bar\",\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=12, w=8, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions: weave.legacy.panels.Plot(\n", - " predictions,\n", - " x=lambda item: (item['prompt_tokens'] + item['completion_tokens']).bin(\n", - " weave.legacy.ops.number_bins_fixed(25)),\n", - " y=lambda preds: preds.count(),\n", - " groupby_dims=['x'],\n", - " mark=\"bar\",\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=8, y=12, w=8, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions: weave.legacy.panels.Plot(\n", - " predictions,\n", - " x=lambda item: item['latency'].bin(\n", - " weave.legacy.ops.numbers_bins_equal(predictions['latency'], 50)),\n", - " y=lambda preds: preds.count(),\n", - " groupby_dims=['x'],\n", - " mark=\"bar\",\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=16, y=12, w=8, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions: predictions,\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=18, w=24, h=12)\n", - " )\n", - " ]\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1d8bafc9", - "metadata": {}, - "outputs": [], - "source": [ - "board" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/Mutations.ipynb b/weave/legacy/examples/experimental/Mutations.ipynb index cc49a537286..9e402df99fb 100644 --- a/weave/legacy/examples/experimental/Mutations.ipynb +++ b/weave/legacy/examples/experimental/Mutations.ipynb @@ -1,70 +1,70 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "dd93a251", - "metadata": {}, - "outputs": [], - "source": [ - "import weave" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "dd93a251", + "metadata": {}, + "outputs": [], + "source": [ + "import weave" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ddcbd7da", + "metadata": {}, + "outputs": [], + "source": [ + "# Only run this cell the first time\n", + "table_data = weave.save([{'a': 5, 'b': 6, 'c': 'hello'}, {'a': 7, 'b': 9, 'c': 'goodbye'}], name='my-table:latest')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0063dcd0", + "metadata": {}, + "outputs": [], + "source": [ + "dataset = weave.legacy.weave.ops.get(\"local-artifact:///my-table:latest/obj\")\n", + "dataset" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b310adec", + "metadata": {}, + "outputs": [], + "source": [ + "# You can mutate data in the UI.\n", + "# In the panel above, switch the c column Panel to StringEditor,\n", + "# then edit one of the cells.\n", + "# To see the changes were saved, rerun cell 3." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cf92cd4e", + "metadata": {}, + "outputs": [], + "source": [ + "# Or you can mutate data from Python. You can press the \"play\" icon in the UI to make it live update.\n", + "for i in range(10):\n", + " dataset.append({'a': 0, 'b': i, 'c': 'k'})" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "ddcbd7da", - "metadata": {}, - "outputs": [], - "source": [ - "# Only run this cell the first time\n", - "table_data = weave.save([{'a': 5, 'b': 6, 'c': 'hello'}, {'a': 7, 'b': 9, 'c': 'goodbye'}], name='my-table:latest')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "0063dcd0", - "metadata": {}, - "outputs": [], - "source": [ - "dataset = weave.legacy.ops.get(\"local-artifact:///my-table:latest/obj\")\n", - "dataset" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b310adec", - "metadata": {}, - "outputs": [], - "source": [ - "# You can mutate data in the UI.\n", - "# In the panel above, switch the c column Panel to StringEditor,\n", - "# then edit one of the cells.\n", - "# To see the changes were saved, rerun cell 3." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "cf92cd4e", - "metadata": {}, - "outputs": [], - "source": [ - "# Or you can mutate data from Python. You can press the \"play\" icon in the UI to make it live update.\n", - "for i in range(10):\n", - " dataset.append({'a': 0, 'b': i, 'c': 'k'})" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/ProductionMonitoring/MonitorPanelPlotGeneric.ipynb b/weave/legacy/examples/experimental/ProductionMonitoring/MonitorPanelPlotGeneric.ipynb index ca7752dbebf..27ff8359257 100644 --- a/weave/legacy/examples/experimental/ProductionMonitoring/MonitorPanelPlotGeneric.ipynb +++ b/weave/legacy/examples/experimental/ProductionMonitoring/MonitorPanelPlotGeneric.ipynb @@ -1,400 +1,400 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "f7512dfa", - "metadata": {}, - "source": [ - "# Model monitoring dashboard example\n", - "\n", - "This notebook currently requires the plotly library to be installed.\n" - ] + "cells": [ + { + "cell_type": "markdown", + "id": "f7512dfa", + "metadata": {}, + "source": [ + "# Model monitoring dashboard example\n", + "\n", + "This notebook currently requires the plotly library to be installed.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "80506dea", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "from weave.legacy.scripts import syndata_mon" + ] + }, + { + "cell_type": "markdown", + "id": "8519889f", + "metadata": {}, + "source": [ + "## Create synthetic data\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7eba21e0", + "metadata": {}, + "outputs": [], + "source": [ + "#preds = syndata_mon.random_predictions(10)\n", + "\n", + "#predictions = weave.save(preds, 'predictions')\n", + "#len(preds.column('prompt').to_pylist_raw())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8934efcf", + "metadata": {}, + "outputs": [], + "source": [ + "import logging\n", + "import json\n", + "import os\n", + "from pathlib import Path\n", + "\n", + "import tiktoken\n", + "import faiss\n", + "import numpy as np\n", + "from tenacity import (\n", + " before_sleep_log,\n", + " retry,\n", + " retry_if_exception_type,\n", + " stop_after_attempt,\n", + " wait_exponential,\n", + ")\n", + "import openai\n", + "\n", + "logger = logging.getLogger(__name__)\n", + "openai.api_key = os.environ['OPENAI_API_KEY']\n", + "\n", + "# OpenAI API functions\n", + "retry_openai_decorator = retry(\n", + " reraise=True,\n", + " stop=stop_after_attempt(4),\n", + " wait=wait_exponential(multiplier=1, min=4, max=10),\n", + " retry=(\n", + " retry_if_exception_type(openai.error.Timeout)\n", + " | retry_if_exception_type(openai.error.APIError)\n", + " | retry_if_exception_type(openai.error.APIConnectionError)\n", + " | retry_if_exception_type(openai.error.RateLimitError)\n", + " | retry_if_exception_type(openai.error.ServiceUnavailableError)\n", + " ),\n", + " before_sleep=before_sleep_log(logger, logging.WARNING),\n", + " )\n", + "\n", + "@retry_openai_decorator\n", + "def openai_embed(model, input):\n", + " return openai.Embedding.create(input = input, model=model)\n", + "\n", + "@retry_openai_decorator\n", + "def openai_chatcompletion(model, messages):\n", + " return openai.ChatCompletion.create(\n", + " model=\"gpt-3.5-turbo\", # The deployment name you chose when you deployed the ChatGPT or GPT-4 model.\n", + " messages = messages\n", + " )\n", + "\n", + "# Helper to efficiently embed a set of documents using the OpenAI embedding API\n", + "# This is from langchain\n", + "\n", + "embedding_ctx_length = 8191\n", + "OPENAI_EMBEDDING_MODEL = \"text-embedding-ada-002\"\n", + "chunk_size = 1000\n", + "\n", + "from typing import List\n", + "\n", + "def embed_texts(texts: List[str], embedding_model: str) -> List[List[float]]:\n", + " embeddings: List[List[float]] = [[] for _ in range(len(texts))]\n", + " tokens = []\n", + " indices = []\n", + " encoding = tiktoken.model.encoding_for_model(embedding_model)\n", + " for i, text in enumerate(texts):\n", + " if embedding_model.endswith(\"001\"):\n", + " # See: https://github.com/openai/openai-python/issues/418#issuecomment-1525939500\n", + " # replace newlines, which can negatively affect performance.\n", + " text = text.replace(\"\\n\", \" \")\n", + " token = encoding.encode(\n", + " text,\n", + " disallowed_special=\"all\",\n", + " )\n", + " for j in range(0, len(token), embedding_ctx_length):\n", + " tokens += [token[j : j + embedding_ctx_length]]\n", + " indices += [i]\n", + "\n", + " batched_embeddings = []\n", + " _chunk_size = chunk_size\n", + " for i in range(0, len(tokens), _chunk_size):\n", + " response = openai_embed(\n", + " embedding_model,\n", + " input=tokens[i : i + _chunk_size],\n", + " )\n", + " batched_embeddings += [r[\"embedding\"] for r in response[\"data\"]]\n", + "\n", + " results: List[List[List[float]]] = [[] for _ in range(len(texts))]\n", + " num_tokens_in_batch: List[List[int]] = [[] for _ in range(len(texts))]\n", + " for i in range(len(indices)):\n", + " results[indices[i]].append(batched_embeddings[i])\n", + " num_tokens_in_batch[indices[i]].append(len(tokens[i]))\n", + "\n", + " for i in range(len(texts)):\n", + " _result = results[i]\n", + " if len(_result) == 0:\n", + " average = embed_with_retry(\n", + " embedding_model,\n", + " input=\"\",\n", + " )[\"data\"][0][\"embedding\"]\n", + " else:\n", + " average = np.average(\n", + " _result, axis=0, weights=num_tokens_in_batch[i]\n", + " )\n", + " embeddings[i] = (average / np.linalg.norm(average)).tolist()\n", + "\n", + " return embeddings" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6ab2debd", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas\n", + "data = pandas.read_csv('/Users/shawn/datasets/wandb_export_2023-06-03T15_01_20.066-07_00.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4c084173", + "metadata": {}, + "outputs": [], + "source": [ + "data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eef1fb56", + "metadata": {}, + "outputs": [], + "source": [ + "embeddings = embed_texts(data['question'][:100], OPENAI_EMBEDDING_MODEL)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "45c9bcf8", + "metadata": {}, + "outputs": [], + "source": [ + "from weave.legacy.weave.ecosystem import umap" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "54a1f09d", + "metadata": {}, + "outputs": [], + "source": [ + "umap.umap_projection(embeddings, {})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0781ddcd", + "metadata": {}, + "outputs": [], + "source": [ + "len(embeddings)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c190e190", + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.datasets import fetch_openml\n", + "from sklearn.decomposition import PCA\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "%matplotlib inline\n", + "\n", + "# Dimension reduction and clustering libraries\n", + "import umap\n", + "import hdbscan\n", + "import sklearn.cluster as cluster\n", + "from sklearn.metrics import adjusted_rand_score, adjusted_mutual_info_score" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "16e52ec2", + "metadata": {}, + "outputs": [], + "source": [ + "standard_embedding = umap.UMAP(random_state=42).fit_transform(embeddings)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c28defdb", + "metadata": {}, + "outputs": [], + "source": [ + "plt.scatter(standard_embedding[:, 0], standard_embedding[:, 1], s=0.1, cmap='Spectral');" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5e59fd77", + "metadata": {}, + "outputs": [], + "source": [ + "clusterable_embedding = umap.UMAP(\n", + " n_neighbors=30,\n", + " min_dist=0.0,\n", + " n_components=2,\n", + " random_state=42,\n", + ").fit_transform(embeddings)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d571528d", + "metadata": {}, + "outputs": [], + "source": [ + "clusterable_embedding.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c568b42a", + "metadata": {}, + "outputs": [], + "source": [ + "plt.scatter(clusterable_embedding[:, 0], clusterable_embedding[:, 1], s=0.1, cmap='Spectral');" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bf0920f0", + "metadata": {}, + "outputs": [], + "source": [ + "labels = hdbscan.HDBSCAN(\n", + " min_samples=10,\n", + " min_cluster_size=50,\n", + ").fit_predict(clusterable_embedding)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ead20089", + "metadata": {}, + "outputs": [], + "source": [ + "#labels\n", + "np.unique(labels, return_counts=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "32d4fabe", + "metadata": {}, + "outputs": [], + "source": [ + "clustered = (labels >= 0)\n", + "plt.scatter(standard_embedding[~clustered, 0],\n", + " standard_embedding[~clustered, 1],\n", + " color=(0.5, 0.5, 0.5),\n", + " s=0.1,\n", + " alpha=0.5)\n", + "plt.scatter(standard_embedding[clustered, 0],\n", + " standard_embedding[clustered, 1],\n", + " c=labels[clustered],\n", + " s=0.1,\n", + " cmap='Spectral');" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "289f1c42", + "metadata": {}, + "outputs": [], + "source": [ + "data['embedding_x'] = standard_embedding[:,0]\n", + "data['embedding_y'] = standard_embedding[:,1]\n", + "data['cluster_id'] = labels.astype(str)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aafaa6f9", + "metadata": {}, + "outputs": [], + "source": [ + "weave.show(data)" + ] + }, + { + "cell_type": "markdown", + "id": "cdd59e39", + "metadata": {}, + "source": [ + "## Create a Weave Board for the data\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "22be0bd4", + "metadata": {}, + "outputs": [], + "source": [ + "from weave.legacy.weave.panels_py import panel_autoboard\n", + "\n", + "panel_autoboard.auto_panels(predictions)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "80506dea", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "from weave.legacy.scripts import syndata_mon" - ] - }, - { - "cell_type": "markdown", - "id": "8519889f", - "metadata": {}, - "source": [ - "## Create synthetic data\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7eba21e0", - "metadata": {}, - "outputs": [], - "source": [ - "#preds = syndata_mon.random_predictions(10)\n", - "\n", - "#predictions = weave.save(preds, 'predictions')\n", - "#len(preds.column('prompt').to_pylist_raw())" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8934efcf", - "metadata": {}, - "outputs": [], - "source": [ - "import logging\n", - "import json\n", - "import os\n", - "from pathlib import Path\n", - "\n", - "import tiktoken\n", - "import faiss\n", - "import numpy as np\n", - "from tenacity import (\n", - " before_sleep_log,\n", - " retry,\n", - " retry_if_exception_type,\n", - " stop_after_attempt,\n", - " wait_exponential,\n", - ")\n", - "import openai\n", - "\n", - "logger = logging.getLogger(__name__)\n", - "openai.api_key = os.environ['OPENAI_API_KEY']\n", - "\n", - "# OpenAI API functions\n", - "retry_openai_decorator = retry(\n", - " reraise=True,\n", - " stop=stop_after_attempt(4),\n", - " wait=wait_exponential(multiplier=1, min=4, max=10),\n", - " retry=(\n", - " retry_if_exception_type(openai.error.Timeout)\n", - " | retry_if_exception_type(openai.error.APIError)\n", - " | retry_if_exception_type(openai.error.APIConnectionError)\n", - " | retry_if_exception_type(openai.error.RateLimitError)\n", - " | retry_if_exception_type(openai.error.ServiceUnavailableError)\n", - " ),\n", - " before_sleep=before_sleep_log(logger, logging.WARNING),\n", - " )\n", - "\n", - "@retry_openai_decorator\n", - "def openai_embed(model, input):\n", - " return openai.Embedding.create(input = input, model=model)\n", - "\n", - "@retry_openai_decorator\n", - "def openai_chatcompletion(model, messages):\n", - " return openai.ChatCompletion.create(\n", - " model=\"gpt-3.5-turbo\", # The deployment name you chose when you deployed the ChatGPT or GPT-4 model.\n", - " messages = messages\n", - " )\n", - "\n", - "# Helper to efficiently embed a set of documents using the OpenAI embedding API\n", - "# This is from langchain\n", - "\n", - "embedding_ctx_length = 8191\n", - "OPENAI_EMBEDDING_MODEL = \"text-embedding-ada-002\"\n", - "chunk_size = 1000\n", - "\n", - "from typing import List\n", - "\n", - "def embed_texts(texts: List[str], embedding_model: str) -> List[List[float]]:\n", - " embeddings: List[List[float]] = [[] for _ in range(len(texts))]\n", - " tokens = []\n", - " indices = []\n", - " encoding = tiktoken.model.encoding_for_model(embedding_model)\n", - " for i, text in enumerate(texts):\n", - " if embedding_model.endswith(\"001\"):\n", - " # See: https://github.com/openai/openai-python/issues/418#issuecomment-1525939500\n", - " # replace newlines, which can negatively affect performance.\n", - " text = text.replace(\"\\n\", \" \")\n", - " token = encoding.encode(\n", - " text,\n", - " disallowed_special=\"all\",\n", - " )\n", - " for j in range(0, len(token), embedding_ctx_length):\n", - " tokens += [token[j : j + embedding_ctx_length]]\n", - " indices += [i]\n", - "\n", - " batched_embeddings = []\n", - " _chunk_size = chunk_size\n", - " for i in range(0, len(tokens), _chunk_size):\n", - " response = openai_embed(\n", - " embedding_model,\n", - " input=tokens[i : i + _chunk_size],\n", - " )\n", - " batched_embeddings += [r[\"embedding\"] for r in response[\"data\"]]\n", - "\n", - " results: List[List[List[float]]] = [[] for _ in range(len(texts))]\n", - " num_tokens_in_batch: List[List[int]] = [[] for _ in range(len(texts))]\n", - " for i in range(len(indices)):\n", - " results[indices[i]].append(batched_embeddings[i])\n", - " num_tokens_in_batch[indices[i]].append(len(tokens[i]))\n", - "\n", - " for i in range(len(texts)):\n", - " _result = results[i]\n", - " if len(_result) == 0:\n", - " average = embed_with_retry(\n", - " embedding_model,\n", - " input=\"\",\n", - " )[\"data\"][0][\"embedding\"]\n", - " else:\n", - " average = np.average(\n", - " _result, axis=0, weights=num_tokens_in_batch[i]\n", - " )\n", - " embeddings[i] = (average / np.linalg.norm(average)).tolist()\n", - "\n", - " return embeddings" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6ab2debd", - "metadata": {}, - "outputs": [], - "source": [ - "import pandas\n", - "data = pandas.read_csv('/Users/shawn/datasets/wandb_export_2023-06-03T15_01_20.066-07_00.csv')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4c084173", - "metadata": {}, - "outputs": [], - "source": [ - "data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "eef1fb56", - "metadata": {}, - "outputs": [], - "source": [ - "embeddings = embed_texts(data['question'][:100], OPENAI_EMBEDDING_MODEL)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "45c9bcf8", - "metadata": {}, - "outputs": [], - "source": [ - "from weave.legacy.ecosystem import umap" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "54a1f09d", - "metadata": {}, - "outputs": [], - "source": [ - "umap.umap_projection(embeddings, {})" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "0781ddcd", - "metadata": {}, - "outputs": [], - "source": [ - "len(embeddings)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c190e190", - "metadata": {}, - "outputs": [], - "source": [ - "from sklearn.datasets import fetch_openml\n", - "from sklearn.decomposition import PCA\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "%matplotlib inline\n", - "\n", - "# Dimension reduction and clustering libraries\n", - "import umap\n", - "import hdbscan\n", - "import sklearn.cluster as cluster\n", - "from sklearn.metrics import adjusted_rand_score, adjusted_mutual_info_score" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "16e52ec2", - "metadata": {}, - "outputs": [], - "source": [ - "standard_embedding = umap.UMAP(random_state=42).fit_transform(embeddings)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c28defdb", - "metadata": {}, - "outputs": [], - "source": [ - "plt.scatter(standard_embedding[:, 0], standard_embedding[:, 1], s=0.1, cmap='Spectral');" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5e59fd77", - "metadata": {}, - "outputs": [], - "source": [ - "clusterable_embedding = umap.UMAP(\n", - " n_neighbors=30,\n", - " min_dist=0.0,\n", - " n_components=2,\n", - " random_state=42,\n", - ").fit_transform(embeddings)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d571528d", - "metadata": {}, - "outputs": [], - "source": [ - "clusterable_embedding.shape" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c568b42a", - "metadata": {}, - "outputs": [], - "source": [ - "plt.scatter(clusterable_embedding[:, 0], clusterable_embedding[:, 1], s=0.1, cmap='Spectral');" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "bf0920f0", - "metadata": {}, - "outputs": [], - "source": [ - "labels = hdbscan.HDBSCAN(\n", - " min_samples=10,\n", - " min_cluster_size=50,\n", - ").fit_predict(clusterable_embedding)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ead20089", - "metadata": {}, - "outputs": [], - "source": [ - "#labels\n", - "np.unique(labels, return_counts=True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "32d4fabe", - "metadata": {}, - "outputs": [], - "source": [ - "clustered = (labels >= 0)\n", - "plt.scatter(standard_embedding[~clustered, 0],\n", - " standard_embedding[~clustered, 1],\n", - " color=(0.5, 0.5, 0.5),\n", - " s=0.1,\n", - " alpha=0.5)\n", - "plt.scatter(standard_embedding[clustered, 0],\n", - " standard_embedding[clustered, 1],\n", - " c=labels[clustered],\n", - " s=0.1,\n", - " cmap='Spectral');" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "289f1c42", - "metadata": {}, - "outputs": [], - "source": [ - "data['embedding_x'] = standard_embedding[:,0]\n", - "data['embedding_y'] = standard_embedding[:,1]\n", - "data['cluster_id'] = labels.astype(str)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "aafaa6f9", - "metadata": {}, - "outputs": [], - "source": [ - "weave.show(data)" - ] - }, - { - "cell_type": "markdown", - "id": "cdd59e39", - "metadata": {}, - "source": [ - "## Create a Weave Board for the data\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "22be0bd4", - "metadata": {}, - "outputs": [], - "source": [ - "from weave.legacy.panels_py import panel_autoboard\n", - "\n", - "panel_autoboard.auto_panels(predictions)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/ProductionMonitoring/ProductionMonitoringConceptualOverview.ipynb b/weave/legacy/examples/experimental/ProductionMonitoring/ProductionMonitoringConceptualOverview.ipynb index 84fd549f7c7..0a4bd3d3ac2 100644 --- a/weave/legacy/examples/experimental/ProductionMonitoring/ProductionMonitoringConceptualOverview.ipynb +++ b/weave/legacy/examples/experimental/ProductionMonitoring/ProductionMonitoringConceptualOverview.ipynb @@ -1,358 +1,358 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "36a9f92a", - "metadata": {}, - "source": [ - "# W&B Production Monitoring Overview\n", - "\n", - "This notebook demonstrates how to monitor production models with W&B through an illustrative example. We will train a model to correctly identify handwritten digits, then monitor a locally deployed version of the model. We create a gradio app which runs in the notebook and lets a user draw/\"handwrite\" characters with the mouse and give live feedback by labeling the character as the digit 0-9.\n", - "\n", - "_Note: To keep the example focused on important code, much of the dataset manipulation, modelling, and other utilities are packaged in local files and imported here_\n", - "\n", - "# Step 0: Setup & import dependencies" - ] + "cells": [ + { + "cell_type": "markdown", + "id": "36a9f92a", + "metadata": {}, + "source": [ + "# W&B Production Monitoring Overview\n", + "\n", + "This notebook demonstrates how to monitor production models with W&B through an illustrative example. We will train a model to correctly identify handwritten digits, then monitor a locally deployed version of the model. We create a gradio app which runs in the notebook and lets a user draw/\"handwrite\" characters with the mouse and give live feedback by labeling the character as the digit 0-9.\n", + "\n", + "_Note: To keep the example focused on important code, much of the dataset manipulation, modelling, and other utilities are packaged in local files and imported here_\n", + "\n", + "# Step 0: Setup & import dependencies" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3af52605", + "metadata": {}, + "outputs": [], + "source": [ + "!pip install tensorflow\n", + "!pip install gradio\n", + "!pip install weave" + ] + }, + { + "cell_type": "markdown", + "id": "55afcd6c", + "metadata": {}, + "source": [ + "Log in to W&B to sync these examples to your W&B account, where you can view, interact with, and customize the resulting Tables and Boards." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c9e3e332", + "metadata": {}, + "outputs": [], + "source": [ + "import wandb\n", + "wandb.login()" + ] + }, + { + "cell_type": "markdown", + "id": "48354a22", + "metadata": {}, + "source": [ + "Set your W&B entity (username or team name) and optionally rename the destination project." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "424dc619", + "metadata": {}, + "outputs": [], + "source": [ + "WB_ENTITY = \"shawn\"\n", + "WB_PROJECT = \"prodmon_mnist\"" + ] + }, + { + "cell_type": "markdown", + "id": "8daaf18d", + "metadata": {}, + "source": [ + "# Step 1: Get data\n", + "In this example, we will use `keras.datasets.mnist.load_data()` to load in the MNIST dataset. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "de553636", + "metadata": {}, + "outputs": [], + "source": [ + "import model_util\n", + "\n", + "dataset = model_util.get_dataset()\n", + "model_util.image_from_array(dataset[0][0])" + ] + }, + { + "cell_type": "markdown", + "id": "6822a544", + "metadata": {}, + "source": [ + "# Step 2: Train model\n", + "Next we will train a classic NN to predict the digits" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "39bf1bc2", + "metadata": {}, + "outputs": [], + "source": [ + "model = model_util.train_model(*dataset, conv_layers=0, epochs=1) # 1 epoch so we can actually see some errors" + ] + }, + { + "cell_type": "markdown", + "id": "68a38ddd", + "metadata": {}, + "source": [ + "# Step 3: Query model\n", + "Now, let's query the model! Normally there is a little pre- and post- processing needed to make a prediction - we will write a short function to handle this for us." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5b8afe99", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import json\n", + "\n", + "def simple_predict(image_arr):\n", + " # Prepare image for model\n", + " tensor = (image_arr.astype(\"float32\")).reshape(1, 28, 28, 1)\n", + "\n", + " # Make the prediction\n", + " prediction = model.predict(tensor, verbose=False)\n", + "\n", + " # In this application, we need to reshape the output:\n", + " raw_predictions = prediction[0].tolist()\n", + " logits = {\n", + " str(k): v for k, v in zip(range(10), raw_predictions)\n", + " }\n", + " \n", + " prediction = np.argmax(raw_predictions).tolist()\n", + " \n", + " return {\"logits\": logits, \"prediction\": prediction}\n", + "\n", + "_, _, x_test, y_test = dataset\n", + "for i in range(10):\n", + " image_arr = x_test[i]\n", + " truth = y_test[i]\n", + " preds = simple_predict(image_arr)\n", + " \n", + " print(f\"Input: {truth}\")\n", + " display(model_util.image_from_array(image_arr))\n", + " print(f\"Prediction: {preds['prediction']}\")\n", + " print(f\"Logits: {json.dumps(preds['logits'], indent=2)}\")\n", + " print(\"\")\n", + " " + ] + }, + { + "cell_type": "markdown", + "id": "8826acf8", + "metadata": {}, + "source": [ + "# Step 3A: Save predictions with W&B Weave using StreamTable\n", + "With W&B's Weave library, we can stream any data to W&B for storage and further analysis." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9c59bccb", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "weave.use_frontend_devmode()\n", + "from weave.legacy.weave.monitoring import StreamTable\n", + "\n", + "# Initialize a stream table\n", + "# (optionally change the name argument to any string\n", + "# that follows the wandbentity_name/project_name/table_name format)\n", + "st = StreamTable(f\"{WB_ENTITY}/{WB_PROJECT}/logged_predictions\")\n", + "_, _, x_test, y_test = dataset\n", + "for i in range(100):\n", + " image_arr = x_test[i]\n", + " truth = y_test[i].tolist()\n", + " preds = simple_predict(image_arr)\n", + " \n", + " # Log the data\n", + " st.log({\n", + " **preds,\n", + " \"image\": model_util.image_from_array(image_arr),\n", + " \"truth\": truth\n", + " })\n", + "\n", + "# Optional: wait for the logs to finish uploading (nicer for live demos)\n", + "st.finish()\n", + "\n", + "# Show the StreamTable\n", + "st " + ] + }, + { + "cell_type": "markdown", + "id": "dcb0cc29", + "metadata": {}, + "source": [ + "# Step 3B: Save predictions with W&B Weave using `monitor` decorator\n", + "This pattern of logging inputs and outputs of a functions is so common, that we provide a decorator which automatically logs a function's I/O." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "90ab5fe4", + "metadata": {}, + "outputs": [], + "source": [ + "from weave.legacy.weave.monitoring import monitor\n", + "import numpy as np\n", + "\n", + "mon = monitor.init_monitor(f\"{WB_ENTITY}/{WB_PROJECT}/monitor_predict_function\")\n", + "\n", + "def preprocess(span):\n", + " span.inputs['image'] = model_util.image_from_array(span.inputs['image_arr'])\n", + " del span.inputs['image_arr']\n", + "\n", + "@mon.trace(\n", + " # An preprocessor allows the function arguments to be pre-processed before logging.\n", + " preprocess = preprocess\n", + ")\n", + "def monitor_predict(image_arr):\n", + " # Prepare image for model\n", + " tensor = (image_arr.astype(\"float32\")).reshape(1, 28, 28, 1)\n", + "\n", + " # Make the prediction\n", + " prediction = model.predict(tensor, verbose=False)\n", + "\n", + " # In this application, we need to reshape the output:\n", + " raw_predictions = prediction[0].tolist()\n", + " logits = {\n", + " str(k): v for k, v in zip(range(10), raw_predictions)\n", + " }\n", + " \n", + " prediction = np.argmax(raw_predictions).tolist()\n", + " \n", + " return {\"logits\": logits, \"prediction\": prediction}\n", + "\n", + "_, _, x_test, y_test = dataset\n", + "for i in range(100):\n", + " image_arr = x_test[i]\n", + " truth = y_test[i].tolist()\n", + " # Use the added monitor_attributes argument to add additional data\n", + " preds = monitor_predict(image_arr, monitor_attributes={'truth': truth})" + ] + }, + { + "cell_type": "markdown", + "id": "d3896993", + "metadata": {}, + "source": [ + "# Step 4: End-to-end example\n", + "Typically a production application will contain a prediction service that provides predictions to a client. To demonstrate this in a notebook, we will create a `PredictionService` and an `AppUI`: a small interface which lets the user to draw an image, view the prediction, and give feedback on a result (in this case, correctly label a handdrawn digit 0-9). These communicate via `predict` and `record_feedback` methods. \n", + "\n", + "Note: this is purely for example purposes—your production systems may widely vary in structure_" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "efc97d6a", + "metadata": {}, + "outputs": [], + "source": [ + "# TODO: not yet working with new API\n", + "\n", + "# import app_util\n", + "# from weave.legacy.weave.monitoring import monitor\n", + "# import PIL\n", + "# import numpy as np\n", + "\n", + "# class PredictionService(app_util.PredictionServiceInterface):\n", + "# def __init__(self, model):\n", + "# self.model = model\n", + "# self.last_prediction = {}\n", + " \n", + "# @monitor(auto_log = False, entity_name=WB_ENTITY, project_name=WB_PROJECT)\n", + "# def _raw_predict(self, pil_image: PIL.Image) -> dict:\n", + "# # Prepare image for model\n", + "# tensor = (np.array(pil_image.resize((28, 28))).astype(\"float32\") / 255).reshape(1, 28, 28, 1)\n", + "\n", + "# # Make the prediction\n", + "# prediction = self.model.predict(tensor, verbose=False)\n", + "\n", + "# # In this application, we need to reshape the output:\n", + "# raw_predictions = prediction[0].tolist()\n", + "# logits = {\n", + "# str(k): v for k, v in zip(range(10), raw_predictions)\n", + "# }\n", + "\n", + "# prediction = np.argmax(raw_predictions).tolist()\n", + "\n", + "# return {\"logits\": logits, \"prediction\": prediction}\n", + " \n", + "# def _update_last_prediction(self, prediction) -> None:\n", + "# if len(self.last_prediction) > 0:\n", + "# last_pred = self.last_prediction.pop(list(self.last_prediction.keys())[0])\n", + "# last_pred.finalize()\n", + "# self.last_prediction[prediction.id] = prediction\n", + "\n", + " \n", + "# def predict(self, pil_image: PIL.Image) -> app_util.Prediction:\n", + "# record = self._raw_predict(pil_image)\n", + " \n", + "# # Cache the last prediction for ground_truth recording\n", + "# self._update_last_prediction(record)\n", + " \n", + "# # Return the prediction\n", + "# return app_util.Prediction(record.get()['logits'], record.id)\n", + " \n", + "# def record_feedback(self, prediction_id: str, feedback: int) -> None:\n", + "# if prediction_id not in self.last_prediction:\n", + "# return\n", + "\n", + "# # Get the past prediction\n", + "# prediction = self.last_prediction.pop(prediction_id)\n", + " \n", + "# # Save the user feedback\n", + "# prediction.add_data({'user_feedback': feedback})\n", + " \n", + "# # Log the results\n", + "# prediction.finalize()\n", + " \n", + "# app_util.render_app(PredictionService(model))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "3af52605", - "metadata": {}, - "outputs": [], - "source": [ - "!pip install tensorflow\n", - "!pip install gradio\n", - "!pip install weave" - ] - }, - { - "cell_type": "markdown", - "id": "55afcd6c", - "metadata": {}, - "source": [ - "Log in to W&B to sync these examples to your W&B account, where you can view, interact with, and customize the resulting Tables and Boards." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c9e3e332", - "metadata": {}, - "outputs": [], - "source": [ - "import wandb\n", - "wandb.login()" - ] - }, - { - "cell_type": "markdown", - "id": "48354a22", - "metadata": {}, - "source": [ - "Set your W&B entity (username or team name) and optionally rename the destination project." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "424dc619", - "metadata": {}, - "outputs": [], - "source": [ - "WB_ENTITY = \"shawn\"\n", - "WB_PROJECT = \"prodmon_mnist\"" - ] - }, - { - "cell_type": "markdown", - "id": "8daaf18d", - "metadata": {}, - "source": [ - "# Step 1: Get data\n", - "In this example, we will use `keras.datasets.mnist.load_data()` to load in the MNIST dataset. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "de553636", - "metadata": {}, - "outputs": [], - "source": [ - "import model_util\n", - "\n", - "dataset = model_util.get_dataset()\n", - "model_util.image_from_array(dataset[0][0])" - ] - }, - { - "cell_type": "markdown", - "id": "6822a544", - "metadata": {}, - "source": [ - "# Step 2: Train model\n", - "Next we will train a classic NN to predict the digits" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "39bf1bc2", - "metadata": {}, - "outputs": [], - "source": [ - "model = model_util.train_model(*dataset, conv_layers=0, epochs=1) # 1 epoch so we can actually see some errors" - ] - }, - { - "cell_type": "markdown", - "id": "68a38ddd", - "metadata": {}, - "source": [ - "# Step 3: Query model\n", - "Now, let's query the model! Normally there is a little pre- and post- processing needed to make a prediction - we will write a short function to handle this for us." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5b8afe99", - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import json\n", - "\n", - "def simple_predict(image_arr):\n", - " # Prepare image for model\n", - " tensor = (image_arr.astype(\"float32\")).reshape(1, 28, 28, 1)\n", - "\n", - " # Make the prediction\n", - " prediction = model.predict(tensor, verbose=False)\n", - "\n", - " # In this application, we need to reshape the output:\n", - " raw_predictions = prediction[0].tolist()\n", - " logits = {\n", - " str(k): v for k, v in zip(range(10), raw_predictions)\n", - " }\n", - " \n", - " prediction = np.argmax(raw_predictions).tolist()\n", - " \n", - " return {\"logits\": logits, \"prediction\": prediction}\n", - "\n", - "_, _, x_test, y_test = dataset\n", - "for i in range(10):\n", - " image_arr = x_test[i]\n", - " truth = y_test[i]\n", - " preds = simple_predict(image_arr)\n", - " \n", - " print(f\"Input: {truth}\")\n", - " display(model_util.image_from_array(image_arr))\n", - " print(f\"Prediction: {preds['prediction']}\")\n", - " print(f\"Logits: {json.dumps(preds['logits'], indent=2)}\")\n", - " print(\"\")\n", - " " - ] - }, - { - "cell_type": "markdown", - "id": "8826acf8", - "metadata": {}, - "source": [ - "# Step 3A: Save predictions with W&B Weave using StreamTable\n", - "With W&B's Weave library, we can stream any data to W&B for storage and further analysis." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9c59bccb", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "weave.use_frontend_devmode()\n", - "from weave.legacy.monitoring import StreamTable\n", - "\n", - "# Initialize a stream table\n", - "# (optionally change the name argument to any string\n", - "# that follows the wandbentity_name/project_name/table_name format)\n", - "st = StreamTable(f\"{WB_ENTITY}/{WB_PROJECT}/logged_predictions\")\n", - "_, _, x_test, y_test = dataset\n", - "for i in range(100):\n", - " image_arr = x_test[i]\n", - " truth = y_test[i].tolist()\n", - " preds = simple_predict(image_arr)\n", - " \n", - " # Log the data\n", - " st.log({\n", - " **preds,\n", - " \"image\": model_util.image_from_array(image_arr),\n", - " \"truth\": truth\n", - " })\n", - "\n", - "# Optional: wait for the logs to finish uploading (nicer for live demos)\n", - "st.finish()\n", - "\n", - "# Show the StreamTable\n", - "st " - ] - }, - { - "cell_type": "markdown", - "id": "dcb0cc29", - "metadata": {}, - "source": [ - "# Step 3B: Save predictions with W&B Weave using `monitor` decorator\n", - "This pattern of logging inputs and outputs of a functions is so common, that we provide a decorator which automatically logs a function's I/O." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "90ab5fe4", - "metadata": {}, - "outputs": [], - "source": [ - "from weave.legacy.monitoring import monitor\n", - "import numpy as np\n", - "\n", - "mon = monitor.init_monitor(f\"{WB_ENTITY}/{WB_PROJECT}/monitor_predict_function\")\n", - "\n", - "def preprocess(span):\n", - " span.inputs['image'] = model_util.image_from_array(span.inputs['image_arr'])\n", - " del span.inputs['image_arr']\n", - "\n", - "@mon.trace(\n", - " # An preprocessor allows the function arguments to be pre-processed before logging.\n", - " preprocess = preprocess\n", - ")\n", - "def monitor_predict(image_arr):\n", - " # Prepare image for model\n", - " tensor = (image_arr.astype(\"float32\")).reshape(1, 28, 28, 1)\n", - "\n", - " # Make the prediction\n", - " prediction = model.predict(tensor, verbose=False)\n", - "\n", - " # In this application, we need to reshape the output:\n", - " raw_predictions = prediction[0].tolist()\n", - " logits = {\n", - " str(k): v for k, v in zip(range(10), raw_predictions)\n", - " }\n", - " \n", - " prediction = np.argmax(raw_predictions).tolist()\n", - " \n", - " return {\"logits\": logits, \"prediction\": prediction}\n", - "\n", - "_, _, x_test, y_test = dataset\n", - "for i in range(100):\n", - " image_arr = x_test[i]\n", - " truth = y_test[i].tolist()\n", - " # Use the added monitor_attributes argument to add additional data\n", - " preds = monitor_predict(image_arr, monitor_attributes={'truth': truth})" - ] - }, - { - "cell_type": "markdown", - "id": "d3896993", - "metadata": {}, - "source": [ - "# Step 4: End-to-end example\n", - "Typically a production application will contain a prediction service that provides predictions to a client. To demonstrate this in a notebook, we will create a `PredictionService` and an `AppUI`: a small interface which lets the user to draw an image, view the prediction, and give feedback on a result (in this case, correctly label a handdrawn digit 0-9). These communicate via `predict` and `record_feedback` methods. \n", - "\n", - "Note: this is purely for example purposes—your production systems may widely vary in structure_" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "efc97d6a", - "metadata": {}, - "outputs": [], - "source": [ - "# TODO: not yet working with new API\n", - "\n", - "# import app_util\n", - "# from weave.legacy.monitoring import monitor\n", - "# import PIL\n", - "# import numpy as np\n", - "\n", - "# class PredictionService(app_util.PredictionServiceInterface):\n", - "# def __init__(self, model):\n", - "# self.model = model\n", - "# self.last_prediction = {}\n", - " \n", - "# @monitor(auto_log = False, entity_name=WB_ENTITY, project_name=WB_PROJECT)\n", - "# def _raw_predict(self, pil_image: PIL.Image) -> dict:\n", - "# # Prepare image for model\n", - "# tensor = (np.array(pil_image.resize((28, 28))).astype(\"float32\") / 255).reshape(1, 28, 28, 1)\n", - "\n", - "# # Make the prediction\n", - "# prediction = self.model.predict(tensor, verbose=False)\n", - "\n", - "# # In this application, we need to reshape the output:\n", - "# raw_predictions = prediction[0].tolist()\n", - "# logits = {\n", - "# str(k): v for k, v in zip(range(10), raw_predictions)\n", - "# }\n", - "\n", - "# prediction = np.argmax(raw_predictions).tolist()\n", - "\n", - "# return {\"logits\": logits, \"prediction\": prediction}\n", - " \n", - "# def _update_last_prediction(self, prediction) -> None:\n", - "# if len(self.last_prediction) > 0:\n", - "# last_pred = self.last_prediction.pop(list(self.last_prediction.keys())[0])\n", - "# last_pred.finalize()\n", - "# self.last_prediction[prediction.id] = prediction\n", - "\n", - " \n", - "# def predict(self, pil_image: PIL.Image) -> app_util.Prediction:\n", - "# record = self._raw_predict(pil_image)\n", - " \n", - "# # Cache the last prediction for ground_truth recording\n", - "# self._update_last_prediction(record)\n", - " \n", - "# # Return the prediction\n", - "# return app_util.Prediction(record.get()['logits'], record.id)\n", - " \n", - "# def record_feedback(self, prediction_id: str, feedback: int) -> None:\n", - "# if prediction_id not in self.last_prediction:\n", - "# return\n", - "\n", - "# # Get the past prediction\n", - "# prediction = self.last_prediction.pop(prediction_id)\n", - " \n", - "# # Save the user feedback\n", - "# prediction.add_data({'user_feedback': feedback})\n", - " \n", - "# # Log the results\n", - "# prediction.finalize()\n", - " \n", - "# app_util.render_app(PredictionService(model))" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/ProductionMonitoring/StreamTable.md b/weave/legacy/examples/experimental/ProductionMonitoring/StreamTable.md index c2878b9e37c..b353164c22d 100644 --- a/weave/legacy/examples/experimental/ProductionMonitoring/StreamTable.md +++ b/weave/legacy/examples/experimental/ProductionMonitoring/StreamTable.md @@ -11,7 +11,7 @@ A Weave StreamTable object enables continuous streaming of data from an applicat The only required argument to create a StreamTable is the name of the StreamTable object. ```python -from weave.legacy.monitoring import StreamTable +from weave.legacy.weave.monitoring import StreamTable st = StreamTable("my_entity_name/my_project_name/my_table_name") ``` diff --git a/weave/legacy/examples/experimental/ProductionMonitoring/stream_table_api.ipynb b/weave/legacy/examples/experimental/ProductionMonitoring/stream_table_api.ipynb index ec47a481774..6b106621520 100644 --- a/weave/legacy/examples/experimental/ProductionMonitoring/stream_table_api.ipynb +++ b/weave/legacy/examples/experimental/ProductionMonitoring/stream_table_api.ipynb @@ -1,160 +1,160 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "eccb44d3", - "metadata": {}, - "source": [ - "# Weave StreamTable Usage\n", - "\n", - "This notebook demonstrates basic Weave StreamTable usage with interactive examples.\n", - "\n", - "## Step 0: Setup\n", - "\n", - "All the StreamTables created in this notebook will be saved to the WB_PROJECT under the WB_ENTITY account on the public W&B cloud. \n", - "\n", - "**Please login to W&B and set your WB_ENTITY** before running this demo. If entity is not provided explicitly, this will attempt to default to the current logged-in entity if one is available." - ] + "cells": [ + { + "cell_type": "markdown", + "id": "eccb44d3", + "metadata": {}, + "source": [ + "# Weave StreamTable Usage\n", + "\n", + "This notebook demonstrates basic Weave StreamTable usage with interactive examples.\n", + "\n", + "## Step 0: Setup\n", + "\n", + "All the StreamTables created in this notebook will be saved to the WB_PROJECT under the WB_ENTITY account on the public W&B cloud. \n", + "\n", + "**Please login to W&B and set your WB_ENTITY** before running this demo. If entity is not provided explicitly, this will attempt to default to the current logged-in entity if one is available." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3e034bf1", + "metadata": {}, + "outputs": [], + "source": [ + "!pip install weave\n", + "import wandb\n", + "wandb.login()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "51c30e7a", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "from weave.legacy.weave.monitoring import StreamTable" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5684f0b8", + "metadata": {}, + "outputs": [], + "source": [ + "STREAM_TABLE_NAME = \"my_stream_table\"\n", + "WB_PROJECT = \"mesa\"\n", + "WB_ENTITY = \"\"" + ] + }, + { + "cell_type": "markdown", + "id": "6f676d96", + "metadata": {}, + "source": [ + "## Step 1: Define a StreamTable\n", + "\n", + "StreamTable has a single required argument: the name of the StreamTable object.\n", + "\n", + "```python\n", + "st = StreamTable(\"stacey/mesa/my_stream_table\")\n", + "```\n", + "\n", + "This takes the form `my_wb_entity/my_wb_project_name/my_stream_table_name` where you can modify the component names to the relevant strings (e.g. your W&B username or shared W&B team name, a new or existing W&B project name).\n", + "\n", + "## Step 2: Log some data\n", + "\n", + "To add rows to the StreamTable, call `.log()` on the StreamTable object. \n", + "`.log()` accepts a single dictionary or a list of dictionaries, where each dictionary entry corresponds to one row of the table. In each dictionary, the keys are column names and the values are the corresponding cell values.\n", + "\n", + "```python\n", + "st.log({\"one_column_name\" : \"value_a\", \"another_column_name\" : 7})\n", + "st.log([{\"one_column_name\" : \"value_b\", \"another_column_name\" : 19},\n", + " {\"one_column_name\" : \"value_c\", \"another_column_name\" : 28},\n", + " {\"one_column_name\" : \"value_d\", \"another_column_name\" : 36}]\n", + "```\n", + "\n", + "The first call to `.log()` will return a Weave Panel URL, where you can view, edit, and save the resulting StreamTable as a Weave Board, of the form:\n", + "\n", + "View data at: https://weave.wandb.ai/?exp=get%28%0A++++%22wandb-artifact%3A%2F%2F%2Fstacey%2Fmesa%2Fmy_stream_table%3Alatest%2Fobj%22%29%0A++.rows" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b928c2e0", + "metadata": {}, + "outputs": [], + "source": [ + "st = StreamTable(f\"{WB_ENTITY}/{WB_PROJECT}/{STREAM_TABLE_NAME}\")\n", + "\n", + "# log data to the StreamTable as a dictionary or list of dictionaries\n", + "st.log({\"col_a\" : \"1\", \"col_b\" : \"17\", \"col_c\" : \"42\"})\n", + "\n", + "# show the StreamTable\n", + "st" + ] + }, + { + "cell_type": "markdown", + "id": "83cec916", + "metadata": {}, + "source": [ + "All log calls on a given StreamTable instance will append the given rows to that instance.\n", + "\n", + "In a notebook, the StreamTable variable on a line by itself will return a Weave Panel view of the StreamTable. The StreamTable will contain all the logged columns and their values, as well as a `timestamp` column indicating when the row was logged. By default, rows will be ordered by oldest first. You can modify a StreamTable Panel from the UI to sort by columns, group by column values, filter for specific ranges or values, etc.\n", + "\n", + "**Note:** If you would like to customize and save a specific view of a StreamTable Panel, open the StreamTable Panel in a new window as a Board and edit/save a Board from this seed panel. There are two options to achieve this:\n", + "* via the weave.wandb.ai/?exp=... URL\n", + "* via \"Open in new tab\" arrow button, revealed in the menu when you hover on the right side of a StreamTable panel displayed in the notebok)\n", + "\n", + "## Step 3: Log more data & explore the results!\n", + "\n", + "Continue logging as much data as you like to any StreamTable instance. You can keep a reference to a given Python StreamTable object in your notebook session or script, and you can reconnect to the same StreamTable instance across multiple sessions/runs of your script via the StreamTable's unique name (e.g. `st = StreamTable(\"stacey/mesa/my_stream_table\")` ) and keep adding rows. Multiple/parallel processes writing to the same StreamTable are also supported—the server will use a queue to order any concurrent messages.\n", + "\n", + "If you save the StreamTable Panel as a Board, the Board will continue to update as you send more data to the same StreamTable instance." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "294d68c0", + "metadata": {}, + "outputs": [], + "source": [ + "st.log({\"col_a\" : 5, \"col_b\" : -24, \"col_c\" : \"hello\"})\n", + "st.log([{\"col_a\" : 255, \"col_b\" : 3.1415926, \"col_c\" : \"hi!\"}])\n", + "\n", + "# optional: wait for all the rows to finish logging before loading\n", + "st.finish()\n", + "\n", + "st" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "3e034bf1", - "metadata": {}, - "outputs": [], - "source": [ - "!pip install weave\n", - "import wandb\n", - "wandb.login()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "51c30e7a", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "from weave.legacy.monitoring import StreamTable" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5684f0b8", - "metadata": {}, - "outputs": [], - "source": [ - "STREAM_TABLE_NAME = \"my_stream_table\"\n", - "WB_PROJECT = \"mesa\"\n", - "WB_ENTITY = \"\"" - ] - }, - { - "cell_type": "markdown", - "id": "6f676d96", - "metadata": {}, - "source": [ - "## Step 1: Define a StreamTable\n", - "\n", - "StreamTable has a single required argument: the name of the StreamTable object.\n", - "\n", - "```python\n", - "st = StreamTable(\"stacey/mesa/my_stream_table\")\n", - "```\n", - "\n", - "This takes the form `my_wb_entity/my_wb_project_name/my_stream_table_name` where you can modify the component names to the relevant strings (e.g. your W&B username or shared W&B team name, a new or existing W&B project name).\n", - "\n", - "## Step 2: Log some data\n", - "\n", - "To add rows to the StreamTable, call `.log()` on the StreamTable object. \n", - "`.log()` accepts a single dictionary or a list of dictionaries, where each dictionary entry corresponds to one row of the table. In each dictionary, the keys are column names and the values are the corresponding cell values.\n", - "\n", - "```python\n", - "st.log({\"one_column_name\" : \"value_a\", \"another_column_name\" : 7})\n", - "st.log([{\"one_column_name\" : \"value_b\", \"another_column_name\" : 19},\n", - " {\"one_column_name\" : \"value_c\", \"another_column_name\" : 28},\n", - " {\"one_column_name\" : \"value_d\", \"another_column_name\" : 36}]\n", - "```\n", - "\n", - "The first call to `.log()` will return a Weave Panel URL, where you can view, edit, and save the resulting StreamTable as a Weave Board, of the form:\n", - "\n", - "View data at: https://weave.wandb.ai/?exp=get%28%0A++++%22wandb-artifact%3A%2F%2F%2Fstacey%2Fmesa%2Fmy_stream_table%3Alatest%2Fobj%22%29%0A++.rows" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b928c2e0", - "metadata": {}, - "outputs": [], - "source": [ - "st = StreamTable(f\"{WB_ENTITY}/{WB_PROJECT}/{STREAM_TABLE_NAME}\")\n", - "\n", - "# log data to the StreamTable as a dictionary or list of dictionaries\n", - "st.log({\"col_a\" : \"1\", \"col_b\" : \"17\", \"col_c\" : \"42\"})\n", - "\n", - "# show the StreamTable\n", - "st" - ] - }, - { - "cell_type": "markdown", - "id": "83cec916", - "metadata": {}, - "source": [ - "All log calls on a given StreamTable instance will append the given rows to that instance.\n", - "\n", - "In a notebook, the StreamTable variable on a line by itself will return a Weave Panel view of the StreamTable. The StreamTable will contain all the logged columns and their values, as well as a `timestamp` column indicating when the row was logged. By default, rows will be ordered by oldest first. You can modify a StreamTable Panel from the UI to sort by columns, group by column values, filter for specific ranges or values, etc.\n", - "\n", - "**Note:** If you would like to customize and save a specific view of a StreamTable Panel, open the StreamTable Panel in a new window as a Board and edit/save a Board from this seed panel. There are two options to achieve this:\n", - "* via the weave.wandb.ai/?exp=... URL\n", - "* via \"Open in new tab\" arrow button, revealed in the menu when you hover on the right side of a StreamTable panel displayed in the notebok)\n", - "\n", - "## Step 3: Log more data & explore the results!\n", - "\n", - "Continue logging as much data as you like to any StreamTable instance. You can keep a reference to a given Python StreamTable object in your notebook session or script, and you can reconnect to the same StreamTable instance across multiple sessions/runs of your script via the StreamTable's unique name (e.g. `st = StreamTable(\"stacey/mesa/my_stream_table\")` ) and keep adding rows. Multiple/parallel processes writing to the same StreamTable are also supported—the server will use a queue to order any concurrent messages.\n", - "\n", - "If you save the StreamTable Panel as a Board, the Board will continue to update as you send more data to the same StreamTable instance." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "294d68c0", - "metadata": {}, - "outputs": [], - "source": [ - "st.log({\"col_a\" : 5, \"col_b\" : -24, \"col_c\" : \"hello\"})\n", - "st.log([{\"col_a\" : 255, \"col_b\" : 3.1415926, \"col_c\" : \"hi!\"}])\n", - "\n", - "# optional: wait for all the rows to finish logging before loading\n", - "st.finish()\n", - "\n", - "st" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/Table Summary Panel.ipynb b/weave/legacy/examples/experimental/Table Summary Panel.ipynb index 11f63f7ba68..75897f7f465 100644 --- a/weave/legacy/examples/experimental/Table Summary Panel.ipynb +++ b/weave/legacy/examples/experimental/Table Summary Panel.ipynb @@ -1,95 +1,95 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "e9f32c0f", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "# Weave package now defaults to eager mode, but lazy mode required for this example notebook for now.\n", - "weave.use_lazy_execution()\n", - "import xgboost\n", - "from weave.legacy.ecosystem import sklearn" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "e9f32c0f", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "# Weave package now defaults to eager mode, but lazy mode required for this example notebook for now.\n", + "weave.use_lazy_execution()\n", + "import xgboost\n", + "from weave.legacy.weave.ecosystem import sklearn" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "50ff1335", + "metadata": {}, + "outputs": [], + "source": [ + "dataset = weave.use(sklearn.ca_housing_dataset(1))\n", + "dataset_arrow = weave.legacy.weave.ops.dataframe_to_arrow(dataset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1f9dcd73", + "metadata": {}, + "outputs": [], + "source": [ + "import typing\n", + "\n", + "@weave.op()\n", + "def table_summary(table: typing.Any) -> list[weave.legacy.weave.panels.Panel]:\n", + " if not table:\n", + " # TODO: type\n", + " return\n", + " col_names = list(table[0].keys())\n", + " with weave.legacy.weave.context_state.lazy_execution():\n", + " cols = {col_name: weave.legacy.weave.ops.legacy.ops_arrow.dict.pick(table, col_name) for col_name in col_names}\n", + " panels = []\n", + " for col_name, col_values in cols.items():\n", + " panels.append(weave.legacy.weave.panels.LabeledItem(item=col_values, label=col_name))\n", + " return panels" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5d464ef4", + "metadata": {}, + "outputs": [], + "source": [ + "data = weave.save(dataset_arrow, 'my-data')\n", + "table_summary(dataset_arrow)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "47c4cdd9", + "metadata": {}, + "outputs": [], + "source": [ + "# Currently broken\n", + "#weave.publish(table_summary)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.8" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "50ff1335", - "metadata": {}, - "outputs": [], - "source": [ - "dataset = weave.use(sklearn.ca_housing_dataset(1))\n", - "dataset_arrow = weave.legacy.ops.dataframe_to_arrow(dataset)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1f9dcd73", - "metadata": {}, - "outputs": [], - "source": [ - "import typing\n", - "\n", - "@weave.op()\n", - "def table_summary(table: typing.Any) -> list[weave.legacy.panels.Panel]:\n", - " if not table:\n", - " # TODO: type\n", - " return\n", - " col_names = list(table[0].keys())\n", - " with weave.legacy.context_state.lazy_execution():\n", - " cols = {col_name: weave.legacy.ops.legacy.ops_arrow.dict.pick(table, col_name) for col_name in col_names}\n", - " panels = []\n", - " for col_name, col_values in cols.items():\n", - " panels.append(weave.legacy.panels.LabeledItem(item=col_values, label=col_name))\n", - " return panels" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5d464ef4", - "metadata": {}, - "outputs": [], - "source": [ - "data = weave.save(dataset_arrow, 'my-data')\n", - "table_summary(dataset_arrow)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "47c4cdd9", - "metadata": {}, - "outputs": [], - "source": [ - "# Currently broken\n", - "#weave.publish(table_summary)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.8" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/app/Embeddings.ipynb b/weave/legacy/examples/experimental/app/Embeddings.ipynb index b777bf90fc8..221d85d77b9 100644 --- a/weave/legacy/examples/experimental/app/Embeddings.ipynb +++ b/weave/legacy/examples/experimental/app/Embeddings.ipynb @@ -1,123 +1,123 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "d3f10990", - "metadata": {}, - "source": [ - "## Embedding explorer\n", - "\n", - "- Embeds a string column using OpenAI Embeddings\n", - "- Follows the clustering / projection approach from here: https://umap-learn.readthedocs.io/en/latest/clustering.html" - ] + "cells": [ + { + "cell_type": "markdown", + "id": "d3f10990", + "metadata": {}, + "source": [ + "## Embedding explorer\n", + "\n", + "- Embeds a string column using OpenAI Embeddings\n", + "- Follows the clustering / projection approach from here: https://umap-learn.readthedocs.io/en/latest/clustering.html" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "13a3497f", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas\n", + "import weave\n", + "from weave.legacy.weave.ecosystem import openai\n", + "from weave.legacy.weave.ecosystem import umap\n", + "from weave.legacy.weave.ecosystem import hdbscan" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e68f6c86", + "metadata": {}, + "outputs": [], + "source": [ + "#raw_data = pandas.read_csv('/Users/shawn/datasets/wandb_export_2023-06-03T15_01_20.066-07_00.csv')\n", + "raw_data = pandas.read_csv('wandb_export_2023-07-25T11_43_18.362-04_00.csv')\n", + "\n", + "#raw_data['request_timestamp'] = pandas.to_datetime(raw_data['request_timestamp'], unit='ms', utc=True)\n", + "\n", + "data = weave.save(weave.legacy.weave.ops.dataframe_to_arrow(raw_data), 'data')\n", + "# from weave.legacy.weave.panels_py import panel_autoboard\n", + "# panel_autoboard.auto_panels(data)\n", + "#data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "500e19b1", + "metadata": {}, + "outputs": [], + "source": [ + "data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e194b3ce", + "metadata": {}, + "outputs": [], + "source": [ + "weave.legacy.weave.panels.Board(\n", + " vars={\n", + " 'data': data,\n", + " 'limit': 1005,\n", + " 'limited_data': lambda data, limit: data.limit(limit),\n", + " 'embeddings': lambda limited_data: openai.openai_embed(limited_data['question'], {\"model\": \"text-embedding-ada-002\"}),\n", + " 'clusterable_projection': lambda embeddings: umap.umap_project(\n", + " embeddings, {\n", + " 'n_neighbors': 30,\n", + " 'min_dist': 0,\n", + " 'n_components': 2,\n", + " }\n", + " ),\n", + " 'clusters': lambda clusterable_projection: hdbscan.hdbscan_cluster(clusterable_projection, {\n", + " 'min_samples': 10,\n", + " 'min_cluster_size': 50\n", + " }),\n", + " 'projection': lambda embeddings: umap.umap_project(embeddings, {})\n", + " },\n", + " panels=[\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda limited_data, projection, clusters: weave.legacy.weave.panels.Plot(\n", + " limited_data,\n", + " x=lambda row, index: projection[index][0],\n", + " y=lambda row, index: projection[index][1],\n", + " label=lambda row, index: clusters[index],\n", + " ),\n", + " id='projection_plot',\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=24, h=12)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda projection_plot: projection_plot.selected_data(),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=24, h=12)\n", + " )\n", + " ]\n", + ")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "13a3497f", - "metadata": {}, - "outputs": [], - "source": [ - "import pandas\n", - "import weave\n", - "from weave.legacy.ecosystem import openai\n", - "from weave.legacy.ecosystem import umap\n", - "from weave.legacy.ecosystem import hdbscan" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e68f6c86", - "metadata": {}, - "outputs": [], - "source": [ - "#raw_data = pandas.read_csv('/Users/shawn/datasets/wandb_export_2023-06-03T15_01_20.066-07_00.csv')\n", - "raw_data = pandas.read_csv('wandb_export_2023-07-25T11_43_18.362-04_00.csv')\n", - "\n", - "#raw_data['request_timestamp'] = pandas.to_datetime(raw_data['request_timestamp'], unit='ms', utc=True)\n", - "\n", - "data = weave.save(weave.legacy.ops.dataframe_to_arrow(raw_data), 'data')\n", - "# from weave.legacy.panels_py import panel_autoboard\n", - "# panel_autoboard.auto_panels(data)\n", - "#data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "500e19b1", - "metadata": {}, - "outputs": [], - "source": [ - "data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e194b3ce", - "metadata": {}, - "outputs": [], - "source": [ - "weave.legacy.panels.Board(\n", - " vars={\n", - " 'data': data,\n", - " 'limit': 1005,\n", - " 'limited_data': lambda data, limit: data.limit(limit),\n", - " 'embeddings': lambda limited_data: openai.openai_embed(limited_data['question'], {\"model\": \"text-embedding-ada-002\"}),\n", - " 'clusterable_projection': lambda embeddings: umap.umap_project(\n", - " embeddings, {\n", - " 'n_neighbors': 30,\n", - " 'min_dist': 0,\n", - " 'n_components': 2,\n", - " }\n", - " ),\n", - " 'clusters': lambda clusterable_projection: hdbscan.hdbscan_cluster(clusterable_projection, {\n", - " 'min_samples': 10,\n", - " 'min_cluster_size': 50\n", - " }),\n", - " 'projection': lambda embeddings: umap.umap_project(embeddings, {})\n", - " },\n", - " panels=[\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda limited_data, projection, clusters: weave.legacy.panels.Plot(\n", - " limited_data,\n", - " x=lambda row, index: projection[index][0],\n", - " y=lambda row, index: projection[index][1],\n", - " label=lambda row, index: clusters[index],\n", - " ),\n", - " id='projection_plot',\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=24, h=12)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda projection_plot: projection_plot.selected_data(),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=24, h=12)\n", - " )\n", - " ]\n", - ")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/app/RunChain.ipynb b/weave/legacy/examples/experimental/app/RunChain.ipynb index 4c4a82a6338..02b02a89b63 100644 --- a/weave/legacy/examples/experimental/app/RunChain.ipynb +++ b/weave/legacy/examples/experimental/app/RunChain.ipynb @@ -1,177 +1,177 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "d6a6e7cf", - "metadata": {}, - "source": [ - "## Example of plotting RunChains\n", - "\n", - "As described here: https://github.com/wandb/runchain" - ] + "cells": [ + { + "cell_type": "markdown", + "id": "d6a6e7cf", + "metadata": {}, + "source": [ + "## Example of plotting RunChains\n", + "\n", + "As described here: https://github.com/wandb/runchain" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bd34fae3", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "from weave.legacy.weave.ecosystem import wandb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "baa0a8ac", + "metadata": {}, + "outputs": [], + "source": [ + "# big project, maybe 41 deep\n", + "#chain = wandb.run_chain('shawn/branchtest_400_200_1000/2ji8emz2')\n", + "\n", + "# big project, 61 deep\n", + "#chain = wandb.run_chain('shawn/branchtest_400_200_1000/sf0vvene')\n", + "\n", + "# big project, 141 deep\n", + "#chain = wandb.run_chain('shawn/branchtest_400_200_1000/hja8k932')\n", + "\n", + "# 3 deep, 200 metrics, 10k steps each (the default, this is fast for CI)\n", + "chain = wandb.run_chain('shawn/run_chain_20_200_10000/h4vz7n29')\n", + "\n", + "# 14 deep, 200 metrics, 10k steps each\n", + "#chain = wandb.run_chain('shawn/run_chain_20_200_10000/6wdyzlq9')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0431fff0", + "metadata": {}, + "outputs": [], + "source": [ + "# display the chain information\n", + "chain" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4fd52674", + "metadata": {}, + "outputs": [], + "source": [ + "# or fetch the chain object\n", + "weave.use(chain)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ee1bbb90", + "metadata": {}, + "outputs": [], + "source": [ + "weave.use(chain.segments.count())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "55b0b5c3", + "metadata": {}, + "outputs": [], + "source": [ + "# view the chain's metrics table\n", + "chain.history()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "67caf99a", + "metadata": {}, + "outputs": [], + "source": [ + "# Display plots from a RunChain. You need to do some resizing to seem them all currently.\n", + "\n", + "def plot_metric(run, metric_name):\n", + " return weave.legacy.weave.panels.Plot(\n", + " run.history(),\n", + " series=[\n", + " # Use two plot series, one for the avg line, and one for\n", + " # min/max area. We could reduce duplication here a bit more\n", + " # by updating the Plot API to allow common features of series\n", + " # to be factored out.\n", + " weave.legacy.weave.panels.Series(\n", + " run.history(),\n", + " select_functions={\n", + " 'x': lambda row, index: index.bin(\n", + " weave.legacy.weave.ops.numbers_bins_equal(\n", + " weave.legacy.weave.ops.make_list(a=0, b=run.history().count()), 250))[\"start\"],\n", + " 'y': lambda row: row[metric_name].avg()\n", + " },\n", + " groupby_dims=['x'],\n", + " constants=weave.legacy.weave.panels.PlotConstants(\n", + " mark='line'\n", + " )\n", + " ),\n", + " weave.legacy.weave.panels.Series(\n", + " run.history(),\n", + " select_functions={\n", + " 'x': lambda row, index: index.bin(\n", + " weave.legacy.weave.ops.numbers_bins_equal(\n", + " weave.legacy.weave.ops.make_list(a=0, b=run.history().count()), 250))[\"start\"],\n", + " 'y': lambda row: row[metric_name].min(),\n", + " 'y2': lambda row: row[metric_name].max(),\n", + " },\n", + " groupby_dims=['x'],\n", + " constants=weave.legacy.weave.panels.PlotConstants(\n", + " mark='area'\n", + " )\n", + " )\n", + " ],\n", + " )\n", + "\n", + "board = weave.legacy.weave.panels.Board(\n", + " vars={\n", + " 'run_chain': chain,\n", + " },\n", + " panels=[\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda run_chain: weave.legacy.weave.panels.Group(\n", + " layoutMode='flow',\n", + " #gridConfig=bank.flow_nxn(2, 3),\n", + " items={k: plot_metric(run_chain, k) for k in ['metric' + str(i) for i in range(10)]}\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=24, h=12)\n", + " )\n", + " ]\n", + ")\n", + "board" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "bd34fae3", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "from weave.legacy.ecosystem import wandb" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "baa0a8ac", - "metadata": {}, - "outputs": [], - "source": [ - "# big project, maybe 41 deep\n", - "#chain = wandb.run_chain('shawn/branchtest_400_200_1000/2ji8emz2')\n", - "\n", - "# big project, 61 deep\n", - "#chain = wandb.run_chain('shawn/branchtest_400_200_1000/sf0vvene')\n", - "\n", - "# big project, 141 deep\n", - "#chain = wandb.run_chain('shawn/branchtest_400_200_1000/hja8k932')\n", - "\n", - "# 3 deep, 200 metrics, 10k steps each (the default, this is fast for CI)\n", - "chain = wandb.run_chain('shawn/run_chain_20_200_10000/h4vz7n29')\n", - "\n", - "# 14 deep, 200 metrics, 10k steps each\n", - "#chain = wandb.run_chain('shawn/run_chain_20_200_10000/6wdyzlq9')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "0431fff0", - "metadata": {}, - "outputs": [], - "source": [ - "# display the chain information\n", - "chain" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4fd52674", - "metadata": {}, - "outputs": [], - "source": [ - "# or fetch the chain object\n", - "weave.use(chain)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ee1bbb90", - "metadata": {}, - "outputs": [], - "source": [ - "weave.use(chain.segments.count())" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "55b0b5c3", - "metadata": {}, - "outputs": [], - "source": [ - "# view the chain's metrics table\n", - "chain.history()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "67caf99a", - "metadata": {}, - "outputs": [], - "source": [ - "# Display plots from a RunChain. You need to do some resizing to seem them all currently.\n", - "\n", - "def plot_metric(run, metric_name):\n", - " return weave.legacy.panels.Plot(\n", - " run.history(),\n", - " series=[\n", - " # Use two plot series, one for the avg line, and one for\n", - " # min/max area. We could reduce duplication here a bit more\n", - " # by updating the Plot API to allow common features of series\n", - " # to be factored out.\n", - " weave.legacy.panels.Series(\n", - " run.history(),\n", - " select_functions={\n", - " 'x': lambda row, index: index.bin(\n", - " weave.legacy.ops.numbers_bins_equal(\n", - " weave.legacy.ops.make_list(a=0, b=run.history().count()), 250))[\"start\"],\n", - " 'y': lambda row: row[metric_name].avg()\n", - " },\n", - " groupby_dims=['x'],\n", - " constants=weave.legacy.panels.PlotConstants(\n", - " mark='line'\n", - " )\n", - " ),\n", - " weave.legacy.panels.Series(\n", - " run.history(),\n", - " select_functions={\n", - " 'x': lambda row, index: index.bin(\n", - " weave.legacy.ops.numbers_bins_equal(\n", - " weave.legacy.ops.make_list(a=0, b=run.history().count()), 250))[\"start\"],\n", - " 'y': lambda row: row[metric_name].min(),\n", - " 'y2': lambda row: row[metric_name].max(),\n", - " },\n", - " groupby_dims=['x'],\n", - " constants=weave.legacy.panels.PlotConstants(\n", - " mark='area'\n", - " )\n", - " )\n", - " ],\n", - " )\n", - "\n", - "board = weave.legacy.panels.Board(\n", - " vars={\n", - " 'run_chain': chain,\n", - " },\n", - " panels=[\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda run_chain: weave.legacy.panels.Group(\n", - " layoutMode='flow',\n", - " #gridConfig=bank.flow_nxn(2, 3),\n", - " items={k: plot_metric(run_chain, k) for k in ['metric' + str(i) for i in range(10)]}\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=24, h=12)\n", - " )\n", - " ]\n", - ")\n", - "board" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/app/beautiful_runs.ipynb b/weave/legacy/examples/experimental/app/beautiful_runs.ipynb index a4d880471db..d1b168c35e2 100644 --- a/weave/legacy/examples/experimental/app/beautiful_runs.ipynb +++ b/weave/legacy/examples/experimental/app/beautiful_runs.ipynb @@ -1,161 +1,161 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "632b052f", - "metadata": {}, - "source": [ - "## Beautiful run plot rendering\n", - "\n", - "This notebook shows how to create a Weave Board with W&B workspace-like behavior.\n", - "\n", - "We group data along the x-axis into 250 bins, and exactly compute the min / max / avg of each bucket. Unlike the W&B workspace, this computation is exact because it happens on unsampled data in the Weave engine. Only the final grouped result is sent back to the UI.\n", - "\n", - "You can zoom on any of the plots by dragging a box. All plots are zoom synchronized using Weave 2-way binding, and all plots automatically rebin for the new window.\n", - "\n", - "We've also factored out a \"groupby\" variable so you can group by run parameters from the varbar. You can change it to 'id' or 'config.b' to try other groupings.\n", - "\n", - "All of this behavior is complete defined by the code below.\n", - "\n", - "_TODO: There is one major outstanding issue here: we're using the start of the bucket for the x-coordinate\n", - "instead of the midpoint! Fix this!_\n" - ] + "cells": [ + { + "cell_type": "markdown", + "id": "632b052f", + "metadata": {}, + "source": [ + "## Beautiful run plot rendering\n", + "\n", + "This notebook shows how to create a Weave Board with W&B workspace-like behavior.\n", + "\n", + "We group data along the x-axis into 250 bins, and exactly compute the min / max / avg of each bucket. Unlike the W&B workspace, this computation is exact because it happens on unsampled data in the Weave engine. Only the final grouped result is sent back to the UI.\n", + "\n", + "You can zoom on any of the plots by dragging a box. All plots are zoom synchronized using Weave 2-way binding, and all plots automatically rebin for the new window.\n", + "\n", + "We've also factored out a \"groupby\" variable so you can group by run parameters from the varbar. You can change it to 'id' or 'config.b' to try other groupings.\n", + "\n", + "All of this behavior is complete defined by the code below.\n", + "\n", + "_TODO: There is one major outstanding issue here: we're using the start of the bucket for the x-coordinate\n", + "instead of the midpoint! Fix this!_\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d2492048", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "from weave.legacy.scripts import syndata" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "af8e89a5", + "metadata": {}, + "outputs": [], + "source": [ + "# Generate synthetic run data for now\n", + "runs = weave.save(syndata.random_runs(10, 10000, 10), 'runs')\n", + "# Doing this unnest operation in the UI doesn't work (like in the varbar). I don't remember\n", + "# if the types are wrong, or what the specific situation is.\n", + "# TODO: Figure out why we have to do this!\n", + "unnested_runs = weave.save(weave.use(runs.unnest()), 'random_runs_unnested')\n", + "#unnested_runs" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "69f0792f", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "def plot_for_metric(metric_name):\n", + " return weave.legacy.weave.panels.BoardPanel(\n", + " lambda runs, groupby, zoom_domain_x, bin_domain_x: weave.legacy.weave.panels.Plot(\n", + " runs,\n", + " series=[\n", + " # Use two plot series, one for the avg line, and one for\n", + " # min/max area. We could reduce duplication here a bit more\n", + " # by updating the Plot API to allow common features of series\n", + " # to be factored out.\n", + " weave.legacy.weave.panels.Series(\n", + " runs,\n", + " select_functions={\n", + " 'x': lambda row: row[\"history.step\"].bin(\n", + " weave.legacy.weave.ops.numbers_bins_equal(bin_domain_x, 250))[\"start\"],\n", + " 'label': lambda row: row[groupby],\n", + " 'y': lambda row: row[\"history\"][metric_name].avg()\n", + " },\n", + " groupby_dims=['x', 'label'],\n", + " constants=weave.legacy.weave.panels.PlotConstants(\n", + " mark='line'\n", + " )\n", + " ),\n", + " weave.legacy.weave.panels.Series(\n", + " runs,\n", + " select_functions={\n", + " 'x': lambda row: row[\"history.step\"].bin(\n", + " weave.legacy.weave.ops.numbers_bins_equal(bin_domain_x, 250))[\"start\"],\n", + " 'label': lambda row: row[groupby],\n", + " 'y': lambda row: row[\"history\"][metric_name].min(),\n", + " 'y2': lambda row: row[\"history\"][metric_name].max(),\n", + " },\n", + " groupby_dims=['x', 'label'],\n", + " constants=weave.legacy.weave.panels.PlotConstants(\n", + " mark='area'\n", + " )\n", + " )\n", + " ],\n", + " domain_x=zoom_domain_x,\n", + " ),\n", + " #layout=weave.legacy.weave.panels.BoardPanelLayout(x=x, y=0, w=12, h=6)\n", + " )\n", + "\n", + "board = weave.legacy.weave.panels.Board(\n", + " vars={\n", + " 'runs': unnested_runs,\n", + " 'groupby': 'config.a',\n", + " # This holds the zoom boundaries, and is two-way synchronized with the plot zooms\n", + " 'zoom_domain_x': None,\n", + " # This is the extent of the step field in our data (the minimum and maxium values)\n", + " 'step_domain': lambda runs: weave.legacy.weave.ops.make_list(\n", + " a=weave.legacy.weave.ops.numbers_min(runs['history']['step']),\n", + " b=weave.legacy.weave.ops.numbers_max(runs['history']['step'])),\n", + " # The \"domain\" used for binning, which is the zoom range if its non-null, otherwise\n", + " # the step_extent\n", + " 'bin_domain_x': lambda zoom_domain_x, step_domain: zoom_domain_x.coalesce(step_domain)\n", + " },\n", + " # TODO: Use EachColumn to do this automatically for all metrics.\n", + " panels=[\n", + " plot_for_metric('metric0'),\n", + " plot_for_metric('metric1'),\n", + " plot_for_metric('metric2'),\n", + " plot_for_metric('metric3'),\n", + " plot_for_metric('metric4'),\n", + " plot_for_metric('metric5'),\n", + " plot_for_metric('metric6'),\n", + " plot_for_metric('metric7'),\n", + " ]\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3f157310", + "metadata": {}, + "outputs": [], + "source": [ + "board" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "d2492048", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "from weave.legacy.scripts import syndata" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "af8e89a5", - "metadata": {}, - "outputs": [], - "source": [ - "# Generate synthetic run data for now\n", - "runs = weave.save(syndata.random_runs(10, 10000, 10), 'runs')\n", - "# Doing this unnest operation in the UI doesn't work (like in the varbar). I don't remember\n", - "# if the types are wrong, or what the specific situation is.\n", - "# TODO: Figure out why we have to do this!\n", - "unnested_runs = weave.save(weave.use(runs.unnest()), 'random_runs_unnested')\n", - "#unnested_runs" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "69f0792f", - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "def plot_for_metric(metric_name):\n", - " return weave.legacy.panels.BoardPanel(\n", - " lambda runs, groupby, zoom_domain_x, bin_domain_x: weave.legacy.panels.Plot(\n", - " runs,\n", - " series=[\n", - " # Use two plot series, one for the avg line, and one for\n", - " # min/max area. We could reduce duplication here a bit more\n", - " # by updating the Plot API to allow common features of series\n", - " # to be factored out.\n", - " weave.legacy.panels.Series(\n", - " runs,\n", - " select_functions={\n", - " 'x': lambda row: row[\"history.step\"].bin(\n", - " weave.legacy.ops.numbers_bins_equal(bin_domain_x, 250))[\"start\"],\n", - " 'label': lambda row: row[groupby],\n", - " 'y': lambda row: row[\"history\"][metric_name].avg()\n", - " },\n", - " groupby_dims=['x', 'label'],\n", - " constants=weave.legacy.panels.PlotConstants(\n", - " mark='line'\n", - " )\n", - " ),\n", - " weave.legacy.panels.Series(\n", - " runs,\n", - " select_functions={\n", - " 'x': lambda row: row[\"history.step\"].bin(\n", - " weave.legacy.ops.numbers_bins_equal(bin_domain_x, 250))[\"start\"],\n", - " 'label': lambda row: row[groupby],\n", - " 'y': lambda row: row[\"history\"][metric_name].min(),\n", - " 'y2': lambda row: row[\"history\"][metric_name].max(),\n", - " },\n", - " groupby_dims=['x', 'label'],\n", - " constants=weave.legacy.panels.PlotConstants(\n", - " mark='area'\n", - " )\n", - " )\n", - " ],\n", - " domain_x=zoom_domain_x,\n", - " ),\n", - " #layout=weave.legacy.panels.BoardPanelLayout(x=x, y=0, w=12, h=6)\n", - " )\n", - "\n", - "board = weave.legacy.panels.Board(\n", - " vars={\n", - " 'runs': unnested_runs,\n", - " 'groupby': 'config.a',\n", - " # This holds the zoom boundaries, and is two-way synchronized with the plot zooms\n", - " 'zoom_domain_x': None,\n", - " # This is the extent of the step field in our data (the minimum and maxium values)\n", - " 'step_domain': lambda runs: weave.legacy.ops.make_list(\n", - " a=weave.legacy.ops.numbers_min(runs['history']['step']),\n", - " b=weave.legacy.ops.numbers_max(runs['history']['step'])),\n", - " # The \"domain\" used for binning, which is the zoom range if its non-null, otherwise\n", - " # the step_extent\n", - " 'bin_domain_x': lambda zoom_domain_x, step_domain: zoom_domain_x.coalesce(step_domain)\n", - " },\n", - " # TODO: Use EachColumn to do this automatically for all metrics.\n", - " panels=[\n", - " plot_for_metric('metric0'),\n", - " plot_for_metric('metric1'),\n", - " plot_for_metric('metric2'),\n", - " plot_for_metric('metric3'),\n", - " plot_for_metric('metric4'),\n", - " plot_for_metric('metric5'),\n", - " plot_for_metric('metric6'),\n", - " plot_for_metric('metric7'),\n", - " ]\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3f157310", - "metadata": {}, - "outputs": [], - "source": [ - "board" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/app/scenario_compare.ipynb b/weave/legacy/examples/experimental/app/scenario_compare.ipynb index befb14b8f0a..338ef5ae813 100644 --- a/weave/legacy/examples/experimental/app/scenario_compare.ipynb +++ b/weave/legacy/examples/experimental/app/scenario_compare.ipynb @@ -1,176 +1,176 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "67551526", - "metadata": {}, - "outputs": [], - "source": [ - "import random\n", - "import weave\n", - "# Weave package now defaults to eager mode, but lazy mode required for this example notebook for now.\n", - "weave.use_lazy_execution()\n", - "from weave.legacy.ecosystem import scenario" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "67551526", + "metadata": {}, + "outputs": [], + "source": [ + "import random\n", + "import weave\n", + "# Weave package now defaults to eager mode, but lazy mode required for this example notebook for now.\n", + "weave.use_lazy_execution()\n", + "from weave.legacy.weave.ecosystem import scenario" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6e12d2d0", + "metadata": {}, + "outputs": [], + "source": [ + "# a = weave.save(5)\n", + "# b = a + 2\n", + "# weave.type_of(b)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4882d74b", + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "def make_run(n_scenarios, n) -> list[scenario.ScenarioResult]:\n", + " return [\n", + " scenario.ScenarioResult(\n", + " scenario_id=str(i),\n", + " metric1=random.expovariate(n / 33),\n", + " metric2=random.gauss(42, n / 100),\n", + " metric3=random.triangular(n, 11),\n", + " metric4=random.random() * random.random() * n,\n", + " metric5=random.random(),\n", + " metric6=random.betavariate(0.01, n / 2),\n", + " )\n", + " for i in range(n_scenarios)\n", + " ]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "218e28e2", + "metadata": {}, + "outputs": [], + "source": [ + "#panel_input = weave.save({'baseline': make_run(10), 'candidate': make_run(10)}, name='panel_input')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "984bcb3c", + "metadata": {}, + "outputs": [], + "source": [ + "#panel_input" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7e1890ca", + "metadata": {}, + "outputs": [], + "source": [ + "# make some runs\n", + "\n", + "weave.save(make_run(100, 1), name='run1:latest')\n", + "weave.save(make_run(100, 2), name='run2:latest')\n", + "weave.save(make_run(100, 3), name='run3:latest')\n", + "weave.save(make_run(100, 4), name='run4:latest')\n", + "weave.save(make_run(100, 5), name='run5:latest')\n", + "pass" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9f2b3a72", + "metadata": {}, + "outputs": [], + "source": [ + "# Ugly. We need to compute the Weave type right now.\n", + "# TODO: Fix\n", + "from weave.legacy.weave import infer_types\n", + "run_type = weave.types.List(infer_types.python_type_to_type(scenario.ScenarioResult))\n", + "\n", + "import time\n", + "runs = weave.legacy.weave.ops.objects(run_type, 'latest', int(time.time()))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "89e4b718", + "metadata": {}, + "outputs": [], + "source": [ + "panel = weave.legacy.weave.panels.Group(\n", + " preferHorizontal=True,\n", + " items={\n", + " \"sidebar\": weave.legacy.weave.panels.Group(\n", + " style=\"width: 200px; padding: 16px;\",\n", + " items={\n", + " \"baseline\": weave.legacy.weave.panels.ObjectPicker(runs, label='baseline'),\n", + " \"candidate\": weave.legacy.weave.panels.ObjectPicker(runs, label='candidate')\n", + " }\n", + " ),\n", + " \"main\": lambda sidebar: weave.legacy.weave.panels.Group(\n", + " items={\n", + " \"tables\": weave.legacy.weave.panels.Group(\n", + " style=\"height: 300px;\",\n", + " preferHorizontal=True,\n", + " equalSize=True,\n", + " items={\n", + " \"baseline_table\": weave.legacy.weave.panels.LabeledItem(\n", + " label=\"Baseline Table\",\n", + " item=weave.legacy.weave.ops.execute(sidebar.config.items['baseline'].config.choice).get()\n", + " ),\n", + " \"candidate_table\": weave.legacy.weave.panels.LabeledItem(\n", + " label=\"Candidate Table\",\n", + " item=weave.legacy.weave.ops.execute(sidebar.config.items['candidate'].config.choice).get()\n", + " )\n", + " }),\n", + " \"plots\": \n", + " weave.legacy.weave.panels.LabeledItem(\n", + " label='Scenario plots',\n", + " item=scenario.MetricsBankPanel(\n", + " weave.legacy.weave.ops.dict_(\n", + " baseline=weave.legacy.weave.ops.execute(sidebar.config.items['baseline'].config.choice).get(),\n", + " candidate=weave.legacy.weave.ops.execute(sidebar.config.items['candidate'].config.choice).get()\n", + " ))\n", + " )\n", + "\n", + " }\n", + " )\n", + " })\n", + "panel" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "6e12d2d0", - "metadata": {}, - "outputs": [], - "source": [ - "# a = weave.save(5)\n", - "# b = a + 2\n", - "# weave.type_of(b)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4882d74b", - "metadata": {}, - "outputs": [], - "source": [ - "import math\n", - "def make_run(n_scenarios, n) -> list[scenario.ScenarioResult]:\n", - " return [\n", - " scenario.ScenarioResult(\n", - " scenario_id=str(i),\n", - " metric1=random.expovariate(n / 33),\n", - " metric2=random.gauss(42, n / 100),\n", - " metric3=random.triangular(n, 11),\n", - " metric4=random.random() * random.random() * n,\n", - " metric5=random.random(),\n", - " metric6=random.betavariate(0.01, n / 2),\n", - " )\n", - " for i in range(n_scenarios)\n", - " ]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "218e28e2", - "metadata": {}, - "outputs": [], - "source": [ - "#panel_input = weave.save({'baseline': make_run(10), 'candidate': make_run(10)}, name='panel_input')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "984bcb3c", - "metadata": {}, - "outputs": [], - "source": [ - "#panel_input" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7e1890ca", - "metadata": {}, - "outputs": [], - "source": [ - "# make some runs\n", - "\n", - "weave.save(make_run(100, 1), name='run1:latest')\n", - "weave.save(make_run(100, 2), name='run2:latest')\n", - "weave.save(make_run(100, 3), name='run3:latest')\n", - "weave.save(make_run(100, 4), name='run4:latest')\n", - "weave.save(make_run(100, 5), name='run5:latest')\n", - "pass" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9f2b3a72", - "metadata": {}, - "outputs": [], - "source": [ - "# Ugly. We need to compute the Weave type right now.\n", - "# TODO: Fix\n", - "from weave.legacy import infer_types\n", - "run_type = weave.types.List(infer_types.python_type_to_type(scenario.ScenarioResult))\n", - "\n", - "import time\n", - "runs = weave.legacy.ops.objects(run_type, 'latest', int(time.time()))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "89e4b718", - "metadata": {}, - "outputs": [], - "source": [ - "panel = weave.legacy.panels.Group(\n", - " preferHorizontal=True,\n", - " items={\n", - " \"sidebar\": weave.legacy.panels.Group(\n", - " style=\"width: 200px; padding: 16px;\",\n", - " items={\n", - " \"baseline\": weave.legacy.panels.ObjectPicker(runs, label='baseline'),\n", - " \"candidate\": weave.legacy.panels.ObjectPicker(runs, label='candidate')\n", - " }\n", - " ),\n", - " \"main\": lambda sidebar: weave.legacy.panels.Group(\n", - " items={\n", - " \"tables\": weave.legacy.panels.Group(\n", - " style=\"height: 300px;\",\n", - " preferHorizontal=True,\n", - " equalSize=True,\n", - " items={\n", - " \"baseline_table\": weave.legacy.panels.LabeledItem(\n", - " label=\"Baseline Table\",\n", - " item=weave.legacy.ops.execute(sidebar.config.items['baseline'].config.choice).get()\n", - " ),\n", - " \"candidate_table\": weave.legacy.panels.LabeledItem(\n", - " label=\"Candidate Table\",\n", - " item=weave.legacy.ops.execute(sidebar.config.items['candidate'].config.choice).get()\n", - " )\n", - " }),\n", - " \"plots\": \n", - " weave.legacy.panels.LabeledItem(\n", - " label='Scenario plots',\n", - " item=scenario.MetricsBankPanel(\n", - " weave.legacy.ops.dict_(\n", - " baseline=weave.legacy.ops.execute(sidebar.config.items['baseline'].config.choice).get(),\n", - " candidate=weave.legacy.ops.execute(sidebar.config.items['candidate'].config.choice).get()\n", - " ))\n", - " )\n", - "\n", - " }\n", - " )\n", - " })\n", - "panel" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/bert_viz.ipynb b/weave/legacy/examples/experimental/bert_viz.ipynb index a971cf76964..869a4961b13 100644 --- a/weave/legacy/examples/experimental/bert_viz.ipynb +++ b/weave/legacy/examples/experimental/bert_viz.ipynb @@ -1,71 +1,71 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "f4fcc7fa", - "metadata": {}, - "source": [ - "# BertViz + HuggingFace: Visualize Attention for Language Models\n", - "\n", - "Integrates the amazing [bertviz package](https://github.com/jessevig/bertviz) to visualize the attention for a provided language model (here loaded in from Hugging Face).\n", - "\n", - "## Settings to explore\n", - "\n", - "* model name: select a different model from HuggingFace (or add your own :)\n", - "* input text: edit the text sample on which to visualize attention \n", - "* visualization type: try toggling the output panel type to see the full attention map across heads and layers :)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d85f7aaa", - "metadata": { - "execution": { - "iopub.execute_input": "2023-06-02T01:46:20.864046Z", - "iopub.status.busy": "2023-06-02T01:46:20.863903Z", - "iopub.status.idle": "2023-06-02T01:46:26.125190Z", - "shell.execute_reply": "2023-06-02T01:46:26.124715Z" + "cells": [ + { + "cell_type": "markdown", + "id": "f4fcc7fa", + "metadata": {}, + "source": [ + "# BertViz + HuggingFace: Visualize Attention for Language Models\n", + "\n", + "Integrates the amazing [bertviz package](https://github.com/jessevig/bertviz) to visualize the attention for a provided language model (here loaded in from Hugging Face).\n", + "\n", + "## Settings to explore\n", + "\n", + "* model name: select a different model from HuggingFace (or add your own :)\n", + "* input text: edit the text sample on which to visualize attention \n", + "* visualization type: try toggling the output panel type to see the full attention map across heads and layers :)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d85f7aaa", + "metadata": { + "execution": { + "iopub.execute_input": "2023-06-02T01:46:20.864046Z", + "iopub.status.busy": "2023-06-02T01:46:20.863903Z", + "iopub.status.idle": "2023-06-02T01:46:26.125190Z", + "shell.execute_reply": "2023-06-02T01:46:26.124715Z" + } + }, + "outputs": [], + "source": [ + "import weave\n", + "# Weave package now defaults to eager mode, but lazy mode required for this example notebook for now.\n", + "weave.use_lazy_execution()\n", + "from weave.legacy.weave.ecosystem.huggingface import huggingface\n", + "\n", + "# Call a hugging face model\n", + "hf_model = huggingface().model('gpt2')\n", + "model_output = hf_model.call('The cat sat on the mat')\n", + "\n", + "# The type of .attention() is huggingface.ModelOutputType. Our bertviz panel is\n", + "# registered as the only handler for that type, so it will automatically get rendered.\n", + "\n", + "# model_output.attention()\n", + "model_output" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" } - }, - "outputs": [], - "source": [ - "import weave\n", - "# Weave package now defaults to eager mode, but lazy mode required for this example notebook for now.\n", - "weave.use_lazy_execution()\n", - "from weave.legacy.ecosystem.huggingface import huggingface\n", - "\n", - "# Call a hugging face model\n", - "hf_model = huggingface().model('gpt2')\n", - "model_output = hf_model.call('The cat sat on the mat')\n", - "\n", - "# The type of .attention() is huggingface.ModelOutputType. Our bertviz panel is\n", - "# registered as the only handler for that type, so it will automatically get rendered.\n", - "\n", - "# model_output.attention()\n", - "model_output" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/composite_histograms.ipynb b/weave/legacy/examples/experimental/composite_histograms.ipynb index 08cce9ad62e..e74e0c47130 100644 --- a/weave/legacy/examples/experimental/composite_histograms.ipynb +++ b/weave/legacy/examples/experimental/composite_histograms.ipynb @@ -1,136 +1,136 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "d70e6c48", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "from weave.legacy.ecosystem import lens" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "d70e6c48", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "from weave.legacy.weave.ecosystem import lens" + ] + }, + { + "cell_type": "markdown", + "id": "c3d89416", + "metadata": {}, + "source": [ + "# Composite Histograms\n", + "\n", + "Let's plot some histograms.\n", + "\n", + "## Base case: One series, no customization" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e739d513", + "metadata": {}, + "outputs": [], + "source": [ + "lens.histogram([[1.0, 2, 3, -1.4]], 1.0, \"Composite Histogram\", ['series'])" + ] + }, + { + "cell_type": "markdown", + "id": "81fd5769", + "metadata": {}, + "source": [ + "## Two series with customization" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "301be405", + "metadata": {}, + "outputs": [], + "source": [ + "lens.histogram([[-1.8, -0.4, 0.1, -0.9, -0.77, 0.5, 0.7, 0.2, 0.1, 0.8],[0.9, 0.4, 0.5, 0.6, 1.2, 1.5, 1.6, 1.7, 2, 2.4, 2.3, 2.1]], 0.5, \"My Histogram\", [\"series A\", \"series B\"])" + ] + }, + { + "cell_type": "markdown", + "id": "ee794dd4", + "metadata": {}, + "source": [ + "## Three series" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fba3acec", + "metadata": {}, + "outputs": [], + "source": [ + "lens.histogram([[1.0, 2, 3, -1.4],[8.1, 2.2, 3.3, 5.6, 1.1], [1.6, 1.7, 1.8, -2.0, 5]], 0.5, 'Composite histogram', ['a', 'b', 'c'])" + ] + }, + { + "cell_type": "markdown", + "id": "ac8ee3eb", + "metadata": {}, + "source": [ + "## More than three series :)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "070314da", + "metadata": {}, + "outputs": [], + "source": [ + "lens.histogram([[1.0, -20.0, -25.0, -15.0, 2.0, 3.0, 2.0, 2.0, 2.0, 2.0, 4.0, 5.0, 6.0], [1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 3.0, 3.0, 3.0, 3.0, 2.0, 2.0, 2.0],[16.2, 17.9, 18.2, 2.3, -5.2, 6.0, 7.2, -10.9, 8.2,41.0], [1.3, 2.2, 5.3, 7.7, 8.8, 9.0, 2.0, 3.2, 43.7, 4.2, 5.1, 4.5, 6.9], [1.0, 2.1, 3.0, 4.1, 19.0, 6.0, 12.2, 14.9, 15.0, 16.1, 17.2]], 5.0, 'Composite histogram', ['a', 'b', 'c', 'd', 'e'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2245a600", + "metadata": {}, + "outputs": [], + "source": [ + "# weave-test-skip: in-notebook ops don't yet work with server\n", + "# super simple example for now to illustrate fetching W&B data & plotting histograms\n", + "from wandb.apis import public as wandb_api\n", + "from PIL import Image\n", + "\n", + "@weave.op(render_info={\"type\": \"function\"})\n", + "def run_accuracy_barchart(runs: list[wandb_api.Run]) -> Image.Image:\n", + " runs = list(runs) #[:100] # could shorten this list\n", + " acc = [r.summary_metrics.get(\"acc\") or 0.0 for r in runs]\n", + " car_acc = [r.summary_metrics.get(\"car_acc\") or 0.0 for r in runs]\n", + " traffic_acc = [r.summary_metrics.get(\"traffic_acc\") or 0.0 for r in runs]\n", + " road_acc = [r.summary_metrics.get(\"road_acc\") or 0.0 for r in runs]\n", + " \n", + " # filter out NaNs\n", + " for l in [acc, car_acc, traffic_acc, road_acc]:\n", + " if \"NaN\" in l:\n", + " l = l.remove(\"NaN\")\n", + "\n", + " return weave.use(lens.histogram([acc, car_acc, traffic_acc, road_acc],\n", + " bin_size=0.05,\n", + " chart_title=\"Semantic Segmentation Accuracy Across Experiments by Label Class\", \n", + " series_names=[\"Overall acc\", \"Car acc\", \"Traffic acc\", \"Road acc\"]\n", + " )\n", + " )\n", + "\n", + "runs = weave.legacy.weave.ops.project('stacey', 'deep-drive').runs()\n", + "run_accuracy_barchart(runs)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + } }, - { - "cell_type": "markdown", - "id": "c3d89416", - "metadata": {}, - "source": [ - "# Composite Histograms\n", - "\n", - "Let's plot some histograms.\n", - "\n", - "## Base case: One series, no customization" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e739d513", - "metadata": {}, - "outputs": [], - "source": [ - "lens.histogram([[1.0, 2, 3, -1.4]], 1.0, \"Composite Histogram\", ['series'])" - ] - }, - { - "cell_type": "markdown", - "id": "81fd5769", - "metadata": {}, - "source": [ - "## Two series with customization" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "301be405", - "metadata": {}, - "outputs": [], - "source": [ - "lens.histogram([[-1.8, -0.4, 0.1, -0.9, -0.77, 0.5, 0.7, 0.2, 0.1, 0.8],[0.9, 0.4, 0.5, 0.6, 1.2, 1.5, 1.6, 1.7, 2, 2.4, 2.3, 2.1]], 0.5, \"My Histogram\", [\"series A\", \"series B\"])" - ] - }, - { - "cell_type": "markdown", - "id": "ee794dd4", - "metadata": {}, - "source": [ - "## Three series" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "fba3acec", - "metadata": {}, - "outputs": [], - "source": [ - "lens.histogram([[1.0, 2, 3, -1.4],[8.1, 2.2, 3.3, 5.6, 1.1], [1.6, 1.7, 1.8, -2.0, 5]], 0.5, 'Composite histogram', ['a', 'b', 'c'])" - ] - }, - { - "cell_type": "markdown", - "id": "ac8ee3eb", - "metadata": {}, - "source": [ - "## More than three series :)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "070314da", - "metadata": {}, - "outputs": [], - "source": [ - "lens.histogram([[1.0, -20.0, -25.0, -15.0, 2.0, 3.0, 2.0, 2.0, 2.0, 2.0, 4.0, 5.0, 6.0], [1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 3.0, 3.0, 3.0, 3.0, 2.0, 2.0, 2.0],[16.2, 17.9, 18.2, 2.3, -5.2, 6.0, 7.2, -10.9, 8.2,41.0], [1.3, 2.2, 5.3, 7.7, 8.8, 9.0, 2.0, 3.2, 43.7, 4.2, 5.1, 4.5, 6.9], [1.0, 2.1, 3.0, 4.1, 19.0, 6.0, 12.2, 14.9, 15.0, 16.1, 17.2]], 5.0, 'Composite histogram', ['a', 'b', 'c', 'd', 'e'])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2245a600", - "metadata": {}, - "outputs": [], - "source": [ - "# weave-test-skip: in-notebook ops don't yet work with server\n", - "# super simple example for now to illustrate fetching W&B data & plotting histograms\n", - "from wandb.apis import public as wandb_api\n", - "from PIL import Image\n", - "\n", - "@weave.op(render_info={\"type\": \"function\"})\n", - "def run_accuracy_barchart(runs: list[wandb_api.Run]) -> Image.Image:\n", - " runs = list(runs) #[:100] # could shorten this list\n", - " acc = [r.summary_metrics.get(\"acc\") or 0.0 for r in runs]\n", - " car_acc = [r.summary_metrics.get(\"car_acc\") or 0.0 for r in runs]\n", - " traffic_acc = [r.summary_metrics.get(\"traffic_acc\") or 0.0 for r in runs]\n", - " road_acc = [r.summary_metrics.get(\"road_acc\") or 0.0 for r in runs]\n", - " \n", - " # filter out NaNs\n", - " for l in [acc, car_acc, traffic_acc, road_acc]:\n", - " if \"NaN\" in l:\n", - " l = l.remove(\"NaN\")\n", - "\n", - " return weave.use(lens.histogram([acc, car_acc, traffic_acc, road_acc],\n", - " bin_size=0.05,\n", - " chart_title=\"Semantic Segmentation Accuracy Across Experiments by Label Class\", \n", - " series_names=[\"Overall acc\", \"Car acc\", \"Traffic acc\", \"Road acc\"]\n", - " )\n", - " )\n", - "\n", - "runs = weave.legacy.ops.project('stacey', 'deep-drive').runs()\n", - "run_accuracy_barchart(runs)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/dir_browsing.ipynb b/weave/legacy/examples/experimental/dir_browsing.ipynb index eaa36563837..2e5d0e3d569 100644 --- a/weave/legacy/examples/experimental/dir_browsing.ipynb +++ b/weave/legacy/examples/experimental/dir_browsing.ipynb @@ -1,26 +1,26 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "79d64dea", - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "import weave\n", - "\n", - "#weave.legacy.ops.local_path(os.path.abspath('../weave/testdata'))" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "79d64dea", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import weave\n", + "\n", + "#weave.legacy.weave.ops.local_path(os.path.abspath('../weave/testdata'))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/ecosystem.ipynb b/weave/legacy/examples/experimental/ecosystem.ipynb index b8f6c86266d..2adc1728b23 100644 --- a/weave/legacy/examples/experimental/ecosystem.ipynb +++ b/weave/legacy/examples/experimental/ecosystem.ipynb @@ -1,25 +1,25 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "3d5d0d34", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "from weave.legacy.ecosystem import ecosystem\n", - "ecosystem()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "3d5d0d34", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "from weave.legacy.weave.ecosystem import ecosystem\n", + "ecosystem()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/huggingface_datasets.ipynb b/weave/legacy/examples/experimental/huggingface_datasets.ipynb index 76e7365cc2d..8f8074494b8 100644 --- a/weave/legacy/examples/experimental/huggingface_datasets.ipynb +++ b/weave/legacy/examples/experimental/huggingface_datasets.ipynb @@ -1,89 +1,89 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "897e0314", - "metadata": {}, - "source": [ - "# HuggingFace Datasets\n", - "\n", - "A quick overview of exploring [Datasets from HuggingFace](https://huggingface.co/docs/datasets/index).\n", - "\n", - "### Known issues\n", - "\n", - "- Using a dataset often reboots the weave server the first time, causing the first request to fail. Run again and it'll work\n", - "- We only load 100 items" - ] + "cells": [ + { + "cell_type": "markdown", + "id": "897e0314", + "metadata": {}, + "source": [ + "# HuggingFace Datasets\n", + "\n", + "A quick overview of exploring [Datasets from HuggingFace](https://huggingface.co/docs/datasets/index).\n", + "\n", + "### Known issues\n", + "\n", + "- Using a dataset often reboots the weave server the first time, causing the first request to fail. Run again and it'll work\n", + "- We only load 100 items" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ba78a68c", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "# Weave package now defaults to eager mode, but lazy mode required for this example notebook for now.\n", + "weave.use_lazy_execution()\n", + "from weave.legacy.weave.ecosystem import huggingface as hf" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3e3b90c5", + "metadata": {}, + "outputs": [], + "source": [ + "hf.hf_datasets()" + ] + }, + { + "cell_type": "markdown", + "id": "d82a6ac3", + "metadata": {}, + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b861a911", + "metadata": {}, + "outputs": [], + "source": [ + "hf.dataset('app_reviews')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9935abb0", + "metadata": {}, + "outputs": [], + "source": [ + "hf.dataset('fashion_mnist')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "ba78a68c", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "# Weave package now defaults to eager mode, but lazy mode required for this example notebook for now.\n", - "weave.use_lazy_execution()\n", - "from weave.legacy.ecosystem import huggingface as hf" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3e3b90c5", - "metadata": {}, - "outputs": [], - "source": [ - "hf.hf_datasets()" - ] - }, - { - "cell_type": "markdown", - "id": "d82a6ac3", - "metadata": {}, - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b861a911", - "metadata": {}, - "outputs": [], - "source": [ - "hf.dataset('app_reviews')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9935abb0", - "metadata": {}, - "outputs": [], - "source": [ - "hf.dataset('fashion_mnist')" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/huggingface_models.ipynb b/weave/legacy/examples/experimental/huggingface_models.ipynb index 8cc3c98028a..c28d270f5dd 100644 --- a/weave/legacy/examples/experimental/huggingface_models.ipynb +++ b/weave/legacy/examples/experimental/huggingface_models.ipynb @@ -1,131 +1,131 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "d46881ea", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "# Weave package now defaults to eager mode, but lazy mode required for this example notebook for now.\n", - "weave.use_lazy_execution()\n", - "from weave.legacy.ecosystem.huggingface import huggingface as hf" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "d46881ea", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "# Weave package now defaults to eager mode, but lazy mode required for this example notebook for now.\n", + "weave.use_lazy_execution()\n", + "from weave.legacy.weave.ecosystem.huggingface import huggingface as hf" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9d181896", + "metadata": {}, + "outputs": [], + "source": [ + "# Models\n", + "#hf().models()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cb3fb536", + "metadata": {}, + "outputs": [], + "source": [ + "# Model card\n", + "text_gen_model = hf().model('gpt2')\n", + "text_gen_model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5961a5c5", + "metadata": {}, + "outputs": [], + "source": [ + "# Calling a text generation model\n", + "text_gen_output = text_gen_model.call('This is the start')\n", + "text_gen_output" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "974e1a18", + "metadata": {}, + "outputs": [], + "source": [ + "# Bertviz for attention\n", + "text_gen_output.attention()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b9ab742c", + "metadata": {}, + "outputs": [], + "source": [ + "# Model card\n", + "classification_model = hf().model('bhadresh-savani/distilbert-base-uncased-emotion')\n", + "classification_model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "493448cc", + "metadata": {}, + "outputs": [], + "source": [ + "classification_output = classification_model.call(\"I'm feeling just swell\")\n", + "classification_output" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "36305bb0", + "metadata": {}, + "outputs": [], + "source": [ + "classification_output.attention()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b1aa95d3", + "metadata": {}, + "outputs": [], + "source": [ + "# Text classification models can be explained with shap\n", + "\n", + "# TODO: we wan't chain shap_explain in Python right now. But we can in JS. Fix!\n", + "from weave.legacy.weave.ecosystem import shap\n", + "shap.shap_explain(classification_output)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "9d181896", - "metadata": {}, - "outputs": [], - "source": [ - "# Models\n", - "#hf().models()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "cb3fb536", - "metadata": {}, - "outputs": [], - "source": [ - "# Model card\n", - "text_gen_model = hf().model('gpt2')\n", - "text_gen_model" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5961a5c5", - "metadata": {}, - "outputs": [], - "source": [ - "# Calling a text generation model\n", - "text_gen_output = text_gen_model.call('This is the start')\n", - "text_gen_output" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "974e1a18", - "metadata": {}, - "outputs": [], - "source": [ - "# Bertviz for attention\n", - "text_gen_output.attention()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b9ab742c", - "metadata": {}, - "outputs": [], - "source": [ - "# Model card\n", - "classification_model = hf().model('bhadresh-savani/distilbert-base-uncased-emotion')\n", - "classification_model" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "493448cc", - "metadata": {}, - "outputs": [], - "source": [ - "classification_output = classification_model.call(\"I'm feeling just swell\")\n", - "classification_output" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "36305bb0", - "metadata": {}, - "outputs": [], - "source": [ - "classification_output.attention()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b1aa95d3", - "metadata": {}, - "outputs": [], - "source": [ - "# Text classification models can be explained with shap\n", - "\n", - "# TODO: we wan't chain shap_explain in Python right now. But we can in JS. Fix!\n", - "from weave.legacy.ecosystem import shap\n", - "shap.shap_explain(classification_output)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/image_gen_craiyon.ipynb b/weave/legacy/examples/experimental/image_gen_craiyon.ipynb index a2535d4f58b..36eab9de975 100644 --- a/weave/legacy/examples/experimental/image_gen_craiyon.ipynb +++ b/weave/legacy/examples/experimental/image_gen_craiyon.ipynb @@ -1,52 +1,52 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "2088ebdf", - "metadata": {}, - "outputs": [], - "source": [ - "# weave-test-skip-all: The craiyon API takes at least 60s per prediction!\n", - "import weave" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "2088ebdf", + "metadata": {}, + "outputs": [], + "source": [ + "# weave-test-skip-all: The craiyon API takes at least 60s per prediction!\n", + "import weave" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b6e6882b", + "metadata": {}, + "outputs": [], + "source": [ + "from weave.legacy.weave.ecosystem import craiyon\n", + "craiyon.generate('hello')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3322e1c5", + "metadata": {}, + "outputs": [], + "source": [ + "prompts = ['cats', 'dogs', 'catdogs']\n", + "panel = weave.legacy.weave.panels.Table(prompts,\n", + " columns=[\n", + " lambda prompt: prompt,\n", + " lambda prompt: craiyon.generate(prompt)\n", + " ]\n", + " )\n", + "weave.show(panel)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "b6e6882b", - "metadata": {}, - "outputs": [], - "source": [ - "from weave.legacy.ecosystem import craiyon\n", - "craiyon.generate('hello')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3322e1c5", - "metadata": {}, - "outputs": [], - "source": [ - "prompts = ['cats', 'dogs', 'catdogs']\n", - "panel = weave.legacy.panels.Table(prompts,\n", - " columns=[\n", - " lambda prompt: prompt,\n", - " lambda prompt: craiyon.generate(prompt)\n", - " ]\n", - " )\n", - "weave.show(panel)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/image_gen_ops.ipynb b/weave/legacy/examples/experimental/image_gen_ops.ipynb index 673994b3ae9..5f3078c5fd2 100644 --- a/weave/legacy/examples/experimental/image_gen_ops.ipynb +++ b/weave/legacy/examples/experimental/image_gen_ops.ipynb @@ -1,126 +1,126 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "22034460", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "import io\n", - "from PIL import Image\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "import random\n", - "from weave.legacy import ops\n", - "\n", - "def plt_image():\n", - " \"\"\"Return current matplotlib figure as PIL Image\"\"\"\n", - " img_buf = io.BytesIO()\n", - " plt.savefig(img_buf, format='png')\n", - " im = Image.open(img_buf)\n", - " return im" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "22034460", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "import io\n", + "from PIL import Image\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "import random\n", + "from weave.legacy.weave import ops\n", + "\n", + "def plt_image():\n", + " \"\"\"Return current matplotlib figure as PIL Image\"\"\"\n", + " img_buf = io.BytesIO()\n", + " plt.savefig(img_buf, format='png')\n", + " im = Image.open(img_buf)\n", + " return im" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d03dc328", + "metadata": {}, + "outputs": [], + "source": [ + "# Declare an op that plots a sin weave using matplotlib, and returns the plot as an Image\n", + "\n", + "@weave.op(render_info={\"type\": \"function\"})\n", + "def sin_image(f: int) -> Image.Image: \n", + " x = np.arange(0, f * np.pi, 0.1)\n", + " y = np.sin(x)\n", + " plt.rcParams[\"figure.figsize\"] = (22, 7)\n", + " plt.plot(x, y)\n", + " \n", + " return plt_image()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "217d0cd2", + "metadata": {}, + "outputs": [], + "source": [ + "x = weave.save(7, name='my-number')\n", + "\n", + "im = sin_image(x + 2)\n", + "im" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d8d06148", + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "from weave.legacy.weave.ops_domain import wb_domain_types\n", + "from weave import gql_op_plugin\n", + "import wandb\n", + "\n", + "\n", + "@weave.op(\n", + " render_info={\"type\": \"function\"},\n", + " plugins=gql_op_plugin.wb_gql_op_plugin(\n", + " lambda inputs, inner: \"project {id name entity {id name}}\"\n", + " )\n", + ")\n", + "def run_accuracy_barchart(runs: list[wb_domain_types.Run]) -> Image.Image:\n", + " runs = list(runs)[:10]\n", + " runs = [wandb.Api().run(f'{r[\"project\"][\"entity\"][\"name\"]}/{r[\"project\"][\"name\"]}/{r[\"name\"]}') for r in runs]\n", + " names = [r.name for r in runs]\n", + " xs = range(len(runs))\n", + " ys = [r.summary_metrics.get(\"acc\") or 0 for r in runs]\n", + "\n", + " plt.rcParams[\"figure.figsize\"] = (15, 5)\n", + " plt.bar(xs, ys, align=\"center\", alpha=0.5)\n", + " plt.xticks(xs, names)\n", + " plt.ylabel(\"acc\")\n", + " plt.title(\"Run accuracies\")\n", + "\n", + " return plt_image()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a4dc62a2", + "metadata": {}, + "outputs": [], + "source": [ + "runs = weave.legacy.weave.ops.project('shawn', 'fasion-sweep').runs()\n", + "run_accuracy_barchart(runs)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "d03dc328", - "metadata": {}, - "outputs": [], - "source": [ - "# Declare an op that plots a sin weave using matplotlib, and returns the plot as an Image\n", - "\n", - "@weave.op(render_info={\"type\": \"function\"})\n", - "def sin_image(f: int) -> Image.Image: \n", - " x = np.arange(0, f * np.pi, 0.1)\n", - " y = np.sin(x)\n", - " plt.rcParams[\"figure.figsize\"] = (22, 7)\n", - " plt.plot(x, y)\n", - " \n", - " return plt_image()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "217d0cd2", - "metadata": {}, - "outputs": [], - "source": [ - "x = weave.save(7, name='my-number')\n", - "\n", - "im = sin_image(x + 2)\n", - "im" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d8d06148", - "metadata": {}, - "outputs": [], - "source": [ - "import json\n", - "from weave.legacy.ops_domain import wb_domain_types\n", - "from weave import gql_op_plugin\n", - "import wandb\n", - "\n", - "\n", - "@weave.op(\n", - " render_info={\"type\": \"function\"},\n", - " plugins=gql_op_plugin.wb_gql_op_plugin(\n", - " lambda inputs, inner: \"project {id name entity {id name}}\"\n", - " )\n", - ")\n", - "def run_accuracy_barchart(runs: list[wb_domain_types.Run]) -> Image.Image:\n", - " runs = list(runs)[:10]\n", - " runs = [wandb.Api().run(f'{r[\"project\"][\"entity\"][\"name\"]}/{r[\"project\"][\"name\"]}/{r[\"name\"]}') for r in runs]\n", - " names = [r.name for r in runs]\n", - " xs = range(len(runs))\n", - " ys = [r.summary_metrics.get(\"acc\") or 0 for r in runs]\n", - "\n", - " plt.rcParams[\"figure.figsize\"] = (15, 5)\n", - " plt.bar(xs, ys, align=\"center\", alpha=0.5)\n", - " plt.xticks(xs, names)\n", - " plt.ylabel(\"acc\")\n", - " plt.title(\"Run accuracies\")\n", - "\n", - " return plt_image()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a4dc62a2", - "metadata": {}, - "outputs": [], - "source": [ - "runs = weave.legacy.ops.project('shawn', 'fasion-sweep').runs()\n", - "run_accuracy_barchart(runs)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/layout_panels.ipynb b/weave/legacy/examples/experimental/layout_panels.ipynb index a7536f0191f..c7bd996af26 100644 --- a/weave/legacy/examples/experimental/layout_panels.ipynb +++ b/weave/legacy/examples/experimental/layout_panels.ipynb @@ -1,206 +1,206 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "cfebbf95", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "from weave.legacy import panels" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "cfebbf95", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "from weave.legacy.weave import panels" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e427d65a", + "metadata": {}, + "outputs": [], + "source": [ + "# LabeledItem example\n", + "# panels.LabeledItem(item='item', label='label')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f9852987", + "metadata": {}, + "outputs": [], + "source": [ + "# Group example\n", + "# panels.Group(\n", + "# items=[\n", + "# panels.Group(\n", + "# prefer_horizontal=True,\n", + "# items=[\n", + "# panels.LabeledItem(item='item1', label='label1'),\n", + "# panels.LabeledItem(item='item2', label='label2'),\n", + "# panels.LabeledItem(item='item3', label='label3'),\n", + "# ]\n", + "# ),\n", + "# panels.LabeledItem(item='item4', label='label4'),\n", + "# panels.LabeledItem(item='item5', label='label5')\n", + "# ]\n", + "# )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6ee2951b", + "metadata": {}, + "outputs": [], + "source": [ + "# Card example\n", + "\n", + "panel = panels.Card(\n", + " title='GPT-3',\n", + " subtitle='OpenAI',\n", + " content=[\n", + " panels.CardTab(\n", + " name='Overview',\n", + " content=panels.Group(\n", + " items={\n", + " '0': panels.Group(\n", + " preferHorizontal=True,\n", + " items={\n", + " 'a': panels.LabeledItem(item='item1', label='label1'),\n", + " 'b': panels.LabeledItem(item='item2', label='label2'),\n", + " 'c': panels.LabeledItem(item='item3', label='label3'),\n", + " }\n", + " ),\n", + " '1': panels.LabeledItem(item='item4', label='label4'),\n", + " '2': panels.LabeledItem(item='item5', label='label5')\n", + " }\n", + " )\n", + " ),\n", + " panels.CardTab(\n", + " name='Limitations & Use',\n", + " content=panels.LabeledItem(item='tab2', label='tab2-label')\n", + " ),\n", + " \n", + " ]\n", + ")\n", + "panel" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "762467e8", + "metadata": {}, + "outputs": [], + "source": [ + "# Table in Card example\n", + "\n", + "# panels.Card(\n", + "# title='GPT-3',\n", + "# subtitle='OpenAI',\n", + "# content=[\n", + "# panels.CardTab(\n", + "# name='Overview',\n", + "# content=panels.Group(\n", + "# items=[\n", + "# panels.Group(\n", + "# prefer_horizontal=True,\n", + "# items=[\n", + "# panels.LabeledItem(item='item1', label='label1'),\n", + "# panels.LabeledItem(item='item2', label='label2'),\n", + "# panels.LabeledItem(item='item3', label='label3'),\n", + "# ]\n", + "# ),\n", + "# panels.LabeledItem(item='item4', label='label4'),\n", + "# panels.LabeledItem(\n", + "# item=[\n", + "# {\"a\": 5, \"b\": 6},\n", + "# {\"a\": 14, \"b\": 9},\n", + "# {\"a\": 4, \"b\": 22},\n", + "# ],\n", + "# height=400,\n", + "# label=\"Example\",\n", + "# ),\n", + "# ]\n", + "# )\n", + "# ),\n", + "# panels.CardTab(\n", + "# name='Limitations & Use',\n", + "# content=panels.LabeledItem(item='tab2', label='tab2-label')\n", + "# ),\n", + " \n", + "# ]\n", + "# )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "81c83f19", + "metadata": {}, + "outputs": [], + "source": [ + "# If you want full control over table columns\n", + "\n", + "# table = panels.Table([\n", + "# {\"a\": 5, \"b\": 6},\n", + "# {\"a\": 14, \"b\": 9},\n", + "# {\"a\": 4, \"b\": 22},\n", + "# ])\n", + "# table.append_column(lambda row: row['a'] + 3, name=\"a name\")\n", + "# table.append_column(lambda row: row['a'] + row['b']) # Will have an automatic name\n", + "\n", + "# panels.LabeledItem(\n", + "# item=table,\n", + "# height=400,\n", + "# label=\"Example\",\n", + "# )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eaea1261", + "metadata": {}, + "outputs": [], + "source": [ + "# Plot in Labeled item (you can do the same in a Card)\n", + "\n", + "# plot = panels.Plot(\n", + "# input_node=[\n", + "# {\"a\": 5, \"b\": 6},\n", + "# {\"a\": 14, \"b\": 9},\n", + "# {\"a\": 4, \"b\": 22}],\n", + "# x=lambda row: row['a'],\n", + "# y=lambda row: row['b']\n", + "# )\n", + "\n", + "# panels.LabeledItem(\n", + "# item=plot,\n", + "# label=\"Example\",\n", + "# )" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "e427d65a", - "metadata": {}, - "outputs": [], - "source": [ - "# LabeledItem example\n", - "# panels.LabeledItem(item='item', label='label')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f9852987", - "metadata": {}, - "outputs": [], - "source": [ - "# Group example\n", - "# panels.Group(\n", - "# items=[\n", - "# panels.Group(\n", - "# prefer_horizontal=True,\n", - "# items=[\n", - "# panels.LabeledItem(item='item1', label='label1'),\n", - "# panels.LabeledItem(item='item2', label='label2'),\n", - "# panels.LabeledItem(item='item3', label='label3'),\n", - "# ]\n", - "# ),\n", - "# panels.LabeledItem(item='item4', label='label4'),\n", - "# panels.LabeledItem(item='item5', label='label5')\n", - "# ]\n", - "# )" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6ee2951b", - "metadata": {}, - "outputs": [], - "source": [ - "# Card example\n", - "\n", - "panel = panels.Card(\n", - " title='GPT-3',\n", - " subtitle='OpenAI',\n", - " content=[\n", - " panels.CardTab(\n", - " name='Overview',\n", - " content=panels.Group(\n", - " items={\n", - " '0': panels.Group(\n", - " preferHorizontal=True,\n", - " items={\n", - " 'a': panels.LabeledItem(item='item1', label='label1'),\n", - " 'b': panels.LabeledItem(item='item2', label='label2'),\n", - " 'c': panels.LabeledItem(item='item3', label='label3'),\n", - " }\n", - " ),\n", - " '1': panels.LabeledItem(item='item4', label='label4'),\n", - " '2': panels.LabeledItem(item='item5', label='label5')\n", - " }\n", - " )\n", - " ),\n", - " panels.CardTab(\n", - " name='Limitations & Use',\n", - " content=panels.LabeledItem(item='tab2', label='tab2-label')\n", - " ),\n", - " \n", - " ]\n", - ")\n", - "panel" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "762467e8", - "metadata": {}, - "outputs": [], - "source": [ - "# Table in Card example\n", - "\n", - "# panels.Card(\n", - "# title='GPT-3',\n", - "# subtitle='OpenAI',\n", - "# content=[\n", - "# panels.CardTab(\n", - "# name='Overview',\n", - "# content=panels.Group(\n", - "# items=[\n", - "# panels.Group(\n", - "# prefer_horizontal=True,\n", - "# items=[\n", - "# panels.LabeledItem(item='item1', label='label1'),\n", - "# panels.LabeledItem(item='item2', label='label2'),\n", - "# panels.LabeledItem(item='item3', label='label3'),\n", - "# ]\n", - "# ),\n", - "# panels.LabeledItem(item='item4', label='label4'),\n", - "# panels.LabeledItem(\n", - "# item=[\n", - "# {\"a\": 5, \"b\": 6},\n", - "# {\"a\": 14, \"b\": 9},\n", - "# {\"a\": 4, \"b\": 22},\n", - "# ],\n", - "# height=400,\n", - "# label=\"Example\",\n", - "# ),\n", - "# ]\n", - "# )\n", - "# ),\n", - "# panels.CardTab(\n", - "# name='Limitations & Use',\n", - "# content=panels.LabeledItem(item='tab2', label='tab2-label')\n", - "# ),\n", - " \n", - "# ]\n", - "# )" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "81c83f19", - "metadata": {}, - "outputs": [], - "source": [ - "# If you want full control over table columns\n", - "\n", - "# table = panels.Table([\n", - "# {\"a\": 5, \"b\": 6},\n", - "# {\"a\": 14, \"b\": 9},\n", - "# {\"a\": 4, \"b\": 22},\n", - "# ])\n", - "# table.append_column(lambda row: row['a'] + 3, name=\"a name\")\n", - "# table.append_column(lambda row: row['a'] + row['b']) # Will have an automatic name\n", - "\n", - "# panels.LabeledItem(\n", - "# item=table,\n", - "# height=400,\n", - "# label=\"Example\",\n", - "# )" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "eaea1261", - "metadata": {}, - "outputs": [], - "source": [ - "# Plot in Labeled item (you can do the same in a Card)\n", - "\n", - "# plot = panels.Plot(\n", - "# input_node=[\n", - "# {\"a\": 5, \"b\": 6},\n", - "# {\"a\": 14, \"b\": 9},\n", - "# {\"a\": 4, \"b\": 22}],\n", - "# x=lambda row: row['a'],\n", - "# y=lambda row: row['b']\n", - "# )\n", - "\n", - "# panels.LabeledItem(\n", - "# item=plot,\n", - "# label=\"Example\",\n", - "# )" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/llm_monitor_helper.ipynb b/weave/legacy/examples/experimental/llm_monitor_helper.ipynb index d2cfe85b752..48e92a18e90 100644 --- a/weave/legacy/examples/experimental/llm_monitor_helper.ipynb +++ b/weave/legacy/examples/experimental/llm_monitor_helper.ipynb @@ -1,198 +1,198 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ENTITY = 'timssweeney'\n", - "PROJECT = 'weave'\n", - "STREAM = 'custom_llm_monitoring_example'" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ENTITY = 'timssweeney'\n", + "PROJECT = 'weave'\n", + "STREAM = 'custom_llm_monitoring_example'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import uuid\n", + "import time\n", + "import typing\n", + "from datetime import datetime \n", + "\n", + "from weave.stream_data_interfaces import LLMCompletionDict, _LLMCompletionInputs, _LLMCompletionOutput, _LLMCompletionSummary, _LLMCompletionMessage, _LLMCompletionChoice\n", + "import tiktoken\n", + "\n", + "def count_chat_completion_tokens(\n", + " model_name: typing.Optional[str] = None,\n", + " prompt_input_messages: typing.List[_LLMCompletionMessage] = [],\n", + " completion_choices: typing.List[_LLMCompletionChoice] = []\n", + ") -> dict:\n", + " \n", + " summary = {}\n", + " if not model_name:\n", + " encoding = tiktoken.get_encoding(\"cl100k_base\")\n", + " else:\n", + " encoding = tiktoken.encoding_for_model(model_name)\n", + "\n", + " prompt_tokens = (encoding.encode(m[\"content\"]) for m in prompt_input_messages)\n", + " summary[\"prompt_tokens\"] = sum(len(c) for c in prompt_tokens)\n", + "\n", + " completion_tokens = (\n", + " encoding.encode(c[\"message\"][\"content\"]) for c in completion_choices\n", + " )\n", + " summary[\"completion_tokens\"] = sum(len(c) for c in completion_tokens)\n", + " summary[\"total_tokens\"] = summary[\"prompt_tokens\"] + summary[\"completion_tokens\"]\n", + " return summary\n", + "\n", + "def create_llm_record(\n", + "\n", + " # The end-format is that of `_LLMCompletionInputs`, but we can add helper processing to convert from other formats\n", + " inputs: typing.Union[_LLMCompletionInputs, typing.List[_LLMCompletionMessage], typing.List[str], str] = None,\n", + "\n", + " # the end-format is that of `_LLMCompletionOutput`, but we can add helper processing to convert from other formats\n", + " output: typing.Union[_LLMCompletionOutput, str] = None,\n", + "\n", + " # Required for cost analysis\n", + " model_name: str = \"\",\n", + "\n", + " # Optional fields\n", + " span_id: typing.Optional[str] = None,\n", + " name: typing.Optional[str] = None,\n", + " trace_id: typing.Optional[str] = None,\n", + " status_code: typing.Optional[str] = None,\n", + " start_time_s: typing.Optional[float] = None,\n", + " end_time_s: typing.Optional[float] = None,\n", + " parent_id: typing.Optional[str] = None,\n", + "\n", + " # Must contain dictionaries, lists, and primitives (ie json serializable)\n", + " attributes: typing.Optional[typing.Dict[str, typing.Any]] = None,\n", + "\n", + " summary: typing.Optional[_LLMCompletionSummary] = None,\n", + "\n", + " exception: typing.Optional[str] = None\n", + "):\n", + " span_id = span_id or str(uuid.uuid4())\n", + " name = name or \"llm_completion\"\n", + " trace_id = trace_id or span_id\n", + " status_code = status_code or \"UNSET\"\n", + " start_time_s = start_time_s or time.time()\n", + " end_time_s = end_time_s or (start_time_s + 1)\n", + " latency_s = end_time_s - start_time_s\n", + " # parent_id can be None\n", + " attributes = attributes or {}\n", + " \n", + "\n", + " # Input handling\n", + " if isinstance(inputs, dict):\n", + " # Assume correct format\n", + " inputs = inputs\n", + " elif isinstance(inputs, list):\n", + " messages = []\n", + " for item in inputs:\n", + " if isinstance(item, str):\n", + " messages.append(_LLMCompletionMessage(content=item))\n", + " elif isinstance(item, dict):\n", + " # Assume correct format\n", + " messages.append(item)\n", + " else:\n", + " raise ValueError(f\"Invalid type for item in inputs: {type(item)}\")\n", + " inputs = _LLMCompletionInputs(messages=messages)\n", + " elif isinstance(inputs, str):\n", + " inputs = _LLMCompletionInputs(messages=[_LLMCompletionMessage(content=inputs)])\n", + " else:\n", + " raise ValueError(f\"Invalid type for inputs: {type(inputs)}\")\n", + " \n", + "\n", + " # Output handling\n", + " if isinstance(output, dict):\n", + " # Assume correct format\n", + " output = output\n", + " elif isinstance(output, str):\n", + " output = _LLMCompletionOutput(model=model_name, choices=[_LLMCompletionChoice(message=_LLMCompletionMessage(content=output))])\n", + " else:\n", + " raise ValueError(f\"Invalid type for output: {type(output)}\")\n", + "\n", + " # Sort of odd, but we need at least one key for now\n", + " summary = summary or {}\n", + " summary = {\n", + " **(summary or {}),\n", + " \"latency_s\": latency_s,\n", + " **count_chat_completion_tokens(\n", + " model_name,\n", + " inputs['messages'],\n", + " output['choices'])\n", + " }\n", + " \n", + "\n", + " # exception can be None\n", + "\n", + " assert status_code in [\"SUCCESS\", \"ERROR\", \"UNSET\"]\n", + "\n", + " return LLMCompletionDict(\n", + " span_id = span_id,\n", + " name = name,\n", + " trace_id = trace_id,\n", + " status_code = status_code,\n", + " start_time_s = start_time_s,\n", + " end_time_s = end_time_s,\n", + " parent_id = parent_id,\n", + " attributes = attributes,\n", + " inputs = inputs,\n", + " output = output,\n", + " summary = summary,\n", + " exception = exception,\n", + " # Manually set timestamp - else it will be set to the time of the function call\n", + " timestamp = datetime.fromtimestamp(start_time_s)\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from weave.legacy.weave.monitoring import StreamTable\n", + "st = StreamTable(f\"{ENTITY}/{PROJECT}/{STREAM}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Base Case\n", + "record = create_llm_record(\n", + " inputs=\"hello\",\n", + " output=\"world\"\n", + ")\n", + "st.log(record)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "wandb-weave", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.8" + } }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import uuid\n", - "import time\n", - "import typing\n", - "from datetime import datetime \n", - "\n", - "from weave.stream_data_interfaces import LLMCompletionDict, _LLMCompletionInputs, _LLMCompletionOutput, _LLMCompletionSummary, _LLMCompletionMessage, _LLMCompletionChoice\n", - "import tiktoken\n", - "\n", - "def count_chat_completion_tokens(\n", - " model_name: typing.Optional[str] = None,\n", - " prompt_input_messages: typing.List[_LLMCompletionMessage] = [],\n", - " completion_choices: typing.List[_LLMCompletionChoice] = []\n", - ") -> dict:\n", - " \n", - " summary = {}\n", - " if not model_name:\n", - " encoding = tiktoken.get_encoding(\"cl100k_base\")\n", - " else:\n", - " encoding = tiktoken.encoding_for_model(model_name)\n", - "\n", - " prompt_tokens = (encoding.encode(m[\"content\"]) for m in prompt_input_messages)\n", - " summary[\"prompt_tokens\"] = sum(len(c) for c in prompt_tokens)\n", - "\n", - " completion_tokens = (\n", - " encoding.encode(c[\"message\"][\"content\"]) for c in completion_choices\n", - " )\n", - " summary[\"completion_tokens\"] = sum(len(c) for c in completion_tokens)\n", - " summary[\"total_tokens\"] = summary[\"prompt_tokens\"] + summary[\"completion_tokens\"]\n", - " return summary\n", - "\n", - "def create_llm_record(\n", - "\n", - " # The end-format is that of `_LLMCompletionInputs`, but we can add helper processing to convert from other formats\n", - " inputs: typing.Union[_LLMCompletionInputs, typing.List[_LLMCompletionMessage], typing.List[str], str] = None,\n", - "\n", - " # the end-format is that of `_LLMCompletionOutput`, but we can add helper processing to convert from other formats\n", - " output: typing.Union[_LLMCompletionOutput, str] = None,\n", - "\n", - " # Required for cost analysis\n", - " model_name: str = \"\",\n", - "\n", - " # Optional fields\n", - " span_id: typing.Optional[str] = None,\n", - " name: typing.Optional[str] = None,\n", - " trace_id: typing.Optional[str] = None,\n", - " status_code: typing.Optional[str] = None,\n", - " start_time_s: typing.Optional[float] = None,\n", - " end_time_s: typing.Optional[float] = None,\n", - " parent_id: typing.Optional[str] = None,\n", - "\n", - " # Must contain dictionaries, lists, and primitives (ie json serializable)\n", - " attributes: typing.Optional[typing.Dict[str, typing.Any]] = None,\n", - "\n", - " summary: typing.Optional[_LLMCompletionSummary] = None,\n", - "\n", - " exception: typing.Optional[str] = None\n", - "):\n", - " span_id = span_id or str(uuid.uuid4())\n", - " name = name or \"llm_completion\"\n", - " trace_id = trace_id or span_id\n", - " status_code = status_code or \"UNSET\"\n", - " start_time_s = start_time_s or time.time()\n", - " end_time_s = end_time_s or (start_time_s + 1)\n", - " latency_s = end_time_s - start_time_s\n", - " # parent_id can be None\n", - " attributes = attributes or {}\n", - " \n", - "\n", - " # Input handling\n", - " if isinstance(inputs, dict):\n", - " # Assume correct format\n", - " inputs = inputs\n", - " elif isinstance(inputs, list):\n", - " messages = []\n", - " for item in inputs:\n", - " if isinstance(item, str):\n", - " messages.append(_LLMCompletionMessage(content=item))\n", - " elif isinstance(item, dict):\n", - " # Assume correct format\n", - " messages.append(item)\n", - " else:\n", - " raise ValueError(f\"Invalid type for item in inputs: {type(item)}\")\n", - " inputs = _LLMCompletionInputs(messages=messages)\n", - " elif isinstance(inputs, str):\n", - " inputs = _LLMCompletionInputs(messages=[_LLMCompletionMessage(content=inputs)])\n", - " else:\n", - " raise ValueError(f\"Invalid type for inputs: {type(inputs)}\")\n", - " \n", - "\n", - " # Output handling\n", - " if isinstance(output, dict):\n", - " # Assume correct format\n", - " output = output\n", - " elif isinstance(output, str):\n", - " output = _LLMCompletionOutput(model=model_name, choices=[_LLMCompletionChoice(message=_LLMCompletionMessage(content=output))])\n", - " else:\n", - " raise ValueError(f\"Invalid type for output: {type(output)}\")\n", - "\n", - " # Sort of odd, but we need at least one key for now\n", - " summary = summary or {}\n", - " summary = {\n", - " **(summary or {}),\n", - " \"latency_s\": latency_s,\n", - " **count_chat_completion_tokens(\n", - " model_name,\n", - " inputs['messages'],\n", - " output['choices'])\n", - " }\n", - " \n", - "\n", - " # exception can be None\n", - "\n", - " assert status_code in [\"SUCCESS\", \"ERROR\", \"UNSET\"]\n", - "\n", - " return LLMCompletionDict(\n", - " span_id = span_id,\n", - " name = name,\n", - " trace_id = trace_id,\n", - " status_code = status_code,\n", - " start_time_s = start_time_s,\n", - " end_time_s = end_time_s,\n", - " parent_id = parent_id,\n", - " attributes = attributes,\n", - " inputs = inputs,\n", - " output = output,\n", - " summary = summary,\n", - " exception = exception,\n", - " # Manually set timestamp - else it will be set to the time of the function call\n", - " timestamp = datetime.fromtimestamp(start_time_s)\n", - " )" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from weave.legacy.monitoring import StreamTable\n", - "st = StreamTable(f\"{ENTITY}/{PROJECT}/{STREAM}\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Base Case\n", - "record = create_llm_record(\n", - " inputs=\"hello\",\n", - " output=\"world\"\n", - ")\n", - "st.log(record)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "wandb-weave", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.8" - } - }, - "nbformat": 4, - "nbformat_minor": 2 + "nbformat": 4, + "nbformat_minor": 2 } diff --git a/weave/legacy/examples/experimental/mnist_train.ipynb b/weave/legacy/examples/experimental/mnist_train.ipynb index f6cb2821cc0..664459dcae5 100644 --- a/weave/legacy/examples/experimental/mnist_train.ipynb +++ b/weave/legacy/examples/experimental/mnist_train.ipynb @@ -1,82 +1,82 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "37f6d676", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "# Weave package now defaults to eager mode, but lazy mode required for this example notebook for now.\n", - "weave.use_lazy_execution()\n", - "from weave.legacy.ecosystem import torchvision, torch_mnist_model_example" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "37f6d676", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "# Weave package now defaults to eager mode, but lazy mode required for this example notebook for now.\n", + "weave.use_lazy_execution()\n", + "from weave.legacy.weave.ecosystem import torchvision, torch_mnist_model_example" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b450f4df", + "metadata": {}, + "outputs": [], + "source": [ + "# TODO: Fix WeaveJS to automatically pick the more specific dataset_card Panel\n", + "mnist_dataset = torchvision.mnist(100) # Or try mnist.food101(100), but currently broken\n", + "mnist_dataset" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "664f3447", + "metadata": {}, + "outputs": [], + "source": [ + "hyperparams = {\n", + " 'fc_layer_size': 256,\n", + " 'dropout': 0.5,\n", + " 'epochs': 5,\n", + " 'learning_rate': 0.005,\n", + " 'batch_size': 128,\n", + "}\n", + "train_split = mnist_dataset['data']['train']\n", + "#train_split.pick('image')\n", + "model = torch_mnist_model_example.train(\n", + " train_split.pick('image'), train_split.pick('label'), hyperparams)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8d204664", + "metadata": {}, + "outputs": [], + "source": [ + "test_split_images = mnist_dataset['data']['test']['image']\n", + "preds = model.predict(test_split_images)\n", + "preds" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "b450f4df", - "metadata": {}, - "outputs": [], - "source": [ - "# TODO: Fix WeaveJS to automatically pick the more specific dataset_card Panel\n", - "mnist_dataset = torchvision.mnist(100) # Or try mnist.food101(100), but currently broken\n", - "mnist_dataset" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "664f3447", - "metadata": {}, - "outputs": [], - "source": [ - "hyperparams = {\n", - " 'fc_layer_size': 256,\n", - " 'dropout': 0.5,\n", - " 'epochs': 5,\n", - " 'learning_rate': 0.005,\n", - " 'batch_size': 128,\n", - "}\n", - "train_split = mnist_dataset['data']['train']\n", - "#train_split.pick('image')\n", - "model = torch_mnist_model_example.train(\n", - " train_split.pick('image'), train_split.pick('label'), hyperparams)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8d204664", - "metadata": {}, - "outputs": [], - "source": [ - "test_split_images = mnist_dataset['data']['test']['image']\n", - "preds = model.predict(test_split_images)\n", - "preds" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/object_version_compare.ipynb b/weave/legacy/examples/experimental/object_version_compare.ipynb index c74bf916295..216aba6973b 100644 --- a/weave/legacy/examples/experimental/object_version_compare.ipynb +++ b/weave/legacy/examples/experimental/object_version_compare.ipynb @@ -1,116 +1,116 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "e114a840", - "metadata": {}, - "outputs": [], - "source": [ - "import math\n", - "import weave\n", - "import typing" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "e114a840", + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import weave\n", + "import typing" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "47ae117d", + "metadata": {}, + "outputs": [], + "source": [ + "@weave.op(render_info={'type': 'function'})\n", + "def weave_range(n: int) -> list[int]:\n", + " return list(range(n))\n", + "\n", + "class Point(typing.TypedDict):\n", + " x: float\n", + " y: float\n", + "\n", + "@weave.op()\n", + "def compute_points(xs: list[int], freq: float) -> list[Point]:\n", + " res: list[Point] = []\n", + " for x in xs:\n", + " res.append({\"x\": x, \"y\": math.sin(freq * x)})\n", + " return res" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e6db91c9", + "metadata": {}, + "outputs": [], + "source": [ + "xs = weave_range(1000)\n", + "points = compute_points(xs, 0.16)\n", + "points = weave.save(points, 'points')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5c88c35e", + "metadata": {}, + "outputs": [], + "source": [ + "plot = weave.legacy.weave.panels.Plot(points,\n", + " x=lambda row: row['x'],\n", + " y=lambda row: row['y'])\n", + "plot\n", + "\n", + "# NOTE! There is a UI bug here. You need to click the gear icon and\n", + "# then \"Reset & Automate Plot\" -> \"OK\" to make it render correctly" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "db404b2e", + "metadata": {}, + "outputs": [], + "source": [ + "for version in weave.versions(points):\n", + " print(weave.expr(version))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "caa2daef", + "metadata": {}, + "outputs": [], + "source": [ + "plot = weave.legacy.weave.panels.Plot(weave.legacy.weave.ops.compare_versions(points))\n", + "plot.set_x(lambda row: row['x'])\n", + "plot.set_y(lambda row: row['y'])\n", + "plot.set_label(lambda row: row['version'])\n", + "weave.show(plot)\n", + "\n", + "# NOTE! There is a UI bug here. You need to click the gear icon and\n", + "# then \"Reset & Automate Plot\" -> \"OK\" to make it render correctly" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "47ae117d", - "metadata": {}, - "outputs": [], - "source": [ - "@weave.op(render_info={'type': 'function'})\n", - "def weave_range(n: int) -> list[int]:\n", - " return list(range(n))\n", - "\n", - "class Point(typing.TypedDict):\n", - " x: float\n", - " y: float\n", - "\n", - "@weave.op()\n", - "def compute_points(xs: list[int], freq: float) -> list[Point]:\n", - " res: list[Point] = []\n", - " for x in xs:\n", - " res.append({\"x\": x, \"y\": math.sin(freq * x)})\n", - " return res" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e6db91c9", - "metadata": {}, - "outputs": [], - "source": [ - "xs = weave_range(1000)\n", - "points = compute_points(xs, 0.16)\n", - "points = weave.save(points, 'points')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5c88c35e", - "metadata": {}, - "outputs": [], - "source": [ - "plot = weave.legacy.panels.Plot(points,\n", - " x=lambda row: row['x'],\n", - " y=lambda row: row['y'])\n", - "plot\n", - "\n", - "# NOTE! There is a UI bug here. You need to click the gear icon and\n", - "# then \"Reset & Automate Plot\" -> \"OK\" to make it render correctly" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "db404b2e", - "metadata": {}, - "outputs": [], - "source": [ - "for version in weave.versions(points):\n", - " print(weave.expr(version))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "caa2daef", - "metadata": {}, - "outputs": [], - "source": [ - "plot = weave.legacy.panels.Plot(weave.legacy.ops.compare_versions(points))\n", - "plot.set_x(lambda row: row['x'])\n", - "plot.set_y(lambda row: row['y'])\n", - "plot.set_label(lambda row: row['version'])\n", - "weave.show(plot)\n", - "\n", - "# NOTE! There is a UI bug here. You need to click the gear icon and\n", - "# then \"Reset & Automate Plot\" -> \"OK\" to make it render correctly" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/old_openai_monitoring.ipynb b/weave/legacy/examples/experimental/old_openai_monitoring.ipynb index 5cc04cbf307..038a1932e79 100644 --- a/weave/legacy/examples/experimental/old_openai_monitoring.ipynb +++ b/weave/legacy/examples/experimental/old_openai_monitoring.ipynb @@ -1,226 +1,226 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "30ccfdbc", - "metadata": {}, - "source": [ - "This notebook shows how to use our openai logging integration to monitor api calls" - ] + "cells": [ + { + "cell_type": "markdown", + "id": "30ccfdbc", + "metadata": {}, + "source": [ + "This notebook shows how to use our openai logging integration to monitor api calls" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8107732a-fb90-45f8-8377-6381bd28475d", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "weave.use_frontend_devmode()\n", + "from weave.legacy.weave.monitoring import openai, init_monitor\n", + "\n", + "OPENAI_MODEL = 'gpt-3.5-turbo'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ba2b2070", + "metadata": {}, + "outputs": [], + "source": [ + "# Pass //\n", + "m = init_monitor('shawn/oai-mon/test21')\n", + "\n", + "# Do an initial request, otherwise we don't have a type on which to recommend the OpenAI board!\n", + "# We need at least 2 requests for the Board to work, otherwise we get divide by zero errors.\n", + "# TODO: fix this onboarding issue\n", + "r = openai.ChatCompletion.create(model=OPENAI_MODEL, messages=[{\"role\": \"user\", \"content\": f\"hello world!\"}])\n", + "r = openai.ChatCompletion.create(model=OPENAI_MODEL, messages=[{\"role\": \"user\", \"content\": f\"what is 2+2?\"}])" + ] + }, + { + "cell_type": "markdown", + "id": "fb51abb4", + "metadata": {}, + "source": [ + "Click the link above to go to the Weave UI for the table we're logging to.\n", + "\n", + "From there you can click \"OpenAI Monitor Board\" to create a Weave Board for this data stream." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e711d521", + "metadata": {}, + "outputs": [], + "source": [ + "# Monitor ChatCompletion requests\n", + "r = openai.ChatCompletion.create(model=OPENAI_MODEL, messages=[\n", + " {\"role\": \"user\", \"content\": f\"who won the world series in 2006?\"},\n", + " ])\n", + "r['choices'][0]['message']['content']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7930e774", + "metadata": {}, + "outputs": [], + "source": [ + "# To keep track of prompts and parameters, add them to attributes on the logged\n", + "# record.\n", + "\n", + "system_prompt = \"you always write in bullet points\"\n", + "prompt = 'solve the following equation step by step: {equation}'\n", + "params = {'equation': '4 * (3 - 1)'}\n", + "openai.ChatCompletion.create(model=OPENAI_MODEL,\n", + " messages=[\n", + " {\"role\": \"system\", \"content\": system_prompt},\n", + " {\"role\": \"user\", \"content\": prompt.format(**params)},\n", + " ],\n", + " # you can add additional attributes to the logged record\n", + " # see the monitor_api notebook for more examples\n", + " monitor_attributes={\n", + " 'system_prompt': system_prompt,\n", + " 'prompt': prompt,\n", + " 'params': params\n", + " })" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b8b423df", + "metadata": {}, + "outputs": [], + "source": [ + "# Monitor streaming requests\n", + "# TODO: we don't get token counts here yet.\n", + "from weave.legacy.weave.monitoring.openai import message_from_stream\n", + "r = openai.ChatCompletion.create(model=OPENAI_MODEL, messages=[\n", + " {\"role\": \"system\", \"content\": \"Your are a robot and only speak in robot, like beep bloop bop.\"},\n", + " {\"role\": \"user\", \"content\": f\"Tell me a 50 word story.\"},\n", + " ], stream=True)\n", + "for s in message_from_stream(r):\n", + " print(s, end='')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bca62fdb", + "metadata": {}, + "outputs": [], + "source": [ + "# Render table inline\n", + "#m.rows()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bdae9ba5-aa2b-4191-9a42-c1078ba0698a", + "metadata": {}, + "outputs": [], + "source": [ + "# Render board inline\n", + "# from weave.legacy.weave.panels_py import panel_llm_monitor\n", + "# board = panel_llm_monitor.board.raw_resolve_fn(m.rows())\n", + "# board" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d237a885", + "metadata": {}, + "outputs": [], + "source": [ + "# Other examples\n", + "\n", + "# TODO: restore async variant\n", + "\n", + "# result = await monitored_a_create(model=\"gpt-3.5-turbo\", messages=[\n", + "# {\"role\": \"system\", \"content\": \"You are a world-class machine learning researcher.\"},\n", + "# {\"role\": \"user\", \"content\": f\"Please provide a simple, fact-based question to send to an AI system. Do not say anything other than the question itself. Use this random number as inspiration: {random.random()}.\"},\n", + "# ])\n", + "# result\n", + "\n", + "# TODO: ensure works with function calls\n", + "# functions = [\n", + "# {\n", + "# \"name\": \"get_current_weather\",\n", + "# \"description\": \"Get the current weather\",\n", + "# \"parameters\": {\n", + "# \"type\": \"object\",\n", + "# \"properties\": {\n", + "# \"location\": {\n", + "# \"type\": \"string\",\n", + "# \"description\": \"The city and state, e.g. San Francisco, CA\",\n", + "# },\n", + "# \"format\": {\n", + "# \"type\": \"string\",\n", + "# \"enum\": [\"celsius\", \"fahrenheit\"],\n", + "# \"description\": \"The temperature unit to use. Infer this from the users location.\",\n", + "# },\n", + "# },\n", + "# \"required\": [\"location\", \"format\"],\n", + "# },\n", + "# },\n", + "# {\n", + "# \"name\": \"get_n_day_weather_forecast\",\n", + "# \"description\": \"Get an N-day weather forecast\",\n", + "# \"parameters\": {\n", + "# \"type\": \"object\",\n", + "# \"properties\": {\n", + "# \"location\": {\n", + "# \"type\": \"string\",\n", + "# \"description\": \"The city and state, e.g. San Francisco, CA\",\n", + "# },\n", + "# \"format\": {\n", + "# \"type\": \"string\",\n", + "# \"enum\": [\"celsius\", \"fahrenheit\"],\n", + "# \"description\": \"The temperature unit to use. Infer this from the users location.\",\n", + "# },\n", + "# \"num_days\": {\n", + "# \"type\": \"integer\",\n", + "# \"description\": \"The number of days to forecast\",\n", + "# }\n", + "# },\n", + "# \"required\": [\"location\", \"format\", \"num_days\"]\n", + "# },\n", + "# },\n", + "# ]\n", + "\n", + "# result = openai.ChatCompletion.create(model=\"gpt-3.5-turbo\", functions=functions, messages=[\n", + "# {\"role\": \"system\", \"content\": \"You love to call functions.\"},\n", + "# {\"role\": \"user\", \"content\": f\"what's the weather today\"},\n", + "# ])" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "8107732a-fb90-45f8-8377-6381bd28475d", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "weave.use_frontend_devmode()\n", - "from weave.legacy.monitoring import openai, init_monitor\n", - "\n", - "OPENAI_MODEL = 'gpt-3.5-turbo'" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ba2b2070", - "metadata": {}, - "outputs": [], - "source": [ - "# Pass //\n", - "m = init_monitor('shawn/oai-mon/test21')\n", - "\n", - "# Do an initial request, otherwise we don't have a type on which to recommend the OpenAI board!\n", - "# We need at least 2 requests for the Board to work, otherwise we get divide by zero errors.\n", - "# TODO: fix this onboarding issue\n", - "r = openai.ChatCompletion.create(model=OPENAI_MODEL, messages=[{\"role\": \"user\", \"content\": f\"hello world!\"}])\n", - "r = openai.ChatCompletion.create(model=OPENAI_MODEL, messages=[{\"role\": \"user\", \"content\": f\"what is 2+2?\"}])" - ] - }, - { - "cell_type": "markdown", - "id": "fb51abb4", - "metadata": {}, - "source": [ - "Click the link above to go to the Weave UI for the table we're logging to.\n", - "\n", - "From there you can click \"OpenAI Monitor Board\" to create a Weave Board for this data stream." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e711d521", - "metadata": {}, - "outputs": [], - "source": [ - "# Monitor ChatCompletion requests\n", - "r = openai.ChatCompletion.create(model=OPENAI_MODEL, messages=[\n", - " {\"role\": \"user\", \"content\": f\"who won the world series in 2006?\"},\n", - " ])\n", - "r['choices'][0]['message']['content']" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7930e774", - "metadata": {}, - "outputs": [], - "source": [ - "# To keep track of prompts and parameters, add them to attributes on the logged\n", - "# record.\n", - "\n", - "system_prompt = \"you always write in bullet points\"\n", - "prompt = 'solve the following equation step by step: {equation}'\n", - "params = {'equation': '4 * (3 - 1)'}\n", - "openai.ChatCompletion.create(model=OPENAI_MODEL,\n", - " messages=[\n", - " {\"role\": \"system\", \"content\": system_prompt},\n", - " {\"role\": \"user\", \"content\": prompt.format(**params)},\n", - " ],\n", - " # you can add additional attributes to the logged record\n", - " # see the monitor_api notebook for more examples\n", - " monitor_attributes={\n", - " 'system_prompt': system_prompt,\n", - " 'prompt': prompt,\n", - " 'params': params\n", - " })" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b8b423df", - "metadata": {}, - "outputs": [], - "source": [ - "# Monitor streaming requests\n", - "# TODO: we don't get token counts here yet.\n", - "from weave.legacy.monitoring.openai import message_from_stream\n", - "r = openai.ChatCompletion.create(model=OPENAI_MODEL, messages=[\n", - " {\"role\": \"system\", \"content\": \"Your are a robot and only speak in robot, like beep bloop bop.\"},\n", - " {\"role\": \"user\", \"content\": f\"Tell me a 50 word story.\"},\n", - " ], stream=True)\n", - "for s in message_from_stream(r):\n", - " print(s, end='')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "bca62fdb", - "metadata": {}, - "outputs": [], - "source": [ - "# Render table inline\n", - "#m.rows()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "bdae9ba5-aa2b-4191-9a42-c1078ba0698a", - "metadata": {}, - "outputs": [], - "source": [ - "# Render board inline\n", - "# from weave.legacy.panels_py import panel_llm_monitor\n", - "# board = panel_llm_monitor.board.raw_resolve_fn(m.rows())\n", - "# board" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d237a885", - "metadata": {}, - "outputs": [], - "source": [ - "# Other examples\n", - "\n", - "# TODO: restore async variant\n", - "\n", - "# result = await monitored_a_create(model=\"gpt-3.5-turbo\", messages=[\n", - "# {\"role\": \"system\", \"content\": \"You are a world-class machine learning researcher.\"},\n", - "# {\"role\": \"user\", \"content\": f\"Please provide a simple, fact-based question to send to an AI system. Do not say anything other than the question itself. Use this random number as inspiration: {random.random()}.\"},\n", - "# ])\n", - "# result\n", - "\n", - "# TODO: ensure works with function calls\n", - "# functions = [\n", - "# {\n", - "# \"name\": \"get_current_weather\",\n", - "# \"description\": \"Get the current weather\",\n", - "# \"parameters\": {\n", - "# \"type\": \"object\",\n", - "# \"properties\": {\n", - "# \"location\": {\n", - "# \"type\": \"string\",\n", - "# \"description\": \"The city and state, e.g. San Francisco, CA\",\n", - "# },\n", - "# \"format\": {\n", - "# \"type\": \"string\",\n", - "# \"enum\": [\"celsius\", \"fahrenheit\"],\n", - "# \"description\": \"The temperature unit to use. Infer this from the users location.\",\n", - "# },\n", - "# },\n", - "# \"required\": [\"location\", \"format\"],\n", - "# },\n", - "# },\n", - "# {\n", - "# \"name\": \"get_n_day_weather_forecast\",\n", - "# \"description\": \"Get an N-day weather forecast\",\n", - "# \"parameters\": {\n", - "# \"type\": \"object\",\n", - "# \"properties\": {\n", - "# \"location\": {\n", - "# \"type\": \"string\",\n", - "# \"description\": \"The city and state, e.g. San Francisco, CA\",\n", - "# },\n", - "# \"format\": {\n", - "# \"type\": \"string\",\n", - "# \"enum\": [\"celsius\", \"fahrenheit\"],\n", - "# \"description\": \"The temperature unit to use. Infer this from the users location.\",\n", - "# },\n", - "# \"num_days\": {\n", - "# \"type\": \"integer\",\n", - "# \"description\": \"The number of days to forecast\",\n", - "# }\n", - "# },\n", - "# \"required\": [\"location\", \"format\", \"num_days\"]\n", - "# },\n", - "# },\n", - "# ]\n", - "\n", - "# result = openai.ChatCompletion.create(model=\"gpt-3.5-turbo\", functions=functions, messages=[\n", - "# {\"role\": \"system\", \"content\": \"You love to call functions.\"},\n", - "# {\"role\": \"user\", \"content\": f\"what's the weather today\"},\n", - "# ])" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/openai_monitoring.ipynb b/weave/legacy/examples/experimental/openai_monitoring.ipynb index 0db4b93e1c3..686b881dc0d 100644 --- a/weave/legacy/examples/experimental/openai_monitoring.ipynb +++ b/weave/legacy/examples/experimental/openai_monitoring.ipynb @@ -1,239 +1,239 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## OpenAI Monitoring Examples\n", - "\n", - "This updates our monitoring code to:\n", - "1. Be compatible with `openai>=1.0.0`\n", - "2. Use patching (instead of forcing the user to import from our custom impl)\n", - "3. Use a callback system to add new functionality before/after certain stages" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Setup" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import openai\n", - "import weave\n", - "from weave.legacy.monitoring.openai import patch, unpatch\n", - "\n", - "weave.legacy.monitoring.openai.patch()\n", - "# weave.legacy.monitoring.openai.unpatch()\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Advanced Setup\n", - "You can customize callbacks (e.g. which StreamTable to log to) by explicitly passing callbacks to `patch`" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# from weave.legacy.monitoring.openai import ReassembleStream, LogToStreamTable\n", - "\n", - "# weave.legacy.monitoring.openai.patch(\n", - "# callbacks=[LogToStreamTable.from_stream_name(\"stream\", \"project\", \"entity\")]\n", - "# )\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Module-level Sync Completion" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "result = openai.chat.completions.create(\n", - " model=\"gpt-3.5-turbo\",\n", - " messages=[{\"role\": \"system\", \"content\": \"Tell me a joke\"}],\n", - ")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "result\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Sync Completion" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "client = openai.OpenAI()\n", - "\n", - "result = client.chat.completions.create(\n", - " model=\"gpt-3.5-turbo\",\n", - " messages=[{\"role\": \"system\", \"content\": \"Tell me a joke\"}],\n", - ")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "result\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Sync Completion (Streaming)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "client = openai.OpenAI()\n", - "\n", - "stream = client.chat.completions.create(\n", - " model=\"gpt-3.5-turbo\",\n", - " messages=[{\"role\": \"system\", \"content\": \"Tell me a joke\"}],\n", - " stream=True\n", - ")\n", - "\n", - "for x in stream:\n", - " print(x)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Async Completion" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "client = openai.AsyncOpenAI()\n", - "\n", - "result = await client.chat.completions.create(\n", - " model=\"gpt-3.5-turbo\",\n", - " messages=[{\"role\": \"system\", \"content\": \"Tell me a joke\"}],\n", - ")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "result\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Async Completion (Streaming)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "client = openai.AsyncOpenAI()\n", - "\n", - "stream = await client.chat.completions.create(\n", - " model=\"gpt-3.5-turbo\",\n", - " messages=[{\"role\": \"system\", \"content\": \"Tell me a joke\"}],\n", - " stream=True\n", - ")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "async for x in stream:\n", - " ...\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "weave310", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.11" - } - }, - "nbformat": 4, - "nbformat_minor": 2 + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## OpenAI Monitoring Examples\n", + "\n", + "This updates our monitoring code to:\n", + "1. Be compatible with `openai>=1.0.0`\n", + "2. Use patching (instead of forcing the user to import from our custom impl)\n", + "3. Use a callback system to add new functionality before/after certain stages" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Setup" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import openai\n", + "import weave\n", + "from weave.legacy.weave.monitoring.openai import patch, unpatch\n", + "\n", + "weave.legacy.weave.monitoring.openai.patch()\n", + "# weave.legacy.weave.monitoring.openai.unpatch()\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Advanced Setup\n", + "You can customize callbacks (e.g. which StreamTable to log to) by explicitly passing callbacks to `patch`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# from weave.legacy.weave.monitoring.openai import ReassembleStream, LogToStreamTable\n", + "\n", + "# weave.legacy.weave.monitoring.openai.patch(\n", + "# callbacks=[LogToStreamTable.from_stream_name(\"stream\", \"project\", \"entity\")]\n", + "# )\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Module-level Sync Completion" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "result = openai.chat.completions.create(\n", + " model=\"gpt-3.5-turbo\",\n", + " messages=[{\"role\": \"system\", \"content\": \"Tell me a joke\"}],\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "result\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Sync Completion" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "client = openai.OpenAI()\n", + "\n", + "result = client.chat.completions.create(\n", + " model=\"gpt-3.5-turbo\",\n", + " messages=[{\"role\": \"system\", \"content\": \"Tell me a joke\"}],\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "result\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Sync Completion (Streaming)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "client = openai.OpenAI()\n", + "\n", + "stream = client.chat.completions.create(\n", + " model=\"gpt-3.5-turbo\",\n", + " messages=[{\"role\": \"system\", \"content\": \"Tell me a joke\"}],\n", + " stream=True\n", + ")\n", + "\n", + "for x in stream:\n", + " print(x)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Async Completion" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "client = openai.AsyncOpenAI()\n", + "\n", + "result = await client.chat.completions.create(\n", + " model=\"gpt-3.5-turbo\",\n", + " messages=[{\"role\": \"system\", \"content\": \"Tell me a joke\"}],\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "result\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Async Completion (Streaming)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "client = openai.AsyncOpenAI()\n", + "\n", + "stream = await client.chat.completions.create(\n", + " model=\"gpt-3.5-turbo\",\n", + " messages=[{\"role\": \"system\", \"content\": \"Tell me a joke\"}],\n", + " stream=True\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "async for x in stream:\n", + " ...\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "weave310", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.11" + } + }, + "nbformat": 4, + "nbformat_minor": 2 } diff --git a/weave/legacy/examples/experimental/prompts_dev/generate_synth_mon_board.ipynb b/weave/legacy/examples/experimental/prompts_dev/generate_synth_mon_board.ipynb index 96454814a2f..2ee6b8f6d03 100644 --- a/weave/legacy/examples/experimental/prompts_dev/generate_synth_mon_board.ipynb +++ b/weave/legacy/examples/experimental/prompts_dev/generate_synth_mon_board.ipynb @@ -1,192 +1,192 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "4549831c", - "metadata": {}, - "source": [ - "\"Weights\n", - "\n", - "\n", - "\n", - " \"Open\n", - "\n", - "\n", - "# Generate Synthetic Data for Large-Scale LLM Monitoring Demo\n", - "\n", - "This notebook generates synthetic data (Shakespearean dialogue) in the format used by the monitoring.openai integration.\n", - "See the openai_monitoring notebook for instructions for logging real OpenAI API calls.\n", - "\n", - "# Step 0: Setup\n", - "\n", - "Import dependencies" - ] + "cells": [ + { + "cell_type": "markdown", + "id": "4549831c", + "metadata": {}, + "source": [ + "\"Weights\n", + "\n", + "\n", + "\n", + " \"Open\n", + "\n", + "\n", + "# Generate Synthetic Data for Large-Scale LLM Monitoring Demo\n", + "\n", + "This notebook generates synthetic data (Shakespearean dialogue) in the format used by the monitoring.openai integration.\n", + "See the openai_monitoring notebook for instructions for logging real OpenAI API calls.\n", + "\n", + "# Step 0: Setup\n", + "\n", + "Import dependencies" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "00647082", + "metadata": {}, + "outputs": [], + "source": [ + "!pip install -qqq weave\n", + "\n", + "import uuid\n", + "from datetime import timedelta\n", + "import weave\n", + "from weave.legacy.weave import ops_arrow\n", + "from weave.legacy.weave.monitoring import monitor\n", + "from weave.syndata_mon import random_predictions" + ] + }, + { + "cell_type": "markdown", + "id": "a8b49310-4d7a-4f3f-a901-e1f9e87baff8", + "metadata": {}, + "source": [ + "# Step 1: Generate random predictions and montior call spans" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "93653c45", + "metadata": {}, + "outputs": [], + "source": [ + "preds = random_predictions(100)\n", + "\n", + "# Convert synthetic data into the format used by the weave.legacy.weave.monitoring.openai integration\n", + "\n", + "# convert model_version in the synthetic data to an openai model version\n", + "# this makes it so that there's a new API key that has appeared in our logs recently, and that key\n", + "# has started using gpt-4 which makes a cost spike\n", + "versions = sorted(preds.column('model_version').unique())\n", + "version_map = {}\n", + "for i, v in enumerate(reversed(versions)):\n", + " api_key = 'sk-U4...yK7z'\n", + " model = 'gpt-3.5-turbo-0613'\n", + " if i == 1 or i == 2:\n", + " # second and third most recent versions use a different api key\n", + " api_key = 'sk-U9...a22c'\n", + " if i == 1:\n", + " # second most recent version uses gpt-4\n", + " model = 'gpt-4-0613'\n", + " version_map[v] = (api_key, model)\n", + " \n", + "spans = [] \n", + "for i, pred in enumerate(preds):\n", + " api_key, model = version_map[pred['model_version']]\n", + " latency_mult = 1\n", + " if model == 'gpt-4-0613':\n", + " latency_mult = 3\n", + " span = monitor.Span('openai.api_resources.chat_completion.type.create',\n", + " inputs={\n", + " 'messages':[\n", + " {\"role\": \"user\", \"content\": pred['prompt']}\n", + " ]\n", + " },\n", + " output={\n", + " 'id': 'chatcmpl-%s' % uuid.uuid4(),\n", + " 'object': 'chat.completion',\n", + " 'created': pred['timestamp'].timestamp(),\n", + " 'model': model,\n", + " 'choices': [\n", + " {\n", + " 'index': 0,\n", + " 'message': {\n", + " 'role': 'assistant',\n", + " 'content': pred['completion']\n", + " },\n", + " 'finish_reason': 'stop'\n", + " }\n", + " ],\n", + "\n", + " },\n", + " attributes={\n", + " 'api_key': api_key,\n", + " 'username': pred['username']\n", + " },\n", + " summary={\n", + " 'prompt_tokens': pred['prompt_tokens'],\n", + " 'completion_tokens': pred['completion_tokens'],\n", + " 'total_tokens': (pred['prompt_tokens'] + pred['completion_tokens'])\n", + " })\n", + " span.start_time = pred['timestamp']\n", + " span.end_time = pred['timestamp'] + timedelta(seconds=pred['latency'] * latency_mult)\n", + " spans.append({'timestamp': pred['timestamp'], **span.asdict()})" + ] + }, + { + "cell_type": "markdown", + "id": "88479dbd-6fae-4353-974e-5e13704f720f", + "metadata": {}, + "source": [ + "# Step 2: Save and view synthetic data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9548c9aa", + "metadata": {}, + "outputs": [], + "source": [ + "# Save as a local table\n", + "oai_data = weave.save(ops_arrow.to_arrow(spans), 'oai_data')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b59be0b5", + "metadata": {}, + "outputs": [], + "source": [ + "oai_data" + ] + }, + { + "cell_type": "markdown", + "id": "46669b4f-c569-40ee-a6fe-c5f2fdf64eb7", + "metadata": {}, + "source": [ + "# Step 3: View LLM Monitoring Board with synthetic data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7045f1eb", + "metadata": {}, + "outputs": [], + "source": [ + "# Use the llm monitoring template to visualize the data\n", + "from weave.legacy.weave.panels_py import panel_llm_monitor\n", + "board = panel_llm_monitor.board.raw_resolve_fn(oai_data)\n", + "board" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "00647082", - "metadata": {}, - "outputs": [], - "source": [ - "!pip install -qqq weave\n", - "\n", - "import uuid\n", - "from datetime import timedelta\n", - "import weave\n", - "from weave.legacy import ops_arrow\n", - "from weave.legacy.monitoring import monitor\n", - "from weave.syndata_mon import random_predictions" - ] - }, - { - "cell_type": "markdown", - "id": "a8b49310-4d7a-4f3f-a901-e1f9e87baff8", - "metadata": {}, - "source": [ - "# Step 1: Generate random predictions and montior call spans" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "93653c45", - "metadata": {}, - "outputs": [], - "source": [ - "preds = random_predictions(100)\n", - "\n", - "# Convert synthetic data into the format used by the weave.legacy.monitoring.openai integration\n", - "\n", - "# convert model_version in the synthetic data to an openai model version\n", - "# this makes it so that there's a new API key that has appeared in our logs recently, and that key\n", - "# has started using gpt-4 which makes a cost spike\n", - "versions = sorted(preds.column('model_version').unique())\n", - "version_map = {}\n", - "for i, v in enumerate(reversed(versions)):\n", - " api_key = 'sk-U4...yK7z'\n", - " model = 'gpt-3.5-turbo-0613'\n", - " if i == 1 or i == 2:\n", - " # second and third most recent versions use a different api key\n", - " api_key = 'sk-U9...a22c'\n", - " if i == 1:\n", - " # second most recent version uses gpt-4\n", - " model = 'gpt-4-0613'\n", - " version_map[v] = (api_key, model)\n", - " \n", - "spans = [] \n", - "for i, pred in enumerate(preds):\n", - " api_key, model = version_map[pred['model_version']]\n", - " latency_mult = 1\n", - " if model == 'gpt-4-0613':\n", - " latency_mult = 3\n", - " span = monitor.Span('openai.api_resources.chat_completion.type.create',\n", - " inputs={\n", - " 'messages':[\n", - " {\"role\": \"user\", \"content\": pred['prompt']}\n", - " ]\n", - " },\n", - " output={\n", - " 'id': 'chatcmpl-%s' % uuid.uuid4(),\n", - " 'object': 'chat.completion',\n", - " 'created': pred['timestamp'].timestamp(),\n", - " 'model': model,\n", - " 'choices': [\n", - " {\n", - " 'index': 0,\n", - " 'message': {\n", - " 'role': 'assistant',\n", - " 'content': pred['completion']\n", - " },\n", - " 'finish_reason': 'stop'\n", - " }\n", - " ],\n", - "\n", - " },\n", - " attributes={\n", - " 'api_key': api_key,\n", - " 'username': pred['username']\n", - " },\n", - " summary={\n", - " 'prompt_tokens': pred['prompt_tokens'],\n", - " 'completion_tokens': pred['completion_tokens'],\n", - " 'total_tokens': (pred['prompt_tokens'] + pred['completion_tokens'])\n", - " })\n", - " span.start_time = pred['timestamp']\n", - " span.end_time = pred['timestamp'] + timedelta(seconds=pred['latency'] * latency_mult)\n", - " spans.append({'timestamp': pred['timestamp'], **span.asdict()})" - ] - }, - { - "cell_type": "markdown", - "id": "88479dbd-6fae-4353-974e-5e13704f720f", - "metadata": {}, - "source": [ - "# Step 2: Save and view synthetic data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9548c9aa", - "metadata": {}, - "outputs": [], - "source": [ - "# Save as a local table\n", - "oai_data = weave.save(ops_arrow.to_arrow(spans), 'oai_data')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b59be0b5", - "metadata": {}, - "outputs": [], - "source": [ - "oai_data" - ] - }, - { - "cell_type": "markdown", - "id": "46669b4f-c569-40ee-a6fe-c5f2fdf64eb7", - "metadata": {}, - "source": [ - "# Step 3: View LLM Monitoring Board with synthetic data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7045f1eb", - "metadata": {}, - "outputs": [], - "source": [ - "# Use the llm monitoring template to visualize the data\n", - "from weave.legacy.panels_py import panel_llm_monitor\n", - "board = panel_llm_monitor.board.raw_resolve_fn(oai_data)\n", - "board" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/prompts_dev/synthetic_openai_data.ipynb b/weave/legacy/examples/experimental/prompts_dev/synthetic_openai_data.ipynb index c63c29d4311..6baaae82cfb 100644 --- a/weave/legacy/examples/experimental/prompts_dev/synthetic_openai_data.ipynb +++ b/weave/legacy/examples/experimental/prompts_dev/synthetic_openai_data.ipynb @@ -1,167 +1,167 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "4549831c", - "metadata": {}, - "source": [ - "\"Weights\n", - "\n", - "# Generate Synthetic Trace Data\n", - "\n", - "Generate some synthetic OpenAI data we can explore in a LLM Monitoring Debugging Board." - ] + "cells": [ + { + "cell_type": "markdown", + "id": "4549831c", + "metadata": {}, + "source": [ + "\"Weights\n", + "\n", + "# Generate Synthetic Trace Data\n", + "\n", + "Generate some synthetic OpenAI data we can explore in a LLM Monitoring Debugging Board." + ] + }, + { + "cell_type": "markdown", + "id": "e3d9305e", + "metadata": {}, + "source": [ + "# Step 0: Setup" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "00647082", + "metadata": {}, + "outputs": [], + "source": [ + "import uuid\n", + "from datetime import timedelta\n", + "import weave\n", + "\n", + "from weave.legacy.weave import ops_arrow\n", + "from weave.legacy.weave.monitoring import monitor, StreamTable" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "93041e2e", + "metadata": {}, + "outputs": [], + "source": [ + "from weave.syndata_mon import random_predictions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "61b9c12a", + "metadata": {}, + "outputs": [], + "source": [ + "WB_ENTITY = # replace with your W&B username or team name\n", + "WB_PROJECT = \"weave\"\n", + "WB_STREAM = \"synthetic_openai_stream\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "93653c45", + "metadata": {}, + "outputs": [], + "source": [ + "preds = random_predictions(10)\n", + "\n", + "# Convert synthetic data into the format used by the weave.legacy.weave.monitoring.openai integration\n", + "\n", + "# convert model_version in the synthetic data to an openai model version\n", + "# this makes it so that there's a new API key that has appeared in our logs recently, and that key\n", + "# has started using gpt-4 which makes a cost spike\n", + "versions = sorted(preds.column('model_version').unique())\n", + "version_map = {}\n", + "for i, v in enumerate(reversed(versions)):\n", + " api_key = 'sk-U4...yK7z'\n", + " model = 'gpt-3.5-turbo-0613'\n", + " if i == 1 or i == 2:\n", + " # second and third most recent versions use a different api key\n", + " api_key = 'sk-U9...a22c'\n", + " if i == 1:\n", + " # second most recent version uses gpt-4\n", + " model = 'gpt-4-0613'\n", + " version_map[v] = (api_key, model)\n", + " \n", + "spans = [] \n", + "for i, pred in enumerate(preds):\n", + " api_key, model = version_map[pred['model_version']]\n", + " latency_mult = 1\n", + " if model == 'gpt-4-0613':\n", + " latency_mult = 3\n", + " span = monitor.Span('openai.api_resources.chat_completion.type.create',\n", + " inputs={\n", + " 'messages':[\n", + " {\"role\": \"user\", \"content\": pred['prompt']}\n", + " ]\n", + " },\n", + " output={\n", + " 'id': 'chatcmpl-%s' % uuid.uuid4(),\n", + " 'object': 'chat.completion',\n", + " 'created': pred['timestamp'].timestamp(),\n", + " 'model': model,\n", + " 'choices': [\n", + " {\n", + " 'index': 0,\n", + " 'message': {\n", + " 'role': 'assistant',\n", + " 'content': pred['completion']\n", + " },\n", + " 'finish_reason': 'stop'\n", + " }\n", + " ],\n", + "\n", + " },\n", + " attributes={\n", + " 'api_key': api_key,\n", + " 'username': pred['username']\n", + " },\n", + " summary={\n", + " 'prompt_tokens': pred['prompt_tokens'],\n", + " 'completion_tokens': pred['completion_tokens'],\n", + " 'total_tokens': (pred['prompt_tokens'] + pred['completion_tokens'])\n", + " })\n", + " span.start_time = pred['timestamp']\n", + " span.end_time = pred['timestamp'] + timedelta(seconds=pred['latency'] * latency_mult)\n", + " spans.append({'timestamp': pred['timestamp'], **span.asdict()})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9548c9aa", + "metadata": {}, + "outputs": [], + "source": [ + "st = StreamTable(f\"{WB_ENTITY}/{WB_PROJECT}/{WB_STREAM}\")\n", + "\n", + "for span in spans:\n", + " st.log(span)\n", + "\n", + "st.finish()\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "markdown", - "id": "e3d9305e", - "metadata": {}, - "source": [ - "# Step 0: Setup" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "00647082", - "metadata": {}, - "outputs": [], - "source": [ - "import uuid\n", - "from datetime import timedelta\n", - "import weave\n", - "\n", - "from weave.legacy import ops_arrow\n", - "from weave.legacy.monitoring import monitor, StreamTable" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "93041e2e", - "metadata": {}, - "outputs": [], - "source": [ - "from weave.syndata_mon import random_predictions" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "61b9c12a", - "metadata": {}, - "outputs": [], - "source": [ - "WB_ENTITY = # replace with your W&B username or team name\n", - "WB_PROJECT = \"weave\"\n", - "WB_STREAM = \"synthetic_openai_stream\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "93653c45", - "metadata": {}, - "outputs": [], - "source": [ - "preds = random_predictions(10)\n", - "\n", - "# Convert synthetic data into the format used by the weave.legacy.monitoring.openai integration\n", - "\n", - "# convert model_version in the synthetic data to an openai model version\n", - "# this makes it so that there's a new API key that has appeared in our logs recently, and that key\n", - "# has started using gpt-4 which makes a cost spike\n", - "versions = sorted(preds.column('model_version').unique())\n", - "version_map = {}\n", - "for i, v in enumerate(reversed(versions)):\n", - " api_key = 'sk-U4...yK7z'\n", - " model = 'gpt-3.5-turbo-0613'\n", - " if i == 1 or i == 2:\n", - " # second and third most recent versions use a different api key\n", - " api_key = 'sk-U9...a22c'\n", - " if i == 1:\n", - " # second most recent version uses gpt-4\n", - " model = 'gpt-4-0613'\n", - " version_map[v] = (api_key, model)\n", - " \n", - "spans = [] \n", - "for i, pred in enumerate(preds):\n", - " api_key, model = version_map[pred['model_version']]\n", - " latency_mult = 1\n", - " if model == 'gpt-4-0613':\n", - " latency_mult = 3\n", - " span = monitor.Span('openai.api_resources.chat_completion.type.create',\n", - " inputs={\n", - " 'messages':[\n", - " {\"role\": \"user\", \"content\": pred['prompt']}\n", - " ]\n", - " },\n", - " output={\n", - " 'id': 'chatcmpl-%s' % uuid.uuid4(),\n", - " 'object': 'chat.completion',\n", - " 'created': pred['timestamp'].timestamp(),\n", - " 'model': model,\n", - " 'choices': [\n", - " {\n", - " 'index': 0,\n", - " 'message': {\n", - " 'role': 'assistant',\n", - " 'content': pred['completion']\n", - " },\n", - " 'finish_reason': 'stop'\n", - " }\n", - " ],\n", - "\n", - " },\n", - " attributes={\n", - " 'api_key': api_key,\n", - " 'username': pred['username']\n", - " },\n", - " summary={\n", - " 'prompt_tokens': pred['prompt_tokens'],\n", - " 'completion_tokens': pred['completion_tokens'],\n", - " 'total_tokens': (pred['prompt_tokens'] + pred['completion_tokens'])\n", - " })\n", - " span.start_time = pred['timestamp']\n", - " span.end_time = pred['timestamp'] + timedelta(seconds=pred['latency'] * latency_mult)\n", - " spans.append({'timestamp': pred['timestamp'], **span.asdict()})" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9548c9aa", - "metadata": {}, - "outputs": [], - "source": [ - "st = StreamTable(f\"{WB_ENTITY}/{WB_PROJECT}/{WB_STREAM}\")\n", - "\n", - "for span in spans:\n", - " st.log(span)\n", - "\n", - "st.finish()\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/04 Tutorial - Publishing Data and Ops.ipynb b/weave/legacy/examples/experimental/skip_test/04 Tutorial - Publishing Data and Ops.ipynb index 1e5591b2b11..e7355e75f3f 100644 --- a/weave/legacy/examples/experimental/skip_test/04 Tutorial - Publishing Data and Ops.ipynb +++ b/weave/legacy/examples/experimental/skip_test/04 Tutorial - Publishing Data and Ops.ipynb @@ -1,125 +1,125 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "b174bac3", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "from typing import Any\n", - "\n", - "@weave.op()\n", - "def inc(a: int, delta: int = 1) -> int:\n", - " return a + delta\n", - "\n", - "# store x in local dir\n", - "x = weave.save(10, \"local-num\")\n", - "print(x)\n", - "# store y as a remote artifact - this is stateful and will create\n", - "# new versions if you've previously saved this artifact\n", - "y = weave.publish(100, \"remote-num\")\n", - "print(y)" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "b174bac3", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "from typing import Any\n", + "\n", + "@weave.op()\n", + "def inc(a: int, delta: int = 1) -> int:\n", + " return a + delta\n", + "\n", + "# store x in local dir\n", + "x = weave.save(10, \"local-num\")\n", + "print(x)\n", + "# store y as a remote artifact - this is stateful and will create\n", + "# new versions if you've previously saved this artifact\n", + "y = weave.publish(100, \"remote-num\")\n", + "print(y)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1949651f", + "metadata": {}, + "outputs": [], + "source": [ + "# increment constant\n", + "print(weave.use(inc(1)))\n", + "# increment local number - DO NOT SAVE\n", + "print(weave.use(inc(x)))\n", + "# increment remote number - DO NOT SAVE\n", + "print(weave.use(inc(y)))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "efd9ed1c", + "metadata": {}, + "outputs": [], + "source": [ + "# this might take a minute since constructing w&b artifacts is a bit slow atm\n", + "for i in range(0, 5):\n", + " y = weave.use(inc(y, 1))\n", + " # publish result back to remote-num\n", + " weave.publish(y, \"remote-num\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "35a0e593", + "metadata": {}, + "outputs": [], + "source": [ + "# TODO: this doesn't work yet, it only returns the current version\n", + "for version in weave.versions(y):\n", + " print(version)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9d6a69fc", + "metadata": {}, + "outputs": [], + "source": [ + "# we can also publish ops\n", + "remote_op = weave.publish(inc)\n", + "print(remote_op)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7548b05f", + "metadata": {}, + "outputs": [], + "source": [ + "# this cell can be run from a full kernel restart and it should work\n", + "import weave\n", + "import shutil\n", + "from weave.legacy.weave.artifacts_local import LOCAL_ARTIFACT_DIR\n", + "from weave import uris\n", + "\n", + "try:\n", + " shutil.rmtree(LOCAL_ARTIFACT_DIR)\n", + "except FileNotFoundError:\n", + " pass\n", + "\n", + "remote_y = uris.WeaveURI.parse('wandb-artifact://jzhao/weave_ops/remote-num:v0').to_ref().get()\n", + "remote_inc = uris.WeaveURI.parse('wandb-artifact://jzhao/weave_ops/op-def-op-inc:v0').to_ref().get()\n", + "\n", + "remote_y" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "1949651f", - "metadata": {}, - "outputs": [], - "source": [ - "# increment constant\n", - "print(weave.use(inc(1)))\n", - "# increment local number - DO NOT SAVE\n", - "print(weave.use(inc(x)))\n", - "# increment remote number - DO NOT SAVE\n", - "print(weave.use(inc(y)))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "efd9ed1c", - "metadata": {}, - "outputs": [], - "source": [ - "# this might take a minute since constructing w&b artifacts is a bit slow atm\n", - "for i in range(0, 5):\n", - " y = weave.use(inc(y, 1))\n", - " # publish result back to remote-num\n", - " weave.publish(y, \"remote-num\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "35a0e593", - "metadata": {}, - "outputs": [], - "source": [ - "# TODO: this doesn't work yet, it only returns the current version\n", - "for version in weave.versions(y):\n", - " print(version)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9d6a69fc", - "metadata": {}, - "outputs": [], - "source": [ - "# we can also publish ops\n", - "remote_op = weave.publish(inc)\n", - "print(remote_op)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7548b05f", - "metadata": {}, - "outputs": [], - "source": [ - "# this cell can be run from a full kernel restart and it should work\n", - "import weave\n", - "import shutil\n", - "from weave.legacy.artifacts_local import LOCAL_ARTIFACT_DIR\n", - "from weave import uris\n", - "\n", - "try:\n", - " shutil.rmtree(LOCAL_ARTIFACT_DIR)\n", - "except FileNotFoundError:\n", - " pass\n", - "\n", - "remote_y = uris.WeaveURI.parse('wandb-artifact://jzhao/weave_ops/remote-num:v0').to_ref().get()\n", - "remote_inc = uris.WeaveURI.parse('wandb-artifact://jzhao/weave_ops/op-def-op-inc:v0').to_ref().get()\n", - "\n", - "remote_y" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/Composable Python panels.ipynb b/weave/legacy/examples/experimental/skip_test/Composable Python panels.ipynb index 22400d2130f..2a3d08c47be 100644 --- a/weave/legacy/examples/experimental/skip_test/Composable Python panels.ipynb +++ b/weave/legacy/examples/experimental/skip_test/Composable Python panels.ipynb @@ -1,79 +1,79 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "6f2db98c", - "metadata": {}, - "source": [ - "## This demo is not currently working" - ] + "cells": [ + { + "cell_type": "markdown", + "id": "6f2db98c", + "metadata": {}, + "source": [ + "## This demo is not currently working" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5b582daf", + "metadata": {}, + "outputs": [], + "source": [ + "import weave" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "06ea5a95", + "metadata": {}, + "outputs": [], + "source": [ + "container = weave.legacy.weave.panels.Container()\n", + "\n", + "# A couple variables to hold our slider values (this is unnecessary boilerplate that I can\n", + "# get rid of)\n", + "var_a = container.config.add_variable('slider_value_a', weave.types.Number(), 5)\n", + "var_b = container.config.add_variable('slider_value_b', weave.types.Number(), 19)\n", + "\n", + "# Create two sliders in the Container\n", + "container.config.add_panel(\n", + " weave.legacy.weave.panels.Slider(input_node=var_a, config=weave.legacy.weave.panels.SliderConfig(0, 100, 0.1)))\n", + "container.config.add_panel(\n", + " weave.legacy.weave.panels.Slider(input_node=var_b, config=weave.legacy.weave.panels.SliderConfig(-1000, 1000, 1)))\n", + "\n", + "# Use a Number panel to show the results of adding the two sliders together\n", + "container.config.add_panel(\n", + " weave.legacy.weave.panels.Number(input_node=var_a + var_b)\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9423cf32", + "metadata": {}, + "outputs": [], + "source": [ + "weave.show(container)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "5b582daf", - "metadata": {}, - "outputs": [], - "source": [ - "import weave" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "06ea5a95", - "metadata": {}, - "outputs": [], - "source": [ - "container = weave.legacy.panels.Container()\n", - "\n", - "# A couple variables to hold our slider values (this is unnecessary boilerplate that I can\n", - "# get rid of)\n", - "var_a = container.config.add_variable('slider_value_a', weave.types.Number(), 5)\n", - "var_b = container.config.add_variable('slider_value_b', weave.types.Number(), 19)\n", - "\n", - "# Create two sliders in the Container\n", - "container.config.add_panel(\n", - " weave.legacy.panels.Slider(input_node=var_a, config=weave.legacy.panels.SliderConfig(0, 100, 0.1)))\n", - "container.config.add_panel(\n", - " weave.legacy.panels.Slider(input_node=var_b, config=weave.legacy.panels.SliderConfig(-1000, 1000, 1)))\n", - "\n", - "# Use a Number panel to show the results of adding the two sliders together\n", - "container.config.add_panel(\n", - " weave.legacy.panels.Number(input_node=var_a + var_b)\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9423cf32", - "metadata": {}, - "outputs": [], - "source": [ - "weave.show(container)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/Confusion Matrix.ipynb b/weave/legacy/examples/experimental/skip_test/Confusion Matrix.ipynb index 02e964017eb..2aabd645afa 100644 --- a/weave/legacy/examples/experimental/skip_test/Confusion Matrix.ipynb +++ b/weave/legacy/examples/experimental/skip_test/Confusion Matrix.ipynb @@ -1,288 +1,288 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "51500f80", - "metadata": {}, - "outputs": [], - "source": [ - "import random\n", - "import typing\n", - "import itertools\n", - "from PIL import Image\n", - "import weave\n", - "from weave.legacy import storage\n", - "from weave.legacy import weave_internal\n", - "#weave.use_frontend_devmode()" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "51500f80", + "metadata": {}, + "outputs": [], + "source": [ + "import random\n", + "import typing\n", + "import itertools\n", + "from PIL import Image\n", + "import weave\n", + "from weave.legacy.weave import storage\n", + "from weave.legacy.weave import weave_internal\n", + "#weave.use_frontend_devmode()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b6e5e1c9", + "metadata": {}, + "outputs": [], + "source": [ + "# Not really model predictions but it'll work for now\n", + "import string\n", + "import hashlib\n", + "\n", + "def simple_hash(n, b):\n", + " return int.from_bytes(hashlib.sha256(str(n).encode()).digest(), \"little\") % b\n", + "\n", + "def create_data(n_rows, n_extra_cols, images=False):\n", + " inner_count = int(n_rows / 25)\n", + " base_im = Image.linear_gradient('L').resize((32, 32))\n", + " x_choices = string.ascii_lowercase\n", + " extra_cols = [chr(ord('a') + i) for i in range(n_extra_cols)]\n", + " ims = []\n", + " for i, (rotate, shear, _) in enumerate(\n", + " itertools.product(range(5), range(5), range(inner_count))\n", + " ):\n", + " im ={\n", + " 'rotate': rotate,\n", + " 'shear': shear,\n", + " 'y': x_choices[simple_hash(i**13, 5)],\n", + " 'x': x_choices[simple_hash(i**13, 11)]\n", + " }\n", + " if images:\n", + " im['image'] = (base_im\n", + " .rotate(rotate * 4)\n", + " .transform((32, 32), Image.AFFINE, (1, shear / 10, 0, 0, 1, 0), Image.BICUBIC))\n", + " for j, col in enumerate(extra_cols):\n", + " im[col] = x_choices[simple_hash(i*13**j, 11)]\n", + " ims.append(im)\n", + " return ims\n", + "\n", + "ims = create_data(100, 1, True)\n", + "#ims = storage.to_arrow(ims)\n", + "#ims = weave.save(ims)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2da45914", + "metadata": {}, + "outputs": [], + "source": [ + "weave.show(ims)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "49501ff4", + "metadata": {}, + "outputs": [], + "source": [ + "plot = weave.legacy.weave.panels.Plot(ims)\n", + "plot.set_x(lambda row: row['rotate'])\n", + "plot.set_y(lambda row: row['x'])\n", + "plot.set_tooltip(lambda row: row['image'])\n", + "weave.show(plot)" + ] + }, + { + "cell_type": "markdown", + "id": "6583e01c", + "metadata": {}, + "source": [ + "## Facet is fun!\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "090d8ab8", + "metadata": {}, + "outputs": [], + "source": [ + "# This is one way to build a multi-confusion matrix.\n", + "\n", + "facet = weave.legacy.weave.panels.Facet(\n", + " input_node=ims,\n", + " x=lambda im: im['rotate'],\n", + " y=lambda im: im['shear'],\n", + " select=lambda cell: weave.legacy.weave.panels.Plot(\n", + " input_node=cell.groupby(lambda row: row['y']),\n", + " x=lambda group: group.count(),\n", + " y=lambda group: group.key(),\n", + " label=lambda group: group.key(),\n", + " tooltip=lambda group: group.map(lambda r: r['image']),\n", + " mark='bar',\n", + " no_axes=True,\n", + " no_legend=True\n", + " )\n", + ")\n", + "\n", + "weave.show(facet)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e987f626", + "metadata": {}, + "outputs": [], + "source": [ + "# @weave.op()\n", + "# def confusion_matrix(inp: typing.Any, guess_col: str, truth_col: str, compare_col: str) -> weave.legacy.weave.panels.Facet:\n", + "# return weave.legacy.weave.panels.Facet(\n", + "# input_node=inp,\n", + "# x=lambda i: i[guess_col],\n", + "# y=lambda i: i[truth_col],\n", + "# select=lambda cell: weave.legacy.weave.panels.Plot(\n", + "# input_node=cell.groupby(\n", + "# weave.define_fn({'row': cell.type.object_type}, lambda row: row[compare_col])),\n", + "# x=lambda group: group.count(),\n", + "# y=lambda group: group.key(),\n", + "# label=lambda group: group.key(),\n", + "# mark='bar',\n", + "# no_axes=True,\n", + "# no_legend=True\n", + "# )\n", + "# )\n", + "\n", + "# An example of a Panel returning op. This (sort of) works but there are lots of \n", + "\n", + "@weave.op()\n", + "def confusion_matrix(inp: typing.Any, guess_col: str, truth_col: str, compare_col: str) -> weave.legacy.weave.panels.Facet:\n", + " return weave.legacy.weave.panels.Facet(\n", + " input_node=inp,\n", + " x=lambda i: i[guess_col],\n", + " y=lambda i: i[truth_col],\n", + " select=lambda cell: cell.count()\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9c800bac", + "metadata": {}, + "outputs": [], + "source": [ + "demos.confusion_matrix(ims, 'rotate', 'x', 'y')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7eff6907", + "metadata": {}, + "outputs": [], + "source": [ + "# Other explorations\n", + "\n", + "\n", + "# weave.show(facet)\n", + "\n", + "# # Not working yet, but playing with removing lambdas\n", + "# facet = weave.legacy.weave.panels.Facet(\n", + "# input_node=ims,\n", + "# x=ims['rotate'],\n", + "# y=ims['shear'],\n", + "# select=lambda cell: weave.legacy.weave.panels.Plot(\n", + "# input_node=cell.groupby(cell.row['y']),\n", + "# x=lambda group: group.count(),\n", + "# y=lambda group: group.key(),\n", + "# label=lambda group: group.key(),\n", + "# mark='bar',\n", + "# no_axes=True,\n", + "# no_legend=True\n", + "# )\n", + "# )\n", + "\n", + "# # Maybe another cool thing\n", + "# facet = weave.legacy.weave.panels.Facet(\n", + "# input_node=ims,\n", + "# x=lambda im: im['rotate'],\n", + "# y=lambda im: im['shear'],\n", + "# select=lambda cell_ims: cell_ims.groupby(cell.row['y'])\n", + "# .Plot(\n", + "# x=lambda group: group.count(),\n", + "# y=lambda group: group.key(),\n", + "# label=lambda group: group.key(),\n", + "# mark='bar',\n", + "# no_axes=True,\n", + "# no_legend=True\n", + "# )\n", + "# )\n", + "\n", + "# # OK actually its more like we just always want to drop the first argument\n", + "# # This is finally minimal, but we can't get autocomplete help.\n", + "# facet = ims.Facet(\n", + "# x=select('rotate'),\n", + "# y=select('shear'),\n", + "# select=groupby('y')\n", + "# .Plot(\n", + "# x=count(),\n", + "# y=group_key(),\n", + "# label=group_key(),\n", + "# mark=select('bar'),\n", + "# no_axes=True,\n", + "# no_legend=True\n", + "# )\n", + "# )\n", + "\n", + "# # Hmm.\n", + "# facet = ims\n", + "# .groupby(\n", + "# facet_x=select('rotate'),\n", + "# facet_y=select('shear'),\n", + "# y=select('run'))\n", + "# .count()\n", + "# .Plot()\n", + "\n", + "# facet = Plot(\n", + "# ims,\n", + "# facet_x=select('rotate'),\n", + "# facet_y=select('shear'),\n", + "# y=select('run')\n", + "# x=count()\n", + ")\n", + "\n", + "# TODO:\n", + "# - get rid of lambdas (ims.row could be a variable?)\n", + "# ... or we could just treat ims as the row variable when its assigned to a plot?\n", + "# - This is why react is a little nicer, component control flow isn't usually hidden\n", + "# away inside other components (framework style). Instead, you decide how you want to lay stuff\n", + "# out...\n", + "# - But we can achieve that here... We just need to make some lower level components.\n", + "# (Try IT!) Instead of PanelFacet, use PanelLayout or PanelGrid or something\n", + "# - see if we can get rid of groupby requirement in PanelPlot. You don't need it in Vega\n", + "# - also maybe look at Altair API?\n", + "#\n", + "# In react you'd do:\n", + "# const ConfusionMatrix = (ims) => (\n", + "# \n", + "# \n", + "# \n", + "# )" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "b6e5e1c9", - "metadata": {}, - "outputs": [], - "source": [ - "# Not really model predictions but it'll work for now\n", - "import string\n", - "import hashlib\n", - "\n", - "def simple_hash(n, b):\n", - " return int.from_bytes(hashlib.sha256(str(n).encode()).digest(), \"little\") % b\n", - "\n", - "def create_data(n_rows, n_extra_cols, images=False):\n", - " inner_count = int(n_rows / 25)\n", - " base_im = Image.linear_gradient('L').resize((32, 32))\n", - " x_choices = string.ascii_lowercase\n", - " extra_cols = [chr(ord('a') + i) for i in range(n_extra_cols)]\n", - " ims = []\n", - " for i, (rotate, shear, _) in enumerate(\n", - " itertools.product(range(5), range(5), range(inner_count))\n", - " ):\n", - " im ={\n", - " 'rotate': rotate,\n", - " 'shear': shear,\n", - " 'y': x_choices[simple_hash(i**13, 5)],\n", - " 'x': x_choices[simple_hash(i**13, 11)]\n", - " }\n", - " if images:\n", - " im['image'] = (base_im\n", - " .rotate(rotate * 4)\n", - " .transform((32, 32), Image.AFFINE, (1, shear / 10, 0, 0, 1, 0), Image.BICUBIC))\n", - " for j, col in enumerate(extra_cols):\n", - " im[col] = x_choices[simple_hash(i*13**j, 11)]\n", - " ims.append(im)\n", - " return ims\n", - "\n", - "ims = create_data(100, 1, True)\n", - "#ims = storage.to_arrow(ims)\n", - "#ims = weave.save(ims)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2da45914", - "metadata": {}, - "outputs": [], - "source": [ - "weave.show(ims)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "49501ff4", - "metadata": {}, - "outputs": [], - "source": [ - "plot = weave.legacy.panels.Plot(ims)\n", - "plot.set_x(lambda row: row['rotate'])\n", - "plot.set_y(lambda row: row['x'])\n", - "plot.set_tooltip(lambda row: row['image'])\n", - "weave.show(plot)" - ] - }, - { - "cell_type": "markdown", - "id": "6583e01c", - "metadata": {}, - "source": [ - "## Facet is fun!\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "090d8ab8", - "metadata": {}, - "outputs": [], - "source": [ - "# This is one way to build a multi-confusion matrix.\n", - "\n", - "facet = weave.legacy.panels.Facet(\n", - " input_node=ims,\n", - " x=lambda im: im['rotate'],\n", - " y=lambda im: im['shear'],\n", - " select=lambda cell: weave.legacy.panels.Plot(\n", - " input_node=cell.groupby(lambda row: row['y']),\n", - " x=lambda group: group.count(),\n", - " y=lambda group: group.key(),\n", - " label=lambda group: group.key(),\n", - " tooltip=lambda group: group.map(lambda r: r['image']),\n", - " mark='bar',\n", - " no_axes=True,\n", - " no_legend=True\n", - " )\n", - ")\n", - "\n", - "weave.show(facet)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e987f626", - "metadata": {}, - "outputs": [], - "source": [ - "# @weave.op()\n", - "# def confusion_matrix(inp: typing.Any, guess_col: str, truth_col: str, compare_col: str) -> weave.legacy.panels.Facet:\n", - "# return weave.legacy.panels.Facet(\n", - "# input_node=inp,\n", - "# x=lambda i: i[guess_col],\n", - "# y=lambda i: i[truth_col],\n", - "# select=lambda cell: weave.legacy.panels.Plot(\n", - "# input_node=cell.groupby(\n", - "# weave.define_fn({'row': cell.type.object_type}, lambda row: row[compare_col])),\n", - "# x=lambda group: group.count(),\n", - "# y=lambda group: group.key(),\n", - "# label=lambda group: group.key(),\n", - "# mark='bar',\n", - "# no_axes=True,\n", - "# no_legend=True\n", - "# )\n", - "# )\n", - "\n", - "# An example of a Panel returning op. This (sort of) works but there are lots of \n", - "\n", - "@weave.op()\n", - "def confusion_matrix(inp: typing.Any, guess_col: str, truth_col: str, compare_col: str) -> weave.legacy.panels.Facet:\n", - " return weave.legacy.panels.Facet(\n", - " input_node=inp,\n", - " x=lambda i: i[guess_col],\n", - " y=lambda i: i[truth_col],\n", - " select=lambda cell: cell.count()\n", - " )" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9c800bac", - "metadata": {}, - "outputs": [], - "source": [ - "demos.confusion_matrix(ims, 'rotate', 'x', 'y')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7eff6907", - "metadata": {}, - "outputs": [], - "source": [ - "# Other explorations\n", - "\n", - "\n", - "# weave.show(facet)\n", - "\n", - "# # Not working yet, but playing with removing lambdas\n", - "# facet = weave.legacy.panels.Facet(\n", - "# input_node=ims,\n", - "# x=ims['rotate'],\n", - "# y=ims['shear'],\n", - "# select=lambda cell: weave.legacy.panels.Plot(\n", - "# input_node=cell.groupby(cell.row['y']),\n", - "# x=lambda group: group.count(),\n", - "# y=lambda group: group.key(),\n", - "# label=lambda group: group.key(),\n", - "# mark='bar',\n", - "# no_axes=True,\n", - "# no_legend=True\n", - "# )\n", - "# )\n", - "\n", - "# # Maybe another cool thing\n", - "# facet = weave.legacy.panels.Facet(\n", - "# input_node=ims,\n", - "# x=lambda im: im['rotate'],\n", - "# y=lambda im: im['shear'],\n", - "# select=lambda cell_ims: cell_ims.groupby(cell.row['y'])\n", - "# .Plot(\n", - "# x=lambda group: group.count(),\n", - "# y=lambda group: group.key(),\n", - "# label=lambda group: group.key(),\n", - "# mark='bar',\n", - "# no_axes=True,\n", - "# no_legend=True\n", - "# )\n", - "# )\n", - "\n", - "# # OK actually its more like we just always want to drop the first argument\n", - "# # This is finally minimal, but we can't get autocomplete help.\n", - "# facet = ims.Facet(\n", - "# x=select('rotate'),\n", - "# y=select('shear'),\n", - "# select=groupby('y')\n", - "# .Plot(\n", - "# x=count(),\n", - "# y=group_key(),\n", - "# label=group_key(),\n", - "# mark=select('bar'),\n", - "# no_axes=True,\n", - "# no_legend=True\n", - "# )\n", - "# )\n", - "\n", - "# # Hmm.\n", - "# facet = ims\n", - "# .groupby(\n", - "# facet_x=select('rotate'),\n", - "# facet_y=select('shear'),\n", - "# y=select('run'))\n", - "# .count()\n", - "# .Plot()\n", - "\n", - "# facet = Plot(\n", - "# ims,\n", - "# facet_x=select('rotate'),\n", - "# facet_y=select('shear'),\n", - "# y=select('run')\n", - "# x=count()\n", - ")\n", - "\n", - "# TODO:\n", - "# - get rid of lambdas (ims.row could be a variable?)\n", - "# ... or we could just treat ims as the row variable when its assigned to a plot?\n", - "# - This is why react is a little nicer, component control flow isn't usually hidden\n", - "# away inside other components (framework style). Instead, you decide how you want to lay stuff\n", - "# out...\n", - "# - But we can achieve that here... We just need to make some lower level components.\n", - "# (Try IT!) Instead of PanelFacet, use PanelLayout or PanelGrid or something\n", - "# - see if we can get rid of groupby requirement in PanelPlot. You don't need it in Vega\n", - "# - also maybe look at Altair API?\n", - "#\n", - "# In react you'd do:\n", - "# const ConfusionMatrix = (ims) => (\n", - "# \n", - "# \n", - "# \n", - "# )" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/Custom ops.ipynb b/weave/legacy/examples/experimental/skip_test/Custom ops.ipynb index 0b0ee07a208..6392f1d34fd 100644 --- a/weave/legacy/examples/experimental/skip_test/Custom ops.ipynb +++ b/weave/legacy/examples/experimental/skip_test/Custom ops.ipynb @@ -1,149 +1,149 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "f6c524b9", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "import math\n", - "weave.use_frontend_devmode()" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "f6c524b9", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "import math\n", + "weave.use_frontend_devmode()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a257651b", + "metadata": {}, + "outputs": [], + "source": [ + "# Create our own useful op.\n", + "\n", + "import math\n", + "\n", + "@weave.op()\n", + "def my_func(x: float) -> float:\n", + " return math.sin(x / 0.2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "89b6c0db", + "metadata": {}, + "outputs": [], + "source": [ + "# Now show it.\n", + "# Weave tries to guess the best way to show your data. Its first guess is not very good yet, so let's teach it!\n", + "# Click the gear icon to configure the Panel\n", + "# Try \"List of: Number\". You can page left to right using the controls that the bottom.\n", + "# Switch to \"Plot\"\n", + "# Pick \"row\" as the x value (todo this should be called \"i\" or \"item\" instead of row)\n", + "# Pick \"row * row\" as the y value.\n", + "# Cool, we made a curve!\n", + "\n", + "\n", + "x = [i / 1000.0 for i in range(0, 1000)]\n", + "\n", + "plot = weave.legacy.weave.panels.Plot(x)\n", + "plot.set_x(lambda row: row)\n", + "plot.set_y(lambda row: my_func(row))\n", + "weave.show(plot)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3d97c0fd", + "metadata": {}, + "outputs": [], + "source": [ + "run_data = []\n", + "xs = [i / 1000.0 for i in range(0, 1000)]\n", + "for run in range(3):\n", + " run_data.append({\n", + " 'id': 'id-%s' % run,\n", + " 'x': xs,\n", + " 'y': [math.sin(10 * x / (run+1)) for x in xs]\n", + " })\n", + "plot = weave.legacy.weave.panels.Plot(run_data)\n", + "plot.set_x(lambda row: row['x'])\n", + "plot.set_y(lambda row: row['y'])\n", + "plot.set_label(lambda row: row['id'])\n", + "weave.show(plot)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5f9b0741", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "df = pd.DataFrame()\n", + "df['x'] = [i / 1000.0 for i in range(0, 1000)]\n", + "df['y1'] = df['x'].map(lambda x: math.sin(10 * x / 1))\n", + "df['y2'] = df['x'].map(lambda x: math.sin(10 * x / 2))\n", + "df['y3'] = df['x'].map(lambda x: math.sin(10 * x / 3))\n", + "\n", + "# df.melt converts to a table with three columns: x, series, y\n", + "df = df.melt(id_vars=['x'], value_vars=['y1', 'y2', 'y3'], var_name='series', value_name='y')\n", + "\n", + "multiple_y = df.to_dict('records')\n", + "plot = weave.legacy.weave.panels.Plot(multiple_y)\n", + "plot.set_x(lambda row: row['x'])\n", + "plot.set_y(lambda row: row['y'])\n", + "plot.set_label(lambda row: row['series'])\n", + "plot.set_mark('line')\n", + "weave.show(plot)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "07752656", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "df = pd.DataFrame()\n", + "df['x'] = [i / 1000.0 for i in range(0, 1000)]\n", + "df['y1'] = df['x'].map(lambda x: math.sin(10 * x / 1))\n", + "df['y2'] = df['x'].map(lambda x: math.sin(10 * x / 2))\n", + "df['y3'] = df['x'].map(lambda x: math.sin(10 * x / 3))\n", + "multiple_y = df.to_dict('records')\n", + "\n", + "plot = weave.legacy.weave.panels.Plot(multiple_y)\n", + "plot.set_x(lambda row: row['x'])\n", + "plot.set_y(lambda row: [row['y1'], row['y2'], row['y3']])\n", + "plot.set_label(lambda row: ['y1', 'y2', 'y3'])\n", + "plot.set_mark('line')\n", + "weave.show(plot)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "a257651b", - "metadata": {}, - "outputs": [], - "source": [ - "# Create our own useful op.\n", - "\n", - "import math\n", - "\n", - "@weave.op()\n", - "def my_func(x: float) -> float:\n", - " return math.sin(x / 0.2)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "89b6c0db", - "metadata": {}, - "outputs": [], - "source": [ - "# Now show it.\n", - "# Weave tries to guess the best way to show your data. Its first guess is not very good yet, so let's teach it!\n", - "# Click the gear icon to configure the Panel\n", - "# Try \"List of: Number\". You can page left to right using the controls that the bottom.\n", - "# Switch to \"Plot\"\n", - "# Pick \"row\" as the x value (todo this should be called \"i\" or \"item\" instead of row)\n", - "# Pick \"row * row\" as the y value.\n", - "# Cool, we made a curve!\n", - "\n", - "\n", - "x = [i / 1000.0 for i in range(0, 1000)]\n", - "\n", - "plot = weave.legacy.panels.Plot(x)\n", - "plot.set_x(lambda row: row)\n", - "plot.set_y(lambda row: my_func(row))\n", - "weave.show(plot)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3d97c0fd", - "metadata": {}, - "outputs": [], - "source": [ - "run_data = []\n", - "xs = [i / 1000.0 for i in range(0, 1000)]\n", - "for run in range(3):\n", - " run_data.append({\n", - " 'id': 'id-%s' % run,\n", - " 'x': xs,\n", - " 'y': [math.sin(10 * x / (run+1)) for x in xs]\n", - " })\n", - "plot = weave.legacy.panels.Plot(run_data)\n", - "plot.set_x(lambda row: row['x'])\n", - "plot.set_y(lambda row: row['y'])\n", - "plot.set_label(lambda row: row['id'])\n", - "weave.show(plot)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5f9b0741", - "metadata": {}, - "outputs": [], - "source": [ - "import pandas as pd\n", - "df = pd.DataFrame()\n", - "df['x'] = [i / 1000.0 for i in range(0, 1000)]\n", - "df['y1'] = df['x'].map(lambda x: math.sin(10 * x / 1))\n", - "df['y2'] = df['x'].map(lambda x: math.sin(10 * x / 2))\n", - "df['y3'] = df['x'].map(lambda x: math.sin(10 * x / 3))\n", - "\n", - "# df.melt converts to a table with three columns: x, series, y\n", - "df = df.melt(id_vars=['x'], value_vars=['y1', 'y2', 'y3'], var_name='series', value_name='y')\n", - "\n", - "multiple_y = df.to_dict('records')\n", - "plot = weave.legacy.panels.Plot(multiple_y)\n", - "plot.set_x(lambda row: row['x'])\n", - "plot.set_y(lambda row: row['y'])\n", - "plot.set_label(lambda row: row['series'])\n", - "plot.set_mark('line')\n", - "weave.show(plot)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "07752656", - "metadata": {}, - "outputs": [], - "source": [ - "import pandas as pd\n", - "df = pd.DataFrame()\n", - "df['x'] = [i / 1000.0 for i in range(0, 1000)]\n", - "df['y1'] = df['x'].map(lambda x: math.sin(10 * x / 1))\n", - "df['y2'] = df['x'].map(lambda x: math.sin(10 * x / 2))\n", - "df['y3'] = df['x'].map(lambda x: math.sin(10 * x / 3))\n", - "multiple_y = df.to_dict('records')\n", - "\n", - "plot = weave.legacy.panels.Plot(multiple_y)\n", - "plot.set_x(lambda row: row['x'])\n", - "plot.set_y(lambda row: [row['y1'], row['y2'], row['y3']])\n", - "plot.set_label(lambda row: ['y1', 'y2', 'y3'])\n", - "plot.set_mark('line')\n", - "weave.show(plot)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/Diffusion explore 2.ipynb b/weave/legacy/examples/experimental/skip_test/Diffusion explore 2.ipynb index 3337cda943e..00723093f18 100644 --- a/weave/legacy/examples/experimental/skip_test/Diffusion explore 2.ipynb +++ b/weave/legacy/examples/experimental/skip_test/Diffusion explore 2.ipynb @@ -1,101 +1,101 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "00411857", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "from weave.legacy import weave_internal\n", - "from weave.legacy.ecosystem.all import langchain\n", - "weave.use_frontend_devmode()" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "00411857", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "from weave.legacy.weave import weave_internal\n", + "from weave.legacy.weave.ecosystem.all import langchain\n", + "weave.use_frontend_devmode()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "30c46465", + "metadata": {}, + "outputs": [], + "source": [ + "weave.legacy.weave.panels.Board(\n", + " vars={\n", + " \"chat_model\": langchain.chat_openai(\"gpt-3.5-turbo\", 0.7),\n", + " \"animals\": weave.legacy.weave.panels.Query(\n", + " [\"koala\", \"giraffe\", \"leopard\"],\n", + " text=lambda item: item\n", + " ),\n", + " \"objects\": weave.legacy.weave.panels.Query(\n", + " [\"spoon\", \"guitar\"],\n", + " text=lambda item: item\n", + " ),\n", + " \"prompts\": weave.legacy.weave.panels.Query([\n", + " \"A {animal} with an {object}\",\n", + " \"A 20-word story about a {animal} with an {object}\",\n", + " \"You are creative writer. Describe a scene with a {animal} and a {object}. Choose an art style and use adjectives that evoke it.\"\n", + " ],\n", + " text=lambda item: item),\n", + " \"combos\": lambda animals, objects, prompts:\n", + " weave.legacy.weave.ops.cross_product(weave.legacy.weave.ops.dict_(\n", + " animal=animals.pinned_data(),\n", + " object=objects.pinned_data(),\n", + " prompt=prompts.pinned_data())),\n", + "\n", + " },\n", + " panels=[\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda chat_model, combos: weave.legacy.weave.panels.Facet(\n", + " combos,\n", + " cell_size=(256, 256),\n", + " x=lambda item: item['animal'] + ' ' + item['object'],\n", + " y=lambda item: item['prompt'],\n", + " select=lambda items: \n", + " weave.legacy.weave.panels.Group(\n", + " vars={\n", + " 'gen_text': chat_model.predict(\n", + " items[0]['prompt'].format(weave.legacy.weave.ops.dict_(\n", + " animal=items[0]['animal'],\n", + " object=items[0]['object'],\n", + " ))),\n", + " },\n", + " items={\n", + " 'text': lambda gen_text: gen_text,\n", + " 'image': lambda gen_text: gen_text.stable_diffusion()\n", + " }\n", + " )\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=24, h=24)\n", + " )\n", + "# weave.legacy.weave.panels.BoardPanel(\n", + "# lambda col_names: weave.legacy.weave.panels.Table(col_names, columns=[lambda col: col]),\n", + "# layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=12, w=12, h=6)\n", + "# ),\n", + "# weave.legacy.weave.panels.BoardPanel(\n", + "# lambda row_names: weave.legacy.weave.panels.Table(row_names, columns=[lambda row: row]),\n", + "# layout=weave.legacy.weave.panels.BoardPanelLayout(x=12, y=12, w=12, h=6)\n", + "# ),\n", + " ]\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c8d3d23b", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "30c46465", - "metadata": {}, - "outputs": [], - "source": [ - "weave.legacy.panels.Board(\n", - " vars={\n", - " \"chat_model\": langchain.chat_openai(\"gpt-3.5-turbo\", 0.7),\n", - " \"animals\": weave.legacy.panels.Query(\n", - " [\"koala\", \"giraffe\", \"leopard\"],\n", - " text=lambda item: item\n", - " ),\n", - " \"objects\": weave.legacy.panels.Query(\n", - " [\"spoon\", \"guitar\"],\n", - " text=lambda item: item\n", - " ),\n", - " \"prompts\": weave.legacy.panels.Query([\n", - " \"A {animal} with an {object}\",\n", - " \"A 20-word story about a {animal} with an {object}\",\n", - " \"You are creative writer. Describe a scene with a {animal} and a {object}. Choose an art style and use adjectives that evoke it.\"\n", - " ],\n", - " text=lambda item: item),\n", - " \"combos\": lambda animals, objects, prompts:\n", - " weave.legacy.ops.cross_product(weave.legacy.ops.dict_(\n", - " animal=animals.pinned_data(),\n", - " object=objects.pinned_data(),\n", - " prompt=prompts.pinned_data())),\n", - "\n", - " },\n", - " panels=[\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda chat_model, combos: weave.legacy.panels.Facet(\n", - " combos,\n", - " cell_size=(256, 256),\n", - " x=lambda item: item['animal'] + ' ' + item['object'],\n", - " y=lambda item: item['prompt'],\n", - " select=lambda items: \n", - " weave.legacy.panels.Group(\n", - " vars={\n", - " 'gen_text': chat_model.predict(\n", - " items[0]['prompt'].format(weave.legacy.ops.dict_(\n", - " animal=items[0]['animal'],\n", - " object=items[0]['object'],\n", - " ))),\n", - " },\n", - " items={\n", - " 'text': lambda gen_text: gen_text,\n", - " 'image': lambda gen_text: gen_text.stable_diffusion()\n", - " }\n", - " )\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=24, h=24)\n", - " )\n", - "# weave.legacy.panels.BoardPanel(\n", - "# lambda col_names: weave.legacy.panels.Table(col_names, columns=[lambda col: col]),\n", - "# layout=weave.legacy.panels.BoardPanelLayout(x=0, y=12, w=12, h=6)\n", - "# ),\n", - "# weave.legacy.panels.BoardPanel(\n", - "# lambda row_names: weave.legacy.panels.Table(row_names, columns=[lambda row: row]),\n", - "# layout=weave.legacy.panels.BoardPanelLayout(x=12, y=12, w=12, h=6)\n", - "# ),\n", - " ]\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c8d3d23b", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/Diffusion explore.ipynb b/weave/legacy/examples/experimental/skip_test/Diffusion explore.ipynb index a253ccdaae5..9289d57e217 100644 --- a/weave/legacy/examples/experimental/skip_test/Diffusion explore.ipynb +++ b/weave/legacy/examples/experimental/skip_test/Diffusion explore.ipynb @@ -1,169 +1,169 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "6048a38a", - "metadata": {}, - "source": [ - "# Diffusion exploration\n", - "\n", - "Progammatically build a Weave Dashboard that generates a grid of increasingly magical images of unlikely pairs of animals.\n", - "\n", - "## Play with parameters\n", - "\n", - "* topic: change what the pairs are (animals? plants? minerals?)\n", - "* num_cols: change the number of levels/granularity of increasing magic\n", - "* num_rows: change how many groupings of the subject are generated :)\n", - "* prompts: edit the text of the prompt in col_names or row_names to modify this setup :)" - ] + "cells": [ + { + "cell_type": "markdown", + "id": "6048a38a", + "metadata": {}, + "source": [ + "# Diffusion exploration\n", + "\n", + "Progammatically build a Weave Dashboard that generates a grid of increasingly magical images of unlikely pairs of animals.\n", + "\n", + "## Play with parameters\n", + "\n", + "* topic: change what the pairs are (animals? plants? minerals?)\n", + "* num_cols: change the number of levels/granularity of increasing magic\n", + "* num_rows: change how many groupings of the subject are generated :)\n", + "* prompts: edit the text of the prompt in col_names or row_names to modify this setup :)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "00411857", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "from weave.legacy.weave import weave_internal\n", + "from weave.legacy.weave.ecosystem.all import langchain" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "30c46465", + "metadata": {}, + "outputs": [], + "source": [ + "weave.legacy.weave.panels.Board(\n", + " vars={\n", + " \"chat_model\": langchain.chat_openai(\"gpt-3.5-turbo\", 0.7),\n", + " \"topic\": \"animals\",\n", + " \"num_cols\": 2,\n", + " \"col_names\": lambda chat_model, num_cols: weave.legacy.weave.ops.range(0, num_cols, 1).map(\n", + " lambda i: chat_model.predict(weave_internal.const(\"You are a creative writer. You've come up with \")\n", + " + i.toString()\n", + " + \" ordered descriptive phrases (3 words or fewer) that represent how magical something is, from least magical to most. Phrase \"\n", + " + i.toString()\n", + " + \" is:\")\n", + " ),\n", + " \"num_rows\": 2,\n", + " \"row_names\": lambda chat_model, topic, num_rows: weave.legacy.weave.ops.range(0, num_rows, 1).map(\n", + " lambda i: chat_model.predict(weave_internal.const(\"You are a creative writer. You've come up with \")\n", + " + i.toString()\n", + " + \" \" + topic\n", + " + \" that are unlikely to be seen together. Number \"\n", + " + i.toString()\n", + " + \" is: \")\n", + " ),\n", + "\n", + " },\n", + " panels=[\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda num_rows, num_cols, row_names, col_names: weave.legacy.weave.panels.Facet(\n", + " weave.legacy.weave.ops.range(0, num_rows * num_cols, 1),\n", + " cell_size=(192, 192),\n", + " x=lambda i: col_names[i % num_cols],\n", + " y=lambda i: row_names[(i / num_cols).floor()],\n", + " select=lambda cell_values: (\n", + " weave_internal.const(\"cute hd cartoon of \")\n", + " + row_names[(cell_values[0] / num_cols).floor()]\n", + " + \" \"\n", + " + col_names[(cell_values[0] % num_cols)]).stable_diffusion()\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=24, h=12)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda col_names: weave.legacy.weave.panels.Table(col_names, columns=[lambda col: col]),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=12, w=12, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda row_names: weave.legacy.weave.panels.Table(row_names, columns=[lambda row: row]),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=12, y=12, w=12, h=6)\n", + " ),\n", + " ]\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c0f6057c", + "metadata": {}, + "outputs": [], + "source": [ + "weave.save(\n", + "\"\"\"\n", + "weave.legacy.weave.panels.Board(\n", + " vars={\n", + " \"chat_model\": langchain.chat_openai(\"gpt-3.5-turbo\", 0.7),\n", + " \"num_cols\": 2,\n", + " \"col_names\": lambda chat_model, num_cols: weave.legacy.weave.ops.range(0, num_cols, 1).map(\n", + " lambda i: chat_model.predict(weave_internal.const(\"You are a creative writer. You've come up with \")\n", + " + i.toString()\n", + " + \" ordered descriptive phrases (3 words or fewer) that represent how magical something is, from least magical to most. Phrase \"\n", + " + i.toString()\n", + " + \" is:\")\n", + " ),\n", + " \"num_rows\": 2,\n", + " \"row_names\": lambda chat_model, num_rows: weave.legacy.weave.ops.range(0, num_rows, 1).map(\n", + " lambda i: chat_model.predict(weave_internal.const(\"You are a creative writer. You've come up with \")\n", + " + i.toString()\n", + " + \" animals that are unlikely to be seen together. Animal \"\n", + " + i.toString()\n", + " + \" is: \")\n", + " ),\n", + "\n", + " },\n", + " panels=[\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda num_rows, num_cols, row_names, col_names: weave.legacy.weave.panels.Facet(\n", + " weave.legacy.weave.ops.range(0, num_rows * num_cols, 1),\n", + " cell_size=(192, 192),\n", + " x=lambda i: col_names[i % num_cols],\n", + " y=lambda i: row_names[(i / num_cols).floor()],\n", + " select=lambda cell_values: (\n", + " weave_internal.const(\"cute hd cartoon of \")\n", + " + row_names[(cell_values[0] / num_cols).floor()]\n", + " + \" \"\n", + " + col_names[(cell_values[0] % num_cols)]).stable_diffusion()\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=24, h=12)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda col_names: weave.legacy.weave.panels.Table(col_names, columns=[lambda col: col]),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=12, w=12, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda row_names: weave.legacy.weave.panels.Table(row_names, columns=[lambda row: row]),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=12, y=12, w=12, h=6)\n", + " ),\n", + " ]\n", + ")\n", + "\"\"\", 'stable_diffusion_board_str')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "00411857", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "from weave.legacy import weave_internal\n", - "from weave.legacy.ecosystem.all import langchain" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "30c46465", - "metadata": {}, - "outputs": [], - "source": [ - "weave.legacy.panels.Board(\n", - " vars={\n", - " \"chat_model\": langchain.chat_openai(\"gpt-3.5-turbo\", 0.7),\n", - " \"topic\": \"animals\",\n", - " \"num_cols\": 2,\n", - " \"col_names\": lambda chat_model, num_cols: weave.legacy.ops.range(0, num_cols, 1).map(\n", - " lambda i: chat_model.predict(weave_internal.const(\"You are a creative writer. You've come up with \")\n", - " + i.toString()\n", - " + \" ordered descriptive phrases (3 words or fewer) that represent how magical something is, from least magical to most. Phrase \"\n", - " + i.toString()\n", - " + \" is:\")\n", - " ),\n", - " \"num_rows\": 2,\n", - " \"row_names\": lambda chat_model, topic, num_rows: weave.legacy.ops.range(0, num_rows, 1).map(\n", - " lambda i: chat_model.predict(weave_internal.const(\"You are a creative writer. You've come up with \")\n", - " + i.toString()\n", - " + \" \" + topic\n", - " + \" that are unlikely to be seen together. Number \"\n", - " + i.toString()\n", - " + \" is: \")\n", - " ),\n", - "\n", - " },\n", - " panels=[\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda num_rows, num_cols, row_names, col_names: weave.legacy.panels.Facet(\n", - " weave.legacy.ops.range(0, num_rows * num_cols, 1),\n", - " cell_size=(192, 192),\n", - " x=lambda i: col_names[i % num_cols],\n", - " y=lambda i: row_names[(i / num_cols).floor()],\n", - " select=lambda cell_values: (\n", - " weave_internal.const(\"cute hd cartoon of \")\n", - " + row_names[(cell_values[0] / num_cols).floor()]\n", - " + \" \"\n", - " + col_names[(cell_values[0] % num_cols)]).stable_diffusion()\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=24, h=12)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda col_names: weave.legacy.panels.Table(col_names, columns=[lambda col: col]),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=12, w=12, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda row_names: weave.legacy.panels.Table(row_names, columns=[lambda row: row]),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=12, y=12, w=12, h=6)\n", - " ),\n", - " ]\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c0f6057c", - "metadata": {}, - "outputs": [], - "source": [ - "weave.save(\n", - "\"\"\"\n", - "weave.legacy.panels.Board(\n", - " vars={\n", - " \"chat_model\": langchain.chat_openai(\"gpt-3.5-turbo\", 0.7),\n", - " \"num_cols\": 2,\n", - " \"col_names\": lambda chat_model, num_cols: weave.legacy.ops.range(0, num_cols, 1).map(\n", - " lambda i: chat_model.predict(weave_internal.const(\"You are a creative writer. You've come up with \")\n", - " + i.toString()\n", - " + \" ordered descriptive phrases (3 words or fewer) that represent how magical something is, from least magical to most. Phrase \"\n", - " + i.toString()\n", - " + \" is:\")\n", - " ),\n", - " \"num_rows\": 2,\n", - " \"row_names\": lambda chat_model, num_rows: weave.legacy.ops.range(0, num_rows, 1).map(\n", - " lambda i: chat_model.predict(weave_internal.const(\"You are a creative writer. You've come up with \")\n", - " + i.toString()\n", - " + \" animals that are unlikely to be seen together. Animal \"\n", - " + i.toString()\n", - " + \" is: \")\n", - " ),\n", - "\n", - " },\n", - " panels=[\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda num_rows, num_cols, row_names, col_names: weave.legacy.panels.Facet(\n", - " weave.legacy.ops.range(0, num_rows * num_cols, 1),\n", - " cell_size=(192, 192),\n", - " x=lambda i: col_names[i % num_cols],\n", - " y=lambda i: row_names[(i / num_cols).floor()],\n", - " select=lambda cell_values: (\n", - " weave_internal.const(\"cute hd cartoon of \")\n", - " + row_names[(cell_values[0] / num_cols).floor()]\n", - " + \" \"\n", - " + col_names[(cell_values[0] % num_cols)]).stable_diffusion()\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=24, h=12)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda col_names: weave.legacy.panels.Table(col_names, columns=[lambda col: col]),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=12, w=12, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda row_names: weave.legacy.panels.Table(row_names, columns=[lambda row: row]),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=12, y=12, w=12, h=6)\n", - " ),\n", - " ]\n", - ")\n", - "\"\"\", 'stable_diffusion_board_str')" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/Diffusion story.ipynb b/weave/legacy/examples/experimental/skip_test/Diffusion story.ipynb index 93844909d88..4a9a040968d 100644 --- a/weave/legacy/examples/experimental/skip_test/Diffusion story.ipynb +++ b/weave/legacy/examples/experimental/skip_test/Diffusion story.ipynb @@ -1,122 +1,122 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "00411857", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "from weave.legacy import weave_internal\n", - "from weave.legacy.ecosystem.all import langchain\n", - "weave.use_frontend_devmode()" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "00411857", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "from weave.legacy.weave import weave_internal\n", + "from weave.legacy.weave.ecosystem.all import langchain\n", + "weave.use_frontend_devmode()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "30c46465", + "metadata": {}, + "outputs": [], + "source": [ + "weave.legacy.weave.panels.Board(\n", + " vars={\n", + " 'gpt35': langchain.chat_openai(\"gpt-3.5-turbo\", 0.7),\n", + " 'gpt4': langchain.chat_openai(\"gpt-4\", 0.7),\n", + " 'chat_model': lambda gpt4, gpt35: gpt4,\n", + " 'director': 'Wes Anderson',\n", + " 'director_emotion': 'worldy',\n", + " 'film_style': 'rollerblading documentary',\n", + " 'number_of_panes': 4,\n", + " 'story_gen_prompt': \"\"\"\n", + " You are {director} creating the next {film_style} film. Today you're feeling {director_emotion}.\n", + " In initial sketches, you write a {number_of_panes} step sketch of the plot of your film.\n", + " You include specific details about how the plot proceeds.\n", + " What do you write? Since you are so creative, you can overcome any limitations you might\n", + " think you have when it comes to writing style. In this case, you write your outline as a json list\n", + " with one item for each step.\n", + " \"\"\",\n", + " 'prompt': lambda director, director_emotion, film_style, number_of_panes, story_gen_prompt: story_gen_prompt.format(weave.legacy.weave.ops.dict_(\n", + " director= director,\n", + " director_emotion=director_emotion,\n", + " film_style=film_style,\n", + " number_of_panes=number_of_panes)),\n", + " 'storyline': lambda prompt, chat_model: chat_model.predict(prompt),\n", + " 'storyline_parsed': lambda storyline: storyline.json_parse_list(),\n", + " 'panel_prompt': 'A storyboard pane for a movie by {director} for their next {film_style} film, The scene description is: {panel}',\n", + " 'storyboard_panes': lambda storyline_parsed, panel_prompt, director, film_style:\n", + " storyline_parsed.map(lambda row:\n", + " panel_prompt.format(weave.legacy.weave.ops.dict_(\n", + " panel=row.json_dumps(),\n", + " director=director,\n", + " film_style=film_style,\n", + " ))).stable_diffusion()\n", + " },\n", + " panels=[ \n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda storyline_parsed: storyline_parsed,\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=24, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda storyboard_panes: weave.legacy.weave.panels.Each(storyboard_panes),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=24, h=12)\n", + " )\n", + " ]\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c8d3d23b", + "metadata": {}, + "outputs": [], + "source": [ + "# imperative version\n", + "\n", + "gpt35 = langchain.chat_openai(\"gpt-3.5-turbo\", 0.7)\n", + "gpt4 = langchain.chat_openai(\"gpt-4\", 0.7)\n", + "chat_model = gpt4\n", + "\n", + "director = 'Wes Anderson'\n", + "film_style = 'great american'\n", + "number_of_panes = 4\n", + "story_gen_prompt = weave.save(\"\"\"\n", + "You are {director} creating the next {film_style} film.\n", + "In initial sketches, you write a {number_of_panes} step sketch of the plot of your film.\n", + "You include specific details about how the plot proceeds.\n", + "What do you write? Since you are so creative, you can overcome any limitations you might\n", + "think you have when it comes to writing style. In this case, you write your outline as a json list\n", + "with one item for each step.\n", + "\"\"\",\n", + " name='story_gen_prompt')\n", + "storyline = gpt35.predict(story_gen_prompt.format({\n", + " 'director': director,\n", + " 'film_style': film_style,\n", + " 'number_of_panes': number_of_panes}))\n", + "storyline_parsed = storyline.json_parse()\n", + "#storyline_parsed" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6fddc9a8", + "metadata": {}, + "outputs": [], + "source": [ + "#weave.legacy.weave.panels.Each(storyline_parsed.map(lambda row: row.json_dumps()).stable_diffusion())" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "30c46465", - "metadata": {}, - "outputs": [], - "source": [ - "weave.legacy.panels.Board(\n", - " vars={\n", - " 'gpt35': langchain.chat_openai(\"gpt-3.5-turbo\", 0.7),\n", - " 'gpt4': langchain.chat_openai(\"gpt-4\", 0.7),\n", - " 'chat_model': lambda gpt4, gpt35: gpt4,\n", - " 'director': 'Wes Anderson',\n", - " 'director_emotion': 'worldy',\n", - " 'film_style': 'rollerblading documentary',\n", - " 'number_of_panes': 4,\n", - " 'story_gen_prompt': \"\"\"\n", - " You are {director} creating the next {film_style} film. Today you're feeling {director_emotion}.\n", - " In initial sketches, you write a {number_of_panes} step sketch of the plot of your film.\n", - " You include specific details about how the plot proceeds.\n", - " What do you write? Since you are so creative, you can overcome any limitations you might\n", - " think you have when it comes to writing style. In this case, you write your outline as a json list\n", - " with one item for each step.\n", - " \"\"\",\n", - " 'prompt': lambda director, director_emotion, film_style, number_of_panes, story_gen_prompt: story_gen_prompt.format(weave.legacy.ops.dict_(\n", - " director= director,\n", - " director_emotion=director_emotion,\n", - " film_style=film_style,\n", - " number_of_panes=number_of_panes)),\n", - " 'storyline': lambda prompt, chat_model: chat_model.predict(prompt),\n", - " 'storyline_parsed': lambda storyline: storyline.json_parse_list(),\n", - " 'panel_prompt': 'A storyboard pane for a movie by {director} for their next {film_style} film, The scene description is: {panel}',\n", - " 'storyboard_panes': lambda storyline_parsed, panel_prompt, director, film_style:\n", - " storyline_parsed.map(lambda row:\n", - " panel_prompt.format(weave.legacy.ops.dict_(\n", - " panel=row.json_dumps(),\n", - " director=director,\n", - " film_style=film_style,\n", - " ))).stable_diffusion()\n", - " },\n", - " panels=[ \n", - " weave.legacy.panels.BoardPanel(\n", - " lambda storyline_parsed: storyline_parsed,\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=24, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda storyboard_panes: weave.legacy.panels.Each(storyboard_panes),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=24, h=12)\n", - " )\n", - " ]\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c8d3d23b", - "metadata": {}, - "outputs": [], - "source": [ - "# imperative version\n", - "\n", - "gpt35 = langchain.chat_openai(\"gpt-3.5-turbo\", 0.7)\n", - "gpt4 = langchain.chat_openai(\"gpt-4\", 0.7)\n", - "chat_model = gpt4\n", - "\n", - "director = 'Wes Anderson'\n", - "film_style = 'great american'\n", - "number_of_panes = 4\n", - "story_gen_prompt = weave.save(\"\"\"\n", - "You are {director} creating the next {film_style} film.\n", - "In initial sketches, you write a {number_of_panes} step sketch of the plot of your film.\n", - "You include specific details about how the plot proceeds.\n", - "What do you write? Since you are so creative, you can overcome any limitations you might\n", - "think you have when it comes to writing style. In this case, you write your outline as a json list\n", - "with one item for each step.\n", - "\"\"\",\n", - " name='story_gen_prompt')\n", - "storyline = gpt35.predict(story_gen_prompt.format({\n", - " 'director': director,\n", - " 'film_style': film_style,\n", - " 'number_of_panes': number_of_panes}))\n", - "storyline_parsed = storyline.json_parse()\n", - "#storyline_parsed" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6fddc9a8", - "metadata": {}, - "outputs": [], - "source": [ - "#weave.legacy.panels.Each(storyline_parsed.map(lambda row: row.json_dumps()).stable_diffusion())" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/Docbot.ipynb b/weave/legacy/examples/experimental/skip_test/Docbot.ipynb index 328117dfa9a..c754aef88f5 100644 --- a/weave/legacy/examples/experimental/skip_test/Docbot.ipynb +++ b/weave/legacy/examples/experimental/skip_test/Docbot.ipynb @@ -1,329 +1,329 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "ef0c98ad", - "metadata": {}, - "outputs": [], - "source": [ - "import pathlib\n", - "import weave\n", - "weave.use_frontend_devmode()\n", - "from weave.legacy.ecosystem import langchain" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "ef0c98ad", + "metadata": {}, + "outputs": [], + "source": [ + "import pathlib\n", + "import weave\n", + "weave.use_frontend_devmode()\n", + "from weave.legacy.weave.ecosystem import langchain" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8f7192c3", + "metadata": {}, + "outputs": [], + "source": [ + "neg_feedback = [\"Is there a way that I can embed an iframe component in Weights and Biases report?\",\n", + " \"how do i create the pretty sweeps plot?\",\n", + " \"I'm getting error 400. What can I do?\",\n", + " \"How can I move a column in a table to the right?\",\n", + " \"In Prompts, how can I resize the Trace Timeline to make it bigger or full screen?\",\n", + " \"I have a question about exporting CSV files from a web panel. Whenever I do this, I always get two extra columns for MAX and MIN values, even if I only have one data curve. Does anyone know how to solve this issue?\",\n", + " \"artifacts cli command to upload a folder of images\",\n", + " \"Is there a recommended way to use Launch in an SLURM environment?\",\n", + " \"How to export a single chart's data using the API?\",\n", + " \"how can i login with a different wandb user?\"\n", + "]\n", + "\n", + "pos_feedback = [\"my logging doesn't seem to include errors when the training crashes, how do I change the logging level for wandb logging?\",\n", + " \"how can i get the data from my wandb run by querying my logs using python?\",\n", + " \"how do I fix an error with wandb Table construction from pandas dataframe: TypeError: Data row contained incompatible types\",\n", + " \"how can i make a heatmap using vega and plot it to wandb? what is the vegaspec?\",\n", + " \"is there a good way to join 2 tables together programmatically?\",\n", + " \"I have a question about sweeps. How can you constrain relationship between parameters. For example, I now that if num_layers * hidden_dim is large, I'll run out of GPU memory. So, also I would like to explore some hyperparameter space, there are some combination I know will fail. optuna as a way to do that: you can throw an special exception to cancel a run during a sweep, so that it is not recorded. Is there something similar in W&B, or another way of pruning unwanted combination of hyperparameters?\",\n", + " \"where can I find my run_id\",\n", + " \"How do I group runs?\",\n", + " \"I am using the Hugging Face trainer to train a GPT-2 model. How can I log in wandb the results of the model in each evaluation?\",\n", + " \"I am looking to finetune LLAMA on my own dataset using OpenAI, can you give me examples on how to do this?\"\n", + " ]\n", + "\n", + "all_qs = [\n", + " {'question': q, 'feedback': 'positive'} for q in pos_feedback] + [\n", + " {'question': q, 'feedback': 'negative'} for q in neg_feedback]\n", + "\n", + "questions = weave.save(all_qs, 'eval_questions')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "03a68bf9", + "metadata": {}, + "outputs": [], + "source": [ + "questions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f6e1c366", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.docstore.document import Document\n", + "from langchain.text_splitter import (\n", + " MarkdownTextSplitter,\n", + " PythonCodeTextSplitter,\n", + " TokenTextSplitter,\n", + ")\n", + "# Get markdown files from our docs repo\n", + "\n", + "# Checkout of our docs repo: https://github.com/wandb/docodile/\n", + "DOC_DIR = '/Users/shawn/code2/docodile'\n", + "DOC_SUFFIX = '.md'\n", + "\n", + "docs = []\n", + "for file in pathlib.Path(DOC_DIR).glob('**/*' + DOC_SUFFIX):\n", + " with file.open('r') as f:\n", + " # store them as langchain Document objects\n", + " docs.append(Document(page_content=f.read(), metadata={'path': file.name}))\n", + "docs = MarkdownTextSplitter().split_documents(docs)\n", + "docs = TokenTextSplitter().split_documents(docs)\n", + "\n", + "docs = weave.save(docs, 'wandb-docs')\n", + "docs" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "624e0b9e", + "metadata": {}, + "outputs": [], + "source": [ + "# Vector store with langchain\n", + "from langchain.vectorstores import VectorStore, FAISS\n", + "from langchain.embeddings.openai import OpenAIEmbeddings\n", + "embeddings = OpenAIEmbeddings()\n", + "vector_store = FAISS.from_documents(weave.use(docs), embeddings)\n", + "\n", + "weave.save(vector_store)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a97a3a9c", + "metadata": {}, + "outputs": [], + "source": [ + "# Vector store with Weave\n", + "\n", + "# Stuff you can do:\n", + "# - .similarity_search()\n", + "# - but currently there is a crash because Row.Group tries to render and fails. Need to switch the\n", + "# panel to Table and then change column to row.__getattr__('page_content')\n", + "# - .document_embeddings\n", + "# - this gets the embeddings out of FAISS, and also performs FAISS' k-means with 20 clusters\n", + "# - switch to projection.plot\n", + "# TODO:\n", + "# - give control over k for k-means\n", + "\n", + "from weave.legacy.weave.ecosystem import langchain\n", + "\n", + "vector_store_node = langchain.faiss_from_documents(docs, langchain.openai_embeddings())\n", + "vector_store_node" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bd31e988", + "metadata": {}, + "outputs": [], + "source": [ + "# With langchain\n", + "from langchain.chat_models import ChatOpenAI\n", + "from langchain.chains import RetrievalQA\n", + "model_gpt_35_temp07 = RetrievalQA.from_chain_type(\n", + " llm=ChatOpenAI(model_name='gpt-3.5-turbo', temperature=0.7),\n", + " chain_type='stuff',\n", + " retriever=vector_store.as_retriever()\n", + " )\n", + "model = model_gpt_35_temp07\n", + "model = weave.save(model_gpt_35_temp07, 'mymodel')\n", + "\n", + "#model.run('hello')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "694ce5d6", + "metadata": {}, + "outputs": [], + "source": [ + "# With weave\n", + "from weave.legacy.weave.ecosystem import langchain\n", + "qa = langchain.retrieval_qa_from_chain_type(\n", + " langchain.chat_openai('gpt-3.5-turbo', 0.7),\n", + " 'stuff',\n", + " vector_store_node)\n", + "qa.run('hello')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "27fc1618", + "metadata": {}, + "outputs": [], + "source": [ + "# from langchain.chat_models import ChatOpenAI\n", + "# from langchain.chains import RetrievalQA\n", + "model_02 = RetrievalQA.from_chain_type(\n", + " llm=ChatOpenAI(model_name='gpt-3.5-turbo', temperature=0.2),\n", + " chain_type='stuff',\n", + " retriever=vector_store.as_retriever()\n", + " )\n", + "model_07 = RetrievalQA.from_chain_type(\n", + " llm=ChatOpenAI(model_name='gpt-3.5-turbo', temperature=0.7),\n", + " chain_type='stuff',\n", + " retriever=vector_store.as_retriever()\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f18ae43f", + "metadata": {}, + "outputs": [], + "source": [ + "# Two with LC and weave.save\n", + "\n", + "models = [model_02, model_07]\n", + "models = weave.save(models, 'docbot-models')\n", + "models.run('hello')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "34c3e345", + "metadata": {}, + "outputs": [], + "source": [ + "# You can map over questions\n", + "weave.legacy.weave.panels.Table(questions.limit(3), columns=[\n", + " lambda q: q['question'],\n", + " lambda q: models.run(q['question'])])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "876bc738", + "metadata": {}, + "outputs": [], + "source": [ + "# Interactive evaluation and exploration dashboard\n", + "\n", + "weave.legacy.weave.panels.Board(\n", + " vars={\n", + " 'documents': docs,\n", + " 'questions': questions.limit(2),\n", + " 'embeddings': langchain.openai_embeddings(),\n", + " 'vector_store': lambda embeddings, documents: langchain.faiss_from_documents(documents, embeddings),\n", + " 'doc_embeddings': lambda vector_store: vector_store.document_embeddings(),\n", + " #'models': models,\n", + " 'model_a': lambda vector_store: langchain.retrieval_qa_from_chain_type(\n", + " langchain.chat_openai('gpt-3.5-turbo', 0.2),\n", + " 'stuff',\n", + " vector_store),\n", + " 'model_b': lambda vector_store: langchain.retrieval_qa_from_chain_type(\n", + " langchain.chat_openai('gpt-3.5-turbo', 0.7),\n", + " 'stuff',\n", + " vector_store),\n", + " 'models': lambda model_a, model_b: weave.legacy.weave.ops.make_list(a=model_a, b=model_b),\n", + " 'projection': lambda doc_embeddings: doc_embeddings.projection2D(\n", + " 'pca',\n", + " 'single',\n", + " ['embedding'],\n", + " {'pca': {},\n", + " 'tsne': {\n", + " 'perplexity': 30,\n", + " 'learningRate': 10,\n", + " 'iterations': 25\n", + " },\n", + " 'umap': {\n", + " 'neighbors': 15,\n", + " 'minDist': 0.1,\n", + " 'spread': 1.0\n", + " }\n", + " }),\n", + " },\n", + " panels=[ \n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda models: weave.legacy.weave.panels.Each(models.run(\"What is Weave?\")),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=24, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda model_a, model_b: weave.legacy.weave.panels.Table(questions,\n", + " columns=[\n", + " lambda question: question['question'],\n", + " lambda question: question['feedback'],\n", + " weave.legacy.weave.panels.TableColumn(\n", + " lambda question: model_a.run(question['question']).result,\n", + " name='model_a'\n", + " ),\n", + " weave.legacy.weave.panels.TableColumn(\n", + " lambda question: model_b.run(question['question']).result,\n", + " name='model_b'\n", + " ),\n", + " ]),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=6, w=24, h=6)\n", + " ), \n", + " weave.legacy.weave.panels.BoardPanel(\n", + " id='docs_projection',\n", + " panel=lambda projection: weave.legacy.weave.panels.Plot(\n", + " projection,\n", + " x=lambda row: row['projection.x'],\n", + " y=lambda row: row['projection.y'],\n", + " color=lambda row: row['source.cluster']\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=12, w=12, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda docs_projection: docs_projection.selected_data(),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=12, y=12, w=12, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda documents: weave.legacy.weave.panels.Table(documents,\n", + " columns=[\n", + " lambda doc: doc.page_content,\n", + " lambda doc: doc.metadata['path']\n", + " ]),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=18, w=12, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda vector_store: weave.legacy.weave.panels.Table(vector_store.similarity_search('weave'),\n", + " columns=[\n", + " lambda doc: doc.page_content,\n", + " lambda doc: doc.metadata['path'] \n", + " ]),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=12, y=18, w=12, h=6)\n", + " ),\n", + " ]\n", + ")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "8f7192c3", - "metadata": {}, - "outputs": [], - "source": [ - "neg_feedback = [\"Is there a way that I can embed an iframe component in Weights and Biases report?\",\n", - " \"how do i create the pretty sweeps plot?\",\n", - " \"I'm getting error 400. What can I do?\",\n", - " \"How can I move a column in a table to the right?\",\n", - " \"In Prompts, how can I resize the Trace Timeline to make it bigger or full screen?\",\n", - " \"I have a question about exporting CSV files from a web panel. Whenever I do this, I always get two extra columns for MAX and MIN values, even if I only have one data curve. Does anyone know how to solve this issue?\",\n", - " \"artifacts cli command to upload a folder of images\",\n", - " \"Is there a recommended way to use Launch in an SLURM environment?\",\n", - " \"How to export a single chart's data using the API?\",\n", - " \"how can i login with a different wandb user?\"\n", - "]\n", - "\n", - "pos_feedback = [\"my logging doesn't seem to include errors when the training crashes, how do I change the logging level for wandb logging?\",\n", - " \"how can i get the data from my wandb run by querying my logs using python?\",\n", - " \"how do I fix an error with wandb Table construction from pandas dataframe: TypeError: Data row contained incompatible types\",\n", - " \"how can i make a heatmap using vega and plot it to wandb? what is the vegaspec?\",\n", - " \"is there a good way to join 2 tables together programmatically?\",\n", - " \"I have a question about sweeps. How can you constrain relationship between parameters. For example, I now that if num_layers * hidden_dim is large, I'll run out of GPU memory. So, also I would like to explore some hyperparameter space, there are some combination I know will fail. optuna as a way to do that: you can throw an special exception to cancel a run during a sweep, so that it is not recorded. Is there something similar in W&B, or another way of pruning unwanted combination of hyperparameters?\",\n", - " \"where can I find my run_id\",\n", - " \"How do I group runs?\",\n", - " \"I am using the Hugging Face trainer to train a GPT-2 model. How can I log in wandb the results of the model in each evaluation?\",\n", - " \"I am looking to finetune LLAMA on my own dataset using OpenAI, can you give me examples on how to do this?\"\n", - " ]\n", - "\n", - "all_qs = [\n", - " {'question': q, 'feedback': 'positive'} for q in pos_feedback] + [\n", - " {'question': q, 'feedback': 'negative'} for q in neg_feedback]\n", - "\n", - "questions = weave.save(all_qs, 'eval_questions')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "03a68bf9", - "metadata": {}, - "outputs": [], - "source": [ - "questions" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f6e1c366", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.docstore.document import Document\n", - "from langchain.text_splitter import (\n", - " MarkdownTextSplitter,\n", - " PythonCodeTextSplitter,\n", - " TokenTextSplitter,\n", - ")\n", - "# Get markdown files from our docs repo\n", - "\n", - "# Checkout of our docs repo: https://github.com/wandb/docodile/\n", - "DOC_DIR = '/Users/shawn/code2/docodile'\n", - "DOC_SUFFIX = '.md'\n", - "\n", - "docs = []\n", - "for file in pathlib.Path(DOC_DIR).glob('**/*' + DOC_SUFFIX):\n", - " with file.open('r') as f:\n", - " # store them as langchain Document objects\n", - " docs.append(Document(page_content=f.read(), metadata={'path': file.name}))\n", - "docs = MarkdownTextSplitter().split_documents(docs)\n", - "docs = TokenTextSplitter().split_documents(docs)\n", - "\n", - "docs = weave.save(docs, 'wandb-docs')\n", - "docs" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "624e0b9e", - "metadata": {}, - "outputs": [], - "source": [ - "# Vector store with langchain\n", - "from langchain.vectorstores import VectorStore, FAISS\n", - "from langchain.embeddings.openai import OpenAIEmbeddings\n", - "embeddings = OpenAIEmbeddings()\n", - "vector_store = FAISS.from_documents(weave.use(docs), embeddings)\n", - "\n", - "weave.save(vector_store)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a97a3a9c", - "metadata": {}, - "outputs": [], - "source": [ - "# Vector store with Weave\n", - "\n", - "# Stuff you can do:\n", - "# - .similarity_search()\n", - "# - but currently there is a crash because Row.Group tries to render and fails. Need to switch the\n", - "# panel to Table and then change column to row.__getattr__('page_content')\n", - "# - .document_embeddings\n", - "# - this gets the embeddings out of FAISS, and also performs FAISS' k-means with 20 clusters\n", - "# - switch to projection.plot\n", - "# TODO:\n", - "# - give control over k for k-means\n", - "\n", - "from weave.legacy.ecosystem import langchain\n", - "\n", - "vector_store_node = langchain.faiss_from_documents(docs, langchain.openai_embeddings())\n", - "vector_store_node" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "bd31e988", - "metadata": {}, - "outputs": [], - "source": [ - "# With langchain\n", - "from langchain.chat_models import ChatOpenAI\n", - "from langchain.chains import RetrievalQA\n", - "model_gpt_35_temp07 = RetrievalQA.from_chain_type(\n", - " llm=ChatOpenAI(model_name='gpt-3.5-turbo', temperature=0.7),\n", - " chain_type='stuff',\n", - " retriever=vector_store.as_retriever()\n", - " )\n", - "model = model_gpt_35_temp07\n", - "model = weave.save(model_gpt_35_temp07, 'mymodel')\n", - "\n", - "#model.run('hello')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "694ce5d6", - "metadata": {}, - "outputs": [], - "source": [ - "# With weave\n", - "from weave.legacy.ecosystem import langchain\n", - "qa = langchain.retrieval_qa_from_chain_type(\n", - " langchain.chat_openai('gpt-3.5-turbo', 0.7),\n", - " 'stuff',\n", - " vector_store_node)\n", - "qa.run('hello')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "27fc1618", - "metadata": {}, - "outputs": [], - "source": [ - "# from langchain.chat_models import ChatOpenAI\n", - "# from langchain.chains import RetrievalQA\n", - "model_02 = RetrievalQA.from_chain_type(\n", - " llm=ChatOpenAI(model_name='gpt-3.5-turbo', temperature=0.2),\n", - " chain_type='stuff',\n", - " retriever=vector_store.as_retriever()\n", - " )\n", - "model_07 = RetrievalQA.from_chain_type(\n", - " llm=ChatOpenAI(model_name='gpt-3.5-turbo', temperature=0.7),\n", - " chain_type='stuff',\n", - " retriever=vector_store.as_retriever()\n", - " )" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f18ae43f", - "metadata": {}, - "outputs": [], - "source": [ - "# Two with LC and weave.save\n", - "\n", - "models = [model_02, model_07]\n", - "models = weave.save(models, 'docbot-models')\n", - "models.run('hello')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "34c3e345", - "metadata": {}, - "outputs": [], - "source": [ - "# You can map over questions\n", - "weave.legacy.panels.Table(questions.limit(3), columns=[\n", - " lambda q: q['question'],\n", - " lambda q: models.run(q['question'])])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "876bc738", - "metadata": {}, - "outputs": [], - "source": [ - "# Interactive evaluation and exploration dashboard\n", - "\n", - "weave.legacy.panels.Board(\n", - " vars={\n", - " 'documents': docs,\n", - " 'questions': questions.limit(2),\n", - " 'embeddings': langchain.openai_embeddings(),\n", - " 'vector_store': lambda embeddings, documents: langchain.faiss_from_documents(documents, embeddings),\n", - " 'doc_embeddings': lambda vector_store: vector_store.document_embeddings(),\n", - " #'models': models,\n", - " 'model_a': lambda vector_store: langchain.retrieval_qa_from_chain_type(\n", - " langchain.chat_openai('gpt-3.5-turbo', 0.2),\n", - " 'stuff',\n", - " vector_store),\n", - " 'model_b': lambda vector_store: langchain.retrieval_qa_from_chain_type(\n", - " langchain.chat_openai('gpt-3.5-turbo', 0.7),\n", - " 'stuff',\n", - " vector_store),\n", - " 'models': lambda model_a, model_b: weave.legacy.ops.make_list(a=model_a, b=model_b),\n", - " 'projection': lambda doc_embeddings: doc_embeddings.projection2D(\n", - " 'pca',\n", - " 'single',\n", - " ['embedding'],\n", - " {'pca': {},\n", - " 'tsne': {\n", - " 'perplexity': 30,\n", - " 'learningRate': 10,\n", - " 'iterations': 25\n", - " },\n", - " 'umap': {\n", - " 'neighbors': 15,\n", - " 'minDist': 0.1,\n", - " 'spread': 1.0\n", - " }\n", - " }),\n", - " },\n", - " panels=[ \n", - " weave.legacy.panels.BoardPanel(\n", - " lambda models: weave.legacy.panels.Each(models.run(\"What is Weave?\")),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=24, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda model_a, model_b: weave.legacy.panels.Table(questions,\n", - " columns=[\n", - " lambda question: question['question'],\n", - " lambda question: question['feedback'],\n", - " weave.legacy.panels.TableColumn(\n", - " lambda question: model_a.run(question['question']).result,\n", - " name='model_a'\n", - " ),\n", - " weave.legacy.panels.TableColumn(\n", - " lambda question: model_b.run(question['question']).result,\n", - " name='model_b'\n", - " ),\n", - " ]),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=6, w=24, h=6)\n", - " ), \n", - " weave.legacy.panels.BoardPanel(\n", - " id='docs_projection',\n", - " panel=lambda projection: weave.legacy.panels.Plot(\n", - " projection,\n", - " x=lambda row: row['projection.x'],\n", - " y=lambda row: row['projection.y'],\n", - " color=lambda row: row['source.cluster']\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=12, w=12, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda docs_projection: docs_projection.selected_data(),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=12, y=12, w=12, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda documents: weave.legacy.panels.Table(documents,\n", - " columns=[\n", - " lambda doc: doc.page_content,\n", - " lambda doc: doc.metadata['path']\n", - " ]),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=18, w=12, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda vector_store: weave.legacy.panels.Table(vector_store.similarity_search('weave'),\n", - " columns=[\n", - " lambda doc: doc.page_content,\n", - " lambda doc: doc.metadata['path'] \n", - " ]),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=12, y=18, w=12, h=6)\n", - " ),\n", - " ]\n", - ")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/Hack demo.ipynb b/weave/legacy/examples/experimental/skip_test/Hack demo.ipynb index 8df75d8efcc..9d4eea67e0a 100644 --- a/weave/legacy/examples/experimental/skip_test/Hack demo.ipynb +++ b/weave/legacy/examples/experimental/skip_test/Hack demo.ipynb @@ -1,117 +1,117 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "6e89befe", - "metadata": {}, - "outputs": [], - "source": [ - "import typing\n", - "import weave\n", - "from weave.legacy.ecosystem import hackdemo\n", - "\n", - "PROJECT = 'hackdemo'" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "6e89befe", + "metadata": {}, + "outputs": [], + "source": [ + "import typing\n", + "import weave\n", + "from weave.legacy.weave.ecosystem import hackdemo\n", + "\n", + "PROJECT = 'hackdemo'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e0209514", + "metadata": {}, + "outputs": [], + "source": [ + "dataset = hackdemo.ca_housing_dataset(25000)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4893a4a8", + "metadata": {}, + "outputs": [], + "source": [ + "weave.show(dataset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "35d52005", + "metadata": {}, + "outputs": [], + "source": [ + "@weave.op()\n", + "def table_summary(table: typing.Any) -> list[weave.legacy.weave.panels.Panel]:\n", + " if not table:\n", + " return\n", + " col_names = list(table[0].keys())\n", + " with weave.lazy_execution():\n", + " cols = {col_name: table.pick(col_name) for col_name in col_names}\n", + " panels = []\n", + " for col_name, col_values in cols.items():\n", + " panels.append(weave.legacy.weave.panels.LabeledItem(item=col_values, label=col_name))\n", + " return panels" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "42638af4", + "metadata": {}, + "outputs": [], + "source": [ + "data_card = hackdemo.Dataset(\n", + " name='California Housing',\n", + " created_by=hackdemo.User(name='Pace, R. Kelley'),\n", + " description='S&P Letters Data\\n\\nWe collected information on the variables using all the block groups in California from the 1990 Cens us. In this sample a block group on average includes 1425.5 individuals living in a geographically co mpact area. Naturally, the geographical area included varies inversely with the population density. W e computed distances among the centroids of each block group as measured in latitude and longitude. W e excluded all the block groups reporting zero entries for the independent and dependent variables. T he final data contained 20,640 observations on 9 variables. The dependent variable is ln(median house value).',\n", + " updated_at='August 25th 2021, at 3:36:29pm',\n", + " table=weave.use(dataset) \n", + ")\n", + "\n", + "saved_data_card = weave.save(data_card)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "578adec4", + "metadata": {}, + "outputs": [], + "source": [ + "#weave.publish(data_card, '%s/ca-housing-cadr' % PROJECT)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c35a4702", + "metadata": {}, + "outputs": [], + "source": [ + "hackdemo.ca_housing_dataset_card(saved_data_card)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "e0209514", - "metadata": {}, - "outputs": [], - "source": [ - "dataset = hackdemo.ca_housing_dataset(25000)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4893a4a8", - "metadata": {}, - "outputs": [], - "source": [ - "weave.show(dataset)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "35d52005", - "metadata": {}, - "outputs": [], - "source": [ - "@weave.op()\n", - "def table_summary(table: typing.Any) -> list[weave.legacy.panels.Panel]:\n", - " if not table:\n", - " return\n", - " col_names = list(table[0].keys())\n", - " with weave.lazy_execution():\n", - " cols = {col_name: table.pick(col_name) for col_name in col_names}\n", - " panels = []\n", - " for col_name, col_values in cols.items():\n", - " panels.append(weave.legacy.panels.LabeledItem(item=col_values, label=col_name))\n", - " return panels" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "42638af4", - "metadata": {}, - "outputs": [], - "source": [ - "data_card = hackdemo.Dataset(\n", - " name='California Housing',\n", - " created_by=hackdemo.User(name='Pace, R. Kelley'),\n", - " description='S&P Letters Data\\n\\nWe collected information on the variables using all the block groups in California from the 1990 Cens us. In this sample a block group on average includes 1425.5 individuals living in a geographically co mpact area. Naturally, the geographical area included varies inversely with the population density. W e computed distances among the centroids of each block group as measured in latitude and longitude. W e excluded all the block groups reporting zero entries for the independent and dependent variables. T he final data contained 20,640 observations on 9 variables. The dependent variable is ln(median house value).',\n", - " updated_at='August 25th 2021, at 3:36:29pm',\n", - " table=weave.use(dataset) \n", - ")\n", - "\n", - "saved_data_card = weave.save(data_card)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "578adec4", - "metadata": {}, - "outputs": [], - "source": [ - "#weave.publish(data_card, '%s/ca-housing-cadr' % PROJECT)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c35a4702", - "metadata": {}, - "outputs": [], - "source": [ - "hackdemo.ca_housing_dataset_card(saved_data_card)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/KerasModel.ipynb b/weave/legacy/examples/experimental/skip_test/KerasModel.ipynb index 86de437c093..f03a31c6e65 100644 --- a/weave/legacy/examples/experimental/skip_test/KerasModel.ipynb +++ b/weave/legacy/examples/experimental/skip_test/KerasModel.ipynb @@ -1,305 +1,305 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "ad4e3073", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "weave.use_frontend_devmode()\n", - "from weave.legacy.ecosystem import keras as weave_keras" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "ad4e3073", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "weave.use_frontend_devmode()\n", + "from weave.legacy.weave.ecosystem import keras as weave_keras" + ] + }, + { + "cell_type": "markdown", + "id": "2f3cbb0d", + "metadata": {}, + "source": [ + "# Train Language Model\n", + "\n", + "From: https://keras.io/examples/nlp/text_classification_from_scratch/" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ec47e09b", + "metadata": {}, + "outputs": [], + "source": [ + "import tensorflow as tf\n", + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d288f1b0", + "metadata": {}, + "outputs": [], + "source": [ + "!curl -O https://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz\n", + "!tar -xf aclImdb_v1.tar.gz\n", + "!rm -r aclImdb/train/unsup" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4e74e162", + "metadata": {}, + "outputs": [], + "source": [ + "batch_size = 32\n", + "raw_train_ds = tf.keras.preprocessing.text_dataset_from_directory(\n", + " \"aclImdb/train\",\n", + " batch_size=batch_size,\n", + " validation_split=0.2,\n", + " subset=\"training\",\n", + " seed=1337,\n", + ")\n", + "raw_val_ds = tf.keras.preprocessing.text_dataset_from_directory(\n", + " \"aclImdb/train\",\n", + " batch_size=batch_size,\n", + " validation_split=0.2,\n", + " subset=\"validation\",\n", + " seed=1337,\n", + ")\n", + "raw_test_ds = tf.keras.preprocessing.text_dataset_from_directory(\n", + " \"aclImdb/test\", batch_size=batch_size\n", + ")\n", + "\n", + "print(f\"Number of batches in raw_train_ds: {raw_train_ds.cardinality()}\")\n", + "print(f\"Number of batches in raw_val_ds: {raw_val_ds.cardinality()}\")\n", + "print(f\"Number of batches in raw_test_ds: {raw_test_ds.cardinality()}\")\n", + "\n", + "from tensorflow.keras.layers import TextVectorization\n", + "import string\n", + "import re\n", + "\n", + "# Having looked at our data above, we see that the raw text contains HTML break\n", + "# tags of the form '
'. These tags will not be removed by the default\n", + "# standardizer (which doesn't strip HTML). Because of this, we will need to\n", + "# create a custom standardization function.\n", + "def custom_standardization(input_data):\n", + " lowercase = tf.strings.lower(input_data)\n", + " stripped_html = tf.strings.regex_replace(lowercase, \"
\", \" \")\n", + " return tf.strings.regex_replace(\n", + " stripped_html, f\"[{re.escape(string.punctuation)}]\", \"\"\n", + " )\n", + "\n", + "\n", + "# Model constants.\n", + "max_features = 20000\n", + "embedding_dim = 128\n", + "sequence_length = 500\n", + "\n", + "# Now that we have our custom standardization, we can instantiate our text\n", + "# vectorization layer. We are using this layer to normalize, split, and map\n", + "# strings to integers, so we set our 'output_mode' to 'int'.\n", + "# Note that we're using the default split function,\n", + "# and the custom standardization defined above.\n", + "# We also set an explicit maximum sequence length, since the CNNs later in our\n", + "# model won't support ragged sequences.\n", + "vectorize_layer = TextVectorization(\n", + " standardize=custom_standardization,\n", + " max_tokens=max_features,\n", + " output_mode=\"int\",\n", + " output_sequence_length=sequence_length,\n", + ")\n", + "\n", + "vectorize_layer_non_custom = TextVectorization(\n", + "# standardize=custom_standardization,\n", + " max_tokens=max_features,\n", + " output_mode=\"int\",\n", + " output_sequence_length=sequence_length,\n", + ")\n", + "\n", + "# Now that the vocab layer has been created, call `adapt` on a text-only\n", + "# dataset to create the vocabulary. You don't have to batch, but for very large\n", + "# datasets this means you're not keeping spare copies of the dataset in memory.\n", + "\n", + "# Let's make a text-only dataset (no labels):\n", + "text_ds = raw_train_ds.map(lambda x, y: x)\n", + "# Let's call `adapt`:\n", + "vectorize_layer.adapt(text_ds)\n", + "vectorize_layer_non_custom.adapt(text_ds)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7e48486a", + "metadata": {}, + "outputs": [], + "source": [ + "def vectorize_text(text, label):\n", + " text = tf.expand_dims(text, -1)\n", + " return vectorize_layer(text), label\n", + "\n", + "\n", + "# Vectorize the data.\n", + "train_ds = raw_train_ds.map(vectorize_text)\n", + "val_ds = raw_val_ds.map(vectorize_text)\n", + "test_ds = raw_test_ds.map(vectorize_text)\n", + "\n", + "# Do async prefetching / buffering of the data for best performance on GPU.\n", + "train_ds = train_ds.cache().prefetch(buffer_size=10)\n", + "val_ds = val_ds.cache().prefetch(buffer_size=10)\n", + "test_ds = test_ds.cache().prefetch(buffer_size=10)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7f053ba5", + "metadata": {}, + "outputs": [], + "source": [ + "from tensorflow.keras import layers\n", + "\n", + "# A integer input for vocab indices.\n", + "inputs = tf.keras.Input(shape=(None,), dtype=\"int64\")\n", + "\n", + "# Next, we add a layer to map those vocab indices into a space of dimensionality\n", + "# 'embedding_dim'.\n", + "x = layers.Embedding(max_features, embedding_dim)(inputs)\n", + "x = layers.Dropout(0.5)(x)\n", + "\n", + "# Conv1D + global max pooling\n", + "x = layers.Conv1D(128, 7, padding=\"valid\", activation=\"relu\", strides=3)(x)\n", + "x = layers.Conv1D(128, 7, padding=\"valid\", activation=\"relu\", strides=3)(x)\n", + "x = layers.GlobalMaxPooling1D()(x)\n", + "\n", + "# We add a vanilla hidden layer:\n", + "x = layers.Dense(128, activation=\"relu\")(x)\n", + "x = layers.Dropout(0.5)(x)\n", + "\n", + "# We project onto a single unit output layer, and squash it with a sigmoid:\n", + "predictions = layers.Dense(1, activation=\"sigmoid\", name=\"predictions\")(x)\n", + "\n", + "text_model = tf.keras.Model(inputs, predictions)\n", + "\n", + "# Compile the model with binary crossentropy loss and an adam optimizer.\n", + "text_model.compile(loss=\"binary_crossentropy\", optimizer=\"adam\", metrics=[\"accuracy\"])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f177875d", + "metadata": {}, + "outputs": [], + "source": [ + "epochs = 1\n", + "\n", + "# Fit the model using the train and test datasets.\n", + "text_model.fit(train_ds, validation_data=val_ds, epochs=epochs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a276fc85", + "metadata": {}, + "outputs": [], + "source": [ + "# A string input\n", + "inputs = tf.keras.Input(shape=(1,), dtype=\"string\")\n", + "# Turn strings into vocab indices\n", + "indices = vectorize_layer_non_custom(inputs)\n", + "# Turn vocab indices into predictions\n", + "outputs = text_model(indices)\n", + "\n", + "# Our end to end model\n", + "end_to_end_model = tf.keras.Model(inputs, outputs)\n", + "end_to_end_model.compile(\n", + " loss=\"binary_crossentropy\", optimizer=\"adam\", metrics=[\"accuracy\"]\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "06493feb", + "metadata": {}, + "outputs": [], + "source": [ + "saved_text_model = weave.save(end_to_end_model)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3040ac71", + "metadata": {}, + "outputs": [], + "source": [ + "weave_keras.call_string(saved_text_model, \"single test string\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "027e8660", + "metadata": {}, + "outputs": [], + "source": [ + "weave.legacy.weave.panels.Table([\n", + " {'input_str': \"This is a test\"},\n", + " {'input_str': \"This is a horrible test\"},\n", + " {'input_str': \"I love weave\"},\n", + " {'input_str': \"please work!\"},\n", + " {'input_str': \"I am a person in a house\"},\n", + "], columns=[\n", + " lambda row: row['input_str'],\n", + " lambda row: weave_keras.call_string(saved_text_model, row['input_str'])\n", + "])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f0e435bc", + "metadata": {}, + "outputs": [], + "source": [ + "# published_text_model = weave.save(end_to_end_model)\n", + "published_text_model = weave.publish(end_to_end_model)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8691e38a", + "metadata": {}, + "outputs": [], + "source": [ + "weave_keras.call_string(published_text_model, \"single test string\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "markdown", - "id": "2f3cbb0d", - "metadata": {}, - "source": [ - "# Train Language Model\n", - "\n", - "From: https://keras.io/examples/nlp/text_classification_from_scratch/" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ec47e09b", - "metadata": {}, - "outputs": [], - "source": [ - "import tensorflow as tf\n", - "import numpy as np" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d288f1b0", - "metadata": {}, - "outputs": [], - "source": [ - "!curl -O https://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz\n", - "!tar -xf aclImdb_v1.tar.gz\n", - "!rm -r aclImdb/train/unsup" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4e74e162", - "metadata": {}, - "outputs": [], - "source": [ - "batch_size = 32\n", - "raw_train_ds = tf.keras.preprocessing.text_dataset_from_directory(\n", - " \"aclImdb/train\",\n", - " batch_size=batch_size,\n", - " validation_split=0.2,\n", - " subset=\"training\",\n", - " seed=1337,\n", - ")\n", - "raw_val_ds = tf.keras.preprocessing.text_dataset_from_directory(\n", - " \"aclImdb/train\",\n", - " batch_size=batch_size,\n", - " validation_split=0.2,\n", - " subset=\"validation\",\n", - " seed=1337,\n", - ")\n", - "raw_test_ds = tf.keras.preprocessing.text_dataset_from_directory(\n", - " \"aclImdb/test\", batch_size=batch_size\n", - ")\n", - "\n", - "print(f\"Number of batches in raw_train_ds: {raw_train_ds.cardinality()}\")\n", - "print(f\"Number of batches in raw_val_ds: {raw_val_ds.cardinality()}\")\n", - "print(f\"Number of batches in raw_test_ds: {raw_test_ds.cardinality()}\")\n", - "\n", - "from tensorflow.keras.layers import TextVectorization\n", - "import string\n", - "import re\n", - "\n", - "# Having looked at our data above, we see that the raw text contains HTML break\n", - "# tags of the form '
'. These tags will not be removed by the default\n", - "# standardizer (which doesn't strip HTML). Because of this, we will need to\n", - "# create a custom standardization function.\n", - "def custom_standardization(input_data):\n", - " lowercase = tf.strings.lower(input_data)\n", - " stripped_html = tf.strings.regex_replace(lowercase, \"
\", \" \")\n", - " return tf.strings.regex_replace(\n", - " stripped_html, f\"[{re.escape(string.punctuation)}]\", \"\"\n", - " )\n", - "\n", - "\n", - "# Model constants.\n", - "max_features = 20000\n", - "embedding_dim = 128\n", - "sequence_length = 500\n", - "\n", - "# Now that we have our custom standardization, we can instantiate our text\n", - "# vectorization layer. We are using this layer to normalize, split, and map\n", - "# strings to integers, so we set our 'output_mode' to 'int'.\n", - "# Note that we're using the default split function,\n", - "# and the custom standardization defined above.\n", - "# We also set an explicit maximum sequence length, since the CNNs later in our\n", - "# model won't support ragged sequences.\n", - "vectorize_layer = TextVectorization(\n", - " standardize=custom_standardization,\n", - " max_tokens=max_features,\n", - " output_mode=\"int\",\n", - " output_sequence_length=sequence_length,\n", - ")\n", - "\n", - "vectorize_layer_non_custom = TextVectorization(\n", - "# standardize=custom_standardization,\n", - " max_tokens=max_features,\n", - " output_mode=\"int\",\n", - " output_sequence_length=sequence_length,\n", - ")\n", - "\n", - "# Now that the vocab layer has been created, call `adapt` on a text-only\n", - "# dataset to create the vocabulary. You don't have to batch, but for very large\n", - "# datasets this means you're not keeping spare copies of the dataset in memory.\n", - "\n", - "# Let's make a text-only dataset (no labels):\n", - "text_ds = raw_train_ds.map(lambda x, y: x)\n", - "# Let's call `adapt`:\n", - "vectorize_layer.adapt(text_ds)\n", - "vectorize_layer_non_custom.adapt(text_ds)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7e48486a", - "metadata": {}, - "outputs": [], - "source": [ - "def vectorize_text(text, label):\n", - " text = tf.expand_dims(text, -1)\n", - " return vectorize_layer(text), label\n", - "\n", - "\n", - "# Vectorize the data.\n", - "train_ds = raw_train_ds.map(vectorize_text)\n", - "val_ds = raw_val_ds.map(vectorize_text)\n", - "test_ds = raw_test_ds.map(vectorize_text)\n", - "\n", - "# Do async prefetching / buffering of the data for best performance on GPU.\n", - "train_ds = train_ds.cache().prefetch(buffer_size=10)\n", - "val_ds = val_ds.cache().prefetch(buffer_size=10)\n", - "test_ds = test_ds.cache().prefetch(buffer_size=10)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7f053ba5", - "metadata": {}, - "outputs": [], - "source": [ - "from tensorflow.keras import layers\n", - "\n", - "# A integer input for vocab indices.\n", - "inputs = tf.keras.Input(shape=(None,), dtype=\"int64\")\n", - "\n", - "# Next, we add a layer to map those vocab indices into a space of dimensionality\n", - "# 'embedding_dim'.\n", - "x = layers.Embedding(max_features, embedding_dim)(inputs)\n", - "x = layers.Dropout(0.5)(x)\n", - "\n", - "# Conv1D + global max pooling\n", - "x = layers.Conv1D(128, 7, padding=\"valid\", activation=\"relu\", strides=3)(x)\n", - "x = layers.Conv1D(128, 7, padding=\"valid\", activation=\"relu\", strides=3)(x)\n", - "x = layers.GlobalMaxPooling1D()(x)\n", - "\n", - "# We add a vanilla hidden layer:\n", - "x = layers.Dense(128, activation=\"relu\")(x)\n", - "x = layers.Dropout(0.5)(x)\n", - "\n", - "# We project onto a single unit output layer, and squash it with a sigmoid:\n", - "predictions = layers.Dense(1, activation=\"sigmoid\", name=\"predictions\")(x)\n", - "\n", - "text_model = tf.keras.Model(inputs, predictions)\n", - "\n", - "# Compile the model with binary crossentropy loss and an adam optimizer.\n", - "text_model.compile(loss=\"binary_crossentropy\", optimizer=\"adam\", metrics=[\"accuracy\"])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f177875d", - "metadata": {}, - "outputs": [], - "source": [ - "epochs = 1\n", - "\n", - "# Fit the model using the train and test datasets.\n", - "text_model.fit(train_ds, validation_data=val_ds, epochs=epochs)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a276fc85", - "metadata": {}, - "outputs": [], - "source": [ - "# A string input\n", - "inputs = tf.keras.Input(shape=(1,), dtype=\"string\")\n", - "# Turn strings into vocab indices\n", - "indices = vectorize_layer_non_custom(inputs)\n", - "# Turn vocab indices into predictions\n", - "outputs = text_model(indices)\n", - "\n", - "# Our end to end model\n", - "end_to_end_model = tf.keras.Model(inputs, outputs)\n", - "end_to_end_model.compile(\n", - " loss=\"binary_crossentropy\", optimizer=\"adam\", metrics=[\"accuracy\"]\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "06493feb", - "metadata": {}, - "outputs": [], - "source": [ - "saved_text_model = weave.save(end_to_end_model)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3040ac71", - "metadata": {}, - "outputs": [], - "source": [ - "weave_keras.call_string(saved_text_model, \"single test string\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "027e8660", - "metadata": {}, - "outputs": [], - "source": [ - "weave.legacy.panels.Table([\n", - " {'input_str': \"This is a test\"},\n", - " {'input_str': \"This is a horrible test\"},\n", - " {'input_str': \"I love weave\"},\n", - " {'input_str': \"please work!\"},\n", - " {'input_str': \"I am a person in a house\"},\n", - "], columns=[\n", - " lambda row: row['input_str'],\n", - " lambda row: weave_keras.call_string(saved_text_model, row['input_str'])\n", - "])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f0e435bc", - "metadata": {}, - "outputs": [], - "source": [ - "# published_text_model = weave.save(end_to_end_model)\n", - "published_text_model = weave.publish(end_to_end_model)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8691e38a", - "metadata": {}, - "outputs": [], - "source": [ - "weave_keras.call_string(published_text_model, \"single test string\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/LLMs Via Weave.ipynb b/weave/legacy/examples/experimental/skip_test/LLMs Via Weave.ipynb index cf781c31cce..f974b36f8ef 100644 --- a/weave/legacy/examples/experimental/skip_test/LLMs Via Weave.ipynb +++ b/weave/legacy/examples/experimental/skip_test/LLMs Via Weave.ipynb @@ -1,111 +1,111 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "2dc04fd0", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "# weave.use_frontend_devmode()" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "2dc04fd0", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "# weave.use_frontend_devmode()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "615e5163", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "import weave.legacy.weave\n", + "panels = weave.legacy.weave.panels\n", + "\n", + "project = \"tim-test-llms-test-all-final-colab-01\"\n", + "entity = \"timssweeney\"\n", + "\n", + "# Create a Weave Query to get Traces\n", + "traces = (\n", + " weave.legacy.weave.ops\n", + " .project(entity, project)\n", + " .runs()\n", + " .history().map(\n", + " lambda row: row['langchain_trace'].dropna()\n", + " )\n", + " .concat()\n", + " .dropna()\n", + " .sort(\n", + " lambda row: weave.legacy.weave.ops.make_list(a=row.startTime()), \n", + " ['asc']\n", + " )\n", + ")\n", + "\n", + "# Create a table from the query\n", + "table = panels.Table(traces)\n", + "table_state = table.config.tableState\n", + "\n", + "# Add columns, set sorting, and specify panels for columns\n", + "table_state.add_column(lambda row: row.traceSummaryDict()[\"isSuccess\"], \"Success\")\n", + "start_time_col_id = table_state.add_column(lambda row: row.traceSummaryDict()[\"startTime\"].toTimestamp(), \"Timestamp\")\n", + "table_state.enable_sort(start_time_col_id, \"desc\")\n", + "\n", + "markdown_panel = panels.table_state.PanelDef('string', {'mode': 'markdown'})\n", + "table_state.add_column(lambda row: row.traceSummaryDict()[\"formattedInput\"], \"Input\", markdown_panel)\n", + "table_state.add_column(lambda row: row.traceSummaryDict()[\"formattedOutput\"], \"Output\", markdown_panel)\n", + "table_state.add_column(lambda row: row.traceSummaryDict()[\"formattedChain\"], \"Chain\", markdown_panel)\n", + "table_state.add_column(lambda row: row.traceSummaryDict()[\"error\"], \"Error\")\n", + "table_state.add_column(lambda row: row.traceSummaryDict()[\"modelHash\"], \"Model ID\")\n", + "\n", + "# Compose into a group with detail view below\n", + "dash = panels.Group(\n", + " items={\n", + " \"all_traces\": table,\n", + " \"selected_details\": lambda all_traces: panels.Card(\n", + " title='Trace Viewer',\n", + " subtitle='',\n", + " content=[\n", + " panels.CardTab(\n", + " name='Trace Timeline',\n", + " content=panels.PanelWBTraceTreeTraceViewer(all_traces.active_data())\n", + " ),\n", + " panels.CardTab(\n", + " name='Model Architecture',\n", + " content=panels.PanelWBTraceTreeModelViewer(all_traces.active_data())\n", + " ),\n", + "\n", + " ]\n", + " )\n", + " }\n", + ")\n", + "\n", + "# Publish to W&B\n", + "# weave.publish(dash, \"weave_ops/prompts_in_weave1\")\n", + "\n", + "# View locally\n", + "dash" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "615e5163", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "import weave.legacy\n", - "panels = weave.legacy.panels\n", - "\n", - "project = \"tim-test-llms-test-all-final-colab-01\"\n", - "entity = \"timssweeney\"\n", - "\n", - "# Create a Weave Query to get Traces\n", - "traces = (\n", - " weave.legacy.ops\n", - " .project(entity, project)\n", - " .runs()\n", - " .history().map(\n", - " lambda row: row['langchain_trace'].dropna()\n", - " )\n", - " .concat()\n", - " .dropna()\n", - " .sort(\n", - " lambda row: weave.legacy.ops.make_list(a=row.startTime()), \n", - " ['asc']\n", - " )\n", - ")\n", - "\n", - "# Create a table from the query\n", - "table = panels.Table(traces)\n", - "table_state = table.config.tableState\n", - "\n", - "# Add columns, set sorting, and specify panels for columns\n", - "table_state.add_column(lambda row: row.traceSummaryDict()[\"isSuccess\"], \"Success\")\n", - "start_time_col_id = table_state.add_column(lambda row: row.traceSummaryDict()[\"startTime\"].toTimestamp(), \"Timestamp\")\n", - "table_state.enable_sort(start_time_col_id, \"desc\")\n", - "\n", - "markdown_panel = panels.table_state.PanelDef('string', {'mode': 'markdown'})\n", - "table_state.add_column(lambda row: row.traceSummaryDict()[\"formattedInput\"], \"Input\", markdown_panel)\n", - "table_state.add_column(lambda row: row.traceSummaryDict()[\"formattedOutput\"], \"Output\", markdown_panel)\n", - "table_state.add_column(lambda row: row.traceSummaryDict()[\"formattedChain\"], \"Chain\", markdown_panel)\n", - "table_state.add_column(lambda row: row.traceSummaryDict()[\"error\"], \"Error\")\n", - "table_state.add_column(lambda row: row.traceSummaryDict()[\"modelHash\"], \"Model ID\")\n", - "\n", - "# Compose into a group with detail view below\n", - "dash = panels.Group(\n", - " items={\n", - " \"all_traces\": table,\n", - " \"selected_details\": lambda all_traces: panels.Card(\n", - " title='Trace Viewer',\n", - " subtitle='',\n", - " content=[\n", - " panels.CardTab(\n", - " name='Trace Timeline',\n", - " content=panels.PanelWBTraceTreeTraceViewer(all_traces.active_data())\n", - " ),\n", - " panels.CardTab(\n", - " name='Model Architecture',\n", - " content=panels.PanelWBTraceTreeModelViewer(all_traces.active_data())\n", - " ),\n", - "\n", - " ]\n", - " )\n", - " }\n", - ")\n", - "\n", - "# Publish to W&B\n", - "# weave.publish(dash, \"weave_ops/prompts_in_weave1\")\n", - "\n", - "# View locally\n", - "dash" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/Model Cards.ipynb b/weave/legacy/examples/experimental/skip_test/Model Cards.ipynb index f00044eebfd..73760222547 100644 --- a/weave/legacy/examples/experimental/skip_test/Model Cards.ipynb +++ b/weave/legacy/examples/experimental/skip_test/Model Cards.ipynb @@ -1,79 +1,79 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "c6b2e19b", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "weave.use_frontend_devmode()\n", - "from weave.legacy.ecosystem import models" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "c6b2e19b", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "weave.use_frontend_devmode()\n", + "from weave.legacy.weave.ecosystem import models" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4b51e4d5", + "metadata": {}, + "outputs": [], + "source": [ + "# Declare an instance of a ModelCard\n", + "model_card = models.ModelCard(\n", + " model_name='GPT-3',\n", + " created_by=models.User(name='OpenAI'),\n", + " updated_at='August 25th 2021, at 3:36:29pm', # TODO: timestamp\n", + " model_type='Language model',\n", + " primary_metric=models.TargetMetric(name='acc', direction='up'),\n", + " application='Our API has been deployed in thousands of applications with tasks ranging from helping people learn new languages to solving complex classification problems',\n", + " example='...Slightly better example...'\n", + ")\n", + "model_card_ref = weave.save(model_card, 'my-model-card')\n", + "models.model_card_panel(model_card_ref)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ba518a7e", + "metadata": {}, + "outputs": [], + "source": [ + "# Publish it to W&B\n", + "model_card_wbref = weave.publish(model_card, name='my-model')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "32dd7d50", + "metadata": {}, + "outputs": [], + "source": [ + "weave.show(model_card_wbref)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "4b51e4d5", - "metadata": {}, - "outputs": [], - "source": [ - "# Declare an instance of a ModelCard\n", - "model_card = models.ModelCard(\n", - " model_name='GPT-3',\n", - " created_by=models.User(name='OpenAI'),\n", - " updated_at='August 25th 2021, at 3:36:29pm', # TODO: timestamp\n", - " model_type='Language model',\n", - " primary_metric=models.TargetMetric(name='acc', direction='up'),\n", - " application='Our API has been deployed in thousands of applications with tasks ranging from helping people learn new languages to solving complex classification problems',\n", - " example='...Slightly better example...'\n", - ")\n", - "model_card_ref = weave.save(model_card, 'my-model-card')\n", - "models.model_card_panel(model_card_ref)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ba518a7e", - "metadata": {}, - "outputs": [], - "source": [ - "# Publish it to W&B\n", - "model_card_wbref = weave.publish(model_card, name='my-model')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "32dd7d50", - "metadata": {}, - "outputs": [], - "source": [ - "weave.show(model_card_wbref)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/Models.ipynb b/weave/legacy/examples/experimental/skip_test/Models.ipynb index d54666776e4..176f5767541 100644 --- a/weave/legacy/examples/experimental/skip_test/Models.ipynb +++ b/weave/legacy/examples/experimental/skip_test/Models.ipynb @@ -1,103 +1,103 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "0c235474", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "import xgboost\n", - "from weave.legacy.ecosystem import shap\n", - "#weave.use_frontend_devmode()" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "0c235474", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "import xgboost\n", + "from weave.legacy.weave.ecosystem import shap\n", + "#weave.use_frontend_devmode()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "63a29a5f", + "metadata": {}, + "outputs": [], + "source": [ + "dataset = weave.use(shap.ca_housing_dataset(1))\n", + "dataset_arrow = weave.legacy.weave.ops.dataframe_to_arrow(dataset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c5633045", + "metadata": {}, + "outputs": [], + "source": [ + "weave.show(dataset_arrow)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b6edbb55", + "metadata": {}, + "outputs": [], + "source": [ + "weave.publish(dataset_arrow, 'my-dataset-transform')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dcccca4b", + "metadata": {}, + "outputs": [], + "source": [ + "weave.show(x)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "40f37c5a", + "metadata": {}, + "outputs": [], + "source": [ + "weave.legacy.weave.ops.get('wandb-artifact://shawn/weave_ops/my-dataset-transform:8c478776a5e01c3c051d')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7a0d6be5", + "metadata": {}, + "outputs": [], + "source": [ + "@weave.op()\n", + "def some_plotly_op():\n", + " return Plotly.plot(whatever)\n", + "\n", + "weave.name(some_plotly_op(), name='my-cool-plot')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "63a29a5f", - "metadata": {}, - "outputs": [], - "source": [ - "dataset = weave.use(shap.ca_housing_dataset(1))\n", - "dataset_arrow = weave.legacy.ops.dataframe_to_arrow(dataset)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c5633045", - "metadata": {}, - "outputs": [], - "source": [ - "weave.show(dataset_arrow)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b6edbb55", - "metadata": {}, - "outputs": [], - "source": [ - "weave.publish(dataset_arrow, 'my-dataset-transform')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "dcccca4b", - "metadata": {}, - "outputs": [], - "source": [ - "weave.show(x)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "40f37c5a", - "metadata": {}, - "outputs": [], - "source": [ - "weave.legacy.ops.get('wandb-artifact://shawn/weave_ops/my-dataset-transform:8c478776a5e01c3c051d')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7a0d6be5", - "metadata": {}, - "outputs": [], - "source": [ - "@weave.op()\n", - "def some_plotly_op():\n", - " return Plotly.plot(whatever)\n", - "\n", - "weave.name(some_plotly_op(), name='my-cool-plot')" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/Monitor2.ipynb b/weave/legacy/examples/experimental/skip_test/Monitor2.ipynb index 27fad384dec..3b3cb66ccaf 100644 --- a/weave/legacy/examples/experimental/skip_test/Monitor2.ipynb +++ b/weave/legacy/examples/experimental/skip_test/Monitor2.ipynb @@ -1,310 +1,310 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "039f298a", - "metadata": {}, - "outputs": [], - "source": [ - "import pandas as pd\n", - "import weave\n", - "weave.use_frontend_devmode()\n", - "from weave.legacy.ops_arrow.list_ import dataframe_to_arrow\n", - "from weave.legacy.ecosystem import wandb" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "039f298a", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import weave\n", + "weave.use_frontend_devmode()\n", + "from weave.legacy.weave.ops_arrow.list_ import dataframe_to_arrow\n", + "from weave.legacy.weave.ecosystem import wandb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5e0d6245", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import random\n", + "from faker import Faker\n", + "from datetime import timedelta, time\n", + "\n", + "# Generate the version schedule\n", + "def generate_version_schedule(start_date, end_date):\n", + " current_date = start_date\n", + " versions = ['1.0']\n", + " version_schedule = {}\n", + " while current_date <= end_date:\n", + " date_versions = []\n", + " for version in versions:\n", + " service_percent = random.uniform(0, 1)\n", + " date_versions.append((version, service_percent))\n", + "\n", + " version_schedule[current_date.date()] = date_versions\n", + " current_date += timedelta(days=1)\n", + " if random.random() < 0.10: # 5% chance to introduce a new version each day\n", + " new_version = f'{float(versions[-1])+0.1:.1f}'\n", + " versions.append(new_version)\n", + " if len(versions) > 1 and random.random() < 0.10:\n", + " versions.pop(0)\n", + " return version_schedule\n", + "\n", + "# Generate the latency schedule\n", + "def generate_latency_schedule(start_date, end_date):\n", + " latency_schedule = {}\n", + " for current_date in pd.date_range(start_date, end_date):\n", + " base_latency = random.uniform(0.1, 1)\n", + " day_factor = random.uniform(0.5, 1.5)\n", + " month_factor = random.uniform(0.5, 1.5)\n", + " latency = base_latency * day_factor * month_factor\n", + " latency_schedule[current_date.date()] = latency\n", + " return latency_schedule\n", + "\n", + "# Generate the cost schedule\n", + "def generate_cost_schedule(start_date, end_date, cost_change_date):\n", + " cost_schedule = {}\n", + " current_date = start_date\n", + " cost_per_token = 0.01\n", + " while current_date <= end_date:\n", + " if current_date >= cost_change_date:\n", + " cost_per_token = 0.005\n", + " cost_schedule[current_date.date()] = cost_per_token\n", + " current_date += timedelta(days=1)\n", + " return cost_schedule\n", + "\n", + "def generate_user_usage_schedule(start_date, end_date, users):\n", + " user_usage_schedule = []\n", + " for user in users:\n", + " current_date = start_date + timedelta(days=random.randrange(90))\n", + " while current_date <= end_date:\n", + " usage_periods = random.randint(1, 30)\n", + " for _ in range(usage_periods):\n", + " period_length_timedelta = timedelta(hours=random.randint(1, 24 * 7))\n", + " rate = random.uniform(0.1, 10)\n", + " user_usage_schedule.append((current_date, user, period_length_timedelta, rate))\n", + " current_date += period_length_timedelta # Increment current_date\n", + " if current_date > end_date:\n", + " break\n", + " return user_usage_schedule" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9d6a0318", + "metadata": {}, + "outputs": [], + "source": [ + "# Define our fake users\n", + "fake = Faker()\n", + "users = [fake.user_name() for _ in range(100)]\n", + "\n", + "# Read the file and generate prompts\n", + "with open('/Users/shawn/Downloads/t8.shakespeare.txt', 'r') as f:\n", + " lines = f.read().split('\\n')\n", + "\n", + "# Define the time range\n", + "start_date = pd.to_datetime('2023-01-01', utc=True)\n", + "end_date = pd.to_datetime('2023-03-31', utc=True)\n", + "cost_change_date = pd.to_datetime('2023-02-15', utc=True)\n", + "\n", + "# Generate the schedules\n", + "version_schedule = generate_version_schedule(start_date, end_date)\n", + "latency_schedule = generate_latency_schedule(start_date, end_date)\n", + "cost_schedule = generate_cost_schedule(start_date, end_date, cost_change_date)\n", + "user_usage_schedule = generate_user_usage_schedule(start_date, end_date, users)\n", + "\n", + "# Helper function to generate a random completion\n", + "def generate_completion(prompt):\n", + " words = prompt.split()\n", + " completion = ' '.join(random.choices(words, k=int(len(words)* (random.random() + 0.1) * 10)))\n", + " return completion\n", + "\n", + "#latency_schedule" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a672c782", + "metadata": {}, + "outputs": [], + "source": [ + "import tqdm\n", + "data = []\n", + "for usage in tqdm.tqdm(user_usage_schedule):\n", + " usage_date, user, usage_period, rate = usage\n", + " \n", + " end_date = usage_date + usage_period\n", + " increment = timedelta(hours=rate)\n", + " \n", + " while usage_date < end_date:\n", + " # Find the version that was active during this usage\n", + " if usage_date.date() not in version_schedule:\n", + " break\n", + " active_versions = version_schedule[usage_date.date()]\n", + " #active_versions = [(version, percent) for date, version, percent in version_schedule if date.date() == usage_date.date()]\n", + " # Normalize the service percentages\n", + " total_percent = sum([percent for version, percent in active_versions])\n", + " if total_percent == 0:\n", + " continue\n", + " normalized_percentages = [percent / total_percent for version, percent in active_versions]\n", + "\n", + " version = np.random.choice([v for v, p in active_versions], p=normalized_percentages)\n", + " \n", + " # Find the cost during this usage\n", + " cost_per_token = cost_schedule[usage_date.date()]\n", + " \n", + " # Find the average latency during this usage\n", + " latency = latency_schedule[usage_date.date()]\n", + " latency *= (0.9 + random.random() *.2)\n", + " \n", + " prompt = ' '.join(random.sample(lines, 10)) # Increase prompt size\n", + " completion = generate_completion(prompt)\n", + " prompt_tokens = len(prompt.split())\n", + " completion_tokens = len(completion.split())\n", + " api_cost = (prompt_tokens + completion_tokens) * cost_per_token\n", + "\n", + " data.append([usage_date, user, version, prompt, completion, \n", + " prompt_tokens, completion_tokens, api_cost, latency])\n", + " \n", + " usage_date += increment\n", + "\n", + "df = pd.DataFrame(data, columns=['timestamp', 'username', 'model_version', 'prompt', 'completion', \n", + " 'prompt_tokens', 'completion_tokens', 'api_cost', 'latency'])\n", + "\n", + "predictions = weave.save(dataframe_to_arrow(df), 'predictions')\n", + "predictions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "57fc86e0", + "metadata": {}, + "outputs": [], + "source": [ + "predictions = weave.legacy.weave.ops.get(\"local-artifact:///predictions:latest/obj\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8049b6dd", + "metadata": {}, + "outputs": [], + "source": [ + "weave.legacy.weave.panels.Board(\n", + " vars={\n", + " 'all_preds': predictions,\n", + " 'x_max': weave.legacy.weave.ops.date_parse(str(end_date)),\n", + " 'x_min': lambda x_max: x_max - weave.legacy.weave.ops.days(5),\n", + " 'predictions': lambda x_min: predictions.filter(lambda pred: pred['timestamp'] > x_min)\n", + " },\n", + " panels=[\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", + " predictions,\n", + " x=lambda item: item[\"timestamp\"],\n", + " label=lambda item: item[\"model_version\"],\n", + " agg=lambda preds: preds.count(),\n", + " min_x=x_min,\n", + " max_x=x_max,\n", + " mark=\"bar\",\n", + " axis_labels={\"y\": \"num_preds\"},\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=12, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", + " predictions,\n", + " x=lambda item: item[\"timestamp\"],\n", + " label=lambda item: item[\"username\"],\n", + " agg=lambda preds: preds.count(),\n", + " min_x=x_min,\n", + " max_x=x_max,\n", + " mark=\"bar\",\n", + " axis_labels={\"y\": \"num_preds\"},\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=12, y=0, w=12, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", + " predictions,\n", + " x=lambda item: item[\"timestamp\"],\n", + " #label=lambda item: item[\"model_version\"],\n", + " agg=lambda preds: preds[\"api_cost\"].sum(),\n", + " min_x=x_min,\n", + " max_x=x_max,\n", + " mark=\"line\",\n", + " axis_labels={\"y\": \"api_cost\"},\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=6, w=8, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", + " predictions,\n", + " x=lambda item: item[\"timestamp\"],\n", + " #label=lambda item: item[\"model_version\"],\n", + " agg=lambda preds: preds[\"prompt_tokens\"].sum() + preds['completion_tokens'].sum(),\n", + " min_x=x_min,\n", + " max_x=x_max,\n", + " mark=\"line\",\n", + " axis_labels={\"y\": \"total_tokens\"},\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=8, y=6, w=8, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", + " predictions,\n", + " x=lambda item: item[\"timestamp\"],\n", + " #label=lambda item: item[\"model_version\"],\n", + " agg=lambda preds: preds[\"latency\"].avg(),\n", + " min_x=x_min,\n", + " max_x=x_max,\n", + " mark=\"line\",\n", + " axis_labels={\"y\": \"avg_latency\"},\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=16, y=6, w=8, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, x_min, x_max: wandb.Distribution(\n", + " predictions,\n", + " value_fn=lambda pred: pred['api_cost'],\n", + " bin_size=0.2\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=12, w=8, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, x_min, x_max: wandb.Distribution(\n", + " predictions,\n", + " value_fn=lambda pred: pred['prompt_tokens'] + pred['completion_tokens'],\n", + " bin_size=25\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=8, y=12, w=8, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, x_min, x_max: wandb.Distribution(\n", + " predictions,\n", + " value_fn=lambda pred: pred['latency'],\n", + " bin_size=0.05\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=16, y=12, w=8, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions: predictions,\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=18, w=24, h=12)\n", + " )\n", + " ]\n", + ")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "5e0d6245", - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import pandas as pd\n", - "import random\n", - "from faker import Faker\n", - "from datetime import timedelta, time\n", - "\n", - "# Generate the version schedule\n", - "def generate_version_schedule(start_date, end_date):\n", - " current_date = start_date\n", - " versions = ['1.0']\n", - " version_schedule = {}\n", - " while current_date <= end_date:\n", - " date_versions = []\n", - " for version in versions:\n", - " service_percent = random.uniform(0, 1)\n", - " date_versions.append((version, service_percent))\n", - "\n", - " version_schedule[current_date.date()] = date_versions\n", - " current_date += timedelta(days=1)\n", - " if random.random() < 0.10: # 5% chance to introduce a new version each day\n", - " new_version = f'{float(versions[-1])+0.1:.1f}'\n", - " versions.append(new_version)\n", - " if len(versions) > 1 and random.random() < 0.10:\n", - " versions.pop(0)\n", - " return version_schedule\n", - "\n", - "# Generate the latency schedule\n", - "def generate_latency_schedule(start_date, end_date):\n", - " latency_schedule = {}\n", - " for current_date in pd.date_range(start_date, end_date):\n", - " base_latency = random.uniform(0.1, 1)\n", - " day_factor = random.uniform(0.5, 1.5)\n", - " month_factor = random.uniform(0.5, 1.5)\n", - " latency = base_latency * day_factor * month_factor\n", - " latency_schedule[current_date.date()] = latency\n", - " return latency_schedule\n", - "\n", - "# Generate the cost schedule\n", - "def generate_cost_schedule(start_date, end_date, cost_change_date):\n", - " cost_schedule = {}\n", - " current_date = start_date\n", - " cost_per_token = 0.01\n", - " while current_date <= end_date:\n", - " if current_date >= cost_change_date:\n", - " cost_per_token = 0.005\n", - " cost_schedule[current_date.date()] = cost_per_token\n", - " current_date += timedelta(days=1)\n", - " return cost_schedule\n", - "\n", - "def generate_user_usage_schedule(start_date, end_date, users):\n", - " user_usage_schedule = []\n", - " for user in users:\n", - " current_date = start_date + timedelta(days=random.randrange(90))\n", - " while current_date <= end_date:\n", - " usage_periods = random.randint(1, 30)\n", - " for _ in range(usage_periods):\n", - " period_length_timedelta = timedelta(hours=random.randint(1, 24 * 7))\n", - " rate = random.uniform(0.1, 10)\n", - " user_usage_schedule.append((current_date, user, period_length_timedelta, rate))\n", - " current_date += period_length_timedelta # Increment current_date\n", - " if current_date > end_date:\n", - " break\n", - " return user_usage_schedule" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9d6a0318", - "metadata": {}, - "outputs": [], - "source": [ - "# Define our fake users\n", - "fake = Faker()\n", - "users = [fake.user_name() for _ in range(100)]\n", - "\n", - "# Read the file and generate prompts\n", - "with open('/Users/shawn/Downloads/t8.shakespeare.txt', 'r') as f:\n", - " lines = f.read().split('\\n')\n", - "\n", - "# Define the time range\n", - "start_date = pd.to_datetime('2023-01-01', utc=True)\n", - "end_date = pd.to_datetime('2023-03-31', utc=True)\n", - "cost_change_date = pd.to_datetime('2023-02-15', utc=True)\n", - "\n", - "# Generate the schedules\n", - "version_schedule = generate_version_schedule(start_date, end_date)\n", - "latency_schedule = generate_latency_schedule(start_date, end_date)\n", - "cost_schedule = generate_cost_schedule(start_date, end_date, cost_change_date)\n", - "user_usage_schedule = generate_user_usage_schedule(start_date, end_date, users)\n", - "\n", - "# Helper function to generate a random completion\n", - "def generate_completion(prompt):\n", - " words = prompt.split()\n", - " completion = ' '.join(random.choices(words, k=int(len(words)* (random.random() + 0.1) * 10)))\n", - " return completion\n", - "\n", - "#latency_schedule" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a672c782", - "metadata": {}, - "outputs": [], - "source": [ - "import tqdm\n", - "data = []\n", - "for usage in tqdm.tqdm(user_usage_schedule):\n", - " usage_date, user, usage_period, rate = usage\n", - " \n", - " end_date = usage_date + usage_period\n", - " increment = timedelta(hours=rate)\n", - " \n", - " while usage_date < end_date:\n", - " # Find the version that was active during this usage\n", - " if usage_date.date() not in version_schedule:\n", - " break\n", - " active_versions = version_schedule[usage_date.date()]\n", - " #active_versions = [(version, percent) for date, version, percent in version_schedule if date.date() == usage_date.date()]\n", - " # Normalize the service percentages\n", - " total_percent = sum([percent for version, percent in active_versions])\n", - " if total_percent == 0:\n", - " continue\n", - " normalized_percentages = [percent / total_percent for version, percent in active_versions]\n", - "\n", - " version = np.random.choice([v for v, p in active_versions], p=normalized_percentages)\n", - " \n", - " # Find the cost during this usage\n", - " cost_per_token = cost_schedule[usage_date.date()]\n", - " \n", - " # Find the average latency during this usage\n", - " latency = latency_schedule[usage_date.date()]\n", - " latency *= (0.9 + random.random() *.2)\n", - " \n", - " prompt = ' '.join(random.sample(lines, 10)) # Increase prompt size\n", - " completion = generate_completion(prompt)\n", - " prompt_tokens = len(prompt.split())\n", - " completion_tokens = len(completion.split())\n", - " api_cost = (prompt_tokens + completion_tokens) * cost_per_token\n", - "\n", - " data.append([usage_date, user, version, prompt, completion, \n", - " prompt_tokens, completion_tokens, api_cost, latency])\n", - " \n", - " usage_date += increment\n", - "\n", - "df = pd.DataFrame(data, columns=['timestamp', 'username', 'model_version', 'prompt', 'completion', \n", - " 'prompt_tokens', 'completion_tokens', 'api_cost', 'latency'])\n", - "\n", - "predictions = weave.save(dataframe_to_arrow(df), 'predictions')\n", - "predictions" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "57fc86e0", - "metadata": {}, - "outputs": [], - "source": [ - "predictions = weave.legacy.ops.get(\"local-artifact:///predictions:latest/obj\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8049b6dd", - "metadata": {}, - "outputs": [], - "source": [ - "weave.legacy.panels.Board(\n", - " vars={\n", - " 'all_preds': predictions,\n", - " 'x_max': weave.legacy.ops.date_parse(str(end_date)),\n", - " 'x_min': lambda x_max: x_max - weave.legacy.ops.days(5),\n", - " 'predictions': lambda x_min: predictions.filter(lambda pred: pred['timestamp'] > x_min)\n", - " },\n", - " panels=[\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", - " predictions,\n", - " x=lambda item: item[\"timestamp\"],\n", - " label=lambda item: item[\"model_version\"],\n", - " agg=lambda preds: preds.count(),\n", - " min_x=x_min,\n", - " max_x=x_max,\n", - " mark=\"bar\",\n", - " axis_labels={\"y\": \"num_preds\"},\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=12, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", - " predictions,\n", - " x=lambda item: item[\"timestamp\"],\n", - " label=lambda item: item[\"username\"],\n", - " agg=lambda preds: preds.count(),\n", - " min_x=x_min,\n", - " max_x=x_max,\n", - " mark=\"bar\",\n", - " axis_labels={\"y\": \"num_preds\"},\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=12, y=0, w=12, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", - " predictions,\n", - " x=lambda item: item[\"timestamp\"],\n", - " #label=lambda item: item[\"model_version\"],\n", - " agg=lambda preds: preds[\"api_cost\"].sum(),\n", - " min_x=x_min,\n", - " max_x=x_max,\n", - " mark=\"line\",\n", - " axis_labels={\"y\": \"api_cost\"},\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=6, w=8, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", - " predictions,\n", - " x=lambda item: item[\"timestamp\"],\n", - " #label=lambda item: item[\"model_version\"],\n", - " agg=lambda preds: preds[\"prompt_tokens\"].sum() + preds['completion_tokens'].sum(),\n", - " min_x=x_min,\n", - " max_x=x_max,\n", - " mark=\"line\",\n", - " axis_labels={\"y\": \"total_tokens\"},\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=8, y=6, w=8, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", - " predictions,\n", - " x=lambda item: item[\"timestamp\"],\n", - " #label=lambda item: item[\"model_version\"],\n", - " agg=lambda preds: preds[\"latency\"].avg(),\n", - " min_x=x_min,\n", - " max_x=x_max,\n", - " mark=\"line\",\n", - " axis_labels={\"y\": \"avg_latency\"},\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=16, y=6, w=8, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, x_min, x_max: wandb.Distribution(\n", - " predictions,\n", - " value_fn=lambda pred: pred['api_cost'],\n", - " bin_size=0.2\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=12, w=8, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, x_min, x_max: wandb.Distribution(\n", - " predictions,\n", - " value_fn=lambda pred: pred['prompt_tokens'] + pred['completion_tokens'],\n", - " bin_size=25\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=8, y=12, w=8, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, x_min, x_max: wandb.Distribution(\n", - " predictions,\n", - " value_fn=lambda pred: pred['latency'],\n", - " bin_size=0.05\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=16, y=12, w=8, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions: predictions,\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=18, w=24, h=12)\n", - " )\n", - " ]\n", - ")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/Monitor3.ipynb b/weave/legacy/examples/experimental/skip_test/Monitor3.ipynb index 36c7bd69d62..f6634410915 100644 --- a/weave/legacy/examples/experimental/skip_test/Monitor3.ipynb +++ b/weave/legacy/examples/experimental/skip_test/Monitor3.ipynb @@ -1,320 +1,320 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "039f298a", - "metadata": {}, - "outputs": [], - "source": [ - "import pandas as pd\n", - "import weave\n", - "weave.use_frontend_devmode()\n", - "from weave.legacy.ops_arrow.list_ import dataframe_to_arrow\n", - "from weave.legacy.ecosystem import wandb" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "039f298a", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import weave\n", + "weave.use_frontend_devmode()\n", + "from weave.legacy.weave.ops_arrow.list_ import dataframe_to_arrow\n", + "from weave.legacy.weave.ecosystem import wandb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5e0d6245", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import random\n", + "from faker import Faker\n", + "from datetime import timedelta, time\n", + "\n", + "# Generate the version schedule\n", + "def generate_version_schedule(start_date, end_date):\n", + " current_date = start_date\n", + " versions = ['1.0']\n", + " version_schedule = {}\n", + " while current_date <= end_date:\n", + " date_versions = []\n", + " for version in versions:\n", + " service_percent = random.uniform(0, 1)\n", + " date_versions.append((version, service_percent))\n", + "\n", + " version_schedule[current_date.date()] = date_versions\n", + " current_date += timedelta(days=1)\n", + " if random.random() < 0.10: # 5% chance to introduce a new version each day\n", + " new_version = f'{float(versions[-1])+0.1:.1f}'\n", + " versions.append(new_version)\n", + " if len(versions) > 1 and random.random() < 0.10:\n", + " versions.pop(0)\n", + " return version_schedule\n", + "\n", + "# Generate the latency schedule\n", + "def generate_latency_schedule(start_date, end_date):\n", + " latency_schedule = {}\n", + " for current_date in pd.date_range(start_date, end_date):\n", + " base_latency = random.uniform(0.1, 1)\n", + " day_factor = random.uniform(0.5, 1.5)\n", + " month_factor = random.uniform(0.5, 1.5)\n", + " latency = base_latency * day_factor * month_factor\n", + " latency_schedule[current_date.date()] = latency\n", + " return latency_schedule\n", + "\n", + "# Generate the cost schedule\n", + "def generate_cost_schedule(start_date, end_date, cost_change_date):\n", + " cost_schedule = {}\n", + " current_date = start_date\n", + " cost_per_token = 0.01\n", + " while current_date <= end_date:\n", + " if current_date >= cost_change_date:\n", + " cost_per_token = 0.005\n", + " cost_schedule[current_date.date()] = cost_per_token\n", + " current_date += timedelta(days=1)\n", + " return cost_schedule\n", + "\n", + "def generate_user_usage_schedule(start_date, end_date, users):\n", + " user_usage_schedule = []\n", + " for user in users:\n", + " current_date = start_date + timedelta(days=random.randrange(90))\n", + " while current_date <= end_date:\n", + " usage_periods = random.randint(1, 30)\n", + " for _ in range(usage_periods):\n", + " period_length_timedelta = timedelta(hours=random.randint(1, 24 * 7))\n", + " rate = random.uniform(0.1, 10)\n", + " user_usage_schedule.append((current_date, user, period_length_timedelta, rate))\n", + " current_date += period_length_timedelta # Increment current_date\n", + " if current_date > end_date:\n", + " break\n", + " return user_usage_schedule" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9d6a0318", + "metadata": {}, + "outputs": [], + "source": [ + "# Define our fake users\n", + "fake = Faker()\n", + "users = [fake.user_name() for _ in range(100)]\n", + "\n", + "# Read the file and generate prompts\n", + "with open('/Users/shawn/Downloads/t8.shakespeare.txt', 'r') as f:\n", + " lines = f.read().split('\\n')\n", + "\n", + "# Define the time range\n", + "start_date = pd.to_datetime('2023-01-01', utc=True)\n", + "end_date = pd.to_datetime('2023-03-31', utc=True)\n", + "cost_change_date = pd.to_datetime('2023-02-15', utc=True)\n", + "\n", + "# Generate the schedules\n", + "version_schedule = generate_version_schedule(start_date, end_date)\n", + "latency_schedule = generate_latency_schedule(start_date, end_date)\n", + "cost_schedule = generate_cost_schedule(start_date, end_date, cost_change_date)\n", + "user_usage_schedule = generate_user_usage_schedule(start_date, end_date, users)\n", + "\n", + "# Helper function to generate a random completion\n", + "def generate_completion(prompt):\n", + " words = prompt.split()\n", + " completion = ' '.join(random.choices(words, k=int(len(words)* (random.random() + 0.1) * 10)))\n", + " return completion\n", + "\n", + "#latency_schedule" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a672c782", + "metadata": {}, + "outputs": [], + "source": [ + "import tqdm\n", + "data = []\n", + "for usage in tqdm.tqdm(user_usage_schedule):\n", + " usage_date, user, usage_period, rate = usage\n", + " \n", + " end_date = usage_date + usage_period\n", + " increment = timedelta(hours=rate)\n", + " \n", + " while usage_date < end_date:\n", + " # Find the version that was active during this usage\n", + " if usage_date.date() not in version_schedule:\n", + " break\n", + " active_versions = version_schedule[usage_date.date()]\n", + " #active_versions = [(version, percent) for date, version, percent in version_schedule if date.date() == usage_date.date()]\n", + " # Normalize the service percentages\n", + " total_percent = sum([percent for version, percent in active_versions])\n", + " if total_percent == 0:\n", + " continue\n", + " normalized_percentages = [percent / total_percent for version, percent in active_versions]\n", + "\n", + " version = np.random.choice([v for v, p in active_versions], p=normalized_percentages)\n", + " \n", + " # Find the cost during this usage\n", + " cost_per_token = cost_schedule[usage_date.date()]\n", + " \n", + " # Find the average latency during this usage\n", + " latency = latency_schedule[usage_date.date()]\n", + " latency *= (0.9 + random.random() *.2)\n", + " \n", + " prompt = ' '.join(random.sample(lines, 10)) # Increase prompt size\n", + " completion = generate_completion(prompt)\n", + " prompt_tokens = len(prompt.split())\n", + " completion_tokens = len(completion.split())\n", + " api_cost = (prompt_tokens + completion_tokens) * cost_per_token\n", + "\n", + " data.append([usage_date, user, version, prompt, completion, \n", + " prompt_tokens, completion_tokens, api_cost, latency])\n", + " \n", + " usage_date += increment\n", + "\n", + "df = pd.DataFrame(data, columns=['timestamp', 'username', 'model_version', 'prompt', 'completion', \n", + " 'prompt_tokens', 'completion_tokens', 'api_cost', 'latency'])\n", + "\n", + "predictions = weave.save(dataframe_to_arrow(df), 'predictions')\n", + "predictions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "57fc86e0", + "metadata": {}, + "outputs": [], + "source": [ + "predictions = weave.legacy.weave.ops.get(\"local-artifact:///predictions:latest/obj\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8049b6dd", + "metadata": {}, + "outputs": [], + "source": [ + "weave.legacy.weave.panels.Board(\n", + " vars={\n", + " #'all_preds': predictions,\n", + " 'x_max': weave.legacy.weave.ops.date_parse(str(end_date)),\n", + " 'x_min': lambda x_max: x_max - weave.legacy.weave.ops.days(5),\n", + " 'predictions_query': weave.legacy.weave.panels.Query(\n", + " predictions,\n", + " conditions=[\n", + " lambda query_input: weave.legacy.weave.panels.QueryCondition(\n", + " expression=query_input['username'],\n", + " editor=weave.legacy.weave.panels.SelectEditor(\n", + " choices=query_input['username']\n", + " )\n", + " )\n", + " ]),\n", + " 'predictions': lambda predictions_query: predictions_query.selected()\n", + " },\n", + " panels=[\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", + " predictions,\n", + " x=lambda item: item[\"timestamp\"],\n", + " label=lambda item: item[\"model_version\"],\n", + " agg=lambda preds: preds.count(),\n", + " min_x=x_min,\n", + " max_x=x_max,\n", + " mark=\"bar\",\n", + " axis_labels={\"y\": \"num_preds\"},\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=12, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", + " predictions,\n", + " x=lambda item: item[\"timestamp\"],\n", + " label=lambda item: item[\"username\"],\n", + " agg=lambda preds: preds.count(),\n", + " min_x=x_min,\n", + " max_x=x_max,\n", + " mark=\"bar\",\n", + " axis_labels={\"y\": \"num_preds\"},\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=12, y=0, w=12, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", + " predictions,\n", + " x=lambda item: item[\"timestamp\"],\n", + " #label=lambda item: item[\"model_version\"],\n", + " agg=lambda preds: preds[\"api_cost\"].sum(),\n", + " min_x=x_min,\n", + " max_x=x_max,\n", + " mark=\"line\",\n", + " axis_labels={\"y\": \"api_cost\"},\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=6, w=8, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", + " predictions,\n", + " x=lambda item: item[\"timestamp\"],\n", + " #label=lambda item: item[\"model_version\"],\n", + " agg=lambda preds: preds[\"prompt_tokens\"].sum() + preds['completion_tokens'].sum(),\n", + " min_x=x_min,\n", + " max_x=x_max,\n", + " mark=\"line\",\n", + " axis_labels={\"y\": \"total_tokens\"},\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=8, y=6, w=8, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", + " predictions,\n", + " x=lambda item: item[\"timestamp\"],\n", + " #label=lambda item: item[\"model_version\"],\n", + " agg=lambda preds: preds[\"latency\"].avg(),\n", + " min_x=x_min,\n", + " max_x=x_max,\n", + " mark=\"line\",\n", + " axis_labels={\"y\": \"avg_latency\"},\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=16, y=6, w=8, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, x_min, x_max: wandb.Distribution(\n", + " predictions,\n", + " value_fn=lambda pred: pred['api_cost'],\n", + " bin_size=0.2\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=12, w=8, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, x_min, x_max: wandb.Distribution(\n", + " predictions,\n", + " value_fn=lambda pred: pred['prompt_tokens'] + pred['completion_tokens'],\n", + " bin_size=25\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=8, y=12, w=8, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, x_min, x_max: wandb.Distribution(\n", + " predictions,\n", + " value_fn=lambda pred: pred['latency'],\n", + " bin_size=0.05\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=16, y=12, w=8, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions: predictions,\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=18, w=24, h=12)\n", + " )\n", + " ]\n", + ")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "5e0d6245", - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import pandas as pd\n", - "import random\n", - "from faker import Faker\n", - "from datetime import timedelta, time\n", - "\n", - "# Generate the version schedule\n", - "def generate_version_schedule(start_date, end_date):\n", - " current_date = start_date\n", - " versions = ['1.0']\n", - " version_schedule = {}\n", - " while current_date <= end_date:\n", - " date_versions = []\n", - " for version in versions:\n", - " service_percent = random.uniform(0, 1)\n", - " date_versions.append((version, service_percent))\n", - "\n", - " version_schedule[current_date.date()] = date_versions\n", - " current_date += timedelta(days=1)\n", - " if random.random() < 0.10: # 5% chance to introduce a new version each day\n", - " new_version = f'{float(versions[-1])+0.1:.1f}'\n", - " versions.append(new_version)\n", - " if len(versions) > 1 and random.random() < 0.10:\n", - " versions.pop(0)\n", - " return version_schedule\n", - "\n", - "# Generate the latency schedule\n", - "def generate_latency_schedule(start_date, end_date):\n", - " latency_schedule = {}\n", - " for current_date in pd.date_range(start_date, end_date):\n", - " base_latency = random.uniform(0.1, 1)\n", - " day_factor = random.uniform(0.5, 1.5)\n", - " month_factor = random.uniform(0.5, 1.5)\n", - " latency = base_latency * day_factor * month_factor\n", - " latency_schedule[current_date.date()] = latency\n", - " return latency_schedule\n", - "\n", - "# Generate the cost schedule\n", - "def generate_cost_schedule(start_date, end_date, cost_change_date):\n", - " cost_schedule = {}\n", - " current_date = start_date\n", - " cost_per_token = 0.01\n", - " while current_date <= end_date:\n", - " if current_date >= cost_change_date:\n", - " cost_per_token = 0.005\n", - " cost_schedule[current_date.date()] = cost_per_token\n", - " current_date += timedelta(days=1)\n", - " return cost_schedule\n", - "\n", - "def generate_user_usage_schedule(start_date, end_date, users):\n", - " user_usage_schedule = []\n", - " for user in users:\n", - " current_date = start_date + timedelta(days=random.randrange(90))\n", - " while current_date <= end_date:\n", - " usage_periods = random.randint(1, 30)\n", - " for _ in range(usage_periods):\n", - " period_length_timedelta = timedelta(hours=random.randint(1, 24 * 7))\n", - " rate = random.uniform(0.1, 10)\n", - " user_usage_schedule.append((current_date, user, period_length_timedelta, rate))\n", - " current_date += period_length_timedelta # Increment current_date\n", - " if current_date > end_date:\n", - " break\n", - " return user_usage_schedule" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9d6a0318", - "metadata": {}, - "outputs": [], - "source": [ - "# Define our fake users\n", - "fake = Faker()\n", - "users = [fake.user_name() for _ in range(100)]\n", - "\n", - "# Read the file and generate prompts\n", - "with open('/Users/shawn/Downloads/t8.shakespeare.txt', 'r') as f:\n", - " lines = f.read().split('\\n')\n", - "\n", - "# Define the time range\n", - "start_date = pd.to_datetime('2023-01-01', utc=True)\n", - "end_date = pd.to_datetime('2023-03-31', utc=True)\n", - "cost_change_date = pd.to_datetime('2023-02-15', utc=True)\n", - "\n", - "# Generate the schedules\n", - "version_schedule = generate_version_schedule(start_date, end_date)\n", - "latency_schedule = generate_latency_schedule(start_date, end_date)\n", - "cost_schedule = generate_cost_schedule(start_date, end_date, cost_change_date)\n", - "user_usage_schedule = generate_user_usage_schedule(start_date, end_date, users)\n", - "\n", - "# Helper function to generate a random completion\n", - "def generate_completion(prompt):\n", - " words = prompt.split()\n", - " completion = ' '.join(random.choices(words, k=int(len(words)* (random.random() + 0.1) * 10)))\n", - " return completion\n", - "\n", - "#latency_schedule" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a672c782", - "metadata": {}, - "outputs": [], - "source": [ - "import tqdm\n", - "data = []\n", - "for usage in tqdm.tqdm(user_usage_schedule):\n", - " usage_date, user, usage_period, rate = usage\n", - " \n", - " end_date = usage_date + usage_period\n", - " increment = timedelta(hours=rate)\n", - " \n", - " while usage_date < end_date:\n", - " # Find the version that was active during this usage\n", - " if usage_date.date() not in version_schedule:\n", - " break\n", - " active_versions = version_schedule[usage_date.date()]\n", - " #active_versions = [(version, percent) for date, version, percent in version_schedule if date.date() == usage_date.date()]\n", - " # Normalize the service percentages\n", - " total_percent = sum([percent for version, percent in active_versions])\n", - " if total_percent == 0:\n", - " continue\n", - " normalized_percentages = [percent / total_percent for version, percent in active_versions]\n", - "\n", - " version = np.random.choice([v for v, p in active_versions], p=normalized_percentages)\n", - " \n", - " # Find the cost during this usage\n", - " cost_per_token = cost_schedule[usage_date.date()]\n", - " \n", - " # Find the average latency during this usage\n", - " latency = latency_schedule[usage_date.date()]\n", - " latency *= (0.9 + random.random() *.2)\n", - " \n", - " prompt = ' '.join(random.sample(lines, 10)) # Increase prompt size\n", - " completion = generate_completion(prompt)\n", - " prompt_tokens = len(prompt.split())\n", - " completion_tokens = len(completion.split())\n", - " api_cost = (prompt_tokens + completion_tokens) * cost_per_token\n", - "\n", - " data.append([usage_date, user, version, prompt, completion, \n", - " prompt_tokens, completion_tokens, api_cost, latency])\n", - " \n", - " usage_date += increment\n", - "\n", - "df = pd.DataFrame(data, columns=['timestamp', 'username', 'model_version', 'prompt', 'completion', \n", - " 'prompt_tokens', 'completion_tokens', 'api_cost', 'latency'])\n", - "\n", - "predictions = weave.save(dataframe_to_arrow(df), 'predictions')\n", - "predictions" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "57fc86e0", - "metadata": {}, - "outputs": [], - "source": [ - "predictions = weave.legacy.ops.get(\"local-artifact:///predictions:latest/obj\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8049b6dd", - "metadata": {}, - "outputs": [], - "source": [ - "weave.legacy.panels.Board(\n", - " vars={\n", - " #'all_preds': predictions,\n", - " 'x_max': weave.legacy.ops.date_parse(str(end_date)),\n", - " 'x_min': lambda x_max: x_max - weave.legacy.ops.days(5),\n", - " 'predictions_query': weave.legacy.panels.Query(\n", - " predictions,\n", - " conditions=[\n", - " lambda query_input: weave.legacy.panels.QueryCondition(\n", - " expression=query_input['username'],\n", - " editor=weave.legacy.panels.SelectEditor(\n", - " choices=query_input['username']\n", - " )\n", - " )\n", - " ]),\n", - " 'predictions': lambda predictions_query: predictions_query.selected()\n", - " },\n", - " panels=[\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", - " predictions,\n", - " x=lambda item: item[\"timestamp\"],\n", - " label=lambda item: item[\"model_version\"],\n", - " agg=lambda preds: preds.count(),\n", - " min_x=x_min,\n", - " max_x=x_max,\n", - " mark=\"bar\",\n", - " axis_labels={\"y\": \"num_preds\"},\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=12, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", - " predictions,\n", - " x=lambda item: item[\"timestamp\"],\n", - " label=lambda item: item[\"username\"],\n", - " agg=lambda preds: preds.count(),\n", - " min_x=x_min,\n", - " max_x=x_max,\n", - " mark=\"bar\",\n", - " axis_labels={\"y\": \"num_preds\"},\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=12, y=0, w=12, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", - " predictions,\n", - " x=lambda item: item[\"timestamp\"],\n", - " #label=lambda item: item[\"model_version\"],\n", - " agg=lambda preds: preds[\"api_cost\"].sum(),\n", - " min_x=x_min,\n", - " max_x=x_max,\n", - " mark=\"line\",\n", - " axis_labels={\"y\": \"api_cost\"},\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=6, w=8, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", - " predictions,\n", - " x=lambda item: item[\"timestamp\"],\n", - " #label=lambda item: item[\"model_version\"],\n", - " agg=lambda preds: preds[\"prompt_tokens\"].sum() + preds['completion_tokens'].sum(),\n", - " min_x=x_min,\n", - " max_x=x_max,\n", - " mark=\"line\",\n", - " axis_labels={\"y\": \"total_tokens\"},\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=8, y=6, w=8, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, x_min, x_max: wandb.TimeSeries(\n", - " predictions,\n", - " x=lambda item: item[\"timestamp\"],\n", - " #label=lambda item: item[\"model_version\"],\n", - " agg=lambda preds: preds[\"latency\"].avg(),\n", - " min_x=x_min,\n", - " max_x=x_max,\n", - " mark=\"line\",\n", - " axis_labels={\"y\": \"avg_latency\"},\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=16, y=6, w=8, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, x_min, x_max: wandb.Distribution(\n", - " predictions,\n", - " value_fn=lambda pred: pred['api_cost'],\n", - " bin_size=0.2\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=12, w=8, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, x_min, x_max: wandb.Distribution(\n", - " predictions,\n", - " value_fn=lambda pred: pred['prompt_tokens'] + pred['completion_tokens'],\n", - " bin_size=25\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=8, y=12, w=8, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, x_min, x_max: wandb.Distribution(\n", - " predictions,\n", - " value_fn=lambda pred: pred['latency'],\n", - " bin_size=0.05\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=16, y=12, w=8, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions: predictions,\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=18, w=24, h=12)\n", - " )\n", - " ]\n", - ")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/Multiple Y Axes.ipynb b/weave/legacy/examples/experimental/skip_test/Multiple Y Axes.ipynb index ef49ac5d28e..a3d9af12a7c 100644 --- a/weave/legacy/examples/experimental/skip_test/Multiple Y Axes.ipynb +++ b/weave/legacy/examples/experimental/skip_test/Multiple Y Axes.ipynb @@ -1,184 +1,184 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "0903a3ef", - "metadata": {}, - "source": [ - "## Using this notebook to develop multiple y axes on Panel Plot" - ] + "cells": [ + { + "cell_type": "markdown", + "id": "0903a3ef", + "metadata": {}, + "source": [ + "## Using this notebook to develop multiple y axes on Panel Plot" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f6c524b9", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "import math\n", + "import random\n", + "weave.use_frontend_devmode()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f8d46616", + "metadata": {}, + "outputs": [], + "source": [ + "# PanelPlot supports multiple Y axes. Create a table with one row per series, with lists of x and y values.\n", + "data = []\n", + "for run in ['a1', 'a2', 'b1', 'b2', 'b3', 'c1']:\n", + " for x in range(100):\n", + " data.append({\n", + " 'group': run[0],\n", + " 'run': run,\n", + " 'step': x,\n", + " 'acc': random.random(),\n", + " })\n", + " \n", + "plot = weave.legacy.weave.panels.Plot(data)\n", + "plot.set_x(lambda row: row['step'])\n", + "plot.set_y(lambda row: row['acc'])\n", + "plot.set_label(lambda row: row['run'])\n", + "weave.show(plot)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3d97c0fd", + "metadata": {}, + "outputs": [], + "source": [ + "# PanelPlot supports multiple Y axes. Create a table with one row per series, with lists of x and y values.\n", + "data = []\n", + "xs = [i / 1000.0 for i in range(0, 1000)]\n", + "for series in range(3):\n", + " data.append({\n", + " 'key': 'y%s' % series,\n", + " 'x': xs,\n", + " 'y': [math.sin(10 * x / (series+1)) for x in xs]\n", + " })\n", + "plot = weave.legacy.weave.panels.Plot(data)\n", + "plot.set_x(lambda row: row['x'])\n", + "plot.set_y(lambda row: row['y'])\n", + "plot.set_label(lambda row: row['key'])\n", + "weave.show(plot)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "00fdefb5", + "metadata": {}, + "outputs": [], + "source": [ + "# Or you can unnest the data yourself (one row per point)\n", + "data = []\n", + "xs = [i / 1000.0 for i in range(0, 1000)]\n", + "for series in range(3):\n", + " for x in xs:\n", + " data.append({\n", + " 'key': 'y%s' % series,\n", + " 'x': x,\n", + " 'y': math.sin(10 * x / (series+1))\n", + " })\n", + "plot = weave.legacy.weave.panels.Plot(data)\n", + "plot.set_x(lambda row: row['x'])\n", + "plot.set_y(lambda row: row['y'])\n", + "plot.set_label(lambda row: row['key'])\n", + "plot.set_mark('line')\n", + "weave.show(plot)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5f9b0741", + "metadata": {}, + "outputs": [], + "source": [ + "# If your series are column-oriented, you can use df.melt to orient the data to work with PanelPlot\n", + "\n", + "import pandas as pd\n", + "df = pd.DataFrame()\n", + "df['x'] = [i / 1000.0 for i in range(0, 1000)]\n", + "df['y1'] = df['x'].map(lambda x: math.sin(10 * x / 1))\n", + "df['y2'] = df['x'].map(lambda x: math.sin(10 * x / 2))\n", + "df['y3'] = df['x'].map(lambda x: math.sin(10 * x / 3))\n", + "\n", + "# df.melt converts to a table with three columns: x, series, y\n", + "df = df.melt(id_vars=['x'], value_vars=['y1', 'y2', 'y3'], var_name='series', value_name='y')\n", + "\n", + "multiple_y = df.to_dict('records')\n", + "plot = weave.legacy.weave.panels.Plot(multiple_y)\n", + "plot.set_x(lambda row: row['x'])\n", + "plot.set_y(lambda row: row['y'])\n", + "plot.set_label(lambda row: row['series'])\n", + "plot.set_mark('line')\n", + "weave.show(plot)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "07752656", + "metadata": {}, + "outputs": [], + "source": [ + "# Or, leave the table in columnar form, and return arrays of the values you want for each series for PanelPlot\n", + "# x and label dimensions.\n", + "\n", + "# This relies on changes in this branch.\n", + "\n", + "# Note ExpressionEditor doesn't render list literals so it looks weird in the panel config. And we'll probably want\n", + "# to make the config editor more helpful, so that you choose labels along-side each y axis choice, or so that\n", + "# if you return a dict for Y we use the keys as the labels.\n", + "\n", + "import pandas as pd\n", + "df = pd.DataFrame()\n", + "df['x'] = [i / 100.0 for i in range(0, 100)]\n", + "df['x1'] = [i / 100.0 for i in range(0, 100)]\n", + "df['x2'] = [2 * i / 100.0 for i in range(0, 100)]\n", + "df['x3'] = [3 * i / 100.0 for i in range(0, 100)]\n", + "df['y1'] = df['x'].map(lambda x: math.sin(10 * x / 1))\n", + "df['y2'] = df['x'].map(lambda x: math.sin(10 * x / 2))\n", + "df['y3'] = df['x'].map(lambda x: math.sin(10 * x / 3))\n", + "multiple_y = df.to_dict('records')\n", + "\n", + "plot = weave.legacy.weave.panels.Plot(multiple_y)\n", + "plot.set_x(lambda row: row['x'])\n", + "\n", + "# Return lists for y and label\n", + "plot.set_y(lambda row: [row['y1'], row['y2'], row['y3']])\n", + "plot.set_label(lambda row: ['y1', 'y2', 'y3'])\n", + "plot.set_mark('line')\n", + "weave.show(plot)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "f6c524b9", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "import math\n", - "import random\n", - "weave.use_frontend_devmode()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f8d46616", - "metadata": {}, - "outputs": [], - "source": [ - "# PanelPlot supports multiple Y axes. Create a table with one row per series, with lists of x and y values.\n", - "data = []\n", - "for run in ['a1', 'a2', 'b1', 'b2', 'b3', 'c1']:\n", - " for x in range(100):\n", - " data.append({\n", - " 'group': run[0],\n", - " 'run': run,\n", - " 'step': x,\n", - " 'acc': random.random(),\n", - " })\n", - " \n", - "plot = weave.legacy.panels.Plot(data)\n", - "plot.set_x(lambda row: row['step'])\n", - "plot.set_y(lambda row: row['acc'])\n", - "plot.set_label(lambda row: row['run'])\n", - "weave.show(plot)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3d97c0fd", - "metadata": {}, - "outputs": [], - "source": [ - "# PanelPlot supports multiple Y axes. Create a table with one row per series, with lists of x and y values.\n", - "data = []\n", - "xs = [i / 1000.0 for i in range(0, 1000)]\n", - "for series in range(3):\n", - " data.append({\n", - " 'key': 'y%s' % series,\n", - " 'x': xs,\n", - " 'y': [math.sin(10 * x / (series+1)) for x in xs]\n", - " })\n", - "plot = weave.legacy.panels.Plot(data)\n", - "plot.set_x(lambda row: row['x'])\n", - "plot.set_y(lambda row: row['y'])\n", - "plot.set_label(lambda row: row['key'])\n", - "weave.show(plot)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "00fdefb5", - "metadata": {}, - "outputs": [], - "source": [ - "# Or you can unnest the data yourself (one row per point)\n", - "data = []\n", - "xs = [i / 1000.0 for i in range(0, 1000)]\n", - "for series in range(3):\n", - " for x in xs:\n", - " data.append({\n", - " 'key': 'y%s' % series,\n", - " 'x': x,\n", - " 'y': math.sin(10 * x / (series+1))\n", - " })\n", - "plot = weave.legacy.panels.Plot(data)\n", - "plot.set_x(lambda row: row['x'])\n", - "plot.set_y(lambda row: row['y'])\n", - "plot.set_label(lambda row: row['key'])\n", - "plot.set_mark('line')\n", - "weave.show(plot)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5f9b0741", - "metadata": {}, - "outputs": [], - "source": [ - "# If your series are column-oriented, you can use df.melt to orient the data to work with PanelPlot\n", - "\n", - "import pandas as pd\n", - "df = pd.DataFrame()\n", - "df['x'] = [i / 1000.0 for i in range(0, 1000)]\n", - "df['y1'] = df['x'].map(lambda x: math.sin(10 * x / 1))\n", - "df['y2'] = df['x'].map(lambda x: math.sin(10 * x / 2))\n", - "df['y3'] = df['x'].map(lambda x: math.sin(10 * x / 3))\n", - "\n", - "# df.melt converts to a table with three columns: x, series, y\n", - "df = df.melt(id_vars=['x'], value_vars=['y1', 'y2', 'y3'], var_name='series', value_name='y')\n", - "\n", - "multiple_y = df.to_dict('records')\n", - "plot = weave.legacy.panels.Plot(multiple_y)\n", - "plot.set_x(lambda row: row['x'])\n", - "plot.set_y(lambda row: row['y'])\n", - "plot.set_label(lambda row: row['series'])\n", - "plot.set_mark('line')\n", - "weave.show(plot)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "07752656", - "metadata": {}, - "outputs": [], - "source": [ - "# Or, leave the table in columnar form, and return arrays of the values you want for each series for PanelPlot\n", - "# x and label dimensions.\n", - "\n", - "# This relies on changes in this branch.\n", - "\n", - "# Note ExpressionEditor doesn't render list literals so it looks weird in the panel config. And we'll probably want\n", - "# to make the config editor more helpful, so that you choose labels along-side each y axis choice, or so that\n", - "# if you return a dict for Y we use the keys as the labels.\n", - "\n", - "import pandas as pd\n", - "df = pd.DataFrame()\n", - "df['x'] = [i / 100.0 for i in range(0, 100)]\n", - "df['x1'] = [i / 100.0 for i in range(0, 100)]\n", - "df['x2'] = [2 * i / 100.0 for i in range(0, 100)]\n", - "df['x3'] = [3 * i / 100.0 for i in range(0, 100)]\n", - "df['y1'] = df['x'].map(lambda x: math.sin(10 * x / 1))\n", - "df['y2'] = df['x'].map(lambda x: math.sin(10 * x / 2))\n", - "df['y3'] = df['x'].map(lambda x: math.sin(10 * x / 3))\n", - "multiple_y = df.to_dict('records')\n", - "\n", - "plot = weave.legacy.panels.Plot(multiple_y)\n", - "plot.set_x(lambda row: row['x'])\n", - "\n", - "# Return lists for y and label\n", - "plot.set_y(lambda row: [row['y1'], row['y2'], row['y3']])\n", - "plot.set_label(lambda row: ['y1', 'y2', 'y3'])\n", - "plot.set_mark('line')\n", - "weave.show(plot)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/Mutation - Code Editor.ipynb b/weave/legacy/examples/experimental/skip_test/Mutation - Code Editor.ipynb index cd57106914e..937f2c0a27c 100644 --- a/weave/legacy/examples/experimental/skip_test/Mutation - Code Editor.ipynb +++ b/weave/legacy/examples/experimental/skip_test/Mutation - Code Editor.ipynb @@ -1,55 +1,55 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "b856b674", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "weave.use_frontend_devmode()\n", - "weave.capture_weave_server_logs()" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "b856b674", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "weave.use_frontend_devmode()\n", + "weave.capture_weave_server_logs()" + ] + }, + { + "cell_type": "markdown", + "id": "e056ac84", + "metadata": {}, + "source": [ + "Run the cell below, then click the gear icon to change to TextEditor. Your changes will be reflected in train.py" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c71000cc", + "metadata": {}, + "outputs": [], + "source": [ + "weave.legacy.weave.ops.local_path('../weave/testdata/train.py')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "markdown", - "id": "e056ac84", - "metadata": {}, - "source": [ - "Run the cell below, then click the gear icon to change to TextEditor. Your changes will be reflected in train.py" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c71000cc", - "metadata": {}, - "outputs": [], - "source": [ - "weave.legacy.ops.local_path('../weave/testdata/train.py')" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/Mutation.ipynb b/weave/legacy/examples/experimental/skip_test/Mutation.ipynb index a6c5bbf6796..454d25c6e5f 100644 --- a/weave/legacy/examples/experimental/skip_test/Mutation.ipynb +++ b/weave/legacy/examples/experimental/skip_test/Mutation.ipynb @@ -1,54 +1,54 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "b856b674", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "weave.capture_weave_server_logs()" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "b856b674", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "weave.capture_weave_server_logs()" + ] + }, + { + "cell_type": "markdown", + "id": "e056ac84", + "metadata": {}, + "source": [ + "Change the \"name\" column in the panel below to StringEditor, then click a cell to edit the underlying csv." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c71000cc", + "metadata": {}, + "outputs": [], + "source": [ + "weave.legacy.weave.ops.local_path('../weave/testdata/cereal.csv').readcsv" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "markdown", - "id": "e056ac84", - "metadata": {}, - "source": [ - "Change the \"name\" column in the panel below to StringEditor, then click a cell to edit the underlying csv." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c71000cc", - "metadata": {}, - "outputs": [], - "source": [ - "weave.legacy.ops.local_path('../weave/testdata/cereal.csv').readcsv" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/OpenAI.ipynb b/weave/legacy/examples/experimental/skip_test/OpenAI.ipynb index 76e86685c1e..dae4d5b5262 100644 --- a/weave/legacy/examples/experimental/skip_test/OpenAI.ipynb +++ b/weave/legacy/examples/experimental/skip_test/OpenAI.ipynb @@ -1,106 +1,106 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "94f2344d", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "from weave.legacy.ecosystem import openai" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "94f2344d", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "from weave.legacy.weave.ecosystem import openai" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1abed8ce", + "metadata": {}, + "outputs": [], + "source": [ + "# Construct a dataset, we'll see if GPT-3 can do simple arithmetic\n", + "data = []\n", + "for i in range (101):\n", + " a = i\n", + " b = i % 9\n", + " r = a + b\n", + " data.append({'id': i, 'prompt': '%s + %s =' % (a, b), 'completion': ' %s' % r})\n", + "data = weave.save(data, name='openai-dataset')\n", + "data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "348d63f0", + "metadata": {}, + "outputs": [], + "source": [ + "# Fine tune gpt-3 on our dataset.\n", + "\n", + "# Change this to \"openai.finetune_gpt3\" to run a real OpenAI fine-tune job\n", + "fine_tune = openai.finetune_gpt3_demo(data, {'n_epochs' : 2})\n", + "fine_tune" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fe3d0872", + "metadata": {}, + "outputs": [], + "source": [ + "model = fine_tune.model()\n", + "model = weave.save(model, name='openai-model')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7d656075", + "metadata": {}, + "outputs": [], + "source": [ + "# Show all the models we've trained, and \n", + "for version in weave.versions(model):\n", + " print(weave.expr(version))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "89bebbff", + "metadata": {}, + "outputs": [], + "source": [ + "# make some predictions using our new model\n", + "\n", + "panel = weave.legacy.weave.panels.Table(['1 + 9 =', '2 + 14 ='])\n", + "panel.table_query.add_column(lambda row: row)\n", + "panel.table_query.add_column(lambda row: model.complete(row)['choices'][0]['text'])\n", + "weave.show(panel)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "1abed8ce", - "metadata": {}, - "outputs": [], - "source": [ - "# Construct a dataset, we'll see if GPT-3 can do simple arithmetic\n", - "data = []\n", - "for i in range (101):\n", - " a = i\n", - " b = i % 9\n", - " r = a + b\n", - " data.append({'id': i, 'prompt': '%s + %s =' % (a, b), 'completion': ' %s' % r})\n", - "data = weave.save(data, name='openai-dataset')\n", - "data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "348d63f0", - "metadata": {}, - "outputs": [], - "source": [ - "# Fine tune gpt-3 on our dataset.\n", - "\n", - "# Change this to \"openai.finetune_gpt3\" to run a real OpenAI fine-tune job\n", - "fine_tune = openai.finetune_gpt3_demo(data, {'n_epochs' : 2})\n", - "fine_tune" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "fe3d0872", - "metadata": {}, - "outputs": [], - "source": [ - "model = fine_tune.model()\n", - "model = weave.save(model, name='openai-model')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7d656075", - "metadata": {}, - "outputs": [], - "source": [ - "# Show all the models we've trained, and \n", - "for version in weave.versions(model):\n", - " print(weave.expr(version))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "89bebbff", - "metadata": {}, - "outputs": [], - "source": [ - "# make some predictions using our new model\n", - "\n", - "panel = weave.legacy.panels.Table(['1 + 9 =', '2 + 14 ='])\n", - "panel.table_query.add_column(lambda row: row)\n", - "panel.table_query.add_column(lambda row: model.complete(row)['choices'][0]['text'])\n", - "weave.show(panel)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/Oxford-IIIT Pet Dataset.ipynb b/weave/legacy/examples/experimental/skip_test/Oxford-IIIT Pet Dataset.ipynb index 4a0836dccac..5b84ccbda13 100644 --- a/weave/legacy/examples/experimental/skip_test/Oxford-IIIT Pet Dataset.ipynb +++ b/weave/legacy/examples/experimental/skip_test/Oxford-IIIT Pet Dataset.ipynb @@ -1,115 +1,115 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "2cfb0934", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "weave.use_frontend_devmode()" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "2cfb0934", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "weave.use_frontend_devmode()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b81fda7c", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "im_names = os.listdir('/Users/shawn/datasets/oxford-iiit-pet-dataset/images')\n", + "breeds = set(i.rsplit('_', 1)[0] for i in im_names)\n", + "#sorted(breeds)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5e3925df", + "metadata": {}, + "outputs": [], + "source": [ + "import typing\n", + "type(typing.Optional[int])\n", + "type(typing._UnionGenericAlias)\n", + "# isinstance(typing.Optional, typing._SpecialForm)\n", + "# typing._SpecialForm.__class__" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9d20c10d", + "metadata": {}, + "outputs": [], + "source": [ + "#weave.legacy.weave.ops.local_path('/Users/shawn/datasets')\n", + "# :(, broken right now" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7f668d48", + "metadata": {}, + "outputs": [], + "source": [ + "from weave.legacy.weave.ecosystem.shawn import petdataset\n", + "\n", + "data = petdataset.petdataset('/Users/shawn/datasets/oxford-iiit-pet-dataset')\n", + "#data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "981fc71f", + "metadata": {}, + "outputs": [], + "source": [ + "from weave.legacy.weave.ecosystem import wandb\n", + "wandb.MultiDistribution(data, value_fn=lambda item: item['breed'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b123d4f9", + "metadata": {}, + "outputs": [], + "source": [ + "# A PanelPlot only histogram\n", + "plot = weave.legacy.weave.panels.Plot(\n", + " data,\n", + " y=lambda item: item['breed'],\n", + " groupby_y=True,\n", + " x=lambda group: group.count(),\n", + " mark='bar')\n", + "#plot" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "b81fda7c", - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "im_names = os.listdir('/Users/shawn/datasets/oxford-iiit-pet-dataset/images')\n", - "breeds = set(i.rsplit('_', 1)[0] for i in im_names)\n", - "#sorted(breeds)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5e3925df", - "metadata": {}, - "outputs": [], - "source": [ - "import typing\n", - "type(typing.Optional[int])\n", - "type(typing._UnionGenericAlias)\n", - "# isinstance(typing.Optional, typing._SpecialForm)\n", - "# typing._SpecialForm.__class__" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9d20c10d", - "metadata": {}, - "outputs": [], - "source": [ - "#weave.legacy.ops.local_path('/Users/shawn/datasets')\n", - "# :(, broken right now" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7f668d48", - "metadata": {}, - "outputs": [], - "source": [ - "from weave.legacy.ecosystem.shawn import petdataset\n", - "\n", - "data = petdataset.petdataset('/Users/shawn/datasets/oxford-iiit-pet-dataset')\n", - "#data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "981fc71f", - "metadata": {}, - "outputs": [], - "source": [ - "from weave.legacy.ecosystem import wandb\n", - "wandb.MultiDistribution(data, value_fn=lambda item: item['breed'])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b123d4f9", - "metadata": {}, - "outputs": [], - "source": [ - "# A PanelPlot only histogram\n", - "plot = weave.legacy.panels.Plot(\n", - " data,\n", - " y=lambda item: item['breed'],\n", - " groupby_y=True,\n", - " x=lambda group: group.count(),\n", - " mark='bar')\n", - "#plot" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/Performance profiling.ipynb b/weave/legacy/examples/experimental/skip_test/Performance profiling.ipynb index d128c91d462..c69c3f119d6 100644 --- a/weave/legacy/examples/experimental/skip_test/Performance profiling.ipynb +++ b/weave/legacy/examples/experimental/skip_test/Performance profiling.ipynb @@ -1,153 +1,153 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "c87095b6", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "import numpy as np\n", - "import pyarrow as pa\n", - "import pyarrow.parquet as pq\n", - "\n", - "!rm -rf /tmp/local-artifacts\n", - "\n", - "t = pa.table({d: list(range(400)) * 1000 for d in \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"})\n", - "weave_t = weave.legacy.ops.ArrowWeaveList(t)\n", - "weave.use(weave_t.groupby(lambda x: x['A']).map(lambda row: row.key()))" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "c87095b6", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "import numpy as np\n", + "import pyarrow as pa\n", + "import pyarrow.parquet as pq\n", + "\n", + "!rm -rf /tmp/local-artifacts\n", + "\n", + "t = pa.table({d: list(range(400)) * 1000 for d in \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"})\n", + "weave_t = weave.legacy.weave.ops.ArrowWeaveList(t)\n", + "weave.use(weave_t.groupby(lambda x: x['A']).map(lambda row: row.key()))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3a7726e4", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import cProfile\n", + "import weave\n", + "from weave.legacy.weave import storage\n", + "import random\n", + "import time\n", + "import pyarrow as pa\n", + "from PIL import Image\n", + "\n", + "def create_arrow_data(n_rows):\n", + " inner_count = int(n_rows / 25)\n", + " rotates = []\n", + " shears = []\n", + " x = []\n", + " y = []\n", + " random.seed(0)\n", + " for rotate in range(5):\n", + " for shear in range(5):\n", + " for i in range(inner_count):\n", + " rotates.append(rotate)\n", + " shears.append(shear)\n", + " x.append(random.choice(['a', 'b', 'c']))\n", + " y.append(random.randrange(10))\n", + " table = pa.table({\n", + " 'rotate': rotates,\n", + " 'shear': shears,\n", + " 'x': x,\n", + " 'y': y,\n", + " })\n", + " table_list = weave.legacy.weave.ops.ArrowTableList(table)\n", + "\n", + " return storage.save(table_list)\n", + "\n", + "def create_data(n_rows):\n", + " inner_count = int(n_rows / 25)\n", + " ims = []\n", + " base_im = Image.linear_gradient(\"L\")\n", + " random.seed(0)\n", + " for rotate in range(5):\n", + " for shear in range(5):\n", + " for i in range(inner_count):\n", + " ims.append(\n", + " {\n", + " \"rotate\": rotate,\n", + " \"shear\": shear,\n", + " \"y\": random.choice([\"a\", \"b\", \"c\"]),\n", + " \"x\": random.randrange(10),\n", + "# \"image\": base_im.rotate(rotate * 4).transform(\n", + "# (256, 256),\n", + "# Image.AFFINE,\n", + "# (1, shear / 10, 0, 0, 1, 0),\n", + "# Image.BICUBIC,\n", + "# ),\n", + " }\n", + " )\n", + "\n", + " return storage.save(ims)\n", + "\n", + "\n", + "def run(ref):\n", + "# node = (\n", + "# weave.get(ref)\n", + "# .groupby(lambda row: weave.legacy.weave.ops.dict_(rotate=row[\"rotate\"], shear=row[\"shear\"]))\n", + "# .map(lambda row: row.groupby(lambda row: row[\"y\"]))\n", + "# .dropna()\n", + "# .count()\n", + "# )\n", + " node = (\n", + " weave.get(ref)\n", + " # .map(lambda row: row['rotate'] + 1)\n", + " # .map(lambda row: row + 9)\n", + " .groupby(lambda row: weave.legacy.weave.ops.dict_(rotate=row[\"rotate\"], shear=row[\"shear\"]))\n", + " [1]\n", + " .count()\n", + " )\n", + " result = weave.use(node)\n", + " print('Run result: %s' % result)\n", + "\n", + "\n", + "os.system(\"rm -rf /tmp/local-artifacts/*\")\n", + "ref = create_data(100000)\n", + "print(\"Data ref: \", ref)\n", + "start_time = time.time()\n", + "cProfile.run('run(\"%s\")' % ref, \"profile_stats\")\n", + "print('Run time: %ss' % (time.time() - start_time))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "44f3f7ba", + "metadata": {}, + "outputs": [], + "source": [ + "import pstats\n", + "from pstats import SortKey\n", + "p = pstats.Stats('profile_stats')\n", + "#p.strip_dirs().sort_stats(SortKey.CUMULATIVE).print_stats()\n", + "p.strip_dirs().sort_stats(SortKey.CUMULATIVE).print_callers('type_of')\n", + "#p.strip_dirs().sort_stats(SortKey.TIME).print_stats()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "3a7726e4", - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "import cProfile\n", - "import weave\n", - "from weave.legacy import storage\n", - "import random\n", - "import time\n", - "import pyarrow as pa\n", - "from PIL import Image\n", - "\n", - "def create_arrow_data(n_rows):\n", - " inner_count = int(n_rows / 25)\n", - " rotates = []\n", - " shears = []\n", - " x = []\n", - " y = []\n", - " random.seed(0)\n", - " for rotate in range(5):\n", - " for shear in range(5):\n", - " for i in range(inner_count):\n", - " rotates.append(rotate)\n", - " shears.append(shear)\n", - " x.append(random.choice(['a', 'b', 'c']))\n", - " y.append(random.randrange(10))\n", - " table = pa.table({\n", - " 'rotate': rotates,\n", - " 'shear': shears,\n", - " 'x': x,\n", - " 'y': y,\n", - " })\n", - " table_list = weave.legacy.ops.ArrowTableList(table)\n", - "\n", - " return storage.save(table_list)\n", - "\n", - "def create_data(n_rows):\n", - " inner_count = int(n_rows / 25)\n", - " ims = []\n", - " base_im = Image.linear_gradient(\"L\")\n", - " random.seed(0)\n", - " for rotate in range(5):\n", - " for shear in range(5):\n", - " for i in range(inner_count):\n", - " ims.append(\n", - " {\n", - " \"rotate\": rotate,\n", - " \"shear\": shear,\n", - " \"y\": random.choice([\"a\", \"b\", \"c\"]),\n", - " \"x\": random.randrange(10),\n", - "# \"image\": base_im.rotate(rotate * 4).transform(\n", - "# (256, 256),\n", - "# Image.AFFINE,\n", - "# (1, shear / 10, 0, 0, 1, 0),\n", - "# Image.BICUBIC,\n", - "# ),\n", - " }\n", - " )\n", - "\n", - " return storage.save(ims)\n", - "\n", - "\n", - "def run(ref):\n", - "# node = (\n", - "# weave.get(ref)\n", - "# .groupby(lambda row: weave.legacy.ops.dict_(rotate=row[\"rotate\"], shear=row[\"shear\"]))\n", - "# .map(lambda row: row.groupby(lambda row: row[\"y\"]))\n", - "# .dropna()\n", - "# .count()\n", - "# )\n", - " node = (\n", - " weave.get(ref)\n", - " # .map(lambda row: row['rotate'] + 1)\n", - " # .map(lambda row: row + 9)\n", - " .groupby(lambda row: weave.legacy.ops.dict_(rotate=row[\"rotate\"], shear=row[\"shear\"]))\n", - " [1]\n", - " .count()\n", - " )\n", - " result = weave.use(node)\n", - " print('Run result: %s' % result)\n", - "\n", - "\n", - "os.system(\"rm -rf /tmp/local-artifacts/*\")\n", - "ref = create_data(100000)\n", - "print(\"Data ref: \", ref)\n", - "start_time = time.time()\n", - "cProfile.run('run(\"%s\")' % ref, \"profile_stats\")\n", - "print('Run time: %ss' % (time.time() - start_time))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "44f3f7ba", - "metadata": {}, - "outputs": [], - "source": [ - "import pstats\n", - "from pstats import SortKey\n", - "p = pstats.Stats('profile_stats')\n", - "#p.strip_dirs().sort_stats(SortKey.CUMULATIVE).print_stats()\n", - "p.strip_dirs().sort_stats(SortKey.CUMULATIVE).print_callers('type_of')\n", - "#p.strip_dirs().sort_stats(SortKey.TIME).print_stats()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/ProdMonStreamTableIntro.ipynb b/weave/legacy/examples/experimental/skip_test/ProdMonStreamTableIntro.ipynb index 878d9804b6e..f8233308156 100644 --- a/weave/legacy/examples/experimental/skip_test/ProdMonStreamTableIntro.ipynb +++ b/weave/legacy/examples/experimental/skip_test/ProdMonStreamTableIntro.ipynb @@ -1,135 +1,135 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "9617c234", - "metadata": {}, - "source": [ - "# StreamTable API" - ] + "cells": [ + { + "cell_type": "markdown", + "id": "9617c234", + "metadata": {}, + "source": [ + "# StreamTable API" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "307ad3b7", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "weave.use_frontend_devmode()\n", + "from weave.legacy.weave.monitoring import StreamTable\n", + "import PIL\n", + "import numpy as np\n", + "\n", + "def make_image():\n", + " imarray = np.random.rand(100, 100, 3) * 255\n", + " return PIL.Image.fromarray(imarray.astype(\"uint8\")).convert(\"RGBA\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8c7b6c63", + "metadata": {}, + "outputs": [], + "source": [ + "table = StreamTable(\"pm_demo_all_2\", entity_name=\"timssweeney\", project_name=\"prodmon\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "643f46e3", + "metadata": {}, + "outputs": [], + "source": [ + "for _ in range(10):\n", + " table.log({\n", + " 'number': 1, \n", + " 'string': 'hello', \n", + " 'bool': True, \n", + " 'nested': {'data': 5}, \n", + " 'lists': list(range(10)), \n", + " 'custom': make_image()})\n", + "table" + ] + }, + { + "cell_type": "markdown", + "id": "56c50afb", + "metadata": {}, + "source": [ + "# Monitor Decorator" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e7db9358", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.agents import load_tools\n", + "from langchain.agents import initialize_agent\n", + "from langchain.agents import AgentType\n", + "from langchain.llms import OpenAI\n", + "\n", + "llm = OpenAI(temperature=0)\n", + "tools = load_tools([\"llm-math\"], llm=llm)\n", + "agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "90aba081", + "metadata": {}, + "outputs": [], + "source": [ + "from weave.legacy.weave.monitoring import monitor\n", + "\n", + "@monitor(entity_name=\"timssweeney\", project_name=\"prodmon\")\n", + "def ask_llm_calculator(prompt, question):\n", + " return agent.run(prompt + \" \" + question)\n", + "\n", + "\n", + "ask_llm_calculator(\n", + " \"Please accurately answer the following question:\", \n", + " \"Find the square root of 5.4.\"\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f49b9b31", + "metadata": {}, + "outputs": [], + "source": [ + "# This API will change\n", + "ask_llm_calculator._stream_table._stream_table.rows()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.8" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "307ad3b7", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "weave.use_frontend_devmode()\n", - "from weave.legacy.monitoring import StreamTable\n", - "import PIL\n", - "import numpy as np\n", - "\n", - "def make_image():\n", - " imarray = np.random.rand(100, 100, 3) * 255\n", - " return PIL.Image.fromarray(imarray.astype(\"uint8\")).convert(\"RGBA\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8c7b6c63", - "metadata": {}, - "outputs": [], - "source": [ - "table = StreamTable(\"pm_demo_all_2\", entity_name=\"timssweeney\", project_name=\"prodmon\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "643f46e3", - "metadata": {}, - "outputs": [], - "source": [ - "for _ in range(10):\n", - " table.log({\n", - " 'number': 1, \n", - " 'string': 'hello', \n", - " 'bool': True, \n", - " 'nested': {'data': 5}, \n", - " 'lists': list(range(10)), \n", - " 'custom': make_image()})\n", - "table" - ] - }, - { - "cell_type": "markdown", - "id": "56c50afb", - "metadata": {}, - "source": [ - "# Monitor Decorator" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e7db9358", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.agents import load_tools\n", - "from langchain.agents import initialize_agent\n", - "from langchain.agents import AgentType\n", - "from langchain.llms import OpenAI\n", - "\n", - "llm = OpenAI(temperature=0)\n", - "tools = load_tools([\"llm-math\"], llm=llm)\n", - "agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "90aba081", - "metadata": {}, - "outputs": [], - "source": [ - "from weave.legacy.monitoring import monitor\n", - "\n", - "@monitor(entity_name=\"timssweeney\", project_name=\"prodmon\")\n", - "def ask_llm_calculator(prompt, question):\n", - " return agent.run(prompt + \" \" + question)\n", - "\n", - "\n", - "ask_llm_calculator(\n", - " \"Please accurately answer the following question:\", \n", - " \"Find the square root of 5.4.\"\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f49b9b31", - "metadata": {}, - "outputs": [], - "source": [ - "# This API will change\n", - "ask_llm_calculator._stream_table._stream_table.rows()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.8" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/Shap.ipynb b/weave/legacy/examples/experimental/skip_test/Shap.ipynb index f0885b69e2d..5ca6196df6d 100644 --- a/weave/legacy/examples/experimental/skip_test/Shap.ipynb +++ b/weave/legacy/examples/experimental/skip_test/Shap.ipynb @@ -1,60 +1,60 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "eb58c451", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "from weave.legacy.ecosystem import shap" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "eb58c451", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "from weave.legacy.weave.ecosystem import shap" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bac8abef", + "metadata": {}, + "outputs": [], + "source": [ + "dataset = shap.ca_housing_dataset(1)\n", + "xy = shap.split_labels(dataset, 'MedHouseVal')\n", + "model = shap.xgboost_train(xy, {'learning_rate': 0.02})\n", + "\n", + "explain_res = model.shap_explain(xy['X'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aa726585", + "metadata": {}, + "outputs": [], + "source": [ + "explain_res.summary_plot()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "bac8abef", - "metadata": {}, - "outputs": [], - "source": [ - "dataset = shap.ca_housing_dataset(1)\n", - "xy = shap.split_labels(dataset, 'MedHouseVal')\n", - "model = shap.xgboost_train(xy, {'learning_rate': 0.02})\n", - "\n", - "explain_res = model.shap_explain(xy['X'])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "aa726585", - "metadata": {}, - "outputs": [], - "source": [ - "explain_res.summary_plot()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/StreamTables.ipynb b/weave/legacy/examples/experimental/skip_test/StreamTables.ipynb index e83bc3909b9..78e5331bec8 100644 --- a/weave/legacy/examples/experimental/skip_test/StreamTables.ipynb +++ b/weave/legacy/examples/experimental/skip_test/StreamTables.ipynb @@ -1,92 +1,92 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "1333d291", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "weave.use_frontend_devmode()" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "1333d291", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "weave.use_frontend_devmode()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "17a80a08", + "metadata": {}, + "outputs": [], + "source": [ + "from weave.legacy.weave.wandb_interface.wandb_stream_table import StreamTable" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "058fa5af", + "metadata": {}, + "outputs": [], + "source": [ + "import time\n", + "entity_name = \"timssweeney\"\n", + "project_name = \"stream_tables\"\n", + "run_name = \"tt\" + str(int(time.time()))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f0691851", + "metadata": {}, + "outputs": [], + "source": [ + "st = StreamTable(run_name, project_name, entity_name)\n", + "\n", + "for i in range(10):\n", + " st.log({'a': i})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e0a597a5", + "metadata": {}, + "outputs": [], + "source": [ + "st" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fb42732f", + "metadata": {}, + "outputs": [], + "source": [ + "weave.legacy.weave.ops.project(entity_name, project_name).run(run_name).history2()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.8" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "17a80a08", - "metadata": {}, - "outputs": [], - "source": [ - "from weave.legacy.wandb_interface.wandb_stream_table import StreamTable" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "058fa5af", - "metadata": {}, - "outputs": [], - "source": [ - "import time\n", - "entity_name = \"timssweeney\"\n", - "project_name = \"stream_tables\"\n", - "run_name = \"tt\" + str(int(time.time()))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f0691851", - "metadata": {}, - "outputs": [], - "source": [ - "st = StreamTable(run_name, project_name, entity_name)\n", - "\n", - "for i in range(10):\n", - " st.log({'a': i})" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e0a597a5", - "metadata": {}, - "outputs": [], - "source": [ - "st" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "fb42732f", - "metadata": {}, - "outputs": [], - "source": [ - "weave.legacy.ops.project(entity_name, project_name).run(run_name).history2()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.8" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/TimeSeries.ipynb b/weave/legacy/examples/experimental/skip_test/TimeSeries.ipynb index 251def88910..73e03f7079a 100644 --- a/weave/legacy/examples/experimental/skip_test/TimeSeries.ipynb +++ b/weave/legacy/examples/experimental/skip_test/TimeSeries.ipynb @@ -1,148 +1,148 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "e4885744", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "weave.use_frontend_devmode()\n", - "from weave.legacy import ops_arrow\n", - "from weave.legacy.ecosystem import wandb" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "e4885744", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "weave.use_frontend_devmode()\n", + "from weave.legacy.weave import ops_arrow\n", + "from weave.legacy.weave.ecosystem import wandb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "50e46344", + "metadata": {}, + "outputs": [], + "source": [ + "import datetime\n", + "import random\n", + "random.seed(1)\n", + "\n", + "min_x = datetime.datetime(2023, 3, 22, 11, 0, 0)\n", + "max_x = min_x + datetime.timedelta(hours=1)\n", + "\n", + "users = ['nick', 'shawn', 'stacey', 'tim', 'danny']\n", + "model_versions = ['v1', 'v2']\n", + "\n", + "num_requests = 10000\n", + "\n", + "def random_datetime_in_range() -> datetime.datetime:\n", + " min_timestamp = min_x.timestamp()\n", + " max_timestamp = max_x.timestamp()\n", + " random_timestamp = random.uniform(min_timestamp, max_timestamp)\n", + " return datetime.datetime.fromtimestamp(random_timestamp)\n", + "\n", + "def random_suggestion(n: int) -> str:\n", + " result = ''\n", + " for i in range(n):\n", + " result += random.choice('abcdefghijklmnopqrstuvwxyz')\n", + " return result\n", + "\n", + "\n", + "items = weave.save(\n", + " ops_arrow.to_arrow([\n", + " {\n", + " \"pred\": random_suggestion(7),\n", + " \"time\": random_datetime_in_range(),\n", + " \"user\": random.choice(users),\n", + " \"version\": random.choice(model_versions),\n", + " \"accepted\": random.choice([1, 1, 1, 0, 0]),\n", + " } \n", + " for _ in range(num_requests)\n", + " ])\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fb863d87", + "metadata": {}, + "outputs": [], + "source": [ + "panel = weave.legacy.weave.panels.Group(\n", + " items={\n", + " \"num_preds\": weave.legacy.weave.panels.LabeledItem(\n", + " label=\"Predictions by version over time\",\n", + " item=wandb.TimeSeries(\n", + " items,\n", + " x=lambda item: item[\"time\"],\n", + " label=lambda item: item[\"version\"],\n", + " agg=lambda preds: preds.count(),\n", + " min_x=min_x,\n", + " max_x=max_x,\n", + " mark=\"bar\",\n", + " axis_labels={\"y\": \"num_preds\"},\n", + " ),\n", + " ),\n", + " \"bottom_row\": weave.legacy.weave.panels.Group(\n", + " style=\"height: 400px;\",\n", + " preferHorizontal=True,\n", + " items={\n", + " \"preds_by_user\": weave.legacy.weave.panels.LabeledItem(\n", + " label=\"Predictions by user over time\",\n", + " item=wandb.TimeSeries(\n", + " items,\n", + " x=lambda item: item[\"time\"],\n", + " label=lambda item: item[\"user\"],\n", + " agg=lambda preds: preds.count(),\n", + " min_x=min_x,\n", + " max_x=max_x,\n", + " mark=\"bar\",\n", + " axis_labels={\"y\": \"num_preds\"},\n", + " ),\n", + " ),\n", + " \"acceptance_rate\": weave.legacy.weave.panels.LabeledItem(\n", + " label=\"Acceptance rate over time by version\",\n", + " item=wandb.TimeSeries(\n", + " items,\n", + " x=lambda item: item[\"time\"],\n", + " label=lambda item: item[\"version\"],\n", + " agg=lambda preds: preds[\"accepted\"].sum() / preds.count(),\n", + " min_x=min_x,\n", + " max_x=max_x,\n", + " mark=\"line\",\n", + " axis_labels={\"y\": \"acceptance_rate\"},\n", + " ),\n", + " ),\n", + " },\n", + " ),\n", + " }\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "35c7e310", + "metadata": {}, + "outputs": [], + "source": [ + "panel" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "50b1be3e", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "50e46344", - "metadata": {}, - "outputs": [], - "source": [ - "import datetime\n", - "import random\n", - "random.seed(1)\n", - "\n", - "min_x = datetime.datetime(2023, 3, 22, 11, 0, 0)\n", - "max_x = min_x + datetime.timedelta(hours=1)\n", - "\n", - "users = ['nick', 'shawn', 'stacey', 'tim', 'danny']\n", - "model_versions = ['v1', 'v2']\n", - "\n", - "num_requests = 10000\n", - "\n", - "def random_datetime_in_range() -> datetime.datetime:\n", - " min_timestamp = min_x.timestamp()\n", - " max_timestamp = max_x.timestamp()\n", - " random_timestamp = random.uniform(min_timestamp, max_timestamp)\n", - " return datetime.datetime.fromtimestamp(random_timestamp)\n", - "\n", - "def random_suggestion(n: int) -> str:\n", - " result = ''\n", - " for i in range(n):\n", - " result += random.choice('abcdefghijklmnopqrstuvwxyz')\n", - " return result\n", - "\n", - "\n", - "items = weave.save(\n", - " ops_arrow.to_arrow([\n", - " {\n", - " \"pred\": random_suggestion(7),\n", - " \"time\": random_datetime_in_range(),\n", - " \"user\": random.choice(users),\n", - " \"version\": random.choice(model_versions),\n", - " \"accepted\": random.choice([1, 1, 1, 0, 0]),\n", - " } \n", - " for _ in range(num_requests)\n", - " ])\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "fb863d87", - "metadata": {}, - "outputs": [], - "source": [ - "panel = weave.legacy.panels.Group(\n", - " items={\n", - " \"num_preds\": weave.legacy.panels.LabeledItem(\n", - " label=\"Predictions by version over time\",\n", - " item=wandb.TimeSeries(\n", - " items,\n", - " x=lambda item: item[\"time\"],\n", - " label=lambda item: item[\"version\"],\n", - " agg=lambda preds: preds.count(),\n", - " min_x=min_x,\n", - " max_x=max_x,\n", - " mark=\"bar\",\n", - " axis_labels={\"y\": \"num_preds\"},\n", - " ),\n", - " ),\n", - " \"bottom_row\": weave.legacy.panels.Group(\n", - " style=\"height: 400px;\",\n", - " preferHorizontal=True,\n", - " items={\n", - " \"preds_by_user\": weave.legacy.panels.LabeledItem(\n", - " label=\"Predictions by user over time\",\n", - " item=wandb.TimeSeries(\n", - " items,\n", - " x=lambda item: item[\"time\"],\n", - " label=lambda item: item[\"user\"],\n", - " agg=lambda preds: preds.count(),\n", - " min_x=min_x,\n", - " max_x=max_x,\n", - " mark=\"bar\",\n", - " axis_labels={\"y\": \"num_preds\"},\n", - " ),\n", - " ),\n", - " \"acceptance_rate\": weave.legacy.panels.LabeledItem(\n", - " label=\"Acceptance rate over time by version\",\n", - " item=wandb.TimeSeries(\n", - " items,\n", - " x=lambda item: item[\"time\"],\n", - " label=lambda item: item[\"version\"],\n", - " agg=lambda preds: preds[\"accepted\"].sum() / preds.count(),\n", - " min_x=min_x,\n", - " max_x=max_x,\n", - " mark=\"line\",\n", - " axis_labels={\"y\": \"acceptance_rate\"},\n", - " ),\n", - " ),\n", - " },\n", - " ),\n", - " }\n", - ")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "35c7e310", - "metadata": {}, - "outputs": [], - "source": [ - "panel" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "50b1be3e", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/Untitled.ipynb b/weave/legacy/examples/experimental/skip_test/Untitled.ipynb index a3755ff5feb..ff38e5faef8 100644 --- a/weave/legacy/examples/experimental/skip_test/Untitled.ipynb +++ b/weave/legacy/examples/experimental/skip_test/Untitled.ipynb @@ -1,51 +1,51 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "5ca8d4be", - "metadata": {}, - "outputs": [], - "source": [ - "import csv\n", - "import weave" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "5ca8d4be", + "metadata": {}, + "outputs": [], + "source": [ + "import csv\n", + "import weave" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "492a6655", + "metadata": {}, + "outputs": [], + "source": [ + "#help(csv.reader)\n", + "# reader = csv.reader(open('/Users/shawn/Downloads/wandb_export_2023-03-30T15_21_00.493-04_00.csv'))\n", + "# for row in reader:\n", + "# print(row)\n", + "#help(csv.reader)\n", + "weave.legacy.weave.ops.local_path('/Users/shawn/code2/weave/weave/testdata/cereal.csv').readcsv()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "492a6655", - "metadata": {}, - "outputs": [], - "source": [ - "#help(csv.reader)\n", - "# reader = csv.reader(open('/Users/shawn/Downloads/wandb_export_2023-03-30T15_21_00.493-04_00.csv'))\n", - "# for row in reader:\n", - "# print(row)\n", - "#help(csv.reader)\n", - "weave.legacy.ops.local_path('/Users/shawn/code2/weave/weave/testdata/cereal.csv').readcsv()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/Vectorizing.ipynb b/weave/legacy/examples/experimental/skip_test/Vectorizing.ipynb index 456c64262a8..488c7f42ff5 100644 --- a/weave/legacy/examples/experimental/skip_test/Vectorizing.ipynb +++ b/weave/legacy/examples/experimental/skip_test/Vectorizing.ipynb @@ -1,91 +1,91 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "5f10d941", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "import time\n", - "from weave.legacy import storage\n", - "from weave.legacy.ops_primitives import geom" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "5f10d941", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "import time\n", + "from weave.legacy.weave import storage\n", + "from weave.legacy.weave.ops_primitives import geom" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9f3026bd", + "metadata": {}, + "outputs": [], + "source": [ + "segs = []\n", + "for i in range(1000000):\n", + " segs.append(geom.LineSegment(i*0.1, i+0.2, i+0.3, i*0.5))\n", + "l = weave.save(segs)\n", + "arr = weave.legacy.weave.ops.ArrowArrayList(storage.to_arrow(segs))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7544d866", + "metadata": {}, + "outputs": [], + "source": [ + "# pure python\n", + "start_time = time.time()\n", + "sum(seg.length.resolve_fn(seg) for seg in segs)\n", + "print('TIME: ', time.time() - start_time)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "11c2a9b6", + "metadata": {}, + "outputs": [], + "source": [ + "# weave list\n", + "start_time = time.time()\n", + "weave.use(l.map(lambda seg: seg.length()).sum())\n", + "print('TIME: ', time.time() - start_time)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "71816731", + "metadata": {}, + "outputs": [], + "source": [ + "# weave vectorized arrow\n", + "start_time = time.time()\n", + "weave.use(arr.map(lambda seg: seg.length()).sum())\n", + "print('TIME: ', time.time() - start_time)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "9f3026bd", - "metadata": {}, - "outputs": [], - "source": [ - "segs = []\n", - "for i in range(1000000):\n", - " segs.append(geom.LineSegment(i*0.1, i+0.2, i+0.3, i*0.5))\n", - "l = weave.save(segs)\n", - "arr = weave.legacy.ops.ArrowArrayList(storage.to_arrow(segs))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7544d866", - "metadata": {}, - "outputs": [], - "source": [ - "# pure python\n", - "start_time = time.time()\n", - "sum(seg.length.resolve_fn(seg) for seg in segs)\n", - "print('TIME: ', time.time() - start_time)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "11c2a9b6", - "metadata": {}, - "outputs": [], - "source": [ - "# weave list\n", - "start_time = time.time()\n", - "weave.use(l.map(lambda seg: seg.length()).sum())\n", - "print('TIME: ', time.time() - start_time)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "71816731", - "metadata": {}, - "outputs": [], - "source": [ - "# weave vectorized arrow\n", - "start_time = time.time()\n", - "weave.use(arr.map(lambda seg: seg.length()).sum())\n", - "print('TIME: ', time.time() - start_time)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/WB data.ipynb b/weave/legacy/examples/experimental/skip_test/WB data.ipynb index ce5c1633310..a7a545ffa0a 100644 --- a/weave/legacy/examples/experimental/skip_test/WB data.ipynb +++ b/weave/legacy/examples/experimental/skip_test/WB data.ipynb @@ -1,80 +1,80 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "bb76d9d8", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "weave.use_frontend_devmode()" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "bb76d9d8", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "weave.use_frontend_devmode()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "54243e21", + "metadata": {}, + "outputs": [], + "source": [ + "project = weave.legacy.weave.ops.project('shawn', 'fasion-sweep')\n", + "runs = project.runs()\n", + "\n", + "panel = weave.legacy.weave.panels.Group(\n", + " preferHorizontal=True,\n", + " items={\n", + " \"sidebar\": weave.legacy.weave.panels.Group(\n", + " style=\"width: 200px; padding: 16px;\",\n", + " items={\n", + " \"run\": weave.legacy.weave.panels.ObjectPicker(runs, label='run'),\n", + " }\n", + " ),\n", + " #\"main\": lambda sidebar: project.run(sidebar.config.items['run_id'].config.choice).history()\n", + " \"main\": lambda sidebar: sidebar.config.items['run'].config.choice.history()\n", + " }\n", + ")\n", + "panel" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5a771433", + "metadata": {}, + "outputs": [], + "source": [ + "project = weave.legacy.weave.ops.project('shawn', 'fasion-sweep')\n", + "run_ids = project.runs().id()\n", + "\n", + "panel = weave.legacy.weave.panels.Group(\n", + " preferHorizontal=True,\n", + " items={\n", + " \"sidebar\": weave.legacy.weave.panels.Group(\n", + " style=\"width: 200px; padding: 16px;\",\n", + " items={\n", + " \"run_id\": weave.legacy.weave.panels.ObjectPicker(run_ids, label='run_id'),\n", + " }\n", + " ),\n", + " #\"main\": lambda sidebar: project.run(sidebar.config.items['run_id'].config.choice).history()\n", + " \"main\": lambda sidebar: weave.legacy.weave.panels.Plot(\n", + " project.run(sidebar.config.items['run_id'].config.choice).history(),\n", + " x=lambda row: row['_step'],\n", + " y=lambda row: row['loss'],\n", + " )\n", + " }\n", + ")\n", + "#panel" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "54243e21", - "metadata": {}, - "outputs": [], - "source": [ - "project = weave.legacy.ops.project('shawn', 'fasion-sweep')\n", - "runs = project.runs()\n", - "\n", - "panel = weave.legacy.panels.Group(\n", - " preferHorizontal=True,\n", - " items={\n", - " \"sidebar\": weave.legacy.panels.Group(\n", - " style=\"width: 200px; padding: 16px;\",\n", - " items={\n", - " \"run\": weave.legacy.panels.ObjectPicker(runs, label='run'),\n", - " }\n", - " ),\n", - " #\"main\": lambda sidebar: project.run(sidebar.config.items['run_id'].config.choice).history()\n", - " \"main\": lambda sidebar: sidebar.config.items['run'].config.choice.history()\n", - " }\n", - ")\n", - "panel" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5a771433", - "metadata": {}, - "outputs": [], - "source": [ - "project = weave.legacy.ops.project('shawn', 'fasion-sweep')\n", - "run_ids = project.runs().id()\n", - "\n", - "panel = weave.legacy.panels.Group(\n", - " preferHorizontal=True,\n", - " items={\n", - " \"sidebar\": weave.legacy.panels.Group(\n", - " style=\"width: 200px; padding: 16px;\",\n", - " items={\n", - " \"run_id\": weave.legacy.panels.ObjectPicker(run_ids, label='run_id'),\n", - " }\n", - " ),\n", - " #\"main\": lambda sidebar: project.run(sidebar.config.items['run_id'].config.choice).history()\n", - " \"main\": lambda sidebar: weave.legacy.panels.Plot(\n", - " project.run(sidebar.config.items['run_id'].config.choice).history(),\n", - " x=lambda row: row['_step'],\n", - " y=lambda row: row['loss'],\n", - " )\n", - " }\n", - ")\n", - "#panel" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/Weave geo data.ipynb b/weave/legacy/examples/experimental/skip_test/Weave geo data.ipynb index 7b63ffb245e..fba602aec01 100644 --- a/weave/legacy/examples/experimental/skip_test/Weave geo data.ipynb +++ b/weave/legacy/examples/experimental/skip_test/Weave geo data.ipynb @@ -1,106 +1,106 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "8d5be6da", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "import pandas as pd\n", - "from weave.legacy.ecosystem import wandb\n", - "weave.use_frontend_devmode()" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "8d5be6da", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "import pandas as pd\n", + "from weave.legacy.weave.ecosystem import wandb\n", + "weave.use_frontend_devmode()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "90518a5e", + "metadata": {}, + "outputs": [], + "source": [ + "data = pd.read_csv(\"/Users/shawn/code2/weave/database.csv\").to_dict(orient='records')\n", + "data = data[:1000]\n", + "weave.show(data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f643bb3f", + "metadata": {}, + "outputs": [], + "source": [ + "#wandb.Scatter(data, x_fn=lambda item: item[\"Longitude\"], y_fn=lambda item: item[\"Latitude\"])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b94b992b", + "metadata": {}, + "outputs": [], + "source": [ + "# wandb.plotly_geo([\n", + "# {'lat': 35, 'long': 39, 'color': 0.1},\n", + "# {'lat': 19, 'long': 24, 'color': 100}])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6b31859b", + "metadata": {}, + "outputs": [], + "source": [ + "#wandb.Geo(data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "872cb8d0", + "metadata": {}, + "outputs": [], + "source": [ + "weave.legacy.weave.panels.Group(\n", + " items={\n", + " 'geo': wandb.Geo(data,\n", + " x_fn=lambda item: item['Longitude'],\n", + " y_fn=lambda item: item[\"Latitude\"],\n", + " color_fn=lambda item: item[\"Magnitude\"]),\n", + " 'table': lambda geo: weave.legacy.weave.panels.LabeledItem(\n", + " label='Selected items',\n", + " item=weave.legacy.weave.panels.Group(\n", + " style=\"height: 400px;\",\n", + " preferHorizontal=True,\n", + " items={\n", + " 'table': geo.selected()\n", + " }))\n", + " })\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "90518a5e", - "metadata": {}, - "outputs": [], - "source": [ - "data = pd.read_csv(\"/Users/shawn/code2/weave/database.csv\").to_dict(orient='records')\n", - "data = data[:1000]\n", - "weave.show(data)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f643bb3f", - "metadata": {}, - "outputs": [], - "source": [ - "#wandb.Scatter(data, x_fn=lambda item: item[\"Longitude\"], y_fn=lambda item: item[\"Latitude\"])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b94b992b", - "metadata": {}, - "outputs": [], - "source": [ - "# wandb.plotly_geo([\n", - "# {'lat': 35, 'long': 39, 'color': 0.1},\n", - "# {'lat': 19, 'long': 24, 'color': 100}])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6b31859b", - "metadata": {}, - "outputs": [], - "source": [ - "#wandb.Geo(data)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "872cb8d0", - "metadata": {}, - "outputs": [], - "source": [ - "weave.legacy.panels.Group(\n", - " items={\n", - " 'geo': wandb.Geo(data,\n", - " x_fn=lambda item: item['Longitude'],\n", - " y_fn=lambda item: item[\"Latitude\"],\n", - " color_fn=lambda item: item[\"Magnitude\"]),\n", - " 'table': lambda geo: weave.legacy.panels.LabeledItem(\n", - " label='Selected items',\n", - " item=weave.legacy.panels.Group(\n", - " style=\"height: 400px;\",\n", - " preferHorizontal=True,\n", - " items={\n", - " 'table': geo.selected()\n", - " }))\n", - " })\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/art_explore.ipynb b/weave/legacy/examples/experimental/skip_test/art_explore.ipynb index b591b5a163e..bf693b598ea 100644 --- a/weave/legacy/examples/experimental/skip_test/art_explore.ipynb +++ b/weave/legacy/examples/experimental/skip_test/art_explore.ipynb @@ -1,141 +1,141 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "3df06c92", - "metadata": {}, - "source": [ - "# Art Exploration Dashboard\n", - "\n", - "This quick example programmatically buids a Weave Dashboard to explore and remix visual art.\n", - "* generate creative descriptions of artwork given some famous artists as reference points/inspiration\n", - "* create a Table (one column of text) of these art prompts (named \"style_riff\")\n", - "* use Stable Diffusion to generate art based on these prompts (\"riff_art\" column)\n", - "* inverse-generate a prompt which would lead to that image (and perhaps describe it better? \"art_desc\" column)\n", - "* imagine a perfect title for an artwork with that description (\"desc title\")\n", - "* finally, generate a remixed artwork for that title (\"remixed_art\"), except with more of the generated color specified in the horizontal panel (itself generated from the RGB values in the left sidebar)\n", - "\n", - "## Play with these parameters\n", - "\n", - "* the artist names and artist_id for which artist is the starting point\n", - "* the \"palette\" colors—these are the rows in the Dashboard\n", - "* the number of works (must be <= the number of colors in the palette and the number of artists\n", - "* the RGB values (0, 255)—these are combined to generate the \"color\" which is amplified in the remix art. Sometimes the color names are returned with extra words :)\n", - "* any of the prompts used to generate images or titles!\n" - ] + "cells": [ + { + "cell_type": "markdown", + "id": "3df06c92", + "metadata": {}, + "source": [ + "# Art Exploration Dashboard\n", + "\n", + "This quick example programmatically buids a Weave Dashboard to explore and remix visual art.\n", + "* generate creative descriptions of artwork given some famous artists as reference points/inspiration\n", + "* create a Table (one column of text) of these art prompts (named \"style_riff\")\n", + "* use Stable Diffusion to generate art based on these prompts (\"riff_art\" column)\n", + "* inverse-generate a prompt which would lead to that image (and perhaps describe it better? \"art_desc\" column)\n", + "* imagine a perfect title for an artwork with that description (\"desc title\")\n", + "* finally, generate a remixed artwork for that title (\"remixed_art\"), except with more of the generated color specified in the horizontal panel (itself generated from the RGB values in the left sidebar)\n", + "\n", + "## Play with these parameters\n", + "\n", + "* the artist names and artist_id for which artist is the starting point\n", + "* the \"palette\" colors—these are the rows in the Dashboard\n", + "* the number of works (must be <= the number of colors in the palette and the number of artists\n", + "* the RGB values (0, 255)—these are combined to generate the \"color\" which is amplified in the remix art. Sometimes the color names are returned with extra words :)\n", + "* any of the prompts used to generate images or titles!\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1ef13bdf", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "from weave.legacy.weave import weave_internal\n", + "from weave.legacy.weave.ecosystem.all import langchain" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c765a214", + "metadata": {}, + "outputs": [], + "source": [ + "weave.legacy.weave.panels.Board(\n", + " vars={\n", + " \"chat_model\": langchain.chat_openai(\"gpt-3.5-turbo\", 0.7),\n", + " \"artists\" : [\"René Magritte\", \"Josephine Wall\", \"Android Jones\", \"Alphonse Mucha\", \"Claude Monet\"],\n", + " \"artist_id\" : 0,\n", + " \"num_works\": 3,\n", + " \"palette\" : [\"red\", \"orange\", \"yellow\", \"green\", \"blue\", \"violet\"],\n", + " \"style_riff\": \n", + " lambda chat_model, num_works, artists, palette, artist_id:\n", + " weave.legacy.weave.ops.range(0, num_works, 1).map(\n", + " lambda row:\n", + " chat_model.predict(weave_internal.const(\"You are an expert art historian. In a sophisticated, avant-garde art museum, you see pieces in \")\n", + " + palette[row] + \" by \" + artists[artist_id]\n", + " + \", which has a fantastic contrast and synergy with the work of\")\n", + " \n", + " ),\n", + " \"riff_art\":\n", + " lambda style_riff, num_works:\n", + " weave.legacy.weave.ops.range(0, num_works, 1).map(\n", + " lambda row: style_riff[row]).stable_diffusion(),\n", + " \"art_desc\":\n", + " lambda riff_art, num_works:\n", + " weave.legacy.weave.ops.range(0, num_works, 1).map(\n", + " lambda row: riff_art[row]).img2prompt(),\n", + " \"desc_title\":\n", + " lambda art_desc, num_works, chat_model:\n", + " weave.legacy.weave.ops.range(0, num_works, 1).map(\n", + " lambda row: chat_model.predict(weave_internal.const(\"Art description: \")\n", + " + art_desc[row] + \". Perfect title:\")),\n", + " \"R\" : 168,\n", + " \"G\" : 156,\n", + " \"B\" : 234,\n", + " \"color\" : lambda chat_model, R, G, B:\n", + " chat_model.predict(weave_internal.const(\"RGB value: (\")\n", + " + R.toString() + \",\" + G.toString() + \",\" + B.toString()\n", + " + \"). Precise color name:\"),\n", + " \"remixed_art\":\n", + " lambda desc_title, num_works, color:\n", + " weave.legacy.weave.ops.range(0, num_works, 1).map(\n", + " lambda row: weave_internal.const(\"a beautiful painting titled \")\n", + " + desc_title[row] + \" with more \" + color).stable_diffusion()\n", + " \n", + " },\n", + " panels=[\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda style_riff: weave.legacy.weave.panels.Table(style_riff, columns=[lambda col: col]),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=4, h=16)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda riff_art: weave.legacy.weave.panels.Table(riff_art, columns=[lambda col: col]),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=4, y=0, w=6, h=16)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda art_desc: weave.legacy.weave.panels.Table(art_desc, columns=[lambda col: col]),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=10, y=0, w=4, h=16)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda desc_title: weave.legacy.weave.panels.Table(desc_title, columns=[lambda col: col]),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=14, y=0, w=4, h=16)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda remixed_art: weave.legacy.weave.panels.Table(remixed_art, columns=[lambda col: col]),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=18, y=0, w=6, h=16)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda color: weave.legacy.weave.panels.StringEditor(color),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=7, y=16, w=10, h=4)\n", + " ),\n", + " \n", + " ]\n", + ")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "1ef13bdf", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "from weave.legacy import weave_internal\n", - "from weave.legacy.ecosystem.all import langchain" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c765a214", - "metadata": {}, - "outputs": [], - "source": [ - "weave.legacy.panels.Board(\n", - " vars={\n", - " \"chat_model\": langchain.chat_openai(\"gpt-3.5-turbo\", 0.7),\n", - " \"artists\" : [\"René Magritte\", \"Josephine Wall\", \"Android Jones\", \"Alphonse Mucha\", \"Claude Monet\"],\n", - " \"artist_id\" : 0,\n", - " \"num_works\": 3,\n", - " \"palette\" : [\"red\", \"orange\", \"yellow\", \"green\", \"blue\", \"violet\"],\n", - " \"style_riff\": \n", - " lambda chat_model, num_works, artists, palette, artist_id:\n", - " weave.legacy.ops.range(0, num_works, 1).map(\n", - " lambda row:\n", - " chat_model.predict(weave_internal.const(\"You are an expert art historian. In a sophisticated, avant-garde art museum, you see pieces in \")\n", - " + palette[row] + \" by \" + artists[artist_id]\n", - " + \", which has a fantastic contrast and synergy with the work of\")\n", - " \n", - " ),\n", - " \"riff_art\":\n", - " lambda style_riff, num_works:\n", - " weave.legacy.ops.range(0, num_works, 1).map(\n", - " lambda row: style_riff[row]).stable_diffusion(),\n", - " \"art_desc\":\n", - " lambda riff_art, num_works:\n", - " weave.legacy.ops.range(0, num_works, 1).map(\n", - " lambda row: riff_art[row]).img2prompt(),\n", - " \"desc_title\":\n", - " lambda art_desc, num_works, chat_model:\n", - " weave.legacy.ops.range(0, num_works, 1).map(\n", - " lambda row: chat_model.predict(weave_internal.const(\"Art description: \")\n", - " + art_desc[row] + \". Perfect title:\")),\n", - " \"R\" : 168,\n", - " \"G\" : 156,\n", - " \"B\" : 234,\n", - " \"color\" : lambda chat_model, R, G, B:\n", - " chat_model.predict(weave_internal.const(\"RGB value: (\")\n", - " + R.toString() + \",\" + G.toString() + \",\" + B.toString()\n", - " + \"). Precise color name:\"),\n", - " \"remixed_art\":\n", - " lambda desc_title, num_works, color:\n", - " weave.legacy.ops.range(0, num_works, 1).map(\n", - " lambda row: weave_internal.const(\"a beautiful painting titled \")\n", - " + desc_title[row] + \" with more \" + color).stable_diffusion()\n", - " \n", - " },\n", - " panels=[\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda style_riff: weave.legacy.panels.Table(style_riff, columns=[lambda col: col]),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=4, h=16)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda riff_art: weave.legacy.panels.Table(riff_art, columns=[lambda col: col]),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=4, y=0, w=6, h=16)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda art_desc: weave.legacy.panels.Table(art_desc, columns=[lambda col: col]),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=10, y=0, w=4, h=16)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda desc_title: weave.legacy.panels.Table(desc_title, columns=[lambda col: col]),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=14, y=0, w=4, h=16)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda remixed_art: weave.legacy.panels.Table(remixed_art, columns=[lambda col: col]),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=18, y=0, w=6, h=16)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda color: weave.legacy.panels.StringEditor(color),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=7, y=16, w=10, h=4)\n", - " ),\n", - " \n", - " ]\n", - ")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/branching_runs.ipynb b/weave/legacy/examples/experimental/skip_test/branching_runs.ipynb index 86b3c167e31..ac3106dfdc9 100644 --- a/weave/legacy/examples/experimental/skip_test/branching_runs.ipynb +++ b/weave/legacy/examples/experimental/skip_test/branching_runs.ipynb @@ -1,215 +1,215 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "930f7487", - "metadata": {}, - "outputs": [], - "source": [ - "import time\n", - "import weave\n", - "from weave.legacy.ops_primitives import ArrowWeaveList\n", - "from weave.legacy.ops_domain import RunSegment\n", - "from weave.legacy import storage\n", - "from weave import publish, type_of\n", - "from weave.legacy.weave_types import List\n", - "import typing\n", - "import time\n", - "import sys\n", - "import numpy as np\n", - "from weave.legacy.ops import to_arrow\n", - "\n", - "import logging\n", - "import pyarrow as pa\n", - "\n", - "\n", - "logger = logging.getLogger(\"run_segment\")\n", - "handler = logging.StreamHandler(stream=sys.stdout)\n", - "handler.setFormatter(logging.Formatter(\"%(asctime)s - %(message)s\"))\n", - "logger.addHandler(handler)\n", - "\n", - "# set to logging.INFO for more verbose profiling\n", - "logger.setLevel(logging.ERROR)\n", - "\n", - "# serializer = publish # uses w&b artifacts intead of local artifacts\n", - "serializer = storage.save\n", - "\n", - "N_NUMERIC_METRICS = 99 # number of numerical columns in the metrics table\n", - "\n", - "\n", - "def random_metrics(n: int = 10, starting_step: int = 0, delta_step: int = 1):\n", - " \"\"\"Create an array of metrics of length n starting from step starting_index.\"\"\"\n", - " if n <= 0:\n", - " raise ValueError(\"n must be at least 1\")\n", - " if starting_step < 0:\n", - " raise ValueError(\"starting index must be at least 0\")\n", - " if delta_step < 1:\n", - " raise ValueError(\"delta_step must be an integer greater than or equal to 1.\")\n", - " data = {\n", - " \"step\": np.arange(starting_step, starting_step + n * delta_step, delta_step),\n", - " \"string_col\": np.random.choice(list(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"), n),\n", - " }\n", - " for j in range(N_NUMERIC_METRICS):\n", - " data[f\"metric{j}\"] = np.random.random(n) + np.sin(data['step'] * np.pi / 1e5)\n", - " data[f\"metric{j}\"][n // 10] = 10.\n", - " \n", - " return ArrowWeaveList(pa.table(data))\n", - "\n", - "\n", - "def create_branch(\n", - " name: str,\n", - " previous_segment: typing.Optional[RunSegment] = None,\n", - " length=10,\n", - " previous_segment_branch_frac=0.8,\n", - ") -> RunSegment:\n", - " \"\"\"Create a new segment and optionally attach it to a previous segment.\n", - "\n", - " Parameters\n", - " ----------\n", - " name: str\n", - " The name of the segment.\n", - " previous_segment: Optional[RunSegment], default None.\n", - " The parent run segment. If this is a root run segment, use None.\n", - " length: int, default = 10\n", - " The number of history rows to generate for the segment.\n", - " previous_segment_branch_frac: float satisfying 0 < branch_frac <= 1.\n", - " Parameter describing where in the previous segment to set the branch point.\n", - " A previous_segment_branch_frac of 0 sets the branch point at the previous\n", - " segment's root, whereas a previous_segment_branch_frac of 1 sets the branch\n", - " point at the end of the previous segment. A previous_segment_branch_frac of\n", - " 0.5 would include half of the previous segment's metric rows.\n", - "\n", - " Returns\n", - " -------\n", - " segment: RunSegment\n", - " The new segment.\n", - " \"\"\"\n", - " if not (0 < previous_segment_branch_frac <= 1):\n", - " raise ValueError(\"branch_frac must satisfy 0 < branch_frac <= 1\")\n", - "\n", - " if length <= 0:\n", - " raise ValueError(\"Length must be greater than 0.\")\n", - "\n", - " if previous_segment:\n", - " previous_metrics = previous_segment.metrics\n", - " n_previous_metrics = len(previous_metrics)\n", - " if n_previous_metrics > 0:\n", - " previous_segment_branch_index = (\n", - " int(previous_segment_branch_frac * n_previous_metrics) - 1\n", - " )\n", - "\n", - " # this run segment has a different root than the previous one\n", - " if previous_segment_branch_index < 0:\n", - " raise ValueError(\n", - " f\"Invalid branch point on RunSegment: previous_segment_branch_index \"\n", - " f\"{previous_segment_branch_index} must be between 0 and {len(previous_metrics) - 1}\"\n", - " )\n", - "\n", - " previous_segment_branch_step = (\n", - " previous_metrics._index(0)[\"step\"] + previous_segment_branch_index\n", - " )\n", - "\n", - " ref = storage.save(previous_segment)\n", - " new_metrics = random_metrics(\n", - " n=length, starting_step=previous_segment_branch_step + 1\n", - " )\n", - "\n", - " return RunSegment(name, ref.uri, previous_segment_branch_index, new_metrics)\n", - " return RunSegment(name, None, 0, random_metrics(length, 0))\n", - "\n", - "\n", - "def create_experiment(\n", - " num_steps: int, num_runs: int, branch_frac: float = 0.8\n", - ") -> typing.Optional[RunSegment]:\n", - " num_steps_per_run = num_steps // num_runs\n", - " segment = None\n", - " for i in range(num_runs):\n", - " segment = create_branch(\n", - " f\"branch {i}\",\n", - " segment,\n", - " length=num_steps_per_run,\n", - " previous_segment_branch_frac=branch_frac,\n", - " )\n", - " return segment\n", - "\n", - "last_segment = create_experiment(1000000, 100, 0.8)" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "930f7487", + "metadata": {}, + "outputs": [], + "source": [ + "import time\n", + "import weave\n", + "from weave.legacy.weave.ops_primitives import ArrowWeaveList\n", + "from weave.legacy.weave.ops_domain import RunSegment\n", + "from weave.legacy.weave import storage\n", + "from weave import publish, type_of\n", + "from weave.legacy.weave.weave_types import List\n", + "import typing\n", + "import time\n", + "import sys\n", + "import numpy as np\n", + "from weave.legacy.weave.ops import to_arrow\n", + "\n", + "import logging\n", + "import pyarrow as pa\n", + "\n", + "\n", + "logger = logging.getLogger(\"run_segment\")\n", + "handler = logging.StreamHandler(stream=sys.stdout)\n", + "handler.setFormatter(logging.Formatter(\"%(asctime)s - %(message)s\"))\n", + "logger.addHandler(handler)\n", + "\n", + "# set to logging.INFO for more verbose profiling\n", + "logger.setLevel(logging.ERROR)\n", + "\n", + "# serializer = publish # uses w&b artifacts intead of local artifacts\n", + "serializer = storage.save\n", + "\n", + "N_NUMERIC_METRICS = 99 # number of numerical columns in the metrics table\n", + "\n", + "\n", + "def random_metrics(n: int = 10, starting_step: int = 0, delta_step: int = 1):\n", + " \"\"\"Create an array of metrics of length n starting from step starting_index.\"\"\"\n", + " if n <= 0:\n", + " raise ValueError(\"n must be at least 1\")\n", + " if starting_step < 0:\n", + " raise ValueError(\"starting index must be at least 0\")\n", + " if delta_step < 1:\n", + " raise ValueError(\"delta_step must be an integer greater than or equal to 1.\")\n", + " data = {\n", + " \"step\": np.arange(starting_step, starting_step + n * delta_step, delta_step),\n", + " \"string_col\": np.random.choice(list(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"), n),\n", + " }\n", + " for j in range(N_NUMERIC_METRICS):\n", + " data[f\"metric{j}\"] = np.random.random(n) + np.sin(data['step'] * np.pi / 1e5)\n", + " data[f\"metric{j}\"][n // 10] = 10.\n", + " \n", + " return ArrowWeaveList(pa.table(data))\n", + "\n", + "\n", + "def create_branch(\n", + " name: str,\n", + " previous_segment: typing.Optional[RunSegment] = None,\n", + " length=10,\n", + " previous_segment_branch_frac=0.8,\n", + ") -> RunSegment:\n", + " \"\"\"Create a new segment and optionally attach it to a previous segment.\n", + "\n", + " Parameters\n", + " ----------\n", + " name: str\n", + " The name of the segment.\n", + " previous_segment: Optional[RunSegment], default None.\n", + " The parent run segment. If this is a root run segment, use None.\n", + " length: int, default = 10\n", + " The number of history rows to generate for the segment.\n", + " previous_segment_branch_frac: float satisfying 0 < branch_frac <= 1.\n", + " Parameter describing where in the previous segment to set the branch point.\n", + " A previous_segment_branch_frac of 0 sets the branch point at the previous\n", + " segment's root, whereas a previous_segment_branch_frac of 1 sets the branch\n", + " point at the end of the previous segment. A previous_segment_branch_frac of\n", + " 0.5 would include half of the previous segment's metric rows.\n", + "\n", + " Returns\n", + " -------\n", + " segment: RunSegment\n", + " The new segment.\n", + " \"\"\"\n", + " if not (0 < previous_segment_branch_frac <= 1):\n", + " raise ValueError(\"branch_frac must satisfy 0 < branch_frac <= 1\")\n", + "\n", + " if length <= 0:\n", + " raise ValueError(\"Length must be greater than 0.\")\n", + "\n", + " if previous_segment:\n", + " previous_metrics = previous_segment.metrics\n", + " n_previous_metrics = len(previous_metrics)\n", + " if n_previous_metrics > 0:\n", + " previous_segment_branch_index = (\n", + " int(previous_segment_branch_frac * n_previous_metrics) - 1\n", + " )\n", + "\n", + " # this run segment has a different root than the previous one\n", + " if previous_segment_branch_index < 0:\n", + " raise ValueError(\n", + " f\"Invalid branch point on RunSegment: previous_segment_branch_index \"\n", + " f\"{previous_segment_branch_index} must be between 0 and {len(previous_metrics) - 1}\"\n", + " )\n", + "\n", + " previous_segment_branch_step = (\n", + " previous_metrics._index(0)[\"step\"] + previous_segment_branch_index\n", + " )\n", + "\n", + " ref = storage.save(previous_segment)\n", + " new_metrics = random_metrics(\n", + " n=length, starting_step=previous_segment_branch_step + 1\n", + " )\n", + "\n", + " return RunSegment(name, ref.uri, previous_segment_branch_index, new_metrics)\n", + " return RunSegment(name, None, 0, random_metrics(length, 0))\n", + "\n", + "\n", + "def create_experiment(\n", + " num_steps: int, num_runs: int, branch_frac: float = 0.8\n", + ") -> typing.Optional[RunSegment]:\n", + " num_steps_per_run = num_steps // num_runs\n", + " segment = None\n", + " for i in range(num_runs):\n", + " segment = create_branch(\n", + " f\"branch {i}\",\n", + " segment,\n", + " length=num_steps_per_run,\n", + " previous_segment_branch_frac=branch_frac,\n", + " )\n", + " return segment\n", + "\n", + "last_segment = create_experiment(1000000, 100, 0.8)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "139bc4d0", + "metadata": {}, + "outputs": [], + "source": [ + "weave.show(last_segment)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2ca43fb6", + "metadata": {}, + "outputs": [], + "source": [ + "weave.show(last_segment.experiment())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5d8b6719", + "metadata": {}, + "outputs": [], + "source": [ + "plot = weave.legacy.weave.panels.Plot(last_segment.experiment())\n", + "series = plot.series[-1]\n", + "series2 = series.clone()\n", + "\n", + "plot.add_series(series2)\n", + "plot.set_x(lambda row: weave.legacy.weave.ops.number_bin(row['step'], weave.legacy.weave.ops.numbers_bins_equal([1, 2000], 2)))\n", + "\n", + "series.set_y(lambda row: weave.legacy.weave.ops.numbers_avg(row['metric0']))\n", + "series.set_mark_constant('line')\n", + "\n", + "series2.set_y(lambda row: weave.legacy.weave.ops.numbers_min(row['metric0']))\n", + "series2.set_y2(lambda row: weave.legacy.weave.ops.numbers_max(row['metric0']))\n", + "series2.set_mark_constant('area')\n", + "\n", + "plot.groupby_x()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ee4656e4", + "metadata": {}, + "outputs": [], + "source": [ + "plot" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "139bc4d0", - "metadata": {}, - "outputs": [], - "source": [ - "weave.show(last_segment)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2ca43fb6", - "metadata": {}, - "outputs": [], - "source": [ - "weave.show(last_segment.experiment())" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5d8b6719", - "metadata": {}, - "outputs": [], - "source": [ - "plot = weave.legacy.panels.Plot(last_segment.experiment())\n", - "series = plot.series[-1]\n", - "series2 = series.clone()\n", - "\n", - "plot.add_series(series2)\n", - "plot.set_x(lambda row: weave.legacy.ops.number_bin(row['step'], weave.legacy.ops.numbers_bins_equal([1, 2000], 2)))\n", - "\n", - "series.set_y(lambda row: weave.legacy.ops.numbers_avg(row['metric0']))\n", - "series.set_mark_constant('line')\n", - "\n", - "series2.set_y(lambda row: weave.legacy.ops.numbers_min(row['metric0']))\n", - "series2.set_y2(lambda row: weave.legacy.ops.numbers_max(row['metric0']))\n", - "series2.set_mark_constant('area')\n", - "\n", - "plot.groupby_x()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ee4656e4", - "metadata": {}, - "outputs": [], - "source": [ - "plot" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/image_gen_replicate.ipynb b/weave/legacy/examples/experimental/skip_test/image_gen_replicate.ipynb index dad519c4e85..8d4c05d0b14 100644 --- a/weave/legacy/examples/experimental/skip_test/image_gen_replicate.ipynb +++ b/weave/legacy/examples/experimental/skip_test/image_gen_replicate.ipynb @@ -1,77 +1,77 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "a1d79cb9", - "metadata": {}, - "source": [ - "# Image Generation with Replicate\n", - "\n", - "Convert a text prompt to an image and back to text with img2prompt or clip captioning." - ] + "cells": [ + { + "cell_type": "markdown", + "id": "a1d79cb9", + "metadata": {}, + "source": [ + "# Image Generation with Replicate\n", + "\n", + "Convert a text prompt to an image and back to text with img2prompt or clip captioning." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7c49c962", + "metadata": {}, + "outputs": [], + "source": [ + "# weave-test-skip-all: replicate API is slow and fails sometimes\n", + "import os\n", + "from weave.legacy.weave.ecosystem import replicate as weave_replicate" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "38f878f2", + "metadata": {}, + "outputs": [], + "source": [ + "weave_replicate.stable_diffusion(\"Your life is a sheep herd. You're the driver.\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6e848393", + "metadata": {}, + "outputs": [], + "source": [ + "weave_replicate.img2prompt(weave_replicate.stable_diffusion(\"Your life is a sheep herd. You're the driver.\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "50596314", + "metadata": {}, + "outputs": [], + "source": [ + "weave_replicate.clip_prefix_caption(weave_replicate.stable_diffusion(\"Your life is a sheep herd. You're the driver.\"))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "7c49c962", - "metadata": {}, - "outputs": [], - "source": [ - "# weave-test-skip-all: replicate API is slow and fails sometimes\n", - "import os\n", - "from weave.legacy.ecosystem import replicate as weave_replicate" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "38f878f2", - "metadata": {}, - "outputs": [], - "source": [ - "weave_replicate.stable_diffusion(\"Your life is a sheep herd. You're the driver.\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6e848393", - "metadata": {}, - "outputs": [], - "source": [ - "weave_replicate.img2prompt(weave_replicate.stable_diffusion(\"Your life is a sheep herd. You're the driver.\"))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "50596314", - "metadata": {}, - "outputs": [], - "source": [ - "weave_replicate.clip_prefix_caption(weave_replicate.stable_diffusion(\"Your life is a sheep herd. You're the driver.\"))" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/langchain docbot.ipynb b/weave/legacy/examples/experimental/skip_test/langchain docbot.ipynb index f9fe0650898..ef4eeb10d91 100644 --- a/weave/legacy/examples/experimental/skip_test/langchain docbot.ipynb +++ b/weave/legacy/examples/experimental/skip_test/langchain docbot.ipynb @@ -1,89 +1,89 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "0d6220cd", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "from weave import trace\n", - "weave.use_frontend_devmode()\n", - "from weave.legacy.ecosystem.all import langchain" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "0d6220cd", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "from weave import trace\n", + "weave.use_frontend_devmode()\n", + "from weave.legacy.weave.ecosystem.all import langchain" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a674fd63", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.chat_models import ChatOpenAI\n", + "#ChatOpenAI(model_name='gpt-3.5-turbo').query('hey whats up')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f8cff0cd", + "metadata": {}, + "outputs": [], + "source": [ + "weave.save([\n", + " 'how do I use weave?',\n", + " 'what products does W&B have?',\n", + " 'how do I get a sweep ID from a run?'\n", + "], 'questions')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a47df334", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.docstore.document import Document\n", + "documents = weave.legacy.weave.ops.local_path('/Users/shawn/Downloads/documents.jsonl').readjsonl().limit(1000)\n", + "docs = weave.save([Document(**d) for d in weave.use(documents)], 'documents:latest')\n", + "#docs" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "865af8ce", + "metadata": {}, + "outputs": [], + "source": [ + "db = langchain.faiss_from_documents(docs, langchain.openai_embeddings())\n", + "llm = langchain.chat_openai('gpt-3.5-turbo', 0.7)\n", + "qa = langchain.retrieval_qa_from_chain_type(llm, 'stuff', db)\n", + "qa.run('lets try again 2')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "a674fd63", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.chat_models import ChatOpenAI\n", - "#ChatOpenAI(model_name='gpt-3.5-turbo').query('hey whats up')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f8cff0cd", - "metadata": {}, - "outputs": [], - "source": [ - "weave.save([\n", - " 'how do I use weave?',\n", - " 'what products does W&B have?',\n", - " 'how do I get a sweep ID from a run?'\n", - "], 'questions')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a47df334", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.docstore.document import Document\n", - "documents = weave.legacy.ops.local_path('/Users/shawn/Downloads/documents.jsonl').readjsonl().limit(1000)\n", - "docs = weave.save([Document(**d) for d in weave.use(documents)], 'documents:latest')\n", - "#docs" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "865af8ce", - "metadata": {}, - "outputs": [], - "source": [ - "db = langchain.faiss_from_documents(docs, langchain.openai_embeddings())\n", - "llm = langchain.chat_openai('gpt-3.5-turbo', 0.7)\n", - "qa = langchain.retrieval_qa_from_chain_type(llm, 'stuff', db)\n", - "qa.run('lets try again 2')" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/plot_selection.ipynb b/weave/legacy/examples/experimental/skip_test/plot_selection.ipynb index 624fa155ee2..dac241c03bc 100644 --- a/weave/legacy/examples/experimental/skip_test/plot_selection.ipynb +++ b/weave/legacy/examples/experimental/skip_test/plot_selection.ipynb @@ -1,63 +1,63 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "c09f7649", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "# weave.use_frontend_devmode()" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "c09f7649", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "# weave.use_frontend_devmode()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a6b83817", + "metadata": {}, + "outputs": [], + "source": [ + "panel = weave.legacy.weave.panels.Group(\n", + " items={\n", + " \"plot\": weave.legacy.weave.panels.Plot(weave.legacy.weave.ops.range(1, 100, 1),\n", + " x=lambda row: row,\n", + " y=lambda row: row ** 2,\n", + " ),\n", + " \"table\": lambda plot: weave.legacy.weave.panels.panel_plot.selected_rows(plot)\n", + " })\n", + "\n", + "panel" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "55f43427", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "a6b83817", - "metadata": {}, - "outputs": [], - "source": [ - "panel = weave.legacy.panels.Group(\n", - " items={\n", - " \"plot\": weave.legacy.panels.Plot(weave.legacy.ops.range(1, 100, 1),\n", - " x=lambda row: row,\n", - " y=lambda row: row ** 2,\n", - " ),\n", - " \"table\": lambda plot: weave.legacy.panels.panel_plot.selected_rows(plot)\n", - " })\n", - "\n", - "panel" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "55f43427", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/slurm.ipynb b/weave/legacy/examples/experimental/skip_test/slurm.ipynb index cf1ebf69670..4429a7285d8 100644 --- a/weave/legacy/examples/experimental/skip_test/slurm.ipynb +++ b/weave/legacy/examples/experimental/skip_test/slurm.ipynb @@ -1,66 +1,66 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "8817764c", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "from weave.legacy.ecosystem import slurm" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "8817764c", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "from weave.legacy.weave.ecosystem import slurm" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cda9e9a3", + "metadata": {}, + "outputs": [], + "source": [ + "#slurm.slurm('http://localhost:8899').jobs()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9bee4444", + "metadata": {}, + "outputs": [], + "source": [ + "#slurm.slurm('http://localhost:8899').nodes()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e69a2f48", + "metadata": {}, + "outputs": [], + "source": [ + "slurm.slurm('http://localhost:8899')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "cda9e9a3", - "metadata": {}, - "outputs": [], - "source": [ - "#slurm.slurm('http://localhost:8899').jobs()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9bee4444", - "metadata": {}, - "outputs": [], - "source": [ - "#slurm.slurm('http://localhost:8899').nodes()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e69a2f48", - "metadata": {}, - "outputs": [], - "source": [ - "slurm.slurm('http://localhost:8899')" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/weave_engine_tracing.ipynb b/weave/legacy/examples/experimental/skip_test/weave_engine_tracing.ipynb index d409656ab68..f395535b7de 100644 --- a/weave/legacy/examples/experimental/skip_test/weave_engine_tracing.ipynb +++ b/weave/legacy/examples/experimental/skip_test/weave_engine_tracing.ipynb @@ -1,126 +1,126 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "de9a4837", - "metadata": {}, - "source": [ - "## Visualize Weave engine traces using Weave\n", - "\n", - "To produce data, run the Weave server with Datadog logging on, and WEAVE_TRACE_STREAM=//" - ] + "cells": [ + { + "cell_type": "markdown", + "id": "de9a4837", + "metadata": {}, + "source": [ + "## Visualize Weave engine traces using Weave\n", + "\n", + "To produce data, run the Weave server with Datadog logging on, and WEAVE_TRACE_STREAM=//
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c62364f5", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "from weave.legacy.weave.wandb_interface.wandb_stream_table import StreamTable" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8d099de8", + "metadata": {}, + "outputs": [], + "source": [ + "# set this to the StreamTable your server logs to. Or run as is to use public test data.\n", + "spans = StreamTable('shawn/weave-trace-test2/test15').rows()\n", + "\n", + "board = weave.legacy.weave.panels.Board(\n", + " vars={\n", + " 'all_spans': spans,\n", + " 'trace_id': '',\n", + " 'selected_spans': lambda trace_id, all_spans: all_spans.filter(lambda row: row['trace_id'] == trace_id)\n", + " },\n", + " panels=[\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " # TODO: have to compute all columns we want here, there's no way to\n", + " # tell js or python to do auto-columns behavior.\n", + " lambda all_spans: all_spans,\n", + " id='table',\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=24, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " # TODO: have to compute all columns we want here, there's no way to\n", + " # tell js or python to do auto-columns behavior.\n", + " lambda all_spans: weave.legacy.weave.panels.Table(\n", + " all_spans,\n", + " columns=[\n", + " weave.legacy.weave.panels.TableColumn(\n", + " lambda row: row['trace_id'],\n", + " groupby=True,\n", + " ),\n", + " weave.legacy.weave.panels.TableColumn(\n", + " lambda row: row.count(),\n", + " name='span count'\n", + " ),\n", + " weave.legacy.weave.panels.TableColumn(\n", + " # TODO: not exact, we need to add duration to get end time, but we don't have an add\n", + " # for 2 vectors yet.\n", + " lambda row: (row['start_time_ms'].max() - row['start_time_ms'].min()) / 1000,\n", + " name='duration_s'\n", + " )\n", + " ]\n", + " ),\n", + " id='traces',\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=24, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " # TODO: have to compute all columns we want here, there's no way to\n", + " # tell js or python to do auto-columns behavior.\n", + " lambda all_spans: weave.legacy.weave.panels.Table(\n", + " all_spans,\n", + " columns=[\n", + " weave.legacy.weave.panels.TableColumn(\n", + " lambda row: row['name'],\n", + " groupby=True,\n", + " ),\n", + " lambda row: row.count(),\n", + " weave.legacy.weave.panels.TableColumn(\n", + " # TODO: not exact, we need to add duration to get end time, but we don't have an add\n", + " # for 2 vectors yet.\n", + " lambda row: (row['start_time_ms'].max() - row['start_time_ms'].min()) / 1000,\n", + " name='duration_s'\n", + " )\n", + " ]\n", + " ),\n", + " id='spans',\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=24, h=6)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda selected_spans: weave.legacy.weave.panels.Trace(selected_spans),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=6, w=24, h=6)\n", + " )\n", + " ]\n", + ")\n", + "board" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "c62364f5", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "from weave.legacy.wandb_interface.wandb_stream_table import StreamTable" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8d099de8", - "metadata": {}, - "outputs": [], - "source": [ - "# set this to the StreamTable your server logs to. Or run as is to use public test data.\n", - "spans = StreamTable('shawn/weave-trace-test2/test15').rows()\n", - "\n", - "board = weave.legacy.panels.Board(\n", - " vars={\n", - " 'all_spans': spans,\n", - " 'trace_id': '',\n", - " 'selected_spans': lambda trace_id, all_spans: all_spans.filter(lambda row: row['trace_id'] == trace_id)\n", - " },\n", - " panels=[\n", - " weave.legacy.panels.BoardPanel(\n", - " # TODO: have to compute all columns we want here, there's no way to\n", - " # tell js or python to do auto-columns behavior.\n", - " lambda all_spans: all_spans,\n", - " id='table',\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=24, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " # TODO: have to compute all columns we want here, there's no way to\n", - " # tell js or python to do auto-columns behavior.\n", - " lambda all_spans: weave.legacy.panels.Table(\n", - " all_spans,\n", - " columns=[\n", - " weave.legacy.panels.TableColumn(\n", - " lambda row: row['trace_id'],\n", - " groupby=True,\n", - " ),\n", - " weave.legacy.panels.TableColumn(\n", - " lambda row: row.count(),\n", - " name='span count'\n", - " ),\n", - " weave.legacy.panels.TableColumn(\n", - " # TODO: not exact, we need to add duration to get end time, but we don't have an add\n", - " # for 2 vectors yet.\n", - " lambda row: (row['start_time_ms'].max() - row['start_time_ms'].min()) / 1000,\n", - " name='duration_s'\n", - " )\n", - " ]\n", - " ),\n", - " id='traces',\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=24, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " # TODO: have to compute all columns we want here, there's no way to\n", - " # tell js or python to do auto-columns behavior.\n", - " lambda all_spans: weave.legacy.panels.Table(\n", - " all_spans,\n", - " columns=[\n", - " weave.legacy.panels.TableColumn(\n", - " lambda row: row['name'],\n", - " groupby=True,\n", - " ),\n", - " lambda row: row.count(),\n", - " weave.legacy.panels.TableColumn(\n", - " # TODO: not exact, we need to add duration to get end time, but we don't have an add\n", - " # for 2 vectors yet.\n", - " lambda row: (row['start_time_ms'].max() - row['start_time_ms'].min()) / 1000,\n", - " name='duration_s'\n", - " )\n", - " ]\n", - " ),\n", - " id='spans',\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=24, h=6)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda selected_spans: weave.legacy.panels.Trace(selected_spans),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=6, w=24, h=6)\n", - " )\n", - " ]\n", - ")\n", - "board" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/skip_test/weave_scifi.ipynb b/weave/legacy/examples/experimental/skip_test/weave_scifi.ipynb index e08c7cc5ed2..1c6d8b02736 100644 --- a/weave/legacy/examples/experimental/skip_test/weave_scifi.ipynb +++ b/weave/legacy/examples/experimental/skip_test/weave_scifi.ipynb @@ -1,80 +1,80 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "3c4790a9", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "from weave.legacy import weave_internal\n", - "from weave.legacy.ecosystem.all import langchain\n", - "weave.use_frontend_devmode()" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "3c4790a9", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "from weave.legacy.weave import weave_internal\n", + "from weave.legacy.weave.ecosystem.all import langchain\n", + "weave.use_frontend_devmode()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2e9fe6dd", + "metadata": {}, + "outputs": [], + "source": [ + "weave.legacy.weave.panels.Board(\n", + " vars={\n", + " \"gpt\": langchain.chat_openai(\"gpt-3.5-turbo\", 0.7),\n", + " \"viz_style\" : [\"vintage art deco travel poster\",\n", + " \"futuristic science fiction movie\",\n", + " \"cute retro space anime\"],\n", + " \"viz_id\" : 0,\n", + " \"num_rows\": 2,\n", + " \"ml_terms\" : [\"models\", \"datasets\"],\n", + " \"prompts\": \n", + " lambda gpt, num_rows, ml_terms:\n", + " weave.legacy.weave.ops.range(0, num_rows, 1).map(\n", + " lambda row:\n", + " gpt.predict(weave_internal.const(\"You are an expert AGI architect describing the most powerful and flexible user interface for working with \")\n", + " + ml_terms[row] + \"in machine learning and AI. The three most important features for this are:\")\n", + " \n", + " ),\n", + " \"dream_view\":\n", + " lambda prompts, num_rows, viz_style, viz_id:\n", + " weave.legacy.weave.ops.range(0, num_rows, 1).map(\n", + " lambda row: weave_internal.const(\"a \") + viz_style[viz_id] + \" of a \" + prompts[row]).stable_diffusion(),\n", + " },\n", + " panels=[\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda prompts: weave.legacy.weave.panels.Table(prompts, columns=[lambda col: col]),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=12, h=16)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda dream_view: weave.legacy.weave.panels.Table(dream_view, columns=[lambda col: col]),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=12, y=0, w=12, h=16)\n", + " ),\n", + " ]\n", + ")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.9" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "2e9fe6dd", - "metadata": {}, - "outputs": [], - "source": [ - "weave.legacy.panels.Board(\n", - " vars={\n", - " \"gpt\": langchain.chat_openai(\"gpt-3.5-turbo\", 0.7),\n", - " \"viz_style\" : [\"vintage art deco travel poster\",\n", - " \"futuristic science fiction movie\",\n", - " \"cute retro space anime\"],\n", - " \"viz_id\" : 0,\n", - " \"num_rows\": 2,\n", - " \"ml_terms\" : [\"models\", \"datasets\"],\n", - " \"prompts\": \n", - " lambda gpt, num_rows, ml_terms:\n", - " weave.legacy.ops.range(0, num_rows, 1).map(\n", - " lambda row:\n", - " gpt.predict(weave_internal.const(\"You are an expert AGI architect describing the most powerful and flexible user interface for working with \")\n", - " + ml_terms[row] + \"in machine learning and AI. The three most important features for this are:\")\n", - " \n", - " ),\n", - " \"dream_view\":\n", - " lambda prompts, num_rows, viz_style, viz_id:\n", - " weave.legacy.ops.range(0, num_rows, 1).map(\n", - " lambda row: weave_internal.const(\"a \") + viz_style[viz_id] + \" of a \" + prompts[row]).stable_diffusion(),\n", - " },\n", - " panels=[\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda prompts: weave.legacy.panels.Table(prompts, columns=[lambda col: col]),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=12, h=16)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda dream_view: weave.legacy.panels.Table(dream_view, columns=[lambda col: col]),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=12, y=0, w=12, h=16)\n", - " ),\n", - " ]\n", - ")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.9" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/spacy_demo.ipynb b/weave/legacy/examples/experimental/spacy_demo.ipynb index b5340e51112..bb8b4a4560f 100644 --- a/weave/legacy/examples/experimental/spacy_demo.ipynb +++ b/weave/legacy/examples/experimental/spacy_demo.ipynb @@ -1,52 +1,52 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "cd35f2be", - "metadata": {}, - "outputs": [], - "source": [ - "# Run the following installation if you have not already\n", - "#!python -m spacy download en_core_web_sm" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "cd35f2be", + "metadata": {}, + "outputs": [], + "source": [ + "# Run the following installation if you have not already\n", + "#!python -m spacy download en_core_web_sm" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ede77c85", + "metadata": {}, + "outputs": [], + "source": [ + "from weave.legacy.weave.ecosystem.spacy import spacy\n", + "\n", + "text = \"\"\"Welcome to the spaCy Demo.\\\n", + "We currently support the small English language model, \\\n", + "and will add support for different types in the near future!\"\"\"\n", + "\n", + "spacy(text)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.9" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "ede77c85", - "metadata": {}, - "outputs": [], - "source": [ - "from weave.legacy.ecosystem.spacy import spacy\n", - "\n", - "text = \"\"\"Welcome to the spaCy Demo.\\\n", - "We currently support the small English language model, \\\n", - "and will add support for different types in the near future!\"\"\"\n", - "\n", - "spacy(text)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.9" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/table_data_passing.ipynb b/weave/legacy/examples/experimental/table_data_passing.ipynb index de674e689ff..66cedc7efbd 100644 --- a/weave/legacy/examples/experimental/table_data_passing.ipynb +++ b/weave/legacy/examples/experimental/table_data_passing.ipynb @@ -1,82 +1,82 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "c09f7649", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "import weave.legacy.panels\n", - "# Weave package now defaults to eager mode, but lazy mode required for this example notebook for now.\n", - "weave.use_lazy_execution()" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "c09f7649", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "import weave.legacy.weave.panels\n", + "# Weave package now defaults to eager mode, but lazy mode required for this example notebook for now.\n", + "weave.use_lazy_execution()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a6b83817", + "metadata": {}, + "outputs": [], + "source": [ + "panel = weave.legacy.weave.panels.Group(\n", + " items={\n", + " \"table\": weave.legacy.weave.panels.Table(weave.legacy.weave.ops.range(1, 100, 1), \n", + " columns=[\n", + " lambda row: row,\n", + " lambda row: row ** 2,\n", + " ],\n", + " ),\n", + " \"all_rows\": lambda table: weave.legacy.weave.panels.Plot(table.all_rows(),\n", + " x=lambda row: row['c_0'],\n", + " y=lambda row: row['c_1']\n", + " ),\n", + " \"derived\": lambda table: weave.legacy.weave.panels.Group(\n", + " preferHorizontal=True,\n", + " layoutMode=\"horizontal\",\n", + " items={\n", + " \"rows\": weave.legacy.weave.panels.Group(\n", + " items={\n", + " \"pinned_rows\": weave.legacy.weave.panels.Plot(table.pinned_rows(),\n", + " x=lambda row: row['c_0'],\n", + " y=lambda row: row['c_1']\n", + " ),\n", + " \"active_row\": table.active_row(),\n", + " }\n", + " ),\n", + " \"data\": weave.legacy.weave.panels.Group(\n", + " items={\n", + " \"pinned_data\": table.pinned_data(),\n", + " \"active_data\": table.active_data(),\n", + " }\n", + " )\n", + " }) \n", + " })\n", + "\n", + "panel" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "a6b83817", - "metadata": {}, - "outputs": [], - "source": [ - "panel = weave.legacy.panels.Group(\n", - " items={\n", - " \"table\": weave.legacy.panels.Table(weave.legacy.ops.range(1, 100, 1), \n", - " columns=[\n", - " lambda row: row,\n", - " lambda row: row ** 2,\n", - " ],\n", - " ),\n", - " \"all_rows\": lambda table: weave.legacy.panels.Plot(table.all_rows(),\n", - " x=lambda row: row['c_0'],\n", - " y=lambda row: row['c_1']\n", - " ),\n", - " \"derived\": lambda table: weave.legacy.panels.Group(\n", - " preferHorizontal=True,\n", - " layoutMode=\"horizontal\",\n", - " items={\n", - " \"rows\": weave.legacy.panels.Group(\n", - " items={\n", - " \"pinned_rows\": weave.legacy.panels.Plot(table.pinned_rows(),\n", - " x=lambda row: row['c_0'],\n", - " y=lambda row: row['c_1']\n", - " ),\n", - " \"active_row\": table.active_row(),\n", - " }\n", - " ),\n", - " \"data\": weave.legacy.panels.Group(\n", - " items={\n", - " \"pinned_data\": table.pinned_data(),\n", - " \"active_data\": table.active_data(),\n", - " }\n", - " )\n", - " }) \n", - " })\n", - "\n", - "panel" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/experimental/tag_search.ipynb b/weave/legacy/examples/experimental/tag_search.ipynb index d28245ee8ad..e3e7ef3de53 100644 --- a/weave/legacy/examples/experimental/tag_search.ipynb +++ b/weave/legacy/examples/experimental/tag_search.ipynb @@ -1,110 +1,110 @@ { - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "id": "550a2af8", - "metadata": {}, - "source": [ - "## An example implementation of tag search\n", - "\n", - "This shows how to achieve a UI for tag search.\n", - "\n", - "Its not ideal in these ways:\n", - "- we're missing an intersection op.\n", - "- we'll need to be sure the pattern vectorizes\n", - "- list of tag strings may not be the best representation for performance at scale\n", - "- we don't have a nice way to display list of strings as tags\n", - "- no centralized tag color control\n", - "- you should be able to click on a tag and filter the table down to that tag\n", - "- varbar construction of controls is still pretty odd\n", - "\n", - "But it works!\n" - ] + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "id": "550a2af8", + "metadata": {}, + "source": [ + "## An example implementation of tag search\n", + "\n", + "This shows how to achieve a UI for tag search.\n", + "\n", + "Its not ideal in these ways:\n", + "- we're missing an intersection op.\n", + "- we'll need to be sure the pattern vectorizes\n", + "- list of tag strings may not be the best representation for performance at scale\n", + "- we don't have a nice way to display list of strings as tags\n", + "- no centralized tag color control\n", + "- you should be able to click on a tag and filter the table down to that tag\n", + "- varbar construction of controls is still pretty odd\n", + "\n", + "But it works!\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9c690522", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "from weave.legacy.weave import weave_internal" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cd9ad6f9", + "metadata": {}, + "outputs": [], + "source": [ + "data = weave.save([\n", + " {'x': 15, 'tags': ['a', 'b']},\n", + " {'x': 23.9, 'tags': ['b', 'c']},\n", + " {'x': -8, 'tags': ['a']}\n", + "], 'taggeddata')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "34fb2bba", + "metadata": {}, + "outputs": [], + "source": [ + "weave.legacy.weave.panels.Board(\n", + " vars={\n", + " # The strange that we need to use two variables for structuring our tag picker and its value.\n", + " 'filter_tags': [],\n", + " 'tag_picker': lambda filter_tags: weave.legacy.weave.panels.SelectEditor(\n", + " filter_tags,\n", + " choices=weave_internal.const(['a', 'b', 'c'])\n", + " ),\n", + " 'data': data,\n", + " 'filtered_data': lambda data, filter_tags: data.filter(\n", + " # We don't currently have an intersection op, so we have to write the logic for it here.\n", + " # This will probably not vectorize currently, so will be slower on large amounts of data.\n", + " lambda row: weave.legacy.weave.ops.List.concat(weave.legacy.weave.ops.make_list(a=row['tags'], b=filter_tags)).unique().count()\n", + " < (row['tags'].count() + filter_tags.count())\n", + " )\n", + " },\n", + " panels=[\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda filtered_data: weave.legacy.weave.panels.Table(\n", + " filtered_data,\n", + " columns=[\n", + " lambda row: row['x'],\n", + " # Use json_dumps to get a better view for now.\n", + " lambda row: row['tags'].json_dumps()\n", + " ]\n", + " )\n", + " )\n", + " ]\n", + ")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "9c690522", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "from weave.legacy import weave_internal" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "cd9ad6f9", - "metadata": {}, - "outputs": [], - "source": [ - "data = weave.save([\n", - " {'x': 15, 'tags': ['a', 'b']},\n", - " {'x': 23.9, 'tags': ['b', 'c']},\n", - " {'x': -8, 'tags': ['a']}\n", - "], 'taggeddata')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "34fb2bba", - "metadata": {}, - "outputs": [], - "source": [ - "weave.legacy.panels.Board(\n", - " vars={\n", - " # The strange that we need to use two variables for structuring our tag picker and its value.\n", - " 'filter_tags': [],\n", - " 'tag_picker': lambda filter_tags: weave.legacy.panels.SelectEditor(\n", - " filter_tags,\n", - " choices=weave_internal.const(['a', 'b', 'c'])\n", - " ),\n", - " 'data': data,\n", - " 'filtered_data': lambda data, filter_tags: data.filter(\n", - " # We don't currently have an intersection op, so we have to write the logic for it here.\n", - " # This will probably not vectorize currently, so will be slower on large amounts of data.\n", - " lambda row: weave.legacy.ops.List.concat(weave.legacy.ops.make_list(a=row['tags'], b=filter_tags)).unique().count()\n", - " < (row['tags'].count() + filter_tags.count())\n", - " )\n", - " },\n", - " panels=[\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda filtered_data: weave.legacy.panels.Table(\n", - " filtered_data,\n", - " columns=[\n", - " lambda row: row['x'],\n", - " # Use json_dumps to get a better view for now.\n", - " lambda row: row['tags'].json_dumps()\n", - " ]\n", - " )\n", - " )\n", - " ]\n", - ")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/get_started.ipynb b/weave/legacy/examples/get_started.ipynb index b8b5a4f101a..8b8ffbd2bbb 100644 --- a/weave/legacy/examples/get_started.ipynb +++ b/weave/legacy/examples/get_started.ipynb @@ -1,301 +1,301 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "81c835f8", - "metadata": {}, - "source": [ - "# Get Started building with Weave\n", - "\n", - "In this tutorial, you will learn how to use Weave to build an interactive dashboard to help you explore, understand, and evaluate machine learning models.\n", - "\n", - "After this tutorials, you'll know how to build a dashboard to:\n", - "\n", - "- explore inputs, outputs & labels of your models\n", - "- calculate and plot metrics about your models\n", - "- interactively build live, connected plots to drill deeper into your data\n", - "- publish sharable interactive dashboards to enable colleagues to build on your work\n", - "\n", - "# Hello, World\n", - "\n", - "First, install `weave`:\n" - ] + "cells": [ + { + "cell_type": "markdown", + "id": "81c835f8", + "metadata": {}, + "source": [ + "# Get Started building with Weave\n", + "\n", + "In this tutorial, you will learn how to use Weave to build an interactive dashboard to help you explore, understand, and evaluate machine learning models.\n", + "\n", + "After this tutorials, you'll know how to build a dashboard to:\n", + "\n", + "- explore inputs, outputs & labels of your models\n", + "- calculate and plot metrics about your models\n", + "- interactively build live, connected plots to drill deeper into your data\n", + "- publish sharable interactive dashboards to enable colleagues to build on your work\n", + "\n", + "# Hello, World\n", + "\n", + "First, install `weave`:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e45d5578", + "metadata": {}, + "outputs": [], + "source": [ + "!pip install weave -qqq" + ] + }, + { + "cell_type": "markdown", + "id": "56c791d0", + "metadata": {}, + "source": [ + "Next, we'll use Weave to explore the Iris flower dataset.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b2f76045", + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.datasets import load_iris\n", + "\n", + "def get_iris_dataset():\n", + " iris = load_iris(as_frame=True)\n", + " data = iris['data']\n", + " data['target_id'] = iris['target']\n", + " data['target_name'] = iris['target_names'][iris['target']]\n", + "\n", + " def clean_column_name(c):\n", + " return c.replace(\" (cm)\", \"\").replace(\" \", \"_\")\n", + " data.columns = [clean_column_name(c) for c in data.columns]\n", + " return data\n", + "\n", + "iris_df = get_iris_dataset()" + ] + }, + { + "cell_type": "markdown", + "id": "ae1d5797", + "metadata": {}, + "source": [ + "Now that we have a dataframe, we can display it in an interactive table by calling `weave.show`.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "84f1a891", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "from weave.legacy.weave.show import show\n", + "show(iris_df)" + ] + }, + { + "cell_type": "markdown", + "id": "091192b7-ede4-423f-a78d-b06a9b877bab", + "metadata": {}, + "source": [ + "This is already a lot more powerful that the static visualization of a pandas `DataFrame` because you can page through it——and we're just getting started.\n", + "\n", + "# Building plots\n", + "\n", + "Weave can dynamically create visualizations of your data.\n", + "\n", + "- At the top of the panel, click `Table`\n", + "- You should see a dropdown, click `Plot`\n", + "\n", + "You should now see a plot of `sepal_width` versus `sepal_length`, colored by `target_name`. Weave's visualization engine uses the type of each column to choose a reasonable way to display your data. You can edit this plot by clicking the pencil icon ✏️ in the top right of the panel to open the panel editor.\n", + "\n", + "Note: You can build these plots interactively using the UI or define them programmatically in Python. In this tutorial, we'll focus on building these dashboards using the UI and keep programmatic dashboard building for later tutorials.\n" + ] + }, + { + "cell_type": "markdown", + "id": "9866379b", + "metadata": {}, + "source": [ + "!['image'](https://raw.githubusercontent.com/wandb/weave/6936cd8233f382ae3fd165480dce5832c06c2453/docs/assets/get_started_0.png)\n" + ] + }, + { + "cell_type": "markdown", + "id": "bd62be8e", + "metadata": {}, + "source": [ + "## Exercise\n", + "\n", + "- Try changing the X and Y axes\n", + "- Try changing the color\n", + "\n", + "Tip: `row[\"\"]` is a **Weave Expression**. You can edit the column name inside the quotes to show the relevant column from your data.\n", + "\n", + "# Exploring Tables\n", + "\n", + "Let's display our data as a `Table` again:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "886c7c49-e7f8-4651-8a6a-b2a08d417dda", + "metadata": {}, + "outputs": [], + "source": [ + "show(iris_df)" + ] + }, + { + "cell_type": "markdown", + "id": "6d12837d", + "metadata": {}, + "source": [ + "You can add, remove and sort each column by using the three dots button ⋮ beside the column name.\n", + "\n", + "## Exercise\n", + "\n", + "- Try sorting by the `sepal_length` column\n", + "- Try removing the `target_id` column\n", + "\n", + "## Filtering\n", + "\n", + "You can filter tables using the funnel icon ▼ on the top left.\n", + "\n", + "For example, to filter the data to only display the `setosa` flowers:\n", + "\n", + "- Click the filter icon\n", + "- Add the expression `row[\"target_name\"] == \"setosa\"`\n", + "\n", + "# Transforming data\n", + "\n", + "When analyzing models, you often need to use your data to calculate metrics or statistics to get summaries for comparison.\n", + "\n", + "To enable this, Weave has built-in operations, or **Weave Ops**, to transform data. You can also configure the data displayed in each column as we did with the plot.\n", + "\n", + "For example, to display the sum of each examples' `sepal_width` and `sepal_length`:\n", + "\n", + "- Click a column to edit (e.g. `sepal_length`)\n", + "- Change the Cell expression to `row[\"sepal_width\"] + row[\"sepal_length\"]`\n", + "- Click anywhere outside the popover to apply the change\n", + "\n", + "# Group by columns to compare splits and calculate summary statistics\n", + "\n", + "Comparing performance across different data splits is vital to uncovering biases and edge cases. This is fast and visual in Weave using the **Group by** operation.\n", + "\n", + "For example, if we want to calculate summary statistics of each type of flower in our dataset, we can group by the `target_name` column.\n", + "\n", + "- Click the three dots button ⋮ on the `target_name` column\n", + "- Click `Group by`\n", + "\n", + "We now see that Weave has grouped our data by the `target_name` and made plots for each column. We can now use different operations on these columns because they're now _lists_ rather than individual elements.\n", + "\n", + "For example, we can calculate the average of each column by changing the cell expression to be `row[\"\"].avg` e.g. `row[\"sepal_length\"].avg`.\n", + "\n", + "## Exercise\n", + "\n", + "- Try calculating the maximum of each column\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "0954b735", + "metadata": {}, + "source": [ + "!['image'](https://raw.githubusercontent.com/wandb/weave/4885095070704922189ba4d761029821c4e5da42/docs/assets/get_started_1.png)\n" + ] + }, + { + "cell_type": "markdown", + "id": "60acbe66", + "metadata": {}, + "source": [ + "## Drilldown with connected plots\n", + "\n", + "Finally, once you have found a split of data that is interesting, you often want to view individual elements of that data to better understand it. Weave makes it easy to connect multiple visualizations so that you can drilldown into selected data.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "531013bb", + "metadata": {}, + "outputs": [], + "source": [ + "show(iris_df)" + ] + }, + { + "cell_type": "markdown", + "id": "2519db1c", + "metadata": {}, + "source": [ + "!['image'](https://raw.githubusercontent.com/wandb/weave/4885095070704922189ba4d761029821c4e5da42/docs/assets/get_started_2.png)\n" + ] + }, + { + "cell_type": "markdown", + "id": "ddad55c3", + "metadata": {}, + "source": [ + "For example, to select data from a plot and display it in a table:\n", + "\n", + "- Add a new panel from the drawer menu on the right (1)\n", + "- Using the panel name (2), refer to the `.selected_data` from the first panel in the expression editor (3)\n", + "- Use the selection tool (4) to display that data in the drilldown table\n", + "\n", + "Tip: You can also connect `Tables` to other plots. To select a row on a table, click the row number. To use that selection, use `.active_data`.\n", + "\n", + "# Publish your dashboard and share it\n", + "\n", + "Once you have something you're happy with, you can click the arrow ↗️ from the drawer menu on the right to open it in a new tab. From there, you can click \"Publish board\" to send your creation to the cloud and share it with the world. You can also use this area to add new panels and update your dashboard.\n", + "\n", + "# What's next?\n", + "\n", + "With what you've learned, try build something on your own data. Weave works with lots of different types of data and is performant at large scales!\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e2011a09", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy\n", + "from PIL import Image\n", + "\n", + "def random_image():\n", + " imarray = numpy.random.rand(100,100,3) * 255\n", + " return Image.fromarray(imarray.astype('uint8')).convert('RGBA')\n", + "\n", + "show([{'image_col': random_image(), 'text_col': 'Hello'}, \n", + " {'image_col': random_image(), 'text_col': 'World'}]*1000)" + ] + }, + { + "cell_type": "markdown", + "id": "6db51292", + "metadata": {}, + "source": [ + "We're heads down focusing on adding templates and improving our documentation. Weave is open source, and we're very excited to merge your contributions. If you have feedback, feature requests, or bugs, you can open an issue on the Weave Github repository.\n", + "\n", + "## Not finished learning?\n", + "\n", + "Check out our [examples](https://github.com/wandb/weave/tree/master/examples) to see more tutorials, a gallery of dashboards, and reference guides to different components.\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.11" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "e45d5578", - "metadata": {}, - "outputs": [], - "source": [ - "!pip install weave -qqq" - ] - }, - { - "cell_type": "markdown", - "id": "56c791d0", - "metadata": {}, - "source": [ - "Next, we'll use Weave to explore the Iris flower dataset.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b2f76045", - "metadata": {}, - "outputs": [], - "source": [ - "from sklearn.datasets import load_iris\n", - "\n", - "def get_iris_dataset():\n", - " iris = load_iris(as_frame=True)\n", - " data = iris['data']\n", - " data['target_id'] = iris['target']\n", - " data['target_name'] = iris['target_names'][iris['target']]\n", - "\n", - " def clean_column_name(c):\n", - " return c.replace(\" (cm)\", \"\").replace(\" \", \"_\")\n", - " data.columns = [clean_column_name(c) for c in data.columns]\n", - " return data\n", - "\n", - "iris_df = get_iris_dataset()" - ] - }, - { - "cell_type": "markdown", - "id": "ae1d5797", - "metadata": {}, - "source": [ - "Now that we have a dataframe, we can display it in an interactive table by calling `weave.show`.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "84f1a891", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "from weave.legacy.show import show\n", - "show(iris_df)" - ] - }, - { - "cell_type": "markdown", - "id": "091192b7-ede4-423f-a78d-b06a9b877bab", - "metadata": {}, - "source": [ - "This is already a lot more powerful that the static visualization of a pandas `DataFrame` because you can page through it——and we're just getting started.\n", - "\n", - "# Building plots\n", - "\n", - "Weave can dynamically create visualizations of your data.\n", - "\n", - "- At the top of the panel, click `Table`\n", - "- You should see a dropdown, click `Plot`\n", - "\n", - "You should now see a plot of `sepal_width` versus `sepal_length`, colored by `target_name`. Weave's visualization engine uses the type of each column to choose a reasonable way to display your data. You can edit this plot by clicking the pencil icon ✏️ in the top right of the panel to open the panel editor.\n", - "\n", - "Note: You can build these plots interactively using the UI or define them programmatically in Python. In this tutorial, we'll focus on building these dashboards using the UI and keep programmatic dashboard building for later tutorials.\n" - ] - }, - { - "cell_type": "markdown", - "id": "9866379b", - "metadata": {}, - "source": [ - "!['image'](https://raw.githubusercontent.com/wandb/weave/6936cd8233f382ae3fd165480dce5832c06c2453/docs/assets/get_started_0.png)\n" - ] - }, - { - "cell_type": "markdown", - "id": "bd62be8e", - "metadata": {}, - "source": [ - "## Exercise\n", - "\n", - "- Try changing the X and Y axes\n", - "- Try changing the color\n", - "\n", - "Tip: `row[\"\"]` is a **Weave Expression**. You can edit the column name inside the quotes to show the relevant column from your data.\n", - "\n", - "# Exploring Tables\n", - "\n", - "Let's display our data as a `Table` again:\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "886c7c49-e7f8-4651-8a6a-b2a08d417dda", - "metadata": {}, - "outputs": [], - "source": [ - "show(iris_df)" - ] - }, - { - "cell_type": "markdown", - "id": "6d12837d", - "metadata": {}, - "source": [ - "You can add, remove and sort each column by using the three dots button ⋮ beside the column name.\n", - "\n", - "## Exercise\n", - "\n", - "- Try sorting by the `sepal_length` column\n", - "- Try removing the `target_id` column\n", - "\n", - "## Filtering\n", - "\n", - "You can filter tables using the funnel icon ▼ on the top left.\n", - "\n", - "For example, to filter the data to only display the `setosa` flowers:\n", - "\n", - "- Click the filter icon\n", - "- Add the expression `row[\"target_name\"] == \"setosa\"`\n", - "\n", - "# Transforming data\n", - "\n", - "When analyzing models, you often need to use your data to calculate metrics or statistics to get summaries for comparison.\n", - "\n", - "To enable this, Weave has built-in operations, or **Weave Ops**, to transform data. You can also configure the data displayed in each column as we did with the plot.\n", - "\n", - "For example, to display the sum of each examples' `sepal_width` and `sepal_length`:\n", - "\n", - "- Click a column to edit (e.g. `sepal_length`)\n", - "- Change the Cell expression to `row[\"sepal_width\"] + row[\"sepal_length\"]`\n", - "- Click anywhere outside the popover to apply the change\n", - "\n", - "# Group by columns to compare splits and calculate summary statistics\n", - "\n", - "Comparing performance across different data splits is vital to uncovering biases and edge cases. This is fast and visual in Weave using the **Group by** operation.\n", - "\n", - "For example, if we want to calculate summary statistics of each type of flower in our dataset, we can group by the `target_name` column.\n", - "\n", - "- Click the three dots button ⋮ on the `target_name` column\n", - "- Click `Group by`\n", - "\n", - "We now see that Weave has grouped our data by the `target_name` and made plots for each column. We can now use different operations on these columns because they're now _lists_ rather than individual elements.\n", - "\n", - "For example, we can calculate the average of each column by changing the cell expression to be `row[\"\"].avg` e.g. `row[\"sepal_length\"].avg`.\n", - "\n", - "## Exercise\n", - "\n", - "- Try calculating the maximum of each column\n" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "0954b735", - "metadata": {}, - "source": [ - "!['image'](https://raw.githubusercontent.com/wandb/weave/4885095070704922189ba4d761029821c4e5da42/docs/assets/get_started_1.png)\n" - ] - }, - { - "cell_type": "markdown", - "id": "60acbe66", - "metadata": {}, - "source": [ - "## Drilldown with connected plots\n", - "\n", - "Finally, once you have found a split of data that is interesting, you often want to view individual elements of that data to better understand it. Weave makes it easy to connect multiple visualizations so that you can drilldown into selected data.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "531013bb", - "metadata": {}, - "outputs": [], - "source": [ - "show(iris_df)" - ] - }, - { - "cell_type": "markdown", - "id": "2519db1c", - "metadata": {}, - "source": [ - "!['image'](https://raw.githubusercontent.com/wandb/weave/4885095070704922189ba4d761029821c4e5da42/docs/assets/get_started_2.png)\n" - ] - }, - { - "cell_type": "markdown", - "id": "ddad55c3", - "metadata": {}, - "source": [ - "For example, to select data from a plot and display it in a table:\n", - "\n", - "- Add a new panel from the drawer menu on the right (1)\n", - "- Using the panel name (2), refer to the `.selected_data` from the first panel in the expression editor (3)\n", - "- Use the selection tool (4) to display that data in the drilldown table\n", - "\n", - "Tip: You can also connect `Tables` to other plots. To select a row on a table, click the row number. To use that selection, use `.active_data`.\n", - "\n", - "# Publish your dashboard and share it\n", - "\n", - "Once you have something you're happy with, you can click the arrow ↗️ from the drawer menu on the right to open it in a new tab. From there, you can click \"Publish board\" to send your creation to the cloud and share it with the world. You can also use this area to add new panels and update your dashboard.\n", - "\n", - "# What's next?\n", - "\n", - "With what you've learned, try build something on your own data. Weave works with lots of different types of data and is performant at large scales!\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e2011a09", - "metadata": {}, - "outputs": [], - "source": [ - "import numpy\n", - "from PIL import Image\n", - "\n", - "def random_image():\n", - " imarray = numpy.random.rand(100,100,3) * 255\n", - " return Image.fromarray(imarray.astype('uint8')).convert('RGBA')\n", - "\n", - "show([{'image_col': random_image(), 'text_col': 'Hello'}, \n", - " {'image_col': random_image(), 'text_col': 'World'}]*1000)" - ] - }, - { - "cell_type": "markdown", - "id": "6db51292", - "metadata": {}, - "source": [ - "We're heads down focusing on adding templates and improving our documentation. Weave is open source, and we're very excited to merge your contributions. If you have feedback, feature requests, or bugs, you can open an issue on the Weave Github repository.\n", - "\n", - "## Not finished learning?\n", - "\n", - "Check out our [examples](https://github.com/wandb/weave/tree/master/examples) to see more tutorials, a gallery of dashboards, and reference guides to different components.\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.11" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/reference/WB_API.ipynb b/weave/legacy/examples/reference/WB_API.ipynb index 04747e092f6..d97e0eb952c 100644 --- a/weave/legacy/examples/reference/WB_API.ipynb +++ b/weave/legacy/examples/reference/WB_API.ipynb @@ -1,89 +1,89 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "eae3e8dd", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "import weave.legacy.panels\n", - "import weave.legacy.ops\n", - "from weave.legacy.show import show" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "eae3e8dd", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "import weave.legacy.weave.panels\n", + "import weave.legacy.weave.ops\n", + "from weave.legacy.weave.show import show" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "887d88a4", + "metadata": {}, + "outputs": [], + "source": [ + "project = weave.legacy.weave.ops.project('stacey', \"mendeleev\")\n", + "#project" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b7705fb7", + "metadata": {}, + "outputs": [], + "source": [ + "panel = weave.legacy.weave.panels.Table(weave.legacy.weave.ops.project('stacey', \"mendeleev\").artifactType('test_results').artifacts(),\n", + " columns=[\n", + " lambda art: weave.legacy.weave.ops.artifact_collection_ops.artifact_name(art), # hack to get around shadowed `name` op\n", + " lambda art: art.versions().count()\n", + " ])\n", + "show(panel)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "58b26e21", + "metadata": {}, + "outputs": [], + "source": [ + "weave.legacy.weave.ops.project('stacey', \"mendeleev\").artifactType('test_results').artifacts()[0].versions()[0].file('test_results.table.json')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "debbb5d4", + "metadata": {}, + "outputs": [], + "source": [ + "weave.legacy.weave.ops.project('shawn', \"dsviz-simple-tables\").artifactType('dataset').artifacts()[0].versions()[5].file('my-table.table.json')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + }, + "vscode": { + "interpreter": { + "hash": "cdaa5b4f919dd2bcc1e1b23efc336c7178fbd1227e862ece13b7d448295c4271" + } + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "887d88a4", - "metadata": {}, - "outputs": [], - "source": [ - "project = weave.legacy.ops.project('stacey', \"mendeleev\")\n", - "#project" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b7705fb7", - "metadata": {}, - "outputs": [], - "source": [ - "panel = weave.legacy.panels.Table(weave.legacy.ops.project('stacey', \"mendeleev\").artifactType('test_results').artifacts(),\n", - " columns=[\n", - " lambda art: weave.legacy.ops.artifact_collection_ops.artifact_name(art), # hack to get around shadowed `name` op\n", - " lambda art: art.versions().count()\n", - " ])\n", - "show(panel)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "58b26e21", - "metadata": {}, - "outputs": [], - "source": [ - "weave.legacy.ops.project('stacey', \"mendeleev\").artifactType('test_results').artifacts()[0].versions()[0].file('test_results.table.json')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "debbb5d4", - "metadata": {}, - "outputs": [], - "source": [ - "weave.legacy.ops.project('shawn', \"dsviz-simple-tables\").artifactType('dataset').artifacts()[0].versions()[5].file('my-table.table.json')" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - }, - "vscode": { - "interpreter": { - "hash": "cdaa5b4f919dd2bcc1e1b23efc336c7178fbd1227e862ece13b7d448295c4271" - } - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/reference/confusion_matrix.ipynb b/weave/legacy/examples/reference/confusion_matrix.ipynb index 415c75a743a..e0305d4fd6f 100644 --- a/weave/legacy/examples/reference/confusion_matrix.ipynb +++ b/weave/legacy/examples/reference/confusion_matrix.ipynb @@ -1,234 +1,234 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "562cca2e-fd23-4725-9c04-416fde40aadc", - "metadata": {}, - "source": [ - "# Create an Interactive Confusion Matrix in Weave\n", - "\n", - "In this tutorial, we will set up an interactive confusion matrix Weave panel using Weave expressions and Python):\n", - "* pick an existing W&B Table of predictions\n", - "* load this data into Weave locally\n", - "* programmatically configure two Weave Panels: a Facet panel for the confusion matrix grid and an active selection panel to show the details of items in that cell of the confusion matrix\n", - "\n", - "\n", - "\n", - "# Step 0: Setup\n", - "\n", - "Install dependencies and login to W&B to save & publish your work." - ] + "cells": [ + { + "cell_type": "markdown", + "id": "562cca2e-fd23-4725-9c04-416fde40aadc", + "metadata": {}, + "source": [ + "# Create an Interactive Confusion Matrix in Weave\n", + "\n", + "In this tutorial, we will set up an interactive confusion matrix Weave panel using Weave expressions and Python):\n", + "* pick an existing W&B Table of predictions\n", + "* load this data into Weave locally\n", + "* programmatically configure two Weave Panels: a Facet panel for the confusion matrix grid and an active selection panel to show the details of items in that cell of the confusion matrix\n", + "\n", + "\n", + "\n", + "# Step 0: Setup\n", + "\n", + "Install dependencies and login to W&B to save & publish your work." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8544cf72", + "metadata": {}, + "outputs": [], + "source": [ + "# if not already installed\n", + "!pip install -qqq weave" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5b86972f-d8d7-4f5a-bf5a-9a6be887978c", + "metadata": {}, + "outputs": [], + "source": [ + "import wandb\n", + "wandb.login()\n", + "import weave\n", + "import weave.legacy.weave.panels" + ] + }, + { + "cell_type": "markdown", + "id": "b35a8e31-3f51-43a9-bf89-543ed6fe62e8", + "metadata": {}, + "source": [ + "Use our public example or substitute your own W&B Tables by replacing the fields below. You can find the relevant information by navigating to a project in W&B, clicking on the \"Artifacts\" tab, and browsing using the sidebar until you find the artifact type and corresponding table file of interest (e.g. [this one used in the example](https://wandb.ai/stacey/mendeleev/artifacts/test_results/test_res_1fwmcd3q/v0/files/test_results.table.json)).\n", + "\n", + "**Note:** the index '0' after `artifacts()` and `versions()` will take the first element in those lists." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "01183f54-efa6-405a-be6a-142f75540913", + "metadata": {}, + "outputs": [], + "source": [ + "ENTITY = \"stacey\"\n", + "PROJECT = \"mendeleev\"\n", + "ARTIFACT_TYPE = \"test_results\"\n", + "TABLE_FILE = \"test_results.table.json\"" + ] + }, + { + "cell_type": "markdown", + "id": "2c910260-a5c0-4c99-bd00-1b9b95ddde54", + "metadata": {}, + "source": [ + "# Step 1: Compose Weave expression to load W&B Table\n", + "\n", + "Navigate the W&B object tree programmatically with Weave\n", + "* start with the specified W&B project\n", + "* fetch all artifacts of the specified type and take the first artifact\n", + "* fetch all the versions of that artifact and take the first one\n", + "* load the specified W&B Table file associated with that artifact version\n", + "* convert that file into a Weave table (with `.table.rows()`)\n", + "\n", + "The second cell below will display an interactive Weave Panel of the corresponding Table. You can interact with this panel in the notebook as you would with the underlying W&B Table in the cloud UI: sort, filter, group, etc. You can also expand the panel to open it in a Weave Board in order to iterate further/save and publish your work." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7f5447d2", + "metadata": {}, + "outputs": [], + "source": [ + "predictions = (weave.legacy.weave.ops.project(ENTITY, PROJECT)\n", + " .artifactType(ARTIFACT_TYPE)\n", + " .artifacts()[0]\n", + " .versions()[0]\n", + " .file(TABLE_FILE)\n", + " .table()\n", + " .rows())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e414990d", + "metadata": {}, + "outputs": [], + "source": [ + "predictions" + ] + }, + { + "cell_type": "markdown", + "id": "9ee223ef-1a97-46f6-9933-24cdb78d2488", + "metadata": {}, + "source": [ + "# Step 2: Configure a Weave Panel Group in code\n", + "\n", + "We write a function to create a group of panels in Weave:\n", + "* Group panel: this is a container to arrange a set of panels — in our case, in equal sizes horizontally\n", + "* Facet panel: this is the main 2D grid of the confusion matrix, showing the `truth` column (correct label) on the x-axis and the `guess` column (model's prediction) on the y-axis\n", + "* each cell of the Facet Panel is again a Group with two layers of panels: 1) a Number panel showing the total number of rows/model predictions in that cell of the confusion matrix, and 2) a background Color panel with the count from 1) rescaled on a blue hue, so the more saturated the blue, the more items in that cell\n", + "* a final Table panel to show the full rows/details of any selected cell from the main Facet panel." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a940dab4", + "metadata": {}, + "outputs": [], + "source": [ + "def confusion_matrix(table_data):\n", + " conf_mat = weave.legacy.weave.panels.Group(\n", + " equalSize=True,\n", + " preferHorizontal=True,\n", + " items={\n", + " 'confusion': weave.legacy.weave.panels.Facet(\n", + " table_data,\n", + " x=lambda row: row[\"truth\"],\n", + " y=lambda row: row[\"guess\"],\n", + " select=lambda row: weave.legacy.weave.panels.Group(\n", + " layoutMode='layer',\n", + " items={\n", + " 'count': row.count(),\n", + " 'color': weave.legacy.weave.panels.Color(row.count() / 50)\n", + " }\n", + " )\n", + " ),\n", + " 'selected': lambda confusion: confusion.selected()\n", + " }\n", + " )\n", + " return conf_mat" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ccf9a5a9-07b0-4967-a5ee-9255f9660ee3", + "metadata": {}, + "outputs": [], + "source": [ + "confusion_matrix(predictions)" + ] + }, + { + "cell_type": "markdown", + "id": "050f6119-7933-4084-9a9c-edb829c6c075", + "metadata": {}, + "source": [ + "# Step 3: Filter for incorrect predictions\n", + "\n", + "We can add a filter predicate to the Weave expression to select only the rows where the model's prediction doesn't match the correct label. Note that the highest-count / most-blue squares are absent in this version.\n", + "\n", + "Try opening this panel as a Weave Board by hovering over the right side and clicking \"Open in new tab\". You can explore more cells, add more panels, and share your work. Let us know if you find any interesting mistakes or patterns—for example, the mammal confused for an arachnid :)\n", + "\n", + "" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "75d50c33-9712-4ffe-9971-5552d32648bc", + "metadata": {}, + "outputs": [], + "source": [ + "mistakes_only = predictions.filter(lambda row: row[\"truth\"] != row[\"guess\"])\n", + "confusion_matrix(mistakes_only)" + ] + }, + { + "cell_type": "markdown", + "id": "9e4195fe-09cb-48e8-99a0-e01acf75e6c2", + "metadata": {}, + "source": [ + "# Bonus: Make a confusion matrix from the UI only\n", + "\n", + "To create a confusion matrix from the UI only:\n", + "1. Start with a Weave Table object saved with `weave.save()` and loaded into a panel with an expression of the form `get(\"wandb-artifact:///your_entity/your_project/obj:0123456789abcde/obj\")`.\n", + "2. Click the pencil \"Edit\" icon on the panel to open the panel config menu.\n", + "3. Change the Panel type to \"Facet\"—this is the main confusion matrix layout.\n", + "4. Set the X and Y axes for the intended confusion matrix, e.g to `row[\"truth\"]` and `row[\"guess\"]` for this example.\n", + "5. In the lower \"Properties\" section, change the child panel type from \"Expression\" to \"Group\", then change the layout from \"vertical\" to \"layer\" and select \"Add child\"—each child is a cell of the confusion matrix which \"groups\" or \"layers\" the count of items in that cell and the corresponding background color of the cell.\n", + "6. The \"Input\" of one child can be the count: enter `row.count` as the Weave expression. When you hit \"Run\", \"Panel type\" should update to \"Number\" and you should see numbers render in the confusion matrix panel.\n", + "7. Click \"Add Child\" and optionally add the cell background. Change \"Panel type\" to \"Color\" and enter `row.count / N` as the \"Input\", where N is some normalizing constant to scale your values from 0 for white to ~1.5 for the highest-saturation blue.\n", + "\n", + "Your settings menu should look something like this:\n", + "\n", + "" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "8544cf72", - "metadata": {}, - "outputs": [], - "source": [ - "# if not already installed\n", - "!pip install -qqq weave" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5b86972f-d8d7-4f5a-bf5a-9a6be887978c", - "metadata": {}, - "outputs": [], - "source": [ - "import wandb\n", - "wandb.login()\n", - "import weave\n", - "import weave.legacy.panels" - ] - }, - { - "cell_type": "markdown", - "id": "b35a8e31-3f51-43a9-bf89-543ed6fe62e8", - "metadata": {}, - "source": [ - "Use our public example or substitute your own W&B Tables by replacing the fields below. You can find the relevant information by navigating to a project in W&B, clicking on the \"Artifacts\" tab, and browsing using the sidebar until you find the artifact type and corresponding table file of interest (e.g. [this one used in the example](https://wandb.ai/stacey/mendeleev/artifacts/test_results/test_res_1fwmcd3q/v0/files/test_results.table.json)).\n", - "\n", - "**Note:** the index '0' after `artifacts()` and `versions()` will take the first element in those lists." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "01183f54-efa6-405a-be6a-142f75540913", - "metadata": {}, - "outputs": [], - "source": [ - "ENTITY = \"stacey\"\n", - "PROJECT = \"mendeleev\"\n", - "ARTIFACT_TYPE = \"test_results\"\n", - "TABLE_FILE = \"test_results.table.json\"" - ] - }, - { - "cell_type": "markdown", - "id": "2c910260-a5c0-4c99-bd00-1b9b95ddde54", - "metadata": {}, - "source": [ - "# Step 1: Compose Weave expression to load W&B Table\n", - "\n", - "Navigate the W&B object tree programmatically with Weave\n", - "* start with the specified W&B project\n", - "* fetch all artifacts of the specified type and take the first artifact\n", - "* fetch all the versions of that artifact and take the first one\n", - "* load the specified W&B Table file associated with that artifact version\n", - "* convert that file into a Weave table (with `.table.rows()`)\n", - "\n", - "The second cell below will display an interactive Weave Panel of the corresponding Table. You can interact with this panel in the notebook as you would with the underlying W&B Table in the cloud UI: sort, filter, group, etc. You can also expand the panel to open it in a Weave Board in order to iterate further/save and publish your work." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7f5447d2", - "metadata": {}, - "outputs": [], - "source": [ - "predictions = (weave.legacy.ops.project(ENTITY, PROJECT)\n", - " .artifactType(ARTIFACT_TYPE)\n", - " .artifacts()[0]\n", - " .versions()[0]\n", - " .file(TABLE_FILE)\n", - " .table()\n", - " .rows())" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e414990d", - "metadata": {}, - "outputs": [], - "source": [ - "predictions" - ] - }, - { - "cell_type": "markdown", - "id": "9ee223ef-1a97-46f6-9933-24cdb78d2488", - "metadata": {}, - "source": [ - "# Step 2: Configure a Weave Panel Group in code\n", - "\n", - "We write a function to create a group of panels in Weave:\n", - "* Group panel: this is a container to arrange a set of panels — in our case, in equal sizes horizontally\n", - "* Facet panel: this is the main 2D grid of the confusion matrix, showing the `truth` column (correct label) on the x-axis and the `guess` column (model's prediction) on the y-axis\n", - "* each cell of the Facet Panel is again a Group with two layers of panels: 1) a Number panel showing the total number of rows/model predictions in that cell of the confusion matrix, and 2) a background Color panel with the count from 1) rescaled on a blue hue, so the more saturated the blue, the more items in that cell\n", - "* a final Table panel to show the full rows/details of any selected cell from the main Facet panel." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a940dab4", - "metadata": {}, - "outputs": [], - "source": [ - "def confusion_matrix(table_data):\n", - " conf_mat = weave.legacy.panels.Group(\n", - " equalSize=True,\n", - " preferHorizontal=True,\n", - " items={\n", - " 'confusion': weave.legacy.panels.Facet(\n", - " table_data,\n", - " x=lambda row: row[\"truth\"],\n", - " y=lambda row: row[\"guess\"],\n", - " select=lambda row: weave.legacy.panels.Group(\n", - " layoutMode='layer',\n", - " items={\n", - " 'count': row.count(),\n", - " 'color': weave.legacy.panels.Color(row.count() / 50)\n", - " }\n", - " )\n", - " ),\n", - " 'selected': lambda confusion: confusion.selected()\n", - " }\n", - " )\n", - " return conf_mat" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ccf9a5a9-07b0-4967-a5ee-9255f9660ee3", - "metadata": {}, - "outputs": [], - "source": [ - "confusion_matrix(predictions)" - ] - }, - { - "cell_type": "markdown", - "id": "050f6119-7933-4084-9a9c-edb829c6c075", - "metadata": {}, - "source": [ - "# Step 3: Filter for incorrect predictions\n", - "\n", - "We can add a filter predicate to the Weave expression to select only the rows where the model's prediction doesn't match the correct label. Note that the highest-count / most-blue squares are absent in this version.\n", - "\n", - "Try opening this panel as a Weave Board by hovering over the right side and clicking \"Open in new tab\". You can explore more cells, add more panels, and share your work. Let us know if you find any interesting mistakes or patterns—for example, the mammal confused for an arachnid :)\n", - "\n", - "" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "75d50c33-9712-4ffe-9971-5552d32648bc", - "metadata": {}, - "outputs": [], - "source": [ - "mistakes_only = predictions.filter(lambda row: row[\"truth\"] != row[\"guess\"])\n", - "confusion_matrix(mistakes_only)" - ] - }, - { - "cell_type": "markdown", - "id": "9e4195fe-09cb-48e8-99a0-e01acf75e6c2", - "metadata": {}, - "source": [ - "# Bonus: Make a confusion matrix from the UI only\n", - "\n", - "To create a confusion matrix from the UI only:\n", - "1. Start with a Weave Table object saved with `weave.save()` and loaded into a panel with an expression of the form `get(\"wandb-artifact:///your_entity/your_project/obj:0123456789abcde/obj\")`.\n", - "2. Click the pencil \"Edit\" icon on the panel to open the panel config menu.\n", - "3. Change the Panel type to \"Facet\"—this is the main confusion matrix layout.\n", - "4. Set the X and Y axes for the intended confusion matrix, e.g to `row[\"truth\"]` and `row[\"guess\"]` for this example.\n", - "5. In the lower \"Properties\" section, change the child panel type from \"Expression\" to \"Group\", then change the layout from \"vertical\" to \"layer\" and select \"Add child\"—each child is a cell of the confusion matrix which \"groups\" or \"layers\" the count of items in that cell and the corresponding background color of the cell.\n", - "6. The \"Input\" of one child can be the count: enter `row.count` as the Weave expression. When you hit \"Run\", \"Panel type\" should update to \"Number\" and you should see numbers render in the confusion matrix panel.\n", - "7. Click \"Add Child\" and optionally add the cell background. Change \"Panel type\" to \"Color\" and enter `row.count / N` as the \"Input\", where N is some normalizing constant to scale your values from 0 for white to ~1.5 for the highest-saturation blue.\n", - "\n", - "Your settings menu should look something like this:\n", - "\n", - "" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/reference/control/Object Picker.ipynb b/weave/legacy/examples/reference/control/Object Picker.ipynb index 779f9eac812..abe0dca0244 100644 --- a/weave/legacy/examples/reference/control/Object Picker.ipynb +++ b/weave/legacy/examples/reference/control/Object Picker.ipynb @@ -1,121 +1,121 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "f9712d25", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "import weave.legacy.panels" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "f9712d25", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "import weave.legacy.weave.panels" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2a60bff3", + "metadata": {}, + "outputs": [], + "source": [ + "ints = weave.save([1, 2, 3])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2185cbbc", + "metadata": {}, + "outputs": [], + "source": [ + "panel = weave.legacy.weave.panels.Group(\n", + " showExpressions=False,\n", + " items={\n", + " \"a\": weave.legacy.weave.panels.ObjectPicker(ints, label=\"a\"),\n", + " \"b\": weave.legacy.weave.panels.ObjectPicker(ints, label=\"b\"),\n", + " \"panel\": lambda a, b: a.config.choice + b.config.choice\n", + " })\n", + "panel" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a0f2f998", + "metadata": {}, + "outputs": [], + "source": [ + "# A more complex example with sidebar\n", + "\n", + "# ints = weave.legacy.weave.ops.objects(weave.types.Int(), 'latest', 9)\n", + "# weave.use(ints[0])\n", + "ints = weave.save([1, 2, 3], name='ints:latest')\n", + "panel = weave.legacy.weave.panels.Group(\n", + " preferHorizontal=True,\n", + " equalSize=True,\n", + " items={\n", + " \"sidebar\": weave.legacy.weave.panels.Group(\n", + " items={\n", + " \"a\": weave.legacy.weave.panels.ObjectPicker(ints, label=\"A\"),\n", + " \"b\": weave.legacy.weave.panels.ObjectPicker(ints, label=\"B\")\n", + " }\n", + " ),\n", + " \"main\": lambda sidebar: weave.legacy.weave.panels.Group(\n", + " items={\n", + " \"choice_values\": weave.legacy.weave.panels.Group(\n", + " preferHorizontal=True,\n", + " style=\"height:150px\",\n", + " items={\n", + " 'choice_a': weave.legacy.weave.panels.LabeledItem(\n", + " label=\"A\",\n", + " item=sidebar.config.items['a'].config.choice.execute()\n", + " ),\n", + " 'choice_b': weave.legacy.weave.panels.LabeledItem(\n", + " label=\"B\",\n", + " item=sidebar.config.items['b'].config.choice.execute()\n", + " )\n", + " }\n", + " ),\n", + " \"aggregates\": weave.legacy.weave.panels.Group(\n", + " preferHorizontal=True,\n", + " style=\"height:150px\",\n", + " items={\n", + " 'sum': weave.legacy.weave.panels.LabeledItem(\n", + " label='sum',\n", + " item=sidebar.config.items['a'].config.choice + sidebar.config.items['b'].config.choice\n", + " ),\n", + " 'product': weave.legacy.weave.panels.LabeledItem(\n", + " label='product',\n", + " item=sidebar.config.items['a'].config.choice * sidebar.config.items['b'].config.choice\n", + " )\n", + " }\n", + " )\n", + " }\n", + " )\n", + " })\n", + "panel" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "2a60bff3", - "metadata": {}, - "outputs": [], - "source": [ - "ints = weave.save([1, 2, 3])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2185cbbc", - "metadata": {}, - "outputs": [], - "source": [ - "panel = weave.legacy.panels.Group(\n", - " showExpressions=False,\n", - " items={\n", - " \"a\": weave.legacy.panels.ObjectPicker(ints, label=\"a\"),\n", - " \"b\": weave.legacy.panels.ObjectPicker(ints, label=\"b\"),\n", - " \"panel\": lambda a, b: a.config.choice + b.config.choice\n", - " })\n", - "panel" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a0f2f998", - "metadata": {}, - "outputs": [], - "source": [ - "# A more complex example with sidebar\n", - "\n", - "# ints = weave.legacy.ops.objects(weave.types.Int(), 'latest', 9)\n", - "# weave.use(ints[0])\n", - "ints = weave.save([1, 2, 3], name='ints:latest')\n", - "panel = weave.legacy.panels.Group(\n", - " preferHorizontal=True,\n", - " equalSize=True,\n", - " items={\n", - " \"sidebar\": weave.legacy.panels.Group(\n", - " items={\n", - " \"a\": weave.legacy.panels.ObjectPicker(ints, label=\"A\"),\n", - " \"b\": weave.legacy.panels.ObjectPicker(ints, label=\"B\")\n", - " }\n", - " ),\n", - " \"main\": lambda sidebar: weave.legacy.panels.Group(\n", - " items={\n", - " \"choice_values\": weave.legacy.panels.Group(\n", - " preferHorizontal=True,\n", - " style=\"height:150px\",\n", - " items={\n", - " 'choice_a': weave.legacy.panels.LabeledItem(\n", - " label=\"A\",\n", - " item=sidebar.config.items['a'].config.choice.execute()\n", - " ),\n", - " 'choice_b': weave.legacy.panels.LabeledItem(\n", - " label=\"B\",\n", - " item=sidebar.config.items['b'].config.choice.execute()\n", - " )\n", - " }\n", - " ),\n", - " \"aggregates\": weave.legacy.panels.Group(\n", - " preferHorizontal=True,\n", - " style=\"height:150px\",\n", - " items={\n", - " 'sum': weave.legacy.panels.LabeledItem(\n", - " label='sum',\n", - " item=sidebar.config.items['a'].config.choice + sidebar.config.items['b'].config.choice\n", - " ),\n", - " 'product': weave.legacy.panels.LabeledItem(\n", - " label='product',\n", - " item=sidebar.config.items['a'].config.choice * sidebar.config.items['b'].config.choice\n", - " )\n", - " }\n", - " )\n", - " }\n", - " )\n", - " })\n", - "panel" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/reference/control/Slider.ipynb b/weave/legacy/examples/reference/control/Slider.ipynb index 434f22dddf9..43664e12d6d 100644 --- a/weave/legacy/examples/reference/control/Slider.ipynb +++ b/weave/legacy/examples/reference/control/Slider.ipynb @@ -1,75 +1,75 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "83fee798", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "from weave.legacy import panels" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "83fee798", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "from weave.legacy.weave import panels" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6c85e3b7", + "metadata": {}, + "outputs": [], + "source": [ + "# Uncontrolled: panel creates its own state slot\n", + "panel = panels.Group(\n", + " items={\n", + " \"my_slider\": panels.Slider(),\n", + " \"val\": lambda my_slider: my_slider.value()\n", + " })\n", + "panel" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0dd8dd51", + "metadata": {}, + "outputs": [], + "source": [ + "# Controlled: state is external to panel\n", + "\n", + "panel = panels.Group(\n", + " vars={'slider_val': 5},\n", + " items={\n", + " 'state_value': lambda slider_val: slider_val,\n", + " 'slider': lambda slider_val: panels.Group(\n", + " items={\n", + " \"my_slider\": panels.Slider(slider_val),\n", + " \"val\": lambda my_slider: my_slider.value(),\n", + " \"my_slider2\": panels.Slider(slider_val)\n", + " })\n", + " })\n", + "panel" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "6c85e3b7", - "metadata": {}, - "outputs": [], - "source": [ - "# Uncontrolled: panel creates its own state slot\n", - "panel = panels.Group(\n", - " items={\n", - " \"my_slider\": panels.Slider(),\n", - " \"val\": lambda my_slider: my_slider.value()\n", - " })\n", - "panel" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "0dd8dd51", - "metadata": {}, - "outputs": [], - "source": [ - "# Controlled: state is external to panel\n", - "\n", - "panel = panels.Group(\n", - " vars={'slider_val': 5},\n", - " items={\n", - " 'state_value': lambda slider_val: slider_val,\n", - " 'slider': lambda slider_val: panels.Group(\n", - " items={\n", - " \"my_slider\": panels.Slider(slider_val),\n", - " \"val\": lambda my_slider: my_slider.value(),\n", - " \"my_slider2\": panels.Slider(slider_val)\n", - " })\n", - " })\n", - "panel" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/reference/create_plots_ui_guide.ipynb b/weave/legacy/examples/reference/create_plots_ui_guide.ipynb index 468507e3b2e..faf00a0b6d3 100644 --- a/weave/legacy/examples/reference/create_plots_ui_guide.ipynb +++ b/weave/legacy/examples/reference/create_plots_ui_guide.ipynb @@ -1,330 +1,330 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "1305d15c-9677-4f65-8cd8-338d1cb7aa82", - "metadata": {}, - "source": [ - "# Weave Plot: Interactively visualize your data\n", - "\n", - "In this tutorial, we will visualize data with the **Weave Plot Panel**:\n", - "* load a Pandas DataFrame or other tabular data into Weave \n", - "* visualize your data as a 2D plot of (x, y) points with **Weave Plot**\n", - "* customize the plot to filter or annotate the data\n", - "\n", - "We use an example dataset of [notable machine learning models](https://docs.google.com/spreadsheets/d/1AAIebjNsnJj_uKALHbXNfn3_YsT6sHXtCU0q7OIPuc4/edit#gid=0) to get started—you can try your own CSV file, Pandas DataFrame, or any public Google Sheets url.\n", - "\n", - "# 0: Setup\n", - "Import dependencies & login to W&B to save your work and share any visualizations you create." - ] + "cells": [ + { + "cell_type": "markdown", + "id": "1305d15c-9677-4f65-8cd8-338d1cb7aa82", + "metadata": {}, + "source": [ + "# Weave Plot: Interactively visualize your data\n", + "\n", + "In this tutorial, we will visualize data with the **Weave Plot Panel**:\n", + "* load a Pandas DataFrame or other tabular data into Weave \n", + "* visualize your data as a 2D plot of (x, y) points with **Weave Plot**\n", + "* customize the plot to filter or annotate the data\n", + "\n", + "We use an example dataset of [notable machine learning models](https://docs.google.com/spreadsheets/d/1AAIebjNsnJj_uKALHbXNfn3_YsT6sHXtCU0q7OIPuc4/edit#gid=0) to get started—you can try your own CSV file, Pandas DataFrame, or any public Google Sheets url.\n", + "\n", + "# 0: Setup\n", + "Import dependencies & login to W&B to save your work and share any visualizations you create." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "43053b45-eed1-445c-8bbd-05f113302060", + "metadata": {}, + "outputs": [], + "source": [ + "!pip install -qqq weave\n", + "import pandas as pd" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0d5645e7", + "metadata": {}, + "outputs": [], + "source": [ + "import wandb\n", + "wandb.login()\n", + "import weave\n", + "from weave.legacy.weave.show import show" + ] + }, + { + "cell_type": "markdown", + "id": "cb79fff5-f4fd-45db-a48e-c8581e0e5ad1", + "metadata": {}, + "source": [ + "# 1: Load your data as an interactive table\n", + "\n", + "Load a sample dataset of notable ML publications (560 rows, 33 columns as of Aug 8 2023). Feel free to edit these variables to\n", + "* load in your own Pandas DataFrame\n", + "* load a different CSV file\n", + "* modify the Google Sheets URL and sheet id to work with a different public spreadsheet" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8cf0eddd", + "metadata": {}, + "outputs": [], + "source": [ + "GOOGLE_SHEETS_URL = \"https://docs.google.com/spreadsheets/d/1AAIebjNsnJj_uKALHbXNfn3_YsT6sHXtCU0q7OIPuc4\"\n", + "SHEET_ID = \"0\"\n", + "CSV_SOURCE = f\"{GOOGLE_SHEETS_URL}/export?format=csv&gid={SHEET_ID}\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c52f0700", + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv(CSV_SOURCE)\n", + "df.head()" + ] + }, + { + "cell_type": "markdown", + "id": "6e48d6d1-e935-4244-b9ea-500fdb18e0bd", + "metadata": {}, + "source": [ + "View an interactive panel with your data in one line [1]. As with any Weave Table Panel, you can sort or group by any column to explore and build some intuition for the dataset." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c1e62e5a-6a56-4581-a8e6-4f5d3bcc4d0e", + "metadata": {}, + "outputs": [], + "source": [ + "show(df)" + ] + }, + { + "cell_type": "markdown", + "id": "ad96850c-93e7-4b1f-a479-1e4f3655aebc", + "metadata": { + "scrolled": true + }, + "source": [ + "# 2: Plot the data in Weave\n", + "\n", + "You can convert any Weave Table into a **Weave Plot**. Change the panel type in the expression at the top of the panel from `table` to `plot`:\n", + "\n", + "\n", + "\n", + "Weave infers a reasonable view of your data based on the column types:\n", + "* two numerical columns x and y become the scatter plot axes\n", + "* each row is rendered as an (x, y) point on the resulting 2D grid, with a tooltip showing details on hover\n", + "* if available, the first string-type column becomes the label / the color shown in the legend.\n", + "\n", + "Before we dive into the detailed customization of a Weave Plot, how can we build with and iterate on this starter plot?\n", + "\n", + "## Full-screen a plot: Open as a Weave Board\n", + "\n", + "If you want more visual space or screen real estate to explore—zoom into details, zoom out for more context, iterate on multiple panel views in parallel—open any Weave Panel in a new browser tab. Mouse over the right-hand side and select \"Open in a new tab\"\n", + "\n", + "\n", + "## Multiple views in parallel: Refer to source data as you customize the plot\n", + "\n", + "Duplicate a panel so you can keep one copy in the `table` state and convert the second into a `plot`: click on the horizontal three-dot icon in the top right corner and select \"Duplicate\".\n", + "\n", + "\n", + "\n", + "## Resize one panel to adjust layout & iterate incrementally\n", + "\n", + "Combine these UX moves to iterate quickly on a neat layout: duplicate panels, resize one panel from a corner to a smaller portion of the grid to accommodate more panels, and independently modify individual panels until you're happy with the latest version.\n", + "\n", + "\n", + "Try the whole process starting from the single Table panel below:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b85268d4-ef89-4bf5-9aed-2b8650fcd701", + "metadata": {}, + "outputs": [], + "source": [ + "show(df)" + ] + }, + { + "cell_type": "markdown", + "id": "16cc1620-4d10-41a1-9220-55ca238d5015", + "metadata": {}, + "source": [ + "# 3. Explore a plot with zoom and interactive selection\n", + "\n", + "Interactively explore PanelPlot data with zoom and region highlighting (subset selection):\n", + "\n", + "## Zoom level: Click + drag to zoom into a seleted rectangle, double-click to reset\n", + "To zoom into a region of the plot:\n", + "* click on the magnifying glass icon in the bottom right corner\n", + "* click, hold, and drag to select a set of points—a gray rectangle shows the active selected region\n", + "* optionally repeat as you find new/different points of interest\n", + "* double-click anywhere on the plot area to reset to the original zoom level\n", + "\n", + "## Selected data: Use the .selected_data Weave op to show point details\n", + "To see the full row details for selected points:\n", + "* given one plot panel named `panelN`, create another `panelN+1` and enter `panelN.selected_data` as the new panel's expression. `PanelN+1` will now show any points highlighted in `panelN`\n", + "* to select points from `panelN`, first click on the pointer icon in the bottom right corner of `panelN`\n", + "* click, hold, and drag to select a set of points in `panelN`—a gray rectangle shows the active selected region\n", + "* view the full details for those points in panelN+1\n", + "\n", + "\n", + "\n", + "# 4. Customize Weave Plots: Choose columns or compose Weave expressions\n", + "\n", + "Weave plot panels for scatter, line, and bar charts share most of their configuration parameters. To customize a Weave Plot, click on the `Edit` pencil icon in the top right corner to open the settings menu.\n", + "\n", + "## X axis & Y axis\n", + "\n", + "Define the X and Y dimensions of a plot:\n", + "* choose a column from your source data:`row[\"your column name here\"]` (with helpful suggestions in the dropdown showing available column names as you type)\n", + "* further customize the Weave expression using arithmetic (`row[\"x\"] * 2`), combined columns (`row[\"a\"] + row[\"b\"]`), or more advanced Weave ops (`row[\"cost_per_month\"].avg`)\n", + "\n", + "Try modifying the X and Y of the starter plot: for example, is there a correlation between publication impact (citations) and compute costs? Try setting X = `row[\"Training compute cost (2020 USD)\"]` and Y = `row[\"Citations\"]`\n", + " \n", + "## Colors\n", + "\n", + "Point color is set by one of two input methods:\n", + "* default `Enter a Weave Expression` method: takes the [tableau10 color palette](https://vega.github.io/vega/docs/schemes/#tableau10) and cycles its 10 colors over the distinct values of the result of the Weave Expression, e.g the values of a string column. In our sample plot, the `Color` field defaults to `row[\"System\"]`, and the legend in the top right of the plot shows the [tableau10 colors]((https://vega.github.io/vega/docs/schemes/#tableau10)) repeating over the full list of unique \"System\" names in the source data. Try editing this to `row[\"Domain\"]` to see publication trends by field (the Games and Language models seem to have the highest compute costs).\n", + "* `Select via Dropdown` -> `Encode from series` : this option defaults to one blue color for a single series, and otherwise cycles through the same tableau10 color palette for multiple series\n", + "\n", + "## Tooltip\n", + "\n", + "The tooltip field determines the content displayed when the mouse hovers over a data point. This defaults to a subset of columns from the underlying Weave Table and can be configured via Weave Expression to select one or more columns and optionally link them with string literals for readability/formatting. The following expression might be a useful summary for our sample data to show the authors and date for each model in addition to the system name: `row[\"System\"] + \" - \" + row[\"Authors\"] + \"; \" + row[\"Publication date\"]`\n", + "\n", + "## Labels\n", + "\n", + "This menu (at the very bottom of the plot settings) optionally sets the titles of the X axis, Y axis, and Color legend to the provided text. In our sample, we might condense the X axis title to \"Compute cost\", expand the Color legend title as \"ML task type\", etc.\n", + "\n", + "Here is a [sample side-by-side Weave Board](https://weave.wandb.ai/?exp=get%28%0A++++%22wandb-artifact%3A%2F%2F%2Fstacey%2Fpivot%2Fdefault_plot_with_mods%3Alatest%2Fobj%22%29) of the default starter plot and the final state with all the above modifications (note that the tooltip appears to the bottom right of the cursor/corresponds to the point on the upper left corner of the textbox)\n", + "\n", + "\n", + "## Multiple series\n", + "\n", + "Use the \"New Series +\" button to add one or more series of points. You can treat each of the Series 1, 2, 3... in a plot as an independent group/collection of settings with a separate instance of the specifications described above. When a plot contains multiple series, all of the series are overlayed/rendered on the same plot area when visualized and their settings combined in the legend/titles/etc. With our sample dataset, we may want to configure a different series/visual settings for each domain: language models in one series, computer vision in another, etc.\n", + "\n", + "## Advanced configuration\n", + "\n", + "### Switch linear scale to log scale\n", + "\n", + "There are two ways to convert a plot axis to log scale:\n", + "\n", + "1. Use the **Advanced properties editor**: click the pencil \"edit\" icon on a plot to expand the config menu on the right, then select \"Advanced properties\" at the end of the first 'Properties\" section. Set x- and y- axes to be log scale instead of linear in the dropdown menu.\n", + "\n", + "2. Convert the Weave expression to **log base 10 mathematically**: e.g. convert `row[\"Parameters\"]` to `row[\"Parameters\"] ** 0.1`. This will not adust the grid scale markers like the first option, but it will apply to any expression/dimension (not only x- and y- axes) and can be easier to try in the flow of editing charts.\n", + "\n", + "\n", + "### Filter source data to remove outliers\n", + "\n", + "Sometimes a log scale or zooming in is still insufficient. You can remove outliers by filtering the input data based on a range of column values. Use the `.filter` Weave op on the `Input` field to plot only the points that meet the specified condition. For example, compare the default starter plot with dropping any models that have >= 1e12 parameters:\n", + "\n", + "\n", + "Try editing some of these settings from the Table below:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4b56735b-f35f-4bb7-bcb6-ce315a16ba30", + "metadata": {}, + "outputs": [], + "source": [ + "show(df)" + ] + }, + { + "cell_type": "markdown", + "id": "dd71e9f7-9c37-440b-8acf-7997baa60065", + "metadata": {}, + "source": [ + "# 5. Scatter plot: Customize point shape and size via explicit assignment or enumeration over option list\n", + "\n", + "The `Mark` setting intially determines the plot style: scatter plot, line plot, bar chart, etc. This defaults to \"auto\" and picks the best option based on the incoming data types. If `Mark` is set explicitly to `point`, this reveals controls for the shape and size of the points.\n", + "\n", + "## Point shape\n", + "\n", + "* defaults to \"Enter a Weave Expression\": as with the other config fields, write a Weave Expression that returns a list, where each distinct option in that list will cycle throught the built-in list of shape options\n", + "* \"Select via dropdown\" -> \"circle\", \"square\", \"cross\", \"diamond\", etc: this input method sets a specific literal point shape from the list of available options\n", + "* \"Select via dropdown\" -> \"Encode from series\": cycle the shape options over the multiple series in the plot\n", + "\n", + "In our example scenario, we could look at how compute sponsorship compares for notable papers: set `Shape` to `row[\"Compute Sponsor Categorization\"]` and observe circles for academia and squares for industry.\n", + "\n", + "## Point size (with approximately-bucketed enumeration)\n", + "\n", + "* default 100 / user-specified number: point size for scatter plots defaults to 100 and can be set to any other numerical value [2]\n", + "* Weave expression: as in other settings, the list of distinct values resulting from the user-specified Weave expression will cycle through five perceptually-distinguishable point sizes from smallest to larges\n", + "\n", + "In this sample plot, try log-scaling point size with compute costs: set `Size` to `row[\"Training compute cost (2020 USD)\"] ** 0.1`. \n", + "\n", + "### Combining all of these suggestions\n", + "\n", + "Here's a static view of the original plot with the modifications described—one more chance to try the fully-interactive and customizable version below\n", + "" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "06b8483f-1db0-4c2d-a27d-e0592a6ce160", + "metadata": {}, + "outputs": [], + "source": [ + "show(df)" + ] + }, + { + "cell_type": "markdown", + "id": "cfc8055c-0406-4b4c-a545-11f8c870d2d4", + "metadata": {}, + "source": [ + "# 6. Inspiration for many possible data exploration workflows\n", + "\n", + "Weave is a maximally general toolkit, and the path of any interactive visual exploration will depend on the data, context, interests, goals, etc. We've described the main options and useful features of Weave Plot to both illustrate concrete steps and hopefully spark your own questions and insights. In follow-up tutorials, we will cover settings specific to line plots and bar charts. We'd love to hear if you discover something interesting in this or your own iterations!\n", + "\n", + "# 7. End notes\n", + "\n", + "## [1] Viewing data in Weave\n", + "\n", + "When starting with a Pandas DataFrame, you have two options for getting data into Weave:\n", + "\n", + "### weave.show(my_dataframe)\n", + "\n", + "`weave.show(my_dataframe)` returns an interactive Weave Panel with the Pandas DataFrame as a Table. This is the fastest and simplest way to load an interactive panel with your data.\n", + "\n", + "### weave.save(weave.from_pandas(my_dataframe), name=\"my_dataframe\")\n", + "\n", + "If you'd like to save the DataFrame as a local object, first wrap it a in format Weave can parse using the `weave.from_pandas` op:\n", + "\n", + "```python\n", + "my_data = weave.save(weave.from_pandas(dataframe), name=\"my_dataframe\")\n", + "my_data\n", + "```\n", + "\n", + "## [2] Configuring point size\n", + "\n", + "Point size is currently \"perceptually clamped\" to around five distinguishable sizes: tiny, small, medium, larger, largest. Increasing/decreasing the literal number will not perceptually increase the biggest points or add more perceptible gradations of size. It may make the smallest points effectively invisible." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "43053b45-eed1-445c-8bbd-05f113302060", - "metadata": {}, - "outputs": [], - "source": [ - "!pip install -qqq weave\n", - "import pandas as pd" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "0d5645e7", - "metadata": {}, - "outputs": [], - "source": [ - "import wandb\n", - "wandb.login()\n", - "import weave\n", - "from weave.legacy.show import show" - ] - }, - { - "cell_type": "markdown", - "id": "cb79fff5-f4fd-45db-a48e-c8581e0e5ad1", - "metadata": {}, - "source": [ - "# 1: Load your data as an interactive table\n", - "\n", - "Load a sample dataset of notable ML publications (560 rows, 33 columns as of Aug 8 2023). Feel free to edit these variables to\n", - "* load in your own Pandas DataFrame\n", - "* load a different CSV file\n", - "* modify the Google Sheets URL and sheet id to work with a different public spreadsheet" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8cf0eddd", - "metadata": {}, - "outputs": [], - "source": [ - "GOOGLE_SHEETS_URL = \"https://docs.google.com/spreadsheets/d/1AAIebjNsnJj_uKALHbXNfn3_YsT6sHXtCU0q7OIPuc4\"\n", - "SHEET_ID = \"0\"\n", - "CSV_SOURCE = f\"{GOOGLE_SHEETS_URL}/export?format=csv&gid={SHEET_ID}\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c52f0700", - "metadata": {}, - "outputs": [], - "source": [ - "df = pd.read_csv(CSV_SOURCE)\n", - "df.head()" - ] - }, - { - "cell_type": "markdown", - "id": "6e48d6d1-e935-4244-b9ea-500fdb18e0bd", - "metadata": {}, - "source": [ - "View an interactive panel with your data in one line [1]. As with any Weave Table Panel, you can sort or group by any column to explore and build some intuition for the dataset." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c1e62e5a-6a56-4581-a8e6-4f5d3bcc4d0e", - "metadata": {}, - "outputs": [], - "source": [ - "show(df)" - ] - }, - { - "cell_type": "markdown", - "id": "ad96850c-93e7-4b1f-a479-1e4f3655aebc", - "metadata": { - "scrolled": true - }, - "source": [ - "# 2: Plot the data in Weave\n", - "\n", - "You can convert any Weave Table into a **Weave Plot**. Change the panel type in the expression at the top of the panel from `table` to `plot`:\n", - "\n", - "\n", - "\n", - "Weave infers a reasonable view of your data based on the column types:\n", - "* two numerical columns x and y become the scatter plot axes\n", - "* each row is rendered as an (x, y) point on the resulting 2D grid, with a tooltip showing details on hover\n", - "* if available, the first string-type column becomes the label / the color shown in the legend.\n", - "\n", - "Before we dive into the detailed customization of a Weave Plot, how can we build with and iterate on this starter plot?\n", - "\n", - "## Full-screen a plot: Open as a Weave Board\n", - "\n", - "If you want more visual space or screen real estate to explore—zoom into details, zoom out for more context, iterate on multiple panel views in parallel—open any Weave Panel in a new browser tab. Mouse over the right-hand side and select \"Open in a new tab\"\n", - "\n", - "\n", - "## Multiple views in parallel: Refer to source data as you customize the plot\n", - "\n", - "Duplicate a panel so you can keep one copy in the `table` state and convert the second into a `plot`: click on the horizontal three-dot icon in the top right corner and select \"Duplicate\".\n", - "\n", - "\n", - "\n", - "## Resize one panel to adjust layout & iterate incrementally\n", - "\n", - "Combine these UX moves to iterate quickly on a neat layout: duplicate panels, resize one panel from a corner to a smaller portion of the grid to accommodate more panels, and independently modify individual panels until you're happy with the latest version.\n", - "\n", - "\n", - "Try the whole process starting from the single Table panel below:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b85268d4-ef89-4bf5-9aed-2b8650fcd701", - "metadata": {}, - "outputs": [], - "source": [ - "show(df)" - ] - }, - { - "cell_type": "markdown", - "id": "16cc1620-4d10-41a1-9220-55ca238d5015", - "metadata": {}, - "source": [ - "# 3. Explore a plot with zoom and interactive selection\n", - "\n", - "Interactively explore PanelPlot data with zoom and region highlighting (subset selection):\n", - "\n", - "## Zoom level: Click + drag to zoom into a seleted rectangle, double-click to reset\n", - "To zoom into a region of the plot:\n", - "* click on the magnifying glass icon in the bottom right corner\n", - "* click, hold, and drag to select a set of points—a gray rectangle shows the active selected region\n", - "* optionally repeat as you find new/different points of interest\n", - "* double-click anywhere on the plot area to reset to the original zoom level\n", - "\n", - "## Selected data: Use the .selected_data Weave op to show point details\n", - "To see the full row details for selected points:\n", - "* given one plot panel named `panelN`, create another `panelN+1` and enter `panelN.selected_data` as the new panel's expression. `PanelN+1` will now show any points highlighted in `panelN`\n", - "* to select points from `panelN`, first click on the pointer icon in the bottom right corner of `panelN`\n", - "* click, hold, and drag to select a set of points in `panelN`—a gray rectangle shows the active selected region\n", - "* view the full details for those points in panelN+1\n", - "\n", - "\n", - "\n", - "# 4. Customize Weave Plots: Choose columns or compose Weave expressions\n", - "\n", - "Weave plot panels for scatter, line, and bar charts share most of their configuration parameters. To customize a Weave Plot, click on the `Edit` pencil icon in the top right corner to open the settings menu.\n", - "\n", - "## X axis & Y axis\n", - "\n", - "Define the X and Y dimensions of a plot:\n", - "* choose a column from your source data:`row[\"your column name here\"]` (with helpful suggestions in the dropdown showing available column names as you type)\n", - "* further customize the Weave expression using arithmetic (`row[\"x\"] * 2`), combined columns (`row[\"a\"] + row[\"b\"]`), or more advanced Weave ops (`row[\"cost_per_month\"].avg`)\n", - "\n", - "Try modifying the X and Y of the starter plot: for example, is there a correlation between publication impact (citations) and compute costs? Try setting X = `row[\"Training compute cost (2020 USD)\"]` and Y = `row[\"Citations\"]`\n", - " \n", - "## Colors\n", - "\n", - "Point color is set by one of two input methods:\n", - "* default `Enter a Weave Expression` method: takes the [tableau10 color palette](https://vega.github.io/vega/docs/schemes/#tableau10) and cycles its 10 colors over the distinct values of the result of the Weave Expression, e.g the values of a string column. In our sample plot, the `Color` field defaults to `row[\"System\"]`, and the legend in the top right of the plot shows the [tableau10 colors]((https://vega.github.io/vega/docs/schemes/#tableau10)) repeating over the full list of unique \"System\" names in the source data. Try editing this to `row[\"Domain\"]` to see publication trends by field (the Games and Language models seem to have the highest compute costs).\n", - "* `Select via Dropdown` -> `Encode from series` : this option defaults to one blue color for a single series, and otherwise cycles through the same tableau10 color palette for multiple series\n", - "\n", - "## Tooltip\n", - "\n", - "The tooltip field determines the content displayed when the mouse hovers over a data point. This defaults to a subset of columns from the underlying Weave Table and can be configured via Weave Expression to select one or more columns and optionally link them with string literals for readability/formatting. The following expression might be a useful summary for our sample data to show the authors and date for each model in addition to the system name: `row[\"System\"] + \" - \" + row[\"Authors\"] + \"; \" + row[\"Publication date\"]`\n", - "\n", - "## Labels\n", - "\n", - "This menu (at the very bottom of the plot settings) optionally sets the titles of the X axis, Y axis, and Color legend to the provided text. In our sample, we might condense the X axis title to \"Compute cost\", expand the Color legend title as \"ML task type\", etc.\n", - "\n", - "Here is a [sample side-by-side Weave Board](https://weave.wandb.ai/?exp=get%28%0A++++%22wandb-artifact%3A%2F%2F%2Fstacey%2Fpivot%2Fdefault_plot_with_mods%3Alatest%2Fobj%22%29) of the default starter plot and the final state with all the above modifications (note that the tooltip appears to the bottom right of the cursor/corresponds to the point on the upper left corner of the textbox)\n", - "\n", - "\n", - "## Multiple series\n", - "\n", - "Use the \"New Series +\" button to add one or more series of points. You can treat each of the Series 1, 2, 3... in a plot as an independent group/collection of settings with a separate instance of the specifications described above. When a plot contains multiple series, all of the series are overlayed/rendered on the same plot area when visualized and their settings combined in the legend/titles/etc. With our sample dataset, we may want to configure a different series/visual settings for each domain: language models in one series, computer vision in another, etc.\n", - "\n", - "## Advanced configuration\n", - "\n", - "### Switch linear scale to log scale\n", - "\n", - "There are two ways to convert a plot axis to log scale:\n", - "\n", - "1. Use the **Advanced properties editor**: click the pencil \"edit\" icon on a plot to expand the config menu on the right, then select \"Advanced properties\" at the end of the first 'Properties\" section. Set x- and y- axes to be log scale instead of linear in the dropdown menu.\n", - "\n", - "2. Convert the Weave expression to **log base 10 mathematically**: e.g. convert `row[\"Parameters\"]` to `row[\"Parameters\"] ** 0.1`. This will not adust the grid scale markers like the first option, but it will apply to any expression/dimension (not only x- and y- axes) and can be easier to try in the flow of editing charts.\n", - "\n", - "\n", - "### Filter source data to remove outliers\n", - "\n", - "Sometimes a log scale or zooming in is still insufficient. You can remove outliers by filtering the input data based on a range of column values. Use the `.filter` Weave op on the `Input` field to plot only the points that meet the specified condition. For example, compare the default starter plot with dropping any models that have >= 1e12 parameters:\n", - "\n", - "\n", - "Try editing some of these settings from the Table below:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4b56735b-f35f-4bb7-bcb6-ce315a16ba30", - "metadata": {}, - "outputs": [], - "source": [ - "show(df)" - ] - }, - { - "cell_type": "markdown", - "id": "dd71e9f7-9c37-440b-8acf-7997baa60065", - "metadata": {}, - "source": [ - "# 5. Scatter plot: Customize point shape and size via explicit assignment or enumeration over option list\n", - "\n", - "The `Mark` setting intially determines the plot style: scatter plot, line plot, bar chart, etc. This defaults to \"auto\" and picks the best option based on the incoming data types. If `Mark` is set explicitly to `point`, this reveals controls for the shape and size of the points.\n", - "\n", - "## Point shape\n", - "\n", - "* defaults to \"Enter a Weave Expression\": as with the other config fields, write a Weave Expression that returns a list, where each distinct option in that list will cycle throught the built-in list of shape options\n", - "* \"Select via dropdown\" -> \"circle\", \"square\", \"cross\", \"diamond\", etc: this input method sets a specific literal point shape from the list of available options\n", - "* \"Select via dropdown\" -> \"Encode from series\": cycle the shape options over the multiple series in the plot\n", - "\n", - "In our example scenario, we could look at how compute sponsorship compares for notable papers: set `Shape` to `row[\"Compute Sponsor Categorization\"]` and observe circles for academia and squares for industry.\n", - "\n", - "## Point size (with approximately-bucketed enumeration)\n", - "\n", - "* default 100 / user-specified number: point size for scatter plots defaults to 100 and can be set to any other numerical value [2]\n", - "* Weave expression: as in other settings, the list of distinct values resulting from the user-specified Weave expression will cycle through five perceptually-distinguishable point sizes from smallest to larges\n", - "\n", - "In this sample plot, try log-scaling point size with compute costs: set `Size` to `row[\"Training compute cost (2020 USD)\"] ** 0.1`. \n", - "\n", - "### Combining all of these suggestions\n", - "\n", - "Here's a static view of the original plot with the modifications described—one more chance to try the fully-interactive and customizable version below\n", - "" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "06b8483f-1db0-4c2d-a27d-e0592a6ce160", - "metadata": {}, - "outputs": [], - "source": [ - "show(df)" - ] - }, - { - "cell_type": "markdown", - "id": "cfc8055c-0406-4b4c-a545-11f8c870d2d4", - "metadata": {}, - "source": [ - "# 6. Inspiration for many possible data exploration workflows\n", - "\n", - "Weave is a maximally general toolkit, and the path of any interactive visual exploration will depend on the data, context, interests, goals, etc. We've described the main options and useful features of Weave Plot to both illustrate concrete steps and hopefully spark your own questions and insights. In follow-up tutorials, we will cover settings specific to line plots and bar charts. We'd love to hear if you discover something interesting in this or your own iterations!\n", - "\n", - "# 7. End notes\n", - "\n", - "## [1] Viewing data in Weave\n", - "\n", - "When starting with a Pandas DataFrame, you have two options for getting data into Weave:\n", - "\n", - "### weave.show(my_dataframe)\n", - "\n", - "`weave.show(my_dataframe)` returns an interactive Weave Panel with the Pandas DataFrame as a Table. This is the fastest and simplest way to load an interactive panel with your data.\n", - "\n", - "### weave.save(weave.from_pandas(my_dataframe), name=\"my_dataframe\")\n", - "\n", - "If you'd like to save the DataFrame as a local object, first wrap it a in format Weave can parse using the `weave.from_pandas` op:\n", - "\n", - "```python\n", - "my_data = weave.save(weave.from_pandas(dataframe), name=\"my_dataframe\")\n", - "my_data\n", - "```\n", - "\n", - "## [2] Configuring point size\n", - "\n", - "Point size is currently \"perceptually clamped\" to around five distinguishable sizes: tiny, small, medium, larger, largest. Increasing/decreasing the literal number will not perceptually increase the biggest points or add more perceptible gradations of size. It may make the smallest points effectively invisible." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/reference/layout/Each.ipynb b/weave/legacy/examples/reference/layout/Each.ipynb index 17248f033d2..87429d18843 100644 --- a/weave/legacy/examples/reference/layout/Each.ipynb +++ b/weave/legacy/examples/reference/layout/Each.ipynb @@ -1,70 +1,70 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "4093cfd3", - "metadata": {}, - "outputs": [], - "source": [ - "from PIL import Image\n", - "import weave\n", - "from weave.legacy.scripts import syndata\n", - "from weave.legacy import panels" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "4093cfd3", + "metadata": {}, + "outputs": [], + "source": [ + "from PIL import Image\n", + "import weave\n", + "from weave.legacy.scripts import syndata\n", + "from weave.legacy.weave import panels" + ] + }, + { + "cell_type": "markdown", + "id": "b05e49a1", + "metadata": {}, + "source": [ + "## PanelEach\n", + "\n", + "PanelEach renders each item in a list.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b2cc5af5", + "metadata": {}, + "outputs": [], + "source": [ + "data = weave.save(syndata.random_metrics(100, 100))\n", + "panels.Each(data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "36755a04", + "metadata": {}, + "outputs": [], + "source": [ + "ims = weave.save([Image.linear_gradient(\"L\").rotate(i * 4) for i in range(100)])\n", + "panels.Each(ims)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "markdown", - "id": "b05e49a1", - "metadata": {}, - "source": [ - "## PanelEach\n", - "\n", - "PanelEach renders each item in a list.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b2cc5af5", - "metadata": {}, - "outputs": [], - "source": [ - "data = weave.save(syndata.random_metrics(100, 100))\n", - "panels.Each(data)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "36755a04", - "metadata": {}, - "outputs": [], - "source": [ - "ims = weave.save([Image.linear_gradient(\"L\").rotate(i * 4) for i in range(100)])\n", - "panels.Each(ims)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/reference/layout/Group & LabeledItem.ipynb b/weave/legacy/examples/reference/layout/Group & LabeledItem.ipynb index 8f59c238d43..890e9b76bd3 100644 --- a/weave/legacy/examples/reference/layout/Group & LabeledItem.ipynb +++ b/weave/legacy/examples/reference/layout/Group & LabeledItem.ipynb @@ -1,48 +1,48 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "2e4a39ce", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "import weave.legacy.panels" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "2e4a39ce", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "import weave.legacy.weave.panels" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "32953f12", + "metadata": {}, + "outputs": [], + "source": [ + "# Group example\n", + "weave.legacy.weave.panels.Group(\n", + " items={\n", + " '0': weave.legacy.weave.panels.Group(\n", + " preferHorizontal=True,\n", + " items={\n", + " '0': weave.legacy.weave.panels.LabeledItem(item='item1', label='label1'),\n", + " '1': weave.legacy.weave.panels.LabeledItem(item='item2', label='label2'),\n", + " '2': weave.legacy.weave.panels.LabeledItem(item='item3', label='label3'),\n", + " }\n", + " ),\n", + " '1': weave.legacy.weave.panels.LabeledItem(item='item4', label='label4'),\n", + " '2': weave.legacy.weave.panels.LabeledItem(item='item5', label='label5')\n", + " }\n", + ")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "32953f12", - "metadata": {}, - "outputs": [], - "source": [ - "# Group example\n", - "weave.legacy.panels.Group(\n", - " items={\n", - " '0': weave.legacy.panels.Group(\n", - " preferHorizontal=True,\n", - " items={\n", - " '0': weave.legacy.panels.LabeledItem(item='item1', label='label1'),\n", - " '1': weave.legacy.panels.LabeledItem(item='item2', label='label2'),\n", - " '2': weave.legacy.panels.LabeledItem(item='item3', label='label3'),\n", - " }\n", - " ),\n", - " '1': weave.legacy.panels.LabeledItem(item='item4', label='label4'),\n", - " '2': weave.legacy.panels.LabeledItem(item='item5', label='label5')\n", - " }\n", - ")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/reference/markdown.ipynb b/weave/legacy/examples/reference/markdown.ipynb index ee612bac66e..a047c4186fb 100644 --- a/weave/legacy/examples/reference/markdown.ipynb +++ b/weave/legacy/examples/reference/markdown.ipynb @@ -1,50 +1,50 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "9357be91", - "metadata": {}, - "outputs": [], - "source": [ - "import weave" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "9357be91", + "metadata": {}, + "outputs": [], + "source": [ + "import weave" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "42e421dd", + "metadata": {}, + "outputs": [], + "source": [ + "weave.legacy.weave.panels.Board(\n", + " vars={},\n", + " panels=[weave.legacy.weave.panels.BoardPanel(\n", + " weave.legacy.weave.panels.PanelString(\"## I am markdown\\n\\nHear me roar\", mode=\"markdown\"),\n", + " id='some_markdown')\n", + " ])" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "42e421dd", - "metadata": {}, - "outputs": [], - "source": [ - "weave.legacy.panels.Board(\n", - " vars={},\n", - " panels=[weave.legacy.panels.BoardPanel(\n", - " weave.legacy.panels.PanelString(\"## I am markdown\\n\\nHear me roar\", mode=\"markdown\"),\n", - " id='some_markdown')\n", - " ])" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/reference/panels/plot/synced_axes.ipynb b/weave/legacy/examples/reference/panels/plot/synced_axes.ipynb index 6db386cf402..ed3d030632d 100644 --- a/weave/legacy/examples/reference/panels/plot/synced_axes.ipynb +++ b/weave/legacy/examples/reference/panels/plot/synced_axes.ipynb @@ -1,153 +1,153 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "f1022622", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "import weave.legacy.panels" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "f1022622", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "import weave.legacy.weave.panels" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "af978245", + "metadata": {}, + "outputs": [], + "source": [ + "from weave.legacy.scripts import syndata" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4a2a4713", + "metadata": {}, + "outputs": [], + "source": [ + "data = weave.save(syndata.random_metrics(100, 100))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "85e9d219", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "from weave.legacy.weave import ops_arrow\n", + "from weave.legacy.weave.ecosystem import wandb\n", + "import datetime\n", + "import random\n", + "random.seed(1)\n", + "\n", + "min_x = datetime.datetime(2023, 3, 22, 11, 0, 0)\n", + "max_x = min_x + datetime.timedelta(hours=1)\n", + "\n", + "users = ['nick', 'shawn', 'stacey', 'tim', 'danny']\n", + "model_versions = ['v1', 'v2']\n", + "\n", + "num_requests = 100\n", + "\n", + "def random_datetime_in_range() -> datetime.datetime:\n", + " min_timestamp = min_x.timestamp()\n", + " max_timestamp = max_x.timestamp()\n", + " random_timestamp = random.uniform(min_timestamp, max_timestamp)\n", + " return datetime.datetime.fromtimestamp(random_timestamp)\n", + "\n", + "def random_suggestion(n: int) -> str:\n", + " result = ''\n", + " for i in range(n):\n", + " result += random.choice('abcdefghijklmnopqrstuvwxyz')\n", + " return result\n", + "\n", + "\n", + "items = weave.save(\n", + " ops_arrow.to_arrow(sorted([\n", + " {\n", + " \"pred\": random_suggestion(7),\n", + " \"time\": random_datetime_in_range(),\n", + " \"user\": random.choice(users),\n", + " \"version\": random.choice(model_versions),\n", + " \"accepted\": random.choice([1, 1, 1, 0, 0]),\n", + " \"metric\": random.uniform(0, 1)\n", + " } \n", + " for _ in range(num_requests)\n", + " ], key=lambda d: d['time']))\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3d5919ee", + "metadata": {}, + "outputs": [], + "source": [ + "from weave.legacy.weave.panels.panel_plot import Signals, AxisSelections, Plot\n", + "from weave.legacy.weave import weave_internal\n", + "\n", + "\n", + "domain_node = weave_internal.const(None)\n", + "#domain_node = weave_internal.save(None)\n", + "\n", + "board = weave.legacy.weave.panels.Board(\n", + " vars={\n", + " 'predictions': items,\n", + " 'domain': domain_node,\n", + " },\n", + " panels=[\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, domain: Plot(\n", + " predictions,\n", + " x=lambda row: row[\"time\"],\n", + " y=lambda row: row[\"metric\"],\n", + " label=lambda row: row['user'],\n", + " mark=\"point\",\n", + " domain_x=domain,\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=12, h=12)\n", + " ),\n", + " weave.legacy.weave.panels.BoardPanel(\n", + " lambda predictions, domain: Plot(\n", + " predictions,\n", + " x=lambda row: row[\"time\"],\n", + " y=lambda row: row[\"metric\"] * 2,\n", + " label=lambda row: row['version'],\n", + " mark=\"point\",\n", + " domain_x=domain,\n", + " ),\n", + " layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=12, h=12)\n", + " ), \n", + " ]\n", + ")\n", + "board" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "af978245", - "metadata": {}, - "outputs": [], - "source": [ - "from weave.legacy.scripts import syndata" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4a2a4713", - "metadata": {}, - "outputs": [], - "source": [ - "data = weave.save(syndata.random_metrics(100, 100))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "85e9d219", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "from weave.legacy import ops_arrow\n", - "from weave.legacy.ecosystem import wandb\n", - "import datetime\n", - "import random\n", - "random.seed(1)\n", - "\n", - "min_x = datetime.datetime(2023, 3, 22, 11, 0, 0)\n", - "max_x = min_x + datetime.timedelta(hours=1)\n", - "\n", - "users = ['nick', 'shawn', 'stacey', 'tim', 'danny']\n", - "model_versions = ['v1', 'v2']\n", - "\n", - "num_requests = 100\n", - "\n", - "def random_datetime_in_range() -> datetime.datetime:\n", - " min_timestamp = min_x.timestamp()\n", - " max_timestamp = max_x.timestamp()\n", - " random_timestamp = random.uniform(min_timestamp, max_timestamp)\n", - " return datetime.datetime.fromtimestamp(random_timestamp)\n", - "\n", - "def random_suggestion(n: int) -> str:\n", - " result = ''\n", - " for i in range(n):\n", - " result += random.choice('abcdefghijklmnopqrstuvwxyz')\n", - " return result\n", - "\n", - "\n", - "items = weave.save(\n", - " ops_arrow.to_arrow(sorted([\n", - " {\n", - " \"pred\": random_suggestion(7),\n", - " \"time\": random_datetime_in_range(),\n", - " \"user\": random.choice(users),\n", - " \"version\": random.choice(model_versions),\n", - " \"accepted\": random.choice([1, 1, 1, 0, 0]),\n", - " \"metric\": random.uniform(0, 1)\n", - " } \n", - " for _ in range(num_requests)\n", - " ], key=lambda d: d['time']))\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3d5919ee", - "metadata": {}, - "outputs": [], - "source": [ - "from weave.legacy.panels.panel_plot import Signals, AxisSelections, Plot\n", - "from weave.legacy import weave_internal\n", - "\n", - "\n", - "domain_node = weave_internal.const(None)\n", - "#domain_node = weave_internal.save(None)\n", - "\n", - "board = weave.legacy.panels.Board(\n", - " vars={\n", - " 'predictions': items,\n", - " 'domain': domain_node,\n", - " },\n", - " panels=[\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, domain: Plot(\n", - " predictions,\n", - " x=lambda row: row[\"time\"],\n", - " y=lambda row: row[\"metric\"],\n", - " label=lambda row: row['user'],\n", - " mark=\"point\",\n", - " domain_x=domain,\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=12, h=12)\n", - " ),\n", - " weave.legacy.panels.BoardPanel(\n", - " lambda predictions, domain: Plot(\n", - " predictions,\n", - " x=lambda row: row[\"time\"],\n", - " y=lambda row: row[\"metric\"] * 2,\n", - " label=lambda row: row['version'],\n", - " mark=\"point\",\n", - " domain_x=domain,\n", - " ),\n", - " layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=12, h=12)\n", - " ), \n", - " ]\n", - ")\n", - "board" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/reference/vis/Distribution.ipynb b/weave/legacy/examples/reference/vis/Distribution.ipynb index 3248599762f..ea96aa5fc5a 100644 --- a/weave/legacy/examples/reference/vis/Distribution.ipynb +++ b/weave/legacy/examples/reference/vis/Distribution.ipynb @@ -1,138 +1,138 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "726127b0", - "metadata": {}, - "outputs": [], - "source": [ - "import random\n", - "import weave\n", - "# Weave package now defaults to eager mode, but lazy mode required for this example notebook for now.\\n\n", - "weave.use_lazy_execution()\n", - "from weave.legacy.ecosystem import wandb" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "726127b0", + "metadata": {}, + "outputs": [], + "source": [ + "import random\n", + "import weave\n", + "# Weave package now defaults to eager mode, but lazy mode required for this example notebook for now.\\n\n", + "weave.use_lazy_execution()\n", + "from weave.legacy.weave.ecosystem import wandb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a9875d92", + "metadata": {}, + "outputs": [], + "source": [ + "items = weave.save([\n", + " {'name': 'x',\n", + " 'loss1': [random.gauss(5, 2) for i in range(500)],\n", + " 'loss2': [random.gauss(5, 2) for i in range(500)],\n", + " 'str_val': [random.choice(['a', 'b', 'c']) for i in range(500)]},\n", + " {'name': 'y',\n", + " 'loss1': [random.gauss(9, 4) for i in range(500)],\n", + " 'loss2': [random.gauss(-1, 2) for i in range(500)],\n", + " 'str_val': [random.choice(['a', 'b', 'c']) for i in range(500)]},\n", + " ])\n", + "items" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a92bcc0e", + "metadata": {}, + "outputs": [], + "source": [ + "from weave.legacy.weave import weave_internal\n", + "# Numeric distribution\n", + "dist = wandb.Distribution(\n", + " items,\n", + " value_fn=lambda x: x['loss1'],\n", + " bin_size=0.1\n", + ")\n", + "dist" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fb380da9", + "metadata": {}, + "outputs": [], + "source": [ + "# String distribution\n", + "wandb.Distribution(\n", + " items,\n", + " value_fn=lambda x: x['str_val'],\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6db75ca1", + "metadata": {}, + "outputs": [], + "source": [ + "# Colored numeric distribution\n", + "wandb.Distribution(\n", + " items,\n", + " value_fn=lambda x: x['loss1'],\n", + " label_fn=lambda x: x['name'],\n", + " bin_size=0.2\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4eee28b9", + "metadata": {}, + "outputs": [], + "source": [ + "# Colored string distribution\n", + "wandb.Distribution(\n", + " items,\n", + " value_fn=lambda x: x['str_val'],\n", + " label_fn=lambda x: x['name'],\n", + " bin_size=0.2\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "30ab60fb", + "metadata": {}, + "outputs": [], + "source": [ + "# Labeled numeric distribution by nested value\n", + "wandb.Distribution(\n", + " items,\n", + " value_fn=lambda x: x['loss1'],\n", + " label_fn=lambda x: x['str_val'],\n", + " bin_size=0.2\n", + ")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "a9875d92", - "metadata": {}, - "outputs": [], - "source": [ - "items = weave.save([\n", - " {'name': 'x',\n", - " 'loss1': [random.gauss(5, 2) for i in range(500)],\n", - " 'loss2': [random.gauss(5, 2) for i in range(500)],\n", - " 'str_val': [random.choice(['a', 'b', 'c']) for i in range(500)]},\n", - " {'name': 'y',\n", - " 'loss1': [random.gauss(9, 4) for i in range(500)],\n", - " 'loss2': [random.gauss(-1, 2) for i in range(500)],\n", - " 'str_val': [random.choice(['a', 'b', 'c']) for i in range(500)]},\n", - " ])\n", - "items" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a92bcc0e", - "metadata": {}, - "outputs": [], - "source": [ - "from weave.legacy import weave_internal\n", - "# Numeric distribution\n", - "dist = wandb.Distribution(\n", - " items,\n", - " value_fn=lambda x: x['loss1'],\n", - " bin_size=0.1\n", - ")\n", - "dist" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "fb380da9", - "metadata": {}, - "outputs": [], - "source": [ - "# String distribution\n", - "wandb.Distribution(\n", - " items,\n", - " value_fn=lambda x: x['str_val'],\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6db75ca1", - "metadata": {}, - "outputs": [], - "source": [ - "# Colored numeric distribution\n", - "wandb.Distribution(\n", - " items,\n", - " value_fn=lambda x: x['loss1'],\n", - " label_fn=lambda x: x['name'],\n", - " bin_size=0.2\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4eee28b9", - "metadata": {}, - "outputs": [], - "source": [ - "# Colored string distribution\n", - "wandb.Distribution(\n", - " items,\n", - " value_fn=lambda x: x['str_val'],\n", - " label_fn=lambda x: x['name'],\n", - " bin_size=0.2\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "30ab60fb", - "metadata": {}, - "outputs": [], - "source": [ - "# Labeled numeric distribution by nested value\n", - "wandb.Distribution(\n", - " items,\n", - " value_fn=lambda x: x['loss1'],\n", - " label_fn=lambda x: x['str_val'],\n", - " bin_size=0.2\n", - ")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/reference/vis/Scatter.ipynb b/weave/legacy/examples/reference/vis/Scatter.ipynb index 7584ee9b4cd..6d11b709d1b 100644 --- a/weave/legacy/examples/reference/vis/Scatter.ipynb +++ b/weave/legacy/examples/reference/vis/Scatter.ipynb @@ -1,101 +1,101 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "81e1af41", - "metadata": {}, - "outputs": [], - "source": [ - "import random\n", - "import weave\n", - "import weave.legacy.panels\n", - "from weave.legacy.show import show\n", - "# Weave package now defaults to eager mode, but lazy mode required for this example notebook for now.\n", - "weave.use_lazy_execution()\n", - "from weave.legacy.ecosystem import wandb" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "81e1af41", + "metadata": {}, + "outputs": [], + "source": [ + "import random\n", + "import weave\n", + "import weave.legacy.weave.panels\n", + "from weave.legacy.weave.show import show\n", + "# Weave package now defaults to eager mode, but lazy mode required for this example notebook for now.\n", + "weave.use_lazy_execution()\n", + "from weave.legacy.weave.ecosystem import wandb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b6687922", + "metadata": {}, + "outputs": [], + "source": [ + "data = weave.save([{\n", + " 'a': random.gauss(5, 2),\n", + " 'b': random.gauss(0, 9),\n", + " 'c': random.gauss(15, 0.9),\n", + " 'd': random.random(),\n", + " 'e': random.choice(['a', 'b'])} for i in range(500)])\n", + "data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "726b9294", + "metadata": {}, + "outputs": [], + "source": [ + "panel = weave.legacy.weave.panels.Group(\n", + " items={\n", + " 'scatter': wandb.Scatter(data,\n", + " x_fn=lambda item: item['a'],\n", + " y_fn=lambda item: item['b'],\n", + " label_fn=lambda item: item['e']\n", + " ),\n", + " 'detail': lambda scatter: weave.legacy.weave.panels.Group(\n", + " style=\"height: 400px;\",\n", + " preferHorizontal=True,\n", + " items={\n", + " 'a_dist': weave.legacy.weave.panels.LabeledItem(\n", + " label='Distribution for metric a in selection',\n", + " item=wandb.Distribution(scatter.selected(),\n", + " value_fn=lambda item: item['a'],\n", + " label_fn=lambda item: item['e'],\n", + " bin_size=0.1)),\n", + " 'b_dist': weave.legacy.weave.panels.LabeledItem(\n", + " label='Distribution for metric b in selection',\n", + " item=wandb.Distribution(scatter.selected(),\n", + " value_fn=lambda item: item['b'],\n", + " label_fn=lambda item: item['e'],\n", + " bin_size=0.1))\n", + " }),\n", + " 'table': lambda scatter: weave.legacy.weave.panels.LabeledItem(\n", + " label='Selected items',\n", + " item=weave.legacy.weave.panels.Group(\n", + " style=\"height: 400px;\",\n", + " preferHorizontal=True,\n", + " items={\n", + " 'table': scatter.selected()\n", + " }))\n", + " }\n", + ")\n", + "show(panel, height=1000)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "b6687922", - "metadata": {}, - "outputs": [], - "source": [ - "data = weave.save([{\n", - " 'a': random.gauss(5, 2),\n", - " 'b': random.gauss(0, 9),\n", - " 'c': random.gauss(15, 0.9),\n", - " 'd': random.random(),\n", - " 'e': random.choice(['a', 'b'])} for i in range(500)])\n", - "data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "726b9294", - "metadata": {}, - "outputs": [], - "source": [ - "panel = weave.legacy.panels.Group(\n", - " items={\n", - " 'scatter': wandb.Scatter(data,\n", - " x_fn=lambda item: item['a'],\n", - " y_fn=lambda item: item['b'],\n", - " label_fn=lambda item: item['e']\n", - " ),\n", - " 'detail': lambda scatter: weave.legacy.panels.Group(\n", - " style=\"height: 400px;\",\n", - " preferHorizontal=True,\n", - " items={\n", - " 'a_dist': weave.legacy.panels.LabeledItem(\n", - " label='Distribution for metric a in selection',\n", - " item=wandb.Distribution(scatter.selected(),\n", - " value_fn=lambda item: item['a'],\n", - " label_fn=lambda item: item['e'],\n", - " bin_size=0.1)),\n", - " 'b_dist': weave.legacy.panels.LabeledItem(\n", - " label='Distribution for metric b in selection',\n", - " item=wandb.Distribution(scatter.selected(),\n", - " value_fn=lambda item: item['b'],\n", - " label_fn=lambda item: item['e'],\n", - " bin_size=0.1))\n", - " }),\n", - " 'table': lambda scatter: weave.legacy.panels.LabeledItem(\n", - " label='Selected items',\n", - " item=weave.legacy.panels.Group(\n", - " style=\"height: 400px;\",\n", - " preferHorizontal=True,\n", - " items={\n", - " 'table': scatter.selected()\n", - " }))\n", - " }\n", - ")\n", - "show(panel, height=1000)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/examples/reference/vis/derived_plots_from_tables.ipynb b/weave/legacy/examples/reference/vis/derived_plots_from_tables.ipynb index 200c338d869..638de728518 100644 --- a/weave/legacy/examples/reference/vis/derived_plots_from_tables.ipynb +++ b/weave/legacy/examples/reference/vis/derived_plots_from_tables.ipynb @@ -1,111 +1,111 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "14b320aa", - "metadata": {}, - "outputs": [], - "source": [ - "import weave\n", - "from weave.legacy.ecosystem import wandb\n", - "\n", - "# Group tags are broken with caching\n", - "# import os \n", - "# os.environ[\"WEAVE_NO_CACHE\"] = 'true'" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "14b320aa", + "metadata": {}, + "outputs": [], + "source": [ + "import weave\n", + "from weave.legacy.weave.ecosystem import wandb\n", + "\n", + "# Group tags are broken with caching\n", + "# import os \n", + "# os.environ[\"WEAVE_NO_CACHE\"] = 'true'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bfc9678e", + "metadata": {}, + "outputs": [], + "source": [ + "table = weave.legacy.weave.panels.Table(list(range(100)))\n", + "\n", + "# Add Filter\n", + "table.config.tableState.set_filter_fn(lambda i: i < 50)\n", + "\n", + "# Add Grouping\n", + "table.config.tableState.add_column(lambda i: i % 3, 'col_name_a')\n", + "group_col_id = table.config.tableState.order[0]\n", + "# table.config.tableState.enable_groupby(group_col_id)\n", + "\n", + "# Add Selections (Note: Important to add after grouping so `i` is correctly typed)\n", + "table.config.tableState.add_column(lambda i: i ** 2, 'col_name_b')\n", + "# table.config.tableState.add_column(lambda i: i.max(), 'col_name_c')\n", + "\n", + "# Add Sort\n", + "table.config.tableState.enable_sort(group_col_id)\n", + "\n", + "\n", + "panel = weave.legacy.weave.panels.Group(\n", + " layoutMode='horizontal',\n", + " items={\n", + " \"table\": table,\n", + "# \"table_2\": lambda table: table.rows()[0]['col_name_a']\n", + " \"plot\": lambda table: weave.legacy.weave.panels.Plot(\n", + " table.all_rows(),\n", + " x=lambda row: row['col_name_a'],\n", + " y=lambda row: row['col_name_b'],\n", + " )\n", + " }\n", + ")\n", + "panel" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bf475571", + "metadata": {}, + "outputs": [], + "source": [ + "panel = weave.legacy.weave.panels.Group(\n", + " layoutMode='horizontal',\n", + " items={\n", + " \"table\": weave.legacy.weave.panels.Table(list(range(100)), columns=[\n", + " lambda i: i,\n", + " lambda i: i**2,\n", + " lambda i: i * 0 + 1\n", + " ]),\n", + " \"table_2\": lambda table: weave.legacy.weave.panels.Table(table.all_rows(), columns=[\n", + " lambda i: table.all_rows()['c_0'].max() - i['c_0'],\n", + " lambda i: i['c_1'] / 2,\n", + " lambda i: i['c_2'] - 2\n", + " ]),\n", + " \"plot\": lambda table, table_2: weave.legacy.weave.panels.Plot(\n", + " weave.legacy.weave.ops.make_list(a=table.all_rows(), b=table_2.all_rows()).concat(),\n", + " x=lambda row: row['c_0'],\n", + " y=lambda row: row['c_1'],\n", + " color=lambda row: row['c_2']\n", + " )\n", + " }\n", + ")\n", + "panel" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "bfc9678e", - "metadata": {}, - "outputs": [], - "source": [ - "table = weave.legacy.panels.Table(list(range(100)))\n", - "\n", - "# Add Filter\n", - "table.config.tableState.set_filter_fn(lambda i: i < 50)\n", - "\n", - "# Add Grouping\n", - "table.config.tableState.add_column(lambda i: i % 3, 'col_name_a')\n", - "group_col_id = table.config.tableState.order[0]\n", - "# table.config.tableState.enable_groupby(group_col_id)\n", - "\n", - "# Add Selections (Note: Important to add after grouping so `i` is correctly typed)\n", - "table.config.tableState.add_column(lambda i: i ** 2, 'col_name_b')\n", - "# table.config.tableState.add_column(lambda i: i.max(), 'col_name_c')\n", - "\n", - "# Add Sort\n", - "table.config.tableState.enable_sort(group_col_id)\n", - "\n", - "\n", - "panel = weave.legacy.panels.Group(\n", - " layoutMode='horizontal',\n", - " items={\n", - " \"table\": table,\n", - "# \"table_2\": lambda table: table.rows()[0]['col_name_a']\n", - " \"plot\": lambda table: weave.legacy.panels.Plot(\n", - " table.all_rows(),\n", - " x=lambda row: row['col_name_a'],\n", - " y=lambda row: row['col_name_b'],\n", - " )\n", - " }\n", - ")\n", - "panel" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "bf475571", - "metadata": {}, - "outputs": [], - "source": [ - "panel = weave.legacy.panels.Group(\n", - " layoutMode='horizontal',\n", - " items={\n", - " \"table\": weave.legacy.panels.Table(list(range(100)), columns=[\n", - " lambda i: i,\n", - " lambda i: i**2,\n", - " lambda i: i * 0 + 1\n", - " ]),\n", - " \"table_2\": lambda table: weave.legacy.panels.Table(table.all_rows(), columns=[\n", - " lambda i: table.all_rows()['c_0'].max() - i['c_0'],\n", - " lambda i: i['c_1'] / 2,\n", - " lambda i: i['c_2'] - 2\n", - " ]),\n", - " \"plot\": lambda table, table_2: weave.legacy.panels.Plot(\n", - " weave.legacy.ops.make_list(a=table.all_rows(), b=table_2.all_rows()).concat(),\n", - " x=lambda row: row['c_0'],\n", - " y=lambda row: row['c_1'],\n", - " color=lambda row: row['c_2']\n", - " )\n", - " }\n", - ")\n", - "panel" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/notebooks/Eval Board Syn.ipynb b/weave/legacy/notebooks/Eval Board Syn.ipynb index 50aa1e926c0..6a7ea54e9e6 100644 --- a/weave/legacy/notebooks/Eval Board Syn.ipynb +++ b/weave/legacy/notebooks/Eval Board Syn.ipynb @@ -1,318 +1,318 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "5214b543", - "metadata": {}, - "source": [ - "- Load two eval_results\n", - "\n", - "EvalResult\n", - "- example, label, result, item_summary" - ] + "cells": [ + { + "cell_type": "markdown", + "id": "5214b543", + "metadata": {}, + "source": [ + "- Load two eval_results\n", + "\n", + "EvalResult\n", + "- example, label, result, item_summary" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "314bb6b4", + "metadata": {}, + "outputs": [], + "source": [ + "import random\n", + "import string\n", + "import time\n", + "\n", + "import weave\n", + "\n", + "weave.use_frontend_devmode()\n", + "from weave.legacy.weave.panels import panel_board" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "550daef6", + "metadata": {}, + "outputs": [], + "source": [ + "def rand_string_n(n: int) -> str:\n", + " return \"\".join(\n", + " random.choice(string.ascii_uppercase + string.digits) for _ in range(n)\n", + " )\n", + "\n", + "\n", + "dataset_raw = [\n", + " {\n", + " \"id\": str(i),\n", + " \"example\": rand_string_n(10),\n", + " \"label\": random.choice(string.ascii_uppercase),\n", + " }\n", + " for i in range(50)\n", + "]\n", + "dataset = weave.save(dataset_raw, \"dataset\")\n", + "# dataset" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d0d930d8", + "metadata": {}, + "outputs": [], + "source": [ + "def predict(dataset_row, config):\n", + " if random.random() < config[\"correct_chance\"]:\n", + " return dataset_row[\"label\"]\n", + " return random.choice(string.ascii_uppercase)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eb86b95c", + "metadata": {}, + "outputs": [], + "source": [ + "def evaluate(dataset, predict_config):\n", + " eval_result = []\n", + " correct_count = 0\n", + " count = 0\n", + " for dataset_row in dataset:\n", + " start_time = time.time()\n", + " result = predict(dataset_row, predict_config)\n", + " latency = time.time() - start_time\n", + " latency = random.gauss(\n", + " predict_config[\"latency_mu\"], predict_config[\"latency_sigma\"]\n", + " )\n", + " correct = dataset_row[\"label\"] == result\n", + " if correct:\n", + " correct_count += 1\n", + " count += 1\n", + " eval_result.append(\n", + " {\n", + " \"dataset_id\": dataset_row[\"id\"],\n", + " \"result\": result,\n", + " \"summary\": {\"latency\": latency, \"correct\": correct},\n", + " }\n", + " )\n", + " return {\n", + " \"config\": predict_config,\n", + " \"eval_table\": eval_result,\n", + " \"summary\": {\"accuracy\": correct_count / len(dataset)},\n", + " }" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "05d16a5e", + "metadata": {}, + "outputs": [], + "source": [ + "eval_result_raw0 = evaluate(\n", + " dataset_raw, {\"correct_chance\": 0.5, \"latency_mu\": 0.3, \"latency_sigma\": 0.1}\n", + ")\n", + "eval_result_raw1 = evaluate(\n", + " dataset_raw, {\"correct_chance\": 0.5, \"latency_mu\": 0.4, \"latency_sigma\": 0.2}\n", + ")\n", + "eval_result0 = weave.save(eval_result_raw0, \"eval_result0\")\n", + "eval_result1 = weave.save(eval_result_raw1, \"eval_result1\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e8065ad6", + "metadata": {}, + "outputs": [], + "source": [ + "varbar = panel_board.varbar()\n", + "\n", + "dataset_var = varbar.add(\"dataset\", dataset)\n", + "eval_result0_var = varbar.add(\"eval_result0\", eval_result0)\n", + "eval_result1_var = varbar.add(\"eval_result1\", eval_result1)\n", + "\n", + "summary = varbar.add(\n", + " \"summary\",\n", + " weave.legacy.weave.ops.make_list(\n", + " a=weave.legacy.weave.ops.TypedDict.merge(\n", + " weave.legacy.weave.ops.dict_(name=\"res0\"), eval_result0_var[\"summary\"]\n", + " ),\n", + " b=weave.legacy.weave.ops.TypedDict.merge(\n", + " weave.legacy.weave.ops.dict_(name=\"res1\"), eval_result1_var[\"summary\"]\n", + " ),\n", + " ),\n", + ")\n", + "\n", + "weave.legacy.weave.ops.make_list(\n", + " a=eval_result0_var[\"eval_table\"], b=eval_result0_var[\"eval_table\"]\n", + ")\n", + "\n", + "concatted_evals = varbar.add(\n", + " \"concatted_evals\",\n", + " weave.legacy.weave.ops.List.concat(\n", + " weave.legacy.weave.ops.make_list(\n", + " a=eval_result0_var[\"eval_table\"].map(\n", + " lambda row: weave.legacy.weave.ops.TypedDict.merge(\n", + " weave.legacy.weave.ops.dict_(name=\"res0\"), row\n", + " )\n", + " ),\n", + " b=eval_result1_var[\"eval_table\"].map(\n", + " lambda row: weave.legacy.weave.ops.TypedDict.merge(\n", + " weave.legacy.weave.ops.dict_(name=\"res1\"), row\n", + " )\n", + " ),\n", + " )\n", + " ),\n", + ")\n", + "\n", + "# join evals together first\n", + "joined_evals = varbar.add(\n", + " \"joined_evals\",\n", + " weave.legacy.weave.ops.join_all(\n", + " weave.legacy.weave.ops.make_list(\n", + " a=eval_result0_var[\"eval_table\"], b=eval_result1_var[\"eval_table\"]\n", + " ),\n", + " lambda row: row[\"dataset_id\"],\n", + " False,\n", + " ),\n", + ")\n", + "\n", + "# then join dataset to evals\n", + "dataset_evals = varbar.add(\n", + " \"dataset_evals\",\n", + " weave.legacy.weave.ops.join_2(\n", + " dataset_var,\n", + " joined_evals,\n", + " lambda row: row[\"id\"],\n", + " lambda row: row[\"dataset_id\"][0],\n", + " \"dataset\",\n", + " \"evals\",\n", + " False,\n", + " False,\n", + " ),\n", + ")\n", + "\n", + "\n", + "main = weave.legacy.weave.panels.Group(\n", + " layoutMode=\"grid\",\n", + " showExpressions=True,\n", + " enableAddPanel=True,\n", + ")\n", + "\n", + "#### Run/config info TODO\n", + "\n", + "#### Summary info\n", + "\n", + "main.add(\n", + " \"accuracy\",\n", + " weave.legacy.weave.panels.Plot(\n", + " summary,\n", + " x=lambda row: row[\"accuracy\"],\n", + " y=lambda row: row[\"name\"],\n", + " color=lambda row: row[\"name\"],\n", + " ),\n", + " layout=weave.legacy.weave.panels.GroupPanelLayout(x=0, y=0, w=12, h=4),\n", + ")\n", + "\n", + "\n", + "main.add(\n", + " \"latency\",\n", + " weave.legacy.weave.panels.Plot(\n", + " concatted_evals,\n", + " x=lambda row: row[\"summary\"][\"latency\"],\n", + " y=lambda row: row[\"name\"],\n", + " color=lambda row: row[\"name\"],\n", + " mark=\"boxplot\",\n", + " ),\n", + " layout=weave.legacy.weave.panels.GroupPanelLayout(x=12, y=0, w=12, h=4),\n", + ")\n", + "\n", + "# ct = main.add('concat_t', concatted_evals, layout=weave.legacy.weave.panels.GroupPanelLayout(x=0, y=4, w=24, h=12))\n", + "# main.add('dataset_table', dataset)\n", + "# main.add('joined_evals', joined_evals)\n", + "# main.add('dataset_evals', dataset_evals, layout=weave.legacy.weave.panels.GroupPanelLayout(x=0, y=4, w=24, h=6))\n", + "\n", + "##### Example details\n", + "\n", + "# more ideas: show examples that all got wrong, or that are confusing\n", + "\n", + "faceted_view = weave.legacy.weave.panels.Facet(\n", + " dataset_evals,\n", + " x=lambda row: row[\"evals.summary\"][0][\"correct\"],\n", + " y=lambda row: row[\"evals.summary\"][1][\"correct\"],\n", + " select=lambda row: row.count(),\n", + ")\n", + "\n", + "faceted = main.add(\n", + " \"faceted\",\n", + " faceted_view,\n", + " layout=weave.legacy.weave.panels.GroupPanelLayout(x=0, y=4, w=12, h=6),\n", + ")\n", + "\n", + "main.add(\n", + " \"example_latencies\",\n", + " weave.legacy.weave.panels.Plot(\n", + " dataset_evals,\n", + " x=lambda row: row[\"evals.summary\"][\"latency\"][0],\n", + " y=lambda row: row[\"evals.summary\"][\"latency\"][1],\n", + " ),\n", + " layout=weave.legacy.weave.panels.GroupPanelLayout(x=12, y=4, w=12, h=6),\n", + ")\n", + "\n", + "faceted_sel = weave.legacy.weave.panels.Table(faceted.selected())\n", + "faceted_sel.config.rowSize = 2\n", + "faceted_sel.add_column(lambda row: row[\"dataset.id\"], \"id\")\n", + "faceted_sel.add_column(lambda row: row[\"dataset.example\"], \"example\")\n", + "faceted_sel.add_column(lambda row: row[\"dataset.label\"], \"label\")\n", + "faceted_sel.add_column(\n", + " lambda row: weave.legacy.weave.ops.dict_(\n", + " res0=row[\"evals.result\"][0], res1=row[\"evals.result\"][1]\n", + " ),\n", + " \"result\",\n", + ")\n", + "faceted_sel.add_column(\n", + " lambda row: weave.legacy.weave.ops.dict_(\n", + " res0=row[\"evals.summary\"][0][\"correct\"], res1=row[\"evals.summary\"][1][\"correct\"]\n", + " ),\n", + " \"correct\",\n", + ")\n", + "faceted_sel.add_column(\n", + " lambda row: weave.legacy.weave.ops.dict_(\n", + " res0=row[\"evals.summary\"][0][\"latency\"], res1=row[\"evals.summary\"][1][\"latency\"]\n", + " ),\n", + " \"latency\",\n", + ")\n", + "\n", + "main.add(\n", + " \"faceted_sel\",\n", + " faceted_sel,\n", + " layout=weave.legacy.weave.panels.GroupPanelLayout(x=0, y=10, w=24, h=12),\n", + ")\n", + "\n", + "weave.legacy.weave.panels.Board(vars=varbar, panels=main)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "314bb6b4", - "metadata": {}, - "outputs": [], - "source": [ - "import random\n", - "import string\n", - "import time\n", - "\n", - "import weave\n", - "\n", - "weave.use_frontend_devmode()\n", - "from weave.legacy.panels import panel_board" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "550daef6", - "metadata": {}, - "outputs": [], - "source": [ - "def rand_string_n(n: int) -> str:\n", - " return \"\".join(\n", - " random.choice(string.ascii_uppercase + string.digits) for _ in range(n)\n", - " )\n", - "\n", - "\n", - "dataset_raw = [\n", - " {\n", - " \"id\": str(i),\n", - " \"example\": rand_string_n(10),\n", - " \"label\": random.choice(string.ascii_uppercase),\n", - " }\n", - " for i in range(50)\n", - "]\n", - "dataset = weave.save(dataset_raw, \"dataset\")\n", - "# dataset" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d0d930d8", - "metadata": {}, - "outputs": [], - "source": [ - "def predict(dataset_row, config):\n", - " if random.random() < config[\"correct_chance\"]:\n", - " return dataset_row[\"label\"]\n", - " return random.choice(string.ascii_uppercase)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "eb86b95c", - "metadata": {}, - "outputs": [], - "source": [ - "def evaluate(dataset, predict_config):\n", - " eval_result = []\n", - " correct_count = 0\n", - " count = 0\n", - " for dataset_row in dataset:\n", - " start_time = time.time()\n", - " result = predict(dataset_row, predict_config)\n", - " latency = time.time() - start_time\n", - " latency = random.gauss(\n", - " predict_config[\"latency_mu\"], predict_config[\"latency_sigma\"]\n", - " )\n", - " correct = dataset_row[\"label\"] == result\n", - " if correct:\n", - " correct_count += 1\n", - " count += 1\n", - " eval_result.append(\n", - " {\n", - " \"dataset_id\": dataset_row[\"id\"],\n", - " \"result\": result,\n", - " \"summary\": {\"latency\": latency, \"correct\": correct},\n", - " }\n", - " )\n", - " return {\n", - " \"config\": predict_config,\n", - " \"eval_table\": eval_result,\n", - " \"summary\": {\"accuracy\": correct_count / len(dataset)},\n", - " }" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "05d16a5e", - "metadata": {}, - "outputs": [], - "source": [ - "eval_result_raw0 = evaluate(\n", - " dataset_raw, {\"correct_chance\": 0.5, \"latency_mu\": 0.3, \"latency_sigma\": 0.1}\n", - ")\n", - "eval_result_raw1 = evaluate(\n", - " dataset_raw, {\"correct_chance\": 0.5, \"latency_mu\": 0.4, \"latency_sigma\": 0.2}\n", - ")\n", - "eval_result0 = weave.save(eval_result_raw0, \"eval_result0\")\n", - "eval_result1 = weave.save(eval_result_raw1, \"eval_result1\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e8065ad6", - "metadata": {}, - "outputs": [], - "source": [ - "varbar = panel_board.varbar()\n", - "\n", - "dataset_var = varbar.add(\"dataset\", dataset)\n", - "eval_result0_var = varbar.add(\"eval_result0\", eval_result0)\n", - "eval_result1_var = varbar.add(\"eval_result1\", eval_result1)\n", - "\n", - "summary = varbar.add(\n", - " \"summary\",\n", - " weave.legacy.ops.make_list(\n", - " a=weave.legacy.ops.TypedDict.merge(\n", - " weave.legacy.ops.dict_(name=\"res0\"), eval_result0_var[\"summary\"]\n", - " ),\n", - " b=weave.legacy.ops.TypedDict.merge(\n", - " weave.legacy.ops.dict_(name=\"res1\"), eval_result1_var[\"summary\"]\n", - " ),\n", - " ),\n", - ")\n", - "\n", - "weave.legacy.ops.make_list(\n", - " a=eval_result0_var[\"eval_table\"], b=eval_result0_var[\"eval_table\"]\n", - ")\n", - "\n", - "concatted_evals = varbar.add(\n", - " \"concatted_evals\",\n", - " weave.legacy.ops.List.concat(\n", - " weave.legacy.ops.make_list(\n", - " a=eval_result0_var[\"eval_table\"].map(\n", - " lambda row: weave.legacy.ops.TypedDict.merge(\n", - " weave.legacy.ops.dict_(name=\"res0\"), row\n", - " )\n", - " ),\n", - " b=eval_result1_var[\"eval_table\"].map(\n", - " lambda row: weave.legacy.ops.TypedDict.merge(\n", - " weave.legacy.ops.dict_(name=\"res1\"), row\n", - " )\n", - " ),\n", - " )\n", - " ),\n", - ")\n", - "\n", - "# join evals together first\n", - "joined_evals = varbar.add(\n", - " \"joined_evals\",\n", - " weave.legacy.ops.join_all(\n", - " weave.legacy.ops.make_list(\n", - " a=eval_result0_var[\"eval_table\"], b=eval_result1_var[\"eval_table\"]\n", - " ),\n", - " lambda row: row[\"dataset_id\"],\n", - " False,\n", - " ),\n", - ")\n", - "\n", - "# then join dataset to evals\n", - "dataset_evals = varbar.add(\n", - " \"dataset_evals\",\n", - " weave.legacy.ops.join_2(\n", - " dataset_var,\n", - " joined_evals,\n", - " lambda row: row[\"id\"],\n", - " lambda row: row[\"dataset_id\"][0],\n", - " \"dataset\",\n", - " \"evals\",\n", - " False,\n", - " False,\n", - " ),\n", - ")\n", - "\n", - "\n", - "main = weave.legacy.panels.Group(\n", - " layoutMode=\"grid\",\n", - " showExpressions=True,\n", - " enableAddPanel=True,\n", - ")\n", - "\n", - "#### Run/config info TODO\n", - "\n", - "#### Summary info\n", - "\n", - "main.add(\n", - " \"accuracy\",\n", - " weave.legacy.panels.Plot(\n", - " summary,\n", - " x=lambda row: row[\"accuracy\"],\n", - " y=lambda row: row[\"name\"],\n", - " color=lambda row: row[\"name\"],\n", - " ),\n", - " layout=weave.legacy.panels.GroupPanelLayout(x=0, y=0, w=12, h=4),\n", - ")\n", - "\n", - "\n", - "main.add(\n", - " \"latency\",\n", - " weave.legacy.panels.Plot(\n", - " concatted_evals,\n", - " x=lambda row: row[\"summary\"][\"latency\"],\n", - " y=lambda row: row[\"name\"],\n", - " color=lambda row: row[\"name\"],\n", - " mark=\"boxplot\",\n", - " ),\n", - " layout=weave.legacy.panels.GroupPanelLayout(x=12, y=0, w=12, h=4),\n", - ")\n", - "\n", - "# ct = main.add('concat_t', concatted_evals, layout=weave.legacy.panels.GroupPanelLayout(x=0, y=4, w=24, h=12))\n", - "# main.add('dataset_table', dataset)\n", - "# main.add('joined_evals', joined_evals)\n", - "# main.add('dataset_evals', dataset_evals, layout=weave.legacy.panels.GroupPanelLayout(x=0, y=4, w=24, h=6))\n", - "\n", - "##### Example details\n", - "\n", - "# more ideas: show examples that all got wrong, or that are confusing\n", - "\n", - "faceted_view = weave.legacy.panels.Facet(\n", - " dataset_evals,\n", - " x=lambda row: row[\"evals.summary\"][0][\"correct\"],\n", - " y=lambda row: row[\"evals.summary\"][1][\"correct\"],\n", - " select=lambda row: row.count(),\n", - ")\n", - "\n", - "faceted = main.add(\n", - " \"faceted\",\n", - " faceted_view,\n", - " layout=weave.legacy.panels.GroupPanelLayout(x=0, y=4, w=12, h=6),\n", - ")\n", - "\n", - "main.add(\n", - " \"example_latencies\",\n", - " weave.legacy.panels.Plot(\n", - " dataset_evals,\n", - " x=lambda row: row[\"evals.summary\"][\"latency\"][0],\n", - " y=lambda row: row[\"evals.summary\"][\"latency\"][1],\n", - " ),\n", - " layout=weave.legacy.panels.GroupPanelLayout(x=12, y=4, w=12, h=6),\n", - ")\n", - "\n", - "faceted_sel = weave.legacy.panels.Table(faceted.selected())\n", - "faceted_sel.config.rowSize = 2\n", - "faceted_sel.add_column(lambda row: row[\"dataset.id\"], \"id\")\n", - "faceted_sel.add_column(lambda row: row[\"dataset.example\"], \"example\")\n", - "faceted_sel.add_column(lambda row: row[\"dataset.label\"], \"label\")\n", - "faceted_sel.add_column(\n", - " lambda row: weave.legacy.ops.dict_(\n", - " res0=row[\"evals.result\"][0], res1=row[\"evals.result\"][1]\n", - " ),\n", - " \"result\",\n", - ")\n", - "faceted_sel.add_column(\n", - " lambda row: weave.legacy.ops.dict_(\n", - " res0=row[\"evals.summary\"][0][\"correct\"], res1=row[\"evals.summary\"][1][\"correct\"]\n", - " ),\n", - " \"correct\",\n", - ")\n", - "faceted_sel.add_column(\n", - " lambda row: weave.legacy.ops.dict_(\n", - " res0=row[\"evals.summary\"][0][\"latency\"], res1=row[\"evals.summary\"][1][\"latency\"]\n", - " ),\n", - " \"latency\",\n", - ")\n", - "\n", - "main.add(\n", - " \"faceted_sel\",\n", - " faceted_sel,\n", - " layout=weave.legacy.panels.GroupPanelLayout(x=0, y=10, w=24, h=12),\n", - ")\n", - "\n", - "weave.legacy.panels.Board(vars=varbar, panels=main)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/notebooks/Eval Board.ipynb b/weave/legacy/notebooks/Eval Board.ipynb index be2baf592eb..1cf4b810b8a 100644 --- a/weave/legacy/notebooks/Eval Board.ipynb +++ b/weave/legacy/notebooks/Eval Board.ipynb @@ -1,161 +1,163 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": 61, - "id": "314bb6b4", - "metadata": {}, - "outputs": [], - "source": [ - "import typing\n", - "\n", - "import weave\n", - "from weave.legacy import weave_internal\n", - "\n", - "weave.use_frontend_devmode()\n", - "from weave.legacy import ops_domain\n", - "from weave.legacy.panels import panel_board" - ] - }, - { - "cell_type": "code", - "execution_count": 62, - "id": "550daef6", - "metadata": {}, - "outputs": [], - "source": [ - "@weave.type()\n", - "class Dataset:\n", - " rows: list[typing.Any]" - ] - }, + "cells": [ + { + "cell_type": "code", + "execution_count": 61, + "id": "314bb6b4", + "metadata": {}, + "outputs": [], + "source": [ + "import typing\n", + "\n", + "import weave\n", + "from weave.legacy.weave import weave_internal\n", + "\n", + "weave.use_frontend_devmode()\n", + "from weave.legacy.weave import ops_domain\n", + "from weave.legacy.weave.panels import panel_board" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "id": "550daef6", + "metadata": {}, + "outputs": [], + "source": [ + "@weave.type()\n", + "class Dataset:\n", + " rows: list[typing.Any]" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "id": "e8065ad6", + "metadata": {}, + "outputs": [ { - "cell_type": "code", - "execution_count": 64, - "id": "e8065ad6", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "\n", - " \n", - " " - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } + "data": { + "text/html": [ + "\n", + " \n", + " " ], - "source": [ - "varbar = panel_board.varbar()\n", - "\n", - "entity_name_val = varbar.add(\"entity_name_val\", \"shawn\", hidden=True)\n", - "entity = ops_domain.entity(entity_name_val)\n", - "entity_name = varbar.add(\n", - " \"entity_name\",\n", - " weave.legacy.panels.Dropdown(\n", - " entity_name_val, choices=ops_domain.viewer().entities().name()\n", - " ),\n", - ")\n", - "\n", - "project_name_val = varbar.add(\"project_name_val\", \"weave-flow1\", hidden=True)\n", - "project = ops_domain.project(entity_name_val, project_name_val)\n", - "project_name = varbar.add(\n", - " \"project_name\",\n", - " weave.legacy.panels.Dropdown(project_name_val, choices=entity.projects().name()),\n", - ")\n", - "\n", - "dataset_name_val = varbar.add(\"dataset_name_val\", \"my_dataset1\", hidden=True)\n", - "dataset = varbar.add(\n", - " \"dataset\",\n", - " weave.legacy.ops.get(\n", - " weave_internal.const(\"wandb-artifact:///\")\n", - " + entity_name_val\n", - " + \"/\"\n", - " + project_name_val\n", - " + \"/\"\n", - " + dataset_name_val\n", - " + \":latest/obj\"\n", - " ),\n", - " hidden=True,\n", - ")\n", - "dataset_ref = varbar.add(\n", - " \"dataset_ref\",\n", - " weave.legacy.ops.ref(\n", - " weave_internal.const(\"wandb-artifact:///\")\n", - " + entity_name_val\n", - " + \"/\"\n", - " + project_name_val\n", - " + \"/\"\n", - " + dataset_name_val\n", - " + \":latest/obj\"\n", - " ),\n", - ")\n", - "dataset_name = varbar.add(\n", - " \"dataset_name\",\n", - " weave.legacy.panels.Dropdown(\n", - " dataset_name_val, choices=project.artifactType(\"Dataset\").artifacts().name()\n", - " ),\n", - ")\n", - "\n", - "# Now here I want to pick model A and model B\n", - "# I need to a way to get to artifact from an object, like get_ref.artifact ?\n", - "# like dataset_ref.artifact().usedBy().filter(lambda row: row.jobName() == 'eval')\n", - "# then from there find consuming runs of a given job_type (\"eval\")\n", - "# let the user pick two of those\n", - "\n", - "# want a really nice data grid of the table metric comparsion per row\n", - "\n", - "main = weave.legacy.panels.Group(\n", - " layoutMode=\"grid\",\n", - " showExpressions=True,\n", - " enableAddPanel=True,\n", - ")\n", - "\n", - "main.add(\"ename\", entity_name_val)\n", - "main.add(\"pname\", project_name_val)\n", - "main.add(\"dsrows\", weave.legacy.ops.obj_getattr(dataset, \"rows\"))\n", - "# main.add(\"artifact\", dataset_ref.artifact())\n", - "\n", - "# I Need a programmable Table. One that's columns are defined by Nodes\n", - "# Same for panels, I want to be able to generate a bunch of panels\n", - "# Can I do this with Weaveify?\n", - "# Like I can pass a function in in the Board that returns the panel I want maybe?\n", - "\n", - "weave.legacy.panels.Board(vars=varbar, panels=main)" + "text/plain": [ + "" ] + }, + "metadata": {}, + "output_type": "display_data" } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } + ], + "source": [ + "varbar = panel_board.varbar()\n", + "\n", + "entity_name_val = varbar.add(\"entity_name_val\", \"shawn\", hidden=True)\n", + "entity = ops_domain.entity(entity_name_val)\n", + "entity_name = varbar.add(\n", + " \"entity_name\",\n", + " weave.legacy.weave.panels.Dropdown(\n", + " entity_name_val, choices=ops_domain.viewer().entities().name()\n", + " ),\n", + ")\n", + "\n", + "project_name_val = varbar.add(\"project_name_val\", \"weave-flow1\", hidden=True)\n", + "project = ops_domain.project(entity_name_val, project_name_val)\n", + "project_name = varbar.add(\n", + " \"project_name\",\n", + " weave.legacy.weave.panels.Dropdown(\n", + " project_name_val, choices=entity.projects().name()\n", + " ),\n", + ")\n", + "\n", + "dataset_name_val = varbar.add(\"dataset_name_val\", \"my_dataset1\", hidden=True)\n", + "dataset = varbar.add(\n", + " \"dataset\",\n", + " weave.legacy.weave.ops.get(\n", + " weave_internal.const(\"wandb-artifact:///\")\n", + " + entity_name_val\n", + " + \"/\"\n", + " + project_name_val\n", + " + \"/\"\n", + " + dataset_name_val\n", + " + \":latest/obj\"\n", + " ),\n", + " hidden=True,\n", + ")\n", + "dataset_ref = varbar.add(\n", + " \"dataset_ref\",\n", + " weave.legacy.weave.ops.ref(\n", + " weave_internal.const(\"wandb-artifact:///\")\n", + " + entity_name_val\n", + " + \"/\"\n", + " + project_name_val\n", + " + \"/\"\n", + " + dataset_name_val\n", + " + \":latest/obj\"\n", + " ),\n", + ")\n", + "dataset_name = varbar.add(\n", + " \"dataset_name\",\n", + " weave.legacy.weave.panels.Dropdown(\n", + " dataset_name_val, choices=project.artifactType(\"Dataset\").artifacts().name()\n", + " ),\n", + ")\n", + "\n", + "# Now here I want to pick model A and model B\n", + "# I need to a way to get to artifact from an object, like get_ref.artifact ?\n", + "# like dataset_ref.artifact().usedBy().filter(lambda row: row.jobName() == 'eval')\n", + "# then from there find consuming runs of a given job_type (\"eval\")\n", + "# let the user pick two of those\n", + "\n", + "# want a really nice data grid of the table metric comparsion per row\n", + "\n", + "main = weave.legacy.weave.panels.Group(\n", + " layoutMode=\"grid\",\n", + " showExpressions=True,\n", + " enableAddPanel=True,\n", + ")\n", + "\n", + "main.add(\"ename\", entity_name_val)\n", + "main.add(\"pname\", project_name_val)\n", + "main.add(\"dsrows\", weave.legacy.weave.ops.obj_getattr(dataset, \"rows\"))\n", + "# main.add(\"artifact\", dataset_ref.artifact())\n", + "\n", + "# I Need a programmable Table. One that's columns are defined by Nodes\n", + "# Same for panels, I want to be able to generate a bunch of panels\n", + "# Can I do this with Weaveify?\n", + "# Like I can pass a function in in the Board that returns the panel I want maybe?\n", + "\n", + "weave.legacy.weave.panels.Board(vars=varbar, panels=main)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" }, - "nbformat": 4, - "nbformat_minor": 5 + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/notebooks/Text Extraction Eval.ipynb b/weave/legacy/notebooks/Text Extraction Eval.ipynb index 64daefac32b..a2d2705eb97 100644 --- a/weave/legacy/notebooks/Text Extraction Eval.ipynb +++ b/weave/legacy/notebooks/Text Extraction Eval.ipynb @@ -1,445 +1,445 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "04bba52c", - "metadata": {}, - "outputs": [], - "source": [ - "import glob\n", - "import os\n", - "import random\n", - "import time\n", - "import typing\n", - "\n", - "import weave\n", - "\n", - "weave.use_frontend_devmode()" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "04bba52c", + "metadata": {}, + "outputs": [], + "source": [ + "import glob\n", + "import os\n", + "import random\n", + "import time\n", + "import typing\n", + "\n", + "import weave\n", + "\n", + "weave.use_frontend_devmode()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8172d67c", + "metadata": {}, + "outputs": [], + "source": [ + "raw_labels = {\n", + " \"Articles_of_Incorporation_Real_Example_3_txt\": {\n", + " \"name\": \"HealthFirst Solutions LLC\",\n", + " \"shares\": 500000,\n", + " },\n", + " \"Articles_of_Incorporation_Real_Example_2_txt\": {\n", + " \"name\": \"GreenLeaf LLC\",\n", + " \"shares\": None,\n", + " \"directors\": [\"Sarah Miller\", \"Daniel Lee\"],\n", + " },\n", + " \"Articles_of_Incorporation_Real_Example_1_txt\": {\n", + " \"name\": \"TechBoost Corp\",\n", + " \"shares\": 1000000,\n", + " },\n", + " \"Highly_Varied_Article_of_Incorporation_10_txt\": {\n", + " \"name\": \"Brown, Fernandez and Smith\",\n", + " \"shares\": 41141,\n", + " },\n", + " \"Highly_Varied_Article_of_Incorporation_9_txt\": {\n", + " \"name\": \"Ruiz-Goodman\",\n", + " \"shares\": 31783,\n", + " },\n", + " \"Highly_Varied_Article_of_Incorporation_8_txt\": {\n", + " \"name\": \"Gibson, Hunt and Davidson\",\n", + " \"shares\": 96403,\n", + " },\n", + " \"Highly_Varied_Article_of_Incorporation_7_txt\": {\n", + " \"name\": \"Boyd-Browning\",\n", + " \"shares\": 41300,\n", + " },\n", + " \"Highly_Varied_Article_of_Incorporation_6_txt\": {\n", + " \"name\": \"Newton, Moreno and Yang\",\n", + " \"shares\": 73981,\n", + " },\n", + " \"Highly_Varied_Article_of_Incorporation_5_txt\": {\n", + " \"name\": \"Matthews and Sons\",\n", + " \"shares\": 98608,\n", + " },\n", + " \"Highly_Varied_Article_of_Incorporation_4_txt\": {\n", + " \"name\": \"Moore LLC\",\n", + " \"shares\": 5732,\n", + " },\n", + " \"Highly_Varied_Article_of_Incorporation_3_txt\": {\n", + " \"name\": \"Mullen Inc\",\n", + " \"shares\": 76197,\n", + " },\n", + " \"Highly_Varied_Article_of_Incorporation_2_txt\": {\n", + " \"name\": \"Ellis and Sons\",\n", + " \"shares\": 54183,\n", + " },\n", + " \"Highly_Varied_Article_of_Incorporation_1_txt\": {\n", + " \"name\": \"French, Wyatt and Coleman\",\n", + " \"shares\": 78821,\n", + " },\n", + "}\n", + "\n", + "\n", + "def read_dataset(root):\n", + " dataset_rows = []\n", + " for p in glob.glob(os.path.join(root, \"*.txt\")):\n", + " # Have to do replace here because of weave '.' access issues\n", + " example_id = os.path.basename(p).replace(\".\", \"_\")\n", + " label = raw_labels.get(example_id)\n", + " if label:\n", + " dataset_rows.append(\n", + " {\"id\": example_id, \"example\": open(p).read(), \"label\": label}\n", + " )\n", + " return dataset_rows" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cb93f2a4", + "metadata": {}, + "outputs": [], + "source": [ + "# Can't just make our own types, server won't deserialize.\n", + "# A fairly easy fix.\n", + "@weave.type()\n", + "class Dataset:\n", + " rows: list[typing.Any]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "92c6535c", + "metadata": {}, + "outputs": [], + "source": [ + "raw_dataset = read_dataset(\"/Users/shawn/datasets/aoi\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7e803efd", + "metadata": {}, + "outputs": [], + "source": [ + "# raw_dataset" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fc723706", + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "dataset = weave.save(Dataset(raw_dataset), \"my_dataset5\")\n", + "# Now, here I really want to make my own labels in the UI immediately.\n", + "# where should the added column go? A new version of this dataset?\n", + "# yeah sure why not.\n", + "# What's missing for editing to be good?\n", + "# - batch editing, ie make a bunch of changes and choose where/how to save" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4a99df38", + "metadata": {}, + "outputs": [], + "source": [ + "# published = weave.publish(Dataset(raw_dataset), 'weave-flow1/my_dataset1')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "77c71a23", + "metadata": {}, + "outputs": [], + "source": [ + "dataset.rows\n", + "# Here i went to render labels next to dataset.\n", + "# I need access to labels in the notebook memory... would be easy enough to pass in" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "331d88d6", + "metadata": {}, + "outputs": [], + "source": [ + "import re\n", + "\n", + "\n", + "def split_paragraphs(doc):\n", + " lines = [l.strip() for l in doc.split(\"\\n\")]\n", + " stripped_doc = \"\\n\".join(lines)\n", + " return [p.strip() for p in stripped_doc.split(\"\\n\\n\")]\n", + "\n", + "\n", + "def find_first_numeric(s):\n", + " match = re.search(r\"\\d+\", s)\n", + " if match is None:\n", + " return None\n", + " return int(match.group().replace(\",\", \"\"))\n", + "\n", + "\n", + "def predict(dataset_row, config):\n", + " paragraphs = split_paragraphs(dataset_row[\"example\"])\n", + " capital_paragraph = None\n", + " name_paragraph = None\n", + " for p in paragraphs:\n", + " if \"name\" in p.lower():\n", + " name_paragraph = p\n", + " if \"share\" in p.lower():\n", + " capital_paragraph = p\n", + " result = {\n", + " \"name\": None,\n", + " \"shares\": None,\n", + " }\n", + " if capital_paragraph:\n", + " paragraph_start = config.get(\"shares_skip_chars\", 0)\n", + " result[\"shares\"] = find_first_numeric(capital_paragraph[paragraph_start:])\n", + " if name_paragraph:\n", + " match = re.search(r\"is \", name_paragraph)\n", + " if match is not None:\n", + " result[\"name\"] = name_paragraph[match.end() :]\n", + " if result[\"name\"] and config.get(\"name_up_to_period\"):\n", + " match = re.search(r\"\\.\", result[\"name\"])\n", + " if match is not None:\n", + " result[\"name\"] = result[\"name\"][: match.start()]\n", + " return result" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b2378174", + "metadata": {}, + "outputs": [], + "source": [ + "for dataset_row in weave.use(dataset.rows):\n", + " print(predict(dataset_row, {\"shares_skip_chars\": 4}))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "efc63aa7", + "metadata": {}, + "outputs": [], + "source": [ + "fields = [\"name\", \"shares\", \"directors\"]\n", + "\n", + "\n", + "def p_r_f1(tp, fp, fn):\n", + " # if any denom is zero, then zero. could use NaN instead...\n", + " precision = 0\n", + " if tp or fp:\n", + " precision = tp / (tp + fp)\n", + " recall = 0\n", + " if tp or fn:\n", + " recall = tp / (tp + fn)\n", + " f1 = 0\n", + " if precision or recall:\n", + " f1 = 2 * (precision * recall) / (precision + recall)\n", + " return precision, recall, f1\n", + "\n", + "\n", + "def summarize_item(item_result, item_label):\n", + " item_summary = {}\n", + " for f in fields:\n", + " item_summary[f\"{f}_negative\"] = item_result.get(f) is None\n", + " item_summary[f\"{f}_correct\"] = item_result.get(f) == item_label.get(f)\n", + "\n", + " item_correct = sum([item_summary[f\"{f}_correct\"] for f in fields])\n", + " item_tp = sum(\n", + " [item_label.get(f) is not None and item_summary[f\"{f}_correct\"] for f in fields]\n", + " )\n", + " item_fp = sum(\n", + " [\n", + " item_label.get(f) is not None and not item_summary[f\"{f}_correct\"]\n", + " for f in fields\n", + " ]\n", + " )\n", + " item_tn = sum(\n", + " [item_label.get(f) is None and item_summary[f\"{f}_correct\"] for f in fields]\n", + " )\n", + " item_fn = sum(\n", + " [item_label.get(f) is None and not item_summary[f\"{f}_correct\"] for f in fields]\n", + " )\n", + "\n", + " item_precision, item_recall, item_f1 = p_r_f1(item_tp, item_fp, item_fn)\n", + "\n", + " return {\n", + " **item_summary,\n", + " \"correct\": item_correct,\n", + " \"tp\": item_tp,\n", + " \"fp\": item_fp,\n", + " \"tn\": item_tn,\n", + " \"fn\": item_fn,\n", + " \"precision\": item_precision,\n", + " \"recall\": item_recall,\n", + " \"f1\": item_f1,\n", + " }\n", + "\n", + "\n", + "def field_pr(eval_result, field_name):\n", + " tp = sum(\n", + " not item[\"summary\"][f\"{field_name}_negative\"]\n", + " and item[\"summary\"][f\"{field_name}_correct\"]\n", + " for item in eval_result\n", + " )\n", + " fp = sum(\n", + " not item[\"summary\"][f\"{field_name}_negative\"]\n", + " and not item[\"summary\"][f\"{field_name}_correct\"]\n", + " for item in eval_result\n", + " )\n", + " tn = sum(\n", + " item[\"summary\"][f\"{field_name}_negative\"]\n", + " and item[\"summary\"][f\"{field_name}_correct\"]\n", + " for item in eval_result\n", + " )\n", + " fn = sum(\n", + " item[\"summary\"][f\"{field_name}_negative\"]\n", + " and not item[\"summary\"][f\"{field_name}_correct\"]\n", + " for item in eval_result\n", + " )\n", + "\n", + " precision, recall, f1 = p_r_f1(tp, fp, fn)\n", + " return {\n", + " \"tp\": tp,\n", + " \"fp\": fp,\n", + " \"tn\": tn,\n", + " \"fn\": fn,\n", + " \"precision\": precision,\n", + " \"recall\": recall,\n", + " \"f1\": f1,\n", + " }\n", + "\n", + "\n", + "def summarize(eval_result):\n", + " summary = {}\n", + " for field in fields:\n", + " summary[f\"field_{field}\"] = field_pr(eval_result, field)\n", + " for metric in [\"precision\", \"recall\", \"f1\"]:\n", + " summary[f\"avg_{metric}\"] = sum(\n", + " summary[f\"field_{f}\"][metric] for f in fields\n", + " ) / len(fields)\n", + " return summary\n", + "\n", + "\n", + "def evaluate(dataset, predict_config):\n", + " eval_result = []\n", + " correct_count = 0\n", + " count = 0\n", + " for dataset_row in dataset:\n", + " start_time = time.time()\n", + " result = predict(dataset_row, predict_config)\n", + " latency = time.time() - start_time\n", + " latency = random.gauss(\n", + " predict_config[\"latency_mu\"], predict_config[\"latency_sigma\"]\n", + " )\n", + " item_summary = summarize_item(result, dataset_row[\"label\"])\n", + " eval_result.append(\n", + " {\n", + " \"dataset_id\": dataset_row[\"id\"],\n", + " \"result\": result,\n", + " \"summary\": {\"latency\": latency, **item_summary},\n", + " }\n", + " )\n", + " return {\n", + " \"config\": predict_config,\n", + " \"eval_table\": eval_result,\n", + " \"summary\": summarize(eval_result),\n", + " }" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f2248364", + "metadata": {}, + "outputs": [], + "source": [ + "eval_results0 = weave.save(\n", + " evaluate(weave.use(dataset).rows, {\"latency_mu\": 0.3, \"latency_sigma\": 0.1}),\n", + " \"eval_results0\",\n", + ")\n", + "eval_results1 = weave.save(\n", + " evaluate(\n", + " weave.use(dataset).rows,\n", + " {\"latency_mu\": 0.3, \"latency_sigma\": 0.1, \"name_up_to_period\": True},\n", + " ),\n", + " \"eval_results1\",\n", + ")\n", + "eval_results2 = weave.save(\n", + " evaluate(\n", + " weave.use(dataset).rows,\n", + " {\n", + " \"latency_mu\": 0.3,\n", + " \"latency_sigma\": 0.1,\n", + " \"name_up_to_period\": True,\n", + " \"shares_skip_chars\": 4,\n", + " },\n", + " ),\n", + " \"eval_results2\",\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "93727275", + "metadata": {}, + "outputs": [], + "source": [ + "from weave.legacy.weave.panels_py import panel_eval\n", + "\n", + "panel_eval.eval_board(dataset.rows, eval_results0, eval_results2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "166e8607", + "metadata": {}, + "outputs": [], + "source": [ + "# To add:\n", + "# - backed by W&B runs\n", + "# - show run code / config comparison\n", + "# - show traces of pipelines and compare them\n", + "# - add view of N runs instead of 2" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "8172d67c", - "metadata": {}, - "outputs": [], - "source": [ - "raw_labels = {\n", - " \"Articles_of_Incorporation_Real_Example_3_txt\": {\n", - " \"name\": \"HealthFirst Solutions LLC\",\n", - " \"shares\": 500000,\n", - " },\n", - " \"Articles_of_Incorporation_Real_Example_2_txt\": {\n", - " \"name\": \"GreenLeaf LLC\",\n", - " \"shares\": None,\n", - " \"directors\": [\"Sarah Miller\", \"Daniel Lee\"],\n", - " },\n", - " \"Articles_of_Incorporation_Real_Example_1_txt\": {\n", - " \"name\": \"TechBoost Corp\",\n", - " \"shares\": 1000000,\n", - " },\n", - " \"Highly_Varied_Article_of_Incorporation_10_txt\": {\n", - " \"name\": \"Brown, Fernandez and Smith\",\n", - " \"shares\": 41141,\n", - " },\n", - " \"Highly_Varied_Article_of_Incorporation_9_txt\": {\n", - " \"name\": \"Ruiz-Goodman\",\n", - " \"shares\": 31783,\n", - " },\n", - " \"Highly_Varied_Article_of_Incorporation_8_txt\": {\n", - " \"name\": \"Gibson, Hunt and Davidson\",\n", - " \"shares\": 96403,\n", - " },\n", - " \"Highly_Varied_Article_of_Incorporation_7_txt\": {\n", - " \"name\": \"Boyd-Browning\",\n", - " \"shares\": 41300,\n", - " },\n", - " \"Highly_Varied_Article_of_Incorporation_6_txt\": {\n", - " \"name\": \"Newton, Moreno and Yang\",\n", - " \"shares\": 73981,\n", - " },\n", - " \"Highly_Varied_Article_of_Incorporation_5_txt\": {\n", - " \"name\": \"Matthews and Sons\",\n", - " \"shares\": 98608,\n", - " },\n", - " \"Highly_Varied_Article_of_Incorporation_4_txt\": {\n", - " \"name\": \"Moore LLC\",\n", - " \"shares\": 5732,\n", - " },\n", - " \"Highly_Varied_Article_of_Incorporation_3_txt\": {\n", - " \"name\": \"Mullen Inc\",\n", - " \"shares\": 76197,\n", - " },\n", - " \"Highly_Varied_Article_of_Incorporation_2_txt\": {\n", - " \"name\": \"Ellis and Sons\",\n", - " \"shares\": 54183,\n", - " },\n", - " \"Highly_Varied_Article_of_Incorporation_1_txt\": {\n", - " \"name\": \"French, Wyatt and Coleman\",\n", - " \"shares\": 78821,\n", - " },\n", - "}\n", - "\n", - "\n", - "def read_dataset(root):\n", - " dataset_rows = []\n", - " for p in glob.glob(os.path.join(root, \"*.txt\")):\n", - " # Have to do replace here because of weave '.' access issues\n", - " example_id = os.path.basename(p).replace(\".\", \"_\")\n", - " label = raw_labels.get(example_id)\n", - " if label:\n", - " dataset_rows.append(\n", - " {\"id\": example_id, \"example\": open(p).read(), \"label\": label}\n", - " )\n", - " return dataset_rows" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "cb93f2a4", - "metadata": {}, - "outputs": [], - "source": [ - "# Can't just make our own types, server won't deserialize.\n", - "# A fairly easy fix.\n", - "@weave.type()\n", - "class Dataset:\n", - " rows: list[typing.Any]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "92c6535c", - "metadata": {}, - "outputs": [], - "source": [ - "raw_dataset = read_dataset(\"/Users/shawn/datasets/aoi\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7e803efd", - "metadata": {}, - "outputs": [], - "source": [ - "# raw_dataset" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "fc723706", - "metadata": { - "scrolled": false - }, - "outputs": [], - "source": [ - "dataset = weave.save(Dataset(raw_dataset), \"my_dataset5\")\n", - "# Now, here I really want to make my own labels in the UI immediately.\n", - "# where should the added column go? A new version of this dataset?\n", - "# yeah sure why not.\n", - "# What's missing for editing to be good?\n", - "# - batch editing, ie make a bunch of changes and choose where/how to save" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4a99df38", - "metadata": {}, - "outputs": [], - "source": [ - "# published = weave.publish(Dataset(raw_dataset), 'weave-flow1/my_dataset1')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "77c71a23", - "metadata": {}, - "outputs": [], - "source": [ - "dataset.rows\n", - "# Here i went to render labels next to dataset.\n", - "# I need access to labels in the notebook memory... would be easy enough to pass in" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "331d88d6", - "metadata": {}, - "outputs": [], - "source": [ - "import re\n", - "\n", - "\n", - "def split_paragraphs(doc):\n", - " lines = [l.strip() for l in doc.split(\"\\n\")]\n", - " stripped_doc = \"\\n\".join(lines)\n", - " return [p.strip() for p in stripped_doc.split(\"\\n\\n\")]\n", - "\n", - "\n", - "def find_first_numeric(s):\n", - " match = re.search(r\"\\d+\", s)\n", - " if match is None:\n", - " return None\n", - " return int(match.group().replace(\",\", \"\"))\n", - "\n", - "\n", - "def predict(dataset_row, config):\n", - " paragraphs = split_paragraphs(dataset_row[\"example\"])\n", - " capital_paragraph = None\n", - " name_paragraph = None\n", - " for p in paragraphs:\n", - " if \"name\" in p.lower():\n", - " name_paragraph = p\n", - " if \"share\" in p.lower():\n", - " capital_paragraph = p\n", - " result = {\n", - " \"name\": None,\n", - " \"shares\": None,\n", - " }\n", - " if capital_paragraph:\n", - " paragraph_start = config.get(\"shares_skip_chars\", 0)\n", - " result[\"shares\"] = find_first_numeric(capital_paragraph[paragraph_start:])\n", - " if name_paragraph:\n", - " match = re.search(r\"is \", name_paragraph)\n", - " if match is not None:\n", - " result[\"name\"] = name_paragraph[match.end() :]\n", - " if result[\"name\"] and config.get(\"name_up_to_period\"):\n", - " match = re.search(r\"\\.\", result[\"name\"])\n", - " if match is not None:\n", - " result[\"name\"] = result[\"name\"][: match.start()]\n", - " return result" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b2378174", - "metadata": {}, - "outputs": [], - "source": [ - "for dataset_row in weave.use(dataset.rows):\n", - " print(predict(dataset_row, {\"shares_skip_chars\": 4}))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "efc63aa7", - "metadata": {}, - "outputs": [], - "source": [ - "fields = [\"name\", \"shares\", \"directors\"]\n", - "\n", - "\n", - "def p_r_f1(tp, fp, fn):\n", - " # if any denom is zero, then zero. could use NaN instead...\n", - " precision = 0\n", - " if tp or fp:\n", - " precision = tp / (tp + fp)\n", - " recall = 0\n", - " if tp or fn:\n", - " recall = tp / (tp + fn)\n", - " f1 = 0\n", - " if precision or recall:\n", - " f1 = 2 * (precision * recall) / (precision + recall)\n", - " return precision, recall, f1\n", - "\n", - "\n", - "def summarize_item(item_result, item_label):\n", - " item_summary = {}\n", - " for f in fields:\n", - " item_summary[f\"{f}_negative\"] = item_result.get(f) is None\n", - " item_summary[f\"{f}_correct\"] = item_result.get(f) == item_label.get(f)\n", - "\n", - " item_correct = sum([item_summary[f\"{f}_correct\"] for f in fields])\n", - " item_tp = sum(\n", - " [item_label.get(f) is not None and item_summary[f\"{f}_correct\"] for f in fields]\n", - " )\n", - " item_fp = sum(\n", - " [\n", - " item_label.get(f) is not None and not item_summary[f\"{f}_correct\"]\n", - " for f in fields\n", - " ]\n", - " )\n", - " item_tn = sum(\n", - " [item_label.get(f) is None and item_summary[f\"{f}_correct\"] for f in fields]\n", - " )\n", - " item_fn = sum(\n", - " [item_label.get(f) is None and not item_summary[f\"{f}_correct\"] for f in fields]\n", - " )\n", - "\n", - " item_precision, item_recall, item_f1 = p_r_f1(item_tp, item_fp, item_fn)\n", - "\n", - " return {\n", - " **item_summary,\n", - " \"correct\": item_correct,\n", - " \"tp\": item_tp,\n", - " \"fp\": item_fp,\n", - " \"tn\": item_tn,\n", - " \"fn\": item_fn,\n", - " \"precision\": item_precision,\n", - " \"recall\": item_recall,\n", - " \"f1\": item_f1,\n", - " }\n", - "\n", - "\n", - "def field_pr(eval_result, field_name):\n", - " tp = sum(\n", - " not item[\"summary\"][f\"{field_name}_negative\"]\n", - " and item[\"summary\"][f\"{field_name}_correct\"]\n", - " for item in eval_result\n", - " )\n", - " fp = sum(\n", - " not item[\"summary\"][f\"{field_name}_negative\"]\n", - " and not item[\"summary\"][f\"{field_name}_correct\"]\n", - " for item in eval_result\n", - " )\n", - " tn = sum(\n", - " item[\"summary\"][f\"{field_name}_negative\"]\n", - " and item[\"summary\"][f\"{field_name}_correct\"]\n", - " for item in eval_result\n", - " )\n", - " fn = sum(\n", - " item[\"summary\"][f\"{field_name}_negative\"]\n", - " and not item[\"summary\"][f\"{field_name}_correct\"]\n", - " for item in eval_result\n", - " )\n", - "\n", - " precision, recall, f1 = p_r_f1(tp, fp, fn)\n", - " return {\n", - " \"tp\": tp,\n", - " \"fp\": fp,\n", - " \"tn\": tn,\n", - " \"fn\": fn,\n", - " \"precision\": precision,\n", - " \"recall\": recall,\n", - " \"f1\": f1,\n", - " }\n", - "\n", - "\n", - "def summarize(eval_result):\n", - " summary = {}\n", - " for field in fields:\n", - " summary[f\"field_{field}\"] = field_pr(eval_result, field)\n", - " for metric in [\"precision\", \"recall\", \"f1\"]:\n", - " summary[f\"avg_{metric}\"] = sum(\n", - " summary[f\"field_{f}\"][metric] for f in fields\n", - " ) / len(fields)\n", - " return summary\n", - "\n", - "\n", - "def evaluate(dataset, predict_config):\n", - " eval_result = []\n", - " correct_count = 0\n", - " count = 0\n", - " for dataset_row in dataset:\n", - " start_time = time.time()\n", - " result = predict(dataset_row, predict_config)\n", - " latency = time.time() - start_time\n", - " latency = random.gauss(\n", - " predict_config[\"latency_mu\"], predict_config[\"latency_sigma\"]\n", - " )\n", - " item_summary = summarize_item(result, dataset_row[\"label\"])\n", - " eval_result.append(\n", - " {\n", - " \"dataset_id\": dataset_row[\"id\"],\n", - " \"result\": result,\n", - " \"summary\": {\"latency\": latency, **item_summary},\n", - " }\n", - " )\n", - " return {\n", - " \"config\": predict_config,\n", - " \"eval_table\": eval_result,\n", - " \"summary\": summarize(eval_result),\n", - " }" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f2248364", - "metadata": {}, - "outputs": [], - "source": [ - "eval_results0 = weave.save(\n", - " evaluate(weave.use(dataset).rows, {\"latency_mu\": 0.3, \"latency_sigma\": 0.1}),\n", - " \"eval_results0\",\n", - ")\n", - "eval_results1 = weave.save(\n", - " evaluate(\n", - " weave.use(dataset).rows,\n", - " {\"latency_mu\": 0.3, \"latency_sigma\": 0.1, \"name_up_to_period\": True},\n", - " ),\n", - " \"eval_results1\",\n", - ")\n", - "eval_results2 = weave.save(\n", - " evaluate(\n", - " weave.use(dataset).rows,\n", - " {\n", - " \"latency_mu\": 0.3,\n", - " \"latency_sigma\": 0.1,\n", - " \"name_up_to_period\": True,\n", - " \"shares_skip_chars\": 4,\n", - " },\n", - " ),\n", - " \"eval_results2\",\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "93727275", - "metadata": {}, - "outputs": [], - "source": [ - "from weave.legacy.panels_py import panel_eval\n", - "\n", - "panel_eval.eval_board(dataset.rows, eval_results0, eval_results2)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "166e8607", - "metadata": {}, - "outputs": [], - "source": [ - "# To add:\n", - "# - backed by W&B runs\n", - "# - show run code / config comparison\n", - "# - show traces of pipelines and compare them\n", - "# - add view of N runs instead of 2" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/weave/legacy/ops_arrow/__init__.py b/weave/legacy/ops_arrow/__init__.py deleted file mode 100644 index 6b954627d8b..00000000000 --- a/weave/legacy/ops_arrow/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from weave.legacy import context_state as _context_state - -_loading_builtins_token = _context_state.set_loading_built_ins() - -from weave.legacy.arrow.arrow import * -from weave.legacy.arrow.convert import * -from weave.legacy.arrow.list_ import * -from weave.legacy.ops_arrow import ops -from weave.legacy.ops_arrow.list_range import range -from weave.legacy.ops_arrow.vectorize import vectorize - -_context_state.clear_loading_built_ins(_loading_builtins_token) diff --git a/weave/legacy/ops_arrow/ops.py b/weave/legacy/ops_arrow/ops.py deleted file mode 100644 index b51ad06934c..00000000000 --- a/weave/legacy/ops_arrow/ops.py +++ /dev/null @@ -1,11 +0,0 @@ -from weave.legacy.ops_arrow.arraylist_ops import * -from weave.legacy.ops_arrow.boolean import * -from weave.legacy.ops_arrow.convert_ops import * -from weave.legacy.ops_arrow.date import * -from weave.legacy.ops_arrow.dict import * -from weave.legacy.ops_arrow.list_join import * -from weave.legacy.ops_arrow.list_ops import * # type: ignore -from weave.legacy.ops_arrow.number import * -from weave.legacy.ops_arrow.obj import * -from weave.legacy.ops_arrow.ref_ops import * -from weave.legacy.ops_arrow.string import * diff --git a/weave/legacy/ops_primitives/test_list_range.py b/weave/legacy/ops_primitives/test_list_range.py deleted file mode 100644 index ce98b09fbae..00000000000 --- a/weave/legacy/ops_primitives/test_list_range.py +++ /dev/null @@ -1,7 +0,0 @@ -import pytest - -import weave - - -def test_range(): - assert weave.use(weave.legacy.ops.range(0, 3, 1)).to_pylist_tagged() == [0, 1, 2] diff --git a/weave/legacy/panels/__init__.py b/weave/legacy/panels/__init__.py deleted file mode 100644 index 8652aaabea1..00000000000 --- a/weave/legacy/panels/__init__.py +++ /dev/null @@ -1,70 +0,0 @@ -from weave.legacy import context_state as _context_state - -_loading_builtins_token = _context_state.set_loading_built_ins() - -from weave.legacy.panels.panel_auto import * - -# basic -from weave.legacy.panels.panel_basic import * - -# top level board -from weave.legacy.panels.panel_board import Board, BoardPanel, BoardPanelLayout -from weave.legacy.panels.panel_card import Card, CardTab -from weave.legacy.panels.panel_color import Color -from weave.legacy.panels.panel_daterange import DateRange - -# domain -from weave.legacy.panels.panel_domain import * -from weave.legacy.panels.panel_dropdown import Dropdown, DropdownConfig -from weave.legacy.panels.panel_each import Each -from weave.legacy.panels.panel_each_column import EachColumn - -# special -from weave.legacy.panels.panel_expression import * -from weave.legacy.panels.panel_facet import Facet -from weave.legacy.panels.panel_facet_tabs import FacetTabs -from weave.legacy.panels.panel_filter_editor import FilterEditor -from weave.legacy.panels.panel_function_editor import ( - FunctionEditor, - FunctionEditorConfig, -) -from weave.legacy.panels.panel_group import ( - Group, - GroupLayoutFlow, - GroupPanel, - GroupPanelLayout, -) -from weave.legacy.panels.panel_grouping_editor import GroupingEditor - -# Incomplete -from weave.legacy.panels.panel_histogram import * -from weave.legacy.panels.panel_html import PanelHtml - -# layout -from weave.legacy.panels.panel_labeled_item import LabeledItem - -# legacy -from weave.legacy.panels.panel_legacy import * -from weave.legacy.panels.panel_markdown import PanelMarkdown - -# Non-standard editor (todo: update) -from weave.legacy.panels.panel_object_picker import ObjectPicker, ObjectPickerConfig -from weave.legacy.panels.panel_plot import Plot, PlotConstants, Series - -# sidebar specific -from weave.legacy.panels.panel_query import Query, QueryCondition, QueryConfig -from weave.legacy.panels.panel_sections import Sections -from weave.legacy.panels.panel_select import SelectEditor, SelectEditorConfig - -# editors -from weave.legacy.panels.panel_slider import Slider, SliderConfig -from weave.legacy.panels.panel_string import PanelString -from weave.legacy.panels.panel_string_editor import StringEditor -from weave.legacy.panels.panel_table import ColumnDef, Table, TableColumn -from weave.legacy.panels.panel_trace import Trace - -# navigation -from weave.legacy.panels.panel_weavelink import WeaveLink -from weave.legacy.panel import Panel - -_context_state.clear_loading_built_ins(_loading_builtins_token) diff --git a/weave/legacy/scripts/clear_cache.py b/weave/legacy/scripts/clear_cache.py index 39a6186efef..b630e019f6d 100644 --- a/weave/legacy/scripts/clear_cache.py +++ b/weave/legacy/scripts/clear_cache.py @@ -1,7 +1,7 @@ import os import time -from weave.legacy import cache +from weave.legacy.weave import cache # Script to run to delete expired caches if __name__ == "__main__": diff --git a/weave/legacy/scripts/syndata.py b/weave/legacy/scripts/syndata.py index c2436a7efd9..6ecbc110363 100644 --- a/weave/legacy/scripts/syndata.py +++ b/weave/legacy/scripts/syndata.py @@ -5,8 +5,8 @@ import pyarrow as pa from scipy.signal import butter, filtfilt -from weave.legacy import util -from ..ops_arrow import ArrowWeaveList +from weave.legacy.weave import util +from weave.legacy.weave.ops_arrow import ArrowWeaveList value_fns: list[typing.Any] = [ lambda steps: steps**2, diff --git a/weave/legacy/scripts/syndata_mon.py b/weave/legacy/scripts/syndata_mon.py index d93d7ccb64d..d615b6eb777 100644 --- a/weave/legacy/scripts/syndata_mon.py +++ b/weave/legacy/scripts/syndata_mon.py @@ -10,7 +10,7 @@ import tqdm from faker import Faker -from weave.legacy.arrow.list_ import ArrowWeaveList, dataframe_to_arrow +from weave.legacy.weave.arrow.list_ import ArrowWeaveList, dataframe_to_arrow # Generate the version schedule diff --git a/weave/legacy/tests/test_access.py b/weave/legacy/tests/test_access.py index 15b1157581d..f15627af727 100644 --- a/weave/legacy/tests/test_access.py +++ b/weave/legacy/tests/test_access.py @@ -1,7 +1,7 @@ import pytest import weave -from weave.legacy import ( +from weave.legacy.weave import ( artifact_fs, artifact_local, environment, @@ -25,7 +25,7 @@ def public_env(): def test_access_file(public_env): with pytest.raises(errors.WeaveAccessDeniedError): - weave.use(weave.legacy.ops.local_path("/tmp/bad.json")) + weave.use(weave.legacy.weave.ops.local_path("/tmp/bad.json")) @pytest.mark.parametrize("path", ["..", "/tmp", "//tmp", "//tmp/bad.json", "/tmp/.../"]) diff --git a/weave/legacy/tests/test_api.py b/weave/legacy/tests/test_api.py index 75111a6fc8c..25ca58a9d8b 100644 --- a/weave/legacy/tests/test_api.py +++ b/weave/legacy/tests/test_api.py @@ -1,8 +1,8 @@ import shutil -from weave.legacy import api as weave +from weave.legacy.weave import api as weave -from ...legacy.show import _show_params +from ...legacy.weave.show import _show_params def test_print_save_val(): diff --git a/weave/legacy/tests/test_arrow.py b/weave/legacy/tests/test_arrow.py index afad3e65b2d..b9966221b94 100644 --- a/weave/legacy/tests/test_arrow.py +++ b/weave/legacy/tests/test_arrow.py @@ -7,8 +7,8 @@ import pytest from PIL import Image -from weave.legacy import api as weave -from weave.legacy import ( +from weave.legacy.weave import api as weave +from weave.legacy.weave import ( box, context_state, errors, @@ -21,20 +21,20 @@ # If you're thinking of import vectorize here, don't! Put your # tests in test_arrow_vectorizer.py instead -from weave.legacy import ops_arrow as arrow -from weave.legacy import weave_types as types -from weave.legacy.arrow import constructors -from weave.legacy.arrow.arrow_tags import ( +from weave.legacy.weave import ops_arrow as arrow +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.arrow import constructors +from weave.legacy.weave.arrow.arrow_tags import ( recursively_encode_pyarrow_strings_as_dictionaries, ) -from weave.legacy.language_features.tagging import ( +from weave.legacy.weave.language_features.tagging import ( make_tag_getter_op, tag_store, tagged_value_type, ) -from weave.legacy.op_def import map_type -from weave.legacy.ops_domain import project_ops -from weave.legacy.ops_primitives import list_, make_list +from weave.legacy.weave.op_def import map_type +from weave.legacy.weave.ops_domain import project_ops +from weave.legacy.weave.ops_primitives import list_, make_list from .util import list_arrow_test_helpers as lath from weave.legacy.tests.util import tag_test_util as ttu @@ -1316,7 +1316,7 @@ def test_stddev(): def test_join_all_struct_val(): - from weave.legacy import ops_arrow + from weave.legacy.weave import ops_arrow t1 = arrow.to_arrow([{"a": 5, "b": {"c": 6}}]) t2 = arrow.to_arrow([{"a": 9, "b": {"c": 10}}, {"a": 5, "b": {"c": 11}}]) diff --git a/weave/legacy/tests/test_arrow_awl.py b/weave/legacy/tests/test_arrow_awl.py index 62babfc75bd..03e857e288f 100644 --- a/weave/legacy/tests/test_arrow_awl.py +++ b/weave/legacy/tests/test_arrow_awl.py @@ -3,10 +3,10 @@ import pytest import weave -import weave.legacy.weave_types as types -from weave.legacy import box, ops_arrow -from weave.legacy.arrow.convert import to_arrow -from weave.legacy.language_features.tagging import tag_store, tagged_value_type +import weave.legacy.weave.weave_types as types +from weave.legacy.weave import box, ops_arrow +from weave.legacy.weave.arrow.convert import to_arrow +from weave.legacy.weave.language_features.tagging import tag_store, tagged_value_type from weave.legacy.tests.util.concrete_tagged_value import ( TaggedValue, diff --git a/weave/legacy/tests/test_arrow_concat.py b/weave/legacy/tests/test_arrow_concat.py index 45317b3f39a..4e8f551475a 100644 --- a/weave/legacy/tests/test_arrow_concat.py +++ b/weave/legacy/tests/test_arrow_concat.py @@ -3,9 +3,9 @@ import pytest import weave -from weave.legacy import artifact_local, storage -from weave.legacy.ops_arrow import to_arrow -from weave.legacy.ops_domain import wbmedia +from weave.legacy.weave import artifact_local, storage +from weave.legacy.weave.ops_arrow import to_arrow +from weave.legacy.weave.ops_domain import wbmedia # This is not a valid artifact, but we need one to test. We set _read_dirname # so that the artifact's is_saved property is True, so that everything works diff --git a/weave/legacy/tests/test_arrow_perf.py b/weave/legacy/tests/test_arrow_perf.py index 2ee09f152ed..87f7c2c4576 100644 --- a/weave/legacy/tests/test_arrow_perf.py +++ b/weave/legacy/tests/test_arrow_perf.py @@ -5,7 +5,7 @@ import pytest import weave -from weave.legacy import ops_arrow, ops_primitives +from weave.legacy.weave import ops_arrow, ops_primitives @pytest.mark.skip(reason="Performance test") diff --git a/weave/legacy/tests/test_arrow_topy.py b/weave/legacy/tests/test_arrow_topy.py index 8e6d87e5c70..59317cc3ce8 100644 --- a/weave/legacy/tests/test_arrow_topy.py +++ b/weave/legacy/tests/test_arrow_topy.py @@ -4,7 +4,7 @@ import pytest import weave -from weave.legacy import ops_arrow +from weave.legacy.weave import ops_arrow from weave.legacy.tests.util.concrete_tagged_value import ( TaggedValue, diff --git a/weave/legacy/tests/test_arrow_vectorizer.py b/weave/legacy/tests/test_arrow_vectorizer.py index 1bb224fdb4f..fc920d14c48 100644 --- a/weave/legacy/tests/test_arrow_vectorizer.py +++ b/weave/legacy/tests/test_arrow_vectorizer.py @@ -5,19 +5,19 @@ import pytest from pyarrow import compute as pc -from weave.legacy import api as weave -from weave.legacy import box, dispatch, errors, ops, weave_internal -from weave.legacy import ops_arrow as arrow -from weave.legacy import weave_types as types -from weave.legacy.language_features.tagging import ( +from weave.legacy.weave import api as weave +from weave.legacy.weave import box, dispatch, errors, ops, weave_internal +from weave.legacy.weave import ops_arrow as arrow +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.language_features.tagging import ( make_tag_getter_op, tag_store, tagged_value_type, ) -from weave.legacy.ops_arrow import arraylist_ops, convert_ops, util -from weave.legacy.ops_domain import run_ops -from weave.legacy.ops_domain import wb_domain_types as wdt -from weave.legacy.ops_primitives import Boolean, Number, date, dict_, list_ +from weave.legacy.weave.ops_arrow import arraylist_ops, convert_ops, util +from weave.legacy.weave.ops_domain import run_ops +from weave.legacy.weave.ops_domain import wb_domain_types as wdt +from weave.legacy.weave.ops_primitives import Boolean, Number, date, dict_, list_ string_ops_test_cases = [ ("eq-scalar", lambda x: x == "bc", [True, False, False]), diff --git a/weave/legacy/tests/test_artifact.py b/weave/legacy/tests/test_artifact.py index 2c62094c36e..5a05479a9d0 100644 --- a/weave/legacy/tests/test_artifact.py +++ b/weave/legacy/tests/test_artifact.py @@ -1,8 +1,8 @@ import pytest import weave -from weave.legacy import artifact_fs, artifact_local, storage -from weave.legacy import ops_arrow as arrow +from weave.legacy.weave import artifact_fs, artifact_local, storage +from weave.legacy.weave import ops_arrow as arrow def test_artifact(): diff --git a/weave/legacy/tests/test_artifact_metadata.py b/weave/legacy/tests/test_artifact_metadata.py index 30e8812d4dd..889eef4137b 100644 --- a/weave/legacy/tests/test_artifact_metadata.py +++ b/weave/legacy/tests/test_artifact_metadata.py @@ -1,8 +1,8 @@ import wandb import weave -from weave.legacy import artifact_local, artifact_wandb -from weave.legacy.wandb_interface.wandb_artifact_pusher import ( +from weave.legacy.weave import artifact_local, artifact_wandb +from weave.legacy.weave.wandb_interface.wandb_artifact_pusher import ( write_artifact_to_wandb, ) @@ -56,8 +56,8 @@ def test_artifact_metadata(user_by_api_key_in_env): } # Push an artifact to wandb and verify that the metadata is correct - remote_uri = weave.legacy.ops.publish_artifact( - weave.legacy.ops.get(local_art.uri + "/obj"), + remote_uri = weave.legacy.weave.ops.publish_artifact( + weave.legacy.weave.ops.get(local_art.uri + "/obj"), "test_artifact", "test_project", None, @@ -113,7 +113,7 @@ def test_artifact_files_count(user_by_api_key_in_env): run.finish() count_node = ( - weave.legacy.ops.project(run.entity, run.project) + weave.legacy.weave.ops.project(run.entity, run.project) .artifact("test") .membershipForAlias("v0") .artifactVersion() diff --git a/weave/legacy/tests/test_assignment.py b/weave/legacy/tests/test_assignment.py index dfc10703f07..6f321857939 100644 --- a/weave/legacy/tests/test_assignment.py +++ b/weave/legacy/tests/test_assignment.py @@ -7,7 +7,7 @@ @pytest.mark.parametrize("type_name, type_cls", [(t.name, t) for t in types]) def test_const_assignment(type_name, type_cls): - from weave.legacy.ops_domain import wb_domain_types as wdt + from weave.legacy.weave.ops_domain import wb_domain_types as wdt params = [] # Quick list of types that don't work with this parametrization diff --git a/weave/legacy/tests/test_async.py b/weave/legacy/tests/test_async.py index e0a9632154e..a7601ceda3e 100644 --- a/weave/legacy/tests/test_async.py +++ b/weave/legacy/tests/test_async.py @@ -1,6 +1,6 @@ import pytest -from weave.legacy import api, async_demo, ops, runs, storage +from weave.legacy.weave import api, async_demo, ops, runs, storage def test_run_basic(): diff --git a/weave/legacy/tests/test_async_queue.py b/weave/legacy/tests/test_async_queue.py index 18c37511e38..5556f89b82a 100644 --- a/weave/legacy/tests/test_async_queue.py +++ b/weave/legacy/tests/test_async_queue.py @@ -4,7 +4,7 @@ import aioprocessing import pytest -from weave.legacy.async_queue import ProcessQueue, Queue, ThreadQueue +from weave.legacy.weave.async_queue import ProcessQueue, Queue, ThreadQueue async def process_producer(queue: Queue) -> None: diff --git a/weave/legacy/tests/test_basic_ops.py b/weave/legacy/tests/test_basic_ops.py index e8868da0e03..a40920b967d 100644 --- a/weave/legacy/tests/test_basic_ops.py +++ b/weave/legacy/tests/test_basic_ops.py @@ -1,8 +1,8 @@ -from weave.legacy import api as weave -from weave.legacy import box, ops -from weave.legacy.ops_primitives import number -from weave.legacy.ops_primitives.string import * -from weave.legacy.weave_internal import make_const_node +from weave.legacy.weave import api as weave +from weave.legacy.weave import box, ops +from weave.legacy.weave.ops_primitives import number +from weave.legacy.weave.ops_primitives.string import * +from weave.legacy.weave.weave_internal import make_const_node def test_number_ops(): diff --git a/weave/legacy/tests/test_box.py b/weave/legacy/tests/test_box.py index 22a596cbdaf..4ece9ef3949 100644 --- a/weave/legacy/tests/test_box.py +++ b/weave/legacy/tests/test_box.py @@ -1,6 +1,6 @@ import datetime -from weave.legacy import box +from weave.legacy.weave import box def test_boxdatetime(): diff --git a/weave/legacy/tests/test_cache.py b/weave/legacy/tests/test_cache.py index 0fe6243504c..7f46a6723cb 100644 --- a/weave/legacy/tests/test_cache.py +++ b/weave/legacy/tests/test_cache.py @@ -2,7 +2,7 @@ import os import time -from weave.legacy import cache, environment +from weave.legacy.weave import cache, environment def test_lru_time_window_cache(): diff --git a/weave/legacy/tests/test_codify.py b/weave/legacy/tests/test_codify.py index 9d73a391f7c..fdffd2e4e51 100644 --- a/weave/legacy/tests/test_codify.py +++ b/weave/legacy/tests/test_codify.py @@ -2,7 +2,7 @@ import pytest import weave -from weave.legacy import panels +from weave.legacy.weave import panels # IMPORTANT: Do not import other symbols inside of weave # so that we ensure the produced code only relies on the weave symbol. @@ -19,24 +19,24 @@ ), ( panels.Group(), - "weave.legacy.panels.panel_group.Group()", + "weave.legacy.weave.panels.panel_group.Group()", ), ( lambda: panels.Table( - weave.legacy.ops.range(1, 100, 1).map( - lambda row: weave.legacy.ops_primitives.dict.dict_( + weave.legacy.weave.ops.range(1, 100, 1).map( + lambda row: weave.legacy.weave.ops_primitives.dict.dict_( x=row, - y=weave.legacy.ops_primitives.list_.make_list( + y=weave.legacy.weave.ops_primitives.list_.make_list( a=row, ), ) ) ), - lambda: """weave.legacy.panels.panel_table.Table( - weave.legacy.ops_arrow.list_range.range(1, 100, 1,).map( - lambda row: weave.legacy.ops_primitives.dict.dict_( + lambda: """weave.legacy.weave.panels.panel_table.Table( + weave.legacy.weave.ops_arrow.list_range.range(1, 100, 1,).map( + lambda row: weave.legacy.weave.ops_primitives.dict.dict_( x=row, - y=weave.legacy.ops_primitives.list_.make_list( + y=weave.legacy.weave.ops_primitives.list_.make_list( a=row, ), ), @@ -45,16 +45,16 @@ ), ( lambda: panels.Plot( - weave.legacy.ops.range(1, 100, 1).map( - lambda row: weave.legacy.ops_primitives.dict.dict_( + weave.legacy.weave.ops.range(1, 100, 1).map( + lambda row: weave.legacy.weave.ops_primitives.dict.dict_( x=row, y=row**2, ) ) ), - lambda: """weave.legacy.panels.panel_plot.Plot( - weave.legacy.ops_arrow.list_range.range(1, 100, 1,).map( - lambda row: weave.legacy.ops_primitives.dict.dict_( + lambda: """weave.legacy.weave.panels.panel_plot.Plot( + weave.legacy.weave.ops_arrow.list_range.range(1, 100, 1,).map( + lambda row: weave.legacy.weave.ops_primitives.dict.dict_( x=row, y=row.powBinary(2,), ), @@ -65,7 +65,7 @@ lambda: panels.Group( items={ "table": panels.Table( - weave.legacy.ops.range(1, 100, 1), + weave.legacy.weave.ops.range(1, 100, 1), columns=[ lambda row: row, lambda row: row**2, @@ -99,26 +99,26 @@ ), } ), - lambda: """weave.legacy.panels.panel_group.Group( + lambda: """weave.legacy.weave.panels.panel_group.Group( items={ - "table": weave.legacy.panels.panel_table.Table( - weave.legacy.ops_arrow.list_range.range(1, 100, 1,), + "table": weave.legacy.weave.panels.panel_table.Table( + weave.legacy.weave.ops_arrow.list_range.range(1, 100, 1,), columns=[ lambda row: row, lambda row: row.powBinary(2,), ], ), - "all_rows": lambda table: weave.legacy.panels.panel_plot.Plot( + "all_rows": lambda table: weave.legacy.weave.panels.panel_plot.Plot( table.all_rows(), x=lambda row: row["c_0"], y=lambda row: row["c_1"], ), - "derived": lambda table, all_rows: weave.legacy.panels.panel_group.Group( + "derived": lambda table, all_rows: weave.legacy.weave.panels.panel_group.Group( layoutMode="horizontal", items={ - "rows": weave.legacy.panels.panel_group.Group( + "rows": weave.legacy.weave.panels.panel_group.Group( items={ - "pinned_rows": weave.legacy.panels.panel_plot.Plot( + "pinned_rows": weave.legacy.weave.panels.panel_plot.Plot( table.pinned_rows(), x=lambda row: row["c_0"], y=lambda row: row["c_1"], @@ -126,7 +126,7 @@ "active_row": lambda pinned_rows: table.active_row(), }, ), - "data": lambda rows: weave.legacy.panels.panel_group.Group( + "data": lambda rows: weave.legacy.weave.panels.panel_group.Group( items={ "pinned_data": table.pinned_data(), "active_data": lambda pinned_data: table.active_data(), @@ -153,7 +153,7 @@ def test_group_case(cereal_csv, consistent_table_col_ids): panels.Group( items={ "plot": panels.Plot( - weave.legacy.ops.local_path(cereal_csv).readcsv(), + weave.legacy.weave.ops.local_path(cereal_csv).readcsv(), x=lambda row: row["protein"], y=lambda row: row["calories"], ), @@ -166,16 +166,16 @@ def test_group_case(cereal_csv, consistent_table_col_ids): ), } ), - '''weave.legacy.panels.panel_group.Group( + '''weave.legacy.weave.panels.panel_group.Group( items={ - "plot": weave.legacy.panels.panel_plot.Plot( - weave.legacy.ops.local_path("''' + "plot": weave.legacy.weave.panels.panel_plot.Plot( + weave.legacy.weave.ops.local_path("''' + cereal_csv + """",).readcsv(), x=lambda row: row["protein"], y=lambda row: row["calories"], ), - "table": lambda plot: weave.legacy.panels.panel_table.Table( + "table": lambda plot: weave.legacy.weave.panels.panel_table.Table( plot.selected_rows(), columns=[ lambda row: row["c_0"], @@ -191,12 +191,12 @@ def test_group_case(cereal_csv, consistent_table_col_ids): def test_plot_case(cereal_csv, consistent_table_col_ids): _test_object_codification( panels.Plot( - weave.legacy.ops.local_path(cereal_csv).readcsv(), + weave.legacy.weave.ops.local_path(cereal_csv).readcsv(), x=lambda row: row["protein"], y=lambda row: row["calories"], ), - f"""weave.legacy.panels.panel_plot.Plot( - weave.legacy.ops.local_path('{cereal_csv}',).readcsv(), + f"""weave.legacy.weave.panels.panel_plot.Plot( + weave.legacy.weave.ops.local_path('{cereal_csv}',).readcsv(), x=lambda row: row["protein"], y=lambda row: row["calories"], )""", @@ -206,14 +206,14 @@ def test_plot_case(cereal_csv, consistent_table_col_ids): def test_table_case(cereal_csv, consistent_table_col_ids): _test_object_codification( panels.Table( - weave.legacy.ops.local_path(cereal_csv).readcsv(), + weave.legacy.weave.ops.local_path(cereal_csv).readcsv(), columns=[ lambda row: row["protein"], lambda row: row["calories"], ], ), - f"""weave.legacy.panels.panel_table.Table( - weave.legacy.ops.local_path('{cereal_csv}',).readcsv(), + f"""weave.legacy.weave.panels.panel_table.Table( + weave.legacy.weave.ops.local_path('{cereal_csv}',).readcsv(), columns=[ lambda row: row["protein"], lambda row: row["calories"], @@ -223,7 +223,7 @@ def test_table_case(cereal_csv, consistent_table_col_ids): def _test_object_codification(panel, code=None): - panel_code = weave.legacy.codify.object_to_code(panel) + panel_code = weave.legacy.weave.codify.object_to_code(panel) generated_panel = eval(panel_code) diff --git a/weave/legacy/tests/test_compile.py b/weave/legacy/tests/test_compile.py index dc5679d769d..6e1895eff25 100644 --- a/weave/legacy/tests/test_compile.py +++ b/weave/legacy/tests/test_compile.py @@ -2,14 +2,14 @@ import wandb import weave -from weave.legacy import async_demo, compile, graph -from weave.legacy import weave_types as types -from weave.legacy.api import use -from weave.legacy.dispatch import RuntimeOutputNode -from weave.legacy.ops_arrow import to_arrow -from weave.legacy.ops_arrow.vectorize import raise_on_python_bailout -from weave.legacy.wandb_interface.wandb_stream_table import StreamTable -from weave.legacy.weave_internal import const, define_fn, make_const_node +from weave.legacy.weave import async_demo, compile, graph +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import use +from weave.legacy.weave.dispatch import RuntimeOutputNode +from weave.legacy.weave.ops_arrow import to_arrow +from weave.legacy.weave.ops_arrow.vectorize import raise_on_python_bailout +from weave.legacy.weave.wandb_interface.wandb_stream_table import StreamTable +from weave.legacy.weave.weave_internal import const, define_fn, make_const_node def test_automatic_await_compile(): @@ -144,21 +144,21 @@ def test_executing_js_multi_root(): def test_optimize_merge_empty_dict(): - non_empty_dict = weave.legacy.ops.dict_(a=5, b=2) + non_empty_dict = weave.legacy.weave.ops.dict_(a=5, b=2) assert ( compile.compile_simple_optimizations( - [weave.legacy.ops.TypedDict.merge(non_empty_dict, weave.legacy.ops.dict_())] + [weave.legacy.weave.ops.TypedDict.merge(non_empty_dict, weave.legacy.weave.ops.dict_())] )[0].to_json() == non_empty_dict.to_json() ) assert ( compile.compile_simple_optimizations( - [weave.legacy.ops.TypedDict.merge(weave.legacy.ops.dict_(), non_empty_dict)] + [weave.legacy.weave.ops.TypedDict.merge(weave.legacy.weave.ops.dict_(), non_empty_dict)] )[0].to_json() == non_empty_dict.to_json() ) - non_simplified_merge = weave.legacy.ops.TypedDict.merge( - weave.legacy.ops.dict_(j=3), non_empty_dict + non_simplified_merge = weave.legacy.weave.ops.TypedDict.merge( + weave.legacy.weave.ops.dict_(j=3), non_empty_dict ) assert ( compile.compile_simple_optimizations([non_simplified_merge])[0].to_json() @@ -167,12 +167,12 @@ def test_optimize_merge_empty_dict(): def test_compile_lambda_uniqueness(): - list_node_1 = weave.legacy.ops.make_list(a=make_const_node(weave.types.Number(), 1)) - list_node_2 = weave.legacy.ops.make_list(a=make_const_node(weave.types.Number(), 2)) + list_node_1 = weave.legacy.weave.ops.make_list(a=make_const_node(weave.types.Number(), 1)) + list_node_2 = weave.legacy.weave.ops.make_list(a=make_const_node(weave.types.Number(), 2)) fn_node = define_fn({"row": weave.types.Number()}, lambda row: row + 1) mapped_1 = list_node_1.map(fn_node) mapped_2 = list_node_2.map(fn_node) - combined = weave.legacy.ops.make_list(a=mapped_1, b=mapped_2) + combined = weave.legacy.weave.ops.make_list(a=mapped_1, b=mapped_2) concatted = combined.concat() # list node contains 2 nodes (const, list), x 2 = 4 @@ -204,7 +204,7 @@ def test_compile_lambda_uniqueness(): # This test demonstrates successful execution when there is an explicit # const function instead of a direct node (resulting in an intermediate execution op) # """ -# history_node = weave.legacy.ops.project(run.entity, run.project).run(run.id).history2() +# history_node = weave.legacy.weave.ops.project(run.entity, run.project).run(run.id).history2() # pick = const(history_node).pick("val") # res = weave.use(pick) # assert res.to_pylist_notags() == list(range(10)) @@ -223,7 +223,7 @@ def test_compile_through_function_call(user_by_api_key_in_env): fn_node = define_fn( {"entity_name": types.String()}, lambda entity_name: ( - weave.legacy.ops.project(entity_name, run.project).run(run.id).history2() + weave.legacy.weave.ops.project(entity_name, run.project).run(run.id).history2() ), ) called_node = fn_node(run.entity) @@ -237,7 +237,7 @@ def test_compile_list_flatten_to_awl_concat(): # When the outer list-structure is a list, we want to dispatch to concat, preferably AWL-concat # when the outer list-structure is an AWL, we want to dispatch ensure that we use AWL ops # list of lists - list_list_node = weave.legacy.ops.make_list(a=[1], b=[2]) + list_list_node = weave.legacy.weave.ops.make_list(a=[1], b=[2]) list_list_node_concat = list_list_node.concat() list_list_node_flatten = list_list_node.flatten() list_list_node_concat_compiled = compile.compile([list_list_node_concat])[0] @@ -245,7 +245,7 @@ def test_compile_list_flatten_to_awl_concat(): assert list_list_node_concat_compiled.from_op.name == "concat" assert list_list_node_flatten_compiled.from_op.name == "flatten" # list of awls - list_awl_node = weave.legacy.ops.make_list(a=to_arrow([1]), b=to_arrow([2])) + list_awl_node = weave.legacy.weave.ops.make_list(a=to_arrow([1]), b=to_arrow([2])) list_awl_node_concat = list_awl_node.concat() list_awl_node_flatten = list_awl_node.flatten() list_awl_node_concat_compiled = compile.compile([list_awl_node_concat])[0] diff --git a/weave/legacy/tests/test_complex_calls.py b/weave/legacy/tests/test_complex_calls.py index bb480e1b800..94bebf4cf9f 100644 --- a/weave/legacy/tests/test_complex_calls.py +++ b/weave/legacy/tests/test_complex_calls.py @@ -1,5 +1,5 @@ import weave -from weave.legacy import weave_internal +from weave.legacy.weave import weave_internal def test_weave_fn_in_data(): diff --git a/weave/legacy/tests/test_cond.py b/weave/legacy/tests/test_cond.py index be9b7888e45..f6030535c74 100644 --- a/weave/legacy/tests/test_cond.py +++ b/weave/legacy/tests/test_cond.py @@ -1,12 +1,12 @@ import weave -from weave.legacy import ops_arrow +from weave.legacy.weave import ops_arrow def test_cond_basic(): - assert weave.use(weave.legacy.ops.cond({"a": True}, {"a": 5})) == 5 - assert weave.use(weave.legacy.ops.cond({"a": False}, {"a": 5})) == None + assert weave.use(weave.legacy.weave.ops.cond({"a": True}, {"a": 5})) == 5 + assert weave.use(weave.legacy.weave.ops.cond({"a": False}, {"a": 5})) == None assert ( - weave.use(weave.legacy.ops.cond({"a": False, "b": True}, {"a": 5, "b": 6})) == 6 + weave.use(weave.legacy.weave.ops.cond({"a": False, "b": True}, {"a": 5, "b": 6})) == 6 ) @@ -47,9 +47,9 @@ def test_cond_vector(): ) assert weave.use( conds.map( - lambda row: weave.legacy.ops.cond( - weave.legacy.ops.dict_(**{"a": row["a"], "b": row["b"]}), - weave.legacy.ops.dict_(**{"a": row["val_a"], "b": row["val_b"]}), + lambda row: weave.legacy.weave.ops.cond( + weave.legacy.weave.ops.dict_(**{"a": row["a"], "b": row["b"]}), + weave.legacy.weave.ops.dict_(**{"a": row["val_a"], "b": row["val_b"]}), ) ) ).to_pylist_raw() == [5, None, 10] @@ -68,9 +68,9 @@ def test_cond_vector_arr_value(): ) assert weave.use( conds.map( - lambda row: weave.legacy.ops.cond( - weave.legacy.ops.dict_(**{"a": row["a"], "b": row["b"]}), - weave.legacy.ops.dict_(**{"a": row["val_a"], "b": row["val_b"]}), + lambda row: weave.legacy.weave.ops.cond( + weave.legacy.weave.ops.dict_(**{"a": row["a"], "b": row["b"]}), + weave.legacy.weave.ops.dict_(**{"a": row["val_a"], "b": row["val_b"]}), ) ) ).to_pylist_raw() == [[1, 2], None, [11, 12]] @@ -89,9 +89,9 @@ def test_cond_vector_mixed(): ) assert weave.use( conds.map( - lambda row: weave.legacy.ops.cond( - weave.legacy.ops.dict_(**{"a": row["a"], "b": row["b"]}), - weave.legacy.ops.dict_(**{"a": row["val_a"], "b": 99}), + lambda row: weave.legacy.weave.ops.cond( + weave.legacy.weave.ops.dict_(**{"a": row["a"], "b": row["b"]}), + weave.legacy.weave.ops.dict_(**{"a": row["val_a"], "b": 99}), ) ) ).to_pylist_raw() == [1, None, 99] @@ -110,9 +110,9 @@ def test_cond_vector_mixed_arr_value(): ) assert weave.use( conds.map( - lambda row: weave.legacy.ops.cond( - weave.legacy.ops.dict_(**{"a": row["a"], "b": row["b"]}), - weave.legacy.ops.dict_(**{"a": row["val_a"], "b": [99, 100]}), + lambda row: weave.legacy.weave.ops.cond( + weave.legacy.weave.ops.dict_(**{"a": row["a"], "b": row["b"]}), + weave.legacy.weave.ops.dict_(**{"a": row["val_a"], "b": [99, 100]}), ) ) ).to_pylist_raw() == [[1, 2], None, [99, 100]] diff --git a/weave/legacy/tests/test_const_type_mapper.py b/weave/legacy/tests/test_const_type_mapper.py index 792294572d0..ce2fccef3c0 100644 --- a/weave/legacy/tests/test_const_type_mapper.py +++ b/weave/legacy/tests/test_const_type_mapper.py @@ -1,7 +1,7 @@ import typing import weave -from weave.legacy import context_state, weave_internal +from weave.legacy.weave import context_state, weave_internal _loading_builtins_token = context_state.set_loading_built_ins() diff --git a/weave/legacy/tests/test_custom_types.py b/weave/legacy/tests/test_custom_types.py index 4ee201e8071..75a1aaeefdc 100644 --- a/weave/legacy/tests/test_custom_types.py +++ b/weave/legacy/tests/test_custom_types.py @@ -1,9 +1,9 @@ import pytest from PIL import Image -from weave.legacy import api as weave -from weave.legacy import context_state as _context -from weave.legacy import ops_arrow +from weave.legacy.weave import api as weave +from weave.legacy.weave import context_state as _context +from weave.legacy.weave import ops_arrow from ... import errors from weave.legacy.tests.util import geom diff --git a/weave/legacy/tests/test_datetime_timestamp.py b/weave/legacy/tests/test_datetime_timestamp.py index d878cff1d19..c53fc6c38ec 100644 --- a/weave/legacy/tests/test_datetime_timestamp.py +++ b/weave/legacy/tests/test_datetime_timestamp.py @@ -4,7 +4,7 @@ import pytest import weave -from weave.legacy.ops_primitives import date +from weave.legacy.weave.ops_primitives import date def assert_date_string( diff --git a/weave/legacy/tests/test_decorators.py b/weave/legacy/tests/test_decorators.py index 7682136833f..72ec915a0ae 100644 --- a/weave/legacy/tests/test_decorators.py +++ b/weave/legacy/tests/test_decorators.py @@ -1,7 +1,7 @@ -from weave.legacy import api as weave -from weave.legacy import storage -from weave.legacy import weave_types as types -from weave.legacy.decorator_op import op +from weave.legacy.weave import api as weave +from weave.legacy.weave import storage +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.decorator_op import op def test_function_op_name(): diff --git a/weave/legacy/tests/test_derive_op.py b/weave/legacy/tests/test_derive_op.py index 637255a8ca7..ee3dc7f6c03 100644 --- a/weave/legacy/tests/test_derive_op.py +++ b/weave/legacy/tests/test_derive_op.py @@ -1,6 +1,6 @@ -from weave.legacy import api as weave +from weave.legacy.weave import api as weave -from ...legacy import registry_mem +from ...legacy.weave import registry_mem def test_mapped_add(): diff --git a/weave/legacy/tests/test_dispatch.py b/weave/legacy/tests/test_dispatch.py index 253fb3a8b2c..b9c3eacd833 100644 --- a/weave/legacy/tests/test_dispatch.py +++ b/weave/legacy/tests/test_dispatch.py @@ -1,7 +1,7 @@ import pytest import weave -from weave.legacy import ops_arrow +from weave.legacy.weave import ops_arrow def test_dispatch_lambda(): diff --git a/weave/legacy/tests/test_examples.py b/weave/legacy/tests/test_examples.py index 1fc1a60d773..01b390526e3 100644 --- a/weave/legacy/tests/test_examples.py +++ b/weave/legacy/tests/test_examples.py @@ -1,8 +1,8 @@ import math import typing -from weave.legacy import api as weave -from weave.legacy import context, context_state +from weave.legacy.weave import api as weave +from weave.legacy.weave import context, context_state class XOnly(typing.TypedDict): diff --git a/weave/legacy/tests/test_execute.py b/weave/legacy/tests/test_execute.py index 8c77e72a21e..bb8c4d73e9f 100644 --- a/weave/legacy/tests/test_execute.py +++ b/weave/legacy/tests/test_execute.py @@ -4,14 +4,14 @@ import pytest import weave -from weave.legacy import api, environment, execute, ops, weave_internal -from weave.legacy import weave_types as types +from weave.legacy.weave import api, environment, execute, ops, weave_internal +from weave.legacy.weave import weave_types as types from . import test_wb execute_test_count_op_run_count = 0 -from weave.legacy import context_state as _context_state +from weave.legacy.weave import context_state as _context_state _loading_builtins_token = _context_state.set_loading_built_ins() @@ -173,12 +173,12 @@ def test_cache_column(): expected_result = [{"x": x, "y": x + 10000} for x in input_vals] l = weave.save(input_vals) - mapped = l.map(lambda x: weave.legacy.ops.dict_(x=x, y=expensive_op(x))) + mapped = l.map(lambda x: weave.legacy.weave.ops.dict_(x=x, y=expensive_op(x))) res = weave.use(mapped) assert res == expected_result latest_obj = weave.use( - weave.legacy.ops.get("local-artifact:///run-op-expensive_op:latest/obj") + weave.legacy.weave.ops.get("local-artifact:///run-op-expensive_op:latest/obj") ) assert len(latest_obj) == len(input_vals) assert len(weave.versions(latest_obj)) == 1 @@ -197,7 +197,7 @@ def test_none_not_cached(): assert res == expected_result latest_obj = weave.use( - weave.legacy.ops.get("local-artifact:///run-op-expensive_op:latest/obj") + weave.legacy.weave.ops.get("local-artifact:///run-op-expensive_op:latest/obj") ) assert len(latest_obj) == 1 # not 2! None not cached! assert len(weave.versions(latest_obj)) == 1 diff --git a/weave/legacy/tests/test_execute_fast.py b/weave/legacy/tests/test_execute_fast.py index 0208f29e662..01d26d43b18 100644 --- a/weave/legacy/tests/test_execute_fast.py +++ b/weave/legacy/tests/test_execute_fast.py @@ -1,6 +1,6 @@ import weave -from weave.legacy import dispatch, weave_internal -from weave.legacy import weave_types as types +from weave.legacy.weave import dispatch, weave_internal +from weave.legacy.weave import weave_types as types from weave.legacy.tests.util import weavejs_ops @@ -35,7 +35,7 @@ def test_empty_list(): map_fn = weave_internal.define_fn( {"row": arr.type.object_type}, lambda row: row.merge( - weave.legacy.ops.dict_(output_classid=row["output_class"].id()) + weave.legacy.weave.ops.dict_(output_classid=row["output_class"].id()) ), ) diff --git a/weave/legacy/tests/test_execution_graphs.py b/weave/legacy/tests/test_execution_graphs.py index 37c6caee650..cf7faf64b8a 100644 --- a/weave/legacy/tests/test_execution_graphs.py +++ b/weave/legacy/tests/test_execution_graphs.py @@ -3,8 +3,8 @@ import os import zlib -from weave.legacy import serialize, storage -from weave.legacy.server import handle_request +from weave.legacy.weave import serialize, storage +from weave.legacy.weave.server import handle_request def test_graph_playback(dev_only_admin_env_override): diff --git a/weave/legacy/tests/test_file.py b/weave/legacy/tests/test_file.py index d8561dae6a0..e1b8299c419 100644 --- a/weave/legacy/tests/test_file.py +++ b/weave/legacy/tests/test_file.py @@ -1,7 +1,7 @@ import pytest import weave -from weave.legacy import api, context_state, environment, errors, ops +from weave.legacy.weave import api, context_state, environment, errors, ops def test_dir(): diff --git a/weave/legacy/tests/test_filesystem.py b/weave/legacy/tests/test_filesystem.py index 3fd8cde70cb..ab8599d9505 100644 --- a/weave/legacy/tests/test_filesystem.py +++ b/weave/legacy/tests/test_filesystem.py @@ -2,7 +2,7 @@ import pytest -from weave.legacy import environment, errors, filesystem +from weave.legacy.weave import environment, errors, filesystem @pytest.fixture() diff --git a/weave/legacy/tests/test_gql_to_weave.py b/weave/legacy/tests/test_gql_to_weave.py index e3dc869d9bf..8046b0bb81d 100644 --- a/weave/legacy/tests/test_gql_to_weave.py +++ b/weave/legacy/tests/test_gql_to_weave.py @@ -1,5 +1,5 @@ -from weave.legacy import gql_to_weave -from weave.legacy import weave_types as types +from weave.legacy.weave import gql_to_weave +from weave.legacy.weave import weave_types as types def test_simple_query(): diff --git a/weave/legacy/tests/test_graph.py b/weave/legacy/tests/test_graph.py index ca04c2722d5..3f1c7ce886f 100644 --- a/weave/legacy/tests/test_graph.py +++ b/weave/legacy/tests/test_graph.py @@ -1,6 +1,6 @@ import weave -from weave.legacy import graph, weave_internal -from weave.legacy import weave_types as types +from weave.legacy.weave import graph, weave_internal +from weave.legacy.weave import weave_types as types def test_map_dag_produces_same_len(): diff --git a/weave/legacy/tests/test_graph_debug.py b/weave/legacy/tests/test_graph_debug.py index 957e58699f9..ebe81d6c295 100644 --- a/weave/legacy/tests/test_graph_debug.py +++ b/weave/legacy/tests/test_graph_debug.py @@ -1,6 +1,6 @@ import typing -from weave.legacy import decorator_op, graph, graph_debug +from weave.legacy.weave import decorator_op, graph, graph_debug class RowType(typing.TypedDict): diff --git a/weave/legacy/tests/test_hypothesis.py b/weave/legacy/tests/test_hypothesis.py index 915711acfac..90ed51b1626 100644 --- a/weave/legacy/tests/test_hypothesis.py +++ b/weave/legacy/tests/test_hypothesis.py @@ -44,9 +44,9 @@ from hypothesis.strategies import composite import weave -from weave.legacy import artifact_local, ops_arrow, ops_primitives, storage -from weave.legacy.arrow import convert -from weave.legacy.language_features.tagging import tag_store +from weave.legacy.weave import artifact_local, ops_arrow, ops_primitives, storage +from weave.legacy.weave.arrow import convert +from weave.legacy.weave.language_features.tagging import tag_store # Jack this up to find more bugs. EXAMPLES_PER_TEST = 100 diff --git a/weave/legacy/tests/test_infer_types.py b/weave/legacy/tests/test_infer_types.py index 137af307186..3d08b266378 100644 --- a/weave/legacy/tests/test_infer_types.py +++ b/weave/legacy/tests/test_infer_types.py @@ -1,6 +1,6 @@ import typing -from weave.legacy import graph, infer_types, weave_types +from weave.legacy.weave import graph, infer_types, weave_types def test_node_with_generic(): diff --git a/weave/legacy/tests/test_io_service.py b/weave/legacy/tests/test_io_service.py index 053ee5d19cd..52d29e22a2c 100644 --- a/weave/legacy/tests/test_io_service.py +++ b/weave/legacy/tests/test_io_service.py @@ -2,7 +2,7 @@ import pytest -from weave.legacy import filesystem, io_service +from weave.legacy.weave import filesystem, io_service @pytest.mark.timeout(10) diff --git a/weave/legacy/tests/test_join.py b/weave/legacy/tests/test_join.py index ba6dd4bf70f..f3c06cc956b 100644 --- a/weave/legacy/tests/test_join.py +++ b/weave/legacy/tests/test_join.py @@ -1,6 +1,6 @@ import weave -from weave.legacy import ops_arrow -from weave.legacy.wandb_interface.wandb_stream_table import StreamTable +from weave.legacy.weave import ops_arrow +from weave.legacy.weave.wandb_interface.wandb_stream_table import StreamTable def make_stream_table(*args, **kwargs): @@ -24,7 +24,7 @@ def test_join_awls_with_stitch(user_by_api_key_in_env): feedback_st.log(row) feedback_st.finish() - joined = weave.legacy.ops.join_2( + joined = weave.legacy.weave.ops.join_2( dataset_st.rows(), feedback_st.rows(), lambda row: row["id"], diff --git a/weave/legacy/tests/test_js_compat.py b/weave/legacy/tests/test_js_compat.py index ba37ee1f65e..9dfa277e439 100644 --- a/weave/legacy/tests/test_js_compat.py +++ b/weave/legacy/tests/test_js_compat.py @@ -7,9 +7,9 @@ # Note: This file is not yet complete, there are existing fixups in the # weave Python code that I haven't documented here. -from weave.legacy import partial_object, weavejs_fixes -from weave.legacy import weave_types as types -from weave.legacy.ops_domain import wb_domain_types +from weave.legacy.weave import partial_object, weavejs_fixes +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.ops_domain import wb_domain_types def test_const_serialization(): diff --git a/weave/legacy/tests/test_language.py b/weave/legacy/tests/test_language.py index 48277d2fcae..7c225403e2b 100644 --- a/weave/legacy/tests/test_language.py +++ b/weave/legacy/tests/test_language.py @@ -3,8 +3,8 @@ import typing import weave -from weave.legacy import box, context_state -from weave.legacy.language_features.tagging import ( +from weave.legacy.weave import box, context_state +from weave.legacy.weave.language_features.tagging import ( make_tag_getter_op, tag_store, tagged_value_type, diff --git a/weave/legacy/tests/test_levenshtein.py b/weave/legacy/tests/test_levenshtein.py index 8807cb7dcea..d39d74d8d1e 100644 --- a/weave/legacy/tests/test_levenshtein.py +++ b/weave/legacy/tests/test_levenshtein.py @@ -1,6 +1,6 @@ import pytest -from weave.legacy.ops_primitives.string import _levenshtein +from weave.legacy.weave.ops_primitives.string import _levenshtein @pytest.mark.parametrize( diff --git a/weave/legacy/tests/test_list_arrow_compat.py b/weave/legacy/tests/test_list_arrow_compat.py index d689161abe2..401a1ae7a5c 100644 --- a/weave/legacy/tests/test_list_arrow_compat.py +++ b/weave/legacy/tests/test_list_arrow_compat.py @@ -3,16 +3,16 @@ import numpy as np import pytest -from weave.legacy import api as weave -from weave.legacy import box, ops, weave_internal -from weave.legacy import ops_arrow as arrow -from weave.legacy import weave_types as types -from weave.legacy.language_features.tagging import ( +from weave.legacy.weave import api as weave +from weave.legacy.weave import box, ops, weave_internal +from weave.legacy.weave import ops_arrow as arrow +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.language_features.tagging import ( make_tag_getter_op, tag_store, tagged_value_type, ) -from weave.legacy.ops_primitives import dict_, list_ +from weave.legacy.weave.ops_primitives import dict_, list_ from weave.legacy.tests.util import tag_test_util as ttu from weave.legacy.tests.util import list_arrow_test_helpers as lath @@ -636,7 +636,7 @@ def test_tag_pushdown_on_list_of_lists(use_arrow): if use_arrow: list_node = arrow.ops.list_to_arrow(list_node) - from weave.legacy import context_state + from weave.legacy.weave import context_state _loading_builtins_token = context_state.set_loading_built_ins() diff --git a/weave/legacy/tests/test_list_indexing.py b/weave/legacy/tests/test_list_indexing.py index 95290dd3a11..5d76d397b8f 100644 --- a/weave/legacy/tests/test_list_indexing.py +++ b/weave/legacy/tests/test_list_indexing.py @@ -1,7 +1,7 @@ import pytest import weave -from weave.legacy import ops_arrow +from weave.legacy.weave import ops_arrow LIST_CONSTRUCTORS = [ lambda x: x, diff --git a/weave/legacy/tests/test_logging.py b/weave/legacy/tests/test_logging.py index 6ef1abea8b5..0da877d2cd5 100644 --- a/weave/legacy/tests/test_logging.py +++ b/weave/legacy/tests/test_logging.py @@ -5,7 +5,7 @@ import requests from weave import weave_server -from weave.legacy import api, context, logs, ops, server +from weave.legacy.weave import api, context, logs, ops, server def test_logfile_created(fresh_server_logfile): diff --git a/weave/legacy/tests/test_mappability.py b/weave/legacy/tests/test_mappability.py index 335eff5722e..475bebb4490 100644 --- a/weave/legacy/tests/test_mappability.py +++ b/weave/legacy/tests/test_mappability.py @@ -1,10 +1,10 @@ import weave -from weave.legacy import context_state as _context -from weave.legacy import graph -from weave.legacy import weave_types as types -from weave.legacy.weave_internal import make_const_node +from weave.legacy.weave import context_state as _context +from weave.legacy.weave import graph +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.weave_internal import make_const_node -from ...legacy import registry_mem +from ...legacy.weave import registry_mem _loading_builtins_token = _context.set_loading_built_ins() @@ -61,10 +61,10 @@ def test_non_mapped_use(): def test_non_mapped_serialized(): - node = weave.legacy.weave_internal.make_output_node( + node = weave.legacy.weave.weave_internal.make_output_node( weave.types.Int(), _test_add_one.name, - {"x": weave.legacy.graph.ConstNode(weave.types.Int(), 1)}, + {"x": weave.legacy.weave.graph.ConstNode(weave.types.Int(), 1)}, ) assert weave.use(node) == 2 @@ -82,11 +82,11 @@ def test_mapped_nullable_use(): def test_mapped_serialized(): - node = weave.legacy.weave_internal.make_output_node( + node = weave.legacy.weave.weave_internal.make_output_node( weave.types.Int(), _test_add_one.name, { - "x": weave.legacy.graph.ConstNode( + "x": weave.legacy.weave.graph.ConstNode( weave.types.List(weave.types.Int()), [1, 2, 3] ) }, @@ -101,10 +101,10 @@ def test_mapped_empty_use(): def test_mapped_empty_serialized(): - node = weave.legacy.weave_internal.make_output_node( + node = weave.legacy.weave.weave_internal.make_output_node( weave.types.Int(), _test_add_one.name, - {"x": weave.legacy.graph.ConstNode(weave.types.List(weave.types.Int()), [])}, + {"x": weave.legacy.weave.graph.ConstNode(weave.types.List(weave.types.Int()), [])}, ) assert weave.use(node) == [] @@ -123,7 +123,7 @@ def test_fn(self, a: int) -> int: node = TestType().test_fn(1) assert weave.use(node) == 2 - node_list = weave.legacy.ops.make_list(**{"0": TestType(), "1": TestType()}) + node_list = weave.legacy.weave.ops.make_list(**{"0": TestType(), "1": TestType()}) node = node_list.test_fn(1) assert weave.use(node) == [2, 2] diff --git a/weave/legacy/tests/test_mappers_arrow.py b/weave/legacy/tests/test_mappers_arrow.py index ff380abdf19..18db29708b1 100644 --- a/weave/legacy/tests/test_mappers_arrow.py +++ b/weave/legacy/tests/test_mappers_arrow.py @@ -2,8 +2,8 @@ import pyarrow as pa -from weave.legacy import mappers_arrow -from weave.legacy import weave_types as types +from weave.legacy.weave import mappers_arrow +from weave.legacy.weave import weave_types as types def test_map_list(): diff --git a/weave/legacy/tests/test_mappers_python.py b/weave/legacy/tests/test_mappers_python.py index 61cd78e0c81..3b98d6fd5be 100644 --- a/weave/legacy/tests/test_mappers_python.py +++ b/weave/legacy/tests/test_mappers_python.py @@ -1,7 +1,7 @@ import math -from weave.legacy import api, context, mappers_python, val_const, weave_internal -from weave.legacy import weave_types as types +from weave.legacy.weave import api, context, mappers_python, val_const, weave_internal +from weave.legacy.weave import weave_types as types def test_map_typed_dict(): diff --git a/weave/legacy/tests/test_media.py b/weave/legacy/tests/test_media.py index 502679692c1..e9d3a6708a9 100644 --- a/weave/legacy/tests/test_media.py +++ b/weave/legacy/tests/test_media.py @@ -3,8 +3,8 @@ import numpy as np import pytest -from weave.legacy import storage -from weave.legacy import weave_types as types +from weave.legacy.weave import storage +from weave.legacy.weave import weave_types as types def test_nparray(): diff --git a/weave/legacy/tests/test_media_user.py b/weave/legacy/tests/test_media_user.py index 8bb37deb4f4..c7cf985fdd3 100644 --- a/weave/legacy/tests/test_media_user.py +++ b/weave/legacy/tests/test_media_user.py @@ -1,8 +1,8 @@ from PIL import Image -from weave.legacy import api as weave -from weave.legacy import context_state -from weave.legacy.ops_primitives import geom as media_user +from weave.legacy.weave import api as weave +from weave.legacy.weave import context_state +from weave.legacy.weave.ops_primitives import geom as media_user def test_im_with_metadata(): diff --git a/weave/legacy/tests/test_monitoring.py b/weave/legacy/tests/test_monitoring.py index 73fd0170fd8..d86a32260fe 100644 --- a/weave/legacy/tests/test_monitoring.py +++ b/weave/legacy/tests/test_monitoring.py @@ -5,7 +5,7 @@ import pytest import weave -from weave.legacy.monitoring import monitor +from weave.legacy.weave.monitoring import monitor ### Skipping some tests here. They are for features that no longer exist. Since we're # iterating on the API, I'm not removing them yet. diff --git a/weave/legacy/tests/test_monitoring_openai.py b/weave/legacy/tests/test_monitoring_openai.py index cc7a1b71d20..01df0bfe8a3 100644 --- a/weave/legacy/tests/test_monitoring_openai.py +++ b/weave/legacy/tests/test_monitoring_openai.py @@ -12,13 +12,13 @@ from openai.types.completion_usage import CompletionUsage import weave -from weave.legacy.monitoring import init_monitor -from weave.legacy.monitoring.openai import util -from weave.legacy.monitoring.openai.models import * -from weave.legacy.monitoring.openai.models import Context -from weave.legacy.monitoring.openai.openai import patch, unpatch -from weave.legacy.monitoring.openai.util import Context -from weave.legacy.wandb_interface.wandb_stream_table import StreamTable +from weave.legacy.weave.monitoring import init_monitor +from weave.legacy.weave.monitoring.openai import util +from weave.legacy.weave.monitoring.openai.models import * +from weave.legacy.weave.monitoring.openai.models import Context +from weave.legacy.weave.monitoring.openai.openai import patch, unpatch +from weave.legacy.weave.monitoring.openai.util import Context +from weave.legacy.weave.wandb_interface.wandb_stream_table import StreamTable @pytest.fixture @@ -453,7 +453,7 @@ def test_log_to_span_basic( streamtable = make_stream_table( stream_name, project_name=project, entity_name=entity ) - chat_completions = weave.legacy.monitoring.openai.openai.ChatCompletions( + chat_completions = weave.legacy.weave.monitoring.openai.openai.ChatCompletions( mocked_create ) create_input = dict( @@ -481,7 +481,7 @@ def test_log_to_span_streaming( reassembled_chat_completion_message, client, ): - chat_completions = weave.legacy.monitoring.openai.openai.ChatCompletions( + chat_completions = weave.legacy.weave.monitoring.openai.openai.ChatCompletions( mocked_streaming_create ) create_input = dict( @@ -512,7 +512,7 @@ async def test_log_to_span_async_streaming( reassembled_chat_completion_message, client, ): - chat_completions = weave.legacy.monitoring.openai.openai.AsyncChatCompletions( + chat_completions = weave.legacy.weave.monitoring.openai.openai.AsyncChatCompletions( mocked_async_streaming_create ) create_input = dict( diff --git a/weave/legacy/tests/test_mutation2.py b/weave/legacy/tests/test_mutation2.py index 00f5619423d..d9e28fadfb7 100644 --- a/weave/legacy/tests/test_mutation2.py +++ b/weave/legacy/tests/test_mutation2.py @@ -1,22 +1,22 @@ import weave -from weave.legacy import ref_base, uris, weave_internal +from weave.legacy.weave import ref_base, uris, weave_internal def test_mutation_set_direct_call(): - val = weave.legacy.ops.TypedDict.pick({"a": {"b": 5}}, "a")["b"] - set_result = weave.legacy.ops.set(val, 9) + val = weave.legacy.weave.ops.TypedDict.pick({"a": {"b": 5}}, "a")["b"] + set_result = weave.legacy.weave.ops.set(val, 9) assert set_result == {"a": {"b": 9}} def test_mutation_set_dispatch(): - val = weave.legacy.ops.TypedDict.pick({"a": {"b": 5}}, "a")["b"] + val = weave.legacy.weave.ops.TypedDict.pick({"a": {"b": 5}}, "a")["b"] set_result = val.set(9) assert set_result == {"a": {"b": 9}} def test_mutation_artifact(): weave.save([1, 2, 3], "art:main") - art = weave.legacy.ops.get("local-artifact:///art:main/obj") + art = weave.legacy.weave.ops.get("local-artifact:///art:main/obj") art.append(4) new_art = weave.storage.get("local-artifact:///art:main/obj") assert new_art == [1, 2, 3, 4] @@ -25,12 +25,12 @@ def test_mutation_artifact(): def test_mutation_lazy(): # This is how weavejs does it. weave.save([1, 2, 3], "art:main") - art = weave.legacy.ops.get("local-artifact:///art:main/obj") + art = weave.legacy.weave.ops.get("local-artifact:///art:main/obj") # Quote lhs expr, so that it is not evaluated. quoted_art = weave_internal.const(art) - expr = weave.legacy.ops.append.lazy_call(quoted_art, 4, {}) + expr = weave.legacy.weave.ops.append.lazy_call(quoted_art, 4, {}) weave.use(expr) new_art = weave.storage.get("local-artifact:///art:main/obj") @@ -40,9 +40,9 @@ def test_mutation_lazy(): def test_mutation_lazy_works_without_quoting(): # This relies on "auto quoting behavior". See compile_quote weave.save([1, 2, 3], "art:main") - art = weave.legacy.ops.get("local-artifact:///art:main/obj") + art = weave.legacy.weave.ops.get("local-artifact:///art:main/obj") - expr = weave.legacy.ops.append.lazy_call(art, 4, {}) + expr = weave.legacy.weave.ops.append.lazy_call(art, 4, {}) weave.use(expr) new_art = weave.storage.get("local-artifact:///art:main/obj") @@ -51,14 +51,14 @@ def test_mutation_lazy_works_without_quoting(): def test_merge(): weave.save({"a": 5, "b": 6}, "my-dict:latest") - dict_obj = weave.legacy.ops.get("local-artifact:///my-dict:latest/obj") - weave.legacy.ops.set(dict_obj["a"], 17, root_args={"branch": "my-branch"}) - modified_dict_obj = weave.legacy.ops.get("local-artifact:///my-dict:my-branch/obj") - new_uri = weave.legacy.ops.merge_artifact(modified_dict_obj) - dict_obj_node = weave.legacy.ops.get(new_uri) + dict_obj = weave.legacy.weave.ops.get("local-artifact:///my-dict:latest/obj") + weave.legacy.weave.ops.set(dict_obj["a"], 17, root_args={"branch": "my-branch"}) + modified_dict_obj = weave.legacy.weave.ops.get("local-artifact:///my-dict:my-branch/obj") + new_uri = weave.legacy.weave.ops.merge_artifact(modified_dict_obj) + dict_obj_node = weave.legacy.weave.ops.get(new_uri) assert ( weave.use(dict_obj_node) - == weave.use(weave.legacy.ops.get("local-artifact:///my-dict:latest/obj")) + == weave.use(weave.legacy.weave.ops.get("local-artifact:///my-dict:latest/obj")) == {"a": 17, "b": 6} ) @@ -68,24 +68,24 @@ def test_merge_no_version(): uri = get_node.from_op.inputs["uri"].val # type: ignore # uri now has a direct commit hash for the version - dict_obj = weave.legacy.ops.get(uri) - weave.legacy.ops.set(dict_obj["a"], 17, root_args={"branch": "my-branch"}) - modified_dict_obj = weave.legacy.ops.get("local-artifact:///my-dict:my-branch/obj") - new_uri = weave.legacy.ops.merge_artifact(modified_dict_obj) - dict_obj_node = weave.legacy.ops.get(new_uri) + dict_obj = weave.legacy.weave.ops.get(uri) + weave.legacy.weave.ops.set(dict_obj["a"], 17, root_args={"branch": "my-branch"}) + modified_dict_obj = weave.legacy.weave.ops.get("local-artifact:///my-dict:my-branch/obj") + new_uri = weave.legacy.weave.ops.merge_artifact(modified_dict_obj) + dict_obj_node = weave.legacy.weave.ops.get(new_uri) assert weave.use(dict_obj_node) == {"a": 17, "b": 6} def test_merge_list_type(): - from weave.legacy import object_context + from weave.legacy.weave import object_context weave.save([], "my-list:latest") - obj = weave.legacy.ops.get("local-artifact:///my-list:latest/obj") + obj = weave.legacy.weave.ops.get("local-artifact:///my-list:latest/obj") with object_context.object_context(): obj.append({"a": "x"}, {}) obj.append([1], {}) - assert weave.use(weave.legacy.ops.get("local-artifact:///my-list:latest/obj")) == [ + assert weave.use(weave.legacy.weave.ops.get("local-artifact:///my-list:latest/obj")) == [ {"a": "x"}, [1], ] @@ -95,7 +95,7 @@ def test_artifact_history_local(): num_versions = 4 uri = "local-artifact:///art:main/obj" weave.save([0], "art:main") - art = weave.legacy.ops.get(uri) + art = weave.legacy.weave.ops.get(uri) for i in range(num_versions): art.append(i + 1) @@ -105,7 +105,7 @@ def test_artifact_history_local(): assert new_art == total_list for i in range(num_versions): - new_uri = weave.legacy.ops.undo_artifact(weave.legacy.ops.get(uri)) + new_uri = weave.legacy.weave.ops.undo_artifact(weave.legacy.weave.ops.get(uri)) # We expect these to be the same since the branch pointer changed assert new_uri == uri res = weave.storage.get(uri) @@ -116,12 +116,12 @@ def test_artifact_history_local_from_hash(): num_versions = 4 uri = "local-artifact:///art:main/obj" weave.save([0], "art:main") - art = weave.legacy.ops.get(uri) + art = weave.legacy.weave.ops.get(uri) for i in range(num_versions): art.append(i + 1) - hash_uri = weave.legacy.uris.WeaveURI.parse(uri).to_ref().artifact.uri + hash_uri = weave.legacy.weave.uris.WeaveURI.parse(uri).to_ref().artifact.uri assert "main" not in hash_uri total_list = list(range(num_versions + 1)) @@ -130,7 +130,7 @@ def test_artifact_history_local_from_hash(): new_uri = hash_uri for i in range(num_versions): - new_uri = weave.legacy.ops.undo_artifact(weave.legacy.ops.get(new_uri)) + new_uri = weave.legacy.weave.ops.undo_artifact(weave.legacy.weave.ops.get(new_uri)) assert "main" not in new_uri res = weave.storage.get(new_uri + "/obj") assert res == total_list[: num_versions - i] @@ -140,16 +140,16 @@ def test_artifact_history_remote_with_branch(user_by_api_key_in_env): num_versions = 2 uri = "local-artifact:///art:main/obj" weave.save([0], "art:main") - art = weave.legacy.ops.get(uri) - published_art_uri = weave.legacy.ops.publish_artifact(art, "art", None, None) + art = weave.legacy.weave.ops.get(uri) + published_art_uri = weave.legacy.weave.ops.publish_artifact(art, "art", None, None) - art = weave.legacy.ops.get( + art = weave.legacy.weave.ops.get( f"wandb-artifact:///{user_by_api_key_in_env.username}/weave/art:latest/obj" ) for i in range(num_versions): res_uri = art.append(i + 1) - art = weave.legacy.ops.get(res_uri) + art = weave.legacy.weave.ops.get(res_uri) new_uri = res_uri total_list = list(range(num_versions + 1)) @@ -157,7 +157,7 @@ def test_artifact_history_remote_with_branch(user_by_api_key_in_env): assert new_art == total_list for i in range(num_versions): - new_uri = weave.legacy.ops.undo_artifact(weave.legacy.ops.get(new_uri)) + new_uri = weave.legacy.weave.ops.undo_artifact(weave.legacy.weave.ops.get(new_uri)) res = weave.storage.get(new_uri) if i == num_versions - 1: assert new_uri.startswith("wandb") @@ -170,16 +170,16 @@ def test_artifact_history_remote_with_hash(user_by_api_key_in_env): num_versions = 2 uri = "local-artifact:///art:main/obj" weave.save([0], "art:main") - art = weave.legacy.ops.get(uri) - published_art_uri = weave.legacy.ops.publish_artifact(art, "art", None, None) + art = weave.legacy.weave.ops.get(uri) + published_art_uri = weave.legacy.weave.ops.publish_artifact(art, "art", None, None) assert "latest" not in published_art_uri assert "main" not in published_art_uri - art = weave.legacy.ops.get(published_art_uri) + art = weave.legacy.weave.ops.get(published_art_uri) for i in range(num_versions): res_uri = art.append(i + 1) - art = weave.legacy.ops.get(res_uri) + art = weave.legacy.weave.ops.get(res_uri) new_uri = res_uri total_list = list(range(num_versions + 1)) @@ -187,7 +187,7 @@ def test_artifact_history_remote_with_hash(user_by_api_key_in_env): assert new_art == total_list for i in range(num_versions): - new_uri = weave.legacy.ops.undo_artifact(weave.legacy.ops.get(new_uri)) + new_uri = weave.legacy.weave.ops.undo_artifact(weave.legacy.weave.ops.get(new_uri)) res = weave.storage.get(new_uri) if i == num_versions - 1: assert new_uri.startswith("wandb") diff --git a/weave/legacy/tests/test_mutations.py b/weave/legacy/tests/test_mutations.py index 453d8af7ec5..abdc289cb73 100644 --- a/weave/legacy/tests/test_mutations.py +++ b/weave/legacy/tests/test_mutations.py @@ -1,5 +1,5 @@ -from weave.legacy import api as weave -from weave.legacy import ops, storage, weave_internal +from weave.legacy.weave import api as weave +from weave.legacy.weave import ops, storage, weave_internal def test_autocommit(cereal_csv): diff --git a/weave/legacy/tests/test_node_ref.py b/weave/legacy/tests/test_node_ref.py index 0a8d56f1e7e..75216f629ad 100644 --- a/weave/legacy/tests/test_node_ref.py +++ b/weave/legacy/tests/test_node_ref.py @@ -1,7 +1,7 @@ -from weave.legacy import api as weave -from weave.legacy import graph +from weave.legacy.weave import api as weave +from weave.legacy.weave import graph -from ...legacy import node_ref +from ...legacy.weave import node_ref def test_node_to_ref(): diff --git a/weave/legacy/tests/test_nullability.py b/weave/legacy/tests/test_nullability.py index df8b08be96a..9d07569b799 100644 --- a/weave/legacy/tests/test_nullability.py +++ b/weave/legacy/tests/test_nullability.py @@ -3,8 +3,8 @@ import pytest import weave -from weave.legacy import context_state as _context -from weave.legacy.weave_internal import make_const_node, make_output_node +from weave.legacy.weave import context_state as _context +from weave.legacy.weave.weave_internal import make_const_node, make_output_node _loading_builtins_token = _context.set_loading_built_ins() @@ -57,7 +57,7 @@ def test_basic_nullability(): def test_basic_nullability_in_mappability(): b_arr = weave.save([2]) maybe_int_arr = weave.save( - weave.legacy.graph.ConstNode( + weave.legacy.weave.graph.ConstNode( weave.types.List(weave.types.optional(weave.types.Int())), [1, None] ) ) diff --git a/weave/legacy/tests/test_number_bin.py b/weave/legacy/tests/test_number_bin.py index 22a5a5cd72a..1475ef9c49d 100644 --- a/weave/legacy/tests/test_number_bin.py +++ b/weave/legacy/tests/test_number_bin.py @@ -4,8 +4,8 @@ def test_number_bin_vector(): - awl = weave.legacy.ops.to_weave_arrow([1, 2, 3, 4, 5]) - mapped = awl.map(lambda x: x.bin(weave.legacy.ops.number_bins_fixed(2))) + awl = weave.legacy.weave.ops.to_weave_arrow([1, 2, 3, 4, 5]) + mapped = awl.map(lambda x: x.bin(weave.legacy.weave.ops.number_bins_fixed(2))) res = weave.use(mapped).to_pylist_tagged() assert res == [ {"start": 0.0, "stop": 2.0}, diff --git a/weave/legacy/tests/test_numpy.py b/weave/legacy/tests/test_numpy.py index 99275de1e7d..740c281aa9e 100644 --- a/weave/legacy/tests/test_numpy.py +++ b/weave/legacy/tests/test_numpy.py @@ -1,10 +1,10 @@ import numpy as np -from weave.legacy import artifact_fs, artifact_wandb -from weave.legacy import weave_types as types -from weave.legacy.ops_domain import table +from weave.legacy.weave import artifact_fs, artifact_wandb +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.ops_domain import table -from ...legacy import types_numpy as numpy_types +from ...legacy.weave import types_numpy as numpy_types def test_construct_numpy_type(): diff --git a/weave/legacy/tests/test_op.py b/weave/legacy/tests/test_op.py index dfd0636c0c9..8bb75326f50 100644 --- a/weave/legacy/tests/test_op.py +++ b/weave/legacy/tests/test_op.py @@ -2,10 +2,10 @@ import pytest -from weave.legacy import api as weave -from weave.legacy import context_state, graph, storage, uris, weave_internal -from weave.legacy import context_state as _context_state -from weave.legacy import weave_types as types +from weave.legacy.weave import api as weave +from weave.legacy.weave import context_state, graph, storage, uris, weave_internal +from weave.legacy.weave import context_state as _context_state +from weave.legacy.weave import weave_types as types from . import test_helpers diff --git a/weave/legacy/tests/test_op_behaviors.py b/weave/legacy/tests/test_op_behaviors.py index 4da75809cac..efbc05caf2a 100644 --- a/weave/legacy/tests/test_op_behaviors.py +++ b/weave/legacy/tests/test_op_behaviors.py @@ -12,7 +12,7 @@ import pytest import weave -from weave.legacy import ( +from weave.legacy.weave import ( graph, graph_debug, language_nullability, @@ -22,12 +22,12 @@ storage, weave_internal, ) -from weave.legacy.language_features.tagging import make_tag_getter_op -from weave.legacy.language_features.tagging.tagged_value_type import ( +from weave.legacy.weave.language_features.tagging import make_tag_getter_op +from weave.legacy.weave.language_features.tagging.tagged_value_type import ( TaggedValueType, ) -from ...legacy import registry_mem +from ...legacy.weave import registry_mem from weave.legacy.tests.util.concrete_tagged_value import ( TaggedValue, concrete_from_tagstore, @@ -83,7 +83,7 @@ def check_case(called: graph.Node, result_type: weave.types.Type, result: typing ), f"Expected op output type: {result_type}, but got {called.type}" # This is a way to save the final output, preserving tags. - result_ref = weave.use(weave.legacy.ops.save_to_ref(called, None)) + result_ref = weave.use(weave.legacy.weave.ops.save_to_ref(called, None)) if result_ref == None: actual_result = None else: diff --git a/weave/legacy/tests/test_op_coverage.py b/weave/legacy/tests/test_op_coverage.py index cede44a1109..f933b3e978d 100644 --- a/weave/legacy/tests/test_op_coverage.py +++ b/weave/legacy/tests/test_op_coverage.py @@ -1,4 +1,4 @@ -from ...legacy import registry_mem +from ...legacy.weave import registry_mem def make_error_message(missing_ops, section_name): diff --git a/weave/legacy/tests/test_op_def.py b/weave/legacy/tests/test_op_def.py index 343452305e8..dc8fa42a100 100644 --- a/weave/legacy/tests/test_op_def.py +++ b/weave/legacy/tests/test_op_def.py @@ -5,8 +5,8 @@ import pytest -from weave.legacy import api as weave -from weave.legacy import context_state +from weave.legacy.weave import api as weave +from weave.legacy.weave import context_state _loading_builtins_token = context_state.set_loading_built_ins() diff --git a/weave/legacy/tests/test_op_def_type.py b/weave/legacy/tests/test_op_def_type.py index 303705fac3b..d6eedd6ab0f 100644 --- a/weave/legacy/tests/test_op_def_type.py +++ b/weave/legacy/tests/test_op_def_type.py @@ -1,6 +1,6 @@ import typing -from weave.legacy import op_def_type +from weave.legacy.weave import op_def_type class MyTypedDict(typing.TypedDict): diff --git a/weave/legacy/tests/test_op_dispatching.py b/weave/legacy/tests/test_op_dispatching.py index 7123a19e553..4d583e5cf86 100644 --- a/weave/legacy/tests/test_op_dispatching.py +++ b/weave/legacy/tests/test_op_dispatching.py @@ -1,11 +1,11 @@ import pytest import weave -from weave.legacy import context_state as _context -from weave.legacy import graph, weave_internal -from weave.legacy.dispatch import _dispatch_first_arg, _resolve_op_ambiguity -from weave.legacy.language_features.tagging.tagged_value_type import TaggedValueType -from weave.legacy.ops_domain import wb_domain_types +from weave.legacy.weave import context_state as _context +from weave.legacy.weave import graph, weave_internal +from weave.legacy.weave.dispatch import _dispatch_first_arg, _resolve_op_ambiguity +from weave.legacy.weave.language_features.tagging.tagged_value_type import TaggedValueType +from weave.legacy.weave.ops_domain import wb_domain_types _loading_builtins_token = _context.set_loading_built_ins() @@ -71,7 +71,7 @@ def test_pick_map(): def test_json_pick_map(): - res = weave.legacy.graph.OutputNode.from_json( + res = weave.legacy.weave.graph.OutputNode.from_json( { "nodeType": "output", "type": {"type": "list", "objectType": "number"}, @@ -169,7 +169,7 @@ def test_nested_js_dict_pick(): def test_dispatch_of_ambiguous_ops(): - artifacts_node = weave.legacy.ops.project("a", "b").artifacts() + artifacts_node = weave.legacy.weave.ops.project("a", "b").artifacts() # just making this call is the test since it is # not clear if it should be artifact-project or # tag-project diff --git a/weave/legacy/tests/test_op_serialization.py b/weave/legacy/tests/test_op_serialization.py index 7c08a59b982..c666770a379 100644 --- a/weave/legacy/tests/test_op_serialization.py +++ b/weave/legacy/tests/test_op_serialization.py @@ -1,9 +1,9 @@ import pytest import weave -import weave.legacy +import weave.legacy.weave -ops = weave.legacy.registry_mem.memory_registry.list_ops() +ops = weave.legacy.weave.registry_mem.memory_registry.list_ops() def output_type_dict_is_const_function_node(output_type_dict): diff --git a/weave/legacy/tests/test_panel_coverage.py b/weave/legacy/tests/test_panel_coverage.py index b811196a18a..f1518968b5b 100644 --- a/weave/legacy/tests/test_panel_coverage.py +++ b/weave/legacy/tests/test_panel_coverage.py @@ -14,7 +14,7 @@ def inheritors(klass): def all_panels(): - return inheritors(weave.legacy.panel.Panel) + return inheritors(weave.legacy.weave.panel.Panel) def test_panel_coverage(): diff --git a/weave/legacy/tests/test_panel_time_series.py b/weave/legacy/tests/test_panel_time_series.py index 169b6bb40aa..6b0faab5cbe 100644 --- a/weave/legacy/tests/test_panel_time_series.py +++ b/weave/legacy/tests/test_panel_time_series.py @@ -3,7 +3,7 @@ import wandb import weave -from weave.legacy.ecosystem.wandb.panel_time_series import TimeSeries +from weave.legacy.weave.ecosystem.wandb.panel_time_series import TimeSeries def test_panel_timeseries(user_by_api_key_in_env): @@ -14,7 +14,7 @@ def test_panel_timeseries(user_by_api_key_in_env): run.finish() history_node = ( - weave.legacy.ops.project(run.entity, run.project).run(run.id).history2() + weave.legacy.weave.ops.project(run.entity, run.project).run(run.id).history2() ) panel = TimeSeries(history_node) init_config_node = panel.initialize() diff --git a/weave/legacy/tests/test_panels.py b/weave/legacy/tests/test_panels.py index 14f162987d1..1f309042751 100644 --- a/weave/legacy/tests/test_panels.py +++ b/weave/legacy/tests/test_panels.py @@ -1,11 +1,11 @@ import pytest import weave -from weave.legacy import storage, weave_internal -from weave.legacy.panels import panel_plot +from weave.legacy.weave import storage, weave_internal +from weave.legacy.weave.panels import panel_plot -from ...legacy.panels.panel_group import Group -from ...legacy.panels.panel_slider import Slider +from ...legacy.weave.panels.panel_group import Group +from ...legacy.weave.panels.panel_slider import Slider def test_panel_id(): @@ -82,7 +82,7 @@ def test_synced(): def test_object_picker_choice_type(): ints = weave.save([1, 2, 3], name="my-ints") - panel = weave.legacy.panels.ObjectPicker(ints) + panel = weave.legacy.weave.panels.ObjectPicker(ints) panel_node = weave_internal.make_var_node(weave.type_of(panel), "panel") choice = panel_node.config.choice assert choice.type == weave.types.Function({}, weave.types.Int()) @@ -92,17 +92,17 @@ def test_facet_selected(): data = weave.save( [{"guess": "dog", "truth": "cat"}, {"guess": "dog", "truth": "dog"}] ) - facet = weave.legacy.panels.Group( + facet = weave.legacy.weave.panels.Group( equalSize=True, items={ - "confusion": weave.legacy.panels.Facet( + "confusion": weave.legacy.weave.panels.Facet( data, x=lambda row: row["guess"], y=lambda row: row["truth"], - select=lambda row: weave.legacy.panels.Group( + select=lambda row: weave.legacy.weave.panels.Group( layered=True, items={ - "color": weave.legacy.panels.Color(row.count() / 50), + "color": weave.legacy.weave.panels.Color(row.count() / 50), "count": row.count(), }, ), @@ -115,11 +115,11 @@ def test_facet_selected(): def test_board(): # Just make sure it runs for now. - weave.legacy.panels.Board( + weave.legacy.weave.panels.Board( { - "nums": weave.legacy.ops.range(0, 3, 1), + "nums": weave.legacy.weave.ops.range(0, 3, 1), }, - [weave.legacy.panels.BoardPanel(id="panel0", panel=lambda nums: nums)], + [weave.legacy.weave.panels.BoardPanel(id="panel0", panel=lambda nums: nums)], ) @@ -130,6 +130,6 @@ def test_plot_constants_assign(): def test_plot_assign(): - assert weave.legacy.panels.Plot.WeaveType().assign_type( - weave.type_of(weave.legacy.panels.Plot([{"a": 5}])) + assert weave.legacy.weave.panels.Plot.WeaveType().assign_type( + weave.type_of(weave.legacy.weave.panels.Plot([{"a": 5}])) ) diff --git a/weave/legacy/tests/test_partial_object.py b/weave/legacy/tests/test_partial_object.py index 22eac741e3b..6a1955f23fe 100644 --- a/weave/legacy/tests/test_partial_object.py +++ b/weave/legacy/tests/test_partial_object.py @@ -1,10 +1,10 @@ -from weave.legacy import api as weave -from weave.legacy import compile, ops -from weave.legacy import weave_types as types -from weave.legacy.language_features.tagging.tagged_value_type import TaggedValueType -from weave.legacy.ops_domain import wb_domain_types as wdt -from weave.legacy.ops_domain.project_ops import root_all_projects -from weave.legacy.ops_domain.report_ops import root_all_reports +from weave.legacy.weave import api as weave +from weave.legacy.weave import compile, ops +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.language_features.tagging.tagged_value_type import TaggedValueType +from weave.legacy.weave.ops_domain import wb_domain_types as wdt +from weave.legacy.weave.ops_domain.project_ops import root_all_projects +from weave.legacy.weave.ops_domain.report_ops import root_all_reports from .test_wb import table_mock1_no_display_name diff --git a/weave/legacy/tests/test_plot.py b/weave/legacy/tests/test_plot.py index f124eabf81d..93ce632dd1e 100644 --- a/weave/legacy/tests/test_plot.py +++ b/weave/legacy/tests/test_plot.py @@ -4,9 +4,9 @@ import pytest import weave -from weave.legacy import graph, storage -from weave.legacy import weave_types as types -from weave.legacy.panels.panel_plot import Plot, PlotConstants, Series +from weave.legacy.weave import graph, storage +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.panels.panel_plot import Plot, PlotConstants, Series from .test_run_segment import create_experiment @@ -38,11 +38,11 @@ def test_multi_series_plot_config_with_grouping(): weave.save(last_segment) plot = Plot(last_segment.experiment()) plot.set_x( - lambda row: weave.legacy.ops.number_bin( - row["step"], weave.legacy.ops.numbers_bins_equal([1, 2000], 2) + lambda row: weave.legacy.weave.ops.number_bin( + row["step"], weave.legacy.weave.ops.numbers_bins_equal([1, 2000], 2) ) ) - plot.set_y(lambda row: weave.legacy.ops.numbers_avg(row["metric0"])) + plot.set_y(lambda row: weave.legacy.weave.ops.numbers_avg(row["metric0"])) plot.groupby_x() plot.set_mark_constant("line") @@ -50,8 +50,8 @@ def test_multi_series_plot_config_with_grouping(): series2 = plot.config.series[0].clone() plot.add_series(series2) - series2.set_y(lambda row: weave.legacy.ops.numbers_min(row["metric0"])) - series2.set_y2(lambda row: weave.legacy.ops.numbers_max(row["metric0"])) + series2.set_y(lambda row: weave.legacy.weave.ops.numbers_min(row["metric0"])) + series2.set_y2(lambda row: weave.legacy.weave.ops.numbers_max(row["metric0"])) series2.set_mark_constant("area") plot.groupby_x() @@ -69,20 +69,20 @@ def test_multi_series_grouping(): weave.save(last_segment) plot = Plot(last_segment.experiment()) plot.set_x( - lambda row: weave.legacy.ops.number_bin( - row["step"], weave.legacy.ops.numbers_bins_equal([1, 2000], 2) + lambda row: weave.legacy.weave.ops.number_bin( + row["step"], weave.legacy.weave.ops.numbers_bins_equal([1, 2000], 2) ) ) plot.groupby_x() - plot.set_y(lambda row: weave.legacy.ops.numbers_avg(row["metric0"])) + plot.set_y(lambda row: weave.legacy.weave.ops.numbers_avg(row["metric0"])) plot.set_mark_constant("line") series2 = plot.config.series[0].clone() plot.add_series(series2) - series2.set_y(lambda row: weave.legacy.ops.numbers_min(row["metric0"])) - series2.set_y2(lambda row: weave.legacy.ops.numbers_max(row["metric0"])) + series2.set_y(lambda row: weave.legacy.weave.ops.numbers_min(row["metric0"])) + series2.set_y2(lambda row: weave.legacy.weave.ops.numbers_max(row["metric0"])) series2.set_mark_constant("area") plot2 = copy.deepcopy(plot) @@ -100,8 +100,8 @@ def test_multi_series_setting(): weave.save(last_segment) plot = Plot(last_segment.experiment()) plot.set_x( - lambda row: weave.legacy.ops.number_bin( - row["step"], weave.legacy.ops.numbers_bins_equal([1, 2000], 2) + lambda row: weave.legacy.weave.ops.number_bin( + row["step"], weave.legacy.weave.ops.numbers_bins_equal([1, 2000], 2) ) ) @@ -156,18 +156,18 @@ def test_actual_config_value(fixed_random_seed): weave.save(last_segment) plot = Plot(last_segment.experiment()) plot.set_x( - lambda row: weave.legacy.ops.number_bin( - row["step"], weave.legacy.ops.numbers_bins_equal([1, 2000], 2) + lambda row: weave.legacy.weave.ops.number_bin( + row["step"], weave.legacy.weave.ops.numbers_bins_equal([1, 2000], 2) ) ) - plot.set_y(lambda row: weave.legacy.ops.numbers_avg(row["metric0"])) + plot.set_y(lambda row: weave.legacy.weave.ops.numbers_avg(row["metric0"])) plot.set_mark_constant("line") series2 = plot.config.series[0].clone() plot.add_series(series2) - series2.set_y(lambda row: weave.legacy.ops.numbers_min(row["metric0"])) - series2.set_y2(lambda row: weave.legacy.ops.numbers_max(row["metric0"])) + series2.set_y(lambda row: weave.legacy.weave.ops.numbers_min(row["metric0"])) + series2.set_y2(lambda row: weave.legacy.weave.ops.numbers_max(row["metric0"])) series2.set_mark_constant("area") assert storage.to_python(plot.config) == { "_type": { @@ -1766,7 +1766,7 @@ def test_actual_config_value(fixed_random_seed): def test_panel_plot_scale_serialization(): # checks a problem case where scale would not be serialized correctly as an AxisScale object - plot = weave.legacy.panels.Plot( + plot = weave.legacy.weave.panels.Plot( [1, 2, 3, 4], x=lambda row: row, x_title="x", diff --git a/weave/legacy/tests/test_projection_timeout.py b/weave/legacy/tests/test_projection_timeout.py index b9fd2a7e21e..302b2247226 100644 --- a/weave/legacy/tests/test_projection_timeout.py +++ b/weave/legacy/tests/test_projection_timeout.py @@ -1,7 +1,7 @@ import numpy as np import pytest -from weave.legacy.ops_primitives import projection_utils +from weave.legacy.weave.ops_primitives import projection_utils from ... import errors diff --git a/weave/legacy/tests/test_publish_flow.py b/weave/legacy/tests/test_publish_flow.py index 228fdd200d0..c7fe8c38172 100644 --- a/weave/legacy/tests/test_publish_flow.py +++ b/weave/legacy/tests/test_publish_flow.py @@ -3,20 +3,20 @@ import pytest import weave -from weave.legacy import panels, storage -from weave.legacy.artifact_fs import BranchPointType, FilesystemArtifactRef -from weave.legacy.artifact_local import ( +from weave.legacy.weave import panels, storage +from weave.legacy.weave.artifact_fs import BranchPointType, FilesystemArtifactRef +from weave.legacy.weave.artifact_local import ( LocalArtifact, LocalArtifactRef, WeaveLocalArtifactURI, ) -from weave.legacy.artifact_wandb import ( +from weave.legacy.weave.artifact_wandb import ( WandbArtifact, WandbArtifactRef, WeaveWBArtifactURI, likely_commit_hash, ) -from weave.legacy.uris import WeaveURI +from weave.legacy.weave.uris import WeaveURI def test_publish_values(user_by_api_key_in_env): @@ -26,7 +26,7 @@ def test_publish_values(user_by_api_key_in_env): def test_publish_panel(user_by_api_key_in_env): - from weave.legacy import panel_util + from weave.legacy.weave import panel_util table_obj = panels.Table( panel_util.make_node( @@ -321,12 +321,12 @@ def _perform_post_persist_assertions( expected_uri_with_branch = f"wandb-artifact:///{target_entity}/{target_project_name}/{target_artifact_name}:{branch_name}/obj" # Data Assertions - get_op = weave.legacy.ops.get(expected_uri_with_hash) + get_op = weave.legacy.weave.ops.get(expected_uri_with_hash) get_res = weave.use(get_op) assert p_ref.obj == get_res == data # Only check branch if expected_uri_with_branch is not None if expected_uri_with_branch: - get_op = weave.legacy.ops.get(expected_uri_with_branch) + get_op = weave.legacy.weave.ops.get(expected_uri_with_branch) get_res = weave.use(get_op) assert get_res == data @@ -379,7 +379,7 @@ def test_mutate_remote_with_commit_hash(user_by_api_key_in_env): assert p_ref.version == expected_commit_hash - obj = weave.legacy.ops.get(p_ref.uri)[0] + obj = weave.legacy.weave.ops.get(p_ref.uri)[0] obj.set(new_data[0]) new_branch_name = f"user-{p_ref.version}" new_uri = f"local-artifact:///{target_artifact_name}:{new_branch_name}/obj" @@ -422,7 +422,7 @@ def test_mutate_remote_with_branch(user_by_api_key_in_env): assert p_ref.version == expected_commit_hash assert branch_name in p_ref.branch_uri - obj = weave.legacy.ops.get(p_ref.branch_uri)[0] + obj = weave.legacy.weave.ops.get(p_ref.branch_uri)[0] obj.set(new_data[0]) new_branch_name = f"user-{branch_name}" new_p_ref = LocalArtifactRef.from_str( @@ -461,7 +461,7 @@ def test_mutate_local_with_commit_hash(user_by_api_key_in_env, new_branch_name=N assert p_ref.version == expected_commit_hash - obj = weave.legacy.ops.get(p_ref.uri)[0] + obj = weave.legacy.weave.ops.get(p_ref.uri)[0] if new_branch_name == None: obj.set(new_data[0]) new_branch_name = new_commit_hash @@ -513,14 +513,14 @@ def test_mutate_local_with_commit_hash_and_branchpoint( assert p_ref.version == expected_commit_hash assert branch_name in p_ref.branch_uri - obj = weave.legacy.ops.get(p_ref.branch_uri)[0] + obj = weave.legacy.weave.ops.get(p_ref.branch_uri)[0] obj.set("PLACEHOLDER") mod_ref = LocalArtifactRef.from_uri( WeaveLocalArtifactURI.parse( f"local-artifact:///{target_artifact_name}:user-{branch_name}/obj" ) ) - obj = weave.legacy.ops.get(mod_ref.branch_uri)[0] + obj = weave.legacy.weave.ops.get(mod_ref.branch_uri)[0] if new_branch_name == None: obj.set(new_data[0]) branch_name = None @@ -571,7 +571,7 @@ def test_mutate_local_with_branch(user_by_api_key_in_env, new_branch_name=None): assert p_ref.version == expected_commit_hash - obj = weave.legacy.ops.get(p_ref.branch_uri)[0] + obj = weave.legacy.weave.ops.get(p_ref.branch_uri)[0] if new_branch_name == None: obj.set(new_data[0]) new_branch_name = new_commit_hash @@ -622,9 +622,9 @@ def test_mutate_local_with_branch_and_branchpoint(user_by_api_key_in_env): assert p_ref.version == expected_commit_hash assert branch_name in p_ref.branch_uri - obj = weave.legacy.ops.get(p_ref.branch_uri)[0] + obj = weave.legacy.weave.ops.get(p_ref.branch_uri)[0] obj.set("PLACEHOLDER") - obj = weave.legacy.ops.get( + obj = weave.legacy.weave.ops.get( f"local-artifact:///{target_artifact_name}:user-{branch_name}/obj" )[0] obj.set(new_data[0]) @@ -655,8 +655,8 @@ def test_merge_from_local_with_commit_hash_onto_remote_with_commit_hash( ): test_mutate_remote_with_commit_hash(user_by_api_key_in_env) - merged_uri = weave.legacy.ops.merge_artifact( - weave.legacy.ops.get("local-artifact:///test_artifact:61f78c8877df22942d23/obj") + merged_uri = weave.legacy.weave.ops.merge_artifact( + weave.legacy.weave.ops.get("local-artifact:///test_artifact:61f78c8877df22942d23/obj") ) assert merged_uri.startswith("wandb-artifact://") @@ -681,8 +681,8 @@ def test_merge_from_local_with_commit_hash_onto_remote_with_branch( ): test_mutate_remote_with_branch(user_by_api_key_in_env) - merged_uri = weave.legacy.ops.merge_artifact( - weave.legacy.ops.get("local-artifact:///test_artifact:61f78c8877df22942d23/obj") + merged_uri = weave.legacy.weave.ops.merge_artifact( + weave.legacy.weave.ops.get("local-artifact:///test_artifact:61f78c8877df22942d23/obj") ) assert merged_uri.startswith("wandb-artifact://") @@ -707,8 +707,8 @@ def test_merge_from_local_with_commit_hash_onto_local_with_commit_hash( ): test_mutate_local_with_commit_hash(user_by_api_key_in_env, "new_branch_name") - merged_uri = weave.legacy.ops.merge_artifact( - weave.legacy.ops.get("local-artifact:///test_artifact:61f78c8877df22942d23/obj") + merged_uri = weave.legacy.weave.ops.merge_artifact( + weave.legacy.weave.ops.get("local-artifact:///test_artifact:61f78c8877df22942d23/obj") ) assert merged_uri.startswith("local-artifact://") @@ -739,8 +739,8 @@ def test_merge_from_local_with_commit_hash_onto_local_with_branch( ): test_mutate_local_with_branch(user_by_api_key_in_env, "new_branch_name") - merged_uri = weave.legacy.ops.merge_artifact( - weave.legacy.ops.get("local-artifact:///test_artifact:61f78c8877df22942d23/obj") + merged_uri = weave.legacy.weave.ops.merge_artifact( + weave.legacy.weave.ops.get("local-artifact:///test_artifact:61f78c8877df22942d23/obj") ) assert merged_uri.startswith("local-artifact://") @@ -765,8 +765,8 @@ def test_merge_from_local_with_commit_hash_onto_local_with_branch_and_branchpoin user_by_api_key_in_env, "new_branch_name" ) - merged_uri = weave.legacy.ops.merge_artifact( - weave.legacy.ops.get("local-artifact:///test_artifact:61f78c8877df22942d23/obj") + merged_uri = weave.legacy.weave.ops.merge_artifact( + weave.legacy.weave.ops.get("local-artifact:///test_artifact:61f78c8877df22942d23/obj") ) assert merged_uri.startswith("local-artifact://") @@ -788,7 +788,7 @@ def test_merge_from_local_with_commit_hash_onto_local_with_branch_and_branchpoin ), ) - merged_uri_2 = weave.legacy.ops.merge_artifact(weave.legacy.ops.get(merged_uri)) + merged_uri_2 = weave.legacy.weave.ops.merge_artifact(weave.legacy.weave.ops.get(merged_uri)) new_p_ref_2 = WandbArtifactRef.from_str(merged_uri_2) assert merged_uri_2.startswith("wandb-artifact://") @@ -816,8 +816,8 @@ def test_merge_from_local_with_branch_onto_remote_with_commit_hash( ): test_mutate_remote_with_commit_hash(user_by_api_key_in_env) - merged_uri = weave.legacy.ops.merge_artifact( - weave.legacy.ops.get( + merged_uri = weave.legacy.weave.ops.merge_artifact( + weave.legacy.weave.ops.get( "local-artifact:///test_artifact:user-74d5ba98aca469b59e18/obj" ) ) @@ -842,8 +842,8 @@ def test_merge_from_local_with_branch_onto_remote_with_commit_hash( def test_merge_from_local_with_branch_onto_remote_with_branch(user_by_api_key_in_env): test_mutate_remote_with_branch(user_by_api_key_in_env) - merged_uri = weave.legacy.ops.merge_artifact( - weave.legacy.ops.get("local-artifact:///test_artifact:user-remote_branch/obj") + merged_uri = weave.legacy.weave.ops.merge_artifact( + weave.legacy.weave.ops.get("local-artifact:///test_artifact:user-remote_branch/obj") ) assert merged_uri.startswith("wandb-artifact://") @@ -868,8 +868,8 @@ def test_merge_from_local_with_branch_onto_local_with_commit_hash( ): test_mutate_local_with_commit_hash(user_by_api_key_in_env, "new_branch_name") - merged_uri = weave.legacy.ops.merge_artifact( - weave.legacy.ops.get("local-artifact:///test_artifact:new_branch_name/obj") + merged_uri = weave.legacy.weave.ops.merge_artifact( + weave.legacy.weave.ops.get("local-artifact:///test_artifact:new_branch_name/obj") ) assert merged_uri.startswith("local-artifact://") @@ -898,8 +898,8 @@ def test_merge_from_local_with_branch_onto_local_with_commit_hash( def test_merge_from_local_with_branch_onto_local_with_branch(user_by_api_key_in_env): test_mutate_local_with_branch(user_by_api_key_in_env, "new_branch_name") - merged_uri = weave.legacy.ops.merge_artifact( - weave.legacy.ops.get("local-artifact:///test_artifact:new_branch_name/obj") + merged_uri = weave.legacy.weave.ops.merge_artifact( + weave.legacy.weave.ops.get("local-artifact:///test_artifact:new_branch_name/obj") ) assert merged_uri.startswith("local-artifact://") @@ -924,8 +924,8 @@ def test_merge_from_local_with_branch_onto_local_with_branch_and_branchpoint( user_by_api_key_in_env, "new_branch_name" ) - merged_uri = weave.legacy.ops.merge_artifact( - weave.legacy.ops.get("local-artifact:///test_artifact:new_branch_name/obj") + merged_uri = weave.legacy.weave.ops.merge_artifact( + weave.legacy.weave.ops.get("local-artifact:///test_artifact:new_branch_name/obj") ) assert merged_uri.startswith("local-artifact://") @@ -947,7 +947,7 @@ def test_merge_from_local_with_branch_onto_local_with_branch_and_branchpoint( ), ) - merged_uri_2 = weave.legacy.ops.merge_artifact(weave.legacy.ops.get(merged_uri)) + merged_uri_2 = weave.legacy.weave.ops.merge_artifact(weave.legacy.weave.ops.get(merged_uri)) new_p_ref_2 = WandbArtifactRef.from_str(merged_uri_2) assert merged_uri_2.startswith("wandb-artifact://") @@ -976,7 +976,7 @@ def test_publish_saved_node(user_by_api_key_in_env): assert saved.from_op.inputs["uri"].val.startswith("local-artifact://") assert weave.use(saved) == data - published_art_uri = weave.legacy.ops.publish_artifact(saved, "my_list", None, None) + published_art_uri = weave.legacy.weave.ops.publish_artifact(saved, "my_list", None, None) assert published_art_uri.startswith("wandb-artifact://") assert weave.use(weave.get(published_art_uri)) == data @@ -997,7 +997,7 @@ def _replace_uri_version(uri: str, new_version: str) -> str: return uri.replace(_get_uri_version(uri), new_version) -def _get_uri_from_get_node(node: weave.legacy.graph.Node) -> str: +def _get_uri_from_get_node(node: weave.legacy.weave.graph.Node) -> str: return node.from_op.inputs["uri"].val # type: ignore @@ -1011,44 +1011,44 @@ def test_end_to_end_save_and_publish_flow(user_by_api_key_in_env): assert weave.use(saved_node) == data # Step 2: Make a branching mutation. - weave.legacy.ops.set( + weave.legacy.weave.ops.set( saved_node[0], "test_publish_saved_node_execution_2", root_args={"branch": "my-branch"}, ) branched_data = ["test_publish_saved_node_execution_2"] branched_uri = saved_uri.replace(saved_version, "my-branch") - branched_node = weave.legacy.ops.get(branched_uri) + branched_node = weave.legacy.weave.ops.get(branched_uri) assert weave.use(branched_node) == branched_data # Step 3: Merge the change back into the main branch. - merged_uri = weave.legacy.ops.merge_artifact(branched_node) + merged_uri = weave.legacy.weave.ops.merge_artifact(branched_node) assert merged_uri.startswith("local-artifact://") assert merged_uri != saved_uri != branched_uri - merged_node = weave.legacy.ops.get(merged_uri) + merged_node = weave.legacy.weave.ops.get(merged_uri) assert weave.use(merged_node) == branched_data # Step 4: Publish the new version remotely - published_uri = weave.legacy.ops.publish_artifact( + published_uri = weave.legacy.weave.ops.publish_artifact( merged_node, "my_list", None, None ) assert published_uri.startswith("wandb-artifact://") assert weave.use(weave.get(published_uri)) == branched_data # Step 5: Modify the remote version - weave.legacy.ops.set( - weave.legacy.ops.get(published_uri)[0], + weave.legacy.weave.ops.set( + weave.legacy.weave.ops.get(published_uri)[0], "test_publish_saved_node_execution_3", root_args={"branch": "my-branch-2"}, ) published_branched_data = ["test_publish_saved_node_execution_3"] published_branched_uri = "local-artifact:///my_list:my-branch-2/obj" - published_branched_node = weave.legacy.ops.get(published_branched_uri) + published_branched_node = weave.legacy.weave.ops.get(published_branched_uri) assert weave.use(published_branched_node) == published_branched_data # Step 6: Merge the remote change back into the main branch. - published_merged_uri = weave.legacy.ops.merge_artifact(published_branched_node) + published_merged_uri = weave.legacy.weave.ops.merge_artifact(published_branched_node) assert published_merged_uri.startswith("wandb-artifact://") assert published_merged_uri != published_uri - published_merged_node = weave.legacy.ops.get(published_merged_uri) + published_merged_node = weave.legacy.weave.ops.get(published_merged_uri) assert weave.use(published_merged_node) == published_branched_data diff --git a/weave/legacy/tests/test_pydantic.py b/weave/legacy/tests/test_pydantic.py index 1a57eda18cb..720ec1c1d0b 100644 --- a/weave/legacy/tests/test_pydantic.py +++ b/weave/legacy/tests/test_pydantic.py @@ -3,7 +3,7 @@ import pydantic import weave -from weave.legacy import weave_types as types +from weave.legacy.weave import weave_types as types def test_pydantic_type_inference(): diff --git a/weave/legacy/tests/test_ref_tracking.py b/weave/legacy/tests/test_ref_tracking.py index 47d8ca60408..61b97d769be 100644 --- a/weave/legacy/tests/test_ref_tracking.py +++ b/weave/legacy/tests/test_ref_tracking.py @@ -1,6 +1,6 @@ import weave -from weave.legacy import storage -from weave.legacy import weave_types as types +from weave.legacy.weave import storage +from weave.legacy.weave import weave_types as types def test_reffed_type(ref_tracking): diff --git a/weave/legacy/tests/test_refs.py b/weave/legacy/tests/test_refs.py index e890134d0ff..98bd7048bc5 100644 --- a/weave/legacy/tests/test_refs.py +++ b/weave/legacy/tests/test_refs.py @@ -2,8 +2,8 @@ import weave from weave.flow.obj import Object -from weave.legacy import artifact_local, storage -from weave.legacy import ops_arrow as arrow +from weave.legacy.weave import artifact_local, storage +from weave.legacy.weave import ops_arrow as arrow from weave.trace import ref_util from weave.trace_server.refs_internal import ( DICT_KEY_EDGE_NAME, diff --git a/weave/legacy/tests/test_relpath_no_syscalls.py b/weave/legacy/tests/test_relpath_no_syscalls.py index 412aed2b06e..66ce63b1af0 100644 --- a/weave/legacy/tests/test_relpath_no_syscalls.py +++ b/weave/legacy/tests/test_relpath_no_syscalls.py @@ -1,6 +1,6 @@ import pytest -from weave.legacy.util import relpath_no_syscalls +from weave.legacy.weave.util import relpath_no_syscalls @pytest.mark.parametrize( diff --git a/weave/legacy/tests/test_run_segment.py b/weave/legacy/tests/test_run_segment.py index fd92b66c552..cf918473b88 100644 --- a/weave/legacy/tests/test_run_segment.py +++ b/weave/legacy/tests/test_run_segment.py @@ -6,10 +6,10 @@ import pytest import weave -from weave.legacy import api, ops, storage, weave_internal -from weave.legacy import weave_types as types -from weave.legacy.ops_arrow import ArrowWeaveList, arrow_as_array -from weave.legacy.ops_domain.run_segment import RunSegment +from weave.legacy.weave import api, ops, storage, weave_internal +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.ops_arrow import ArrowWeaveList, arrow_as_array +from weave.legacy.weave.ops_domain.run_segment import RunSegment N_NUMERIC_METRICS = 99 # number of numerical columns in the metrics table diff --git a/weave/legacy/tests/test_serialize.py b/weave/legacy/tests/test_serialize.py index 94251cd1dd4..4a7869e9fe4 100644 --- a/weave/legacy/tests/test_serialize.py +++ b/weave/legacy/tests/test_serialize.py @@ -1,11 +1,11 @@ import pytest import weave -from weave.legacy import api as api -from weave.legacy import graph, op_args, ops, registry_mem, serialize, weave_internal -from weave.legacy import weave_types as types -from weave.legacy.ops_primitives import list_ -from weave.legacy.weave_internal import make_const_node +from weave.legacy.weave import api as api +from weave.legacy.weave import graph, op_args, ops, registry_mem, serialize, weave_internal +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.ops_primitives import list_ +from weave.legacy.weave.weave_internal import make_const_node from ...tests import fixture_fakewandb as fwb diff --git a/weave/legacy/tests/test_show.py b/weave/legacy/tests/test_show.py index bee6ecd76dd..8d56c86cd0c 100644 --- a/weave/legacy/tests/test_show.py +++ b/weave/legacy/tests/test_show.py @@ -2,9 +2,9 @@ # The outputs of weave.show (the generated panel urls and their arguments) # need to match what javascript expects. -from weave.legacy import ops +from weave.legacy.weave import ops -from ...legacy.show import _show_params +from ...legacy.weave.show import _show_params from . import test_helpers diff --git a/weave/legacy/tests/test_stitch.py b/weave/legacy/tests/test_stitch.py index 0c34a27aacd..12e6deb26a5 100644 --- a/weave/legacy/tests/test_stitch.py +++ b/weave/legacy/tests/test_stitch.py @@ -3,12 +3,12 @@ import pytest import weave -from weave.legacy import compile_domain, compile_table, weave_internal -from weave.legacy import context_state as _context -from weave.legacy.language_features.tagging import make_tag_getter_op -from weave.legacy.ops_domain import run_ops +from weave.legacy.weave import compile_domain, compile_table, weave_internal +from weave.legacy.weave import context_state as _context +from weave.legacy.weave.language_features.tagging import make_tag_getter_op +from weave.legacy.weave.ops_domain import run_ops -from ...legacy import stitch +from ...legacy.weave import stitch from ...tests import fixture_fakewandb as fwb from . import test_wb @@ -122,7 +122,7 @@ def test_tag_access_in_filter_expr(): def test_traverse_dict(): obj_node = weave.save(_TestPlanObject("a", 1)) - p = stitch.stitch([weave.legacy.ops.dict_(x=obj_node)["x"].horse()]) + p = stitch.stitch([weave.legacy.weave.ops.dict_(x=obj_node)["x"].horse()]) obj_recorder = p.get_result(obj_node) assert len(obj_recorder.calls) == 1 assert obj_recorder.calls[0].node.from_op.name == "_TestPlanObject-horse" @@ -130,7 +130,7 @@ def test_traverse_dict(): def test_travese_groupby_dict(): obj_node = weave.save([{"o": {"a": 5}, "x": 1}]) - grouped = obj_node.groupby(lambda row: weave.legacy.ops.dict_(x=row["o"])) + grouped = obj_node.groupby(lambda row: weave.legacy.weave.ops.dict_(x=row["o"])) output = grouped[0]["x"] groupkey_output = grouped[0].groupkey()["x"]["a"] p = stitch.stitch([output, groupkey_output]) @@ -163,16 +163,16 @@ def test_zero_arg_ops(): def test_shared_fn_node(): - const_list_node = weave.legacy.ops.make_list(a=1, b=2) + const_list_node = weave.legacy.weave.ops.make_list(a=1, b=2) indexed_node = const_list_node[0] - arr_1_node = weave.legacy.ops.make_list(a=1, b=2, c=3) - arr_2_node = weave.legacy.ops.make_list(a=10, b=20, c=30) + arr_1_node = weave.legacy.weave.ops.make_list(a=1, b=2, c=3) + arr_2_node = weave.legacy.weave.ops.make_list(a=10, b=20, c=30) mapped_1_node = arr_1_node.map( - lambda row: weave.legacy.ops.dict_(item=row, const=indexed_node) + lambda row: weave.legacy.weave.ops.dict_(item=row, const=indexed_node) ) mapped_2_node = arr_2_node.map( - lambda row: weave.legacy.ops.dict_(item=row, const=indexed_node) + lambda row: weave.legacy.weave.ops.dict_(item=row, const=indexed_node) ) mapped_1_item_node = mapped_1_node["item"] @@ -183,7 +183,7 @@ def test_shared_fn_node(): mapped_2_item_add_node = mapped_2_item_node + 100 mapped_2_const_add_node = mapped_2_const_node + 100 - list_of_list_node = weave.legacy.ops.make_list( + list_of_list_node = weave.legacy.weave.ops.make_list( a=mapped_1_item_node, b=mapped_1_const_node, c=mapped_2_item_add_node, @@ -218,9 +218,9 @@ def assert_node_calls(node, expected_call_names): def test_stitch_keytypes_override_fetch_all_columns(fake_wandb): fake_wandb.fake_api.add_mock(test_wb.table_mock_filtered) - keytypes_node = weave.legacy.ops.object_keytypes( + keytypes_node = weave.legacy.weave.ops.object_keytypes( run_ops.run_tag_getter_op( - weave.legacy.ops.project("stacey", "mendeleev") + weave.legacy.weave.ops.project("stacey", "mendeleev") .filteredRuns("{}", "-createdAt") .limit(50) .summary() @@ -255,15 +255,15 @@ def test_stitch_overlapping_tags(fake_wandb): } } ) - project_node = weave.legacy.ops.project("stacey", "mendeleev") + project_node = weave.legacy.weave.ops.project("stacey", "mendeleev") filtered_runs_a_node = project_node.filteredRuns("{}", "-createdAt")[0] summary_a_node = filtered_runs_a_node.summary() - tagged_name_a = weave.legacy.ops.run_ops.run_tag_getter_op( + tagged_name_a = weave.legacy.weave.ops.run_ops.run_tag_getter_op( summary_a_node["a"] ).name() filtered_runs_b_node = project_node.filteredRuns("{}", "+createdAt")[0] summary_b_node = filtered_runs_b_node.summary() - tagged_id_b = weave.legacy.ops.run_ops.run_tag_getter_op(summary_b_node).id() + tagged_id_b = weave.legacy.weave.ops.run_ops.run_tag_getter_op(summary_b_node).id() p = stitch.stitch([tagged_name_a, tagged_id_b]) @@ -273,9 +273,9 @@ def test_stitch_overlapping_tags(fake_wandb): def test_refine_history_type_included_in_gql(): - project_node = weave.legacy.ops.project("stacey", "mendeleev") + project_node = weave.legacy.weave.ops.project("stacey", "mendeleev") runs_node = project_node.runs() - map_node = runs_node.map(lambda row: weave.legacy.ops.dict_(variant=row)) + map_node = runs_node.map(lambda row: weave.legacy.weave.ops.dict_(variant=row)) checkpoint_node = map_node.createIndexCheckpointTag() index_node = checkpoint_node[0] pick_node = index_node["variant"] @@ -286,7 +286,7 @@ def test_refine_history_type_included_in_gql(): def test_stitch_missing_key(): a_node = weave_internal.make_const_node(weave.types.String(), "a") - dict_node = weave.legacy.ops.dict_(a=a_node) + dict_node = weave.legacy.weave.ops.dict_(a=a_node) picked_valid = dict_node["a"] + "-suffix" picked_missing = dict_node["b"] + "-suffix" diff --git a/weave/legacy/tests/test_storage.py b/weave/legacy/tests/test_storage.py index 29dda1e8963..8183200fa3e 100644 --- a/weave/legacy/tests/test_storage.py +++ b/weave/legacy/tests/test_storage.py @@ -7,19 +7,19 @@ import pytest import wandb -from weave.legacy import api as weave -from weave.legacy import ( +from weave.legacy.weave import api as weave +from weave.legacy.weave import ( artifact_mem, artifact_wandb, mappers_python, ops_arrow, storage, ) -from weave.legacy import weave_types as types -from weave.legacy.arrow import list_ as arrow -from weave.legacy.weave_internal import make_const_node +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.arrow import list_ as arrow +from weave.legacy.weave.weave_internal import make_const_node -from ...legacy.weavejs_fixes import recursively_unwrap_unions +from ...legacy.weave.weavejs_fixes import recursively_unwrap_unions from . import test_helpers diff --git a/weave/legacy/tests/test_stream_table.py b/weave/legacy/tests/test_stream_table.py index 393894a8aa3..7591331e979 100644 --- a/weave/legacy/tests/test_stream_table.py +++ b/weave/legacy/tests/test_stream_table.py @@ -1,7 +1,7 @@ import os import time -from weave.legacy.wandb_interface.wandb_stream_table import StreamTable +from weave.legacy.weave.wandb_interface.wandb_stream_table import StreamTable def main(table_name, project_name, entity_name, sample_limit, gap_ms): diff --git a/weave/legacy/tests/test_table_ops.py b/weave/legacy/tests/test_table_ops.py index 83e526edd03..2994235eb37 100644 --- a/weave/legacy/tests/test_table_ops.py +++ b/weave/legacy/tests/test_table_ops.py @@ -3,8 +3,8 @@ import pytest -from weave.legacy import api as weave -from weave.legacy import ( +from weave.legacy.weave import api as weave +from weave.legacy.weave import ( box, context, context_state, @@ -13,8 +13,8 @@ storage, weave_internal, ) -from weave.legacy import weave_types as types -from weave.legacy.ops_domain import table as table_ops +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.ops_domain import table as table_ops from weave.legacy.tests.util import weavejs_ops diff --git a/weave/legacy/tests/test_tagging.py b/weave/legacy/tests/test_tagging.py index da17be75408..471205b4920 100644 --- a/weave/legacy/tests/test_tagging.py +++ b/weave/legacy/tests/test_tagging.py @@ -1,19 +1,19 @@ import pytest import weave -from weave.legacy import box, weave_internal -from weave.legacy import weave_types as types -from weave.legacy.artifact_fs import FilesystemArtifactFileType -from weave.legacy.language_features.tagging import ( +from weave.legacy.weave import box, weave_internal +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.artifact_fs import FilesystemArtifactFileType +from weave.legacy.weave.language_features.tagging import ( make_tag_getter_op, tag_store, tagged_value_type, tagged_value_type_helpers, ) -from weave.legacy.ops_domain.run_ops import run_tag_getter_op -from weave.legacy.ops_domain.wb_domain_types import ProjectType, Run, RunType -from weave.legacy.ops_primitives import dict as dict_ops -from weave.legacy.ops_primitives import list_ as list_ops +from weave.legacy.weave.ops_domain.run_ops import run_tag_getter_op +from weave.legacy.weave.ops_domain.wb_domain_types import ProjectType, Run, RunType +from weave.legacy.weave.ops_primitives import dict as dict_ops +from weave.legacy.weave.ops_primitives import list_ as list_ops def test_tagged_value(): @@ -29,7 +29,7 @@ def test_tagged_types(): class _TestNumber: inner: int - from weave.legacy import context_state + from weave.legacy.weave import context_state _loading_builtins_token = context_state.set_loading_built_ins() diff --git a/weave/legacy/tests/test_templates.py b/weave/legacy/tests/test_templates.py index 76335e6f118..6c3e2289295 100644 --- a/weave/legacy/tests/test_templates.py +++ b/weave/legacy/tests/test_templates.py @@ -3,10 +3,10 @@ import wandb import weave -from weave.legacy import context_state as _context -from weave.legacy.wandb_interface.wandb_stream_table import StreamTable +from weave.legacy.weave import context_state as _context +from weave.legacy.weave.wandb_interface.wandb_stream_table import StreamTable -from ...legacy.panels_py import generator_templates +from ...legacy.weave.panels_py import generator_templates _loading_builtins_token = _context.set_loading_built_ins() @@ -34,17 +34,17 @@ class DummyBoardConfig: def dummy_board( input_node, config: typing.Optional[DummyBoardConfig] = None, -) -> weave.legacy.panels.Group: +) -> weave.legacy.weave.panels.Group: assert board_input_type.assign_type(input_node.type) control_items = [ - weave.legacy.panels.GroupPanel( + weave.legacy.weave.panels.GroupPanel( input_node, id="data", ), ] - return weave.legacy.panels.Board(vars=control_items, panels=[]) + return weave.legacy.weave.panels.Board(vars=control_items, panels=[]) generator_templates.template_registry.register( @@ -77,13 +77,13 @@ def _assert_valid_node_raw(node): output_group = weave.use(dummy_node) # Assert the out template is successfully generated - assert isinstance(output_group, weave.legacy.panels.Group) + assert isinstance(output_group, weave.legacy.weave.panels.Group) data_node = output_group.config.items["sidebar"].config.items["data"] # assert that the node sent to the generator is the same as the node that is used # Note: this is a heuristic, but probably close enough - assert isinstance(data_node, weave.legacy.graph.OutputNode) + assert isinstance(data_node, weave.legacy.weave.graph.OutputNode) assert data_node.from_op.name == node.from_op.name assert str(data_node) == str(node) @@ -102,7 +102,7 @@ def test_templates_for_run_logs_valid(user_by_api_key_in_env): run.finish() run_history_node = ( - weave.legacy.ops.project(run.entity, run.project).run(run.id).history() + weave.legacy.weave.ops.project(run.entity, run.project).run(run.id).history() ) assert_valid_node(run_history_node) @@ -114,7 +114,7 @@ def test_templates_for_run_logs_invalid(user_by_api_key_in_env): run.finish() run_history_node = ( - weave.legacy.ops.project(run.entity, run.project).run(run.id).history() + weave.legacy.weave.ops.project(run.entity, run.project).run(run.id).history() ) assert_invalid_node(run_history_node) @@ -126,7 +126,7 @@ def test_templates_for_logged_table_valid(user_by_api_key_in_env): run.finish() table_node = ( - weave.legacy.ops.project(run.entity, run.project) + weave.legacy.weave.ops.project(run.entity, run.project) .run(run.id) .summary()["table"] .table() @@ -142,7 +142,7 @@ def test_templates_for_logged_table_invalid(user_by_api_key_in_env): run.finish() table_node = ( - weave.legacy.ops.project(run.entity, run.project) + weave.legacy.weave.ops.project(run.entity, run.project) .run(run.id) .summary()["table"] .table() diff --git a/weave/legacy/tests/test_timestamp_bin.py b/weave/legacy/tests/test_timestamp_bin.py index 1243c2d3a3a..1e24617baeb 100644 --- a/weave/legacy/tests/test_timestamp_bin.py +++ b/weave/legacy/tests/test_timestamp_bin.py @@ -6,7 +6,7 @@ def test_timestamp_bins_fixed(): - bin_fn = weave.legacy.ops.timestamp_bins_fixed(60) + bin_fn = weave.legacy.weave.ops.timestamp_bins_fixed(60) ts = datetime(2020, 1, 1, 8, 30, 1) called = bin_fn(ts) @@ -19,7 +19,7 @@ def test_timestamp_bins_fixed(): def test_timestamp_bins_nice(): start_ts = datetime(2020, 1, 1, 8, 30, 1) stop_ts = datetime(2020, 1, 1, 12, 30, 0) - bin_fn = weave.legacy.ops.timestamp_bins_nice([start_ts, stop_ts], 100) + bin_fn = weave.legacy.weave.ops.timestamp_bins_nice([start_ts, stop_ts], 100) ts = datetime(2020, 1, 1, 8, 45, 13) called = bin_fn(ts) @@ -32,7 +32,7 @@ def test_timestamp_bins_nice(): def test_timestamp_bin(): start_ts = datetime(2020, 1, 1, 8, 30, 1) stop_ts = datetime(2020, 1, 1, 12, 30, 0) - bin_fn = weave.legacy.ops.timestamp_bins_nice([start_ts, stop_ts], 100) + bin_fn = weave.legacy.weave.ops.timestamp_bins_nice([start_ts, stop_ts], 100) ts = datetime(2020, 1, 1, 8, 45, 13) ts_node = weave.save(ts) @@ -45,10 +45,10 @@ def test_timestamp_bin(): def test_timestamp_bin_vector(): start_ts = datetime(2020, 1, 1, 8, 30, 1) stop_ts = datetime(2020, 1, 1, 12, 30, 0) - bin_fn = weave.legacy.ops.timestamp_bins_nice([start_ts, stop_ts], 100) + bin_fn = weave.legacy.weave.ops.timestamp_bins_nice([start_ts, stop_ts], 100) ts = datetime(2020, 1, 1, 8, 45, 13, tzinfo=timezone.utc) - ts_node = weave.legacy.ops.to_weave_arrow([ts, ts + timedelta(seconds=90)]) + ts_node = weave.legacy.weave.ops.to_weave_arrow([ts, ts + timedelta(seconds=90)]) # This does not vectorize because mapped ops don't automatically # vectorize! diff --git a/weave/legacy/tests/test_trace.py b/weave/legacy/tests/test_trace.py index a0c308aab12..a809e10a654 100644 --- a/weave/legacy/tests/test_trace.py +++ b/weave/legacy/tests/test_trace.py @@ -1,10 +1,10 @@ import re -from weave.legacy import api as weave -from weave.legacy import graph, storage -from weave.legacy.weave_internal import make_const_node +from weave.legacy.weave import api as weave +from weave.legacy.weave import graph, storage +from weave.legacy.weave.weave_internal import make_const_node -from ...legacy import trace_legacy +from ...legacy.weave import trace_legacy def test_node_expr(): diff --git a/weave/legacy/tests/test_typeddict_notrequired.py b/weave/legacy/tests/test_typeddict_notrequired.py index 0625b430aad..7b9c940184d 100644 --- a/weave/legacy/tests/test_typeddict_notrequired.py +++ b/weave/legacy/tests/test_typeddict_notrequired.py @@ -6,8 +6,8 @@ TypedDict, ) -from weave.legacy import infer_types -from weave.legacy import weave_types as types +from weave.legacy.weave import infer_types +from weave.legacy.weave import weave_types as types class _TestNotRequiredTypedDict(TypedDict): diff --git a/weave/legacy/tests/test_uris.py b/weave/legacy/tests/test_uris.py index ace2efcc36d..f544d9158a5 100644 --- a/weave/legacy/tests/test_uris.py +++ b/weave/legacy/tests/test_uris.py @@ -1,7 +1,7 @@ import pytest -from weave.legacy import uris -from weave.legacy.artifact_wandb import WeaveWBArtifactURI +from weave.legacy.weave import uris +from weave.legacy.weave.artifact_wandb import WeaveWBArtifactURI URIS = [ "op-get", diff --git a/weave/legacy/tests/test_wb.py b/weave/legacy/tests/test_wb.py index e3f3e96892d..b6cc5a11d5d 100644 --- a/weave/legacy/tests/test_wb.py +++ b/weave/legacy/tests/test_wb.py @@ -6,17 +6,17 @@ import pytest import wandb -from weave.legacy import api as weave -from weave.legacy import artifact_fs, artifact_wandb, compile, graph, ops, stitch, uris -from weave.legacy import ops_arrow as arrow -from weave.legacy import weave_types as types -from weave.legacy.language_features.tagging.tagged_value_type import TaggedValueType -from weave.legacy.ops_arrow import ArrowWeaveListType -from weave.legacy.ops_domain import artifact_membership_ops as amo -from weave.legacy.ops_domain import table, wb_util, wbmedia -from weave.legacy.ops_domain import wb_domain_types as wdt -from weave.legacy.ops_primitives import dict_, list_ -from weave.legacy.ops_primitives.file import _as_w0_dict_ +from weave.legacy.weave import api as weave +from weave.legacy.weave import artifact_fs, artifact_wandb, compile, graph, ops, stitch, uris +from weave.legacy.weave import ops_arrow as arrow +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.language_features.tagging.tagged_value_type import TaggedValueType +from weave.legacy.weave.ops_arrow import ArrowWeaveListType +from weave.legacy.weave.ops_domain import artifact_membership_ops as amo +from weave.legacy.weave.ops_domain import table, wb_util, wbmedia +from weave.legacy.weave.ops_domain import wb_domain_types as wdt +from weave.legacy.weave.ops_primitives import dict_, list_ +from weave.legacy.weave.ops_primitives.file import _as_w0_dict_ from .test_wb_domain_ops import assert_gql_str_equal from ...tests import fixture_fakewandb as fwb diff --git a/weave/legacy/tests/test_wb_data_types.py b/weave/legacy/tests/test_wb_data_types.py index ea41588b6c3..aae7baafdc2 100644 --- a/weave/legacy/tests/test_wb_data_types.py +++ b/weave/legacy/tests/test_wb_data_types.py @@ -12,14 +12,14 @@ from wandb.sdk.data_types._dtypes import TypeRegistry as SDKTypeRegistry import weave -from weave.legacy import artifact_fs -from weave.legacy import weave_types as types -from weave.legacy.artifact_wandb import WandbArtifact, WeaveWBArtifactURI -from weave.legacy.language_features.tagging.tagged_value_type import TaggedValueType -from weave.legacy.ops_domain.wbmedia import ImageArtifactFileRefType -from weave.legacy.ops_primitives import file -from weave.legacy.wandb_client_api import wandb_gql_query -from weave.legacy.wandb_util import weave0_type_json_to_weave1_type +from weave.legacy.weave import artifact_fs +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.artifact_wandb import WandbArtifact, WeaveWBArtifactURI +from weave.legacy.weave.language_features.tagging.tagged_value_type import TaggedValueType +from weave.legacy.weave.ops_domain.wbmedia import ImageArtifactFileRefType +from weave.legacy.weave.ops_primitives import file +from weave.legacy.weave.wandb_client_api import wandb_gql_query +from weave.legacy.weave.wandb_util import weave0_type_json_to_weave1_type from ...tests.fixture_fakewandb import FakeApi @@ -109,31 +109,31 @@ def make_molecule(clean_up=True): # ( make_image(), - weave.legacy.ops.ImageArtifactFileRef.WeaveType(), # type: ignore + weave.legacy.weave.ops.ImageArtifactFileRef.WeaveType(), # type: ignore ), ( make_audio(), - weave.legacy.ops.AudioArtifactFileRef.WeaveType(), # type: ignore + weave.legacy.weave.ops.AudioArtifactFileRef.WeaveType(), # type: ignore ), ( make_html(), - weave.legacy.ops.HtmlArtifactFileRef.WeaveType(), # type: ignore + weave.legacy.weave.ops.HtmlArtifactFileRef.WeaveType(), # type: ignore ), ( make_bokeh(), - weave.legacy.ops.BokehArtifactFileRef.WeaveType(), # type: ignore + weave.legacy.weave.ops.BokehArtifactFileRef.WeaveType(), # type: ignore ), ( make_video(), - weave.legacy.ops.VideoArtifactFileRef.WeaveType(), # type: ignore + weave.legacy.weave.ops.VideoArtifactFileRef.WeaveType(), # type: ignore ), ( make_object3d(), - weave.legacy.ops.Object3DArtifactFileRef.WeaveType(), # type: ignore + weave.legacy.weave.ops.Object3DArtifactFileRef.WeaveType(), # type: ignore ), ( make_molecule(), - weave.legacy.ops.MoleculeArtifactFileRef.WeaveType(), # type: ignore + weave.legacy.weave.ops.MoleculeArtifactFileRef.WeaveType(), # type: ignore ), # See comment in wandb_util.py - this may change in the future # Temporarily disabled until we can figure out how to mock @@ -630,7 +630,7 @@ def test_grouping_on_images(fake_wandb): table_node = file_node.table() table_rows = table_node.rows() grouped = table_rows.groupby( - lambda row: weave.legacy.ops.dict_(g_image=row["image"]) + lambda row: weave.legacy.weave.ops.dict_(g_image=row["image"]) ) raw_data = weave.use(grouped).to_pylist_notags() @@ -761,7 +761,7 @@ def make_join_table_row_nodes(fake_wandb): def test_join_all_on_images(fake_wandb): table_1_rows, table_2_rows = make_join_table_row_nodes(fake_wandb) - rows = weave.legacy.ops.make_list(a=table_1_rows, b=table_2_rows) + rows = weave.legacy.weave.ops.make_list(a=table_1_rows, b=table_2_rows) joined = rows.joinAll(lambda row: row["image"], True) @@ -855,12 +855,12 @@ def wait_for(): wait_for_x_times(wait_for) - run_node = weave.legacy.ops.project(run.entity, run.project).run(run.id) + run_node = weave.legacy.weave.ops.project(run.entity, run.project).run(run.id) for history_op_name in ["history3", "history"]: history_node = run_node._get_op(history_op_name)() mapped_node = history_node.map( - lambda row: weave.legacy.ops.dict_( + lambda row: weave.legacy.weave.ops.dict_( **{key: row[key] for key in log_dict.keys()} ) ) diff --git a/weave/legacy/tests/test_wb_domain_ops.py b/weave/legacy/tests/test_wb_domain_ops.py index aefaa47c94c..89c12c8260a 100644 --- a/weave/legacy/tests/test_wb_domain_ops.py +++ b/weave/legacy/tests/test_wb_domain_ops.py @@ -4,12 +4,12 @@ import wandb import weave -from weave.legacy import ops -from weave.legacy.language_features.tagging import tagged_value_type -from weave.legacy.ops_domain import wb_domain_types -from weave.legacy.ops_primitives import _dict_utils +from weave.legacy.weave import ops +from weave.legacy.weave.language_features.tagging import tagged_value_type +from weave.legacy.weave.ops_domain import wb_domain_types +from weave.legacy.weave.ops_primitives import _dict_utils -from ...legacy import registry_mem +from ...legacy.weave import registry_mem from ...tests import fixture_fakewandb as fwb """ diff --git a/weave/legacy/tests/test_wb_domain_types.py b/weave/legacy/tests/test_wb_domain_types.py index ed550677062..5380e0347e3 100644 --- a/weave/legacy/tests/test_wb_domain_types.py +++ b/weave/legacy/tests/test_wb_domain_types.py @@ -1,7 +1,7 @@ -from weave.legacy import api as weave -from weave.legacy import storage -from weave.legacy import weave_types as types -from weave.legacy.ops_domain import wb_domain_types as wdt +from weave.legacy.weave import api as weave +from weave.legacy.weave import storage +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.ops_domain import wb_domain_types as wdt def test_with_keys_assignability(): diff --git a/weave/legacy/tests/test_wb_end_to_end.py b/weave/legacy/tests/test_wb_end_to_end.py index 2232079248d..2902a34d1aa 100644 --- a/weave/legacy/tests/test_wb_end_to_end.py +++ b/weave/legacy/tests/test_wb_end_to_end.py @@ -1,7 +1,7 @@ import wandb import weave -from weave.legacy import compile +from weave.legacy.weave import compile # Example of end to end integration test @@ -11,17 +11,17 @@ def test_run_logging(user_by_api_key_in_env): run.finish() summary_node = ( - weave.legacy.ops.project(run.entity, run.project).run(run.id).summary()["a"] + weave.legacy.weave.ops.project(run.entity, run.project).run(run.id).summary()["a"] ) summary = weave.use(summary_node) assert summary == 1 - is_none_node = weave.legacy.ops.project(run.entity, run.project).isNone() + is_none_node = weave.legacy.weave.ops.project(run.entity, run.project).isNone() assert weave.use(is_none_node) == False - is_none_node = weave.legacy.ops.project( + is_none_node = weave.legacy.weave.ops.project( run.entity, "project_does_not_exist" ).isNone() @@ -60,7 +60,7 @@ def _test_basic_publish(user_fixture): uri == f"wandb-artifact:///{user_fixture.username}/weave/list:0cdf3358dc939f961ca9/obj" ) - assert weave.legacy.ref_base.Ref.from_str(uri).get() == [1, 2, 3] + assert weave.legacy.weave.ref_base.Ref.from_str(uri).get() == [1, 2, 3] # Example of end to end integration test @@ -74,7 +74,7 @@ def test_run_histories(user_by_api_key_in_env): run.finish() history_node = ( - weave.legacy.ops.project(run.entity, run.project).runs().history().concat()["a"] + weave.legacy.weave.ops.project(run.entity, run.project).runs().history().concat()["a"] ) history = weave.use(history_node) @@ -89,7 +89,7 @@ def test_run_history_count(user_by_api_key_in_env, cache_mode_minimal): run.log({"a": 2}) run.finish() - run_node = weave.legacy.ops.project(run.entity, run.project).run(run.id) + run_node = weave.legacy.weave.ops.project(run.entity, run.project).run(run.id) h_count_node = run_node.history().count() history_count = weave.use(h_count_node) assert history_count == 2 diff --git a/weave/legacy/tests/test_wb_history_loading_compatability.py b/weave/legacy/tests/test_wb_history_loading_compatability.py index 84edb18c1db..da2571fac1b 100644 --- a/weave/legacy/tests/test_wb_history_loading_compatability.py +++ b/weave/legacy/tests/test_wb_history_loading_compatability.py @@ -8,13 +8,13 @@ from PIL import Image import weave -from weave.legacy import context_state as _context -from weave.legacy.ops_domain.run_history.context import ( +from weave.legacy.weave import context_state as _context +from weave.legacy.weave.ops_domain.run_history.context import ( error_on_non_vectorized_history_transform, ) -from weave.legacy.ops_domain.run_history.history_op_common import _without_tags -from weave.legacy.wandb_client_api import wandb_gql_query -from weave.legacy.wandb_interface import wandb_stream_table +from weave.legacy.weave.ops_domain.run_history.history_op_common import _without_tags +from weave.legacy.weave.wandb_client_api import wandb_gql_query +from weave.legacy.weave.wandb_interface import wandb_stream_table HISTORY_OP_NAME = "history3" @@ -180,7 +180,7 @@ def do_batch_test(username, rows, do_assertion): row_accumulator, st, user_logged_keys = do_logging(username, rows) row_type = weave.types.TypeRegistry.type_of([{}, *row_accumulator]) - run_node = weave.legacy.ops.project(st._entity_name, st._project_name).run( + run_node = weave.legacy.weave.ops.project(st._entity_name, st._project_name).run( st._table_name ) @@ -392,7 +392,7 @@ def test_stream_table_perf(user_by_api_key_in_env, n_rows, n_cols): timings["log"] += time.time() print(f"Log Time: {timings['log']}") - run_node = weave.legacy.ops.project(st._entity_name, st._project_name).run( + run_node = weave.legacy.weave.ops.project(st._entity_name, st._project_name).run( st._table_name ) diff --git a/weave/legacy/tests/test_wb_stream_table.py b/weave/legacy/tests/test_wb_stream_table.py index 68301ad4dde..55bf16953ff 100644 --- a/weave/legacy/tests/test_wb_stream_table.py +++ b/weave/legacy/tests/test_wb_stream_table.py @@ -5,8 +5,8 @@ from PIL import Image import weave -from weave.legacy import context, execute, gql_json_cache, wandb_api, weave_types -from weave.legacy.wandb_interface.wandb_stream_table import StreamTable +from weave.legacy.weave import context, execute, gql_json_cache, wandb_api, weave_types +from weave.legacy.weave.wandb_interface.wandb_stream_table import StreamTable def make_stream_table(*args, **kwargs): @@ -26,7 +26,7 @@ def test_stream_logging(user_by_api_key_in_env): st.finish() hist_node = ( - weave.legacy.ops.project(user_by_api_key_in_env.username, "stream-tables") + weave.legacy.weave.ops.project(user_by_api_key_in_env.username, "stream-tables") .run("test_table") .history3() ) @@ -56,7 +56,7 @@ def test_bytes_read_from_arrow_reporting(user_by_api_key_in_env): st.finish() hist_node = ( - weave.legacy.ops.project(user_by_api_key_in_env.username, "stream-tables") + weave.legacy.weave.ops.project(user_by_api_key_in_env.username, "stream-tables") .run("test_table") .history3() ) @@ -90,7 +90,7 @@ def image(): time.sleep(5) hist_node = ( - weave.legacy.ops.project(user_by_api_key_in_env.username, "stream-tables") + weave.legacy.weave.ops.project(user_by_api_key_in_env.username, "stream-tables") .run("test_table-8") .history2() ) @@ -121,7 +121,7 @@ def test_multi_writers_sequential(user_by_api_key_in_env): def do_asserts(): hist_node = ( - weave.legacy.ops.project(user_by_api_key_in_env.username, "stream-tables") + weave.legacy.weave.ops.project(user_by_api_key_in_env.username, "stream-tables") .run("test_table") .history2() ) @@ -181,7 +181,7 @@ def test_multi_writers_parallel(user_by_api_key_in_env): st_2.finish() hist_node = ( - weave.legacy.ops.project(entity_name, "stream-tables") + weave.legacy.weave.ops.project(entity_name, "stream-tables") .run(table_name) .history2() ) diff --git a/weave/legacy/tests/test_wb_tables.py b/weave/legacy/tests/test_wb_tables.py index 0c89d128d29..3dca70237be 100644 --- a/weave/legacy/tests/test_wb_tables.py +++ b/weave/legacy/tests/test_wb_tables.py @@ -4,12 +4,12 @@ import wandb import weave -from weave.legacy.language_features.tagging import make_tag_getter_op -from weave.legacy.language_features.tagging.tagged_value_type import TaggedValueType -from weave.legacy.ops_arrow.list_ops import filter -from weave.legacy.ops_domain import wbmedia -from weave.legacy.ops_domain.wandb_domain_gql import _make_alias -from weave.legacy.weave_internal import make_const_node +from weave.legacy.weave.language_features.tagging import make_tag_getter_op +from weave.legacy.weave.language_features.tagging.tagged_value_type import TaggedValueType +from weave.legacy.weave.ops_arrow.list_ops import filter +from weave.legacy.weave.ops_domain import wbmedia +from weave.legacy.weave.ops_domain.wandb_domain_gql import _make_alias +from weave.legacy.weave.weave_internal import make_const_node def use_static_artifact_node( @@ -18,7 +18,7 @@ def use_static_artifact_node( project_name="test_project", collection_name="joined_table_artifact", version="latest", -) -> weave.legacy.graph.Node: +) -> weave.legacy.weave.graph.Node: fake_wandb.fake_api.add_mock( lambda q, ndx: { "project_5702147f0293fd7538d402af13069708": { @@ -53,7 +53,7 @@ def use_static_artifact_node( } } ) - return weave.legacy.ops.project(entity_name, project_name).artifactVersion( + return weave.legacy.weave.ops.project(entity_name, project_name).artifactVersion( collection_name, version ) @@ -242,9 +242,9 @@ def test_metric_table_join(fake_wandb): file_node = art_node.file("table.table.json") table_node = file_node.table() table_rows = table_node.rows().createIndexCheckpointTag() - grouped = table_rows.groupby(lambda row: weave.legacy.ops.dict_(label=row["label"])) + grouped = table_rows.groupby(lambda row: weave.legacy.weave.ops.dict_(label=row["label"])) sorted = grouped.sort( - lambda row: weave.legacy.ops.make_list(a=row.groupkey()["label"]), ["asc"] + lambda row: weave.legacy.weave.ops.make_list(a=row.groupkey()["label"]), ["asc"] ) group_col_0 = sorted[0].groupkey()["label"] group_col_1 = sorted[1].groupkey()["label"] @@ -265,9 +265,9 @@ def test_empty_table(fake_wandb): table_node = file_node.table() table_rows = table_node.rows().createIndexCheckpointTag() filtered = filter(table_rows, lambda row: row["label"] == "cat") - grouped = filtered.groupby(lambda row: weave.legacy.ops.dict_(label=row["label"])) + grouped = filtered.groupby(lambda row: weave.legacy.weave.ops.dict_(label=row["label"])) sorted = grouped.sort( - lambda row: weave.legacy.ops.make_list(a=row.groupkey()["label"]), ["asc"] + lambda row: weave.legacy.weave.ops.make_list(a=row.groupkey()["label"]), ["asc"] ) res = weave.use(sorted) assert res.to_pylist_raw() == [] @@ -306,14 +306,14 @@ def test_join_group_combo(fake_wandb): art_2_node = fake_wandb.mock_artifact_as_node(art_2) table_1_rows = art_1_node.file("table_1.table.json").table().rows() table_2_rows = art_2_node.file("table_2.table.json").table().rows() - list_of_tables = weave.legacy.ops.make_list(a=table_1_rows, b=table_2_rows).dropna() + list_of_tables = weave.legacy.weave.ops.make_list(a=table_1_rows, b=table_2_rows).dropna() joined_tables = list_of_tables.joinAll( - lambda row: weave.legacy.ops.make_list(a=row["id"]), False + lambda row: weave.legacy.weave.ops.make_list(a=row["id"]), False ) indexed = joined_tables.createIndexCheckpointTag() - grouped = indexed.groupby(lambda row: weave.legacy.ops.dict_(label=row["label"][0])) + grouped = indexed.groupby(lambda row: weave.legacy.weave.ops.dict_(label=row["label"][0])) sorted = grouped.sort( - lambda row: weave.legacy.ops.make_list(label=row.groupkey()["label"]), + lambda row: weave.legacy.weave.ops.make_list(label=row.groupkey()["label"]), ["asc"], ) assert weave.use(sorted.count()) == 3 @@ -326,7 +326,7 @@ def test_join_group_combo(fake_wandb): join_obj = sorted[0].joinObj()[0] assert weave.use(join_obj) == [1.0] - from weave.legacy import context_state + from weave.legacy.weave import context_state _loading_builtins_token = context_state.set_loading_built_ins() tag_getter_op = make_tag_getter_op.make_tag_getter_op( @@ -360,7 +360,7 @@ def test_group_by_const(fake_wandb): art_1_node = fake_wandb.mock_artifact_as_node(art_1) table_1_rows = art_1_node.file("table_1.table.json").table().rows() grouped = table_1_rows.groupby( - lambda row: weave.legacy.ops.dict_( + lambda row: weave.legacy.weave.ops.dict_( a=make_const_node(weave.types.Boolean(), True) ) ) @@ -413,14 +413,14 @@ def test_column_sort(fake_wandb): for col in columns: sorted = rows.sort( - lambda row: weave.legacy.ops.make_list(label=row[col]), ["desc"] + lambda row: weave.legacy.weave.ops.make_list(label=row[col]), ["desc"] ) assert weave.use(sorted).to_pylist_notags() == [ dict(zip(columns, row)) for row in [row3, row2, row1] ] sorted = sorted.sort( - lambda row: weave.legacy.ops.make_list(label=row[col]), ["asc"] + lambda row: weave.legacy.weave.ops.make_list(label=row[col]), ["asc"] ) assert weave.use(sorted).to_pylist_notags() == [ dict(zip(columns, row)) for row in data @@ -428,7 +428,7 @@ def test_column_sort(fake_wandb): # Additional test sorting typed timestamps sorted = rows.sort( - lambda row: weave.legacy.ops.make_list(label=row["timestamp"].toTimestamp()), + lambda row: weave.legacy.weave.ops.make_list(label=row["timestamp"].toTimestamp()), ["desc"], ) assert weave.use(sorted).to_pylist_notags() == [ @@ -436,7 +436,7 @@ def test_column_sort(fake_wandb): ] sorted = sorted.sort( - lambda row: weave.legacy.ops.make_list(label=row["timestamp"].toTimestamp()), + lambda row: weave.legacy.weave.ops.make_list(label=row["timestamp"].toTimestamp()), ["asc"], ) assert weave.use(sorted).to_pylist_notags() == [ @@ -464,8 +464,8 @@ def test_group_avg_sort_combo(fake_wandb): art_1_node = fake_wandb.mock_artifact_as_node(art_1) rows = art_1_node.file("table_1.table.json").table().rows() - grouped = rows.groupby(lambda row: weave.legacy.ops.dict_(label=row["label"])) + grouped = rows.groupby(lambda row: weave.legacy.weave.ops.dict_(label=row["label"])) sorted = grouped.sort( - lambda row: weave.legacy.ops.make_list(label=row["score"].avg()), ["asc"] + lambda row: weave.legacy.weave.ops.make_list(label=row["score"].avg()), ["asc"] ) assert weave.use(sorted[2].groupkey()["label"]) == "C" diff --git a/weave/legacy/tests/test_weave_api.py b/weave/legacy/tests/test_weave_api.py index 90fd26ebb24..0e20c9acf37 100644 --- a/weave/legacy/tests/test_weave_api.py +++ b/weave/legacy/tests/test_weave_api.py @@ -3,8 +3,8 @@ import pytest import weave -import weave.legacy.context_state -import weave.legacy.wandb_api +import weave.legacy.weave.context_state +import weave.legacy.weave.wandb_api import weave.trace.weave_init @@ -12,25 +12,25 @@ def test_create_list_rename_delete(): os.environ["WEAVE_CACHE_MODE"] = "minimal" # create - art_node = weave.legacy.ops.get("local-artifact:///my-data:latest/obj") + art_node = weave.legacy.weave.ops.get("local-artifact:///my-data:latest/obj") art_node.set("foo") assert weave.use(art_node) == "foo" # list - arts = weave.use(weave.legacy.ops.local_artifacts()) + arts = weave.use(weave.legacy.weave.ops.local_artifacts()) assert len(arts) == 1 assert arts[0].name == "my-data" # rename - weave.legacy.ops.rename_artifact(art_node, "my-data2") - arts = weave.use(weave.legacy.ops.local_artifacts()) + weave.legacy.weave.ops.rename_artifact(art_node, "my-data2") + arts = weave.use(weave.legacy.weave.ops.local_artifacts()) assert len(arts) == 1 assert arts[0].name == "my-data2" # delete - art_node = weave.legacy.ops.get("local-artifact:///my-data2:latest/obj") - weave.legacy.ops.delete_artifact(art_node) - arts = weave.use(weave.legacy.ops.local_artifacts()) + art_node = weave.legacy.weave.ops.get("local-artifact:///my-data2:latest/obj") + weave.legacy.weave.ops.delete_artifact(art_node) + arts = weave.use(weave.legacy.weave.ops.local_artifacts()) assert len(arts) == 0 diff --git a/weave/legacy/tests/test_weave_types.py b/weave/legacy/tests/test_weave_types.py index 1c88c49d14f..070d1791465 100644 --- a/weave/legacy/tests/test_weave_types.py +++ b/weave/legacy/tests/test_weave_types.py @@ -3,12 +3,12 @@ import pytest import weave -import weave.legacy -import weave.legacy.weave_types -from weave.legacy import _dict_utils, runs -from weave.legacy import weave_types as types -from weave.legacy.language_features.tagging.tagged_value_type import TaggedValueType -from weave.legacy.ops_domain import wbmedia +import weave.legacy.weave +import weave.legacy.weave.weave_types +from weave.legacy.weave import _dict_utils, runs +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.language_features.tagging.tagged_value_type import TaggedValueType +from weave.legacy.weave.ops_domain import wbmedia from ... import errors @@ -155,23 +155,23 @@ def test_typeof_list_dict_merge(): def test_typeof_nested_dict_merge(): """Tests that nested merging is disabled.""" - t1 = weave.legacy.weave_types.TypedDict( - {"a": weave.legacy.weave_types.TypedDict({"b": types.Int()})} + t1 = weave.legacy.weave.weave_types.TypedDict( + {"a": weave.legacy.weave.weave_types.TypedDict({"b": types.Int()})} ) - t2 = weave.legacy.weave_types.TypedDict( - {"a": weave.legacy.weave_types.TypedDict({"c": types.String()})} + t2 = weave.legacy.weave.weave_types.TypedDict( + {"a": weave.legacy.weave.weave_types.TypedDict({"c": types.String()})} ) merged_type = _dict_utils.typeddict_merge_output_type({"self": t1, "other": t2}) - assert merged_type == weave.legacy.weave_types.TypedDict( - {"a": weave.legacy.weave_types.TypedDict({"c": types.String()})} + assert merged_type == weave.legacy.weave.weave_types.TypedDict( + {"a": weave.legacy.weave.weave_types.TypedDict({"c": types.String()})} ) def test_dict_without_key_type(): - fully_typed = weave.legacy.weave_types.TypeRegistry.type_from_dict( + fully_typed = weave.legacy.weave.weave_types.TypeRegistry.type_from_dict( {"type": "dict", "keyType": "string", "objectType": "number"} ) - partial_typed = weave.legacy.weave_types.TypeRegistry.type_from_dict( + partial_typed = weave.legacy.weave.weave_types.TypeRegistry.type_from_dict( {"type": "dict", "objectType": "number"} ) assert fully_typed.assign_type(partial_typed) @@ -179,24 +179,24 @@ def test_dict_without_key_type(): # def test_union_unknown(): # assert ( -# weave.legacy.weave_types.union( -# weave.legacy.weave_types.String(), weave.legacy.weave_types.UnknownType() +# weave.legacy.weave.weave_types.union( +# weave.legacy.weave.weave_types.String(), weave.legacy.weave.weave_types.UnknownType() # ) -# == weave.legacy.weave_types.String() +# == weave.legacy.weave.weave_types.String() # ) # assert ( -# weave.legacy.weave_types.union( -# weave.legacy.weave_types.UnknownType(), weave.legacy.weave_types.UnknownType() +# weave.legacy.weave.weave_types.union( +# weave.legacy.weave.weave_types.UnknownType(), weave.legacy.weave.weave_types.UnknownType() # ) -# == weave.legacy.weave_types.UnknownType() +# == weave.legacy.weave.weave_types.UnknownType() # ) # assert ( -# weave.legacy.weave_types.union( -# weave.legacy.weave_types.UnknownType(), -# weave.legacy.weave_types.UnknownType(), +# weave.legacy.weave.weave_types.union( +# weave.legacy.weave.weave_types.UnknownType(), +# weave.legacy.weave.weave_types.UnknownType(), # weave.types.String(), # ) -# == weave.legacy.weave_types.String() +# == weave.legacy.weave.weave_types.String() # ) @@ -204,78 +204,78 @@ def test_union_access(): ### Type return # Not all members have props - unioned = weave.legacy.weave_types.union( - weave.legacy.weave_types.String(), - weave.legacy.weave_types.List(weave.legacy.weave_types.String()), + unioned = weave.legacy.weave.weave_types.union( + weave.legacy.weave.weave_types.String(), + weave.legacy.weave.weave_types.List(weave.legacy.weave.weave_types.String()), ) with pytest.raises(AttributeError): unioned.object_type # Combined dicts - unioned = weave.legacy.weave_types.union( - weave.legacy.weave_types.List(weave.legacy.weave_types.String()), - weave.legacy.weave_types.List(weave.legacy.weave_types.Number()), + unioned = weave.legacy.weave.weave_types.union( + weave.legacy.weave.weave_types.List(weave.legacy.weave.weave_types.String()), + weave.legacy.weave.weave_types.List(weave.legacy.weave.weave_types.Number()), ) - assert unioned.object_type == weave.legacy.weave_types.union( - weave.legacy.weave_types.String(), weave.legacy.weave_types.Number() + assert unioned.object_type == weave.legacy.weave.weave_types.union( + weave.legacy.weave.weave_types.String(), weave.legacy.weave.weave_types.Number() ) # Nullable type - unioned = weave.legacy.weave_types.union( - weave.legacy.weave_types.NoneType(), - weave.legacy.weave_types.List(weave.legacy.weave_types.String()), + unioned = weave.legacy.weave.weave_types.union( + weave.legacy.weave.weave_types.NoneType(), + weave.legacy.weave.weave_types.List(weave.legacy.weave.weave_types.String()), ) - assert unioned.object_type == weave.legacy.weave_types.union( - weave.legacy.weave_types.String(), weave.legacy.weave_types.NoneType() + assert unioned.object_type == weave.legacy.weave.weave_types.union( + weave.legacy.weave.weave_types.String(), weave.legacy.weave.weave_types.NoneType() ) ### Dict Return # Not all members have props - unioned = weave.legacy.weave_types.union( - weave.legacy.weave_types.String(), - weave.legacy.weave_types.TypedDict({"a": weave.legacy.weave_types.String()}), + unioned = weave.legacy.weave.weave_types.union( + weave.legacy.weave.weave_types.String(), + weave.legacy.weave.weave_types.TypedDict({"a": weave.legacy.weave.weave_types.String()}), ) with pytest.raises(AttributeError): unioned.property_types # Combined dicts - unioned = weave.legacy.weave_types.union( - weave.legacy.weave_types.TypedDict( + unioned = weave.legacy.weave.weave_types.union( + weave.legacy.weave.weave_types.TypedDict( { - "same": weave.legacy.weave_types.Number(), - "solo_a": weave.legacy.weave_types.Number(), - "differ": weave.legacy.weave_types.Number(), + "same": weave.legacy.weave.weave_types.Number(), + "solo_a": weave.legacy.weave.weave_types.Number(), + "differ": weave.legacy.weave.weave_types.Number(), } ), - weave.legacy.weave_types.TypedDict( + weave.legacy.weave.weave_types.TypedDict( { - "same": weave.legacy.weave_types.Number(), - "solo_b": weave.legacy.weave_types.String(), - "differ": weave.legacy.weave_types.String(), + "same": weave.legacy.weave.weave_types.Number(), + "solo_b": weave.legacy.weave.weave_types.String(), + "differ": weave.legacy.weave.weave_types.String(), } ), ) assert unioned.property_types == { - "same": weave.legacy.weave_types.Number(), - "solo_a": weave.legacy.weave_types.union( - weave.legacy.weave_types.Number(), weave.legacy.weave_types.NoneType() + "same": weave.legacy.weave.weave_types.Number(), + "solo_a": weave.legacy.weave.weave_types.union( + weave.legacy.weave.weave_types.Number(), weave.legacy.weave.weave_types.NoneType() ), - "solo_b": weave.legacy.weave_types.union( - weave.legacy.weave_types.String(), weave.legacy.weave_types.NoneType() + "solo_b": weave.legacy.weave.weave_types.union( + weave.legacy.weave.weave_types.String(), weave.legacy.weave.weave_types.NoneType() ), - "differ": weave.legacy.weave_types.union( - weave.legacy.weave_types.Number(), weave.legacy.weave_types.String() + "differ": weave.legacy.weave.weave_types.union( + weave.legacy.weave.weave_types.Number(), weave.legacy.weave.weave_types.String() ), } # Nullable type - unioned = weave.legacy.weave_types.union( - weave.legacy.weave_types.NoneType(), - weave.legacy.weave_types.TypedDict({"a": weave.legacy.weave_types.String()}), + unioned = weave.legacy.weave.weave_types.union( + weave.legacy.weave.weave_types.NoneType(), + weave.legacy.weave.weave_types.TypedDict({"a": weave.legacy.weave.weave_types.String()}), ) assert unioned.property_types == { - "a": weave.legacy.weave_types.union( - weave.legacy.weave_types.String(), weave.legacy.weave_types.NoneType() + "a": weave.legacy.weave.weave_types.union( + weave.legacy.weave.weave_types.String(), weave.legacy.weave.weave_types.NoneType() ) } @@ -713,7 +713,7 @@ def test_deserializes_single_member_union(): def test_wbrun_not_assignable_to_weave_run(): - from weave.legacy.ops_domain import wb_domain_types + from weave.legacy.weave.ops_domain import wb_domain_types assert not weave.types.optional(wb_domain_types.Run().WeaveType()).assign_type( weave.types.RunType( diff --git a/weave/legacy/tests/test_weavejs_fixes.py b/weave/legacy/tests/test_weavejs_fixes.py index 94bc36039a8..9f6cf60b1f7 100644 --- a/weave/legacy/tests/test_weavejs_fixes.py +++ b/weave/legacy/tests/test_weavejs_fixes.py @@ -2,7 +2,7 @@ import pytest -from weave.legacy import ( +from weave.legacy.weave import ( api, context_state, mappers_python, @@ -10,7 +10,7 @@ weave_internal, weavejs_fixes, ) -from weave.legacy import weave_types as types +from weave.legacy.weave import weave_types as types @pytest.mark.skip( diff --git a/weave/legacy/tests/test_weavify.py b/weave/legacy/tests/test_weavify.py index d92fa838759..9335160bdac 100644 --- a/weave/legacy/tests/test_weavify.py +++ b/weave/legacy/tests/test_weavify.py @@ -1,9 +1,9 @@ import pytest -from weave.legacy import graph, ops, weave_internal -from weave.legacy import weave_types as types +from weave.legacy.weave import graph, ops, weave_internal +from weave.legacy.weave import weave_types as types -from ...legacy import weavify +from ...legacy.weave import weavify from weave.legacy.tests.util import geom diff --git a/weave/legacy/tests/test_with_columns.py b/weave/legacy/tests/test_with_columns.py index 1d7404471d1..e68b8e10435 100644 --- a/weave/legacy/tests/test_with_columns.py +++ b/weave/legacy/tests/test_with_columns.py @@ -1,5 +1,5 @@ import weave -from weave.legacy import ops_arrow +from weave.legacy.weave import ops_arrow def test_with_columns_basic(): diff --git a/weave/legacy/tests/util/concrete_tagged_value.py b/weave/legacy/tests/util/concrete_tagged_value.py index ff7d60442a0..403ab8fa21f 100644 --- a/weave/legacy/tests/util/concrete_tagged_value.py +++ b/weave/legacy/tests/util/concrete_tagged_value.py @@ -5,8 +5,8 @@ import dataclasses import typing -from weave.legacy import box -from weave.legacy.language_features.tagging import tag_store +from weave.legacy.weave import box +from weave.legacy.weave.language_features.tagging import tag_store @dataclasses.dataclass diff --git a/weave/legacy/tests/util/geom.py b/weave/legacy/tests/util/geom.py index 93653728cc5..46cbdb7e44e 100644 --- a/weave/legacy/tests/util/geom.py +++ b/weave/legacy/tests/util/geom.py @@ -3,8 +3,8 @@ import typing import weave -from weave.legacy import context_state as _context_state -from weave.legacy import panels +from weave.legacy.weave import context_state as _context_state +from weave.legacy.weave import panels _loading_builtins_token = _context_state.set_loading_built_ins() diff --git a/weave/legacy/tests/util/list_arrow_test_helpers.py b/weave/legacy/tests/util/list_arrow_test_helpers.py index ab7e19d8eb1..c130ba5cde0 100644 --- a/weave/legacy/tests/util/list_arrow_test_helpers.py +++ b/weave/legacy/tests/util/list_arrow_test_helpers.py @@ -1,6 +1,6 @@ -from weave.legacy import api as weave -from weave.legacy import ops_arrow as arrow -from weave.legacy.ops_primitives import list_ +from weave.legacy.weave import api as weave +from weave.legacy.weave import ops_arrow as arrow +from weave.legacy.weave.ops_primitives import list_ class ListLikeNodeInterface: diff --git a/weave/legacy/tests/util/op_specs.py b/weave/legacy/tests/util/op_specs.py index 5e586cdd983..9924f60754b 100644 --- a/weave/legacy/tests/util/op_specs.py +++ b/weave/legacy/tests/util/op_specs.py @@ -3,9 +3,9 @@ import typing import weave -from weave.legacy import op_def, ops_primitives -from weave.legacy.language_features.tagging import tagged_value_type -from weave.legacy.timestamp import PY_DATETIME_MAX_MS, PY_DATETIME_MIN_MS +from weave.legacy.weave import op_def, ops_primitives +from weave.legacy.weave.language_features.tagging import tagged_value_type +from weave.legacy.weave.timestamp import PY_DATETIME_MAX_MS, PY_DATETIME_MIN_MS from .concrete_tagged_value import TaggedValue diff --git a/weave/legacy/tests/util/tag_test_util.py b/weave/legacy/tests/util/tag_test_util.py index b83074d0d71..bfed6da0b88 100644 --- a/weave/legacy/tests/util/tag_test_util.py +++ b/weave/legacy/tests/util/tag_test_util.py @@ -1,9 +1,9 @@ import weave -from weave.legacy import box, graph -from weave.legacy import context_state as _context_state -from weave.legacy import weave_types as types -from weave.legacy.language_features.tagging import tag_store -from weave.legacy.language_features.tagging.tagged_value_type import TaggedValueType +from weave.legacy.weave import box, graph +from weave.legacy.weave import context_state as _context_state +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.language_features.tagging import tag_store +from weave.legacy.weave.language_features.tagging.tagged_value_type import TaggedValueType tag_adders = 0 @@ -34,6 +34,6 @@ def custom_tagger(obj): # type: ignore[no-untyped-def] def make_get_tag(tag_name: str): # type: ignore[no-untyped-def] - from weave.legacy.language_features.tagging import make_tag_getter_op + from weave.legacy.weave.language_features.tagging import make_tag_getter_op return make_tag_getter_op.make_tag_getter_op(f"_ct_{tag_name}", types.String()) diff --git a/weave/legacy/tests/util/weavejs_ops.py b/weave/legacy/tests/util/weavejs_ops.py index 82bceb9fba8..afaab26438b 100644 --- a/weave/legacy/tests/util/weavejs_ops.py +++ b/weave/legacy/tests/util/weavejs_ops.py @@ -1,10 +1,10 @@ # WeaveJS ops used for testing. These are not used in production. -from weave.legacy import graph, weave_internal -from weave.legacy import weave_types as types -from weave.legacy._dict_utils import typeddict_pick_output_type -from weave.legacy.language_features.tagging import tagged_value_type -from weave.legacy.language_features.tagging.tagging_op_logic import ( +from weave.legacy.weave import graph, weave_internal +from weave.legacy.weave import weave_types as types +from weave.legacy.weave._dict_utils import typeddict_pick_output_type +from weave.legacy.weave.language_features.tagging import tagged_value_type +from weave.legacy.weave.language_features.tagging.tagging_op_logic import ( op_get_tag_type_resolver, op_make_type_tagged_resolver, ) diff --git a/weave/legacy/arrow/__init__.py b/weave/legacy/weave/__init__.py similarity index 100% rename from weave/legacy/arrow/__init__.py rename to weave/legacy/weave/__init__.py diff --git a/weave/legacy/_dict_utils.py b/weave/legacy/weave/_dict_utils.py similarity index 97% rename from weave/legacy/_dict_utils.py rename to weave/legacy/weave/_dict_utils.py index 744b62474ff..4636d46037f 100644 --- a/weave/legacy/_dict_utils.py +++ b/weave/legacy/weave/_dict_utils.py @@ -1,10 +1,10 @@ import typing -from weave.legacy import box -from weave.legacy.language_features.tagging import tag_store, tagged_value_type +from weave.legacy.weave import box +from weave.legacy.weave.language_features.tagging import tag_store, tagged_value_type -from weave.legacy import errors -from weave.legacy import weave_types as types +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types def typeddict_pick_output_type(input_types): diff --git a/weave/legacy/api.py b/weave/legacy/weave/api.py similarity index 78% rename from weave/legacy/api.py rename to weave/legacy/weave/api.py index ba13f7e09f8..13d34e60760 100644 --- a/weave/legacy/api.py +++ b/weave/legacy/weave/api.py @@ -2,50 +2,50 @@ import typing -from weave.legacy import graph as _graph -from weave.legacy.graph import Node +from weave.legacy.weave import graph as _graph +from weave.legacy.weave.graph import Node # If this is not imported, serialization of Weave Nodes is incorrect! -from weave.legacy import graph_mapper as _graph_mapper +from weave.legacy.weave import graph_mapper as _graph_mapper -from .. import storage as _storage +from . import storage as _storage from . import ref_base as _ref_base -from weave.legacy import wandb_api as _wandb_api +from weave.legacy.weave import wandb_api as _wandb_api -from weave.legacy import weave_internal as _weave_internal +from weave.legacy.weave import weave_internal as _weave_internal -from weave.legacy import util as _util +from weave.legacy.weave import util as _util -from weave.legacy import context as _context -from ..trace import weave_init as _weave_init -from ..trace import weave_client as _weave_client +from weave.legacy.weave import context as _context +from ...trace import weave_init as _weave_init +from ...trace import weave_client as _weave_client # exposed as part of api -from weave.legacy import weave_types as types +from weave.legacy.weave import weave_types as types # needed to enable automatic numpy serialization from . import types_numpy as _types_numpy -from weave.legacy import errors -from weave.legacy.decorators import weave_class, mutation, type +from weave.legacy.weave import errors +from weave.legacy.weave.decorators import weave_class, mutation, type -from weave.legacy import usage_analytics -from weave.legacy.context import ( +from weave.legacy.weave import usage_analytics +from weave.legacy.weave.context import ( use_fixed_server_port, use_frontend_devmode, # eager_execution, use_lazy_execution, ) -from weave.legacy.panel import Panel +from weave.legacy.weave.panel import Panel -from weave.legacy.arrow.list_ import ArrowWeaveList as WeaveList +from weave.legacy.weave.arrow.list_ import ArrowWeaveList as WeaveList # TODO: This is here because the op overloaded... from weave.trace.op import op # noqa: F401 def save(node_or_obj, name=None): # type: ignore - from weave.legacy.ops_primitives.weave_api import get, save + from weave.legacy.weave.ops_primitives.weave_api import get, save if isinstance(node_or_obj, _graph.Node): return save(node_or_obj, name=name) diff --git a/weave/legacy/ecosystem/twitter/__init__.py b/weave/legacy/weave/arrow/__init__.py similarity index 100% rename from weave/legacy/ecosystem/twitter/__init__.py rename to weave/legacy/weave/arrow/__init__.py diff --git a/weave/legacy/arrow/arrow.py b/weave/legacy/weave/arrow/arrow.py similarity index 97% rename from weave/legacy/arrow/arrow.py rename to weave/legacy/weave/arrow/arrow.py index 0c5576eaa99..b6cc10e8790 100644 --- a/weave/legacy/arrow/arrow.py +++ b/weave/legacy/weave/arrow/arrow.py @@ -11,9 +11,9 @@ py_type = type -from weave.legacy import errors -from weave.legacy import weave_types as types -from weave.legacy import artifact_fs, partial_object +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import artifact_fs, partial_object def arrow_type_to_weave_type(pa_type: pa.DataType) -> types.Type: @@ -184,7 +184,7 @@ def save_instance(self, obj, artifact, name): ) # v1 AWL format - # from weave.legacy.arrow import convert + # from weave.legacy.weave.arrow import convert # parquet_friendly = convert.to_parquet_friendly(obj) # table = pa.table({"arr": parquet_friendly._arrow_data}) @@ -223,7 +223,7 @@ def load_instance( with artifact.open(f"{name}.ArrowWeaveList.type.json") as f: object_type = json.load(f) object_type = types.TypeRegistry.type_from_dict(object_type) - from weave.legacy.arrow import list_ + from weave.legacy.weave.arrow import list_ if "_weave_awl_format" not in artifact.metadata: # v1 AWL format @@ -232,7 +232,7 @@ def load_instance( arr = table["arr"].combine_chunks() with list_.unsafe_awl_construction("load_from_parquet"): l = self.instance_class(arr, object_type=object_type, artifact=artifact) # type: ignore - from weave.legacy.arrow import convert + from weave.legacy.weave.arrow import convert res = convert.from_parquet_friendly(l) elif artifact.metadata["_weave_awl_format"] == 2: @@ -366,7 +366,7 @@ def rewrite_weavelist_refs(arrow_data, object_type, source_artifact, target_arti def _object_type_has_props(object_type): - from weave.legacy.language_features.tagging import tagged_value_type + from weave.legacy.weave.language_features.tagging import tagged_value_type return ( isinstance(object_type, types.TypedDict) @@ -376,7 +376,7 @@ def _object_type_has_props(object_type): def _object_type_prop_types(object_type): - from weave.legacy.language_features.tagging import tagged_value_type + from weave.legacy.weave.language_features.tagging import tagged_value_type if isinstance(object_type, tagged_value_type.TaggedValueType): return { diff --git a/weave/legacy/arrow/arrow_tags.py b/weave/legacy/weave/arrow/arrow_tags.py similarity index 93% rename from weave/legacy/arrow/arrow_tags.py rename to weave/legacy/weave/arrow/arrow_tags.py index 52ba674abca..3fb27314a00 100644 --- a/weave/legacy/arrow/arrow_tags.py +++ b/weave/legacy/weave/arrow/arrow_tags.py @@ -3,10 +3,10 @@ import pyarrow as pa from pyarrow import compute as pc -from weave.legacy import weave_types as types -from weave.legacy.arrow import convert -from weave.legacy.arrow.arrow import offsets_starting_at_zero -from weave.legacy.language_features.tagging import ( +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.arrow import convert +from weave.legacy.weave.arrow.arrow import offsets_starting_at_zero +from weave.legacy.weave.language_features.tagging import ( process_opdef_output_type, tag_store, ) @@ -109,7 +109,7 @@ def awl_add_arrow_tags( new_object_type = process_opdef_output_type.op_make_type_tagged_resolver( l.object_type, tag_type ) - from weave.legacy.arrow.list_ import ArrowWeaveList + from weave.legacy.weave.arrow.list_ import ArrowWeaveList res: ArrowWeaveList = ArrowWeaveList(new_value, new_object_type, l._artifact) if tag_store.is_tagged(l): diff --git a/weave/legacy/arrow/concat.py b/weave/legacy/weave/arrow/concat.py similarity index 98% rename from weave/legacy/arrow/concat.py rename to weave/legacy/weave/arrow/concat.py index 46453d7de70..d383a9c09c9 100644 --- a/weave/legacy/arrow/concat.py +++ b/weave/legacy/weave/arrow/concat.py @@ -12,9 +12,9 @@ import pyarrow as pa from pyarrow import compute as pc -from weave.legacy import errors -from weave.legacy import weave_types as types -from weave.legacy.arrow.list_ import ( +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.arrow.list_ import ( ArrowWeaveList, ArrowWeaveListGeneric, is_list_arrowweavelist, @@ -26,11 +26,11 @@ offsets_starting_at_zero, unsafe_awl_construction, ) -from weave.legacy.language_features.tagging import tagged_value_type +from weave.legacy.weave.language_features.tagging import tagged_value_type DEBUG = False -from weave.legacy import engine_trace +from weave.legacy.weave import engine_trace tracer = engine_trace.tracer() diff --git a/weave/legacy/arrow/constructors.py b/weave/legacy/weave/arrow/constructors.py similarity index 90% rename from weave/legacy/arrow/constructors.py rename to weave/legacy/weave/arrow/constructors.py index 578643160c8..6beeb475d92 100644 --- a/weave/legacy/arrow/constructors.py +++ b/weave/legacy/weave/arrow/constructors.py @@ -3,13 +3,13 @@ import pyarrow as pa -from weave.legacy import errors -from weave.legacy import weave_types as types -from weave.legacy import artifact_base, box -from weave.legacy.arrow import arrow_tags, convert -from weave.legacy.arrow.arrow import ArrowWeaveListType, arrow_as_array -from weave.legacy.arrow.list_ import ArrowWeaveList -from weave.legacy.language_features.tagging import tag_store, tagged_value_type +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import artifact_base, box +from weave.legacy.weave.arrow import arrow_tags, convert +from weave.legacy.weave.arrow.arrow import ArrowWeaveListType, arrow_as_array +from weave.legacy.weave.arrow.list_ import ArrowWeaveList +from weave.legacy.weave.language_features.tagging import tag_store, tagged_value_type def repeat(value: typing.Any, count: int) -> pa.Array: diff --git a/weave/legacy/arrow/convert.py b/weave/legacy/weave/arrow/convert.py similarity index 98% rename from weave/legacy/arrow/convert.py rename to weave/legacy/weave/arrow/convert.py index 95c22eb4f3d..a53a610fd01 100644 --- a/weave/legacy/arrow/convert.py +++ b/weave/legacy/weave/arrow/convert.py @@ -3,19 +3,19 @@ import pyarrow as pa import pyarrow.compute as pc -from weave.legacy import api as api -from weave.legacy import weave_internal -from weave.legacy import weave_types as types -from weave.legacy import errors, arrow_util, artifact_base, artifact_mem, box, mappers_arrow -from weave.legacy.arrow.arrow import ( +from weave.legacy.weave import api as api +from weave.legacy.weave import weave_internal +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import errors, arrow_util, artifact_base, artifact_mem, box, mappers_arrow +from weave.legacy.weave.arrow.arrow import ( ArrowWeaveListType, ) -from weave.legacy.arrow.list_ import ( +from weave.legacy.weave.arrow.list_ import ( ArrowWeaveList, PathType, unsafe_awl_construction, ) -from weave.legacy.language_features.tagging import tag_store, tagged_value_type +from weave.legacy.weave.language_features.tagging import tag_store, tagged_value_type # Hmm... this doesn't work on ObjectType, which contains a Union of Struct... # We need that because our ImageFileArtifactRefType has a union of structs @@ -502,7 +502,7 @@ def simple_to_string(arr: pa.Array): def to_compare_safe(awl: ArrowWeaveList) -> ArrowWeaveList: """Converts any ArrowWeaveList to simple type that pa.compute.equal can compare.""" - from weave.legacy.ops_domain.wbmedia import ArtifactAssetType + from weave.legacy.weave.ops_domain.wbmedia import ArtifactAssetType # Returns a number of string arrow weave list, possibly with Nones def _to_compare_safe( diff --git a/weave/legacy/arrow/list_.py b/weave/legacy/weave/arrow/list_.py similarity index 98% rename from weave/legacy/arrow/list_.py rename to weave/legacy/weave/arrow/list_.py index f0855545fb5..6e3d0e85161 100644 --- a/weave/legacy/arrow/list_.py +++ b/weave/legacy/weave/arrow/list_.py @@ -10,8 +10,8 @@ import pyarrow.compute as pc import typing_extensions -from weave.legacy import weave_types as types -from weave.legacy import ( +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import ( weave_internal, errors, _dict_utils, @@ -25,7 +25,7 @@ node_ref, ref_base, ) -from weave.legacy.arrow.arrow import ( +from weave.legacy.weave.arrow.arrow import ( ArrowWeaveListType, arrow_as_array, arrow_zip, @@ -33,7 +33,7 @@ pretty_print_arrow_type, safe_is_null, ) -from weave.legacy.language_features.tagging import ( +from weave.legacy.weave.language_features.tagging import ( tag_store, tagged_value_type, ) @@ -494,7 +494,7 @@ def unsafe_awl_construction(reason: str): def dict_of_columns_to_awl(d: dict[str, typing.Any]) -> "ArrowWeaveList": - from weave.legacy.arrow import constructors + from weave.legacy.weave.arrow import constructors cols = {} for k, v in d.items(): @@ -522,7 +522,7 @@ def __init__( artifact: typing.Optional[artifact_base.Artifact] = None, invalid_reason=None, ) -> None: - from weave.legacy.arrow import constructors, convert + from weave.legacy.weave.arrow import constructors, convert # Do not dictionary decode this array! That will break performance. # Note we combine chunks here, to make the internal interface easy @@ -610,7 +610,7 @@ def __add__(self, other) -> "ArrowWeaveList": if not isinstance(other, ArrowWeaveList): raise TypeError(f"Expected list or ArrowWeaveList, got {type(other)}") - from weave.legacy.arrow import concat + from weave.legacy.weave.arrow import concat return concat.concatenate(self, other) @@ -901,7 +901,7 @@ def _map_column( type_codes, pa.scalar(i, pa.int8()), ) - from weave.legacy.arrow import concat + from weave.legacy.weave.arrow import concat members[i] = concat.concatenate(member_i, member_j) members[j] = None @@ -1499,12 +1499,12 @@ def apply( self, fn: typing.Union[typing.Callable[[typing.Any], typing.Any], graph.Node] ): fn = self._make_lambda_node(fn) - from weave.legacy.ops_arrow.vectorize import _apply_fn_node_with_tag_pushdown + from weave.legacy.weave.ops_arrow.vectorize import _apply_fn_node_with_tag_pushdown return _apply_fn_node_with_tag_pushdown(self, fn) # type: ignore def concat(self, other: "ArrowWeaveList") -> "ArrowWeaveList": - from weave.legacy.arrow import concat + from weave.legacy.weave.arrow import concat return concat.concatenate(self, other) @@ -1518,7 +1518,7 @@ def join2( leftOuter: bool = False, rightOuter: bool = False, ): - from weave.legacy.ops_arrow import list_join + from weave.legacy.weave.ops_arrow import list_join join1Fn = self._make_lambda_node(join1Fn) join2Fn = other._make_lambda_node(join2Fn) @@ -1666,7 +1666,7 @@ def make_vec_taggedvalue( def awl_zip(*arrs: ArrowWeaveList) -> ArrowWeaveList: if not arrs: raise ValueError("Cannot zip empty list") - from weave.legacy.arrow import convert + from weave.legacy.weave.arrow import convert arrs = convert.unify_types(*arrs) zipped = arrow_zip(*[a._arrow_data for a in arrs]) diff --git a/weave/legacy/arrow_util.py b/weave/legacy/weave/arrow_util.py similarity index 100% rename from weave/legacy/arrow_util.py rename to weave/legacy/weave/arrow_util.py diff --git a/weave/legacy/artifact_base.py b/weave/legacy/weave/artifact_base.py similarity index 95% rename from weave/legacy/artifact_base.py rename to weave/legacy/weave/artifact_base.py index ae98ed7bc84..3d1b56de86d 100644 --- a/weave/legacy/artifact_base.py +++ b/weave/legacy/weave/artifact_base.py @@ -7,8 +7,8 @@ import typing -from weave.legacy import weave_types as types -from weave.legacy import ref_base +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import ref_base class Artifact: diff --git a/weave/legacy/artifact_fs.py b/weave/legacy/weave/artifact_fs.py similarity index 97% rename from weave/legacy/artifact_fs.py rename to weave/legacy/weave/artifact_fs.py index 36ab31229a8..37cc0a3b5ae 100644 --- a/weave/legacy/artifact_fs.py +++ b/weave/legacy/weave/artifact_fs.py @@ -6,14 +6,14 @@ import os import typing -from weave.legacy import errors -from weave.legacy import weave_types as types -from weave.legacy import artifact_base, file_base, object_context, ref_base, uris -from weave.legacy.language_features.tagging import tag_store +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import artifact_base, file_base, object_context, ref_base, uris +from weave.legacy.weave.language_features.tagging import tag_store from weave.trace import ref_util if typing.TYPE_CHECKING: - from weave.legacy import graph + from weave.legacy.weave import graph class FilesystemArtifactType(types.Type): @@ -85,7 +85,7 @@ def get(self, key: str, type_: types.Type) -> typing.Any: return self.ref_from_local_str(key, type_).get() def as_node(self) -> "graph.Node": - from weave.legacy.ops_primitives.weave_api import get as op_get + from weave.legacy.weave.ops_primitives.weave_api import get as op_get return op_get(str(self)) @@ -267,7 +267,7 @@ def type(self) -> types.Type: ot = self._outer_type if self.extra is not None: - from weave.legacy import types_numpy + from weave.legacy.weave import types_numpy if not types.is_list_like(ot) and isinstance( ot, types_numpy.NumpyArrayType @@ -451,7 +451,7 @@ def size(self) -> int: return self.artifact.size(self.path) def digest(self) -> typing.Optional[str]: - from weave.legacy.artifact_wandb import WandbArtifact + from weave.legacy.weave.artifact_wandb import WandbArtifact if isinstance(self.artifact, WandbArtifact): # we can get the digest from the manifest (much faster) diff --git a/weave/legacy/artifact_local.py b/weave/legacy/weave/artifact_local.py similarity index 99% rename from weave/legacy/artifact_local.py rename to weave/legacy/weave/artifact_local.py index a22b6ea30e9..fc49c4c187e 100644 --- a/weave/legacy/artifact_local.py +++ b/weave/legacy/weave/artifact_local.py @@ -9,9 +9,9 @@ import typing from datetime import datetime -from weave.legacy import filesystem -from weave.legacy import weave_types as types -from weave.legacy import ( +from weave.legacy.weave import filesystem +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import ( artifact_fs, artifact_wandb, environment, diff --git a/weave/legacy/artifact_mem.py b/weave/legacy/weave/artifact_mem.py similarity index 90% rename from weave/legacy/artifact_mem.py rename to weave/legacy/weave/artifact_mem.py index 3e01f70ccb3..44fb3f9ff0e 100644 --- a/weave/legacy/artifact_mem.py +++ b/weave/legacy/weave/artifact_mem.py @@ -1,9 +1,9 @@ import typing from . import artifact_base -from weave.legacy import weave_types as types -from weave.legacy import errors -from weave.legacy import ref_base +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import errors +from weave.legacy.weave import ref_base class MemArtifact(artifact_base.Artifact): diff --git a/weave/legacy/artifact_wandb.py b/weave/legacy/weave/artifact_wandb.py similarity index 99% rename from weave/legacy/artifact_wandb.py rename to weave/legacy/weave/artifact_wandb.py index eff48f0519d..a19a33af7ef 100644 --- a/weave/legacy/artifact_wandb.py +++ b/weave/legacy/weave/artifact_wandb.py @@ -13,8 +13,8 @@ from wandb.apis.public import api as wb_public from wandb.sdk.lib.hashutil import b64_to_hex_id, hex_to_b64_id -from weave.legacy import weave_types as types -from weave.legacy import ( +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import ( filesystem, urls, errors, @@ -28,10 +28,10 @@ wandb_client_api, util, ) -from weave.legacy.wandb_interface import wandb_artifact_pusher +from weave.legacy.weave.wandb_interface import wandb_artifact_pusher if typing.TYPE_CHECKING: - from weave.legacy.wandb_interface.wandb_lite_run import InMemoryLazyLiteRun + from weave.legacy.weave.wandb_interface.wandb_lite_run import InMemoryLazyLiteRun from .run_streamtable_span import RunStreamTableSpan @@ -417,7 +417,7 @@ def __init__( ] ] = None, ): - from weave.legacy import io_service + from weave.legacy.weave import io_service self.io_service = io_service.get_sync_client() self.name = name @@ -857,7 +857,7 @@ def from_uri(cls, uri: uris.WeaveURI) -> "WandbArtifactRef": @property def ui_url(self): root_type = self.type.root_type_class() - from weave.legacy.op_def_type import OpDefType + from weave.legacy.weave.op_def_type import OpDefType if issubclass(root_type, OpDefType): return urls.op_version_path( diff --git a/weave/legacy/async_demo.py b/weave/legacy/weave/async_demo.py similarity index 97% rename from weave/legacy/async_demo.py rename to weave/legacy/weave/async_demo.py index 9dcd34bd5f3..1e1f7a3d28a 100644 --- a/weave/legacy/async_demo.py +++ b/weave/legacy/weave/async_demo.py @@ -3,7 +3,7 @@ import time import weave -from weave.legacy import context_state as _context_state +from weave.legacy.weave import context_state as _context_state _loading_builtins_token = _context_state.set_loading_built_ins() diff --git a/weave/legacy/async_map.py b/weave/legacy/weave/async_map.py similarity index 100% rename from weave/legacy/async_map.py rename to weave/legacy/weave/async_map.py diff --git a/weave/legacy/async_queue.py b/weave/legacy/weave/async_queue.py similarity index 100% rename from weave/legacy/async_queue.py rename to weave/legacy/weave/async_queue.py diff --git a/weave/legacy/box.py b/weave/legacy/weave/box.py similarity index 99% rename from weave/legacy/box.py rename to weave/legacy/weave/box.py index b957fc6ba3f..a16725af94a 100644 --- a/weave/legacy/box.py +++ b/weave/legacy/weave/box.py @@ -5,7 +5,7 @@ import numpy as np from weave.trace import ref_util -from weave.legacy import context_state +from weave.legacy.weave import context_state def make_id() -> int: diff --git a/weave/legacy/cache.py b/weave/legacy/weave/cache.py similarity index 98% rename from weave/legacy/cache.py rename to weave/legacy/weave/cache.py index bb254ca9473..5db00184bfa 100644 --- a/weave/legacy/cache.py +++ b/weave/legacy/weave/cache.py @@ -6,8 +6,8 @@ import time import typing -from weave.legacy import errors -from weave.legacy import context_state, environment, wandb_api, engine_trace +from weave.legacy.weave import errors +from weave.legacy.weave import context_state, environment, wandb_api, engine_trace statsd = engine_trace.statsd() # type: ignore logger = logging.getLogger("root") diff --git a/weave/legacy/client.py b/weave/legacy/weave/client.py similarity index 91% rename from weave/legacy/client.py rename to weave/legacy/weave/client.py index e1a3a32ce0c..9c10cd2f455 100644 --- a/weave/legacy/client.py +++ b/weave/legacy/weave/client.py @@ -1,5 +1,5 @@ -from weave.legacy import weave_types -from weave.legacy import storage +from weave.legacy.weave import weave_types +from weave.legacy.weave import storage class Client: diff --git a/weave/legacy/client_interface.py b/weave/legacy/weave/client_interface.py similarity index 100% rename from weave/legacy/client_interface.py rename to weave/legacy/weave/client_interface.py diff --git a/weave/legacy/codifiable_value_mixin.py b/weave/legacy/weave/codifiable_value_mixin.py similarity index 100% rename from weave/legacy/codifiable_value_mixin.py rename to weave/legacy/weave/codifiable_value_mixin.py diff --git a/weave/legacy/codify.py b/weave/legacy/weave/codify.py similarity index 91% rename from weave/legacy/codify.py rename to weave/legacy/weave/codify.py index ca1036dd826..0e6b5c273b6 100644 --- a/weave/legacy/codify.py +++ b/weave/legacy/weave/codify.py @@ -6,8 +6,8 @@ import black -from weave.legacy import weave_types -from weave.legacy import storage, graph, registry_mem +from weave.legacy.weave import weave_types +from weave.legacy.weave import storage, graph, registry_mem from . import codifiable_value_mixin @@ -97,7 +97,7 @@ def _try_otc_using_codifiable_mixin(obj: typing.Any) -> typing.Optional[str]: # assert weave_types.type_name_to_type(obj_type.name)() == obj_type # d = obj_type.instance_to_dict(obj) # obj_type_name = obj_type.name -# return f"""weave.legacy.codify.load_type({obj_type_name}, {d})""" +# return f"""weave.legacy.weave.codify.load_type({obj_type_name}, {d})""" # return None @@ -128,7 +128,7 @@ def _try_otc_using_dataclasses(obj: typing.Any) -> typing.Optional[str]: if class_type.__module__.startswith("weave.decorator_type") and issubclass( class_type, weave_types.Type ): - qualified_classpath = "weave.legacy.weave_types" + qualified_classpath = "weave.legacy.weave.weave_types" qualified_classname = f"type_name_to_type('{class_type.name}')" else: qualified_classpath = _module_name_corrections(class_type.__module__) @@ -162,7 +162,7 @@ def _try_otc_using_dataclasses(obj: typing.Any) -> typing.Optional[str]: def _otc_using_storage_fallback(obj: typing.Any) -> str: - return f"""weave.legacy.codify.load({storage.to_python(obj)})""" + return f"""weave.legacy.weave.codify.load({storage.to_python(obj)})""" # Helpers @@ -170,8 +170,8 @@ def _otc_using_storage_fallback(obj: typing.Any) -> str: # Hack: def _module_name_corrections(qualified_name: str) -> str: - if qualified_name == "weave.legacy.ops_primitives.file_local": - return "weave.legacy.ops" + if qualified_name == "weave.legacy.weave.ops_primitives.file_local": + return "weave.legacy.weave.ops" elif qualified_name.startswith("weave.decorator_class"): raise ValueError("Decorator classes are not supported.") elif qualified_name.startswith("weave.decorator_type"): @@ -201,7 +201,7 @@ def _node_to_code(node: graph.Node, wrap_const_node: bool = True) -> str: if current_frame is not None and node.name in current_frame: return node.name - return f"weave.legacy.weave_internal.make_var_node({_type_to_code(node.type)}, '{node.name}')" + return f"weave.legacy.weave.weave_internal.make_var_node({_type_to_code(node.type)}, '{node.name}')" elif isinstance(node, graph.ConstNode): if isinstance(node.type, weave_types.Function): vars = list(node.type.input_types.keys()) @@ -209,7 +209,7 @@ def _node_to_code(node: graph.Node, wrap_const_node: bool = True) -> str: else: val_as_code = object_to_code_no_format(node.val) if wrap_const_node: - return f"weave.legacy.weave_internal.const({val_as_code})" + return f"weave.legacy.weave.weave_internal.const({val_as_code})" else: return val_as_code elif isinstance(node, graph.OutputNode): @@ -226,7 +226,7 @@ def _node_to_code(node: graph.Node, wrap_const_node: bool = True) -> str: ) if len(node.from_op.inputs) > 0: args += "," - return f"weave.legacy.ops_primitives.dict.dict_({args})" + return f"weave.legacy.weave.ops_primitives.dict.dict_({args})" elif node.from_op.name == "list": args = ",".join( [ @@ -236,7 +236,7 @@ def _node_to_code(node: graph.Node, wrap_const_node: bool = True) -> str: ) if len(node.from_op.inputs) > 0: args += "," - return f"weave.legacy.ops_primitives.list_.make_list({args})" + return f"weave.legacy.weave.ops_primitives.list_.make_list({args})" is_root = len(inputs) == 0 or not isinstance( inputs[0], (graph.OutputNode, graph.VarNode) diff --git a/weave/legacy/compile.py b/weave/legacy/weave/compile.py similarity index 99% rename from weave/legacy/compile.py rename to weave/legacy/weave/compile.py index e55d66daf9b..318e980ee39 100644 --- a/weave/legacy/compile.py +++ b/weave/legacy/weave/compile.py @@ -5,8 +5,8 @@ import re import typing -from weave.legacy import weave_types as types -from weave.legacy import ( +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import ( weave_internal, errors, engine_trace, @@ -28,8 +28,8 @@ stitch, value_or_error, ) -from weave.legacy.language_features.tagging import tagged_value_type_helpers -from weave.legacy.op_def import OpDef +from weave.legacy.weave.language_features.tagging import tagged_value_type_helpers +from weave.legacy.weave.op_def import OpDef # These call_* functions must match the actual op implementations. # But we don't want to import the op definitions themselves here, since @@ -41,7 +41,7 @@ def _dispatch_error_is_client_error( op_name: str, input_types: dict[str, types.Type] ) -> bool: - from weave.legacy.ops_domain import wbmedia + from weave.legacy.weave.ops_domain import wbmedia if op_name in set( ( @@ -268,7 +268,7 @@ def _simple_optimizations(node: graph.Node) -> typing.Optional[graph.Node]: node.type, "ArrowWeaveListTypedDict-columnNames", {"self": awl_node} ) elif isinstance(node, graph.OutputNode) and node.from_op.name == "flatten": - from weave.legacy.arrow.arrow import ArrowWeaveListType + from weave.legacy.weave.arrow.arrow import ArrowWeaveListType from .ops_arrow.list_ops import _concat_output_type @@ -284,7 +284,7 @@ def _simple_optimizations(node: graph.Node) -> typing.Optional[graph.Node]: {"arr": arr_node}, ) elif isinstance(node, graph.OutputNode) and node.from_op.name == "concat": - from weave.legacy.arrow.arrow import ArrowWeaveListType + from weave.legacy.weave.arrow.arrow import ArrowWeaveListType from .ops_arrow.list_ops import flatten_return_type @@ -487,7 +487,7 @@ def compile_dedupe( nodes: dict[str, graph.Node] = {} def _dedupe(node: graph.Node) -> graph.Node: - from weave.legacy import serialize + from weave.legacy.weave import serialize node_id = serialize.node_id(node) if node_id in nodes: diff --git a/weave/legacy/compile_domain.py b/weave/legacy/weave/compile_domain.py similarity index 97% rename from weave/legacy/compile_domain.py rename to weave/legacy/weave/compile_domain.py index 65730e05ab3..fa002b254c3 100644 --- a/weave/legacy/compile_domain.py +++ b/weave/legacy/weave/compile_domain.py @@ -2,13 +2,13 @@ import graphql -from weave.legacy import errors -from weave.legacy import weave_types as types -from weave.legacy import gql_op_plugin, gql_to_weave, graph, op_args, stitch, registry_mem -from weave.legacy.input_provider import InputAndStitchProvider +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import gql_op_plugin, gql_to_weave, graph, op_args, stitch, registry_mem +from weave.legacy.weave.input_provider import InputAndStitchProvider if typing.TYPE_CHECKING: - from weave.legacy import op_def + from weave.legacy.weave import op_def def fragment_to_query(fragment: str) -> str: diff --git a/weave/legacy/compile_table.py b/weave/legacy/weave/compile_table.py similarity index 92% rename from weave/legacy/compile_table.py rename to weave/legacy/weave/compile_table.py index f0efcfc85ec..bbf9f868b49 100644 --- a/weave/legacy/compile_table.py +++ b/weave/legacy/weave/compile_table.py @@ -2,8 +2,8 @@ import typing -from weave.legacy import errors -from weave.legacy import stitch +from weave.legacy.weave import errors +from weave.legacy.weave import stitch KeyTree = typing.Dict[str, "KeyTree"] # type:ignore @@ -20,7 +20,7 @@ def tree_merge(a: KeyTree, b: KeyTree) -> None: def get_projection(obj: stitch.ObjectRecorder) -> KeyTree: """Given an object returned by stitch, return a tree of all accessed columns.""" - from weave.legacy import _dict_utils + from weave.legacy.weave import _dict_utils cols: KeyTree = {} all_keys = False diff --git a/weave/legacy/context.py b/weave/legacy/weave/context.py similarity index 88% rename from weave/legacy/context.py rename to weave/legacy/weave/context.py index ab01ec33727..c45c255f83b 100644 --- a/weave/legacy/context.py +++ b/weave/legacy/weave/context.py @@ -4,15 +4,15 @@ import typing from urllib.parse import urlparse -from weave.legacy import util -from weave.legacy import urls, client, context_state -from weave.legacy.client_interface import ClientInterface +from weave.legacy.weave import util +from weave.legacy.weave import urls, client, context_state +from weave.legacy.weave.client_interface import ClientInterface @contextlib.contextmanager def execution_client(): """Returns a client for use by the execution engine and op resolvers.""" - from weave.legacy import server + from weave.legacy.weave import server # Force in process execution with context_state.client(client.NonCachingClient(server.InProcessServer())): @@ -22,7 +22,7 @@ def execution_client(): @contextlib.contextmanager def local_http_client(): - from weave.legacy import server + from weave.legacy.weave import server s = server.HttpServer() s.start() @@ -34,7 +34,7 @@ def local_http_client(): @contextlib.contextmanager def weavejs_client(): - from weave.legacy import server + from weave.legacy.weave import server s = server.HttpServer() s.start() @@ -48,7 +48,7 @@ def use_fixed_server_port(): # s = server.HttpServer(port=9994) # s.start() # _weave_client.set(server.HttpServerClient(s.url)) - from weave.legacy import server + from weave.legacy.weave import server context_state.set_client(server.HttpServerClient("http://localhost:9994")) @@ -70,7 +70,7 @@ def use_lazy_execution(): def _make_default_client(): - from weave.legacy import server + from weave.legacy.weave import server if util.is_notebook(): serv = context_state.get_server() @@ -105,7 +105,7 @@ def get_client() -> typing.Optional[ClientInterface]: def get_frontend_url(): - from weave.legacy import server + from weave.legacy.weave import server url = os.environ.get("WEAVE_FRONTEND_URL", context_state.get_frontend_url()) if url is None: diff --git a/weave/legacy/context_state.py b/weave/legacy/weave/context_state.py similarity index 98% rename from weave/legacy/context_state.py rename to weave/legacy/weave/context_state.py index 15741b77987..4aef897ed5d 100644 --- a/weave/legacy/context_state.py +++ b/weave/legacy/weave/context_state.py @@ -3,11 +3,11 @@ import dataclasses import typing -from weave.legacy import server_interface +from weave.legacy.weave import server_interface if typing.TYPE_CHECKING: - from weave.legacy import client_interface, uris - from weave.legacy.graph_client import GraphClient + from weave.legacy.weave import client_interface, uris + from weave.legacy.weave.graph_client import GraphClient # colab currently runs ipykernel < 6.0. This resets context on every diff --git a/weave/legacy/weave/core_types/__init__.py b/weave/legacy/weave/core_types/__init__.py new file mode 100644 index 00000000000..0cee69ecdca --- /dev/null +++ b/weave/legacy/weave/core_types/__init__.py @@ -0,0 +1 @@ +from weave.legacy.weave.core_types.stream_table_type import StreamTableType diff --git a/weave/legacy/core_types/stream_table_type.py b/weave/legacy/weave/core_types/stream_table_type.py similarity index 78% rename from weave/legacy/core_types/stream_table_type.py rename to weave/legacy/weave/core_types/stream_table_type.py index c8c3eb7802b..40a2250511e 100644 --- a/weave/legacy/core_types/stream_table_type.py +++ b/weave/legacy/weave/core_types/stream_table_type.py @@ -1,4 +1,4 @@ -from weave.legacy import decorator_type +from weave.legacy.weave import decorator_type @decorator_type.type( diff --git a/weave/legacy/debug.py b/weave/legacy/weave/debug.py similarity index 100% rename from weave/legacy/debug.py rename to weave/legacy/weave/debug.py diff --git a/weave/legacy/debug_compile.py b/weave/legacy/weave/debug_compile.py similarity index 97% rename from weave/legacy/debug_compile.py rename to weave/legacy/weave/debug_compile.py index 1f3ebcf0024..c5d75e8ff77 100644 --- a/weave/legacy/debug_compile.py +++ b/weave/legacy/weave/debug_compile.py @@ -1,5 +1,5 @@ from weave import types -from weave.legacy import graph +from weave.legacy.weave import graph from . import debug_types diff --git a/weave/legacy/debug_types.py b/weave/legacy/weave/debug_types.py similarity index 97% rename from weave/legacy/debug_types.py rename to weave/legacy/weave/debug_types.py index c2a77b2c0cf..4449bfef71c 100644 --- a/weave/legacy/debug_types.py +++ b/weave/legacy/weave/debug_types.py @@ -1,7 +1,7 @@ import textwrap -from weave.legacy.language_features.tagging import tagged_value_type -from weave.legacy.weave_types import * +from weave.legacy.weave.language_features.tagging import tagged_value_type +from weave.legacy.weave.weave_types import * def short_type(type: Type) -> str: diff --git a/weave/legacy/decorator_arrow_op.py b/weave/legacy/weave/decorator_arrow_op.py similarity index 96% rename from weave/legacy/decorator_arrow_op.py rename to weave/legacy/weave/decorator_arrow_op.py index 51869d03760..0b9ba138c69 100644 --- a/weave/legacy/decorator_arrow_op.py +++ b/weave/legacy/weave/decorator_arrow_op.py @@ -1,9 +1,9 @@ import typing -from weave.legacy import weave_types as types -from weave.legacy import op_def -from weave.legacy.arrow.arrow import ArrowWeaveListType -from weave.legacy.language_features.tagging import tagged_value_type +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import op_def +from weave.legacy.weave.arrow.arrow import ArrowWeaveListType +from weave.legacy.weave.language_features.tagging import tagged_value_type from .decorator_op import op diff --git a/weave/legacy/decorator_class.py b/weave/legacy/weave/decorator_class.py similarity index 93% rename from weave/legacy/decorator_class.py rename to weave/legacy/weave/decorator_class.py index c2b2d5314d2..7f6d82f2728 100644 --- a/weave/legacy/decorator_class.py +++ b/weave/legacy/weave/decorator_class.py @@ -1,9 +1,9 @@ import inspect import typing -from weave.legacy import errors -from weave.legacy import weave_types as types -from weave.legacy import context_state, derive_op, op_def, registry_mem +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import context_state, derive_op, op_def, registry_mem # Contrary to the way it is read, the weave.class() decorator runs AFTER the # inner methods are defined. Therefore, this function runs after the ops are diff --git a/weave/legacy/decorator_mutation.py b/weave/legacy/weave/decorator_mutation.py similarity index 100% rename from weave/legacy/decorator_mutation.py rename to weave/legacy/weave/decorator_mutation.py diff --git a/weave/legacy/decorator_op.py b/weave/legacy/weave/decorator_op.py similarity index 93% rename from weave/legacy/decorator_op.py rename to weave/legacy/weave/decorator_op.py index d0081d8494a..e7a156614d6 100644 --- a/weave/legacy/decorator_op.py +++ b/weave/legacy/weave/decorator_op.py @@ -4,11 +4,11 @@ from typing_extensions import ParamSpec -from weave.legacy import weave_types as types -from weave.legacy import context_state, derive_op, op_args, op_def, pyfunc_type_util, registry_mem +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import context_state, derive_op, op_args, op_def, pyfunc_type_util, registry_mem if typing.TYPE_CHECKING: - from weave.legacy.gql_op_plugin import GqlOpPlugin + from weave.legacy.weave.gql_op_plugin import GqlOpPlugin # Important usability note @@ -104,7 +104,7 @@ def wrap(f: Callable[P, R]) -> Callable[P, R]: mutation=mutation, ) if weavify: - from weave.legacy.weavify import op_to_weave_fn + from weave.legacy.weave.weavify import op_to_weave_fn op.weave_fn = op_to_weave_fn(op) diff --git a/weave/legacy/decorator_type.py b/weave/legacy/weave/decorator_type.py similarity index 95% rename from weave/legacy/decorator_type.py rename to weave/legacy/weave/decorator_type.py index 2b761f2838f..1e437a30c2c 100644 --- a/weave/legacy/decorator_type.py +++ b/weave/legacy/weave/decorator_type.py @@ -2,9 +2,9 @@ import inspect import typing -from weave.legacy import errors -from weave.legacy import weave_types as types -from weave.legacy import context_state, decorator_class, object_type_ref_util, infer_types +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import context_state, decorator_class, object_type_ref_util, infer_types _py_type = type @@ -93,7 +93,7 @@ def wrap(target): # and deserialize them along with the data attached to the object if relocatable: for name, member in inspect.getmembers(target): - from weave.legacy import op_def, op_def_type + from weave.legacy.weave import op_def, op_def_type if isinstance(member, op_def.BoundOpDef): static_property_types[name] = op_def_type.OpDefType() diff --git a/weave/legacy/decorator_type.pyi b/weave/legacy/weave/decorator_type.pyi similarity index 100% rename from weave/legacy/decorator_type.pyi rename to weave/legacy/weave/decorator_type.pyi diff --git a/weave/legacy/decorators.py b/weave/legacy/weave/decorators.py similarity index 100% rename from weave/legacy/decorators.py rename to weave/legacy/weave/decorators.py diff --git a/weave/legacy/derive_op.py b/weave/legacy/weave/derive_op.py similarity index 98% rename from weave/legacy/derive_op.py rename to weave/legacy/weave/derive_op.py index 797d16af9fa..05de8dc9309 100644 --- a/weave/legacy/derive_op.py +++ b/weave/legacy/weave/derive_op.py @@ -6,8 +6,8 @@ import inspect import typing -from weave.legacy import weave_types as types -from weave.legacy import ( +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import ( storage, weave_internal, errors, @@ -21,7 +21,7 @@ op_def, op_policy, ) -from weave.legacy.language_features.tagging import tag_store +from weave.legacy.weave.language_features.tagging import tag_store USE_PARALLEL_DOWNLOAD = True USE_PARALLEL_REFINE = True @@ -195,7 +195,7 @@ def make_output_type(input_types): raise errors.WeaveMakeFunctionError( "output_type function must return a node." ) - from weave.legacy.ops_primitives.list_ import make_list + from weave.legacy.weave.ops_primitives.list_ import make_list return types.List.make( { diff --git a/weave/legacy/dispatch.py b/weave/legacy/weave/dispatch.py similarity index 98% rename from weave/legacy/dispatch.py rename to weave/legacy/weave/dispatch.py index 39baffd75a8..3017187613b 100644 --- a/weave/legacy/dispatch.py +++ b/weave/legacy/weave/dispatch.py @@ -5,11 +5,11 @@ import typing from dataclasses import dataclass -from weave.legacy import util -from weave.legacy import weave_types as types -from weave.legacy import graph, memo, op_args, op_def, pyfunc_type_util, registry_mem, errors -from weave.legacy.language_features.tagging.is_tag_getter import is_tag_getter -from weave.legacy.language_features.tagging.tagged_value_type import TaggedValueType +from weave.legacy.weave import util +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import graph, memo, op_args, op_def, pyfunc_type_util, registry_mem, errors +from weave.legacy.weave.language_features.tagging.is_tag_getter import is_tag_getter +from weave.legacy.weave.language_features.tagging.tagged_value_type import TaggedValueType # I originally wrote this thinking that we could always choose the more specific diff --git a/weave/legacy/eager.py b/weave/legacy/weave/eager.py similarity index 93% rename from weave/legacy/eager.py rename to weave/legacy/weave/eager.py index 7b1b1935ffc..393e23ad23f 100644 --- a/weave/legacy/eager.py +++ b/weave/legacy/weave/eager.py @@ -1,9 +1,9 @@ import typing -from weave.legacy import context_state, graph +from weave.legacy.weave import context_state, graph -from weave.legacy import weave_internal -from weave.legacy import weave_types as types +from weave.legacy.weave import weave_internal +from weave.legacy.weave import weave_types as types WeaveIterObjectType = typing.TypeVar("WeaveIterObjectType") @@ -81,7 +81,7 @@ def __iter__(self) -> typing.Iterator[WeaveIterObjectType]: def select_all(node: graph.Node) -> graph.Node: if not types.TypedDict().assign_type(node.type): raise ValueError("only TypedDict supported for now") - from weave.legacy.ops_primitives import dict_ + from weave.legacy.weave.ops_primitives import dict_ node_type = typing.cast(types.TypedDict, node.type) return dict_(**{k: node[k] for k in node_type.property_types}) # type: ignore diff --git a/weave/legacy/weave/ecosystem/__init__.py b/weave/legacy/weave/ecosystem/__init__.py new file mode 100644 index 00000000000..2ba3a1f0da9 --- /dev/null +++ b/weave/legacy/weave/ecosystem/__init__.py @@ -0,0 +1 @@ +from weave.legacy.weave.ecosystem.root import * diff --git a/weave/legacy/ecosystem/all.py b/weave/legacy/weave/ecosystem/all.py similarity index 90% rename from weave/legacy/ecosystem/all.py rename to weave/legacy/weave/ecosystem/all.py index 0fd564f8d46..e1e5c1d39f6 100644 --- a/weave/legacy/ecosystem/all.py +++ b/weave/legacy/weave/ecosystem/all.py @@ -4,7 +4,7 @@ import typing from collections import Counter, defaultdict -from weave.legacy import context_state +from weave.legacy.weave import context_state logger = logging.getLogger(__name__) @@ -38,11 +38,11 @@ LOAD_RESULTS: typing.DefaultDict[str, list[str]] = defaultdict(list[str]) try: - logger.info("Loading weave.legacy.ecosystem") + logger.info("Loading weave.legacy.weave.ecosystem") for module in ALL_MODULES: try: globals()[module] = importlib.import_module( - f"weave.legacy.ecosystem.{module}" + f"weave.legacy.weave.ecosystem.{module}" ) LOAD_RESULTS["loaded"].append(module) except ImportError as exc: diff --git a/weave/legacy/weave/ecosystem/bertviz/__init__.py b/weave/legacy/weave/ecosystem/bertviz/__init__.py new file mode 100644 index 00000000000..e220f65bfaf --- /dev/null +++ b/weave/legacy/weave/ecosystem/bertviz/__init__.py @@ -0,0 +1 @@ +from weave.legacy.weave.ecosystem.bertviz.panels import * diff --git a/weave/legacy/ecosystem/bertviz/panels.py b/weave/legacy/weave/ecosystem/bertviz/panels.py similarity index 83% rename from weave/legacy/ecosystem/bertviz/panels.py rename to weave/legacy/weave/ecosystem/bertviz/panels.py index d4b03c4bf76..36a6a63c0c9 100644 --- a/weave/legacy/ecosystem/bertviz/panels.py +++ b/weave/legacy/weave/ecosystem/bertviz/panels.py @@ -1,11 +1,11 @@ import bertviz import weave -from weave.legacy.ecosystem import huggingface +from weave.legacy.weave.ecosystem import huggingface @weave.op() -def head_view(attention: huggingface.ModelOutputAttention) -> weave.legacy.ops.Html: +def head_view(attention: huggingface.ModelOutputAttention) -> weave.legacy.weave.ops.Html: # All the information we need is attached to the ModelOutputAttention object. # This is important. In Weave, types should "stand alone", meaning they should # contain references to any information that is necessary for their use. @@ -27,7 +27,7 @@ def head_view(attention: huggingface.ModelOutputAttention) -> weave.legacy.ops.H # The .data attribute contains the html string. Wrap it in the weave Html type. # TODO: this would read better as weave.types.Html I think. - return weave.legacy.ops.Html(html.data) + return weave.legacy.weave.ops.Html(html.data) @weave.type() @@ -37,18 +37,18 @@ class BertvizHeadView(weave.Panel): input_node: weave.Node[huggingface.ModelOutputAttention] @weave.op() - def render(self) -> weave.legacy.panels.PanelHtml: + def render(self) -> weave.legacy.weave.panels.PanelHtml: # This is a lazy call! It doesn't execute anything html = head_view(self.input_node) # We add the lazy call as input to the returned Html panel. Nothing has been # computed so far. The UI's Html panel will perform a useNodeValue operation on its # input node. Only then will the head_view function finally be called. - return weave.legacy.panels.PanelHtml(html) + return weave.legacy.weave.panels.PanelHtml(html) @weave.op() -def model_view(attention: huggingface.ModelOutputAttention) -> weave.legacy.ops.Html: +def model_view(attention: huggingface.ModelOutputAttention) -> weave.legacy.weave.ops.Html: # Parallels head_view() to visualize the full matrix of attention heads as rows # and layers as columns for each attention map @@ -61,7 +61,7 @@ def model_view(attention: huggingface.ModelOutputAttention) -> weave.legacy.ops. html = bertviz.model_view(attention._attention, tokens, html_action="return") # TODO: this would read better as weave.types.Html I think. - return weave.legacy.ops.Html(html.data) + return weave.legacy.weave.ops.Html(html.data) @weave.type() @@ -71,6 +71,6 @@ class BertvizModelView(weave.Panel): input_node: weave.Node[huggingface.ModelOutputAttention] @weave.op() - def model_view_panel_render(self) -> weave.legacy.panels.PanelHtml: + def model_view_panel_render(self) -> weave.legacy.weave.panels.PanelHtml: html = model_view(self.input_node) - return weave.legacy.panels.PanelHtml(html) + return weave.legacy.weave.panels.PanelHtml(html) diff --git a/weave/legacy/weave/ecosystem/craiyon/__init__.py b/weave/legacy/weave/ecosystem/craiyon/__init__.py new file mode 100644 index 00000000000..dbcad02cfd5 --- /dev/null +++ b/weave/legacy/weave/ecosystem/craiyon/__init__.py @@ -0,0 +1 @@ +from weave.legacy.weave.ecosystem.craiyon.ops import * diff --git a/weave/legacy/ecosystem/craiyon/ops.py b/weave/legacy/weave/ecosystem/craiyon/ops.py similarity index 100% rename from weave/legacy/ecosystem/craiyon/ops.py rename to weave/legacy/weave/ecosystem/craiyon/ops.py diff --git a/weave/legacy/ecosystem/hdbscan/__init__.py b/weave/legacy/weave/ecosystem/example/__init__.py similarity index 73% rename from weave/legacy/ecosystem/hdbscan/__init__.py rename to weave/legacy/weave/ecosystem/example/__init__.py index 4481af6f01c..2ae52ad30e0 100644 --- a/weave/legacy/ecosystem/hdbscan/__init__.py +++ b/weave/legacy/weave/ecosystem/example/__init__.py @@ -2,13 +2,13 @@ import logging -from weave.legacy import context_state +from weave.legacy.weave import context_state logging.getLogger("ecosystem_example").setLevel(logging.ERROR) loading_builtins_token = context_state.set_loading_built_ins() try: - from weave.legacy.ecosystem.hdbscan.ops import * + from weave.legacy.weave.ecosystem.example import ops finally: context_state.clear_loading_built_ins(loading_builtins_token) diff --git a/weave/legacy/ecosystem/example/ops.py b/weave/legacy/weave/ecosystem/example/ops.py similarity index 100% rename from weave/legacy/ecosystem/example/ops.py rename to weave/legacy/weave/ecosystem/example/ops.py diff --git a/weave/legacy/ecosystem/umap/__init__.py b/weave/legacy/weave/ecosystem/hdbscan/__init__.py similarity index 73% rename from weave/legacy/ecosystem/umap/__init__.py rename to weave/legacy/weave/ecosystem/hdbscan/__init__.py index 820a584fa5a..62b6fee8188 100644 --- a/weave/legacy/ecosystem/umap/__init__.py +++ b/weave/legacy/weave/ecosystem/hdbscan/__init__.py @@ -2,13 +2,13 @@ import logging -from weave.legacy import context_state +from weave.legacy.weave import context_state logging.getLogger("ecosystem_example").setLevel(logging.ERROR) loading_builtins_token = context_state.set_loading_built_ins() try: - from weave.legacy.ecosystem.umap.ops import * + from weave.legacy.weave.ecosystem.hdbscan.ops import * finally: context_state.clear_loading_built_ins(loading_builtins_token) diff --git a/weave/legacy/ecosystem/hdbscan/ops.py b/weave/legacy/weave/ecosystem/hdbscan/ops.py similarity index 95% rename from weave/legacy/ecosystem/hdbscan/ops.py rename to weave/legacy/weave/ecosystem/hdbscan/ops.py index 5dd0ae5184b..e12213661a9 100644 --- a/weave/legacy/ecosystem/hdbscan/ops.py +++ b/weave/legacy/weave/ecosystem/hdbscan/ops.py @@ -10,7 +10,7 @@ ) import weave -from weave.legacy import ops_arrow +from weave.legacy.weave import ops_arrow class HDBSCANOptions(TypedDict): diff --git a/weave/legacy/weave/ecosystem/huggingface/__init__.py b/weave/legacy/weave/ecosystem/huggingface/__init__.py new file mode 100644 index 00000000000..8e6bc2c2ae7 --- /dev/null +++ b/weave/legacy/weave/ecosystem/huggingface/__init__.py @@ -0,0 +1,12 @@ +from weave.legacy.weave import context_state as _context + +_loading_builtins_token = _context.set_loading_built_ins() + +from weave.legacy.weave.ecosystem.huggingface.hfmodel import ModelOutputAttention +from weave.legacy.weave.ecosystem.huggingface.huggingface_datasets import * +from weave.legacy.weave.ecosystem.huggingface.huggingface_models import * +from weave.legacy.weave.ecosystem.huggingface.model_textclassification import ( + FullTextClassificationPipelineOutput, +) + +_context.clear_loading_built_ins(_loading_builtins_token) diff --git a/weave/legacy/ecosystem/huggingface/hfmodel.py b/weave/legacy/weave/ecosystem/huggingface/hfmodel.py similarity index 96% rename from weave/legacy/ecosystem/huggingface/hfmodel.py rename to weave/legacy/weave/ecosystem/huggingface/hfmodel.py index 65debd9f6e6..7a521299a8e 100644 --- a/weave/legacy/ecosystem/huggingface/hfmodel.py +++ b/weave/legacy/weave/ecosystem/huggingface/hfmodel.py @@ -7,8 +7,8 @@ import transformers import weave -from weave.legacy import op_def_type -from weave.legacy.ecosystem import pytorch +from weave.legacy.weave import op_def_type +from weave.legacy.weave.ecosystem import pytorch # This tells Weave how to serialize BaseModelOutput @@ -72,7 +72,7 @@ def tokenizer(self): return transformers.AutoTokenizer.from_pretrained(self._id) @weave.op() - def readme(self) -> weave.legacy.ops.Markdown: + def readme(self) -> weave.legacy.weave.ops.Markdown: readme = huggingface_hub.hf_hub_download(self._id, "README.md") # quick hack: remove the metadata header from the readme readme_contents = "" @@ -85,7 +85,7 @@ def readme(self) -> weave.legacy.ops.Markdown: # if we failed to parse out the header if len(readme_contents) < 1: readme_contents = open(readme).read() - return weave.legacy.ops.Markdown(readme_contents) + return weave.legacy.weave.ops.Markdown(readme_contents) @weave.op() def id(self) -> str: diff --git a/weave/legacy/ecosystem/huggingface/huggingface_datasets.py b/weave/legacy/weave/ecosystem/huggingface/huggingface_datasets.py similarity index 98% rename from weave/legacy/ecosystem/huggingface/huggingface_datasets.py rename to weave/legacy/weave/ecosystem/huggingface/huggingface_datasets.py index d47614eee07..f29bf154d78 100644 --- a/weave/legacy/ecosystem/huggingface/huggingface_datasets.py +++ b/weave/legacy/weave/ecosystem/huggingface/huggingface_datasets.py @@ -41,7 +41,7 @@ def hf_feature_type_to_type(type_): elif isinstance(type_, datasets.features.features.Sequence): return weave.types.List(hf_feature_type_to_type(type_.feature)) elif isinstance(type_, datasets.features.features.Image): - return weave.legacy.ops.PILImageType() + return weave.legacy.weave.ops.PILImageType() elif isinstance(type_, datasets.features.features.ClassLabel): # TODO: this should be a classes type!!!!! return weave.types.Int() diff --git a/weave/legacy/ecosystem/huggingface/huggingface_models.py b/weave/legacy/weave/ecosystem/huggingface/huggingface_models.py similarity index 78% rename from weave/legacy/ecosystem/huggingface/huggingface_models.py rename to weave/legacy/weave/ecosystem/huggingface/huggingface_models.py index f803fd446b9..8fa4865628b 100644 --- a/weave/legacy/ecosystem/huggingface/huggingface_models.py +++ b/weave/legacy/weave/ecosystem/huggingface/huggingface_models.py @@ -7,8 +7,8 @@ import transformers import weave -from weave.legacy.ecosystem import pytorch -from weave.legacy.ecosystem.huggingface import ( +from weave.legacy.weave.ecosystem import pytorch +from weave.legacy.weave.ecosystem.huggingface import ( hfmodel, model_textclassification, model_textgeneration, @@ -40,11 +40,11 @@ class HuggingfaceModelsPanel(weave.Panel): input_node: weave.Node[list[hfmodel.HFModel]] @weave.op() - def render(self) -> weave.legacy.panels.Table: - return weave.legacy.panels.Table( + def render(self) -> weave.legacy.weave.panels.Table: + return weave.legacy.weave.panels.Table( self.input_node, columns=[ - lambda model_row: weave.legacy.panels.WeaveLink( + lambda model_row: weave.legacy.weave.panels.WeaveLink( model_row.id(), to=lambda input: huggingface().model(input), # type: ignore ), @@ -64,24 +64,24 @@ class HuggingfaceModelPanel(weave.Panel): input_node: weave.Node[hfmodel.HFModel] @weave.op(pure=False) - def render(self) -> weave.legacy.panels.Card: + def render(self) -> weave.legacy.weave.panels.Card: model = typing.cast(hfmodel.HFModel, self.input_node) - return weave.legacy.panels.Card( + return weave.legacy.weave.panels.Card( title=model.id(), subtitle="HuggingFace Hub Model", content=[ - weave.legacy.panels.CardTab( + weave.legacy.weave.panels.CardTab( name="Model Card", - content=weave.legacy.panels.PanelMarkdown(model.readme()), # type: ignore + content=weave.legacy.weave.panels.PanelMarkdown(model.readme()), # type: ignore ), - weave.legacy.panels.CardTab( + weave.legacy.weave.panels.CardTab( name="Metadata", - content=weave.legacy.panels.Group( + content=weave.legacy.weave.panels.Group( items={ - "id": weave.legacy.panels.LabeledItem( + "id": weave.legacy.weave.panels.LabeledItem( item=model.id(), label="ID" ), - "pipeline_tag": weave.legacy.panels.LabeledItem( + "pipeline_tag": weave.legacy.weave.panels.LabeledItem( item=model.pipeline_tag(), label="Pipeline tag" ), } @@ -89,10 +89,10 @@ def render(self) -> weave.legacy.panels.Card: ), # Broke in panel refactor. Don't have concrete op name available here so # can't get the right type for the output. - # weave.legacy.panels.CardTab( + # weave.legacy.weave.panels.CardTab( # name="Inference Logs", - # content=weave.legacy.panels.Table( - # weave.legacy.ops.used_by(model, model.call.op_name()), + # content=weave.legacy.weave.panels.Table( + # weave.legacy.weave.ops.used_by(model, model.call.op_name()), # columns=[ # lambda run: run.output.model_input, # lambda run: run.output.model_output[0]["generated_text"], @@ -141,12 +141,12 @@ class HuggingfacePackagePanel(weave.Panel): input_node: weave.Node[HuggingFacePackage] @weave.op() - def render(self) -> weave.legacy.panels.Card: + def render(self) -> weave.legacy.weave.panels.Card: pack = typing.cast(HuggingFacePackage, self.input_node) # type: ignore - return weave.legacy.panels.Card( + return weave.legacy.weave.panels.Card( title="Huggingface Package", subtitle="Browse Models and Datasets", content=[ - weave.legacy.panels.CardTab(name="Models", content=pack.models()), # type: ignore + weave.legacy.weave.panels.CardTab(name="Models", content=pack.models()), # type: ignore ], ) diff --git a/weave/legacy/ecosystem/huggingface/model_textclassification.py b/weave/legacy/weave/ecosystem/huggingface/model_textclassification.py similarity index 89% rename from weave/legacy/ecosystem/huggingface/model_textclassification.py rename to weave/legacy/weave/ecosystem/huggingface/model_textclassification.py index 40a7a496109..4101b36849e 100644 --- a/weave/legacy/ecosystem/huggingface/model_textclassification.py +++ b/weave/legacy/weave/ecosystem/huggingface/model_textclassification.py @@ -4,7 +4,7 @@ import transformers import weave -from weave.legacy.ecosystem.huggingface import hfmodel +from weave.legacy.weave.ecosystem.huggingface import hfmodel # We have to forward-declare the Weave types to avoid circular reference # issues that weave.type() can't resolve yet. @@ -70,13 +70,13 @@ class ClassificationResultPanel(weave.Panel): input_node: weave.Node[list[ClassificationResult]] @weave.op() - def render(self) -> weave.legacy.panels.Table: - from weave.legacy.ecosystem.huggingface.huggingface_models import huggingface + def render(self) -> weave.legacy.weave.panels.Table: + from weave.legacy.weave.ecosystem.huggingface.huggingface_models import huggingface - return weave.legacy.panels.Table( + return weave.legacy.weave.panels.Table( self.input_node, columns=[ - lambda result_row: weave.legacy.panels.WeaveLink( + lambda result_row: weave.legacy.weave.panels.WeaveLink( result_row.model_name(), to=lambda input: huggingface().model(input), # type: ignore ), @@ -115,17 +115,17 @@ class FullTextClassificationResultPanel(weave.Panel): input_node: weave.Node[FullTextClassificationPipelineOutput] @weave.op() - def render(self) -> weave.legacy.panels.Group: + def render(self) -> weave.legacy.weave.panels.Group: output = typing.cast(FullTextClassificationPipelineOutput, self.input_node) - return weave.legacy.panels.Group( + return weave.legacy.weave.panels.Group( preferHorizontal=True, items={ - "input": weave.legacy.panels.LabeledItem( + "input": weave.legacy.weave.panels.LabeledItem( label="input", item=output.model_input ), - "output": weave.legacy.panels.LabeledItem( + "output": weave.legacy.weave.panels.LabeledItem( label="output", - item=weave.legacy.panels.Plot( + item=weave.legacy.weave.panels.Plot( input_node=typing.cast(weave.Node, output.model_output), x=lambda class_score: class_score["score"], y=lambda class_score: class_score["label"], diff --git a/weave/legacy/ecosystem/huggingface/model_textgeneration.py b/weave/legacy/weave/ecosystem/huggingface/model_textgeneration.py similarity index 91% rename from weave/legacy/ecosystem/huggingface/model_textgeneration.py rename to weave/legacy/weave/ecosystem/huggingface/model_textgeneration.py index edbaa739cf2..a422e88f1c2 100644 --- a/weave/legacy/ecosystem/huggingface/model_textgeneration.py +++ b/weave/legacy/weave/ecosystem/huggingface/model_textgeneration.py @@ -4,7 +4,7 @@ import transformers import weave -from weave.legacy.ecosystem.huggingface import hfmodel +from weave.legacy.weave.ecosystem.huggingface import hfmodel # We have to forward-declare the Weave types to avoid circular reference # issues that weave.type() can't resolve yet. @@ -50,15 +50,15 @@ class FullTextGenerationPanel(weave.Panel): input_node: weave.Node[FullTextGenerationPipelineOutput] @weave.op() - def render(self) -> weave.legacy.panels.Group: + def render(self) -> weave.legacy.weave.panels.Group: output = typing.cast(FullTextGenerationPipelineOutput, self.input_node) - return weave.legacy.panels.Group( + return weave.legacy.weave.panels.Group( preferHorizontal=True, items={ - "input": weave.legacy.panels.LabeledItem( + "input": weave.legacy.weave.panels.LabeledItem( label="input", item=output.model_input ), - "output": weave.legacy.panels.LabeledItem( + "output": weave.legacy.weave.panels.LabeledItem( label="output", item=output.model_output ), }, diff --git a/weave/legacy/ecosystem/spacy/__init__.py b/weave/legacy/weave/ecosystem/keras/__init__.py similarity index 51% rename from weave/legacy/ecosystem/spacy/__init__.py rename to weave/legacy/weave/ecosystem/keras/__init__.py index c0b0f5af429..c27c01c5e63 100644 --- a/weave/legacy/ecosystem/spacy/__init__.py +++ b/weave/legacy/weave/ecosystem/keras/__init__.py @@ -1,7 +1,6 @@ -from weave.legacy import context_state as _context +from weave.legacy.weave import context_state as _context _loading_builtins_token = _context.set_loading_built_ins() - -from weave.legacy.ecosystem.spacy.spacy import * +from weave.legacy.weave.ecosystem.keras.model import * _context.clear_loading_built_ins(_loading_builtins_token) diff --git a/weave/legacy/ecosystem/keras/model.py b/weave/legacy/weave/ecosystem/keras/model.py similarity index 100% rename from weave/legacy/ecosystem/keras/model.py rename to weave/legacy/weave/ecosystem/keras/model.py diff --git a/weave/legacy/ecosystem/langchain/__init__.py b/weave/legacy/weave/ecosystem/langchain/__init__.py similarity index 67% rename from weave/legacy/ecosystem/langchain/__init__.py rename to weave/legacy/weave/ecosystem/langchain/__init__.py index 49a02f9cac1..104095d21f5 100644 --- a/weave/legacy/ecosystem/langchain/__init__.py +++ b/weave/legacy/weave/ecosystem/langchain/__init__.py @@ -1,12 +1,12 @@ import logging -from weave.legacy import context_state +from weave.legacy.weave import context_state logging.getLogger("langchain").setLevel(logging.ERROR) loading_builtins_token = context_state.set_loading_built_ins() try: - from weave.legacy.ecosystem.langchain.lc import * + from weave.legacy.weave.ecosystem.langchain.lc import * finally: context_state.clear_loading_built_ins(loading_builtins_token) diff --git a/weave/legacy/ecosystem/langchain/lc.py b/weave/legacy/weave/ecosystem/langchain/lc.py similarity index 98% rename from weave/legacy/ecosystem/langchain/lc.py rename to weave/legacy/weave/ecosystem/langchain/lc.py index 46fd02f6a65..51fc011c7fb 100644 --- a/weave/legacy/ecosystem/langchain/lc.py +++ b/weave/legacy/weave/ecosystem/langchain/lc.py @@ -41,12 +41,12 @@ from langchain.vectorstores.base import VectorStoreRetriever import weave -from weave.legacy import storage -from weave.legacy import artifact_base -from weave.legacy.artifact_fs import FilesystemArtifact -from weave.legacy.ecosystem.langchain import util -from weave.legacy.ops_domain import trace_tree -from weave.legacy.weave_types import Type +from weave.legacy.weave import storage +from weave.legacy.weave import artifact_base +from weave.legacy.weave.artifact_fs import FilesystemArtifact +from weave.legacy.weave.ecosystem.langchain import util +from weave.legacy.weave.ops_domain import trace_tree +from weave.legacy.weave.weave_types import Type class WeaveTracer(BaseTracer): diff --git a/weave/legacy/ecosystem/langchain/util.py b/weave/legacy/weave/ecosystem/langchain/util.py similarity index 99% rename from weave/legacy/ecosystem/langchain/util.py rename to weave/legacy/weave/ecosystem/langchain/util.py index 4341c64995f..b25b592f398 100644 --- a/weave/legacy/ecosystem/langchain/util.py +++ b/weave/legacy/weave/ecosystem/langchain/util.py @@ -13,7 +13,7 @@ from langchain.callbacks.tracers.schemas import Run, RunTypeEnum -from weave.legacy.ops_domain import trace_tree +from weave.legacy.weave.ops_domain import trace_tree if TYPE_CHECKING: from langchain.chains.base import Chain diff --git a/weave/legacy/weave/ecosystem/lens/__init__.py b/weave/legacy/weave/ecosystem/lens/__init__.py new file mode 100644 index 00000000000..4c04886f8c2 --- /dev/null +++ b/weave/legacy/weave/ecosystem/lens/__init__.py @@ -0,0 +1 @@ +from weave.legacy.weave.ecosystem.lens.lens import * diff --git a/weave/legacy/ecosystem/lens/lens.py b/weave/legacy/weave/ecosystem/lens/lens.py similarity index 100% rename from weave/legacy/ecosystem/lens/lens.py rename to weave/legacy/weave/ecosystem/lens/lens.py diff --git a/weave/legacy/weave/ecosystem/py/__init__.py b/weave/legacy/weave/ecosystem/py/__init__.py new file mode 100644 index 00000000000..e535e18a474 --- /dev/null +++ b/weave/legacy/weave/ecosystem/py/__init__.py @@ -0,0 +1 @@ +from weave.legacy.weave.ecosystem.py import pydoc diff --git a/weave/legacy/ecosystem/py/pydoc.py b/weave/legacy/weave/ecosystem/py/pydoc.py similarity index 76% rename from weave/legacy/ecosystem/py/pydoc.py rename to weave/legacy/weave/ecosystem/py/pydoc.py index 946b877cb60..e558f42a5e5 100644 --- a/weave/legacy/ecosystem/py/pydoc.py +++ b/weave/legacy/weave/ecosystem/py/pydoc.py @@ -51,8 +51,8 @@ def module_name(module: types.ModuleType) -> str: @weave.op() -def module_doc(module: types.ModuleType) -> weave.legacy.ops.Markdown: - return weave.legacy.ops.Markdown(module.__doc__ or "") +def module_doc(module: types.ModuleType) -> weave.legacy.weave.ops.Markdown: + return weave.legacy.weave.ops.Markdown(module.__doc__ or "") @weave.op() @@ -93,8 +93,8 @@ def pyclass_module(pyclass: type) -> types.ModuleType: @weave.op() -def pyclass_doc(pyclass: type) -> weave.legacy.ops.Markdown: - return weave.legacy.ops.Markdown(pyclass.__doc__ or "") +def pyclass_doc(pyclass: type) -> weave.legacy.weave.ops.Markdown: + return weave.legacy.weave.ops.Markdown(pyclass.__doc__ or "") @weave.op() @@ -126,8 +126,8 @@ def function_name(pyfunction: types.FunctionType) -> str: @weave.op() -def function_doc(pyfunction: types.FunctionType) -> weave.legacy.ops.Markdown: - return weave.legacy.ops.Markdown(pyfunction.__doc__ or "") +def function_doc(pyfunction: types.FunctionType) -> weave.legacy.weave.ops.Markdown: + return weave.legacy.weave.ops.Markdown(pyfunction.__doc__ or "") @weave.type() @@ -136,34 +136,34 @@ class ModulePanel(weave.Panel): input_node: weave.Node[types.ModuleType] @weave.op() - def render(self) -> weave.legacy.panels.Card: + def render(self) -> weave.legacy.weave.panels.Card: module = self.input_node - return weave.legacy.panels.Card( + return weave.legacy.weave.panels.Card( title=module.module_name(), # type: ignore subtitle="python module", content=[ - weave.legacy.panels.CardTab( + weave.legacy.weave.panels.CardTab( name="Description", - content=weave.legacy.panels.PanelMarkdown(module.module_doc()), # type: ignore + content=weave.legacy.weave.panels.PanelMarkdown(module.module_doc()), # type: ignore ), - weave.legacy.panels.CardTab( + weave.legacy.weave.panels.CardTab( name="Classes", - content=weave.legacy.panels.Table( + content=weave.legacy.weave.panels.Table( module.module_classes(), # type: ignore columns=[ - lambda c: weave.legacy.panels.WeaveLink( + lambda c: weave.legacy.weave.panels.WeaveLink( c.class_name(), to=lambda inp: module.module_class(inp), # type: ignore ) ], ), ), - weave.legacy.panels.CardTab( + weave.legacy.weave.panels.CardTab( name="Functions", - content=weave.legacy.panels.Table( + content=weave.legacy.weave.panels.Table( module.module_functions(), # type: ignore columns=[ - lambda c: weave.legacy.panels.WeaveLink( + lambda c: weave.legacy.weave.panels.WeaveLink( c.function_name(), to=lambda inp: module.module_function(inp), # type: ignore ) @@ -180,22 +180,22 @@ class ClassPanel(weave.Panel): input_node: weave.Node[type] @weave.op() - def render(self) -> weave.legacy.panels.Card: + def render(self) -> weave.legacy.weave.panels.Card: cls = self.input_node - return weave.legacy.panels.Card( + return weave.legacy.weave.panels.Card( title=cls.class_name(), # type: ignore subtitle="python class", content=[ - weave.legacy.panels.CardTab( + weave.legacy.weave.panels.CardTab( name="Description", - content=weave.legacy.panels.PanelMarkdown(cls.pyclass_doc()), # type: ignore + content=weave.legacy.weave.panels.PanelMarkdown(cls.pyclass_doc()), # type: ignore ), - weave.legacy.panels.CardTab( + weave.legacy.weave.panels.CardTab( name="Methods", - content=weave.legacy.panels.Table( + content=weave.legacy.weave.panels.Table( cls.class_methods(), # type: ignore columns=[ - lambda m: weave.legacy.panels.WeaveLink( + lambda m: weave.legacy.weave.panels.WeaveLink( m.function_name(), to=lambda inp: cls.class_method(inp), # type: ignore ) @@ -212,15 +212,15 @@ class FunctionPanel(weave.Panel): input_node: weave.Node[types.FunctionType] @weave.op() - def render(self) -> weave.legacy.panels.Card: + def render(self) -> weave.legacy.weave.panels.Card: func = self.input_node - return weave.legacy.panels.Card( + return weave.legacy.weave.panels.Card( title=func.function_name(), # type: ignore subtitle="python function", content=[ - weave.legacy.panels.CardTab( + weave.legacy.weave.panels.CardTab( name="Description", - content=weave.legacy.panels.PanelMarkdown(func.function_doc()), # type: ignore + content=weave.legacy.weave.panels.PanelMarkdown(func.function_doc()), # type: ignore ), ], ) diff --git a/weave/legacy/weave/ecosystem/pytorch/__init__.py b/weave/legacy/weave/ecosystem/pytorch/__init__.py new file mode 100644 index 00000000000..3b5a12f7690 --- /dev/null +++ b/weave/legacy/weave/ecosystem/pytorch/__init__.py @@ -0,0 +1 @@ +from weave.legacy.weave.ecosystem.pytorch.model import * diff --git a/weave/legacy/ecosystem/pytorch/model.py b/weave/legacy/weave/ecosystem/pytorch/model.py similarity index 100% rename from weave/legacy/ecosystem/pytorch/model.py rename to weave/legacy/weave/ecosystem/pytorch/model.py diff --git a/weave/legacy/ecosystem/replicate/__init__.py b/weave/legacy/weave/ecosystem/replicate/__init__.py similarity index 57% rename from weave/legacy/ecosystem/replicate/__init__.py rename to weave/legacy/weave/ecosystem/replicate/__init__.py index e859a88c467..f957e5b171a 100644 --- a/weave/legacy/ecosystem/replicate/__init__.py +++ b/weave/legacy/weave/ecosystem/replicate/__init__.py @@ -1,8 +1,8 @@ -from weave.legacy import context_state +from weave.legacy.weave import context_state loading_builtins_token = context_state.set_loading_built_ins() try: - from weave.legacy.ecosystem.replicate.rep import * + from weave.legacy.weave.ecosystem.replicate.rep import * finally: context_state.clear_loading_built_ins(loading_builtins_token) diff --git a/weave/legacy/ecosystem/replicate/rep.py b/weave/legacy/weave/ecosystem/replicate/rep.py similarity index 100% rename from weave/legacy/ecosystem/replicate/rep.py rename to weave/legacy/weave/ecosystem/replicate/rep.py diff --git a/weave/legacy/ecosystem/root.py b/weave/legacy/weave/ecosystem/root.py similarity index 96% rename from weave/legacy/ecosystem/root.py rename to weave/legacy/weave/ecosystem/root.py index 6e67b1e8413..38fac4b03d4 100644 --- a/weave/legacy/ecosystem/root.py +++ b/weave/legacy/weave/ecosystem/root.py @@ -1,9 +1,9 @@ import typing -from weave.legacy import api as weave +from weave.legacy.weave import api as weave # TODO: Fix, these should be available from weave -from weave.legacy import context_state, op_def, ops, panel, panels +from weave.legacy.weave import context_state, op_def, ops, panel, panels loading_builtins_token = context_state.set_loading_built_ins() @@ -22,7 +22,7 @@ """ ) -from weave.legacy import registry_mem +from weave.legacy.weave import registry_mem op_org_name = registry_mem.memory_registry.get_op("user-name") @@ -63,7 +63,7 @@ def ops(self) -> list[op_def.OpDef]: # objects. @weave.op(name="op-ecosystem", render_info={"type": "function"}) def ecosystem() -> Ecosystem: - from weave.legacy import registry_mem + from weave.legacy.weave import registry_mem return Ecosystem( _orgs=[], diff --git a/weave/legacy/ecosystem/scenario/__init__.py b/weave/legacy/weave/ecosystem/scenario/__init__.py similarity index 79% rename from weave/legacy/ecosystem/scenario/__init__.py rename to weave/legacy/weave/ecosystem/scenario/__init__.py index f011e37a728..d747eae19c6 100644 --- a/weave/legacy/ecosystem/scenario/__init__.py +++ b/weave/legacy/weave/ecosystem/scenario/__init__.py @@ -1,8 +1,8 @@ import typing import weave -import weave.legacy -from weave.legacy import val_const +import weave.legacy.weave +from weave.legacy.weave import val_const class ScenarioResult(typing.TypedDict): @@ -26,14 +26,14 @@ class MetricsBankPanel(weave.Panel): input_node: weave.Node[MetricsBankInput] @weave.op() - def render(self) -> weave.legacy.panels.Each: + def render(self) -> weave.legacy.weave.panels.Each: input = typing.cast(MetricsBankInput, self.input_node) baseline = input["baseline"] candidate = input["candidate"] - joined = weave.legacy.ops.join_all( - weave.legacy.ops.make_list(l0=baseline, l1=candidate), + joined = weave.legacy.weave.ops.join_all( + weave.legacy.weave.ops.make_list(l0=baseline, l1=candidate), lambda row: row["scenario_id"], False, ) @@ -42,17 +42,17 @@ def render(self) -> weave.legacy.panels.Each: joined_keys = joined[0].keys() # The output type of difference is List["metric1" | "metric2" | "metric3"] - metrics = weave.legacy.ops.difference( + metrics = weave.legacy.weave.ops.difference( joined_keys, [val_const.const("scenario_id")] ) # TODO: broken - return weave.legacy.panels.Each( + return weave.legacy.weave.panels.Each( metrics, - render=lambda metric_name: weave.legacy.panels.Group( + render=lambda metric_name: weave.legacy.weave.panels.Group( items={ "title": metric_name, - "plot": weave.legacy.panels.Plot( + "plot": weave.legacy.weave.panels.Plot( joined, # TODO: bring this back # title=metric_name, diff --git a/weave/legacy/ecosystem/shap/__init__.py b/weave/legacy/weave/ecosystem/shap/__init__.py similarity index 52% rename from weave/legacy/ecosystem/shap/__init__.py rename to weave/legacy/weave/ecosystem/shap/__init__.py index 02c6c8b5027..a22de778e34 100644 --- a/weave/legacy/ecosystem/shap/__init__.py +++ b/weave/legacy/weave/ecosystem/shap/__init__.py @@ -1,7 +1,7 @@ -from weave.legacy import context_state as _context +from weave.legacy.weave import context_state as _context _loading_builtins_token = _context.set_loading_built_ins() -from weave.legacy.ecosystem.shap.shap import * +from weave.legacy.weave.ecosystem.shap.shap import * _context.clear_loading_built_ins(_loading_builtins_token) diff --git a/weave/legacy/ecosystem/shap/shap.py b/weave/legacy/weave/ecosystem/shap/shap.py similarity index 85% rename from weave/legacy/ecosystem/shap/shap.py rename to weave/legacy/weave/ecosystem/shap/shap.py index 8e364d32f61..812fcaaf918 100644 --- a/weave/legacy/ecosystem/shap/shap.py +++ b/weave/legacy/weave/ecosystem/shap/shap.py @@ -13,8 +13,8 @@ import xgboost import weave -from weave.legacy.ecosystem import huggingface as hf -from weave.legacy.ecosystem import xgboost as weave_xgb +from weave.legacy.weave.ecosystem import huggingface as hf +from weave.legacy.weave.ecosystem import xgboost as weave_xgb @weave.op( @@ -42,7 +42,7 @@ def summary_plot(self): path = "/tmp/shap-%s.png" % random.randrange(0, 1000000) plt.savefig(path) plt.close() - return weave.legacy.ops.LocalFile(path) + return weave.legacy.weave.ops.LocalFile(path) class ShapExplanationType(weave.types.Type): @@ -76,9 +76,9 @@ def shap_explain( @weave.op() -def shap_plot_text(shap_values: shap.Explanation) -> weave.legacy.ops.Html: +def shap_plot_text(shap_values: shap.Explanation) -> weave.legacy.weave.ops.Html: html = shap.plots.text(shap_values, display=False) - return weave.legacy.ops.Html(html) + return weave.legacy.weave.ops.Html(html) @weave.type() @@ -87,5 +87,5 @@ class ShapPlotText(weave.Panel): input_node: weave.Node[shap.Explanation] @weave.op() - def render(self) -> weave.legacy.panels.PanelHtml: - return weave.legacy.panels.PanelHtml(shap_plot_text(self.input_node)) + def render(self) -> weave.legacy.weave.panels.PanelHtml: + return weave.legacy.weave.panels.PanelHtml(shap_plot_text(self.input_node)) diff --git a/weave/legacy/weave/ecosystem/shawn/__init__.py b/weave/legacy/weave/ecosystem/shawn/__init__.py new file mode 100644 index 00000000000..53e96633366 --- /dev/null +++ b/weave/legacy/weave/ecosystem/shawn/__init__.py @@ -0,0 +1,7 @@ +from weave.legacy.weave import context_state as _context + +_loading_builtins_token = _context.set_loading_built_ins() + +from weave.legacy.weave.ecosystem.shawn import petdataset, scratch + +_context.clear_loading_built_ins(_loading_builtins_token) diff --git a/weave/legacy/ecosystem/shawn/petdataset.py b/weave/legacy/weave/ecosystem/shawn/petdataset.py similarity index 96% rename from weave/legacy/ecosystem/shawn/petdataset.py rename to weave/legacy/weave/ecosystem/shawn/petdataset.py index fc7becf7e53..9c5b85b66fb 100644 --- a/weave/legacy/ecosystem/shawn/petdataset.py +++ b/weave/legacy/weave/ecosystem/shawn/petdataset.py @@ -71,8 +71,8 @@ class PetDatasetPanel(weave.Panel): input_node: weave.Node[list[OxfordIIITPetDatasetItem]] @weave.op() - def render(self) -> weave.legacy.panels.Table: - return weave.legacy.panels.Table( + def render(self) -> weave.legacy.weave.panels.Table: + return weave.legacy.weave.panels.Table( self.input_node, columns=[ lambda item: item["id"], diff --git a/weave/legacy/ecosystem/shawn/scratch.py b/weave/legacy/weave/ecosystem/shawn/scratch.py similarity index 69% rename from weave/legacy/ecosystem/shawn/scratch.py rename to weave/legacy/weave/ecosystem/shawn/scratch.py index a200e6ff6b2..01614229fa4 100644 --- a/weave/legacy/ecosystem/shawn/scratch.py +++ b/weave/legacy/weave/ecosystem/shawn/scratch.py @@ -2,17 +2,17 @@ import typing import weave -from weave.legacy import panel, panel_util +from weave.legacy.weave import panel, panel_util @weave.op() def single_distribution( input_node: weave.Node[list[float]], -) -> weave.legacy.panels.Plot: +) -> weave.legacy.weave.panels.Plot: binned = input_node.groupby(lambda v: round(v * 10) / 10).map( # type: ignore - lambda group: weave.legacy.ops.dict_(value=group.key(), count=group.count()) + lambda group: weave.legacy.weave.ops.dict_(value=group.key(), count=group.count()) ) - return weave.legacy.panels.Plot( + return weave.legacy.weave.panels.Plot( binned, x=lambda row: row["value"], y=lambda row: row["count"], @@ -23,7 +23,7 @@ def single_distribution( @weave.type() class AdderConfig: operand: weave.Node[int] = dataclasses.field( - default_factory=lambda: weave.legacy.graph.ConstNode(weave.types.Int(), 10) + default_factory=lambda: weave.legacy.weave.graph.ConstNode(weave.types.Int(), 10) ) @@ -42,14 +42,14 @@ def adder_default_config(config: typing.Optional[AdderConfig]) -> AdderConfig: @weave.op() def adder_config( input_node: weave.Node[int], config: AdderConfig -) -> weave.legacy.panels.LabeledItem: +) -> weave.legacy.weave.panels.LabeledItem: input_val = typing.cast(int, input_node) config = adder_default_config(config) - return weave.legacy.panels.LabeledItem( + return weave.legacy.weave.panels.LabeledItem( label="operand", - item=weave.legacy.panels.Slider( - config=weave.legacy.panels.SliderConfig( - weave.legacy.ops.execute(config.operand) + item=weave.legacy.weave.panels.Slider( + config=weave.legacy.weave.panels.SliderConfig( + weave.legacy.weave.ops.execute(config.operand) ) ), ) @@ -58,10 +58,10 @@ def adder_config( @weave.op() def adder( input_node: weave.Node[int], config: AdderConfig -) -> weave.legacy.panels.LabeledItem: +) -> weave.legacy.weave.panels.LabeledItem: input_val = typing.cast(int, input_node) config = adder_default_config(config) - return weave.legacy.panels.LabeledItem(label="output", item=input_val + config.operand) # type: ignore + return weave.legacy.weave.panels.LabeledItem(label="output", item=input_val + config.operand) # type: ignore @weave.type() diff --git a/weave/legacy/weave/ecosystem/sklearn/__init__.py b/weave/legacy/weave/ecosystem/sklearn/__init__.py new file mode 100644 index 00000000000..08e6e889266 --- /dev/null +++ b/weave/legacy/weave/ecosystem/sklearn/__init__.py @@ -0,0 +1 @@ +from weave.legacy.weave.ecosystem.sklearn.datasets import * diff --git a/weave/legacy/ecosystem/sklearn/datasets.py b/weave/legacy/weave/ecosystem/sklearn/datasets.py similarity index 81% rename from weave/legacy/ecosystem/sklearn/datasets.py rename to weave/legacy/weave/ecosystem/sklearn/datasets.py index 0683b58cde1..6c5dc9e3d25 100644 --- a/weave/legacy/ecosystem/sklearn/datasets.py +++ b/weave/legacy/weave/ecosystem/sklearn/datasets.py @@ -7,7 +7,7 @@ @weave.op( name="shap-ca_housing_dataset", render_info={"type": "function"}, - output_type=weave.legacy.ops.DataFrameType(weave.types.TypedDict({})), + output_type=weave.legacy.weave.ops.DataFrameType(weave.types.TypedDict({})), ) def ca_housing_dataset(seed: int): housing = fetch_california_housing(as_frame=True) diff --git a/weave/legacy/weave/ecosystem/slack/__init__.py b/weave/legacy/weave/ecosystem/slack/__init__.py new file mode 100644 index 00000000000..a5018fce230 --- /dev/null +++ b/weave/legacy/weave/ecosystem/slack/__init__.py @@ -0,0 +1,2 @@ +from weave.legacy.weave.ecosystem.slack.panels import * +from weave.legacy.weave.ecosystem.slack.slack import * diff --git a/weave/legacy/ecosystem/slack/panels.py b/weave/legacy/weave/ecosystem/slack/panels.py similarity index 73% rename from weave/legacy/ecosystem/slack/panels.py rename to weave/legacy/weave/ecosystem/slack/panels.py index 679159a381c..41f2ee60014 100644 --- a/weave/legacy/ecosystem/slack/panels.py +++ b/weave/legacy/weave/ecosystem/slack/panels.py @@ -1,7 +1,7 @@ import typing import weave -from weave.legacy.ecosystem.slack import slack +from weave.legacy.weave.ecosystem.slack import slack @weave.type() @@ -10,9 +10,9 @@ class SlackMessagesPanel(weave.Panel): input_node: weave.Node[list[slack.Message]] @weave.op() - def render(self) -> weave.legacy.panels.Table: + def render(self) -> weave.legacy.weave.panels.Table: messages = typing.cast(list[slack.Message], self.input_node) # type: ignore - return weave.legacy.panels.Table( + return weave.legacy.weave.panels.Table( messages, columns=[ lambda message: message.user_id, @@ -27,8 +27,8 @@ class SlackChannelsPanel(weave.Panel): input_node: weave.Node[list[slack.Channel]] @weave.op() - def render(self) -> weave.legacy.panels.Table: - return weave.legacy.panels.Table( + def render(self) -> weave.legacy.weave.panels.Table: + return weave.legacy.weave.panels.Table( self.input_node, columns=[ lambda channel: channel.channel_name, @@ -43,13 +43,13 @@ class SlackChannelPanel(weave.Panel): input_node: weave.Node[slack.Channel] @weave.op() - def render(self) -> weave.legacy.panels.Card: + def render(self) -> weave.legacy.weave.panels.Card: channel = typing.cast(slack.Channel, self.input_node) # type: ignore - return weave.legacy.panels.Card( + return weave.legacy.weave.panels.Card( title=channel.channel_name, subtitle="Slack channel", content=[ - weave.legacy.panels.CardTab( + weave.legacy.weave.panels.CardTab( name="Messages", content=SlackMessagesPanel(channel.messages()) ), ], @@ -62,13 +62,13 @@ class SlackPanel(weave.Panel): input_node: weave.Node[slack.Slack] @weave.op() - def slack_render(self) -> weave.legacy.panels.Card: + def slack_render(self) -> weave.legacy.weave.panels.Card: s = typing.cast(slack.Slack, self.input_node) # type: ignore - return weave.legacy.panels.Card( + return weave.legacy.weave.panels.Card( title="Slack export data", subtitle="", content=[ - weave.legacy.panels.CardTab( + weave.legacy.weave.panels.CardTab( name="Channels", content=SlackChannelsPanel(s.channels()) ), ], diff --git a/weave/legacy/ecosystem/slack/slack.py b/weave/legacy/weave/ecosystem/slack/slack.py similarity index 97% rename from weave/legacy/ecosystem/slack/slack.py rename to weave/legacy/weave/ecosystem/slack/slack.py index fb960284021..f542dfeb021 100644 --- a/weave/legacy/ecosystem/slack/slack.py +++ b/weave/legacy/weave/ecosystem/slack/slack.py @@ -1,6 +1,6 @@ import weave from weave.file_base import Dir -from weave.legacy.ecosystem.slack import slackapi_readexport +from weave.legacy.weave.ecosystem.slack import slackapi_readexport @weave.type() diff --git a/weave/legacy/ecosystem/slack/slackapi.py b/weave/legacy/weave/ecosystem/slack/slackapi.py similarity index 100% rename from weave/legacy/ecosystem/slack/slackapi.py rename to weave/legacy/weave/ecosystem/slack/slackapi.py diff --git a/weave/legacy/ecosystem/slack/slackapi_readexport.py b/weave/legacy/weave/ecosystem/slack/slackapi_readexport.py similarity index 100% rename from weave/legacy/ecosystem/slack/slackapi_readexport.py rename to weave/legacy/weave/ecosystem/slack/slackapi_readexport.py diff --git a/weave/legacy/weave/ecosystem/slurm/__init__.py b/weave/legacy/weave/ecosystem/slurm/__init__.py new file mode 100644 index 00000000000..e9bd4eae0cd --- /dev/null +++ b/weave/legacy/weave/ecosystem/slurm/__init__.py @@ -0,0 +1 @@ +from weave.legacy.weave.ecosystem.slurm.ops import * diff --git a/weave/legacy/ecosystem/slurm/ops.py b/weave/legacy/weave/ecosystem/slurm/ops.py similarity index 79% rename from weave/legacy/ecosystem/slurm/ops.py rename to weave/legacy/weave/ecosystem/slurm/ops.py index 9611df88d73..4bd811a348f 100644 --- a/weave/legacy/ecosystem/slurm/ops.py +++ b/weave/legacy/weave/ecosystem/slurm/ops.py @@ -19,8 +19,8 @@ class SlurmJob: @weave.op() def jobs_render( jobs: weave.Node[list[SlurmJob]], -) -> weave.legacy.panels.Table: - return weave.legacy.panels.Table( +) -> weave.legacy.weave.panels.Table: + return weave.legacy.weave.panels.Table( jobs, columns=[ lambda job: job.job_id, @@ -43,8 +43,8 @@ class SlurmNode: @weave.op() def nodes_render( nodes: weave.Node[list[SlurmNode]], -) -> weave.legacy.panels.Table: - return weave.legacy.panels.Table( +) -> weave.legacy.weave.panels.Table: + return weave.legacy.weave.panels.Table( nodes, columns=[ lambda node: node.node_name, @@ -96,27 +96,27 @@ def slurm(restapi_url: str) -> Slurm: @weave.op() def slurm_render( slurm_node: weave.Node[Slurm], -) -> weave.legacy.panels.Card: +) -> weave.legacy.weave.panels.Card: slurm = typing.cast(Slurm, slurm_node) - return weave.legacy.panels.Card( + return weave.legacy.weave.panels.Card( title="slurm", subtitle="", content=[ - weave.legacy.panels.CardTab( + weave.legacy.weave.panels.CardTab( name="Overview", - content=weave.legacy.panels.Group( + content=weave.legacy.weave.panels.Group( prefer_horizontal=True, items=[ - weave.legacy.panels.LabeledItem( + weave.legacy.weave.panels.LabeledItem( item=slurm.jobs().count(), label="Total jobs" ), - weave.legacy.panels.LabeledItem( + weave.legacy.weave.panels.LabeledItem( item=slurm.nodes().count(), label="Total nodes" ), ], ), ), - weave.legacy.panels.CardTab(name="Nodes", content=slurm.nodes()), - weave.legacy.panels.CardTab(name="Jobs", content=slurm.jobs()), + weave.legacy.weave.panels.CardTab(name="Nodes", content=slurm.nodes()), + weave.legacy.weave.panels.CardTab(name="Jobs", content=slurm.jobs()), ], ) diff --git a/weave/legacy/ecosystem/shawn/__init__.py b/weave/legacy/weave/ecosystem/spacy/__init__.py similarity index 51% rename from weave/legacy/ecosystem/shawn/__init__.py rename to weave/legacy/weave/ecosystem/spacy/__init__.py index 6c2526057a3..b0e2199ab0e 100644 --- a/weave/legacy/ecosystem/shawn/__init__.py +++ b/weave/legacy/weave/ecosystem/spacy/__init__.py @@ -1,7 +1,7 @@ -from weave.legacy import context_state as _context +from weave.legacy.weave import context_state as _context _loading_builtins_token = _context.set_loading_built_ins() -from weave.legacy.ecosystem.shawn import petdataset, scratch +from weave.legacy.weave.ecosystem.spacy.spacy import * _context.clear_loading_built_ins(_loading_builtins_token) diff --git a/weave/legacy/ecosystem/spacy/spacy.py b/weave/legacy/weave/ecosystem/spacy/spacy.py similarity index 72% rename from weave/legacy/ecosystem/spacy/spacy.py rename to weave/legacy/weave/ecosystem/spacy/spacy.py index 9dd9823a385..03f5b0fea5e 100644 --- a/weave/legacy/ecosystem/spacy/spacy.py +++ b/weave/legacy/weave/ecosystem/spacy/spacy.py @@ -31,23 +31,23 @@ def spacy(text: str) -> spacy_lib.tokens.doc.Doc: @weave.op() def spacy_doc_dep_to_html( spacy_doc: spacy_lib.tokens.doc.Doc, -) -> weave.legacy.ops.Html: +) -> weave.legacy.weave.ops.Html: from spacy import displacy html = displacy.render( list(spacy_doc.sents), style="dep", jupyter=False, options={"compact": True} ) - return weave.legacy.ops.Html(html) + return weave.legacy.weave.ops.Html(html) @weave.op() def spacy_doc_ent_to_html( spacy_doc: spacy_lib.tokens.doc.Doc, -) -> weave.legacy.ops.Html: +) -> weave.legacy.weave.ops.Html: from spacy import displacy html = displacy.render(spacy_doc, style="ent", jupyter=False) - return weave.legacy.ops.Html(html) + return weave.legacy.weave.ops.Html(html) @weave.type() @@ -56,18 +56,18 @@ class SpacyDocPanel(weave.Panel): input_node: weave.Node[spacy_lib.tokens.doc.Doc] @weave.op() - def render(self) -> weave.legacy.panels.Card: - return weave.legacy.panels.Card( + def render(self) -> weave.legacy.weave.panels.Card: + return weave.legacy.weave.panels.Card( title="Spacy Visualization", subtitle="", content=[ - weave.legacy.panels.CardTab( + weave.legacy.weave.panels.CardTab( name="Dependencies", - content=weave.legacy.panels.PanelHtml(spacy_doc_dep_to_html(self.input_node)), # type: ignore + content=weave.legacy.weave.panels.PanelHtml(spacy_doc_dep_to_html(self.input_node)), # type: ignore ), - weave.legacy.panels.CardTab( + weave.legacy.weave.panels.CardTab( name="Named Entities", - content=weave.legacy.panels.PanelHtml(spacy_doc_ent_to_html(self.input_node)), # type: ignore + content=weave.legacy.weave.panels.PanelHtml(spacy_doc_ent_to_html(self.input_node)), # type: ignore ), ], ) diff --git a/weave/legacy/ecosystem/test_notebook_ecosystem_executions.py b/weave/legacy/weave/ecosystem/test_notebook_ecosystem_executions.py similarity index 98% rename from weave/legacy/ecosystem/test_notebook_ecosystem_executions.py rename to weave/legacy/weave/ecosystem/test_notebook_ecosystem_executions.py index 9d4e9bbfebb..95817ef76f9 100644 --- a/weave/legacy/ecosystem/test_notebook_ecosystem_executions.py +++ b/weave/legacy/weave/ecosystem/test_notebook_ecosystem_executions.py @@ -1,8 +1,8 @@ -from weave.legacy.server import handle_request +from weave.legacy.weave.server import handle_request def test_playback(): - from weave.legacy import ecosystem + from weave.legacy.weave import ecosystem for payload in [execute_payloads[-1]]: res = handle_request(payload, True) diff --git a/weave/legacy/ecosystem/torch_mnist_model_example.py b/weave/legacy/weave/ecosystem/torch_mnist_model_example.py similarity index 93% rename from weave/legacy/ecosystem/torch_mnist_model_example.py rename to weave/legacy/weave/ecosystem/torch_mnist_model_example.py index ab09c6fc70f..8ce668a1ab8 100644 --- a/weave/legacy/ecosystem/torch_mnist_model_example.py +++ b/weave/legacy/weave/ecosystem/torch_mnist_model_example.py @@ -7,8 +7,8 @@ from torchvision import transforms import weave -from weave.legacy import context_state as _context -from weave.legacy.ecosystem import pytorch +from weave.legacy.weave import context_state as _context +from weave.legacy.weave.ecosystem import pytorch DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu") @@ -54,7 +54,7 @@ class Model: output_type=weave.types.List( weave.types.TypedDict( { - "X": weave.legacy.ops.image.PILImageType(), # type: ignore + "X": weave.legacy.weave.ops.image.PILImageType(), # type: ignore "y": weave.types.Int(), } ) @@ -131,7 +131,7 @@ def train_epoch(network, loader, optimizer): @weave.op( render_info={"type": "function"}, input_type={ - "X": weave.types.List(weave.legacy.ops.image.PILImageType()), # type: ignore + "X": weave.types.List(weave.legacy.weave.ops.image.PILImageType()), # type: ignore "y": weave.types.List(weave.types.Int()), # TODO: class enum? }, # TODO: WeaveJS doesn't support callable output type yet. diff --git a/weave/legacy/weave/ecosystem/torchvision/__init__.py b/weave/legacy/weave/ecosystem/torchvision/__init__.py new file mode 100644 index 00000000000..b003b9b82da --- /dev/null +++ b/weave/legacy/weave/ecosystem/torchvision/__init__.py @@ -0,0 +1 @@ +from weave.legacy.weave.ecosystem.torchvision.datasets import * diff --git a/weave/legacy/ecosystem/torchvision/datasets.py b/weave/legacy/weave/ecosystem/torchvision/datasets.py similarity index 98% rename from weave/legacy/ecosystem/torchvision/datasets.py rename to weave/legacy/weave/ecosystem/torchvision/datasets.py index 46f74273f75..b62e5c9a126 100644 --- a/weave/legacy/ecosystem/torchvision/datasets.py +++ b/weave/legacy/weave/ecosystem/torchvision/datasets.py @@ -11,8 +11,8 @@ from torchvision import datasets import weave -from weave.legacy import infer_types -from weave.legacy import panels +from weave.legacy.weave import infer_types +from weave.legacy.weave import panels ExampleType = TypeVar("ExampleType") diff --git a/weave/legacy/language_features/__init__.py b/weave/legacy/weave/ecosystem/twitter/__init__.py similarity index 100% rename from weave/legacy/language_features/__init__.py rename to weave/legacy/weave/ecosystem/twitter/__init__.py diff --git a/weave/legacy/ecosystem/twitter/tweet.py b/weave/legacy/weave/ecosystem/twitter/tweet.py similarity index 100% rename from weave/legacy/ecosystem/twitter/tweet.py rename to weave/legacy/weave/ecosystem/twitter/tweet.py diff --git a/weave/legacy/ecosystem/example/__init__.py b/weave/legacy/weave/ecosystem/umap/__init__.py similarity index 74% rename from weave/legacy/ecosystem/example/__init__.py rename to weave/legacy/weave/ecosystem/umap/__init__.py index 1ac79cc09e3..e3feb039824 100644 --- a/weave/legacy/ecosystem/example/__init__.py +++ b/weave/legacy/weave/ecosystem/umap/__init__.py @@ -2,13 +2,13 @@ import logging -from weave.legacy import context_state +from weave.legacy.weave import context_state logging.getLogger("ecosystem_example").setLevel(logging.ERROR) loading_builtins_token = context_state.set_loading_built_ins() try: - from weave.legacy.ecosystem.example import ops + from weave.legacy.weave.ecosystem.umap.ops import * finally: context_state.clear_loading_built_ins(loading_builtins_token) diff --git a/weave/legacy/ecosystem/umap/ops.py b/weave/legacy/weave/ecosystem/umap/ops.py similarity index 96% rename from weave/legacy/ecosystem/umap/ops.py rename to weave/legacy/weave/ecosystem/umap/ops.py index 74951e7b7c4..893cba22ecb 100644 --- a/weave/legacy/ecosystem/umap/ops.py +++ b/weave/legacy/weave/ecosystem/umap/ops.py @@ -11,7 +11,7 @@ ) import weave -from weave.legacy import ops_arrow +from weave.legacy.weave import ops_arrow UMAP_LIB = None diff --git a/weave/legacy/weave/ecosystem/wandb/__init__.py b/weave/legacy/weave/ecosystem/wandb/__init__.py new file mode 100644 index 00000000000..9786a4f2489 --- /dev/null +++ b/weave/legacy/weave/ecosystem/wandb/__init__.py @@ -0,0 +1,13 @@ +from weave.legacy.weave import context_state as _context + +_loading_builtins_token = _context.set_loading_built_ins() + +from weave.legacy.weave.ecosystem.wandb import wandb_objs +from weave.legacy.weave.ecosystem.wandb.panel_distribution import * +from weave.legacy.weave.ecosystem.wandb.panel_geo import * +from weave.legacy.weave.ecosystem.wandb.panel_scatter import * +from weave.legacy.weave.ecosystem.wandb.panel_time_series import * +from weave.legacy.weave.ecosystem.wandb.run_chain import * +from weave.legacy.weave.ecosystem.wandb.weave_plotly import * + +_context.clear_loading_built_ins(_loading_builtins_token) diff --git a/weave/legacy/ecosystem/wandb/gql_artifact_dag.py b/weave/legacy/weave/ecosystem/wandb/gql_artifact_dag.py similarity index 98% rename from weave/legacy/ecosystem/wandb/gql_artifact_dag.py rename to weave/legacy/weave/ecosystem/wandb/gql_artifact_dag.py index 4fecc2909e7..ca22e0b1801 100644 --- a/weave/legacy/ecosystem/wandb/gql_artifact_dag.py +++ b/weave/legacy/weave/ecosystem/wandb/gql_artifact_dag.py @@ -1,6 +1,6 @@ import gql -from weave.legacy import wandb_api +from weave.legacy.weave import wandb_api ARTIFACT_LINEAGE_QUERY = gql.gql( """ diff --git a/weave/legacy/ecosystem/wandb/panel_distribution.py b/weave/legacy/weave/ecosystem/wandb/panel_distribution.py similarity index 75% rename from weave/legacy/ecosystem/wandb/panel_distribution.py rename to weave/legacy/weave/ecosystem/wandb/panel_distribution.py index b7d53699e4a..387db6ece06 100644 --- a/weave/legacy/ecosystem/wandb/panel_distribution.py +++ b/weave/legacy/weave/ecosystem/wandb/panel_distribution.py @@ -2,9 +2,9 @@ import typing import weave -from weave.legacy import weave_internal -from weave.legacy import panel_util -from weave.legacy.ecosystem.wandb import weave_plotly +from weave.legacy.weave import weave_internal +from weave.legacy.weave import panel_util +from weave.legacy.weave.ecosystem.wandb import weave_plotly @weave.type() @@ -14,14 +14,14 @@ class DistributionConfig: # We should make a better type to represent this, so it can be # distinguished from an expression like bin_size. value_fn: weave.Node[typing.Any] = dataclasses.field( - default_factory=lambda: weave.legacy.graph.VoidNode() + default_factory=lambda: weave.legacy.weave.graph.VoidNode() ) label_fn: weave.Node[typing.Any] = dataclasses.field( - default_factory=lambda: weave.legacy.graph.VoidNode() + default_factory=lambda: weave.legacy.weave.graph.VoidNode() ) # This is an expression. It will be stored in the config as Node. bin_size: weave.Node[typing.Any] = dataclasses.field( - default_factory=lambda: weave.legacy.graph.VoidNode() + default_factory=lambda: weave.legacy.weave.graph.VoidNode() ) @@ -35,7 +35,7 @@ class Distribution(weave.Panel): @weave.op() def initialize(self) -> DistributionConfig: input_node = self.input_node - unnested = weave.legacy.ops.unnest(input_node) + unnested = weave.legacy.weave.ops.unnest(input_node) return DistributionConfig( value_fn=weave_internal.define_fn( {"item": unnested.type.object_type}, @@ -50,19 +50,19 @@ def initialize(self) -> DistributionConfig: ) @weave.op() - def render_config(self) -> weave.legacy.panels.Group: + def render_config(self) -> weave.legacy.weave.panels.Group: config = typing.cast(DistributionConfig, self.config) - return weave.legacy.panels.Group( + return weave.legacy.weave.panels.Group( items={ - "value_fn": weave.legacy.panels.LabeledItem( + "value_fn": weave.legacy.weave.panels.LabeledItem( label="value", - item=weave.legacy.panels.FunctionEditor(config.value_fn), + item=weave.legacy.weave.panels.FunctionEditor(config.value_fn), ), - "label_fn": weave.legacy.panels.LabeledItem( + "label_fn": weave.legacy.weave.panels.LabeledItem( label="label", - item=weave.legacy.panels.FunctionEditor(config.label_fn), + item=weave.legacy.weave.panels.FunctionEditor(config.label_fn), ), - "bin_size": weave.legacy.panels.LabeledItem( + "bin_size": weave.legacy.weave.panels.LabeledItem( label="bin_size", # Must execute here because bin_size is an expression. # Editor panels take the actual type they edit (in this @@ -70,7 +70,7 @@ def render_config(self) -> weave.legacy.panels.Group: # const node directly in the config, or if the expression # refers to variables, the edit will be routed to the appropriate # owner. - item=weave.legacy.panels.Slider(config.bin_size.execute()), # type: ignore + item=weave.legacy.weave.panels.Slider(config.bin_size.execute()), # type: ignore ), } ) @@ -87,10 +87,10 @@ def render(self) -> weave_plotly.PanelPlotly: config.value_fn.type.output_type # type: ignore ): # TODO: need a nicer way to return error states - return weave.legacy.panels.PanelString("Invalid value_fn") # type: ignore + return weave.legacy.weave.panels.PanelString("Invalid value_fn") # type: ignore # We always unnest, so that we can compare across groups of items # easily. (the Distribution notebook) - unnested = weave.legacy.ops.unnest(input_node) + unnested = weave.legacy.weave.ops.unnest(input_node) bin_size = config.bin_size def bin_func(item): @@ -111,10 +111,10 @@ def bin_func(item): else: group_items["label"] = config.label_fn(item) - return weave.legacy.ops.dict_(**group_items) + return weave.legacy.weave.ops.dict_(**group_items) binned = unnested.groupby(lambda item: bin_func(item)).map( - lambda group: weave.legacy.ops.dict_( + lambda group: weave.legacy.weave.ops.dict_( value=group.groupkey()["value"], label=group.groupkey()["label"], count=group.count(), @@ -128,9 +128,9 @@ def bin_func(item): @weave.op() def distribution_panel_plot_render( input_node: weave.Node[list[typing.Any]], config: DistributionConfig -) -> weave.legacy.panels.Plot: - unnested = weave.legacy.ops.unnest(input_node) - bin_size = weave.legacy.ops.execute(config.bin_size) +) -> weave.legacy.weave.panels.Plot: + unnested = weave.legacy.weave.ops.unnest(input_node) + bin_size = weave.legacy.weave.ops.execute(config.bin_size) def bin_func(item): value_fn_output_type = config.value_fn.type.output_type @@ -146,18 +146,18 @@ def bin_func(item): else: group_items["label"] = config.label_fn(item) - res = weave.legacy.ops.dict_(**group_items) + res = weave.legacy.weave.ops.dict_(**group_items) return res binned = unnested.groupby(lambda item: bin_func(item)).map( - lambda group: weave.legacy.ops.dict_( + lambda group: weave.legacy.weave.ops.dict_( value=group.groupkey()["value"], label=group.groupkey()["label"], count=group.count(), ) ) - return weave.legacy.panels.Plot( + return weave.legacy.weave.panels.Plot( binned, x=lambda row: row["value"], y=lambda row: row["count"], diff --git a/weave/legacy/ecosystem/wandb/panel_geo.py b/weave/legacy/weave/ecosystem/wandb/panel_geo.py similarity index 77% rename from weave/legacy/ecosystem/wandb/panel_geo.py rename to weave/legacy/weave/ecosystem/wandb/panel_geo.py index f0be1990357..15c1f1c479d 100644 --- a/weave/legacy/ecosystem/wandb/panel_geo.py +++ b/weave/legacy/weave/ecosystem/wandb/panel_geo.py @@ -3,8 +3,8 @@ import typing import weave -from weave.legacy import weave_internal -from weave.legacy.ecosystem.wandb import weave_plotly +from weave.legacy.weave import weave_internal +from weave.legacy.weave.ecosystem.wandb import weave_plotly # This is the panel's config (the state that is stored in the panel and configurable @@ -12,13 +12,13 @@ @weave.type() class GeoConfig: x_fn: weave.Node[float] = dataclasses.field( - default_factory=lambda: weave.legacy.graph.VoidNode() + default_factory=lambda: weave.legacy.weave.graph.VoidNode() ) y_fn: weave.Node[float] = dataclasses.field( - default_factory=lambda: weave.legacy.graph.VoidNode() + default_factory=lambda: weave.legacy.weave.graph.VoidNode() ) color_fn: weave.Node[float] = dataclasses.field( - default_factory=lambda: weave.legacy.graph.VoidNode() + default_factory=lambda: weave.legacy.weave.graph.VoidNode() ) @@ -69,10 +69,10 @@ def geo_default_config( def geo( input_node: weave.Node[list[typing.Any]], config: GeoConfig ) -> weave_plotly.PanelPlotly: - unnested = weave.legacy.ops.unnest(input_node) + unnested = weave.legacy.weave.ops.unnest(input_node) config = geo_default_config(config, unnested) plot_data = unnested.map( - lambda item: weave.legacy.ops.dict_( + lambda item: weave.legacy.weave.ops.dict_( long=config.x_fn(item), # type: ignore lat=config.y_fn(item), # type: ignore color=config.color_fn(item), # type: ignore @@ -86,27 +86,27 @@ def geo( @weave.op(name="Geo_config") def geo_config( input_node: weave.Node[list[typing.Any]], config: GeoConfig -) -> weave.legacy.panels.Group: - unnested = weave.legacy.ops.unnest(input_node) +) -> weave.legacy.weave.panels.Group: + unnested = weave.legacy.weave.ops.unnest(input_node) config = geo_default_config(config, unnested) - return weave.legacy.panels.Group( + return weave.legacy.weave.panels.Group( items={ - "x_fn": weave.legacy.panels.LabeledItem( + "x_fn": weave.legacy.weave.panels.LabeledItem( label="x", - item=weave.legacy.panels.FunctionEditor( - config=weave.legacy.panels.FunctionEditorConfig(config.x_fn) + item=weave.legacy.weave.panels.FunctionEditor( + config=weave.legacy.weave.panels.FunctionEditorConfig(config.x_fn) ), ), - "y_fn": weave.legacy.panels.LabeledItem( + "y_fn": weave.legacy.weave.panels.LabeledItem( label="y", - item=weave.legacy.panels.FunctionEditor( - config=weave.legacy.panels.FunctionEditorConfig(config.y_fn) + item=weave.legacy.weave.panels.FunctionEditor( + config=weave.legacy.weave.panels.FunctionEditorConfig(config.y_fn) ), ), - "color_fn": weave.legacy.panels.LabeledItem( + "color_fn": weave.legacy.weave.panels.LabeledItem( label="color", - item=weave.legacy.panels.FunctionEditor( - config=weave.legacy.panels.FunctionEditorConfig(config.color_fn) + item=weave.legacy.weave.panels.FunctionEditor( + config=weave.legacy.weave.panels.FunctionEditorConfig(config.color_fn) ), ), } @@ -134,7 +134,7 @@ def __init__( if self.config is None: self.config = GeoConfig() - unnested = weave.legacy.ops.unnest(self.input_node) + unnested = weave.legacy.weave.ops.unnest(self.input_node) if "x_fn" in options: sig = inspect.signature(options["x_fn"]) param_name = list(sig.parameters.values())[0].name @@ -171,28 +171,28 @@ def __init__( @weave.op(output_type=lambda input_type: input_type["self"].input_node.output_type) def selected(self): # TODO: This function is not right! We need to do a range selection in polar space! - unnested = weave.legacy.ops.unnest(self.input_node) + unnested = weave.legacy.weave.ops.unnest(self.input_node) config = geo_default_config(self.config, unnested) filtered = unnested.filter( - lambda item: weave.legacy.ops.Boolean.bool_and( - weave.legacy.ops.Boolean.bool_and( - weave.legacy.ops.Boolean.bool_and( + lambda item: weave.legacy.weave.ops.Boolean.bool_and( + weave.legacy.weave.ops.Boolean.bool_and( + weave.legacy.weave.ops.Boolean.bool_and( config.x_fn(item) - > weave.legacy.ops.TypedDict.pick( + > weave.legacy.weave.ops.TypedDict.pick( self._renderAsPanel.config.selected, "xMin" ), config.x_fn(item) - < weave.legacy.ops.TypedDict.pick( + < weave.legacy.weave.ops.TypedDict.pick( self._renderAsPanel.config.selected, "xMax" ), ), config.y_fn(item) - > weave.legacy.ops.TypedDict.pick( + > weave.legacy.weave.ops.TypedDict.pick( self._renderAsPanel.config.selected, "yMin" ), ), config.y_fn(item) - < weave.legacy.ops.TypedDict.pick( + < weave.legacy.weave.ops.TypedDict.pick( self._renderAsPanel.config.selected, "yMax" ), ) diff --git a/weave/legacy/ecosystem/wandb/panel_scatter.py b/weave/legacy/weave/ecosystem/wandb/panel_scatter.py similarity index 65% rename from weave/legacy/ecosystem/wandb/panel_scatter.py rename to weave/legacy/weave/ecosystem/wandb/panel_scatter.py index 9794d847313..f670ae23c48 100644 --- a/weave/legacy/ecosystem/wandb/panel_scatter.py +++ b/weave/legacy/weave/ecosystem/wandb/panel_scatter.py @@ -3,20 +3,20 @@ import typing import weave -from weave.legacy import weave_internal -from weave.legacy.ecosystem.wandb import weave_plotly +from weave.legacy.weave import weave_internal +from weave.legacy.weave.ecosystem.wandb import weave_plotly @weave.type() class ScatterConfig: x_fn: weave.Node[typing.Optional[typing.Any]] = dataclasses.field( - default_factory=lambda: weave.legacy.graph.VoidNode() + default_factory=lambda: weave.legacy.weave.graph.VoidNode() ) y_fn: weave.Node[typing.Optional[typing.Any]] = dataclasses.field( - default_factory=lambda: weave.legacy.graph.VoidNode() + default_factory=lambda: weave.legacy.weave.graph.VoidNode() ) label_fn: weave.Node[typing.Any] = dataclasses.field( - default_factory=lambda: weave.legacy.graph.VoidNode() + default_factory=lambda: weave.legacy.weave.graph.VoidNode() ) @@ -30,7 +30,7 @@ class Scatter(weave.Panel): @weave.op() def initialize(self) -> ScatterConfig: input_node = self.input_node - unnested = weave.legacy.ops.unnest(input_node) + unnested = weave.legacy.weave.ops.unnest(input_node) return ScatterConfig( x_fn=weave_internal.define_fn( {"item": unnested.type.object_type}, @@ -48,19 +48,19 @@ def initialize(self) -> ScatterConfig: # The config render op. This renders the config editor. @weave.op() - def render_config(self) -> weave.legacy.panels.Group: + def render_config(self) -> weave.legacy.weave.panels.Group: config = typing.cast(ScatterConfig, self.config) - return weave.legacy.panels.Group( + return weave.legacy.weave.panels.Group( items={ - "x_fn": weave.legacy.panels.LabeledItem( - label="x", item=weave.legacy.panels.FunctionEditor(config.x_fn) + "x_fn": weave.legacy.weave.panels.LabeledItem( + label="x", item=weave.legacy.weave.panels.FunctionEditor(config.x_fn) ), - "y_fn": weave.legacy.panels.LabeledItem( - label="y", item=weave.legacy.panels.FunctionEditor(config.y_fn) + "y_fn": weave.legacy.weave.panels.LabeledItem( + label="y", item=weave.legacy.weave.panels.FunctionEditor(config.y_fn) ), - "label_fn": weave.legacy.panels.LabeledItem( + "label_fn": weave.legacy.weave.panels.LabeledItem( label="label", - item=weave.legacy.panels.FunctionEditor(config.label_fn), + item=weave.legacy.weave.panels.FunctionEditor(config.label_fn), ), } ) @@ -70,7 +70,7 @@ def render_config(self) -> weave.legacy.panels.Group: def render(self) -> weave_plotly.PanelPlotly: input_node = self.input_node config = typing.cast(ScatterConfig, self.config) - unnested = weave.legacy.ops.unnest(input_node) + unnested = weave.legacy.weave.ops.unnest(input_node) if ( not weave.types.optional(weave.types.Float()).assign_type(config.x_fn.type) or not weave.types.optional(weave.types.Float()).assign_type( @@ -80,14 +80,14 @@ def render(self) -> weave_plotly.PanelPlotly: config.label_fn.type ) ): - return weave.legacy.panels.PanelHtml(weave.legacy.ops.Html("No data")) # type: ignore + return weave.legacy.weave.panels.PanelHtml(weave.legacy.weave.ops.Html("No data")) # type: ignore if config.label_fn.type == weave.types.Invalid(): plot_data = unnested.map( - lambda item: weave.legacy.ops.dict_(x=config.x_fn(item), y=config.y_fn(item)) # type: ignore + lambda item: weave.legacy.weave.ops.dict_(x=config.x_fn(item), y=config.y_fn(item)) # type: ignore ) else: plot_data = unnested.map( - lambda item: weave.legacy.ops.dict_( + lambda item: weave.legacy.weave.ops.dict_( x=config.x_fn(item), y=config.y_fn(item), label=config.label_fn(item), @@ -100,28 +100,28 @@ def render(self) -> weave_plotly.PanelPlotly: # TODO: Fix @weave.op(output_type=lambda input_type: input_type["self"].input_node.output_type) def selected(self): - unnested = weave.legacy.ops.unnest(self.input_node) + unnested = weave.legacy.weave.ops.unnest(self.input_node) config = self.config filtered = unnested.filter( - lambda item: weave.legacy.ops.Boolean.bool_and( - weave.legacy.ops.Boolean.bool_and( - weave.legacy.ops.Boolean.bool_and( + lambda item: weave.legacy.weave.ops.Boolean.bool_and( + weave.legacy.weave.ops.Boolean.bool_and( + weave.legacy.weave.ops.Boolean.bool_and( config.x_fn(item) - > weave.legacy.ops.TypedDict.pick( + > weave.legacy.weave.ops.TypedDict.pick( self._renderAsPanel.config.selected, "xMin" ), config.x_fn(item) - < weave.legacy.ops.TypedDict.pick( + < weave.legacy.weave.ops.TypedDict.pick( self._renderAsPanel.config.selected, "xMax" ), ), config.y_fn(item) - > weave.legacy.ops.TypedDict.pick( + > weave.legacy.weave.ops.TypedDict.pick( self._renderAsPanel.config.selected, "yMin" ), ), config.y_fn(item) - < weave.legacy.ops.TypedDict.pick( + < weave.legacy.weave.ops.TypedDict.pick( self._renderAsPanel.config.selected, "yMax" ), ) diff --git a/weave/legacy/ecosystem/wandb/panel_time_series.py b/weave/legacy/weave/ecosystem/wandb/panel_time_series.py similarity index 80% rename from weave/legacy/ecosystem/wandb/panel_time_series.py rename to weave/legacy/weave/ecosystem/wandb/panel_time_series.py index 5d793f3152d..406ff8f140d 100644 --- a/weave/legacy/ecosystem/wandb/panel_time_series.py +++ b/weave/legacy/weave/ecosystem/wandb/panel_time_series.py @@ -2,10 +2,10 @@ import typing import weave -from weave.legacy import weave_internal -from weave.legacy.ecosystem.wandb import weave_plotly -from weave.legacy.language_features.tagging import tagged_value_type -from weave.legacy.panel_util import make_node +from weave.legacy.weave import weave_internal +from weave.legacy.weave.ecosystem.wandb import weave_plotly +from weave.legacy.weave.language_features.tagging import tagged_value_type +from weave.legacy.weave.panel_util import make_node TIME_SERIES_BIN_SIZES_SEC = [ # TODO: will need more steps along here for smooth zooming. @@ -53,27 +53,27 @@ @weave.type() class TimeSeriesConfig: x: weave.Node[typing.Any] = dataclasses.field( - default_factory=lambda: weave.legacy.graph.VoidNode() + default_factory=lambda: weave.legacy.weave.graph.VoidNode() ) agg: weave.Node[typing.Any] = dataclasses.field( - default_factory=lambda: weave.legacy.graph.VoidNode() + default_factory=lambda: weave.legacy.weave.graph.VoidNode() ) min_x: weave.Node[typing.Any] = dataclasses.field( - default_factory=lambda: weave.legacy.graph.VoidNode() + default_factory=lambda: weave.legacy.weave.graph.VoidNode() ) max_x: weave.Node[typing.Any] = dataclasses.field( - default_factory=lambda: weave.legacy.graph.VoidNode() + default_factory=lambda: weave.legacy.weave.graph.VoidNode() ) label: weave.Node[ typing.Optional[typing.Union[str, weave.types.InvalidPy]] - ] = dataclasses.field(default_factory=lambda: weave.legacy.graph.VoidNode()) + ] = dataclasses.field(default_factory=lambda: weave.legacy.weave.graph.VoidNode()) mark: weave.Node[str] = dataclasses.field( - default_factory=lambda: weave.legacy.graph.ConstNode( + default_factory=lambda: weave.legacy.weave.graph.ConstNode( weave.types.String(), "bar" ) ) axis_labels: weave.Node[dict[str, str]] = dataclasses.field( - default_factory=lambda: weave.legacy.graph.ConstNode( + default_factory=lambda: weave.legacy.weave.graph.ConstNode( weave.types.Dict(weave.types.String(), weave.types.String()), {}, ) @@ -83,7 +83,7 @@ class TimeSeriesConfig: def first_column_of_type( node_type: weave.types.Type, desired_type: weave.types.Type, -) -> typing.Tuple[weave.legacy.graph.ConstNode, weave.legacy.graph.ConstNode]: +) -> typing.Tuple[weave.legacy.weave.graph.ConstNode, weave.legacy.weave.graph.ConstNode]: if isinstance(node_type, tagged_value_type.TaggedValueType): node_type = node_type.value if weave.types.List().assign_type(node_type): @@ -119,8 +119,8 @@ def first_column_of_type( {"item": object_type}, lambda item: item[key] ) # return weave_internal.define_fn( - # {"input_node": node_type}, weave.legacy.graph.VoidNode() - # ), weave_internal.define_fn({"item": object_type}, lambda _: weave.legacy.graph.VoidNode()) + # {"input_node": node_type}, weave.legacy.weave.graph.VoidNode() + # ), weave_internal.define_fn({"item": object_type}, lambda _: weave.legacy.weave.graph.VoidNode()) raise ValueError( f"Can't extract column with type {desired_type} from node of type {node_type}" ) @@ -160,7 +160,7 @@ def __init__(self, input_node, vars=None, config=None, **options): super().__init__(input_node=input_node, vars=vars) self.config = config - unnested = weave.legacy.ops.unnest(input_node) + unnested = weave.legacy.weave.ops.unnest(input_node) # TODO: add the ability to configure options here if self.config is None: @@ -168,7 +168,7 @@ def __init__(self, input_node, vars=None, config=None, **options): for attr in ["x", "min_x", "max_x", "label", "mark", "agg", "axis_labels"]: if attr in options: value = options[attr] - if not isinstance(value, weave.legacy.graph.Node): + if not isinstance(value, weave.legacy.weave.graph.Node): if attr in ["min_x", "max_x", "mark", "axis_labels"]: value = make_node(value) if attr in ["min_x", "max_x"]: @@ -186,7 +186,7 @@ def __init__(self, input_node, vars=None, config=None, **options): else: value = weave_internal.define_fn( {"item": unnested.type.object_type}, - lambda item: weave.legacy.graph.VoidNode(), + lambda item: weave.legacy.weave.graph.VoidNode(), ) setattr(self.config, attr, value) @@ -239,32 +239,32 @@ def initialize(self) -> TimeSeriesConfig: # The config render op. This renders the config editor. @weave.op() - def render_config(self) -> weave.legacy.panels.Group: + def render_config(self) -> weave.legacy.weave.panels.Group: input_node = self.input_node config = typing.cast(TimeSeriesConfig, self.config) - return weave.legacy.panels.Group( + return weave.legacy.weave.panels.Group( items={ - "x": weave.legacy.panels.LabeledItem( - label="x", item=weave.legacy.panels.FunctionEditor(config.x) + "x": weave.legacy.weave.panels.LabeledItem( + label="x", item=weave.legacy.weave.panels.FunctionEditor(config.x) ), - "label": weave.legacy.panels.LabeledItem( + "label": weave.legacy.weave.panels.LabeledItem( label="label", - item=weave.legacy.panels.FunctionEditor(config.label), + item=weave.legacy.weave.panels.FunctionEditor(config.label), ), - "min_x": weave.legacy.panels.LabeledItem( + "min_x": weave.legacy.weave.panels.LabeledItem( label="min_x", - item=weave.legacy.panels.FunctionEditor(config.min_x), + item=weave.legacy.weave.panels.FunctionEditor(config.min_x), ), - "max_x": weave.legacy.panels.LabeledItem( + "max_x": weave.legacy.weave.panels.LabeledItem( label="max_x", - item=weave.legacy.panels.FunctionEditor(config.max_x), + item=weave.legacy.weave.panels.FunctionEditor(config.max_x), ), - "agg": weave.legacy.panels.LabeledItem( - label="agg", item=weave.legacy.panels.FunctionEditor(config.agg) + "agg": weave.legacy.weave.panels.LabeledItem( + label="agg", item=weave.legacy.weave.panels.FunctionEditor(config.agg) ), - "mark": weave.legacy.panels.LabeledItem( + "mark": weave.legacy.weave.panels.LabeledItem( label="mark", - item=weave.legacy.panels.ObjectPicker( + item=weave.legacy.weave.panels.ObjectPicker( weave_internal.make_const_node( weave.types.List(weave.types.String()), [ @@ -273,7 +273,7 @@ def render_config(self) -> weave.legacy.panels.Group: "point", ], ), - config=weave.legacy.panels.ObjectPickerConfig( + config=weave.legacy.weave.panels.ObjectPickerConfig( choice=config.mark ), ), @@ -296,13 +296,13 @@ def render(self) -> weave_plotly.PanelPlotly: if not weave.types.optional(weave.types.Timestamp()).assign_type( min_x.type ) or not weave.types.optional(weave.types.Timestamp()).assign_type(max_x.type): - return weave.legacy.panels.PanelHtml(weave.legacy.ops.Html("No data")) # type: ignore + return weave.legacy.weave.panels.PanelHtml(weave.legacy.weave.ops.Html("No data")) # type: ignore exact_bin_size = ((max_x - min_x) / N_BINS).totalSeconds() # type: ignore bin_size_index = TIME_SERIES_BIN_SIZES_SEC_NODE.map( # type: ignore lambda x: ( (x - exact_bin_size).abs() - / weave.legacy.ops.make_list(a=x, b=exact_bin_size).min() + / weave.legacy.weave.ops.make_list(a=x, b=exact_bin_size).min() ) # lambda x: (x / exact_bin_size - 1).abs() # original ).argmin() @@ -323,25 +323,25 @@ def bin_fn(item): bin_start = bin_start_ms bin_end = bin_end_ms - group_items["bin"] = weave.legacy.ops.dict_(start=bin_start, stop=bin_end) + group_items["bin"] = weave.legacy.weave.ops.dict_(start=bin_start, stop=bin_end) if label_fn_output_type == weave.types.Invalid(): group_items["label"] = "no_label" else: group_items["label"] = config.label(item) - return weave.legacy.ops.dict_(**group_items) + return weave.legacy.weave.ops.dict_(**group_items) binned = ( unnested.filter( - lambda item: weave.legacy.ops.Boolean.bool_and( + lambda item: weave.legacy.weave.ops.Boolean.bool_and( config.x(item) <= max_x, config.x(item) >= min_x, # type: ignore ) ) .groupby(lambda item: bin_fn(item)) .map( - lambda group: weave.legacy.ops.dict_( + lambda group: weave.legacy.weave.ops.dict_( x=group.groupkey()["bin"], label=group.groupkey()["label"], y=config.agg(group), # type: ignore @@ -349,12 +349,12 @@ def bin_fn(item): ) # this is needed because otherwise the lines look like a scrambled mess .sort( - lambda item: weave.legacy.ops.make_list(a=item["x"]["start"]), + lambda item: weave.legacy.weave.ops.make_list(a=item["x"]["start"]), ["asc"], ) ) - default_labels = weave.legacy.ops.dict_( + default_labels = weave.legacy.weave.ops.dict_( # x=function_to_string(config.x), # y=function_to_string(config.agg), # label=function_to_string(config.label), diff --git a/weave/legacy/ecosystem/wandb/run_chain.py b/weave/legacy/weave/ecosystem/wandb/run_chain.py similarity index 91% rename from weave/legacy/ecosystem/wandb/run_chain.py rename to weave/legacy/weave/ecosystem/wandb/run_chain.py index e57a79da9ff..3283b1742b8 100644 --- a/weave/legacy/ecosystem/wandb/run_chain.py +++ b/weave/legacy/weave/ecosystem/wandb/run_chain.py @@ -2,8 +2,8 @@ import typing import weave -from weave.legacy import compile, op_def, ops_arrow -from weave.legacy.ecosystem.wandb import gql_artifact_dag +from weave.legacy.weave import compile, op_def, ops_arrow +from weave.legacy.weave.ecosystem.wandb import gql_artifact_dag @weave.type() @@ -20,7 +20,7 @@ class RunChain: def _history_node(self): with op_def.no_refine(): - proj = weave.legacy.ops.project(self.entity_name, self.project_name) + proj = weave.legacy.weave.ops.project(self.entity_name, self.project_name) history_nodes = [] for seg in self.segments: # This is the only use of the deprecated history2 op in the Weave @@ -32,8 +32,8 @@ def _history_node(self): history_nodes.append(hist_node) - history_node = weave.legacy.ops.List.concat( - weave.legacy.ops.make_list( + history_node = weave.legacy.weave.ops.List.concat( + weave.legacy.weave.ops.make_list( **{f"node{i}": n for i, n in enumerate(history_nodes)} ) ) @@ -56,7 +56,7 @@ def history(self): def run_chain(run_path: str) -> RunChain: with op_def.no_refine(): entity, project, run_id = run_path.split("/") - proj = weave.legacy.ops.project(entity, project) + proj = weave.legacy.weave.ops.project(entity, project) run = proj.run(run_id) # Get the checkpoint artifact for this one if one exists diff --git a/weave/legacy/ecosystem/wandb/test_panel_distribution.py b/weave/legacy/weave/ecosystem/wandb/test_panel_distribution.py similarity index 93% rename from weave/legacy/ecosystem/wandb/test_panel_distribution.py rename to weave/legacy/weave/ecosystem/wandb/test_panel_distribution.py index a75a862649c..17b5a7400f8 100644 --- a/weave/legacy/ecosystem/wandb/test_panel_distribution.py +++ b/weave/legacy/weave/ecosystem/wandb/test_panel_distribution.py @@ -1,8 +1,8 @@ import random import weave -from weave.legacy import weave_internal -from weave.legacy.ecosystem.wandb import panel_distribution +from weave.legacy.weave import weave_internal +from weave.legacy.weave.ecosystem.wandb import panel_distribution def test_flow(): diff --git a/weave/legacy/ecosystem/wandb/wandb_objs.py b/weave/legacy/weave/ecosystem/wandb/wandb_objs.py similarity index 73% rename from weave/legacy/ecosystem/wandb/wandb_objs.py rename to weave/legacy/weave/ecosystem/wandb/wandb_objs.py index 449d82ed786..38731a5af83 100644 --- a/weave/legacy/ecosystem/wandb/wandb_objs.py +++ b/weave/legacy/weave/ecosystem/wandb/wandb_objs.py @@ -1,8 +1,8 @@ import typing import weave -from weave.legacy import registry_mem -from weave.legacy.ops_domain import run_ops, wb_domain_types +from weave.legacy.weave import registry_mem +from weave.legacy.weave.ops_domain import run_ops, wb_domain_types # We can't chain ops called .name() because of a weird bug :( [its a field on VarNode]. # So we have to get the ops here and call them directly for now. @@ -23,7 +23,7 @@ def org_model(entity_name: str, model_name: str) -> FakeWandbModel: return FakeWandbModel(model_name) -GHOSTWRITE_MD = weave.legacy.ops.Markdown( +GHOSTWRITE_MD = weave.legacy.weave.ops.Markdown( """ # [ghostwrite.ai](https://ghostwrite.ai). @@ -35,19 +35,19 @@ def org_model(entity_name: str, model_name: str) -> FakeWandbModel: @weave.op() def fakewandbmodel_render( model_node: weave.Node[FakeWandbModel], -) -> weave.legacy.panels.Card: +) -> weave.legacy.weave.panels.Card: model = typing.cast(FakeWandbModel, model_node) - return weave.legacy.panels.Card( + return weave.legacy.weave.panels.Card( title=model.name, subtitle="", content=[ - weave.legacy.panels.CardTab( + weave.legacy.weave.panels.CardTab( name="Description", - content=weave.legacy.panels.PanelMarkdown(GHOSTWRITE_MD), # type: ignore + content=weave.legacy.weave.panels.PanelMarkdown(GHOSTWRITE_MD), # type: ignore ), - weave.legacy.panels.CardTab( + weave.legacy.weave.panels.CardTab( name="Predictions", - content=weave.legacy.ops.project("shawn", "ghostwrite-test1") + content=weave.legacy.weave.ops.project("shawn", "ghostwrite-test1") .runs() .summary()["predictions"] .table() @@ -62,39 +62,39 @@ def fakewandbmodel_render( @weave.op() def entity_render( entity_node: weave.Node[wb_domain_types.Entity], -) -> weave.legacy.panels.Card: +) -> weave.legacy.weave.panels.Card: entity = typing.cast(wb_domain_types.Entity, entity_node) - return weave.legacy.panels.Card( + return weave.legacy.weave.panels.Card( title=entity_name_op(entity), subtitle="", content=[ - weave.legacy.panels.CardTab( + weave.legacy.weave.panels.CardTab( name="Projects", - content=weave.legacy.panels.Table( + content=weave.legacy.weave.panels.Table( entity.projects(), # type: ignore columns=[ - lambda project: weave.legacy.panels.WeaveLink( + lambda project: weave.legacy.weave.panels.WeaveLink( project_name_op(project), vars={ "entity_name": entity_name_op(project.entity()), "project_name": project_name_op(project), }, - to=lambda input, vars: weave.legacy.ops.project( + to=lambda input, vars: weave.legacy.weave.ops.project( vars["entity_name"], vars["project_name"] ), ), ], ), ), - weave.legacy.panels.CardTab( + weave.legacy.weave.panels.CardTab( name="Registered Models", - content=weave.legacy.panels.Table( + content=weave.legacy.weave.panels.Table( weave.save( ["ghostwrite", "credit card predictor", "stopsigns3"], name="model_list", ), columns=[ - lambda model_name: weave.legacy.panels.WeaveLink( + lambda model_name: weave.legacy.weave.panels.WeaveLink( model_name, vars={ "entity_name": entity_name_op(entity), @@ -116,18 +116,18 @@ class ProjectRunsTable(weave.Panel): input_node: weave.Node[list[wb_domain_types.Run]] @weave.op() - def render(self) -> weave.legacy.panels.Table: - return weave.legacy.panels.Table( + def render(self) -> weave.legacy.weave.panels.Table: + return weave.legacy.weave.panels.Table( self.input_node, columns=[ - lambda run: weave.legacy.panels.WeaveLink( + lambda run: weave.legacy.weave.panels.WeaveLink( run.id(), vars={ "entity_name": entity_name_op(run.project().entity()), "project_name": project_name_op(run.project()), "run_id": run.id(), }, - to=lambda input, vars: weave.legacy.ops.project( + to=lambda input, vars: weave.legacy.weave.ops.project( vars["entity_name"], vars["project_name"] ).run(vars["run_id"]), ), @@ -143,28 +143,28 @@ class ProjectArtifactsTable(weave.Panel): input_node: weave.Node[list[wb_domain_types.ArtifactCollection]] @weave.op() - def render(self) -> weave.legacy.panels.Table: + def render(self) -> weave.legacy.weave.panels.Table: # This breaks if there is a variable in the node # types_names = weave.use(artifacts._get_op("type")().name().unique()) - # return weave.legacy.panels.Card( + # return weave.legacy.weave.panels.Card( # title="Artifacts", # subtitle="", # content=[ - # weave.legacy.panels.CardTab(name=type_name, content=[type_name]) + # weave.legacy.weave.panels.CardTab(name=type_name, content=[type_name]) # for type_name in types_names # ], # ) - return weave.legacy.panels.Table( + return weave.legacy.weave.panels.Table( self.input_node, columns=[ - lambda artifact: weave.legacy.panels.WeaveLink( + lambda artifact: weave.legacy.weave.panels.WeaveLink( artifact._get_op("name")(), vars={ "entity_name": entity_name_op(artifact.project().entity()), "project_name": project_name_op(artifact.project()), "artifact_name": artifact._get_op("name")(), }, - to=lambda input, vars: weave.legacy.ops.project( + to=lambda input, vars: weave.legacy.weave.ops.project( vars["entity_name"], vars["project_name"] ).artifact(vars["artifact_name"]), ), diff --git a/weave/legacy/ecosystem/wandb/weave_plotly.py b/weave/legacy/weave/ecosystem/wandb/weave_plotly.py similarity index 97% rename from weave/legacy/ecosystem/wandb/weave_plotly.py rename to weave/legacy/weave/ecosystem/wandb/weave_plotly.py index 0450a9dbd64..31f71fb54d3 100644 --- a/weave/legacy/ecosystem/wandb/weave_plotly.py +++ b/weave/legacy/weave/ecosystem/wandb/weave_plotly.py @@ -9,8 +9,8 @@ from plotly import graph_objs as go import weave -from weave.legacy import weave_internal -from weave.legacy import infer_types +from weave.legacy.weave import weave_internal +from weave.legacy.weave import infer_types class PlotlyType(weave.types.Type): @@ -178,7 +178,7 @@ def bin_center(bin): @weave.op() def plotly_scatter(data: list[ScatterData]) -> plotly.graph_objs.Figure: - from weave.legacy import storage + from weave.legacy.weave import storage data = storage.to_weavejs(data) color = None diff --git a/weave/legacy/ecosystem/xgboost/__init__.py b/weave/legacy/weave/ecosystem/xgboost/__init__.py similarity index 51% rename from weave/legacy/ecosystem/xgboost/__init__.py rename to weave/legacy/weave/ecosystem/xgboost/__init__.py index 361df7d9d64..af07721cc2a 100644 --- a/weave/legacy/ecosystem/xgboost/__init__.py +++ b/weave/legacy/weave/ecosystem/xgboost/__init__.py @@ -1,7 +1,7 @@ -from weave.legacy import context_state as _context +from weave.legacy.weave import context_state as _context _loading_builtins_token = _context.set_loading_built_ins() -from weave.legacy.ecosystem.xgboost.model import * +from weave.legacy.weave.ecosystem.xgboost.model import * _context.clear_loading_built_ins(_loading_builtins_token) diff --git a/weave/legacy/ecosystem/xgboost/model.py b/weave/legacy/weave/ecosystem/xgboost/model.py similarity index 100% rename from weave/legacy/ecosystem/xgboost/model.py rename to weave/legacy/weave/ecosystem/xgboost/model.py diff --git a/weave/legacy/engine_trace.py b/weave/legacy/weave/engine_trace.py similarity index 98% rename from weave/legacy/engine_trace.py rename to weave/legacy/weave/engine_trace.py index 20ce84169e7..b4b6fca18ba 100644 --- a/weave/legacy/engine_trace.py +++ b/weave/legacy/weave/engine_trace.py @@ -18,7 +18,7 @@ import time import typing -from weave.legacy import environment, logs, stream_data_interfaces +from weave.legacy.weave import environment, logs, stream_data_interfaces # Thanks co-pilot! @@ -91,7 +91,7 @@ def current_root_span(self): # type: ignore def weave_trace_stream(): # type: ignore global _weave_trace_stream if _weave_trace_stream is None: - from weave.legacy.wandb_interface.wandb_stream_table import StreamTable + from weave.legacy.weave.wandb_interface.wandb_stream_table import StreamTable _weave_trace_stream = StreamTable(os.getenv("WEAVE_TRACE_STREAM")) return _weave_trace_stream diff --git a/weave/legacy/environment.py b/weave/legacy/weave/environment.py similarity index 98% rename from weave/legacy/environment.py rename to weave/legacy/weave/environment.py index a2bc2d81852..f9418520a1e 100644 --- a/weave/legacy/environment.py +++ b/weave/legacy/weave/environment.py @@ -10,11 +10,11 @@ import typing from distutils.util import strtobool from urllib.parse import urlparse -from weave.legacy import errors -from weave.legacy import util +from weave.legacy.weave import errors +from weave.legacy.weave import util if typing.TYPE_CHECKING: - from weave.legacy import logs + from weave.legacy.weave import logs WANDB_ERROR_REPORTING = "WANDB_ERROR_REPORTING" WEAVE_USAGE_ANALYTICS = "WEAVE_USAGE_ANALYTICS" @@ -105,7 +105,7 @@ def is_public() -> bool: def weave_log_format(default: "logs.LogFormat") -> "logs.LogFormat": - from weave.legacy.logs import LogFormat + from weave.legacy.weave.logs import LogFormat return LogFormat(os.getenv("WEAVE_LOG_FORMAT", default)) diff --git a/weave/legacy/errors.py b/weave/legacy/weave/errors.py similarity index 100% rename from weave/legacy/errors.py rename to weave/legacy/weave/errors.py diff --git a/weave/legacy/execute.py b/weave/legacy/weave/execute.py similarity index 99% rename from weave/legacy/execute.py rename to weave/legacy/weave/execute.py index b4cc7a81570..42ff32ba230 100644 --- a/weave/legacy/execute.py +++ b/weave/legacy/weave/execute.py @@ -9,7 +9,7 @@ import typing from collections.abc import Mapping -from weave.legacy import weave_types as types +from weave.legacy.weave import weave_types as types # Configuration # Libraries @@ -17,7 +17,7 @@ # Ops # Trace / cache # Language Features -from weave.legacy import ( +from weave.legacy.weave import ( errors, engine_trace, environment, @@ -42,7 +42,7 @@ value_or_error, wandb_api, ) -from weave.legacy.language_features.tagging import ( +from weave.legacy.weave.language_features.tagging import ( opdef_util, process_opdef_resolve_fn, tag_store, diff --git a/weave/legacy/execute_fast.py b/weave/legacy/weave/execute_fast.py similarity index 97% rename from weave/legacy/execute_fast.py rename to weave/legacy/weave/execute_fast.py index f3069ffa886..b1bb0f2b87d 100644 --- a/weave/legacy/execute_fast.py +++ b/weave/legacy/weave/execute_fast.py @@ -1,7 +1,7 @@ import logging -from weave.legacy import weave_types as types -from weave.legacy import ( +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import ( weave_internal, errors, engine_trace, @@ -14,7 +14,7 @@ language_nullability, op_policy, ) -from weave.legacy.language_features.tagging import tag_store +from weave.legacy.weave.language_features.tagging import tag_store # from . import object_context diff --git a/weave/legacy/file_base.py b/weave/legacy/weave/file_base.py similarity index 98% rename from weave/legacy/file_base.py rename to weave/legacy/weave/file_base.py index ff03c072471..835d7e1a2f6 100644 --- a/weave/legacy/file_base.py +++ b/weave/legacy/weave/file_base.py @@ -2,7 +2,7 @@ import dataclasses import typing -from weave.legacy import weave_types as types +from weave.legacy.weave import weave_types as types TRACE_EXT = "trace.json" diff --git a/weave/legacy/file_local.py b/weave/legacy/weave/file_local.py similarity index 98% rename from weave/legacy/file_local.py rename to weave/legacy/weave/file_local.py index e20a0a2248b..b68d0cd5c83 100644 --- a/weave/legacy/file_local.py +++ b/weave/legacy/weave/file_local.py @@ -2,7 +2,7 @@ import os import typing -from weave.legacy import weave_types as types +from weave.legacy.weave import weave_types as types from . import file_base, file_util diff --git a/weave/legacy/file_util.py b/weave/legacy/weave/file_util.py similarity index 88% rename from weave/legacy/file_util.py rename to weave/legacy/weave/file_util.py index 31da6fc6647..3946e1e5d57 100644 --- a/weave/legacy/file_util.py +++ b/weave/legacy/weave/file_util.py @@ -2,8 +2,8 @@ import pathlib import typing -from weave.legacy import filesystem -from weave.legacy import cache, environment, path_util +from weave.legacy.weave import filesystem +from weave.legacy.weave import cache, environment, path_util def get_allowed_dir() -> pathlib.Path: diff --git a/weave/legacy/filesystem.py b/weave/legacy/weave/filesystem.py similarity index 98% rename from weave/legacy/filesystem.py rename to weave/legacy/weave/filesystem.py index 559ecaa1bd8..c812090c67a 100644 --- a/weave/legacy/filesystem.py +++ b/weave/legacy/weave/filesystem.py @@ -20,7 +20,7 @@ from aiofiles.threadpool import binary as aiofiles_binary from aiofiles.threadpool import text as aiofiles_text -from weave.legacy import cache, engine_trace, environment, errors, util +from weave.legacy.weave import cache, engine_trace, environment, errors, util tracer = engine_trace.tracer() # type: ignore async_utime = aiofiles_os.wrap(os.utime) # type: ignore diff --git a/weave/legacy/forward_graph.py b/weave/legacy/weave/forward_graph.py similarity index 98% rename from weave/legacy/forward_graph.py rename to weave/legacy/weave/forward_graph.py index 7f3801e3024..e22ea9dfdfc 100644 --- a/weave/legacy/forward_graph.py +++ b/weave/legacy/weave/forward_graph.py @@ -3,9 +3,9 @@ import contextvars import typing -from weave.legacy import graph +from weave.legacy.weave import graph -from weave.legacy import errors +from weave.legacy.weave import errors ExecutableNode = typing.Union[graph.OutputNode, graph.ConstNode] diff --git a/weave/legacy/gql_json_cache.py b/weave/legacy/weave/gql_json_cache.py similarity index 100% rename from weave/legacy/gql_json_cache.py rename to weave/legacy/weave/gql_json_cache.py diff --git a/weave/legacy/gql_op_plugin.py b/weave/legacy/weave/gql_op_plugin.py similarity index 95% rename from weave/legacy/gql_op_plugin.py rename to weave/legacy/weave/gql_op_plugin.py index 090a1536c40..1b2af19c287 100644 --- a/weave/legacy/gql_op_plugin.py +++ b/weave/legacy/weave/gql_op_plugin.py @@ -1,8 +1,8 @@ import typing from dataclasses import dataclass -from weave.legacy import weave_types as types -from weave.legacy import input_provider, op_args, op_def +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import input_provider, op_args, op_def # A GQLOutputTypeFn is a function that is called during the refinement phase of the compile pass # to propagate the GQL keys of a node's input types to its output type. diff --git a/weave/legacy/gql_schema.py b/weave/legacy/weave/gql_schema.py similarity index 87% rename from weave/legacy/gql_schema.py rename to weave/legacy/weave/gql_schema.py index 6ee16b3cd7b..eb3181d3be1 100644 --- a/weave/legacy/gql_schema.py +++ b/weave/legacy/weave/gql_schema.py @@ -2,8 +2,8 @@ import graphql -from weave.legacy import environment -from weave.legacy import wandb_client_api +from weave.legacy.weave import environment +from weave.legacy.weave import wandb_client_api _GQL_SCHEMA_CACHE: dict[typing.Optional[str], graphql.GraphQLSchema] = {} diff --git a/weave/legacy/gql_to_weave.py b/weave/legacy/weave/gql_to_weave.py similarity index 97% rename from weave/legacy/gql_to_weave.py rename to weave/legacy/weave/gql_to_weave.py index 117e3511dea..0dae36abee8 100644 --- a/weave/legacy/gql_to_weave.py +++ b/weave/legacy/weave/gql_to_weave.py @@ -17,9 +17,9 @@ parse, ) -from weave.legacy import errors -from weave.legacy import weave_types as types -from weave.legacy import gql_schema +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import gql_schema def get_outermost_alias(query_str: str) -> str: diff --git a/weave/legacy/graph.py b/weave/legacy/weave/graph.py similarity index 98% rename from weave/legacy/graph.py rename to weave/legacy/weave/graph.py index 9517b687b34..71474069a46 100644 --- a/weave/legacy/graph.py +++ b/weave/legacy/weave/graph.py @@ -2,11 +2,11 @@ import json import typing -from weave.legacy import weave_types -from weave.legacy import uris, errors, storage +from weave.legacy.weave import weave_types +from weave.legacy.weave import uris, errors, storage if typing.TYPE_CHECKING: - from weave.legacy import weave_inspector + from weave.legacy.weave import weave_inspector T = typing.TypeVar("T") @@ -39,7 +39,7 @@ def to_json(self) -> dict: def _inspect(self) -> "weave_inspector.NodeInspector": """Only intended to be used by developers to help debug the graph.""" # Circular import, so we do it here. - from weave.legacy import weave_inspector + from weave.legacy.weave import weave_inspector return weave_inspector.NodeInspector(self) @@ -187,7 +187,7 @@ def __init__(self, type: weave_types.Type, val: typing.Any) -> None: @classmethod def from_json(cls, obj: dict) -> "ConstNode": - from weave.legacy import dispatch + from weave.legacy.weave import dispatch val = obj["val"] if isinstance(val, dict) and "nodeType" in val: @@ -239,7 +239,7 @@ def op_full_name(op: Op) -> str: def node_expr_str(node: Node) -> str: - from weave.legacy import partial_object + from weave.legacy.weave import partial_object if isinstance(node, OutputNode): param_names = list(node.from_op.inputs.keys()) diff --git a/weave/legacy/graph_debug.py b/weave/legacy/weave/graph_debug.py similarity index 98% rename from weave/legacy/graph_debug.py rename to weave/legacy/weave/graph_debug.py index d82a7353661..539ba38b8af 100644 --- a/weave/legacy/graph_debug.py +++ b/weave/legacy/weave/graph_debug.py @@ -2,8 +2,8 @@ import textwrap import typing -from weave.legacy import weave_types as types -from weave.legacy import forward_graph, graph +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import forward_graph, graph class _CombinedConstVal: @@ -123,7 +123,7 @@ def node_expr_str_full(node: graph.Node) -> str: This function is a copy/modification of of node_expr_str. """ - from weave.legacy import partial_object + from weave.legacy.weave import partial_object if isinstance(node, graph.OutputNode): if node.from_op.name == "dict": diff --git a/weave/legacy/graph_mapper.py b/weave/legacy/weave/graph_mapper.py similarity index 75% rename from weave/legacy/graph_mapper.py rename to weave/legacy/weave/graph_mapper.py index 1cf5a6c9e13..fab4bfc6cd2 100644 --- a/weave/legacy/graph_mapper.py +++ b/weave/legacy/weave/graph_mapper.py @@ -1,7 +1,7 @@ -from weave.legacy import ref_base -from weave.legacy import weave_types as types -from weave.legacy import graph, mappers, node_ref -from weave.legacy import mappers_python_def as mappers_python +from weave.legacy.weave import ref_base +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import graph, mappers, node_ref +from weave.legacy.weave import mappers_python_def as mappers_python class FunctionToPyFunction(mappers.Mapper): diff --git a/weave/legacy/infer_types.py b/weave/legacy/weave/infer_types.py similarity index 97% rename from weave/legacy/infer_types.py rename to weave/legacy/weave/infer_types.py index 9eedc3a4c03..018b485d00f 100644 --- a/weave/legacy/infer_types.py +++ b/weave/legacy/weave/infer_types.py @@ -6,9 +6,9 @@ import typing_extensions -from weave.legacy import errors, graph +from weave.legacy.weave import errors, graph -from weave.legacy import weave_types +from weave.legacy.weave import weave_types class TypedDictLike: diff --git a/weave/legacy/input_provider.py b/weave/legacy/weave/input_provider.py similarity index 100% rename from weave/legacy/input_provider.py rename to weave/legacy/weave/input_provider.py diff --git a/weave/legacy/io_service.py b/weave/legacy/weave/io_service.py similarity index 99% rename from weave/legacy/io_service.py rename to weave/legacy/weave/io_service.py index 9091573a914..8e19392040b 100644 --- a/weave/legacy/io_service.py +++ b/weave/legacy/weave/io_service.py @@ -22,7 +22,7 @@ import aioprocessing -from weave.legacy import ( +from weave.legacy.weave import ( weave_http, filesystem, errors, diff --git a/weave/legacy/language_autocall.py b/weave/legacy/weave/language_autocall.py similarity index 93% rename from weave/legacy/language_autocall.py rename to weave/legacy/weave/language_autocall.py index 73822279ed7..97f87e7f01b 100644 --- a/weave/legacy/language_autocall.py +++ b/weave/legacy/weave/language_autocall.py @@ -15,8 +15,8 @@ import typing -from weave.legacy import weave_types as types -from weave.legacy import op_args +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import op_args def update_input_types( diff --git a/weave/legacy/language_features/tagging/__init__.py b/weave/legacy/weave/language_features/__init__.py similarity index 100% rename from weave/legacy/language_features/tagging/__init__.py rename to weave/legacy/weave/language_features/__init__.py diff --git a/weave/legacy/ops_domain/run_history/__init__.py b/weave/legacy/weave/language_features/tagging/__init__.py similarity index 100% rename from weave/legacy/ops_domain/run_history/__init__.py rename to weave/legacy/weave/language_features/tagging/__init__.py diff --git a/weave/legacy/language_features/tagging/is_tag_getter.py b/weave/legacy/weave/language_features/tagging/is_tag_getter.py similarity index 84% rename from weave/legacy/language_features/tagging/is_tag_getter.py rename to weave/legacy/weave/language_features/tagging/is_tag_getter.py index d4d6b83c401..ccc4969f256 100644 --- a/weave/legacy/language_features/tagging/is_tag_getter.py +++ b/weave/legacy/weave/language_features/tagging/is_tag_getter.py @@ -1,11 +1,11 @@ import typing -from weave.legacy import weave_types as types -from weave.legacy import op_args -from weave.legacy.language_features.tagging import tagged_value_type +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import op_args +from weave.legacy.weave.language_features.tagging import tagged_value_type if typing.TYPE_CHECKING: - from weave.legacy import op_def as OpDef + from weave.legacy.weave import op_def as OpDef # This is a heuristic that is used to determine if an op is a tag getter. diff --git a/weave/legacy/language_features/tagging/make_tag_getter_op.py b/weave/legacy/weave/language_features/tagging/make_tag_getter_op.py similarity index 87% rename from weave/legacy/language_features/tagging/make_tag_getter_op.py rename to weave/legacy/weave/language_features/tagging/make_tag_getter_op.py index 9cb06bd9f2f..cd807c2c2ac 100644 --- a/weave/legacy/language_features/tagging/make_tag_getter_op.py +++ b/weave/legacy/weave/language_features/tagging/make_tag_getter_op.py @@ -1,12 +1,12 @@ import typing -from weave.legacy import weave_types as types -from weave.legacy import context_state as _context_state -from weave.legacy import decorator_op -from weave.legacy.language_features.tagging import tag_store, tagged_value_type +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import context_state as _context_state +from weave.legacy.weave import decorator_op +from weave.legacy.weave.language_features.tagging import tag_store, tagged_value_type if typing.TYPE_CHECKING: - from weave.legacy import op_def as OpDef + from weave.legacy.weave import op_def as OpDef def make_tag_getter_op( @@ -26,7 +26,7 @@ def make_tag_getter_op( Returns: The op. """ - from weave.legacy.arrow.list_ import ArrowWeaveList, ArrowWeaveListType + from weave.legacy.weave.arrow.list_ import ArrowWeaveList, ArrowWeaveListType _loading_builtins_token = _context_state.set_loading_built_ins() diff --git a/weave/legacy/language_features/tagging/opdef_util.py b/weave/legacy/weave/language_features/tagging/opdef_util.py similarity index 91% rename from weave/legacy/language_features/tagging/opdef_util.py rename to weave/legacy/weave/language_features/tagging/opdef_util.py index f52a748414b..2e5dee35dc4 100644 --- a/weave/legacy/language_features/tagging/opdef_util.py +++ b/weave/legacy/weave/language_features/tagging/opdef_util.py @@ -1,10 +1,10 @@ import typing -from weave.legacy import weave_types as types -from weave.legacy.language_features.tagging import tagged_value_type +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.language_features.tagging import tagged_value_type if typing.TYPE_CHECKING: - from weave.legacy import op_def as OpDef + from weave.legacy.weave import op_def as OpDef # Determines if the op_def should ftag the output with the input. Currently, this is true diff --git a/weave/legacy/language_features/tagging/process_opdef_output_type.py b/weave/legacy/weave/language_features/tagging/process_opdef_output_type.py similarity index 85% rename from weave/legacy/language_features/tagging/process_opdef_output_type.py rename to weave/legacy/weave/language_features/tagging/process_opdef_output_type.py index b9e1a65b4cc..cc9c40913a6 100644 --- a/weave/legacy/language_features/tagging/process_opdef_output_type.py +++ b/weave/legacy/weave/language_features/tagging/process_opdef_output_type.py @@ -5,21 +5,21 @@ import typing -from weave.legacy import registry_mem -from weave.legacy import weave_types as types -from weave.legacy import graph -from weave.legacy.language_features.tagging.opdef_util import ( +from weave.legacy.weave import registry_mem +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import graph +from weave.legacy.weave.language_features.tagging.opdef_util import ( should_flow_tags, should_tag_op_def_outputs, ) -from weave.legacy.language_features.tagging.tagging_op_logic import ( +from weave.legacy.weave.language_features.tagging.tagging_op_logic import ( op_get_tag_type_resolver, op_make_type_key_tag_resolver, op_make_type_tagged_resolver, ) if typing.TYPE_CHECKING: - from weave.legacy import op_def as OpDef + from weave.legacy.weave import op_def as OpDef # The following 3 functions are used to get the ops without introducing circular references diff --git a/weave/legacy/language_features/tagging/process_opdef_resolve_fn.py b/weave/legacy/weave/language_features/tagging/process_opdef_resolve_fn.py similarity index 91% rename from weave/legacy/language_features/tagging/process_opdef_resolve_fn.py rename to weave/legacy/weave/language_features/tagging/process_opdef_resolve_fn.py index 720c8db3931..86e8275df33 100644 --- a/weave/legacy/language_features/tagging/process_opdef_resolve_fn.py +++ b/weave/legacy/weave/language_features/tagging/process_opdef_resolve_fn.py @@ -11,20 +11,20 @@ import typing_extensions from pyarrow import compute as pc -from weave.legacy import weave_types as types -from weave.legacy import box -from weave.legacy.arrow.arrow_tags import awl_add_arrow_tags -from weave.legacy.arrow.list_ import ArrowWeaveList -from weave.legacy.language_features.tagging import tag_store -from weave.legacy.language_features.tagging.opdef_util import ( +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import box +from weave.legacy.weave.arrow.arrow_tags import awl_add_arrow_tags +from weave.legacy.weave.arrow.list_ import ArrowWeaveList +from weave.legacy.weave.language_features.tagging import tag_store +from weave.legacy.weave.language_features.tagging.opdef_util import ( get_first_arg, should_flow_tags, should_tag_op_def_outputs, ) -from weave.legacy.language_features.tagging.tagged_value_type import TaggedValueType +from weave.legacy.weave.language_features.tagging.tagged_value_type import TaggedValueType if typing.TYPE_CHECKING: - from weave.legacy import op_def as OpDef + from weave.legacy.weave import op_def as OpDef def _is_tagged_value(val: types.Type) -> typing_extensions.TypeGuard[TaggedValueType]: @@ -38,7 +38,7 @@ def _is_optional_tagged_value( def _strip_tags(val: typing.Any) -> typing.Any: - from weave.legacy.ops_arrow import ArrowWeaveList + from weave.legacy.weave.ops_arrow import ArrowWeaveList if isinstance(val, ArrowWeaveList): if _is_tagged_value(val.object_type): diff --git a/weave/legacy/language_features/tagging/tag_store.py b/weave/legacy/weave/language_features/tagging/tag_store.py similarity index 98% rename from weave/legacy/language_features/tagging/tag_store.py rename to weave/legacy/weave/language_features/tagging/tag_store.py index f6fea94eb79..577a446cb8c 100644 --- a/weave/legacy/language_features/tagging/tag_store.py +++ b/weave/legacy/weave/language_features/tagging/tag_store.py @@ -22,9 +22,9 @@ from collections import defaultdict from contextlib import contextmanager -from weave.legacy import errors -from weave.legacy import weave_types as types -from weave.legacy import engine_trace, box +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import engine_trace, box statsd = engine_trace.statsd() # type: ignore diff --git a/weave/legacy/language_features/tagging/tagged_value_type.py b/weave/legacy/weave/language_features/tagging/tagged_value_type.py similarity index 98% rename from weave/legacy/language_features/tagging/tagged_value_type.py rename to weave/legacy/weave/language_features/tagging/tagged_value_type.py index 9ae900a2835..3a95169fba0 100644 --- a/weave/legacy/language_features/tagging/tagged_value_type.py +++ b/weave/legacy/weave/language_features/tagging/tagged_value_type.py @@ -30,13 +30,13 @@ import json import typing -from weave.legacy import errors -from weave.legacy import weave_types as types -from weave.legacy import box, mappers, mappers_python -from weave.legacy.language_features.tagging import tag_store +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import box, mappers, mappers_python +from weave.legacy.weave.language_features.tagging import tag_store if typing.TYPE_CHECKING: - from weave.legacy import artifact_base, artifact_fs + from weave.legacy.weave import artifact_base, artifact_fs def flatten_tag_type_to_typed_dict(tag_type: types.Type) -> types.TypedDict: diff --git a/weave/legacy/language_features/tagging/tagged_value_type_helpers.py b/weave/legacy/weave/language_features/tagging/tagged_value_type_helpers.py similarity index 94% rename from weave/legacy/language_features/tagging/tagged_value_type_helpers.py rename to weave/legacy/weave/language_features/tagging/tagged_value_type_helpers.py index a5b1a83f446..2e3ab0b656c 100644 --- a/weave/legacy/language_features/tagging/tagged_value_type_helpers.py +++ b/weave/legacy/weave/language_features/tagging/tagged_value_type_helpers.py @@ -1,7 +1,7 @@ import typing -from weave.legacy import weave_types as types -from weave.legacy.language_features.tagging import tagged_value_type +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.language_features.tagging import tagged_value_type def push_down_tags_from_container_type_to_element_type( diff --git a/weave/legacy/language_features/tagging/tagging_op_logic.py b/weave/legacy/weave/language_features/tagging/tagging_op_logic.py similarity index 86% rename from weave/legacy/language_features/tagging/tagging_op_logic.py rename to weave/legacy/weave/language_features/tagging/tagging_op_logic.py index 2c2bcc04138..1d88dde0491 100644 --- a/weave/legacy/language_features/tagging/tagging_op_logic.py +++ b/weave/legacy/weave/language_features/tagging/tagging_op_logic.py @@ -1,5 +1,5 @@ -from weave.legacy import weave_types as types -from weave.legacy.language_features.tagging.tagged_value_type import TaggedValueType +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.language_features.tagging.tagged_value_type import TaggedValueType def op_get_tag_type_resolver(obj_type: types.Type) -> types.Type: diff --git a/weave/legacy/language_features/tagging/tagging_ops.py b/weave/legacy/weave/language_features/tagging/tagging_ops.py similarity index 84% rename from weave/legacy/language_features/tagging/tagging_ops.py rename to weave/legacy/weave/language_features/tagging/tagging_ops.py index abb6dfeb9aa..36e7e553d8b 100644 --- a/weave/legacy/language_features/tagging/tagging_ops.py +++ b/weave/legacy/weave/language_features/tagging/tagging_ops.py @@ -1,6 +1,6 @@ -from weave.legacy import weave_types as types -from weave.legacy import decorator_op -from weave.legacy.language_features.tagging import tagging_op_logic +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import decorator_op +from weave.legacy.weave.language_features.tagging import tagging_op_logic @decorator_op.op( diff --git a/weave/legacy/language_nullability.py b/weave/legacy/weave/language_nullability.py similarity index 83% rename from weave/legacy/language_nullability.py rename to weave/legacy/weave/language_nullability.py index 2541721b19a..c5ef29999cd 100644 --- a/weave/legacy/language_nullability.py +++ b/weave/legacy/weave/language_nullability.py @@ -1,11 +1,11 @@ import typing -from weave.legacy import weave_types as types -from weave.legacy import box -from weave.legacy.language_features.tagging import tagged_value_type +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import box +from weave.legacy.weave.language_features.tagging import tagged_value_type if typing.TYPE_CHECKING: - from weave.legacy import op_def as OpDef + from weave.legacy.weave import op_def as OpDef def should_force_none_result( diff --git a/weave/legacy/logs.py b/weave/legacy/weave/logs.py similarity index 99% rename from weave/legacy/logs.py rename to weave/legacy/weave/logs.py index 30c3127834b..a28d7c2bbf3 100644 --- a/weave/legacy/logs.py +++ b/weave/legacy/weave/logs.py @@ -12,7 +12,7 @@ from pythonjsonlogger import jsonlogger -from weave.legacy import environment +from weave.legacy.weave import environment try: from flask.logging import wsgi_errors_stream diff --git a/weave/legacy/make_type.py b/weave/legacy/weave/make_type.py similarity index 81% rename from weave/legacy/make_type.py rename to weave/legacy/weave/make_type.py index 3a39f8aa14d..69a8eb786a7 100644 --- a/weave/legacy/make_type.py +++ b/weave/legacy/weave/make_type.py @@ -1,5 +1,5 @@ -from weave.legacy import weave_internal -from weave.legacy import weave_types as types +from weave.legacy.weave import weave_internal +from weave.legacy.weave import weave_types as types # TODO: Consider if this should accept a *args, **kwargs? diff --git a/weave/legacy/mappers.py b/weave/legacy/weave/mappers.py similarity index 81% rename from weave/legacy/mappers.py rename to weave/legacy/weave/mappers.py index b7a25b0e605..28e4d4a785c 100644 --- a/weave/legacy/mappers.py +++ b/weave/legacy/weave/mappers.py @@ -1,8 +1,8 @@ import typing if typing.TYPE_CHECKING: - from weave.legacy import weave_types as types - from weave.legacy import artifact_local + from weave.legacy.weave import weave_types as types + from weave.legacy.weave import artifact_local class Mapper: diff --git a/weave/legacy/mappers_arrow.py b/weave/legacy/weave/mappers_arrow.py similarity index 98% rename from weave/legacy/mappers_arrow.py rename to weave/legacy/weave/mappers_arrow.py index f74e1ca2ba5..35d5cca157d 100644 --- a/weave/legacy/mappers_arrow.py +++ b/weave/legacy/weave/mappers_arrow.py @@ -5,9 +5,9 @@ import pyarrow as pa -from weave.legacy import errors -from weave.legacy import weave_types as types -from weave.legacy import ( +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import ( arrow_util, artifact_base, box, @@ -17,9 +17,9 @@ partial_object, ref_base, ) -from weave.legacy import mappers_python_def as mappers_python -from weave.legacy.arrow import arrow -from weave.legacy.language_features.tagging import tagged_value_type +from weave.legacy.weave import mappers_python_def as mappers_python +from weave.legacy.weave.arrow import arrow +from weave.legacy.weave.language_features.tagging import tagged_value_type _in_tagging_context = contextvars.ContextVar("in_tagging_context", default=False) diff --git a/weave/legacy/mappers_gql.py b/weave/legacy/weave/mappers_gql.py similarity index 93% rename from weave/legacy/mappers_gql.py rename to weave/legacy/weave/mappers_gql.py index 1f7da87687e..4abfbcc62b5 100644 --- a/weave/legacy/mappers_gql.py +++ b/weave/legacy/weave/mappers_gql.py @@ -1,10 +1,10 @@ import json -from weave.legacy import errors -from weave.legacy import weave_types as types -from weave.legacy import gql_json_cache, mappers -from weave.legacy.mappers_weave import UnionMapper -from weave.legacy.partial_object import PartialObjectType +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import gql_json_cache, mappers +from weave.legacy.weave.mappers_weave import UnionMapper +from weave.legacy.weave.partial_object import PartialObjectType from .mappers_python_def import ( BoolToPyBool, diff --git a/weave/legacy/mappers_publisher.py b/weave/legacy/weave/mappers_publisher.py similarity index 92% rename from weave/legacy/mappers_publisher.py rename to weave/legacy/weave/mappers_publisher.py index 7332f22c16a..2a53e30e3fa 100644 --- a/weave/legacy/mappers_publisher.py +++ b/weave/legacy/weave/mappers_publisher.py @@ -2,13 +2,13 @@ import dataclasses import typing -from weave.legacy import storage -from weave.legacy import weave_internal -from weave.legacy import weave_types as types -from weave.legacy.node_ref import ref_to_node +from weave.legacy.weave import storage +from weave.legacy.weave import weave_internal +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.node_ref import ref_to_node -# from weave.legacy.ops_primitives import weave_api -from weave.legacy import ( +# from weave.legacy.weave.ops_primitives import weave_api +from weave.legacy.weave import ( artifact_local, box, context, @@ -19,9 +19,9 @@ ref_base, errors, ) -from weave.legacy.artifact_wandb import likely_commit_hash -from weave.legacy.language_features.tagging import tag_store, tagged_value_type -from weave.legacy.uris import WeaveURI +from weave.legacy.weave.artifact_wandb import likely_commit_hash +from weave.legacy.weave.language_features.tagging import tag_store, tagged_value_type +from weave.legacy.weave.uris import WeaveURI class RefToPyRef(mappers.Mapper): @@ -128,7 +128,7 @@ def map_to_python_remote_(type, mapper, artifact, path=[], mapper_options=None): def _node_publish_mapper(node: graph.Node) -> typing.Optional[graph.Node]: - from weave.legacy.ops_primitives import weave_api + from weave.legacy.weave.ops_primitives import weave_api if _node_is_op_get(node): node = typing.cast(graph.OutputNode, node) diff --git a/weave/legacy/mappers_python.py b/weave/legacy/weave/mappers_python.py similarity index 85% rename from weave/legacy/mappers_python.py rename to weave/legacy/weave/mappers_python.py index ad3f240eb35..30b41aee953 100644 --- a/weave/legacy/mappers_python.py +++ b/weave/legacy/weave/mappers_python.py @@ -3,8 +3,8 @@ import typing if typing.TYPE_CHECKING: - from weave.legacy import weave_types - from weave.legacy import artifact_base, mappers + from weave.legacy.weave import weave_types + from weave.legacy.weave import artifact_base, mappers def map_to_python( # type: ignore[empty-body] diff --git a/weave/legacy/mappers_python_def.py b/weave/legacy/weave/mappers_python_def.py similarity index 97% rename from weave/legacy/mappers_python_def.py rename to weave/legacy/weave/mappers_python_def.py index c50bdc648ac..7951b462060 100644 --- a/weave/legacy/mappers_python_def.py +++ b/weave/legacy/weave/mappers_python_def.py @@ -4,9 +4,9 @@ import math import typing -from weave.legacy import storage -from weave.legacy import weave_types as types -from weave.legacy import ( +from weave.legacy.weave import storage +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import ( artifact_fs, box, mappers, @@ -16,9 +16,9 @@ val_const, errors, ) -from weave.legacy import timestamp as weave_timestamp -from weave.legacy.language_features.tagging import tagged_value_type -from weave.legacy.partial_object import PartialObject, PartialObjectType +from weave.legacy.weave import timestamp as weave_timestamp +from weave.legacy.weave.language_features.tagging import tagged_value_type +from weave.legacy.weave.partial_object import PartialObject, PartialObjectType from weave.trace.client_context import weave_client as weave_client_context @@ -61,7 +61,7 @@ def apply(self, obj): class ObjectDictToObject(mappers_weave.ObjectMapper): def apply(self, obj): - from weave.legacy.op_def_type import OpDefType + from weave.legacy.weave.op_def_type import OpDefType # Only add keys that are accepted by the constructor. # This is used for Panels where we have an Class-level id attribute @@ -333,7 +333,7 @@ def __init__( self._use_stable_refs = use_stable_refs def apply(self, obj): - from weave.legacy import op_def + from weave.legacy.weave import op_def try: return self.type.instance_to_dict(obj) diff --git a/weave/legacy/mappers_weave.py b/weave/legacy/weave/mappers_weave.py similarity index 95% rename from weave/legacy/mappers_weave.py rename to weave/legacy/weave/mappers_weave.py index 133e1456cce..e33916f7670 100644 --- a/weave/legacy/mappers_weave.py +++ b/weave/legacy/weave/mappers_weave.py @@ -1,8 +1,8 @@ import typing -from weave.legacy import weave_types as types -from weave.legacy import mappers -from weave.legacy.partial_object import PartialObjectType +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import mappers +from weave.legacy.weave.partial_object import PartialObjectType class TypedDictMapper(mappers.Mapper): diff --git a/weave/legacy/memo.py b/weave/legacy/weave/memo.py similarity index 97% rename from weave/legacy/memo.py rename to weave/legacy/weave/memo.py index 4928bb9b062..379a76fd035 100644 --- a/weave/legacy/memo.py +++ b/weave/legacy/weave/memo.py @@ -2,7 +2,7 @@ import contextvars import typing -from weave.legacy import engine_trace +from weave.legacy.weave import engine_trace statsd = engine_trace.statsd() # type: ignore diff --git a/weave/legacy/monitoring/__init__.py b/weave/legacy/weave/monitoring/__init__.py similarity index 58% rename from weave/legacy/monitoring/__init__.py rename to weave/legacy/weave/monitoring/__init__.py index 8a0b5fd944e..e40a17557df 100644 --- a/weave/legacy/monitoring/__init__.py +++ b/weave/legacy/weave/monitoring/__init__.py @@ -2,11 +2,11 @@ # TODO: Notebook Walkthrough -from weave.legacy.monitoring.monitor import ( +from weave.legacy.weave.monitoring.monitor import ( default_monitor, deinit_monitor, init_monitor, ) -from weave.legacy.wandb_interface.wandb_stream_table import StreamTable +from weave.legacy.weave.wandb_interface.wandb_stream_table import StreamTable __all__ = ["StreamTable", "monitor", "openai"] diff --git a/weave/legacy/monitoring/langchain.py b/weave/legacy/weave/monitoring/langchain.py similarity index 94% rename from weave/legacy/monitoring/langchain.py rename to weave/legacy/weave/monitoring/langchain.py index 8e3afddc148..84371bbefee 100644 --- a/weave/legacy/monitoring/langchain.py +++ b/weave/legacy/weave/monitoring/langchain.py @@ -11,8 +11,8 @@ from langchain.callbacks.tracers.schemas import Run from wandb.sdk.data_types import trace_tree -from weave.legacy import stream_data_interfaces -from weave.legacy.monitoring import StreamTable +from weave.legacy.weave import stream_data_interfaces +from weave.legacy.weave.monitoring import StreamTable def _hash_id(s: str) -> str: diff --git a/weave/legacy/monitoring/monitor.py b/weave/legacy/weave/monitoring/monitor.py similarity index 98% rename from weave/legacy/monitoring/monitor.py rename to weave/legacy/weave/monitoring/monitor.py index 518383ab59f..440a72d1291 100644 --- a/weave/legacy/monitoring/monitor.py +++ b/weave/legacy/weave/monitoring/monitor.py @@ -11,13 +11,13 @@ import typing import uuid -from weave.legacy import errors -from weave.legacy import ( +from weave.legacy.weave import errors +from weave.legacy.weave import ( graph, run_streamtable_span, stream_data_interfaces ) -from weave.legacy.wandb_interface.wandb_stream_table import StreamTable +from weave.legacy.weave.wandb_interface.wandb_stream_table import StreamTable from weave.trace import call_context, context as trace_context from weave.trace.client_context import weave_client as weave_client_context diff --git a/weave/legacy/monitoring/openai/__init__.py b/weave/legacy/weave/monitoring/openai/__init__.py similarity index 100% rename from weave/legacy/monitoring/openai/__init__.py rename to weave/legacy/weave/monitoring/openai/__init__.py diff --git a/weave/legacy/monitoring/openai/models.py b/weave/legacy/weave/monitoring/openai/models.py similarity index 90% rename from weave/legacy/monitoring/openai/models.py rename to weave/legacy/weave/monitoring/openai/models.py index d9688f8b281..479d497c189 100644 --- a/weave/legacy/monitoring/openai/models.py +++ b/weave/legacy/weave/monitoring/openai/models.py @@ -7,8 +7,8 @@ ) from pydantic import BaseModel, Field -from weave.legacy import weave_types as types -from weave.legacy.monitoring import monitor +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.monitoring import monitor class ModelTokensConfig(BaseModel): diff --git a/weave/legacy/monitoring/openai/openai.py b/weave/legacy/weave/monitoring/openai/openai.py similarity index 98% rename from weave/legacy/monitoring/openai/openai.py rename to weave/legacy/weave/monitoring/openai/openai.py index f41f551d994..1e2b99a3951 100644 --- a/weave/legacy/monitoring/openai/openai.py +++ b/weave/legacy/weave/monitoring/openai/openai.py @@ -12,9 +12,9 @@ from packaging import version from weave.trace import call_context from weave.trace.client_context import weave_client as weave_client_context -from weave.legacy.monitoring.monitor import _get_global_monitor -from weave.legacy.monitoring.openai.models import * -from weave.legacy.monitoring.openai.util import * +from weave.legacy.weave.monitoring.monitor import _get_global_monitor +from weave.legacy.weave.monitoring.openai.models import * +from weave.legacy.weave.monitoring.openai.util import * from weave.trace.op import Op from weave.trace.op import op as op_deco diff --git a/weave/legacy/monitoring/openai/util.py b/weave/legacy/weave/monitoring/openai/util.py similarity index 98% rename from weave/legacy/monitoring/openai/util.py rename to weave/legacy/weave/monitoring/openai/util.py index e8772fa289d..e20f2fddbb0 100644 --- a/weave/legacy/monitoring/openai/util.py +++ b/weave/legacy/weave/monitoring/openai/util.py @@ -8,7 +8,7 @@ from openai.types.chat.chat_completion_chunk import ChatCompletionChunk, Choice from openai.types.completion_usage import CompletionUsage -from weave.legacy.monitoring.openai.models import * +from weave.legacy.weave.monitoring.openai.models import * T = TypeVar("T") diff --git a/weave/legacy/node_ref.py b/weave/legacy/weave/node_ref.py similarity index 97% rename from weave/legacy/node_ref.py rename to weave/legacy/weave/node_ref.py index 47edbc6804b..2a130af4749 100644 --- a/weave/legacy/node_ref.py +++ b/weave/legacy/weave/node_ref.py @@ -1,7 +1,7 @@ import copy import typing -from weave.legacy import graph +from weave.legacy.weave import graph from . import ref_base @@ -88,7 +88,7 @@ def ref_to_node(ref: ref_base.Ref) -> typing.Optional[graph.Node]: ref = copy.copy(ref) ref.extra = [] - from weave.legacy.ops_primitives import get + from weave.legacy.weave.ops_primitives import get node = get(str(ref)) for str_key in extra: diff --git a/weave/legacy/object_context.py b/weave/legacy/weave/object_context.py similarity index 95% rename from weave/legacy/object_context.py rename to weave/legacy/weave/object_context.py index 3ed119fa154..d062a02652c 100644 --- a/weave/legacy/object_context.py +++ b/weave/legacy/weave/object_context.py @@ -12,9 +12,9 @@ from typing import Any if typing.TYPE_CHECKING: - from weave.legacy import ref_base -from weave.legacy import weave_types as types -from weave.legacy import box, uris + from weave.legacy.weave import ref_base +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import box, uris @dataclasses.dataclass @@ -90,7 +90,7 @@ def add_mutation( self.objects[target_uri].mutations.append(mutation) def finish_mutation(self, target_uri: str) -> None: - from weave.legacy import artifact_fs, artifact_local, artifact_wandb + from weave.legacy.weave import artifact_fs, artifact_local, artifact_wandb target_record = self.objects.get(target_uri) if target_record is None: @@ -115,7 +115,7 @@ def finish_mutation(self, target_uri: str) -> None: if target_branch is None: raise ValueError("No branch to finish mutation on") - from weave.legacy import artifact_wandb + from weave.legacy.weave import artifact_wandb # Hack: if the target branch looks like a commit hash, then we # don't want to use it as a branch - this is the case that we are diff --git a/weave/legacy/object_type_ref_util.py b/weave/legacy/weave/object_type_ref_util.py similarity index 97% rename from weave/legacy/object_type_ref_util.py rename to weave/legacy/weave/object_type_ref_util.py index 53787c4c454..d0bc6a1ee35 100644 --- a/weave/legacy/object_type_ref_util.py +++ b/weave/legacy/weave/object_type_ref_util.py @@ -1,7 +1,7 @@ import typing from weave.trace import ref_util -from weave.legacy import context_state +from weave.legacy.weave import context_state def make_object_getattribute( diff --git a/weave/legacy/op_aliases.py b/weave/legacy/weave/op_aliases.py similarity index 100% rename from weave/legacy/op_aliases.py rename to weave/legacy/weave/op_aliases.py diff --git a/weave/legacy/op_args.py b/weave/legacy/weave/op_args.py similarity index 98% rename from weave/legacy/op_args.py rename to weave/legacy/weave/op_args.py index 15fae9a443b..e0dd2400501 100644 --- a/weave/legacy/op_args.py +++ b/weave/legacy/weave/op_args.py @@ -1,8 +1,8 @@ import typing from dataclasses import dataclass -from weave.legacy import weave_types as types -from weave.legacy import debug_types +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import debug_types BT = typing.TypeVar("BT") diff --git a/weave/legacy/op_def.py b/weave/legacy/weave/op_def.py similarity index 97% rename from weave/legacy/op_def.py rename to weave/legacy/weave/op_def.py index 8fdfd881513..f8e397a375e 100644 --- a/weave/legacy/op_def.py +++ b/weave/legacy/weave/op_def.py @@ -6,8 +6,8 @@ import typing from typing import Iterator, Sequence -from weave.legacy import weave_types as types -from weave.legacy import ( +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import ( weave_internal, errors, context_state, @@ -22,18 +22,18 @@ pyfunc_type_util, uris, ) -from weave.legacy.language_features.tagging import ( +from weave.legacy.weave.language_features.tagging import ( opdef_util, process_opdef_output_type, process_opdef_resolve_fn, tagged_value_type, ) -from weave.legacy.run import Run -from weave.legacy.weavejs_fixes import fixup_node +from weave.legacy.weave.run import Run +from weave.legacy.weave.weavejs_fixes import fixup_node if typing.TYPE_CHECKING: from weave.trace import weave_client - from weave.legacy.run_streamtable_span import RunStreamTableSpan + from weave.legacy.weave.run_streamtable_span import RunStreamTableSpan _no_refine: contextvars.ContextVar[bool] = contextvars.ContextVar( @@ -289,7 +289,7 @@ def __call__(_self, *args, **kwargs): # convert arguments to Const nodes. There is no type checking. # May need to fix this, but the patterns in test_mutation2 work # now. - from weave.legacy import object_context + from weave.legacy.weave import object_context with object_context.object_context(): return _self.resolve_fn(*args, **kwargs) @@ -313,7 +313,7 @@ def unrefined_output_type_for_params(self, params: typing.Dict[str, graph.Node]) return self.output_type(new_input_type) def is_gql_root_resolver(self): - from weave.legacy import gql_op_plugin + from weave.legacy.weave import gql_op_plugin return self in gql_op_plugin._ROOT_RESOLVERS @@ -356,14 +356,14 @@ def _replace_var_with_val(n): tracer = engine_trace.tracer() # type: ignore with tracer.trace("refine.%s" % _self.uri): # api's use auto-creates client. TODO: Fix inline import - from weave.legacy import api as api + from weave.legacy.weave import api as api final_output_type = api.use(called_refine_output_type) # type: ignore if final_output_type == None: # This can happen due to nullability. In that case, accept the output type is null final_output_type = types.NoneType() # Have to deref if in case a ref came back... - from weave.legacy import storage + from weave.legacy.weave import storage final_output_type = storage.deref(final_output_type) @@ -374,7 +374,7 @@ def _replace_var_with_val(n): ) else: final_output_type = _self.unrefined_output_type_for_params(bound_params) - from weave.legacy import dispatch + from weave.legacy.weave import dispatch return dispatch.RuntimeOutputNode(final_output_type, _self.uri, bound_params) diff --git a/weave/legacy/op_def_type.py b/weave/legacy/weave/op_def_type.py similarity index 99% rename from weave/legacy/op_def_type.py rename to weave/legacy/weave/op_def_type.py index 8fd598aa0ca..472f1207d9f 100644 --- a/weave/legacy/op_def_type.py +++ b/weave/legacy/weave/op_def_type.py @@ -11,9 +11,9 @@ from _ast import AsyncFunctionDef, ExceptHandler from typing import Any -from weave.legacy import storage -from weave.legacy import weave_types as types -from weave.legacy import ( +from weave.legacy.weave import storage +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import ( artifact_fs, artifact_local, context_state, @@ -446,7 +446,7 @@ def load_instance(cls, artifact, name, extra=None): except FileNotFoundError: pass - from weave.legacy import artifact_wandb + from weave.legacy.weave import artifact_wandb is_wandb_artifact = False if isinstance(artifact, artifact_wandb.WandbArtifact): diff --git a/weave/legacy/op_execute.py b/weave/legacy/weave/op_execute.py similarity index 100% rename from weave/legacy/op_execute.py rename to weave/legacy/weave/op_execute.py diff --git a/weave/legacy/op_policy.py b/weave/legacy/weave/op_policy.py similarity index 100% rename from weave/legacy/op_policy.py rename to weave/legacy/weave/op_policy.py diff --git a/weave/legacy/ops.py b/weave/legacy/weave/ops.py similarity index 100% rename from weave/legacy/ops.py rename to weave/legacy/weave/ops.py diff --git a/weave/legacy/weave/ops_arrow/__init__.py b/weave/legacy/weave/ops_arrow/__init__.py new file mode 100644 index 00000000000..980f2fd2ce6 --- /dev/null +++ b/weave/legacy/weave/ops_arrow/__init__.py @@ -0,0 +1,12 @@ +from weave.legacy.weave import context_state as _context_state + +_loading_builtins_token = _context_state.set_loading_built_ins() + +from weave.legacy.weave.arrow.arrow import * +from weave.legacy.weave.arrow.convert import * +from weave.legacy.weave.arrow.list_ import * +from weave.legacy.weave.ops_arrow import ops +from weave.legacy.weave.ops_arrow.list_range import range +from weave.legacy.weave.ops_arrow.vectorize import vectorize + +_context_state.clear_loading_built_ins(_loading_builtins_token) diff --git a/weave/legacy/ops_arrow/arraylist_ops.py b/weave/legacy/weave/ops_arrow/arraylist_ops.py similarity index 96% rename from weave/legacy/ops_arrow/arraylist_ops.py rename to weave/legacy/weave/ops_arrow/arraylist_ops.py index cd0d4752f94..209cc8b0813 100644 --- a/weave/legacy/ops_arrow/arraylist_ops.py +++ b/weave/legacy/weave/ops_arrow/arraylist_ops.py @@ -3,11 +3,11 @@ import pyarrow as pa from pyarrow import compute as pc -from weave.legacy import weave_types as types -from weave.legacy.arrow.arrow import ArrowWeaveListType, arrow_as_array -from weave.legacy.arrow.list_ import ArrowWeaveList -from weave.legacy.decorator_arrow_op import arrow_op -from weave.legacy.language_features.tagging import tagged_value_type +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.arrow.arrow import ArrowWeaveListType, arrow_as_array +from weave.legacy.weave.arrow.list_ import ArrowWeaveList +from weave.legacy.weave.decorator_arrow_op import arrow_op +from weave.legacy.weave.language_features.tagging import tagged_value_type def _arrowweavelistlist_listindex_output_type(input_types): @@ -70,7 +70,7 @@ def listindex(self, index): def _list_op_output_object_type(input_types): self_type = input_types["self"] - from weave.legacy import op_def + from weave.legacy.weave import op_def def _remove_tags(t): if isinstance(t, tagged_value_type.TaggedValueType): diff --git a/weave/legacy/ops_arrow/boolean.py b/weave/legacy/weave/ops_arrow/boolean.py similarity index 93% rename from weave/legacy/ops_arrow/boolean.py rename to weave/legacy/weave/ops_arrow/boolean.py index 68b09327c61..5131f10544b 100644 --- a/weave/legacy/ops_arrow/boolean.py +++ b/weave/legacy/weave/ops_arrow/boolean.py @@ -1,11 +1,11 @@ import pyarrow as pa import pyarrow.compute as pc -from weave.legacy import weave_types as types -from weave.legacy.arrow.list_ import ArrowWeaveList, ArrowWeaveListType -from weave.legacy.decorator_arrow_op import arrow_op -from weave.legacy.decorator_op import op -from weave.legacy.ops_arrow import util +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.arrow.list_ import ArrowWeaveList, ArrowWeaveListType +from weave.legacy.weave.decorator_arrow_op import arrow_op +from weave.legacy.weave.decorator_op import op +from weave.legacy.weave.ops_arrow import util unary_input_type = { "self": ArrowWeaveListType(types.Boolean()), diff --git a/weave/legacy/ops_arrow/convert_ops.py b/weave/legacy/weave/ops_arrow/convert_ops.py similarity index 71% rename from weave/legacy/ops_arrow/convert_ops.py rename to weave/legacy/weave/ops_arrow/convert_ops.py index b2538128b42..d67eaa348c4 100644 --- a/weave/legacy/ops_arrow/convert_ops.py +++ b/weave/legacy/weave/ops_arrow/convert_ops.py @@ -1,7 +1,7 @@ -from weave.legacy import weave_types as types -from weave.legacy.api import op -from weave.legacy.arrow import convert -from weave.legacy.arrow.arrow import ArrowWeaveListType +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op +from weave.legacy.weave.arrow import convert +from weave.legacy.weave.arrow.arrow import ArrowWeaveListType @op( diff --git a/weave/legacy/ops_arrow/date.py b/weave/legacy/weave/ops_arrow/date.py similarity index 94% rename from weave/legacy/ops_arrow/date.py rename to weave/legacy/weave/ops_arrow/date.py index 9d93ee161d6..ce84f02cb52 100644 --- a/weave/legacy/ops_arrow/date.py +++ b/weave/legacy/weave/ops_arrow/date.py @@ -3,12 +3,12 @@ import pyarrow as pa import pyarrow.compute as pc -from weave.legacy import weave_types as types -from weave.legacy.api import op -from weave.legacy import timestamp as weave_timestamp -from weave.legacy.arrow.list_ import ArrowWeaveList, ArrowWeaveListType -from weave.legacy.decorator_arrow_op import arrow_op -from weave.legacy.ops_arrow import util +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op +from weave.legacy.weave import timestamp as weave_timestamp +from weave.legacy.weave.arrow.list_ import ArrowWeaveList, ArrowWeaveListType +from weave.legacy.weave.decorator_arrow_op import arrow_op +from weave.legacy.weave.ops_arrow import util ARROW_WEAVE_LIST_TIMESTAMP_TYPE = ArrowWeaveListType(types.Timestamp()) ARROW_WEAVE_LIST_BOOLEAN_TYPE = ArrowWeaveListType(types.Boolean()) diff --git a/weave/legacy/ops_arrow/dict.py b/weave/legacy/weave/ops_arrow/dict.py similarity index 96% rename from weave/legacy/ops_arrow/dict.py rename to weave/legacy/weave/ops_arrow/dict.py index 996ef2e4ffc..883d2295a43 100644 --- a/weave/legacy/ops_arrow/dict.py +++ b/weave/legacy/weave/ops_arrow/dict.py @@ -3,23 +3,23 @@ import numpy as np import pyarrow as pa -from weave.legacy import weave_types as types -from weave.legacy import _dict_utils -from weave.legacy.arrow import convert -from weave.legacy.arrow.arrow import arrow_as_array, offsets_starting_at_zero -from weave.legacy.arrow.arrow_tags import direct_add_arrow_tags -from weave.legacy.arrow.constructors import ( +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import _dict_utils +from weave.legacy.weave.arrow import convert +from weave.legacy.weave.arrow.arrow import arrow_as_array, offsets_starting_at_zero +from weave.legacy.weave.arrow.arrow_tags import direct_add_arrow_tags +from weave.legacy.weave.arrow.constructors import ( vectorized_container_constructor_preprocessor, vectorized_input_types, ) -from weave.legacy.arrow.list_ import ArrowWeaveList, ArrowWeaveListType -from weave.legacy.decorator_arrow_op import arrow_op -from weave.legacy.decorator_op import op -from weave.legacy.language_features.tagging import ( +from weave.legacy.weave.arrow.list_ import ArrowWeaveList, ArrowWeaveListType +from weave.legacy.weave.decorator_arrow_op import arrow_op +from weave.legacy.weave.decorator_op import op +from weave.legacy.weave.language_features.tagging import ( process_opdef_output_type, ) -from weave.legacy.op_args import OpVarArgs -from weave.legacy.ops_primitives import projection_utils +from weave.legacy.weave.op_args import OpVarArgs +from weave.legacy.weave.ops_primitives import projection_utils def typeddict_pick_output_type(input_types): diff --git a/weave/legacy/ops_arrow/list_join.py b/weave/legacy/weave/ops_arrow/list_join.py similarity index 93% rename from weave/legacy/ops_arrow/list_join.py rename to weave/legacy/weave/ops_arrow/list_join.py index 1f026ab61e9..2ba1ed3f158 100644 --- a/weave/legacy/ops_arrow/list_join.py +++ b/weave/legacy/weave/ops_arrow/list_join.py @@ -4,24 +4,24 @@ import pyarrow as pa import pyarrow.compute as pc -from weave.legacy import engine_trace -from weave.legacy import weave_types as types -from weave.legacy.api import op -from weave.legacy import graph -from weave.legacy.arrow import convert -from weave.legacy.arrow.arrow import ( +from weave.legacy.weave import engine_trace +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op +from weave.legacy.weave import graph +from weave.legacy.weave.arrow import convert +from weave.legacy.weave.arrow.arrow import ( ArrowWeaveListType, safe_coalesce, ) -from weave.legacy.arrow.arrow_tags import pushdown_list_tags -from weave.legacy.arrow.list_ import ( +from weave.legacy.weave.arrow.arrow_tags import pushdown_list_tags +from weave.legacy.weave.arrow.list_ import ( ArrowWeaveList, awl_zip, make_vec_dict, make_vec_taggedvalue, ) -from weave.legacy.language_features.tagging import tagged_value_type -from weave.legacy.ops_primitives import list_ as primitive_list +from weave.legacy.weave.language_features.tagging import tagged_value_type +from weave.legacy.weave.ops_primitives import list_ as primitive_list tracer = engine_trace.tracer() # type: ignore diff --git a/weave/legacy/ops_arrow/list_ops.py b/weave/legacy/weave/ops_arrow/list_ops.py similarity index 97% rename from weave/legacy/ops_arrow/list_ops.py rename to weave/legacy/weave/ops_arrow/list_ops.py index 1f034738bf9..7fabe4421d4 100644 --- a/weave/legacy/ops_arrow/list_ops.py +++ b/weave/legacy/weave/ops_arrow/list_ops.py @@ -7,34 +7,34 @@ import pyarrow as pa import pyarrow.compute as pc -from weave.legacy import weave_types as types -from weave.legacy.api import op, type_of -from weave.legacy import op_args, op_def -from weave.legacy.arrow import arrow_tags, convert -from weave.legacy.arrow.arrow import ( +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op, type_of +from weave.legacy.weave import op_args, op_def +from weave.legacy.weave.arrow import arrow_tags, convert +from weave.legacy.weave.arrow.arrow import ( ArrowWeaveListType, arrow_as_array, offsets_starting_at_zero, ) -from weave.legacy.arrow.concat import concatenate_all -from weave.legacy.arrow.constructors import ( +from weave.legacy.weave.arrow.concat import concatenate_all +from weave.legacy.weave.arrow.constructors import ( vectorized_container_constructor_preprocessor, vectorized_input_types, ) -from weave.legacy.arrow.convert import to_compare_safe -from weave.legacy.arrow.list_ import ( +from weave.legacy.weave.arrow.convert import to_compare_safe +from weave.legacy.weave.arrow.list_ import ( ArrowWeaveList, PathType, is_list_arrowweavelist, is_taggedvalue_arrowweavelist, ) -from weave.legacy.decorator_arrow_op import arrow_op -from weave.legacy.language_features.tagging import ( +from weave.legacy.weave.decorator_arrow_op import arrow_op +from weave.legacy.weave.language_features.tagging import ( tagged_value_type, tagged_value_type_helpers, ) -from weave.legacy.ops_arrow.vectorize import _apply_fn_node_with_tag_pushdown -from weave.legacy.ops_primitives import list_ as primitive_list +from weave.legacy.weave.ops_arrow.vectorize import _apply_fn_node_with_tag_pushdown +from weave.legacy.weave.ops_primitives import list_ as primitive_list FLATTEN_DELIMITER = "➡️" @@ -961,7 +961,7 @@ def flatten(arr): def _drop_tags_output_type(input_type): - from weave.legacy.op_def import map_type + from weave.legacy.weave.op_def import map_type return map_type( input_type["arr"], diff --git a/weave/legacy/ops_arrow/list_range.py b/weave/legacy/weave/ops_arrow/list_range.py similarity index 61% rename from weave/legacy/ops_arrow/list_range.py rename to weave/legacy/weave/ops_arrow/list_range.py index 064e8e29a22..3783eaa39b7 100644 --- a/weave/legacy/ops_arrow/list_range.py +++ b/weave/legacy/weave/ops_arrow/list_range.py @@ -2,9 +2,9 @@ import pyarrow as pa -from weave.legacy import weave_types as types -from weave.legacy.api import op -from weave.legacy.arrow.list_ import ArrowWeaveList +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op +from weave.legacy.weave.arrow.list_ import ArrowWeaveList py_range = range diff --git a/weave/legacy/ops_arrow/number.py b/weave/legacy/weave/ops_arrow/number.py similarity index 97% rename from weave/legacy/ops_arrow/number.py rename to weave/legacy/weave/ops_arrow/number.py index 071b4d37ec9..2d424fd08e6 100644 --- a/weave/legacy/ops_arrow/number.py +++ b/weave/legacy/weave/ops_arrow/number.py @@ -4,12 +4,12 @@ import pyarrow as pa import pyarrow.compute as pc -from weave.legacy import weave_types as types -from weave.legacy.api import op -from weave.legacy import timestamp as weave_timestamp -from weave.legacy.arrow.list_ import ArrowWeaveList, ArrowWeaveListType -from weave.legacy.decorator_arrow_op import arrow_op -from weave.legacy.ops_arrow import util +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op +from weave.legacy.weave import timestamp as weave_timestamp +from weave.legacy.weave.arrow.list_ import ArrowWeaveList, ArrowWeaveListType +from weave.legacy.weave.decorator_arrow_op import arrow_op +from weave.legacy.weave.ops_arrow import util ARROW_WEAVE_LIST_NUMBER_TYPE = ArrowWeaveListType(types.Number()) ARROW_WEAVE_LIST_BOOLEAN_TYPE = ArrowWeaveListType(types.Boolean()) diff --git a/weave/legacy/ops_arrow/obj.py b/weave/legacy/weave/ops_arrow/obj.py similarity index 72% rename from weave/legacy/ops_arrow/obj.py rename to weave/legacy/weave/ops_arrow/obj.py index 7e38e90297b..b94fd1ef576 100644 --- a/weave/legacy/ops_arrow/obj.py +++ b/weave/legacy/weave/ops_arrow/obj.py @@ -1,7 +1,7 @@ -from weave.legacy import weave_types as types -from weave.legacy.arrow.list_ import ArrowWeaveList, ArrowWeaveListType -from weave.legacy.decorator_arrow_op import arrow_op -from weave.legacy.ops_primitives import obj as primitives_obj +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.arrow.list_ import ArrowWeaveList, ArrowWeaveListType +from weave.legacy.weave.decorator_arrow_op import arrow_op +from weave.legacy.weave.ops_primitives import obj as primitives_obj @arrow_op( diff --git a/weave/legacy/weave/ops_arrow/ops.py b/weave/legacy/weave/ops_arrow/ops.py new file mode 100644 index 00000000000..452bebd2a93 --- /dev/null +++ b/weave/legacy/weave/ops_arrow/ops.py @@ -0,0 +1,11 @@ +from weave.legacy.weave.ops_arrow.arraylist_ops import * +from weave.legacy.weave.ops_arrow.boolean import * +from weave.legacy.weave.ops_arrow.convert_ops import * +from weave.legacy.weave.ops_arrow.date import * +from weave.legacy.weave.ops_arrow.dict import * +from weave.legacy.weave.ops_arrow.list_join import * +from weave.legacy.weave.ops_arrow.list_ops import * # type: ignore +from weave.legacy.weave.ops_arrow.number import * +from weave.legacy.weave.ops_arrow.obj import * +from weave.legacy.weave.ops_arrow.ref_ops import * +from weave.legacy.weave.ops_arrow.string import * diff --git a/weave/legacy/ops_arrow/ref_ops.py b/weave/legacy/weave/ops_arrow/ref_ops.py similarity index 83% rename from weave/legacy/ops_arrow/ref_ops.py rename to weave/legacy/weave/ops_arrow/ref_ops.py index d40ee05949c..9ea8f800bab 100644 --- a/weave/legacy/ops_arrow/ref_ops.py +++ b/weave/legacy/weave/ops_arrow/ref_ops.py @@ -1,11 +1,11 @@ import pyarrow as pa import pyarrow.compute as pc -from weave.legacy import weave_types as types -from weave.legacy.arrow.list_ import ArrowWeaveList, ArrowWeaveListType -from weave.legacy.decorator_arrow_op import arrow_op -from weave.legacy.decorator_op import op -from weave.legacy.ops_arrow import util +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.arrow.list_ import ArrowWeaveList, ArrowWeaveListType +from weave.legacy.weave.decorator_arrow_op import arrow_op +from weave.legacy.weave.decorator_op import op +from weave.legacy.weave.ops_arrow import util nullable_binary_input_type = { "self": ArrowWeaveListType(types.optional(types.RefType())), @@ -22,7 +22,7 @@ output_type=ArrowWeaveListType(types.Boolean()), ) def ref_equal(self, other): - from weave.legacy import storage + from weave.legacy.weave import storage # Weave engine automatically derefs, so we need to undo that via # _get_ref here. diff --git a/weave/legacy/ops_arrow/string.py b/weave/legacy/weave/ops_arrow/string.py similarity index 97% rename from weave/legacy/ops_arrow/string.py rename to weave/legacy/weave/ops_arrow/string.py index 491ad640a6e..48a8d3f8c19 100644 --- a/weave/legacy/ops_arrow/string.py +++ b/weave/legacy/weave/ops_arrow/string.py @@ -3,12 +3,12 @@ import pyarrow as pa import pyarrow.compute as pc -from weave.legacy import weave_types as types -from weave.legacy.api import op -from weave.legacy.arrow.arrow import ArrowWeaveListType, offsets_starting_at_zero -from weave.legacy.arrow.list_ import ArrowWeaveList, ArrowWeaveListType -from weave.legacy.decorator_arrow_op import arrow_op -from weave.legacy.ops_arrow import util +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op +from weave.legacy.weave.arrow.arrow import ArrowWeaveListType, offsets_starting_at_zero +from weave.legacy.weave.arrow.list_ import ArrowWeaveList, ArrowWeaveListType +from weave.legacy.weave.decorator_arrow_op import arrow_op +from weave.legacy.weave.ops_arrow import util ARROW_WEAVE_LIST_STRING_TYPE = ArrowWeaveListType(types.String()) ARROW_WEAVE_LIST_BOOLEAN_TYPE = ArrowWeaveListType(types.Boolean()) diff --git a/weave/legacy/ops_arrow/util.py b/weave/legacy/weave/ops_arrow/util.py similarity index 91% rename from weave/legacy/ops_arrow/util.py rename to weave/legacy/weave/ops_arrow/util.py index 5d515d9984a..97b12773d82 100644 --- a/weave/legacy/ops_arrow/util.py +++ b/weave/legacy/weave/ops_arrow/util.py @@ -3,15 +3,15 @@ import pyarrow as pa from pyarrow import compute as pc -from weave.legacy import weave_types as types -from weave.legacy import graph +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import graph # Reimplementation of Weave0 `toSafeCall` which # converts media to their digest def _to_compare_safe_call(node: graph.OutputNode) -> graph.OutputNode: - from weave.legacy.ops_domain.wbmedia import ArtifactAssetType - from weave.legacy.ops_primitives.dict import dict_ + from weave.legacy.weave.ops_domain.wbmedia import ArtifactAssetType + from weave.legacy.weave.ops_primitives.dict import dict_ node_type = types.non_none(node.type) if ArtifactAssetType.assign_type(node_type): diff --git a/weave/legacy/ops_arrow/vectorize.py b/weave/legacy/weave/ops_arrow/vectorize.py similarity index 97% rename from weave/legacy/ops_arrow/vectorize.py rename to weave/legacy/weave/ops_arrow/vectorize.py index 002d8c1d86d..fedd1cc5305 100644 --- a/weave/legacy/ops_arrow/vectorize.py +++ b/weave/legacy/weave/ops_arrow/vectorize.py @@ -6,18 +6,18 @@ import numpy as np import pyarrow as pa -from weave.legacy import weave_internal -from weave.legacy import errors,weavify, registry_mem -from weave.legacy import weave_types as types -from weave.legacy.api import op, use -from weave.legacy import dispatch, graph, graph_debug, op_args, op_def -from weave.legacy.arrow import convert -from weave.legacy.arrow.arrow import ArrowWeaveListType -from weave.legacy.arrow.arrow_tags import pushdown_list_tags -from weave.legacy.arrow.list_ import ArrowWeaveList -from weave.legacy.ops_arrow import arraylist_ops, convert_ops -from weave.legacy.ops_arrow.dict import preprocess_merge -from weave.legacy.ops_primitives.dict import dict_ +from weave.legacy.weave import weave_internal +from weave.legacy.weave import errors,weavify, registry_mem +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op, use +from weave.legacy.weave import dispatch, graph, graph_debug, op_args, op_def +from weave.legacy.weave.arrow import convert +from weave.legacy.weave.arrow.arrow import ArrowWeaveListType +from weave.legacy.weave.arrow.arrow_tags import pushdown_list_tags +from weave.legacy.weave.arrow.list_ import ArrowWeaveList +from weave.legacy.weave.ops_arrow import arraylist_ops, convert_ops +from weave.legacy.weave.ops_arrow.dict import preprocess_merge +from weave.legacy.weave.ops_primitives.dict import dict_ class VectorizeError(errors.WeaveBaseError): @@ -73,7 +73,7 @@ def _create_manually_mapped_op( mapped_inputs = {k: v for k, v in inputs.items() if k in vectorized_keys} rest_inputs = {k: v for k, v in inputs.items() if k not in vectorized_keys} - from weave.legacy.ops_arrow import dict + from weave.legacy.weave.ops_arrow import dict input_arr = dict.arrow_dict_(**mapped_inputs).to_py() @@ -643,7 +643,7 @@ def raise_on_python_bailout(): def _call_and_ensure_awl( awl: ArrowWeaveList, called: graph.OutputNode ) -> ArrowWeaveList: - from weave.legacy import compile + from weave.legacy.weave import compile with compile.disable_compile(): res = use(called) @@ -726,7 +726,7 @@ def _apply_fn_node(awl: ArrowWeaveList, fn: graph.OutputNode) -> ArrowWeaveList: ) return convert.to_arrow([], types.List(fn.type), artifact=awl._artifact) - from weave.legacy import execute_fast + from weave.legacy.weave import execute_fast fn = execute_fast._resolve_static_branches(fn) logging.info("Vectorizing. Static branch resolution complete.: %s", debug_str) diff --git a/weave/legacy/ops_domain/__init__.py b/weave/legacy/weave/ops_domain/__init__.py similarity index 93% rename from weave/legacy/ops_domain/__init__.py rename to weave/legacy/weave/ops_domain/__init__.py index c5760cdd35a..7cdc4cfcefb 100644 --- a/weave/legacy/ops_domain/__init__.py +++ b/weave/legacy/weave/ops_domain/__init__.py @@ -1,4 +1,4 @@ -from weave.legacy import context_state as _context_state +from weave.legacy.weave import context_state as _context_state _loading_builtins_token = _context_state.set_loading_built_ins() diff --git a/weave/legacy/ops_domain/artifact_alias_ops.py b/weave/legacy/weave/ops_domain/artifact_alias_ops.py similarity index 61% rename from weave/legacy/ops_domain/artifact_alias_ops.py rename to weave/legacy/weave/ops_domain/artifact_alias_ops.py index 140ffadfbaf..01acd1d6537 100644 --- a/weave/legacy/ops_domain/artifact_alias_ops.py +++ b/weave/legacy/weave/ops_domain/artifact_alias_ops.py @@ -1,11 +1,11 @@ -from weave.legacy import weave_types as types -from weave.legacy.api import op -from weave.legacy.gql_op_plugin import wb_gql_op_plugin -from weave.legacy.language_features.tagging.make_tag_getter_op import ( +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op +from weave.legacy.weave.gql_op_plugin import wb_gql_op_plugin +from weave.legacy.weave.language_features.tagging.make_tag_getter_op import ( make_tag_getter_op, ) -from weave.legacy.ops_domain import wb_domain_types as wdt -from weave.legacy.ops_domain.wandb_domain_gql import ( +from weave.legacy.weave.ops_domain import wb_domain_types as wdt +from weave.legacy.weave.ops_domain.wandb_domain_gql import ( gql_connection_op, gql_direct_edge_op, gql_prop_op, diff --git a/weave/legacy/ops_domain/artifact_collection_ops.py b/weave/legacy/weave/ops_domain/artifact_collection_ops.py similarity index 94% rename from weave/legacy/ops_domain/artifact_collection_ops.py rename to weave/legacy/weave/ops_domain/artifact_collection_ops.py index aaf6231a37e..ccd8dc913ea 100644 --- a/weave/legacy/ops_domain/artifact_collection_ops.py +++ b/weave/legacy/weave/ops_domain/artifact_collection_ops.py @@ -1,12 +1,12 @@ import typing import urllib -from weave.legacy import errors -from weave.legacy import weave_types as types -from weave.legacy.api import op -from weave.legacy.gql_op_plugin import wb_gql_op_plugin -from weave.legacy.ops_domain import wb_domain_types as wdt -from weave.legacy.ops_domain.wandb_domain_gql import ( +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op +from weave.legacy.weave.gql_op_plugin import wb_gql_op_plugin +from weave.legacy.weave.ops_domain import wb_domain_types as wdt +from weave.legacy.weave.ops_domain.wandb_domain_gql import ( gql_connection_op, gql_direct_edge_op, gql_prop_op, diff --git a/weave/legacy/ops_domain/artifact_membership_ops.py b/weave/legacy/weave/ops_domain/artifact_membership_ops.py similarity index 89% rename from weave/legacy/ops_domain/artifact_membership_ops.py rename to weave/legacy/weave/ops_domain/artifact_membership_ops.py index ab042265304..780ec6f93ac 100644 --- a/weave/legacy/ops_domain/artifact_membership_ops.py +++ b/weave/legacy/weave/ops_domain/artifact_membership_ops.py @@ -1,10 +1,10 @@ import urllib -from weave.legacy import weave_types as types -from weave.legacy.api import op -from weave.legacy.gql_op_plugin import wb_gql_op_plugin -from weave.legacy.ops_domain import wb_domain_types as wdt -from weave.legacy.ops_domain.wandb_domain_gql import ( +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op +from weave.legacy.weave.gql_op_plugin import wb_gql_op_plugin +from weave.legacy.weave.ops_domain import wb_domain_types as wdt +from weave.legacy.weave.ops_domain.wandb_domain_gql import ( gql_direct_edge_op, gql_prop_op, ) diff --git a/weave/legacy/ops_domain/artifact_type_ops.py b/weave/legacy/weave/ops_domain/artifact_type_ops.py similarity index 89% rename from weave/legacy/ops_domain/artifact_type_ops.py rename to weave/legacy/weave/ops_domain/artifact_type_ops.py index 4b62b70929e..64a81170436 100644 --- a/weave/legacy/ops_domain/artifact_type_ops.py +++ b/weave/legacy/weave/ops_domain/artifact_type_ops.py @@ -1,10 +1,10 @@ import typing -from weave.legacy import weave_types as types -from weave.legacy.api import op -from weave.legacy.gql_op_plugin import wb_gql_op_plugin -from weave.legacy.ops_domain import wb_domain_types as wdt -from weave.legacy.ops_domain.wandb_domain_gql import ( +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op +from weave.legacy.weave.gql_op_plugin import wb_gql_op_plugin +from weave.legacy.weave.ops_domain import wb_domain_types as wdt +from weave.legacy.weave.ops_domain.wandb_domain_gql import ( _make_alias, gql_connection_op, gql_direct_edge_op, diff --git a/weave/legacy/ops_domain/artifact_version_ops.py b/weave/legacy/weave/ops_domain/artifact_version_ops.py similarity index 96% rename from weave/legacy/ops_domain/artifact_version_ops.py rename to weave/legacy/weave/ops_domain/artifact_version_ops.py index 8203e289189..e9b8136c6f3 100644 --- a/weave/legacy/ops_domain/artifact_version_ops.py +++ b/weave/legacy/weave/ops_domain/artifact_version_ops.py @@ -2,14 +2,14 @@ import typing from urllib.parse import quote -from weave.legacy import errors -from weave.legacy import weave_types as types -from weave.legacy.api import op -from weave.legacy import artifact_fs, artifact_wandb, input_provider -from weave.legacy.gql_op_plugin import wb_gql_op_plugin -from weave.legacy.ops_domain import wb_domain_types as wdt -from weave.legacy.ops_domain import wb_util -from weave.legacy.ops_domain.wandb_domain_gql import ( +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op +from weave.legacy.weave import artifact_fs, artifact_wandb, input_provider +from weave.legacy.weave.gql_op_plugin import wb_gql_op_plugin +from weave.legacy.weave.ops_domain import wb_domain_types as wdt +from weave.legacy.weave.ops_domain import wb_util +from weave.legacy.weave.ops_domain.wandb_domain_gql import ( _make_alias, gql_connection_op, gql_direct_edge_op, @@ -460,10 +460,10 @@ def artifact_version_weave_type( def _get_history_metrics( artifactVersion: wdt.ArtifactVersion, ) -> dict[str, typing.Any]: - from weave.legacy import weave_internal - from weave.legacy.compile import enable_compile - from weave.legacy.graph import ConstNode, OutputNode - from weave.legacy.ops_domain import wb_domain_types + from weave.legacy.weave import weave_internal + from weave.legacy.weave.compile import enable_compile + from weave.legacy.weave.graph import ConstNode, OutputNode + from weave.legacy.weave.ops_domain import wb_domain_types created_by = artifactVersion["createdBy"] if created_by == None or created_by["__typename"] != "Run": diff --git a/weave/legacy/ops_domain/entity_ops.py b/weave/legacy/weave/ops_domain/entity_ops.py similarity index 82% rename from weave/legacy/ops_domain/entity_ops.py rename to weave/legacy/weave/ops_domain/entity_ops.py index 89b45216863..08c433262a9 100644 --- a/weave/legacy/ops_domain/entity_ops.py +++ b/weave/legacy/weave/ops_domain/entity_ops.py @@ -1,11 +1,11 @@ -from weave.legacy import weave_types as types -from weave.legacy.api import op -from weave.legacy.gql_op_plugin import wb_gql_op_plugin -from weave.legacy.language_features.tagging.make_tag_getter_op import ( +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op +from weave.legacy.weave.gql_op_plugin import wb_gql_op_plugin +from weave.legacy.weave.language_features.tagging.make_tag_getter_op import ( make_tag_getter_op, ) -from weave.legacy.ops_domain import wb_domain_types as wdt -from weave.legacy.ops_domain.wandb_domain_gql import ( +from weave.legacy.weave.ops_domain import wb_domain_types as wdt +from weave.legacy.weave.ops_domain.wandb_domain_gql import ( gql_connection_op, gql_direct_edge_op, gql_prop_op, diff --git a/weave/legacy/ops_domain/org_ops.py b/weave/legacy/weave/ops_domain/org_ops.py similarity index 85% rename from weave/legacy/ops_domain/org_ops.py rename to weave/legacy/weave/ops_domain/org_ops.py index c0ce7588ba0..867bc2d299a 100644 --- a/weave/legacy/ops_domain/org_ops.py +++ b/weave/legacy/weave/ops_domain/org_ops.py @@ -1,6 +1,6 @@ -from weave.legacy import weave_types as types -from weave.legacy.ops_domain import wb_domain_types as wdt -from weave.legacy.ops_domain.wandb_domain_gql import ( +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.ops_domain import wb_domain_types as wdt +from weave.legacy.weave.ops_domain.wandb_domain_gql import ( gql_connection_op, gql_direct_edge_op, gql_prop_op, diff --git a/weave/legacy/ops_domain/project_ops.py b/weave/legacy/weave/ops_domain/project_ops.py similarity index 93% rename from weave/legacy/ops_domain/project_ops.py rename to weave/legacy/weave/ops_domain/project_ops.py index b4463818c8a..297fea610b6 100644 --- a/weave/legacy/ops_domain/project_ops.py +++ b/weave/legacy/weave/ops_domain/project_ops.py @@ -1,16 +1,16 @@ import json import typing -from weave.legacy import errors -from weave.legacy import weave_types as types -from weave.legacy.api import op -from weave.legacy import input_provider -from weave.legacy.gql_op_plugin import wb_gql_op_plugin -from weave.legacy.language_features.tagging.make_tag_getter_op import ( +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op +from weave.legacy.weave import input_provider +from weave.legacy.weave.gql_op_plugin import wb_gql_op_plugin +from weave.legacy.weave.language_features.tagging.make_tag_getter_op import ( make_tag_getter_op, ) -from weave.legacy.ops_domain import wb_domain_types as wdt -from weave.legacy.ops_domain.wandb_domain_gql import ( +from weave.legacy.weave.ops_domain import wb_domain_types as wdt +from weave.legacy.weave.ops_domain.wandb_domain_gql import ( gql_connection_op, gql_direct_edge_op, gql_prop_op, diff --git a/weave/legacy/ops_domain/repo_insight_ops.py b/weave/legacy/weave/ops_domain/repo_insight_ops.py similarity index 94% rename from weave/legacy/ops_domain/repo_insight_ops.py rename to weave/legacy/weave/ops_domain/repo_insight_ops.py index 5baa89dec29..3ff32d81e1d 100644 --- a/weave/legacy/ops_domain/repo_insight_ops.py +++ b/weave/legacy/weave/ops_domain/repo_insight_ops.py @@ -1,12 +1,12 @@ import datetime import json -from weave.legacy import errors -from weave.legacy import weave_types as types -from weave.legacy.api import op -from weave.legacy.gql_json_cache import use_json -from weave.legacy.gql_op_plugin import wb_gql_op_plugin -from weave.legacy.ops_domain.wandb_domain_gql import ( +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op +from weave.legacy.weave.gql_json_cache import use_json +from weave.legacy.weave.gql_op_plugin import wb_gql_op_plugin +from weave.legacy.weave.ops_domain.wandb_domain_gql import ( _make_alias, ) diff --git a/weave/legacy/ops_domain/report_ops.py b/weave/legacy/weave/ops_domain/report_ops.py similarity index 91% rename from weave/legacy/ops_domain/report_ops.py rename to weave/legacy/weave/ops_domain/report_ops.py index f0f0db1a61d..011768ac1f9 100644 --- a/weave/legacy/ops_domain/report_ops.py +++ b/weave/legacy/weave/ops_domain/report_ops.py @@ -2,12 +2,12 @@ import typing import urllib -from weave.legacy import errors -from weave.legacy import weave_types as types -from weave.legacy.api import op -from weave.legacy.gql_op_plugin import wb_gql_op_plugin -from weave.legacy.ops_domain import wb_domain_types as wdt -from weave.legacy.ops_domain.wandb_domain_gql import ( +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op +from weave.legacy.weave.gql_op_plugin import wb_gql_op_plugin +from weave.legacy.weave.ops_domain import wb_domain_types as wdt +from weave.legacy.weave.ops_domain.wandb_domain_gql import ( gql_direct_edge_op, gql_prop_op, ) diff --git a/weave/legacy/weave/ops_domain/run_history/__init__.py b/weave/legacy/weave/ops_domain/run_history/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/weave/legacy/ops_domain/run_history/context.py b/weave/legacy/weave/ops_domain/run_history/context.py similarity index 100% rename from weave/legacy/ops_domain/run_history/context.py rename to weave/legacy/weave/ops_domain/run_history/context.py diff --git a/weave/legacy/ops_domain/run_history/history_op_common.py b/weave/legacy/weave/ops_domain/run_history/history_op_common.py similarity index 94% rename from weave/legacy/ops_domain/run_history/history_op_common.py rename to weave/legacy/weave/ops_domain/run_history/history_op_common.py index 3712e488bfc..c38dad124b2 100644 --- a/weave/legacy/ops_domain/run_history/history_op_common.py +++ b/weave/legacy/weave/ops_domain/run_history/history_op_common.py @@ -4,9 +4,9 @@ import pyarrow as pa from pyarrow import parquet as pq -from weave.legacy import weave_types as types -from weave.legacy.api import use -from weave.legacy import ( +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import use +from weave.legacy.weave import ( util, errors, engine_trace, @@ -21,17 +21,17 @@ io_service, op_args, ) -from weave.legacy.arrow.concat import concatenate_all -from weave.legacy.compile_domain import InputAndStitchProvider -from weave.legacy.compile_table import KeyTree -from weave.legacy.language_features.tagging.tagged_value_type import TaggedValueType -from weave.legacy.mappers_arrow import map_to_arrow -from weave.legacy.ops_arrow import ArrowWeaveList -from weave.legacy.ops_arrow.list_ops import concat -from weave.legacy.ops_domain import table, wb_util -from weave.legacy.ops_domain import wb_domain_types as wdt -from weave.legacy.ops_primitives import make_list -from weave.legacy.wandb_interface import wandb_stream_table +from weave.legacy.weave.arrow.concat import concatenate_all +from weave.legacy.weave.compile_domain import InputAndStitchProvider +from weave.legacy.weave.compile_table import KeyTree +from weave.legacy.weave.language_features.tagging.tagged_value_type import TaggedValueType +from weave.legacy.weave.mappers_arrow import map_to_arrow +from weave.legacy.weave.ops_arrow import ArrowWeaveList +from weave.legacy.weave.ops_arrow.list_ops import concat +from weave.legacy.weave.ops_domain import table, wb_util +from weave.legacy.weave.ops_domain import wb_domain_types as wdt +from weave.legacy.weave.ops_primitives import make_list +from weave.legacy.weave.wandb_interface import wandb_stream_table tracer = engine_trace.tracer() @@ -45,8 +45,8 @@ class TypeCount(typing.TypedDict): def history_key_type_count_to_weave_type(tc: TypeCount) -> types.Type: - from weave.legacy.ops_domain.trace_tree import WBTraceTree - from weave.legacy.ops_domain.wbmedia import ImageArtifactFileRefType + from weave.legacy.weave.ops_domain.trace_tree import WBTraceTree + from weave.legacy.weave.ops_domain.wbmedia import ImageArtifactFileRefType tc_type = tc["type"] if tc_type == "string": diff --git a/weave/legacy/ops_domain/run_history/run_history_v1_legacy_ops.py b/weave/legacy/weave/ops_domain/run_history/run_history_v1_legacy_ops.py similarity index 89% rename from weave/legacy/ops_domain/run_history/run_history_v1_legacy_ops.py rename to weave/legacy/weave/ops_domain/run_history/run_history_v1_legacy_ops.py index d12822b462b..c78fe031a41 100644 --- a/weave/legacy/ops_domain/run_history/run_history_v1_legacy_ops.py +++ b/weave/legacy/weave/ops_domain/run_history/run_history_v1_legacy_ops.py @@ -2,14 +2,14 @@ import pyarrow as pa -from weave.legacy import engine_trace -from weave.legacy import weave_types as types -from weave.legacy.api import op -from weave.legacy import gql_json_cache -from weave.legacy.gql_op_plugin import wb_gql_op_plugin -from weave.legacy.ops_domain import wb_domain_types as wdt -from weave.legacy.ops_domain import wb_util -from weave.legacy.ops_domain.run_history import history_op_common +from weave.legacy.weave import engine_trace +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op +from weave.legacy.weave import gql_json_cache +from weave.legacy.weave.gql_op_plugin import wb_gql_op_plugin +from weave.legacy.weave.ops_domain import wb_domain_types as wdt +from weave.legacy.weave.ops_domain import wb_util +from weave.legacy.weave.ops_domain.run_history import history_op_common tracer = engine_trace.tracer() diff --git a/weave/legacy/ops_domain/run_history/run_history_v2_parquet_media.py b/weave/legacy/weave/ops_domain/run_history/run_history_v2_parquet_media.py similarity index 90% rename from weave/legacy/ops_domain/run_history/run_history_v2_parquet_media.py rename to weave/legacy/weave/ops_domain/run_history/run_history_v2_parquet_media.py index db2c0a7a50f..113f9db6abe 100644 --- a/weave/legacy/ops_domain/run_history/run_history_v2_parquet_media.py +++ b/weave/legacy/weave/ops_domain/run_history/run_history_v2_parquet_media.py @@ -6,17 +6,17 @@ import pyarrow as pa -from weave.legacy import engine_trace -from weave.legacy import weave_types as types -from weave.legacy.api import op, use -from weave.legacy import artifact_mem, gql_json_cache -from weave.legacy.arrow import convert -from weave.legacy.arrow.list_ import ArrowWeaveList, ArrowWeaveListType -from weave.legacy.gql_op_plugin import wb_gql_op_plugin -from weave.legacy.ops_arrow.list_ops import concat -from weave.legacy.ops_domain import wb_domain_types as wdt -from weave.legacy.ops_domain import wb_util, wbmedia -from weave.legacy.ops_domain.run_history import history_op_common +from weave.legacy.weave import engine_trace +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op, use +from weave.legacy.weave import artifact_mem, gql_json_cache +from weave.legacy.weave.arrow import convert +from weave.legacy.weave.arrow.list_ import ArrowWeaveList, ArrowWeaveListType +from weave.legacy.weave.gql_op_plugin import wb_gql_op_plugin +from weave.legacy.weave.ops_arrow.list_ops import concat +from weave.legacy.weave.ops_domain import wb_domain_types as wdt +from weave.legacy.weave.ops_domain import wb_util, wbmedia +from weave.legacy.weave.ops_domain.run_history import history_op_common tracer = engine_trace.tracer() diff --git a/weave/legacy/ops_domain/run_history/run_history_v3_parquet_stream_optimized.py b/weave/legacy/weave/ops_domain/run_history/run_history_v3_parquet_stream_optimized.py similarity index 98% rename from weave/legacy/ops_domain/run_history/run_history_v3_parquet_stream_optimized.py rename to weave/legacy/weave/ops_domain/run_history/run_history_v3_parquet_stream_optimized.py index 0b7750ddf1b..3d8dc2fe8d1 100644 --- a/weave/legacy/ops_domain/run_history/run_history_v3_parquet_stream_optimized.py +++ b/weave/legacy/weave/ops_domain/run_history/run_history_v3_parquet_stream_optimized.py @@ -5,10 +5,10 @@ import pyarrow as pa -from weave.legacy import errors -from weave.legacy import weave_types as types -from weave.legacy.api import op -from weave.legacy import ( +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op +from weave.legacy.weave import ( engine_trace, artifact_base, artifact_fs, @@ -16,8 +16,8 @@ gql_json_cache, io_service, ) -from weave.legacy.arrow import convert -from weave.legacy.arrow.list_ import ( +from weave.legacy.weave.arrow import convert +from weave.legacy.weave.arrow.list_ import ( ArrowWeaveList, ArrowWeaveListType, PathItemType, @@ -25,16 +25,16 @@ make_vec_none, weave_arrow_type_check, ) -from weave.legacy.gql_op_plugin import wb_gql_op_plugin -from weave.legacy.op_def import map_type -from weave.legacy.ops_domain import trace_tree, wb_util, wbmedia -from weave.legacy.ops_domain import wb_domain_types as wdt -from weave.legacy.ops_domain.run_history import history_op_common -from weave.legacy.ops_domain.run_history.context import ( +from weave.legacy.weave.gql_op_plugin import wb_gql_op_plugin +from weave.legacy.weave.op_def import map_type +from weave.legacy.weave.ops_domain import trace_tree, wb_util, wbmedia +from weave.legacy.weave.ops_domain import wb_domain_types as wdt +from weave.legacy.weave.ops_domain.run_history import history_op_common +from weave.legacy.weave.ops_domain.run_history.context import ( get_error_on_non_vectorized_history_transform, ) -from weave.legacy.ops_domain.table import _patch_legacy_image_file_types -from weave.legacy.wandb_interface import wandb_stream_table +from weave.legacy.weave.ops_domain.table import _patch_legacy_image_file_types +from weave.legacy.weave.wandb_interface import wandb_stream_table tracer = engine_trace.tracer() diff --git a/weave/legacy/ops_domain/run_ops.py b/weave/legacy/weave/ops_domain/run_ops.py similarity index 95% rename from weave/legacy/ops_domain/run_ops.py rename to weave/legacy/weave/ops_domain/run_ops.py index 542f21fb665..e3bc71c970b 100644 --- a/weave/legacy/ops_domain/run_ops.py +++ b/weave/legacy/weave/ops_domain/run_ops.py @@ -37,26 +37,26 @@ import json import typing -from weave.legacy import engine_trace -from weave.legacy import weave_types as types -from weave.legacy.api import op -from weave.legacy import compile_table -from weave.legacy.gql_op_plugin import wb_gql_op_plugin -from weave.legacy.input_provider import InputAndStitchProvider -from weave.legacy.language_features.tagging.make_tag_getter_op import ( +from weave.legacy.weave import engine_trace +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op +from weave.legacy.weave import compile_table +from weave.legacy.weave.gql_op_plugin import wb_gql_op_plugin +from weave.legacy.weave.input_provider import InputAndStitchProvider +from weave.legacy.weave.language_features.tagging.make_tag_getter_op import ( make_tag_getter_op, ) -from weave.legacy.ops_domain import wb_domain_types as wdt -from weave.legacy.ops_domain import wb_util +from weave.legacy.weave.ops_domain import wb_domain_types as wdt +from weave.legacy.weave.ops_domain import wb_util # Important to re-export ops -from weave.legacy.ops_domain.run_history import ( +from weave.legacy.weave.ops_domain.run_history import ( history_op_common, run_history_v1_legacy_ops, run_history_v2_parquet_media, run_history_v3_parquet_stream_optimized, ) -from weave.legacy.ops_domain.wandb_domain_gql import ( +from weave.legacy.weave.ops_domain.wandb_domain_gql import ( _make_alias, gql_connection_op, gql_direct_edge_op, diff --git a/weave/legacy/ops_domain/run_queue_ops.py b/weave/legacy/weave/ops_domain/run_queue_ops.py similarity index 51% rename from weave/legacy/ops_domain/run_queue_ops.py rename to weave/legacy/weave/ops_domain/run_queue_ops.py index 4211cfdb5cd..77af41ac69b 100644 --- a/weave/legacy/ops_domain/run_queue_ops.py +++ b/weave/legacy/weave/ops_domain/run_queue_ops.py @@ -1,13 +1,13 @@ import json -from weave.legacy import weave_types as types -from weave.legacy.api import op -from weave.legacy.gql_op_plugin import wb_gql_op_plugin -from weave.legacy.language_features.tagging.make_tag_getter_op import ( +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op +from weave.legacy.weave.gql_op_plugin import wb_gql_op_plugin +from weave.legacy.weave.language_features.tagging.make_tag_getter_op import ( make_tag_getter_op, ) -from weave.legacy.ops_domain import wb_domain_types as wdt -from weave.legacy.ops_domain.wandb_domain_gql import ( +from weave.legacy.weave.ops_domain import wb_domain_types as wdt +from weave.legacy.weave.ops_domain.wandb_domain_gql import ( gql_connection_op, gql_direct_edge_op, gql_prop_op, diff --git a/weave/legacy/ops_domain/run_segment.py b/weave/legacy/weave/ops_domain/run_segment.py similarity index 91% rename from weave/legacy/ops_domain/run_segment.py rename to weave/legacy/weave/ops_domain/run_segment.py index 9dff1c01eaa..7924ba22340 100644 --- a/weave/legacy/ops_domain/run_segment.py +++ b/weave/legacy/weave/ops_domain/run_segment.py @@ -3,11 +3,11 @@ from typing import Optional, cast import weave -from weave.legacy import weave_types as types -from weave.legacy.api import Node, get, use -from weave.legacy import context_state as _context -from weave.legacy import panels -from weave.legacy.ops_arrow import ArrowWeaveList, ArrowWeaveListType +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import Node, get, use +from weave.legacy.weave import context_state as _context +from weave.legacy.weave import panels +from weave.legacy.weave.ops_arrow import ArrowWeaveList, ArrowWeaveListType _loading_builtins_token = _context.set_loading_built_ins() diff --git a/weave/legacy/ops_domain/stream_table_ops.py b/weave/legacy/weave/ops_domain/stream_table_ops.py similarity index 68% rename from weave/legacy/ops_domain/stream_table_ops.py rename to weave/legacy/weave/ops_domain/stream_table_ops.py index bc750f574e5..1aec716531b 100644 --- a/weave/legacy/ops_domain/stream_table_ops.py +++ b/weave/legacy/weave/ops_domain/stream_table_ops.py @@ -1,9 +1,9 @@ -from weave.legacy import weave_types -from weave.legacy.api import op -from weave.legacy import compile, op_def -from weave.legacy.arrow.arrow import ArrowWeaveListType -from weave.legacy.core_types import StreamTableType -from weave.legacy.ops_domain.project_ops import project +from weave.legacy.weave import weave_types +from weave.legacy.weave.api import op +from weave.legacy.weave import compile, op_def +from weave.legacy.weave.arrow.arrow import ArrowWeaveListType +from weave.legacy.weave.core_types import StreamTableType +from weave.legacy.weave.ops_domain.project_ops import project def _get_history_node(stream_table: StreamTableType): diff --git a/weave/legacy/ops_domain/table.py b/weave/legacy/weave/ops_domain/table.py similarity index 99% rename from weave/legacy/ops_domain/table.py rename to weave/legacy/weave/ops_domain/table.py index bef6805ad1d..b977104219d 100644 --- a/weave/legacy/ops_domain/table.py +++ b/weave/legacy/weave/ops_domain/table.py @@ -5,10 +5,10 @@ import logging import typing -from weave.legacy import weave_internal -from weave.legacy import weave_types as types -from weave.legacy.api import op, weave_class -from weave.legacy import ( +from weave.legacy.weave import weave_internal +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op, weave_class +from weave.legacy.weave import ( artifact_fs, artifact_wandb, io_service, @@ -18,8 +18,8 @@ errors, util, ) -from weave.legacy import timestamp as weave_timestamp -from weave.legacy.ops_domain import trace_tree, wbmedia +from weave.legacy.weave import timestamp as weave_timestamp +from weave.legacy.weave.ops_domain import trace_tree, wbmedia @dataclasses.dataclass(frozen=True) diff --git a/weave/legacy/ops_domain/trace_tree.py b/weave/legacy/weave/ops_domain/trace_tree.py similarity index 97% rename from weave/legacy/ops_domain/trace_tree.py rename to weave/legacy/weave/ops_domain/trace_tree.py index 595916d1028..9ff5637f956 100644 --- a/weave/legacy/ops_domain/trace_tree.py +++ b/weave/legacy/weave/ops_domain/trace_tree.py @@ -11,11 +11,11 @@ from wandb.sdk.data_types.trace_tree import Result as WBSpanResult from wandb.sdk.data_types.trace_tree import Span as WBSpan -from weave.legacy import api as weave -from weave.legacy import stream_data_interfaces -from weave.legacy import weave_types as types -from weave.legacy import op_def -from weave.legacy.decorator_op import op +from weave.legacy.weave import api as weave +from weave.legacy.weave import stream_data_interfaces +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import op_def +from weave.legacy.weave.decorator_op import op class StatusCode: diff --git a/weave/legacy/ops_domain/user_ops.py b/weave/legacy/weave/ops_domain/user_ops.py similarity index 77% rename from weave/legacy/ops_domain/user_ops.py rename to weave/legacy/weave/ops_domain/user_ops.py index 0c6527eea79..86e6d39a11e 100644 --- a/weave/legacy/ops_domain/user_ops.py +++ b/weave/legacy/weave/ops_domain/user_ops.py @@ -1,11 +1,11 @@ -from weave.legacy import weave_types as types -from weave.legacy.api import op -from weave.legacy.gql_op_plugin import wb_gql_op_plugin -from weave.legacy.language_features.tagging.make_tag_getter_op import ( +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op +from weave.legacy.weave.gql_op_plugin import wb_gql_op_plugin +from weave.legacy.weave.language_features.tagging.make_tag_getter_op import ( make_tag_getter_op, ) -from weave.legacy.ops_domain import wb_domain_types as wdt -from weave.legacy.ops_domain.wandb_domain_gql import ( +from weave.legacy.weave.ops_domain import wb_domain_types as wdt +from weave.legacy.weave.ops_domain.wandb_domain_gql import ( gql_connection_op, gql_direct_edge_op, gql_prop_op, diff --git a/weave/legacy/ops_domain/wandb_domain_gql.py b/weave/legacy/weave/ops_domain/wandb_domain_gql.py similarity index 96% rename from weave/legacy/ops_domain/wandb_domain_gql.py rename to weave/legacy/weave/ops_domain/wandb_domain_gql.py index 554e52f0651..a05a40ece28 100644 --- a/weave/legacy/ops_domain/wandb_domain_gql.py +++ b/weave/legacy/weave/ops_domain/wandb_domain_gql.py @@ -4,14 +4,14 @@ import pyarrow as pa -from weave.legacy import weave_types -from weave.legacy.api import op -from weave.legacy import errors, gql_op_plugin, op_def, partial_object -from weave.legacy.decorator_arrow_op import arrow_op -from weave.legacy.gql_op_plugin import wb_gql_op_plugin -from weave.legacy.input_provider import InputProvider -from weave.legacy.ops_arrow import ArrowWeaveList, ArrowWeaveListType -from weave.legacy.ops_domain import wb_domain_types +from weave.legacy.weave import weave_types +from weave.legacy.weave.api import op +from weave.legacy.weave import errors, gql_op_plugin, op_def, partial_object +from weave.legacy.weave.decorator_arrow_op import arrow_op +from weave.legacy.weave.gql_op_plugin import wb_gql_op_plugin +from weave.legacy.weave.input_provider import InputProvider +from weave.legacy.weave.ops_arrow import ArrowWeaveList, ArrowWeaveListType +from weave.legacy.weave.ops_domain import wb_domain_types """ This file contains utilities for constructing GQL ops (used by all the ops in diff --git a/weave/legacy/ops_domain/wb_domain_types.py b/weave/legacy/weave/ops_domain/wb_domain_types.py similarity index 97% rename from weave/legacy/ops_domain/wb_domain_types.py rename to weave/legacy/weave/ops_domain/wb_domain_types.py index b1bf98bef0d..e99912883b6 100644 --- a/weave/legacy/ops_domain/wb_domain_types.py +++ b/weave/legacy/weave/ops_domain/wb_domain_types.py @@ -1,8 +1,8 @@ import typing -from weave.legacy import weave_types as types -from weave.legacy.decorator_type import type as weave_type -from weave.legacy.partial_object import ( +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.decorator_type import type as weave_type +from weave.legacy.weave.partial_object import ( PartialObject, PartialObjectTypeGeneratorType, ) diff --git a/weave/legacy/ops_domain/wb_util.py b/weave/legacy/weave/ops_domain/wb_util.py similarity index 87% rename from weave/legacy/ops_domain/wb_util.py rename to weave/legacy/weave/ops_domain/wb_util.py index 8ba2582a2ca..9265f24777b 100644 --- a/weave/legacy/ops_domain/wb_util.py +++ b/weave/legacy/weave/ops_domain/wb_util.py @@ -2,15 +2,15 @@ from dataclasses import dataclass from urllib import parse -from weave.legacy import weave_types as types -from weave.legacy import artifact_fs, decorator_type -from weave.legacy.artifact_wandb import ( +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import artifact_fs, decorator_type +from weave.legacy.weave.artifact_wandb import ( WandbArtifact, WeaveWBLoggedArtifactURI, ) -from weave.legacy.ops_domain.run_history import history_op_common -from weave.legacy.wandb_interface import wandb_stream_table -from weave.legacy.runfiles_wandb import WandbRunFiles, WeaveWBRunFilesURI +from weave.legacy.weave.ops_domain.run_history import history_op_common +from weave.legacy.weave.wandb_interface import wandb_stream_table +from weave.legacy.weave.runfiles_wandb import WandbRunFiles, WeaveWBRunFilesURI @dataclass @@ -96,7 +96,7 @@ def _process_run_dict_item(val, run_path: typing.Optional[RunPath] = None): return _filesystem_artifact_file_from_artifact_path(val["artifact_path"]) if val["_type"] == "image-file" and run_path is not None: - from weave.legacy.ops_domain import ImageArtifactFileRef + from weave.legacy.weave.ops_domain import ImageArtifactFileRef fs_artifact_file = _filesystem_runfiles_from_run_path(run_path, val["path"]) return ImageArtifactFileRef( @@ -110,7 +110,7 @@ def _process_run_dict_item(val, run_path: typing.Optional[RunPath] = None): # masks=val.get("masks", {}), ) if val["_type"] == "audio-file" and run_path is not None: - from weave.legacy.ops_domain import AudioArtifactFileRef + from weave.legacy.weave.ops_domain import AudioArtifactFileRef fs_artifact_file = _filesystem_runfiles_from_run_path(run_path, val["path"]) return AudioArtifactFileRef( # type: ignore @@ -119,7 +119,7 @@ def _process_run_dict_item(val, run_path: typing.Optional[RunPath] = None): sha256=val["sha256"], ) if val["_type"] == "bokeh-file" and run_path is not None: - from weave.legacy.ops_domain import BokehArtifactFileRef + from weave.legacy.weave.ops_domain import BokehArtifactFileRef fs_artifact_file = _filesystem_runfiles_from_run_path(run_path, val["path"]) return BokehArtifactFileRef( # type: ignore @@ -128,7 +128,7 @@ def _process_run_dict_item(val, run_path: typing.Optional[RunPath] = None): sha256=val["sha256"], ) if val["_type"] == "video-file" and run_path is not None: - from weave.legacy.ops_domain import VideoArtifactFileRef + from weave.legacy.weave.ops_domain import VideoArtifactFileRef fs_artifact_file = _filesystem_runfiles_from_run_path(run_path, val["path"]) return VideoArtifactFileRef( # type: ignore @@ -137,7 +137,7 @@ def _process_run_dict_item(val, run_path: typing.Optional[RunPath] = None): sha256=val["sha256"], ) if val["_type"] == "object3D-file" and run_path is not None: - from weave.legacy.ops_domain import Object3DArtifactFileRef + from weave.legacy.weave.ops_domain import Object3DArtifactFileRef fs_artifact_file = _filesystem_runfiles_from_run_path(run_path, val["path"]) return Object3DArtifactFileRef( # type: ignore @@ -146,7 +146,7 @@ def _process_run_dict_item(val, run_path: typing.Optional[RunPath] = None): sha256=val["sha256"], ) if val["_type"] == "molecule-file" and run_path is not None: - from weave.legacy.ops_domain import MoleculeArtifactFileRef + from weave.legacy.weave.ops_domain import MoleculeArtifactFileRef fs_artifact_file = _filesystem_runfiles_from_run_path(run_path, val["path"]) return MoleculeArtifactFileRef( # type: ignore @@ -155,7 +155,7 @@ def _process_run_dict_item(val, run_path: typing.Optional[RunPath] = None): sha256=val["sha256"], ) if val["_type"] == "html-file" and run_path is not None: - from weave.legacy.ops_domain import HtmlArtifactFileRef + from weave.legacy.weave.ops_domain import HtmlArtifactFileRef fs_artifact_file = _filesystem_runfiles_from_run_path(run_path, val["path"]) return HtmlArtifactFileRef( # type: ignore @@ -165,7 +165,7 @@ def _process_run_dict_item(val, run_path: typing.Optional[RunPath] = None): ) if val["_type"] == "images/separated" and run_path is not None: - from weave.legacy.ops_domain import ImageArtifactFileRef + from weave.legacy.weave.ops_domain import ImageArtifactFileRef image_list: list[ImageArtifactFileRef] = [] @@ -184,7 +184,7 @@ def _process_run_dict_item(val, run_path: typing.Optional[RunPath] = None): return image_list if val["_type"] == "wb_trace_tree": - from weave.legacy.ops_domain.trace_tree import WBTraceTree + from weave.legacy.weave.ops_domain.trace_tree import WBTraceTree return WBTraceTree( root_span_dumps=val.get("root_span_dumps"), # type: ignore diff --git a/weave/legacy/ops_domain/wbgqlquery_op.py b/weave/legacy/weave/ops_domain/wbgqlquery_op.py similarity index 87% rename from weave/legacy/ops_domain/wbgqlquery_op.py rename to weave/legacy/weave/ops_domain/wbgqlquery_op.py index 4841ee249e3..74c50e2e61a 100644 --- a/weave/legacy/ops_domain/wbgqlquery_op.py +++ b/weave/legacy/weave/ops_domain/wbgqlquery_op.py @@ -1,13 +1,13 @@ import logging import typing -from weave.legacy import errors -from weave.legacy import weave_types as types -from weave.legacy.api import op -from weave.legacy import engine_trace, environment, mappers_gql, partial_object -from weave.legacy.language_features.tagging import tagged_value_type -from weave.legacy.ops_domain import wb_domain_types as wdt -from weave.legacy.wandb_client_api import wandb_gql_query +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op +from weave.legacy.weave import engine_trace, environment, mappers_gql, partial_object +from weave.legacy.weave.language_features.tagging import tagged_value_type +from weave.legacy.weave.ops_domain import wb_domain_types as wdt +from weave.legacy.weave.wandb_client_api import wandb_gql_query def _wbgqlquery_output_type(input_types: dict[str, types.Type]) -> types.Type: diff --git a/weave/legacy/ops_domain/wbmedia.py b/weave/legacy/weave/ops_domain/wbmedia.py similarity index 97% rename from weave/legacy/ops_domain/wbmedia.py rename to weave/legacy/weave/ops_domain/wbmedia.py index 32e3fe4f937..4256c0872d2 100644 --- a/weave/legacy/ops_domain/wbmedia.py +++ b/weave/legacy/weave/ops_domain/wbmedia.py @@ -4,11 +4,11 @@ import json import typing -from weave.legacy import api as weave +from weave.legacy.weave import api as weave from weave import types -from weave.legacy import errors, engine_trace, artifact_fs, file_base -from weave.legacy.language_features.tagging.tag_store import isolated_tagging_context -from weave.legacy.ops_primitives import html, markdown +from weave.legacy.weave import errors, engine_trace, artifact_fs, file_base +from weave.legacy.weave.language_features.tagging.tag_store import isolated_tagging_context +from weave.legacy.weave.ops_primitives import html, markdown class LegacyImageArtifactFileRef: @@ -283,7 +283,7 @@ class LegacyTableNDArrayType(types.Type): # code can work with it. @weave.op() def html_file(html: html.Html) -> HtmlArtifactFileRef: - from weave.legacy import storage + from weave.legacy.weave import storage # This is a ref to the html object with isolated_tagging_context(): @@ -305,7 +305,7 @@ def html_file(html: html.Html) -> HtmlArtifactFileRef: ) ) def markdown_file(md: markdown.Markdown): - from weave.legacy import storage + from weave.legacy.weave import storage with isolated_tagging_context(): ref = storage.save(md) diff --git a/weave/legacy/ops_primitives/__init__.py b/weave/legacy/weave/ops_primitives/__init__.py similarity index 92% rename from weave/legacy/ops_primitives/__init__.py rename to weave/legacy/weave/ops_primitives/__init__.py index be21b91cb3a..41990e9c7e6 100644 --- a/weave/legacy/ops_primitives/__init__.py +++ b/weave/legacy/weave/ops_primitives/__init__.py @@ -28,7 +28,7 @@ from .html import * from .markdown import * from .op_def import * -from weave.legacy.language_features.tagging.tagging_ops import * +from weave.legacy.weave.language_features.tagging.tagging_ops import * from .list_tag_getters import * from .geom import * from .server import * diff --git a/weave/legacy/ops_primitives/_dict_utils.py b/weave/legacy/weave/ops_primitives/_dict_utils.py similarity index 97% rename from weave/legacy/ops_primitives/_dict_utils.py rename to weave/legacy/weave/ops_primitives/_dict_utils.py index 066c47b8616..780257c0638 100644 --- a/weave/legacy/ops_primitives/_dict_utils.py +++ b/weave/legacy/weave/ops_primitives/_dict_utils.py @@ -1,9 +1,9 @@ import typing -from weave.legacy import errors -from weave.legacy import weave_types as types -from weave.legacy import box -from weave.legacy.language_features.tagging import tag_store, tagged_value_type +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import box +from weave.legacy.weave.language_features.tagging import tag_store, tagged_value_type def typeddict_pick_output_type(input_types): diff --git a/weave/legacy/ops_primitives/any.py b/weave/legacy/weave/ops_primitives/any.py similarity index 61% rename from weave/legacy/ops_primitives/any.py rename to weave/legacy/weave/ops_primitives/any.py index f1895ae6c2b..eb10ed9b0c1 100644 --- a/weave/legacy/ops_primitives/any.py +++ b/weave/legacy/weave/ops_primitives/any.py @@ -1,5 +1,5 @@ -from weave.legacy import weave_types as types -from weave.legacy.decorator_op import op +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.decorator_op import op @op( diff --git a/weave/legacy/ops_primitives/artifacts.py b/weave/legacy/weave/ops_primitives/artifacts.py similarity index 96% rename from weave/legacy/ops_primitives/artifacts.py rename to weave/legacy/weave/ops_primitives/artifacts.py index de1e0e0ffa9..9edd8c6e223 100644 --- a/weave/legacy/ops_primitives/artifacts.py +++ b/weave/legacy/weave/ops_primitives/artifacts.py @@ -3,10 +3,10 @@ import pathlib import typing -from weave.legacy.api import op +from weave.legacy.weave.api import op from weave import types -from weave.legacy import artifact_fs, ref_base -from weave.legacy.artifact_local import WORKING_DIR_PREFIX, LocalArtifact +from weave.legacy.weave import artifact_fs, ref_base +from weave.legacy.weave.artifact_local import WORKING_DIR_PREFIX, LocalArtifact @op(name="FilesystemArtifact-fileRefineType", hidden=True) diff --git a/weave/legacy/ops_primitives/boolean.py b/weave/legacy/weave/ops_primitives/boolean.py similarity index 92% rename from weave/legacy/ops_primitives/boolean.py rename to weave/legacy/weave/ops_primitives/boolean.py index 29c6d1ab283..b3f007a22fd 100644 --- a/weave/legacy/ops_primitives/boolean.py +++ b/weave/legacy/weave/ops_primitives/boolean.py @@ -1,9 +1,9 @@ import typing -from weave.legacy import weave_types as types -from weave.legacy.api import op, weave_class -from weave.legacy import dispatch -from weave.legacy.ops_primitives.dict import dict_ +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op, weave_class +from weave.legacy.weave import dispatch +from weave.legacy.weave.ops_primitives.dict import dict_ @weave_class(weave_type=types.Boolean) diff --git a/weave/legacy/ops_primitives/csv_.py b/weave/legacy/weave/ops_primitives/csv_.py similarity index 97% rename from weave/legacy/ops_primitives/csv_.py rename to weave/legacy/weave/ops_primitives/csv_.py index b5f4fe460fb..90a7da01bd2 100644 --- a/weave/legacy/ops_primitives/csv_.py +++ b/weave/legacy/weave/ops_primitives/csv_.py @@ -3,8 +3,8 @@ import pyarrow as pa import pyarrow.csv as pa_csv -from weave.legacy import api as weave -from weave.legacy import file_base +from weave.legacy.weave import api as weave +from weave.legacy.weave import file_base def sniff_dialect(path: str) -> type[csv.Dialect]: diff --git a/weave/legacy/ops_primitives/date.py b/weave/legacy/weave/ops_primitives/date.py similarity index 98% rename from weave/legacy/ops_primitives/date.py rename to weave/legacy/weave/ops_primitives/date.py index 08a5083bfa8..bf08300d3c0 100644 --- a/weave/legacy/ops_primitives/date.py +++ b/weave/legacy/weave/ops_primitives/date.py @@ -4,8 +4,8 @@ import dateutil import dateutil.parser -from weave.legacy import weave_types as types -from weave.legacy.api import op, type +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op, type @op( diff --git a/weave/legacy/ops_primitives/dict.py b/weave/legacy/weave/ops_primitives/dict.py similarity index 92% rename from weave/legacy/ops_primitives/dict.py rename to weave/legacy/weave/ops_primitives/dict.py index cc6e2a25233..a96a9486530 100644 --- a/weave/legacy/ops_primitives/dict.py +++ b/weave/legacy/weave/ops_primitives/dict.py @@ -1,12 +1,12 @@ import typing -from weave.legacy import weave_types as types -from weave.legacy._dict_utils import typeddict_pick_output_type -from weave.legacy.decorator_class import weave_class -from weave.legacy.decorator_op import op -from weave.legacy.language_features.tagging import tagged_value_type -from weave.legacy.op_args import OpVarArgs -from weave.legacy.ops_primitives._dict_utils import ( +from weave.legacy.weave import weave_types as types +from weave.legacy.weave._dict_utils import typeddict_pick_output_type +from weave.legacy.weave.decorator_class import weave_class +from weave.legacy.weave.decorator_op import op +from weave.legacy.weave.language_features.tagging import tagged_value_type +from weave.legacy.weave.op_args import OpVarArgs +from weave.legacy.weave.ops_primitives._dict_utils import ( tag_aware_dict_val_for_escaped_key, ) diff --git a/weave/legacy/ops_primitives/file.py b/weave/legacy/weave/ops_primitives/file.py similarity index 90% rename from weave/legacy/ops_primitives/file.py rename to weave/legacy/weave/ops_primitives/file.py index 75d37ea08db..476c953927b 100644 --- a/weave/legacy/ops_primitives/file.py +++ b/weave/legacy/weave/ops_primitives/file.py @@ -1,13 +1,13 @@ import json import typing -from weave.legacy import environment as weave_env -from weave.legacy import errors -from weave.legacy import weave_types as types -from weave.legacy.api import op -from weave.legacy import file_base, wandb_file_manager -from weave.legacy.artifact_fs import FilesystemArtifactDir, FilesystemArtifactFile -from weave.legacy.artifact_wandb import WandbArtifact, WandbArtifactManifest +from weave.legacy.weave import environment as weave_env +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op +from weave.legacy.weave import file_base, wandb_file_manager +from weave.legacy.weave.artifact_fs import FilesystemArtifactDir, FilesystemArtifactFile +from weave.legacy.weave.artifact_wandb import WandbArtifact, WandbArtifactManifest @op(name="dir-pathReturnType", hidden=True) diff --git a/weave/legacy/ops_primitives/file_artifact.py b/weave/legacy/weave/ops_primitives/file_artifact.py similarity index 87% rename from weave/legacy/ops_primitives/file_artifact.py rename to weave/legacy/weave/ops_primitives/file_artifact.py index 203e2486241..299c4e87be5 100644 --- a/weave/legacy/ops_primitives/file_artifact.py +++ b/weave/legacy/weave/ops_primitives/file_artifact.py @@ -1,7 +1,7 @@ import typing -from weave.legacy.api import op -from weave.legacy import artifact_fs +from weave.legacy.weave.api import op +from weave.legacy.weave import artifact_fs @op(name="FilesystemArtifactFile-directUrl") diff --git a/weave/legacy/ops_primitives/file_local.py b/weave/legacy/weave/ops_primitives/file_local.py similarity index 83% rename from weave/legacy/ops_primitives/file_local.py rename to weave/legacy/weave/ops_primitives/file_local.py index 022bf141e19..dbf21b4c1a6 100644 --- a/weave/legacy/ops_primitives/file_local.py +++ b/weave/legacy/weave/ops_primitives/file_local.py @@ -1,10 +1,10 @@ import os import typing -from weave.legacy import environment -from weave.legacy import weave_types as types -from weave.legacy.api import op -from weave.legacy import file_local +from weave.legacy.weave import environment +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op +from weave.legacy.weave import file_local @op(name="LocalFile-directUrl") diff --git a/weave/legacy/ops_primitives/geom.py b/weave/legacy/weave/ops_primitives/geom.py similarity index 93% rename from weave/legacy/ops_primitives/geom.py rename to weave/legacy/weave/ops_primitives/geom.py index e0931c1bd39..32264b7b9d5 100644 --- a/weave/legacy/ops_primitives/geom.py +++ b/weave/legacy/weave/ops_primitives/geom.py @@ -1,6 +1,6 @@ from PIL import Image -from weave.legacy import api as weave +from weave.legacy.weave import api as weave @weave.type() diff --git a/weave/legacy/ops_primitives/html.py b/weave/legacy/weave/ops_primitives/html.py similarity index 82% rename from weave/legacy/ops_primitives/html.py rename to weave/legacy/weave/ops_primitives/html.py index 2103ff69428..72d6d25a45d 100644 --- a/weave/legacy/ops_primitives/html.py +++ b/weave/legacy/weave/ops_primitives/html.py @@ -1,7 +1,7 @@ import dataclasses -from weave.legacy import api as weave -from weave.legacy import weave_types as types +from weave.legacy.weave import api as weave +from weave.legacy.weave import weave_types as types class HtmlType(types.Type): diff --git a/weave/legacy/ops_primitives/image.py b/weave/legacy/weave/ops_primitives/image.py similarity index 93% rename from weave/legacy/ops_primitives/image.py rename to weave/legacy/weave/ops_primitives/image.py index f44f14357ad..9432887943b 100644 --- a/weave/legacy/ops_primitives/image.py +++ b/weave/legacy/weave/ops_primitives/image.py @@ -5,8 +5,8 @@ import PIL import PIL.Image -from weave.legacy import api as weave -from weave.legacy import weave_types as types +from weave.legacy.weave import api as weave +from weave.legacy.weave import weave_types as types class ImageType(types.Type): diff --git a/weave/legacy/ops_primitives/json_.py b/weave/legacy/weave/ops_primitives/json_.py similarity index 90% rename from weave/legacy/ops_primitives/json_.py rename to weave/legacy/weave/ops_primitives/json_.py index 5cefb079741..b781daab769 100644 --- a/weave/legacy/ops_primitives/json_.py +++ b/weave/legacy/weave/ops_primitives/json_.py @@ -1,8 +1,8 @@ import json import typing -from weave.legacy import api as weave -from weave.legacy import file_base +from weave.legacy.weave import api as weave +from weave.legacy.weave import file_base def load_jsonl(jsonlfile): diff --git a/weave/legacy/ops_primitives/list_.py b/weave/legacy/weave/ops_primitives/list_.py similarity index 97% rename from weave/legacy/ops_primitives/list_.py rename to weave/legacy/weave/ops_primitives/list_.py index e61826f6003..6d80a26a62f 100644 --- a/weave/legacy/ops_primitives/list_.py +++ b/weave/legacy/weave/ops_primitives/list_.py @@ -6,20 +6,20 @@ import numpy as np import pandas as pd -from weave.legacy import storage -from weave.legacy import weave_types as types -from weave.legacy import box, execute_fast, errors -from weave.legacy._dict_utils import tag_aware_dict_val_for_escaped_key -from weave.legacy.decorator_class import weave_class -from weave.legacy.decorator_op import op -from weave.legacy.graph import Node -from weave.legacy.language_features.tagging import ( +from weave.legacy.weave import storage +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import box, execute_fast, errors +from weave.legacy.weave._dict_utils import tag_aware_dict_val_for_escaped_key +from weave.legacy.weave.decorator_class import weave_class +from weave.legacy.weave.decorator_op import op +from weave.legacy.weave.graph import Node +from weave.legacy.weave.language_features.tagging import ( tag_store, tagged_value_type, tagged_value_type_helpers, ) -from weave.legacy.op_args import OpVarArgs -from weave.legacy.ops_primitives import projection_utils +from weave.legacy.weave.op_args import OpVarArgs +from weave.legacy.weave.ops_primitives import projection_utils def getitem_output_type(input_types, list_type=types.List): @@ -392,8 +392,8 @@ def flatten_return_type(input_types): def _flatten(l): - from weave.legacy.arrow.arrow_tags import pushdown_list_tags - from weave.legacy.ops_arrow import ArrowWeaveList + from weave.legacy.weave.arrow.arrow_tags import pushdown_list_tags + from weave.legacy.weave.ops_arrow import ArrowWeaveList if isinstance(l, list): tags = None diff --git a/weave/legacy/ops_primitives/list_tag_getters.py b/weave/legacy/weave/ops_primitives/list_tag_getters.py similarity index 74% rename from weave/legacy/ops_primitives/list_tag_getters.py rename to weave/legacy/weave/ops_primitives/list_tag_getters.py index 61e57c3ae93..ca21015dc17 100644 --- a/weave/legacy/ops_primitives/list_tag_getters.py +++ b/weave/legacy/weave/ops_primitives/list_tag_getters.py @@ -1,5 +1,5 @@ -from weave.legacy import weave_types as types -from weave.legacy.language_features.tagging import make_tag_getter_op +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.language_features.tagging import make_tag_getter_op group_tag_getter_op = make_tag_getter_op.make_tag_getter_op( "groupKey", types.Any(), op_name="group-groupkey" diff --git a/weave/legacy/ops_primitives/markdown.py b/weave/legacy/weave/ops_primitives/markdown.py similarity index 82% rename from weave/legacy/ops_primitives/markdown.py rename to weave/legacy/weave/ops_primitives/markdown.py index ad3822dfdfc..b82e7e547f9 100644 --- a/weave/legacy/ops_primitives/markdown.py +++ b/weave/legacy/weave/ops_primitives/markdown.py @@ -1,7 +1,7 @@ import dataclasses -from weave.legacy import api as weave -from weave.legacy import weave_types as types +from weave.legacy.weave import api as weave +from weave.legacy.weave import weave_types as types class MarkdownType(types.Type): diff --git a/weave/legacy/ops_primitives/number.py b/weave/legacy/weave/ops_primitives/number.py similarity index 98% rename from weave/legacy/ops_primitives/number.py rename to weave/legacy/weave/ops_primitives/number.py index 2cb4aec1254..c260617c53b 100644 --- a/weave/legacy/ops_primitives/number.py +++ b/weave/legacy/weave/ops_primitives/number.py @@ -4,9 +4,9 @@ import numpy as np -from weave.legacy import weave_types as types -from weave.legacy.api import op, weave_class -from weave.legacy import timestamp as weave_timestamp +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op, weave_class +from weave.legacy.weave import timestamp as weave_timestamp binary_number_op_input_type = { "lhs": types.Number(), diff --git a/weave/legacy/ops_primitives/number_bin.py b/weave/legacy/weave/ops_primitives/number_bin.py similarity index 81% rename from weave/legacy/ops_primitives/number_bin.py rename to weave/legacy/weave/ops_primitives/number_bin.py index 97b799fcd3d..d60e531c268 100644 --- a/weave/legacy/ops_primitives/number_bin.py +++ b/weave/legacy/weave/ops_primitives/number_bin.py @@ -1,12 +1,12 @@ import math -from weave.legacy import weave_types as types -from weave.legacy.api import op, use -from weave.legacy import graph -from weave.legacy.ops_primitives import date -from weave.legacy.ops_primitives.dict import dict_ -from weave.legacy.weave_internal import call_fn, define_fn, make_const_node -from weave.legacy.weave_types import Function, NumberBinType +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op, use +from weave.legacy.weave import graph +from weave.legacy.weave.ops_primitives import date +from weave.legacy.weave.ops_primitives.dict import dict_ +from weave.legacy.weave.weave_internal import call_fn, define_fn, make_const_node +from weave.legacy.weave.weave_types import Function, NumberBinType @op( diff --git a/weave/legacy/ops_primitives/obj.py b/weave/legacy/weave/ops_primitives/obj.py similarity index 93% rename from weave/legacy/ops_primitives/obj.py rename to weave/legacy/weave/ops_primitives/obj.py index 615fe8eea3f..35e24284d2c 100644 --- a/weave/legacy/ops_primitives/obj.py +++ b/weave/legacy/weave/ops_primitives/obj.py @@ -1,8 +1,8 @@ import typing -from weave.legacy import codify -from weave.legacy import weave_types as types -from weave.legacy.api import op, weave_class +from weave.legacy.weave import codify +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op, weave_class # This matches the output type logic of the frontend diff --git a/weave/legacy/ops_primitives/op_def.py b/weave/legacy/weave/ops_primitives/op_def.py similarity index 68% rename from weave/legacy/ops_primitives/op_def.py rename to weave/legacy/weave/ops_primitives/op_def.py index 81caf0be0e2..1d7458476fe 100644 --- a/weave/legacy/ops_primitives/op_def.py +++ b/weave/legacy/weave/ops_primitives/op_def.py @@ -1,7 +1,7 @@ -from weave.legacy import api as weave -from weave.legacy import weave_types as types -from weave.legacy.op_def import OpDef -from weave.legacy.op_def_type import OpDefType +from weave.legacy.weave import api as weave +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.op_def import OpDef +from weave.legacy.weave.op_def_type import OpDefType @weave.weave_class(weave_type=OpDefType) diff --git a/weave/legacy/ops_primitives/pandas_.py b/weave/legacy/weave/ops_primitives/pandas_.py similarity index 97% rename from weave/legacy/ops_primitives/pandas_.py rename to weave/legacy/weave/ops_primitives/pandas_.py index 97a9f30c2db..d1e286ed931 100644 --- a/weave/legacy/ops_primitives/pandas_.py +++ b/weave/legacy/weave/ops_primitives/pandas_.py @@ -8,12 +8,12 @@ import pyarrow as pa import pyarrow.parquet as pq -from weave.legacy import errors -from weave.legacy import weave_types as types -from weave.legacy.api import op, weave_class -from weave.legacy import box, file_base, graph, mappers_python -from weave.legacy.language_features.tagging import tag_store, tagged_value_type -from weave.legacy.ops_primitives import list_ +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op, weave_class +from weave.legacy.weave import box, file_base, graph, mappers_python +from weave.legacy.weave.language_features.tagging import tag_store, tagged_value_type +from weave.legacy.weave.ops_primitives import list_ # Hack hack hack diff --git a/weave/legacy/ops_primitives/projection_utils.py b/weave/legacy/weave/ops_primitives/projection_utils.py similarity index 98% rename from weave/legacy/ops_primitives/projection_utils.py rename to weave/legacy/weave/ops_primitives/projection_utils.py index 49e96d1e562..127c41d8773 100644 --- a/weave/legacy/ops_primitives/projection_utils.py +++ b/weave/legacy/weave/ops_primitives/projection_utils.py @@ -9,8 +9,8 @@ from sklearn.decomposition import PCA from sklearn.manifold import TSNE -from weave.legacy import errors -from weave.legacy import context_state, environment +from weave.legacy.weave import errors +from weave.legacy.weave import context_state, environment umap_lib = {} diff --git a/weave/legacy/ops_primitives/random_junk.py b/weave/legacy/weave/ops_primitives/random_junk.py similarity index 82% rename from weave/legacy/ops_primitives/random_junk.py rename to weave/legacy/weave/ops_primitives/random_junk.py index e77ffe0a48b..b158c1221ab 100644 --- a/weave/legacy/ops_primitives/random_junk.py +++ b/weave/legacy/weave/ops_primitives/random_junk.py @@ -1,8 +1,8 @@ # Ideas for ops, but not production ready. -from weave.legacy import api as api -from weave.legacy import weave_types as types -from weave.legacy.api import op, weave_class +from weave.legacy.weave import api as api +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op, weave_class op( name="root-compare_versions", diff --git a/weave/legacy/ops_primitives/server.py b/weave/legacy/weave/ops_primitives/server.py similarity index 76% rename from weave/legacy/ops_primitives/server.py rename to weave/legacy/weave/ops_primitives/server.py index ccc93e6762d..536343a5d9f 100644 --- a/weave/legacy/ops_primitives/server.py +++ b/weave/legacy/weave/ops_primitives/server.py @@ -1,4 +1,4 @@ -from weave.legacy.decorator_op import op +from weave.legacy.weave.decorator_op import op from weave.version import VERSION diff --git a/weave/legacy/ops_primitives/set_.py b/weave/legacy/weave/ops_primitives/set_.py similarity index 94% rename from weave/legacy/ops_primitives/set_.py rename to weave/legacy/weave/ops_primitives/set_.py index d64e7e9f845..f73d5627709 100644 --- a/weave/legacy/ops_primitives/set_.py +++ b/weave/legacy/weave/ops_primitives/set_.py @@ -1,5 +1,5 @@ -from weave.legacy import weave_types as types -from weave.legacy.decorators import op +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.decorators import op def get_const_union_vals(type_, of_type): diff --git a/weave/legacy/ops_primitives/sql.py b/weave/legacy/weave/ops_primitives/sql.py similarity index 97% rename from weave/legacy/ops_primitives/sql.py rename to weave/legacy/weave/ops_primitives/sql.py index 7c05a41a213..f4f78567744 100644 --- a/weave/legacy/ops_primitives/sql.py +++ b/weave/legacy/weave/ops_primitives/sql.py @@ -2,11 +2,11 @@ import functools import math -from weave.legacy import weave_types as types -from weave.legacy.api import op, weave_class -from weave.legacy import decorator_type -from weave.legacy.language_features.tagging import tagged_value_type -from weave.legacy.ops_primitives import graph, list_ +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op, weave_class +from weave.legacy.weave import decorator_type +from weave.legacy.weave.language_features.tagging import tagged_value_type +from weave.legacy.weave.ops_primitives import graph, list_ try: import sqlalchemy diff --git a/weave/legacy/ops_primitives/string.py b/weave/legacy/weave/ops_primitives/string.py similarity index 98% rename from weave/legacy/ops_primitives/string.py rename to weave/legacy/weave/ops_primitives/string.py index db86ae6d233..6f0433f801f 100644 --- a/weave/legacy/ops_primitives/string.py +++ b/weave/legacy/weave/ops_primitives/string.py @@ -4,8 +4,8 @@ import numpy as np -from weave.legacy import weave_types as types -from weave.legacy.api import op, weave_class +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op, weave_class @op(name="root-string") diff --git a/weave/legacy/ops_primitives/test_any.py b/weave/legacy/weave/ops_primitives/test_any.py similarity index 73% rename from weave/legacy/ops_primitives/test_any.py rename to weave/legacy/weave/ops_primitives/test_any.py index 4fd7cd14952..95d2c93c2af 100644 --- a/weave/legacy/ops_primitives/test_any.py +++ b/weave/legacy/weave/ops_primitives/test_any.py @@ -2,9 +2,9 @@ import pytest -from weave.legacy import api as weave -from weave.legacy import box -from weave.legacy.ops_primitives import any +from weave.legacy.weave import api as weave +from weave.legacy.weave import box +from weave.legacy.weave.ops_primitives import any cases: list[typing.Tuple[typing.Any, bool]] = [ (1, False), diff --git a/weave/legacy/ops_primitives/test_dict.py b/weave/legacy/weave/ops_primitives/test_dict.py similarity index 80% rename from weave/legacy/ops_primitives/test_dict.py rename to weave/legacy/weave/ops_primitives/test_dict.py index 165a714a3ee..04a85b7509b 100644 --- a/weave/legacy/ops_primitives/test_dict.py +++ b/weave/legacy/weave/ops_primitives/test_dict.py @@ -1,6 +1,6 @@ import weave -from weave.legacy import weave_internal -from weave.legacy.language_features.tagging import tagged_value_type +from weave.legacy.weave import weave_internal +from weave.legacy.weave.language_features.tagging import tagged_value_type def test_keys_type(): @@ -25,7 +25,7 @@ def test_pick(): ), "a", ) - assert weave.use(weave.legacy.ops.TypedDict.pick(obj, key)) == "x" + assert weave.use(weave.legacy.weave.ops.TypedDict.pick(obj, key)) == "x" def test_pick_none_key(): diff --git a/weave/legacy/ops_primitives/test_file.py b/weave/legacy/weave/ops_primitives/test_file.py similarity index 54% rename from weave/legacy/ops_primitives/test_file.py rename to weave/legacy/weave/ops_primitives/test_file.py index 2715f67a579..247beb744f5 100644 --- a/weave/legacy/ops_primitives/test_file.py +++ b/weave/legacy/weave/ops_primitives/test_file.py @@ -1,8 +1,8 @@ import weave -from weave.legacy.ops_primitives import file_local +from weave.legacy.weave.ops_primitives import file_local def test_file_browsing(): - test_dir = weave.legacy.ops.local_path("./testdata/").path("test_dir") + test_dir = weave.legacy.weave.ops.local_path("./testdata/").path("test_dir") assert test_dir.type == file_local.LocalDirType() assert weave.use(test_dir.path("b.txt").contents()) == "howdy\n" diff --git a/weave/legacy/ops_primitives/test_image.py b/weave/legacy/weave/ops_primitives/test_image.py similarity index 89% rename from weave/legacy/ops_primitives/test_image.py rename to weave/legacy/weave/ops_primitives/test_image.py index 12c0e7868fe..66e17caac85 100644 --- a/weave/legacy/ops_primitives/test_image.py +++ b/weave/legacy/weave/ops_primitives/test_image.py @@ -2,8 +2,8 @@ import pytest from PIL import Image -from weave.legacy import storage -from weave.legacy.ops_primitives import api as weave +from weave.legacy.weave import storage +from weave.legacy.weave.ops_primitives import api as weave def test_image(): diff --git a/weave/legacy/ops_primitives/test_list.py b/weave/legacy/weave/ops_primitives/test_list.py similarity index 96% rename from weave/legacy/ops_primitives/test_list.py rename to weave/legacy/weave/ops_primitives/test_list.py index e9e99073bb0..f2bf31f7cd4 100644 --- a/weave/legacy/ops_primitives/test_list.py +++ b/weave/legacy/weave/ops_primitives/test_list.py @@ -1,15 +1,15 @@ import pytest -from weave.legacy import api as weave -from weave.legacy import weave_internal -from weave.legacy import weave_types as types -from weave.legacy import box -from weave.legacy.language_features.tagging import ( +from weave.legacy.weave import api as weave +from weave.legacy.weave import weave_internal +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import box +from weave.legacy.weave.language_features.tagging import ( make_tag_getter_op, tag_store, tagged_value_type, ) -from weave.legacy.ops_primitives import dict, errors, list_, number, runs +from weave.legacy.weave.ops_primitives import dict, errors, list_, number, runs from weave.legacy.tests.util import geom, weavejs_ops diff --git a/weave/legacy/weave/ops_primitives/test_list_range.py b/weave/legacy/weave/ops_primitives/test_list_range.py new file mode 100644 index 00000000000..d821293f33d --- /dev/null +++ b/weave/legacy/weave/ops_primitives/test_list_range.py @@ -0,0 +1,7 @@ +import pytest + +import weave + + +def test_range(): + assert weave.use(weave.legacy.weave.ops.range(0, 3, 1)).to_pylist_tagged() == [0, 1, 2] diff --git a/weave/legacy/ops_primitives/test_pandas.py b/weave/legacy/weave/ops_primitives/test_pandas.py similarity index 85% rename from weave/legacy/ops_primitives/test_pandas.py rename to weave/legacy/weave/ops_primitives/test_pandas.py index 835aeba71f8..f6977800091 100644 --- a/weave/legacy/ops_primitives/test_pandas.py +++ b/weave/legacy/weave/ops_primitives/test_pandas.py @@ -1,8 +1,8 @@ import pandas as pd -from weave.legacy import api as weave -from weave.legacy import weave_types as types -from weave.legacy.ops_primitives import pandas_ as op_pandas +from weave.legacy.weave import api as weave +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.ops_primitives import pandas_ as op_pandas def test_save_dataframe(): diff --git a/weave/legacy/ops_primitives/test_set.py b/weave/legacy/weave/ops_primitives/test_set.py similarity index 89% rename from weave/legacy/ops_primitives/test_set.py rename to weave/legacy/weave/ops_primitives/test_set.py index 2fb0ffebbf4..96b2048a7df 100644 --- a/weave/legacy/ops_primitives/test_set.py +++ b/weave/legacy/weave/ops_primitives/test_set.py @@ -1,5 +1,5 @@ import weave -from weave.legacy import ops_primitives, val_const +from weave.legacy.weave import ops_primitives, val_const def test_difference_type(): diff --git a/weave/legacy/ops_primitives/test_type.py b/weave/legacy/weave/ops_primitives/test_type.py similarity index 79% rename from weave/legacy/ops_primitives/test_type.py rename to weave/legacy/weave/ops_primitives/test_type.py index a2dff5d9c96..4240de94abf 100644 --- a/weave/legacy/ops_primitives/test_type.py +++ b/weave/legacy/weave/ops_primitives/test_type.py @@ -4,11 +4,11 @@ def test_cast_basic(): - valid_cast = weave.legacy.ops.cast(1, weave.types.Int()) + valid_cast = weave.legacy.weave.ops.cast(1, weave.types.Int()) assert valid_cast.type == weave.types.Int() assert weave.use(valid_cast) == 1 - invalid_cast = weave.legacy.ops.cast(1, weave.types.String()) + invalid_cast = weave.legacy.weave.ops.cast(1, weave.types.String()) assert invalid_cast.type == weave.types.String() with pytest.raises(weave.errors.WeaveTypeError): weave.use(invalid_cast) diff --git a/weave/legacy/ops_primitives/test_typeddict.py b/weave/legacy/weave/ops_primitives/test_typeddict.py similarity index 96% rename from weave/legacy/ops_primitives/test_typeddict.py rename to weave/legacy/weave/ops_primitives/test_typeddict.py index 2818487c9fb..6f57ee0ef8a 100644 --- a/weave/legacy/ops_primitives/test_typeddict.py +++ b/weave/legacy/weave/ops_primitives/test_typeddict.py @@ -1,10 +1,10 @@ import pytest import weave -from weave.legacy import weave_internal -from weave.legacy import box -from weave.legacy.arrow.arrow import ArrowWeaveListType -from weave.legacy.language_features.tagging import tag_store, tagged_value_type +from weave.legacy.weave import weave_internal +from weave.legacy.weave import box +from weave.legacy.weave.arrow.arrow import ArrowWeaveListType +from weave.legacy.weave.language_features.tagging import tag_store, tagged_value_type from weave.legacy.tests.util.list_arrow_test_helpers import ArrowNode pick_options = [ diff --git a/weave/legacy/ops_primitives/timestamp_bin.py b/weave/legacy/weave/ops_primitives/timestamp_bin.py similarity index 86% rename from weave/legacy/ops_primitives/timestamp_bin.py rename to weave/legacy/weave/ops_primitives/timestamp_bin.py index ce5b3e1097b..0263ec39fe6 100644 --- a/weave/legacy/ops_primitives/timestamp_bin.py +++ b/weave/legacy/weave/ops_primitives/timestamp_bin.py @@ -1,10 +1,10 @@ -from weave.legacy import weave_internal -from weave.legacy import weave_types as types -from weave.legacy.api import op, use -from weave.legacy import graph -from weave.legacy.ops_primitives.dict import dict_ -from weave.legacy.weave_internal import call_fn, define_fn, make_const_node -from weave.legacy.weave_types import Function, TimestampBinType +from weave.legacy.weave import weave_internal +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op, use +from weave.legacy.weave import graph +from weave.legacy.weave.ops_primitives.dict import dict_ +from weave.legacy.weave.weave_internal import call_fn, define_fn, make_const_node +from weave.legacy.weave.weave_types import Function, TimestampBinType NICE_BIN_SIZES_SEC = [ # TODO: will need more steps along here for smooth zooming. diff --git a/weave/legacy/ops_primitives/type.py b/weave/legacy/weave/ops_primitives/type.py similarity index 85% rename from weave/legacy/ops_primitives/type.py rename to weave/legacy/weave/ops_primitives/type.py index 4b39df3143e..a2575507f75 100644 --- a/weave/legacy/ops_primitives/type.py +++ b/weave/legacy/weave/ops_primitives/type.py @@ -1,8 +1,8 @@ import typing -from weave.legacy import errors -from weave.legacy import weave_types as types -from weave.legacy.api import op +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import op @op( diff --git a/weave/legacy/ops_primitives/weave_api.py b/weave/legacy/weave/ops_primitives/weave_api.py similarity index 99% rename from weave/legacy/ops_primitives/weave_api.py rename to weave/legacy/weave/ops_primitives/weave_api.py index 1b760c9b5dc..6912fca77ef 100644 --- a/weave/legacy/ops_primitives/weave_api.py +++ b/weave/legacy/weave/ops_primitives/weave_api.py @@ -2,9 +2,9 @@ import time import typing -from weave.legacy import weave_types as types -from weave.legacy.api import mutation, op, weave_class -from weave.legacy import ( +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.api import mutation, op, weave_class +from weave.legacy.weave import ( storage, weave_internal, errors, @@ -20,7 +20,7 @@ trace_legacy, uris, ) -from weave.legacy.graph import Node +from weave.legacy.weave.graph import Node @weave_class(weave_type=types.RefType) @@ -633,7 +633,7 @@ def append( @op(mutation=True, name="stream_table-log") def stream_table_log(self: graph.Node, val: typing.Any) -> typing.Any: st_obj = weave_internal.use(self) - from weave.legacy.monitoring import StreamTable + from weave.legacy.weave.monitoring import StreamTable if not isinstance(st_obj, StreamTable): raise errors.WeaveInternalError( diff --git a/weave/legacy/panel.py b/weave/legacy/weave/panel.py similarity index 95% rename from weave/legacy/panel.py rename to weave/legacy/weave/panel.py index 87af22bca47..4938235861e 100644 --- a/weave/legacy/panel.py +++ b/weave/legacy/weave/panel.py @@ -3,10 +3,10 @@ import typing from tarfile import DEFAULT_FORMAT -from weave.legacy import api as weave -from weave.legacy import weave_internal -from weave.legacy import weave_types as types -from weave.legacy import graph, panel_util, errors, storage +from weave.legacy.weave import api as weave +from weave.legacy.weave import weave_internal +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import graph, panel_util, errors, storage def run_variable_lambdas( @@ -157,6 +157,6 @@ def to_json(self): } def _ipython_display_(self): - from weave.legacy import show + from weave.legacy.weave import show show.show(self) diff --git a/weave/legacy/panel_util.py b/weave/legacy/weave/panel_util.py similarity index 80% rename from weave/legacy/panel_util.py rename to weave/legacy/weave/panel_util.py index 5c86926c92e..87c28b25f1d 100644 --- a/weave/legacy/panel_util.py +++ b/weave/legacy/weave/panel_util.py @@ -1,12 +1,12 @@ import typing -from weave.legacy import weave_types -from weave.legacy import storage, graph, panel +from weave.legacy.weave import weave_types +from weave.legacy.weave import storage, graph, panel def make_node(v: typing.Any) -> graph.Node: """Business logic for how values passed to panels are converted to json.""" - from weave.legacy import ops + from weave.legacy.weave import ops if isinstance(v, graph.Node): return v diff --git a/weave/legacy/weave/panels/__init__.py b/weave/legacy/weave/panels/__init__.py new file mode 100644 index 00000000000..1ba950300b7 --- /dev/null +++ b/weave/legacy/weave/panels/__init__.py @@ -0,0 +1,70 @@ +from weave.legacy.weave import context_state as _context_state + +_loading_builtins_token = _context_state.set_loading_built_ins() + +from weave.legacy.weave.panels.panel_auto import * + +# basic +from weave.legacy.weave.panels.panel_basic import * + +# top level board +from weave.legacy.weave.panels.panel_board import Board, BoardPanel, BoardPanelLayout +from weave.legacy.weave.panels.panel_card import Card, CardTab +from weave.legacy.weave.panels.panel_color import Color +from weave.legacy.weave.panels.panel_daterange import DateRange + +# domain +from weave.legacy.weave.panels.panel_domain import * +from weave.legacy.weave.panels.panel_dropdown import Dropdown, DropdownConfig +from weave.legacy.weave.panels.panel_each import Each +from weave.legacy.weave.panels.panel_each_column import EachColumn + +# special +from weave.legacy.weave.panels.panel_expression import * +from weave.legacy.weave.panels.panel_facet import Facet +from weave.legacy.weave.panels.panel_facet_tabs import FacetTabs +from weave.legacy.weave.panels.panel_filter_editor import FilterEditor +from weave.legacy.weave.panels.panel_function_editor import ( + FunctionEditor, + FunctionEditorConfig, +) +from weave.legacy.weave.panels.panel_group import ( + Group, + GroupLayoutFlow, + GroupPanel, + GroupPanelLayout, +) +from weave.legacy.weave.panels.panel_grouping_editor import GroupingEditor + +# Incomplete +from weave.legacy.weave.panels.panel_histogram import * +from weave.legacy.weave.panels.panel_html import PanelHtml + +# layout +from weave.legacy.weave.panels.panel_labeled_item import LabeledItem + +# legacy +from weave.legacy.weave.panels.panel_legacy import * +from weave.legacy.weave.panels.panel_markdown import PanelMarkdown + +# Non-standard editor (todo: update) +from weave.legacy.weave.panels.panel_object_picker import ObjectPicker, ObjectPickerConfig +from weave.legacy.weave.panels.panel_plot import Plot, PlotConstants, Series + +# sidebar specific +from weave.legacy.weave.panels.panel_query import Query, QueryCondition, QueryConfig +from weave.legacy.weave.panels.panel_sections import Sections +from weave.legacy.weave.panels.panel_select import SelectEditor, SelectEditorConfig + +# editors +from weave.legacy.weave.panels.panel_slider import Slider, SliderConfig +from weave.legacy.weave.panels.panel_string import PanelString +from weave.legacy.weave.panels.panel_string_editor import StringEditor +from weave.legacy.weave.panels.panel_table import ColumnDef, Table, TableColumn +from weave.legacy.weave.panels.panel_trace import Trace + +# navigation +from weave.legacy.weave.panels.panel_weavelink import WeaveLink +from weave.legacy.weave.panel import Panel + +_context_state.clear_loading_built_ins(_loading_builtins_token) diff --git a/weave/legacy/panels/bank.py b/weave/legacy/weave/panels/bank.py similarity index 93% rename from weave/legacy/panels/bank.py rename to weave/legacy/weave/panels/bank.py index b5762d9fe38..0568ae389c2 100644 --- a/weave/legacy/panels/bank.py +++ b/weave/legacy/weave/panels/bank.py @@ -1,6 +1,6 @@ # TODO: move all panelbank stuff here -from weave.legacy.panels import panel_group +from weave.legacy.weave.panels import panel_group def default_panel_bank_flow_section_config(): diff --git a/weave/legacy/panels/panel_auto.py b/weave/legacy/weave/panels/panel_auto.py similarity index 77% rename from weave/legacy/panels/panel_auto.py rename to weave/legacy/weave/panels/panel_auto.py index a50fe9f4170..f97027755b9 100644 --- a/weave/legacy/panels/panel_auto.py +++ b/weave/legacy/weave/panels/panel_auto.py @@ -1,5 +1,5 @@ import weave -from weave.legacy import panel +from weave.legacy.weave import panel # Currently Auto is not a real panel, the system handles it. diff --git a/weave/legacy/panels/panel_basic.py b/weave/legacy/weave/panels/panel_basic.py similarity index 84% rename from weave/legacy/panels/panel_basic.py rename to weave/legacy/weave/panels/panel_basic.py index ffabed4b613..8ae26009cf2 100644 --- a/weave/legacy/panels/panel_basic.py +++ b/weave/legacy/weave/panels/panel_basic.py @@ -1,5 +1,5 @@ import weave -from weave.legacy import panel +from weave.legacy.weave import panel @weave.type() diff --git a/weave/legacy/panels/panel_board.py b/weave/legacy/weave/panels/panel_board.py similarity index 92% rename from weave/legacy/panels/panel_board.py rename to weave/legacy/weave/panels/panel_board.py index 0db30de2a27..ab14570b1ef 100644 --- a/weave/legacy/panels/panel_board.py +++ b/weave/legacy/weave/panels/panel_board.py @@ -2,9 +2,9 @@ import typing import weave -from weave.legacy import weave_internal -from weave.legacy import panel -from weave.legacy.panels import panel_group +from weave.legacy.weave import weave_internal +from weave.legacy.weave import panel +from weave.legacy.weave.panels import panel_group @dataclasses.dataclass @@ -51,7 +51,7 @@ def varbar(editable=True, items=None) -> panel_group.Group: def main() -> panel_group.Group: - return weave.legacy.panels.Group( + return weave.legacy.weave.panels.Group( layoutMode="grid", showExpressions=True, enableAddPanel=True, @@ -65,11 +65,11 @@ def Board( ): showExpressions = True if editable else "titleBar" vb = vars - if not isinstance(vb, weave.legacy.panels.Group): + if not isinstance(vb, weave.legacy.weave.panels.Group): vb = varbar(editable=editable, items=vars) main = panels - if not isinstance(panels, weave.legacy.panels.Group): + if not isinstance(panels, weave.legacy.weave.panels.Group): main_items = {} main_panel_layouts: list[panel_group.LayedOutPanel] = [] for i, p in enumerate(panels): diff --git a/weave/legacy/panels/panel_card.py b/weave/legacy/weave/panels/panel_card.py similarity index 93% rename from weave/legacy/panels/panel_card.py rename to weave/legacy/weave/panels/panel_card.py index 8979583edf4..0eacbcba710 100644 --- a/weave/legacy/panels/panel_card.py +++ b/weave/legacy/weave/panels/panel_card.py @@ -2,7 +2,7 @@ import typing import weave -from weave.legacy import graph, panel, panel_util +from weave.legacy.weave import graph, panel, panel_util CardContentType = typing.TypeVar("CardContentType") diff --git a/weave/legacy/panels/panel_color.py b/weave/legacy/weave/panels/panel_color.py similarity index 81% rename from weave/legacy/panels/panel_color.py rename to weave/legacy/weave/panels/panel_color.py index eb44072878e..f984a7fbba4 100644 --- a/weave/legacy/panels/panel_color.py +++ b/weave/legacy/weave/panels/panel_color.py @@ -2,7 +2,7 @@ import typing import weave -from weave.legacy import graph, panel, panel_util +from weave.legacy.weave import graph, panel, panel_util @weave.type() diff --git a/weave/legacy/panels/panel_daterange.py b/weave/legacy/weave/panels/panel_daterange.py similarity index 93% rename from weave/legacy/panels/panel_daterange.py rename to weave/legacy/weave/panels/panel_daterange.py index 262c64e5410..f06df0b3c75 100644 --- a/weave/legacy/panels/panel_daterange.py +++ b/weave/legacy/weave/panels/panel_daterange.py @@ -2,7 +2,7 @@ import typing import weave -from weave.legacy import graph, panel, panel_util +from weave.legacy.weave import graph, panel, panel_util @weave.type() diff --git a/weave/legacy/panels/panel_domain.py b/weave/legacy/weave/panels/panel_domain.py similarity index 90% rename from weave/legacy/panels/panel_domain.py rename to weave/legacy/weave/panels/panel_domain.py index f3d0ad9307b..535edd09dab 100644 --- a/weave/legacy/panels/panel_domain.py +++ b/weave/legacy/weave/panels/panel_domain.py @@ -1,5 +1,5 @@ import weave -from weave.legacy import panel +from weave.legacy.weave import panel @weave.type(__override_name="wb_trace_tree-traceViewer") # type: ignore diff --git a/weave/legacy/panels/panel_dropdown.py b/weave/legacy/weave/panels/panel_dropdown.py similarity index 88% rename from weave/legacy/panels/panel_dropdown.py rename to weave/legacy/weave/panels/panel_dropdown.py index e39d4e92a87..6eda21e6563 100644 --- a/weave/legacy/panels/panel_dropdown.py +++ b/weave/legacy/weave/panels/panel_dropdown.py @@ -2,7 +2,7 @@ import typing import weave -from weave.legacy import graph, panel, panel_util +from weave.legacy.weave import graph, panel, panel_util @weave.type() @@ -28,7 +28,7 @@ def __init__( self.config = DropdownConfig() if "choices" in options: self.config.choices = options["choices"] - if isinstance(self.input_node, weave.legacy.graph.VoidNode): + if isinstance(self.input_node, weave.legacy.weave.graph.VoidNode): choices_type = typing.cast(weave.types.List, self.config.choices.type) self.input_node = weave_internal.const( [], weave.types.List(choices_type.object_type) diff --git a/weave/legacy/panels/panel_each.py b/weave/legacy/weave/panels/panel_each.py similarity index 82% rename from weave/legacy/panels/panel_each.py rename to weave/legacy/weave/panels/panel_each.py index ad24f7646a6..6ae0188c5e5 100644 --- a/weave/legacy/panels/panel_each.py +++ b/weave/legacy/weave/panels/panel_each.py @@ -2,9 +2,9 @@ import typing import weave -from weave.legacy import graph, panel -from weave.legacy.panels.bank import default_panel_bank_flow_section_config -from weave.legacy.panels.panel_group import PanelBankSectionConfig +from weave.legacy.weave import graph, panel +from weave.legacy.weave.panels.bank import default_panel_bank_flow_section_config +from weave.legacy.weave.panels.panel_group import PanelBankSectionConfig PanelType = typing.TypeVar("PanelType") diff --git a/weave/legacy/panels/panel_each_column.py b/weave/legacy/weave/panels/panel_each_column.py similarity index 84% rename from weave/legacy/panels/panel_each_column.py rename to weave/legacy/weave/panels/panel_each_column.py index 3df7f7c9625..04b6f01aaa4 100644 --- a/weave/legacy/panels/panel_each_column.py +++ b/weave/legacy/weave/panels/panel_each_column.py @@ -2,8 +2,8 @@ import typing import weave -from weave.legacy import graph, panel -from weave.legacy.panels.panel_group import PanelBankSectionConfig +from weave.legacy.weave import graph, panel +from weave.legacy.weave.panels.panel_group import PanelBankSectionConfig RenderType = typing.TypeVar("RenderType") diff --git a/weave/legacy/panels/panel_expression.py b/weave/legacy/weave/panels/panel_expression.py similarity index 68% rename from weave/legacy/panels/panel_expression.py rename to weave/legacy/weave/panels/panel_expression.py index 3b432283e09..0610f093107 100644 --- a/weave/legacy/panels/panel_expression.py +++ b/weave/legacy/weave/panels/panel_expression.py @@ -1,5 +1,5 @@ import weave -from weave.legacy import panel +from weave.legacy.weave import panel @weave.type() diff --git a/weave/legacy/panels/panel_facet.py b/weave/legacy/weave/panels/panel_facet.py similarity index 86% rename from weave/legacy/panels/panel_facet.py rename to weave/legacy/weave/panels/panel_facet.py index 24c4b42d663..bfaa9c3378f 100644 --- a/weave/legacy/panels/panel_facet.py +++ b/weave/legacy/weave/panels/panel_facet.py @@ -2,11 +2,11 @@ import typing import weave -from weave.legacy import weave_internal -from weave.legacy import weave_types as types -from weave.legacy import graph, panel, panel_util -from weave.legacy.arrow import list_ -from weave.legacy.panels import table_state +from weave.legacy.weave import weave_internal +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import graph, panel, panel_util +from weave.legacy.weave.arrow import list_ +from weave.legacy.weave.panels import table_state @weave.type() @@ -38,10 +38,10 @@ class FacetConfig: default_factory=lambda: None ) xAxisLabel: weave.Node[str] = dataclasses.field( - default_factory=lambda: weave.legacy.graph.VoidNode() + default_factory=lambda: weave.legacy.weave.graph.VoidNode() ) yAxisLabel: weave.Node[str] = dataclasses.field( - default_factory=lambda: weave.legacy.graph.VoidNode() + default_factory=lambda: weave.legacy.weave.graph.VoidNode() ) @@ -120,14 +120,14 @@ def selected(self): ) x_fn = self.config.table.columnSelectFunctions[self.config.dims.x] y_fn = self.config.table.columnSelectFunctions[self.config.dims.y] - filtered = weave.legacy.ops.List.filter( + filtered = weave.legacy.weave.ops.List.filter( self.input_node, - lambda item: weave.legacy.ops.Boolean.bool_and( - weave.legacy.ops.String.__eq__( + lambda item: weave.legacy.weave.ops.Boolean.bool_and( + weave.legacy.weave.ops.String.__eq__( x_fn, self.config.selectedCell["x"], ), - weave.legacy.ops.String.__eq__( + weave.legacy.weave.ops.String.__eq__( y_fn, self.config.selectedCell["y"], ), diff --git a/weave/legacy/panels/panel_facet_tabs.py b/weave/legacy/weave/panels/panel_facet_tabs.py similarity index 73% rename from weave/legacy/panels/panel_facet_tabs.py rename to weave/legacy/weave/panels/panel_facet_tabs.py index 799c84dbccb..2a62ebea446 100644 --- a/weave/legacy/panels/panel_facet_tabs.py +++ b/weave/legacy/weave/panels/panel_facet_tabs.py @@ -2,8 +2,8 @@ import typing import weave -from weave.legacy import graph, panel -from weave.legacy.panels.panel_group import PanelBankSectionConfig +from weave.legacy.weave import graph, panel +from weave.legacy.weave.panels.panel_group import PanelBankSectionConfig RenderType = typing.TypeVar("RenderType") @@ -11,7 +11,7 @@ @weave.type() class FacetTabsConfig(typing.Generic[RenderType]): tab: weave.Node[typing.Optional[typing.Any]] = dataclasses.field( - default_factory=lambda: weave.legacy.graph.VoidNode() + default_factory=lambda: weave.legacy.weave.graph.VoidNode() ) panel: RenderType = dataclasses.field(default_factory=lambda: graph.VoidNode()) # type: ignore diff --git a/weave/legacy/panels/panel_filter_editor.py b/weave/legacy/weave/panels/panel_filter_editor.py similarity index 94% rename from weave/legacy/panels/panel_filter_editor.py rename to weave/legacy/weave/panels/panel_filter_editor.py index ccf5ceca6e8..c04e3b07818 100644 --- a/weave/legacy/panels/panel_filter_editor.py +++ b/weave/legacy/weave/panels/panel_filter_editor.py @@ -2,7 +2,7 @@ import typing import weave -from weave.legacy import graph, panel +from weave.legacy.weave import graph, panel ExpressionType = typing.TypeVar("ExpressionType") diff --git a/weave/legacy/panels/panel_function_editor.py b/weave/legacy/weave/panels/panel_function_editor.py similarity index 91% rename from weave/legacy/panels/panel_function_editor.py rename to weave/legacy/weave/panels/panel_function_editor.py index d8b5e2a13b2..dc3f3f488f3 100644 --- a/weave/legacy/panels/panel_function_editor.py +++ b/weave/legacy/weave/panels/panel_function_editor.py @@ -2,7 +2,7 @@ import typing import weave -from weave.legacy import graph, panel +from weave.legacy.weave import graph, panel ExpressionType = typing.TypeVar("ExpressionType") diff --git a/weave/legacy/panels/panel_group.py b/weave/legacy/weave/panels/panel_group.py similarity index 97% rename from weave/legacy/panels/panel_group.py rename to weave/legacy/weave/panels/panel_group.py index 3c4046c7410..54e7566e501 100644 --- a/weave/legacy/panels/panel_group.py +++ b/weave/legacy/weave/panels/panel_group.py @@ -3,8 +3,8 @@ import typing import weave -from weave.legacy import weave_internal -from weave.legacy import ( +from weave.legacy.weave import weave_internal +from weave.legacy.weave import ( errors, codifiable_value_mixin, codify, @@ -13,11 +13,11 @@ panel, panel_util, ) -from weave.legacy.panels.bank import ( +from weave.legacy.weave.panels.bank import ( default_panel_bank_flow_section_config, flow_layout, ) -from weave.legacy.panels.panel_group_panel_info import PanelInfo +from weave.legacy.weave.panels.panel_group_panel_info import PanelInfo ItemsType = typing.TypeVar("ItemsType") @@ -337,7 +337,7 @@ def to_code(self) -> typing.Optional[str]: ",".join([f_name + "=" + f_val for f_name, f_val in field_vals]) + "," ) return ( - f"""weave.legacy.panels.panel_group.Group({input_node_str} {param_str})""" + f"""weave.legacy.weave.panels.panel_group.Group({input_node_str} {param_str})""" ) # @property diff --git a/weave/legacy/panels/panel_group_panel_info.py b/weave/legacy/weave/panels/panel_group_panel_info.py similarity index 100% rename from weave/legacy/panels/panel_group_panel_info.py rename to weave/legacy/weave/panels/panel_group_panel_info.py diff --git a/weave/legacy/panels/panel_grouping_editor.py b/weave/legacy/weave/panels/panel_grouping_editor.py similarity index 94% rename from weave/legacy/panels/panel_grouping_editor.py rename to weave/legacy/weave/panels/panel_grouping_editor.py index ebaa9a7e7fd..ce608643040 100644 --- a/weave/legacy/panels/panel_grouping_editor.py +++ b/weave/legacy/weave/panels/panel_grouping_editor.py @@ -2,7 +2,7 @@ import typing import weave -from weave.legacy import graph, panel +from weave.legacy.weave import graph, panel ExpressionType = typing.TypeVar("ExpressionType") diff --git a/weave/legacy/panels/panel_histogram.py b/weave/legacy/weave/panels/panel_histogram.py similarity index 86% rename from weave/legacy/panels/panel_histogram.py rename to weave/legacy/weave/panels/panel_histogram.py index 6daa14a64bb..79a91e9f726 100644 --- a/weave/legacy/panels/panel_histogram.py +++ b/weave/legacy/weave/panels/panel_histogram.py @@ -1,5 +1,5 @@ import weave -from weave.legacy import panel +from weave.legacy.weave import panel # TODO: This id conflicts with the histogram type! Panel types # should automatically have Panel in the name but they don't at the moment. diff --git a/weave/legacy/panels/panel_html.py b/weave/legacy/weave/panels/panel_html.py similarity index 90% rename from weave/legacy/panels/panel_html.py rename to weave/legacy/weave/panels/panel_html.py index 49d9d5b214a..bba1afb0b55 100644 --- a/weave/legacy/panels/panel_html.py +++ b/weave/legacy/weave/panels/panel_html.py @@ -1,5 +1,5 @@ import weave -from weave.legacy import graph, ops, panel, panel_util +from weave.legacy.weave import graph, ops, panel, panel_util @weave.type() diff --git a/weave/legacy/panels/panel_labeled_item.py b/weave/legacy/weave/panels/panel_labeled_item.py similarity index 93% rename from weave/legacy/panels/panel_labeled_item.py rename to weave/legacy/weave/panels/panel_labeled_item.py index 040038accb6..08c5703dc7f 100644 --- a/weave/legacy/panels/panel_labeled_item.py +++ b/weave/legacy/weave/panels/panel_labeled_item.py @@ -2,7 +2,7 @@ import typing import weave -from weave.legacy import graph, panel, panel_util +from weave.legacy.weave import graph, panel, panel_util ItemType = typing.TypeVar("ItemType") diff --git a/weave/legacy/panels/panel_legacy.py b/weave/legacy/weave/panels/panel_legacy.py similarity index 98% rename from weave/legacy/panels/panel_legacy.py rename to weave/legacy/weave/panels/panel_legacy.py index 4673c7ab3e8..9e7c255dd1d 100644 --- a/weave/legacy/panels/panel_legacy.py +++ b/weave/legacy/weave/panels/panel_legacy.py @@ -73,7 +73,7 @@ class LPanel: def define_panel(p: LPanel): - class DummyClass(weave.legacy.panel.Panel): + class DummyClass(weave.legacy.weave.panel.Panel): id = p.panel_id type_cache.append(DummyClass) diff --git a/weave/legacy/panels/panel_markdown.py b/weave/legacy/weave/panels/panel_markdown.py similarity index 90% rename from weave/legacy/panels/panel_markdown.py rename to weave/legacy/weave/panels/panel_markdown.py index f86f5b8b1a8..fc489f6efc3 100644 --- a/weave/legacy/panels/panel_markdown.py +++ b/weave/legacy/weave/panels/panel_markdown.py @@ -1,5 +1,5 @@ import weave -from weave.legacy import graph, ops, panel, panel_util +from weave.legacy.weave import graph, ops, panel, panel_util @weave.type() diff --git a/weave/legacy/panels/panel_object_picker.py b/weave/legacy/weave/panels/panel_object_picker.py similarity index 95% rename from weave/legacy/panels/panel_object_picker.py rename to weave/legacy/weave/panels/panel_object_picker.py index c3ca313c4cc..35a7321166c 100644 --- a/weave/legacy/panels/panel_object_picker.py +++ b/weave/legacy/weave/panels/panel_object_picker.py @@ -2,8 +2,8 @@ import typing import weave -from weave.legacy import weave_internal -from weave.legacy import graph, panel +from weave.legacy.weave import weave_internal +from weave.legacy.weave import graph, panel ChoiceType = typing.TypeVar("ChoiceType") diff --git a/weave/legacy/panels/panel_plot.py b/weave/legacy/weave/panels/panel_plot.py similarity index 98% rename from weave/legacy/panels/panel_plot.py rename to weave/legacy/weave/panels/panel_plot.py index 6386d26e719..a14469bec3a 100644 --- a/weave/legacy/panels/panel_plot.py +++ b/weave/legacy/weave/panels/panel_plot.py @@ -4,12 +4,12 @@ import typing import weave -from weave.legacy import weave_internal -from weave.legacy import weave_types as types -from weave.legacy import errors, codifiable_value_mixin, codify, graph, panel -from weave.legacy.ops_primitives import boolean, list_ -from weave.legacy.ops_primitives import dict as dict_ -from weave.legacy.panels import panel_table, table_state +from weave.legacy.weave import weave_internal +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import errors, codifiable_value_mixin, codify, graph, panel +from weave.legacy.weave.ops_primitives import boolean, list_ +from weave.legacy.weave.ops_primitives import dict as dict_ +from weave.legacy.weave.panels import panel_table, table_state @weave.type() @@ -696,7 +696,7 @@ def to_code(self) -> typing.Optional[str]: param_str = ( ",".join([f_name + "=" + f_val for f_name, f_val in field_vals]) + "," ) - return f"""weave.legacy.panels.panel_plot.Plot({codify.object_to_code_no_format(self.input_node)}, {param_str})""" + return f"""weave.legacy.weave.panels.panel_plot.Plot({codify.object_to_code_no_format(self.input_node)}, {param_str})""" def make_set_all_series(dim_name: str) -> typing.Callable[[Plot, typing.Any], None]: diff --git a/weave/legacy/panels/panel_query.py b/weave/legacy/weave/panels/panel_query.py similarity index 89% rename from weave/legacy/panels/panel_query.py rename to weave/legacy/weave/panels/panel_query.py index e59d4b666e8..0336cd9e0f7 100644 --- a/weave/legacy/panels/panel_query.py +++ b/weave/legacy/weave/panels/panel_query.py @@ -2,9 +2,9 @@ import typing import weave -from weave.legacy import weave_internal -from weave.legacy import graph, panel -from weave.legacy.panels import table_state +from weave.legacy.weave import weave_internal +from weave.legacy.weave import graph, panel +from weave.legacy.weave.panels import table_state @weave.type() @@ -18,7 +18,7 @@ class QueryDimsConfig: @weave.type() class QueryCondition: expression: weave.Node[typing.Any] = dataclasses.field( - default_factory=lambda: weave.legacy.graph.VoidNode() + default_factory=lambda: weave.legacy.weave.graph.VoidNode() ) editor: EditorType = dataclasses.field(default_factory=lambda: graph.VoidNode()) # type: ignore @@ -76,7 +76,7 @@ def selected(self): and self.config.tableState.preFilterFunction is not None and self.config.tableState.preFilterFunction.type != weave.types.Invalid() ): - table_node = weave.legacy.ops.List.filter( + table_node = weave.legacy.weave.ops.List.filter( table_node, lambda row: weave_internal.call_fn( self.config.tableState.preFilterFunction, {"row": row} diff --git a/weave/legacy/panels/panel_sections.py b/weave/legacy/weave/panels/panel_sections.py similarity index 73% rename from weave/legacy/panels/panel_sections.py rename to weave/legacy/weave/panels/panel_sections.py index 5808d0ad407..e23cbfff43b 100644 --- a/weave/legacy/panels/panel_sections.py +++ b/weave/legacy/weave/panels/panel_sections.py @@ -2,8 +2,8 @@ import typing import weave -from weave.legacy import graph, panel -from weave.legacy.panels.panel_group import PanelBankSectionConfig +from weave.legacy.weave import graph, panel +from weave.legacy.weave.panels.panel_group import PanelBankSectionConfig RenderType = typing.TypeVar("RenderType") @@ -11,7 +11,7 @@ @weave.type() class SectionsConfig(typing.Generic[RenderType]): section: weave.Node[typing.Optional[typing.Any]] = dataclasses.field( - default_factory=lambda: weave.legacy.graph.VoidNode() + default_factory=lambda: weave.legacy.weave.graph.VoidNode() ) panel: RenderType = dataclasses.field(default_factory=lambda: graph.VoidNode()) # type: ignore diff --git a/weave/legacy/panels/panel_select.py b/weave/legacy/weave/panels/panel_select.py similarity index 85% rename from weave/legacy/panels/panel_select.py rename to weave/legacy/weave/panels/panel_select.py index 3ab67039bae..07ca97bde51 100644 --- a/weave/legacy/panels/panel_select.py +++ b/weave/legacy/weave/panels/panel_select.py @@ -2,8 +2,8 @@ import typing import weave -from weave.legacy import weave_internal -from weave.legacy import graph, panel +from weave.legacy.weave import weave_internal +from weave.legacy.weave import graph, panel @weave.type() @@ -27,7 +27,7 @@ def __init__(self, input_node=graph.VoidNode(), vars=None, config=None, **option self.config = SelectEditorConfig() if "choices" in options: self.config.choices = options["choices"] - if isinstance(self.input_node, weave.legacy.graph.VoidNode): + if isinstance(self.input_node, weave.legacy.weave.graph.VoidNode): # TODO: not string! self.input_node = weave_internal.const( [], weave.types.List(self.config.choices.type.object_type) diff --git a/weave/legacy/panels/panel_sidebarcontainer.py b/weave/legacy/weave/panels/panel_sidebarcontainer.py similarity index 89% rename from weave/legacy/panels/panel_sidebarcontainer.py rename to weave/legacy/weave/panels/panel_sidebarcontainer.py index f568b6649f8..23ec5927233 100644 --- a/weave/legacy/panels/panel_sidebarcontainer.py +++ b/weave/legacy/weave/panels/panel_sidebarcontainer.py @@ -1,5 +1,5 @@ -from weave.legacy import graph -from weave.legacy.panels import panel +from weave.legacy.weave import graph +from weave.legacy.weave.panels import panel class VerticalContainerConfig: diff --git a/weave/legacy/panels/panel_slider.py b/weave/legacy/weave/panels/panel_slider.py similarity index 85% rename from weave/legacy/panels/panel_slider.py rename to weave/legacy/weave/panels/panel_slider.py index cbe568a4876..b7eef8aceb4 100644 --- a/weave/legacy/panels/panel_slider.py +++ b/weave/legacy/weave/panels/panel_slider.py @@ -2,8 +2,8 @@ import typing import weave -from weave.legacy import weave_internal -from weave.legacy import panel +from weave.legacy.weave import weave_internal +from weave.legacy.weave import panel @weave.type() @@ -28,7 +28,7 @@ class Slider(panel.Panel): def __post_init__(self, *args): super().__post_init__(*args) - if isinstance(self.input_node, weave.legacy.graph.VoidNode): + if isinstance(self.input_node, weave.legacy.weave.graph.VoidNode): self.__dict__["input_node"] = weave_internal.const(0) @weave.op() diff --git a/weave/legacy/panels/panel_string.py b/weave/legacy/weave/panels/panel_string.py similarity index 94% rename from weave/legacy/panels/panel_string.py rename to weave/legacy/weave/panels/panel_string.py index 0b61a56fe03..58cecb54794 100644 --- a/weave/legacy/panels/panel_string.py +++ b/weave/legacy/weave/panels/panel_string.py @@ -2,7 +2,7 @@ import typing import weave -from weave.legacy import panel +from weave.legacy.weave import panel ModeOption = typing.Literal["plaintext", "markdown", "diff"] diff --git a/weave/legacy/panels/panel_string_editor.py b/weave/legacy/weave/panels/panel_string_editor.py similarity index 82% rename from weave/legacy/panels/panel_string_editor.py rename to weave/legacy/weave/panels/panel_string_editor.py index a6f6bdae949..3aeb0f440d6 100644 --- a/weave/legacy/panels/panel_string_editor.py +++ b/weave/legacy/weave/panels/panel_string_editor.py @@ -1,5 +1,5 @@ import weave -from weave.legacy import panel +from weave.legacy.weave import panel @weave.type() diff --git a/weave/legacy/panels/panel_table.py b/weave/legacy/weave/panels/panel_table.py similarity index 93% rename from weave/legacy/panels/panel_table.py rename to weave/legacy/weave/panels/panel_table.py index a359e7b01c1..e9fb6b0760d 100644 --- a/weave/legacy/panels/panel_table.py +++ b/weave/legacy/weave/panels/panel_table.py @@ -2,11 +2,11 @@ import typing import weave -from weave.legacy import weave_internal -from weave.legacy import codifiable_value_mixin, codify, panel -from weave.legacy.graph import ConstNode, Node, OutputNode, VoidNode -from weave.legacy.panels import table_state -from weave.legacy.panels.panel_query import Query +from weave.legacy.weave import weave_internal +from weave.legacy.weave import codifiable_value_mixin, codify, panel +from weave.legacy.weave.graph import ConstNode, Node, OutputNode, VoidNode +from weave.legacy.weave.panels import table_state +from weave.legacy.weave.panels.panel_query import Query @weave.type("tablePanelConfig") @@ -20,7 +20,7 @@ class TableConfig: class ColumnDef(typing.TypedDict): columnName: str - columnSelectFunction: weave.legacy.graph.Node + columnSelectFunction: weave.legacy.weave.graph.Node @dataclasses.dataclass @@ -128,7 +128,7 @@ def to_code(self) -> typing.Optional[str]: param_str = ( ",".join([f_name + "=" + f_val for f_name, f_val in field_vals]) + "," ) - return f"""weave.legacy.panels.panel_table.Table({codify.object_to_code_no_format(self.input_node)}, {param_str})""" + return f"""weave.legacy.weave.panels.panel_table.Table({codify.object_to_code_no_format(self.input_node)}, {param_str})""" def add_column( self, @@ -165,14 +165,14 @@ def _get_composite_group_key(self: typing.Union[Table, Query]) -> str: # TODO: preserve arrow def _get_pinned_node(self: typing.Union[Table, Query], data_or_rows_node: Node) -> Node: if self.config is None: - return weave.legacy.ops.make_list() + return weave.legacy.weave.ops.make_list() composite_group_key = _get_composite_group_key(self) pinned_data = self.config.pinnedRows.get(composite_group_key) if pinned_data is None or len(pinned_data) == 0: - return weave.legacy.ops.make_list() + return weave.legacy.weave.ops.make_list() - return weave.legacy.ops.make_list( + return weave.legacy.weave.ops.make_list( **{ f"v_{pin_ndx}": OutputNode( data_or_rows_node.type, @@ -213,7 +213,7 @@ def _get_rows_node(self: Table, apply_sort: bool = True) -> Node: and self.config.tableState.preFilterFunction is not None and self.config.tableState.preFilterFunction.type != weave.types.Invalid() ): - data_node = weave.legacy.ops.List.filter( + data_node = weave.legacy.weave.ops.List.filter( data_node, lambda row, index: weave_internal.call_fn( self.config.tableState.preFilterFunction, {"row": row, "index": index} @@ -226,9 +226,9 @@ def _get_rows_node(self: Table, apply_sort: bool = True) -> Node: group_ids: typing.Set[str] = set() if self.config and self.config.tableState.groupBy: group_ids = set(self.config.tableState.groupBy) - data_node = weave.legacy.ops.List.groupby( + data_node = weave.legacy.weave.ops.List.groupby( data_node, - lambda row: weave.legacy.ops.dict_( + lambda row: weave.legacy.weave.ops.dict_( **{ columns[col_id]["columnName"]: weave_internal.call_fn( columns[col_id]["columnSelectFunction"], @@ -242,9 +242,9 @@ def _get_rows_node(self: Table, apply_sort: bool = True) -> Node: ) # Apply Selection - data_node = weave.legacy.ops.List.map( + data_node = weave.legacy.weave.ops.List.map( data_node, - lambda row, index: weave.legacy.ops.dict_( + lambda row, index: weave.legacy.weave.ops.dict_( **{ col_def["columnName"]: ( weave_internal.call_fn( @@ -275,9 +275,9 @@ def make_sort_fn(sort_def, row_node): # else: # return row_node[col_name] - data_node = weave.legacy.ops.List.sort( + data_node = weave.legacy.weave.ops.List.sort( data_node, - lambda row: weave.legacy.ops.make_list( + lambda row: weave.legacy.weave.ops.make_list( **{ f"{sort_ndx}": make_sort_fn(sort_def, row) for sort_ndx, sort_def in enumerate(sort_defs) diff --git a/weave/legacy/panels/panel_trace.py b/weave/legacy/weave/panels/panel_trace.py similarity index 94% rename from weave/legacy/panels/panel_trace.py rename to weave/legacy/weave/panels/panel_trace.py index 5c002a4071b..cd8f0ff4f56 100644 --- a/weave/legacy/panels/panel_trace.py +++ b/weave/legacy/weave/panels/panel_trace.py @@ -2,7 +2,7 @@ import typing import weave -from weave.legacy import panel +from weave.legacy.weave import panel span_typed_dict_type = weave.types.TypedDict( { @@ -62,4 +62,4 @@ def __init__(self, input_node, vars=None, config=None, **options): ) def active_span(self: Trace): index = 0 if self.config is None else self.config.selectedSpanIndex - return weave.legacy.ops_arrow.list_ops.index(self.input_node, index) + return weave.legacy.weave.ops_arrow.list_ops.index(self.input_node, index) diff --git a/weave/legacy/panels/panel_trace_span.py b/weave/legacy/weave/panels/panel_trace_span.py similarity index 85% rename from weave/legacy/panels/panel_trace_span.py rename to weave/legacy/weave/panels/panel_trace_span.py index 460d79bcbfa..35b565d6350 100644 --- a/weave/legacy/panels/panel_trace_span.py +++ b/weave/legacy/weave/panels/panel_trace_span.py @@ -1,5 +1,5 @@ import weave -from weave.legacy import panel +from weave.legacy.weave import panel @weave.type("traceSpanPanel") diff --git a/weave/legacy/panels/panel_weavelink.py b/weave/legacy/weave/panels/panel_weavelink.py similarity index 89% rename from weave/legacy/panels/panel_weavelink.py rename to weave/legacy/weave/panels/panel_weavelink.py index 095926dd167..1d822212323 100644 --- a/weave/legacy/panels/panel_weavelink.py +++ b/weave/legacy/weave/panels/panel_weavelink.py @@ -2,14 +2,14 @@ import typing import weave -from weave.legacy import weave_internal -from weave.legacy import graph, ops, panel, panel_util +from weave.legacy.weave import weave_internal +from weave.legacy.weave import graph, ops, panel, panel_util @weave.type() class WeaveLinkConfig: to: weave.Node[typing.Optional[typing.Any]] = dataclasses.field( - default_factory=lambda: weave.legacy.graph.VoidNode() + default_factory=lambda: weave.legacy.weave.graph.VoidNode() ) vars: typing.Dict[str, graph.Node] = dataclasses.field(default_factory=dict) diff --git a/weave/legacy/panels/table_state.py b/weave/legacy/weave/panels/table_state.py similarity index 97% rename from weave/legacy/panels/table_state.py rename to weave/legacy/weave/panels/table_state.py index 460585136b8..0a333efe967 100644 --- a/weave/legacy/panels/table_state.py +++ b/weave/legacy/weave/panels/table_state.py @@ -7,9 +7,9 @@ import string import typing -from weave.legacy import weave_internal -from weave.legacy import decorator_type, graph, ops, panel, weave_types -from weave.legacy.language_features.tagging import tagged_value_type +from weave.legacy.weave import weave_internal +from weave.legacy.weave import decorator_type, graph, ops, panel, weave_types +from weave.legacy.weave.language_features.tagging import tagged_value_type @decorator_type.type() diff --git a/weave/legacy/panels_py/__init__.py b/weave/legacy/weave/panels_py/__init__.py similarity index 64% rename from weave/legacy/panels_py/__init__.py rename to weave/legacy/weave/panels_py/__init__.py index 3b262288025..90abece1622 100644 --- a/weave/legacy/panels_py/__init__.py +++ b/weave/legacy/weave/panels_py/__init__.py @@ -1,8 +1,8 @@ -from weave.legacy import context_state as _context_state +from weave.legacy.weave import context_state as _context_state _loading_builtins_token = _context_state.set_loading_built_ins() -from weave.legacy.panels_py import ( +from weave.legacy.weave.panels_py import ( generator_templates, panel_autoboard, panel_llm_monitor, @@ -12,6 +12,6 @@ ) # This is just an example, uncomment to enable -# from weave.legacy.panels_py import panel_example_custom_board +# from weave.legacy.weave.panels_py import panel_example_custom_board _context_state.clear_loading_built_ins(_loading_builtins_token) diff --git a/weave/legacy/panels_py/generator_templates.py b/weave/legacy/weave/panels_py/generator_templates.py similarity index 97% rename from weave/legacy/panels_py/generator_templates.py rename to weave/legacy/weave/panels_py/generator_templates.py index 2aa6e524424..63cf1d0c6c8 100644 --- a/weave/legacy/panels_py/generator_templates.py +++ b/weave/legacy/weave/panels_py/generator_templates.py @@ -18,8 +18,8 @@ import dataclasses import typing -from weave.legacy import weave_types -from weave.legacy import decorator_op, graph, registry_mem +from weave.legacy.weave import weave_types +from weave.legacy.weave import decorator_op, graph, registry_mem @dataclasses.dataclass diff --git a/weave/legacy/panels_py/instructions/panel_autoboard.md b/weave/legacy/weave/panels_py/instructions/panel_autoboard.md similarity index 100% rename from weave/legacy/panels_py/instructions/panel_autoboard.md rename to weave/legacy/weave/panels_py/instructions/panel_autoboard.md diff --git a/weave/legacy/panels_py/instructions/panel_llm_monitor.md b/weave/legacy/weave/panels_py/instructions/panel_llm_monitor.md similarity index 100% rename from weave/legacy/panels_py/instructions/panel_llm_monitor.md rename to weave/legacy/weave/panels_py/instructions/panel_llm_monitor.md diff --git a/weave/legacy/panels_py/instructions/panel_trace_monitor.md b/weave/legacy/weave/panels_py/instructions/panel_trace_monitor.md similarity index 93% rename from weave/legacy/panels_py/instructions/panel_trace_monitor.md rename to weave/legacy/weave/panels_py/instructions/panel_trace_monitor.md index 5a3dd39d29b..4f49b229fb0 100644 --- a/weave/legacy/panels_py/instructions/panel_trace_monitor.md +++ b/weave/legacy/weave/panels_py/instructions/panel_trace_monitor.md @@ -25,7 +25,7 @@ pip install weave If you are already using `Langchain`, simply create a tracer and add it as a callback to your next call: ```python -from weave.legacy.monitoring.langchain import WeaveTracer +from weave.legacy.weave.monitoring.langchain import WeaveTracer tracer = WeaveTracer(f"{WB_ENTITY}/{WB_PROJECT}/{WB_STREAM}") llm.run(question, callbacks=[tracer]) @@ -38,7 +38,7 @@ llm.run(question, callbacks=[tracer]) If you have existing code, the Trace decorator (and related utilities) allows you to instrument and log in a variety of formats. For example: ```python -from weave.legacy.monitoring import init_monitor +from weave.legacy.weave.monitoring import init_monitor mon = init_monitor(f"{WB_ENTITY}/{WB_PROJECT}/{WB_STREAM}") @@ -55,7 +55,7 @@ def adder(a, b): Finally, if you want to manually log span data, you can do so as well by logging directly to a StreamTable: ```python -from weave.legacy.monitoring import StreamTable +from weave.legacy.weave.monitoring import StreamTable from weave.stream_data_interfaces import TraceSpanDict st = StreamTable(f"{WB_ENTITY}/{WB_PROJECT}/{WB_STREAM}") diff --git a/weave/legacy/panels_py/panel_autoboard.py b/weave/legacy/weave/panels_py/panel_autoboard.py similarity index 84% rename from weave/legacy/panels_py/panel_autoboard.py rename to weave/legacy/weave/panels_py/panel_autoboard.py index 26ea6c6c468..810bfa88fc4 100644 --- a/weave/legacy/panels_py/panel_autoboard.py +++ b/weave/legacy/weave/panels_py/panel_autoboard.py @@ -26,10 +26,10 @@ import typing import weave -from weave.legacy import weave_internal -from weave.legacy.panels import panel_plot -from weave.legacy.panels_py.generator_templates import template_registry -from weave.legacy import util +from weave.legacy.weave import weave_internal +from weave.legacy.weave.panels import panel_plot +from weave.legacy.weave.panels_py.generator_templates import template_registry +from weave.legacy.weave import util @weave.type() @@ -72,10 +72,10 @@ def timeseries( x_axis_type = input_node[x_axis_key].type.object_type # type: ignore if weave.types.optional(weave.types.Timestamp()).assign_type(x_axis_type): x_title = "" - bin_fn = weave.legacy.ops.timestamp_bins_nice + bin_fn = weave.legacy.weave.ops.timestamp_bins_nice elif weave.types.optional(weave.types.Number()).assign_type(x_axis_type): x_title = x_axis_key - bin_fn = weave.legacy.ops.numbers_bins_equal + bin_fn = weave.legacy.weave.ops.numbers_bins_equal else: raise ValueError(f"Unsupported type for x_axis_key {x_axis_key}: {x_axis_type}") if mark == "bar": @@ -84,7 +84,7 @@ def timeseries( # TODO: should be midpoint x = lambda row: row[x_axis_key].bin(bin_fn(bin_domain_node, n_bins))["start"] - return weave.legacy.panels.Plot( + return weave.legacy.weave.panels.Plot( input_node, x=x, x_title=x_title, @@ -108,12 +108,12 @@ def timeseries_avg_line( ) -> weave.Panel: x_axis_type = input_node[x_axis_key].type.object_type # type: ignore if weave.types.optional(weave.types.Timestamp()).assign_type(x_axis_type): - bin_fn = weave.legacy.ops.timestamp_bins_nice + bin_fn = weave.legacy.weave.ops.timestamp_bins_nice elif weave.types.optional(weave.types.Number()).assign_type(x_axis_type): - bin_fn = weave.legacy.ops.numbers_bins_equal + bin_fn = weave.legacy.weave.ops.numbers_bins_equal else: raise ValueError(f"Unsupported type for x_axis_key {x_axis_key}: {x_axis_type}") - return weave.legacy.panels.Plot( + return weave.legacy.weave.panels.Plot( input_node, x=lambda row: row[x_axis_key].bin(bin_fn(bin_domain_node, 100))["start"], x_title=x_axis_key, @@ -139,13 +139,13 @@ def timeseries_sum_bar( x_axis_type = input_node[x_axis_key].type.object_type # type: ignore if weave.types.optional(weave.types.Timestamp()).assign_type(x_axis_type): x_title = "" - bin_fn = weave.legacy.ops.timestamp_bins_nice + bin_fn = weave.legacy.weave.ops.timestamp_bins_nice elif weave.types.optional(weave.types.Number()).assign_type(x_axis_type): x_title = x_axis_key - bin_fn = weave.legacy.ops.numbers_bins_equal + bin_fn = weave.legacy.weave.ops.numbers_bins_equal else: raise ValueError(f"Unsupported type for x_axis_key {x_axis_key}: {x_axis_type}") - return weave.legacy.panels.Plot( + return weave.legacy.weave.panels.Plot( input_node, x=lambda row: row[x_axis_key].bin(bin_fn(bin_domain_node, n_bins)), x_title=x_title, @@ -170,13 +170,13 @@ def timeseries_count_bar( x_axis_type = input_node[x_axis_key].type.object_type # type: ignore if weave.types.optional(weave.types.Timestamp()).assign_type(x_axis_type): x_title = "" - bin_fn = weave.legacy.ops.timestamp_bins_nice + bin_fn = weave.legacy.weave.ops.timestamp_bins_nice elif weave.types.optional(weave.types.Number()).assign_type(x_axis_type): x_title = x_axis_key - bin_fn = weave.legacy.ops.numbers_bins_equal + bin_fn = weave.legacy.weave.ops.numbers_bins_equal else: raise ValueError(f"Unsupported type for x_axis_key {x_axis_key}: {x_axis_type}") - return weave.legacy.panels.Plot( + return weave.legacy.weave.panels.Plot( input_node, x=lambda row: row[x_axis_key].bin(bin_fn(bin_domain_node, n_bins)), x_title=x_title, @@ -192,7 +192,7 @@ def categorical_dist( input_node: weave.Node[list[typing.Any]], key: str, ) -> weave.Panel: - return weave.legacy.panels.Plot( + return weave.legacy.weave.panels.Plot( input_node, y=lambda row: row[key], x=lambda row: row.count(), @@ -317,49 +317,49 @@ def auto_panels( panel = categorical_dist(window_data_node, key) categorical_panels.append(panel) - metrics = weave.legacy.panels.Group( - layoutMode=weave.legacy.panels.GroupLayoutFlow(2, 3), + metrics = weave.legacy.weave.panels.Group( + layoutMode=weave.legacy.weave.panels.GroupLayoutFlow(2, 3), items={"panel%s" % i: panel for i, panel in enumerate(metric_panels)}, ) - categoricals = weave.legacy.panels.Group( - layoutMode=weave.legacy.panels.GroupLayoutFlow(2, 3), + categoricals = weave.legacy.weave.panels.Group( + layoutMode=weave.legacy.weave.panels.GroupLayoutFlow(2, 3), items={"panel%s" % i: panel for i, panel in enumerate(categorical_panels)}, ) control_items = [ - weave.legacy.panels.GroupPanel( + weave.legacy.weave.panels.GroupPanel( input_node, id="data", ), # TODO: We need a filter editor. Can start with a filter expression # editor and make it more user-friendly later - weave.legacy.panels.GroupPanel( - lambda data: weave.legacy.ops.make_list( + weave.legacy.weave.panels.GroupPanel( + lambda data: weave.legacy.weave.ops.make_list( a=data[x_axis].min(), b=data[x_axis].max() ), id="data_range", hidden=True, ), - weave.legacy.panels.GroupPanel(None, id="zoom_range", hidden=True), - weave.legacy.panels.GroupPanel( + weave.legacy.weave.panels.GroupPanel(None, id="zoom_range", hidden=True), + weave.legacy.weave.panels.GroupPanel( lambda zoom_range, data_range: zoom_range.coalesce(data_range), id="bin_range", hidden=True, ), - weave.legacy.panels.GroupPanel( - lambda data, zoom_range: weave.legacy.panels.DateRange( + weave.legacy.weave.panels.GroupPanel( + lambda data, zoom_range: weave.legacy.weave.panels.DateRange( zoom_range, domain=data[x_axis] ), id="date_picker", ), # TODO: groupby should really be a Dropdown / multi-select instead # of an expression - weave.legacy.panels.GroupPanel( + weave.legacy.weave.panels.GroupPanel( groupby, id="groupby", ), - weave.legacy.panels.GroupPanel( + weave.legacy.weave.panels.GroupPanel( lambda data, bin_range: data.filter( - lambda row: weave.legacy.ops.Boolean.bool_and( + lambda row: weave.legacy.weave.ops.Boolean.bool_and( row[x_axis] >= bin_range[0], row[x_axis] < bin_range[1] ) ), @@ -369,21 +369,21 @@ def auto_panels( ] panels = [ - weave.legacy.panels.BoardPanel( + weave.legacy.weave.panels.BoardPanel( metrics, id="metrics", - layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=24, h=12), + layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=24, h=12), ), - weave.legacy.panels.BoardPanel( + weave.legacy.weave.panels.BoardPanel( categoricals, id="categoricals", - layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=24, h=12), + layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=24, h=12), ), ] if "step" not in x_axis: panels.insert( 0, - weave.legacy.panels.BoardPanel( + weave.legacy.weave.panels.BoardPanel( timeseries_count_bar( data_node, time_domain_node, @@ -393,18 +393,18 @@ def auto_panels( 150, ), id="volume", - layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=24, h=6), + layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=24, h=6), ), ) panels.append( - weave.legacy.panels.BoardPanel( + weave.legacy.weave.panels.BoardPanel( window_data_node, id="table", - layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=24, h=6), + layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=24, h=6), ), ) - return weave.legacy.panels.Board(vars=control_items, panels=panels, editable=False) + return weave.legacy.weave.panels.Board(vars=control_items, panels=panels, editable=False) # The interface for constructing this Panel from Python @@ -415,7 +415,7 @@ class AutoBoard(weave.Panel): config: typing.Optional[AutoBoardConfig] = None @weave.op() # type: ignore - def render(self) -> weave.legacy.panels.Group: + def render(self) -> weave.legacy.weave.panels.Group: return auto_panels(self.input_node, self.config) # type: ignore @@ -426,7 +426,7 @@ def render(self) -> weave.legacy.panels.Group: def seed_autoboard( input_node: weave.Node[typing.Any], config: typing.Optional[AutoBoardConfig] = None, -) -> weave.legacy.panels.Group: +) -> weave.legacy.weave.panels.Group: return auto_panels(input_node, config) # type: ignore diff --git a/weave/legacy/panels_py/panel_eval.py b/weave/legacy/weave/panels_py/panel_eval.py similarity index 67% rename from weave/legacy/panels_py/panel_eval.py rename to weave/legacy/weave/panels_py/panel_eval.py index 95ec348fa89..3cf7afacd07 100644 --- a/weave/legacy/panels_py/panel_eval.py +++ b/weave/legacy/weave/panels_py/panel_eval.py @@ -1,5 +1,5 @@ import weave -from weave.legacy.panels import panel_board +from weave.legacy.weave.panels import panel_board # This is not yet general, it describes a board for a specific # formulation of a text extraction problem @@ -13,34 +13,34 @@ def eval_board(dataset, eval_result0, eval_result1): # type: ignore summary = varbar.add( "summary", - weave.legacy.ops.make_list( - a=weave.legacy.ops.TypedDict.merge( - weave.legacy.ops.dict_(name="baseline"), + weave.legacy.weave.ops.make_list( + a=weave.legacy.weave.ops.TypedDict.merge( + weave.legacy.weave.ops.dict_(name="baseline"), baseline_eval_result["summary"], ), - b=weave.legacy.ops.TypedDict.merge( - weave.legacy.ops.dict_(name="candidate"), + b=weave.legacy.weave.ops.TypedDict.merge( + weave.legacy.weave.ops.dict_(name="candidate"), candidate_eval_result["summary"], ), ), ) - weave.legacy.ops.make_list( + weave.legacy.weave.ops.make_list( a=baseline_eval_result["eval_table"], b=baseline_eval_result["eval_table"] ) concatted_evals = varbar.add( "concatted_evals", - weave.legacy.ops.List.concat( - weave.legacy.ops.make_list( + weave.legacy.weave.ops.List.concat( + weave.legacy.weave.ops.make_list( a=baseline_eval_result["eval_table"].map( - lambda row: weave.legacy.ops.TypedDict.merge( - weave.legacy.ops.dict_(name="baseline"), row + lambda row: weave.legacy.weave.ops.TypedDict.merge( + weave.legacy.weave.ops.dict_(name="baseline"), row ) ), b=candidate_eval_result["eval_table"].map( - lambda row: weave.legacy.ops.TypedDict.merge( - weave.legacy.ops.dict_(name="candidate"), row + lambda row: weave.legacy.weave.ops.TypedDict.merge( + weave.legacy.weave.ops.dict_(name="candidate"), row ) ), ) @@ -50,8 +50,8 @@ def eval_board(dataset, eval_result0, eval_result1): # type: ignore # join evals together first joined_evals = varbar.add( "joined_evals", - weave.legacy.ops.join_all( - weave.legacy.ops.make_list( + weave.legacy.weave.ops.join_all( + weave.legacy.weave.ops.make_list( a=baseline_eval_result["eval_table"], b=candidate_eval_result["eval_table"], ), @@ -63,7 +63,7 @@ def eval_board(dataset, eval_result0, eval_result1): # type: ignore # then join dataset to evals dataset_evals = varbar.add( "dataset_evals", - weave.legacy.ops.join_2( + weave.legacy.weave.ops.join_2( dataset_var, joined_evals, lambda row: row["id"], @@ -75,7 +75,7 @@ def eval_board(dataset, eval_result0, eval_result1): # type: ignore ), ) - main = weave.legacy.panels.Group( + main = weave.legacy.weave.panels.Group( layoutMode="grid", showExpressions=True, enableAddPanel=True, @@ -87,72 +87,72 @@ def eval_board(dataset, eval_result0, eval_result1): # type: ignore main.add( "avg_f1", - weave.legacy.panels.Plot( + weave.legacy.weave.panels.Plot( summary, x=lambda row: row["avg_f1"], y=lambda row: row["name"], color=lambda row: row["name"], ), - layout=weave.legacy.panels.GroupPanelLayout(x=0, y=0, w=12, h=4), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=0, y=0, w=12, h=4), ) main.add( "latency", - weave.legacy.panels.Plot( + weave.legacy.weave.panels.Plot( concatted_evals, x=lambda row: row["summary"]["latency"], y=lambda row: row["name"], color=lambda row: row["name"], mark="boxplot", ), - layout=weave.legacy.panels.GroupPanelLayout(x=12, y=0, w=12, h=4), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=12, y=0, w=12, h=4), ) main.add( "field_name_f1", - weave.legacy.panels.Plot( + weave.legacy.weave.panels.Plot( summary, x=lambda row: row["field_name.f1"], y=lambda row: row["name"], color=lambda row: row["name"], ), - layout=weave.legacy.panels.GroupPanelLayout(x=0, y=4, w=8, h=4), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=0, y=4, w=8, h=4), ) main.add( "field_shares_f1", - weave.legacy.panels.Plot( + weave.legacy.weave.panels.Plot( summary, x=lambda row: row["field_shares.f1"], y=lambda row: row["name"], color=lambda row: row["name"], ), - layout=weave.legacy.panels.GroupPanelLayout(x=8, y=4, w=8, h=4), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=8, y=4, w=8, h=4), ) main.add( "field_directors_f1", - weave.legacy.panels.Plot( + weave.legacy.weave.panels.Plot( summary, x=lambda row: row["field_directors.f1"], y=lambda row: row["name"], color=lambda row: row["name"], ), - layout=weave.legacy.panels.GroupPanelLayout(x=16, y=4, w=8, h=4), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=16, y=4, w=8, h=4), ) - # ct = main.add('concat_t', concatted_evals, layout=weave.legacy.panels.GroupPanelLayout(x=0, y=4, w=24, h=12)) + # ct = main.add('concat_t', concatted_evals, layout=weave.legacy.weave.panels.GroupPanelLayout(x=0, y=4, w=24, h=12)) # main.add('dataset_table', dataset) # main.add('joined_evals', joined_evals) # main.add( # "dataset_evals", # dataset_evals, - # layout=weave.legacy.panels.GroupPanelLayout(x=0, y=4, w=24, h=6), + # layout=weave.legacy.weave.panels.GroupPanelLayout(x=0, y=4, w=24, h=6), # ) ##### Example details # more ideas: show examples that all got wrong, or that are confusing - # facet_f1 = weave.legacy.panels.Facet( + # facet_f1 = weave.legacy.weave.panels.Facet( # dataset_evals, # x=lambda row: row["evals.summary"][0]["f1"], # y=lambda row: row["evals.summary"][1]["f1"], @@ -162,10 +162,10 @@ def eval_board(dataset, eval_result0, eval_result1): # type: ignore # f1_comparison = main.add( # "f1_comparison", # facet_f1, - # layout=weave.legacy.panels.GroupPanelLayout(x=0, y=8, w=12, h=6), + # layout=weave.legacy.weave.panels.GroupPanelLayout(x=0, y=8, w=12, h=6), # ) - facet_correct = weave.legacy.panels.Facet( + facet_correct = weave.legacy.weave.panels.Facet( dataset_evals, x=lambda row: row["evals.summary"][0]["correct"], x_title="baseline correct", @@ -177,34 +177,34 @@ def eval_board(dataset, eval_result0, eval_result1): # type: ignore correct_comparison = main.add( "correct_comparison", facet_correct, - layout=weave.legacy.panels.GroupPanelLayout(x=0, y=8, w=12, h=6), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=0, y=8, w=12, h=6), ) main.add( "help", - weave.legacy.panels.PanelString( + weave.legacy.weave.panels.PanelString( "Click a cell in in the panel to the left to load examples for that cell.\n\nClick a row number in the table below to see details for that row.", mode="markdown", ), - layout=weave.legacy.panels.GroupPanelLayout(x=12, y=8, w=12, h=6), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=12, y=8, w=12, h=6), ) # main.add( # "example_latencies", - # weave.legacy.panels.Plot( + # weave.legacy.weave.panels.Plot( # dataset_evals, # x=lambda row: row["evals.summary"]["latency"][0], # y=lambda row: row["evals.summary"]["latency"][1], # ), - # layout=weave.legacy.panels.GroupPanelLayout(x=12, y=8, w=12, h=6), + # layout=weave.legacy.weave.panels.GroupPanelLayout(x=12, y=8, w=12, h=6), # ) - sel_ex_table = weave.legacy.panels.Table(correct_comparison.selected()) + sel_ex_table = weave.legacy.weave.panels.Table(correct_comparison.selected()) sel_ex_table.config.rowSize = 2 sel_ex_table.add_column(lambda row: row["dataset.id"], "id") sel_ex_table.add_column(lambda row: row["dataset.example"], "example") sel_ex_table.add_column(lambda row: row["dataset.label.name"], "label.name") sel_ex_table.add_column( - lambda row: weave.legacy.ops.dict_( + lambda row: weave.legacy.weave.ops.dict_( baseline=row["evals.result"][0]["name"], candidate=row["evals.result"][1]["name"], ), @@ -212,7 +212,7 @@ def eval_board(dataset, eval_result0, eval_result1): # type: ignore ) sel_ex_table.add_column(lambda row: row["dataset.label.shares"], "label.shares") sel_ex_table.add_column( - lambda row: weave.legacy.ops.dict_( + lambda row: weave.legacy.weave.ops.dict_( baseilne=row["evals.result"][0]["shares"].toString(), candidate=row["evals.result"][1]["shares"].toString(), ), @@ -222,14 +222,14 @@ def eval_board(dataset, eval_result0, eval_result1): # type: ignore lambda row: row["dataset.label.directors"], "label.directors" ) sel_ex_table.add_column( - lambda row: weave.legacy.ops.dict_( + lambda row: weave.legacy.weave.ops.dict_( baseilne=row["evals.result"][0]["directors"].toString(), candidate=row["evals.result"][1]["directors"].toString(), ), "result.directors", ) sel_ex_table.add_column( - lambda row: weave.legacy.ops.dict_( + lambda row: weave.legacy.weave.ops.dict_( baseilne=row["evals.summary"][0]["latency"], candidate=row["evals.summary"][1]["latency"], ), @@ -239,19 +239,19 @@ def eval_board(dataset, eval_result0, eval_result1): # type: ignore selected_examples = main.add( "selected_examples", sel_ex_table, - layout=weave.legacy.panels.GroupPanelLayout(x=0, y=14, w=24, h=12), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=0, y=14, w=24, h=12), ) main.add( "baseilne_detail", selected_examples.active_data()["evals.summary"][0], - layout=weave.legacy.panels.GroupPanelLayout(x=0, y=26, w=12, h=8), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=0, y=26, w=12, h=8), ) main.add( "candidate_detail", selected_examples.active_data()["evals.summary"][1], - layout=weave.legacy.panels.GroupPanelLayout(x=12, y=26, w=12, h=8), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=12, y=26, w=12, h=8), ) - return weave.legacy.panels.Board(vars=varbar, panels=main) + return weave.legacy.weave.panels.Board(vars=varbar, panels=main) diff --git a/weave/legacy/panels_py/panel_example_custom_board.py b/weave/legacy/weave/panels_py/panel_example_custom_board.py similarity index 76% rename from weave/legacy/panels_py/panel_example_custom_board.py rename to weave/legacy/weave/panels_py/panel_example_custom_board.py index fa3bd6641df..eb118a56d5d 100644 --- a/weave/legacy/panels_py/panel_example_custom_board.py +++ b/weave/legacy/weave/panels_py/panel_example_custom_board.py @@ -1,7 +1,7 @@ import weave -from weave.legacy import weave_internal as internal -from weave.legacy import weave_types as types -from weave.legacy.panels_py.generator_templates import template_registry +from weave.legacy.weave import weave_internal as internal +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.panels_py.generator_templates import template_registry # IMPORTANT: To enable this (or any template), it must be imported in # weave/panels_py/__init__.py This example is explicitly commented out since it @@ -40,13 +40,13 @@ ) def board( input_node, -) -> weave.legacy.panels.Group: +) -> weave.legacy.weave.panels.Group: # Define your VarBar variables here control_items = [ - weave.legacy.panels.GroupPanel( + weave.legacy.weave.panels.GroupPanel( internal.const("Example Custom Board"), id="title" ), - weave.legacy.panels.GroupPanel(input_node, id="data"), + weave.legacy.weave.panels.GroupPanel(input_node, id="data"), ] title_var = internal.make_var_node(input_node.type, "title") @@ -54,8 +54,8 @@ def board( # Define your panels here panels = [ - weave.legacy.panels.BoardPanel(title_var, id="title_panel"), - weave.legacy.panels.BoardPanel(data_var, id="table"), + weave.legacy.weave.panels.BoardPanel(title_var, id="title_panel"), + weave.legacy.weave.panels.BoardPanel(data_var, id="table"), ] # Example of using the input type to modify the board: @@ -63,13 +63,13 @@ def board( for column_name, column_type in input_node.type.object_type.property_types.items(): if types.optional(types.Number()).assign_type(column_type): panels.append( - weave.legacy.panels.BoardPanel( + weave.legacy.weave.panels.BoardPanel( data_var[column_name], # type: ignore id=column_name + "_distribution", ) ) - return weave.legacy.panels.Board(vars=control_items, panels=panels) + return weave.legacy.weave.panels.Board(vars=control_items, panels=panels) template_registry.register( diff --git a/weave/legacy/panels_py/panel_llm_monitor.py b/weave/legacy/weave/panels_py/panel_llm_monitor.py similarity index 85% rename from weave/legacy/panels_py/panel_llm_monitor.py rename to weave/legacy/weave/panels_py/panel_llm_monitor.py index d51810eb0a5..ed5c3563ec9 100644 --- a/weave/legacy/panels_py/panel_llm_monitor.py +++ b/weave/legacy/weave/panels_py/panel_llm_monitor.py @@ -2,16 +2,16 @@ import typing import weave -from weave.legacy import weave_internal -from weave.legacy import weave_internal as internal -from weave.legacy import weave_types as types -from weave.legacy import util, dispatch -from weave.legacy.panels import panel_board, panel_group -from weave.legacy.panels_py import panel_autoboard -from weave.legacy.panels_py.generator_templates import template_registry +from weave.legacy.weave import weave_internal +from weave.legacy.weave import weave_internal as internal +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import util, dispatch +from weave.legacy.weave.panels import panel_board, panel_group +from weave.legacy.weave.panels_py import panel_autoboard +from weave.legacy.weave.panels_py.generator_templates import template_registry -panels = weave.legacy.panels -ops = weave.legacy.ops +panels = weave.legacy.weave.panels +ops = weave.legacy.weave.ops # BOARD_ID must be unique across all ops. It must only contain letters and underscores. @@ -101,7 +101,7 @@ # input_node: weave.Node[list[typing.Any]] # @weave.op() -# def render(self) -> weave.legacy.panels.Table: +# def render(self) -> weave.legacy.weave.panels.Table: # table = panels.Table( # self.input_node, # columns=[lambda row: row["inputs"]["messages"][-1]["content"]], @@ -137,7 +137,7 @@ def openai_request_cost(record) -> float: # type: ignore model = record["output.model"] pt = record["summary.prompt_tokens"] ct = record["summary.completion_tokens"] - cost_per_1000 = weave.legacy.ops.case( + cost_per_1000 = weave.legacy.weave.ops.case( [ # finetuned {"when": model.startsWith("ada:"), "then": pt * 0.0016 + ct * 0.0016}, @@ -196,7 +196,7 @@ def board( augmented_data = varbar.add( "augmented_data", source_data.with_columns( - weave.legacy.ops.dict_( + weave.legacy.weave.ops.dict_( **{ "summary.cost": source_data.map( lambda row: openai_request_cost(row) @@ -231,7 +231,7 @@ def board( ## 1. raw_data_range is derived from raw_data filtered_range = varbar.add( "filtered_range", - weave.legacy.ops.make_list( + weave.legacy.weave.ops.make_list( a=filtered_data[timestamp_col_name].min(), b=filtered_data[timestamp_col_name].max(), ), @@ -244,7 +244,7 @@ def board( ## 2.b: Setup a date picker to set the user_zoom_range varbar.add( "time_range", - weave.legacy.panels.DateRange( + weave.legacy.weave.panels.DateRange( user_zoom_range, domain=source_data[timestamp_col_name] ), ) @@ -259,7 +259,7 @@ def board( window_data = varbar.add( "window_data", augmented_data.filter( - lambda row: weave.legacy.ops.Boolean.bool_and( + lambda row: weave.legacy.weave.ops.Boolean.bool_and( row[timestamp_col_name] >= bin_range[0], row[timestamp_col_name] <= bin_range[1], ) @@ -269,7 +269,7 @@ def board( filters = varbar.add( "filters", - weave.legacy.panels.FilterEditor(filter_fn, node=window_data), + weave.legacy.weave.panels.FilterEditor(filter_fn, node=window_data), ) filtered_window_data = varbar.add( @@ -278,14 +278,14 @@ def board( grouping = varbar.add( "grouping", - weave.legacy.panels.GroupingEditor(grouping_fn, node=window_data), + weave.legacy.weave.panels.GroupingEditor(grouping_fn, node=window_data), ) height = 5 ### Overview tab - overview_tab = weave.legacy.panels.Group( + overview_tab = weave.legacy.weave.panels.Group( layoutMode="grid", showExpressions=True, enableAddPanel=True, @@ -304,7 +304,7 @@ def board( n_bins=100, mark="bar", ), - layout=weave.legacy.panels.GroupPanelLayout(x=0, y=0, w=24, h=height), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=0, y=0, w=24, h=height), ) overview_tab.add( @@ -320,7 +320,7 @@ def board( x_domain=user_zoom_range, n_bins=50, ), - layout=weave.legacy.panels.GroupPanelLayout(x=0, y=height, w=12, h=height), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=0, y=height, w=12, h=height), ) overview_tab.add( @@ -336,29 +336,29 @@ def board( x_domain=user_zoom_range, n_bins=50, ), - layout=weave.legacy.panels.GroupPanelLayout(x=12, y=height, w=12, h=height), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=12, y=height, w=12, h=height), ) overview_tab.add( "avg_cost_per_req", filtered_window_data["summary.cost"].avg(), # type: ignore - layout=weave.legacy.panels.GroupPanelLayout(x=0, y=height * 2, w=6, h=3), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=0, y=height * 2, w=6, h=3), ) overview_tab.add( "avg_prompt_tokens_per_req", filtered_window_data["summary.prompt_tokens"].avg(), # type: ignore - layout=weave.legacy.panels.GroupPanelLayout(x=6, y=height * 2, w=6, h=3), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=6, y=height * 2, w=6, h=3), ) overview_tab.add( "avg_completion_tokens_per_req", filtered_window_data["summary.completion_tokens"].avg(), # type: ignore - layout=weave.legacy.panels.GroupPanelLayout(x=12, y=height * 2, w=6, h=3), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=12, y=height * 2, w=6, h=3), ) ( overview_tab.add( "avg_total_tokens_per_req", filtered_window_data["summary.total_tokens"].avg(), # type: ignore - layout=weave.legacy.panels.GroupPanelLayout(x=18, y=height * 2, w=6, h=3), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=18, y=height * 2, w=6, h=3), ), ) @@ -366,12 +366,12 @@ def board( # TODO: This doesn't really work yet (needs some manual UI configuration currently, # and it's ugly). # overview_tab.add( - # "attributes", weave.legacy.panels.EachColumn(filtered_window_data["attributes"]) + # "attributes", weave.legacy.weave.panels.EachColumn(filtered_window_data["attributes"]) # ) ### Requests tab - # requests_tab = weave.legacy.panels.Group( + # requests_tab = weave.legacy.weave.panels.Group( # layoutMode="grid", # showExpressions=True, # ) # l, showExpressions="titleBar") @@ -399,7 +399,7 @@ def board( requests_table_var = overview_tab.add( "table", requests_table, - layout=weave.legacy.panels.GroupPanelLayout(x=0, y=13, w=24, h=8), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=0, y=13, w=24, h=8), ) overview_tab.add( "input", @@ -407,19 +407,19 @@ def board( requests_table_var.active_data()["inputs.messages"], columns=[lambda row: row["role"], lambda row: row["content"]], ), - layout=weave.legacy.panels.GroupPanelLayout(x=0, y=21, w=12, h=8), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=0, y=21, w=12, h=8), ) overview_tab.add( "output", requests_table_var.active_row(), - layout=weave.legacy.panels.GroupPanelLayout(x=12, y=21, w=12, h=8), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=12, y=21, w=12, h=8), ) - # attributes_tab = weave.legacy.panels.Group(layoutMode="grid") + # attributes_tab = weave.legacy.weave.panels.Group(layoutMode="grid") - # users_tab = weave.legacy.panels.Group(layoutMode="grid") + # users_tab = weave.legacy.weave.panels.Group(layoutMode="grid") - # models_tab = weave.legacy.panels.Group(layoutMode="grid") + # models_tab = weave.legacy.weave.panels.Group(layoutMode="grid") # tabs = panels.Group( # layoutMode="tab", diff --git a/weave/legacy/panels_py/panel_observability.py b/weave/legacy/weave/panels_py/panel_observability.py similarity index 81% rename from weave/legacy/panels_py/panel_observability.py rename to weave/legacy/weave/panels_py/panel_observability.py index a6ea920d2f4..1987039cfcb 100644 --- a/weave/legacy/panels_py/panel_observability.py +++ b/weave/legacy/weave/panels_py/panel_observability.py @@ -1,10 +1,10 @@ import weave -from weave.legacy import weave_internal -from weave.legacy import weave_types as types -from weave.legacy.panels import panel_board -from weave.legacy.panels_py.generator_templates import template_registry +from weave.legacy.weave import weave_internal +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.panels import panel_board +from weave.legacy.weave.panels_py.generator_templates import template_registry -panels = weave.legacy.panels +panels = weave.legacy.weave.panels BOARD_INPUT_WEAVE_TYPE = types.List( types.TypedDict( @@ -76,16 +76,16 @@ def observability( timestamp_col_name = "timestamp" num_buckets = 80 - now = weave.legacy.ops.datetime_now() + now = weave.legacy.weave.ops.datetime_now() - dashboard = weave.legacy.panels.Group( + dashboard = weave.legacy.weave.panels.Group( layoutMode="grid", showExpressions=False, enableAddPanel=False, disableDeletePanel=True, ) - display_states = weave.legacy.ops.dict_( + display_states = weave.legacy.weave.ops.dict_( **{ "running": "running", "failed": "failed", @@ -100,7 +100,7 @@ def observability( varbar = panel_board.varbar(editable=False) source_data = input_node.map( - lambda row: weave.legacy.ops.dict_( + lambda row: weave.legacy.weave.ops.dict_( **{ "timestamp": row[timestamp_col_name], "entity_name": row["entity_name"], @@ -141,18 +141,18 @@ def observability( seven_days_in_seconds = 60 * 60 * 24 * 7 window_start = varbar.add( "window_start", - weave.legacy.ops.from_number(now - seven_days_in_seconds), + weave.legacy.weave.ops.from_number(now - seven_days_in_seconds), hidden=True, ) window_end = varbar.add( "window_end", - weave.legacy.ops.from_number(now), + weave.legacy.weave.ops.from_number(now), hidden=True, ) filtered_range = varbar.add( "filtered_range", - weave.legacy.ops.make_list( + weave.legacy.weave.ops.make_list( a=window_start, b=window_end, ), @@ -173,9 +173,9 @@ def observability( ) window_data = source_data.filter( - lambda row: weave.legacy.ops.Boolean.bool_and( + lambda row: weave.legacy.weave.ops.Boolean.bool_and( row["state"] != "TO_REMOVE", # remove hidden states - weave.legacy.ops.Boolean.bool_and( + weave.legacy.weave.ops.Boolean.bool_and( row[timestamp_col_name] >= bin_range[0], row[timestamp_col_name] <= bin_range[1], ), @@ -196,7 +196,7 @@ def observability( panels.FilterEditor(filter_fn, node=window_data), ) - colors_node = weave.legacy.ops.dict_( + colors_node = weave.legacy.weave.ops.dict_( **{ "running": "rgb(57, 126, 237)", "failed": "rgb(255, 122, 136)", @@ -216,7 +216,7 @@ def observability( queued_time_data = varbar.add( "queued_time_data", filtered_window_data.filter( - lambda row: weave.legacy.ops.Boolean.bool_or( + lambda row: weave.legacy.weave.ops.Boolean.bool_or( row["state"] == "queued", row["state"] == "pending", ), @@ -226,11 +226,11 @@ def observability( is_start_stop_state = weave_internal.define_fn( {"row": source_data.type.object_type}, - lambda row: weave.legacy.ops.Boolean.bool_or( + lambda row: weave.legacy.weave.ops.Boolean.bool_or( row["state"] == "running", - weave.legacy.ops.Boolean.bool_or( + weave.legacy.weave.ops.Boolean.bool_or( row["state"] == "finished", - weave.legacy.ops.Boolean.bool_or( + weave.legacy.weave.ops.Boolean.bool_or( row["state"] == "crashed", row["state"] == "failed", ), @@ -241,17 +241,17 @@ def observability( state_transitions_plot = panels.Plot( filtered_window_data, x=lambda row: row[timestamp_col_name].bin( - weave.legacy.ops.timestamp_bins_nice(bin_range, num_buckets) + weave.legacy.weave.ops.timestamp_bins_nice(bin_range, num_buckets) ), x_title="Time", y=lambda row: row.count(), y_title="Count of transitions by state", label=lambda row: row["state"], - tooltip=lambda row: weave.legacy.ops.dict_( + tooltip=lambda row: weave.legacy.weave.ops.dict_( **{ "State": row["state"][0], "Count": row.count(), - "Job (s)": weave.legacy.ops.join_to_str(row["job"].unique(), ","), + "Job (s)": weave.legacy.weave.ops.join_to_str(row["job"].unique(), ","), } ), color_title="state", @@ -261,12 +261,12 @@ def observability( domain_x=user_zoom_range, ) - runs_grouped = weave.legacy.ops.List.groupby( + runs_grouped = weave.legacy.weave.ops.List.groupby( queued_time_data, lambda row: row["trace_id"] ) - runs_mapped = weave.legacy.ops.List.map( + runs_mapped = weave.legacy.weave.ops.List.map( runs_grouped, - lambda row: weave.legacy.ops.dict_( + lambda row: weave.legacy.weave.ops.dict_( **{ "trace_id": row["trace_id"][0], "entity_name": row["entity_name"][0], @@ -275,10 +275,10 @@ def observability( "job": row["job"][-1], "enqueued": row[timestamp_col_name][0], "run_start": row[timestamp_col_name][-1], - "duration": weave.legacy.ops.Number.__truediv__( - weave.legacy.ops.Number.__mul__( - weave.legacy.ops.timedelta_total_seconds( - weave.legacy.ops.datetime_sub( + "duration": weave.legacy.weave.ops.Number.__truediv__( + weave.legacy.weave.ops.Number.__mul__( + weave.legacy.weave.ops.timedelta_total_seconds( + weave.legacy.weave.ops.datetime_sub( row[timestamp_col_name].max(), row[timestamp_col_name].min(), ), @@ -292,7 +292,7 @@ def observability( ) runs_mapped_filtered = varbar.add( "runs_mapped_filtered", - weave.legacy.ops.List.filter( + weave.legacy.weave.ops.List.filter( runs_mapped, lambda row: row["duration"] >= 0, ), @@ -302,19 +302,19 @@ def observability( queued_time_plot = panels.Plot( runs_mapped_filtered, x=lambda row: row["run_start"].bin( - weave.legacy.ops.timestamp_bins_nice(bin_range, num_buckets) + weave.legacy.weave.ops.timestamp_bins_nice(bin_range, num_buckets) ), x_title="Time", y=lambda row: row["duration"].sum(), y_title="Time spent queued (m)", label=lambda row: grouping_fn(row), - tooltip=lambda row: weave.legacy.ops.dict_( + tooltip=lambda row: weave.legacy.weave.ops.dict_( **{ - "Job (s)": weave.legacy.ops.join_to_str(row["job"].unique(), ","), - "User (s)": weave.legacy.ops.join_to_str( + "Job (s)": weave.legacy.weave.ops.join_to_str(row["job"].unique(), ","), + "User (s)": weave.legacy.weave.ops.join_to_str( row["entity_name"].unique(), "," ), - "Project (s)": weave.legacy.ops.join_to_str( + "Project (s)": weave.legacy.weave.ops.join_to_str( row["project_name"].unique(), "," ), "Duration (m)": row["duration"].sum(), @@ -329,7 +329,7 @@ def observability( start_stop_states = varbar.add( "start_stop_states", - weave.legacy.ops.List.filter(filtered_window_data, is_start_stop_state), + weave.legacy.weave.ops.List.filter(filtered_window_data, is_start_stop_state), hidden=True, ) @@ -339,7 +339,7 @@ def observability( x_title="Time", y_title="Job", y=lambda row: row["job"], - tooltip=lambda row: weave.legacy.ops.dict_( + tooltip=lambda row: weave.legacy.weave.ops.dict_( **{ "Job": row["job"][0], "User": row["entity_name"][0], @@ -347,10 +347,10 @@ def observability( "Project": row["project_name"][0], "Run ID": row["run_id"][-1], "Status": row["state"][-1], - "Duration (m)": weave.legacy.ops.Number.__truediv__( - weave.legacy.ops.Number.__mul__( - weave.legacy.ops.timedelta_total_seconds( - weave.legacy.ops.datetime_sub( + "Duration (m)": weave.legacy.weave.ops.Number.__truediv__( + weave.legacy.weave.ops.Number.__mul__( + weave.legacy.weave.ops.timedelta_total_seconds( + weave.legacy.weave.ops.datetime_sub( row[timestamp_col_name].max(), row[timestamp_col_name].min(), ), @@ -378,7 +378,7 @@ def observability( jobs_table = panels.Table(jobs) # type: ignore jobs_table.add_column(lambda row: row["run_id"], "Run", groupby=True) jobs_table.add_column( - lambda row: weave.legacy.ops.run_ops.str_run_link( + lambda row: weave.legacy.weave.ops.run_ops.str_run_link( entity_name=row["queue_uri"][0].split(":").index(2), project_name=row["project_name"][0], name=row["run_id"][0], @@ -396,26 +396,26 @@ def observability( "Current state", ) jobs_table.add_column( - lambda row: weave.legacy.ops.cond( - weave.legacy.ops.dict_( + lambda row: weave.legacy.weave.ops.cond( + weave.legacy.weave.ops.dict_( a=row["state"][-1] != "running", b=row["state"][-1] == "running", ), - weave.legacy.ops.dict_( - a=weave.legacy.ops.Number.__truediv__( - weave.legacy.ops.timedelta_total_seconds( - weave.legacy.ops.datetime_sub( + weave.legacy.weave.ops.dict_( + a=weave.legacy.weave.ops.Number.__truediv__( + weave.legacy.weave.ops.timedelta_total_seconds( + weave.legacy.weave.ops.datetime_sub( row[timestamp_col_name].max(), row[timestamp_col_name].min(), ) ), 60, ), - b=weave.legacy.ops.Number.__truediv__( - weave.legacy.ops.timedelta_total_seconds( - weave.legacy.ops.datetime_sub( - weave.legacy.ops.from_number( - weave.legacy.ops.datetime_now() + b=weave.legacy.weave.ops.Number.__truediv__( + weave.legacy.weave.ops.timedelta_total_seconds( + weave.legacy.weave.ops.datetime_sub( + weave.legacy.weave.ops.from_number( + weave.legacy.weave.ops.datetime_now() ), row[timestamp_col_name].min(), ) @@ -427,66 +427,66 @@ def observability( "Runtime (m)", ) jobs_table.add_column( - lambda row: weave.legacy.ops.cond( - weave.legacy.ops.dict_( + lambda row: weave.legacy.weave.ops.cond( + weave.legacy.weave.ops.dict_( a=row["state"][-1] != "running", b=row["state"][-1] == "running", ), - weave.legacy.ops.dict_( + weave.legacy.weave.ops.dict_( a=row["metrics"]["system"]["cpu_cores_util"][-1].avg(), - b=weave.legacy.ops.make_const_node(types.NoneType(), None), + b=weave.legacy.weave.ops.make_const_node(types.NoneType(), None), ), ), "Avg. CPU %", ) jobs_table.add_column( - lambda row: weave.legacy.ops.cond( - weave.legacy.ops.dict_( + lambda row: weave.legacy.weave.ops.cond( + weave.legacy.weave.ops.dict_( a=row["state"][-1] != "running", b=row["state"][-1] == "running", ), - weave.legacy.ops.dict_( + weave.legacy.weave.ops.dict_( a=row["metrics"]["system"]["gpu_cores_util"][-1].avg(), - b=weave.legacy.ops.make_const_node(types.NoneType(), None), + b=weave.legacy.weave.ops.make_const_node(types.NoneType(), None), ), ), "Avg. GPU %", ) jobs_table.add_column( - lambda row: weave.legacy.ops.cond( - weave.legacy.ops.dict_( + lambda row: weave.legacy.weave.ops.cond( + weave.legacy.weave.ops.dict_( a=row["state"][-1] != "running", b=row["state"][-1] == "running", ), - weave.legacy.ops.dict_( + weave.legacy.weave.ops.dict_( a=row["metrics"]["system"]["gpu_cores_mem"][-1].avg(), - b=weave.legacy.ops.make_const_node(types.NoneType(), None), + b=weave.legacy.weave.ops.make_const_node(types.NoneType(), None), ), ), "Avg. GPU mem. %", ) jobs_table.add_column( - lambda row: weave.legacy.ops.cond( - weave.legacy.ops.dict_( + lambda row: weave.legacy.weave.ops.cond( + weave.legacy.weave.ops.dict_( a=row["state"][-1] != "running", b=row["state"][-1] == "running", ), - weave.legacy.ops.dict_( + weave.legacy.weave.ops.dict_( a=row["metrics"]["system"]["memory"][-1], - b=weave.legacy.ops.make_const_node(types.NoneType(), None), + b=weave.legacy.weave.ops.make_const_node(types.NoneType(), None), ), ), "Avg. mem (MB)", ) - runs_table_data = weave.legacy.ops.List.groupby( + runs_table_data = weave.legacy.weave.ops.List.groupby( filtered_window_data, lambda row: row["trace_id"] ) runs_table_data_mapped = varbar.add( "runs_table_data", - weave.legacy.ops.List.map( + weave.legacy.weave.ops.List.map( runs_table_data, - lambda row: weave.legacy.ops.dict_( + lambda row: weave.legacy.weave.ops.dict_( **{ "trace_id": row["trace_id"][0], "user": row["entity_name"][0], @@ -522,7 +522,7 @@ def observability( ) runs_table.add_column( lambda row: row.filter( - lambda row: weave.legacy.ops.Boolean.bool_or( + lambda row: weave.legacy.weave.ops.Boolean.bool_or( row["states"][-1] == "crashed", row["states"][-1] == "failed", ), @@ -533,9 +533,9 @@ def observability( finished_runs = varbar.add( "finished_runs", filtered_window_data.filter( - lambda row: weave.legacy.ops.Boolean.bool_or( + lambda row: weave.legacy.weave.ops.Boolean.bool_or( row["state"] == "finished", - weave.legacy.ops.Boolean.bool_or( + weave.legacy.weave.ops.Boolean.bool_or( row["state"] == "crashed", row["state"] == "failed", ), @@ -556,24 +556,24 @@ def observability( no_legend=True, ) - metric_plot_data = weave.legacy.ops.List.groupby( + metric_plot_data = weave.legacy.weave.ops.List.groupby( start_stop_states, lambda row: row["trace_id"] ) metric_plot_data_mapped = varbar.add( "metric_plot_data", - weave.legacy.ops.List.map( + weave.legacy.weave.ops.List.map( metric_plot_data, - lambda row: weave.legacy.ops.dict_( + lambda row: weave.legacy.weave.ops.dict_( **{ "trace_id": row["trace_id"][0], "run_id": row["run_id"][-1], "entity_name": row["entity_name"][0], "project_name": row["project_name"][0], "job": row["job"][0], - "duration": weave.legacy.ops.Number.__truediv__( - weave.legacy.ops.Number.__mul__( - weave.legacy.ops.timedelta_total_seconds( - weave.legacy.ops.datetime_sub( + "duration": weave.legacy.weave.ops.Number.__truediv__( + weave.legacy.weave.ops.Number.__mul__( + weave.legacy.weave.ops.timedelta_total_seconds( + weave.legacy.weave.ops.datetime_sub( row[timestamp_col_name].max(), row[timestamp_col_name].min(), ), @@ -598,7 +598,7 @@ def observability( x_title="Run duration (minutes)", y_title="GPU utilization (%)", y=lambda row: row["GPU util %"], - tooltip=lambda row: weave.legacy.ops.dict_( + tooltip=lambda row: weave.legacy.weave.ops.dict_( **{ "Run ID": row["run_id"], "Project": row["project_name"], @@ -622,7 +622,7 @@ def observability( x_title="Run duration (minutes)", y_title="CPU utilization (%)", y=lambda row: row["CPU util %"], - tooltip=lambda row: weave.legacy.ops.dict_( + tooltip=lambda row: weave.legacy.weave.ops.dict_( **{ "Run ID": row["run_id"], "Project": row["project_name"], @@ -646,7 +646,7 @@ def observability( x_title="Run duration (minutes)", y_title="GPU memory (%)", y=lambda row: row["GPU memory %"], - tooltip=lambda row: weave.legacy.ops.dict_( + tooltip=lambda row: weave.legacy.weave.ops.dict_( **{ "Run ID": row["run_id"], "Project": row["project_name"], @@ -670,7 +670,7 @@ def observability( x_title="Run duration (minutes)", y_title="Memory usage (MB)", y=lambda row: row["Memory (MB)"], - tooltip=lambda row: weave.legacy.ops.dict_( + tooltip=lambda row: weave.legacy.weave.ops.dict_( **{ "Run ID": row["run_id"], "Project": row["project_name"], @@ -724,7 +724,7 @@ def observability( ) selected_jobs = panels.Table(latest_runs_plot_selector.selected_rows()) # type: ignore selected_jobs.add_column( - lambda row: weave.legacy.ops.run_ops.str_run_link( + lambda row: weave.legacy.weave.ops.run_ops.str_run_link( entity_name=row["c_4.Team"], project_name=row["c_4.Project"], name=row["c_4.Run ID"], diff --git a/weave/legacy/panels_py/panel_seedboard.py b/weave/legacy/weave/panels_py/panel_seedboard.py similarity index 60% rename from weave/legacy/panels_py/panel_seedboard.py rename to weave/legacy/weave/panels_py/panel_seedboard.py index 4887f66f854..c21cd0e66de 100644 --- a/weave/legacy/panels_py/panel_seedboard.py +++ b/weave/legacy/weave/panels_py/panel_seedboard.py @@ -1,8 +1,8 @@ import typing import weave -from weave.legacy import weave_internal -from weave.legacy.panels_py.generator_templates import template_registry +from weave.legacy.weave import weave_internal +from weave.legacy.weave.panels_py.generator_templates import template_registry @weave.type() @@ -17,22 +17,22 @@ class PyBoardSeedBoardConfig: def seed_board( input_node: weave.Node[typing.Any], config: typing.Optional[PyBoardSeedBoardConfig] = None, -) -> weave.legacy.panels.Group: +) -> weave.legacy.weave.panels.Group: control_items = [ - weave.legacy.panels.GroupPanel( + weave.legacy.weave.panels.GroupPanel( input_node, id="data", ), ] panels = [ - weave.legacy.panels.BoardPanel( + weave.legacy.weave.panels.BoardPanel( weave_internal.make_var_node(input_node.type, "data"), id="panel", - layout=weave.legacy.panels.BoardPanelLayout(x=0, y=0, w=24, h=6), + layout=weave.legacy.weave.panels.BoardPanelLayout(x=0, y=0, w=24, h=6), ), ] - return weave.legacy.panels.Board(vars=control_items, panels=panels) + return weave.legacy.weave.panels.Board(vars=control_items, panels=panels) template_registry.register( diff --git a/weave/legacy/panels_py/panel_trace_monitor.py b/weave/legacy/weave/panels_py/panel_trace_monitor.py similarity index 81% rename from weave/legacy/panels_py/panel_trace_monitor.py rename to weave/legacy/weave/panels_py/panel_trace_monitor.py index 9bd91d96090..e1cf168c432 100644 --- a/weave/legacy/panels_py/panel_trace_monitor.py +++ b/weave/legacy/weave/panels_py/panel_trace_monitor.py @@ -1,17 +1,17 @@ import os import weave -from weave.legacy import weave_internal -from weave.legacy import weave_internal as internal -from weave.legacy import weave_types as types -from weave.legacy import util, dispatch, graph -from weave.legacy.panels import panel_board, panel_group, panel_trace -from weave.legacy.panels.panel_trace_span import TraceSpanModelPanel, TraceSpanPanel -from weave.legacy.panels_py import panel_autoboard -from weave.legacy.panels_py.generator_templates import template_registry +from weave.legacy.weave import weave_internal +from weave.legacy.weave import weave_internal as internal +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import util, dispatch, graph +from weave.legacy.weave.panels import panel_board, panel_group, panel_trace +from weave.legacy.weave.panels.panel_trace_span import TraceSpanModelPanel, TraceSpanPanel +from weave.legacy.weave.panels_py import panel_autoboard +from weave.legacy.weave.panels_py.generator_templates import template_registry -panels = weave.legacy.panels -ops = weave.legacy.ops +panels = weave.legacy.weave.panels +ops = weave.legacy.weave.ops # BOARD_ID must be unique across all ops. It must only contain letters and underscores. @@ -101,7 +101,7 @@ def board( ## 1. raw_data_range is derived from raw_data filtered_range = varbar.add( "filtered_range", - weave.legacy.ops.make_list( + weave.legacy.weave.ops.make_list( a=filtered_data[timestamp_col_name].min(), b=filtered_data[timestamp_col_name].max(), ), @@ -114,7 +114,7 @@ def board( ## 2.b: Setup a date picker to set the user_zoom_range varbar.add( "time_range", - weave.legacy.panels.DateRange( + weave.legacy.weave.panels.DateRange( user_zoom_range, domain=trace_roots[timestamp_col_name] ), ) @@ -129,7 +129,7 @@ def board( window_data = varbar.add( "window_data", trace_roots.filter( - lambda row: weave.legacy.ops.Boolean.bool_and( + lambda row: weave.legacy.weave.ops.Boolean.bool_and( row[timestamp_col_name] >= bin_range[0], row[timestamp_col_name] <= bin_range[1], ) @@ -139,7 +139,7 @@ def board( filters = varbar.add( "filters", - weave.legacy.panels.FilterEditor(filter_fn, node=window_data), + weave.legacy.weave.panels.FilterEditor(filter_fn, node=window_data), ) filtered_window_data = varbar.add( @@ -148,7 +148,7 @@ def board( ### Overview tab - overview_tab = weave.legacy.panels.Group( + overview_tab = weave.legacy.weave.panels.Group( layoutMode="grid", showExpressions=True, enableAddPanel=True, @@ -171,13 +171,13 @@ def board( x_domain=user_zoom_range, n_bins=50, ), - layout=weave.legacy.panels.GroupPanelLayout(x=0, y=0, w=6, h=6), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=0, y=0, w=6, h=6), ) overview_tab.add( "latency_distribution", filtered_window_data.map(lambda row: row["end_time_s"] - row["start_time_s"]), - layout=weave.legacy.panels.GroupPanelLayout(x=6, y=0, w=6, h=6), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=6, y=0, w=6, h=6), ) overview_tab.add( @@ -198,12 +198,12 @@ def board( x_domain=user_zoom_range, n_bins=50, ), - layout=weave.legacy.panels.GroupPanelLayout(x=12, y=0, w=6, h=6), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=12, y=0, w=6, h=6), ) overview_tab.add( "success_distribution", - weave.legacy.ops.dict_( + weave.legacy.weave.ops.dict_( **{ "success": filtered_window_data.filter( lambda row: row["status_code"] == "SUCCESS" @@ -213,13 +213,13 @@ def board( ).count(), } ), - layout=weave.legacy.panels.GroupPanelLayout(x=18, y=0, w=6, h=6), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=18, y=0, w=6, h=6), ) traces_table_var = overview_tab.add( "traces_table", make_span_table(filtered_window_data), - layout=weave.legacy.panels.GroupPanelLayout(x=0, y=6, w=24, h=6), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=0, y=6, w=24, h=6), ) trace_spans = all_spans.filter( @@ -231,13 +231,13 @@ def board( trace_viewer_var = overview_tab.add( "trace_viewer", trace_viewer, - layout=weave.legacy.panels.GroupPanelLayout(x=0, y=12, w=16, h=6), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=0, y=12, w=16, h=6), ) selected_trace_model = overview_tab.add( "selected_trace_model", TraceSpanModelPanel(traces_table_var.active_data()), - layout=weave.legacy.panels.GroupPanelLayout(x=0, y=18, w=16, h=6), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=0, y=18, w=16, h=6), ) active_span = trace_viewer_var.active_span() @@ -245,7 +245,7 @@ def board( selected_span_details = overview_tab.add( "selected_span_details", TraceSpanPanel(active_span), - layout=weave.legacy.panels.GroupPanelLayout(x=16, y=12, w=8, h=12), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=16, y=12, w=8, h=12), ) similar_spans = all_spans.filter(lambda row: row["name"] == active_span["name"]) @@ -254,7 +254,7 @@ def board( similar_spans_table_var = overview_tab.add( "similar_spans_table", similar_spans_table, - layout=weave.legacy.panels.GroupPanelLayout(x=0, y=22, w=24, h=6), + layout=weave.legacy.weave.panels.GroupPanelLayout(x=0, y=22, w=24, h=6), ) return panels.Board(vars=varbar, panels=overview_tab) diff --git a/weave/legacy/parallelism.py b/weave/legacy/weave/parallelism.py similarity index 99% rename from weave/legacy/parallelism.py rename to weave/legacy/weave/parallelism.py index a11dcfeac76..bd27582d836 100644 --- a/weave/legacy/parallelism.py +++ b/weave/legacy/weave/parallelism.py @@ -3,7 +3,7 @@ from concurrent.futures import ThreadPoolExecutor from typing import Callable, Generator, Iterator, Optional, TypeVar -from weave.legacy import ( +from weave.legacy.weave import ( cache, context, context_state, diff --git a/weave/legacy/partial_object.py b/weave/legacy/weave/partial_object.py similarity index 96% rename from weave/legacy/partial_object.py rename to weave/legacy/weave/partial_object.py index 306c12a2d73..bec6862b70a 100644 --- a/weave/legacy/partial_object.py +++ b/weave/legacy/weave/partial_object.py @@ -2,8 +2,8 @@ import typing from dataclasses import dataclass, field -from weave.legacy import weave_types as types -from weave.legacy import artifact_fs +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import artifact_fs T = typing.TypeVar("T", bound="PartialObject") @@ -136,7 +136,7 @@ def from_dict(cls, d: dict) -> "PartialObjectType": def save_instance( self, obj: PartialObject, artifact: artifact_fs.FilesystemArtifact, name: str ) -> None: - from weave.legacy import mappers_python + from weave.legacy.weave import mappers_python serializer = mappers_python.map_to_python(self, artifact) result = serializer.apply(obj) @@ -151,7 +151,7 @@ def load_instance( name: str, extra: typing.Optional[list] = None, ) -> PartialObject: - from weave.legacy import mappers_python + from weave.legacy.weave import mappers_python with artifact.open( f"{name}.{self.keyless_weave_type_class.__name__}WithKeys.json" diff --git a/weave/legacy/path_util.py b/weave/legacy/weave/path_util.py similarity index 90% rename from weave/legacy/path_util.py rename to weave/legacy/weave/path_util.py index a6504697c37..e52d5fa912d 100644 --- a/weave/legacy/path_util.py +++ b/weave/legacy/weave/path_util.py @@ -1,7 +1,7 @@ import pathlib import typing -from weave.legacy import errors +from weave.legacy.weave import errors def safe_join(*args: typing.Union[str, pathlib.Path]) -> str: diff --git a/weave/legacy/propagate_gql_keys.py b/weave/legacy/weave/propagate_gql_keys.py similarity index 93% rename from weave/legacy/propagate_gql_keys.py rename to weave/legacy/weave/propagate_gql_keys.py index b32fbd3ad32..a605b407cf3 100644 --- a/weave/legacy/propagate_gql_keys.py +++ b/weave/legacy/weave/propagate_gql_keys.py @@ -1,8 +1,8 @@ import typing -from weave.legacy import weave_types as types -from weave.legacy import gql_op_plugin, graph, input_provider, op_def, partial_object, registry_mem +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import gql_op_plugin, graph, input_provider, op_def, partial_object, registry_mem def _propagate_gql_keys_for_node( @@ -13,7 +13,7 @@ def _propagate_gql_keys_for_node( ) -> types.Type: # Mutates node # TODO: see if this can be done without mutations - from weave.legacy.language_features.tagging import ( + from weave.legacy.weave.language_features.tagging import ( opdef_util, tagged_value_type, tagged_value_type_helpers, diff --git a/weave/legacy/pyfunc_type_util.py b/weave/legacy/weave/pyfunc_type_util.py similarity index 98% rename from weave/legacy/pyfunc_type_util.py rename to weave/legacy/weave/pyfunc_type_util.py index c72318e515d..2a12827822f 100644 --- a/weave/legacy/pyfunc_type_util.py +++ b/weave/legacy/weave/pyfunc_type_util.py @@ -1,10 +1,10 @@ import inspect import typing -from weave.legacy import infer_types, op_args +from weave.legacy.weave import infer_types, op_args -from weave.legacy import errors -from weave.legacy import weave_types as types +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types InputTypeItemType = typing.Union[types.Type, typing.Callable[..., types.Type]] InputTypeType = typing.Union[op_args.OpArgs, typing.Mapping[str, InputTypeItemType]] diff --git a/weave/legacy/ref_base.py b/weave/legacy/weave/ref_base.py similarity index 95% rename from weave/legacy/ref_base.py rename to weave/legacy/weave/ref_base.py index 107ca9ca6c1..6951fe602b3 100644 --- a/weave/legacy/ref_base.py +++ b/weave/legacy/weave/ref_base.py @@ -6,17 +6,17 @@ from typing import Sequence from weave.trace.client_context import weave_client as weave_client_context -from weave.legacy import box, context_state, object_context, uris -from weave.legacy.language_features.tagging import tag_store +from weave.legacy.weave import box, context_state, object_context, uris +from weave.legacy.weave.language_features.tagging import tag_store -from weave.legacy import errors -from weave.legacy import weave_types as types +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types # We store Refs here if we can't attach them directly to the object REFS: weakref.WeakValueDictionary[int, "Ref"] = weakref.WeakValueDictionary() if typing.TYPE_CHECKING: - from weave.legacy import weave_types as types + from weave.legacy.weave import weave_types as types from ..trace import weave_client diff --git a/weave/legacy/registry_mem.py b/weave/legacy/weave/registry_mem.py similarity index 95% rename from weave/legacy/registry_mem.py rename to weave/legacy/weave/registry_mem.py index 625c18ca60e..7e0f0905b17 100644 --- a/weave/legacy/registry_mem.py +++ b/weave/legacy/weave/registry_mem.py @@ -1,12 +1,12 @@ import datetime import typing -from weave.legacy import weave_types -from weave.legacy import storage, errors, context_state, op_aliases, op_args, uris -from weave.legacy.op_args import OpNamedArgs +from weave.legacy.weave import weave_types +from weave.legacy.weave import storage, errors, context_state, op_aliases, op_args, uris +from weave.legacy.weave.op_args import OpNamedArgs if typing.TYPE_CHECKING: - from weave.legacy.op_def import OpDef + from weave.legacy.weave.op_def import OpDef class Registry: @@ -122,7 +122,7 @@ def is_chainable(op): # type: ignore return [op for op in self._ops.values() if is_chainable(op)] # type: ignore[no-untyped-call] def load_saved_ops(self): # type: ignore - from weave.legacy import op_def_type + from weave.legacy.weave import op_def_type for op_ref in storage.objects(op_def_type.OpDefType()): try: diff --git a/weave/legacy/run.py b/weave/legacy/weave/run.py similarity index 100% rename from weave/legacy/run.py rename to weave/legacy/weave/run.py diff --git a/weave/legacy/run_streamtable_span.py b/weave/legacy/weave/run_streamtable_span.py similarity index 93% rename from weave/legacy/run_streamtable_span.py rename to weave/legacy/weave/run_streamtable_span.py index ae5f9225c22..1583f6e2af4 100644 --- a/weave/legacy/run_streamtable_span.py +++ b/weave/legacy/weave/run_streamtable_span.py @@ -1,10 +1,10 @@ import typing from typing import Iterable -from weave.legacy import stream_data_interfaces -from weave.legacy.eager import WeaveIter -from weave.legacy import artifact_wandb, uris -from weave.legacy.run import Run +from weave.legacy.weave import stream_data_interfaces +from weave.legacy.weave.eager import WeaveIter +from weave.legacy.weave import artifact_wandb, uris +from weave.legacy.weave.run import Run class RunStreamTableSpan: diff --git a/weave/legacy/runfiles_wandb.py b/weave/legacy/weave/runfiles_wandb.py similarity index 97% rename from weave/legacy/runfiles_wandb.py rename to weave/legacy/weave/runfiles_wandb.py index 9353652927a..201baaed024 100644 --- a/weave/legacy/runfiles_wandb.py +++ b/weave/legacy/weave/runfiles_wandb.py @@ -6,10 +6,10 @@ import shutil import typing -from weave.legacy import environment as weave_env -from weave.legacy import filesystem -from weave.legacy import weave_types as types -from weave.legacy import ( +from weave.legacy.weave import environment as weave_env +from weave.legacy.weave import filesystem +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import ( artifact_fs, errors, file_util, diff --git a/weave/legacy/runs.py b/weave/legacy/weave/runs.py similarity index 92% rename from weave/legacy/runs.py rename to weave/legacy/weave/runs.py index bb27e87b374..f20967a4d8e 100644 --- a/weave/legacy/runs.py +++ b/weave/legacy/weave/runs.py @@ -1,7 +1,7 @@ import dataclasses import typing -from weave.legacy import weave_types as types +from weave.legacy.weave import weave_types as types @dataclasses.dataclass diff --git a/weave/legacy/serialize.py b/weave/legacy/weave/serialize.py similarity index 97% rename from weave/legacy/serialize.py rename to weave/legacy/weave/serialize.py index 396a1b956be..f39954a1375 100644 --- a/weave/legacy/serialize.py +++ b/weave/legacy/weave/serialize.py @@ -7,9 +7,9 @@ import random import typing -from weave.legacy import weave_internal -from weave.legacy import weave_types as types -from weave.legacy import storage, errors, graph, memo, value_or_error +from weave.legacy.weave import weave_internal +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import storage, errors, graph, memo, value_or_error NodeOrOp = typing.Union[graph.Node, graph.Op] diff --git a/weave/legacy/server.py b/weave/legacy/weave/server.py similarity index 97% rename from weave/legacy/server.py rename to weave/legacy/weave/server.py index 51f5f6bd6e4..90c2092b1ae 100644 --- a/weave/legacy/server.py +++ b/weave/legacy/weave/server.py @@ -12,7 +12,7 @@ import requests from werkzeug.serving import make_server -from weave.legacy import ( +from weave.legacy.weave import ( cache, context, engine_trace, @@ -27,8 +27,8 @@ storage, weave_types, ) -from weave.legacy.language_features.tagging import tag_store -from weave.legacy.language_features.tagging.tag_store import isolated_tagging_context +from weave.legacy.weave.language_features.tagging import tag_store +from weave.legacy.weave.language_features.tagging.tag_store import isolated_tagging_context # A function to monkeypatch the request post method # def patch_request_post(): diff --git a/weave/legacy/server_error_handling.py b/weave/legacy/weave/server_error_handling.py similarity index 98% rename from weave/legacy/server_error_handling.py rename to weave/legacy/weave/server_error_handling.py index f7c262a24c0..1e3b10ba96f 100644 --- a/weave/legacy/server_error_handling.py +++ b/weave/legacy/weave/server_error_handling.py @@ -26,9 +26,9 @@ from werkzeug import Response from werkzeug import exceptions as werkzeug_exceptions from werkzeug import http as werkzeug_http -from weave.legacy import errors +from weave.legacy.weave import errors -from weave.legacy import util +from weave.legacy.weave import util class WeaveInternalHttpException(werkzeug_exceptions.HTTPException): diff --git a/weave/legacy/server_interface.py b/weave/legacy/weave/server_interface.py similarity index 100% rename from weave/legacy/server_interface.py rename to weave/legacy/weave/server_interface.py diff --git a/weave/legacy/show.py b/weave/legacy/weave/show.py similarity index 95% rename from weave/legacy/show.py rename to weave/legacy/weave/show.py index 204e84d5b7f..5e59d05272e 100644 --- a/weave/legacy/show.py +++ b/weave/legacy/weave/show.py @@ -5,10 +5,10 @@ from IPython.display import IFrame, display -from weave.legacy import storage, artifact_fs, context, errors, graph, ops, node_ref, panel, ref_base -from weave.legacy import util +from weave.legacy.weave import storage, artifact_fs, context, errors, graph, ops, node_ref, panel, ref_base +from weave.legacy.weave import util from . import usage_analytics -from weave.legacy import weave_types as types +from weave.legacy.weave import weave_types as types from . import weavejs_fixes @@ -21,7 +21,7 @@ def make_varname_for_type(t: types.Type): # type: ignore def make_container( obj: typing.Union[panel.Panel, graph.Node], name: str ) -> panel.Panel: - from weave.legacy.panels import Group + from weave.legacy.weave.panels import Group if isinstance(obj, graph.Node): return Group( diff --git a/weave/legacy/signal_handlers.py b/weave/legacy/weave/signal_handlers.py similarity index 99% rename from weave/legacy/signal_handlers.py rename to weave/legacy/weave/signal_handlers.py index d9c1e89e683..be47f10103a 100644 --- a/weave/legacy/signal_handlers.py +++ b/weave/legacy/weave/signal_handlers.py @@ -10,7 +10,7 @@ import typing from types import FrameType -from weave.legacy import environment +from weave.legacy.weave import environment def dump_folder() -> pathlib.Path: diff --git a/weave/legacy/stitch.py b/weave/legacy/weave/stitch.py similarity index 98% rename from weave/legacy/stitch.py rename to weave/legacy/weave/stitch.py index 9ba0145040b..69aba75e31f 100644 --- a/weave/legacy/stitch.py +++ b/weave/legacy/weave/stitch.py @@ -22,11 +22,11 @@ import dataclasses import typing -from weave.legacy import graph, op_def, registry_mem -from weave.legacy.language_features.tagging import opdef_util +from weave.legacy.weave import graph, op_def, registry_mem +from weave.legacy.weave.language_features.tagging import opdef_util -from weave.legacy import errors -from weave.legacy import weave_types as types +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types from . import _dict_utils diff --git a/weave/legacy/storage.py b/weave/legacy/weave/storage.py similarity index 98% rename from weave/legacy/storage.py rename to weave/legacy/weave/storage.py index cd14615af6c..b3eef9a5220 100644 --- a/weave/legacy/storage.py +++ b/weave/legacy/weave/storage.py @@ -8,7 +8,7 @@ import typing from weave.trace.client_context import weave_client as weave_client_context -from weave.legacy import ( +from weave.legacy.weave import ( artifact_base, artifact_fs, artifact_local, @@ -22,12 +22,12 @@ timestamp, ) -from weave.legacy import weave_types as types +from weave.legacy.weave import weave_types as types Ref = ref_base.Ref if typing.TYPE_CHECKING: - from weave.legacy.wandb_interface.wandb_lite_run import InMemoryLazyLiteRun + from weave.legacy.weave.wandb_interface.wandb_lite_run import InMemoryLazyLiteRun def split_path_dotfile(path, dotfile_name): # type: ignore @@ -63,7 +63,7 @@ def _get_weave_type_with_refs(obj: typing.Any): # type: ignore def _ensure_object_components_are_published( # type: ignore obj: typing.Any, wb_type: types.Type, artifact: artifact_wandb.WandbArtifact ): - from weave.legacy.mappers_publisher import map_to_python_remote + from weave.legacy.weave.mappers_publisher import map_to_python_remote mapper = map_to_python_remote(wb_type, artifact) return mapper.apply(obj) @@ -451,7 +451,7 @@ def to_json_with_refs( # type: ignore """ # This is newer than to_python, save and publish above, and doesn't use the "mapper" # pattern, which is overkill. Much better to just write a simple function like this. - from weave.legacy import op_def + from weave.legacy.weave import op_def if wb_type is None: wb_type = types.TypeRegistry.type_of(obj) @@ -508,7 +508,7 @@ def convert_timestamps_to_epoch_ms(obj: typing.Any) -> typing.Any: def to_weavejs(obj, artifact: typing.Optional[artifact_base.Artifact] = None): # type: ignore - from weave.legacy.arrow import list_ as arrow_list + from weave.legacy.weave.arrow import list_ as arrow_list obj = box.unbox(obj) if isinstance(obj, (str, int, float, bool, type(None))): diff --git a/weave/legacy/stream_data_interfaces.py b/weave/legacy/weave/stream_data_interfaces.py similarity index 100% rename from weave/legacy/stream_data_interfaces.py rename to weave/legacy/weave/stream_data_interfaces.py diff --git a/weave/legacy/timestamp.py b/weave/legacy/weave/timestamp.py similarity index 100% rename from weave/legacy/timestamp.py rename to weave/legacy/weave/timestamp.py diff --git a/weave/legacy/trace_legacy.py b/weave/legacy/weave/trace_legacy.py similarity index 96% rename from weave/legacy/trace_legacy.py rename to weave/legacy/weave/trace_legacy.py index aefd89dc605..e4f0a008198 100644 --- a/weave/legacy/trace_legacy.py +++ b/weave/legacy/weave/trace_legacy.py @@ -1,11 +1,11 @@ import os import typing -from weave.legacy import artifact_local, graph, runs +from weave.legacy.weave import artifact_local, graph, runs from . import ref_base from . import errors -from weave.legacy import weave_types as types +from weave.legacy.weave import weave_types as types def get_obj_creator(ref: ref_base.Ref) -> typing.Optional[runs.Run]: diff --git a/weave/legacy/trace_local.py b/weave/legacy/weave/trace_local.py similarity index 95% rename from weave/legacy/trace_local.py rename to weave/legacy/weave/trace_local.py index b38d0df657d..3b969dc5d89 100644 --- a/weave/legacy/trace_local.py +++ b/weave/legacy/weave/trace_local.py @@ -5,14 +5,14 @@ import typing from typing import Mapping -from weave.legacy import artifact_local, graph, op_def, op_policy, runs +from weave.legacy.weave import artifact_local, graph, op_def, op_policy, runs from . import ref_base -from weave.legacy import ( +from weave.legacy.weave import ( storage, weave_internal, ) -from weave.legacy import weave_types as types +from weave.legacy.weave import weave_types as types @dataclasses.dataclass @@ -118,13 +118,13 @@ def get_run(self, run_key: RunKey) -> graph.Node[runs.Run]: return self._single_run(run_key) def get_run_val(self, run_key: RunKey) -> typing.Optional[runs.Run]: - from weave.legacy import execute_fast + from weave.legacy.weave import execute_fast res = execute_fast._execute_fn_no_engine(None, None, self.get_run(run_key)) # type: ignore[no-untyped-call] return res def save_run(self, run: runs.Run): # type: ignore - from weave.legacy.ops_primitives import weave_api + from weave.legacy.weave.ops_primitives import weave_api run_key = RunKey(run.op_name, run.id) if self._should_save_to_table(run_key): diff --git a/weave/legacy/types_numpy.py b/weave/legacy/weave/types_numpy.py similarity index 96% rename from weave/legacy/types_numpy.py rename to weave/legacy/weave/types_numpy.py index c7d661e8780..8d72409f7a3 100644 --- a/weave/legacy/types_numpy.py +++ b/weave/legacy/weave/types_numpy.py @@ -1,6 +1,6 @@ import numpy as np -from weave.legacy import weave_types as types +from weave.legacy.weave import weave_types as types # TODO: this doesn't match how extra works for list types... diff --git a/weave/legacy/uris.py b/weave/legacy/weave/uris.py similarity index 98% rename from weave/legacy/uris.py rename to weave/legacy/weave/uris.py index 465dac98b9f..f207ff32cb7 100644 --- a/weave/legacy/uris.py +++ b/weave/legacy/weave/uris.py @@ -2,7 +2,7 @@ import typing from urllib import parse -from weave.legacy import errors +from weave.legacy.weave import errors if typing.TYPE_CHECKING: from . import ref_base diff --git a/weave/legacy/urls.py b/weave/legacy/weave/urls.py similarity index 96% rename from weave/legacy/urls.py rename to weave/legacy/weave/urls.py index cf7d53cbf38..a74d7e3721c 100644 --- a/weave/legacy/urls.py +++ b/weave/legacy/weave/urls.py @@ -2,7 +2,7 @@ from wandb import util as wb_util -from weave.legacy import context_state, environment +from weave.legacy.weave import context_state, environment BROWSE3_PATH = "browse3" WEAVE_SLUG = "weave" diff --git a/weave/legacy/usage_analytics.py b/weave/legacy/weave/usage_analytics.py similarity index 95% rename from weave/legacy/usage_analytics.py rename to weave/legacy/weave/usage_analytics.py index 5fd8bddc571..f2acef97b0f 100644 --- a/weave/legacy/usage_analytics.py +++ b/weave/legacy/weave/usage_analytics.py @@ -3,7 +3,7 @@ import analytics -from weave.legacy import context_state +from weave.legacy.weave import context_state from . import environment diff --git a/weave/legacy/util.py b/weave/legacy/weave/util.py similarity index 98% rename from weave/legacy/util.py rename to weave/legacy/weave/util.py index 8027cf35a9d..f057ac40073 100644 --- a/weave/legacy/util.py +++ b/weave/legacy/weave/util.py @@ -8,7 +8,7 @@ # import ipynbname import typing -from weave.legacy.errors import WeaveFingerprintErrorMixin +from weave.legacy.weave.errors import WeaveFingerprintErrorMixin sentry_inited = False diff --git a/weave/legacy/val_const.py b/weave/legacy/weave/val_const.py similarity index 90% rename from weave/legacy/val_const.py rename to weave/legacy/weave/val_const.py index c48e34e50cd..458034826e9 100644 --- a/weave/legacy/val_const.py +++ b/weave/legacy/weave/val_const.py @@ -7,7 +7,7 @@ import typing -from weave.legacy import weave_types as types +from weave.legacy.weave import weave_types as types class Const: diff --git a/weave/legacy/value_or_error.py b/weave/legacy/weave/value_or_error.py similarity index 100% rename from weave/legacy/value_or_error.py rename to weave/legacy/weave/value_or_error.py diff --git a/weave/legacy/wandb_api.py b/weave/legacy/weave/wandb_api.py similarity index 98% rename from weave/legacy/wandb_api.py rename to weave/legacy/weave/wandb_api.py index d93a11da936..d0edbeaa8be 100644 --- a/weave/legacy/wandb_api.py +++ b/weave/legacy/weave/wandb_api.py @@ -14,12 +14,12 @@ from gql.transport.requests import RequestsHTTPTransport from requests.auth import HTTPBasicAuth -from weave.legacy import errors -from weave.legacy import environment as weave_env -from weave.legacy import wandb_client_api, engine_trace +from weave.legacy.weave import errors +from weave.legacy.weave import environment as weave_env +from weave.legacy.weave import wandb_client_api, engine_trace # Importing at the top-level namespace so other files can import from here. -from weave.legacy.context_state import WandbApiContext, _wandb_api_context +from weave.legacy.weave.context_state import WandbApiContext, _wandb_api_context tracer = engine_trace.tracer() # type: ignore diff --git a/weave/legacy/wandb_client_api.py b/weave/legacy/weave/wandb_client_api.py similarity index 98% rename from weave/legacy/wandb_client_api.py rename to weave/legacy/weave/wandb_client_api.py index 11bbff4e333..350dd9b8eba 100644 --- a/weave/legacy/wandb_client_api.py +++ b/weave/legacy/weave/wandb_client_api.py @@ -12,7 +12,7 @@ from wandb.errors import CommError as WandbCommError from wandb.sdk.internal.internal_api import _thread_local_api_settings -from weave.legacy import errors +from weave.legacy.weave import errors def wandb_public_api() -> public.Api: diff --git a/weave/legacy/wandb_file_manager.py b/weave/legacy/weave/wandb_file_manager.py similarity index 99% rename from weave/legacy/wandb_file_manager.py rename to weave/legacy/weave/wandb_file_manager.py index ecce61b90d0..af631151048 100644 --- a/weave/legacy/wandb_file_manager.py +++ b/weave/legacy/weave/wandb_file_manager.py @@ -12,8 +12,8 @@ from requests.auth import HTTPBasicAuth from wandb.sdk.lib import hashutil -from weave.legacy import environment as weave_env -from weave.legacy import filesystem, artifact_wandb, cache, errors, wandb_api, engine_trace, weave_http +from weave.legacy.weave import environment as weave_env +from weave.legacy.weave import filesystem, artifact_wandb, cache, errors, wandb_api, engine_trace, weave_http tracer = engine_trace.tracer() # type: ignore diff --git a/weave/legacy/wandb_interface/project_creator.py b/weave/legacy/weave/wandb_interface/project_creator.py similarity index 100% rename from weave/legacy/wandb_interface/project_creator.py rename to weave/legacy/weave/wandb_interface/project_creator.py diff --git a/weave/legacy/wandb_interface/wandb_artifact_pusher.py b/weave/legacy/weave/wandb_interface/wandb_artifact_pusher.py similarity index 95% rename from weave/legacy/wandb_interface/wandb_artifact_pusher.py rename to weave/legacy/weave/wandb_interface/wandb_artifact_pusher.py index fa80c077c16..0bbda99b705 100644 --- a/weave/legacy/wandb_interface/wandb_artifact_pusher.py +++ b/weave/legacy/weave/wandb_interface/wandb_artifact_pusher.py @@ -5,9 +5,9 @@ from wandb import Artifact from wandb.apis.public import api as wb_public -from weave.legacy import engine_trace -from weave.legacy import wandb_client_api -from weave.legacy.wandb_interface.wandb_lite_run import InMemoryLazyLiteRun +from weave.legacy.weave import engine_trace +from weave.legacy.weave import wandb_client_api +from weave.legacy.weave.wandb_interface.wandb_lite_run import InMemoryLazyLiteRun def artifact_commithash_by_digest( diff --git a/weave/legacy/wandb_interface/wandb_lite_run.py b/weave/legacy/weave/wandb_interface/wandb_lite_run.py similarity index 98% rename from weave/legacy/wandb_interface/wandb_lite_run.py rename to weave/legacy/weave/wandb_interface/wandb_lite_run.py index 4cd60b7452b..9703a9d88e4 100644 --- a/weave/legacy/wandb_interface/wandb_lite_run.py +++ b/weave/legacy/weave/wandb_interface/wandb_lite_run.py @@ -15,8 +15,8 @@ from wandb.sdk.internal.sender import _manifest_json_from_proto from wandb.sdk.lib import runid -from weave.legacy import errors -from weave.legacy import engine_trace, wandb_client_api +from weave.legacy.weave import errors +from weave.legacy.weave import engine_trace, wandb_client_api logger = logging.getLogger(__name__) diff --git a/weave/legacy/wandb_interface/wandb_stream_table.py b/weave/legacy/weave/wandb_interface/wandb_stream_table.py similarity index 97% rename from weave/legacy/wandb_interface/wandb_stream_table.py rename to weave/legacy/weave/wandb_interface/wandb_stream_table.py index 63a05b9fb8b..2669282ee2d 100644 --- a/weave/legacy/wandb_interface/wandb_stream_table.py +++ b/weave/legacy/weave/wandb_interface/wandb_stream_table.py @@ -15,8 +15,8 @@ from wandb.sdk.lib.paths import LogicalPath from wandb.sdk.lib.printer import get_printer -from weave.legacy import weave_types -from weave.legacy import ( +from weave.legacy.weave import weave_types +from weave.legacy.weave import ( storage, errors, artifact_base, @@ -27,8 +27,8 @@ runfiles_wandb, wandb_api, ) -from weave.legacy.core_types.stream_table_type import StreamTableType -from weave.legacy.wandb_interface.wandb_lite_run import InMemoryLazyLiteRun +from weave.legacy.weave.core_types.stream_table_type import StreamTableType +from weave.legacy.weave.wandb_interface.wandb_lite_run import InMemoryLazyLiteRun if typing.TYPE_CHECKING: from wandb.sdk.internal.file_pusher import FilePusher @@ -201,8 +201,8 @@ def log(self, row_or_rows: ROW_TYPE) -> None: self._log_row(row) def rows(self) -> graph.Node: - from weave.legacy.ops_domain import stream_table_ops - from weave.legacy.ops_primitives import weave_api + from weave.legacy.weave.ops_domain import stream_table_ops + from weave.legacy.weave.ops_primitives import weave_api if self._weave_stream_table_ref is None: raise errors.WeaveInternalError("ref is None after ensure") @@ -211,7 +211,7 @@ def rows(self) -> graph.Node: ) def _ipython_display_(self) -> graph.Node: - from weave.legacy import show + from weave.legacy.weave import show return show.show(self.rows()) diff --git a/weave/legacy/wandb_util.py b/weave/legacy/weave/wandb_util.py similarity index 98% rename from weave/legacy/wandb_util.py rename to weave/legacy/weave/wandb_util.py index be4161ff038..11c6c717eb9 100644 --- a/weave/legacy/wandb_util.py +++ b/weave/legacy/weave/wandb_util.py @@ -1,8 +1,8 @@ import typing -from weave.legacy import errors -from weave.legacy import weave_types as types -from weave.legacy import ops, ops_domain +from weave.legacy.weave import errors +from weave.legacy.weave import weave_types as types +from weave.legacy.weave import ops, ops_domain class Weave0TypeJson(typing.TypedDict): diff --git a/weave/legacy/weave_http.py b/weave/legacy/weave/weave_http.py similarity index 98% rename from weave/legacy/weave_http.py rename to weave/legacy/weave/weave_http.py index 773625fe9ec..f425dd2567b 100644 --- a/weave/legacy/weave_http.py +++ b/weave/legacy/weave/weave_http.py @@ -13,7 +13,7 @@ import requests.auth import yarl -from weave.legacy import engine_trace, filesystem, server_error_handling +from weave.legacy.weave import engine_trace, filesystem, server_error_handling logging.getLogger("aiohttp.access").setLevel(logging.WARNING) logging.getLogger("aiohttp.client").setLevel(logging.WARNING) diff --git a/weave/legacy/weave_inspector.py b/weave/legacy/weave/weave_inspector.py similarity index 99% rename from weave/legacy/weave_inspector.py rename to weave/legacy/weave/weave_inspector.py index d878e4f8d4d..fdcde5393c6 100644 --- a/weave/legacy/weave_inspector.py +++ b/weave/legacy/weave/weave_inspector.py @@ -105,9 +105,9 @@ import tabulate -from weave.legacy import graph +from weave.legacy.weave import graph -from weave.legacy import weave_types as types +from weave.legacy.weave import weave_types as types from .partial_object import PartialObjectType @@ -137,7 +137,7 @@ def _node_type_name(node: graph.Node) -> str: def _type_name(node_type: types.Type) -> str: - from weave.legacy.language_features.tagging import tagged_value_type + from weave.legacy.weave.language_features.tagging import tagged_value_type if isinstance(node_type, tagged_value_type.TaggedValueType): return f"TV({_type_name(node_type.value)})" diff --git a/weave/legacy/weave_internal.py b/weave/legacy/weave/weave_internal.py similarity index 93% rename from weave/legacy/weave_internal.py rename to weave/legacy/weave/weave_internal.py index e26bcd526c2..4d485658814 100644 --- a/weave/legacy/weave_internal.py +++ b/weave/legacy/weave/weave_internal.py @@ -1,7 +1,7 @@ import typing -from weave.legacy import client_interface, context_state, errors, graph -from weave.legacy import weave_types as types +from weave.legacy.weave import client_interface, context_state, errors, graph +from weave.legacy.weave import weave_types as types def dereference_variables( @@ -83,14 +83,14 @@ def use( def make_var_node(type_: types.Type, name: str) -> graph.VarNode: # Circular import. TODO: fix - from weave.legacy import dispatch + from weave.legacy.weave import dispatch return dispatch.RuntimeVarNode(type_, name) def make_const_node(type_: types.Type, val: typing.Any) -> graph.ConstNode: # Circular import. TODO: fix - from weave.legacy import dispatch + from weave.legacy.weave import dispatch return dispatch.RuntimeConstNode(type_, val) @@ -114,7 +114,7 @@ def make_output_node( type_: types.Type, op_name: str, op_params: dict[str, graph.Node] ) -> graph.OutputNode: # Circular import. TODO: fix - from weave.legacy import dispatch + from weave.legacy.weave import dispatch return dispatch.RuntimeOutputNode(type_, op_name, op_params) @@ -125,7 +125,7 @@ def define_fn( ) -> graph.ConstNode: var_nodes = [make_var_node(t, k) for k, t in parameters.items()] try: - from weave.legacy import op_def + from weave.legacy.weave import op_def with op_def.no_refine(): fnNode = body(*var_nodes) @@ -148,7 +148,7 @@ def define_fn( # and the function doesn't explicitly operate on tagged values. this ensures that the input tags # are propagated appropriately to the output type of the function. def refine_graph(node: graph.Node) -> graph.Node: - from weave.legacy.registry_mem import memory_registry + from weave.legacy.weave.registry_mem import memory_registry if isinstance(node, (graph.ConstNode, graph.VoidNode, graph.VarNode)): return node @@ -176,6 +176,6 @@ def manual_call( You can produce incorrect nodes this way. Use with caution. """ - from weave.legacy import dispatch + from weave.legacy.weave import dispatch return dispatch.RuntimeOutputNode(output_type, op_name, inputs) diff --git a/weave/legacy/weave_pydantic.py b/weave/legacy/weave/weave_pydantic.py similarity index 95% rename from weave/legacy/weave_pydantic.py rename to weave/legacy/weave/weave_pydantic.py index 870b2a83d61..0c9b0f7c7ad 100644 --- a/weave/legacy/weave_pydantic.py +++ b/weave/legacy/weave/weave_pydantic.py @@ -1,6 +1,6 @@ from pydantic import BaseModel, create_model -from weave.legacy import weave_types as types +from weave.legacy.weave import weave_types as types from . import infer_types diff --git a/weave/legacy/weave_types.py b/weave/legacy/weave/weave_types.py similarity index 99% rename from weave/legacy/weave_types.py rename to weave/legacy/weave/weave_types.py index 2b1c45c3891..ad46a314df6 100644 --- a/weave/legacy/weave_types.py +++ b/weave/legacy/weave/weave_types.py @@ -11,20 +11,20 @@ import pydantic from dateutil.parser import isoparse -from weave.legacy import ( +from weave.legacy.weave import ( box, context_state, errors, mappers_python, object_type_ref_util, ) -from weave.legacy import timestamp as weave_timestamp +from weave.legacy.weave import timestamp as weave_timestamp if typing.TYPE_CHECKING: - from weave.legacy import artifact_base - from weave.legacy.artifact_fs import FilesystemArtifact + from weave.legacy.weave import artifact_base + from weave.legacy.weave.artifact_fs import FilesystemArtifact - from weave.legacy import weave_inspector + from weave.legacy.weave import weave_inspector def to_weavejs_typekey(k: str) -> str: @@ -126,7 +126,7 @@ def type_class_of(obj): # type: ignore @staticmethod def type_of(obj: typing.Any) -> "Type": # type: ignore - from weave.legacy import ref_base + from weave.legacy.weave import ref_base if ( context_state.ref_tracking_enabled() @@ -460,7 +460,7 @@ def _make(cls, kwargs={}): # type: ignore def _inspect(self) -> "weave_inspector.TypeInspector": # type: ignore """Only intended to be used by developers to help debug the graph.""" # Circular import, so we do it here. - from weave.legacy import weave_inspector + from weave.legacy.weave import weave_inspector return weave_inspector.TypeInspector(self) @@ -1061,7 +1061,7 @@ def property_types(self) -> dict[str, Type]: # type: ignore @classmethod def typeclass_of_class(cls, check_class): # type: ignore - from weave.legacy import weave_pydantic + from weave.legacy.weave import weave_pydantic if not issubclass(check_class, pydantic.BaseModel): return cls @@ -1278,7 +1278,7 @@ def _hashable(self): # type: ignore @classmethod def type_of_instance(cls, obj): # type: ignore - from weave.legacy import infer_types + from weave.legacy.weave import infer_types attr_types = {} for field in dataclasses.fields(obj): @@ -1361,7 +1361,7 @@ def save_instance(self, obj, artifact, name): # type: ignore def load_instance(self, artifact, name, extra=None): # type: ignore with artifact.open(f"{name}.object.json") as f: # TODO: no circular imports! - from weave.legacy import graph + from weave.legacy.weave import graph return graph.Node.node_from_json(json.load(f)) @@ -1385,7 +1385,7 @@ def _is_assignable_to(self, other_type) -> typing.Optional[bool]: # type: ignor return None def save_instance(self, obj, artifact, name): # type: ignore - from weave.legacy import ref_base + from weave.legacy.weave import ref_base obj_ref = ref_base.get_ref(obj) if obj_ref is None: @@ -1419,7 +1419,7 @@ class LocalArtifactRefType(FilesystemArtifactRefType): @dataclasses.dataclass(frozen=True) class WandbArtifactRefType(FilesystemArtifactRefType): def load_instance(self, artifact, name, extra=None): # type: ignore - from weave.legacy import artifact_wandb + from weave.legacy.weave import artifact_wandb return artifact_wandb.WandbArtifactRef(artifact, name) @@ -1571,7 +1571,7 @@ def merge_types(a: Type, b: Type) -> Type: This implementation must match list.concat implementations (which is the only way to extend a list in Weave). Ie list.concat(list[a], [b]) -> list[merge_types(a, b)] """ - from weave.legacy.language_features.tagging import tagged_value_type + from weave.legacy.weave.language_features.tagging import tagged_value_type if a == b: return a diff --git a/weave/legacy/weavejs_fixes.py b/weave/legacy/weave/weavejs_fixes.py similarity index 99% rename from weave/legacy/weavejs_fixes.py rename to weave/legacy/weave/weavejs_fixes.py index 23c97ee64c7..6957e839a8d 100644 --- a/weave/legacy/weavejs_fixes.py +++ b/weave/legacy/weave/weavejs_fixes.py @@ -8,9 +8,9 @@ import math import typing -from weave.legacy import graph +from weave.legacy.weave import graph -from weave.legacy import weave_types +from weave.legacy.weave import weave_types def _convert_specific_opname_to_generic_opname( diff --git a/weave/legacy/weavify.py b/weave/legacy/weave/weavify.py similarity index 93% rename from weave/legacy/weavify.py rename to weave/legacy/weave/weavify.py index a85567a1e53..af81e62d492 100644 --- a/weave/legacy/weavify.py +++ b/weave/legacy/weave/weavify.py @@ -1,12 +1,12 @@ import typing -from weave.legacy import errors, graph, op_args, val_const +from weave.legacy.weave import errors, graph, op_args, val_const -from weave.legacy import weave_internal -from weave.legacy import weave_types as types +from weave.legacy.weave import weave_internal +from weave.legacy.weave import weave_types as types if typing.TYPE_CHECKING: - from weave.legacy import op_def + from weave.legacy.weave import op_def def verify_weave_fn_is_valid(op: "op_def.OpDef", weavified: graph.Node) -> None: @@ -79,7 +79,7 @@ def weave_fn_body(*args: graph.VarNode) -> graph.Node: def weavify_object(obj: typing.Any) -> graph.Node: - from weave.legacy.ops_primitives import dict_, make_list + from weave.legacy.weave.ops_primitives import dict_, make_list if isinstance(obj, graph.Node): return obj diff --git a/weave/test_scripts/wandb_artifact_perf.py b/weave/test_scripts/wandb_artifact_perf.py index bc38aeb1d64..af3f3e0aa7d 100644 --- a/weave/test_scripts/wandb_artifact_perf.py +++ b/weave/test_scripts/wandb_artifact_perf.py @@ -13,7 +13,7 @@ import cProfile import time -from weave.legacy import ( +from weave.legacy.weave import ( artifact_wandb, async_map, engine_trace, diff --git a/weave/tests/fixture_fakewandb.py b/weave/tests/fixture_fakewandb.py index c5ea0e69773..4406f36613a 100644 --- a/weave/tests/fixture_fakewandb.py +++ b/weave/tests/fixture_fakewandb.py @@ -11,18 +11,18 @@ import wandb import weave +from weave.legacy.tests.util.tag_test_util import op_add_tag # Note: We're mocking out the whole io_service right now. This is too # high level and doesn't test the actual io implementation. We should # mock wandb_api instead probably. -from weave.legacy import io_service, util, wandb_api, wandb_client_api -from weave.legacy.artifact_wandb import ( +from weave.legacy.weave import io_service, util, wandb_api, wandb_client_api +from weave.legacy.weave.artifact_wandb import ( WandbArtifact, WandbArtifactManifest, WeaveWBArtifactByIDURI, WeaveWBArtifactURI, ) -from weave.legacy.tests.util.tag_test_util import op_add_tag TEST_TABLE_ARTIFACT_PATH = "testdata/wb_artifacits/test_res_1fwmcd3q:v0" ABS_TEST_TABLE_ARTIFACT_PATH = os.path.abspath(TEST_TABLE_ARTIFACT_PATH) diff --git a/weave/tests/trace/op_versioning_solo.py b/weave/tests/trace/op_versioning_solo.py index b2ceec4b2d2..bacc0e27155 100644 --- a/weave/tests/trace/op_versioning_solo.py +++ b/weave/tests/trace/op_versioning_solo.py @@ -1,7 +1,7 @@ import numpy as np import weave -from weave.legacy import artifact_fs +from weave.legacy.weave import artifact_fs @weave.op() diff --git a/weave/tests/trace/test_op_versioning.py b/weave/tests/trace/test_op_versioning.py index f1f2203a323..3fc023e235c 100644 --- a/weave/tests/trace/test_op_versioning.py +++ b/weave/tests/trace/test_op_versioning.py @@ -5,7 +5,7 @@ import pytest import weave -from weave.legacy import artifact_fs, derive_op, op_def +from weave.legacy.weave import artifact_fs, derive_op, op_def from weave.trace_server.trace_server_interface import FileContentReadReq, ObjReadReq diff --git a/weave/tests/trace/test_server.py b/weave/tests/trace/test_server.py index 936eb7aa360..c5aa37a3c74 100644 --- a/weave/tests/trace/test_server.py +++ b/weave/tests/trace/test_server.py @@ -6,13 +6,13 @@ import pytest import requests -from weave.legacy import api as weave -from weave.legacy import client as _client -from weave.legacy import context_state, ops -from weave.legacy import server as _server -from weave.legacy import weave_types as types -from weave.legacy.decorator_op import op -from weave.legacy.weave_internal import make_const_node +from weave.legacy.weave import api as weave +from weave.legacy.weave import client as _client +from weave.legacy.weave import context_state, ops +from weave.legacy.weave import server as _server +from weave.legacy.weave import weave_types as types +from weave.legacy.weave.decorator_op import op +from weave.legacy.weave.weave_internal import make_const_node SERVER_TYPES = ["inprocess", "subprocess", "http"] diff --git a/weave/tests/trace/test_weave_client.py b/weave/tests/trace/test_weave_client.py index b0bd9210ec5..17184676066 100644 --- a/weave/tests/trace/test_weave_client.py +++ b/weave/tests/trace/test_weave_client.py @@ -12,7 +12,7 @@ import weave import weave.trace_server.trace_server_interface as tsi from weave import Evaluation -from weave.legacy import op_def +from weave.legacy.weave import op_def from weave.trace import refs, weave_client from weave.trace.isinstance import weave_isinstance from weave.trace.op import Op diff --git a/weave/tests/trace/test_weaveflow.py b/weave/tests/trace/test_weaveflow.py index a41f4eba9d4..e35b7721551 100644 --- a/weave/tests/trace/test_weaveflow.py +++ b/weave/tests/trace/test_weaveflow.py @@ -5,7 +5,7 @@ from pydantic import Field import weave -from weave.legacy import ref_base +from weave.legacy.weave import ref_base pytestmark = pytest.mark.trace diff --git a/weave/tests/wandb_system_tests_conftest.py b/weave/tests/wandb_system_tests_conftest.py index d2c18bbf3e4..a67debe9871 100644 --- a/weave/tests/wandb_system_tests_conftest.py +++ b/weave/tests/wandb_system_tests_conftest.py @@ -15,7 +15,7 @@ import requests import wandb -from weave.legacy.wandb_api import ( +from weave.legacy.weave.wandb_api import ( WandbApiContext, from_environment, wandb_api_context, diff --git a/weave/trace/api.py b/weave/trace/api.py index 916d27c2841..1c7dbbb4bb0 100644 --- a/weave/trace/api.py +++ b/weave/trace/api.py @@ -6,7 +6,7 @@ import time from typing import Any, Callable, Iterator, Optional, Union -from weave.legacy import urls, util +from weave.legacy.weave import urls, util from weave.trace.call_context import get_current_call from weave.trace.client_context import weave_client as weave_client_context @@ -202,7 +202,7 @@ def serve( ) -> str: import uvicorn - from weave.legacy import wandb_api + from weave.legacy.weave import wandb_api from .serve_fastapi import object_method_app diff --git a/weave/trace/box.py b/weave/trace/box.py index 1c39bf5e39f..a185c50a822 100644 --- a/weave/trace/box.py +++ b/weave/trace/box.py @@ -10,7 +10,7 @@ import numpy as np -from weave.legacy.ref_base import Ref +from weave.legacy.weave.ref_base import Ref T = TypeVar("T") diff --git a/weave/trace/cli.py b/weave/trace/cli.py index 2204e2c4c76..edccda7a382 100644 --- a/weave/trace/cli.py +++ b/weave/trace/cli.py @@ -25,7 +25,7 @@ def cli() -> None: # def start_ui() -> None: # print("Starting server...") # try: -# from weave.legacy import server +# from weave.legacy.weave import server # except ModuleNotFoundError: # print("Run 'pip install weave[engine]' to use the local server.") # sys.exit(1) diff --git a/weave/trace/client_context/weave_client.py b/weave/trace/client_context/weave_client.py index b80375adb56..f74759f26ac 100644 --- a/weave/trace/client_context/weave_client.py +++ b/weave/trace/client_context/weave_client.py @@ -1,8 +1,8 @@ import threading from typing import TYPE_CHECKING, Optional -from weave.legacy import context_state -from weave.legacy.errors import WeaveInitError +from weave.legacy.weave import context_state +from weave.legacy.weave.errors import WeaveInitError if TYPE_CHECKING: from weave.trace.weave_client import WeaveClient diff --git a/weave/trace/custom_objs.py b/weave/trace/custom_objs.py index 99b7d41eb60..32272829af1 100644 --- a/weave/trace/custom_objs.py +++ b/weave/trace/custom_objs.py @@ -4,7 +4,7 @@ import tempfile from typing import Any, Dict, Generator, Iterator, Mapping, Optional, Union -from weave.legacy import artifact_fs +from weave.legacy.weave import artifact_fs from weave.trace import op_type # noqa: F401, Must import this to register op save/load from weave.trace.client_context.weave_client import require_weave_client from weave.trace.op import Op, op @@ -136,7 +136,7 @@ def decode_custom_obj( encoded_path_contents: Mapping[str, Union[str, bytes]], load_instance_op_uri: Optional[str], ) -> Any: - from weave.legacy import artifact_fs + from weave.legacy.weave import artifact_fs load_instance_op = None if load_instance_op_uri is not None: diff --git a/weave/trace/feedback.py b/weave/trace/feedback.py index a9a386aa002..99893df018d 100644 --- a/weave/trace/feedback.py +++ b/weave/trace/feedback.py @@ -5,7 +5,7 @@ from rich.table import Table -from weave.legacy import util +from weave.legacy.weave import util from weave.trace import rich_pydantic_util from weave.trace.client_context import weave_client as weave_client_context from weave.trace.refs import parse_uri diff --git a/weave/trace/init_message.py b/weave/trace/init_message.py index d76b8e963be..92f972e71c7 100644 --- a/weave/trace/init_message.py +++ b/weave/trace/init_message.py @@ -1,6 +1,6 @@ import typing -from weave.legacy import urls +from weave.legacy.weave import urls if typing.TYPE_CHECKING: import packaging.version # type: ignore[import-not-found] diff --git a/weave/trace/op.py b/weave/trace/op.py index 3dca692b28d..b10885d43b8 100644 --- a/weave/trace/op.py +++ b/weave/trace/op.py @@ -17,7 +17,7 @@ runtime_checkable, ) -from weave.legacy import context_state +from weave.legacy.weave import context_state from weave.trace import box, call_context, settings from weave.trace.client_context import weave_client as weave_client_context from weave.trace.context import call_attributes @@ -317,7 +317,7 @@ async def extract(): ``` """ if context_state.get_loading_built_ins(): - from weave.legacy.decorator_op import op as legacy_op + from weave.legacy.weave.decorator_op import op as legacy_op return legacy_op(*args, **kwargs) # type: ignore diff --git a/weave/trace/op_type.py b/weave/trace/op_type.py index 90608f9c99b..fd948b8a2e0 100644 --- a/weave/trace/op_type.py +++ b/weave/trace/op_type.py @@ -13,7 +13,7 @@ from _ast import AsyncFunctionDef, ExceptHandler from typing import Any, Callable, Optional, Union, get_args, get_origin -from weave.legacy import artifact_fs, context_state, errors, storage +from weave.legacy.weave import artifact_fs, context_state, errors, storage from weave.trace.ipython import ( ClassNotFoundError, get_class_source, @@ -21,7 +21,7 @@ ) from weave.trace.refs import ObjectRef -from ..legacy import environment +from ..legacy.weave import environment from . import serializer from .op import Op diff --git a/weave/trace/ref_util.py b/weave/trace/ref_util.py index ebaec7dfe1e..47aed3131dd 100644 --- a/weave/trace/ref_util.py +++ b/weave/trace/ref_util.py @@ -2,7 +2,7 @@ import typing from urllib import parse -from weave.legacy import box +from weave.legacy.weave import box from weave.trace_server import refs_internal DICT_KEY_EDGE_NAME = refs_internal.DICT_KEY_EDGE_NAME @@ -22,7 +22,7 @@ def parse_local_ref_str(s: str) -> typing.Tuple[str, typing.Optional[list[str]]] def val_with_relative_ref( parent_object: typing.Any, child_object: typing.Any, ref_extra_parts: list[str] ) -> typing.Any: - from weave.legacy import context_state, ref_base + from weave.legacy.weave import context_state, ref_base # If we already have a ref, resolve it if isinstance(child_object, ref_base.Ref): @@ -31,7 +31,7 @@ def val_with_relative_ref( # Only do this if ref_tracking_enabled right now. I just want to # avoid introducing new behavior into W&B prod for the moment. if context_state.ref_tracking_enabled(): - from weave.legacy import storage + from weave.legacy.weave import storage child_ref = storage.get_ref(child_object) parent_ref = ref_base.get_ref(parent_object) diff --git a/weave/trace/rich_pydantic_util.py b/weave/trace/rich_pydantic_util.py index 2c5e21fa2ed..ec88c0545db 100644 --- a/weave/trace/rich_pydantic_util.py +++ b/weave/trace/rich_pydantic_util.py @@ -6,7 +6,7 @@ from rich.console import Console from rich.table import Table -from weave.legacy import util +from weave.legacy.weave import util def dict_to_table(d: dict[str, Any]) -> Table: diff --git a/weave/trace/serve_fastapi.py b/weave/trace/serve_fastapi.py index 89ef88b1d8c..98adc7537b1 100644 --- a/weave/trace/serve_fastapi.py +++ b/weave/trace/serve_fastapi.py @@ -12,12 +12,12 @@ except ImportError: from typing_extensions import Annotated # type: ignore -from weave.legacy import cache, op_args, pyfunc_type_util -from weave.legacy.wandb_api import WandbApiAsync +from weave.legacy.weave import cache, op_args, pyfunc_type_util +from weave.legacy.weave.wandb_api import WandbApiAsync from weave.trace.op import Op from weave.trace.refs import ObjectRef -from ..legacy import errors, weave_pydantic +from ..legacy.weave import errors, weave_pydantic key_cache: cache.LruTimeWindowCache[str, typing.Optional[bool]] = ( cache.LruTimeWindowCache(datetime.timedelta(minutes=5)) diff --git a/weave/trace/weave_client.py b/weave/trace/weave_client.py index 11029cc64fd..a16884b955d 100644 --- a/weave/trace/weave_client.py +++ b/weave/trace/weave_client.py @@ -10,7 +10,7 @@ from requests import HTTPError from weave import version -from weave.legacy import urls +from weave.legacy.weave import urls from weave.trace import call_context, trace_sentry from weave.trace.client_context import weave_client as weave_client_context from weave.trace.exception import exception_to_json_str @@ -52,7 +52,7 @@ ) if typing.TYPE_CHECKING: - from ..legacy import ref_base + from ..legacy.weave import ref_base # Controls if objects can have refs to projects not the WeaveClient project. diff --git a/weave/trace/weave_init.py b/weave/trace/weave_init.py index 07de4b40045..55188cad443 100644 --- a/weave/trace/weave_init.py +++ b/weave/trace/weave_init.py @@ -1,6 +1,6 @@ import typing -from weave.legacy import errors +from weave.legacy.weave import errors from weave.trace import autopatch, init_message, trace_sentry, weave_client from weave.trace.client_context import weave_client as weave_client_context from weave.trace_server import remote_http_trace_server, sqlite_trace_server @@ -18,7 +18,7 @@ def reset(self) -> None: def get_username() -> typing.Optional[str]: - from weave.legacy import wandb_api + from weave.legacy.weave import wandb_api api = wandb_api.get_wandb_api_sync() try: @@ -28,7 +28,7 @@ def get_username() -> typing.Optional[str]: def get_entity_project_from_project_name(project_name: str) -> tuple[str, str]: - from weave.legacy import wandb_api + from weave.legacy.weave import wandb_api fields = project_name.split("/") if len(fields) == 1: @@ -76,7 +76,7 @@ def init_weave( else: _current_inited_client.reset() - from weave.legacy import wandb_api + from weave.legacy.weave import wandb_api # Must init to read ensure we've read auth from the environment, in # case we're on a new thread. diff --git a/weave/trace_server/remote_http_trace_server.py b/weave/trace_server/remote_http_trace_server.py index 842e5c43893..568552c23f9 100644 --- a/weave/trace_server/remote_http_trace_server.py +++ b/weave/trace_server/remote_http_trace_server.py @@ -6,8 +6,8 @@ import tenacity from pydantic import BaseModel, ValidationError -from weave.legacy.environment import weave_trace_server_url -from weave.legacy.wandb_interface import project_creator +from weave.legacy.weave.environment import weave_trace_server_url +from weave.legacy.weave.wandb_interface import project_creator from . import requests from . import trace_server_interface as tsi diff --git a/weave/weave_server.py b/weave/weave_server.py index b07886df75d..05870a1ea1d 100644 --- a/weave/weave_server.py +++ b/weave/weave_server.py @@ -25,7 +25,7 @@ from flask_cors import CORS from werkzeug.exceptions import HTTPException -from weave.legacy import ( +from weave.legacy.weave import ( context_state, engine_trace, environment, @@ -41,8 +41,10 @@ wandb_api, weavejs_fixes, ) -from weave.legacy.language_features.tagging import tag_store -from weave.legacy.server_error_handling import client_safe_http_exceptions_as_werkzeug +from weave.legacy.weave.language_features.tagging import tag_store +from weave.legacy.weave.server_error_handling import ( + client_safe_http_exceptions_as_werkzeug, +) logger = logging.getLogger(__name__) @@ -91,7 +93,7 @@ def execute(self, document, *args, **kwargs): # Ensure these are imported and registered -from weave.legacy import ops +from weave.legacy.weave import ops # NOTE: Fixes flask dev server's auto-reload capability, by forcing it to use # stat mode instead of watchdog mode. It turns out that "import wandb" breaks @@ -110,11 +112,11 @@ def execute(self, document, *args, **kwargs): def import_ecosystem(): - from weave.legacy import ops, panels, panels_py + from weave.legacy.weave import ops, panels, panels_py # Attempt to import MVP ecosystem modules try: - from weave.legacy.ecosystem import langchain, replicate + from weave.legacy.weave.ecosystem import langchain, replicate except ImportError: pass @@ -127,7 +129,7 @@ def import_ecosystem(): # except (ImportError, OSError, wandb.Error): # print("Error: Couldn't import faiss module for Weaveflow.") try: - from weave.legacy.ecosystem import all + from weave.legacy.weave.ecosystem import all except (ImportError, OSError, wandb.Error): pass From 4dab2669177b98489039e68bef69dd73d1c0b48e Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Sat, 24 Aug 2024 20:35:03 -0400 Subject: [PATCH 61/84] move to legacy: pytest_parallel --- weave/{ => legacy}/scripts/pytest_parallel.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename weave/{ => legacy}/scripts/pytest_parallel.sh (100%) diff --git a/weave/scripts/pytest_parallel.sh b/weave/legacy/scripts/pytest_parallel.sh similarity index 100% rename from weave/scripts/pytest_parallel.sh rename to weave/legacy/scripts/pytest_parallel.sh From 7ee1febb26638a4840b369b46cb0bb4d7d025542 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Sat, 24 Aug 2024 20:36:00 -0400 Subject: [PATCH 62/84] move to legacy: wandb_artifact_perf --- weave/{test_scripts => legacy/scripts}/wandb_artifact_perf.py | 0 weave/test_scripts/__init__.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename weave/{test_scripts => legacy/scripts}/wandb_artifact_perf.py (100%) delete mode 100644 weave/test_scripts/__init__.py diff --git a/weave/test_scripts/wandb_artifact_perf.py b/weave/legacy/scripts/wandb_artifact_perf.py similarity index 100% rename from weave/test_scripts/wandb_artifact_perf.py rename to weave/legacy/scripts/wandb_artifact_perf.py diff --git a/weave/test_scripts/__init__.py b/weave/test_scripts/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 From c2979d4052cac7cf3091326c2462f3b802099956 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Sat, 24 Aug 2024 21:03:35 -0400 Subject: [PATCH 63/84] move to legacy: utils --- pyrightconfig.json => weave/legacy/pyrightconfig.json | 0 supervisord.conf => weave/legacy/supervisord.conf | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename pyrightconfig.json => weave/legacy/pyrightconfig.json (100%) rename supervisord.conf => weave/legacy/supervisord.conf (100%) diff --git a/pyrightconfig.json b/weave/legacy/pyrightconfig.json similarity index 100% rename from pyrightconfig.json rename to weave/legacy/pyrightconfig.json diff --git a/supervisord.conf b/weave/legacy/supervisord.conf similarity index 100% rename from supervisord.conf rename to weave/legacy/supervisord.conf From bb7f21cbf0d694693f269777631e34f461b06464 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Sat, 24 Aug 2024 21:12:51 -0400 Subject: [PATCH 64/84] move to legacy: tutorial_scripts --- {tutorial_scripts => examples/tutorial_scripts}/01_quickstart.py | 0 .../tutorial_scripts}/02_in_app_quickstart.py | 0 {tutorial_scripts => examples/tutorial_scripts}/03_models.py | 0 {tutorial_scripts => examples/tutorial_scripts}/04_datasets.py | 0 .../tutorial_scripts}/05_eval_pipeline.py | 0 .../tutorial_scripts}/06_eval_pipeline_all.py | 0 {tutorial_scripts => examples/tutorial_scripts}/07_objects.py | 0 {tutorial_scripts => examples/tutorial_scripts}/08_ops.py | 0 {tutorial_scripts => examples/tutorial_scripts}/09_tracing.py | 0 {tutorial_scripts => examples/tutorial_scripts}/10_model_serve.sh | 0 {tutorial_scripts => examples/tutorial_scripts}/11_deploy.sh | 0 11 files changed, 0 insertions(+), 0 deletions(-) rename {tutorial_scripts => examples/tutorial_scripts}/01_quickstart.py (100%) rename {tutorial_scripts => examples/tutorial_scripts}/02_in_app_quickstart.py (100%) rename {tutorial_scripts => examples/tutorial_scripts}/03_models.py (100%) rename {tutorial_scripts => examples/tutorial_scripts}/04_datasets.py (100%) rename {tutorial_scripts => examples/tutorial_scripts}/05_eval_pipeline.py (100%) rename {tutorial_scripts => examples/tutorial_scripts}/06_eval_pipeline_all.py (100%) rename {tutorial_scripts => examples/tutorial_scripts}/07_objects.py (100%) rename {tutorial_scripts => examples/tutorial_scripts}/08_ops.py (100%) rename {tutorial_scripts => examples/tutorial_scripts}/09_tracing.py (100%) rename {tutorial_scripts => examples/tutorial_scripts}/10_model_serve.sh (100%) rename {tutorial_scripts => examples/tutorial_scripts}/11_deploy.sh (100%) diff --git a/tutorial_scripts/01_quickstart.py b/examples/tutorial_scripts/01_quickstart.py similarity index 100% rename from tutorial_scripts/01_quickstart.py rename to examples/tutorial_scripts/01_quickstart.py diff --git a/tutorial_scripts/02_in_app_quickstart.py b/examples/tutorial_scripts/02_in_app_quickstart.py similarity index 100% rename from tutorial_scripts/02_in_app_quickstart.py rename to examples/tutorial_scripts/02_in_app_quickstart.py diff --git a/tutorial_scripts/03_models.py b/examples/tutorial_scripts/03_models.py similarity index 100% rename from tutorial_scripts/03_models.py rename to examples/tutorial_scripts/03_models.py diff --git a/tutorial_scripts/04_datasets.py b/examples/tutorial_scripts/04_datasets.py similarity index 100% rename from tutorial_scripts/04_datasets.py rename to examples/tutorial_scripts/04_datasets.py diff --git a/tutorial_scripts/05_eval_pipeline.py b/examples/tutorial_scripts/05_eval_pipeline.py similarity index 100% rename from tutorial_scripts/05_eval_pipeline.py rename to examples/tutorial_scripts/05_eval_pipeline.py diff --git a/tutorial_scripts/06_eval_pipeline_all.py b/examples/tutorial_scripts/06_eval_pipeline_all.py similarity index 100% rename from tutorial_scripts/06_eval_pipeline_all.py rename to examples/tutorial_scripts/06_eval_pipeline_all.py diff --git a/tutorial_scripts/07_objects.py b/examples/tutorial_scripts/07_objects.py similarity index 100% rename from tutorial_scripts/07_objects.py rename to examples/tutorial_scripts/07_objects.py diff --git a/tutorial_scripts/08_ops.py b/examples/tutorial_scripts/08_ops.py similarity index 100% rename from tutorial_scripts/08_ops.py rename to examples/tutorial_scripts/08_ops.py diff --git a/tutorial_scripts/09_tracing.py b/examples/tutorial_scripts/09_tracing.py similarity index 100% rename from tutorial_scripts/09_tracing.py rename to examples/tutorial_scripts/09_tracing.py diff --git a/tutorial_scripts/10_model_serve.sh b/examples/tutorial_scripts/10_model_serve.sh similarity index 100% rename from tutorial_scripts/10_model_serve.sh rename to examples/tutorial_scripts/10_model_serve.sh diff --git a/tutorial_scripts/11_deploy.sh b/examples/tutorial_scripts/11_deploy.sh similarity index 100% rename from tutorial_scripts/11_deploy.sh rename to examples/tutorial_scripts/11_deploy.sh From 43f34ce3bc3bd712a66a1f9b23edaf09f68df69e Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Sun, 25 Aug 2024 08:39:33 -0400 Subject: [PATCH 65/84] move to legacy: pytest --- pytest.ini | 8 -------- weave/legacy/pytest.ini | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 8 deletions(-) create mode 100644 weave/legacy/pytest.ini diff --git a/pytest.ini b/pytest.ini index c5ad7454bb6..40c9ac85e74 100644 --- a/pytest.ini +++ b/pytest.ini @@ -5,14 +5,6 @@ filterwarnings = ; error ; ignore deprecation warnings from installed packages, they're printed at the ; bottom of test output, making it hard to find the actual errors. - ignore::DeprecationWarning:bertviz.*: - ignore::DeprecationWarning:tensorflow.*: - ignore::DeprecationWarning:ddtrace.*: - ignore::DeprecationWarning:keras.*: - ignore::DeprecationWarning:shap.*: - ignore::DeprecationWarning:replicate.*: - ignore::DeprecationWarning:flask.*: - ignore::DeprecationWarning:transformers.*: ignore::DeprecationWarning addopts = -v markers = diff --git a/weave/legacy/pytest.ini b/weave/legacy/pytest.ini new file mode 100644 index 00000000000..12ec4aa9276 --- /dev/null +++ b/weave/legacy/pytest.ini @@ -0,0 +1,17 @@ + +[pytest] +filterwarnings = + ; treat warnings as errors + ; error + ; ignore deprecation warnings from installed packages, they're printed at the + ; bottom of test output, making it hard to find the actual errors. + ignore::DeprecationWarning:bertviz.*: + ignore::DeprecationWarning:tensorflow.*: + ignore::DeprecationWarning:ddtrace.*: + ignore::DeprecationWarning:keras.*: + ignore::DeprecationWarning:shap.*: + ignore::DeprecationWarning:replicate.*: + ignore::DeprecationWarning:flask.*: + ignore::DeprecationWarning:transformers.*: + ignore::DeprecationWarning +addopts = -v From 601c02ffe74cf3af0c806ab1b87191d7fcffb16d Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Sun, 25 Aug 2024 08:43:38 -0400 Subject: [PATCH 66/84] move to legacy: build_dist --- build_dist.py => weave/legacy/build_dist.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename build_dist.py => weave/legacy/build_dist.py (100%) diff --git a/build_dist.py b/weave/legacy/build_dist.py similarity index 100% rename from build_dist.py rename to weave/legacy/build_dist.py From 95280f6506a4896c8adb5ee24df9d7a192f6c20a Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Sun, 25 Aug 2024 09:24:53 -0400 Subject: [PATCH 67/84] move to legacy: docker stuff --- .github/workflows/test.yaml | 4 +- Dockerfile | 51 ------------------- .dockerignore => weave/legacy/.dockerignore | 0 .../legacy/Dockerfile.test | 0 .../legacy/docker_build.py | 0 5 files changed, 2 insertions(+), 53 deletions(-) delete mode 100644 Dockerfile rename .dockerignore => weave/legacy/.dockerignore (100%) rename Dockerfile.test => weave/legacy/Dockerfile.test (100%) rename docker_build.py => weave/legacy/docker_build.py (100%) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 7023d1a87e5..1a7d2c3e17d 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -35,9 +35,9 @@ jobs: - name: Prune docker cache run: docker system prune -f - name: Build unit test image - run: python3 docker_build.py build_deps weave-test builder . Dockerfile.test + run: python3 weave/legacy/docker_build.py build_deps weave-test builder . weave/legacy/Dockerfile.test - name: Build integration test image - run: python3 docker_build.py build weave-integration-test . Dockerfile.test + run: python3 weave/legacy/docker_build.py build weave-integration-test . weave/legacy/Dockerfile.test lint: name: Python lint diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 51417c492c3..00000000000 --- a/Dockerfile +++ /dev/null @@ -1,51 +0,0 @@ -FROM frolvlad/alpine-glibc:alpine-3.17_glibc-2.34 -LABEL MAINTAINER="danny goldstein " - -ENV CONDA_VERSION=4.9.2 \ - CONDA_MD5=b4e46fcc8029e2cfa731b788f25b1d36 \ - PYTHON_VERSION=39 \ - PYTHONDONTWRITEBYTECODE=true \ - PATH=/opt/conda/bin/:/opt/conda/envs/base/:$PATH \ - WEAVE_LOCAL_ARTIFACT_DIR=/local-artifacts - -# We do the following all in one block: -# - Create user and group weave -# - Install miniconda install dependencies -# - Download miniconda and check the md5sum -# - Install miniconda -# - Install tini -# - Remove all conda managed static libraries -# - Remove all conda managed *.pyc files -# - Cleanup conda files -# - Uninstall miniconda install dependencies -RUN mkdir /weave \ - && apk add --no-cache wget bzip2 \ - && wget --quiet https://repo.continuum.io/miniconda/Miniconda3-py${PYTHON_VERSION}_$CONDA_VERSION-Linux-x86_64.sh \ - && echo "${CONDA_MD5} Miniconda3-py${PYTHON_VERSION}_$CONDA_VERSION-Linux-x86_64.sh" > miniconda.md5 \ - && if [ $(md5sum -c miniconda.md5 | awk '{print $2}') != "OK" ] ; then exit 1; fi \ - && mv Miniconda3-py${PYTHON_VERSION}_$CONDA_VERSION-Linux-x86_64.sh miniconda.sh \ - && sh ./miniconda.sh -b -p /opt/conda \ - && rm miniconda.sh miniconda.md5 \ - && ln -s /opt/conda/etc/profile.d/conda.sh /etc/profile.d/conda.sh \ - && echo ". /opt/conda/etc/profile.d/conda.sh" >> /weave/.profile \ - && echo "conda activate base" >> /weave/.profile \ - && /opt/conda/bin/conda install conda==$CONDA_VERSION \ - && echo "conda == $CONDA_VERSION" >> /opt/conda/conda-meta/pinned \ - && /opt/conda/bin/conda install --freeze-installed tini pip gunicorn python=3.9.7 -y \ - && find /opt/conda/ -follow -type f -name '*.a' -delete \ - && find /opt/conda/ -follow -type f -name '*.pyc' -delete \ - && /opt/conda/bin/conda clean -afy \ - && apk del wget bzip2 - -ENV PORT 9239 - -WORKDIR /weave -ADD . . - -RUN pip install -r requirements.engine.txt -RUN mkdir /local-artifacts - -EXPOSE 9239 - -ENTRYPOINT [ "tini", "-g", "--" ] -CMD ["gunicorn", "weave.weave_server:app"] diff --git a/.dockerignore b/weave/legacy/.dockerignore similarity index 100% rename from .dockerignore rename to weave/legacy/.dockerignore diff --git a/Dockerfile.test b/weave/legacy/Dockerfile.test similarity index 100% rename from Dockerfile.test rename to weave/legacy/Dockerfile.test diff --git a/docker_build.py b/weave/legacy/docker_build.py similarity index 100% rename from docker_build.py rename to weave/legacy/docker_build.py From c2cc4417307eb30ee21c82cba2251b105dfcefb0 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Sun, 25 Aug 2024 14:51:25 -0400 Subject: [PATCH 68/84] move to legacy: mutations-perf --- {.github => weave/legacy/.github}/workflows/mutations-perf.yaml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {.github => weave/legacy/.github}/workflows/mutations-perf.yaml (100%) diff --git a/.github/workflows/mutations-perf.yaml b/weave/legacy/.github/workflows/mutations-perf.yaml similarity index 100% rename from .github/workflows/mutations-perf.yaml rename to weave/legacy/.github/workflows/mutations-perf.yaml From 72fcf93fdaae8b1a74ba8c07ea50c669f2332302 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Sun, 25 Aug 2024 16:55:02 -0400 Subject: [PATCH 69/84] move to legacy: manifest --- MANIFEST.in => weave/legacy/MANIFEST.in | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename MANIFEST.in => weave/legacy/MANIFEST.in (100%) diff --git a/MANIFEST.in b/weave/legacy/MANIFEST.in similarity index 100% rename from MANIFEST.in rename to weave/legacy/MANIFEST.in From cbb42bb5a76850617da1c869956ffb5fe689af09 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Sun, 25 Aug 2024 14:28:52 -0400 Subject: [PATCH 70/84] move to trace: trace_test --- .../tests => tests/trace}/test_op_argument_forms.py | 3 +-- .../tests => tests/trace}/test_op_return_forms.py | 3 +-- weave/{trace/tests => tests/trace}/test_patcher.py | 10 +++++----- .../trace/test_patcher_module}/__init__.py | 0 .../trace}/test_patcher_module/example_class.py | 0 weave/tests/trace/test_weave_client.py | 2 +- .../test_vals.py => tests/trace/test_weave_object.py} | 0 weave/{trace/tests => tests/trace}/testutil.py | 0 weave/trace/tests/test_patcher_module/__init__.py | 0 9 files changed, 8 insertions(+), 10 deletions(-) rename weave/{trace/tests => tests/trace}/test_op_argument_forms.py (99%) rename weave/{trace/tests => tests/trace}/test_op_return_forms.py (99%) rename weave/{trace/tests => tests/trace}/test_patcher.py (81%) rename weave/{trace/tests => tests/trace/test_patcher_module}/__init__.py (100%) rename weave/{trace/tests => tests/trace}/test_patcher_module/example_class.py (100%) rename weave/{trace/tests/test_vals.py => tests/trace/test_weave_object.py} (100%) rename weave/{trace/tests => tests/trace}/testutil.py (100%) delete mode 100644 weave/trace/tests/test_patcher_module/__init__.py diff --git a/weave/trace/tests/test_op_argument_forms.py b/weave/tests/trace/test_op_argument_forms.py similarity index 99% rename from weave/trace/tests/test_op_argument_forms.py rename to weave/tests/trace/test_op_argument_forms.py index 37fc4cad211..f771442f77a 100644 --- a/weave/trace/tests/test_op_argument_forms.py +++ b/weave/tests/trace/test_op_argument_forms.py @@ -1,8 +1,7 @@ import pytest import weave - -from ...trace_server import trace_server_interface as tsi +from weave.trace_server import trace_server_interface as tsi # This file tests the different argument variations that can be passed to an op. # diff --git a/weave/trace/tests/test_op_return_forms.py b/weave/tests/trace/test_op_return_forms.py similarity index 99% rename from weave/trace/tests/test_op_return_forms.py rename to weave/tests/trace/test_op_return_forms.py index e441718eb7f..a69cb6e9421 100644 --- a/weave/trace/tests/test_op_return_forms.py +++ b/weave/tests/trace/test_op_return_forms.py @@ -3,8 +3,7 @@ import weave from weave.trace.op_extensions.accumulator import add_accumulator from weave.trace.weave_client import get_ref - -from ...trace_server import trace_server_interface as tsi +from weave.trace_server import trace_server_interface as tsi def test_op_return_sync_empty(client): diff --git a/weave/trace/tests/test_patcher.py b/weave/tests/trace/test_patcher.py similarity index 81% rename from weave/trace/tests/test_patcher.py rename to weave/tests/trace/test_patcher.py index 2528542eb2b..a761ce742dc 100644 --- a/weave/trace/tests/test_patcher.py +++ b/weave/tests/trace/test_patcher.py @@ -4,11 +4,11 @@ def test_symbol_patcher(): - from .test_patcher_module.example_class import ExampleClass + from weave.tests.trace.test_patcher_module.example_class import ExampleClass patcher = SymbolPatcher( lambda: importlib.import_module( - "weave.trace.tests.test_patcher_module.example_class" + "weave.tests.trace.test_patcher_module.example_class" ), "ExampleClass.example_fn", lambda original_fn: lambda self: 43, @@ -38,7 +38,7 @@ def test_symbol_patcher_invalid_module(): def test_symbol_patcher_invalid_attr(): patcher = SymbolPatcher( lambda: importlib.import_module( - "weave.trace.tests.test_patcher_module.example_class" + "weave.tests.trace.test_patcher_module.example_class" ), "NotARealExampleClass.example_fn", lambda original_fn: lambda self: 43, @@ -49,11 +49,11 @@ def test_symbol_patcher_invalid_attr(): def test_symbol_patcher_invalid_patching(): - from .test_patcher_module.example_class import ExampleClass + from weave.tests.trace.test_patcher_module.example_class import ExampleClass patcher = SymbolPatcher( lambda: importlib.import_module( - "weave.trace.tests.test_patcher_module.example_class" + "weave.tests.trace.test_patcher_module.example_class" ), "ExampleClass.example_fn", lambda original_fn: [] + 42, diff --git a/weave/trace/tests/__init__.py b/weave/tests/trace/test_patcher_module/__init__.py similarity index 100% rename from weave/trace/tests/__init__.py rename to weave/tests/trace/test_patcher_module/__init__.py diff --git a/weave/trace/tests/test_patcher_module/example_class.py b/weave/tests/trace/test_patcher_module/example_class.py similarity index 100% rename from weave/trace/tests/test_patcher_module/example_class.py rename to weave/tests/trace/test_patcher_module/example_class.py diff --git a/weave/tests/trace/test_weave_client.py b/weave/tests/trace/test_weave_client.py index 17184676066..2abbb957540 100644 --- a/weave/tests/trace/test_weave_client.py +++ b/weave/tests/trace/test_weave_client.py @@ -13,6 +13,7 @@ import weave.trace_server.trace_server_interface as tsi from weave import Evaluation from weave.legacy.weave import op_def +from weave.tests.trace.testutil import ObjectRefStrMatcher from weave.trace import refs, weave_client from weave.trace.isinstance import weave_isinstance from weave.trace.op import Op @@ -23,7 +24,6 @@ TABLE_ROW_ID_EDGE_NAME, ) from weave.trace.serializer import get_serializer_for_obj, register_serializer -from weave.trace.tests.testutil import ObjectRefStrMatcher from weave.trace_server.sqlite_trace_server import SqliteTraceServer from weave.trace_server.trace_server_interface import ( FileContentReadReq, diff --git a/weave/trace/tests/test_vals.py b/weave/tests/trace/test_weave_object.py similarity index 100% rename from weave/trace/tests/test_vals.py rename to weave/tests/trace/test_weave_object.py diff --git a/weave/trace/tests/testutil.py b/weave/tests/trace/testutil.py similarity index 100% rename from weave/trace/tests/testutil.py rename to weave/tests/trace/testutil.py diff --git a/weave/trace/tests/test_patcher_module/__init__.py b/weave/trace/tests/test_patcher_module/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 From 6aa3935c75bd465afd91a103dd10fd6a626ffb29 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Sun, 25 Aug 2024 08:32:14 -0400 Subject: [PATCH 71/84] move to dev_docs: dev_docs (also move legacy settings and devcontainer) --- .github/workflows/cla.yaml | 8 ++++---- DEVELOPMENT.md => dev_docs/DEVELOPMENT.md | 0 REF_SPEC.md => dev_docs/REF_SPEC.md | 0 RELEASE.md => dev_docs/RELEASE.md | 0 {cla => dev_docs}/cla.md | 0 .../legacy/.devcontainer}/devcontainer.json | 0 .../legacy/.devcontainer}/postCreateCommand.sh | 0 {.vscode => weave/legacy/.vscode}/settings.json | 0 8 files changed, 4 insertions(+), 4 deletions(-) rename DEVELOPMENT.md => dev_docs/DEVELOPMENT.md (100%) rename REF_SPEC.md => dev_docs/REF_SPEC.md (100%) rename RELEASE.md => dev_docs/RELEASE.md (100%) rename {cla => dev_docs}/cla.md (100%) rename {.devcontainer => weave/legacy/.devcontainer}/devcontainer.json (100%) rename {.devcontainer => weave/legacy/.devcontainer}/postCreateCommand.sh (100%) rename {.vscode => weave/legacy/.vscode}/settings.json (100%) diff --git a/.github/workflows/cla.yaml b/.github/workflows/cla.yaml index f211f20e3d2..b7b343bf3bd 100644 --- a/.github/workflows/cla.yaml +++ b/.github/workflows/cla.yaml @@ -3,7 +3,7 @@ on: issue_comment: types: [created] pull_request_target: - types: [opened,closed,synchronize] + types: [opened, closed, synchronize] # explicitly configure permissions, in case your GITHUB_TOKEN workflow permissions are set to read-only in repository settings permissions: @@ -22,9 +22,9 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - path-to-signatures: 'cla/signatures/version1/cla.json' - path-to-document: 'https://github.com/wandb/weave/blob/master/cla/cla.md' # e.g. a CLA or a DCO document + path-to-signatures: "cla/signatures/version1/cla.json" + path-to-document: "https://github.com/wandb/weave/blob/master/dev_docs/cla.md" # e.g. a CLA or a DCO document # branch should not be protected - branch: 'cla' + branch: "cla" # cannot use teams due to: https://github.com/contributor-assistant/github-action/issues/100 allowlist: actions-user, altay, bdytx5, dannygoldstein, davidwallacejackson, jamie-rasmussen, jlzhao27, jo-fang, jwlee64, laxels, morganmcg1, nickpenaranda, scottire, shawnlewis, staceysv, tssweeney, vanpelt, vwrj, wandbmachine diff --git a/DEVELOPMENT.md b/dev_docs/DEVELOPMENT.md similarity index 100% rename from DEVELOPMENT.md rename to dev_docs/DEVELOPMENT.md diff --git a/REF_SPEC.md b/dev_docs/REF_SPEC.md similarity index 100% rename from REF_SPEC.md rename to dev_docs/REF_SPEC.md diff --git a/RELEASE.md b/dev_docs/RELEASE.md similarity index 100% rename from RELEASE.md rename to dev_docs/RELEASE.md diff --git a/cla/cla.md b/dev_docs/cla.md similarity index 100% rename from cla/cla.md rename to dev_docs/cla.md diff --git a/.devcontainer/devcontainer.json b/weave/legacy/.devcontainer/devcontainer.json similarity index 100% rename from .devcontainer/devcontainer.json rename to weave/legacy/.devcontainer/devcontainer.json diff --git a/.devcontainer/postCreateCommand.sh b/weave/legacy/.devcontainer/postCreateCommand.sh similarity index 100% rename from .devcontainer/postCreateCommand.sh rename to weave/legacy/.devcontainer/postCreateCommand.sh diff --git a/.vscode/settings.json b/weave/legacy/.vscode/settings.json similarity index 100% rename from .vscode/settings.json rename to weave/legacy/.vscode/settings.json From 7e9ac2b2826abdae6eed66094f6a1410b0980ef2 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Sun, 25 Aug 2024 08:17:30 -0400 Subject: [PATCH 72/84] move to scripts: auth_modes (also split out jupyter dev script) --- {config => scripts}/auth_modes.sh | 0 scripts/weave_server.sh | 2 +- weave/legacy/scripts/jupyter_dev.sh | 6 ++---- 3 files changed, 3 insertions(+), 5 deletions(-) rename {config => scripts}/auth_modes.sh (100%) diff --git a/config/auth_modes.sh b/scripts/auth_modes.sh similarity index 100% rename from config/auth_modes.sh rename to scripts/auth_modes.sh diff --git a/scripts/weave_server.sh b/scripts/weave_server.sh index 91bc19fccd6..3f94c186b6e 100755 --- a/scripts/weave_server.sh +++ b/scripts/weave_server.sh @@ -2,7 +2,7 @@ # We could set WEAVE_BACKEND_HOST=http://localhost:9994/__weave but the frontend dev server # automatically forwards so it shouldn't be necessary. -source ./config/auth_modes.sh +source ./scripts/auth_modes.sh WEAVE_DISABLE_ANALYTICS=true WEAVE_SERVER_ENABLE_LOGGING=true diff --git a/weave/legacy/scripts/jupyter_dev.sh b/weave/legacy/scripts/jupyter_dev.sh index 696c0e12cf4..04ec0559729 100755 --- a/weave/legacy/scripts/jupyter_dev.sh +++ b/weave/legacy/scripts/jupyter_dev.sh @@ -1,5 +1,3 @@ #!/bin/sh -( - source ./config/auth_modes.sh - WEAVE_FRONTEND_DEVMODE=true jupyter notebook -) +source ./scripts/auth_modes.sh +WEAVE_FRONTEND_DEVMODE=true jupyter notebook From 9a59204aa761dc7711a99eaf9bb87e9d4b45ec0c Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Sun, 25 Aug 2024 08:56:45 -0400 Subject: [PATCH 73/84] delete: useless pyright config --- .pre-commit-config.yaml | 5 -- weave/legacy/pyrightconfig.json | 99 --------------------------------- 2 files changed, 104 deletions(-) delete mode 100644 weave/legacy/pyrightconfig.json diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 78ea91c9759..7f3d2153dea 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,11 +19,6 @@ repos: [types-pkg-resources==0.1.3, types-all, wandb>=0.15.5] # You have to exclude in 3 places. 1) here. 2) mypi.ini exclude, 3) follow_imports = skip for each module in mypy.ini exclude: (.*pyi$)|(weave/legacy)|(weave/tests) - # Turn pyright back off, duplicative of mypy - # - repo: https://github.com/RobertCraigie/pyright-python - # rev: v1.1.341 - # hooks: - # - id: pyright - repo: local hooks: - id: jupyter-nb-clear-output diff --git a/weave/legacy/pyrightconfig.json b/weave/legacy/pyrightconfig.json deleted file mode 100644 index 0ad38dc42a1..00000000000 --- a/weave/legacy/pyrightconfig.json +++ /dev/null @@ -1,99 +0,0 @@ -{ - "include": ["weave/"], - "exclude": [ - "genpydocs.py", - "docker_build.py", - "examples", - "integration_test", - "internal_tools", - "setup.py", - "weave-js", - "mypy_weave_plugin.py", - "weave/api.py", - "weave/artifact_fs.py", - "weave/artifact_local.py", - "weave/artifact_wandb.py", - "weave/arrow_util.py", - "weave/async_demo.py", - "weave/async_queue.py", - "weave/box.py", - "weave/cli.py", - "weave/client_interface.py", - "weave.legacy.weave.codify.py", - "weave/compile_domain.py", - "weave/conftest.py", - "weave/context.py", - "weave/context_state.py", - "weave/decorator_class.py", - "weave/decorator_op.py", - "weave/decorator_type.py", - "weave/deploy", - "weave/derive_op.py", - "weave/dispatch.py", - "weave/ecosystem", - "weave/engine_trace.py", - "weave/execute.py", - "weave/file_base.py", - "weave/file_local.py", - "weave/filesystem.py", - "weave/gql_schema.py", - "weave/gql_to_weave.py", - "weave/infer_types.py", - "weave/io_service.py", - "weave/language_features", - "weave/logs.py", - "weave/mappers_arrow.py", - "weave/mappers_gql.py", - "weave/mappers_publisher.py", - "weave/mappers_python.py", - "weave/mappers_python_def.py", - "weave/monitoring", - "weave/node_ref.py", - "weave/op_def.py", - "weave/op_def_type.py", - "weave/ops_arrow", - "weave/ops_domain", - "weave/ops_primitives", - "weave/panels", - "weave/panel.py", - "weave/panel_util.py", - "weave/panels_py", - "weave/partial_object.py", - "weave/pyfunc_type_util.py", - "weave/registry_mem.py", - "weave/run_streamtable_span.py", - "weave/runfiles_wandb.py", - "weave/serialize.py", - "weave/serve_fastapi.py", - "weave/server.py", - "weave/server_error_handling.py", - "weave/show.py", - "weave/signal_handlers.py", - "weave/stream_data_interfaces.py", - "weave/storage.py", - "weave/legacy/scripts/syndata.py", - "weave/legacy/scripts/syndata_mon.py", - "weave/tests", - "weave/types_numpy.py", - "weave/usage_analytics.py", - "weave/util.py", - "weave/urls.py", - "weave/wandb_api.py", - "weave/wandb_client_api.py", - "weave/wandb_file_manager.py", - "weave/wandb_interface", - "weave/wandb_util.py", - "weave/weave_inspector.py", - "weave/weave_internal.py", - "weave/weave_server.py", - "weave/weave_types.py", - "weave/weaveflow", - "weave/weave_http.py", - "weave/weave_pydantic.py", - "weave/weavify.py" - ], - "reportFunctionMemberAccess": true, - "reportIncompatibleMethodOverride": true, - "reportIncompatibleVariableOverride": true, - "reportOverlappingOverload": true -} From 1e5120602e303a261e924136972368670d13eaa1 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Mon, 26 Aug 2024 08:33:29 -0400 Subject: [PATCH 74/84] move to legacy: test_server --- weave/{tests/trace => legacy/tests}/test_server.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename weave/{tests/trace => legacy/tests}/test_server.py (100%) diff --git a/weave/tests/trace/test_server.py b/weave/legacy/tests/test_server.py similarity index 100% rename from weave/tests/trace/test_server.py rename to weave/legacy/tests/test_server.py From 30fd069e082767e796863ebd083a1b7832ef70c1 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Mon, 26 Aug 2024 08:36:16 -0400 Subject: [PATCH 75/84] cleanup: missing imports --- weave/legacy/weave/ref_base.py | 2 +- weave/trace/box.py | 2 +- weave/trace/op_type.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/weave/legacy/weave/ref_base.py b/weave/legacy/weave/ref_base.py index 6951fe602b3..ba92ea13ca5 100644 --- a/weave/legacy/weave/ref_base.py +++ b/weave/legacy/weave/ref_base.py @@ -17,7 +17,7 @@ if typing.TYPE_CHECKING: from weave.legacy.weave import weave_types as types - from ..trace import weave_client + from ...trace import weave_client def _map_to_ref_strs(obj: typing.Any) -> typing.Any: diff --git a/weave/trace/box.py b/weave/trace/box.py index a185c50a822..d0b7db6db9d 100644 --- a/weave/trace/box.py +++ b/weave/trace/box.py @@ -10,7 +10,7 @@ import numpy as np -from weave.legacy.weave.ref_base import Ref +from weave.trace.refs import Ref T = TypeVar("T") diff --git a/weave/trace/op_type.py b/weave/trace/op_type.py index fd948b8a2e0..c570e60436c 100644 --- a/weave/trace/op_type.py +++ b/weave/trace/op_type.py @@ -19,11 +19,11 @@ get_class_source, is_running_interactively, ) +from weave.trace.op import Op from weave.trace.refs import ObjectRef from ..legacy.weave import environment from . import serializer -from .op import Op WEAVE_OP_PATTERN = re.compile(r"@weave\.op(\(\))?") WEAVE_OP_NO_PAREN_PATTERN = re.compile(r"@weave\.op(?!\()") From 59ab8b7c61eec50d6946ee9e5c1f261e29e6cfe3 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Mon, 26 Aug 2024 08:55:51 -0400 Subject: [PATCH 76/84] split: further split trace and legacy errors --- weave/trace/client_context/weave_client.py | 2 +- weave/trace/errors.py | 21 +++++++++++++++------ weave/trace/weave_client.py | 8 ++------ 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/weave/trace/client_context/weave_client.py b/weave/trace/client_context/weave_client.py index f74759f26ac..ee7e994d68d 100644 --- a/weave/trace/client_context/weave_client.py +++ b/weave/trace/client_context/weave_client.py @@ -2,7 +2,7 @@ from typing import TYPE_CHECKING, Optional from weave.legacy.weave import context_state -from weave.legacy.weave.errors import WeaveInitError +from weave.trace.errors import WeaveInitError if TYPE_CHECKING: from weave.trace.weave_client import WeaveClient diff --git a/weave/trace/errors.py b/weave/trace/errors.py index 6b5617614fb..b1aeab7b3d0 100644 --- a/weave/trace/errors.py +++ b/weave/trace/errors.py @@ -1,10 +1,19 @@ -class Error(Exception): - pass +class Error(Exception): ... -class InternalError(Error): - pass +class InternalError(Error): ... -class OpCallError(Error): - pass +class OpCallError(Error): ... + + +class WeaveTypeError(Error): ... + + +class WeaveSerializeError(Error): ... + + +class WeaveOpSerializeError(WeaveSerializeError): ... + + +class WeaveInitError(Error): ... diff --git a/weave/trace/weave_client.py b/weave/trace/weave_client.py index a16884b955d..6097a6d918a 100644 --- a/weave/trace/weave_client.py +++ b/weave/trace/weave_client.py @@ -51,10 +51,6 @@ TraceServerInterface, ) -if typing.TYPE_CHECKING: - from ..legacy.weave import ref_base - - # Controls if objects can have refs to projects not the WeaveClient project. # If False, object refs with with mismatching projects will be recreated. # If True, use existing ref to object in other project. @@ -904,10 +900,10 @@ def _set_call_display_name( def _remove_call_display_name(self, call: Call) -> None: self._set_call_display_name(call, None) - def _ref_input_to(self, ref: "ref_base.Ref") -> Sequence[Call]: + def _ref_input_to(self, ref: Ref) -> Sequence[Call]: raise NotImplementedError() - def _ref_value_input_to(self, ref: "ref_base.Ref") -> list[Call]: + def _ref_value_input_to(self, ref: Ref) -> list[Call]: raise NotImplementedError() def _ref_output_of(self, ref: ObjectRef) -> typing.Optional[Call]: From ea87f8e9fed02484b59d7079b8eda19166b9199b Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Mon, 26 Aug 2024 09:08:48 -0400 Subject: [PATCH 77/84] split: make separate trace and legacy utils --- weave/trace/api.py | 3 ++- weave/trace/feedback.py | 3 +-- weave/trace/rich_pydantic_util.py | 2 +- weave/trace/util.py | 25 +++++++++++++++++++++++++ 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/weave/trace/api.py b/weave/trace/api.py index 1c7dbbb4bb0..cbb6fecacff 100644 --- a/weave/trace/api.py +++ b/weave/trace/api.py @@ -6,7 +6,8 @@ import time from typing import Any, Callable, Iterator, Optional, Union -from weave.legacy.weave import urls, util +from weave.legacy.weave import urls +from weave.trace import util from weave.trace.call_context import get_current_call from weave.trace.client_context import weave_client as weave_client_context diff --git a/weave/trace/feedback.py b/weave/trace/feedback.py index 99893df018d..312903f1921 100644 --- a/weave/trace/feedback.py +++ b/weave/trace/feedback.py @@ -5,8 +5,7 @@ from rich.table import Table -from weave.legacy.weave import util -from weave.trace import rich_pydantic_util +from weave.trace import rich_pydantic_util, util from weave.trace.client_context import weave_client as weave_client_context from weave.trace.refs import parse_uri from weave.trace.rich_container import AbstractRichContainer diff --git a/weave/trace/rich_pydantic_util.py b/weave/trace/rich_pydantic_util.py index ec88c0545db..03ce95efe9d 100644 --- a/weave/trace/rich_pydantic_util.py +++ b/weave/trace/rich_pydantic_util.py @@ -6,7 +6,7 @@ from rich.console import Console from rich.table import Table -from weave.legacy.weave import util +from weave.trace import util def dict_to_table(d: dict[str, Any]) -> Table: diff --git a/weave/trace/util.py b/weave/trace/util.py index 9631569a6e4..b8fe3e25120 100644 --- a/weave/trace/util.py +++ b/weave/trace/util.py @@ -94,6 +94,31 @@ def run(self) -> None: self.context.run(super().run) +def is_colab(): # type: ignore + import importlib + + spec = importlib.util.find_spec("google.colab") + return bool(spec) + + +def is_notebook() -> bool: + if is_colab(): # type: ignore[no-untyped-call] + return True + try: + from IPython import get_ipython + except ImportError: + return False + else: + ip = get_ipython() + if ip is None: + return False + if "IPKernelApp" not in ip.config: + return False + # if "VSCODE_PID" in os.environ: + # return False + return True + + # rename for cleaner export ThreadPoolExecutor = ContextAwareThreadPoolExecutor Thread = ContextAwareThread From 8c02ceced0faf5b3b4c6fa4f7808e504020df924 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Mon, 26 Aug 2024 08:50:09 -0400 Subject: [PATCH 78/84] delete: extraneous import --- weave/tests/trace/op_versioning_solo.py | 1 - weave/tests/trace/test_op_versioning.py | 2 +- weave/trace/errors.py | 6 ++++++ weave/trace/serve_fastapi.py | 5 ++--- weave/trace/weave_init.py | 3 +-- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/weave/tests/trace/op_versioning_solo.py b/weave/tests/trace/op_versioning_solo.py index bacc0e27155..ac3afc6dd39 100644 --- a/weave/tests/trace/op_versioning_solo.py +++ b/weave/tests/trace/op_versioning_solo.py @@ -1,7 +1,6 @@ import numpy as np import weave -from weave.legacy.weave import artifact_fs @weave.op() diff --git a/weave/tests/trace/test_op_versioning.py b/weave/tests/trace/test_op_versioning.py index 3fc023e235c..b77d35a49d1 100644 --- a/weave/tests/trace/test_op_versioning.py +++ b/weave/tests/trace/test_op_versioning.py @@ -5,7 +5,7 @@ import pytest import weave -from weave.legacy.weave import artifact_fs, derive_op, op_def +from weave.legacy.weave import artifact_fs, derive_op from weave.trace_server.trace_server_interface import FileContentReadReq, ObjReadReq diff --git a/weave/trace/errors.py b/weave/trace/errors.py index b1aeab7b3d0..752ac759e62 100644 --- a/weave/trace/errors.py +++ b/weave/trace/errors.py @@ -17,3 +17,9 @@ class WeaveOpSerializeError(WeaveSerializeError): ... class WeaveInitError(Error): ... + + +class WeaveDefinitionError(Error): ... + + +class WeaveWandbAuthenticationException(Error): ... diff --git a/weave/trace/serve_fastapi.py b/weave/trace/serve_fastapi.py index 98adc7537b1..9351f968e7b 100644 --- a/weave/trace/serve_fastapi.py +++ b/weave/trace/serve_fastapi.py @@ -12,13 +12,12 @@ except ImportError: from typing_extensions import Annotated # type: ignore -from weave.legacy.weave import cache, op_args, pyfunc_type_util +from weave.legacy.weave import cache, op_args, pyfunc_type_util, weave_pydantic from weave.legacy.weave.wandb_api import WandbApiAsync +from weave.trace import errors from weave.trace.op import Op from weave.trace.refs import ObjectRef -from ..legacy.weave import errors, weave_pydantic - key_cache: cache.LruTimeWindowCache[str, typing.Optional[bool]] = ( cache.LruTimeWindowCache(datetime.timedelta(minutes=5)) ) diff --git a/weave/trace/weave_init.py b/weave/trace/weave_init.py index 55188cad443..603cf0b3592 100644 --- a/weave/trace/weave_init.py +++ b/weave/trace/weave_init.py @@ -1,7 +1,6 @@ import typing -from weave.legacy.weave import errors -from weave.trace import autopatch, init_message, trace_sentry, weave_client +from weave.trace import autopatch, errors, init_message, trace_sentry, weave_client from weave.trace.client_context import weave_client as weave_client_context from weave.trace_server import remote_http_trace_server, sqlite_trace_server From 7794e7fd1ff90754a8fd16ac372439ade0258ed1 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Mon, 26 Aug 2024 09:32:26 -0400 Subject: [PATCH 79/84] split: break out wandb_api into its own module for trace --- weave/trace/api.py | 2 +- weave/trace/serve_fastapi.py | 13 +- weave/trace/weave_init.py | 6 +- weave/wandb_api/api.py | 433 +++++++++++++++++++++++++++++++++++ 4 files changed, 441 insertions(+), 13 deletions(-) create mode 100644 weave/wandb_api/api.py diff --git a/weave/trace/api.py b/weave/trace/api.py index cbb6fecacff..0b3b8541602 100644 --- a/weave/trace/api.py +++ b/weave/trace/api.py @@ -203,7 +203,7 @@ def serve( ) -> str: import uvicorn - from weave.legacy.weave import wandb_api + from weave.wandb_api import api as wandb_api from .serve_fastapi import object_method_app diff --git a/weave/trace/serve_fastapi.py b/weave/trace/serve_fastapi.py index 9351f968e7b..0ad797650ca 100644 --- a/weave/trace/serve_fastapi.py +++ b/weave/trace/serve_fastapi.py @@ -1,22 +1,16 @@ import datetime import inspect import typing -from typing import Optional +from typing import Annotated, Optional from fastapi import Depends, FastAPI, Header, HTTPException from fastapi.security import HTTPBasic, HTTPBasicCredentials -try: - from typing import Annotated -# Support python 3.8 -except ImportError: - from typing_extensions import Annotated # type: ignore - from weave.legacy.weave import cache, op_args, pyfunc_type_util, weave_pydantic -from weave.legacy.weave.wandb_api import WandbApiAsync from weave.trace import errors from weave.trace.op import Op from weave.trace.refs import ObjectRef +from weave.wandb_api.api import WandbApiAsync key_cache: cache.LruTimeWindowCache[str, typing.Optional[bool]] = ( cache.LruTimeWindowCache(datetime.timedelta(minutes=5)) @@ -62,7 +56,8 @@ def api_key( ), ], x_wandb_api_key: Annotated[ - Optional[str], Header(description="Optional W&B API Key") + Optional[str], + Header(description="Optional W&B API Key"), ] = None, ) -> Optional[str]: if x_wandb_api_key: diff --git a/weave/trace/weave_init.py b/weave/trace/weave_init.py index 603cf0b3592..d90766b9eff 100644 --- a/weave/trace/weave_init.py +++ b/weave/trace/weave_init.py @@ -17,7 +17,7 @@ def reset(self) -> None: def get_username() -> typing.Optional[str]: - from weave.legacy.weave import wandb_api + from weave.wandb_api import api as wandb_api api = wandb_api.get_wandb_api_sync() try: @@ -27,7 +27,7 @@ def get_username() -> typing.Optional[str]: def get_entity_project_from_project_name(project_name: str) -> tuple[str, str]: - from weave.legacy.weave import wandb_api + from weave.wandb_api import api as wandb_api fields = project_name.split("/") if len(fields) == 1: @@ -75,7 +75,7 @@ def init_weave( else: _current_inited_client.reset() - from weave.legacy.weave import wandb_api + from weave.wandb_api import api as wandb_api # Must init to read ensure we've read auth from the environment, in # case we're on a new thread. diff --git a/weave/wandb_api/api.py b/weave/wandb_api/api.py new file mode 100644 index 00000000000..e6b2e1f09aa --- /dev/null +++ b/weave/wandb_api/api.py @@ -0,0 +1,433 @@ +# Official interface for interacting with the W&B API. All +# Weave interactions with the Weave API should go through this +# module. + +import contextlib +import contextvars +from typing import Any, Generator, Optional + +import aiohttp +import gql +import graphql +from gql.transport.aiohttp import AIOHTTPTransport +from gql.transport.requests import RequestsHTTPTransport +from requests.auth import HTTPBasicAuth + +from weave.legacy.weave import engine_trace, wandb_client_api +from weave.legacy.weave import environment as weave_env + +# Importing at the top-level namespace so other files can import from here. +from weave.legacy.weave.context_state import WandbApiContext, _wandb_api_context + +tracer = engine_trace.tracer() # type: ignore + + +def set_wandb_api_context( + user_id: Optional[str], + api_key: Optional[str], + headers: Optional[dict], + cookies: Optional[dict], +) -> Optional[contextvars.Token[Optional[WandbApiContext]]]: + cur_ctx = get_wandb_api_context() + if cur_ctx: + # WANDB API context is only allowed to be set once per thread, since we + # need to use thread local storage to communicate the context to the wandb + # lib right now. + return None + wandb_client_api.set_wandb_thread_local_api_settings(api_key, cookies, headers) + return _wandb_api_context.set(WandbApiContext(user_id, api_key, headers, cookies)) + + +def reset_wandb_api_context( + token: Optional[contextvars.Token[Optional[WandbApiContext]]], +) -> None: + if token is None: + return + wandb_client_api.reset_wandb_thread_local_api_settings() + _wandb_api_context.reset(token) + + +@contextlib.contextmanager +def wandb_api_context( + ctx: Optional[WandbApiContext], +) -> Generator[None, None, None]: + if ctx: + token = set_wandb_api_context( + ctx.user_id, ctx.api_key, ctx.headers, ctx.cookies + ) + try: + yield + finally: + if ctx: + reset_wandb_api_context(token) + + +def get_wandb_api_context() -> Optional[WandbApiContext]: + return _wandb_api_context.get() + + +def init() -> Optional[contextvars.Token[Optional[WandbApiContext]]]: + cookie = weave_env.weave_wandb_cookie() + headers = weave_env.weave_wandb_gql_headers() + if cookie: + # This is a special case for testing. It should never be used in production. + cookies = {"wandb": cookie} + headers = { + "use-admin-privileges": "true", + "x-origin": "https://app.wandb.test", + **headers, + } + return set_wandb_api_context("admin", None, headers, cookies) + api_key = weave_env.weave_wandb_api_key() + if api_key: + return set_wandb_api_context("admin", api_key, None, None) + return None + + +@contextlib.contextmanager +def from_environment() -> Generator[None, None, None]: + token = init() + try: + yield + finally: + if token: + reset_wandb_api_context(token) + + +class WandbApiAsync: + def __init__(self) -> None: + self.connector = aiohttp.TCPConnector(limit=50) + + async def query(self, query: graphql.DocumentNode, **kwargs: Any) -> Any: + wandb_context = get_wandb_api_context() + headers = None + cookies = None + auth = None + if wandb_context is not None: + headers = wandb_context.headers + cookies = wandb_context.cookies + if wandb_context.api_key is not None: + auth = aiohttp.BasicAuth("api", wandb_context.api_key) + # TODO: This is currently used by our FastAPI auth helper, there's probably a better way. + api_key_override = kwargs.pop("api_key", None) + if api_key_override: + auth = aiohttp.BasicAuth("api", api_key_override) + url_base = weave_env.wandb_base_url() + transport = AIOHTTPTransport( + url=url_base + "/graphql", + client_session_args={ + "connector": self.connector, + "connector_owner": False, + }, + headers=headers, + cookies=cookies, + auth=auth, + ) + # Warning: we do not use the recommended context manager pattern, because we're + # using connector_owner to tell the session not to close our connection pool. + # There is a bug in aiohttp that causes session close to hang for the ssl_close_timeout + # which is 10 seconds by default. See issue: https://github.com/graphql-python/gql/issues/381 + # Closing the session just closes the connector, which we don't want anyway, so we don't + # bother. + client = gql.Client(transport=transport, fetch_schema_from_transport=False) + session = await client.connect_async(reconnecting=False) # type: ignore + result = await session.execute(query, kwargs) + # Manually reset the connection, bypassing the SSL bug, avoiding ERROR:asyncio:Unclosed client session + await transport.session.close() + return result + + SERVER_INFO_QUERY = gql.gql( + """ + query ServerInfo { + serverInfo { + frontendHost + } + } + """ + ) + + async def server_info(self) -> Any: + return await self.query(self.SERVER_INFO_QUERY) + + ARTIFACT_MANIFEST_QUERY = gql.gql( + """ + query ArtifactManifest( + $entityName: String!, + $projectName: String!, + $name: String! + ) { + project(name: $projectName, entityName: $entityName) { + artifact(name: $name) { + currentManifest { + id + file { + directUrl + } + } + } + } + } + """ + ) + + async def artifact_manifest_url( + self, entity_name: str, project_name: str, name: str + ) -> Optional[str]: + try: + result = await self.query( + self.ARTIFACT_MANIFEST_QUERY, + entityName=entity_name, + projectName=project_name, + name=name, + ) + except gql.transport.exceptions.TransportQueryError as e: + return None + project = result["project"] + if project is None: + return None + artifact = project["artifact"] + if artifact is None: + return None + current_manifest = artifact["currentManifest"] + if current_manifest is None: + return None + file = current_manifest["file"] + if file is None: + return None + return file["directUrl"] + + ARTIFACT_MANIFEST_FROM_ID_QUERY = gql.gql( + """ + query ArtifactManifestFromID( + $artifactID: ID! + ) { + artifact(id: $artifactID) { + currentManifest { + id + file { + directUrl + } + } + } + } + """ + ) + + async def artifact_manifest_url_from_id(self, art_id: str) -> Optional[str]: + try: + result = await self.query( + self.ARTIFACT_MANIFEST_FROM_ID_QUERY, artifactID=art_id + ) + except gql.transport.exceptions.TransportQueryError as e: + return None + artifact = result["artifact"] + if artifact is None: + return None + current_manifest = artifact["currentManifest"] + if current_manifest is None: + return None + file = current_manifest["file"] + if file is None: + return None + return file["directUrl"] + + VIEWER_DEFAULT_ENTITY_QUERY = gql.gql( + """ + query DefaultEntity { + viewer { + defaultEntity { + name + } + } + } + """ + ) + + async def default_entity_name(self) -> Optional[str]: + try: + result = await self.query(self.VIEWER_DEFAULT_ENTITY_QUERY) + except gql.transport.exceptions.TransportQueryError as e: + return None + try: + return result.get("viewer", {}).get("defaultEntity", {}).get("name", None) + except AttributeError: + return None + + ENTITY_ACCESS_QUERY = gql.gql( + """ + query Entity($entityName: String!) { + viewer { username } + entity(name: $entityName) { readOnly } + } + """ + ) + + async def can_access_entity(self, entity: str, api_key: Optional[str]) -> bool: + try: + result = await self.query( + self.ENTITY_ACCESS_QUERY, entityName=entity, api_key=api_key + ) + except gql.transport.exceptions.TransportQueryError as e: + return False + return ( + result.get("viewer") + and result.get("entity", {}).get("readOnly", True) == False + ) + + +class WandbApi: + def query(self, query: graphql.DocumentNode, **kwargs: Any) -> Any: + wandb_context = get_wandb_api_context() + headers = None + cookies = None + auth = None + if wandb_context is not None: + headers = wandb_context.headers + cookies = wandb_context.cookies + if wandb_context.api_key is not None: + auth = HTTPBasicAuth("api", wandb_context.api_key) + url_base = weave_env.wandb_base_url() + transport = RequestsHTTPTransport( + url=url_base + "/graphql", headers=headers, cookies=cookies, auth=auth + ) + # Warning: we do not use the recommended context manager pattern, because we're + # using connector_owner to tell the session not to close our connection pool. + # There is a bug in aiohttp that causes session close to hang for the ssl_close_timeout + # which is 10 seconds by default. See issue: https://github.com/graphql-python/gql/issues/381 + # Closing the session just closes the connector, which we don't want anyway, so we don't + # bother. + client = gql.Client(transport=transport, fetch_schema_from_transport=False) + session = client.connect_sync() # type: ignore + return session.execute(query, kwargs) + + SERVER_INFO_QUERY = gql.gql( + """ + query ServerInfo { + serverInfo { + frontendHost + } + } + """ + ) + + def server_info(self) -> Any: + return self.query(self.SERVER_INFO_QUERY) + + ARTIFACT_MANIFEST_QUERY = gql.gql( + """ + query ArtifactManifest( + $entityName: String!, + $projectName: String!, + $name: String! + ) { + project(name: $projectName, entityName: $entityName) { + artifact(name: $name) { + currentManifest { + id + file { + directUrl + } + } + } + } + } + """ + ) + + def artifact_manifest_url( + self, entity_name: str, project_name: str, name: str + ) -> Optional[str]: + try: + result = self.query( + self.ARTIFACT_MANIFEST_QUERY, + entityName=entity_name, + projectName=project_name, + name=name, + ) + except gql.transport.exceptions.TransportQueryError as e: + return None + project = result["project"] + if project is None: + return None + artifact = project["artifact"] + if artifact is None: + return None + current_manifest = artifact["currentManifest"] + if current_manifest is None: + return None + file = current_manifest["file"] + if file is None: + return None + return file["directUrl"] + + ARTIFACT_MANIFEST_FROM_ID_QUERY = gql.gql( + """ + query ArtifactManifestFromID( + $artifactID: ID! + ) { + artifact(id: $artifactID) { + currentManifest { + id + file { + directUrl + } + } + } + } + """ + ) + + def artifact_manifest_url_from_id(self, art_id: str) -> Optional[str]: + try: + result = self.query(self.ARTIFACT_MANIFEST_FROM_ID_QUERY, artifactID=art_id) + except gql.transport.exceptions.TransportQueryError as e: + return None + artifact = result["artifact"] + if artifact is None: + return None + current_manifest = artifact["currentManifest"] + if current_manifest is None: + return None + file = current_manifest["file"] + if file is None: + return None + return file["directUrl"] + + VIEWER_DEFAULT_ENTITY_QUERY = gql.gql( + """ + query DefaultEntity { + viewer { + username + defaultEntity { + name + } + } + } + """ + ) + + def default_entity_name(self) -> Optional[str]: + try: + result = self.query(self.VIEWER_DEFAULT_ENTITY_QUERY) + except gql.transport.exceptions.TransportQueryError as e: + return None + try: + return result.get("viewer", {}).get("defaultEntity", {}).get("name", None) + except AttributeError: + return None + + def username(self) -> Optional[str]: + try: + result = self.query(self.VIEWER_DEFAULT_ENTITY_QUERY) + except gql.transport.exceptions.TransportQueryError as e: + return None + + return result.get("viewer", {}).get("username", None) + + +async def get_wandb_api() -> WandbApiAsync: + return WandbApiAsync() + + +def get_wandb_api_sync() -> WandbApi: + return WandbApi() From a34f36d45683e6bc9a7dd0b6196cb9151460326f Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Mon, 26 Aug 2024 09:34:39 -0400 Subject: [PATCH 80/84] split: further split trace and legacy env --- weave/trace/env.py | 4 ++++ weave/trace/op_type.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/weave/trace/env.py b/weave/trace/env.py index 0d75c3c93f9..90396ed245f 100644 --- a/weave/trace/env.py +++ b/weave/trace/env.py @@ -5,3 +5,7 @@ def get_weave_parallelism() -> int: return int(os.getenv(WEAVE_PARALLELISM, "20")) + + +def wandb_production() -> bool: + return os.getenv("WEAVE_ENV") == "wandb_production" diff --git a/weave/trace/op_type.py b/weave/trace/op_type.py index c570e60436c..6705ac98c35 100644 --- a/weave/trace/op_type.py +++ b/weave/trace/op_type.py @@ -14,6 +14,7 @@ from typing import Any, Callable, Optional, Union, get_args, get_origin from weave.legacy.weave import artifact_fs, context_state, errors, storage +from weave.trace import env as environment from weave.trace.ipython import ( ClassNotFoundError, get_class_source, @@ -22,7 +23,6 @@ from weave.trace.op import Op from weave.trace.refs import ObjectRef -from ..legacy.weave import environment from . import serializer WEAVE_OP_PATTERN = re.compile(r"@weave\.op(\(\))?") From d064148886bf045f86e7a2fcd4b016342151aa27 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Sun, 25 Aug 2024 17:14:55 -0400 Subject: [PATCH 81/84] split: break mypy.ini into trace and legacy pieces and update pre-commit --- .pre-commit-config.yaml | 41 ++- mypy.ini | 339 +----------------- weave/__init__.py | 1 + weave/legacy/mypy.ini | 54 +++ .../legacy/mypy_weave_plugin.py | 7 +- weave/legacy/weave/show.py | 3 +- weave/trace/weave_client.py | 9 +- 7 files changed, 116 insertions(+), 338 deletions(-) create mode 100644 weave/legacy/mypy.ini rename mypy_weave_plugin.py => weave/legacy/mypy_weave_plugin.py (79%) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7f3d2153dea..c7ba557f783 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,10 +15,47 @@ repos: rev: "v1.10.0" hooks: - id: mypy + name: mypy (trace) additional_dependencies: - [types-pkg-resources==0.1.3, types-all, wandb>=0.15.5] + [types-pkg-resources==0.1.3, types-all==1.0.0, wandb>=0.15.5] + exclude: > + (?x)^( + .*\.pyi$ + |weave/tests/ + |weave/trace_server/tests/ + |weave/legacy/ + |integration_test/ + ) + - id: mypy + name: mypy (legacy) + additional_dependencies: + [ + types-pkg-resources==0.1.3, + types-all==1.0.0, + types-setuptools, + wandb>=0.15.5, + ] + files: ^weave/legacy/ # You have to exclude in 3 places. 1) here. 2) mypi.ini exclude, 3) follow_imports = skip for each module in mypy.ini - exclude: (.*pyi$)|(weave/legacy)|(weave/tests) + exclude: > + (?x)^( + .*\.pyi$ + |weave/legacy/tests/ + |weave/legacy/weave/ecosystem/ + |weave/legacy/weave/panel/ + |weave/legacy/weave/panels/ + |weave/legacy/weave/panels_py/ + |weave/legacy/weave/ops/ + |weave/legacy/weave/ops_domain/ + |weave/legacy/weave/ops_arrow/ + |weave/legacy/weave/ops_primitives/ + |weave/legacy/weave/monitoring/ + |weave/trace/ + |weave/trace_server/ + |weave/flow/ + |weave/integrations/ + ) + args: [--config-file=weave/legacy/mypy.ini] - repo: local hooks: - id: jupyter-nb-clear-output diff --git a/mypy.ini b/mypy.ini index 8793034417e..99177b2f031 100644 --- a/mypy.ini +++ b/mypy.ini @@ -1,86 +1,10 @@ [mypy] -plugins = mypy_weave_plugin.py warn_unused_configs = True -exclude = (.*pyi$)|(weave/ecosystem)|(weave/tests)|(weave/panel)|(weave/ops)|(weave/trace_server/tests) - -;; we ignore ecosystem, tests, panel*, ops* for now. To do so you have -;; 1. put in exclude above -;; 2. put in follow_imports = skip below ;; 3. put in exclude in .pre-commit-config.yaml - -[mypy-weave.legacy.weave.ecosystem.*] -follow_imports = skip - -[mypy-weave.legacy.weave.panels_py.*] -follow_imports = skip - -[mypy-weave.legacy.weave.panels.*] -follow_imports = skip - -[mypy-weave.legacy.weave.ops_primitives.*] -follow_imports = skip - -[mypy-weave.legacy.weave.ops_domain.*] -follow_imports = skip - -[mypy-pyarrow.*] -ignore_missing_imports = True - -[mypy-aioprocessing] -ignore_missing_imports = True - -[mypy-ipynbname] -ignore_missing_imports = True - -[mypy-sklearn.*] -ignore_missing_imports = True - -[mypy-ddtrace] -ignore_missing_imports = True - -[mypy-datadog] -ignore_missing_imports = True - -[mypy-umap] -ignore_missing_imports = True - -[mypy-google.*] -ignore_missing_imports = True - -[mypy-langchain.*] -ignore_missing_imports = True - -[mypy-pandas] -ignore_missing_imports = True - -[mypy-replicate] -ignore_missing_imports = True - -[mypy-plotly.*] -ignore_missing_imports = True - -[mypy-matplotlib.*] -ignore_missing_imports = True - -[mypy-huggingface_hub] -ignore_missing_imports = True - -[mypy-datasets] -ignore_missing_imports = True - -[mypy-faiss] -ignore_missing_imports = True - -[mypy-torchvision] -ignore_missing_imports = True - -[mypy-bertviz] -ignore_missing_imports = True - -[mypy-shap] -ignore_missing_imports = True - -[mypy-analytics] -ignore_missing_imports = True +exclude = + .*pyi$ + |weave/tests + |weave/trace_server/tests + |weave/legacy ; Top-level rules [mypy-weave.*] @@ -94,18 +18,13 @@ disallow_untyped_calls = True ; warn_return_any = True ; show_error_codes = True +[mypy-weave.legacy.*] +ignore_errors = True +follow_imports = skip -[mypy-weave.legacy.weave._dict_utils] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.arrow.*] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.ops_arrow.*] -disallow_untyped_defs = False -disallow_untyped_calls = False +[mypy-integration_test.*] +ignore_errors = True +follow_imports = skip [mypy-weave.tests.*] disallow_untyped_defs = False @@ -127,242 +46,6 @@ disallow_untyped_calls = False disallow_untyped_defs = False disallow_untyped_calls = False -[mypy-weave.engine_trace] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.arrow_util] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.box] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.mappers] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.client_interface] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.util] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.weave_types] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.uris] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.types_numpy] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.op_args] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.context_state] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.mappers_weave] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.usage_analytics] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.runs_local] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.artifact_base] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.artifact_local] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.artifact_wandb] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.storage] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.client] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.mappers_python_def] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.mappers_gql] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.mappers_publisher] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.untyped_opaque_json] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.infer_types] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.trace_legacy] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.forward_graph] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.weavejs_fixes] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.make_type] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.serialize] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.op_def] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.trace_local] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.show] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.execute_fast] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.op_def_type] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.op_execute] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.execute] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.registry_mem] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.graph_mapper] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.context] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.decorator_class] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.mappers_arrow] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.server] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.decorator_op] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.decorator_arrow_op] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.lazy] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.decorator_type] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.panel_util] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.compile] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.api] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.query_api] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.panel] -disallow_untyped_defs = False -disallow_untyped_calls = False - [mypy-weave.weave_server] disallow_untyped_defs = False disallow_untyped_calls = False - -[mypy-weave.legacy.weave.derive_op] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.async_demo] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.legacy.weave.runs] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.node_ref] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.wandb_util] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.__init__] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.media_user] -disallow_untyped_defs = False -disallow_untyped_calls = False - -[mypy-weave.language_features.tagging.tagging_ops] -disallow_untyped_defs = False -disallow_untyped_calls = False diff --git a/weave/__init__.py b/weave/__init__.py index 4a92a3147a7..490ebf20e6c 100644 --- a/weave/__init__.py +++ b/weave/__init__.py @@ -16,6 +16,7 @@ from weave.legacy.weave import storage from weave.legacy.weave.api import * from weave.legacy.weave.errors import * +from weave.legacy.weave import errors from weave.legacy.weave import mappers_python_def from weave.legacy.weave import wandb_api as _wandb_api from weave.legacy.weave import context as _context diff --git a/weave/legacy/mypy.ini b/weave/legacy/mypy.ini new file mode 100644 index 00000000000..fdb75297b9a --- /dev/null +++ b/weave/legacy/mypy.ini @@ -0,0 +1,54 @@ +[mypy] +# TODO: Update type deco to dataclass transform: +# https://typing.readthedocs.io/en/latest/spec/dataclasses.html#dataclass-transform + +# plugins = mypy_weave_plugin.py +warn_unused_configs = True +files = weave/legacy/**/*.py +exclude = + .*pyi$ + |weave/legacy/tests/ + |weave/legacy/weave/ecosystem/ + |weave/legacy/weave/panel/ + |weave/legacy/weave/panels/ + |weave/legacy/weave/panels_py/ + |weave/legacy/weave/ops/ + |weave/legacy/weave/ops_domain/ + |weave/legacy/weave/ops_arrow/ + |weave/legacy/weave/ops_primitives/ + |weave/trace/ + |weave/trace_server/ + |weave/flow/ + |weave/integrations/ + |weave/legacy/monitoring/ + +[mypy-weave.legacy.*] +disable_error_code = import-not-found, import-untyped + +[mypy-weave.legacy.weave.*] +disallow_untyped_defs = True +disallow_untyped_calls = True +follow_imports = skip +disable_error_code = no-redef, no-untyped-def, no-untyped-call + +[mypy-weave.legacy.weave.monitoring.*] +ignore_errors = True + +# I don't understand why these are needed, but mypy will complain about them if not... +[mypy-weave.trace_server.*] +ignore_errors = True + +[mypy-weave.weave_server.*] +ignore_errors = True + +[mypy-weave.integrations.*] +ignore_errors = True + +[mypy-weave.wandb_api.*] +ignore_errors = True + +[mypy-weave.flow.*] +ignore_errors = True + +[mypy-weave.trace.*] +ignore_errors = True \ No newline at end of file diff --git a/mypy_weave_plugin.py b/weave/legacy/mypy_weave_plugin.py similarity index 79% rename from mypy_weave_plugin.py rename to weave/legacy/mypy_weave_plugin.py index f2a8b3700d8..080b32f0d61 100644 --- a/mypy_weave_plugin.py +++ b/weave/legacy/mypy_weave_plugin.py @@ -7,24 +7,23 @@ from typing import Callable, Optional from mypy.plugin import ClassDefContext, Plugin +from mypy.plugins import dataclasses class WeavePlugin(Plugin): def get_class_decorator_hook( self, fullname: str ) -> Optional[Callable[[ClassDefContext], None]]: - from mypy.plugins import dataclasses - if fullname in ["weave.decorator_type.type"]: + if fullname in ["weave.legacy.weave.decorator_type.type"]: return dataclasses.dataclass_tag_callback return None def get_class_decorator_hook_2( self, fullname: str ) -> Optional[Callable[[ClassDefContext], bool]]: - from mypy.plugins import dataclasses - if fullname in ["weave.decorator_type.type"]: + if fullname in ["weave.legacy.weave.decorator_type.type"]: return dataclasses.dataclass_class_maker_callback return None diff --git a/weave/legacy/weave/show.py b/weave/legacy/weave/show.py index 5e59d05272e..faebbcecad1 100644 --- a/weave/legacy/weave/show.py +++ b/weave/legacy/weave/show.py @@ -6,6 +6,7 @@ from IPython.display import IFrame, display from weave.legacy.weave import storage, artifact_fs, context, errors, graph, ops, node_ref, panel, ref_base +from weave.legacy.weave.arrow.list_ import dataframe_to_arrow from weave.legacy.weave import util from . import usage_analytics from weave.legacy.weave import weave_types as types @@ -125,7 +126,7 @@ def show(obj: typing.Any = None, height: int = 400) -> typing.Any: ) if util.is_pandas_dataframe(obj): # type: ignore[no-untyped-call] - obj = ops.dataframe_to_arrow(obj) # type: ignore[no-untyped-call] + obj = dataframe_to_arrow(obj) # type: ignore[no-untyped-call] panel_url = show_url(obj) # type: ignore[no-untyped-call] diff --git a/weave/trace/weave_client.py b/weave/trace/weave_client.py index 6097a6d918a..8db231631b4 100644 --- a/weave/trace/weave_client.py +++ b/weave/trace/weave_client.py @@ -4,7 +4,7 @@ import sys import typing from functools import lru_cache -from typing import Any, Dict, Iterator, Optional, Sequence, Union +from typing import TYPE_CHECKING, Any, Dict, Iterator, Optional, Sequence, Union import pydantic from requests import HTTPError @@ -51,6 +51,9 @@ TraceServerInterface, ) +if TYPE_CHECKING: + from weave.legacy.weave import ref_base + # Controls if objects can have refs to projects not the WeaveClient project. # If False, object refs with with mismatching projects will be recreated. # If True, use existing ref to object in other project. @@ -900,10 +903,10 @@ def _set_call_display_name( def _remove_call_display_name(self, call: Call) -> None: self._set_call_display_name(call, None) - def _ref_input_to(self, ref: Ref) -> Sequence[Call]: + def _ref_input_to(self, ref: "ref_base.Ref") -> Sequence[Call]: raise NotImplementedError() - def _ref_value_input_to(self, ref: Ref) -> list[Call]: + def _ref_value_input_to(self, ref: "ref_base.Ref") -> list[Call]: raise NotImplementedError() def _ref_output_of(self, ref: ObjectRef) -> typing.Optional[Call]: From df867eef07f0a0aa81ec8ff950496218f1c498c7 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Mon, 26 Aug 2024 17:48:22 -0400 Subject: [PATCH 82/84] split: test_weave_api into trace and legacy components --- weave/legacy/tests/test_weave_api.py | 28 +---------------------- weave/tests/trace/test_weave_api_trace.py | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+), 27 deletions(-) create mode 100644 weave/tests/trace/test_weave_api_trace.py diff --git a/weave/legacy/tests/test_weave_api.py b/weave/legacy/tests/test_weave_api.py index 0e20c9acf37..ace3a42825d 100644 --- a/weave/legacy/tests/test_weave_api.py +++ b/weave/legacy/tests/test_weave_api.py @@ -1,11 +1,7 @@ import os -import pytest - import weave -import weave.legacy.weave.context_state -import weave.legacy.weave.wandb_api -import weave.trace.weave_init + def test_create_list_rename_delete(): @@ -32,25 +28,3 @@ def test_create_list_rename_delete(): weave.legacy.weave.ops.delete_artifact(art_node) arts = weave.use(weave.legacy.weave.ops.local_artifacts()) assert len(arts) == 0 - - -def test_weave_finish_unsets_client(client): - @weave.op - def foo(): - return 1 - - weave.trace.client_context.weave_client.set_weave_client_global(None) - weave.trace.weave_init._current_inited_client = ( - weave.trace.weave_init.InitializedClient(client) - ) - weave_client = weave.trace.weave_init._current_inited_client.client - assert weave.trace.weave_init._current_inited_client is not None - - foo() - assert len(list(weave_client.calls())) == 1 - - weave.finish() - - foo() - assert len(list(weave_client.calls())) == 1 - assert weave.trace.weave_init._current_inited_client is None diff --git a/weave/tests/trace/test_weave_api_trace.py b/weave/tests/trace/test_weave_api_trace.py new file mode 100644 index 00000000000..4081f180b89 --- /dev/null +++ b/weave/tests/trace/test_weave_api_trace.py @@ -0,0 +1,24 @@ +import weave +import weave.trace.weave_init + + +def test_weave_finish_unsets_client(client): + @weave.op + def foo(): + return 1 + + weave.trace.client_context.weave_client.set_weave_client_global(None) + weave.trace.weave_init._current_inited_client = ( + weave.trace.weave_init.InitializedClient(client) + ) + weave_client = weave.trace.weave_init._current_inited_client.client + assert weave.trace.weave_init._current_inited_client is not None + + foo() + assert len(list(weave_client.calls())) == 1 + + weave.finish() + + foo() + assert len(list(weave_client.calls())) == 1 + assert weave.trace.weave_init._current_inited_client is None From 013444d62386f3355a684e03319f3398065a8c31 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Mon, 26 Aug 2024 18:05:05 -0400 Subject: [PATCH 83/84] split: ref_util into trace and legacy components (this one is hard copy) --- weave/legacy/tests/test_refs.py | 2 +- weave/legacy/weave/arrow/list_.py | 2 +- weave/legacy/weave/artifact_fs.py | 2 +- weave/legacy/weave/box.py | 2 +- weave/legacy/weave/object_type_ref_util.py | 2 +- weave/legacy/weave/ref_util.py | 105 +++++++++++++++++++++ 6 files changed, 110 insertions(+), 5 deletions(-) create mode 100644 weave/legacy/weave/ref_util.py diff --git a/weave/legacy/tests/test_refs.py b/weave/legacy/tests/test_refs.py index 98bd7048bc5..0a22d6028dd 100644 --- a/weave/legacy/tests/test_refs.py +++ b/weave/legacy/tests/test_refs.py @@ -4,7 +4,7 @@ from weave.flow.obj import Object from weave.legacy.weave import artifact_local, storage from weave.legacy.weave import ops_arrow as arrow -from weave.trace import ref_util +from weave.legacy.weave import ref_util from weave.trace_server.refs_internal import ( DICT_KEY_EDGE_NAME, LIST_INDEX_EDGE_NAME, diff --git a/weave/legacy/weave/arrow/list_.py b/weave/legacy/weave/arrow/list_.py index 6e3d0e85161..9a6a28b80ad 100644 --- a/weave/legacy/weave/arrow/list_.py +++ b/weave/legacy/weave/arrow/list_.py @@ -37,7 +37,7 @@ tag_store, tagged_value_type, ) -from weave.trace import ref_util +from weave.legacy.weave import ref_util def reverse_dict(d: dict) -> dict: diff --git a/weave/legacy/weave/artifact_fs.py b/weave/legacy/weave/artifact_fs.py index 37cc0a3b5ae..206d1bf487d 100644 --- a/weave/legacy/weave/artifact_fs.py +++ b/weave/legacy/weave/artifact_fs.py @@ -10,7 +10,7 @@ from weave.legacy.weave import weave_types as types from weave.legacy.weave import artifact_base, file_base, object_context, ref_base, uris from weave.legacy.weave.language_features.tagging import tag_store -from weave.trace import ref_util +from weave.legacy.weave import ref_util if typing.TYPE_CHECKING: from weave.legacy.weave import graph diff --git a/weave/legacy/weave/box.py b/weave/legacy/weave/box.py index a16725af94a..893707e6b26 100644 --- a/weave/legacy/weave/box.py +++ b/weave/legacy/weave/box.py @@ -4,7 +4,7 @@ import numpy as np -from weave.trace import ref_util +from weave.legacy.weave import ref_util from weave.legacy.weave import context_state diff --git a/weave/legacy/weave/object_type_ref_util.py b/weave/legacy/weave/object_type_ref_util.py index d0bc6a1ee35..e841087b064 100644 --- a/weave/legacy/weave/object_type_ref_util.py +++ b/weave/legacy/weave/object_type_ref_util.py @@ -1,6 +1,6 @@ import typing -from weave.trace import ref_util +from weave.legacy.weave import ref_util from weave.legacy.weave import context_state diff --git a/weave/legacy/weave/ref_util.py b/weave/legacy/weave/ref_util.py new file mode 100644 index 00000000000..47aed3131dd --- /dev/null +++ b/weave/legacy/weave/ref_util.py @@ -0,0 +1,105 @@ +import dataclasses +import typing +from urllib import parse + +from weave.legacy.weave import box +from weave.trace_server import refs_internal + +DICT_KEY_EDGE_NAME = refs_internal.DICT_KEY_EDGE_NAME +LIST_INDEX_EDGE_NAME = refs_internal.LIST_INDEX_EDGE_NAME +OBJECT_ATTR_EDGE_NAME = refs_internal.OBJECT_ATTR_EDGE_NAME +AWL_ROW_EDGE_NAME = "row" +AWL_COL_EDGE_NAME = "col" + + +def parse_local_ref_str(s: str) -> typing.Tuple[str, typing.Optional[list[str]]]: + if "#" not in s: + return s, None + path, extra = s.split("#", 1) + return path, extra.split("/") + + +def val_with_relative_ref( + parent_object: typing.Any, child_object: typing.Any, ref_extra_parts: list[str] +) -> typing.Any: + from weave.legacy.weave import context_state, ref_base + + # If we already have a ref, resolve it + if isinstance(child_object, ref_base.Ref): + child_object = child_object.get() + + # Only do this if ref_tracking_enabled right now. I just want to + # avoid introducing new behavior into W&B prod for the moment. + if context_state.ref_tracking_enabled(): + from weave.legacy.weave import storage + + child_ref = storage.get_ref(child_object) + parent_ref = ref_base.get_ref(parent_object) + + # This first check is super important - if the child ref is pointing + # to a completely different artifact (ref), then we want to point to + # the child's inherent ref, not the relative ref from the parent. + if child_ref is not None: + if parent_ref is not None: + if hasattr(child_ref, "digest") and hasattr(parent_ref, "digest"): + if child_ref.digest != parent_ref.digest: + return child_object + + if parent_ref is not None: + child_object = box.box(child_object) + sub_ref = parent_ref.with_extra(None, child_object, ref_extra_parts) + ref_base._put_ref(child_object, sub_ref) + return child_object + + return child_object + + +@dataclasses.dataclass +class RefExtraTuple: + edge_type: str + part: str + + +@dataclasses.dataclass +class ParsedRef: + scheme: str + entity: typing.Optional[str] + project: typing.Optional[str] + artifact: str + alias: str + file_path_parts: list[str] + ref_extra_tuples: list[RefExtraTuple] + + +def parse_ref_str(s: str) -> ParsedRef: + scheme, _, path, _, _, ref_extra = parse.urlparse(s) + entity = None + project = None + assert path.startswith("/") + path = path[1:] + path_parts = path.split("/") + if scheme == "wandb-artifact": + entity = path_parts[0] + project = path_parts[1] + path_parts = path_parts[2:] + + artifact, alias = path_parts[0].split(":") + file_path_parts = path_parts[1:] + ref_extra_tuples = [] + if ref_extra: + ref_extra_parts = ref_extra.split("/") + assert len(ref_extra_parts) % 2 == 0 + for i in range(0, len(ref_extra_parts), 2): + edge_type = ref_extra_parts[i] + part = ref_extra_parts[i + 1] + ref_extra_tuples.append(RefExtraTuple(edge_type, part)) + + return ParsedRef( + scheme=scheme, + entity=entity, + project=project, + artifact=artifact, + alias=alias, + file_path_parts=file_path_parts, + ref_extra_tuples=ref_extra_tuples, + ) From 6292ab61f0776b197dc735d4a21416624e56a8d4 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Mon, 26 Aug 2024 17:43:44 -0400 Subject: [PATCH 84/84] delete: remaining trace code in legacy api --- weave/legacy/weave/api.py | 12 +++--------- weave/legacy/weave/monitoring/monitor.py | 4 +--- weave/legacy/weave/op_def.py | 6 ------ weave/legacy/weave/op_execute.py | 4 ++-- 4 files changed, 6 insertions(+), 20 deletions(-) diff --git a/weave/legacy/weave/api.py b/weave/legacy/weave/api.py index 13d34e60760..e0d8d73f023 100644 --- a/weave/legacy/weave/api.py +++ b/weave/legacy/weave/api.py @@ -8,8 +8,8 @@ # If this is not imported, serialization of Weave Nodes is incorrect! from weave.legacy.weave import graph_mapper as _graph_mapper -from . import storage as _storage -from . import ref_base as _ref_base +from weave.legacy.weave import storage as _storage +from weave.legacy.weave import ref_base as _ref_base from weave.legacy.weave import wandb_api as _wandb_api from weave.legacy.weave import weave_internal as _weave_internal @@ -17,14 +17,12 @@ from weave.legacy.weave import util as _util from weave.legacy.weave import context as _context -from ...trace import weave_init as _weave_init -from ...trace import weave_client as _weave_client # exposed as part of api from weave.legacy.weave import weave_types as types # needed to enable automatic numpy serialization -from . import types_numpy as _types_numpy +from weave.legacy.weave import types_numpy as _types_numpy from weave.legacy.weave import errors from weave.legacy.weave.decorators import weave_class, mutation, type @@ -41,8 +39,6 @@ from weave.legacy.weave.arrow.list_ import ArrowWeaveList as WeaveList -# TODO: This is here because the op overloaded... -from weave.trace.op import op # noqa: F401 def save(node_or_obj, name=None): # type: ignore from weave.legacy.weave.ops_primitives.weave_api import get, save @@ -128,8 +124,6 @@ def from_pandas(df): # type: ignore "_weave_internal", "_util", "_context", - "_weave_init", - "_weave_client", "types", "_types_numpy", "errors", diff --git a/weave/legacy/weave/monitoring/monitor.py b/weave/legacy/weave/monitoring/monitor.py index 440a72d1291..c2fe7e53880 100644 --- a/weave/legacy/weave/monitoring/monitor.py +++ b/weave/legacy/weave/monitoring/monitor.py @@ -2,7 +2,6 @@ import asyncio import contextlib -import contextvars import dataclasses import datetime import inspect @@ -14,11 +13,10 @@ from weave.legacy.weave import errors from weave.legacy.weave import ( graph, - run_streamtable_span, stream_data_interfaces ) from weave.legacy.weave.wandb_interface.wandb_stream_table import StreamTable -from weave.trace import call_context, context as trace_context +from weave.trace import context as trace_context from weave.trace.client_context import weave_client as weave_client_context logger = logging.getLogger(__name__) diff --git a/weave/legacy/weave/op_def.py b/weave/legacy/weave/op_def.py index f8e397a375e..19add4ee900 100644 --- a/weave/legacy/weave/op_def.py +++ b/weave/legacy/weave/op_def.py @@ -4,7 +4,6 @@ import copy import inspect import typing -from typing import Iterator, Sequence from weave.legacy.weave import weave_types as types from weave.legacy.weave import ( @@ -28,13 +27,8 @@ process_opdef_resolve_fn, tagged_value_type, ) -from weave.legacy.weave.run import Run from weave.legacy.weave.weavejs_fixes import fixup_node -if typing.TYPE_CHECKING: - from weave.trace import weave_client - from weave.legacy.weave.run_streamtable_span import RunStreamTableSpan - _no_refine: contextvars.ContextVar[bool] = contextvars.ContextVar( "_no_refine", default=False diff --git a/weave/legacy/weave/op_execute.py b/weave/legacy/weave/op_execute.py index 8ea3b9fc9d0..7410352eac5 100644 --- a/weave/legacy/weave/op_execute.py +++ b/weave/legacy/weave/op_execute.py @@ -1,10 +1,10 @@ import typing from typing import Mapping -from weave.trace.constants import TRACE_CALL_EMOJI - if typing.TYPE_CHECKING: from .op_def import OpDef + +TRACE_CALL_EMOJI = "🍩" def print_run_link(run):