+
    ̒ih                      a  0 t $ ^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	t	^ RI
HtHt ^ RIHtHtHtHtHtHtHt ^ RIt^ RIt^ RIt^ RIHt ]P9                  / RRbRR	bR
RbRRbRRbRRbRRbRRbRRbRRbRRbRR	bRRbRRbRRbRRbR RbR!RR"RR#R/C4      t]P9                  R$R%R&R%R'R(R)R*R+R*R,R-R.R/R0R/R1R/R2R3R4R%R5R6R7R3/4      t]P>                  ! R84      t R9t!R: R; lt"R< R= lt#R> R? lt$R@ RA lt%RB RC lt&RD RE lt'RF RG lt(RH RI lt)RJ RK lt*RL RM lt+RN RO lt,RP RQ lt-]]]]]3,          .]].]],          3,          3,          t/RR RS lt0RT RU lt1RV^RWRRXRY/RZ R[ llt2R\ R] lt3R^ R_ lt4R` Ra lt5Rb Rc lt6Rd Re lt7Rf Rg lt8Rh Ri lt9Rj]5Rk]6Rl]7Rm],Rn]8Ro]8Rp]9/t:Rq];Rr&   Rs Rt lt<Ru Rv lt=Rw Rx lt>Ry Rz lt?R{ R| lt@R} R~ ltAR R ltBRR R lltCRRR^ R^ /R R lltDRRRRRR/R R lltER R ltF ! R R4      tG ! R R]G4      tH ! R R]G4      tIRsJR];R&   ]	P                  ! 4       tLR R ltMR R ltN] ! R R4      4       tO] ! R R4      4       tPR R ltQ/ tRR];R&   ]	P                  ! 4       tSR R ltT ! R R4      tUR R ltVR R ltWR R ltXRR R lltYR R ltZRRRRRRRRRRRRRRRRR^RRRR/R R llt[R# )    )annotationsN)	dataclassfield)DictAnyListOptionalTupleIterableCallable)YOLOu   ۰0u   ۱1u   ۲2u   ۳3u   ۴4u   ۵5u   ۶6u   ۷7u   ۸8u   ۹9u   ٠u   ١u   ٢u   ٣u   ٤u   ٥u   ٦u   ٧u   ٨u   ٩u   يu   یu   ىu   كu   کu   ةu   هu   ۀu   ؤu   وu   إu   اu   أu   ٱu   ء u   ئu   ﻻu   لاu   ـz/[\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06ED]u   ‌c                    V ^8  d   QhRRRR/#    sstrreturn )formats   ")/var/www/html/kyc_policy_engine_llm_v2.py__annotate__r"   <   s     2 2s 2s 2    c                b    \         P                  ! R RT ;'       g    RP                  4       4      # )z\s+ r   )resubstripr   s   &r!   collapse_spacesr*   <   s"    66&#R011r#   c                    V ^8  d   QhRRRR/# r   r   )r    s   "r!   r"   r"   @   s     4 4C 4C 4r#   c                @    T ;'       g    R P                  \        4      # )r   )	translate_FA_AR_TO_EN_DIGITSr)   s   &r!   to_en_digitsr/   @   s    GG233r#   c                    V ^8  d   QhRRRR/# r   r   )r    s   "r!   r"   r"   D   s        r#   c                    T ;'       g    R p \        V 4      p V P                  \        4      p V P                  \        R4      p \
        P                  R V 4      p \        V 4      # )r   r%   )r/   r-   _AR_FA_LETTERSreplace_ZWNJ_DIACRITICS_REr'   r*   r)   s   &r!   normalize_fa_textr6   D   sQ    	
bAQA	N#A			%A2q!A1r#   c                    V ^8  d   QhRRRR/# r   r   )r    s   "r!   r"   r"   M   s     & &c &c &r#   c                    \        V 4      p \        P                  ! R RV \        P                  R7      p \	        V 4      P                  4       # )z0[^\w\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\s\-]r   flags)r6   r&   r'   UNICODEr*   lowerr)   s   &r!   normalize_namer=   M   s<    !A
BBQSQ[Q[\A1##%%r#   c                    V ^8  d   QhRRRR/# r   r   )r    s   "r!   r"   r"   S   s     $ $S $S $r#   c                H    \        V 4      p \        P                  ! R RV 4      # )z[^0-9]r   )r/   r&   r'   r)   s   &r!   normalize_digits_onlyr@   S   s    QA66)R##r#   c                    V ^8  d   QhRRRR/# r   r   )r    s   "r!   r"   r"   X   s     2 2S 2S 2r#   c                d    \        V 4      p \        P                  ! R RV 4      P                  4       # )z[^0-9A-Za-z]r   )r/   r&   r'   upperr)   s   &r!   normalize_id_alphanumrD   X   s'    QA66/2q)//11r#   c               $    V ^8  d   QhRRRRRR/# r   ar   br   floatr   )r    s   "r!   r"   r"   a   s!     . . . . .r#   c                0   T ;'       g    R p T;'       g    R pW8X  d   R# V '       d	   V'       g   R# \        \        \        V4      ^,           4      4      p\        V ^R7       F{  w  r4V.p\        V^R7       F`  w  rgWG8X  d   ^ M^pVP	                  \        W&,          ^,           WV^,
          ,          ^,           W&^,
          ,          V,           4      4       Kb  	  TpK}  	  VR,          p	RV	\        \        V 4      \        V4      4      ,          ,
          # )r         ?        )start)listrangelen	enumerateappendminmax)
rG   rH   previcacurjcbcostdists
   &&        r!   levenshtein_ratior^   a   s    	RA	RAvAc!fqj!"D1A&cq*EA1aDJJs47Q;E
QUd8JKL +  ' 8D$SVSV,,--r#   c               $    V ^8  d   QhRRRRRR/# rF   r   )r    s   "r!   r"   r"   u   s!     
3 
3C 
3C 
3E 
3r#   c                ^   \        V 4      p \        V4      pV '       d	   V'       g   R # \        V P                  4       4      p\        VP                  4       4      p\        W#,          4      p\        W#,          4      pV'       d	   WE,          MR pRV,          R\	        W4      ,          ,           # )rL   333333?g?)r=   setsplitrQ   r^   )rG   rH   sasbinterunionrZ   s   &&     r!   token_set_similarityrh   u   sw    qAqAA	QWWYB	QWWYBLELECA7S,Q2222r#   c                    V ^8  d   QhRRRR/# )r   r   r   r   zOptional[Tuple[int, int, int]]r   )r    s   "r!   r"   r"      s        > r#   c           	        \        T ;'       g    R4      p V P                  RR4      P                  RR4      p \        P                  ! RV 4      p\	        V4      ^8  d   R# VR,           Uu. uF  p\        V4      NK  	  ppV^ ,          V^,          V^,          3V^ ,          V^,          V^,          3V^,          V^ ,          V^,          3V^,          V^,          V^ ,          3V^,          V^ ,          V^,          3V^,          V^,          V^ ,          3.pV FI  w  rVpRTu;8:  d
   R	8:  g   K  M K  ^Tu;8:  d
   ^8:  g   K,  M K0  ^Tu;8:  d
   ^8:  g   KA  M KE  WVV3u # 	  R# u upi )
zr
Accepts common formats and returns (YYYY, M, D) if parseable.
This is only for validation/matching, not for OCR.
r   -/.z\d{1,4}N:N   N  i  )r/   r3   r&   findallrQ   int)r   numsxvalspermsymds   &       r!   parse_date_loosery      sB   
 	QWW"A			#s##C-A::j!$D
4y1} H%HqCFHD%	a$q'47#	a$q'47#	a$q'47#	a$q'47#	a$q'47#	a$q'47#E a1a2!q,B,,!9   &s   ,E+c                    V ^8  d   QhRRRR/# r   coder   r   boolr   )r    s   "r!   r"   r"      s      c d r#   c                B  a \        V 4      p \        V 4      ^
8w  d   R# \        \        V 4      4      ^8X  d   R# V  Uu. uF  p\        V4      NK  	  upo\	        V3R l\        ^	4       4       4      pV^,          pS^	,          pV^8  d   WC8H  # V^V,
          8H  # u upi )
   Fc              3  R   <"   T F  pSV,          ^
V,
          ,          x  K  	  R# 5i)r   Nr   ).0rW   digitss   & r!   	<genexpr>.iran_national_code_is_valid.<locals>.<genexpr>   s!     3(QF1Ia  (s   $')r@   rQ   rb   rq   sumrP   )r|   cr   rcheckr   s   &    @r!   iran_national_code_is_validr      s     &D
4yB
3t9~"#dc!fd#F3%(33A	BA1IE1uzR!V $s   Bc               $    V ^8  d   QhRRRRRR/# r   
value_normr   constraintsDict[str, Any]r   Tuple[bool, Optional[str]]r   )r    s   "r!   r"   r"      s"     - - -. -E_ -r#   c                   \        V 4      p\        V4      ^8w  d   \        R4      # VP                  RR4      '       d   VR,          R8X  d   \        R4      # VP                  RR4      '       d   VR,          R	8X  d   \        R
4      # VR,          p \	        VR,          4      p\	        VR,          4      p\	        VR,          4      p^)Tu;8:  d   ^G8:  d   M M
T^(,
          pM ^Tu;8:  d   ^8:  d   M MTpM\        R4      # ^Tu;8:  d   ^8:  g   M \        R4      # ^^^^^^^^^^^^^^^^^	^^
^^^^^/p^Tu;8:  d   Y,          8:  g   M \        R4      # \        4       #   \
         d    \        R4      u # i ; i)z
Indonesia NIK (KTP/e-KTP) validation:
- Must be 16 digits
- DOB segment: positions 7-12 (DDMMYY) where DD+40 indicates female
- No checksum (structural validation only)

nik_lengthreject_region_000000F:N   N000000nik_region_all_zeroreject_serial_0000:      N0000nik_serial_all_zero:r   r   N:r   r   N:r      N:r   r   Nnik_dob_parsenik_day_rangenik_month_rangenik_day_invalid)r@   rQ   _v_failgetrq   	Exception_v_ok)	r   r   vdobddmm_yydd_real
month_dayss	   &&       r!   validate_id_nikr      ss    	j)A
1v||$$ -u55!B%8:K,--+U33%F8J,-- D'C(S]S]#c(m
 
R~2~r'	
bB''MrM()) RB2q"aQAr1b!RQSUWY[]_aceghJ*JN*())7N'  (''(s   6E' 'F ?F c                    V ^8  d   QhRRRR/# )r   countryr   r   r   )r    s   "r!   r"   r"      s        r#   c                h    T ;'       g    RP                  4       P                  4       pVR8X  d   R# R# )zb
Conservative OCR locale hint. Keep this deterministic; override via policy when you know better.
r   IRfaen)r(   rC   )r   r   s   & r!   default_locale_hintr      s.     
B%%'ADyr#   c                    V ^8  d   QhRRRR/# )r   r   r   r   zOptional[List[int]]r   )r    s   "r!   r"   r"      s     ! !s !2 !r#   c                   V f   R # \        V \        4      '       d)   . pV  F  p VP                  \        V4      4       K   	  V# \        V \
        4      '       d   V P                  4       pV'       g   R # VP                  R4      '       dQ   VP                  R4      '       d:    \        P                  ! V4      p\        V\        4      '       d   \        V4      #  \        P                  ! RV4      p. pV F(  pV'       g   K   VP                  \        V4      4       K*  	  V# R #   \         d      R # i ; i  \         d     Lki ; i  \         d      R # i ; i)N[]z[\s,;]+)
isinstancerO   rS   rq   r   r   r(   
startswithendswithjsonloads_parse_int_listr&   rc   )r   outrs   r   arrpartsps   &      r!   r   r      s*   y!TA

3q6" 
 
!SGGI<<Cjjmc4((*3// ) Q'A

3q6"	  
3      s5   D'$6D: E'D76D7:EEEEc                    V ^8  d   QhRRRR/# r{   r   )r    s   "r!   r"   r"     s     * * * *r#   c                   \        V 4      p \        V 4      ^8  d   R# V  Uu. uF  p\        V4      NK  	  pp^ p\        V4      ^,
          ^,          p\        VRR 4       F>  w  rVV^,          V8X  d$   V^,          pV^	8  d
   V^	,          pW7,          pK6  W6,          pK@  	  VR,          pW8,           ^
,          ^ 8H  # u upi )zStandard Luhn mod-10 checksum.FNrN   )r@   rQ   rq   rR   )	r|   r   r   checksumparityrW   rx   r   r   s	   &        r!   luhn_is_validr     s     &D
4y1}"#dc!fdF#H&kAo"F&"+&q5F?QBAvaNHMH ' 2JE#)) $s   B>modcheck_index
check_rulemod_minus_rc               0    V ^8  d   QhRRRRRRRRR	RR
R/# )r   r|   r   weightsz	List[int]r   rq   r   Optional[int]r   r   r}   r   )r    s   "r!   r"   r"   *  sF     6- 6-6- 6- 	6-
 #6- 6- 
6-r#   c               (   \        V 4      p V '       g   R# V  Uu. uF  p\        V4      NK  	  pp\        V4      pV^8  d   R# Vf
   V^,
          M
\        V4      pV^ 8  d	   Wx,           pV^ 8  g   W8  d   R# Wh,          p	\        V4       U
u. uF  qV8w  g   K  Wj,          NK  	  pp
\        V4      \        V4      8w  d   R# \	        R \        W4       4       4      pV\        V4      ,          pT;'       g    RP                  4       P                  4       pVR8X  d   V^8  d   TM\        V4      V,
          pM6VR9   d$   \        V4      V,
          \        V4      ,          pMVR8X  d   TpMR# \        V	4      \        V4      8H  # u upi u up
i )aw  
Generic weighted mod-11 validator.

Parameters are taken from constraints:
  - weights: list[int] for all digits EXCEPT the check digit.
  - mod: default 11
  - check_index: index of check digit (default last)
  - check_rule:
      * "iran"        : expected = r if r < 2 else (11 - r)
      * "mod_minus_r" : expected = (mod - r) % mod
      * "r"           : expected = r
Fc              3  6   "   T F  w  rW,          x  K  	  R # 5iNr   )r   rx   ws   &  r!   r   *mod11_weighted_is_valid.<locals>.<genexpr>S  s     87daAEE7   r   iranr   >   r   mod-11)r@   rq   rQ   rP   r   zipr(   r<   )r|   r   r   r   r   r   r   ncicheck_digitrW   data_digitsr   r   ruleexpecteds   &$$$$           r!   mod11_weighted_is_validr   *  sV   ( !&D"#dc!fdF#FA1u'!a%S-=B	AvV	Av*K&+Ah:hr'9699hK:
7|s;''8c+788A	CHA"##%++-Dv~A1CHqL	*	*HqLCH,	{s8},,= $ ;s   F
FFc                   V ^8  d   QhRR/# )r   r   r   r   )r    s   "r!   r"   r"   c  s      ) r#   c                     R# )TTNr   r   r#   r!   r   r   c  s    r#   c                    V ^8  d   QhRRRR/# )r   reasonr   r   r   r   )r    s   "r!   r"   r"   g  s      C 6 r#   c                
    R V 3# )Fr   r   s   &r!   r   r   g  s    &=r#   c               $    V ^8  d   QhRRRRRR/# r   r   )r    s   "r!   r"   r"   k  s"     1 1C 1n 1Qk 1r#   c                N    \        V 4      '       d   \        4       # \        R 4      # )iran_national_code_invalid)r   r   r   r   r   s   &&r!   validate_iran_national_coder   k  s     ":..w/00r#   c               $    V ^8  d   QhRRRRRR/# r   r   )r    s   "r!   r"   r"   q  s"     # #c # #C] #r#   c                N    \        V 4      '       d   \        4       # \        R 4      # )luhn_invalid)r   r   r   r   s   &&r!   validate_luhnr   q  s    Z  w>""r#   c               $    V ^8  d   QhRRRRRR/# r   r   )r    s   "r!   r"   r"   w  s"     $ $ $. $Mg $r#   c           	        \        VP                  R 4      ;'       g    VP                  R4      4      pV'       g   \        R4      # VP                  R^4      pVP                  R4      pVP                  RR4      p \        T T\	        V4      Ve   \	        V4      MR\        V4      R7      pV'       d   \        4       # \        R
4      #   \         d    R	p L,i ; i)r   weight_listmod11_missing_weightsr   r   r   r   N)r   r   r   r   Fmod11_invalid)r   r   r   r   rq   r   r   r   )r   r   r   r   r   r   oks   &&     r!   validate_mod11_weightedr   w  s    kooi8ZZKOOM<Z[G.//
//%
$C//-0K}=J	$C-8-D[)$:
 
w?##  s   =1C CCc               $    V ^8  d   QhRRRRRR/# r   r   )r    s   "r!   r"   r"     s"      c  C] r#   c                    \        4       # r   )r   r   s   &&r!   validate_noner     s	    7Nr#   c               $    V ^8  d   QhRRRRRR/# r   r   )r    s   "r!   r"   r"     s"     , ,s , ,Tn ,r#   c                    \        R 4      # )identity_rule_missing)r   r   s   &&r!   validate_missing_identity_ruler     s    *++r#   iran_national_codeluhnmod11_weightedid_niknoneskipmissing_identity_rulezDict[str, ValidatorFn]_VALIDATOR_REGISTRYc               (    V ^8  d   QhRRRRRRRR/# )	r   validator_nameOptional[str]r   r   r   r   r   r   r   )r    s   "r!   r"   r"     s)     3 3- 3S 3~ 3b| 3r#   c                    T ;'       g    RP                  4       P                  4       pV'       g   \        4       # \        P	                  V4      pVf   \        RV 24      # T! T;'       g    RT;'       g    / 4      # )zy
Dispatches to a deterministic validator.
Unknown validator names are treated as invalid (safer than silently skipping).
r   zunknown_validator:)r(   r<   r   r  r   r   )r  r   r   namefns   &&&  r!   run_validatorr	    sr    
   b'')//1Dw		 	 	&B	z+D6233jB 1 1r22r#   c               $    V ^8  d   QhRRRRRR/# )r   quad
np.ndarrayscalerI   r   r   )r    s   "r!   r"   r"     s!     ) )j ) ): )r#   c                    V P                  \        P                  4      p V P                  ^ RR7      pW V,
          \	        V4      ,          ,           # )r   T)axiskeepdims)astypenpfloat32meanrI   )r  r  r   s   && r!   expand_quadr    s<    ;;rzz"D		q4	(AqE%L(((r#   c                    V ^8  d   QhRRRR/# )r   ptsr  r   r   )r    s   "r!   r"   r"     s     8 8
 8z 8r#   c                   V P                  \        P                  4      p V P                  ^R7      pV \        P                  ! V4      ,          pV \        P
                  ! V4      ,          p\        P                  ! V ^R7      P                  R4      pV \        P                  ! V4      ,          pV \        P
                  ! V4      ,          p\        P                  ! W%W6.\        P                  R7      # )   )r  dtyperN   )	r  r  r  r   argminargmaxdiffreshapearray)r  r   tlbrrx   trbls   &      r!   order_points_clockwiser%    s    
**RZZ
 CQA	RYYq\	B	RYYq\	B
