
    #i                       U d Z ddlmZ ddlmZmZ ddlmZmZm	Z	 ddl
mZ ddlmZ ddlmZmZmZ ddlmZ dd	lmZ dd
lmZmZmZmZmZmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z& ddl'm(Z( ddl)m*Z* ddl+m,Z, ddl-m.Z. ddl/m0Z0m1Z1 ddl2m3Z3m4Z4m5Z5m6Z6 ddl7m8Z8  e8e9          Z:dZ;dZ<ddddZ=dZ>dZ?dZ@deAd<    G d d          ZBdS )u5  Research engine — legacy research/qa plus plan-driven deep research.

研究引擎编排层。
作为系统核心查询入口，协调 ResearchRetriever（检索层）和格式化工具函数，
支持标准研究、问答和深度研究三种模式，以及多轮对话（基于可插拔会话存储）。
    )annotations)AnyAsyncIterator)ResearchChunkResearchPlanResearchTask)settings)EmbeddingService)GraphEvidenceGraphQueryPlannerQueryIntent)GraphQueryService)PermissionContext)_build_context_text_build_deep_research_messages_build_messages_build_plan_brief_build_section_hint_build_task_brief_build_task_query_join_report_text_join_section_text_merge_unique_docs_merge_unique_reference_docs_normalize_research_plan_normalize_research_report_normalize_section_rerun_result_resolve_explicit_doc_ids_source_group_label)ResearchRetriever)ESClient)	LLMClient)RedisClient)RedisResearchSessionStoreResearchSessionStore)RESEARCH_PLAN_SYSTEMRESEARCH_PLAN_USERRESEARCH_SECTION_RERUN_SYSTEMRESEARCH_SECTION_RERUN_USER)
get_logger            )standarddeepcomprehensive   )u   办事指南u   办理u   申请   材料u   条件   时限   流程   收费   费用   窗口   咨询   投诉u   预约u   快递u   网办u   在线办理))	materialsu   申请材料)r3   u   证件u   提交u   表格u   原件u	   复印件u   证明)feesu   收费项目)r6   r7   u	   工本费u	   多少钱u   金额)
time_limitu   办理时限)u   多久r4   u   几天u   办结u   时间)windowsu   办理窗口)r8   u   地点u	   哪里办u   大厅u   地址)consultationu   咨询投诉)u   电话r9   r:   u   热线u   联系方式)processu   办理流程)r5   u   步骤u	   怎么办u   如何办理u   办理路径z,tuple[tuple[str, str, tuple[str, ...]], ...]_GUIDE_REFERENCE_FIELD_RULESc                     e Zd ZdZ	 	 	 dUdVdZdWdZdXdZdYdZedZd             Z	edddd!d[d(            Z
ed\d+            Zed]d,            Zed^d.            Zed_d0            Zed_d1            Zed`d2            Zdddd!dad4Zddddd5dbd=Zddd>dcdAZddd>dcdBZddCdddDZddCdedEZddd>dfdFZdddddGdgdKZddLdMdhdOZdidQZdjdTZdS )kResearchEngineu  Orchestrates the Research-mode pipeline.

    Parameters
    ----------
    es_client:
        Async Elasticsearch client.
    embedding_service:
        Used to generate query vectors for ES kNN.
    graph_service:
        Neo4j-backed entity / document discovery.
    llm_client:
        LLM for keyword extraction and answer streaming.
    redis_client:
        Used as fallback session storage when a dedicated session store is not provided.

    研究引擎，编排完整的 Research 模式流水线。
    协调 ES 检索、图谱查询、向量化、LLM 推理等组件，
    支持标准研究和深度研究两种模式以及多轮对话。
    N	es_clientr!   embedding_servicer
   graph_servicer   
llm_clientr"   redis_clientRedisClient | Nonesession_storeResearchSessionStore | NoneplannerGraphQueryPlanner | NonereturnNonec                   || _         || _        || _        || _        ||| _        n2|!t          |t          j                  | _        nt          d          |pt                      | _
        t          ||||| j
                  | _        d S )N)ttl_secondsz7ResearchEngine requires a session_store or redis_client)rD   rE   rF   rG   rL   )_es
_embedding_graph_llm_session_storer$   r	   research_session_ttl_seconds
ValueErrorr   _plannerr    
_retriever)selfrD   rE   rF   rG   rH   rJ   rL   s           2D:\work\zm-rag\backend\app\core\research_engine.py__init__zResearchEngine.__init__q   s     +#	$"/D%";$A# # #D
 VWWW6#4#6#6 ,/'!M
 
 
    questionstr	list[str]c                F   K   | j                             |           d {V S N)rZ   extract_keywords)r[   r_   s     r\   _extract_keywordsz ResearchEngine._extract_keywords   s.      _55h?????????r^   permr   list[dict[str, Any]]c                H   K   | j                             ||           d {V S rc   )rZ   	es_search)r[   r_   rf   s      r\   
_es_searchzResearchEngine._es_search   s2       _..x>>>>>>>>>r^   doc_ids
str | Nonec                J   K   | j                             |||           d {V S rc   )rZ   fetch_graph_docs)r[   rk   r_   rf   s       r\   _fetch_graph_docsz ResearchEngine._fetch_graph_docs   s4       _55gxNNNNNNNNNr^   dict[str, Any]c                    t          | dd           }t          |          r
 |            S d t          | dg           D             }ddddddiigiid	d|iigd
diS )Nbuild_es_filterc                    g | ]}||S  rt   ).0tokens     r\   
<listcomp>z4ResearchEngine._build_acl_filter.<locals>.<listcomp>   s    RRREReRRRr^   
acl_tokensboolmust_notexistsfieldacl_idsterms   )shouldminimum_should_match)getattrcallable)rf   build_filterrx   s      r\   _build_acl_filterz ResearchEngine._build_acl_filter   s    t%6==L!! 	"<>>!RR|R)H)HRRR
jHw	6J+K*LMNy*56 )* 
 	
r^   planrk   
matter_ids
query_textr   
Any | Nonelist[str] | Noner   ry   c                    |s|rdS |!t          |dd           t          j        k    rdS t           fdt          D                       S )NTintentc              3      K   | ]}|v V  	d S rc   rt   )ru   keywordr   s     r\   	<genexpr>zHResearchEngine._should_collect_service_guide_evidence.<locals>.<genexpr>   s(      VVW7j(VVVVVVr^   )r   r   MATTER_DETAILany_SERVICE_GUIDE_QUERY_KEYWORDS)r   r   rk   r   s   `   r\   &_should_collect_service_guide_evidencez5ResearchEngine._should_collect_service_guide_evidence   sa      	j 	4h = =AZ Z Z4VVVV8UVVVVVVr^   source	field_keyc           	        |dk    r7t          |                     d          p|                     d                    S |dk    r7t          |                     d          p|                     d                    S |dk    r|                     d          pi }t          d |                     d          |                     d	          |                    d
          pi                     d          |                    d          pi                     d          fD                       S |dk    r7t          |                     d          p|                     d                    S |dk    rx|                     d          pi }t          |                    d          p>|                    d          p)|                    d          p|                    d                    S |dk    rc|                     d          pi }t          |                    d          p)|                    d          p|                    d                    S dS )Nr;   material_namesr<   	fee_namesr=   
