
    XjN&                         U d dl mZ d dlmZ d dlmZ d dlmZ  ee          Z	 G d d          Z
dae
dz  ed<   d	e
fd
ZdS )    )Any)get_graph_cache)Neo4jClient)
get_loggerc                      e Zd ZdefdZ	 	 	 ddee         deded	ed
ee         dz  dedeeee	f                  fdZ
dedededeeee	f                  fdZ	 ddededededeeee	f                  f
dZ	 ddededededeeee	f                  f
dZ	 	 ddededededz  dedeeee	f                  fdZ	 ddedededededeee	f         dz  fdZdS ) GraphQueryServiceneo4j_clientc                 :    || _         t                      | _        d S )N)r	   r   cache)selfr	   s     F/lsinfo/ai/hellotax_ai/base_platform/app/services/graph/graph_query.py__init__zGraphQueryService.__init__   s    ($&&


       N   document_ids	tenant_idkb_iddepthrelation_typeslimitreturnc           	      ^   |sg S | j                             dt          |          |||||          }| j                             |          }||S |ddg}d                    |          }	|dk    rd|	 d}
nd	|	 d
}
	 | j                            |
||||d          }t                              dt          |           dt          |           d           | j         
                    ||           |S # t          $ r)}t                              d|            g cY d }~S d }~ww xY w)N	neighbors)doc_idsr   r   r   r   r   
REFERENCES
SIMILAR_TO|r   z
            MATCH (d:Document)
            WHERE d.id IN $doc_ids
              AND d.tenant_id = $tenant_id
              AND d.kb_id = $kb_id
            MATCH (d)-[r:aQ  ]-(neighbor:Document)
            WHERE neighbor.tenant_id = $tenant_id
              AND neighbor.kb_id = $kb_id
              AND NOT (neighbor.id IN $doc_ids)
              AND (neighbor.doc_status IS NULL OR NOT (neighbor.doc_status IN ['obsolete', 'expired']))
            RETURN DISTINCT
                neighbor.id as id,
                neighbor.title as title,
                neighbor.summary as summary,
                type(r) as relation_type,
                COALESCE(r.similarity, r.confidence, 0.5) as score
            ORDER BY score DESC
            LIMIT $limit
            z
            MATCH (d:Document)
            WHERE d.id IN $doc_ids
              AND d.tenant_id = $tenant_id
              AND d.kb_id = $kb_id
            MATCH path = (d)-[:as  *1..2]-(neighbor:Document)
            WHERE neighbor.tenant_id = $tenant_id
              AND neighbor.kb_id = $kb_id
              AND NOT (neighbor.id IN $doc_ids)
              AND (neighbor.doc_status IS NULL OR NOT (neighbor.doc_status IN ['obsolete', 'expired']))
            WITH DISTINCT neighbor, length(path) as distance
            RETURN
                neighbor.id as id,
                neighbor.title as title,
                neighbor.summary as summary,
                'multi_hop' as relation_type,
                1.0 / distance as score
            ORDER BY score DESC
            LIMIT $limit
            )r   r   r   r   
parametersz	Expanded z neighbors from z seed documentszFailed to expand neighbors: )r   _generate_keysortedgetjoinr	   execute_queryloggerinfolenset	Exceptionerror)r   r   r   r   r   r   r   	cache_keycached_resultrel_patternqueryresultses                r   expand_neighborsz"GraphQueryService.expand_neighbors   s     	IJ,,<(() - 
 
	 
y11$  !*L9Nhh~..A:: r  GR  r  r  rEE [  MX  [  [  [E	'55+!*""	  6  G KK\CLL\\#l:K:K\\\   JNN9g...N 	 	 	LL;;;<<<IIIIII	s    A8C9 9
D,D'!D,'D,document_idc                 f   | j                             d|||          }| j                             |          }||S d}	 | j                            ||||d          }| j                             ||           |S # t          $ r)}t                              d|            g cY d }~S d }~ww xY w)Ndoc_entities)doc_idr   r   a8  
        MATCH (d:Document {id: $doc_id, tenant_id: $tenant_id, kb_id: $kb_id})
        MATCH (d)-[r:CONTAINS]->(e:Entity)
        RETURN
            e.name as name,
            e.type as type,
            e.description as description,
            r.salience as salience
        ORDER BY r.salience DESC
        r   z!Failed to get document entities: )	r   r!   r#   r	   r%   r)   r*   r&   r+   )	r   r3   r   r   r,   r-   r/   r0   r1   s	            r   get_document_entitiesz'GraphQueryService.get_document_entitiesA   s     J,,;)5 - 
 
	 