!$$R(A	RYYq\	B	RYYq\	B88RR$BJJ77r#   c               (    V ^8  d   QhRRRRRRRR/# )r   r  r  r   rq   hr   r   )r    s   "r!   r"   r"     s(      Z C C J r#   c                    \         P                  ! V R,          ^ V^,
          4      V R&   \         P                  ! V R,          ^ V^,
          4      V R&   V # )NNN)r)  r   )r)  r  )r  clip)r  r   r'  s   &&&r!   clip_pointsr+    sC    D	1a!e,CID	1a!e,CIJr#   c               $    V ^8  d   QhRRRRRR/# )r   img_bgrr  r  r   r   )r    s   "r!   r"   r"     s&     P Pz P P
 Pr#   c                b   V P                   R ,          w  r#VP                  \        P                  4      p\	        WV4      p\        V4      pVw  rErg\        P                  P                  Wg,
          4      p\        P                  P                  WT,
          4      p	\        \        W4      4      p
\        P                  P                  WV,
          4      p\        P                  P                  WG,
          4      p\        \        W4      4      p\        V
^4      p
\        V^4      p\        P                  ! ^ ^ .V
^,
          ^ .V
^,
          V^,
          .^ V^,
          ..\        P                  R7      p\        P                  ! W4      p\        P                  ! WW3\        P                  R7      # )Nr   Nr  r9   )shaper  r  r  r+  r%  linalgnormrq   rU   r   cv2getPerspectiveTransformwarpPerspectiveINTER_CUBIC)r-  r  HWr!  r#  r"  r$  widthAwidthBmaxWheightAheightBmaxHdstMs   &&              r!   warp_quad_to_rectrA    s3   ==DA;;rzz"Dt"D!$'DNBBYY^^BG$FYY^^BG$Fs6"#DiinnRW%GiinnRW%Gs7$%DtQ<DtQ<D
((QFTAXqMD1HdQh+?!TAXOWYWaWa
bC##D.AwD<sOOr#   c                    V ^8  d   QhRRRR/# r   r-  r  r   r   )r    s   "r!   r"   r"     s     0 0* 0 0r#   c                ^   \         P                  ! V \         P                  4      p\         P                  ! R RR7      pVP	                  V4      p\         P
                  ! VR^ 4      p\         P                  ! V^\         P                  \         P                  ^^4      pVP                  R,          w  rE\        ^\        \        R\        WE4      ,          4      4      4      p\         P                  ! W6WfV\         P                  ^R7      p\         P                  ! V\         P                  4      # )g      @)	clipLimittileGridSizer/  g
ףp=
?value)   rI  )rn   rn   )r3  cvtColorCOLOR_BGR2GRAYcreateCLAHEapplyGaussianBluradaptiveThresholdADAPTIVE_THRESH_GAUSSIAN_CTHRESH_BINARYr0  rU   rq   roundcopyMakeBorderBORDER_CONSTANTCOLOR_GRAY2BGR)r-  grayclahethr'  r   pads   &      r!   apply_numeric_ocr_filter_cv2rZ    s    <<!3!34DOOc?E;;tDD&!,D			c&&
B	
B 88B<DA
b#eD3q9,-.
/C			BSsC4G4Gs	SB<<C..//r#   c                    V ^8  d   QhRRRR/# rC  r   )r    s   "r!   r"   r"     s     4 4
 4z 4r#   c           
        \         P                  ! V \         P                  4      pRp^
p\         P                  ! WVR7      p\        P
                  ! . RO. RO. RO.4      p\         P                  ! VRV4      pVP                  w  rx^
p	\         P                  ! WiWV	\         P                  ^R7      p
\         P                  ! V
\         P                  4      # )z=
Apply Grayscale + Contrast + Sharpening for better LLM OCR.
gffffff?alphabetarG  rN   )r   rN   r   )rN      rN   )r3  rJ  rK  convertScaleAbsr  r   filter2Dr0  rS  rT  rU  )r-  rV  r^  r_  contrastkernelsharpr'  r   rY  paddeds   &          r!   apply_smart_ocr_filter_cv2rg    s    
 <<!3!34D ED""44@H XXz"!# $F LL2v.E ;;DA
CCc3;N;NVYZF << 2 233r#   c               $    V ^8  d   QhRRRRRR/# )r   imgr  max_dimrq   r   r   )r    s   "r!   r"   r"     s&     C C Cc CZ Cr#   c           	     V   V P                   R ,          w  r#\        W#4      pWA8:  d   V # V\        V4      ,          p\        ^\        \	        W5,          4      4      4      p\        ^\        \	        W%,          4      4      4      p\
        P                  ! WV3\
        P                  R7      # )r/  interpolation)r0  rU   rI   rq   rR  r3  resize
INTER_AREA)ri  rj  r'  r   rw   r  nwnhs   &&      r!   _resize_max_dimrr    s{    99R=DAA	A|
eAhE	QE!)$%	&B	QE!)$%	&B::c83>>BBr#   rj  ix  min_hmin_wc          
     ,    V ^8  d   QhRRRRRRRRRR/# )r   ri  r  rj  rq   rs  rt  r   r   )r    s   "r!   r"   r"     s1      * # S UX ak r#   c                  V P                   R ,          w  rE\        WE4      pWa8  d   V\        V4      ,          p\        P                  ! V \        ^\        \        WW,          4      4      4      \        ^\        \        WG,          4      4      4      3\        P                  R7      p V P                   R ,          w  rERpV'       d"   WB8  d   \        W\        V4      ,          4      pV'       d"   WS8  d   \        W\        V4      ,          4      pVR8  dZ   \        P                  ! V \        \        WX,          4      4      \        \        WH,          4      4      3\        P                  R7      p V # )r/  rl  rK   g)\(?)	r0  rU   rI   r3  rn  rq   rR  ro  r6  )	ri  rj  rs  rt  r'  r   rw   r   s_ups	   &$$$     r!   _resize_to_rangerx    s    99R=DA 	A	A{eAhjjs1c%*o6As5:8OP`c`n`noyy} D4q)*4q)*d{jjs5=13uQV}3EFVYVeVefJr#   kindtextvariantsmartc          
     ,    V ^8  d   QhRRRRRRRRRR/# )	r   r-  r  ry  r   r{  rj  rq   r   r   )r    s   "r!   r"   r"   1  s<     * ** * 	*
 * 	*r#   c                  T;'       g    R P                  4       pT;'       g    RP                  4       pVR9   d   \        W^RR7      p M\        W^x^ R7      p VR8X  d   T pM}VR9   dl   VR8X  de   \        P                  ! V \        P                  4      p\        P
                  ! VRRR7      p\        P                  ! V\        P                  4      pM\        V 4      p\        P                  ! RV4      w  rxV'       g   \        R	4      h\        P                  ! VP                  4       4      P                  R
4      p	RV	 2# )rz  r|  iX  )rj  rs  rt  rawthreshg?r]  .pngzcv2.imencode(.png) failedasciizdata:image/png;base64,numericdatei)r<   rx  r3  rJ  rK  ra  rU  rg  imencodeRuntimeErrorbase64	b64encodetobytesdecode)
r-  ry  r{  rj  	processedrV  rc  r   bufb64s
   &$$$      r!   _encode_image_for_llmr  1  s	    NNF!!#D!!'((*G"""73cR"73aP%		$	$H)<||GS%7%78&&t3SALL3+=+=>	.w7	ll69-GB677


3;;=
)
0
0
9C#C5))r#   c               (    V ^8  d   QhRRRRRRRR/# )	r   crop_bgrr  ry  r   rj  rq   r   	List[str]r   )r    s   "r!   r"   r"   R  s)       c C T] r#   c          	         T;'       g    R P                  4       pVR9   d-   \        V RRVR7      \        V RRVR7      \        V RRVR7      .# \        WRVR7      .# )rz  r  r  ry  r{  rj  r|  r  r  )r<   r  )r  ry  rj  ks   &$$ r!   build_llm_candidate_imagesr  R  sn    	 A!(ESZ[!(GU\]!(HV]^
 	
 	hQ r#   c                  "    ] tR tRtR R ltRtR# )FaceMatcherBaseie  c               $    V ^8  d   QhRRRRRR/# r   doc_photo_bgrr  
selfie_bgrr   r   r   )r    s   "r!   r"   FaceMatcherBase.__annotate__f  s!     $ $: $: $. $r#   c                	    \        4       hr   )NotImplementedErrorselfr  r  s   &&&r!   matchFaceMatcherBase.matchf  s    !##r#   r   N__name__
__module____qualname____firstlineno__r  __static_attributes__r   r#   r!   r  r  e  s    $ $r#   r  c                  "    ] tR tRtR R ltRtR# )FaceMatcherUnavailableij  c               $    V ^8  d   QhRRRRRR/# r  r   )r    s   "r!   r"   #FaceMatcherUnavailable.__annotate__k  s&     g g: g: g. gr#   c                	    R RRRRRRR/# )score01Ncosiner   face_module_unavailabledetailsr   r  s   &&&r!   r  FaceMatcherUnavailable.matchk  s    44;TV_aeffr#   r   Nr  r   r#   r!   r  r  j  s    g gr#   r  c                  X    ] tR tRtRR R llt]R 4       t]R R l4       tR R ltR	t	R
# )InsightFaceMatcherio  c                    V ^8  d   QhRRRR/# )r   det_sizezTuple[int, int]
prefer_gpur}   r   )r    s   "r!   r"   InsightFaceMatcher.__annotate__p  s     7 7 74 7r#   c                	    ^ RI Hp V'       d   RR.MR.pV! RVR7      V n        V P                  P                  RVR7       R# )	r   )FaceAnalysisCUDAExecutionProviderCPUExecutionProvider	buffalo_l)r  	providers)ctx_idr  NrN   )insightface.appr  appprepare)r  r  r  r  r  s   &&&  r!   __init__InsightFaceMatcher.__init__p  s>    0IS,.DEZpYq	[IFX6r#   c                	4    V '       g   R # R p\        WR7      # )Nc                \    V P                   w  rr4\        W1,
          WB,
          ,          4      # r   )bboxrI   )fx1y1x2y2s   &    r!   area.InsightFaceMatcher._largest_face.<locals>.area{  s#    VVNBB"'bg.//r#   key)rU   )facesr  s   & r!   _largest_face InsightFaceMatcher._largest_facev  s    	0 5##r#   c               $    V ^8  d   QhRRRRRR/# )r   rG   r  rH   r   rI   r   )r    s   "r!   r"   r    s!     / /: /* / /r#   c                	n   V P                  \        P                  4      p VP                  \        P                  4      p\        P                  P	                  V 4      R ,           p\        P                  P	                  V4      R ,           p\        \        P                  ! W4      W#,          ,          4      # )g&.>)r  r  r  r1  r2  rI   dot)rG   rH   nanbs   &&  r!   _cosineInsightFaceMatcher._cosine  sn    HHRZZ HHRZZ YY^^A%YY^^A%RVVA\RW-..r#   c               $    V ^8  d   QhRRRRRR/# r  r   )r    s   "r!   r"   r    s&     b b: b: b. br#   c                	   V P                   P                  V4      pV P                   P                  V4      pV P                  V4      pV P                  V4      pVf   RR RR RRRR\        V4      //# Vf   RR RR RRRR\        V4      //# V P	                  VP
                  VP
                  4      pVR	,           R
