
    giH                       d Z ddlmZ ddlmZmZ ddlmZmZm	Z	m
Z
 ddlmZ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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	l0m1Z1  e1e2          Z3 ed
dg          Z4d|dZ5e46                    de          d}d            Z7e46                    de          d~d            Z8e46                    de          dd            Z9e4:                    de)d !          dd%            Z;e4<                    d&          dd+            Z=e4>                    d&          dd,            Z?e46                    d-e'          dd/            Z@e4:                    d-e+d !          dd2            ZAe4<                    d3          dd5            ZBe4>                    d3          dd6            ZCe46                    d7e          	 	 	 dddB            ZDe4:                    dCe          ddF            ZEe46                    dGe          	 	 	 	 	 dddO            ZFe46                    dPe          ddS            ZGe4:                    dGed !          ddV            ZHe4<                    dP          ddX            ZIe4>                    dPe          ddZ            ZJe4:                    d[e!          dd^            ZKe4:                    d_e          dda            ZLe46                    dbe"          dde            ZMe46                    dfe%          	 	 	 	 	 dddk            ZNe4:                    dfe$d !          ddn            ZOe4>                    do          ddq            ZPe46                    dre          ddt            ZQe4:                    due          ddy            ZRe4>                    dz          dd{            ZSd8S )u  Admin endpoints for knowledge-graph management.

Provides entity CRUD, type definition management, dedup/merge,
relationship management, rebuild, placeholder handling, and statistics.

知识图谱管理接口模块。
提供实体与关系的增删改查、实体/关系类型定义管理、
重复实体检测与合并、图谱重建任务、占位符处理，
以及图谱统计与数据质量健康度检查。
    )annotations)	AnnotatedAny)	APIRouterDependsHTTPExceptionRequest)UserContextget_current_user)DuplicateListResponseEntityCreateRequestEntityCreateResponseEntityDeleteResponseEntityDetailEntityListResponseEntityMergeRequestEntityMergeResponseEntityTypeCreateRequestEntityTypeListResponseEntityTypeUpdateRequestGraphHealthResponseGraphStatsResponsePlaceholderLinkRequestPlaceholderLinkResponsePlaceholderListResponseRebuildAllResponseRebuildRequestRebuildResponseRebuildStatusResponseRelationshipCreateRequestRelationshipCreateResponseRelationshipListResponseRelTypeCreateRequestRelTypeListResponseRelTypeUpdateRequestEntityTypeItemEntityUpdateRequestRelTypeItem)settings)GraphAdminService)
