| from __future__ import annotations |
|
|
| from dataclasses import dataclass, asdict |
| from typing import List, Optional |
|
|
|
|
| |
| |
| |
|
|
| @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] |
|
|
|
|
| |
| |
| |
|
|
| class LegalChunker: |
|
|
| def __init__( |
| self, |
| document_name: str = "BNSS" |
| ): |
| self.document_name = document_name |
|
|
| |
| |
| |
|
|
| 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) |
|
|
| |
| |
| |
|
|
| 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", |
| "" |
| ) |
|
|
| |
| |
| |
|
|
| 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 |
| ) |
| ) |
|
|
| |
| |
| |
|
|
| 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 |
| ) |
| ) |
|
|
| |
| |
| |
|
|
| 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 |
| ) |
| ) |
|
|
| |
| |
| |
|
|
| 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 |
| ) |
| ) |
|
|
| |
| |
| |
|
|
| 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 |
|
|
|
|
| |
| |
| |
|
|
| def chunks_to_dicts( |
| chunks: List[LegalChunk] |
| ): |
|
|
| return [ |
| asdict(chunk) |
| for chunk in chunks |
| ] |