hankcs/HanLP · error · RuntimeError

output ({}) must be of type bool or str

Error message

output ({}) must be of type bool or str

What it means

build_criterion on Word2VecEmbedding always raises NotImplementedError because a static pretrained embedding has no loss function. Loss/criterion construction only makes sense for trainable task components in HanLP's Component API.

Source

Thrown at hanlp/common/keras_component.py:73

            name = 'evaluate'
        if save_dir and not logger:
            logger = init_logger(name=name, root_dir=save_dir, level=logging.INFO if verbose else logging.WARN,
                                 mode='w')
        tst_data = self.transform.file_to_dataset(input_path, batch_size=batch_size)
        samples = self.num_samples_in(tst_data)
        num_batches = math.ceil(samples / batch_size)
        if warm_up:
            for x, y in tst_data:
                self.model.predict_on_batch(x)
                break
        if output:
            assert save_dir, 'Must pass save_dir in order to output'
            if isinstance(output, bool):
                output = os.path.join(save_dir, name) + '.predict' + ext
            elif isinstance(output, str):
                output = output
            else:
                raise RuntimeError('output ({}) must be of type bool or str'.format(repr(output)))
        timer = Timer()
        eval_outputs = self.evaluate_dataset(tst_data, callbacks, output, num_batches, **kwargs)
        loss, score, output = eval_outputs[0], eval_outputs[1], eval_outputs[2]
        delta_time = timer.stop()
        speed = samples / delta_time.delta_seconds

        if logger:
            f1: IOBES_F1_TF = None
            for metric in self.model.metrics:
                if isinstance(metric, IOBES_F1_TF):
                    f1 = metric
                    break
            extra_report = ''
            if f1:
                overall, by_type, extra_report = f1.state.result(full=True, verbose=False)
                extra_report = ' \n' + extra_report
            logger.info('Evaluation results for {} - '
                        'loss: {:.4f} - {} - speed: {:.2f} sample/sec{}'

View on GitHub (pinned to ddb1299bdd)

Solutions

  1. Train a task component and use Word2VecEmbedding as its embedding layer
  2. Skip criterion-building for embedding modules (check isinstance before calling)
  3. Override build_criterion in a subclass if custom behavior is required
Defensive patterns

Strategy: type-guard

Validate before calling

assert not isinstance(model, Word2VecEmbedding), 'build_criterion unsupported for embeddings'

Type guard

def supports_criterion(c) -> bool:
    return c.__class__.build_criterion is not Word2VecEmbedding.build_criterion

Try / catch

try:
    criterion = model.build_criterion()
except NotImplementedError:
    criterion = None  # inference-only component

Prevention

When it happens

Trigger: Any code path that calls build_criterion on a Word2VecEmbedding, e.g. a generic trainer iterating over components and unconditionally building criteria, or calling .fit() on the embedding.

Common situations: Running a generic training pipeline over a config whose model is only an embedding; migrating training code from a task model to a pure embedding module.

Related errors


AI-assisted analysis of hankcs/HanLP@ddb1299bdd (2026-08-27). Data as JSON: /api/errors/402d569ba5bf9de3. Report an issue: GitHub.