Repository: skit-ai/dialogy (language: python)

Issue:
ListEntityPlugin doesn't parse regex entities
**Describe the bug**
Entities are not created even if the pattern matches.

**To Reproduce**
Steps to reproduce the behavior:
1. Setup the plugin with `candidates`, `entity_map` and `style` as "regex"
2. Add the plugin to a Workflow, I used the `XLMRWorkflow`
3. `XLMRWorkflow.run(...)` doesn't create the entity, even if pattern matches.

**Expected behavior**
Custom or pre-defined entities should be created.

**Desktop (please complete the following information):**
 - OS: Ubuntu 20
 - Python version 3.8

**Additional context**
1. There is no mapping for entity-type, entity-value and entity-patterns all together.
2. Debug logs show incorrect usage of entity-value
3. set_value on [this line](https://github.com/Vernacular-ai/dialogy/blob/ea9fc5638cc3e4b99d33c78af91606d8bf208584/dialogy/preprocess/text/list_entity_plugin/__init__.py#L193) returns None if the method doesn't return `self`, this is not documented.


Discussion / hints:

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 87481a4e..5f1daceb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+# 0.6.2
+- [x] fix: `ListEntityPlugin` 
+  - Now supports a map for entity-type, entity-values for keyword based entities.
+  - Fixed bug that returns `None` when custom entity classes are required.
+
 # 0.6.1
 - [x] feat: future or past datetime only support from `DucklingPlugin`.
 
diff --git a/dialogy/preprocess/text/list_entity_plugin/__init__.py b/dialogy/preprocess/text/list_entity_plugin/__init__.py
index dda8bc6b..2f080312 100644
--- a/dialogy/preprocess/text/list_entity_plugin/__init__.py
+++ b/dialogy/preprocess/text/list_entity_plugin/__init__.py
@@ -19,7 +19,11 @@
 from dialogy.types import BaseEntity
 from dialogy.utils.logger import dbg, log
 
-MatchType = List[Tuple[str, str, Tuple[int, int]]]
+Text = str
+Label = str
+Span = Tuple[int, int]
+Value = str
+MatchType = List[Tuple[Text, Label, Value, Span]]
 
 
 class ListEntityPlugin(Plugin):
@@ -57,7 +61,7 @@ def __init__(
         self,
         entity_map: Dict[str, BaseEntity],
         style: Optional[str] = None,
-        candidates: Optional[Dict[str, List[str]]] = None,
+        candidates: Optional[Dict[str, Dict[str, List[Any]]]] = None,
         spacy_nlp: Any = None,
         labels: Optional[List[str]] = None,
         access: Optional[PluginFn] = None,
@@ -71,17 +75,16 @@ def __init__(
         }
 
         self.style = style or const.REGEX
-        self.entity_map = entity_map
+        self.entity_map: Dict[str, BaseEntity] = entity_map
         self.labels = labels
         self.keywords = None
         self.spacy_nlp = spacy_nlp
-        self.compiled_patterns: Optional[Dict[str, List[Any]]] = None
+        self.compiled_patterns: Dict[str, Dict[str, List[Any]]] = {}
 
         if self.style == const.REGEX:
             self._parse(candidates)
 
-    @dbg(log)
-    def _parse(self, candidates: Optional[Dict[str, List[str]]]) -> None:
+    def _parse(self, candidates: Optional[Dict[str, Dict[str, List[Any]]]]) -> None:
         """
         Pre compile regex patterns to speed up runtime evaluation.
 
@@ -117,16 +120,29 @@ def _parse(self, candidates: Optional[Dict[str, List[str]]]) -> None:
                 f"Expected style to be one of {list(self.__style_search_map.keys())}"
                 f' but "{self.style}" was found.'
             )
+        self.compiled_patterns = {}
 
         if self.style == const.REGEX:
-            self.compiled_patterns = {
-                label: [re.compile(pattern) for pattern in patterns]
-                for label, patterns in candidates.items()
-            }
+            for entity_type, entity_value_dict in candidates.items():
+                for entity_value, entity_patterns in entity_value_dict.items():
+                    if not self.compiled_patterns:
+                        self.compiled_patterns = {
+                            entity_type: {
+                                entity_value: [
+                                    re.compile(pattern) for pattern in entity_patterns
+                                ]
+                            }
+                        }
+                    else:
+                        self.compiled_patterns[entity_type] = {
+                            entity_value: [
+                                re.compile(pattern) for pattern in entity_patterns
+                            ]
+                        }
+
         log.debug("compiled patterns")
         log.debug(self.compiled_patterns)
 
-    @dbg(log)
     def _search(self, transcripts: List[str]) -> List[MatchType]:
         """
         Search for tokens in a list of strings.
@@ -148,7 +164,6 @@ def _search(self, transcripts: List[str]) -> List[MatchType]:
         token_list = [search_fn(transcript) for transcript in transcripts]
         return token_list
 
-    @dbg(log)
     def get_entities(self, transcripts: List[str]) -> List[BaseEntity]:
         """
         Parse entities using regex and spacy ner.
@@ -159,11 +174,12 @@ def get_entities(self, transcripts: List[str]) -> List[BaseEntity]:
         :rtype: List[BaseEntity]
         """
         matches_on_transcripts = self._search(transcripts)
+        log.debug(matches_on_transcripts)
         entity_metadata = []
         entities = []
 
         for i, matches_on_transcript in enumerate(matches_on_transcripts):
-            for text, label, span in matches_on_transcript:
+            for text, label, value, span in matches_on_transcript:
                 entity = {
                     "start": span[0],
                     "end": span[1],
@@ -177,7 +193,7 @@ def get_entities(self, transcripts: List[str]) -> List[BaseEntity]:
                     "type": label,
                     "entity_type": label,
                     "value": {
-                        "values": [{"value": text}],
+                        "values": [{"value": value}],
                     },
                 }
                 entity_metadata.append(entity)
@@ -189,13 +205,15 @@ def get_entities(self, transcripts: List[str]) -> List[BaseEntity]:
             entity = sorted(grouped_entities, key=lambda e: e["alternative_index"])[0]
             del entity["__group"]
             entity["score"] = round(len(grouped_entities) / len(transcripts), 4)
-            entity_class = self.entity_map.get(entity["type"]) or BaseEntity
-            entity = entity_class.from_dict(entity).set_value()  # type: ignore
-            entities.append(entity)
+            entity_class = self.entity_map.get(entity["type"]) or BaseEntity  # type: ignore
+            entity_ = entity_class.from_dict(entity)
+            entity_.set_value()
+            entities.append(entity_)
         log.debug("Parsed entities")
         log.debug(entities)
-        return entities  # type:ignore
+        return entities
 
+    @dbg(log)
     def utility(self, *args: Any) -> Any:
         return self.get_entities(*args)  # pylint: disable=no-value-for-parameter
 
@@ -214,11 +232,13 @@ def ner_search(self, transcript: str) -> MatchType:
                 f" instance but {self.spacy_nlp} was found."
             )
         parsed_transcript = self.spacy_nlp(transcript)
+
         if self.labels:
             return [
                 (
                     token.text,
                     token.label_,
+                    token.text,
                     (
                         transcript.index(token.text),
                         transcript.index(token.text) + len(token.text),
@@ -232,6 +252,7 @@ def ner_search(self, transcript: str) -> MatchType:
                 (
                     token.text,
                     token.label_,
+                    token.text,
                     (
                         transcript.index(token.text),
                         transcript.index(token.text) + len(token.text),
@@ -256,9 +277,13 @@ def regex_search(self, transcript: str) -> MatchType:
             )
 
         entity_tokens = []
-        for label, patterns in self.compiled_patterns.items():
-            for pattern in patterns:
-                matches = pattern.search(transcript)
-                if matches:
-                    entity_tokens.append((matches.group(), label, matches.span()))
+        for entity_type, entity_value_dict in self.compiled_patterns.items():
+            for entity_value, entity_patterns in entity_value_dict.items():
+                for pattern in entity_patterns:
+                    matches = pattern.search(transcript)
+                    if matches:
+                        entity_tokens.append(
+                            (matches.group(), entity_type, entity_value, matches.span())
+                        )
+        log.debug(entity_tokens)
         return entity_tokens
diff --git a/docs/_modules/dialogy/preprocess/text/list_entity_plugin.html b/docs/_modules/dialogy/preprocess/text/list_entity_plugin.html
index 936fe426..ac28b684 100644
--- a/docs/_modules/dialogy/preprocess/text/list_entity_plugin.html
+++ b/docs/_modules/dialogy/preprocess/text/list_entity_plugin.html
@@ -204,7 +204,11 @@ <h1>Source code for dialogy.preprocess.text.list_entity_plugin</h1><div class="h
 <span class="kn">from</span> <span class="nn">dialogy.types</span> <span class="kn">import</span> <span class="n">BaseEntity</span>
 <span class="kn">from</span> <span class="nn">dialogy.utils.logger</span> <span class="kn">import</span> <span class="n">dbg</span><span class="p">,</span> <span class="n">log</span>
 
-<span class="n">MatchType</span> <span class="o">=</span> <span class="n">List</span><span class="p">[</span><span class="n">Tuple</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="nb">str</span><span class="p">,</span> <span class="n">Tuple</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="nb">int</span><span class="p">]]]</span>
+<span class="n">Text</span> <span class="o">=</span> <span class="nb">str</span>
+<span class="n">Label</span> <span class="o">=</span> <span class="nb">str</span>
+<span class="n">Span</span> <span class="o">=</span> <span class="n">Tuple</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="nb">int</span><span class="p">]</span>
+<span class="n">Value</span> <span class="o">=</span> <span class="nb">str</span>
+<span class="n">MatchType</span> <span class="o">=</span> <span class="n">List</span><span class="p">[</span><span class="n">Tuple</span><span class="p">[</span><span class="n">Text</span><span class="p">,</span> <span class="n">Label</span><span class="p">,</span> <span class="n">Value</span><span class="p">,</span> <span class="n">Span</span><span class="p">]]</span>
 
 
 <div class="viewcode-block" id="ListEntityPlugin"><a class="viewcode-back" href="../../../../source/dialogy.preprocess.text.list_entity_plugin.html#dialogy.preprocess.text.list_entity_plugin.ListEntityPlugin">[docs]</a><span class="k">class</span> <span class="nc">ListEntityPlugin</span><span class="p">(</span><span class="n">Plugin</span><span class="p">):</span>
@@ -242,7 +246,7 @@ <h1>Source code for dialogy.preprocess.text.list_entity_plugin</h1><div class="h
         <span class="bp">self</span><span class="p">,</span>
         <span class="n">entity_map</span><span class="p">:</span> <span class="n">Dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">BaseEntity</span><span class="p">],</span>
         <span class="n">style</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
-        <span class="n">candidates</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]]]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
+        <span class="n">candidates</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">List</span><span class="p">[</span><span class="n">Any</span><span class="p">]]]]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
         <span class="n">spacy_nlp</span><span class="p">:</span> <span class="n">Any</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
         <span class="n">labels</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
         <span class="n">access</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">PluginFn</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
