
    tj3                         d Z ddlZddlZddl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 ddlmZ  ej"                  e      Z G d d	      Z G d
 dee      Z G d dee      Z G d dee      ZeeedZy)uR   감독 Phase StepRunner -- scene_director, scene_cinematography, scene_dependency.    N)Path)AnyDictListOptional)build_name_indexlookup_name)
StepRunner)call_structuredc                   P    e Zd ZdZd
dedefdZdedee   fdZ	defdZ
defd	Zy)_DirectorStepMixinuE   감독 단계 공통 -- fulltext 로드, 이전 단계 결과 로드.N
extra_tagsreturnc                 @    t        | d      r| j                  |      S i S )Nbuild_opik_metadata)hasattrr   )selfr   s     S/Users/manta/Documents/Projects/TheRoad-I1/backend/app/core/steps/director_steps.py
_opik_metaz_DirectorStepMixin._opik_meta   s#    4./++J77	    step_idc                     ddl m} t        |j                        | j                  z  dz  dz  | j
                  z  |z  dz  }|j                         r%t        j                  |j                  d            S y )Nr   settingscheckpointsepisodeszmanifest.jsonzutf-8)encoding)
app.core.configr   r   projects_dir
project_id
episode_idexistsjsonloads	read_text)r   r   r   cps       r   _load_prev_checkpointz(_DirectorStepMixin._load_prev_checkpoint   s    , &&'oo  oo	
   	 99;::bllGl<==r   c                 L   ddl m} ddlm} | j                  j                  |      j                   ||j                              j                  |j                  | j                  k(        j                         }|r|j                  sddlm}  |ddd      |j                  S )	Nr   )Episode)undeferAppErrorzstep.no_fulltextu'   시나리오 텍스트가 없습니다.  codemessagestatus_code)app.models.projectr)   sqlalchemy.ormr*   dbqueryoptionsfulltextfilteridr!   firstapp.core.errorsr,   )r   r)   r*   epr,   s        r   _load_fulltextz!_DirectorStepMixin._load_fulltext'   s    .* GGMM'"WWW--./VGJJ$//12UW	 	 0'A 
 {{r   c                     | j                  d      }|r)|j                  di       j                  d      r|d   d   S | j                         S )u6   text_cleanup 결과 사용, 없으면 원본 fulltext.text_cleanupdatacleaned_text)r'   getr=   )r   r&   s     r   _load_cleaned_textz%_DirectorStepMixin._load_cleaned_text;   sK    ''7"&&$((8f:n--""$$r   )N)__name__
__module____qualname____doc__listr   r   strr   r'   r=   rC    r   r   r   r      sG    OT T 
S Xd^   (%C %r   r   c                   (    e Zd ZdZddeeef   fdZy)SceneDirectorStepu$   Step 12: 씬 감독 (V/A/H 3분류).r   c                 	   | j                  d      }| j                  d      }|xs i j                  di       j                  d      xs) |xs i j                  di       j                  d      xs g }| j                  d      }|r|j                  di       ni }	 ddlm}  || j                  | j
                  | j                        }|rt        |j                               }	t        |	d d	 
      }
dg }}dD ]y  }|j                  |g       D ]b  }|j                  d      rt        |
|j                  dd            xs d}|r||d<   |dz  }B|j                  |j                  dd             d { t        j                  d|       |r9t        j                  dt        |      |d d        nt        j                  d       | j                  d      }d}|r|j                  d      r|d   }|j                  dg       }|rddj#                  d |D              z   }nwg }|j                  dg       D ]M  }|j                  d      dv s|j                  d|j                  dd       d|j                  d d              O |rdj#                  |      }| j                  d!      }| j                  d"      }|r|r|j                  di       j                  d#      ri }|j                  di       j                  d#g       D ]#  }t%        |j                  d$g             ||d%   <   % g }|d   d#   D ]  }|d%   }|j                  |t%                     }|j                  d&g       D ]Q  }|r|d'   |v sd(j#                  |j                  d)g             }|j                  d*| d+|d'    d,|d-    d.| d/	       S  |r|d0dj#                  |      z   z  }dd1lm}   | | j
                  | j                  | j                        }!||!j+                  d2d3      z  }||!j+                  d4d5      z  }dd6lm}"  |"|||| j0                  | j3                         7      }#|#j                  d#g       }$t        |$      t        |      t5        dt        |      t        |$      z
        |#d8S # t         $ r!}t        j                  d|       Y d }~d }~ww xY w)9N