get_loggerz/admin/graphzadmin-graph)prefixtagsrequestr	   returnr*   c                $    | j         j        j        S )z)Resolve GraphAdminService from app.state.)appstategraph_admin_service)r.   s    0D:\work\zm-rag\backend\app\api\v1\admin_graph.py_get_graph_admin_servicer5   >   s    ;00    z/stats)response_modeluser1Annotated[UserContext, Depends(get_current_user)]svc?Annotated[GraphAdminService, Depends(_get_graph_admin_service)]r   c                R   K   |                                  d{V }t          di |S )zBReturn graph-level statistics (node/relationship counts, orphans).N )get_graph_statsr   )r8   r:   datas      r4   graph_statsr@   F   s?       $$&&&&&&&&D%%%%%r6   z/healthr   c                r  K   |j         j        j        }	 |j                            t
          j        ddddiidd           d{V }t          |t                    r|n|j	        }d	 |d
         d
         D             }n# t          $ r g }Y nw xY w|                    |           d{V }t          di |S )u   Return data-quality health metrics.

    数据质量健康度检查：对比 ES 与 Neo4j 的文档覆盖率，
    检测孤立实体和重复实体候选数量。
    i'  termstatus	completedF)sizequery_sourceindexbodyNc                    g | ]
}|d          S )_idr=   ).0hits     r4   
<listcomp>z graph_health.<locals>.<listcomp>g   s    @@@Sc%j@@@r6   hitsr=   )r1   r2   	es_clientrawsearchr)   es_meta_index
isinstancedictrJ   	Exceptionget_graph_healthr   )r8   r:   r.   rQ   resprR   
es_doc_idsr?   s           r4   graph_healthr[   P   s      !+I]))( 8["9:   * 
 
 
 
 
 
 
 
 !t,,;dd$)@@CK,?@@@

   


 %%j11111111D&&&&&s   A*B   BBz/entity-typesr   c                n   K   |                                  d {V }t          d |D                       S )Nc                &    g | ]}t          d i |S r=   )r&   rM   is     r4   rO   z%list_entity_types.<locals>.<listcomp>x   s&    (L(L(L)<)<!)<)<(L(L(Lr6   items)list_entity_typesr   r8   r:   rb   s      r4   rc   rc   r   sK      
 ''))))))))E!(L(Le(L(L(LMMMMr6      )r7   status_coderJ   r   r&   c                   K   	 |                     | j        | j        | j        | j        | j                   d {V }t          di |ddiS # t          $ r$}t          dt          |                    |d }~ww xY w)N)namedescriptioniconcolorproperties_schemainstance_countr     rf   detailr=   )
create_entity_typerh   ri   rj   rk   rl   r&   
ValueErrorr   strrJ   r8   r:   resultexcs        r4   rq   rq   {   s      
G--(*"4 . 
 
 
 
 
 
 
 
 9999q9999 G G GCHH===3FGs   AA 
A;A66A;z/entity-types/{name}rh   rs   r   dict[str, Any]c                   K   |                     d          }	 |                    | |           d {V S # t          $ r$}t          dt	          |                    |d }~ww xY wNT)exclude_none  ro   )
model_dumpupdate_entity_typerr   r   rs   rh   rJ   r8   r:   updatesrv   s         r4   r}   r}      s       oo4o00GG++D'::::::::: G G GCHH===3FG   6 
A$ AA$c                   K   	 |                     |            d {V S # t          $ r$}t          dt          |                    |d }~ww xY wNr{   ro   )delete_entity_typerr   r   rs   rh   r8   r:   rv   s       r4   r   r      sp      G++D111111111 G G GCHH===3FG    
AAAz/relationship-typesr$   c                n   K   |                                  d {V }t          d |D                       S )Nc                &    g | ]}t          d i |S r^   )r(   r_   s     r4   rO   z"list_rel_types.<locals>.<listcomp>   s&    %F%F%F1k&6&6A&6&6%F%F%Fr6   ra   )list_rel_typesr$   rd   s      r4   r   r      sK      
 $$&&&&&&&&E%F%F%F%F%FGGGGr6   r#   r(   c                   K   	 |                     | j        | j        | j        | j                   d {V }t          di |ddiS # t          $ r$}t          dt          |                    |d }~ww xY w)N)rh   ri   source_labelstarget_labelsrm   r   rn   ro   r=   )	create_rel_typerh   ri   r   r   r(   rr   r   rs   rt   s        r4   r   r      s      	G**(,,	 + 
 
 
 
 
 
 
 
 66V66A6666 G G GCHH===3FGs   AA 
A5A00A5z/relationship-types/{name}r%   c                   K   |                     d          }	 |                    | |           d {V S # t          $ r$}t          dt	          |                    |d }~ww xY wry   )r|   update_rel_typerr   r   rs   r~   s         r4   r   r      s       oo4o00GG((w777777777 G G GCHH===3FGr   c                   K   	 |                     |            d {V S # t          $ r$}t          dt          |                    |d }~ww xY wr   )delete_rel_typerr   r   rs   r   s       r4   r   r      sp      G((......... G G GCHH===3FGr   z/duplicatesN333333?2   label
str | None	thresholdfloatlimitintr   c                ~   K   |                     |||           d {V }t          |t          |                    S )N)r   r   r   )
candidatestotal)detect_duplicatesr   len)r8   r:   r   r   r   r   s         r4   r   r      sN       ,,5IUZ,[[[[[[[[J Jc*ooNNNNr6   z/entities/merger   r   c                   K   	 |                     | j        | j        | j                   d {V }t	          di |S # t
          $ r$}t          dt          |                    |d }~ww xY w)N)
primary_idsecondary_id	add_aliasr{   ro   r=   )merge_entitiesr   r   r   r   rr   r   rs   rt   s        r4   r   r      s      G))*n * 
 
 
 
 
 
 
 

 #,,V,,, G G GCHH===3FGs   8= 
A+A&&A+z	/entities      connection_countpage	page_sizesort_byr   c                ^   K   |                     |||||           d {V }t          di |S )N)r   rh   r   r   r   r=   )list_entitiesr   )r8   r:   r   rh   r   r   r   r?   s           r4   r   r     sa       ""$TY #        D %%%%%r6   z/entities/{entity_id}	entity_idr   c                z   K   |                     |            d {V }|t          dd          t          di |S )N  zEntity not foundro   r=   )get_entity_detailr   r   )r   r8   r:   rp   s       r4   r   r     sZ       ((33333333F~4FGGGG!!&!!!r6   r   r   c                   K   	 |                     | j        | j                   d {V }t          di |S # t          $ r9}dt          |          v rdnd}t          |t          |                    |d }~ww xY w)N)r   
propertieszalready existsrn   r{   ro   r=   )create_entityr   r   r   rr   rs   r   )rJ   r8   r:   ru   rv   codes         r4   r   r     s      H((tzdo(VVVVVVVV#--f--- H H H&#c((22ssSXX>>>CGHs   27 
A:4A55A:r'   c                   K   	 |                     | |j                   d {V S # t          $ r$}t          dt	          |                    |d }~ww xY w)Nr   ro   )update_entityr   rr   r   rs   )r   rJ   r8   r:   rv   s        r4   r   r   ,  st      G&&y$/BBBBBBBBB G G GCHH===3FGs    % 
AAAr   c                T   K   |                     |            d {V }t          di |S )Nr=   )delete_entityr   )r   r8   r:   ru   s       r4   r   r   9  sA       $$Y////////F))&)))r6   z/rebuildr   r   c                   K   ddl m} |                    | j                  }t	          |j        t          | j                            S )uG   对指定文档重新构建知识图谱，通过 Celery 异步执行。r   )rebuild_document_graphs_task)task_id	doc_count)app.tasks.graph_taskr   delaydoc_idsr   idr   )rJ   r8   r   tasks       r4   rebuild_doc_graphsr   F  sO       BAAAAA'--dl;;D47c$,6G6GHHHHr6   z/rebuild-allr   c                |  K   ddl m} |j        j        j        }	 |j                            t          j        ddddiii           d{V }t          |t                    r|n|j        }|                    d	d          }n# t          $ r d}Y nw xY w|                                }t          |j        |
          S )u<   对所有已完成入库的文档重新构建知识图谱。r   )rebuild_all_graph_taskrF   rB   rC   rD   rH   Ncount)r   