@@ -256,17 +260,16 @@ <h1>Source code for dialogy.preprocess.text.list_entity_plugin</h1><div class="h
         <span class="p">}</span>
 
         <span class="bp">self</span><span class="o">.</span><span class="n">style</span> <span class="o">=</span> <span class="n">style</span> <span class="ow">or</span> <span class="n">const</span><span class="o">.</span><span class="n">REGEX</span>
-        <span class="bp">self</span><span class="o">.</span><span class="n">entity_map</span> <span class="o">=</span> <span class="n">entity_map</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">entity_map</span><span class="p">:</span> <span class="n">Dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">BaseEntity</span><span class="p">]</span> <span class="o">=</span> <span class="n">entity_map</span>
         <span class="bp">self</span><span class="o">.</span><span class="n">labels</span> <span class="o">=</span> <span class="n">labels</span>
         <span class="bp">self</span><span class="o">.</span><span class="n">keywords</span> <span class="o">=</span> <span class="kc">None</span>
         <span class="bp">self</span><span class="o">.</span><span class="n">spacy_nlp</span> <span class="o">=</span> <span class="n">spacy_nlp</span>
-        <span class="bp">self</span><span class="o">.</span><span class="n">compiled_patterns</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">List</span><span class="p">[</span><span class="n">Any</span><span class="p">]]]</span> <span class="o">=</span> <span class="kc">None</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">compiled_patterns</span><span class="p">:</span> <span class="n">Dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">List</span><span class="p">[</span><span class="n">Any</span><span class="p">]]]</span> <span class="o">=</span> <span class="p">{}</span>
 
         <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">style</span> <span class="o">==</span> <span class="n">const</span><span class="o">.</span><span class="n">REGEX</span><span class="p">:</span>
             <span class="bp">self</span><span class="o">.</span><span class="n">_parse</span><span class="p">(</span><span class="n">candidates</span><span class="p">)</span>
 
