Skip to content

MachineLearningScorer: metric list is double-encoded into one string #6790

Description

@kz930

What happened?

MachineLearningScorerOpDesc.getSelectedMetrics() returns the chosen metric names as one comma-separated, already-quoted fragment, and its return type is EncodableString:

common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/machineLearning/Scorer/MachineLearningScorerOpDesc.scala

private def getSelectedMetrics(): EncodableString = {
  val metric = if (isRegression) regressionMetrics else classificationMetrics
  metric.map(metric => getMetricName(metric)).mkString("'", "','", "'")   // -> 'Accuracy','F1 Score'
}

It is spliced into the generated Python as a list:

metric_list = [${getSelectedMetrics()}]

Because the value is an EncodableString, the Python template builder re-encodes the whole fragment as one Python string value (rendered via self.decode_python_template(...)) instead of splicing it verbatim. The generated code becomes:

metric_list = ["'Accuracy','F1 Score'"]   # ONE element: the literal string, incl. inner quotes

instead of the intended:

metric_list = ['Accuracy', 'F1 Score']

So every downstream if 'X' in metric_list and for metric in metric_list / metrics_func[metric] operates on that single malformed element — the selected metrics are never matched, and the classification path hits a KeyError on the bogus key. The Scorer produces wrong/empty output for both the classification and regression paths.

Expected: metric_list is a proper list of metric names and each selected metric is computed.

How to reproduce?

A — user-facing: Add a Machine Learning Scorer operator, select one or more metrics (e.g. Accuracy, F1 Score), give it prediction/label columns, and run. The selected metrics are not computed correctly (empty result / KeyError).

B — confirmed against main's operator directly: construct MachineLearningScorerOpDesc with isRegression = false and classificationMetrics = List(accuracy, f1Score), then call generatePythonCode(). The emitted line is:

metric_list = [self.decode_python_template('J0FjY3VyYWN5JywnRjEgU2NvcmUn')]

The base64 J0FjY3VyYWN5JywnRjEgU2NvcmUn decodes to 'Accuracy','F1 Score' — i.e. the entire quoted list collapses into a single decoded string element, so metric_list has one malformed entry rather than two metric names.

Proposed fix: change getSelectedMetrics()'s return type from EncodableString to plain String, so the builder splices it verbatim into metric_list = ['Accuracy','F1 Score']. The method body is unchanged.

Version/Branch

1.3.0-incubating-SNAPSHOT (main)

Commit Hash (Optional)

No response

What browsers are you seeing the problem on?

No response

Relevant log output

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions