
    $j-                        d Z ddlmZ ddlmZmZ ddlmZmZ  G d de          Z G d de          Z	 G d	 d
e          Z
 G d de          Z G d de          Z G d de          Z G d de          Z G d de          Z G d de          Z G d de          Z G d de          Z G d de          Z G d de          Z G d d e          Zd!S )"z
Search trace models for debugging and visualization.

These Pydantic models define the structure of search traces, capturing
every step of the spreading activation search process for analysis.
    )datetime)AnyLiteral)	BaseModelFieldc                   h    e Zd ZU dZ edd          Zedz  ed<    edd          Zedz  ed<   dS )TemporalConstraintz1Detected temporal constraint from query analysis.NzStart of temporal rangedefaultdescriptionstartzEnd of temporal rangeend)	__name__
__module____qualname____doc__r   r   r   __annotations__r        i/home/rurouni/.hermes/hermes-agent/venv/lib/python3.11/site-packages/hindsight_api/engine/search/trace.pyr	   r	      s`         ;;"U4=VWWWE8d?WWW 5;RSSSCDSSSSSr   r	   c                   T   e Zd ZU dZ ed          Zeed<    ed          Ze	e
         ed<    ed          Zeed<    ed	          Zeed
<    ed          Zeed<    edd          Ze	e         dz  ed<    edd          Zedz  ed<    edd          Zedz  ed<   dS )	QueryInfoz#Information about the search query.zOriginal query textr   
query_textz Generated query embedding vectorquery_embeddingzWhen the query was executed	timestampzMaximum nodes to explorebudgetz#Maximum tokens to return in results
max_tokensNzTags filter applied to recallr
   tagsz4Tags matching mode: any, all, any_strict, all_strict
tags_matchz"Detected temporal range from querytemporal_constraint)r   r   r   r   r   r   strr   r   listfloatr   r   r   intr   r   r    r!   r	   r   r   r   r   r      s7        --e(=>>>J>>>#(55W#X#X#XOT%[XXX%,IJJJIxJJJ%$>???FC???e(MNNNJNNN"U4=\]]]D$s)d
]]]"U4=stttJd
ttt5:U"F6 6 6+d2     r   r   c                       e Zd ZU dZ ed          Zeed<    ed          Zeed<    eddd	
          Z	e
ed<    ed          Zeed<   dS )
EntryPointz(An entry point node selected for search.Memory unit IDr   node_idMemory unit text contenttextzCosine similarity to query              ?r   gelesimilarity_scorez!Rank among entry points (1-based)rankN)r   r   r   r   r   r)   r"   r   r+   r1   r$   r2   r%   r   r   r   r'   r'   $   s         225%5666GS666"<===D#===#e0LQTY\]]]e]]]"EFFFD#FFFFFr   r'   c                   T   e Zd ZU dZ edd          Zeed<    eddd          Zeed	<    ed
dd          Z	eed<    eddd          Z
eed<    ed          Zeed<    ed          Zeed<    ed          Zeed<    ed          Zeed<    ed          Zeed<   dS )WeightComponentsz+Breakdown of weight calculation components.z?Activation from spreading (can exceed 1.0 through accumulation)r,   r   r/   
activationzSemantic similarity to queryr-   r.   semantic_similarityzRecency weightrecencyzNormalized frequency weight	frequencyzCombined final weightr   final_weightz0.3 * activationactivation_contributionz0.3 * semantic_similaritysemantic_contributionz0.25 * recencyrecency_contributionz0.15 * frequencyfrequency_contributionN)r   r   r   r   r   r6   r$   r   r7   r8   r9   r:   r;   r<   r=   r>   r   r   r   r4   r4   -   s?        55*kpstttJttt!&3QVY^a!b!b!bbbbU'7CCHHHGUHHHu)F3SVWWWIuWWW%,CDDDL%DDD &+U7I%J%J%JUJJJ#(55P#Q#Q#Q5QQQ"'%4D"E"E"E%EEE$)E6H$I$I$IEIIIIIr   r4   c                   L   e Zd ZU dZ ed          Zeed<    ed          Ze	d         ed<    edd	
          Z
eed<    edd          Zedz  ed<    edd          Zedz  ed<    ed          Zeed<    edd          Zedz  ed<    edd          Zeed<   dS )LinkInfoz'Information about a link to a neighbor.zTarget node IDr   
to_node_idzType of linktemporalsemanticentity	link_typezIWeight of the link (can exceed 1.0 when aggregating multiple connections)r,   r5   link_weightNz"Entity ID if link_type is 'entity'r
   	entity_idzJActivation that would be passed to neighbor (None for supplementary links)new_activationz*Whether this link was followed (or pruned)followedz+Why link was not followed (if not followed)prune_reasonFzHWhether this is a supplementary link (multiple connections to same node)is_supplementary)r   r   r   r   r   rA   r"   r   rF   r   rG   r$   rH   rI   rJ   boolrK   rL   r   r   r   r@   r@   =   sS        11e(8999J999;@5^;\;\;\Iw78\\\_dg  K    "E$<`aaaIsTzaaa#(5"n$ $ $NEDL    U'STTTHdTTT$uT?lmmmL#*mmm"U#m  d     r   r@   c                      e Zd ZU dZ ed          Zeed<    ed          Ze	ed<    ed          Z
e	ed<    ed	          Ze	ed
<    edd          Zedz  ed<    ed          Zeed<    edd          Ze	dz  ed<    edd          Zed         dz  ed<    edd          Zedz  ed<    ed          Zeed<    eed          Zee         ed<    edd          Zedz  ed<   dS )	NodeVisitz0Information about visiting a node during search.zStep number in search (1-based)r   stepr(   r)   r*   r+   Memory unit contextcontextNWhen the memory occurredr
   
event_datezWhether this is an entry pointis_entry_pointzNode that led to this oneparent_node_idzType of link from parentrB   rF   zWeight of link from parentrG   zWeight calculation breakdownweightszLinks explored from this nodedefault_factoryr   neighbors_exploredz5Final rank in results (1-based, None if not in top-k)
final_rank)r   r   r   r   r   rP   r%   r   r)   r"   r+   rR   rT   r   rU   rM   rV   rF   r   rG   r$   rW   r4   r#   rZ   r@   r[   r   r   r   rO   rO   P   s        ::"CDDDD#DDD5%5666GS666"<===D#===5%:;;;GS;;;"'%B\"]"]"]J4]]] !5-MNNNNDNNN!&tA\!]!]!]NC$J]]]BG%"<C C CIw784?    !&d@\ ] ] ]K]]] !&2P Q Q QGQQQ */tQp)q)q)qXqqq #U4=tuuuJd
uuuuur   rO   c                       e Zd ZU dZ ed          Zeed<    ed          Ze	d         ed<    ed          Z
eed	<    ed
          Zeed<   dS )PruningDecisionz3Records when a node was considered but not visited.zNode that was prunedr   r)   zWhy it was pruned)already_visitedactivation_too_lowbudget_exhaustedreasonzActivation value when prunedr6   z'What step it would have been if visitedwould_have_been_stepN)r   r   r   r   r   r)   r"   r   ra   r   r6   r$   rb   r%   r   r   r   r]   r]   k   s         ==5%;<<<GS<<<SXSX'T T TFGOP    *HIIIJIII %2[ \ \ \#\\\\\r   r]   c                       e Zd ZU dZ ed          Zeed<    ed          Ze	ed<    ee
d          Ze
eef         ed	<   d
S )SearchPhaseMetricsz'Performance metrics for a search phase.zName of the phaser   
phase_namezTime taken in secondsduration_secondsz!Additional phase-specific metricsrX   detailsN)r   r   r   r   r   re   r"   r   rf   r$   dictrg   r   r   r   r   rd   rd   v   s}         11e(;<<<J<<<#e0GHHHeHHH#eDFijjjGT#s(^jjjjjr   rd   c                   6   e Zd ZU dZ ed          Zeed<    ed          Ze	ed<    ed          Z
e	ed<    ed	d
          Ze	ed<    edd          Zedz  ed<    edd          Ze	dz  ed<    ed          Zeed<    ed          Ze	ed<   dS )RetrievalResultz(A single result from a retrieval method.z'Rank in this retrieval method (1-based)r   r2   r(   r)   r*   r+    rQ   r
   rR   NrS   rT   zFact type (world, experience)	fact_typez Score from this retrieval methodscorezBName of the score (e.g., 'similarity', 'bm25_score', 'activation')
score_name)r   r   r   r   r   r2   r%   r   r)   r"   r+   rR   rT   r   rl   rm   r$   rn   r   r   r   rj   rj   ~   s        22"KLLLD#LLL5%5666GS666"<===D#===51FGGGGSGGG"'%B\"]"]"]J4]]]!E$<[\\\IsTz\\\5%GHHHE5HHHe(lmmmJmmmmmr   rj   c                       e Zd ZU dZ ed          Zed         ed<    edd          Ze	dz  ed	<    ed
          Z
ee         ed<    ed          Zeed<    eed          Zee	ef         ed<   dS )RetrievalMethodResultsz'Results from a single retrieval method.zName of retrieval methodr   )rD   bm25graphrC   method_nameNz4Fact type this retrieval was for (world, experience)r
   rl   zRetrieved results with ranksresultszTime taken for this retrievalrf   zMethod-specific metadatarX   metadata)r   r   r   r   r   rs   r   r   rl   r"   rt   r#   rj   rf   r$   rh   ru   r   r   r   r   rp   rp      s         11DIEVpDqDqDqK@Aqqq!E$<rsssIsTzsss%*U7U%V%V%VGT/"VVV#e0OPPPePPP$uTGabbbHd38nbbbbbr   rp   c                       e Zd ZU dZ ed          Zeed<    ed          Zeed<    ed          Z	e
ed<    ed	          Zeeef         ed
<    ed          Zeed<   dS )RRFMergeResultzA result after RRF merging.r(   r   r)   r*   r+   zReciprocal Rank Fusion score	rrf_scorez:Rank in each source that contributed (method_name -> rank)source_rankszRank after RRF merge (1-based)final_rrf_rankN)r   r   r   r   r   r)   r"   r   r+   rx   r$   ry   rh   r%   rz   r   r   r   rw   rw      s         %%5%5666GS666"<===D#===u)GHHHIuHHH#(55q#r#r#rL$sCx.rrr%,LMMMNCMMMMMr   rw   c                      e Zd ZU dZ ed          Zeed<    ed          Zeed<    ed          Z	e
ed<    ed	          Zeed
<    ed          Zeed<    ed          Zeed<    eed          Zeee
f         ed<   dS )RerankedResultzA result after reranking.r(   r   r)   r*   r+   zFinal reranking scorererank_scorezRank after reranking (1-based)rerank_rankz"Original RRF rank before rerankingrrf_rankz$Change in rank (positive = moved up)rank_changezScore breakdownrX   score_componentsN)r   r   r   r   r   r)   r"   r   r+   r}   r$   r~   r%   r   r   rh   r   r   r   r   r|   r|      s         ##5%5666GS666"<===D#===%,CDDDL%DDDu)IJJJKJJJE&JKKKHcKKKu)OPPPKPPP).tQb)c)c)cd3:&cccccr   r|   c                      e Zd ZU dZ ed          Zeed<    ed          Zeed<    ed          Z	eed<    ed	          Z
eed
<    ed          Zeed<    ed          Zeed<    ed          Zeed<    edd          Zeed<    edd          Zeed<    edd          Zeed<    eed          Zee         ed<   dS )SearchSummaryz$Summary statistics about the search.zTotal nodes visitedr   total_nodes_visitedzTotal nodes prunedtotal_nodes_prunedzNumber of entry pointsentry_points_foundzHow much budget was usedbudget_usedzHow much budget remainedbudget_remainingzTotal search durationtotal_duration_secondszNumber of results returnedresults_returnedr   zTemporal links followedr
   temporal_links_followedzSemantic links followedsemantic_links_followedzEntity links followedentity_links_followedzMetrics for each phaserX   phase_metricsN)r   r   r   r   r   r   r%   r   r   r   r   r   r   r$   r   r   r   r   r#   r   rd   r   r   r   r   r      s}        ..$u1FGGGGGG#e0DEEEEEE#e0HIIIIIIu)CDDDKDDD!E.HIIIcIII$)E6M$N$N$NENNN!E.JKKKcKKK $)5@Y#Z#Z#ZSZZZ#(5@Y#Z#Z#ZSZZZ!&q>U!V!V!V3VVV /4eDVn.o.o.oM4*+ooooor   r   c                   N   e Zd ZU dZ ed          Zeed<    eed          Z	ee
         ed<    eed          Zee         ed	<    eed
          Zee         ed<    eed          Zee         ed<    eed          Zee         ed<    eed          Zee         ed<    ed          Zeed<    ed          Zeeeef                  ed<   ded iiZdefdZdefdZdededz  fdZdedee         fdZ de!d          dee         fd!Z"dee         fd"Z#dS )#SearchTracez%Complete trace of a search operation.zQuery informationr   queryz"Results from each retrieval methodrX   retrieval_resultszResults after RRF merging
rrf_mergedzResults after rerankingrerankedz)Entry points selected for search (legacy)entry_pointsz7All nodes visited during search (legacy, for graph viz)visitszNodes that were pruned (legacy)prunedzSummary statisticssummaryz%Final ranked results returned to userfinal_resultsjson_encodersc                 *    |                                  S )N)	isoformat)vs    r   <lambda>zSearchTrace.<lambda>   s    !++-- r   returnc                       | j         dddi|S )zExport trace as JSON string.indent   r   )model_dump_json)selfkwargss     r   to_jsonzSearchTrace.to_json   s     #t#7717777r   c                 *    |                                  S )zExport trace as dictionary.)
model_dumpr   s    r   to_dictzSearchTrace.to_dict   s       r   r)   Nc                 8    | j         D ]}|j        |k    r|c S dS )zFind a visit by node ID.N)r   r)   )r   r)   visits      r   get_visit_by_node_idz SearchTrace.get_visit_by_node_id   s3    [ 	 	E}'' (tr   c                     g }|                      |          }|r;|                    d|           |j        r|                      |j                  }nn|;|S )z1Get the path from entry point to a specific node.r   )r   insertrV   )r   r)   pathcurrent_visits       r   get_search_path_to_nodez#SearchTrace.get_search_path_to_node   sm    11':: 	KK=)))+  $ 9 9-:V W W  	 r   rF   rB   c                 *    fd| j         D             S )z/Get all nodes reached via a specific link type.c                 *    g | ]}|j         k    |S r   )rF   ).0r   rF   s     r   
<listcomp>z6SearchTrace.get_nodes_by_link_type.<locals>.<listcomp>   s%    CCCa!+*B*B*B*B*Br   r   )r   rF   s    `r   get_nodes_by_link_typez"SearchTrace.get_nodes_by_link_type   s    CCCC4;CCCCr   c                 $    d | j         D             S )zGet all entry point visits.c                      g | ]}|j         	|S r   )rU   )r   r   s     r   r   z5SearchTrace.get_entry_point_nodes.<locals>.<listcomp>   s     ;;;a!*:;;;;r   r   r   s    r   get_entry_point_nodesz!SearchTrace.get_entry_point_nodes   s    ;;4;;;;;r   )$r   r   r   r   r   r   r   r   r#   r   rp   r   rw   r   r|   r   r'   r   rO   r   r]   r   r   r   rh   r"   r   r   model_configr   r   r   r   r   r   r   r   r   r   r   r      s        //u)<===E9=== 7<e*N7 7 7t23    (-uTOj'k'k'kJ^$kkk%*U4Mf%g%g%gHd>"ggg &+U*U& & &L$z"    $e*c  FDO    %*E$Lm$n$n$nFD!nnn"U/CDDDG]DDD +0%<c*d*d*dM4S#X'ddd#h0G0G%HIL83 8 8 8 8! ! ! ! !C I4D    s tI    D8X0Y D^bcl^m D D D D<tI < < < < < <r   r   N)r   r   typingr   r   pydanticr   r   r	   r   r'   r4   r@   rO   r]   rd   rj   rp   rw   r|   r   r   r   r   r   <module>r      s                  % % % % % % % %T T T T T T T T    	   G G G G G G G GJ J J J Jy J J J     y   &v v v v v	 v v v6] ] ] ] ]i ] ] ]k k k k k k k k
n 
n 
n 
n 
ni 
n 
n 
nc c c c cY c c cN N N N NY N N N	d 	d 	d 	d 	dY 	d 	d 	dp p p p pI p p p(?< ?< ?< ?< ?<) ?< ?< ?< ?< ?<r   