o
    .i`                     @   s
  d dl mZmZ d dlmZ d dlmZ d dlmZm	Z	 d dl
mZmZmZmZ d dlmZ d dlZd dlZd dlZd dlmZ d d	lmZ d dlZe  d d
lmZ d dlmZ d dlmZ d dlmZ d dl m!Z! d dl"m#Z# eddddZ$e$j%edgddgdgd e Z&e Z'ee&e'Z(ee&e'Z)e!e&e'Z*G dd deZ+G dd deZ,G dd deZ-G dd deZ.G dd  d eZ/G d!d" d"eZ0G d#d$ d$eZ1G d%d& d&eZ2G d'd( d(eZ3G d)d* d*eZ4G d+d, d,eZ5G d-d. d.eZ6G d/d0 d0eZ7G d1d2 d2eZ8G d3d4 d4eZ9e$:d5d6d7 Z;e$:d8d9d: Z<e$j=d;e0d<d=e/fd>d?Z>e$j=d@e5d<d=e7fdAdBZ?e$j=dCe6d<d=e/fdDdEZ@e$j=dFe9d<d=e8fdGdHZAdud=e/dIeBdJee# fdKdLZCdMeDdNeDdJeDfdOdPZEdQeDdReFdJee# fdSdTZGdUe#dJeeeDeDf  fdVdWZHdIeBdJe.fdXdYZIdZe#dJeDfd[d\ZJd]eDd^eDd_eeD dJeeD fd`daZKdMeDd]eDd^eDdNeDdbeDdJeDfdcddZLdeeDdJeeD fdfdgZMdhejdJejfdidjZNdhejdkeFdleFdJejfdmdnZOdeeDdJeeD fdodpZPdvdeeDdreDdJeeD fdsdtZQdS )w    )FastAPIHTTPException)CORSMiddleware)JSONResponse)	BaseModelField)ListDictAnyOptional)datetimeN)load_dotenv)Image)ScenarioGenerator)RoleplayEngine)GroqService)OllamaService)SkillAnalyzer)RoleplayScenarioAI Roleplay Servicez:AI service for roleplay scenario preview and conversationsz2.0.0)titledescriptionversion*T)allow_originsallow_credentialsallow_methodsallow_headersc                   @   s   e Zd ZU eed< eed< dS )	SkillDataskill_id
skill_nameN__name__
__module____qualname__str__annotations__ r'   r'   @/var/www/eduai.edurigo.com/roleplay/staging/roleplay_fast_api.pyr   3      
 r   c                   @   sv   e Zd ZU eed< eed< edddZeed< eed< edd	dZeed
< ee	 ed< dZ
eed< eed< eed< dS )RoleplayDatacategory	objective.zLearner role)aliaslearner_roleadditional_info Constraints/Policiescompany_policiesskills_for_roleplayEasydifficulty_levelisAdmingroqRoleplayN)r"   r#   r$   r%   r&   r   r.   r2   r   r   r5   intr'   r'   r'   r(   r*   7   s   
 r*   c                   @   &   e Zd ZU eed< eed< eed< dS )
TokenCountinputoutputtotalN)r"   r#   r$   r8   r&   r'   r'   r'   r(   r:   B      
 r:   c                   @   s.   e Zd ZU eed< eed< eed< eed< dS )TokenCountspreviewconversation
assessmentservice_usedN)r"   r#   r$   r:   r&   r%   r'   r'   r'   r(   r?   G   
   
 r?   c                   @   s.   e Zd ZU eed< eed< eed< eed< dS )RoleplayRequest	client_id
session_idroleplay_dataqueryNr"   r#   r$   r%   r&   r*   r'   r'   r'   r(   rE   M   rD   rE   c                   @   s&   e Zd ZU eed< eed< eed< dS )RoleplayResponserG   responsetoken_countsN)r"   r#   r$   r%   r&   r?   r'   r'   r'   r(   rK   S   r>   rK   c                   @   s6   e Zd ZU eed< eed< eed< eed< eed< dS )CharacterDetailsnamepersonalitygoals
backgroundemotional_stateNr!   r'   r'   r'   r(   rN   X   s   
 rN   c                   @   r9   )ScenarioSetupcontextenvironmentconstraintsNr!   r'   r'   r'   r(   rT   _   r>   rT   c                   @   s   e Zd ZU eed< eed< eed< eed< eed< ee ed< eed< eed< eed	< eed
< eeef ed< eed< eed< dS )PreviewResponsescenario_idr+   r,   r.   ai_roleskills_to_assessscenario_setupcharacter_detailsscenario_introconversation_startersuccess_criteriar5   background_infoN)	r"   r#   r$   r%   r&   r   rT   rN   r	   r'   r'   r'   r(   rX   d   s   
 rX   c                   @   s2   e Zd ZU eed< eed< dZeee  ed< dS )SlideheadingcontentNrQ   )r"   r#   r$   r%   r&   rQ   r   r   r'   r'   r'   r(   rb   s   s   
 rb   c                   @   s:   e Zd ZU ee ed< eed< eed< dZe	e ed< dS )ScenarioPreviewResponseslidesscenariorM   Nroleplay_image_base64)
r"   r#   r$   r   rb   r&   r%   r?   rh   r   r'   r'   r'   r(   re   x   s
   
 re   c                   @   s>   e Zd ZU eed< eed< dZeeeef  ed< e	ed< dS )EndSessionResponsemessagerG   NrB   rM   )
r"   r#   r$   r%   r&   rB   r   r	   r
   r?   r'   r'   r'   r(   ri      s
   
 ri   c                   @      e Zd ZU eed< eed< dS )EndSessionRequestrG   rH   NrJ   r'   r'   r'   r(   rl      r)   rl   c                   @   rk   )CleanupRequestrG   is_adminN)r"   r#   r$   r%   r&   r8   r'   r'   r'   r(   rm      r)   rm   c                   @   s.   e Zd ZU eed< eed< eeef ed< dS )CleanupResponserj   rG   cleanup_statusN)r"   r#   r$   r%   r&   r	   boolr'   r'   r'   r(   ro      s   
 ro   /c                      s   dddS )Nr   running)rj   statusr'   r'   r'   r'   r(   root   s   
ru   z/healthc               
      s   z5dt   i} td}|rddinddd| d< t }d|r%dnd	i| d
< |s.|r0dnd| d< | W S  tyM } ztddt	| dd }~ww )N	timestampGROQ_API_KEYrt   healthyerrorzGROQ_API_KEY not configured)rt   rj   groqunavailableollamaoverall  zHealth check failed: status_codedetail)
r   now	isoformatosgetenvollama_servicehealth_check	Exceptionr   r%   )health_statusapi_keyollama_availableer'   r'   r(   r      s   
r   z	/roleplay)response_modelrequestc           	   
      sB  zy| j }| jjdk}t|| jj}|s8t| |}|s!tdddtj|| jjdd t	|}t
||j|dW S t|| jj}|d u r[tj|| jjdd t	|}t
||j|dW S t||| j| jj|}|sotdddt	|}t
|||dW S  ty     ty } zd	d l}|  tdd
t| dd }~ww )N   r~   zFailed to create scenarior   T)force_restart)rG   rL   rM   zFailed to generate AI responser   zInternal error: )rG   rH   r7   load_scenario_for_sessionr6   create_scenario_from_requestr   roleplay_enginestart_sessionget_token_counts_responserK   r_   get_conversation_historyadd_learner_responserI   r   	traceback	print_excr%   )	r   rG   use_groqrg   rM   conversation_historyai_responser   r   r'   r'   r(   handle_roleplay   s>   
r   z/roleplay_scenarioc              
      s\  z| j jdk}t| j| j j}|pt| |}|stdddt|}t|j	|j
|jp,g d}t|}dd |D }|tdd	|d
 t|}d }	zt| j j| j j	| j j
