html_template doesn't work

Hi all,
I am not able to apply custom HTML template to my recipe. It doesn't show anything apart from metadata.
Please help

from typing import List, Optional
import prodigy
from prodigy.components.loaders import JSONL
from prodigy.util import split_string

# Helper functions for adding user provided labels to annotation tasks.
def add_label_options_to_stream(stream, labels):
    options = [{"id": label, "text": label} for label in labels]
    for task in stream:
        task["options"] = options
        yield task

# Recipe decorator with argument annotations: (description, argument type,
# shortcut, type / converter function called on value before it's passed to
# the function). Descriptions are also shown when typing --help.
    dataset=("The dataset to use", "positional", None, str),
    source=("The source data as a JSONL file", "positional", None, str),
    label=("One or more comma-separated labels", "option", "l", split_string),
    exclusive=("Treat classes as mutually exclusive", "flag", "E", bool),
    exclude=("Names of datasets to exclude", "option", "e", split_string),
def memt_manual(
    dataset: str,
    source: str,
    label: Optional[List[str]] = None,
    exclusive: bool = False,
    exclude: Optional[List[str]] = None,
    Manually annotate categories that apply to a text. If more than one label
    is specified, categories are added as multiple choice options. If the
    --exclusive flag is set, categories become mutually exclusive, meaning that
    only one can be selected during annotation.

    # Load the stream from a JSONL file and return a generator that yields a
    # dictionary for each example in the data.
    stream = JSONL(source)

    #Add labels to each task in stream
    stream = add_label_options_to_stream(stream, label)

    return {
        "view_id": "html",  # Annotation interface to use
        "dataset": dataset,  # Name of dataset to save annotations
        "stream": stream,  # Incoming stream of examples
        "config": {  # Additional config settings, mostly for app UI
            "exclude_by": "task", # Hash value used to filter out already seen examples
            "choice_style": "single",
            "force_stream_order": True,
            "validate": False,
            "batch_size": 10,
            "html_template": "<h2>{{ text }}</h2><strong>{{ meta.source }}</strong>"

{"text": "target 1, s1", "meta": {"source": "source 1"}}

prodigy memt.manual eval_user data.jsonl --label FPE+LPE,"LPE only",None -F

What I get:

hi @zparcheta!

Thanks for your question (and your extremely helpful reproducible example! :pray:)

That's interesting.

I was able to run it fine :thinking:

python -m prodigy memt.manual eval_user data/data.jsonl --label FPE+LPE,"LPE only",None -F scripts/

Can you right click your browser (if you're using Chrome), select "Inspect", then go to the Console tab to look for any errors?

By the way, unrelated to html_template, I'd recommend you replace stream = JSONL(source) with stream = get_stream( source, rehash=True, dedup=True, input_key="text" ) (you'll also need to replace the JSONL call with from prodigy.components.loaders import get_stream at the top too).

Our built-in recipes use get_stream (see the docs) which provide the hashing/deduplication. Since you added "exclude_by": "task" (which is the default), you may be getting a console warning message because without it (or set_hashes, which get_stream uses), it can't do any of the dedup that you'd expect. We'll work on improving this as I suspect you saw this in our prodigy-recipes repo.

1 Like

Thank you for the hints. I will change it. I also confirm that in the console there are no errors. May it be some problem with prodigy.json?

  "theme": "basic",
  "custom_theme": {},
  "buttons": ["undo"],
  "batch_size": 10,
  "history_size": 10,
  "port": 8880,
  "host": "xxxxxxxxx",
  "cors": true,
  "db": "postgresql",
  "db_settings": {
    "postgresql": {
      "dbname": "prodigy",
      "user": "prodigy",
      "password": "xxxxxxxxxxxx"
  "validate": true,
  "auto_exclude_current": false,
  "choice_auto_accept": true,
  "feed_overlap": false,
  "auto_exclude_current": false,
  "instant_submit": false,
  "feed_overlap": false,
  "auto_count_stream": false,
  "total_examples_target": 0,
  "ui_lang": "en",
  "project_info": ["dataset", "session", "lang", "recipe_name", "view_id", "label"],
  "show_stats": true,
  "hide_meta": false,
  "show_flag": false,
  "instructions": false,
  "swipe": false,
  "swipe_gestures": { "left": "accept", "right": "reject" },
  "split_sents_threshold": false,
  "html_template": false,
  "global_css": null,
  "javascript": null,
  "writing_dir": "ltr",
  "show_whitespace": false,
  "exclude_by": "task"

Ok, definitely it was a problem of the config :sweat_smile:
I just put all default parameters and it worked.
Thank you for trying the code!

1 Like

Excellent! By the way, I edited your earlier post to remove what may have been sensitive info in your config :slight_smile:

1 Like