,          pR\        V4      R\        V4      RRRR /# )Nr  r  r   no_face_in_document_photor  	doc_facesno_face_in_selfieselfie_facesrK          @r   )r  r   r  rQ   r  normed_embeddingrI   )	r  r  r  r  	sel_facesfdfscosr  s	   &&&      r!   r  InsightFaceMatcher.match  s    HHLL/	HHLL,		*	*:tXtX?Z\ehsux  zC  vD  hE  F  F:tXtX?RT]`npst}p~_  A  All2..0C0CD9#5>8U3Z4QZ\`aar#   )r  N))  r  F)
r  r  r  r  r  staticmethodr  r  r  r  r   r#   r!   r  r  o  s;    7 $ $ / /b br#   r  zOptional[FaceMatcherBase]_FACE_MATCHERc                   V ^8  d   QhRR/# )r   r   r  r   )r    s   "r!   r"   r"     s     	 	/ 	r#   c                     \         ;_uu_ 4        \        e   \        uuR R R 4       #  \        RR7      s\        uuR R R 4       #   \         d    \	        4       s L'i ; i  + '       g   i     R # ; i)NF)r  )
_FACE_LOCKr  r  r   r  r   r#   r!   get_face_matcherr    sU    	$  
	5.%@M  

  	524M	5 
s-   A AA AA AA  A1	c               (    V ^8  d   QhRRRRRRRR/# )r   doc_image_pathr   selfie_image_pathdoc_photo_quadzOptional[List[List[float]]]r   r   r   )r    s   "r!   r"   r"     s2     ( (( ( 4	(
 (r#   c                p   V'       g   RRRRRRRR/# V'       g   RRRRRRRR/# \         P                  ! V 4      p\         P                  ! V4      pVf   RRRRRRRR/# Vf   RRRRRR	RR/# \        V\        P                  ! V\        P
                  R
7      4      p\        4       pVP                  WT4      # )zV
Computes face match pack once. Caller decides whether to use it depending on policy.
r  Nr  r   selfie_missingr  doc_photo_not_detectedcannot_read_doc_imagecannot_read_selfie_imager  )r3  imreadrA  r  r   r  r  r  )r  r  r  doc_imgsel_imgcropmatchers   $$$    r!   compute_face_packr    s     44;KYX\]]44;SU^`deejj(Gjj*+G44;RT]_cdd44;UW`bfggWbhh~RZZ&PQD G==''r#   c                      ] tR tRt$ R]R&   R]R&   R]R&   RtR	]R
&   RtR	]R&   RtR]R&   RtR]R&   Rt	R	]R&   ^ t
R]R&   RtR]R&   ]! ]R7      tR]R&   RtR	]R&   RtR]R&   RtR]R&   ^tR]R &   RtR!]R"&   R#tR# )$	FieldRulei  r  class_namesr   r  r}   required      ?rI   min_det_confg?min_ocr_confrz  ocr_kindoptional
match_type333333?match_thresholdrq   expected_lenNr  	validatordefault_factoryr   r   rK   weightF
must_match
match_gatemax_candidateszOptional[List[str]]input_aliasesr   )r  r  r  r  __annotations__r  r  r  r  r
  r  r  r   dictr   r  r  r  r  r  r  r   r#   r!   r   r     s    	HNL% L%Hc J !OU!L##I}#"'"=K=FEJJNC)-M&-r#   r   c                  (   ] tR tRt$ R]R&   R]R&   RtR]R&   RtR]R&   R	tR]R
&   RtR]R&   Rt	R]R&   Rt
R]R&   RtR]R&   RtR]R&   RtR]R&   RtR]R&   RtR]R&   RtR]R&   R tR]R!&   RtR]R"&   ]! ]R#7      tR$]R%&   R&tR]R'&   R(tR]R)&   R*tR# )+	DocConfigi  r   doc_idzList[FieldRule]rulesr   r   doc_typer   ocr_locale_hintNr   min_detected_fields_countrK   rI   approve_min_coverage(\?approve_min_extractionq=
ףp?approve_min_match_corerL   approve_min_match_all      ?review_min_coverage      ?reject_below_coverage皙?approve_no_input_extra_bufferFr}   require_face_matchr  face_metricface_match_thresholdr  zList[Tuple[str, str]]
swap_pairsTenable_name_swapQ?name_swap_marginr   )r  r  r  r  r  r   r  r  r  r  r  r!  r"  r$  r&  r(  r)  r*  r+  r   rO   r,  r-  r/  r  r   r#   r!   r  r    s    K GSHcOS/3}3"%%%$(E($(E(#&5&!%%#'5'+/!5/  %$ K "&%& ).d(CJ%C!d!"e"r#   r  c                    V ^8  d   QhRRRR/# )r   payloadr   r   r  r   )r    s   "r!   r"   r"     s     9 9^ 9	 9r#   c                :   . pV P                  R . 4       EF  p\        V4      pVP                  R4      ;'       g    VP                  R4      p\        V\        4      '       d   V.VR&   M\	        T;'       g    . 4      VR&   VP                  RR4       VP                  R4      pVf   / VR&   ML\        V\        4      '       d    \        P                  ! V4      VR&   M\        V\        4      '       g   / VR&   VP                  \        R'/ VB 4       EK  	  V P                  R4      ;'       g    . pV Uu. uF>  p\        V\        \        34      '       g   K!  \        V4      ^8X  g   K3  \        V4      NK@  	  pp\        R'/ R\        V P                  R4      ;'       g    V P                  R4      ;'       g    R4      bR VbR	\        V P                  R	4      ;'       g    R
4      P                  4       bR\        V P                  R4      ;'       g    R
4      bR\        V P                  R4      ;'       gG    V P                  R4      ;'       g.    \        \        V P                  R	4      ;'       g    R
4      4      4      bRV P                  RR4      bR\!        V P                  RR4      4      bR\!        V P                  RR4      4      bR\!        V P                  RV P                  RR4      4      4      bR\!        V P                  RR4      4      bR\!        V P                  RR4      4      bR\!        V P                  RR4      4      bR\!        V P                  RR4      4      bR\#        V P                  RR4      4      bR \        V P                  R R!4      4      bR"\!        V P                  R"R4      4      bRVbR#\#        V P                  R#R$4      4      bR%\!        V P                  R%R&4      4      b #   \         d
    / TR&    ELi ; iu upi )(r  r  
class_nameNr   r,  r  iddocr   r   r  r  locale_hintr  r  rK   r  r  r!  approve_min_matchr   r"  rL   r$  r#  r&  r%  r(  r'  r)  Fr*  r  r+  r-  Tr/  r.  r   )r   r  r   r   rO   popr   r   r   rS   r   tuplerQ   r  rC   r   rI   r}   )r1  r  r   rrcncstr,  rs   s   &       r!   doc_config_from_payloadr=    s   E[["%!WVVM"::bff\&:b#!#B} $RXX2B}
|T"ff]#; "B}S!!'$(JJsO=! C&& "B}Y__%) &, \*00bJ$._Jq*Qu2N(SVWXSY]^S^(%(JJ_ 7;;x(FFGKK,=FFG GKK	*00b1779	
 W[[,223 KK)* F F{{=)F F"3w{{9'='C'C#DE
 #*++.I4"P #7;;/Es#KL  %W[[1I4%PQ   %W[[1I7;;WjlpKq%rs!" $GKK0G$MN#& "'++.CT"JK'( $GKK0G$NO)* ',GKK8WY],^&_+.  ,@% HI/0 M9=>12 #7;;/Et#LM36 78 gkk*<dCD9: w{{+=tDE;   '$&=!' `s$   P:PP/PPPzDict[str, 'KYCEngine']_ENGINE_CACHEc                    V ^8  d   QhRRRR/# )r   
model_pathr   r   z'KYCEngine'r   )r    s   "r!   r"   r"   L  s     " "3 "; "r#   c                    \        V 4      p\        ;_uu_ 4        V\        9  d   \        V 4      \        V&   \        V,          uuR R R 4       #   + '       g   i     R # ; ir   )r   _ENGINE_LOCKr>  	KYCEngine)r@  r  s   & r!   
get_enginerD  L  s;    
j/C	m#!*:!6M#S! 
s   *AA 	c                      ] tR tRtR R lt]R R l4       tR R ltR R	 lt]R
R/R R ll4       t	]R R l4       t
]R R l4       tRR R lltR R ltRtR# )rC  iT  c                   V ^8  d   QhRR/# )r   yolo_model_pathr   r   )r    s   "r!   r"   KYCEngine.__annotate__U  s     	, 	, 	,r#   c                	   \        V4      V n        V P                  P                  p\        V\        4      '       d>   VP                  4        UUu/ uF  w  r4\        V4      \        V4      bK  	  uppV n        M.\        V4       UUu/ uF  w  rVV\        V4      bK  	  uppV n        \        P                  ! 4       V n        R # u uppi u uppi r   )r   modelnamesr   r  itemsrq   r   r  rR   	threadingLock_infer_lock)r  rG  rK  r  r   rW   r   s   &&     r!   r  KYCEngine.__init__U  s    /*


  eT"";@;;=I=41AA=ID6?6FG6Fda3q6	6FGD$>>+	  JGs    CC