scene_savescene_segmentationr@   segments
entity_t2ir   )build_short_id_infoc                 ,    | d   j                  dd      S )N   name )rB   its    r   <lambda>z,SceneDirectorStep._execute.<locals>.<lambda>]   s    beii&;r   c                     | d   S )Nr   rJ   rW   s    r   rY   z,SceneDirectorStep._execute.<locals>.<lambda>^   s    1r   )key_fnvalue_fn)
characters	locationspropsshort_idrU   rV   rT   ?zInjected %d short_ids from DBu   short_id 미매칭 %d개: %s   uA   DB에 short_id 없음 — scene_director가 이름으로 fallbackz)short_id injection failed (non-fatal): %svisual_world_rulesdirector_notesuU   시각적 존재 판단 참고사항 (단, 카메라에 보이면 무조건 포함):

c              3   &   K   | ]	  }d |   yw)- NrJ   ).0ns     r   	<genexpr>z-SceneDirectorStep._execute.<locals>.<genexpr>y   s>       D]  W\  RS  GI  JK  IL  EM  W\s   rules	rule_type)
possession
projectionghost[z] visual_guidelineshot_selectionshot_validatorscenesselected_shot_indicesscene_indexshots
shot_indexz, r]   Sz Shot: description []u   

[Shot 분석 참고]
)get_planning_context	story_arcu   ## 기획서: 전체 줄거리	tone_moodu   ## 기획서: 톤/분위기)direct_scenes)entitiesvisual_rulesproject_configopik_metadatacompleted_countapplicable_countfailed_countr@   )r'   rB   app.modules.short_idrR   r4   r    r!   rH   itemsr   r	   appendloggerinfowarninglen	Exceptionjoinsetapp.core.planning_doc_contextr~   inject_if_available&app.modules.pipeline.scene_director_v2r   r   r   max)%r   modesave_cpseg_cprP   t2i_cpr   rR   sid_info
_sid_itemsname_to_shortinjectedmissingetypeesidexcrules_cpr   
rules_datanotesrules_linesrsel_cpshot_cpselected_mapsshot_context_linessisel_indicesshcharsr~   pctxr   resultrt   s%                                        r   _executezSceneDirectorStep._executeF   s   ,,\:++,@A ]+//
; "!!&"-11*= 	 ++L9-36::fb)	M@*477DOOT__UH!(.."23
 0;-!
 %&r'AE%\\%4 uuZ0"-mQUU62=N"O"USUC"03* (A 'quuVS/A B 5 B ;XFNN#A3w<QXY[Z[Q\]bc
 --.BCV,!&)JNN#3R8Ewz~  {D  {D  D]  W\  D]  {]   ] !#4Auu[)-RR#**Qquu[/D.ERN`acHdGe+fg 5 #'99[#9L ++,<=,,-=>g'++fb"9"="=h"GLZZ+//"=14QUU;RTV5W1XQ}-. > "$V_X.}%*..r359%%,B&"\*:k*I $		"&&r*B C*11t5L)9(:"R=N<OrRWQXXYZ - / " <tyyI[?\ \\ 	G#DOOT__dggN00>^__00>[\\H%..224
 Hb)  #6{ #H3x=3v;#>?	
 	
C  	MNNFLL	Ms    BR& $B#R& &	S/SSNresumerD   rE   rF   rG   r   rI   r   r   rJ   r   r   rL   rL   C   s    .o
c3h o
r   rL   c                   (    e Zd ZdZddeeef   fdZy)SceneCinematographyStepuC   촬영 감독 -- 전체 씬 일괄로 촬영 기법 N가지 선택.r   c           
         | j                  d      }|s| j                  d      }|r|j                  d      sddlm}  |ddd	      |d   d
   }ddlm}m} ddlm} ddl	m
} |j                  }	 |dd| j                  |	      }
 |dd| j                        } |dd| j                        }| j                  j                   |d            j                         }dj                  d |D              }g }|D ]4  }|j                  dd      }|j!                  d|d    d|d    d|        6 dj                  |      }|j#                  |||	      }t$        j'                  dt)        |      t)        |      |	       t+        d|