total_docs)r   r   r1   r2   rQ   rR   r   r)   rT   rU   rV   rJ   getrW   r   r   r   )r8   r.   r   rQ   rY   rR   r   r   s           r4   rebuild_all_graphsr   R  s       <;;;;; !+I](((FX{$;<= ) 
 
 
 
 
 
 
 
 !t,,;dd$)##    "''))Ddg%@@@@s   A&B BBz/rebuild-status/{task_id}r   r   c                  K   ddl m} ddlm}  || |          }|j        dk    rt          | d          S |j        dv r|j        pi }t          | dt          |t                    r|	                    d	d
          nd
t          |t                    r|	                    dd          ndt          |t                    r|	                    dd          ndt          |t                    r|	                    dd          nd          S |j        dk    rs|j
        pi }t          | ddt          |t                    r|	                    dd          ndt          |t                    r|	                    dd          nd          S |j        dk    r$t          | dt          |j
                            S t          | |j                  S )u3   查询图谱重建任务的执行状态与进度。r   )AsyncResult)
celery_app)r1   PENDING)r   rC   )STARTED
PROCESSINGr   progressg        currentr   current_doc_id )r   rC   r   r   r   r   SUCCESS	COMPLETEDg      ?)r   rC   r   r   r   FAILUREFAILED)r   rC   error)celery.resultr   app.tasks.celery_appr   r2   r   inforU   rV   r   ru   rs   )r   r8   r   r   ru   r   s         r4   rebuild_statusr   j  s      *)))))//////[j111F|y  $WYGGGG	2	2	2{ b$2<T42H2HQTXXj#...c.8t.D.DKDHHY***!*4T4*@*@G$((7A&&&a=Gd=S=S[488$4b999Y[
 
 
 	
 
	"	"}"$K#*4T4*@*@G$((7A&&&a,6tT,B,BIDHHWa(((
 
 
 	

 
	"	"$HC4F4F
 
 
 	
 %WV\JJJJr6   z/relationshipstype	source_id	target_idr"   c                ^   K   |                     |||||           d {V }t          di |S )N)rel_typer   r   r   r   r=   )list_relationshipsr"   )r8   r:   r   r   r   r   r   r?   s           r4   r   r     sb       ''iY (        D $++d+++r6   r    r!   c                   K   	 |                     | j        | j        | j        | j                   d {V }t          di |S # t          $ r$}t          dt          |                    |d }~ww xY w)N)r   r   r   r   r{   ro   r=   )	create_relationshipr   r   r   r   r!   rr   r   rs   rt   s        r4   r   r     s      G..nY4? / 
 
 
 
 
 
 
 
 *33F333 G G GCHH===3FGs   >A 
A1A,,A1z/relationships/{rel_id}rel_idc                l   K   |                     |            d {V }|st          dd          | ddS )Nr   zRelationship not foundro   Tr   deleted)delete_relationshipr   )r   r8   r:   r   s       r4   r   r     sX       ++F33333333G N4LMMMMT***r6   z/placeholdersr   c                v   K   |                                  d {V }t          |t          |                    S )N)rb   r   )list_placeholdersr   r   rd   s      r4   r   r     sD      
 ''))))))))E"c%jjAAAAr6   z#/placeholders/{placeholder_id}/linkplaceholder_idr   r   c                   K   	 |                     | |j                   d {V }t          di |S # t          $ r$}t	          dt          |                    |d }~ww xY w)Nr{   ro   r=   )link_placeholderreal_doc_idr   rr   r   rs   )r   rJ   r8   r:   ru   rv   s         r4   r   r     s      G++ND<LMMMMMMMM&00000 G G GCHH===3FGs   ,1 
