Which may be very useful to extract long entities / spans which usually are not extracted properly with traditional NER models
! pip install -q johnsnowlabs
Using my.johnsnowlabs.com SSO
from johnsnowlabs import nlp, legal
# nlp.install(force_browser=True)
If you are not registered in my.johnsnowlabs.com, you received a license via e-email or you are using Safari, you may need to do a manual update of the license.
from google.colab import files
print('Please Upload your John Snow Labs License using the button below')
license_keys = files.upload()
nlp.install()
spark = nlp.start()
Legal documents are known to be very long. Although you can divide the docuuments into paragraphs or sections, and those into sentences, the resulted sentences are still long.
Let's take a look at this example:
Buyer shall use such materials and supplies only in accordance with the present agreement
Not, let's imagine we want to extract three entities:
Buyer
)shall use
)such materials and supplies only in accordance with the present agreement
)Although Subject and Action can be totally manageable by traditional NER, it usually struggles the longer the spans are. Trying to model the extraction of Object with a simple NER may result in word fading, when some of the initial or ending words fade into O
.
We present in this notebook a solution for Long Span Extraction: Using an Automatic Question Generator and a Question Answering model to:
Subject
and the Action
.Example: Buyer - SUBJECT
, shall use - OBJECT
Object
, using Subject
and Action
;Example: What shall the Buyer use?
Object
, without the limitations of traditional NER;Example: What shall the Buyer use? such materials and supplies only in accordance with the present agreement
Last, but not least, it's very important to chose a domain-specific Question Answering model.
What?
¶Let's suppose we have the sentence of the example:
The Buyer shall use such materials and supplies only in accordance with the present agreement
In Spark NLP for Legal, we have a trained NER model which is able to extract Subjects (Buyer
) and Actions (shall use
) of agreements / obligations with good accuracy.
It's also trained for extracting the Object
using NER, but it's usage is limited due to the restrictions commented above.
Let's get SUBJECT and ACTION and automatically create a question with them.
text = """The Buyer shall use such materials and supplies only in accordance with the present agreement"""
import pandas as pd
documentAssembler = nlp.DocumentAssembler()\
.setInputCol("text")\
.setOutputCol("document")
sparktokenizer = nlp.Tokenizer()\
.setInputCols("document")\
.setOutputCol("token")
tokenClassifier = legal.BertForTokenClassification.pretrained("legner_obligations", "en", "legal/models")\
.setInputCols("token", "document")\
.setOutputCol("label")\
.setCaseSensitive(True)
nerconverter = nlp.NerConverter()\
.setInputCols(["document", "token", "label"])\
.setOutputCol("ner_chunk")
# setEntities1 says which entity from NER goes first in the question
# setEntities2 says which entity from NER goes second in the question
# setQuestionMark to True adds a '?' at the end of the sentence (after entity 2)
# To sum up, the pattern is [QUESTIONPRONOUN] [ENTITY1] [ENTITY2] [QUESTIONMARK]
qagenerator = legal.NerQuestionGenerator()\
.setInputCols(["ner_chunk"])\
.setOutputCol("question")\
.setQuestionMark(False)\
.setQuestionPronoun("What")\
.setEntities1(["OBLIGATION_SUBJECT"])\
.setEntities2(["OBLIGATION_ACTION"])
qa =nlp.BertForQuestionAnswering.pretrained("legqa_bert_large","en", "legal/models") \
.setInputCols(["question", "document"]) \
.setOutputCol("answer") \
.setCaseSensitive(True)
pipeline = nlp.Pipeline(stages=[
documentAssembler,
sparktokenizer,
tokenClassifier,
nerconverter,
qagenerator,
qa
]
)
p_model = pipeline.fit(spark.createDataFrame(pd.DataFrame({'text': ['']})))
res = p_model.transform(spark.createDataFrame([[text]]).toDF("text"))
legner_obligations download started this may take some time. [OK!] legqa_bert_large download started this may take some time. Approximate size to download 1.2 GB [OK!]
res.select('question.result').show(truncate=False)
+-----------------------+ |result | +-----------------------+ |[What Buyer shall use ]| +-----------------------+
res.select('answer.result').show(truncate=False)
+-------------------------------------------------+ |result | +-------------------------------------------------+ |[The Buyer shall use such materials and supplies]| +-------------------------------------------------+
Let's get 4 additional examples
texts = [
"""The Buyer shall use such materials and supplies only in accordance with the present agreement""",
"""The Provider will notify the Buyer about the release date""",
"""Amazon agrees to supply 1-year license without fees""",
"""The Supplier should ship the product in less than 1 month"""
]
pdf = pd.DataFrame(texts, columns = ["text"])
pdf
text | |
---|---|
0 | The Buyer shall use such materials and supplie... |
1 | The Provider will notify the Buyer about the r... |
2 | Amazon agrees to supply 1-year license without... |
3 | The Supplier should ship the product in less t... |
df = spark.createDataFrame(pdf)
res = p_model.transform(df)
res.select('question.result', 'answer.result').show(truncate=False)
+-------------------------------+-----------------------------------------------------------+ |result |result | +-------------------------------+-----------------------------------------------------------+ |[What Buyer shall use ] |[The Buyer shall use such materials and supplies] | |[What Provider will notify ] |[The Provider will notify the Buyer about the release date]| |[What Amazon agrees to supply ]|[1 - year license without fees] | |[What Supplier should ship ] |[The Supplier should ship the product in less than 1 month]| +-------------------------------+-----------------------------------------------------------+
To whom?
¶Let's try to get now the Indirect Object. That is, the recipient of an action. For example, to whom a supplier should send a shipment.
qagenerator = legal.NerQuestionGenerator()\
.setInputCols(["ner_chunk"])\
.setOutputCol("question")\
.setQuestionMark(False)\
.setQuestionPronoun("To whom")\
.setEntities1(["OBLIGATION_ACTION"])\
.setEntities2(["OBLIGATION_SUBJECT"])
pipeline = nlp.Pipeline(stages=[
documentAssembler,
sparktokenizer,
tokenClassifier,
nerconverter,
qagenerator,
qa
]
)
p_model = pipeline.fit(spark.createDataFrame(pd.DataFrame({'text': ['']})))
text = """The Provider shall send the shipment to the Buyer"""
res = p_model.transform(spark.createDataFrame([[text]]).toDF("text"))
res.select('text', 'question.result', 'answer.result').show(truncate=False)
+-------------------------------------------------+------------------------------+-----------------------------------------------+ |text |result |result | +-------------------------------------------------+------------------------------+-----------------------------------------------+ |The Provider shall send the shipment to the Buyer|[To whom shall send Provider ]|[Provider shall send the shipment to the Buyer]| +-------------------------------------------------+------------------------------+-----------------------------------------------+
This approach works very well also with other clauses and phrases, as temporal ones. Let's try to ask for the deadline of a contract
qagenerator = legal.NerQuestionGenerator()\
.setInputCols(["ner_chunk"])\
.setOutputCol("question")\
.setQuestionMark(False)\
.setQuestionPronoun("Before when")\
.setEntities1(["OBLIGATION_ACTION"])\
.setEntities2(["OBLIGATION_SUBJECT"])
pipeline = nlp.Pipeline(stages=[
documentAssembler,
sparktokenizer,
tokenClassifier,
nerconverter,
qagenerator,
qa
]
)
p_model = pipeline.fit(spark.createDataFrame(pd.DataFrame({'text': ['']})))
text = """The customer should sign the contract before May, 2023"""
res = p_model.transform(spark.createDataFrame([[text]]).toDF("text"))
res.select('text', 'question.result', 'answer.result').show(truncate=False)
+------------------------------------------------------+-----------------------------------+-------------------+ |text |result |result | +------------------------------------------------------+-----------------------------------+-------------------+ |The customer should sign the contract before May, 2023|[Before when should sign customer ]|[before May , 2023]| +------------------------------------------------------+-----------------------------------+-------------------+