Skip to content

CLI and getting spans directly from a prodigy or a spaCy model #49

Description

@ivyleavedtoadflax

This is following on from our discussion in #48.

First off, I think the default CLI should be a very simple wrapper for the Evaluate class, so it doesn't need to be much more complicated than (note I didn't test any of this):

./nervaluate/cli.py:

import typer

from nervaluate import Evaluator

app = typer.Typer()

app.command()
def evaluate(
    true_path: str = typer.Argument(help="Path to true entity labels"),
    pred_path: str = typer.Argument(help="Path to predicted entity labels"),
    tags: str = typer.Argument(
        None, help="Comma separated list of tags to include in the evaluation"
    ),
    loader: str = typer.Option(
        None,
        help="Optional loader when not using prodigy style spans. One of [list, conll]",
    ),
    by_tag: bool = typer.Option(
        None,
        help="If set, will return tag level results instead of aggregated results.",
    ),
    pretty: bool = typer.Option(
        None,
        help="If set, will print the results in a pretty format instead of returning the raw json",
    ),
):

    tags_list = tags.split(",")
    evaluator = Evaluator(true_path, pred_path, tags=tags_list, loader=loader)

    results, results_by_tag = evaluator.evaluate()

    if by_tag:
        output = results_by_tag
    else:
        output = results

    if pretty:
        pass
        # Some code from wasabi to print a pretty table https://pypi.org/project/wasabi/
    else:
        return output


if __name__ == "__main__":
    app()

For handling predictions directly from a spacy/prodigy model, I think we should implement a typer command that does what @Eleni170 implemented in f2841e2. So it would be something like:

@app.command()
def predict(
    model_path: str=typer.Argument(help="Path to spaCy model"),
    data_path: str=typer.Argument(
        help="Path to data in prodigy format (including the raw text)"
    ), 
    by_tag: bool = typer.Option(
        None,
        help="If set, will return tag level results instead of aggregated results.",
    ),
    pretty: bool = typer.Option(
        None,
        help="If set, will print the results in a pretty format instead of returning the raw json",
    ),
):
    spacy_model = spacy.load(model_path)

    true = []
    pred = []
    tags = {}

    with open(data_path) as f:
        for line in f:
            pattern = json.loads(line)
            text = pattern["text"]
            meta = pattern["meta"]
            labels = check_labels(meta)
            for label in labels:
                tags[label] = ''
            true.append(meta)
            doc = spacy_model(text)
            pred.append(create_prodigy_spans(doc))

    # Maybe we want also to pass tags to the CLI as above but default to all tags as below if nothing is passed.

    evaluator = Evaluator(true, pred, tags=list(tags.keys()))
    global_results, aggregation_results = evaluator.evaluate()

# Similar logic as above to print results to console either as raw json or pretty printed.

Let me know what you think! @Eleni170 @nsorros

Metadata

Metadata

Labels

questionFurther information is requested

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions