
    P1i                     n   d Z ddlZddlZddlmZmZmZmZ ddlm	Z	 ddl
mZmZmZmZmZmZ ddlmZ ddlmZ ddlZddlmZ dd	lmZ dd
lmZ ddlmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*  ejV                  e,      Z-de.de.fdZ/dde	de.de.de.fdZ0	 	 	 dde	dee.   dee.   dee.   dee.ef   f
dZ1y)z/
Utility functions for BaZi analysis using AI.
    N)DictAnyOptionalList)Person)gGodstem
gEarthstemgGodstem5ElementgEarthElementfindEarthstemGodfindGodstem5E)gShagodNames)timezone)get_active_template)LLMServiceFactory)filter_prompt_for_response)normalize_languagetranslate_gendertranslate_elementget_text	none_text
error_textunknown_text	join_listformat_luck_description
is_missingtranslate_heavenly_stemtranslate_earthly_branchtranslate_ten_godtranslate_special_startemplate_namereturnc                 F    | j                  d      d   }t        |d|       S )a  
    Load a prompt template from the file system or database.
    This is a compatibility wrapper around get_active_template.
    
    Args:
        template_name: Name of the template file (without path)
        
    Returns:
        The template content as a string
    _r   zh-hans)languagefilename)splitr   )r!   divination_types     //home/cursorai/projects/iching/ai/utils/bazi.pyload_prompt_templater+   %   s(     $))#.q1O][[    personcustom_templater&   c                 4   t              t              t              }t              }	 | j	                         }|s.t
        j                  d| j                   d       t        d      g d}|D cg c]	  }||vs| }}|rQt
        j                  d| j                   ddj                  |              t        ddj                  |             |D ]  }||   }	|	5t
        j                  d| j                   d	| d
       t        d| d
      t        |	t              sKt
        j                  d| j                   d| dt        |	              t        d| dt        |	             d|	vr9d|	vr5t
        j                  d| j                   d| d       t        d| d      d|	vsd|	vst
        j                  d| j                   d| d       t        d| d       t
        j                  ddj                  |j                                       	 |r|}t
        j                  d       nXt
        j#                  d        t%        d       }t
        j#                  d!        t
        j                  d"|dd#         | j&                  t)        | j*                        t!        | j,                        | j.                  rt!        | j.                        nd%}g d&}g d'}|D ]  }|D ]  }|d(| d)| d*<     |D ]  }	 |j1                  |      }	|	st
        j3                  | d+       1|	j1                  d      }|	j1                  d      }||t
        j3                  | d,| d-| d.       vt5        j0                  |      }t7        j0                  |      }|t8        v rt8        |   d   nd}|rt;        |      n}|rt=        |      n}||d(| d/<   ||d(| d0<   t?        |      |d(| d1<   g }g }	 tA        |      }|r|jC                         D ]  }t5        j0                  |      }t9        j0                  |i       j1                  d      }|r-t;        |      }|jE                  | d2t?        |       d3       |	j1                  d4      s~|	d4   D ]\  }|j1                  d5      |k(  s|j1                  d6      s*tG        |d6         }t;        |      } |jE                  |  d2| d3          |rtI        |      n|d(| d8<   |rtI        |      n|d(| d9<   |	j1                  d6      }"|d:k(  rtK        d;      |d(| d<<   n!|"rtG        |"      }||d(| d<<   n	||d(| d<<   	 |j1                  d=i       j1                  |      }#|#rw|#j1                  d>      f|#j1                  d>g       D cg c]  }|s|j1                  d?d@       }$}|$D %cg c]  }%|%stM        |%       }&}%|&rtI        |&      n|d(| dA<   n	|d(| dA<     	 g dD}'|j1                  dE      }(|(&t
        j3                  dF       |'D ]  })|d(|) dG<    n.|'D ])  })|(j1                  |)      }*|*t!        |*      n|d(|) dG<   + 	 t
        j                  dIdj                  |r|j                         ng               |j1                  dJ      }+|+t!        |+      n|dK<   |j1                  dL      },|,	 t!        |,      |dM<   nt
        j3                  dO       |dM<   |j1                  dP      }-|-t!        |-      n|dQ<   |j1                  dR      }.|.	 t!        |.      |dS<   nt
        j3                  dU       |dS<   d}/d}0d}1|dV<   |dW<   |dX<   |dY<   |j1                  dZ      }2d}3t        |2t              r?|2j1                  d[      }4|2j1                  d\      }3t        |4tN              r|4D ]  }5|5st        |5t              s|5j1                  d]      s)|5j1                  d5      }6|5j1                  d^      }7|5j1                  d_      }8|6r |6d`k7  rt!        |6      jQ                         r|6nd}/|7r |7d`k7  rt!        |7      jQ                         r|7nd}0|8r |8d`k7  rt!        |8      jQ                         r|8nd}1 n |/|0|3t        |3tR              rda|3cxk  rtU        |4      k  rn n|4|3   }5|5rt        |5t              r|5j1                  d5      }6|5j1                  d^      }7|5j1                  d_      }8|6r |6d`k7  rt!        |6      jQ                         r|6nd}/|7r |7d`k7  rt!        |7      jQ                         r|7nd}0|8r |8d`k7  rt!        |8      jQ                         r|8nd}1|/A|0>|.;	 |2j1                  db      }9|2j1                  dc      }:|9|:tU        |4      dakD  r|.|9z
  ddz  };|4da   }<|<rt        |<t              r|<j1                  d5      }=|<j1                  d^      }>|=r|>rd}?d}@t5        jV                         D ]  \  }A}||=k(  sA}? n t7        jV                         D ]  \  }A}||>k(  sA}@ n |?n@ldadel,m-}Bm.}C |:dfk(  r|?|;z   Bz  }D@|;z   Cz  }En|?|;z
  Bz  }D@|;z
  Cz  }Et5        j0                  D      }/t7        j0                  E      }0|9|;ddz  z   }F|Fdgz   }G|F dh|G }1|3,t        |3tR              rd|j1                  d:      r*|d:   j1                  d      xs |d:   j1                  d      dadjl,m/}Hm0}I tc        dk      D ]  }J|3|Jz   dfz   }K|KtU        |4      k  rsKdgk  rm|4K   }5|5rWt        |5t              rF|5j1                  d5      xs d}L|5j1                  d^      xs d}M|5j1                  d_      xs d}Nd}Od}PLr	 d}Qt5        jV                         D ]  \  }A}|Lk(  sA}Q n Q HQ      }R|RrtG        R      nd}OMrd}St7        jV                         D ]  \  }A}|Mk(  sA}S n SW IS      }T|TrLTjC                         D Ucg c]  }U|UsU	 }V}U|VD Ucg c]  }U|UstG        U       }W}U|WrtI        W      nd}Pte        LMNtg        O      rdnOtg        P      rdnP      }X|X|dmJdfz    d*<   |dmJdfz    d*<   |dmJdfz    d*<    n-t
        j3                  dn       n|2t
        j3                  do       |/t!        |/      jQ                         s|0ht!        |0      jQ                         rN	 d|j1                  d:      r*|d:   j1                  d      xs |d:   j1                  d      d}Yd}Z|/r	 dadjl,m/}Hm0}I d}Qt5        jV                         D ]  \  }A}||/k(  sA}Q n Q HQ      }R|RrtG        R      nd}Y|0rd}St7        jV                         D ]  \  }A}||0k(  sA}S n SW IS      }T|TrLTjC                         D Ucg c]  }U|UsU	 }V}U|VD Ucg c]  }U|UstG        U       }W}U|WrtI        W      nd}Zte        |/xs d@|0xs d@|1xs d@tg        Y      rdnYtg        Z      rdnZ      |dV<   ti        jj                         jl                  }[t!        |[      |dr<   |[dfz   }\|[dsz   }]|[dkz   }^|[dtz   }_|[duz   }`|[dvz   }a|[dwz   }b|[dxz   }c|[dgz   }dd}ed}fd}gd}hd}id}jd}kd}ld}md}nd}od}pd}qd}rd}sd}td}ud}vd}wd}x|j1                  dy      }yt        |yt              rNyj1                  d[      }zt        |ztN              rzD ]  }5|5rt        |5t              s|5j1                  dz      }{|5j1                  d5      xs d}|5j1                  d^      xs d}|{[k(  r|}e|}f[{\k(  r|}g|}he{]k(  r|}i|}jo{^k(  r|}k|}ly{_k(  r|}m|}n{`k(  r|}o|}p{ak(  r|}q|}r{bk(  r|}s|}t{ck(  r|}u|}v{dk(  s|}w|}x efzD ]S  }5|5st        |5t              s|5j1                  d]      s)|5j1                  d5      xs d}e|5j1                  d^      xs d}f n/ n-t
        j3                  d{       nyt
        j3                  d|       ert;        e      n|d}<   frt=        f      n|d~<   t!        \      |d<   grt;        g      n|d<   hrt=        h      n|d<   t!        ]      |d<   irt;        i      n|d<   jrt=        j      n|d<   t!        ^      |d<   krt;        k      n|d<   lrt=        l      n|d<   t!        _      |d<   mrt;        m      n|d<   nrt=        n      n|d<   t!        `      |d<   ort;        o      n|d<   prt=        p      n|d<   t!        a      |d<   qrt;        q      n|d<   rrt=        r      n|d<   t!        b      |d<   srt;        s      n|d<   trt=        t      n|d<   t!        c      |d<   urt;        u      n|d<   vrt=        v      n|d<   t!        d      |d<   wrt;        w      n|d<   xrt=        x      n|d<   	 d|j1                  d:      r*|d:   j1                  d      xs |d:   j1                  d      dtn        t            dtn        t            ffd}} |}ef      \  }~}|~|d<   ||d<    |}gh      \  }}||d<   ||d<    |}ij      \  }}||d<   ||d<    |}kl      \  }}||d<   ||d<    |}mn      \  }}||d<   ||d<    |}op      \  }}||d<   ||d<    |}qr      \  }}||d<   ||d<    |}st      \  }}||d<   ||d<    |}uv      \  }}||d<   ||d<    |}wx      \  }}||d<   ||d<   |/t!        |/      jQ                         s|0`t!        |0      jQ                         rG }|/|0      \  }Y}Zte        |/xs d@|0xs d@|1xs d@tg        Y      rdnYtg        Z      rdnZ      |dV<   	 |}|jW                         D ]  \  }}*jq                  ||*      } tU              }ts        |      }tU        |      |k  r%t
        j                  dtU               d d3       t
        j                  dtU               d       |S c c}w # t        $ rL}
