diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2c45dda5fa0..a5649a71720 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: hooks: - id: mypy additional_dependencies: - [types-pkg-resources==0.1.3, types-all, wandb>=0.15.5] + [types-pkg-resources==0.1.3, types-all, wandb>=0.15.5, wandb<0.19.0] # Note: You have to update pyproject.toml[tool.mypy] too! args: ["--config-file=pyproject.toml"] exclude: (.*pyi$)|(weave_query)|(tests)|(examples) diff --git a/docs/docs/guides/tools/comparison.md b/docs/docs/guides/tools/comparison.md new file mode 100644 index 00000000000..9149e34369d --- /dev/null +++ b/docs/docs/guides/tools/comparison.md @@ -0,0 +1,125 @@ +# Comparison + +The Weave Comparison feature allows you to visually compare and diff code, traces, prompts, models, and model configurations. You can compare two objects side-by-side or analyze a larger set of objects to identify differences, patterns, and trends. + +This guide covers the steps to start a comparison and the available actions to tailor your comparison view, including baseline comparisons, numeric diff formatting, and more. + +## Access the Comparison view + +1. In the sidebar, select the type of object you'd like to compare (e.g. **Traces**, **Models**, etc.). +2. Select the objects that you want to compare. The selection method varies depending on the type of object you are comparing: + - For **Traces**, select traces to compare by checking the checkboxes in the appropriate rows in the Traces column. + - For objects such as **Models**, navigate to the model Versions page and check the checkboxes next to the versions that you want to compare. +3. Click **Compare** to open the Comparison view. Now, you can refine your view using the [available actions](#available-actions). + +## Available actions + +In the Comparison view, you have multiple actions available, depending on how many objects are being compared. Make sure to look at the [usage notes](#usage-notes). + +- [Change the diff display](#change-the-diff-display) +- [Display side-by-side](#display-side-by-side) +- [Display in a unified view](#display-in-a-unified-view) +- [Set a baseline](#set-a-baseline) +- [Remove a baseline](#remove-a-baseline) +- [Change the comparison order](#change-the-comparison-order) +- [Change numeric diff display format](#change-numeric-diff-display-format) +- [Compare with baseline or previous](#compare-with-baseline-or-previous) +- [Compare a pair from a multi-object comparison](#compare-a-pair-from-a-multi-object-comparison) +- [Remove an object from comparison](#remove-an-object-from-comparison) + +### Change the diff display + +By default, **Diff only** is set to off. To filter the table rows so that only changed rows are displayed, toggle **Diff only** on. + +### Display side-by-side + +> This option is only available when comparing two objects, or a [pair from a multi-object comparison](#compare-a-pair-from-a-multi-object-comparison). + +To compare each object side-by-side in separate columns, select **Side-by-side**. + +![Side-by-side Comparison view of two objects](imgs/comparison-2objs-sidebyside.png) + +### Display in a unified view + +> This option is only available when comparing two objects, or a [pair from a multi-object comparison](#compare-a-pair-from-a-multi-object-comparison). + +To compare each object in a unified view, select **Unified**. + +![Unified Comparison view of two objects](imgs/comparison-2objs-unified.png) + +### Set a baseline + +By default, each object in the Comparison view is compared to the object to its left. However, you can set an object as the _baseline_, which means that all objects will be compared to the leftmost object in the view. +To set an object as baseline, do the following: + +1. In the Comparison view topbar, mouse over the object that you want to set as the baseline. +2. Click the three dots to the right of the ID. + ![Make baseline option displayed.](imgs/comparison-2objs-baseline.png) +3. In the dropdown, select **Make baseline**. The UI refreshes so that the baseline object is furthest left in the topbar, and `Baseline` displays next to the ID. + ![Baseline set.](imgs/comparison-2objs-baseline-set.png) + +### Remove a baseline + +To remove an object as baseline, do the following: + +1. In the Comparison view topbar, mouse over the baseline object. +2. Click the three dots to the right of the ID. +3. In the dropdown, select **Remove baseline**. Now, `Baseline` no longer displays next to the call ID. + +### Change the comparison order + +To change the comparison order, do the following: + +1. In the Comparison view topbar, mouse over the ID that you want to reorder. +2. Click the six dots to the left of the ID. + ![Setting the order.](imgs/comparison-2objs-reorder.png) +3. Drag the ID to the left or the right, depending on which object was selected. +4. Place the ID in the desired ordering. The UI refreshes with an updated comparison ordering. + +### Change numeric diff display format + +For numeric values such as `completion_tokens` and `total_tokens`, you can view the diff as either an integer or a percentage. Additionally, positive numeric values can be viewed as a multiplier. To change a numeric diff's display format, do the following: + +1. In the Comparison table, find the numeric value that you want to update the diff display format for. + ![A numeric value displayed as an integer.](imgs/comparison-2objs-numericdiffformat.png) +2. Click the diff value. The format automatically updates to either an integer or a percentage. + ![A numeric value updated to a percentage.](imgs/comparison-2objs-numericdiffformat-updated.png) + +### Compare with baseline or previous + +> This option is only available when comparing 3 or more objects. +> You can also [set](#set-a-baseline) or [remove an existing baseline by clicking the 3 dots to the right of the ID](#remove-a-baseline). + +To perform a baseline comparison with 3 or more objects, do the following: + +1. In the right hand corner of the Comparison view, click the dropdown. Depending on your current view configuration, the dropdown is either titled **Compare with previous** or **Compare with baseline**. +2. Depending on your current view configuration, select either **Compare with previous** or **Compare with baseline**. + - **Compare with baseline**: Sets the leftmost object as the baseline. The table updates so that the leftmost column is the baseline. + - **Compare with previous**: No object is set as baseline. + +### Compare a pair from a multi-object comparison + +> This option is only available when comparing 3 or more objects. + +When comparing 3 or more objects, you can compare a single object to a previous object or baseline. This changes the Comparison table view so that the view is identical to a two-object comparison. To compare a pair of objects from a multi-object comparison, do the following: + +1. In the Comparison view topbar, find the ID that you want to compare to previous or baseline. +2. To select the item, click the ID. The UI refreshes with a two-way comparison table. + ![Comparing a pair from a multi-object comparison.](imgs/comparsion-7objs-diffonly-subset.png) + +To reset the view so that the first 6 objects selected for comparison are displayed in the table, click the ID again. + +### Remove an object from comparison + +> This option is only available when comparing 3 or more objects. + +To remove an object from comparison, do the following: + +1. In the Comparison view topbar, find the object that you want to remove from comparison. +2. Click the three dots to the right of the ID. +3. In the dropdown, select **Remove object from comparison**. The UI refreshes with an updated table that no longer includes the removed object. + +## Usage notes + + - The Comparison feature is only available in the UI. + - You can compare as many objects as you'd like. However, the UI only displays a maximum of 6. To view an object in the comparison table that is not visible when comparing more than 6 objects, either [change the comparison order](#change-the-comparison-order) so that the object is one of the first 6 objects from left to right, or [pair from a multi-object comparison](#compare-a-pair-from-a-multi-object-comparison) for easy viewing. \ No newline at end of file diff --git a/docs/docs/guides/tools/imgs/comparison-2objs-baseline-set.png b/docs/docs/guides/tools/imgs/comparison-2objs-baseline-set.png new file mode 100644 index 00000000000..0eae1a51b5b Binary files /dev/null and b/docs/docs/guides/tools/imgs/comparison-2objs-baseline-set.png differ diff --git a/docs/docs/guides/tools/imgs/comparison-2objs-baseline.png b/docs/docs/guides/tools/imgs/comparison-2objs-baseline.png new file mode 100644 index 00000000000..3226d5a9a63 Binary files /dev/null and b/docs/docs/guides/tools/imgs/comparison-2objs-baseline.png differ diff --git a/docs/docs/guides/tools/imgs/comparison-2objs-numericdiffformat-updated.png b/docs/docs/guides/tools/imgs/comparison-2objs-numericdiffformat-updated.png new file mode 100644 index 00000000000..1f03d5d3123 Binary files /dev/null and b/docs/docs/guides/tools/imgs/comparison-2objs-numericdiffformat-updated.png differ diff --git a/docs/docs/guides/tools/imgs/comparison-2objs-numericdiffformat.png b/docs/docs/guides/tools/imgs/comparison-2objs-numericdiffformat.png new file mode 100644 index 00000000000..1886a64de96 Binary files /dev/null and b/docs/docs/guides/tools/imgs/comparison-2objs-numericdiffformat.png differ diff --git a/docs/docs/guides/tools/imgs/comparison-2objs-reorder.png b/docs/docs/guides/tools/imgs/comparison-2objs-reorder.png new file mode 100644 index 00000000000..a894ce9b967 Binary files /dev/null and b/docs/docs/guides/tools/imgs/comparison-2objs-reorder.png differ diff --git a/docs/docs/guides/tools/imgs/comparison-2objs-sidebyside.png b/docs/docs/guides/tools/imgs/comparison-2objs-sidebyside.png new file mode 100644 index 00000000000..08544f580b0 Binary files /dev/null and b/docs/docs/guides/tools/imgs/comparison-2objs-sidebyside.png differ diff --git a/docs/docs/guides/tools/imgs/comparison-2objs-unified.png b/docs/docs/guides/tools/imgs/comparison-2objs-unified.png new file mode 100644 index 00000000000..7814f711b6c Binary files /dev/null and b/docs/docs/guides/tools/imgs/comparison-2objs-unified.png differ diff --git a/docs/docs/guides/tools/imgs/comparsion-7objs-diffonly-allobjs.png b/docs/docs/guides/tools/imgs/comparsion-7objs-diffonly-allobjs.png new file mode 100644 index 00000000000..5820c600e08 Binary files /dev/null and b/docs/docs/guides/tools/imgs/comparsion-7objs-diffonly-allobjs.png differ diff --git a/docs/docs/guides/tools/imgs/comparsion-7objs-diffonly-remove.png b/docs/docs/guides/tools/imgs/comparsion-7objs-diffonly-remove.png new file mode 100644 index 00000000000..f7f929f7275 Binary files /dev/null and b/docs/docs/guides/tools/imgs/comparsion-7objs-diffonly-remove.png differ diff --git a/docs/docs/guides/tools/imgs/comparsion-7objs-diffonly-subset.png b/docs/docs/guides/tools/imgs/comparsion-7objs-diffonly-subset.png new file mode 100644 index 00000000000..bcaf293c25a Binary files /dev/null and b/docs/docs/guides/tools/imgs/comparsion-7objs-diffonly-subset.png differ diff --git a/docs/docs/guides/tools/playground.md b/docs/docs/guides/tools/playground.md index a3a0654f446..ad7a983aa29 100644 --- a/docs/docs/guides/tools/playground.md +++ b/docs/docs/guides/tools/playground.md @@ -16,7 +16,7 @@ Evaluating LLM prompts and responses is challenging. The Weave Playground is des Get started with the Playground to optimize your LLM interactions and streamline your prompt engineering process and LLM application development. - [Prerequisites](#prerequisites) - - [Add a provider API key](#add-a-provider-api-key) + - [Add provider credentials and information](#add-provider-credentials-and-information) - [Access the Playground](#access-the-playground) - [Select an LLM](#select-an-llm) - [Adjust LLM parameters](#adjust-llm-parameters) @@ -27,17 +27,21 @@ Get started with the Playground to optimize your LLM interactions and streamline ## Prerequisites -Before you can use Playground, you must [add an API key](#add-a-provider-api-key) for your preferred LLM provider(s), and [open the Playground UI](#access-the-playground). +Before you can use Playground, you must [add provider credentials](#add-provider-credentials-and-information), and [open the Playground UI](#access-the-playground). -### Add a provider API key +### Add provider credentials and information -Playground currently supports OpenAI, Anthropic, Gemini, and Groq models. -To use one of the available LLMs, your W&B admin must add the appropriate API key to your team secrets in W&B settings. +Playground currently supports OpenAI, Anthropic, Gemini, Groq, and Amazon Bedrock models. +To use one of the available models, add the appropriate information to your team secrets in W&B settings. - OpenAI: `OPENAI_API_KEY` - Anthropic: `ANTHROPIC_API_KEY` - Gemini: `GOOGLE_API_KEY` - Groq: `GEMMA_API_KEY` +- Amazon Bedrock: + - `AWS_ACCESS_KEY_ID` + - `AWS_SECRET_ACCESS_KEY` + - `AWS_REGION_NAME` ### Access the Playground @@ -105,6 +109,32 @@ You can switch the LLM using the dropdown menu in the top left. Currently, the a - o1-mini - o1-preview-2024-09-12 - o1-preview +- ai21.j2-mid-v1 +- ai21.j2-ultra-v1 +- amazon.titan-text-lite-v1 +- amazon.titan-text-express-v1 +- mistral.mistral-7b-instruct-v0:2 +- mistral.mixtral-8x7b-instruct-v0:1 +- mistral.mistral-large-2402-v1:0 +- mistral.mistral-large-2407-v1:0 +- anthropic.claude-3-sonnet-20240229-v1:0 +- anthropic.claude-3-5-sonnet-20240620-v1:0 +- anthropic.claude-3-haiku-20240307-v1:0 +- anthropic.claude-3-opus-20240229-v1:0 +- anthropic.claude-v2 +- anthropic.claude-v2:1 +- anthropic.claude-instant-v1 +- cohere.command-text-v14 +- cohere.command-light-text-v14 +- cohere.command-r-plus-v1:0 +- cohere.command-r-v1:0 +- meta.llama2-13b-chat-v1 +- meta.llama2-70b-chat-v1 +- meta.llama3-8b-instruct-v1:0 +- meta.llama3-70b-instruct-v1:0 +- meta.llama3-1-8b-instruct-v1:0 +- meta.llama3-1-70b-instruct-v1:0 +- meta.llama3-1-405b-instruct-v1:0 ## Adjust LLM parameters diff --git a/docs/docs/guides/tracking/tracing.mdx b/docs/docs/guides/tracking/tracing.mdx index 354d804be60..fbdf6bea96f 100644 --- a/docs/docs/guides/tracking/tracing.mdx +++ b/docs/docs/guides/tracking/tracing.mdx @@ -361,16 +361,16 @@ You can also manually create Calls using the API directly. import weave # Initialize Weave Tracing - weave.init('intro-example') + client = weave.init('intro-example') def my_function(name: str): # Start a call - call = weave.create_call(op="my_function", inputs={"name": name}) + call = client.create_call(op="my_function", inputs={"name": name}) # ... your function code ... # End a call - weave.finish_call(call, output="Hello, World!") + client.finish_call(call, output="Hello, World!") # Call your function print(my_function("World")) diff --git a/docs/sidebars.ts b/docs/sidebars.ts index ede80ed6c50..fa2f7f80d32 100644 --- a/docs/sidebars.ts +++ b/docs/sidebars.ts @@ -67,6 +67,7 @@ const sidebars: SidebarsConfig = { "guides/core-types/datasets", "guides/tracking/feedback", "guides/tracking/costs", + "guides/tools/comparison", "guides/tools/playground", "guides/core-types/media", { diff --git a/pyproject.toml b/pyproject.toml index 2f3e4c93bab..d392d527b60 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -226,7 +226,7 @@ module = "weave_query.*" ignore_errors = true [tool.bumpversion] -current_version = "0.51.23-dev0" +current_version = "0.51.24-dev0" parse = """(?x) (?P0|[1-9]\\d*)\\. (?P0|[1-9]\\d*)\\. diff --git a/sdks/node/package-lock.json b/sdks/node/package-lock.json index 83fe5755ee6..bbd003cde05 100644 --- a/sdks/node/package-lock.json +++ b/sdks/node/package-lock.json @@ -1,12 +1,12 @@ { "name": "weave", - "version": "0.7.0", + "version": "0.7.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "weave", - "version": "0.7.0", + "version": "0.7.3", "license": "Apache-2.0", "dependencies": { "cli-progress": "^3.12.0", diff --git a/sdks/node/package.json b/sdks/node/package.json index f2f884f3dcd..00861420103 100644 --- a/sdks/node/package.json +++ b/sdks/node/package.json @@ -1,11 +1,19 @@ { "name": "weave", - "version": "0.7.0", + "version": "0.7.3", "description": "AI development toolkit", - "types": "dist/src/index.d.ts", - "main": "dist/src/index.js", + "types": "dist/index.d.ts", + "main": "dist/index.js", "type": "commonjs", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + }, "scripts": { + "build": "tsc --outDir dist", + "prepare": "npm run build", "test": "jest --silent", "test:coverage": "jest --coverage", "test:watch": "jest --watch", @@ -14,6 +22,9 @@ "generate-api": "swagger-typescript-api -p ./weave.openapi.json -o ./src/generated -n traceServerApi.ts", "dev": "nodemon" }, + "files": [ + "dist" + ], "repository": { "type": "git", "url": "https://github.com/wandb/weave/js" diff --git a/sdks/node/tsconfig.json b/sdks/node/tsconfig.json index f44dc0d2933..141908653c1 100644 --- a/sdks/node/tsconfig.json +++ b/sdks/node/tsconfig.json @@ -7,19 +7,28 @@ "sourceMap": true, "strict": true, "esModuleInterop": true, - "outDir": "./dist", + "outDir": "dist", "paths": { "weave": ["./src/index.ts"] - } + }, + "declaration": true, + "declarationMap": true, + "rootDir": "src", + "tsBuildInfoFile": "dist/.tsbuildinfo" }, "include": ["src/**/*"], - "exclude": ["src", "examples", "dist", "node_modules"], - "references": [ - { - "path": "./src/tsconfig.src.json" - }, - { - "path": "./examples/tsconfig.examples.json" - } + "exclude": [ + "examples", + "dist", + "node_modules", + "src/integrations/checkOpenai.ts" ] + // "references": [ + // { + // "path": "./src/tsconfig.src.json" + // }, + // { + // "path": "./examples/tsconfig.examples.json" + // } + // ] } diff --git a/tests/trace/test_exec.py b/tests/trace/test_exec.py index 117bfec18bc..bff1cf18f4d 100644 --- a/tests/trace/test_exec.py +++ b/tests/trace/test_exec.py @@ -101,7 +101,7 @@ def test_publish_works_for_code_with_no_source_file( ref = captured["ref"] op = ref.get() - actual_captured_code = op.art.path_contents["obj.py"].decode() + actual_captured_code = op.get_captured_code() expected_captured_code = expected_captured_code[1:] # ignore first newline assert actual_captured_code == expected_captured_code diff --git a/tests/trace/test_trace_settings.py b/tests/trace/test_trace_settings.py index bcbd27aeea8..7a4c0de4397 100644 --- a/tests/trace/test_trace_settings.py +++ b/tests/trace/test_trace_settings.py @@ -104,7 +104,7 @@ def test_func(): ref = weave.publish(test_func) test_func2 = ref.get() - code2 = test_func2.art.path_contents["obj.py"].decode() + code2 = test_func2.get_captured_code() assert "Code-capture was disabled" in code2 parse_and_apply_settings(UserSettings(capture_code=True)) @@ -117,7 +117,7 @@ def test_func(): ref2 = weave.publish(test_func) test_func3 = ref2.get() - code3 = test_func3.art.path_contents["obj.py"].decode() + code3 = test_func3.get_captured_code() assert "Code-capture was disabled" not in code3 @@ -130,7 +130,7 @@ def test_func(): ref = weave.publish(test_func) test_func2 = ref.get() - code2 = test_func2.art.path_contents["obj.py"].decode() + code2 = test_func2.get_captured_code() assert "Code-capture was disabled" in code2 os.environ["WEAVE_CAPTURE_CODE"] = "true" @@ -141,7 +141,7 @@ def test_func(): ref2 = weave.publish(test_func) test_func3 = ref2.get() - code3 = test_func3.art.path_contents["obj.py"].decode() + code3 = test_func3.get_captured_code() assert "Code-capture was disabled" not in code3 diff --git a/tests/trace/type_serializers/Audio/audio_test.py b/tests/trace/type_handlers/Audio/audio_test.py similarity index 100% rename from tests/trace/type_serializers/Audio/audio_test.py rename to tests/trace/type_handlers/Audio/audio_test.py diff --git a/tests/trace/type_serializers/Image/image_test.py b/tests/trace/type_handlers/Image/image_test.py similarity index 78% rename from tests/trace/type_serializers/Image/image_test.py rename to tests/trace/type_handlers/Image/image_test.py index 65a2c7b0ba7..dc99d6bf704 100644 --- a/tests/trace/type_serializers/Image/image_test.py +++ b/tests/trace/type_handlers/Image/image_test.py @@ -1,3 +1,4 @@ +import random from pathlib import Path import pytest @@ -130,3 +131,41 @@ def accept_image_jpg_pillow(val): assert res == "Image size: 100x100" finally: file_path.unlink() + + +@pytest.fixture +def dataset_ref(client): + # This fixture represents a saved dataset containing images + IMAGE_SIZE = (1024, 1024) + N_ROWS = 50 + + def make_random_image(): + random_colour = ( + random.randint(0, 255), + random.randint(0, 255), + random.randint(0, 255), + ) + return Image.new("RGB", IMAGE_SIZE, random_colour) + + rows = [{"img": make_random_image()} for _ in range(N_ROWS)] + dataset = weave.Dataset(rows=rows) + ref = weave.publish(dataset) + + return ref + + +@pytest.mark.asyncio +async def test_images_in_dataset_for_evaluation(client, dataset_ref): + dataset = dataset_ref.get() + evaluation = weave.Evaluation(dataset=dataset) + + @weave.op + def model(img: Image) -> dict[str, str]: + return {"result": "hello"} + + # Expect that evaluation works for a ref-get'd dataset containing images + res = await evaluation.evaluate(model) + + assert isinstance(res, dict) + assert "model_latency" in res and "mean" in res["model_latency"] + assert isinstance(res["model_latency"]["mean"], (int, float)) diff --git a/tests/trace_server/test_remote_http_trace_server.py b/tests/trace_server/test_remote_http_trace_server.py index 5358c19d129..5c1830e1c8e 100644 --- a/tests/trace_server/test_remote_http_trace_server.py +++ b/tests/trace_server/test_remote_http_trace_server.py @@ -42,7 +42,7 @@ def test_ok(self, mock_post): mock_post.assert_called_once() @patch("weave.trace_server.requests.post") - def test_400_500_no_retry(self, mock_post): + def test_400_no_retry(self, mock_post): call_id = generate_id() resp1 = requests.Response() resp1.json = lambda: dict( @@ -50,29 +50,25 @@ def test_400_500_no_retry(self, mock_post): ) resp1.status_code = 400 - resp2 = requests.Response() - resp2.status_code = 500 - mock_post.side_effect = [ resp1, - resp2, ] start = generate_start(call_id) with self.assertRaises(requests.HTTPError): self.server.call_start(tsi.CallStartReq(start=start)) - with self.assertRaises(requests.HTTPError): - self.server.call_start(tsi.CallStartReq(start=start)) - def test_invalid_no_retry(self): with self.assertRaises(ValidationError): self.server.call_start(tsi.CallStartReq(start={"invalid": "broken"})) @patch("weave.trace_server.requests.post") - def test_502_503_504_429_retry(self, mock_post): + def test_500_502_503_504_429_retry(self, mock_post): call_id = generate_id() + resp0 = requests.Response() + resp0.status_code = 500 + resp1 = requests.Response() resp1.status_code = 502 @@ -91,7 +87,7 @@ def test_502_503_504_429_retry(self, mock_post): ) resp5.status_code = 200 - mock_post.side_effect = [resp1, resp2, resp3, resp4, resp5] + mock_post.side_effect = [resp0, resp1, resp2, resp3, resp4, resp5] start = generate_start(call_id) self.server.call_start(tsi.CallStartReq(start=start)) diff --git a/weave-js/src/assets/icons/icon-automated-workspace.svg b/weave-js/src/assets/icons/icon-automated-workspace.svg new file mode 100644 index 00000000000..5faf9bba4de --- /dev/null +++ b/weave-js/src/assets/icons/icon-automated-workspace.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/weave-js/src/components/FancyPage/useProjectSidebar.ts b/weave-js/src/components/FancyPage/useProjectSidebar.ts index 5cd1190dbbe..19dce4215df 100644 --- a/weave-js/src/components/FancyPage/useProjectSidebar.ts +++ b/weave-js/src/components/FancyPage/useProjectSidebar.ts @@ -10,7 +10,8 @@ export const useProjectSidebar = ( hasModelsData: boolean, hasWeaveData: boolean, hasTraceBackend: boolean = true, - hasModelsAccess: boolean = true + hasModelsAccess: boolean = true, + isLaunchActive: boolean = false ): FancyPageSidebarItem[] => { // Should show models sidebar items if we have models data or if we don't have a trace backend let showModelsSidebarItems = hasModelsData || !hasTraceBackend; @@ -41,6 +42,13 @@ export const useProjectSidebar = ( label: 'Models', isShown: isShowAll, }, + { + type: 'button' as const, + name: 'Overview', + slug: 'overview', + isShown: isModelsOnly, + iconName: IconNames.Info, + }, { type: 'button' as const, name: 'Workspace', @@ -61,7 +69,7 @@ export const useProjectSidebar = ( type: 'button' as const, name: 'Jobs', slug: 'jobs', - isShown: isModelsOnly, + isShown: isModelsOnly && isLaunchActive, isDisabled: viewingRestricted, iconName: IconNames.FlashBolt, }, @@ -98,13 +106,6 @@ export const useProjectSidebar = ( iconName: IconNames.VersionsLayers, isDisabled: viewingRestricted, }, - { - type: 'button' as const, - name: 'Overview', - slug: 'overview', - isShown: isModelsOnly, - iconName: IconNames.Info, - }, { type: 'menuPlaceholder' as const, isShown: isShowAll, @@ -250,5 +251,6 @@ export const useProjectSidebar = ( viewingRestricted, isModelsOnly, showWeaveSidebarItems, + isLaunchActive, ]); }; diff --git a/weave-js/src/components/Icon/Icon.tsx b/weave-js/src/components/Icon/Icon.tsx index c1c07c7df01..a87f41dfe56 100644 --- a/weave-js/src/components/Icon/Icon.tsx +++ b/weave-js/src/components/Icon/Icon.tsx @@ -8,6 +8,7 @@ import {ReactComponent as ImportAmazonSagemaker} from '../../assets/icons/icon-a import {ReactComponent as ImportArea} from '../../assets/icons/icon-area.svg'; import {ReactComponent as ImportArtifactTypeAlt} from '../../assets/icons/icon-artifact-type-alt.svg'; import {ReactComponent as ImportAudioVolume} from '../../assets/icons/icon-audio-volume.svg'; +import {ReactComponent as ImportAutomatedWorkspace} from '../../assets/icons/icon-automated-workspace.svg'; import {ReactComponent as ImportAutomationRobotArm} from '../../assets/icons/icon-automation-robot-arm.svg'; import {ReactComponent as ImportBack} from '../../assets/icons/icon-back.svg'; import {ReactComponent as ImportBaselineAlt} from '../../assets/icons/icon-baseline-alt.svg'; @@ -298,6 +299,9 @@ export const IconArtifactTypeAlt = (props: SVGIconProps) => ( export const IconAudioVolume = (props: SVGIconProps) => ( ); +export const IconAutomatedWorkspace = (props: SVGIconProps) => ( + +); export const IconAutomationRobotArm = (props: SVGIconProps) => ( ); @@ -1064,6 +1068,7 @@ const ICON_NAME_TO_ICON: Record = { area: IconArea, 'artifact-type-alt': IconArtifactTypeAlt, 'audio-volume': IconAudioVolume, + 'automated-workspace': IconAutomatedWorkspace, 'automation-robot-arm': IconAutomationRobotArm, back: IconBack, 'baseline-alt': IconBaselineAlt, diff --git a/weave-js/src/components/Icon/index.ts b/weave-js/src/components/Icon/index.ts index 98a0208b8d2..aa92f74b31a 100644 --- a/weave-js/src/components/Icon/index.ts +++ b/weave-js/src/components/Icon/index.ts @@ -8,6 +8,7 @@ export { IconArea, IconArtifactTypeAlt, IconAudioVolume, + IconAutomatedWorkspace, IconAutomationRobotArm, IconBack, IconBaselineAlt, diff --git a/weave-js/src/components/Icon/types.ts b/weave-js/src/components/Icon/types.ts index 142dd8f562a..8002b47eb9c 100644 --- a/weave-js/src/components/Icon/types.ts +++ b/weave-js/src/components/Icon/types.ts @@ -7,6 +7,7 @@ export const IconNames = { Area: 'area', ArtifactTypeAlt: 'artifact-type-alt', AudioVolume: 'audio-volume', + AutomatedWorkspace: 'automated-workspace', AutomationRobotArm: 'automation-robot-arm', Back: 'back', BaselineAlt: 'baseline-alt', diff --git a/weave-js/src/components/PagePanelComponents/Home/Browse3/SideNav.tsx b/weave-js/src/components/PagePanelComponents/Home/Browse3/SideNav.tsx deleted file mode 100644 index 75945264d97..00000000000 --- a/weave-js/src/components/PagePanelComponents/Home/Browse3/SideNav.tsx +++ /dev/null @@ -1,128 +0,0 @@ -import {IconNames} from '@wandb/weave/components/Icon'; -import _ from 'lodash'; -import React, {useMemo} from 'react'; -import {useParams} from 'react-router-dom'; - -import {useWeaveflowRouteContext} from './context'; -import {useEvaluationsFilter} from './pages/CallsPage/evaluationsFilter'; -import {useURLSearchParamsDict} from './pages/util'; -import {Sidebar, SidebarItem} from './Sidebar'; - -export const SideNav = () => { - const params = useParams<{ - entity: string; - project: string; - tab: - | 'types' - | 'type-versions' - | 'objects' - | 'object-versions' - | 'ops' - | 'op-versions' - | 'calls' - | 'boards' - | 'tables'; - }>(); - const {entity, project} = params; - const currentProject = project; - const currentEntity = entity; - const query = useURLSearchParamsDict(); - const filters = useMemo(() => { - if (query.filter === undefined) { - return {}; - } - try { - return JSON.parse(query.filter); - } catch (e) { - console.log(e); - return {}; - } - }, [query.filter]); - - const evaluationsFilter = useEvaluationsFilter(currentEntity, currentProject); - - const selectedItemId = useMemo(() => { - const category = Object.keys(filters).find(key => - key.includes('baseObjectClass') - ); - let filterCategory; - if (category !== undefined) { - filterCategory = filters[category]; - } - - if (params.tab === 'types' || params.tab === 'type-versions') { - return 'types'; - } else if (params.tab === 'objects' || params.tab === 'object-versions') { - if (filterCategory === 'Model') { - return 'models'; - } else if (filterCategory === 'Dataset') { - return 'datasets'; - } - return 'objects'; - } else if (params.tab === 'ops' || params.tab === 'op-versions') { - return 'ops'; - } else if (params.tab === 'calls') { - if (_.isEqual(filters, evaluationsFilter)) { - return 'evaluation'; - } - return 'calls'; - } - return null; - }, [evaluationsFilter, filters, params.tab]); - - const {baseRouter} = useWeaveflowRouteContext(); - if (!currentProject || !currentEntity) { - return null; - } - - const items: SidebarItem[][] = [ - [ - { - id: 'evaluation', - name: 'Evaluations', - iconName: IconNames.TypeBoolean, - path: baseRouter.callsUIUrl(entity, project, evaluationsFilter), - }, - { - id: 'models', - name: 'Models', - iconName: IconNames.Model, - path: baseRouter.objectVersionsUIUrl(entity, project, { - baseObjectClass: 'Model', - }), - }, - { - id: 'datasets', - name: 'Datasets', - iconName: IconNames.Table, - path: baseRouter.objectVersionsUIUrl(entity, project, { - baseObjectClass: 'Dataset', - }), - }, - ], - [ - { - id: 'calls', - name: 'Traces', - iconName: IconNames.LayoutTabs, - path: baseRouter.callsUIUrl(entity, project, { - traceRootsOnly: true, - }), - }, - { - id: 'ops', - name: 'Operations', - iconName: IconNames.JobProgramCode, - path: baseRouter.opVersionsUIUrl(entity, project, {}), - }, - { - id: 'objects', - name: 'Objects', - iconName: IconNames.CubeContainer, - path: baseRouter.objectVersionsUIUrl(entity, project, {}), - }, - ], - ]; - - return ; -}; diff --git a/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/EmojiDetails.tsx b/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/EmojiDetails.tsx index cc67d7e6380..e018fe28c17 100644 --- a/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/EmojiDetails.tsx +++ b/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/EmojiDetails.tsx @@ -63,7 +63,7 @@ export const EmojiDetails = ({ return (
-
{emoji}
+
{emoji}
{Object.entries(groupedByAlias).map(([alias, aliasReactions]) => { // TODO (Tim): After https://github.com/wandb/core/pull/22947 is deployed, // change the fallback from `r.wb_user_id` to `null`-like (this means no access) diff --git a/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/FeedbackGridInner.tsx b/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/FeedbackGridInner.tsx index 5a47b8d1bd2..15a4bad2262 100644 --- a/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/FeedbackGridInner.tsx +++ b/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/FeedbackGridInner.tsx @@ -40,7 +40,9 @@ export const FeedbackGridInner = ({ return ; } if (params.row.feedback_type === 'wandb.reaction.1') { - return params.row.payload.emoji; + return ( + {params.row.payload.emoji} + ); } if (params.row.feedback_type.startsWith('wandb.annotation.')) { return ( diff --git a/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/StructuredFeedback/FeedbackSidebar.tsx b/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/StructuredFeedback/FeedbackSidebar.tsx index 2e09a3516f7..ef6bcbd69ff 100644 --- a/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/StructuredFeedback/FeedbackSidebar.tsx +++ b/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/StructuredFeedback/FeedbackSidebar.tsx @@ -3,7 +3,6 @@ import {useOrgName} from '@wandb/weave/common/hooks/useOrganization'; import {useViewerInfo} from '@wandb/weave/common/hooks/useViewerInfo'; import {useViewerUserInfo2} from '@wandb/weave/common/hooks/useViewerUserInfo'; import {Button} from '@wandb/weave/components/Button'; -import {Icon} from '@wandb/weave/components/Icon'; import {Loading} from '@wandb/weave/components/Loading'; import {annotationsViewed} from '@wandb/weave/integrations/analytics/viewEvents'; import {makeRefCall} from '@wandb/weave/util/refs'; @@ -93,22 +92,25 @@ export const FeedbackSidebar = ({ return (
-
+
Feedback
+
{humanAnnotationSpecs.length > 0 ? ( <> -
- + + (a.name ?? '').localeCompare(b.name ?? '') + )} setUnsavedFeedbackChanges={setUnsavedFeedbackChanges} />
-
+
- ); -}; - type HumanAnnotationInputsProps = { entity: string; project: string; @@ -254,7 +175,7 @@ const HumanAnnotationInputs = ({
{field.name}
{field.description && ( -
+
{field.description}
)} @@ -275,11 +196,3 @@ const HumanAnnotationInputs = ({
); }; - -const DisplayNumericCounter = ({count}: {count: number}) => { - return ( -
- {count} -
- ); -}; diff --git a/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/StructuredFeedback/HumanAnnotation.tsx b/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/StructuredFeedback/HumanAnnotation.tsx index eadcd2abe1d..7facffe9556 100644 --- a/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/StructuredFeedback/HumanAnnotation.tsx +++ b/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/StructuredFeedback/HumanAnnotation.tsx @@ -1,7 +1,6 @@ -import {Autocomplete, TextField as MuiTextField} from '@mui/material'; import {toast} from '@wandb/weave/common/components/elements/Toast'; -import {MOON_300} from '@wandb/weave/common/css/color.styles'; import {Button} from '@wandb/weave/components/Button'; +import {Select} from '@wandb/weave/components/Form/Select'; import {TextField} from '@wandb/weave/components/Form/TextField'; import {LoadingDots} from '@wandb/weave/components/LoadingDots'; import {Tailwind} from '@wandb/weave/components/Tailwind'; @@ -413,11 +412,11 @@ export const TextFeedbackColumn = ({ value={value} onChange={onValueChange} maxLength={maxLength} - placeholder="..." + placeholder="" /> {maxLength && (
- {`character max: ${maxLength}`} + {`Maximum characters: ${maxLength}`}
)}
@@ -445,78 +444,30 @@ export const EnumFeedbackColumn = ({ label: option, value: option, })); - opts.splice(0, 0, {label: '', value: ''}); return opts; }, [options]); - - const [value, setValue] = useState