o
    5&h:                     @   sR   d dl Z d dlZd dlmZmZmZmZ d dlmZm	Z	m
Z
mZ G dd dZdS )    N)DictListAnyOptional)SCENARIO_GENERATION_PROMPTCHARACTER_ROLEPLAY_PROMPTSKILL_ANALYSIS_PROMPTget_skill_analysis_templatec                   @   sP  e Zd Zd*defddZdedefddZd	ed
eeef fddZ	deeef fddZ
dd Zd+dededededeee eeeef  f f
ddZdeeef deeeef  fddZdeeef deeeef  dedee fd d!Zdeeef d"eeeef  deeeef  fd#d$Zdedee fd%d&Zdefd'd(Zd)S ),OllamaServicehttp://127.0.0.1:11434base_urlc                 C   s6   || _ d| _ddddddddddddd| _d S )Nz
gemma3:12br   inputoutputtotal)previewconversation
assessment)r   modeltoken_counts)selfr    r   X/var/www/eduai.edurigo.com/doc_train/edurigo_ai/roleplay/prod/services/ollama_service.py__init__   s   


zOllamaService.__init__textreturnc                 C   s   t dt|d S )uM   Estimate token count for text (rough approximation: 1 token ≈ 4 characters)      )maxlen)r   r   r   r   r   _estimate_tokens   s   zOllamaService._estimate_tokensoperation_typeusage_statsc              	   C   s   |rQ| dd}| dd}| d|| }|dkr|| }| j| d  |7  < | j| d  |7  < | j| d  |7  < td	| d
| d| d|  dS td| d dS )zDUpdate token counts for specific operation using actual Ollama statsprompt_eval_countr   
eval_counttotal_durationi r   r   r   zOLLAMA Token count for z: Input=z	, Output=z, Total=z%OLLAMA: No usage stats available for z, skipping token countN)getr   print)r   r!   r"   input_tokensoutput_tokenstotal_tokensr   r   r   _update_token_count   s   $z!OllamaService._update_token_countc                 C   s
   | j  S )z+Get current token counts for all operations)r   copy)r   r   r   r   get_token_counts.   s   
zOllamaService.get_token_countsc                 C   s"   | j D ]}dddd| j |< qdS )zReset all token countersr   r   N)r   )r   	operationr   r   r   reset_token_counts2   s   
z OllamaService.reset_token_counts ffffff?   promptsystem_prompttemperature
max_tokensc              
   C   s  z| j  d}td|  td| j  |}|r"d| d| }| j|d||dd}td	|d
   tj||dd}td|j  |jdkrWtd| j d W dS |  | }	|	dd	 }
|	dd|	dd|	dd|	dd|	ddd}tdt
|
  td|  |
|fW S  tjjy } ztd|  td| j   W Y d}~dS d}~w tjjy } z!td |  t|dr|jdurtd!|jj  W Y d}~dS d}~w ty } ztd"|  W Y d}~dS d}~ww )#zEMake a request to Ollama API and return response text and usage statsz/api/generatez!DEBUG: Making Ollama request to: zDEBUG: Using model: zSystem: z

User: F)r5   num_predict)r   r3   streamoptionszDEBUG: Payload model: r   x   )jsontimeoutzDEBUG: Response status: i  zERROR: 404 - Model 'z>' not found. Available models can be checked with: ollama list)NNresponser0   r#   r   r$   r%   prompt_eval_durationeval_duration)r#   r$   r%   r>   r?   zDEBUG: Ollama response length: zDEBUG: Ollama usage stats: z#Error connecting to Ollama server: zMake sure Ollama is running on NzError making Ollama request: zResponse content: z$Unexpected error in Ollama request: )r   r'   r   requestspoststatus_coderaise_for_statusr;   r&   stripr   
exceptionsConnectionErrorRequestExceptionhasattrr=   r   	Exception)r   r3   r4   r5   r6   urlfull_promptpayloadr=   resultresponse_textr"   er   r   r   _make_request7   s`   







zOllamaService._make_requestadmin_inputc              
   C   s,  z{t j|d |d |d d|d d}d}| j||dd	d
\}}|s'W dS | d| z+|dr:|dd }n|drE|dd }|drP|dd }t|	 W W S  tj
y{ } ztd|  td|  W Y d}~W dS d}~ww  ty } ztd|  W Y d}~dS d}~ww )z-Generate structured scenario from admin inputcategory	objectivedetails, skills_to_assess)rR   rS   rT   skillszHYou are a training scenario expert. Always respond with valid JSON only.r1   r2   r3   r4   r5   r6   Nr   ```json   ```   zJSON parsing error: Response text: z'Error generating scenario with Ollama: )r   formatjoinrP   r+   
startswithendswithr;   loadsrD   JSONDecodeErrorr'   rI   )r   rQ   r3   r4   rN   r"   rO   r   r   r   generate_scenarior   sH   