| j j| j jd}
t|
}	W n ty~ } zd }	td|  W Y d }~nd }~ww t||||	dW S  ty     ty } zdd l}|  tddt| dd }~ww )Nr   r~   z%Failed to create scenario for previewr   )r.   r,   skillsc                 S   s    g | ]}t |d  |d dqS )rc   rd   rc   rd   )rb   .0sr'   r'   r(   
<listcomp>   s     z1get_roleplay_scenario_preview.<locals>.<listcomp>Goalsz,Focus on these outcomes during the roleplay.)rc   rd   rQ   )r+   r.   r,   r/   r2   z8WARNING: Pollinations ultra HD image generation failed: )rf   rg   rM   rh   r   zError generating preview: )rH   r7   r   rG   r6   r   r    build_professional_scenario_textbuild_short_goalsr.   r,   r[   format_scenario_as_slidesappendrb   r   "build_pollinations_ultra_hd_promptr+   r/   r2   %pollinations_generate_ultra_hd_base64r   printre   r   r   r%   )r   r   existing_scenariorg   scenario_text
goals_listbase_slidesslides_as_modelsrM   roleplay_image_b64poll_promptr   r   r'   r'   r(   get_roleplay_scenario_preview   s^   r   z/end_sessionc              
      s8  z|| j jdk}t| j| j j}|stdddt| j| j j}|s)tdddt| j| j j}|s:tdddt	
| j||| j j|}t|}|rNtnt}|  |rgtj| j| j j}td|  d	| j|d
}	|rv| |	d< tdi |	W S  ty     ty }
 ztddt|
 dd }
~
ww )Nr   i  zSession/Scenario not foundr   zNo conversation history foundr~   zFailed to end sessionzDEBUG: Conversation deleted: zSession ended successfully)rj   rG   rM   rB   zError ending session: r'   )rH   r7   r   rG   r6   r   r   %get_conversation_turns_for_assessmentend_sessionskill_analyzeranalyze_sessionr   groq_servicer   reset_token_countsjson_handlerdelete_conversationr   to_dictri   r   r%   )r   r   rg   conversation_turnssuccessrB   final_token_counts
ai_serviceconversation_deletedresponse_datar   r'   r'   r(   r     sL   

r   z/cleanupc              
      sF  zdddd}zt j| j| j}||d< W n ty0 } ztd|  W Y d }~nd }~ww ztj| j| j}||d< W n tyY } ztd|  W Y d }~nd }~ww zt	j
| j| j}||d< W n ty } ztd|  W Y d }~nd }~ww td	| j|d
W S  ty } ztddt| dd }~ww )NF)scenario_deletedassessment_deletedr   r   zError deleting scenario: r   zError deleting assessment: r   zError deleting conversation: z$Session data cleaned up successfully)rj   rG   rp   r~   z Error cleaning up session data: r   )scenario_generatorr   delete_scenariorG   rn   r   r   r   delete_assessmentr   r   ro   r   r%   )r   rp   r   r   r   r   r'   r'   r(   cleanup_session_data2  s:   r   r   returnc                 C   s   z2| j }dd |jD }|j|jd|jd}t|j|j}tj| j	|j|j
|||j||j|d	}|W S  tyL } ztd|  W Y d }~d S d }~ww )Nc                 S   s   g | ]}|j qS r'   )r    r   r'   r'   r(   r   N  s    z0create_scenario_from_request.<locals>.<listcomp>zRoleplay conversation)rR   rW   rV   r5   )	rG   r+   r,   detailsrZ   r.   r[   rn   r   zError creating scenario: )rH   r3   r/   r2   r5   generate_ai_roler+   r   create_scenariorG   r,   r.   r6   r   r   )r   r   rH   r[   r   rZ   rg   r   r'   r'   r(   r   K  s4   r   r+   r/   c                 C   sr   dddddd}| |  d}| }d|v rd	| S d
|v s%d|v r*d| S d|v s2d|v r7d| S |S )NzPotential CustomerzCustomer with IssuezTeam MemberzNegotiation PartnerzUser with Technical Problem)saleszcustomer service
leadershipnegotiationztechnical supportzConversation Partner
enterprisezEnterprise budgetpricezBudget-Conscious 
frustrated	complaintzFrustrated )getlower)r+   r/   category_roles	base_rolelowr'   r'   r(   r   f  s   


r   rG   rn   c              
   C   sJ   zt | |W S  ty$ } ztd|  d|  W Y d }~d S d }~ww )Nz#Error loading scenario for session z: )r   load_scenarior   r   )rG   rn   r   r'   r'   r(   r   x  s   r   rg   c              
   C   s   z3g }| j dp
