-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
import textwrap
import langextract as lx
import fitz # PyMuPDF for PDF text extraction
prompt = textwrap.dedent("""
Extract Article, Title, Section, Content.
Use exact text for extractions. Do not paraphrase or overlap entities.
Provide meaningful attributes for each entity to add context.
""")
examples = [
lx.data.ExampleData(
text="CHAPITRE PREMIER\n\n\n\nDU TRAVAILLEUR ET DE L'EMPLOYEUR\n\nArticle premier - La présente loi est applicable à tout employeur et à tout \n\ntravailleur dont le contrat de travail, quels que soient sa forme, le lieu de sa \n\nconclusion et la résidence de l'une ou de l'autre partie, est exécuté à Madagascar. \n\nElle détermine les règles et principes applicables en matière de relations de \n\ntravail individuelles aussi bien que collectives.\n\nLes dispositions du présent Code ne sont pas applicables aux agents publics \n\nrégis par un statut général ou par un statut particulier, aux travailleurs indépendants \n\net aux travailleurs régis par le Code maritime.",
extractions=[
lx.data.Extraction(
extraction_class="title",
extraction_text="CHAPITRE PREMIER",
attributes={"type": "chapter", "level": 1}
),
lx.data.Extraction(
extraction_class="section",
extraction_text="DU TRAVAILLEUR ET DE L'EMPLOYEUR",
attributes={"type": "section_title"}
),
lx.data.Extraction(
extraction_class="article",
extraction_text="Article premier",
attributes={"number": "premier", "type": "article_header"}
),
lx.data.Extraction(
extraction_class="content",
extraction_text="La présente loi est applicable à tout employeur et à tout travailleur dont le contrat de travail, quels que soient sa forme, le lieu de sa conclusion et la résidence de l'une ou de l'autre partie, est exécuté à Madagascar.",
attributes={"article": "premier", "paragraph": 1}
),
lx.data.Extraction(
extraction_class="content",
extraction_text="Elle détermine les règles et principes applicables en matière de relations de travail individuelles aussi bien que collectives.",
attributes={"article": "premier", "paragraph": 2}
),
lx.data.Extraction(
extraction_class="content",
extraction_text="Les dispositions du présent Code ne sont pas applicables aux agents publics régis par un statut général ou par un statut particulier, aux travailleurs indépendants et aux travailleurs régis par le Code maritime.",
attributes={"article": "premier", "paragraph": 3, "exclusions": True}
),
]
),
lx.data.ExampleData(
text="Article 2 - Est considéré comme travailleur au sens du présent Code, quels \n\nque soient son sexe et sa nationalité, toute personne qui s'est engagée à mettre son \n\nactivité professionnelle, moyennant rémunération, sous la direction et l'autorité d'une \n\nautre personne physique ou morale, publique ou privée.",
extractions=[
lx.data.Extraction(
extraction_class="article",
extraction_text="Article 2",
attributes={"number": "2", "type": "article_header"}
),
lx.data.Extraction(
extraction_class="content",
extraction_text="Est considéré comme travailleur au sens du présent Code, quels que soient son sexe et sa nationalité, toute personne qui s'est engagée à mettre son activité professionnelle, moyennant rémunération, sous la direction et l'autorité d'une autre personne physique ou morale, publique ou privée.",
attributes={"article": "2", "paragraph": 1, "definition": "travailleur"}
),
]
)
]
def extract_text_from_pdf(pdf_path):
"""
Extract text from a PDF file using PyMuPDF.
Args:
pdf_path: Path to the PDF file
Returns:
str: Extracted text from the PDF
"""
doc = fitz.open(pdf_path)
text_parts = []
for page_num in range(len(doc)):
page = doc[page_num]
text = page.get_text()
text_parts.append(text)
doc.close()
return "\n".join(text_parts)
Extract text from PDF
pdf_path = r"pdf_path.pdf"
print(f"Extracting text from PDF: {pdf_path}")
pdf_text = extract_text_from_pdf(pdf_path)
print(f"Extracted {len(pdf_text)} characters from PDF")
Perform extraction using langextract
print("Starting extraction with langextract...")
result = lx.extract(
text_or_documents=pdf_text, # Pass the extracted text string
prompt_description=prompt,
examples=examples,
model_id="gemma3:4b",
model_url="http://xxxxxx:11434",
use_schema_constraints=False,
fence_output=False,
extraction_passes=3, # Improves recall through multiple passes
max_workers=20, # Parallel processing for speed
max_char_buffer=1000 # Smaller contexts for better accuracy
)
Save the results to a JSONL file
lx.io.save_annotated_documents([result], output_name="extraction_results.jsonl", output_dir=".")
Generate the visualization from the file
html_content = lx.visualize("extraction_results.jsonl")
with open("visualization.html", "w") as f:
if hasattr(html_content, 'data'):
f.write(html_content.data) # For Jupyter/Colab
else:
f.write(html_content)