o
    Gnh$M                     @   s   d dl Z d dlZd dl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 d dlZd dlmZ d dlmZ d dlZeeZeG dd dZG d	d
 d
ZdS )    N)ListDictAnyOptional)	dataclass)quote)SequenceMatcher)Ollamac                   @   s~   e Zd ZU eed< eed< eed< dZee ed< dZee ed< dZ	ee ed< dZ
ee ed< d	Zeed
< dZeed< dS )OnlineCoursetitleplatformurlN
instructorratingpriceduration        relevance_score reason)__name__
__module____qualname__str__annotations__r   r   r   floatr   r   r   r    r   r   W/var/www/eduai.edurigo.com/doc_train/edurigo_ai/TNA/testing/tna_fetch_online_courses.pyr
      s   
 r
   c                   @   s  e Zd ZdZdd Zdedee dee dee	eef  dee	eef  f
d	d
Z
dedee dee dee fddZdedefddZdedee fddZdedee fddZdedee fddZdefddZdee dee fddZdee dedee dee	eef  dee dee fddZdedededed edefd!d"Zdeded#ee dee d$ee defd%d&Zdee dee fd'd(Zd)S )*OnlineCourseFetcherzI
    Advanced online course fetcher for YouTube, Udemy, and Coursera
    c                 C   s   t dd| _dddd| _d S )Nz
gemma3:12b)model333333?g?youtubeudemycoursera)r	   llmplatform_weightsselfr   r   r   __init__!   s
   zOnlineCourseFetcher.__init__
user_queryfiltered_skillsdepartment_nameoffline_coursesreturnc                    s  zt d|  | |||I dH }g }g }|D ]}|| | || | || | qtj|ddiI dH }	|	D ]}
t	|
t
rO||
 qBt	|
tr^t dt|
  qB| |}| |||||I dH }|jdd dd | |dd	 }g }|dd
 D ]}||j|j|j|j|j|j|jt|jd|jd	 qt dt| d |W S  ty } zt dt|  g W  Y d}~S d}~ww )z^
        Fetch online courses from multiple platforms with advanced relevance scoring
        z)Starting online course search for query: Nreturn_exceptionsTzError fetching courses: c                 S   s   | j S N)r   )xr   r   r   <lambda>P   s    z:OnlineCourseFetcher.fetch_online_courses.<locals>.<lambda>)keyreverse   
      )	r   r   r   r   r   r   r   r   r   z
Returning z online courseszError in fetch_online_courses: )loggerinfo_generate_search_queriesappend_fetch_youtube_courses_fetch_udemy_courses_fetch_coursera_coursesasynciogather
isinstancelistextend	Exceptionerrorr   _remove_duplicates_score_courses_advancedsort_apply_platform_diversityr   r   r   r   r   r   r   roundr   r   len)r(   r*   r+   r,   r-   search_queriesall_coursestasksqueryresultsresultunique_coursesscored_coursesfinal_coursesresult_coursescourseer   r   r   fetch_online_courses)   sR   




z(OnlineCourseFetcher.fetch_online_coursesc           
   
      s  zb|rd dd |D nd}d| d|pd d| d	}t jj|I d
H }dd |dD }|sK|d
d |r>|nd|rH|dd ndg}|| tt fdd|D }|d
d W S  t	y }	 zt
dt|	  ||pyddgW  Y d
}	~	S d
}	~	ww )z=
        Generate optimized search queries using LLM
        , c                 S   s   g | ]}|j qS r   )
