o
    ?7i )                     @   sh   d Z ddlZddlmZmZ ddlmZ eeZ	G dd de
eZG dd dZdad	efd
dZdS )uQ   
文本分片服务
使用 LangChain 的 text splitters 进行文本分片处理
    N)ListOptional)Enumc                   @   s$   e Zd ZdZdZdZdZdZdZdS )SplitterTypeu   文本分片器类型	recursive	charactertokenmarkdowntax_adaptiveN)	__name__
__module____qualname____doc__	RECURSIVE	CHARACTERTOKENMARKDOWNTAX_ADAPTIVE r   r   T/lsinfo/ai/hellotax_ai/base_platform/app/services/knowledge/text_splitter_service.pyr      s    r   c                   @   s  e Zd ZdZeddejddddfdededed	ed
ede	e de	e de	e fddZ
ededededee fddZedededed
edee f
ddZededededee fddZededededee fddZedededede	e dee f
ddZededededede	e dee fddZeddejddddfdededed	ede	e de	e de	e de	e dee fdd ZdS )!TextSplitterServiceu   文本分片服务类i     

Ntext
chunk_sizechunk_overlapsplitter_type	separatordocument_titledocument_iddocument_numberc           	   
   C   s   zX|t jkrt| ||W S |t jkrt| |||W S |t jkr)t| ||W S |t jkr6t	| ||W S |t j
krHt| |pAd|pDd|W S td| d t| ||W S  tyu } ztd|  | gW  Y d}~S d}~ww )uy  
        分片文本

        Args:
            text: 要分片的文本
            chunk_size: 每个分片的大小（字符数或 token 数）
            chunk_overlap: 分片之间的重叠大小
            splitter_type: 分片器类型
            separator: 分隔符（仅用于 character 类型）
            document_title: 文档标题（用于税务分割器）
            document_id: 文档ID（用于税务自适应分割器）
            document_number: 文档编号（用于税务自适应分割器）

        Returns:
            分片后的文本列表（对于tax_adaptive，返回dict列表）
        unknown zUnknown splitter type: z", using default recursive splitterzText splitting failed: N)r   r   r   _split_recursiver   _split_characterr   _split_tokenr   _split_markdownr   _split_tax_adaptiveloggerwarning	Exceptionerror)	r   r   r   r   r   r   r   r    er   r   r   
split_text   s(   




zTextSplitterService.split_textreturnc                 C   sN   ddl m} |||tg dd}|| }tdt|  dt| d |S )u   使用递归字符分割器r   )RecursiveCharacterTextSplitter)
r   
u   。u   ！u   ？.!? r"   )r   r   length_function
separatorszRecursive splitting completed:  characters ->  chunks)langchain_text_splittersr/   lenr-   r(   info)r   r   r   r/   splitterchunksr   r   r   r#   H   s   
 z$TextSplitterService._split_recursivec                 C   sJ   ddl m} ||||td}|| }tdt|  dt| d |S )u   使用字符分割器r   )CharacterTextSplitter)r   r   r   r5   zCharacter splitting completed: r7   r8   )r9   r>   r:   r-   r(   r;   )r   r   r   r   r>   r<   r=   r   r   r   r$   X   s   
 z$TextSplitterService._split_characterc                 C   F   ddl m} |||d}|| }tdt|  dt| d |S )u   使用 Token 分割器r   )TokenTextSplitterr   r   zToken splitting completed: r7   r8   )r9   r@   r-   r(   r;   r:   )r   r   r   r@   r<   r=   r   r   r   r%   h      
 z TextSplitterService._split_tokenc                 C   r?   )u   使用 Markdown 分割器r   )MarkdownTextSplitterrA   zMarkdown splitting completed: r7   r8   )r9   rC   r-   r(   r;   r:   )r   r   r   rC   r<   r=   r   r   r   r&   v   rB   z#TextSplitterService._split_markdownc           
      C   s   ddl m} | }d}|r"d|v sd|v rd}n
d|v s d|v r"d	}|j| |||d
}g }|D ]}	||	j|	j|	j|	j|	j|	j	|	j
|	jd q/tdt|  dt| dtdd |D  dtdd |D  d	 |S )u;   使用税务自适应分割器，返回完整的chunk字典r   )TaxAdaptiveSplitterlawu   公告u   通知announcementu   案例u   判决case)r   r   r    doc_type)r   chunk_id	is_parentparent_chunk_idchunk_levelchunk_index
referencesmetadataz"Tax adaptive splitting completed: r7   z	 chunks (c                 s   s    | ]	}|d  rdV  qdS rJ      Nr   .0cr   r   r   	<genexpr>       z:TextSplitterService._split_tax_adaptive.<locals>.<genexpr>z parents + c                 s   s    | ]	}|d  sdV  qdS rP   r   rR   r   r   r   rU      rV   z
 children)),app.services.knowledge.tax_adaptive_splitterrD   splitappendr   rI   rJ   rK   rL   rM   rN   rO   r(   r;   r:   sum)
r   r   r    r   rD   r<   rH   
tax_chunksr=   chunkr   r   r   r'      s8   
Hz'TextSplitterService._split_tax_adaptivegranularityc              	   C   sR   ddl m} ||d|||d}|| }tdt|  dt| d| d |S )	uE   使用税务文档分割器（已废弃，保留用于向后兼容）r   )TaxDocumentSplitterT)r]   add_contextr   r   r   z"Tax document splitting completed: r7   z chunks (granularity: )),app.services.knowledge.tax_document_splitterr^   r-   r(   r;   r:   )r   r]   r   r   r   r^   r<   r=   r   r   r   
_split_tax   s   	
&zTextSplitterService._split_taxwindow_sizec              
   C   s   |t jkrtj| |||||rt|nd|d}|S tj| |||||r&t|nd|d}g }	t|D ]\}
}||
t|t||||
t|dd}|	| q1|	S )u'  
        创建带元数据的文本分片

        Args:
            text: 要分片的文本
            chunk_size: 每个分片的大小
            chunk_overlap: 分片之间的重叠大小
            splitter_type: 分片器类型
            document_id: 文档 ID
            document_title: 文档标题
            document_number: 文档编号（用于税务自适应分割器）
            window_size: 窗口大小（用于父子分块，当前未使用）

        Returns:
            包含文本和元数据的分片列表
        N)r   r   r   r   r   r   r    )r   r   rM   total_chunks)r   rM   rd   r   rO   )r   r   r   r-   str	enumerater:   rY   )r   r   r   r   r   r   r    rc   r=   resultir\   
chunk_datar   r   r   create_chunks_with_metadata   sD   


z/TextSplitterService.create_chunks_with_metadata)r   r   r   r   staticmethodr   r   re   intr   r-   r   r#   r$   r%   r&   dictr'   rb   rj   r   r   r   r   r      s    / $  +	r   r.   c                   C   s   t du rt a t S )u0   获取文本分片服务实例（单例模式）N)_text_splitter_servicer   r   r   r   r   get_text_splitter_service  s   ro   )r   loggingtypingr   r   enumr   	getLoggerr   r(   re   r   r   rn   ro   r   r   r   r   <module>   s    
	 {