Ë
    I»j…  ã                  óž   — d Z ddlmZ ddlZddlZddlmZ ddlZddlm	Z	  G d„ de
«      Zdd„Zdd	„Zdd
„Zdd„Zdd„Zddœ	 	 	 	 	 	 	 dd„Zy)u�   LLM provider client â€” OpenAI / Anthropic / Gemini via httpx.

Uses keys from `.env`. Falls back to the next configured provider, then to local generation.
é    )ÚannotationsN)ÚAny)Úget_settingsc                  ó   — e Zd Zy)ÚLLMErrorN)Ú__name__Ú
__module__Ú__qualname__© ó    ú!/var/www/html/TJ-AI/tj/app/llm.pyr   r      s   „ Ør   r   c                óÊ   — | j                  «       } | j                  d«      r.t        j                  dd| «      } t        j                  dd| «      } t	        j
                  | «      S )Nz```z^```(?:json)?\s*Ú z\s*```$)ÚstripÚ
startswithÚreÚsubÚjsonÚloads)Útexts    r   Ú_extract_jsonr      sM   € Ø�:‰:‹<€DØ‡��uÔÜ�v‰vÐ)¨2¨tÓ4ˆÜ�v‰v�j " dÓ+ˆÜ�:‰:�dÓÐr   c             ƒ  óX  K  — t        j                  d¬«      4 ƒd {  –—† }|j                  ddd|› �i|dddid	| d
œd|d
œgdœ¬«      ƒ d {  –—† }|j                  «        |j	                  «       d   d   d   d   cd d d «      ƒd {  –—†  S 7 Œq7 ŒC7 Œ	# 1 ƒd {  –—†7  sw Y   y xY w­w)Nç     €V@©Útimeoutz*https://api.openai.com/v1/chat/completionsÚAuthorizationzBearer çš™™™™™Ù?ÚtypeÚjson_objectÚsystem©ÚroleÚcontentÚuser)ÚmodelÚtemperatureÚresponse_formatÚmessages©Úheadersr   Úchoicesr   Úmessager#   ©ÚhttpxÚAsyncClientÚpostÚraise_for_statusr   )r    r$   r%   Úapi_keyÚclientÚress         r   Ú_openai_chatr5      s·   è ø€ Ü× Ñ ¨×.Õ.°&Ø—K‘KØ8Ø$¨°¨yÐ&9Ð:àØ"Ø$*¨MÐ#:à%°&Ñ9Ø#°Ñ5ðñ	ð  ó 
÷ 
ˆð 	×ÑÔØ�x‰x‹z˜)Ñ$ QÑ'¨	Ñ2°9Ñ=÷ /×.Ò.øð
øð /ø×.×.Ñ.üsV   ‚B*�BžB*¡,BÁBÁ/BÁ=B*Â	BÂ
B*ÂBÂB*ÂB'ÂBÂB'Â#B*c             ƒ  ó‚  K  — t        j                  d¬«      4 ƒd {  –—† }|j                  d|dddœ|d| d|d	œgd
œ¬«      ƒ d {  –—† }|j                  «        |j	                  «       }dj                  d„ |j                  dg «      D «       «      cd d d «      ƒd {  –—†  S 7 Œ†7 Œ_7 Œ	# 1 ƒd {  –—†7  sw Y   y xY w­w)Nr   r   z%https://api.anthropic.com/v1/messagesz
2023-06-01úapplication/json)z	x-api-keyzanthropic-versionzcontent-typei   r$   r!   )r%   Ú
max_tokensr    r(   r)   r   c              3  ó@   K  — | ]  }|j                  d d«      –— Œ y­w)r   r   N)Úget)Ú.0Úparts     r   Ú	<genexpr>z"_anthropic_chat.<locals>.<genexpr>B   s   è ø€ ÐPÑ8O°�t—x‘x ¨×+Ñ8Oùs   ‚r#   )r.   r/   r0   r1   r   Újoinr:   )r    r$   r%   r2   r3   r4   Údatas          r   Ú_anthropic_chatr@   0   s´   è ø€ Ü× Ñ ¨×.Õ.°&Ø—K‘KØ3à$Ø%1Ø 2ñð Ø"Ø Ø&,¸Ñ>Ð?ñ	ð  ó 
÷ 
ˆð 	×ÑÔØ�x‰x‹zˆØ�w‰wÑP¸¿¹ÀÈBÔ8OÓPÓP÷# /×.Ò.øð
øð /ø×.×.Ñ.üsW   ‚B?�B$žB?¡%B*ÁB&ÁAB*ÂB?ÂB(ÂB?Â&B*Â(B?Â*B<Â0B3Â1B<Â8B?c          	   ƒ  ót  K  — d|› d|› �}t        j                  d¬«      4 ƒd {  –—† }|j                  |dd| igidd|igdœgd	d
dœdœ¬«      ƒ d {  –—† }|j                  «        |j	                  «       }|d   d   d   d   d   d   cd d d «      ƒd {  –—†  S 7 Œw7 ŒK7 Œ	# 1 ƒd {  –—†7  sw Y   y xY w­w)Nz8https://generativelanguage.googleapis.com/v1beta/models/z:generateContent?key=r   r   Úpartsr   r$   )r"   rB   r   r7   )r&   ÚresponseMimeType)ÚsystemInstructionÚcontentsÚgenerationConfig)r   Ú
candidatesr   r#   r-   )r    r$   r%   r2   Úurlr3   r4   r?   s           r   Ú_gemini_chatrI   E   sÜ   è ø€ à
BØˆ'Ð& w ið	1ð ô × Ñ ¨×.Õ.°&Ø—K‘KØà&-°¸Ð0@Ð/AÐ%BØ&,¸À¸Ð7GÑHÐIà#&Ø(:ñ%ñð  ó 

÷ 

ˆð 	×ÑÔØ�x‰x‹zˆØ�LÑ! !Ñ$ YÑ/°Ñ8¸Ñ;¸FÑC÷ /×.Ò.øð

øð /ø×.×.Ñ.üsV   ‚#B8¥B¦B8©*B#ÁBÁ7B#ÂB8ÂB!ÂB8ÂB#Â!B8Â#B5Â)B,Â*B5Â1B8c                ó  — t        «       }| dv r#t        |j                  j                  «       «      S | dv r#t        |j                  j                  «       «      S | dv r#t        |j
                  j                  «       «      S y)N©Úopenaizgpt-4oÚgpt©Ú	anthropicÚclaude©ÚgeminiÚgoogleF)r   ÚboolÚopenai_api_keyr   Úanthropic_api_keyÚgoogle_api_key)ÚnameÚss     r   Ú_provider_availablerZ   [   su   € Ü‹€AØÐ*Ñ*Ü�A×$Ñ$×*Ñ*Ó,Ó-Ð-ØÐ&Ñ&Ü�A×'Ñ'×-Ñ-Ó/Ó0Ð0ØÐ#Ñ#Ü�A×$Ñ$×*Ñ*Ó,Ó-Ð-Ør   )Úproviderc              ƒ  ó$  K  — t        «       }|xs |j                  xs dj                  «       }|j                  xs dj                  «       }|g}||vr|j	                  |«       dD ]  }||vsŒ|j	                  |«       Œ d}|D ]Ì  }t        |«      sŒ	 |dv r;t        | ||j                  |j                  ¬«      ƒ d{  –—† }	t        |	«      ddfc S |dv r;t        | ||j                  |j                  ¬«      ƒ d{  –—† }	t        |	«      d	dfc S |d
v r;t        | ||j                  |j                  ¬«      ƒ d{  –—† }	t        |	«      ddfc S ŒÎ |rt#        d|› �«      |‚t#        d«      ‚7 Œ°7 Œs7 Œ6# t         $ r}
|
}Y d}
~
�Œd}
~
ww xY w­w)z‘Return (parsed_json, provider_used, used_live_llm).

    If no API keys are configured, raises LLMError so callers can use local generation.
    rL   rR   )rL   rO   rR   NrK   )r%   r2   TrN   rO   rQ   zAll LLM providers failed: z"No LLM API keys configured in .env)r   Údefault_llm_providerÚlowerÚfallback_llm_providerÚappendrZ   r5   Úopenai_modelrU   r   r@   Úanthropic_modelrV   rI   Úgoogle_modelrW   Ú	Exceptionr   )r    r$   r[   rY   ÚprimaryÚfallbackÚorderrX   Ú
last_errorÚrawÚexcs              r   Ú	chat_jsonrk   f   s´  è ø€ ô 	‹€AØÒ=˜1×1Ñ1Ò=°X×DÑDÓF€GØ×'Ñ'Ò3¨8×:Ñ:Ó<€HØˆI€EØ�uÑØ�‰�XÔÛ1ˆØ�uÒØ�L‰L˜Õð 2ð $(€JÛˆÜ" 4Ô(Øð	ØÐ2Ñ2Ü(Ø˜D¨¯©À×@PÑ@Pô÷ �ô % SÓ)¨8°TÐ9Ò9ØÐ.Ñ.Ü+Ø˜D¨×(9Ñ(9À1×CVÑCVô÷ �ô % SÓ)¨;¸Ð<Ò<ØÐ+Ñ+Ü(Ø˜D¨¯©À×@PÑ@Pô÷ �ô % SÓ)¨8°TÐ9Ò9ð	 ,ð ñ. ÜÐ3°J°<Ð@ÓAÀzÐQÜ
Ð7Ó
8Ð8ð)øð
øð
ùô ò 	ØˆJÝûð	üs„   ‚A,FÁ/&FÂ*E7Ã E1ÃE7ÃFÃ*E7Ã?E3Ä E7ÄFÄ*E7Ä>E5Ä?E7Å!FÅ1E7Å3E7Å5E7Å7	FÆ FÆFÆFÆF)r   ÚstrÚreturnr   )
r    rl   r$   rl   r%   rl   r2   rl   rm   rl   )rX   rl   rm   rT   )r    rl   r$   rl   r[   z
str | Nonerm   z tuple[dict[str, Any], str, bool])Ú__doc__Ú
__future__r   r   r   Útypingr   r.   Ú
app.configr   rd   r   r   r5   r@   rI   rZ   rk   r   r   r   Ú<module>rr      su   ðñõ
 #ã Û 	Ý ã å #ô	ˆyô 	óó>ó&Qó*Dó,ð  ñ	.9àð.9ð ð.9ð ð	.9ð
 &ô.9r   