AAAz/placeholders/{placeholder_id}c                l   K   |                     |            d {V }|st          dd          | ddS )Nr   zPlaceholder not foundro   Tr   )delete_placeholderr   )r   r8   r:   r   s       r4   r   r     sX       **>::::::::G M4KLLLL T222r6   )r.   r	   r/   r*   )r8   r9   r:   r;   r/   r   )r8   r9   r:   r;   r.   r	   r/   r   )r8   r9   r:   r;   r/   r   )rJ   r   r8   r9   r:   r;   r/   r&   )
rh   rs   rJ   r   r8   r9   r:   r;   r/   rw   )rh   rs   r8   r9   r:   r;   r/   rw   )r8   r9   r:   r;   r/   r$   )rJ   r#   r8   r9   r:   r;   r/   r(   )
rh   rs   rJ   r%   r8   r9   r:   r;   r/   rw   )Nr   r   )r8   r9   r:   r;   r   r   r   r   r   r   r/   r   )rJ   r   r8   r9   r:   r;   r/   r   )NNr   r   r   )r8   r9   r:   r;   r   r   rh   r   r   r   r   r   r   rs   r/   r   )r   rs   r8   r9   r:   r;   r/   r   )rJ   r   r8   r9   r:   r;   r/   r   )
r   rs   rJ   r'   r8   r9   r:   r;   r/   rw   )r   rs   r8   r9   r:   r;   r/   r   )rJ   r   r8   r9   r/   r   )r8   r9   r.   r	   r/   r   )r   rs   r8   r9   r/   r   )NNNr   r   )r8   r9   r:   r;   r   r   r   r   r   r   r   r   r   r   r/   r"   )rJ   r    r8   r9   r:   r;   r/   r!   )r   rs   r8   r9   r:   r;   r/   rw   )r8   r9   r:   r;   r/   r   )
r   rs   rJ   r   r8   r9   r:   r;   r/   r   )r   rs   r8   r9   r:   r;   r/   rw   )T__doc__
__future__r   typingr   r   fastapir   r   r   r	   app.api.depsr
   r   app.api.schemas.admin_graphr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   
app.configr)   app.core.graph_admin_servicer*   app.utils.loggerr+   __name__loggerrouterr5   r   r@   r[   rc   postrq   putr}   deleter   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r=   r6   r4   <module>r      s  	 	 # " " " " " ! ! ! ! ! ! ! ! > > > > > > > > > > > > 6 6 6 6 6 6 6 6                                                             >        : : : : : : ' ' ' ' ' '	H			.	?	?	?1 1 1 1 H%788& & & 98& I&9::' ' ' ;:'B O,BCCN N N DCN _^MMG G G NMG$ "##
G 
G 
G $#
G %&&G G G '&G !2EFFH H H GFH ";CPPG G G QPG" ())
G 
G 
G *)
G +,,G G G -,G  M*?@@ O O O O A@O /BCCG G G DCG  K(:;; %& & & & <;& #LAA" " " BA" [)=3OO
H 
H 
H PO
H #$$	G 	G 	G %$	G &7KLL* * * ML* Z88I I I 98I ^,>??A A A @?A. '8MNN#K #K #K ON#KR -EFF   , , , , GF,  .HVYZZG G G [ZG ())+ + + *)+ O,CDDB B B EDB 2CZ[[
G 
G 
G \[
G /003 3 3 103 3 3r6   