spaczz for spaCy

repository·main·Indexed 42 days ago

https://github.com/gandersen101/spaczz

An extension for spaCy (>= 3.0) that adds fuzzy matching, advanced regex capabilities, and vector-based similarity matching to NLP pipelines. It provides the SpaczzRuler pipeline component to integrate FuzzyMatcher, RegexMatcher, and TokenMatcher into a single workflow, allowing for robust pattern matching and automatic entity updates in spaCy Doc, Span, and Token objects. Version 0.6.1.

Tokens
11.5K
Snippets
28
Records
45
Agent score
53%

What's inside spaczz

  1. Overview of spaczz for spaCy

    main

    spaczz provides fuzzy matching and enhanced regex matching functionality for spaCy.

    Key characteristics:

    • API Compatibility: Components follow APIs similar to their spaCy counterparts.
    • Pipeline Integration: spaczz pipeline components can be integrated into spaCy pipelines, allowing them to be saved and loaded as part of a model.
    • Core Technologies: Fuzzy matching is powered by RapidFuzz, and regex matching relies on the regex library.
    • Compatibility: Supports spaCy >= 3.0 and Python >= 3.7, <= 3.11.
  2. Overview of spaczz functionality

    main

    Spaczz extends spaCy with two primary capabilities:

    1. Fuzzy matching: Finding matches that are not exact string matches.
    2. Multi-token regex matching: Using regular expressions to match across multiple tokens in a spaCy Doc.

    Spaczz components are designed to have APIs similar to their spaCy counterparts. This allows spaczz pipeline components to integrate directly into spaCy pipelines, enabling them to be saved and loaded as part of a standard spaCy model.

  3. Integrate SpaczzRuler into a spaCy pipeline

    main

    The SpaczzRuler is a pipeline component (similar to EntityRuler) that integrates FuzzyMatcher, RegexMatcher, and TokenMatcher into a single workflow. It handles overlapping matches and can automatically update doc.ents.

    Pattern Format: Patterns must be an iterable of dictionaries with the following keys:

    • label (str): The entity label.
    • pattern (str or list): The pattern to match.
    • type (str): The matcher type ("fuzzy", "regex", or "token").
    • kwargs (dict, optional): Configuration for the specific matcher.
    • id (str, optional): An identifier.

    Example Pattern Types:

    • Fuzzy phrase: {'label': 'ORG', 'pattern': 'Apple', 'type': 'fuzzy', 'kwargs': {'min_r2': 90}}
    • Token pattern: {'label': 'ORG', 'pattern': [{'TEXT': {'FUZZY': 'Apple'}}], 'type': 'token'}
    • Regex pattern: {'label': 'STREET', 'pattern': 'street_addresses', 'type': 'regex', 'kwargs': {'predef': True}}
    import spacy
    from spaczz.pipeline import SpaczzRuler
    
    nlp = spacy.blank("en")
    text = "..."
    doc = nlp(text)
    
    patterns = [
        {"label": "NAME", "pattern": "Grant Andersen", "type": "fuzzy", "kwargs": {"fuzzy_func": "token_sort"}},
        {"label": "STREET", "pattern": "street_addresses", "type": "regex", "kwargs": {"predef": True}},
        {"label": "GPE", "pattern": "Nashville", "type": "fuzzy"},
        {"label": "ZIP", "pattern": r"\b(?:55554){s<=1}(?:(?:[-\s])?\d{4}\b)", "type": "regex"},
        {"label": "BAND", "pattern": [{"LOWER": {"FREGEX": "(converge){e<=1}"}}], "type": "token"},
    ]
    
    ruler = SpaczzRuler(nlp)
    ruler.add_patterns(patterns)
    doc = ruler(doc)
  4. Set up spaczz development environment

    main

    To contribute to spaczz, fork the repository and install the project and its development dependencies using Poetry. You will also need to install the en_core_web_md spaCy model separately for testing and documentation examples.

    Follow these steps within the spaczz root directory:

    1. Install dependencies: poetry install
    2. Install pre-commit hooks: pre-commit install
    3. Download the required spaCy model: poetry run python -m spacy download "en_core_web_md"
    poetry install
    pre-commit install
    poetry run python -m spacy download "en_core_web_md"
  5. Define Spaczz patterns for SpaczzRuler

    main

    Patterns for the SpaczzRuler are defined as dictionaries with specific keys. The type key determines which matcher is used:

    • fuzzy: Uses FuzzyMatcher. The pattern is a string (or Doc). You can provide optional kwargs for matcher-specific settings (e.g., min_r2).
    • regex: Uses RegexMatcher. The pattern is a regex string. You can provide optional kwargs.
    • token: Uses TokenMatcher. The pattern is a list of token patterns (compatible with spaCy's Matcher).

    All patterns can optionally include an id string to separate entity IDs from labels using the ent_id_sep (default ||).

    # Fuzzy phrase pattern
    {
        'label': 'ORG',
        'pattern': 'Apple',
        'kwargs': {'min_r2': 90},
        'type': 'fuzzy',
    }
    
    # Token pattern
    {
        'label': 'ORG',
        'pattern': [{'TEXT': {'FUZZY': 'Apple'}}],
        'type': 'token',
    }
    
    # Regex pattern
    {
        'label': 'STREET',
        'pattern': 'street_addresses',
        'type': 'regex',
        'kwargs': {'predef': True},
    }
  6. How phrase matching optimization (flexing) works

    main

    The PhraseSearcher uses a two-stage process to find high-quality phrase matches:

    1. Scanning (_scan): The searcher iterates through the Doc in chunks of the same length as the query. It identifies any chunk where the match ratio is at least min_r1.
    2. Optimization (_optimize): For each candidate found in the scan, the searcher attempts to "flex" the boundaries. It expands the start and end indices of the match by up to flex tokens in both directions (left, right, or both) to see if a larger or more accurate span yields a higher match ratio.

    If the optimized match ratio meets the min_r2 requirement, the match is kept. Finally, filter_overlapping_matches is used to ensure the returned results do not overlap, prioritizing matches with higher ratios or earlier positions.

  7. Use SpaczzRuler in a spaCy pipeline

    main

    The SpaczzRuler is a spaCy pipeline component that adds fuzzy, regex, and token-based matches to Doc.ents. It can be used alongside statistical NER models or the standard spaCy EntityRuler to improve entity recognition accuracy. You can add it to an existing nlp object using nlp.add_pipe("spaczz_ruler") or instantiate it directly.

    import spacy
    from spaczz.pipeline import SpaczzRuler
    
    nlp = spacy.blank("en")
    ruler = SpaczzRuler(nlp)
    ruler.add_patterns([{
        "label": "NAME", 
        "pattern": "Grant Andersen",
        "type": "fuzzy", 
        "kwargs": {"fuzzy_func": "token_sort"}
    }])
    
    # Add to pipeline
    nlp.add_pipe("spaczz_ruler", config={"patterns": [...]})
    
    doc = nlp("My name is Anderson, Grunt")
    # Matches are now in doc.ents
  8. Setup the SpaczzRuler pipeline

    main

    To use spaczz with spaCy, add the spaczz_ruler to your spaCy pipeline and provide patterns. Patterns for fuzzy matching must include "type": "fuzzy".

    Example setup:

    import spacy
    from spaczz.pipeline import SpaczzRuler
    
    # Create a blank English model
    nlp = spacy.blank("en")
    
    # Add the spaczz_ruler to the pipeline
    spaccz_ruler = nlp.add_pipe("spaczz_ruler")
    
    # Define patterns
    fuzzy_patterns = [
        {
            "label": "COUNTRY",
            "pattern": "Egypt",
            "type": "fuzzy",
            "id": "Egypt",
        }
    ]
    
    # Add patterns to the ruler
    spaccz_ruler.add_patterns(fuzzy_patterns)
    import spacy
    from spaczz.pipeline import SpaczzRuler
    
    nlp = spacy.blank("en")
    spaccz_ruler = nlp.add_pipe("spaczz_ruler")
    spaccz_ruler.add_patterns(fuzzy_patterns)
  9. Initialize spaczz custom spaCy attributes

    main

    To use the custom attributes provided by spaczz on spaCy Doc, Span, and Token objects, you must first call SpaczzAttrs.initialize(). This registers the spaczz_ prefixed extensions. If these extensions have already been registered (e.g., by another part of your application), a warning of type AttrOverwriteWarning will be issued, and the attributes will be force-overwritten.

    from spaczz.customattrs import SpaczzAttrs
    
    # Register the custom attributes on spaCy objects
    SpaczzAttrs.initialize()
  10. Optimize performance for FuzzyMatcher and SimilarityMatcher

    main

    Because spaczz is written in pure Python and does not currently utilize spaCy vocabularies, it may be slower and more memory-intensive than native spaCy components.

    To speed up FuzzyMatcher and SimilarityMatcher, you can adjust the following parameters, noting that these changes may impact match quality:

    • Decrease the flex parameter towards 0.
    • If flex > 0, increase the min_r1 parameter towards the value of min_r2.
    • If flex > 0, lower the thresh parameter towards min_r2.

    Additionally, utilizing a GPU may help speed up the matching process for SimilarityMatcher.

  11. Use FuzzyMatcher for fuzzy phrase matching

    main

    The FuzzyMatcher allows for fuzzy matching of phrases in a spaCy Doc. It is similar to spaCy's PhraseMatcher but returns additional information: the fuzzy ratio and the matched pattern.

    Note: Unlike spaCy matchers, spaczz matchers are written in pure Python and require a spaCy vocab during initialization. Because they are pure Python, the match_id returned is a string rather than an integer.

    When unpacking results, you must include variables for the ratio and the pattern: for match_id, start, end, ratio, pattern in matches:

    import spacy
    from spaczz.matcher import FuzzyMatcher
    
    nlp = spacy.blank("en")
    text = """Grint M Anderson created spaczz in his home at 555 Fake St,
    Apt 5 in Nashv1le, TN 55555-1234 in the US."""
    doc = nlp(text)
    
    matcher = FuzzyMatcher(nlp.vocab)
    matcher.add("NAME", [nlp("Grant Andersen")])
    matcher.add("GPE", [nlp("Nashville")])
    matches = matcher(doc)
    
    for match_id, start, end, ratio, pattern in matches:
        print(match_id, doc[start:end], ratio, pattern)