Updating meta data location in multi-label text annotation UI, using html_template.

Hi Innes,

I am trying html_template to show my meta data (title, source, url) in the top section, and then follows the text and labels.

  "theme": "basic",
  "custom_theme": {"largeText":18,"mediumText":16,"smallText":14,"cardMinWidth":300,"cardMaxWidth":1400,"cardMinHeight":200,"buttonSize":50,"relationHeight":130,"relationHeightWrap":40},
  "html_template": "<h2>{{meta.title}}</h2><strong>{{meta.URL}}</strong><small>{{meta.domain}}</small><p>{{text}}</p><br />"
  "buttons": ["accept","undo"],
  "batch_size": 8,
  "history_size": 8,
  "port": 7474,
  "host": "*",
  "cors": true,
  "db": "sqlite",
  "db_settings": {},
  "api_keys": {},
  "validate": true,
  "auto_exclude_current": true,
  "instant_submit": false,
  "feed_overlap": false,
  "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,
  "global_css": null,
  "javascript": null,
  "writing_dir": "ltr",
  "show_whitespace": false

However, html_template is not accepted by the annotation UI.

Could you please help?

Adding screen-shots.

Hi! The html_template is only applied if the UI content is displayed as HTML.

One option for this is to use a custom interface with two blocks (html and choice). If you're using a built-in recipe like textcat.manual, you can also "trick" Prodigy into rendering the main content as HTML by adding a key "html": "" to your data. If a key "html" is present, the main content of the choice UI is rendered as HTML and your html_template will be applied.

Hi Ines!

Thanks for the quick reply.

However, even after adding "html": "" key to the input data, there is no change in UI.
and html template as:


In other ways around, I tried custom recipe with blocks.

import prodigy
from prodigy.components.loaders import JSONL
    dataset=("The dataset to save to", "positional", None, str),
    file_path=("Path to texts", "positional", None, str),
def article_cat(dataset, file_path):
    """Annotate the sentiment of texts using different mood options."""
    stream = JSONL(file_path)     # load in the JSONL file
    stream = add_options(stream)  # add options to each task
    blocks = [
        {"view_id": "html"},
        {"view_id": "text"},
        {"view_id": "choice", "text": None}
    return {
        "dataset": dataset,   # save annotations in this dataset
        "view_id": "blocks",   # set the view_id to "blocks"
        "stream": stream,
        "config": {
            "blocks": blocks         # add the blocks to the config
            "html_template": "<h2>{{ meta.title }}</h2><strong>{{ meta.URL }}</strong><small>{{ meta.domain }}</small>"
def add_options(stream):
    # Helper function to add options to every task in a stream
    options = [
        {"id": "1", "text": "C"},
        {"id": "2", "text": "T"},
        {"id": "3", "text": "CC"},
        {"id": "4", "text": "CD"},
    for task in stream:
        task["options"] = options
        yield task

Still this also did not render the html.

Are you sure you're adding a key "html" to your data in your custom recipe? If there's a key html, the html block should render whatever is in it, or use the `html_template if it's available. What's the output you see in the UI when you run your custom recipe?

(Btw, you can format code by wrapping it in 3 backticks: ``` – this makes it a bit easier to read and prevents Markdown formatting. I edited your post above accordingly so I could read the code better.)

I have already added "html" key to the data:

{"html":"","text": "xyz", "meta": {"url": "fghhh", "domain": "scre.com", "title": "Colm", "source": "hub"}}

and tried both the ways:

  1. including "html_template" in custom recipy and using it.
  2. including "html_template" in prodigy.json with textcat.manual

"html_template": "<h2>{{ meta.title }}</h2><strong>{{ meta.URL }}</strong><small>{{ meta.domain }}</small>

I just tried it with the blocks recipe you posted above and the example JSON and for me, the result looks like this, which seems correct: