o
    p›Xj¦  ã                   @  s„   d dl mZ d dlZd dlZd dlmZmZ d dlmZm	Z	m
Z
 G dd„ deƒZddd„ZG dd„ dƒZG dd„ dƒZddd„ZdS )é    )ÚannotationsN)ÚAnyÚProtocol)ÚretryÚstop_after_attemptÚwait_exponentialc                   @  s$   e Zd Zdddd	„Zdddd„ZdS )Ú
LLMServiceé   ÚsystemÚstrÚuserÚ
max_tokensÚintÚreturnc                 C  ó   d S ©N© ©Úselfr
   r   r   r   r   ú=/home/esfera/Documents/content_generation/src/services/llm.pyÚcomplete   ó    zLLMService.completer   c                 C  r   r   r   r   r   r   r   Úcomplete_json   r   zLLMService.complete_jsonN©r	   ©r
   r   r   r   r   r   r   r   ©r
   r   r   r   r   r   r   r   )Ú__name__Ú
__module__Ú__qualname__r   r   r   r   r   r   r   
   s    r   Útextr   r   r   c              	   C  sÂ   |   ¡ } t d| ¡}|r| d¡  ¡ } zt | ¡W S  tjy`   |  d¡}|  d¡}|dkr@||kr@t | ||d … ¡ Y S |  d¡}|  d¡}|dkr_||kr_t | ||d … ¡ Y S ‚ w )Nz```(?:json)?\s*([\s\S]*?)```é   Ú{Ú}r   ú[ú])	ÚstripÚreÚsearchÚgroupÚjsonÚloadsÚJSONDecodeErrorÚfindÚrfind)r   ÚfenceÚstartÚendr   r   r   Úparse_json_loose   s"   



÷r1   c                   @  óL   e Zd ZdZddd„Zeedƒedd	d
�dd�dddd„ƒZdddd„Z	dS )Ú	ClaudeLLMu7   Anthropic Claude â€” used for ideation + platform copy.Úapi_keyr   Úmodelc                 C  s    dd l }|j|d�| _|| _d S )Nr   ©r4   )Ú	anthropicÚ	AnthropicÚclientr5   )r   r4   r5   r7   r   r   r   Ú__init__&   s   
zClaudeLLM.__init__é   é   é   ©ÚminÚmaxT©ÚstopÚwaitÚreraiser	   r
   r   r   r   r   c                 C  s>   | j jj| j||d|dœgd�}dd„ |jD ƒ}d |¡ ¡ S )Nr   ©ÚroleÚcontent)r5   r   r
   Úmessagesc                 S  s"   g | ]}t |d dƒdkr|j‘qS )ÚtypeNr   )Úgetattrr   )Ú.0Úbr   r   r   Ú
<listcomp>4   s   " z&ClaudeLLM.complete.<locals>.<listcomp>Ú
)r9   rH   Úcreater5   rG   Újoinr%   )r   r
   r   r   ÚmsgÚpartsr   r   r   r   ,   s   
üzClaudeLLM.completer   c                 C  s   | j |d ||d�}t|ƒS )Nú3

Respond with valid JSON only. No markdown fences.©r
   r   r   )r   r1   )r   r
   r   r   Úrawr   r   r   r   7   s   ýzClaudeLLM.complete_jsonN©r4   r   r5   r   r   r   r   ©
r   r   r   Ú__doc__r:   r   r   r   r   r   r   r   r   r   r3   #   s    

r3   c                   @  r2   )Ú	OpenAILLMu;   OpenAI Chat Completions â€” optional fallback for ideation.r4   r   r5   c                 C  s"   ddl m} ||d�| _|| _d S )Nr   )ÚOpenAIr6   )ÚopenairZ   r9   r5   )r   r4   r5   rZ   r   r   r   r:   C   s   
zOpenAILLM.__init__r;   r<   r=   r>   TrA   r	   r
   r   r   r   r   c                 C  s>   | j jjj| j|d|dœd|dœgd�}|jd jjpd ¡ S )Nr
   rE   r   )r5   r   rH   r   Ú )	r9   ÚchatÚcompletionsrO   r5   ÚchoicesÚmessagerG   r%   )r   r
   r   r   Úresponser   r   r   r   I   s   
þýzOpenAILLM.completer   c                 C  s‚   z)| j jjj| j|ddid|d dœd|dœgd�}|jd jjp"d	 ¡ }t	|ƒW S  t
y@   | j|d
 ||d�}t	|ƒ Y S w )NrI   Újson_objectr
   z

Respond with valid JSON only.rE   r   )r5   r   Úresponse_formatrH   r   r\   rS   rT   )r9   r]   r^   rO   r5   r_   r`   rG   r%   r1   Ú	Exceptionr   )r   r
   r   r   ra   rU   r   r   r   r   U   s&   
þü	
ýúzOpenAILLM.complete_jsonNrV   r   r   r   rW   r   r   r   r   rY   @   s    
rY   ÚproviderÚanthropic_keyÚclaude_modelÚ
openai_keyÚopenai_modelc                 C  s\   | pd  ¡  ¡ } | dkr|stdƒ‚t||ƒS | dkr&|s!tdƒ‚t||ƒS td| › d�ƒ‚)Nr[   z1LLM_PROVIDER=openai but OPENAI_API_KEY is missingÚclaudez4LLM_PROVIDER=claude but ANTHROPIC_API_KEY is missingzUnknown LLM_PROVIDER: z (use claude or openai))r%   ÚlowerÚRuntimeErrorrY   r3   )re   rf   rg   rh   ri   r   r   r   Ú
create_llmk   s   

rm   )r   r   r   r   )
re   r   rf   r   rg   r   rh   r   ri   r   )Ú
__future__r   r)   r&   Útypingr   r   Útenacityr   r   r   r   r1   r3   rY   rm   r   r   r   r   Ú<module>   s    
+