d }|r|d|d | j dpd }|r1| dvr1|d|d |W S  tyW } ztd|  dd	| j d
dgW  Y d }~S d }~ww )NrU   r0   Contextr   rW   )r0   znot specifiednoner1   z%Error formatting scenario as slides: z
This is a z7 roleplay scenario where you will practice your skills.)r\   r   stripr   r   r   r   r+   )rg   rf   rU   rW   r   r'   r'   r(   r     s   "r   c                 C   sZ   | rt nt}| }ttdi |d tdi |d tdi |d | r)ddS ddS )Nr@   rA   rB   rz   r|   )r@   rA   rB   rC   r'   )r   r   get_token_countsr?   r:   )r   r   tdr'   r'   r(   r     s   r   scnc              	   C   s   | j }| j}| j}| j}| jdpd}d|  d| d|  d|  d	g}|rTd|v r;| dd d nt	|d	krK| d d	 d
 n| }|
| d|S )NrU   r0   zIn this z roleplay, you act as a z collaborating with an z to achieve the objective: .r   d   z... )r+   r.   rZ   r,   r\   r   r   r   splitlenr   join)r   r+   learnerrZ   r,   rU   partsshort_contextr'   r'   r(   r     s   (F

r   r.   r,   r   c                 C   s   g d}| d | d d |  }g }d|v r|d d|v s&d|v r+|d d|v s3d	|v r8|d
 d|v s@d|v rE|d |d d D ]}t|dk rX|| qK|d d S )N)z-Clarify the user's intent and missing detailsz@Structure effective prompts with clear instructions and examplesz4Validate responses for accuracy, tone, and relevancez4Iterate based on feedback to improve the next outputr   promptz8Apply prompt patterns (role, task, context, constraints)customersupportz.Use empathetic, concise language for end users	technicalengineeringz,Ground outputs in accurate, testable detailsr   r   z)Surface value, objections, and next steps      )r   r   r   r   )r.   r,   r   basetextcustomcr'   r'   r(   r     s    




r   r2   c                 C   s^   d|  d| ddddddd	g}|r&t | d
kr&|| dd  d|dd S )z
    Build a concise, focused ultra HD prompt for Pollinations.
    Shorter, more focused prompts often yield better results.
    zprofessional z scenez in modern office environmentphotorealisticz8K ultra HDzsharp focuszprofessional lightingzcinematic compositionzhigh detail
   Nr   z,    )r   r   r   r   )r+   r.   r,   r/   r2   scene_partsr'   r'   r(   r     s   
r   r   c              
   C   s  ddl m} ddlm}m}m} d}d}d}d}|j| dd	}	d
|	 d| d| dtt| d  }
ddddd}zt	d| d| d t
j|
|ddd}|jdkr_t	d|j  W dS |j}|rjt|dk rqt	d W dS |t|}|d}|j\}}t	d| d| d t| d! t|}t|||}||jd"dd#d$}t }|j|d%d&dddd' t| d(}t| }t	d)| d| d*| d! |W S  t
jy   t	d+ Y dS  ty
 } zt	d,t|  ddl }|!  W Y d}~dS d}~ww )-z
    Enhanced version with multiple strategies for HD image generation.
    Uses higher base resolution and better upscaling techniques.
    r   N)r   ImageEnhanceImageFilter  8  i 
  i  r0   safe%https://image.pollinations.ai/prompt/z?width=z&height=z7?nologo=true&private=true&enhance=true&model=flux&seed=i@B z7image/jpeg,image/png,image/webp,image/*;q=0.9,*/*;q=0.8z<Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36zgzip, deflate, brzno-cache)Acceptz