c                    V ^8  d   QhRRRR/# )r   rs   rI   r   r   )r    s   "r!   r"   rH  a  s     , ,E ,e ,r#   c           	     	@    \        R \        R\        V 4      4      4      # )rL   rK   )rU   rT   rI   rs   s   &r!   _clamp01KYCEngine._clamp01`  s    3Cq*++r#   c               $    V ^8  d   QhRRRRRR/# )r   r   r   
user_inputDict[str, str]r   r  r   )r    s   "r!   r"   rH  d  s!     	 	) 	 	M 	r#   c                	    VP                  VP                  4      pV'       d   V# VP                  '       d1   VP                   F   pVP                  V4      pV'       g   K  Vu # 	  R # r   )r   r  r  )r  r   rW  r   akvvs   &&&   r!   _get_expectedKYCEngine._get_expectedd  sU    NN488$H((^^B'2I ) r#   c               0    V ^8  d   QhRRRRRRRRRRR	R
/# )r   
image_pathr   confrI   ioudevicemax_detrq   r   List[Dict[str, Any]]r   )r    s   "r!   r"   rH  o  s8     ; ; ;E ; ;s ;UX ;]q ;r#   c                	   V P                   ;_uu_ 4        V P                  P                  WW4VR R7      pRRR4       X'       g   . # V^ ,          p. p\        VRR4      Ee   VP                  Ee   VP                  P
                  p	VP                  P                  p
VP                  P                  p\        V	\        P                  4      '       d-   V	P                  4       P                  4       P                  4       p	\        V
\        P                  4      '       d-   V
P                  4       P                  4       P                  4       p
\        V\        P                  4      '       d-   VP                  4       P                  4       P                  4       p\        \        V	4      4       F  p\!        W,          4      pVP#                  RVRV P$                  P'                  V\)        V4      4      R\+        W,          4      RW,          P-                  \*        4      P/                  4       /4       K  	  V# \        VRR4      Ee   VP0                  Ee   VP0                  P2                  pVP0                  P                  p
VP0                  P                  p\        V\        P                  4      '       d-   VP                  4       P                  4       P                  4       p\        V
\        P                  4      '       d-   V
P                  4       P                  4       P                  4       p
\        V\        P                  4      '       d-   VP                  4       P                  4       P                  4       p\        \        V4      4       F  pW,           Uu. uF  p\+        V4      NK  	  upw  pppp\!        W,          4      pVV.VV.VV.VV..pVP#                  RVRV P$                  P'                  V\)        V4      4      R\+        W,          4      RV/4       K  	  V#   + '       g   i     EL; iu upi )	F)sourcer`  ra  rb  rc  verboseNobbclass_idr3  r`  r  boxes)rO  rJ  predictgetattrrh  xyxyxyxyclsr`  r   torchTensordetachcpunumpyrP   rQ   rq   rS   r  r   r   rI   r  tolistrj  xyxy)r  r_  r`  ra  rb  rc  predsr   detsquadsrn  cfrW   cidru  rs   r  r  r  r  r  s   &&&&&&               r!   detectKYCEngine.detecto  s   JJ&&!#g_d ' E 
 I!H%' 1eT".1553DEENNE%%))CB%..**,224#u||,,jjl&&(..0"ell++YY[__&,,.3u:&#&k $"2"2"6"6sCH"EE"%LEHOOE299;	  ' K 1gt$0QWW5H77<<D''++CB$--{{}((*002#u||,,jjl&&(..0"ell++YY[__&,,.3t9%48G!<Gq%(G!<BB#&kR2r(RHr2h? $"2"2"6"6sCH"EE"%LD	 	 & u ` "=s    P)P=)P:	r6  r   c               $    V ^8  d   QhRRRRRR/# )r   fields_planrd  r6  r   r   r   r   )r    s   "r!   r"   rH    s(     , ,-, , 
	,r#   c                <    R^RRRVRV RRRR	R.R
RRRRRRRR///pV# )ah  
Returns a single, self-contained bundle to be sent to your LLM layer.
You can convert it to OpenAI Responses API (or any other provider) on your server.

fields_plan: list of:
  {
    "key": str,
    "kind": "text|numeric|date|mrz",
    "candidates": [{"idx": int, "det_conf": float, "image_data_url": str}, ...]
  }

Expected LLM response:
  {
    "fields": {
      "<key>": {
         "candidate_idx": 0,
         "text": "...",          # what you read
         "confidence": 0.0-1.0,  # optional but recommended
         "normalized": "..."     # optional; server can re-normalize anyway
      }, ...
    }
  }
schema_versiontaskkyc_field_ocrr6  fieldsoutput_contracttyper   top_level_keysfield_objectcandidate_idxzint (required)rz  zstring|null (required)
confidencezfloat 0..1 (optional)
normalizedzstring|null (optional)r   )r~  r6  schemas   $$ r!   build_llm_ocr_prompt_bundle%KYCEngine.build_llm_ocr_prompt_bundle  sZ    < aO;k 8*#%54 "9 ":	!	 
  r#   c                    V ^8  d   QhRRRR/# r   bundler   r   rd  r   )r    s   "r!   r"   rH    s     8 8N 8G[ 8r#   c                	\   V P                  R 4      ;'       g    . pV Uu. uF  q"P                  R4      NK  	  ppRRP                  V4       2pRRRV/.pV F  pVP                  R4      pVP                  R4      pVP                  R4      ;'       g    . pRV R	V R
2p	VR8X  d
   V	R,          p	VP                  RRRV	/4       V FB  p
RV
9   g   K  V
R,          P                  R^4      w  rVP                  RRRRRRRRV//4       KD  	  K  	  VP                  RRRR/4       V# u upi )r  r  uv  You are a specialized OCR engine for Iranian ID cards (National Card/Shenasnameh).
CRITICAL INSTRUCTION FOR DIGITS:
The images contain Persian/Arabic numerals (۰, ۱, ۲, ۳, ۴, ۵, ۶, ۷, ۸, ۹).
You MUST transcribe them directly as standard English digits (0-9).
 - Visible: '۳۴۸' -> Output: '348'
 - Visible: '۱۴۰۲' -> Output: '1402'

OUTPUT RULES:
1. Return ONLY valid JSON. No markdown.
2. If a field is blurry or unreadable, set 'text': null.
3. Do not include any explanations.

JSON Response Structure:
{
  "fields": {
    "KEY": {"text": "value", "confidence": 0.99, "candidate_idx": 0}
  }
}
REQUIRED FIELDS: z, r  rz  ry  
candidatesz
Target Field: 'z	' (Type: )r  z -> EXTRACT ONLY DIGITS (0-9)image_data_url,imagerf  r  
media_typez	image/pngdataz
JSON Output:)r   joinrS   rc   )r  r  r  	keys_listintrorL  r  ry  cands
field_hintr   _b64_datas   &            r!   #anthropic_content_items_from_bundle-KYCEngine.anthropic_content_items_from_bundle  s[   H%+++126aUU5\6	2
 $ !%		) 45%7 	, &&%01A%%,C55=DEE,'--2E -SE4&BJy ==