||| j,                  d| j/                                }|j                  d!g       }|D ]j  }|j                  d"g       }t)        |      |	kD  r	|d |	 |d"<   ,t)        |      |	k  s;t$        j1                  d#|j                  d      t)        |      |	       l t)        |      t)        |      t)        |      t)        |      z
  ||	d$d%S )&NrN   rO   r@   r   r+   step.no_input   세그먼트 결과 없음r-   r.   rP   )load_promptload_schemar   )textscene_cinematographysystem)r4   
shot_countanalyze)r4   analyze_schemaz\SELECT name, category, description FROM shot_type WHERE is_active = true ORDER BY sort_orderre   c              3   D   K   | ]  }d |d    d|d    d|d      yw)rg   r   r|   rT   z]:    NrJ   )rh   r   s     r   rj   z3SceneCinematographyStep._execute.<locals>.<genexpr>   s3      %
2;Qb1b1c!A$()s    r   rV   u   씬 rv   rz   headingz

)shot_types_blockscenes_blockr   z=Scene cinematography: %d scenes, %d shot types, %d variations)stepsystem_promptuser_promptresponse_schemar   schema_namer   rt   rw   z(Scene %d: %d shots returned, expected %d)rt   r   r   )r'   rB   r;   r,   app.modules.prompt_loaderr   r   r   r   
sqlalchemyr   scene_variation_countr4   executefetchallr   r   formatr   r   r   r   r   r   r   )r   r   seg_prevr,   rP   r   r   r   sql_textr   r   analyze_templateschema	shot_rowsr   scenes_block_itemsseg
scene_textr   r   r   rt   scrw   s                           r   r   z SceneCinematographyStep._execute   s~   --l;112FGHx||F30$4 
 F#J/F,/33
#"H!

 '"I$''
 35E$''R GGOO=

 (* 	  99 %
2;%
 

  C,J%%s=)*"S^,<BzlK 
 {{#56&---%! . 
 	KM3y>:	

 !''#"...//+
 Hb) BFF7B'E5zJ&#KZ07Uj(I266R_K`befkblnxy   #6{ #HMCK7%Z@	
 	
r   Nr   r   rJ   r   r   r   r      s    MV
c3h V
r   r   c                   (    e Zd ZdZddeeef   fdZy)SceneDependencyStepu=   씬 연관 분석 v2 -- 배경 중심 + 인물 중심 분리.r   c                    | j                  d      }|s| j                  d      }|r|j                  d      sddlm}  |ddd	      |d   d
   }| j                  d      }|r|j                  di       ni }| j                  d      }|s| j                  d      }|r|j                  di       ni }ddlm}	  |	|||| j                  | j                               }
|
j                  dg       }t        |      t        |      dd|idS )NrN   rO   r@   r   r+   r   r   r-   r.   rP   scene_directorrQ   entity_detail_batch)extract_dependencies)rP   director_resultr   r   r   dependenciesr   )	r'   rB   r;   r,   (app.modules.pipeline.scene_dependency_v2r   r   r   r   )r   r   r   r,   rP   director_prevr   entity_prevr   r   r   depss               r   r   zSceneDependencyStep._execute  s!   --l;112FGHx||F30$4 
 F#J/ 223CD;H-++FB7b 00>445JKK2=;??62.2Q%+..//+
 zz."-  #4y #H#T*	
 	
r   Nr   r   rJ   r   r   r   r     s    G)
c3h )
r   r   )r   r   scene_dependency)rG   r#   loggingpathlibr   typingr   r   r   r   app.core.name_matcherr   r	   app.core.step_runnerr
   app.modules.llm.llm_clientr   	getLoggerrD   r   r   rL   r   r   DIRECTOR_STEP_CLASSESrJ   r   r   <module>r      s    X    , , ? + 6			8	$1% 1%hr
*J r
pY
0* Y
~,
,j ,
` (3+ r   