-    <span class="nd">@dbg</span><span class="p">(</span><span class="n">log</span><span class="p">)</span>
-    <span class="k">def</span> <span class="nf">_parse</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">candidates</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]]])</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
+    <span class="k">def</span> <span class="nf">_parse</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">candidates</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">List</span><span class="p">[</span><span class="n">Any</span><span class="p">]]]])</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
         <span class="sd">"""</span>
 <span class="sd">        Pre compile regex patterns to speed up runtime evaluation.</span>
 
@@ -302,16 +305,29 @@ <h1>Source code for dialogy.preprocess.text.list_entity_plugin</h1><div class="h
                 <span class="sa">f</span><span class="s2">"Expected style to be one of </span><span class="si">{</span><span class="nb">list</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__style_search_map</span><span class="o">.</span><span class="n">keys</span><span class="p">())</span><span class="si">}</span><span class="s2">"</span>
                 <span class="sa">f</span><span class="s1">' but "</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">style</span><span class="si">}</span><span class="s1">" was found.'</span>
             <span class="p">)</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">compiled_patterns</span> <span class="o">=</span> <span class="p">{}</span>
 
         <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">style</span> <span class="o">==</span> <span class="n">const</span><span class="o">.</span><span class="n">REGEX</span><span class="p">:</span>
-            <span class="bp">self</span><span class="o">.</span><span class="n">compiled_patterns</span> <span class="o">=</span> <span class="p">{</span>
-                <span class="n">label</span><span class="p">:</span> <span class="p">[</span><span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="n">pattern</span><span class="p">)</span> <span class="k">for</span> <span class="n">pattern</span> <span class="ow">in</span> <span class="n">patterns</span><span class="p">]</span>
-                <span class="k">for</span> <span class="n">label</span><span class="p">,</span> <span class="n">patterns</span> <span class="ow">in</span> <span class="n">candidates</span><span class="o">.</span><span class="n">items</span><span class="p">()</span>
-            <span class="p">}</span>
+            <span class="k">for</span> <span class="n">entity_type</span><span class="p">,</span> <span class="n">entity_value_dict</span> <span class="ow">in</span> <span class="n">candidates</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
+                <span class="k">for</span> <span class="n">entity_value</span><span class="p">,</span> <span class="n">entity_patterns</span> <span class="ow">in</span> <span class="n">entity_value_dict</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
+                    <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">compiled_patterns</span><span class="p">:</span>
+                        <span class="bp">self</span><span class="o">.</span><span class="n">compiled_patterns</span> <span class="o">=</span> <span class="p">{</span>
+                            <span class="n">entity_type</span><span class="p">:</span> <span class="p">{</span>
+                                <span class="n">entity_value</span><span class="p">:</span> <span class="p">[</span>
+                                    <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="n">pattern</span><span class="p">)</span> <span class="k">for</span> <span class="n">pattern</span> <span class="ow">in</span> <span class="n">entity_patterns</span>
+                                <span class="p">]</span>
+                            <span class="p">}</span>
+                        <span class="p">}</span>
+                    <span class="k">else</span><span class="p">:</span>
+                        <span class="bp">self</span><span class="o">.</span><span class="n">compiled_patterns</span><span class="p">[</span><span class="n">entity_type</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span>
+                            <span class="n">entity_value</span><span class="p">:</span> <span class="p">[</span>
+                                <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="n">pattern</span><span class="p">)</span> <span class="k">for</span> <span class="n">pattern</span> <span class="ow">in</span> <span class="n">entity_patterns</span>
+                            <span class="p">]</span>
+                        <span class="p">}</span>
+
         <span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"compiled patterns"</span><span class="p">)</span>
         <span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">compiled_patterns</span><span class="p">)</span>
 
-    <span class="nd">@dbg</span><span class="p">(</span><span class="n">log</span><span class="p">)</span>
     <span class="k">def</span> <span class="nf">_search</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">transcripts</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">MatchType</span><span class="p">]:</span>
         <span class="sd">"""</span>
 <span class="sd">        Search for tokens in a list of strings.</span>
@@ -333,8 +349,7 @@ <h1>Source code for dialogy.preprocess.text.list_entity_plugin</h1><div class="h
         <span class="n">token_list</span> <span class="o">=</span> <span class="p">[</span><span class="n">search_fn</span><span class="p">(</span><span class="n">transcript</span><span class="p">)</span> <span class="k">for</span> <span class="n">transcript</span> <span class="ow">in</span> <span class="n">transcripts</span><span class="p">]</span>
         <span class="k">return</span> <span class="n">token_list</span>
 
