
    Ojc                     t    d Z ddlZddlmZmZ ddlmZ ddlmZ  ej                  e
      Z G d dee      Zy)uM   요소 관계 추출 StepRunner — entity_merge 이후 변형 관계 분석.    N)AnyDict)
StepRunner)_EntityStepMixinc                   J    e Zd ZdZdeeef   fdZddeeef   fdZdefdZ	y)EntityRelationStepu   Step 13.6: 요소 변형 관계 추출.

    entity_merge 결과에서 같은 대상의 변형 쌍을 식별하고
    시각적 유사성 여부를 판단하여 RelationFact에 기록.
    returnc                 `   ddl m} ddlm} | j	                  d      }|xs i j                  d      xs i }|s |ddd	      |j                  t        |j                  d
      xs g             }|j                  |d         }t        |      t        |      d|d|d   |j                  ddS )u-  C(c) 판 — `part_of` 를 **호출 0** 으로 투영한다.

        ★★producer 가 한 판독에서 `part_of` 를 이미 냈다. 그것을 관계 행으로
        옮기기만 한다 — 모델에게 다시 안 묻는다. `project_part_of` 는 sync 와
        **같은 짝 검사 함수**를 쓰므로 여기서 규칙이 갈리지 않는다.

        ★앞 판은 이 스텝에 C(c) 갈래가 없어서, `location_part` 의
        `part_of` RelationFact 가 **활성 경로에서 아예 안 생겼다**
        (Codex 재현 2026-09-01).
        r   )AppError)grounding_relation_projectiongrounding_chunkdatazstep.no_inputuc   grounding_chunk 산출 없음 — C(c) 판에서 관계는 그 producer 가 낸 짝이 정본이다i  )codemessagestatus_codegrounding_part_offor_db
not_for_db)	relationsprojected_frompart_of_not_for_dbprojection_contractcompleted_countapplicable_countfailed_countr   )app.core.errorsr   app.modules.pipeliner   _load_prev_checkpointgetselect_db_part_oflistproject_part_oflenPROJECTION_CONTRACT_VERSION)selfr   rpcpr   splitrowss          Y/Users/manta/Documents/Projects/TheRoad-I1/backend/app/core/steps/entity_relation_step.py_chunk_projectionz$EntityRelationStep._chunk_projection   s     	-L''(9:b~~f%+$D	! ! $$T$((3F*G*M2%NO!!%/2"4yc$i"&'8+0+>,.,J,J	L
 	
    c           	      Z   ddl m}m}  | |t        | dd                   r| j	                         S | j                  d      }|rQ|j                  d      r@|d   j                  dg       |d   j                  dg       |d   j                  dg       d	}n| j                  d
      }| j                  d      }| j                  d      }|xs i j                  di       j                  dg       |xs i j                  di       j                  dg       |xs i j                  di       j                  dg       d	}t        d |j                         D              }	|	dk(  rdddg dddddS | j                         }
ddl
m}  |||
| j                  | j                               }ddd|dS )Nr   )resolve_grounding_modeuses_chunk_producerproject_configentity_merger   
characters	locationsprops)r3   r4   r5   entity_extract_characterentity_extract_locationentity_extract_propc              3   2   K   | ]  }t        |        y w)N)r$   ).0vs     r+   	<genexpr>z.EntityRelationStep._execute.<locals>.<genexpr>U   s     ?->SV->s   )r   candidates_checkedrelations_foundvisual_similar_countr   )extract_entity_relations)entitiesbeat_shot_contextr1   opik_metadata   )app.core.grounding_moder/   r0   getattrr,   r   r    sumvalues_build_beat_shot_context$app.modules.pipeline.entity_relationr@   r1   build_opik_metadata)r&   moder/   r0   merge_cprA   char_cploc_cpprop_cptotal_entitiesrB   r@   results                r+   _executezEntityRelationStep._execute:   s   	B 5.5 7 8))++ --n=V,&v.22<D%f-11+rB!&)--gr:H 001KLG//0IJF001FGG&}"11&"=AA,PRS$l//;??RP!-R,,VR8<<WbIH ?X__->??Q#$$% !&(VWqrs	  !99;Q)/..224	
  ! !	
 	
r-   c                 2   g }| j                  d      }| j                  d      }i }|rF|j                  di       j                  d      r%|d   d   D ]  }|j                  dg       ||d   <    i }|rF|j                  di       j                  d      r%|d   d   D ]  }|j                  dg       ||d   <    t        t        t	        |j                               t	        |j                               z               }|D ]   }|j                  d| d	       |j                  |g       }	|	D ]L  }
|j                  d
|
j                  dd       d|
j                  dd       d|
j                  dd              N |j                  |g       }|D ]]  }dj                  |j                  dg             }|j                  d|j                  dd       d| d|j                  dd              _ |j                  d        |rdj                  |      S dS )uG   beat_extract + shot_extract 결과를 컨텍스트 문자열로 구성.beat_extractshot_validatorr   scenesbeatsscene_indexshotsu   [씬 ]z  Beat 
beat_index?z: [change_type z] descriptionz, r3   z  Shot 
shot_index
u   (beat/shot 데이터 없음))r   r    sortedsetr"   keysappendjoin)r&   linesbeat_cpshot_cpbeats_by_scenescshots_by_sceneall_indicessirX   brZ   shcharss                 r+   rI   z+EntityRelationStep._build_beat_shot_contextq   s   ,,^<,,-=>w{{62.228<foh/46FF7B4Gr-01 0 w{{62.228<foh/46FF7B4Gr-01 0 Sn&9&9&;!<tNDWDWDY?Z!Z[\BLL5A'"&&r2.Ewquu\3'?&@AEE-Y[D\C]]_`a`e`efsuw`x_yz{ "&&r2.E		"&&r":;wrvvlC'@&AUG2bffUbdfNgMhij  LL  $)tyyL.LLr-   N)resume)
__name__
__module____qualname____doc__r   strr   r,   rS   rI    r-   r+   r   r      s?    &
4S> &
P5
c3h 5
nM# Mr-   r   )rw   loggingtypingr   r   app.core.step_runnerr   app.core.steps.entity_stepsr   	getLoggerrt   loggerr   ry   r-   r+   <module>r      s9    S   + 8			8	$DM): DMr-   