basic_infoc              3  *   K   | ]}|d uo|dk    V  d S )N rt   )ru   values     r\   r   z9ResearchEngine._guide_source_has_field.<locals>.<genexpr>   sD         T!1erk     r^   promised_time_limit_dayslegal_time_limit_dayspromised_time_limitraw_textlegal_time_limitr>   window_namesservice_windowsr?   consultation_and_supervisionconsultation_phonesconsultation_urlscomplaint_phonescomplaint_urlsr@   process_infosummarystep_titlesF)ry   getr   )r   r   r   r?   r   s        r\   _guide_source_has_fieldz&ResearchEngine._guide_source_has_field   sg   ##

#344O

;8O8OPPP

;//E6::f3E3EFFF$$L117RJ   JJ9::JJ677^^$9::@bEEjQQ^^$677=2BB:NN	      	!!

>22SfjjAR6S6STTT&&!::&DEEKL  !677 6##$7886##$6776  ##$455	   	!!!::n55;L  ++ 0##M220##J//  
 ur^   c                  
 |pd                                 
g }g }t          D ]b\  }}}|                     ||          st          
fd|D                       r*|                    |           |                    |           cd}|r:|d d         }	dd                    |	           }t          |          dk    r|dz  }|||dS )Nr   c              3      K   | ]}|v V  	d S rc   rt   )ru   r   normalized_querys     r\   r   z=ResearchEngine._build_guide_match_metadata.<locals>.<genexpr>   s)      GG77..GGGGGGr^   r,   u   命中   、u	   等字段)matched_fieldsmatched_field_labelsr   )striprA   r   r   appendjoinlen)clsr   r   r   r   r   labelkeywordsr   visible_labelsr   s             @r\   _build_guide_match_metadataz*ResearchEngine._build_guide_match_metadata   s   &,"3355$&*,*F 	3 	3&Iuh..vyAA GGGGhGGGGG 3%%i000$++E222 	'1"1"5N;uzz.99;;G'((1,,;& -$8
 
 	
r^   hitsc                R   g }|D ] }|                     di           }|                     dd          }|s2|                     d          pi                      d          p|                     d          pd| }|                     ||          }|                    |||                     d          p|                     d	          |                     d
|                     dd                    |                     d          d|d         |d         |d         d	           "|S )N_sourcedoc_idr   document_infotitlematter_nameu   办事指南：implementation_codeguide_version
profile_id_id_scoreguider   r   r   )	r   r   
doc_numberr   score_source_typer   r   r   )r   r   r   )	r   r   r   docshitr   r   r   
match_metas	            r\   _guide_reference_docsz$ResearchEngine._guide_reference_docs  sH   %' 	 	CWWY++FZZ"--F O,,277@@ .::m,,.-V-- 
 88VLLJKK$""(**-B"C"C"bvzzRaGbGb"(**\3775";M;M"N"N WWX..$+&01A&B,67M,N))4
 
    r^   docc                d   t          |                     d          p|                     d          pd          }|dk    }|t          |          |r|                     d          nd |r|                     d          nd |r|                     d          nd |r|                     d          nd d	S )
Nr   source_groupsearchr   r   r   r   r   )r   source_labelr   r   r   r   )r`   r   r   )r   r   is_guides      r\   _reference_payloadz!ResearchEngine._reference_payload!  s    377>22Ycggn6M6MYQYZZ7*(/==3;E#'',///;CMcgg&6777GO$YCGG,B$C$C$CUY-5?swwy)))4
 
 	
r^   c                    |d         |                     dd          |                     dd          |                     d          d|                     |          S )Nr   r   r   r   r   )r   r   r   relevance_score)r   r   )r   r   s     r\   _session_reference_docz%ResearchEngine._session_reference_doc.  sc     (mWWWb))'',33"www//	
 

 $$S))
 	
r^   c           
     
   | sdS g }| D ]O}|                     di           }|                     d          p+|                     d          pi                      d          pd}d| g}d |                     d	g           D             }|r3|                    d
d                    |d d                               |                     d          pd}|r|                    d|            d |                     dg           D             }|r3|                    dd                    |d d                               d |                     dg           D             }	g }
|                     d          r|
                    d           |                     d          r|
                    d           |	s|
r>|                    dd                    |	d d         |
d d         z                         d |                     dg           D             }|r3|                    dd                    |d d                               d  |                     d!g           D             }|r3|                    d"d                    |d d                               g }|                     d#          r|                    d$|d#          d%           |                     d&          r|                    d'|d&          d%           |r+|                    d(d                    |                      |                     d)          pi }d* |                     d+g           D             }|r4|                    d,d-                    |d d.                               n@|                     d/          r+|                    d0|                     d/                      d1 |                     d2g           D             }|r3|                    d3d                    |d d                               d4 |                     d5g           D             }|r3|                    d6d                    |d d                               |                     d7          pi }d8 |                     d9g           D             }|r3|                    d:d                    |d d                               |                     d;d          }|r|                    d<|            |                    d=                    |                     Qd>d?                    |          z   S )@Nr   r   r   r   r   u   未命名事项u   ### 事项：c                    g | ]}||S rt   rt   )ru   mids     r\   rw   zAResearchEngine._format_service_guide_evidence.<locals>.<listcomp>C  s     [ [ [WZ [ [ [ [r^   linked_matter_idsu   - 绑定 Matter：r   r2   implementing_subjectu   - 实施主体：c                    g | ]}||S rt   rt   ru   items     r\   rw   zAResearchEngine._format_service_guide_evidence.<locals>.<listcomp>K  s    ZZZUYZtZZZr^   service_objectsu   - 服务对象：r,   c                    g | ]}||S rt   rt   r   s     r\   rw   zAResearchEngine._format_service_guide_evidence.<locals>.<listcomp>O  s    VVVdQUVTVVVr^   service_modesexpress_supportedu   支持快递reservation_supportedu   支持预约u   - 办理方式：   c                    g | ]}||S rt   rt   ru   names     r\   rw   zAResearchEngine._format_service_guide_evidence.<locals>.<listcomp>X  s    SSS$dSSSSr^   r   u   - 申请材料：u   ；   c                    g | ]}||S rt   rt   r   s     r\   rw   zAResearchEngine._format_service_guide_evidence.<locals>.<listcomp>\  s    IIITDIDIIIr^   r   u   - 收费项目：r   u   承诺 u    日r   u   法定 u   - 办理时限：r   c                    g | ]}||S rt   rt   r   s     r\   rw   zAResearchEngine._format_service_guide_evidence.<locals>.<listcomp>i  s    XXXDSWX4XXXr^   r   u   - 流程步骤：u    →    r   u   - 流程摘要：c                    g | ]}||S rt   rt   r   s     r\   rw   zAResearchEngine._format_service_guide_evidence.<locals>.<listcomp>o  s    TTTTtTDTTTr^   r   u   - 办理窗口：c                    g | ]}||S rt   rt   r   s     r\   rw   zAResearchEngine._format_service_guide_evidence.<locals>.<listcomp>s  s    QQQTDQDQQQr^   legal_basis_namesu   - 依据：r   c                    g | ]}||S rt   rt   )ru   phones     r\   rw   zAResearchEngine._format_service_guide_evidence.<locals>.<listcomp>x  s    "k"k"kUej"k5"k"k"kr^   r   u   - 咨询电话：r   u   - 来源文档：
u    ## 办事指南结构化证据



)r   r   r   )r   sectionsr   r   r   linesr   r   r   r   service_flagsr;   r<   time_limit_partsr   r   r   lawsr?   r   r   s                        r\   _format_service_guide_evidencez-ResearchEngine._format_service_guide_evidence8  s    	2  B	. B	.CWWY++F **]33|

?8S8S8YWY7^7^_f7g7g|k|K2[223E [ [

;NPR0S0S [ [ [  WU%**=NrPQr=R2S2SUUVVV#)::.D#E#E#K # IG1EGGHHHZZ

;Lb0Q0QZZZO TROBQB<O1P1PRRSSSVVfjj".M.MVVVM')Mzz-.. 5$$^444zz122 5$$^444 f fdM"1"<MP]^`_`^`Pa<a1b1bddeeeSS&**5Er*J*JSSSI NLIbqbM1J1JLLMMMIIVZZR%@%@IIID IGD!H1E1EGGHHH*,zz455 \ ''(Z&9S2T(Z(Z(Z[[[zz122 Y ''(W&9P2Q(W(W(WXXX QO<L1M1MOOPPP!::n55;LXXL,<,<]B,O,OXXXK PPk"1"o1N1NPPQQQQ!!),, PN1A1A)1L1LNNOOOTTVZZ-K-KTTTL QOL!<L1M1MOOPPPQQVZZ0CR%H%HQQQD CA5::d2A2h+?+?AABBB!::&DEEKL"k"kl6F6FG\^`6a6a"k"k"k" XV<OPRQRPR<S1T1TVVWWWZZ"--F ;999:::OODIIe,,----3fkk(6K6KKKr^    tuple[str, list[dict[str, Any]]]c               V  K   d t                               |pg           D             }d t                               |pg           D             }|                     ||||          sdg fS d}|Dt          |dd           t          j        k    r%t          |dd          pd                                }	 | j                            | 	                    |          ||||t                     d {V }	|	s@|r>|r<| j                            | 	                    |          ||t                     d {V }	nD# t          $ r7}
t                              d	t          |
          
           dg fcY d }
~
S d }
~
ww xY w|	sdg fS |                     |	          |                     |	|          fS )Nc                    g | ]}||S rt   rt   ru   r   s     r\   rw   zBResearchEngine._collect_service_guide_evidence.<locals>.<listcomp>  s    XXXvQWXFXXXr^   c                    g | ]}||S rt   rt   )ru   	matter_ids     r\   rw   zBResearchEngine._collect_service_guide_evidence.<locals>.<listcomp>  s    gggY]fgygggr^   r   r   r   matter_query)
acl_filterr   rk   r   r   size)r  r   r   r  service_guide_evidence_failederror)dictfromkeysr   r   r   r   r   rR   search_service_guidesr   _MAX_SERVICE_GUIDE_DOCS	Exceptionloggerwarningr`   r   r   )r[   r   rf   r   rk   r   explicit_doc_idsexplicit_matter_idsr   
guide_hitsexcs              r\   _collect_service_guide_evidencez.ResearchEngine._collect_service_guide_evidence  s*      YXw}"1M1MXXXgg$--
HXVX:Y:Yggg::$*	 ; 
 
 	 r6Mh = =AZ Z Z"4<<BIIKKK	#x==11$77%(.',  >          J  "5 + #'8#A#A#55d;;) +0	 $B $ $      
  	 	 	NN:#c((NKKKr6MMMMMM	  	r6M22:>>@Z@Z[egq@r@rrrs   5B D6 6
E7 ,E2,E72E7seed_doc_idsextra_doc_idssection_hintexplicit_querytaskr   r   r  r  r  r  c                 K   t          |dg           }t          ||          }	|r!d                    d |	|fD                       }	|                     |	           d{V }
| j                            |	|
          }t                      }|j        t          j	        k    rx	 | j        
                    || j        |           d{V }nN# t          $ rA}t                              dt          |                     t                      }Y d}~nd}~ww xY w|                     |	|           d{V }|D ]}d|d	<   d
 |D             t#          ||||          }g }|r/|                     |dd         ||           d{V }|D ]}d|d	<   g }|
rg	 | j                            |
d|           d{V }nB# t          $ r5}t                              dt          |                     g }Y d}~nd}~ww xY w|j        r|                    |j                   t-          |          fdt.                              |          D             }g }|r/|                     |dd         |	|           d{V }|D ]}d|d	<   t2                              |j        t8                    }t;          |||          d|         }|                     |	|||t?          t.                              t?          |j         pg           t?          |j!        pg           z                                  d{V \  }}|	|
||||dS )ul   收集深度研究所需的全部材料：显式纳入 + ES 检索 + 图谱补充，合并去重后返回。rx   r   c              3     K   | ]}||V  	d S rc   rt   ru   parts     r\   r   zBResearchEngine._collect_deep_research_materials.<locals>.<genexpr>  s(      "W"WDRV"W4"W"W"W"W"W"Wr^   Nrx   #deep_research_graph_evidence_failedr  r   r   c                    h | ]
}|d          S r   rt   ru   r   s     r\   	<setcomp>zBResearchEngine._collect_deep_research_materials.<locals>.<setcomp>  s    777c(m777r^   )r  r  r-   seedlimit_per_keywordrx   (deep_research_graph_doc_discovery_failedc                (    g | ]}|r
|v|v|S rt   rt   ru   r   
es_doc_ids
scoped_idss     r\   rw   zCResearchEngine._collect_deep_research_materials.<locals>.<listcomp>  sB     
 
 

 !
