Ah, sorry if my answer was confusing! The rel.manual
recipe definitely includes some more complex logic and you can check it out in the recipes/rel.py
in your Prodigy installation. (Run prodigy stats
to find the exact path.) So if you just quickly want to try it out the hacky way, you can also just edit this file in your Prodigy installation.
If you want a standalone recipe, you don't necessarily have to implement or copy the whole functionality. A recipe is just a Python function that returns a dictionary of components – so you can also just call a built-in recipe as a function in your own custom recipe.
Here's an example – I just copy-pasted all arguments and argument annotations you can see how it all fits together Of course don't have to set or overwrite all of them. You can make your custom recipe only take the arguments that it needs and that you want to set on the CLI.
from typing import List, Optional, Union, Iterable, Dict, Any
import prodigy
from prodigy.recipes.rel import manual as rel_manual
@recipe(
"custom.rel.manual",
dataset=("Dataset to save annotations to", "positional", None, str),
spacy_model=("Loadable spaCy model or blank:lang (e.g. blank:en)", "positional", None, str),
source=("Data to annotate (file path or '-' to read from standard input)", "positional", None, str),
loader=("Loader (guessed from file extension if not set)", "option", "lo", str),
label=("Comma-separated relation label(s) to annotate or text file with one label per line", "option", "l", get_labels),
span_label=("Comma-separated span label(s) to annotate or text file with one label per line", "option", "sl", get_labels),
patterns=("Patterns file for defining custom spans to be added", "option", "pt", str),
disable_patterns=("Patterns file for defining tokens to disable (make unselectable)", "option", "dpt", str),
add_ents=("Add entities predicted by the model", "flag", "AE", bool),
add_nps=("Add noun phrases (if noun chunks rules are available), based on tagger and parser", "flag", "AN"),
wrap=("Wrap lines in the UI by default (instead of showing tokens in one row)", "flag", "W", bool),
exclude=("Comma-separated list of dataset IDs whose annotations to exclude", "option", "e", split_string),
hide_arrow_heads=("Hide the arrow heads visually", "option", "HA", bool),
)
def custom_rel_manual(
dataset: str,
spacy_model: str,
source: Union[str, Iterable[dict]] = "-",
loader: Optional[str] = None,
label: Optional[List[str]] = None,
span_label: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
patterns: Optional[Union[str, List]] = None,
disable_patterns: Optional[Union[str, List]] = None,
add_ents: bool = False,
add_nps: bool = False,
wrap: bool = False,
hide_arrow_heads: bool = False,
) -> Dict[str, Any]:
def custom_rel_manual():
components = rel_manual(
dataset=dataset,
spacy_model=spacy_model,
source=source,
loader=loader,
label=label,
span_label=span_label,
exclude=exclude,
patterns=patterns,
disable_patterns=disable_patterns,
add_ents=add_ents,
add_nps=add_nps,
wrap=wrap,
hide_arrow_heads=hide_arrow_heads,
)
# Add callback to the components returned by the recipe
components["validate_answer"] = validate_answer
return components