LL&&&*=> #q("#$4"5";";C"CKALL "H(+"H#"   2 	fff.>?@m 3s   D)c                    V ^8  d   QhRRRR/# r  r   )r    s   "r!   r"   rH    s     9 9 9DX 9r#   c                   V P                  R4      ;'       g    . pRpRRRV/.pV EF%  pVP                  R4      pVP                  R4      pVP                  R4      ;'       g    . p\        VP                  R	4      ;'       g    ^ 4      pVP                  R
4      ;'       g    RP                  4       p	VP                  RRRRV RV RV RV	 R\	        V4       2
/4       V Fd  p
V
P                  R4      pV
P                  R4      pVP                  RRRRV RV 2/4       VP                  RRRV
P                  R4      /4       Kf  	  EK(  	  VP                  RRRR/4       V# )a  
Helper: convert bundle into OpenAI Responses API `input` content items in ONE request.
(You can do the same on your server; provided for clarity.)

Output is a list of items like:
  {"type":"input_text","text":"..."}
  {"type":"input_image","image_url":"data:image/jpeg;base64,..."}
r  a  You are a deterministic OCR engine for KYC field crops.
Return ONLY valid JSON. No markdown.

Global rules:
- Do NOT guess. If unreadable or ambiguous: text=null and confidence<=0.3.
- Never invent missing characters.
- Preserve native letters for names (do not transliterate).

Numeric/date rules:
- For kind=numeric: output ONLY ASCII digits 0-9 (no spaces, no separators).
- For kind=date: output as seen; if you can normalize to YYYY-MM-DD, also set normalized.
- NEVER drop leading zeros.

Constraint handling (IMPORTANT):
- Each FIELD may provide expected_len and/or regex.
- If kind=numeric and expected_len>0: you MUST return exactly that many digits.
- If regex is provided: your text MUST match it exactly.
- If you cannot satisfy constraints with high confidence: text=null.

Output JSON format:
{ "fields": { "<key>": {"candidate_idx":0, "text":null, "confidence":0.0, "normalized":null} } }
r  
input_textrz  r  ry  r  r  regexr   z
FIELD key=z kind=z expected_len=z regex=z candidates=idxdet_confzCandidate idx=z
 det_conf=input_image	image_urlr  z
Return ONLY JSON. No markdown.)r   rq   r(   rS   rQ   )r  r  r  rL  r  r  ry  r  r  r  r   r  r  s   &            r!    openai_content_items_from_bundle*KYCEngine.openai_content_items_from_bundle  sy    H%++} 	4 )/fe'L&MA%%,C55=DEE,'--2Equu^499:LUU7^))r002ELL,se6$~l^SZ[`Zaamnqrwnxmyz 
 eeEl55,flFnSEQ[\d[e<fghfm[!%%HXBYZ[  " 	flF4VWXr#   Nc               @    V ^8  d   QhRRRRRRRRR	R
RRRRRRRRRR/
# )r   r  r   doc_cfgr  rw  rd  llm_ocrz*Callable[[Dict[str, Any]], Dict[str, Any]]r6  r  rW  Optional[Dict[str, str]]debugr}   jpeg_qualityrq   rj  r   r   r   )r    s   "r!   r"   rH  T  s{     y yy y '	y
 @y 'y 1y y y y 
yr#   c
                   T;'       g    / p\         P                  ! V4      p
V
f   \        RV 24      h/ pV F+  pVP                  VR,          . 4      P	                  V4       K-  	  V F  pW,          P                  R R7       K  	  / pR R lp. pR/ R	\        V
P                  R
,          4      /p/ pVP                   EF  p. pVP                   F$  pVP                  VP                  V. 4      4       K&  	  V'       g   KD  V Uu. uF:  p\        VP                  RR4      4      \        VP                  4      8  g   K8  VNK<  	  ppVP                  R R7       VRV! V4       pV'       g   K  VP                  ;'       g    RP                  4       pVR8X  dq   V^ ,          pRVP                  ^ ,          R\        VR,          4      RRRRRRRRRVR,          R^ /VVP                   &   VR,          VR,          VP                   &   EKM  \#        VP$                  ;'       g0    VP&                  ;'       g    / P                  R4      ;'       g    ^ 4      p\)        VP&                  ;'       g    / P                  R4      ;'       g    R4      P+                  4       pRVP                   RVRVRVR. /p. VVP                   &   Rp\,        P.                  P1                  V4      '       g   \,        P2                  ! V4       V EFh  p\4        P6                  ! VR,          \4        P8                  R7      p\;        TVR:9   d   R MR!4      p\=        V
V4      pR".p VR:9   d   R".p V  EF  p!\?        VR,          4      p"\A        VVV!V	R#7      p# VP                    R$V! R$V" R%2p$\,        P.                  PC                  VV$4      p%V#PE                  R&^4      w  p&p'\G        V%R'4      ;_uu_ 4       p(V(PI                  \J        PL                  ! V'4      4       RRR4       TR,          P	                  R)T"R\        TR,          4      R*T#/4       TTP                   ,          P	                  T4       EK  	  EKk  	  VR,          '       g   EK  VP	                  V4       EK  	  \)        T;'       g*    VPR                  ;'       g    \U        VPV                  4      4      p*V PY                  VV*R+7      p+V! V+4      ;'       g    / p,\[        V,\\        4      '       d   V,P                  R,4      MRp-\[        V-\\        4      '       g   / p-R- R. lp.R;R/ R0 llp/VP                   EFq  pVP                  ;'       g    RP                  4       pVR8X  d   K1  VP                   V9  d   KD  V-P                  VP                   4      ;'       g    / p0\[        V0\\        4      '       g   / p0V0P                  R4      p1 \#        V14      p1VP                  VP                   4      ;'       g    . p2V2'       g   K  V1^ 8  g   V1\?        V24      8  d   ^ p1V2V1,          p\        VP                  RR4      4      p3V0P                  R4      p4V4f   V0P                  R14      p4V4f   Rp4\)        V44      p4V0P                  R24      p5V5fL   T/! TT4\#        VP$                  ;'       g&    VP&                  P                  R4      ;'       g    ^ 4      R37      p5 \        V54      p5V P_                  V54      p5V0P                  R44      p6V6e   \)        V64      P+                  4       R8X  d   V.! VVV44      p6MV.! VV\)        V64      4      p6RVP                  ^ ,          RV3RV5RV4P+                  4       RV6RR5RVR,          RV1/VVP                   &   VR,          VR,          VP                   &   EKt  	  R,VR6V/p7V'       da   ^ RI0p8V8Pc                  V+4      p9 V9P                  R,. 4       F*  p(V(P                  R. 4       F  pR*V9   g   K  R7VR*&   K  	  K,  	  V9V7R8&   V,V7R9&   V7# u upi   + '       g   i     EL:; i  \N         d   p)\Q        R(T) 24        Rp)?)EL\Rp)?)ii ; i  \N         d    ^ p1 ELi ; i  \N         dP    T/! TT4\#        TP$                  ;'       g&    TP&                  P                  R4      ;'       g    ^ 4      R37      p5 ELi ; i  \N         d     Li ; i)<z
1) Uses YOLO detections + rules to crop candidates.
2) Builds ONE bundle and calls llm_ocr(bundle).
3) Maps response back to per-field extraction pack (same shape as before).
NzCannot read image: r3  c                :    \        V P                  R R4      4      ) # r`  rL   rI   r   rS  s   &r!   <lambda>,KYCEngine.extract_with_llm.<locals>.<lambda>o  s    E!%%2D,E+Er#   r  c                    V ^8  d   QhRRRR/# )r   r   r   r   rq   r   )r    s   "r!   r"   0KYCEngine.extract_with_llm.<locals>.__annotate__t  s     	 		 	c 	r#   c                j    \        V P                  ;'       g    ^4      pV^ 8:  d   ^p\        V^4      # )r  )rq   r  rT   )r   r  s   & r!   top_k)KYCEngine.extract_with_llm.<locals>.top_kt  s2    D'',,1-AAvq!9r#   rx  doc_image_shaper/  r`  rL   c                :    \        V P                  R R4      4      ) # r  r  rS  s   &r!   r  r    s    5vs1C+D*Dr#   rz  r   r  ocr_conf	value_rawr   
ocr_methodr  r  lengthr  r   r  ry  r  r  llm_ocr_debugr  gffffff?gHzG?r|  r  r  r  r  wbzFailed to save debug image: r  r  )r~  r6  r  c               (    V ^8  d   QhRRRRRRRR/# )r   r   r   ry  r   rH  r   r   )r    s   "r!   r"   r    s(     		, 		,) 		,3 		,s 		,s 		,r#   c                   VR 8X  d   \        V4      # VR8X  d   \        \        V4      4      # V P                  R9   d   \	        V4      # V P                  R9   d   VR 8X  d   \        V4      # \        V4      # \        V4      # )r  r  
first_name	last_name	full_name)	id_numberpassport_no)r@   r*   r/   r  r=   rD   r6   )r   ry  rH  s   &&&r!   normalize_value3KYCEngine.extract_with_llm.<locals>.normalize_value  s{    y ,U33v~&|E':;;xxCC%e,,xx777;y7H,U3jNcdiNjj$U++r#   c               (    V ^8  d   QhRRRRRRRR/# )	r   ry  r   rz  r  r  rq   r   rI   r   )r    s   "r!   r"   r    s)     	 	 	M 	 	UZ 	r#   c                B   T;'       g    R P                  4       pV'       g   R# V R8X  d(   \        V4      pV'       d   \        V4      V8X  d   R# R# V R8X  d   \        V4      '       d   R# R# V R8X  d*   R	V9   d!   \        VP	                  4       4      ^8  d   R# R# R
# )r   rL   r  g??r  r	  g?mrz<gffffff?)r(   r@   rQ   ry   
splitlines)ry  rz  r  trx   s   &&&  r!   heuristic_conf2KYCEngine.extract_with_llm.<locals>.heuristic_conf  s    ""$Ay )!,CFl$:v~#A&&u}!8ALLN 3q 8r#   rH  r  )r  r  llm	internalsz<BASE64_REMOVED_FOR_LOG>
llm_bundlellm_response_rawr  )r   )2r3  r  r  
setdefaultrS   sortrO   r0  r  r  extendr   rI   r  r  r<   r  rq   r  r   r   r(   ospathexistsmakedirsr  r   r  r  rA  rQ   r  r  rc   openwriter  	b64decoder   printr  r   r   r  r   r  rT  copydeepcopy):r  r  r  rw  r  r6  rW  r  r  rj  ri  by_classrx   r  candidates_for_keyr  r~  r  r  r   r  r;  r   ry  bestr  r  
plan_entry	debug_dirdetr  r  variantsr   r  data_urlimg_filenameimg_pathheaderencodedr  elhr  llm_resp
llm_fieldsr  r  respcand_idxdet_listr  raw_textr`  	norm_textr   r  clean_bundles:   &&&&&&&&&&                                                r!   extract_with_llmKYCEngine.extract_with_llmT  sB   "  %%2
jj(;!4^4DEFF46A,4;;A> AK!EF  ?A	 -/%,b2CT#))TV-EX$Y	!#MMD/1J&&!!(,,r2"67 '%/iZ5vs9K3LPUVZVgVgPh3h!!ZJiOO DOE#LU4[1JMM++V224D v~!!} $"2"21"5d6l 3 $ $DL#Q	$txx  04F|	'"488,
 !!  $$**//9 L ))//R44W=CCDJJLE txxbJ ,.txx('I77>>),,I&!xxF2::>"49L1LRVW(d3#9.. 'yH "Aj67C4TaY`aHB*.((1QCqT'B#%77<<	<#H*2..a*@!(D11QGGF$4$4W$=> 2
 |,33s"E#f+$6((5 
 'txx077<# " "8 ,''"":.k "p __ 7 7__;Nw;_`11kWY1Z6?((b/9(D/I/IX\\(+t
*d++J		,	& MMDMM++V224Dv~xx11>>$((+11rDdD))xx0Hx= *--dhh7==2H!|x3x=88$CSWWVS12Hxx'H88G,8}H88L)D|%dH3tGXGXGG\`\l\l\p\pqy\zGG~  DA  BBT{ ==&D.I C	N$8$8$:b$@+D$A	+D$IG	 d..q1HDX^^-ieF	 F488 ,/v;Igtxx(w "z i8 ==0L%))(B7AUU<4+q02LA./ 5 8 !-C&.C"# 
M jB 211$ B <QC@AABD  0  B%dH3tGXGXGG\`\l\l\p\pqy\zGG~  DA  BBD  s   
5`<`<Aa*&aa)a<8b0.c- #c- aaaa9	 a4	4a9	<bb&c*7"c*c*)c*-c;:c;c               0    V ^8  d   QhRRRRRRRRR	R
RR/# )r   r  r  extracted_fieldsr   rW  r  	face_packOptional[Dict[str, Any]]r  r}   r   r   )r    s   "r!   r"   rH  Q  sN     H
 H
H
 -H
 1	H

 0H
 H
 
H
r#   c                	   T;'       g    / pVP                    Uu. uF  qfP                  '       g   K  VNK  	  pp^ p\        4       p	. p
. p. p/ p. p. pR R lpR R lpVP                    EF  pVP                  VP                  4      pV'       g   RRRRRRR	R
RRRR/VVP                  &   KD  V P                  \        VP                  RR
4      4      4      pV\        VP                  4      8  pV'       d   V	P                  VP                  4       VP                  ;'       g    RP                  4       pVR8X  d'   Rp\        P                  ! VR,          4      pRpRpRpMT P                  \        VP                  RR
4      ;'       g    R
4      4      pVP                  R4      ;'       g    RpVP                  R4      ;'       g    RpV\        VP                  4      8  ;'       d#    \        \        V4      P!                  4       4      p\        P                  ! V\#        RV4      ,          4      pVP                  '       d   V'       d
   V^,          pRpRpVR8w  dw   VP$                  '       de   \'        VP$                  \        T;'       g    R4      VP(                  ;'       g    / 4      w  ppV'       g   RpT;'       g    VP$                   R2pV! VVVV4      w  p p!V '       g   RpT;'       g    T!pV'       g"   VP+                  RVP                   RV 24       V
P+                  \        V4      \        VP,                  4      34       V P/                  VV4      p"Rp#Rp$V"'       EdL   VR8w  EdD   VP0                  ;'       g    RP                  4       p%V%R8X  d   T;'       g    Rp&T"p'VR8X  d   \3        V&4      p&\3        V'4      p'M>VP                  RD9   d   \5        V&4      p&\5        V'4      p'M\7        V&4      p&\7        V'4      p'V&V'8X  d   RMR
p#V#R8X  d   R MR!p$MV%R"8X  d?   \        \9        T;'       g    RV"4      4      p#V#\        VP:                  4      8  d   R"MR#p$MRV%R$8X  dL   \=        T;'       g    R4      p(\=        V"4      p)V('       d    V)'       d   V(V)8X  d   RMR
p#V#R8X  d   R%MR&p$MRp#R'p$V#eq   VP+                  \        V#4      \        VP,                  4      34       VP>                  '       d0   VP+                  \        V#4      \        VP,                  4      34       VP@                  '       dR   V#R
8X  d&   V$RE9   d   VP+                  R(VP                   24       V$R#8X  d   VP+                  R(VP                   24       RVRVRVRVRVR	\        V4      RV#RV$R)VR*V/
p*V'       dZ   V*PC                  R+VR,VR-VP                  R-4      R.VP                  R.4      R/VP                  R/4      R0VP                  R04      /4       V*VVP                  &   EK  	  V'       d   V\#        ^\E        V4      4      ,          MRp+V! V
4      p,V'       d	   V! V4      MRp-V'       d	   V! V4      MRp.Rp/VPF                  e"   \E        V	4      \I        VPF                  4      8  p/Rp0Rp1VeF   VP                  R4      p1VPJ                  R18X  d   VP                  R14      p0MVP                  R24      p0\        V.e   T.MT-;'       g    R
4      p2V P                  R3\        V,4      ,          R3V2,          ,           4      p3T3p4VPL                  '       dF   V0e@   V P                  R4V3,          R5V P                  \        V04      4      ,          ,           4      p4MT3p4\O        VV+V,V-V.V/\E        V	4      VVV0V1R67      w  p5p6R7V5R8V6R9R:V+R	V,R;V-R<V.R=\E        V	4      R>V/R?V0R@VPJ                  RAV3RBV4/
RCV/# u upi )Fr   c          
     ,    V ^8  d   QhRRRRRRRRRR	/# )
r   r   r   ry  r   r  r  r2  r   r   r   )r    s   "r!   r"   %KYCEngine.score.<locals>.__annotate__h  s5     4	 4	y 4	 4	- 4	Wd 4	  jD 4	r#   c                   V P                   ;'       g    / pV'       g   R# T;'       g    RpT;'       g    RpVP                  R4      pVP                  R4      pVP                  R4      p	Ve%    \        V4      p
\        V4      V
8w  d   RRV
 23#  Ve%    \        V4      p
\        V4      V
8  d   RRV
 23#  V	e%    \        V	4      p
\        V4      V
8  d   RRV
 23#  VP                  R	4      pV'       d3   \        V4      p\        V4      P                  V4      '       g   RR
V 23# VP                  R4      pV'       d0    \        P                  ! \        V4      \        V4      4      f   R#  VR8X  d(   VP                  RR4      '       d   \        V4      f   R# R#   \         d     EL!i ; i  \         d     ELi ; i  \         d     Li ; i  \        P                   d     L|i ; i)Tr   r  
min_length
max_lengthFlength_expected_min_length_max_length_prefixprefix_r  r  
must_parser   )Fregex_mismatch)Fdate_unparsed)r   r   rq   rQ   r   r   r   r&   	fullmatcherrorry   )r   ry  r  r2  r   raw_snorm_sr  r	  r
  Lr  prefr  s   &&&&          r!   validate_constraints-KYCEngine.score.<locals>.validate_constraintsh  s     &&BA!!II2EZZRFUU8_F|,J|,J!FA6{a'$(8&<<< ( %JA6{Q$A3&777 ' %JA6{Q$A3&777 '
 UU8_F6{6{--d33 GD6"222EE'NE||CJF<D66 E
 v~!%%e"<"<#E*211G !  !  !  xx sH   1!F' !F9 !G 	,G 'F65F69GGGGG43G4c                    V ^8  d   QhRRRR/# )r   pairszList[Tuple[float, float]]r   rI   r   )r    s   "r!   r"   r    s     	O 	O1 	Oe 	Or#   c                    V '       g   R # \        R V  4       4      pV^ 8  d#   \        \        R V  4       4      V,          4      # R # )rL   c              3  *   "   T F	  w  rVx  K  	  R # 5ir   r   )r   r  r   s   &  r!   r   0KYCEngine.score.<locals>.wavg.<locals>.<genexpr>  s     )541Q5s   c              3  6   "   T F  w  rW,          x  K  	  R # 5ir   r   )r   r   r   s   &  r!   r   r    s     5utqQUUur   )r   rI   )r  sws   & r!   wavgKYCEngine.score.<locals>.wavg  s>    )5))B?AAv55u55:;N3Nr#   presentFdet_okocr_ok
extractionrL   r  Nr   missingr  rz  r   TrK   r  r  r   r   g{Gz?_invalidzinvalid::no_user_inputr  exactr  exact_matchexact_mismatchfuzzyfuzzy_below_thresholdr  
date_matchdate_mismatchr  z	mismatch:validvalid_reasonr  r  r3  r  r  r  r  r  r%  r  gffffff?)r  coverager'  	match_all
match_corecount_gate_okdetected_countmismatch_flagsinvalid_flags
face_valueface_reasondecisionreasonsscoresr5  r6  r7  detected_fields_countr8  facer*  	doc_scorefinal_score	per_fieldr  )r.  r2  )(r  r  rb   r   r  rT  rI   r  addr  r<   mathsqrtr  r}   r   r(   rU   r  r	  r   rS   r  r\  r  r@   r=   r6   rh   r
  ry   r  r  updaterQ   r  rq   r*  r)  decide)7r  r  r  rW  r  r  r   required_rulesfound_required_detdet_ok_keysextraction_pairsmatch_pairs_allmatch_pairs_corerE  r:  r;  r  r"  r   r  r  r%  ry  r&  r'  r  	raw_value
norm_valuevalid_okr4  r   r   c_okc_reasonr   mscoremreasonmtgot_normexp_normgotexprecr5  extraction_scorer6  r7  r8  face_valr=  
base_matchrC  rD  r>  r?  s7   &&&&&&                                                 r!   scoreKYCEngine.scoreQ  sN     %%2
%,]]A]jj!!]A5685768$&	$&#%4	l	O MMD $$TXX.AuhxVYT8Y'	$((# }}U155S+A%BCHt'8'8!99F)MM++V224Dv~!YYx#~6
 	!
==quuZ/E/L/L)MNEE+.44"	UU<066B
"eD,=,=&>>aaDZI^I^I`Da!YYx#dH2E'EF
}}}"a'"HLv~$...*4>>3z?O?OR;PRVRbRbRhRhfhi
F$H#)#H#H/?x-HL1$iTND( +77x$$xz<.%IJ##U:%6dkk8J$KL))$
;H&*F%GxDFNoo33::<=)//RH'Hy(#8#B#8#B%MM#1(#;#1(#;#4X#>#4X#>$,$8ScF/5}mBRG7]"#7	R#RSF)/59M9M3N)NgTkG6\*9??;C*84Cs(+s
28C-,_!%"1!&&fuT[[7I'JK???$++U6]E$++<N,OPS=W0S%S"))IdhhZ*@A55"))IdhhZ*@A 6&&HHeJ/'#C 

