Legora / db /parsers /bnss /chunker.py
sai-Rohan's picture
combined results of all parsers and made a single pipeline
dbabef2
Raw
History Blame Contribute Delete
17 kB
from __future__ import annotations
from dataclasses import dataclass, asdict
from typing import List, Optional
# =========================================================
# CHUNK MODEL
# =========================================================
@dataclass
class LegalChunk:
chunk_id: str
level: str
document: str
chapter_no: Optional[str]
chapter_title: Optional[str]
section_no: Optional[str]
clause_no: Optional[str]
sub_clause_no: Optional[str]
roman_no: Optional[str]
title: str
text: str
enriched_text: str
parent_id: Optional[str]
root_section_id: Optional[str]
path: Optional[str]
# =========================================================
# CHUNKER
# =========================================================
class LegalChunker:
def __init__(
self,
document_name: str = "BNSS"
):
self.document_name = document_name
# -----------------------------------------------------
# Helpers
# -----------------------------------------------------
def build_context(
self,
document: str,
chapter_no: str = "",
chapter_title: str = "",
section_no: str = "",
title: str = "",
clause_no: str = "",
sub_clause_no: str = "",
roman_no: str = ""
) -> str:
parts = [document.upper()]
if chapter_no:
parts.append(
f"Chapter {chapter_no}"
)
if chapter_title:
parts.append(
chapter_title
)
if section_no:
parts.append(
f"Section {section_no}"
)
if title:
parts.append(
title
)
if clause_no:
parts.append(
f"Clause ({clause_no})"
)
if sub_clause_no:
parts.append(
f"SubClause ({sub_clause_no})"
)
if roman_no:
parts.append(
f"Roman Clause ({roman_no})"
)
return "\n".join(parts)
# -----------------------------------------------------
# Main
# -----------------------------------------------------
def chunk_document(
self,
document
) -> List[LegalChunk]:
chunks = []
document_name = getattr(
document,
"document",
self.document_name
).upper()
for chapter in document.chapters:
chapter_title = getattr(
chapter,
"title",
""
)
for section in chapter.sections:
section_id = (
f"{document_name}-"
f"{section.section_no}"
)
section_path = (
section_id
)
title = getattr(
section,
"title",
""
)
# =================================
# SECTION
# =================================
chunks.append(
LegalChunk(
chunk_id=
section_id,
level=
"section",
document=
document_name.lower(),
chapter_no=
chapter.chapter_no,
chapter_title=
chapter_title,
section_no=
section.section_no,
clause_no=
None,
sub_clause_no=
None,
roman_no=
None,
title=
title,
text=
section.text,
enriched_text=
self.build_context(
document=
document_name,
chapter_no=
chapter.chapter_no,
chapter_title=
chapter_title,
section_no=
section.section_no,
title=
title
)
+ "\n\n"
+ section.text,
parent_id=
None,
root_section_id=
section_id,
path=
section_path
)
)
# =================================
# CLAUSES
# =================================
for clause in section.clauses:
clause_id = (
f"{section_id}"
f"({clause.clause_no})"
)
clause_path = (
f"{section_path}"
f" > Clause({clause.clause_no})"
)
chunks.append(
LegalChunk(
chunk_id=
clause_id,
level=
"clause",
document=
document_name.lower(),
chapter_no=
chapter.chapter_no,
chapter_title=
chapter_title,
section_no=
section.section_no,
clause_no=
clause.clause_no,
sub_clause_no=
None,
roman_no=
None,
title=
title,
text=
clause.text,
enriched_text=
self.build_context(
document=
document_name,
chapter_no=
chapter.chapter_no,
chapter_title=
chapter_title,
section_no=
section.section_no,
title=
title,
clause_no=
clause.clause_no
)
+ "\n\n"
+ clause.text,
parent_id=
section_id,
root_section_id=
section_id,
path=
clause_path
)
)
# =============================
# SUB CLAUSES
# =============================
for sub in clause.sub_clauses:
sub_id = (
f"{clause_id}"
f"({sub.sub_clause_no})"
)
sub_path = (
f"{clause_path}"
f" > SubClause({sub.sub_clause_no})"
)
chunks.append(
LegalChunk(
chunk_id=
sub_id,
level=
"subclause",
document=
document_name.lower(),
chapter_no=
chapter.chapter_no,
chapter_title=
chapter_title,
section_no=
section.section_no,
clause_no=
clause.clause_no,
sub_clause_no=
sub.sub_clause_no,
roman_no=
None,
title=
title,
text=
sub.text,
enriched_text=
self.build_context(
document=
document_name,
chapter_no=
chapter.chapter_no,
chapter_title=
chapter_title,
section_no=
section.section_no,
title=
title,
clause_no=
clause.clause_no,
sub_clause_no=
sub.sub_clause_no
)
+ "\n\n"
+ sub.text,
parent_id=
clause_id,
root_section_id=
section_id,
path=
sub_path
)
)
# =========================
# ROMAN CLAUSES
# =========================
for roman in sub.roman_clauses:
roman_id = (
f"{sub_id}"
f"({roman.roman_no})"
)
roman_path = (
f"{sub_path}"
f" > Roman({roman.roman_no})"
)
chunks.append(
LegalChunk(
chunk_id=
roman_id,
level=
"roman",
document=
document_name.lower(),
chapter_no=
chapter.chapter_no,
chapter_title=
chapter_title,
section_no=
section.section_no,
clause_no=
clause.clause_no,
sub_clause_no=
sub.sub_clause_no,
roman_no=
roman.roman_no,
title=
title,
text=
roman.text,
enriched_text=
self.build_context(
document=
document_name,
chapter_no=
chapter.chapter_no,
chapter_title=
chapter_title,
section_no=
section.section_no,
title=
title,
clause_no=
clause.clause_no,
sub_clause_no=
sub.sub_clause_no,
roman_no=
roman.roman_no
)
+ "\n\n"
+ roman.text,
parent_id=
sub_id,
root_section_id=
section_id,
path=
roman_path
)
)
# =================================
# EXPLANATIONS
# =================================
for explanation in section.explanations:
exp_no = (
explanation.explanation_no
if explanation.explanation_no
else "UNNUMBERED"
)
explanation_id = (
f"{section_id}"
f"-EXP-{exp_no}"
)
exp_path = (
f"{section_path}"
f" > Explanation({exp_no})"
)
chunks.append(
LegalChunk(
chunk_id=
explanation_id,
level=
"explanation",
document=
document_name.lower(),
chapter_no=
chapter.chapter_no,
chapter_title=
chapter_title,
section_no=
section.section_no,
clause_no=
None,
sub_clause_no=
None,
roman_no=
None,
title=
title,
text=
explanation.text,
enriched_text=
self.build_context(
document=
document_name,
chapter_no=
chapter.chapter_no,
chapter_title=
chapter_title,
section_no=
section.section_no,
title=
title
)
+ "\n\n"
+ explanation.text,
parent_id=
section_id,
root_section_id=
section_id,
path=
exp_path
)
)
return chunks
# =========================================================
# EXPORT
# =========================================================
def chunks_to_dicts(
chunks: List[LegalChunk]
):
return [
asdict(chunk)
for chunk in chunks
]