-<div class="viewcode-block" id="ListEntityPlugin.get_entities"><a class="viewcode-back" href="../../../../source/dialogy.preprocess.text.list_entity_plugin.html#dialogy.preprocess.text.list_entity_plugin.ListEntityPlugin.get_entities">[docs]</a>    <span class="nd">@dbg</span><span class="p">(</span><span class="n">log</span><span class="p">)</span>
-    <span class="k">def</span> <span class="nf">get_entities</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">transcripts</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">BaseEntity</span><span class="p">]:</span>
+<div class="viewcode-block" id="ListEntityPlugin.get_entities"><a class="viewcode-back" href="../../../../source/dialogy.preprocess.text.list_entity_plugin.html#dialogy.preprocess.text.list_entity_plugin.ListEntityPlugin.get_entities">[docs]</a>    <span class="k">def</span> <span class="nf">get_entities</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">transcripts</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">BaseEntity</span><span class="p">]:</span>
         <span class="sd">"""</span>
 <span class="sd">        Parse entities using regex and spacy ner.</span>
 
@@ -344,11 +359,12 @@ <h1>Source code for dialogy.preprocess.text.list_entity_plugin</h1><div class="h
 <span class="sd">        :rtype: List[BaseEntity]</span>
 <span class="sd">        """</span>
         <span class="n">matches_on_transcripts</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_search</span><span class="p">(</span><span class="n">transcripts</span><span class="p">)</span>
+        <span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">matches_on_transcripts</span><span class="p">)</span>
         <span class="n">entity_metadata</span> <span class="o">=</span> <span class="p">[]</span>
         <span class="n">entities</span> <span class="o">=</span> <span class="p">[]</span>
 
         <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">matches_on_transcript</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">matches_on_transcripts</span><span class="p">):</span>
-            <span class="k">for</span> <span class="n">text</span><span class="p">,</span> <span class="n">label</span><span class="p">,</span> <span class="n">span</span> <span class="ow">in</span> <span class="n">matches_on_transcript</span><span class="p">:</span>
+            <span class="k">for</span> <span class="n">text</span><span class="p">,</span> <span class="n">label</span><span class="p">,</span> <span class="n">value</span><span class="p">,</span> <span class="n">span</span> <span class="ow">in</span> <span class="n">matches_on_transcript</span><span class="p">:</span>
                 <span class="n">entity</span> <span class="o">=</span> <span class="p">{</span>
                     <span class="s2">"start"</span><span class="p">:</span> <span class="n">span</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span>
                     <span class="s2">"end"</span><span class="p">:</span> <span class="n">span</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span>
@@ -362,7 +378,7 @@ <h1>Source code for dialogy.preprocess.text.list_entity_plugin</h1><div class="h
                     <span class="s2">"type"</span><span class="p">:</span> <span class="n">label</span><span class="p">,</span>
                     <span class="s2">"entity_type"</span><span class="p">:</span> <span class="n">label</span><span class="p">,</span>
                     <span class="s2">"value"</span><span class="p">:</span> <span class="p">{</span>
-                        <span class="s2">"values"</span><span class="p">:</span> <span class="p">[{</span><span class="s2">"value"</span><span class="p">:</span> <span class="n">text</span><span class="p">}],</span>
+                        <span class="s2">"values"</span><span class="p">:</span> <span class="p">[{</span><span class="s2">"value"</span><span class="p">:</span> <span class="n">value</span><span class="p">}],</span>
                     <span class="p">},</span>
                 <span class="p">}</span>
                 <span class="n">entity_metadata</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">entity</span><span class="p">)</span>
@@ -374,14 +390,16 @@ <h1>Source code for dialogy.preprocess.text.list_entity_plugin</h1><div class="h
             <span class="n">entity</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">grouped_entities</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">e</span><span class="p">:</span> <span class="n">e</span><span class="p">[</span><span class="s2">"alternative_index"</span><span class="p">])[</span><span class="mi">0</span><span class="p">]</span>
             <span class="k">del</span> <span class="n">entity</span><span class="p">[</span><span class="s2">"__group"</span><span class="p">]</span>
             <span class="n">entity</span><span class="p">[</span><span class="s2">"score"</span><span class="p">]</span> <span class="o">=</span> <span class="nb">round</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">grouped_entities</span><span class="p">)</span> <span class="o">/</span> <span class="nb">len</span><span class="p">(</span><span class="n">transcripts</span><span class="p">),</span> <span class="mi">4</span><span class="p">)</span>
-            <span class="n">entity_class</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">entity_map</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">entity</span><span class="p">[</span><span class="s2">"type"</span><span class="p">])</span> <span class="ow">or</span> <span class="n">BaseEntity</span>
-            <span class="n">entity</span> <span class="o">=</span> <span class="n">entity_class</span><span class="o">.</span><span class="n">from_dict</span><span class="p">(</span><span class="n">entity</span><span class="p">)</span><span class="o">.</span><span class="n">set_value</span><span class="p">()</span>  <span class="c1"># type: ignore</span>
-            <span class="n">entities</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">entity</span><span class="p">)</span>
+            <span class="n">entity_class</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">entity_map</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">entity</span><span class="p">[</span><span class="s2">"type"</span><span class="p">])</span> <span class="ow">or</span> <span class="n">BaseEntity</span>  <span class="c1"># type: ignore</span>
+            <span class="n">entity_</span> <span class="o">=</span> <span class="n">entity_class</span><span class="o">.</span><span class="n">from_dict</span><span class="p">(</span><span class="n">entity</span><span class="p">)</span>
+            <span class="n">entity_</span><span class="o">.</span><span class="n">set_value</span><span class="p">()</span>
+            <span class="n">entities</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">entity_</span><span class="p">)</span>
         <span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"Parsed entities"</span><span class="p">)</span>
         <span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">entities</span><span class="p">)</span>
-        <span class="k">return</span> <span class="n">entities</span>  <span class="c1"># type:ignore</span></div>
+        <span class="k">return</span> <span class="n">entities</span></div>
 