y11$   T	'55[y[`"a"a 6  G JNN9g...N 	 	 	LL@Q@@AAAIIIIII	s    <A= =
B0B+%B0+B0
   entity_namec                     d}	 | j                             |||||d          }|S # t          $ r)}t                              d|            g cY d }~S d }~ww xY w)Na  
        MATCH (e:Entity {name: $entity_name, tenant_id: $tenant_id, kb_id: $kb_id})
        MATCH (e)<-[r:CONTAINS]-(d:Document)
        WHERE d.tenant_id = $tenant_id
          AND d.kb_id = $kb_id
        RETURN
            d.id as id,
            d.title as title,
            d.summary as summary,
            r.salience as salience
        ORDER BY r.salience DESC
        LIMIT $limit
        r9   r   r   r   r   z!Failed to find entity documents: r	   r%   r*   r&   r+   r   r9   r   r   r   r/   r0   r1   s           r   find_entity_documentsz'GraphQueryService.find_entity_documentsU   s     o	'55#.!*""	  6  G N 	 	 	LL@Q@@AAAIIIIII	   "' 
AAAAc                     d}	 | j                             |||||d          }|S # t          $ r)}t                              d|            g cY d }~S d }~ww xY w)Na  
        MATCH (e1:Entity {name: $entity_name, tenant_id: $tenant_id, kb_id: $kb_id})
        MATCH (e1)-[r:RELATED_TO|CO_OCCURS_WITH]-(e2:Entity)
        WHERE e2.tenant_id = $tenant_id
          AND e2.kb_id = $kb_id
        RETURN
            e2.name as name,
            e2.type as type,
            e2.description as description,
            type(r) as relation_type,
            COALESCE(r.confidence, r.count, 0.5) as score
        ORDER BY score DESC
        LIMIT $limit
        r;   r   z Failed to get related entities: r<   r=   s           r   get_related_entitiesz&GraphQueryService.get_related_entitiesh   s     H	'55#.!*""	  6  G N 	 	 	LL?A??@@@IIIIII	r?   
query_textentity_typec                    | j                             d|||||          }| j                             |          }||S g d}|r|                    d           d                    |          }	d|	 d}
||||d}|r||d	<   	 | j                            |
|
          }| j                             ||           |S # t          $ r)}t          
                    d|            g cY d }~S d }~ww xY w)Nsearch_entities)r/   r   r   rC   r   )ze.tenant_id = $tenant_idze.kb_id = $kb_idz(toLower(e.name) CONTAINS toLower($query)ze.type = $entity_typez AND z(
        MATCH (e:Entity)
        WHERE z
        RETURN
            e.name as name,
            e.type as type,
            e.description as description
        LIMIT $limit
        )r/   r   r   r   rC   r   zFailed to search entities: )r   r!   r#   appendr$   r	   r%   r)   r*   r&   r+   )r   rB   r   r   rC   r   r,   r-   where_clauseswhere_clauser/   paramsr0   r1   s                 r   rE   z!GraphQueryService.search_entities{   sX    J,,# - 
 
	 
y11$  
 
 

  	:  !8999||M22 `\  `  `  `%IX]^^ 	0$/F=!	'55e5OOGJNN9g...N 	 	 	LL:q::;;;IIIIII	s   8B= =
C0C+%C0+C0   source_doc_idtarget_doc_id	max_depthc                    d}	 | j                             |                    dt          |                    ||||d          }|r|d         nd S # t          $ r(}t
                              d|            Y d }~d S d }~ww xY w)Na  
        MATCH (d1:Document {id: $source_id, tenant_id: $tenant_id, kb_id: $kb_id})
        MATCH (d2:Document {id: $target_id, tenant_id: $tenant_id, kb_id: $kb_id})
        MATCH path = shortestPath((d1)-[*..{max_depth}]-(d2))
        RETURN
            [node in nodes(path) | node.id] as node_ids,
            [rel in relationships(path) | type(rel)] as relation_types,
            length(path) as path_length
        z{max_depth})	source_id	target_idr   r   r   r   zFailed to find shortest path: )r	   r%   replacestrr*   r&   r+   )	r   rK   rL   r   r   rM   r/   r0   r1   s	            r   get_shortest_pathz#GraphQueryService.get_shortest_path   s     @	'55mS^^<<!.!.!*"	  6  G ")271::d2 	 	 	LL=!==>>>44444	s   AA 
BA??B)r   Nr   )r8   )Nr   )rJ   )__name__
__module____qualname__r   r   listintrR   dictr   r2   r7   r>   rA   rE   rS    r   r   r   r   
   sg       '[ ' ' ' ' +// /3i/ / 	/
 / S	D(/ / 
d38n	/ / / /b+.7:	d38n	   * JL +.7:CF	d38n	   ( JL +.7:CF	d38n	   0 #'% %% % 	%
 4Z% % 
d38n	% % % %P de  14ADMP]`	c3h$	     r   r   Ngraph_query_servicer   c                  H    t           ddlm}  t          |           a t           S )Nr   r	   )r[   app.services.graph.neo4j_clientr	   r   r]   s    r   get_graph_query_servicer_      s.    "@@@@@@/==r   )typingr   app.services.graph.graph_cacher   r^   r   common_loggingr   rT   r&   r   r[   __annotations__r_   rZ   r   r   <module>rd      s           : : : : : : 7 7 7 7 7 7 % % % % % %	H		i i i i i i i iX 15 &- 4 4 4!2      r   