t
        j                  d| j                   dt!        |
       d       t        dt!        |
             d}
~
ww xY w# t        $ r)}
t
        j                  d$t!        |
       d        d}
~
ww xY w# t        $ r1}!t
        j                  d7| dt!        |!       d       Y d}!~!d}!~!ww xY wc c}w c c}%w # t        $ r:}!t
        j                  dB| dt!        |!       d       ||d(| dA<   Y d}!~!d}!~!ww xY w# t        $ rD}!t
        j                  dC| dt!        |!       d       |D ]  }||d(| d)| d*<    Y d}!~!]d}!~!ww xY w# t        $ r>}!t
        j                  dHt!        |!       d       dDD ]  })||d(|) dG<    Y d}!~!d}!~!ww xY w# t        $ r1}!t
        j3                  dNt!        |!              |dM<   Y d}!~!d}!~!ww xY w# t        $ r1}!t
        j3                  dTt!        |!              |dS<   Y d}!~!d}!~!ww xY w# t        $ r.}!t
        j3                  dit!        |!       d       Y d}!~!od}!~!ww xY wc c}Uw c c}Uw # t        $ r2}!t
        j3                  dlJdfz    dt!        |!              Y d}!~!d}!~!ww xY wc c}Uw c c}Uw # t        $ r,}!t
        j3                  dpt!        |!              Y d}!~!	d}!~!ww xY w# t        $ r}!t
        j3                  dqt!        |!              |/rt!        |/      jQ                         s|0r9t!        |0      jQ                         r te        |/xs d@|0xs d@|1xs d@dd      |dV<   n|dV<   Y d}!~!	d}!~!ww xY w# t        $ r}!t
        j                  dt!        |!       d       |d<   |d<   |d<   |d<   |d<   |d<   |d<   |d<   |d<   |d<   |d<   |d<   |d<   |d<   |d<   |d<   |d<   |d<   |d<   |d<   |/t!        |/      jQ                         s|09t!        |0      jQ                         r te        |/xs d@|0xs d@|1xs d@dd      |dV<   n|dV<   Y d}!~!d}!~!ww xY w# t        $ rV}!t
        j                  dt!        |!       d       |dK<   |dM<   |dQ<   |dS<   |dV<   |dW<   |dX<   |dY<   Y d}!~!wd}!~!ww xY w# t        $ r?}
