probablepeople

repository·main·Indexed 20 days ago

https://github.com/datamade/probablepeople

A Python library for parsing romanized names and companies using advanced NLP methods (Conditional Random Fields via parserator). It provides the `parse()` method for granular token-label tuples and the `tag()` method for structured entity extraction into OrderedDicts. The library supports generic, person, and company model types, which can be re-trained using the parserator CLI tool to improve accuracy on specific formats.

Tokens
3.3K
Snippets
13
Records
15
Agent score
70%

What's inside probablepeople

  1. Re-train the probablepeople model

    main

    After adding new labeled training data, you must re-train the model using parserator train. You can train specific model files (person, company, or generic) by pointing to the corresponding XML training files. To train a generic model that handles both, separate the training files with a comma.

    Training Commands:

    • Generic model (both people and companies): parserator train name_data/labeled/person_labeled.xml,name_data/labeled/company_labeled.xml probablepeople --modelfile=generic

    • Person model only: parserator train name_data/labeled/person_labeled.xml probablepeople --modelfile=person

    • Company model only: parserator train name_data/labeled/company_labeled.xml probablepeople --modelfile=company

    parserator train [traindata] probablepeople
  2. How to add labeled training data using parserator

    main

    If the parser fails on specific formats, you can improve it by adding labeled training data using the parserator tool.

    1. Prepare a CSV file ([infile]) containing your raw, unlabeled strings.
    2. Run the parserator label command to start a console-based labeling task. This will prompt you to manually label the strings.
    3. Specify the appropriate output XML file based on the entity type:
      • For people: name_data/labeled/labeled.xml
      • For companies: name_data/labeled/company_labeled.xml

    Example command:

    parserator label my_companies.csv name_data/labeled/company_labeled.xml probablepeople
    parserator label [infile] [outfile] probablepeople
  3. Handle RepeatedLabelError

    main

    If the tag method encounters multiple tokens with the same label that cannot be merged into a single key in the resulting OrderedDict, it raises a probablepeople.RepeatedLabelError.

    This error object provides two useful attributes for debugging or custom handling:

    • original_string: The raw input string.
    • parsed_string: The output of the parse method for that input.

    Example handling:

    try:
        tagged_name, name_type = probablepeople.tag(string)
    except probablepeople.RepeatedLabelError as e:
        # Use e.parsed_string and e.original_string to handle the error
        some_special_instructions(e.parsed_string, e.original_string)
  4. Use the tag method for structured entity extraction

    main

    The pp.tag() method provides a higher-level abstraction than parse(). It attempts to be 'smarter' by:

    1. Merging consecutive components of the same type.
    2. Stripping unnecessary characters like commas.
    3. Returning an OrderedDict of labels to values and identifying the overall entity type (e.g., 'Person' or 'Corporation').
    import probablepeople as pp
    name_str='Mr George "Gob" Bluth II'
    corp_str='Sitwell Housing Inc'
    
    # Returns (OrderedDict, entity_type)
    pp.tag(name_str) 
    # expected output: (OrderedDict([('PrefixMarital', 'Mr'), ('GivenName', 'George'), ('Nickname', '"Gob"'), ('Surname', 'Bluth'), ('SuffixGenerational', 'II')]), 'Person')
    
    pp.tag(corp_str) 
    # expected output: (OrderedDict([('CorporationName', 'Sitwell Housing'), ('CorporationLegalType', 'Inc')]), 'Corporation')
  5. Use the parse method to split strings into components

    main

    The pp.parse() method splits a name or company string into a list of tuples. Each tuple contains the individual component string and its corresponding label (e.g., GivenName, Surname, CorporationName). This is useful when you need the granular breakdown of every part of the string.

    import probablepeople as pp
    name_str='Mr George "Gob" Bluth II'
    corp_str='Sitwell Housing Inc'
    
    # Returns a list of (component, label) tuples
    pp.parse(name_str) 
    # expected output: [('Mr', 'PrefixMarital'), ('George', 'GivenName'), ('"Gob"', 'Nickname'), ('Bluth', 'Surname'), ('II', 'SuffixGenerational')]
    
    pp.parse(corp_str) 
    # expected output: [('Sitwell', 'CorporationName'), ('Housing', 'CorporationName'), ('Inc', 'CorporationLegalType')]
  6. Use the tag method to get structured name data

    main

    The tag method returns a tuple containing:

    1. An OrderedDict where keys are distinct labels and values are the concatenated parts of the string for that label.
    2. A string representing the detected type: 'Person', 'Household', or 'Corporation'.

    Note: Because tag uses labels as keys, it will raise a RepeatedLabelError if multiple parts of the string share the same label and cannot be merged.

    import probablepeople
    
    # Example: Tagging a person
    print(probablepeople.tag('Mr George "Gob" Bluth II'))
    # Output: (OrderedDict([('PrefixMarital', 'Mr'), ('GivenName', 'George'), ('Nickname', '"Gob"'), ('Surname', 'Bluth'), ('SuffixGenerational', 'II')]), 'Person')
    
    # Example: Tagging a household
    print(probablepeople.tag('Lucille & George Bluth'))
    # Output: (OrderedDict([('GivenName', 'Lucille'), ('And', '&'), ('SecondGivenName', 'George'), ('Surname', 'Bluth')]), 'Household')
    
    # Example: Tagging a corporation
    print(probablepeople.tag('Sitwell Housing Inc'))
    # Output: (OrderedDict([('CorporationName', 'Sitwell Housing'), ('CorporationLegalType', 'Inc')]), 'Corporation')
  7. Specify name type in parse and tag methods

    main

    If you already know whether a string refers to a person or a company, you can pass the type argument to the parse or tag methods to guide the NLP model.

    Valid options for type are:

    • 'person'
    • 'company'
    import probablepeople
    
    # Forcing a household string to be treated as a person
    print(probablepeople.tag('Lucille & George Bluth', type='person'))
    
    # Forcing a string to be treated as a company
    print(probablepeople.tag('Lucille & George Bluth', type='company'))
    # Output: (OrderedDict([('CorporationName', 'Lucille & George Bluth')]), 'Corporation')
  8. Reference: Available name and company labels

    main

    The following labels are used by probablepeople during the parsing process:

    * PrefixMarital
    * PrefixOther
    * GivenName
    * FirstInitial
    * MiddleName
    * MiddleInitial
    * Surname
    * LastInitial
    * SuffixGenerational
    * SuffixOther
    * Nickname
    * And
    * CorporationName
    * CorporationNameOrganization
    * CorporationLegalType
    * CorporationNamePossessiveOf
    * ShortForm
    * ProxyFor
    * AKA
  9. Troubleshoot missing model files

    main

    If you encounter an OSError stating MISSING MODEL FILE, it means the required .crfsuite files have not been generated. The library does not ship with pre-trained models; they must be trained using the parserator CLI tool.

    To train the model and create the necessary files, run:

    parserator train [traindata] [modulename]

    Common model file names include:

    • generic_learned_settings.crfsuite
    • person_learned_settings.crfsuite
    • company_learned_settings.crfsuite
  10. Extract structured name data with tag()

    main

    The tag function is the primary high-level method for extracting structured information from a name string. It returns a dictionary of components and a classification of the name type.

    Parameters:

    • raw_string (str): The name string to process.
    • type (str, optional): The model type to use (generic, person, or company). Defaults to generic.

    Returns:

    • tuple[dict[str, str], str]: A tuple containing:
      1. A dictionary where keys are labels (e.g., GivenName, Surname) and values are the extracted component strings.
      2. A string representing the name_type (Person, Corporation, or Household).

    Logic for name_type:

    • Corporation: If CorporationName or ShortForm labels are present.
    • Household: If the And label is present.
    • Person: Default case.
    from probablepeople import tag
    
    # Returns (components_dict, name_type)
    data, name_type = tag("John and Jane Doe")
    print(data)
    # Example: {'GivenName': 'John', 'And': 'and', 'GivenName': 'Jane', 'Surname': 'Doe'}
    print(name_type)
    # Output: 'Household'
  11. Parse strings into name components with parse()

    main

    The parse function splits a raw string into a list of tuples, where each tuple contains a (token, label) pair. This is useful for low-level inspection of how the library identifies specific parts of a name (e.g., GivenName, Surname, Suffix).

    Parameters:

    • raw_string (str): The name string to parse.
    • type (str, optional): The model type to use. Options are generic, person, or company. Defaults to generic.

    Returns:

    • list[tuple[str, str]]: A list of (token, label) tuples.

    Note: You must have trained the model files (e.g., generic_learned_settings.crfsuite) before calling this function. If the model is missing, an OSError is raised.

    from probablepeople import parse
    
    # Returns list of (token, label) tuples
    results = parse("John Doe")
    # Example output: [("John", "GivenName"), ("Doe", "Surname")]