22vZ7O7O 7O7O7Or^   graphr   )r   r   graph_evidenceall_docs
guide_docsguide_evidence_text)"r   r   r   re   rY   r   r   r   r   GENERALcollect_evidencerT   r  r  r  r`   rj   r   ro   search_graph_for_docsrk   extendsetr
  r  _DEPTH_DOC_LIMITSr   depth_level_MAX_CONTEXT_DOCSr   r  listincluded_matter_idsrequired_matter_ids)r[   r  r   rf   r  r  r  r  rx   r   r   planner_planr/  r  es_docsr   r  explicit_docsgraph_doc_ids
graph_docscontext_limitr0  r2  r1  r,  r-  s                           @@r\    _collect_deep_research_materialsz/ResearchEngine._collect_deep_research_materials  sx      T<44
&tT22
 	X"W"WZ4N"W"W"WWWJ//
;;;;;;;;}))*h??&+"5551'+}'E'E K) (F ( ( " " " " " "
  1 1 1DCPSHHUUU!.1 
D99999999 	+ 	+C"*C77w777
4%'	
 
 
 /1 	-"&"8"89I"1"9M~_c"d"dddddddM$ - -&,N###% 		##&*k&G&G&') 'H ' ' ! ! ! ! ! !
  # # #IQTUXQYQYZZZ "# ! 	9  !7888)**

 
 
 
 
--66
 
 
 ,.
 	.#55mBQB6GUYZZZZZZZZJ! . .&-N##)--d.>@QRR%mWjII.=.Y040T0T$d4#;#ArBBT$JbJhfhEiEiijj  1U 1
 1
 +
 +
 +
 +
 +
 +
'Z % , $#6
 
 	
s0   #(C 
D7DD#F; ;
G:+G55G:
session_idr  rF  AsyncIterator[ResearchChunk]c               4    |                      ||||          S )u  标准研究模式入口：流式输出研究结果块。

        Stream research answer chunks for the given question.

        Yields
        ------
        ResearchChunk objects with type in:
        ``thinking`` | ``reference`` | ``text`` | ``done`` | ``error``
        rE  _streamr[   r_   rf   rF  r  s        r\   researchzResearchEngine.research  s+    " ||!%	  
 
 	
r^   c               6    |                      ||||d          S )u^   问答模式入口：与 research 共享流水线，但使用问答专用的系统提示词。qa)rF  r  moderI  rK  s        r\   rN  zResearchEngine.qa1  s.     ||!%  
 
 	
r^   r  c               P  K   t          |dg           }|                     |           d{V }t                              d|dd         |           t	                      }| j                            ||          }|j        t          j	        k    rx	 | j        
                    || j        |           d{V }nN# t          $ rA}t                              dt          |                     t	                      }Y d}~nd}~ww xY w|                     ||           d{V }	|	D ]}
d	|
d
<   d |	D             g }d t                               |pg           D             }|r/|                     |dd         d|           d{V }|D ]}
d|
d
<   g }|rg	 | j                            |d|           d{V }nB# t          $ r5}t                              dt          |                     g }Y d}~nd}~ww xY w|j        r|                    |j                   fdt                               |          D             }g }|r/|                     |dd         ||           d{V }|D ]}
d|
d
<   t-          ||	|          dt.                   }|                     ||||           d{V \  }}t3          ||          }t5          |          g}|j        r|                    |j                   |r|                    |           d                    d |D                       }g }|D ]}
|                    |
d         |
                    dd          |
                    d          |
                    d          |
                    d          |
                    d          |
                    d          |
                    dg           |
                    d
d	          d	|                     |
                     ||||j        j         |j        pd|d S )!u/  QA 材料检索：执行 Phase 1-3（关键词提取 → 图谱规划 → 多路召回 → 合并），
        返回结构化的检索结果和上下文文本，跳过 LLM 生成。

        Returns a dict with keys:
        - ``documents``: merged reference doc list
        - ``context_text``: formatted context ready for LLM
        - ``keywords``: extracted keywords
        - ``intent``: graph query intent
        - ``graph_evidence_text``: graph structured evidence (if any)
        - ``guide_evidence_text``: service guide evidence (if any)
        rx   Nqa_search_keywordsP   r_   r   r   qa_search_graph_evidence_failedr  r   r   c                    h | ]
}|d          S r#  rt   ru   ds     r\   r%  z+ResearchEngine.qa_search.<locals>.<setcomp>i  s    333aak333r^   c                    g | ]}||S rt   rt   r  s     r\   rw   z,ResearchEngine.qa_search.<locals>.<listcomp>l  s-     
 
 
f

 
 
r^   r-   r&  r'  $qa_search_graph_doc_discovery_failedc                    g | ]}|v|	S rt   rt   ru   rX  r,  s     r\   rw   z,ResearchEngine.qa_search.<locals>.<listcomp>  s*     
 
 
q
7J7JA7J7J7Jr^   r.  r   rk   r   c              3     K   | ]}||V  	d S rc   rt   r  s     r\   r   z+ResearchEngine.qa_search.<locals>.<genexpr>  s'      "J"JDT"J4"J"J"J"J"J"Jr^   r   r   r   r   issuing_orgdoc_typepublish_dater   passages)	r   r   r   r_  r`  ra  r   rb  source_type)	documentscontext_textr   r   graph_evidence_textr2  )!r   re   r  infor   rY   r   r   r   r3  r4  rT   r  r  r`   rj   r
  r  ro   r5  rk   r6  r   r:  r  r   r   textr   r   r   r   r   )r[   r_   rf   r  rx   r   r/  r   r  r?  r   r@  r  rA  rB  r0  r2  r1  reference_docscontext_partsre  rd  r,  s                         @r\   	qa_searchzResearchEngine.qa_searchB  s     $ T<44
 //99999999(8CRC=8TTT&}!!(H55;+---1'+}'E'E$+* (F ( ( " " " " " "  1 1 1@CQQQ!.1
 $77777777 	+ 	+C"*C337333
.0
 
!%|/Ar!B!B
 
 
  	-"&"8"8 !$dD# #      M % - -&,N###% 	##&*k&G&Gj 'H ' ' ! ! ! ! ! !  # # #ESQTXXVVV "# ! 	9  !7888
 
 
 
}}]33
 
 
 ,.
 	.#55bqb!8T         J " . .&-N## &mWjII
 150T0Td/? 1U 1
 1
 +
 +
 +
 +
 +
 +