t
        j                  dt!        |
       d       t        dt!        |
             d}
~
ww xY w)as  
    Prepare a prompt for BaZi analysis based on a Person object.
    
    Args:
        person: Person object with BaZi data
        custom_template: Optional custom template string to use instead of loading from file/db
        language: Language code for template retrieval and placeholder text
        
    Returns:
        Formatted prompt string with BaZi data
    z
Person id=z returned empty BaZi dataz"Person has no BaZi data to analyze)yearmonthdayz is missing required pillars: , z'BaZi data is missing required pillars: Nz has None for z pillarzBaZi data has None for z has invalid z	 pillar: zBaZi data has invalid god_idxg z pillar missing god_idx/gz
BaZi data 	earth_idxez pillar missing earth_idx/ezBaZi data keys: z%Error calculating BaZi for person id=: Texc_infozFailed to calculate BaZi data: zUsing provided custom templatez'Requesting BaZi template for language: bazir&   z9Successfully loaded BaZi analysis template for language: z$Template preview (first 200 chars):    zError loading template: )z{{name}}z
{{gender}}z{{birth_date}}z{{birth_time}})r0   r1   r2   hour)stembranchstem_elementhidden_elementshidden_relationshipsstem_relationshipsha_godsz{{r$   z}}z' pillar not found or empty in BaZi dataz pillar missing stem (z) or branch (z) indexz_stem}}z	_branch}}z_stem_element}}z ()hidden_godsgodten_godz!Error processing hidden gods for z_hidden_elements}}z_hidden_relationships}}r2   
self_labelz_stem_relationship}}rF   godsname z_sha_gods}}zError processing sha_gods for zError processing )woodfireearthmetalwaterelement_strengthsz$element_strengths is None or missingz_strength}}z$Error processing element strengths: z+Processing additional BaZi data with keys: chart_structurez{{chart_structure}}life_numberz{{life_number}}z(Error converting life_number to string: z"life_number not found in BaZi datalife_palacez{{life_palace}}nominal_agez{{current_age}}z(Error converting nominal_age to string: z"nominal_age not found in BaZi dataz{{current_luck_pillar}}z{{luck_pillar_1}}z{{luck_pillar_2}}z{{luck_pillar_3}}ten_year_fatecolumnscurrent_column_index
is_currentrQ   	age_rangeNoner   
start_year	direction
   )gGLengELen   	   -z0Error calculating current luck pillar from age: )	calc10GodcalcEarthstem10God   z8Error calculating ten god relationships for luck pillar z{{luck_pillar_z(ten_year_fate columns missing or invalidz#ten_year_fate has unexpected formatzAError calculating ten god relationships for current luck pillar: z&Error formatting current luck pillar: z{{current_year}}                  	year_fater0   z$year_fate columns missing or invalidzyear_fate has unexpected formatz{{current_year_stem}}z{{current_year_branch}}z{{next_year}}z{{next_year_stem}}z{{next_year_branch}}z{{next2_year}}z{{next2_year_stem}}z{{next2_year_branch}}z{{next3_year}}z{{next3_year_stem}}z{{next3_year_branch}}z{{next4_year}}z{{next4_year_stem}}z{{next4_year_branch}}z{{next5_year}}z{{next5_year_stem}}z{{next5_year_branch}}z{{next6_year}}z{{next6_year_stem}}z{{next6_year_branch}}z{{next7_year}}z{{next7_year_stem}}z{{next7_year_branch}}z{{next8_year}}z{{next8_year_stem}}z{{next8_year_branch}}z{{next9_year}}z{{next9_year_stem}}z{{next9_year_branch}}	year_stemyear_branchc                    }}| s||fS d }t        j                         D ]  \  }}|| k(  s|} n |||fS ddlm}  ||      }|rt	        |      n}|s||fS d }	t        j                         D ]  \  }}
|
|k(  s|}	 n |	||fS ddlm}  ||	      }|rL|j                         D cg c]  }|s|	 }}|D cg c]  }|st	        |       }}|rt        |      n}||fS c c}w c c}w )Nr   )rg   )rh   )	r   itemsiching.utils.bzrg   r   r	   rh   valuesr   )rq   rr   rE   branch_relationshipsyear_stem_idxidxr@   rg   stem_relyear_branch_idxrA   rh   branch_ten_godsrJ   descriptionstranslated_descriptionsday_god_idxr&   
none_values                   r*   calculate_year_ten_godsz4prepare_bazi_prompt.<locals>.calculate_year_ten_gods  sU   $.!'1$&i,.BBB $!)!1ICy((+ "2
 !(,.BBB5$[-@MU$5h$I[e!",.BBB"&#-#3#3#5KC,*- $6
 #*,.BBB>"4[/"R";J;Q;Q;S#_;SW^G;SL#_co.{coX_sz/@(/Sco+.{[r95Lh+W  yC((*>>> $`.{s   0C.8C.C3
C3z"{{current_year_stem_relationship}}z%{{current_year_branch_relationships}}z{{next_year_stem_relationship}}z"{{next_year_branch_relationships}}z {{next2_year_stem_relationship}}z#{{next2_year_branch_relationships}}z {{next3_year_stem_relationship}}z#{{next3_year_branch_relationships}}z {{next4_year_stem_relationship}}z#{{next4_year_branch_relationships}}z {{next5_year_stem_relationship}}z#{{next5_year_branch_relationships}}z {{next6_year_stem_relationship}}z#{{next6_year_branch_relationships}}z {{next7_year_stem_relationship}}z#{{next7_year_branch_relationships}}z {{next8_year_stem_relationship}}z#{{next8_year_branch_relationships}}z {{next9_year_stem_relationship}}z#{{next9_year_branch_relationships}}z9Error calculating ten god relationships for yearly data: z'Error processing additional BaZi data: z9Stripped content after last '---' separator, new length: z characters (was z&Successfully prepared prompt, length:  charactersz*Error replacing placeholders in template: zError formatting BaZi prompt: ):r   r   r   r   calculate_baziloggererrorid
ValueErrorjoin
isinstancedicttypedebugkeys	Exceptionstrinfor   rM   r   gender
birth_date
birth_timegetwarningr   r	   r
   r   r   r   r   rv   appendr   r   r   r    liststripintlenrt   ru   rb   rc   rg   rh   ranger   r   r   nowr0   r   replacer   )r-   r.   r&   error_valueunknown_value	bazi_datarequired_pillarspillarmissing_pillarspillar_datar8   templatereplacementspillarspillar_fieldsfieldstem_idx
branch_idxr@   rA   rB   translated_stemtranslated_branchrH   rD   
earth_godsr4   rI   god_elementtranslated_god
hidden_godtranslated_ten_godtranslated_god_for_relexcten_god_valuesha_gods_datanamesrM   translated_nameselements	strengthselementvaluerU   rV   rW   rX   current_luck_godcurrent_luck_earthcurrent_luck_age_rangerY   r[   rZ   columngod_val	earth_valage_valr_   r`   pillar_offsetfirst_column	first_godfirst_earthfirst_god_idxfirst_earth_idxry   rb   rc   current_god_idxcurrent_earth_idx	age_startage_endrg   rh   ipillar_index
pillar_godpillar_earthpillar_age_rangepillar_stem_relationshippillar_branch_relationshipspillar_stem_idxrz   pillar_branch_idxr|   rJ   r}   r~   formatted_pillarcurrent_luck_stem_relationship!current_luck_branch_relationshipscurrent_year	next_year
next2_year
next3_year
next4_year
next5_year
next6_year
next7_year
next8_year
next9_yearcurrent_year_stemcurrent_year_branchnext_year_stemnext_year_branchnext2_year_stemnext2_year_branchnext3_year_stemnext3_year_branchnext4_year_stemnext4_year_branchnext5_year_stemnext5_year_branchnext6_year_stemnext6_year_branchnext7_year_stemnext7_year_branchnext8_year_stemnext8_year_branchnext9_year_stemnext9_year_branchrp   year_columnsr0   rQ   r   current_year_stem_relationship!current_year_branch_relationshipsnext_year_stem_relationshipnext_year_branch_relationshipsnext2_year_stem_relationshipnext2_year_branch_relationshipsnext3_year_stem_relationshipnext3_year_branch_relationshipsnext4_year_stem_relationshipnext4_year_branch_relationshipsnext5_year_stem_relationshipnext5_year_branch_relationshipsnext6_year_stem_relationshipnext6_year_branch_relationshipsnext7_year_stem_relationshipnext7_year_branch_relationshipsnext8_year_stem_relationshipnext8_year_branch_relationshipsnext9_year_stem_relationshipnext9_year_branch_relationshipspromptplaceholderoriginal_lengthr   r   s     `                                                                                                                                                  @@r*   prepare_bazi_promptr  5   sJ     "(+H8$JX&K *M$E))+	LL:fii[0IJKABB 40@\0@fFR[D[60@\LL:fii[0NtyyYhOiNjklFtyyQ`GaFbcdd 'F#F+K"z&))N6('RS #:6('!JKKk40z&))M&SWXcSdRefg #9&4P[K\J]!^__+;0Fz&))AfX=VWX :fX5N!OPP+-#[2Hz&))AfX=XYZ :fX5P!QRR! '$ 	'		)..2B(C'DEF&HLL9: KKA(LM*6HEHKKST\S]^_LL?#?OPQ KK&v}}h?f//04:4E4E#f//0:	L /G CM"E8BL4xqt45 #  Q	H#--/K&)PQR"y1H$5J:#5&)?zWaVbbijk<<)D^^J/F>FJZ>Z+H5c:`dL JN5dHES]ONT 8 JZd5DL4xy127HL4x{34=N|]e=fL4x'89: &(K.0 f-j9
#-#4#4#6&ll73&6&:&:7B&G&K&KC&P-DS(-SN'...1ADUVackDlCmmn/op&??=9.9-.H
#->>%#8C#?JNNS\D]9J:V_K`bj9k$6=TUXZb=c$:$8$?$?CYBZZ\]o\ppq@r$s$) /I $7$ ep	+W_@`uL4x';<= sGYOcemEn  MWL4x'@AB (OOI6MFN|]eFftF8+ABC%6}h%O"FXtF8+ABCFStF8+ABCI )j" = A A& I ]%6%6v%>%J<I<M<MfVX<Ya<YS]`SWWVR0<YEa[`'i[`SWdh(>tX(N[`$'ijzK[]eAf  AKL4x}!=>AKL4x}!=>U jF>MM"56	NNAB#>HtG9M:; $ $!g.LQL]c%jcmtG9M:; $[7B499ajY^^M]prCsBtuv#--(9:FUFac/.Bgq*+mmM2"=25k2B./
 NN?@.8L*+mmM2>I>U#k*:[e&'mmM2"=25k2B./
 NN?@.8L*+*.,0042<./ -7(),6(),6()!o6.2mT*#''	2G#0#4#45K#L '4(%F*VT":vzz,?W"(**U"3$*JJw$7	"(**["96='VBSX[\cXdXjXjXl7rv(:C	U[H[`cdm`n`t`t`vY  }A*<CSYHY^abi^j^p^p^rx|. & $+0B0J+7JG[]`<a 4Cs7|C%,-A%BF%*VT*B*0**U*;,2JJw,?	*0**[*A>E'U[J[`cdk`l`r`r`t7z~ 0BKPY]cPchkluhvh|h|h~Y  EI 2DKPW[aPafijqfrfxfxfz  AE 6 $+0B0J{Of0u%2%6%6|%D
