o
    iE                  
   @   s8  d Z ddlZddlZddlZddlmZmZmZmZ ddl	m
Z
mZ eeZe
G dd dZG dd dZed	kre Zd
ZejeddZedee d eedD ]C\ZZede dej dejdd  d edej  edej  ejredej  ejredej  e  qVdS dS )uo   
命题级切片器模块
实现自适应的命题级文本切分，支持税法文档的多层级结构切分
    N)ListOptionalDictAny)	dataclassfieldc                   @   s   e Zd ZU dZeed< eed< dZee ed< dZeed< dZ	ee ed< dZ
ee ed	< d
Zeed< dZee ed< dZee ed< eedZeeef ed< dd ZdS )PropositionChunku   命题切片数据结构chunk_idtextN	parent_idsentencelevelarticle_numberchapter_numberr   
char_countprev_chunk_idnext_chunk_id)default_factorymetadatac                 C   s   | j dkrt| j| _ d S d S )Nr   )r   lenr
   )self r   S/lsinfo/ai/hellotax_ai/base_platform/app/services/knowledge/proposition_splitter.py__post_init__   s   
zPropositionChunk.__post_init__)__name__
__module____qualname____doc__str__annotations__r   r   r   r   r   r   intr   r   r   dictr   r   r   r   r   r   r   r   r      s   
 r   c                   @   s  e Zd ZdZedZedZedZd5de	d	e	d
e	fddZ
d6dededee fddZdefddZdee dedee fddZdedee fddZdedeej dee fddZdededee fd d!Zded"eej dee fd#d$Zd%ed&edee d'ee dee f
d(d)Zdedee fd*d+Zdedee fd,d-Zdedee fd.d/Zdee dee fd0d1Zdee dd2fd3d4Zd2S )7AdaptivePropositionSplitteru   自适应命题级切片器u0   第[一二三四五六七八九十百千万]+章u0   第[一二三四五六七八九十百千万]+条u   第[一二三四五六七八九十百千万]+款|（[一二三四五六七八九十百千万]+）|\([一二三四五六七八九十百千万]+\)        min_sizemax_sizetarget_sizec                 C   s   || _ || _|| _dS )u   
        初始化切片器

        Args:
            min_size: 最小切片大小（字符数）
            max_size: 最大切片大小（字符数）
            target_size: 目标切片大小（字符数）
        N)r&   r'   r(   )r   r&   r'   r(   r   r   r   __init__*   s   	
z$AdaptivePropositionSplitter.__init__lawr
   doc_typereturnc                 C   s   |r|  sg S | |\}}|dkr| |}n|dkr#| |}n|dv r-| |}n| |}|r:| ||}| | |S )u   
        切分文本

        Args:
            text: 要切分的文本
            doc_type: 文档类型 ('law'/'announcement'/'case'/'practice')

        Returns:
            切片列表
        r*   announcement)casepractice)strip_extract_tables_split_law_document_split_by_paragraph_split_by_heading_restore_tables_link_chunks)r   r
   r+   table_placeholderschunksr   r   r   split7   s   

z!AdaptivePropositionSplitter.splitc                    sJ   ddl }i dg |d fdd}|jd||jd}|fS )u   
        将文本中的 <table>...</table> 替换为占位符，返回 (处理后文本, 占位符字典)
        同时记录每个表格前最近的章/条标题作为上下文
        r   NuL   (第[一二三四五六七八九十百千万\d]+[章条][\s　]*[^\n]{0,30})c                    s|    d } d  d7  < d| d}d |    }t|}|r,|d d nd}| d|dd| d	< |S )
Nr      z


__TABLE_z__

 )htmlcontext_prefix__TABLE___)startlistfinditergroupr0   )midxplaceholderprefix_textheading_matchesr>   counterheading_patternplaceholdersr
   r   r   replace_tableg   s   zBAdaptivePropositionSplitter._extract_tables.<locals>.replace_tablez<table[\s\S]*?</table>)flags)recompilesub
IGNORECASE)r   r
   rP   rN   	processedr   rJ   r   r1   [   s   
z+AdaptivePropositionSplitter._extract_tablesr8   rM   c                    s   ddl }g }|D ]^}|d|j}|rE|d} |}|rD|d r+d|d  dnd}	|	|d	  |_t|j|_d
|jd< || q fdd}
|	d|
|j}||jkra||_t|j|_|| q|S )uo   
        将 chunks 中的占位符还原为 HTML 表格，并在表格 chunk 前追加章节上下文
        r   Nz\s*(__TABLE_\d+__)\s*r:   r>   u   【u   】

r<   r=   Tis_tablec                    s*   |  d} |i }d|dd d S )Nr:   z

r=   r<   )rD   get)m2keyinforM   r   r   inline_replace   s   
zCAdaptivePropositionSplitter._restore_tables.<locals>.inline_replacez(__TABLE_\d+__))
rP   	fullmatchr
   rD   rV   r   r   r   appendrR   )r   r8   rM   rP   resultchunkrE   rX   rY   prefixr[   new_textr   rZ   r   r5   z   s*   




z+AdaptivePropositionSplitter._restore_tablesc                 C   sZ   g }t | j|}|r| ||}|S t | j|}|r&| ||}|S | |}|S )u3   切分法律文档（章→条→款三级结构）)rB   CHAPTER_PATTERNrC   _split_by_chapterARTICLE_PATTERN_split_by_articler3   )r   r
   r8   chapter_matchesarticle_matchesr   r   r   r2      s   

z/AdaptivePropositionSplitter._split_law_documentrf   c              
   C   s  g }|d   dkr+|d|d     }|r+tt }|t||dddid t|D ]O\}}|  }|d t|k rG||d    nt|}	|||	  }