9 * !%%"5 !%%"5AEE&M#QUU?%;  #&Idhhq "t JX&QN0C)DD]` 01.=T/*4	0@d+,d
,,8 -W5V5V1WWM #--1K""h.$==2$==3)?:iFVFVSVX
MM#.>(?"?#
BR"RS	  %%%#"mmD9,<tdmmTYZbTcFd?d,de'"'!'{+)'#
' wH.Yj'[)9w22Y{ 
 	
] Bs
   _3_3)rO  r  rJ  )NNF\   i  )r  r  r  r  r  r  rT  r\  r{  r  r  r  r  ra  r  r   r#   r!   rC  rC  T  s    	, , ,	;~ ,  $, ,\ 8 8t 9 9vyzH
 H
r#   rC  c               H    V ^8  d   Qh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  r5  rI   r'  r6  zOptional[float]r7  r8  r}   r9  rq   r:  r  r;  r<  r=  r  r   zTuple[str, List[str]]r   )r    s   "r!   r"   r"   `  s     D DDD D #	D
 $D D D "D !D $D #D Dr#   c                   . pV P                   e?   V'       g7   VP                  R4       VP                  RV RV P                    24       RV3# WP                  8  d   VP                  R4       RV3# V'       d   VP                  VR,          4       RV3# V'       d   VP                  VR,          4       RV3# V P                  '       d   V	f#   TP                  RT
;'       g    R	 24       RV3# \        V	4      \        V P                  4      8  d9   VP                  R
4       VP                  RV	R RV P                  R 24       RV3# WP                  8  d   W P                  8  d   Vf;   W P                  V P                  ,           8  d   RV3# VP                  R4       RV3# W@P                  8  d   RV3# VP                  R4       Ve   VP                  RVR 24       RV3# WP                  8  dG   W P                  8  d   VP                  R4       WP                  8  d   VP                  R4       RV3# VP                  R4       RV3# )Ndetected_fields_count_too_lowz	detected=z_min=REJECTcoverage_too_low:Nr   NREVIEWzface_required_but_unavailable:unknownface_below_thresholdzface=z.3fz_thr=APPROVEno_core_user_inputcore_match_below_thresholdz
match_all=extraction_lowpartial_coveragecoverage_insufficient)r  rS   r&  r  r)  rI   r+  r  r  r(  r!  r$  )r  r5  r'  r6  r7  r8  r9  r:  r;  r<  r=  r?  s   &&&&&&&&&&& r!   rJ  rJ  `  sL    G((4]67>"2%8Y8Y7Z[\  ///)*   }S)*  ~c*+   !!!NN;K<T<T9;UVWW$$uW%A%ABBNN12NNU:c"2%8T8TUX7YZ[W$$ ///JB`B`4`<<w?d?dde '))NN/0W$$777g%%34 NNZ	#78   ...666NN+,222NN-.  NN*+Wr#   c               0    V ^8  d   QhRRRRRRRRRRRR	/# )
r   r  r   r  rG   r   rH   r   r   Noner   )r    s   "r!   r"   r"     sA     W WN W~ W# WRU W_b Wgk Wr#   c                    W 9   d   W09   d   W,          W,          uW&   W&   VP                  R / 4      pW%9   d   W59   d   WS,          WR,          uWR&   WS&   VP                  R. 4      P                  RVRVRV/4       R# )rx  swap_eventsrG   rH   r   N)r   r  rS   )r  r  rG   rH   r   qs   &&&&& r!   swap_field_keysrw    ss    {q{%y&)	69gr"Av!&T14
ad+22CCHf3UVr#   c               (    V ^8  d   QhRRRRRRRR/# )r   r  r   r  cfgr  r   rs  r   )r    s   "r!   r"   r"     s/     M M~ M. My M]a Mr#   c           	     L    VP                    F  w  r4\        WW4R R7       K  	  R# )config_swap_pairsr   N)r,  rw  )r  r  ry  rG   rH   s   &&&  r!   apply_config_swapsr|    s    18KL r#   c               0    V ^8  d   QhRRRRRRRRRRRR	/# )
r   ocr_first_rawr   ocr_last_raw	exp_firstexp_lastmarginrI   r   r   r   )r    s   "r!   r"   r"     sL     B BBB B 	B
 B Br#   c                   \        T ;'       g    R T;'       g    R 4      p\        T;'       g    R T;'       g    R 4      pWV,           R,          p\        T ;'       g    R T;'       g    R 4      p\        T;'       g    R T;'       g    R 4      p	W,           R,          p