zOllamaService.generate_scenarioscenarioconversation_historyuser_messagec                 C   s  zod}|D ]}|d dkrdn|d d }|| d|d  d	7 }qt j|d d |d d
 |d d |d d |d dd|d d |d d |d d ||d
}d}| j||ddd\}	}
|	rh| d|
 |	rm|	W S dW S  ty } ztd|  W Y d}~dS d}~ww )z&AI character responses during roleplayr0   speakerlearnerLearnerai_charactername: message
personalitygoals
backgroundemotional_stateneutralscenario_setupcontextenvironmentconstraints)
character_namerq   rr   rs   rt   rw   rx   ry   rg   rh   zbYou are a roleplay character. Stay in character at all times. Respond naturally and realistically.g?i   rX   r   z:I'm having trouble responding right now. Please try again.z)Error in character roleplay with Ollama: N)r   r_   r&   rP   r+   rI   r'   )r   rf   rg   rh   history_textturnri   r3   r4   r=   r"   rO   r   r   r   play_character   s@   







zOllamaService.play_characterconversation_turnsc                    sL  z	d}|D ]}|d dkrdnd}|| d|d  d7 }qd	|d
  d|d  d|d d  d|d  d|d d  d|d d  d}|d }t |}tjd||||d}	d}
| j|	|
ddd\}}|slW dS | d| zB|d r|d!d }n|d"r|d#d }|d"r|dd$ }| }t	
| t fd%d&d'D std( W W dS  W W S  t	jy
 } zHtd)|  td*|  d+dl}|d,||j}|rzt	
|  td-  W W  Y d}~W S  t	jy   td. Y nw W Y d}~W dS d}~ww  ty% } ztd/|  W Y d}~dS d}~ww )0zComprehensive skill analysisr0   ri   rj   rk   zAI Characterrn   ro   rp   z
Category: rR   z
Objective: rS   z

Context: rv   rw   z
Success Criteria: success_criteriaz
AI Character: rl   rm   z - rs   rV   rU   )rW   scenario_contextr   skill_analysis_templatez`You are an expert skill assessor. Provide detailed, accurate analysis in valid JSON format only.g333333?i  rX   Nr   rY   rZ   r[   r\   r]   c                 3   s    | ]}| v V  qd S )Nr   ).0keyanalysisr   r   	<genexpr>  s    z/OllamaService.analyze_skills.<locals>.<genexpr>)skill_analysisoverall_performanceconversation_analysisrecommendationszAnalysis missing required keysz JSON parsing error in analysis: r^   r   z\{.*\}z0Successfully extracted JSON using regex fallbackzRegex fallback also failedz$Error analyzing skills with Ollama: )r	   r   r_   r`   rP   r+   ra   rb   rD   r;   rc   allr'   rd   researchDOTALLgrouprI   )r   rf   r~   conversation_textr|   ri   r   rW   skill_templater3   r4   rN   r"   rO   r   
json_matchr   r   r   analyze_skills   s   







zOllamaService.analyze_skillsc              
   C   sf   zd}| j ||ddd\}}|r| d| |W S  ty2 } ztd|  W Y d}~dS d}~ww )z(Get a simple text completion from Ollamaz]You are a helpful assistant. Provide clear, natural responses without any formatting symbols.r1   i  rX   r   z&Error getting completion from Ollama: N)rP   r+   rI   r'   )r   r3   r4   r=   r"   rO   r   r   r   get_completion  s    
zOllamaService.get_completionc              
   C   s   zU| j  d}td|  tj|dd}td|j  |jdkrS| dg }dd	 |D }td
|  | j|vrPtd| j d td|  W dS W dS W dS  tyo } ztd|  W Y d}~dS d}~ww )z$Check if Ollama service is availablez	/api/tagsz"DEBUG: Checking Ollama health at:    )r<   z%DEBUG: Health check response status:    modelsc                 S   s   g | ]}| d dqS )rm   r0   )r&   )r   r   r   r   r   
<listcomp>=  s    z.OllamaService.health_check.<locals>.<listcomp>zDEBUG: Available models: zWARNING: Model 'z' not found in available modelszAvailable models: FTzDEBUG: Health check failed: N)r   r'   r@   r&   rB   r;   r   rI   )r   rJ   r=   r   model_namesrO   r   r   r   health_check2  s(   

zOllamaService.health_checkN)r   )r0   r1   r2   )__name__
__module____qualname__strr   intr    r   r   r+   r-   r/   floattupler   rP   re   r   r}   r   r   boolr   r   r   r   r   r
      s    8&;2-6)Tr
   )r;   r@   typingr   r   r   r   config.promptsr   r   r   r	   r
   r   r   r   r   <module>   s
    