microsoft / TaskWeaver

A code-first agent framework for seamlessly planning and executing data analytics tasks.
https://microsoft.github.io/TaskWeaver/
MIT License
5.38k stars 689 forks source link

Plugins fail to register: "Can't mix strings and bytes in path components" #216

Closed twtester2 closed 9 months ago

twtester2 commented 9 months ago

Describe the bug Code execution fails because plugin fails to register when including multiple plugins. Including only a single plugin works, but when both are included, the following error message is output:

Plugin umap_transform failed to load: Plugin umap_transform failed to register: failed to load plugin umap_transform Can't mix strings and bytes in path components

To Reproduce Steps to reproduce the behavior:

  1. Minimal example has two plugins:

Example yaml:

pca_transform
enabled: true
required: false
plugin_only: true
description: >-
  perform PCA transform on data and return the transformed data
examples: |-
  result = pca_transform(n_components=3)... etc
umap_transform
enabled: true
required: false
plugin_only: true
description: >-
  perform UMAP transform on data and return the transformed data
examples: |-
  result = umap_transform(n_components=3)... etc

Expected behavior

  1. Including only PCA .py and .yaml in project/plugins correctly loads and calls in response to query.
  2. Including only UMAP .py and .yaml correctly loads and calls in response to query
  3. Including both plugins should correctly load and call in response to query

Screenshots

image

Environment Information (please complete the following information):

Additional context Tried deleting logs and past sessions Tried other examples of plugins that had been working previously. Taskweaver only appears to be able to recognize a single plugin

liqul commented 9 months ago

The error suggests that the implementation of that plugin has syntax error. Take a look at the FAQ here

twtester2 commented 9 months ago

Simplified the plugin to attempt debugging. Syntax appears to match instructions in FAQ: `name: umap_transform enabled: true required: false plugin_only: true description: >- Call the endpoint to perform UMAP transform on IRIS data and return the transformed data examples: |- result = umap_transform(n_components=2)

parameters:

returns:

`from taskweaver.plugin import Plugin, register_plugin

@register_plugin class UMAPTransformPlugin(Plugin): def call(self, n_components: int):

    return 1`

Still getting: Plugin umap_transform failed to load: Plugin umap_transform failed to register: failed to load plugin umap_transform Can't mix strings and bytes in path components

liqul commented 9 months ago

Simplified the plugin to attempt debugging. Syntax appears to match instructions in FAQ: `name: umap_transform enabled: true required: false plugin_only: true description: >- Call the endpoint to perform UMAP transform on IRIS data and return the transformed data examples: |- result = umap_transform(n_components=2)

parameters:

  • name: n_components type: int required: true description: the number of principal components

returns:

  • name: result type: int description: the transformed data`

`from taskweaver.plugin import Plugin, register_plugin

@register_plugin class UMAPTransformPlugin(Plugin): def call(self, n_components: int):

    return 1`

Still getting: Plugin umap_transform failed to load: Plugin umap_transform failed to register: failed to load plugin umap_transform Can't mix strings and bytes in path components

I mean the syntax of your python implementation should contain errors.

twtester2 commented 9 months ago

Liqul, thank you for getting back to me on the issue so quickly, and thanks for your work on TaskWeaver.

I was able to trace the issue to line 63 in TaskWeaver/taskweaver/ces/runtime/executor.py:

module_path = os.path.join(temp_dir, f"{self.name}.py") The error was raised because temp_dir was in bytes and f"{self.name}.py" was a string. I resolved the issue by changing the lines to:

try:
    data = temp_dir.decode("utf-8")
except (UnicodeDecodeError, AttributeError):
    data = temp_dir
module_path = os.path.join(data, f"{self.name}.py")

The plugins now load correctly and I believe the issue is resolved. Maybe happened because I am developing on Windows? Adding an appropriate revision to your framework may be worth considering.

Best regards, twtester2

liqul commented 9 months ago

Liqul, thank you for getting back to me on the issue so quickly, and thanks for your work on TaskWeaver.

I was able to trace the issue to line 63 in TaskWeaver/taskweaver/ces/runtime/executor.py:

module_path = os.path.join(temp_dir, f"{self.name}.py") The error was raised because temp_dir was in bytes and f"{self.name}.py" was a string. I resolved the issue by changing the lines to:

try:
    data = temp_dir.decode("utf-8")
except (UnicodeDecodeError, AttributeError):
    data = temp_dir
module_path = os.path.join(data, f"{self.name}.py")

The plugins now load correctly and I believe the issue is resolved. Maybe happened because I am developing on Windows? Adding an appropriate revision to your framework may be worth considering.

Best regards, twtester2

Thanks for your help in tracing this issue. We haven't seen it before and my guess would be due to an environment issue. I don't know the root cause, but since we also develop on Windows and so it should not be a problem. We will add a fix to this issue by wrapping the temp_dir with something like str().