WV,           8  d   RRRVRV
RRVRV	//# RR	RVRV
RR
VRV//# )r   r  swapTscore_normalscore_swappedr  zfirst->lastzlast->firstFzfirst->firstz
last->last)rh   )r~  r  r  r  r  s11s22normals12s21swappeds   &&&&&      r!   best_name_assignmentr    s     }22IOO
DC
|11r8>>r
BCi3F
}22HNN
CC
|11r9??
CCyCG& nfowPY\iknp}  @C  \D  E  	EE>6?GYYgilnz|  YA  B  Br#   c          
     ,    V ^8  d   QhRRRRRRRRRR	/# )
r   r  r   r  ry  r  rW  rX  r   rs  r   )r    s   "r!   r"   r"     s=     M Mn M MV_ Mm{ M  AE Mr#   c           
     8   VP                   '       g   R # RV 9  g   RV 9  d   R # VP                  R4      ;'       g    RpVP                  R4      ;'       g    RpV'       d	   V'       g   R # V R,          P                  R4      ;'       g    RpV R,          P                  R4      ;'       g    Rp\        WgWEVP                  R7      pVP                  R4      '       d;   \	        WRRRR7       VP                  R	. 4      P                  R
RRRRRRV/4       R # R # )Nr  r  r   r  )r  r  heuristic_name_swapr   ru  rG   rH   r   meta)r-  r   r  r/  rw  r  rS   )	r  r  ry  rW  r  r  f_rawl_rawinfos	   &&&&     r!   apply_name_swap_if_neededr    s   6![%>|,22I~~k*00bHH< $$[177RE;##K066BEi#J^J^_Dxx<Mbc]B/66\3P[]eg|  E  GK  8L  	M r#   doc_config_payload
doc_configr  rW  r  	yolo_confr  yolo_ioura   rb  rc  cache_engineTr  Fc               T    V ^8  d   Qh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RR/# )r   r@  r   r  r  r  r  r  zOptional[DocConfig]r  z4Optional[Callable[[Dict[str, Any]], Dict[str, Any]]]rW  r  r  r  r  rI   r  rb  rc  rq   r  r}   r  r   r   r   )r    s   "r!   r"   r"     s     X XX X 	X
 5X (X FX -X )X X X  !X" #X& 'X( )X* +Xr#   c                   Ve   \        V4      pMVe   TpM\        R4      hVf   \        R4      hV'       d   \        V 4      M
\        V 4      pVP	                  WWVR7      pVP                  VVVVVVR7      pVR,          pVR,          p\        VVV4       \        TTY;'       g    / 4       R pVP                  '       dY   V'       dG   VR,          P                  R4      ;'       g    VR,          P                  R	4      p\        WVR
7      pM
RR RR RRRR /pVP                  VVVVVR7      pRVRVR,          RVR,          RVR,          RVR,          /pVP                  '       d   RMRp. pVP                  '       d   V'       g   VP                  R4       VR,          R8X  d   VP                  R4       VVR&   VVR&   V'       d=   VVR&   VVR&   VVR&   VVR&   VP                  R4      VR&   VP                  R 4      VR &   V# )!NzBdoc_config_payload or doc_config must be provided (server-driven).z0llm_ocr callback is required in LLM-OCR edition.)r`  ra  rb  rc  )r  rW  r  r  r  rx  	doc_photophoto)r  r  r  r  r  r   r  r  )rW  r  r  r  r>  r@  r?  rE  r  disabledupload_selfie_requiredrg  retake_document_photoselfie_mode
next_steps
detectionsrB  r  r  )r=  
ValueErrorrD  rC  r{  r  r|  r  r)  r   r  ra  rS   )r@  r  r  r  r  r  rW  r  r  r  rb  rc  r  r  ry  enginerw  packr  r  r  r  scoringresultr  r  s   $$$$$$$$$$$$$$            r!   run_kycr    s?   , %%&89		]^^KLL'3Z
#:9NF==X^e=fD"" # D (^F[!Ivy#.fi6F6FBG I
W%))+6YY)G:L:P:PQX:YD)  ~B  CI"D(D(DTV_aefIll3:Z_l`G 	&GJ''(#79%W[)F !$ 6 6 6*JKJ
&723jX%12'F=%F<#|!x'{"v#xx5|%)XX.@%A!"Mr#   )ro   )r.  )\__conditional_annotations__
__future__r   r  r&   rG  r   r  loggingrM  dataclassesr   r   typingr   r   r   r	   r
   r   r   r3  rs  r  ro  ultralyticsr   r   	maketransr.   r2   compiler5   r4   r*   r/   r6   r=   r@   rD   r^   rh   ry   r   r   r   r}   ValidatorFnr   r   r   r   r   r   r   r   r   r   r  r  r	  r  r%  r+  rA  rZ  rg  rr  rx  r  r  r  r  r  r  rN  r  r  r  r   r  r=  r>  rB  rD  rC  rJ  rw  r|  r  r  r  )r  s   @r!   <module>r     s>   # " 	 	      ( G G G 
    mm %#%S%%%)3%04c%#%S%%%)3%04c% 	#% S% % &*3% 15c% 	#	% S	% T3c	%   $$$$$$$$$"$	6"    NO24&$
2.(
3<&-^ T#s(^,eD(3-4G.HHI!H*.6- 	6-
 &*6- (6-r1#$2,
 5
M-o
M
M;/ + 3&)
8P*0*46C 1 [\ ,* * 	*
 *B&$ $
g_ g
(b (bV ,0( /^^
	(< . . .< # # #@9@ )+% *~~"E
 E
XDVWM
B(M.X
 8<X +/X IMX 04X ,0X  X X  !X" #X& "'X( )X Xr#   