skill_name).0skillr   r   r   
<listcomp>p   s    z@OnlineCourseFetcher._generate_search_queries.<locals>.<listcomp>r   zt
            You are an expert at creating search queries for online courses. 
            
            User Goal: ""
            Department: Generalz
            Related Skills: a  
            
            Generate 3-4 concise search queries (2-4 words each) that would find the most relevant online courses.
            Focus on:
            1. Core concepts from the user goal
            2. Professional/technical terms
            3. Industry-specific keywords
            4. Skill-based searches
            
            Return only the search queries, one per line, no explanations.
            Nc                 S   s   g | ]
}|  r|  qS r   )stripr[   qr   r   r   r]      s    
2   zprofessional development,r   trainingc                    s   g | ]	}|r  |qS r   )_clean_queryra   r'   r   r   r]      s    r7   z!Error generating search queries: )joinr?   	to_threadr%   invokesplitr;   rB   setrD   r8   rE   r   )
r(   r*   r+   r,   skills_textpromptresponsequeriesclean_queriesrW   r   r'   r   r:   k   s2   


z,OnlineCourseFetcher._generate_search_queriesrO   c                 C   sJ   t dd|}t dd| }| }t|dkr#d|dd }|S )zClean and optimize search queryz[^\w\s] z\s+r7   N)resubr`   rk   rK   rh   )r(   rO   wordsr   r   r   rg      s   z OnlineCourseFetcher._clean_queryc                    s   z<t | ddd|   dddddt d	| d
dd|   dddddt | ddd|   dddddg}|W S  ty[ } ztdt|  g W  Y d}~S d}~ww )z?
        Fetch YouTube courses using search simulation
        z Complete TutorialYouTubezhttps://youtube.com/watch?v=zTech Expert      @Freez	2-4 hoursr   r   r   r   r   r   r   zLearn z from ScratchzProfessional Trainerg333333@z	3-5 hoursz MasterclasszIndustry Leader@z	1-2 hoursz Error fetching YouTube courses: N)r
   _generate_video_idrD   r8   rE   r   )r(   rO   youtube_coursesrW   r   r   r   r<      sH   	
	z*OnlineCourseFetcher._fetch_youtube_coursesc              
      s   z4t d| ddd| dd ddd	d
ddt | ddd| dd ddddddg}|W S  tyS } ztdt|  g W  Y d}~S d}~ww )z=
        Fetch Udemy courses using search simulation
        z	Complete z CourseUdemyzhttps://udemy.com/course/rr   -z	-completezCertified Instructorg@z$49.99z
8-12 hoursry   z for Beginners to Advancedz
-beginnerszExpert Trainergffffff@z$59.99z10-15 hourszError fetching Udemy courses: Nr
   lowerreplacerD   r8   rE   r   )r(   rO   udemy_coursesrW   r   r   r   r=      s6   
	z(OnlineCourseFetcher._fetch_udemy_coursesc              
      s   z1t | ddd| dd dddd	d
t d| dd| dd ddddd
g}|W S  tyP } ztdt|  g W  Y d}~S d}~ww )z@
        Fetch Coursera courses using search simulation
        z SpecializationCourseraz%https://coursera.org/specializations/rr   r~   zUniversity Professorrw   z	$39/monthz
3-6 monthsry   zProfessional Certificate in z/https://coursera.org/professional-certificates/zIndustry Partnerrz   z	$49/monthz
4-8 monthsz!Error fetching Coursera courses: Nr   )r(   rO   coursera_coursesrW   r   r   r   r>      s6   	z+OnlineCourseFetcher._fetch_coursera_coursesc                 C   s(   ddl }dtj|j|j d ddS )z"Generate a random YouTube video IDr   Nr   z_-   )k)stringrh   randomchoicesascii_lettersdigits)r(   r   r   r   r   r{     s    z&OnlineCourseFetcher._generate_video_idcoursesc                 C   sj   g }t  }|D ]+}d}|D ]}td|j |  dkr"d} nq|s2|| ||j  q|S )z2Remove duplicate courses based on title similarityFNg?T)rl   r   r   r   ratior;   add)r(   r   rR   seen_titlesrV   is_duplicate
seen_titler   r   r   rF     s   
z&OnlineCourseFetcher._remove_duplicatesc              
      s  zmt |  }t  }g }|r&|D ]}	||	j   ||	j qt  }