User-AgentzAccept-EncodingzCache-Controlz-INFO: Requesting HD image from Pollinations (xz)...x   T)headerstimeoutstream   z$ERROR: Pollinations returned status   z(ERROR: Received invalid/empty image dataRGBzINFO: Received image: z (z bytes)r      )radiuspercent	thresholdJPEGb   )formatqualityoptimizeprogressivesubsamplingutf-8zSUCCESS: Generated z HD image (z#ERROR: Timeout while fetching imagez ERROR: Image generation failed: )"urllib.parseparsePILr   r   r   quoteabshashr   requestsr   r   rd   r   openioBytesIOconvertsizeenhance_image_qualityresize_and_crop_hqfilterUnsharpMasksavebase64	b64encodegetvaluedecodeTimeoutr   r%   r   r   )r   upr   r   r   TARGET_WIDTHTARGET_HEIGHTREQUEST_WIDTHREQUEST_HEIGHTencoded_prompturlr  resprd   imgorig_worig_h	img_finaloutput_bytes
b64_result
final_sizer   r   r'   r'   r(   r     sx   


 	r   r3  c                 C   s@   t | }|d} t | }|d} t | }|d} | S )z2
    Apply quality enhancements to the image.
    g?gffffff?g?)r   Contrastenhance	SharpnessColor)r3  enhancerr'   r'   r(   r!  8  s   





r!  target_wtarget_hc                 C   s   | j \}}|| }|| }||kr|}t|||  }n
|}t|||  }| j||ftjd}	|| d }
|| d }|
| }|| }|	|
|||f}|S )zi
    High-quality resize and crop to exact dimensions.
    Uses Lanczos resampling for best quality.
    )resampler   )r   r8   resizer   LANCZOScrop)r3  r?  r@  r4  r5  target_ratio
orig_rationew_hnew_wimg_resizedlefttoprightbottomimg_croppedr'   r'   r(   r"  K  s   
r"  c                 C   s0   t | }|r|S td t| dd}|r|S dS )zC
    Try multiple strategies/services for HD image generation.
    z9INFO: Pollinations failed, trying alternative approach...turbo)modelN)r   r   try_alternative_pollinations)r   resultr'   r'   r(   generate_hd_image_with_fallbackm  s   rS  rO  rP  c           	   
   C   s   ddl m} |j| dd}d| d| d}zItj|dd	}|jd
krZt|jdkr]t	t
|j}|d}t|}t|dd}t
 }|j|dddd t| dW S W dS W dS  tyy } ztd|  W Y d}~dS d}~ww )z;
    Try Pollinations with alternative model settings.
    r   Nr0   r   r   z?width=1920&height=1080&model=z&enhance=true&nologo=truer  )r  r  r  r  r   r   r  r  T)r  r  r  r  zAlternative strategy failed: )r  r  r  r  r   r   r   rd   r   r  r  r  r  r!  r"  r%  r&  r'  r(  r)  r   r   )	r   rP  r+  r0  r1  r2  r3  r<   r   r'   r'   r(   rQ    s2   	
rQ  )T)rO  )Rfastapir   r   fastapi.middleware.corsr   fastapi.responsesr   pydanticr   r   typingr   r	   r
   r   r   r   r&  r  dotenvr   r  r   r  services.scenario_generatorr   services.roleplay_enginer   services.groq_servicer   services.ollama_servicer   services.skill_analyzerr   models.scenarior   appadd_middlewarer   r   r   r   r   r   r*   r:   r?   rE   rK   rN   rT   rX   rb   re   ri   rl   rm   ro   r   ru   r   postr   r   r   r   rq   r   r%   r   r8   r   r   r   r   r   r   r   r!  r"  rS  rQ  r'   r'   r'   r(   <module>   s   	




$40
"
\" 