'Z 6h
KK -X667 	6  !4555 	6  !4555{{"J"JM"J"J"JJJ 	! 	 	Ch-"--!ggl33"ww}55GGJ// # 7 7))GGJ33"ww~x@@  ))#..     #( k'#1#6#<"#6
 
 	
s0   (B= =
D7DD#F? ?
G>	+G99G>c               8  K   |                      |j                   d{V }| j                            |j        |          }	 | j                            dt          ddt          j        t          |          d
                    |          pd|j        j        t          |pg                     dgdd	
           d{V }nB# t          $ r5}t                              dt#          |                     i }Y d}~nd}~ww xY wt%          |||||          S )u   生成结构化研究计划：提取关键词 → 图谱意图规划 → LLM 生成计划 → 标准化输出。

        Generate a structured research plan with safe fallbacks.Nsystemrolecontentuserr      无)
task_briefr   r   seed_doc_count皙?i  temperature
max_tokensresearch_plan_generation_failedr  )r   r>  r  )re   r_   rY   r   rU   	chat_jsonr&   r'   formatr   r   r   r   r   r  r  r  r`   r   )r[   r  r  r   r>  resultr  s          r\   
build_planzResearchEngine.build_plan  sq      //>>>>>>>>}))$-BB	9..%2FGG &#5#<'8'>'>%*ZZ%9%9%BU#/#6#<+.|/Ar+B+B	$ $ $    /        FF   	 	 	NN<CHHNMMMFFFFFF	 (%%
 
 
 	
s   BC 
D+D  Dc                 %&'K   t          |dg           }t          |dd          }	 t          dddd          W V  t          d	|                                
          W V  t          ||          }                     |           d{V }	 j                            ||	          }
t                      }|
j        t          j
        k    rt          dddd          W V  	  j                            |
 j        |           d{V }nN# t          $ rA}t                              dt!          |                     t                      }Y d}~nd}~ww xY wt          dddd          W V                       ||           d{V }|D ]}d|d<   d |D             %t%          |||          }g }|rEt          dddd          W V                       |dd         d|           d{V }|D ]}d|d<   g }|	rg	  j                            |	d|           d{V }nB# t          $ r5}t                              dt!          |                     g }Y d}~nd}~ww xY w|j        r|                    |j                   t/          |          &%&fdt0                              |          D             }g }|rEt          dddd          W V                       |dd         ||           d{V }|D ]}d|d<   t4                              |j        t:                    }t=          |||          d|         }                     |||
|tA          t0                              tA          |j!        pg           tA          |j"        pg           z                                  d{V \  }}|s+|s)t          d d!"          W V  t          d#$          W V  dS d%D ]`\  '}'d&k    r|n'fd'|D             }|st          d(|d)tG          |           d*'tG          |          d+ |D             d,-          W V  atI          ||          }|D ]m}t          d.|d/         |                    d0d          |                    d1          |                    d2           %                    |          3          W V  nt          dd4dd5          W V  tM          |          g}|j'        r|(                    |j'                   |r|(                    |           d6)                    d7 |D                       }|r *                    ||           d{V ng } j+        ,                    t[          ||||          d8t\          j/        9           d{V }ta          |||          }|d:         rt          d;|d:         "          W V  |d<         D ]3}t          d=|d0         |d>         |d?         d@|d@         iA          W V  4|dB         D ]3} t          dC| d0         | d>         | dD         d@| d@         iE          W V  4|dF         D ]#}!t          dG|!dH         |!dI         J          W V  $|dK         D ]3}"t          dL|"d0         |"d>         |"d;         |"d@         dM-          W V  4|dN         rt          dOdP|dN         dQdNi-          W V  |dR         r6t          dSdT)                    |dR                   dU|dR         iV          W V  |r< fdW|D             }#tc          |          }$ 2                    ||||$|#           d{V  t          ddXdYdZ          W V  t          d#$          W V  dS # t          $ rL}t          3                    d[           t          d d\"          W V  t          d#$          W V  Y d}~dS d}~ww xY w)]u   深度研究模式：按已确认的研究计划执行多源检索，生成结构化研究报告并通过 SSE 流式输出。

        Execute a confirmed research plan and emit structured SSE events.rx   user_idr   progressinitrunningu-   正在装载研究任务与已确认计划…typestagestatusrp  r   )r  payloadNr.  u$   正在补充图谱结构化证据…r   r!  r  retrieveu!   正在检索混合检索结果…r   r   c                    h | ]
}|d          S r#  rt   rW  s     r\   r%  z3ResearchEngine.run_deep_research.<locals>.<setcomp>      777!!H+777r^   rP  scopeu!   正在装载显式纳入资料…r-   r&  r'  r)  c                (    g | ]}|r
|v|v|S rt   rt   r+  s     r\   rw   z4ResearchEngine.run_deep_research.<locals>.<listcomp>;  sB        %J666;S;S ;S;S;Sr^   u!   正在补充图谱关联文档…r   r	  uf   未检索到与当前研究任务相关的可用材料，请调整研究范围或补充显式资料。r  rp  doner  )r&  u   显式纳入资料)r   u   混合检索命中)r.  u   图谱补充材料)r   u   办事指南结构化证据r   c                F    g | ]}|                     d           k    |S r   r   ru   r   r   s     r\   rw   z4ResearchEngine.run_deep_research.<locals>.<listcomp>j  0    ]]]#SWW^5L5LP\5\5\#5\5\5\r^   r      纳入 
    份材料c                    g | ]
}|d          S r#  rt   r$  s     r\   rw   z4ResearchEngine.run_deep_research.<locals>.<listcomp>u      #E#E#EcCM#E#E#Er^   groupcountrk   r  r   rp  r  	referencer   r   r   r   r  r   r   r   r   r  analysisu-   正在汇总发现、冲突和章节报告…r   c              3     K   | ]}||V  	d S rc   rt   r  s     r\   r   z3ResearchEngine.run_deep_research.<locals>.<genexpr>  '      &N&N&Nt&N&N&N&N&N&Nr^   ru  rv  executive_summaryr   findingsfindingrp  strengthsource_doc_ids)r  r   rp  r  r  	conflictsconflictseverity)r  r   rp  r  r  open_questionsopen_questionr_   reason)r  r   rp  r   section)r   r  one_page_summaryreportu   一页式摘要kindrecommended_next_steps	follow_upr   itemsr  rp  r  c                :    g | ]}                     |          S rt   r   ru   r   r[   s     r\   rw   z4ResearchEngine.run_deep_research.<locals>.<listcomp>  '    SSSS33C88SSSr^   complete	completedu   研究报告已生成。deep_research_error3   研究过程中发生内部错误，请稍后重试)4r   r   
model_dumpr   re   rY   r   r   r   r   r3  r4  rT   r  r  r  r`   rj   r   ro   r5  rk   r6  r7  r
  r  r8  r   r9  r:  r   r  r;  r<  r=  r   r   r   r   rh  r   r   _load_sessionrU   rz  r   r	   llm_max_tokensr   r   _save_session	exception)(r[   r  r   rf   rF  r  rx   r  r   r   r>  r/  r  r?  r   r  r@  rA  rB  rC  r0  r2  r1  r   groupedri  rj  re  historyr|  r  r  r  r_   r  refsfull_answerr,  r-  r   s(   `                                    @@@r\   run_deep_researchz ResearchEngine.run_deep_research  s      T<44