$1$5$5k$B	%1i6KPST[P\_`P` .9:-E",LM ,31:L+
<0N,8,<,<U,C	.:.>.>w.G#,48M6:O5=^^5E	T+/9+<<?M,1 6F 8B7G7G7IV+1[+@>AO,1 8J
 (5'@_E` )Q+4>?L}?\`e>eOAPS`A`di@i,=?L}?\`e>eOAPS`A`di@i,=;C<<;X(8=G^^L]=^(: 5?-RTBT4U	2;a-DM;aPWyAY(> (3
CWY\8]"&K }}U+&/&6&:&:9&E&bSXIYI]I]^aIb N
 #1X';a'?!'C'#g,6<1;L%,\%:F%*VT*B-3ZZ->-F$
/5zz'/B/Jd39::k3J3Rd 0 <@ 8>B ;#.#:z%E ;?9A9IIC/3z/ABE05 :J
 ,;+F7@o7^HpxGXYackGl  C,D ,8@D,=?I?O?O?QV39\3IHK4E49 @R
 0A/LBTU`bsBt3B[j[q[q[sC[sPWw~G[sLC DP  O\  DPx  T[O`ahjrOs  DP4K  O\ CZR[\su}R~  `d4O
 4K$.$0$4,67OQY,ZD`x,67RT\,]Dc~$,4" 0 N^/?!uD-I JMW/?!uD-I J JTL+;AaC5)EFs &v IJ&NN@A
 (S1A-B-H-H-JPbPnsv  xJ  tK  tQ  tQ  tS@I"=='"+E"2"6"6y"A"^YuEUEYEYZ]E^K 26.481*/?wQ +/)1)9IC#'7725 % *:
 +6'0o'NHfn=NxYa=btx: .04-/9/?/?/AV#)-?#?8;$5$) 0B
  1<2D[Rc2d#2KZKaKaKc3oKcgnGKcL3os  ?Lsho  DK?PQXZb?cs$;  ?L yP	RiksHt  VZ$E ;R$*&,"*0b&'ExPDVt&'H(SDYz;67.  ||~**+.|+<'( 1$	!A%
!A%
!A%
!A%
!A%
!A%
!A%
!A%
+/-1(,*.)-+/)-+/)-+/)-+/)-+/)-+/)-+/)-+/MM+.	i&$==3L,-*F!FD)A !::f-D **U+3tC"JJw/74E|+,/).3+*),+0(+*-,1)+*-,1)+*-,1)+*-,1)+*-,1)+*-,1)+*-,1)+*-,1)I +L %,1D1L".!j&>6::lC[06

50A0IT-28**W2E2M/!	 #/ EF"NN<= iz0GHY[c0d  @J,- nA2JK^`h2i  GQ./(+I_%bp-D^U]-^  wA)*gw/GHXZb/c  ~H+,),Z%&ds.EoW_.`  zD*+iz0HIZ\d0e  AK,-),Z%&ds.EoW_.`  zD*+iz0HIZ\d0e  AK,-),Z%&ds.EoW_.`  zD*+iz0HIZ\d0e  AK,-),Z%&ds.EoW_.`  zD*+iz0HIZ\d0e  AK,-),Z%&ds.EoW_.`  zD*+iz0HIZ\d0e  AK,-),Z%&ds.EoW_.`  zD*+iz0HIZ\d0e  AK,-),Z%&ds.EoW_.`  zD*+iz0HIZ\d0e  AK,-),Z%&ds.EoW_.`  zD*+iz0HIZ\d0e  AK,-G	EK}}U#'.229=Z5AQAUAUVYAZ)?8C= )?xX[} )?V Qhhy  |O  QPM*,MA_L=>DeL@AJabp  sC  KDG')G>YL:;A_L=>Lcds  vG  MHI(*I?[L;<BaL>?Lcds  vG  MHI(*I?[L;<BaL>?Lcds  vG  MHI(*I?[L;<BaL>?Lcds  vG  MHI(*I?[L;<BaL>?Lcds  vG  MHI(*I?[L;<BaL>?Lcds  vG  MHI(*I?[L;<BaL>?Lcds  vG  MHI(*I?[L;<BaL>?Lcds  vG  MHI(*I?[L;<BaL>? !,5E1F1L1L1NTfTrwz  |N  xO  xU  xU  xWTkl|  Q  URQ.0Q:Q$*&,"*0b&'ExPDVt&'H(SDYz;67tD"."4"4"6K^^K7F #7 f++F3v;(LLTUXY_U`Taar  tC  sD  DE  F  G=c&k]+VWc ]4  E<VYYKr#a&R]ab:3q6(CDDE   /Ax84HH  f@3s8*U`deef* b'i  I=fXRCzR]ab=HtF8=9:I  	HLL,VHIc#hZHSWLX&<GtF81UG489 '	H"  F;CH:FQUVBG:EL4y67 CF   =!I#c(TU2<./=  =!I#c(TU2<./=F % u)YZ]^aZbYc'dosttul D@ O\+4 %E(.9qrsturuqvvxy|  ~A  zB  yC  8D  )E  )E%E@ 4p ?L$ w)jknorksjt'uvvw  I!GCzRS$-=)>)D)D)FL^cfgycz  dA  dA  dC>U(.B*0b.4" ?L!:; ?IL!:;IR  #	ELLTUXY\U]T^_jnLoAKL=>DNL@A>HL:;AKL=>?IL;<BLL>??IL;<BLL>??IL;<BLL>??IL;<BLL>??IL;<BLL>??IL;<BLL>??IL;<BLL>??IL;<BLL>? !,5E1F1L1L1NTfTrwz  |N  xO  xU  xU  xW:Q$*&,"*0b;67 ;E67G#	EJ  	7>s3xjITXY.8*+*4&'*4&'*4&'2<./,6(),6(),6()	78  DA#a&JUYZ9#a&BCCDs  AAT 9	ATATD3AT ;AT  A+AT ,A2AU.  +AX0AAX0B	AX0BAV#6AV#AV#%7AV#A9AX0AAW*AW &AW :AW* AW%AW%#AW*=A+AZ  )A/Af A[
 'AAf 9A\ BAf Af ,Af >FAf BA] -$A] A5A] C%Af -!A^AA^$A^7A]>?A]>A^	A^A^A^1B=Af /AA` 5)A_ AA_ #$A_ A_A_A_ A_!A_/A_ ;A` <E7Af @4Af AAf AAf A)IAf J?F8Ab Q8BAg6 TAT T	AU+TAAU&U&AU+U.	AV U7$AVVAV V#	AWV,&AWWAX0WAWWAX0W 
AW*W*	AX-W3/AX(X"AX0X(AX-X-AX0X0	AY=X99AY8Y8AY=Z 	A[Z	3A[[A[[
	A\[&A[?[9Af [?A\\Af \	A]\&A\<\6Af \<A]]Af ]	A];]#A]6]0Af ]6A];];Af ]>