g }|D ]}|
|dd   ||dd q-|D ]#}| |||||
I dH }| |||||I dH }t	|d|_
||_qH|W S  ty } ztdt|  |W  Y d}~S d}~ww )z<
        Advanced scoring with AI-generated reasons
        namer   N      ?zError in advanced scoring: )rl   r   rk   updaterZ   r;   get_calculate_relevance_score_generate_course_reasonminr   r   rD   r8   rE   r   )r(   r   r*   r+   r-   r,   query_wordsskill_wordsskill_namesr\   offline_topicsoffline_namesrV   scorer   rW   r   r   r   rG   .  s:   



z+OnlineCourseFetcher._score_courses_advancedrV   r   r   r   c              
      s  zt  j  }d}t||}|r.|t| }	td|	 td }	||	d 7 }|rOt||}
|
t| }td| td }||d 7 }| j	 j
 d}||d 7 }d} jrm jdkrm|d7 } jr{t jd	kr{|d
7 } jrt fdddD r|d
7 }||d 7 }d}|rt||t| }d| }||d 7 }|W S  ty } ztdt|  W Y d}~dS d}~ww )zK
        Calculate advanced relevance score using multiple factors
        r         gffffff?r    g      ?g333333?g      @   g?c                 3   s    | ]
}| j  v V  qd S r0   )r   r   )r[   r1   rV   r   r   	<genexpr>}  s    zAOnlineCourseFetcher._calculate_relevance_score.<locals>.<genexpr>)hourmonthg?r   z#Error calculating relevance score: Ng      ?)rl   r   r   rk   rK   intersectionmathlogr&   r   r   r   r   r   anyrD   r8   rE   r   )r(   rV   r*   r   r   r   course_wordsr   query_overlapsemantic_scoreskill_overlapskill_scoreplatform_scorequality_scorediversity_scoreoverlap_ratiorW   r   r   r   r   [  sF   z.OnlineCourseFetcher._calculate_relevance_scorer   r   c                    s:  zu|rd |dd nd}|rd |dd nd}d| d|p#d	 d
| d|j d|j d| d}t| jj|I dH }	|	 }
t	dd|
}
|

 }t|dkr^d |dd }
|
rft|
dk rtd|dd  d|j d}
|
W S  ty } ztdt|  d|dd  dW  Y d}~S d}~ww )zF
        Generate AI-powered reason for course recommendation
        rY   N   zgeneral skillsr   zyour training planz
            You are an expert training advisor. Generate a concise, professional reason (max 25 words) why this online course is recommended.
            
            User Goal: "r^   r_   z
            Key Skills: z
            Course: z (z)
            Complements: a  
            
            Focus on:
            - Direct relevance to user goal
            - Skill development benefit
            - Platform advantage
            - How it complements offline training
            
            Return only the reason, no explanations.
            z
[^\w\s,.-]r      rr   r6   zHighly relevant to    z	... with z accessibilityz Error generating course reason: zRecommended for r5   z... skill development)rh   r   r   r?   ri   r%   rj   r`   rs   rt   rk   rK   rD   r8   rE   r   )r(   rV   r*   r   r,   r   rm   offline_textrn   ro   r   ru   rW   r   r   r   r     s>    z+OnlineCourseFetcher._generate_course_reasonc              
   C   s   zXdddd}g }dD ]#}|D ]}|j  |kr-|| dkr-|| ||  d7  <  nqqd}|D ]"}||vrU|j  }||d|k rU|| ||dd ||< q3|W S  tyv } ztdt|  |W  Y d}~S d}~ww )zK
        Apply diversity filter to ensure variety across platforms
        r   r!   r   r7   z#Error applying platform diversity: N)r   r   r;   r   rD   r8   rE   r   )r(   r   platform_countsdiverse_coursesr   rV   max_per_platformrW   r   r   r   rI     s0   


z-OnlineCourseFetcher._apply_platform_diversityN)r   r   r   __doc__r)   r   r   r   r   r   rX   r:   rg   r
   r<   r=   r>   r{   rF   rG   rl   r   r   r   rI   r   r   r   r   r      sb    
&B/+""

-

3
/r   )r?   aiohttpjsonrs   loggingtypingr   r   r   r   dataclassesr   urllib.parser   r   difflibr   langchain_community.llmsr	   r   	getLoggerr   r8   r
   r   r   r   r   r   <module>   s     