$	2..z	- G	        VT__5F5FGGGGGGG*466J!33J????????H=--j(CCL*__N"k&999##!$B	      5+/=+I+I$#- ,J , , & & & & & &NN
 ! 5 5 5NN#HPSTWPXPXNYYY%2__NNNNNN5    ;	       !OOJ========G / /&.N##77w777J8)     
 35M 	1##!$?	       '+&<&<=Mbqb=QSWY]&^&^ ^ ^ ^ ^ ^ ^( 1 1C*0C''')M 	''*.+*K*K *+#- +L + + % % % % % %MM
 ! ' ' 'NN#MUXY\U]U]N^^^$&MMMMMM' % =$$^%;<<<-..J    "mmM::  M 02J 	2##!$?	       $(#9#9-:KZY]#^#^^^^^^^
% 2 2C*1C''-11$2BDUVVM)-*MMn}n]H484X4X!(MM$t'?'E2"F"FdNfNljlImIm"mnn  5Y 5 5 / / / / / /+  J #  E       $0000000(  #e $w.. J]]]]]]] 
  #'>c'll>>>!-!$W#E#EW#E#E#E 		 	 	 	 	 	 	 	 :(JOON%  #$x='''2.."ww|44$'GGG$4$4 33C88           G	       1::;M" :$$^%8999" :$$%8999!;;&N&N&N&N&NNNL &d((W=========#%   9..-dD,PP#2 /        F
 0$GGF)* Y#FCV<WXXXXXXX!*-  #"!'*#I.$Z0-w7G/HI        #;/  ##"7+$Y/%j1-x8H/IJ        ##34  #(":.$X.        "*- 	 	#"!'*#I.#*9#5*12B*C 	        () #!+"#56#%78	       ./ #$ IIf-E&FGG$f-E&FG        	SSSSNSSS/77((           "2	        V,,,,,,,,, 	- 	- 	-2333W6klllllllV,,,,,,,,,,,,,		-sv   B;^ &(D ^ 
E7E^ EB*^ #H) (^ )
I(3+I#^ #I((E?^ )N^ 
_A__)section_summaryr  rF  r  section_titler  r  c              T   K   t          |dd          }		 t          dddd          W V  t          dddd	          W V  t          ||          }
                     ||||||