|	 }t|
| j
krj| |
|}|| q/tt }|t||
d|d|id q/|S )	u   按章切分r   Npreambletyper	   r
   r   r   r:   chapterr	   r
   r   r   r   )rA   r0   r   uuiduuid4r]   r   	enumerater   rD   r'   _split_chapter_by_articleextend)r   r
   rf   r8   rh   r	   imatchrA   endchapter_textr   
sub_chunksr   r   r   rc      s8   (
z-AdaptivePropositionSplitter._split_by_chapterru   r   c                 C   sR  g }t t }t| j|}|s"|t||d|d|id |S |d  dkrN|d|d   	 }|rNt t }|t|||d||ddd t
|D ]T\}}	|	 }
|d	 t|k rj||d	   nt|}||
| 	 }|	 }t|| jkr| ||||}|| qRt t }|t|||d
||||dd qR|S )u   将章节按条切分rk   rl   r   Nchapter_headerheader)rk   ri   )r	   r
   r   r   r   r   r:   articlery   rk   r	   r
   r   r   r   r   r   )r   rm   rn   rB   rd   rC   r]   r   rA   r0   ro   r   rD   r'   _split_article_by_clauserq   )r   ru   r   r8   r   rg   rx   r	   rr   rs   rA   rt   article_textr   rv   r   r   r   rp      sV   
(

z5AdaptivePropositionSplitter._split_chapter_by_articlerg   c              
   C   s  g }|d   dkr+|d|d     }|r+tt }|t||dddid t|D ]Q\}}|  }|d t|k rG||d    nt|}	|||	  }
|	 }t|
| j
krl| |
|dd}|| q/tt }|t||
d|d|id q/|S )	u   按条切分r   Nrh   ri   rj   r:   ry   )r	   r
   r   r   r   )rA   r0   r   rm   rn   r]   r   ro   r   rD   r'   r|   rq   )r   r
   rg   r8   rh   r	   rr   rs   rA   rt   r}   r   rv   r   r   r   re     s8   (
z-AdaptivePropositionSplitter._split_by_articler}   r   r   c                 C   s>  g }t | j|}|s/| |}|D ]}tt }	|t|	||d||||dd q|S |d 	 dkr]|d|d 	  
 }
|
r]tt }	|t|	|
|d||||ddd t|D ];\}}|	 }|d	 t|k ry||d	  	 nt|}||| 
 }tt }	|t|	||d
||||dd qa|S )u   将条文按款切分ry   rz   r{   r   Narticle_headerrx   )ry   rk   ri   r:   clause)rB   CLAUSE_PATTERNrC   _split_by_paragraph_rawr   rm   rn   r]   r   rA   r0   ro   r   )r   r}   r   r   r   r8   clause_matches
paragraphsparar	   rx   rr   rs   rA   rt   clause_textr   r   r   r|   8  sX   

	
(

z4AdaptivePropositionSplitter._split_article_by_clausec              	   C   sL   |  |}| |}g }|D ]}tt }|t||dddid q|S )u$   按段落切分（带滑动窗口）	paragraphri   rj   r   _adaptive_merger   rm   rn   r]   r   )r   r
   r   mergedr8   r   r	   r   r   r   r3   v  s   


z/AdaptivePropositionSplitter._split_by_paragraphc                 C   s   t d|}dd |D S )u   按段落切分（原始）z\n\n+|\nc                 S   s   g | ]
}|  r|  qS r   )r0   ).0pr   r   r   
<listcomp>  s    zGAdaptivePropositionSplitter._split_by_paragraph_raw.<locals>.<listcomp>)rP   r9   )r   r
   r   r   r   r   r     s   z3AdaptivePropositionSplitter._split_by_paragraph_rawc              	   C   sL   g }|  |}| |}|D ]}tt }|t||dddid q|S )u4   按标题层级切分（用于案例/实务文档）sectionri   rj   r   )r   r
   r8   r   r   r   r	   r   r   r   r4     s   


z-AdaptivePropositionSplitter._split_by_headingc                 C   s   |sg S g }d}|D ]2}|s|}q
t |t | d | jkr%|d| 7 }q
t || jks.|s6|| |}q
|d| 7 }q
|rY|rTt || jk rT|d  d| 7  < |S || |S )u*   自适应合并过短片段到目标大小r<   r:   
r;   )r   r(   r&   r]   )r   r8   r   currentr_   r   r   r   r     s&   

z+AdaptivePropositionSplitter._adaptive_mergeNc                 C   sV   t t|D ]"}|dkr||d  j|| _|t|d k r(||d  j|| _qdS )u!   建立切片之间的链接关系r   r:   N)ranger   r	   r   r   )r   r8   rr   r   r   r   r6     s   z(AdaptivePropositionSplitter._link_chunks)r#   r$   r%   )r*   )r   r   r   r   rP   rQ   rb   rd   r   r    r)   r   r   r   r9   r1   r!   r5   r2   Matchrc   rp   re   r   r|   r3   r   r4   r   r6   r   r   r   r   r"   "   s:    


$" ' 9'
>!r"   __main__u  第一章 总则
第一条 本法适用于中华人民共和国境内的企业和其他取得收入的组织。
第二条 本法所称企业，是指依法在中国境内成立的企业、事业单位、社会团体以及其他取得收入的组织。
第二章 税率
第三条 企业所得税的税率为25%。
第四条 符合条件的小型微利企业，减按20%的税率征收企业所得税。r*   )r+   u   切分结果：共 u    个切片
r:   [z] z: 2   z...z    ID: u       字符数: u       章节: u       条文: ) r   rP   rm   loggingtypingr   r   r   r   dataclassesr   r   	getLoggerr   loggerr   r"   splitter	test_textr9   r8   printr   ro   rr   cr   r
   r	   r   r   r   r   r   r   r   <module>   s:    
   +(