A^^	A_^'A^>^8Af ^>A__Af _
A_ _	A`_!A` _:A` ` A``A` `	Ab`A<AbbAf bAbbAf b	Afb$C"AffAf fAffAf f	Ag3fAAg.g.Ag3g6	Ah>g?:Ah9h9Ah>	model_keyproviderc           	         	 t        |      }|r|s ddlm}  |d      }|xs |d   }|xs |d   }t        j	                  d| j
                   d| d|        	 t        j                  |      }t        j                  d	|j                  j                          |r*	 |j                  |       t        j                  d|        	 t!        | |      }t        j                  dt#        |       d       	 t        j                  d       |j%                  |dd      }	t        j                  d|	rt#        |	      nd d       |	s t        j                  d       t        d      	 |	j'                         }
d}	 t)        j*                  d|
t(        j,                        }|rv|j/                  d       j'                         }t)        j0                  d!d"|
t(        j,                  #      j'                         }
t        j                  d$t#        |       d       t)        j*                  d%|
t(        j,                        }|r6|j/                  d       j'                         }|}
t        j                  d&       	 t3        j4                  |
      }|}
t        j                  d'       	 |j:                  }|}t        j                  d.| d/|        	 |
t=        |      |||d2}|r||d3<   t        j                  d4d5j?                  |jA                                       	 || _!        tE        jF                         | _$        d8| _%        | jM                  g d9:       t        j	                  d;| j
                          | jB                  S # t        $ r=}t        j                  d
t        |              t        dt        |             d}~ww xY w# t        $ rC}t        j                  d| dt        |              t        d| dt        |             d}~ww xY w# t        $ r=}t        j                  dt        |              t        dt        |             d}~ww xY w# t        $ r=}t        j                  dt        |              t        dt        |             d}~ww xY w# t2        j6                  $ r,}t        j9                  d(t        |              Y d}~Fd}~ww xY w# t        $ rY}t        j                  d)t        |              t        j                  d*|	dd+  d,       t        d-t        |             d}~ww xY w# t        $ r8}t        j                  d0t        |              |xs d1}|xs d1}Y d}~d}~ww xY w# t        $ r=}t        j                  d6t        |              t        d7t        |             d}~ww xY w# t        $ r=}t        j                  d<t        |              t        d=t        |             d}~ww xY w# t        $ r6}t        j                  d>| j
                   dt        |       d?@        d}~ww xY w)Aa  
    Analyze a person's BaZi chart using AI.
    
    This function uses the active template from the database if available,
    otherwise falls back to the file system template.
    
    Args:
        person: Person object to analyze
        model_key: Optional model key to use (from settings.GROQ_MODELS or settings.OPENAI_MODELS)
        provider: Optional LLM provider to use ('groq' or 'openai')
        
    Returns:
        Dictionary with analysis results
    r   )get_ai_configr<   r  modelz%Starting BaZi analysis for person id=z using provider=z, model=zCreated LLM service: zFailed to create LLM service: z"Could not initialize LLM service: NzChanged model to zFailed to change model to r9   zCould not change model to r=   z4Prepared BaZi prompt using active template, length: r   zFailed to prepare BaZi prompt: zCould not prepare BaZi prompt: zRequesting LLM completiongffffff?i   )r  temperature
max_tokenszReceived LLM response, length: zLLM returned empty responsezEmpty response from LLM servicezFailed to get LLM completion: z+Error getting completion from LLM service: z<think>(.*?)</think>rd   z<think>.*?</think>rN   )flagsz$Extracted thinking content, length: z```(?:json)?(.*?)```z Extracted content from backticksz$Successfully parsed analysis as JSONz*Analysis not valid JSON, using as string: z Failed to process LLM response: zRaw analysis: d   z...zError processing LLM response: zUsed model: z, provider: z!Failed to get model information: unknown)bazi_analysisr  r  r  r&   thinkz+Prepared AI analysis dictionary with keys: r3   z*Failed to prepare ai_analysis dictionary: z%Error preparing analysis dictionary: 	completed)ai_analysisanalysis_timestampanalysis_status)update_fieldsz*Successfully saved analysis for person id=z*Failed to save analysis to person object: z#Error saving analysis to database: z Error analyzing BaZi for person Tr:   )'r   ai.utils.configr  r   r   r   r   get_servicer   	__class____name__r   r   r   r   change_modelr  r   get_completionr   researchDOTALLgroupsubjsonloadsJSONDecodeErrorr   r  r   r   r   r  r   r   r  r   save)r-   r  r  r&   r  configllm_servicer8   r  raw_analysisanalysisthinking_contentthinking_matchbackticks_matchbackticks_content	json_datajson_err
used_modelused_providerr  s                       r*   analyze_bazir=  %  s   (F%h/ y5"6*F56*#5H!4VG_I 	;FII;FVW_V``hirhstu	L+77AKLL01F1F1O1O0PQR U((30<=	I((CFLLOPSTZP[}\ghi	ULL46&55 6 L
 LL:P\3|;Lbc:ddopq:; !BCC    %%'	IYY'>"))TN#1#7#7#:#@#@#B 66"7XRYYW]]_CCHXDYCZZefg !ii(?299UO$3$9$9!$<$B$B$D!,?@] JJx0	$CD	2$**J$MLL<
|<OP	O!)4V<)#$K  '7G$LLFtyyQ\QaQaQcGdFefg	M!,F(0F%%0F"KK&^K_KKDVYYKPQ
 !!!c  	LLL9#a&BCA#a&JKK	L  U9)Bs1vhOP #=i[3q6(!STTU  	ILL:3q6(CD>s1vhGHH	I"  	ULL9#a&BCJ3q6(STT	U> '' ]!KCPXM?[\\]  	ILL;CF8DELL>,t*<)=SAB>s1vhGHH	I  	2LL<SVHEF"/iJ$1	M	2(  	OLLEc!fXNODSVHMNN	O  	MLLEc!fXNOB3q6(KLL	M  7		{"SVHMX\]sJ  AX- AN X- )O /P 8A1Q' )X- =C:S2 8,R0 %)U AV AW$ :X- 	O8OOX- 	P>PPX- 	Q$'8QQ$$X- '	R-08R((R--X- 0S/!S*$S2 *S//S2 2	U;AUUX- 	V -VX- VX- 	W!$8WW!!X- $	X*-8X%%X**X- -	Y,61Y''Y,)Nr%   )NNN)2__doc__loggingr-  typingr   r   r   r   bazi.modelsr   ru   r   r	   r
   r   r   r   iching.utils.bzshagodr   django.utilsr   r(  ai.utilsr   ai.services.factoryr   iching.utils.utilsr   ai.utils.i18nr   r   r   r   r   r   r   r   r   r   r   r   r   r    	getLoggerr%  r   r   r+   r  r=   r,   r*   <module>rJ     s      , ,   / ! 	 ( 1 9   " 
		8	$\ \ \ nD nD nDs nDcf nDd  $""	ZZ}Z smZ sm	Z
 
#s(^Zr,   