|

           d{V }|d         }|d         }|s+|s)t          dd          W V  t          d          W V  dS dD ]`\  }dk    r|nfd|D             }|st          d|dt	          |           dt	          |          d |D             d          W V  at          ||          }|D ]m}t          d|d         |                    dd          |                    d          |                    d                                |          !          W V  nt          dd"dd#          W V  t          |          g}|d$         }|j	        r|
                    |j	                   |d%         r|
                    |d%                    d&                    d' |D                       } j                            d(t          d)d*t          j        t#          |          t%          |          ||pd+|,          d)gd-t&          j        .           d{V }t+          |||          }|d/         }|d0         s'|r%d1 |D             fd2|D             dd3         |d0<   t          d/|d         |d4         |d5         |d0         d6d7          W V  |d8         r7t          d9d:                    |d8                   |d8         d;d<=          W V  |rE fd>|D             }                     ||	|j         d?| d@t1          |          |           d{V  t          ddAdBdC          W V  t          d          W V  dS # t2          $ r^}t4                              dDt9          |          E           t          ddF|           W V  t          d          W V  Y d}~dS d}~ww xY w)Gu   章节局部重跑：针对指定章节重新收集证据并重写内容，不影响其他章节。

        Re-run a single report section with focused evidence collection.r  r   r  r  r  u!   正在准备章节局部重跑…r  r  u'   正在围绕目标章节重取证据…r  Nr0  r1  r	  uW   未检索到可用于重跑该章节的材料，请补充章节证据范围后重试。r  r  r  r  r   c                F    g | ]}|                     d           k    |S r  r  r  s     r\   rw   z0ResearchEngine.rerun_section.<locals>.<listcomp>(  r  r^   r   r  r  c                    g | ]
}|d          S r#  rt   r$  s     r\   rw   z0ResearchEngine.rerun_section.<locals>.<listcomp>3  r  r^   r  r  r  r   r   r   r   r  r  u   正在重写目标章节…r/  r2  r   c              3     K   | ]}||V  	d S rc   rt   r  s     r\   r   z/ResearchEngine.rerun_section.<locals>.<genexpr>O  r  r^   rm  rn  rq  rr  )rs  
plan_briefr  r  contextru  rv  r  r  c                    h | ]
}|d          S r#  rt   r$  s     r\   r%  z/ResearchEngine.rerun_section.<locals>.<setcomp>f  s    $G$G$GsS]$G$G$Gr^   c                    g | ]}|v |	S rt   rt   )ru   r   available_doc_idss     r\   rw   z0ResearchEngine.rerun_section.<locals>.<listcomp>g  s+     - - -%6EV;V;VF;V;V;Vr^   r-   rp  r   T)r   r  rerunnotesr  r   section_rerun_notes)r  r  r  c                :    g | ]}                     |          S rt   r  r  s     r\   rw   z0ResearchEngine.rerun_section.<locals>.<listcomp>  r  r^   u   （章节重跑：u   ）r  r  u   章节局部重跑已完成。research_section_rerun_errorr  u   章节局部重跑失败：)r   r   r   rD  r   r   r   r   r   rh  r   r   rU   rz  r(   r)   r{  r   r   r	   r  r   r  r_   r   r  r  r	  r`   )r[   r  r   r  rf   r  r  rF  r  r  r  r;   r0  r1  r   r  ri  r   rj  r/  re  r|  rerun_resultr  r  r  r  r   s   `                         @@r\   rerun_sectionzResearchEngine.rerun_section  s      $	2..Y	- ;	          A	       /}oNNL"CC),)+ D        I !,H"<0J J # u       $0000000(  #e $w.. J]]]]]]] 
  #'>c'll>>>!-!$W#E#EW#E#E#E 		 	 	 	 	 	 	 	 :(JOON%  #$x='''2.."ww|44$'GGG$4$4 33C88           5	       1::;M&'78N" :$$^%8999./ G$$Y/D%EFFF!;;&N&N&N&N&NNNL9..%2OPP &#>#E'8'>'>'8'>'>*7,;,Du$0$ $ $	 	  #2 /        F" ;68][[L"9-G+,  $G$Gh$G$G$G!- - - -)7- - -1"-()  g&	*&y1&-.>&?! 		 	 	 	 	 	 	 G$ #$ IIl7&;<<!-g!6 5         SSSSNSSS((}JJJJJ&w//           "8	        V,,,,,,,,, 	- 	- 	-LL7s3xxLHHHW6YTW6Y6YZZZZZZZV,,,,,,,,,,,,,	-s    BN? 3L
N? ?
P'	AP""P'rL  )r  rO  rO  c              v    !K   t          |dg           }t          |dd          }	 t          d|dk    rdnd          W V                       |           d	{V }t                              d
|d	d         |           t                      }	 j                            ||          }
t                              d|
j        j	        |
j
        |
j        |
j        |
j                   |
j        t          j        k    rt          dd          W V  	  j                            |
 j        |           d	{V }	nN# t$          $ rA}t                              dt)          |                     t                      }	Y d	}~nd	}~ww xY wt          dd          W V                       ||           d	{V }|D ]}d|d<   d |D              g }d t,                              |pg           D             }|rCt          dd          W V                       |d	d         d	|           d	{V }|D ]}d|d<   g }|rg	  j                            |d|           d	{V }nB# t$          $ r5}t                              dt)          |                     g }Y d	}~nd	}~ww xY w|	j        r|                    |	j                    fdt,                              |          D             }g }|r/                     |d	d         ||           d	{V }|D ]}d|d<   t9          |||          d	t:                   }                     |||
|           d	{V \  }}|s+|s)t          d d!          W V  t          d"#          W V  d	S d$D ]`\  !}!d%k    r|n!fd&|D             }|st          d'|d(t?          |           d)!t?          |          d* |D             d+,          W V  atA          ||          }|D ]m}t          d-|d.         |!                    d/d          |!                    d0          |!                    d1           "                    |          2          W V  nt          d|dk    rd3nd4          W V  tG          |          g}|	j$        r|%                    |	j$                   |r|%                    |           d5&                    d6 |D                       }|r '                    ||           d	{V ng }tQ          ||||7          }g } j)        *                    |d8tV          j,        9          2 3 d	{V }|%                    |           t          d |          W V  16 d&                    |          }|r- fd:|D             } -                    |||||           d	{V  t          d"#          W V  d	S # t$          $ rO}t          .                    | d;           t          d<d=          W V  t          d"#          W V  Y d	}~d	S d	}~ww xY w)>u   标准研究/问答的核心流水线：关键词提取 → 图谱规划 → ES 混合检索 → 图谱补充 → LLM 流式回答。rx   r  r   thinkingrL  u   正在理解研究问题…u   正在分析问答问题…r  Nresearch_keywordsrS  rT  research_query_plan)r   doc_codeentity_nameentity_labelr  u$   正在查询图谱结构化证据…r   research_graph_evidence_failedr  u   正在检索相关公文…r   r   c                    h | ]
}|d          S r#  rt   rW  s     r\   r%  z)ResearchEngine._stream.<locals>.<setcomp>  r  r^   c                    g | ]}||S rt   rt   r  s     r\   rw   z*ResearchEngine._stream.<locals>.<listcomp>  s    aaa6Z`aaaar^   u   正在载入导入资料…r-   r&  r'  #research_graph_doc_discovery_failedc                    g | ]}|v|	S rt   rt   r\  s     r\   rw   z*ResearchEngine._stream.<locals>.<listcomp>  s$    \\\1Q[H[H[QH[H[H[r^   r.  r]  rh  u`   未检索到与您问题相关的公文材料，请尝试更换关键词或调整权限范围。r  r  r  r   c                F    g | ]}|                     d           k    |S r  r  r  s     r\   rw   z*ResearchEngine._stream.<locals>.<listcomp>  r  r^   r   r  r  c                    g | ]
}|d          S r#  rt   r$  s     r\   rw   z*ResearchEngine._stream.<locals>.<listcomp>  r  r^   r  r  r  r   r   r   r   r  u!   正在生成研究分析报告…u   正在生成问答结果…r   c              3     K   | ]}||V  	d S rc   rt   r  s     r\   r   z)ResearchEngine._stream.<locals>.<genexpr>2  r  r^   )rO  g333333?rv  c                :    g | ]}                     |          S rt   r  r  s     r\   rw   z*ResearchEngine._stream.<locals>.<listcomp>K  r  r^   _errorr	  r  )/r   r   re   r  rg  r   rY   r   r   r   r  r  r  r  r   r3  r4  rT   r  r  r`   rj   r
  r  ro   r5  rk   r6  r   r:  r  r   r   r   r   r   rh  r   r   r  r   rU   chatr	   r  r  r  )"r[   r_   rf   rF  r  rO  rx   r  r   r/  r   r  r?  r   r@  r  rA  rB  r0  r2  r1  r   r  ri  rj  re  r  messagesanswer_partsrv   r  r  r,  r   s"   `                               @@r\   rJ  zResearchEngine._stream  sO	      T<44
$	2..z	-9=9K9K55Qn      
 "33H========HKK+hssmhKWWW +__N=%%h99DKK%{( ,!.!.     {k111#=cddddddd5+/=+I+I#- ,J , , & & & & & &NN
 ! 5 5 5NN#C3s88NTTT%2__NNNNNN5
  Z9VWWWWWWW OOHd;;;;;;;;G / /&.N##77w777J24MaaT]]<CUSU5V5Vaaa 1#=Z[[[[[[[&*&<&<$RaR(' ' ! ! ! ! ! !
 ) 1 1C*0C'' (*M 	''*.+*K*K *+#- +L + + % % % % % %MM
 ! ' ' 'NN#HPSTWPXPXNYYY$&MMMMMM' % =$$^%;<<< ]\\\m(D(D\\\M 02J 2#'#9#9!"1"%x$ $      
 & 2 2C*1C'' *-*MMN`O`N`aH484X4X(	 5Y 5 5 / / / / / /+  J #~       $0000000(  #e $w.. J]]]]]]] 
  #'>c'll>>>!-!$W#E#EW#E#E#E 		 	 	 	 	 	 	 	 :(JOON%  #$x='''2.."ww|44$'GGG$4$4 33C88         ?Cz?Q?Q;;Wt       1::;M" :$$^%8999" :$$%8999!;;&N&N&N&N&NNNL
 &d((W=========#%  'xwTRRRH ')L#y~~#2  .     @ @ @ @ @ @ @e
 ##E***#????????  '',//K  SSSSNSSS((          V,,,,,,,,, 	- 	- 	-___---M        V,,,,,,,,,,,,,	-s   C,W (D? >W ?
F
	7F W F

B:W #I) (W )
J(3+J#W #J((C(W GW VBW 
X8)AX33X8r  c           	        K   	 | j                             ||           d{V }|r|t           d         S nB# t          $ r5}t                              d||t          |                     Y d}~nd}~ww xY wg S )u   从会话存储中加载多轮对话历史，仅保留最近 N 轮。

        Load conversation history from the configured session store.Nsession_load_failedrF  r  r	  )rV   load_session_MAX_HISTORY_TURNSr  r  r  r`   )r[   rF  r  r  r  s        r\   r  zResearchEngine._load_sessionc  s      
	 /<<ZQQQQQQQQG 5 2233445 	 	 	NN%%#hh	         	 	s   28 
A7+A22A7answerr  c           	        K   	 | j                             |||||           d{V  dS # t          $ r6}t                              d||t          |                     Y d}~dS d}~ww xY w)u   将当前问答轮次追加到会话存储中，用于后续多轮对话。

        Append a Q&A turn to the configured session store.Nsession_save_failedr  )rV   save_sessionr  r  r  r`   )r[   rF  r  r_   r  r  r  s          r\   r  zResearchEngine._save_sessionx  s      	%22            	 	 	NN%%#hh	          	s   $* 
A*+A%%A*)NNN)rD   r!   rE   r
   rF   r   rG   r"   rH   rI   rJ   rK   rL   rM   rN   rO   )r_   r`   rN   ra   )r_   r`   rf   r   rN   rg   )rk   ra   r_   rl   rf   r   rN   rg   )rf   r   rN   rp   )