-<div class="viewcode-block" id="ListEntityPlugin.utility"><a class="viewcode-back" href="../../../../source/dialogy.preprocess.text.list_entity_plugin.html#dialogy.preprocess.text.list_entity_plugin.ListEntityPlugin.utility">[docs]</a>    <span class="k">def</span> <span class="nf">utility</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">Any</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Any</span><span class="p">:</span>
+<div class="viewcode-block" id="ListEntityPlugin.utility"><a class="viewcode-back" href="../../../../source/dialogy.preprocess.text.list_entity_plugin.html#dialogy.preprocess.text.list_entity_plugin.ListEntityPlugin.utility">[docs]</a>    <span class="nd">@dbg</span><span class="p">(</span><span class="n">log</span><span class="p">)</span>
+    <span class="k">def</span> <span class="nf">utility</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">Any</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Any</span><span class="p">:</span>
         <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_entities</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>  <span class="c1"># pylint: disable=no-value-for-parameter</span></div>
 
 <div class="viewcode-block" id="ListEntityPlugin.ner_search"><a class="viewcode-back" href="../../../../source/dialogy.preprocess.text.list_entity_plugin.html#dialogy.preprocess.text.list_entity_plugin.ListEntityPlugin.ner_search">[docs]</a>    <span class="k">def</span> <span class="nf">ner_search</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">transcript</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">MatchType</span><span class="p">:</span>
@@ -399,11 +417,13 @@ <h1>Source code for dialogy.preprocess.text.list_entity_plugin</h1><div class="h
                 <span class="sa">f</span><span class="s2">" instance but </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">spacy_nlp</span><span class="si">}</span><span class="s2"> was found."</span>
             <span class="p">)</span>
         <span class="n">parsed_transcript</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">spacy_nlp</span><span class="p">(</span><span class="n">transcript</span><span class="p">)</span>