r   r`   r   r   rk   r   r   r   rN   ry   )r   rp   r   r`   rN   ry   )r   r`   r   rp   rN   rp   )r   rg   r   r`   rN   rg   )r   rp   rN   rp   )r   rg   rN   r`   )r   r`   rf   r   r   r   rk   r   r   r   rN   r   )r  r   r   r   rf   r   r  r   r  r   r  rl   r  rl   rN   rp   )
r_   r`   rf   r   rF  rl   r  r   rN   rG  )r_   r`   rf   r   r  r   rN   rp   )r  r   r  r   rN   r   )r  r   r   r   rf   r   rF  rl   r  r   rN   rG  )r  r   r   r   r  r`   rf   r   r  rl   r  r   rF  rl   r  r   rN   rG  )r_   r`   rf   r   rF  rl   r  r   rO  r`   rN   rG  )rF  r`   r  r`   rN   rg   )rF  r`   r  r`   r_   r`   r  r`   r  rg   rN   rO   )__name__
__module____qualname____doc__r]   re   rj   ro   staticmethodr   r   r   classmethodr   r   r   r   r   r  rD  rL  rN  rk  r}  r  r  rJ  r  r  rt   r^   r\   rC   rC   \   s^        4 ,059,0 
  
  
  
  
L@ @ @ @? ? ? ?
O O O O 
 
 
 \
    $('+W W W W W \W ! ! ! \!F 
 
 
 [
2    [8 

 

 

 \

 
 
 
 [
 IL IL IL \IL`  $('+.s .s .s .s .s .sl *.*.#'%)_
 _
 _
 _
 _
 _
T "&)-
 
 
 
 
 
: "&)-
 
 
 
 
 
, *.u
 u
 u
 u
 u
 u
v *.	'
 '
 '
 '
 '
 '
^ "&)-H- H- H- H- H- H-b '++/!%)-i- i- i- i- i- i-b *.F- F- F- F- F- F-X   *     r^   rC   N)Cr  
__future__r   typingr   r   app.api.schemas.researchr   r   r   
app.configr	   app.core.embeddingr
   app.core.graph_query_plannerr   r   r   app.core.graph_query_servicer   app.core.permissionr   app.core.research_formatterr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   app.core.research_retrieverr    app.infrastructure.es_clientr!   app.infrastructure.llm_clientr"   app.infrastructure.redis_clientr#    app.infrastructure.session_storer$   r%   app.prompts.research_promptsr&   r'   r(   r)   app.utils.loggerr*   r  r  r:  r  r8  r  r   rA   __annotations__rC   rt   r^   r\   <module>r     s     # " " " " " % % % % % % % % N N N N N N N N N N       / / / / / / V V V V V V V V V V : : : : : : 1 1 1 1 1 1                                   $ : 9 9 9 9 9 1 1 1 1 1 1 3 3 3 3 3 3 7 7 7 7 7 7                   ( ' ' ' ' '	H		     
  ! $N     u u u u u u u u u ur^   