+
         <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">labels</span><span class="p">:</span>
             <span class="k">return</span> <span class="p">[</span>
                 <span class="p">(</span>
                     <span class="n">token</span><span class="o">.</span><span class="n">text</span><span class="p">,</span>
                     <span class="n">token</span><span class="o">.</span><span class="n">label_</span><span class="p">,</span>
+                    <span class="n">token</span><span class="o">.</span><span class="n">text</span><span class="p">,</span>
                     <span class="p">(</span>
                         <span class="n">transcript</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">token</span><span class="o">.</span><span class="n">text</span><span class="p">),</span>
                         <span class="n">transcript</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">token</span><span class="o">.</span><span class="n">text</span><span class="p">)</span> <span class="o">+</span> <span class="nb">len</span><span class="p">(</span><span class="n">token</span><span class="o">.</span><span class="n">text</span><span class="p">),</span>
@@ -417,6 +437,7 @@ <h1>Source code for dialogy.preprocess.text.list_entity_plugin</h1><div class="h
                 <span class="p">(</span>
                     <span class="n">token</span><span class="o">.</span><span class="n">text</span><span class="p">,</span>
                     <span class="n">token</span><span class="o">.</span><span class="n">label_</span><span class="p">,</span>
+                    <span class="n">token</span><span class="o">.</span><span class="n">text</span><span class="p">,</span>
                     <span class="p">(</span>
                         <span class="n">transcript</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">token</span><span class="o">.</span><span class="n">text</span><span class="p">),</span>
                         <span class="n">transcript</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">token</span><span class="o">.</span><span class="n">text</span><span class="p">)</span> <span class="o">+</span> <span class="nb">len</span><span class="p">(</span><span class="n">token</span><span class="o">.</span><span class="n">text</span><span class="p">),</span>
@@ -441,11 +462,15 @@ <h1>Source code for dialogy.preprocess.text.list_entity_plugin</h1><div class="h
             <span class="p">)</span>
 
         <span class="n">entity_tokens</span> <span class="o">=</span> <span class="p">[]</span>
-        <span class="k">for</span> <span class="n">label</span><span class="p">,</span> <span class="n">patterns</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">compiled_patterns</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
-            <span class="k">for</span> <span class="n">pattern</span> <span class="ow">in</span> <span class="n">patterns</span><span class="p">:</span>
-                <span class="n">matches</span> <span class="o">=</span> <span class="n">pattern</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="n">transcript</span><span class="p">)</span>
-                <span class="k">if</span> <span class="n">matches</span><span class="p">:</span>
-                    <span class="n">entity_tokens</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">matches</span><span class="o">.</span><span class="n">group</span><span class="p">(),</span> <span class="n">label</span><span class="p">,</span> <span class="n">matches</span><span class="o">.</span><span class="n">span</span><span class="p">()))</span>
+        <span class="k">for</span> <span class="n">entity_type</span><span class="p">,</span> <span class="n">entity_value_dict</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">compiled_patterns</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
+            <span class="k">for</span> <span class="n">entity_value</span><span class="p">,</span> <span class="n">entity_patterns</span> <span class="ow">in</span> <span class="n">entity_value_dict</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
+                <span class="k">for</span> <span class="n">pattern</span> <span class="ow">in</span> <span class="n">entity_patterns</span><span class="p">:</span>
+                    <span class="n">matches</span> <span class="o">=</span> <span class="n">pattern</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="n">transcript</span><span class="p">)</span>
+                    <span class="k">if</span> <span class="n">matches</span><span class="p">:</span>
+                        <span class="n">entity_tokens</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+                            <span class="p">(</span><span class="n">matches</span><span class="o">.</span><span class="n">group</span><span class="p">(),</span> <span class="n">entity_type</span><span class="p">,</span> <span class="n">entity_value</span><span class="p">,</span> <span class="n">matches</span><span class="o">.</span><span class="n">span</span><span class="p">())</span>
+                        <span class="p">)</span>
+        <span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">entity_tokens</span><span class="p">)</span>
         <span class="k">return</span> <span class="n">entity_tokens</span></div></div>
 </pre></div>
       </article>
diff --git a/docs/source/dialogy.preprocess.text.list_entity_plugin.html b/docs/source/dialogy.preprocess.text.list_entity_plugin.html
index bfdda7fa..8df9d3da 100644
--- a/docs/source/dialogy.preprocess.text.list_entity_plugin.html
+++ b/docs/source/dialogy.preprocess.text.list_entity_plugin.html
@@ -193,7 +193,7 @@ <h1>dialogy.preprocess.text.list_entity_plugin package<a class="headerlink" href
 all other entities. So that their <code class="code docutils literal notranslate"><span class="pre">from_dict(...)</span></code> methods are pristine and involve no shape hacking.</p>
 <dl class="py class">
 <dt id="dialogy.preprocess.text.list_entity_plugin.ListEntityPlugin">
-<em class="property"><span class="pre">class</span> </em><code class="sig-prename descclassname"><span class="pre">dialogy.preprocess.text.list_entity_plugin.</span></code><code class="sig-name descname"><span class="pre">ListEntityPlugin</span></code><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">entity_map</span></span><span class="p"><span class="pre">:</span></span> <span class="n"><span class="pre">Dict</span><span class="p"><span class="pre">[</span></span><span class="pre">str</span><span class="p"><span class="pre">,</span> </span><a class="reference internal" href="dialogy.types.entity.html#dialogy.types.entity.base_entity.BaseEntity" title="dialogy.types.entity.base_entity.BaseEntity"><span class="pre">dialogy.types.entity.base_entity.BaseEntity</span></a><span class="p"><span class="pre">]</span></span></span></em>, <em class="sig-param"><span class="n"><span class="pre">style</span></span><span class="p"><span class="pre">:</span></span> <span class="n"><span class="pre">Optional</span><span class="p"><span class="pre">[</span></span><span class="pre">str</span><span class="p"><span class="pre">]</span></span></span> <span class="o"><span class="pre">=</span></span> <span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">candidates</span></span><span class="p"><span class="pre">:</span></span> <span class="n"><span class="pre">Optional</span><span class="p"><span class="pre">[</span></span><span class="pre">Dict</span><span class="p"><span class="pre">[</span></span><span class="pre">str</span><span class="p"><span class="pre">,</span> </span><span class="pre">List</span><span class="p"><span class="pre">[</span></span><span class="pre">str</span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span></span> <span class="o"><span class="pre">=</span></span> <span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">spacy_nlp</span></span><span class="p"><span class="pre">:</span></span> <span class="n"><span class="pre">Optional</span><span class="p"><span class="pre">[</span></span><span class="pre">Any</span><span class="p"><span class="pre">]</span></span></span> <span class="o"><span class="pre">=</span></span> <span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">labels</span></span><span class="p"><span class="pre">:</span></span> <span class="n"><span class="pre">Optional</span><span class="p"><span class="pre">[</span></span><span class="pre">List</span><span class="p"><span class="pre">[</span></span><span class="pre">str</span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span></span> <span class="o"><span class="pre">=</span></span> <span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">access</span></span><span class="p"><span class="pre">:</span></span> <span class="n"><span class="pre">Optional</span><span class="p"><span class="pre">[</span></span><span class="pre">Callable</span><span class="p"><span class="pre">[</span></span><span class="p"><span class="pre">[</span></span><span class="p"><span class="pre">…</span></span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">,</span> </span><span class="pre">Any</span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span></span> <span class="o"><span class="pre">=</span></span> <span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">mutate</span></span><span class="p"><span class="pre">:</span></span> <span class="n"><span class="pre">Optional</span><span class="p"><span class="pre">[</span></span><span class="pre">Callable</span><span class="p"><span class="pre">[</span></span><span class="p"><span class="pre">[</span></span><span class="p"><span class="pre">…</span></span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">,</span> </span><span class="pre">Any</span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span></span> <span class="o"><span class="pre">=</span></span> <span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">debug</span></span><span class="p"><span class="pre">:</span></span> <span class="n"><span class="pre">bool</span></span> <span class="o"><span class="pre">=</span></span> <span class="default_value"><span class="pre">False</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/dialogy/preprocess/text/list_entity_plugin.html#ListEntityPlugin"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#dialogy.preprocess.text.list_entity_plugin.ListEntityPlugin" title="Permalink to this definition">¶</a></dt>
+<em class="property"><span class="pre">class</span> </em><code class="sig-prename descclassname"><span class="pre">dialogy.preprocess.text.list_entity_plugin.</span></code><code class="sig-name descname"><span class="pre">ListEntityPlugin</span></code><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">entity_map</span></span><span class="p"><span class="pre">:</span></span> <span class="n"><span class="pre">Dict</span><span class="p"><span class="pre">[</span></span><span class="pre">str</span><span class="p"><span class="pre">,</span> </span><a class="reference internal" href="dialogy.types.entity.html#dialogy.types.entity.base_entity.BaseEntity" title="dialogy.types.entity.base_entity.BaseEntity"><span class="pre">dialogy.types.entity.base_entity.BaseEntity</span></a><span class="p"><span class="pre">]</span></span></span></em>, <em class="sig-param"><span class="n"><span class="pre">style</span></span><span class="p"><span class="pre">:</span></span> <span class="n"><span class="pre">Optional</span><span class="p"><span class="pre">[</span></span><span class="pre">str</span><span class="p"><span class="pre">]</span></span></span> <span class="o"><span class="pre">=</span></span> <span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">candidates</span></span><span class="p"><span class="pre">:</span></span> <span class="n"><span class="pre">Optional</span><span class="p"><span class="pre">[</span></span><span class="pre">Dict</span><span class="p"><span class="pre">[</span></span><span class="pre">str</span><span class="p"><span class="pre">,</span> </span><span class="pre">Dict</span><span class="p"><span class="pre">[</span></span><span class="pre">str</span><span class="p"><span class="pre">,</span> </span><span class="pre">List</span><span class="p"><span class="pre">[</span></span><span class="pre">Any</span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span></span> <span class="o"><span class="pre">=</span></span> <span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">spacy_nlp</span></span><span class="p"><span class="pre">:</span></span> <span class="n"><span class="pre">Optional</span><span class="p"><span class="pre">[</span></span><span class="pre">Any</span><span class="p"><span class="pre">]</span></span></span> <span class="o"><span class="pre">=</span></span> <span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">labels</span></span><span class="p"><span class="pre">:</span></span> <span class="n"><span class="pre">Optional</span><span class="p"><span class="pre">[</span></span><span class="pre">List</span><span class="p"><span class="pre">[</span></span><span class="pre">str</span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span></span> <span class="o"><span class="pre">=</span></span> <span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">access</span></span><span class="p"><span class="pre">:</span></span> <span class="n"><span class="pre">Optional</span><span class="p"><span class="pre">[</span></span><span class="pre">Callable</span><span class="p"><span class="pre">[</span></span><span class="p"><span class="pre">[</span></span><span class="p"><span class="pre">…</span></span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">,</span> </span><span class="pre">Any</span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span></span> <span class="o"><span class="pre">=</span></span> <span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">mutate</span></span><span class="p"><span class="pre">:</span></span> <span class="n"><span class="pre">Optional</span><span class="p"><span class="pre">[</span></span><span class="pre">Callable</span><span class="p"><span class="pre">[</span></span><span class="p"><span class="pre">[</span></span><span class="p"><span class="pre">…</span></span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">,</span> </span><span class="pre">Any</span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span></span> <span class="o"><span class="pre">=</span></span> <span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">debug</span></span><span class="p"><span class="pre">:</span></span> <span class="n"><span class="pre">bool</span></span> <span class="o"><span class="pre">=</span></span> <span class="default_value"><span class="pre">False</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../_modules/dialogy/preprocess/text/list_entity_plugin.html#ListEntityPlugin"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#dialogy.preprocess.text.list_entity_plugin.ListEntityPlugin" title="Permalink to this definition">¶</a></dt>
 <dd><p>Bases: <a class="reference internal" href="dialogy.plugin.html#dialogy.plugin.plugin.Plugin" title="dialogy.plugin.plugin.Plugin"><code class="xref py py-class docutils literal notranslate"><span class="pre">dialogy.plugin.plugin.Plugin</span></code></a></p>
 <blockquote>
 <div><p>A <a class="reference internal" href="dialogy.plugin.html#plugin"><span class="std std-ref">Plugin</span></a> for extracting entities using spacy or a list of regex patterns.</p>
@@ -235,7 +235,7 @@ <h1>dialogy.preprocess.text.list_entity_plugin package<a class="headerlink" href
 </dd></dl>
 <dl class="py method">
 <dt id="dialogy.preprocess.text.list_entity_plugin.ListEntityPlugin.ner_search">
-<code class="sig-name descname"><span class="pre">ner_search</span></code><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">transcript</span></span><span class="p"><span class="pre">:</span></span> <span class="n"><span class="pre">str</span></span></em><span class="sig-paren">)</span> → <span class="pre">List</span><span class="p"><span class="pre">[</span></span><span class="pre">Tuple</span><span class="p"><span class="pre">[</span></span><span class="pre">str</span><span class="p"><span class="pre">,</span> </span><span class="pre">str</span><span class="p"><span class="pre">,</span> </span><span class="pre">Tuple</span><span class="p"><span class="pre">[</span></span><span class="pre">int</span><span class="p"><span class="pre">,</span> </span><span class="pre">int</span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span><a class="reference internal" href="../_modules/dialogy/preprocess/text/list_entity_plugin.html#ListEntityPlugin.ner_search"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#dialogy.preprocess.text.list_entity_plugin.ListEntityPlugin.ner_search" title="Permalink to this definition">¶</a></dt>
+<code class="sig-name descname"><span class="pre">ner_search</span></code><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">transcript</span></span><span class="p"><span class="pre">:</span></span> <span class="n"><span class="pre">str</span></span></em><span class="sig-paren">)</span> → <span class="pre">List</span><span class="p"><span class="pre">[</span></span><span class="pre">Tuple</span><span class="p"><span class="pre">[</span></span><span class="pre">str</span><span class="p"><span class="pre">,</span> </span><span class="pre">str</span><span class="p"><span class="pre">,</span> </span><span class="pre">str</span><span class="p"><span class="pre">,</span> </span><span class="pre">Tuple</span><span class="p"><span class="pre">[</span></span><span class="pre">int</span><span class="p"><span class="pre">,</span> </span><span class="pre">int</span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span><a class="reference internal" href="../_modules/dialogy/preprocess/text/list_entity_plugin.html#ListEntityPlugin.ner_search"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#dialogy.preprocess.text.list_entity_plugin.ListEntityPlugin.ner_search" title="Permalink to this definition">¶</a></dt>
 <dd><p>Wrapper over spacy’s ner search.</p>
 <dl class="field-list simple">
 <dt class="field-odd">Parameters</dt>
@@ -251,7 +251,7 @@ <h1>dialogy.preprocess.text.list_entity_plugin package<a class="headerlink" href
 </dd></dl>
 <dl class="py method">
 <dt id="dialogy.preprocess.text.list_entity_plugin.ListEntityPlugin.regex_search">
-<code class="sig-name descname"><span class="pre">regex_search</span></code><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">transcript</span></span><span class="p"><span class="pre">:</span></span> <span class="n"><span class="pre">str</span></span></em><span class="sig-paren">)</span> → <span class="pre">List</span><span class="p"><span class="pre">[</span></span><span class="pre">Tuple</span><span class="p"><span class="pre">[</span></span><span class="pre">str</span><span class="p"><span class="pre">,</span> </span><span class="pre">str</span><span class="p"><span class="pre">,</span> </span><span class="pre">Tuple</span><span class="p"><span class="pre">[</span></span><span class="pre">int</span><span class="p"><span class="pre">,</span> </span><span class="pre">int</span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span><a class="reference internal" href="../_modules/dialogy/preprocess/text/list_entity_plugin.html#ListEntityPlugin.regex_search"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#dialogy.preprocess.text.list_entity_plugin.ListEntityPlugin.regex_search" title="Permalink to this definition">¶</a></dt>
+<code class="sig-name descname"><span class="pre">regex_search</span></code><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">transcript</span></span><span class="p"><span class="pre">:</span></span> <span class="n"><span class="pre">str</span></span></em><span class="sig-paren">)</span> → <span class="pre">List</span><span class="p"><span class="pre">[</span></span><span class="pre">Tuple</span><span class="p"><span class="pre">[</span></span><span class="pre">str</span><span class="p"><span class="pre">,</span> </span><span class="pre">str</span><span class="p"><span class="pre">,</span> </span><span class="pre">str</span><span class="p"><span class="pre">,</span> </span><span class="pre">Tuple</span><span class="p"><span class="pre">[</span></span><span class="pre">int</span><span class="p"><span class="pre">,</span> </span><span class="pre">int</span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span><a class="reference internal" href="../_modules/dialogy/preprocess/text/list_entity_plugin.html#ListEntityPlugin.regex_search"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#dialogy.preprocess.text.list_entity_plugin.ListEntityPlugin.regex_search" title="Permalink to this definition">¶</a></dt>
 <dd><p>Wrapper over regex searches.</p>
 <dl class="field-list simple">
 <dt class="field-odd">Parameters</dt>
diff --git a/pyproject.toml b/pyproject.toml
index eccee24c..d53076ee 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
 [tool.poetry]
 name = "dialogy"
-version = "0.6.1"
+version = "0.6.2"
 description = "Language understanding for human dialog."
 authors = ["Amresh Venugopal <amresh.venugopal@gmail.com>"]
 


Test patch:
diff --git a/tests/preprocess/text/test_list_entity_plugin/test___init__.py b/tests/preprocess/text/test_list_entity_plugin/test___init__.py
index 7cd733de..25df66df 100644
--- a/tests/preprocess/text/test_list_entity_plugin/test___init__.py
+++ b/tests/preprocess/text/test_list_entity_plugin/test___init__.py
@@ -1,10 +1,43 @@
+from typing import Dict, List, Optional
+
+import attr
 import pytest
 
 from dialogy.preprocess.text.list_entity_plugin import ListEntityPlugin
+from dialogy.types.entity import BaseEntity
 from dialogy.workflow import Workflow
 from tests import EXCEPTIONS, load_tests
 
 
+@attr.s
+class MockCustomEntity(BaseEntity):
+    """
+    Extend BaseEntity for products of any kind.
+    An instance of this class should be used to
+    wrap tokens that are understood as product entities.
+    """
+
+    values = attr.ib(
+        type=List[Dict[str, str]],
+        default=attr.Factory(list),
+        validator=attr.validators.instance_of(List),
+    )
+    _meta = attr.ib(type=Dict[str, str], default=attr.Factory(dict))
+    value: Optional[str] = attr.ib(default=None)
+
+    def __attrs_post_init__(self) -> None:
+        self.entity_type = "mock_entity"
+
+    def set_value(self, keyword: Optional[str] = None):
+        if keyword:
+            value = keyword.lower().strip()
+            self.values = [{"value": value}]
+            self.value = value
+        else:
+            print(self.values)
+            self.value = self.values[0]["value"]
+
+
 class EntMocker:
     def __init__(self, token, label):
         self.text = token
@@ -69,6 +102,10 @@ def test_get_entities(payload):
     config = payload.get("config")
     spacy_mocker = None
     transcripts = [expectation["text"] for expectation in input_]
+    entity_class_map = {"MockCustomEntity": MockCustomEntity}
+
+    for entity_type, entity_class_name in config["entity_map"].items():
+        config["entity_map"][entity_type] = entity_class_map[entity_class_name]
 
     if config["style"] == "spacy":
         spacy_mocker = SpacyMocker(input_)
@@ -81,6 +118,13 @@ def test_get_entities(payload):
         workflow = Workflow(preprocessors=[list_entity_plugin], postprocessors=[])
         workflow.run(input_=transcripts)
         entities = workflow.output
+
+        print(entities)
+        print(expected)
+
+        if not entities and expected:
+            pytest.fail("No entities found!")
+
         for i, entity in enumerate(entities):
             assert entity.value == expected[i]["value"]
             assert entity.type == expected[i]["type"]
diff --git a/tests/preprocess/text/test_list_entity_plugin/test_cases.yaml b/tests/preprocess/text/test_list_entity_plugin/test_cases.yaml
index 1c8f0e64..e7e04cdd 100644
--- a/tests/preprocess/text/test_list_entity_plugin/test_cases.yaml
+++ b/tests/preprocess/text/test_list_entity_plugin/test_cases.yaml
@@ -25,19 +25,27 @@
 
 - description: "Test location entities using regex"
   input:
-    - text: "i want it in New Delhi"
-      entities:
-      - type: "location"
-        value: "New Delhi"
+    - text: "i want to parse a token in delhi"
   expected:
+    - type: "some_entity_type"
+      value: "entity_value"
     - type: "location"
-      value: "New Delhi"
+      value: "delhi"
   config:
+    debug: true
     style: regex
-    entity_map: {}
+    entity_map: {
+      "location": "MockCustomEntity"
+    }
     candidates:
+      some_entity_type:
+        entity_value:
+          - "token"
       location:
-        - "New Delhi"
+        delhi:
+          - "New Delhi"
+          - "new delhi"
+          - "delhi"
 
 - description: "Test spacy restricted on labels"
   input: