
    ANi@                         d dl Zd dlZd dlZd dlZd dlmZ d dlZ e         eed      sej                  e_
         ej                  dd        ej                  e      Z G d d      Zy)	    N)load_dotenvfloat_ignorez.*np.float_.*)messagec                       e Zd Zd ZdefdZdefdZ	 	 	 ddedededed	ef
d
Z	 	 ddededede	fdZ
ddedefdZ	 ddedededefdZddede	defdZy)Embedderc                 n    t        j                  d      | _        t        j                  dd      | _        y)z1Initialize embedder with OpenAI API configurationOPENAI_API_KEYOPENAI_EMBEDDING_MODELtext-embedding-3-smallN)osgetenvopenai_api_keyembedding_model)selfs    7/var/www/html/drjob-dev/drjob-ai/services/embeddings.py__init__zEmbedder.__init__   s)     ii(89!yy)AC[\    textc                 T   	 | j                   st        j                  d       yd}d| j                    dd}|ddd	}t        j                  |||
      }|j                          |j                         }|d   d   d   }t        j                  dt        |       d       |S # t        $ ry}t        j                  dt        |              t        |d      rBt        |j                  d      r,t        j                  d|j                  j                          Y d}~yd}~ww xY w)z$Generate embeddings using OpenAI APIzOpenAI API key not configuredNz$https://api.openai.com/v1/embeddingszBearer application/json)AuthorizationContent-Typer   i   )inputmodel
dimensionsjsonheadersdatar   	embeddingzGenerated embedding with z dimensionsz(Error generating embedding with OpenAI: responser   zOpenAI API response: )r   loggererrorrequestspostraise_for_statusr   debuglen	Exceptionstrhasattrr"   r   )	r   r   urlr   payloadr"   resultr!   es	            r   generate_embeddingzEmbedder.generate_embedding   s   	&&<=8C#*4+>+>*?!@ 2G 1!G  }}SwHH%%']]_Fvq)+6ILL4S^4DKPQ 	LLCCF8LMq*%'!**f*E4QZZ__4EFG		s   !B% B B% %	D'.A/D""D'c                 $    | j                  |      S )z@Generate embeddings using OpenAI API (wrapper for compatibility))r1   )r   r   s     r   embed_with_qdrantzEmbedder.embed_with_qdrantA   s    &&t,,r   Njobseeker_idr!   country_namecountry_header_codec           	      v   	 || j                  |      }t        j                  d      }t        j                  d      }t        j                  d      }t        |||g      st        j                  d       y| d| d}	|d	d
}
	 t        |      }d||||dd ||ddgi}t        j                  |	||
      }|j                          t        j                  d| d       y# t        $ r t        |      dz  }Y lw xY w# t        $ r.}t        j                  d| dt        |              Y d}~yd}~ww xY w)z?Store resume data in Qdrant collection with country informationNQDRANT_COLLECTION_NAMEQDRANT_SEARCH_URLQDRANT_API_KEY:Qdrant configuration not complete in environment variablesF//pointsr   zapi-keyr           points  )	resume_idr   r5   r6   idvectorr.   r   Successfully stored jobseeker z
 in QdrantTz&Error storing in Qdrant for jobseeker : )r3   r   r   allr#   warningint
ValueErrorhashr%   putr'   infor*   r$   r+   )r   r4   r   r!   r5   r6   collection_namer9   r:   r-   r   point_idpoint_payloadr"   r0   s                  r   store_in_qdrantzEmbedder.store_in_qdrantE   sa   3	  2248	 ii(@AO "		*= >YY'78N):NKLP &'q(9AC) 2G8|, &"+)5$($K,83F	$	M  ||CmWMH%%'KK8jQR-  8-780  	LL8bQQ 		sC   A5D 8D C$ AD $C>;D =C>>D 	D8
$D33D8payload_datac                 (   	 || j                  |      }t        j                  d      }t        j                  d      }t        j                  d      }t        |||g      st        j                  d       y| d| d}|d	d
}		 t        |      }
||dd d}|r|j                  |j                  dd      |j                  dd      |j                  dd      |j                  dd      |j                  dd      |j                  dd      dd |j                  dg       dd |j                  dd      |j                  dd      |j                  dd      |j                  dg       dd d       d|
||d gi}t        j                  |||	!      }|j                          t        j                  d"| d#       y$# t        $ r t        |      dz  }
Y Ew xY w# t        $ r.}t        j!                  d%| d&t#        |              Y d}~yd}~ww xY w)'zHStore resume data in Qdrant collection with detailed payload informationNr8   r9   r:   r;   Fr<   r=   r   r>   r?   rA   )rB   r   r5    r6   email
first_name	last_nameprofile_summaryi  skills   experience_yearsr   highest_educationcurrent_designation	languages
   )r5   r6   rV   rW   rX   rY   rZ   r\   r]   r^   r_   r@   rC   r   rF   z  in Qdrant with detailed payloadTz4Error storing detailed data in Qdrant for jobseeker rG   )r3   r   r   rH   r#   rI   rJ   rK   rL   updategetr%   rM   r'   rN   r*   r$   r+   )r   r4   r   r!   rS   rO   r9   r:   r-   r   rP   r.   rQ   r"   r0   s                  r   store_in_qdrant_with_detailsz%Embedder.store_in_qdrant_with_details   sf   R	  2248	 ii(@AO "		*= >YY'78N):NKLP &'q(9AC) 2G8|, *UdG (4(8(8(L/;/?/?120 ".!1!1'2!>&2&6&6|R&H%1%5%5k2%F+7+;+;<Mr+R S, #/"2"28R"@R# -9,<,<=OQR,S-9-=-=>QSU-V/;/?/?120 &2%5%5k2%FR&'6 &"+#*M  ||CmWMH%%'KK0>^_ k  8-78n  	LLF|nTVWZ[\W]V^_ 		sC   A5G 8G F< D*G <GG GG 	H#$HHquerytop_kc                    	 t        j                  d      }t        j                  d      }t        j                  d      }t        |||g      st        j	                  d       dg iS | j                  |      }| d| d}|dd	}||d
d}	t        j                  ||	|      }
|
j                          |
j                         S # t        $ r/}t        j                  dt        |              dg icY d}~S d}~ww xY w)z0Search resumes in Qdrant using vector similarityr9   r:   r8   r;   r/   r<   /points/searchr   r>   TrE   topwith_payloadr   zError searching Qdrant: N)r   r   rH   r#   rI   r3   r%   r&   r'   r   r*   r$   r+   )r   rd   re   r9   r:   rO   r!   r-   r   r.   r"   r0   s               r   search_with_qdrantzEmbedder.search_with_qdrant   s    	" "		*= >YY'78N ii(@AO)>?KLP !"~% ..u5I&'q(9HC) 2G "+5$OG}}SwHH%%'==?" 	"LL3CF8<=b>!	"s%   A%C (AC 	C<$C71C<7C<filtered_resume_idscountry_codec           
         	 t        j                  d      }t        j                  d      }t        j                  d      }t        |||g      st        j	                  d       dg iS |st        j                  d       dg iS | j                  |      }|st        j                  d       dg iS | d| d	}	|d
d}
t        |      }|}t        j                  d| d       ||dd}|r%ddd|idgi|d<   t        j                  d|        t        j                  |	||
      }|j                  dk7  r/t        j                  d|j                   d|j                          |j                          |j                         }t        d |D              }g }|j!                  dg       D ]S  }|j!                  di       j!                  d      }|rt#        |      |v r|j%                  |       t        |      |k\  sS n t        j                  dt        |j!                  dg              dt        |       dt        |       d        d|iS # t&        $ r/}t        j                  d!t#        |              dg icY d"}~S d"}~ww xY w)#z
        Search specific candidates in Qdrant using vector similarity
        Uses client-side filtering for better performance with large ID lists
        Optionally filters by country code
        r9   r:   r8   r;   r/   z1No filtered resume IDs provided for vector searchz&Failed to generate embedding for queryr<   rg   r   r>   zVector search: searching ALL z candidates (no limit)T)rE   limitrj   mustr6   valuekeymatchfilterz#Vector search with country filter: r      zQdrant API error: z - c              3   2   K   | ]  }t        |        y w)N)r+   ).0rids     r   	<genexpr>z6Embedder.search_filtered_candidates.<locals>.<genexpr>F  s     )Rs#c()Rs   r.   rB   zVector search: retrieved z total, filtered to z from z target IDsz/Error searching filtered candidates in Qdrant: N)r   r   rH   r#   rI   rN   r3   r$   r)   r%   r&   status_coder   r'   r   setrb   r+   appendr*   )r   rd   rl   re   rm   r9   r:   rO   r!   r-   r   num_candidatessearch_limitr.   r"   r/   filtered_resume_ids_setfiltered_resultsitemrB   r0   s                        r   search_filtered_candidatesz#Embedder.search_filtered_candidates   s   U	" "		*= >YY'78N ii(@AO)>?KLP !"~%&OP "~% ..u5IEF "~%&'q(9HC) 2G !!45N *LKK77GG]^_ $% $G #8&-|%<%! A,PQ}}SwHH ##s*1(2F2F1Gs8==/Z[%%']]_F '*)R>Q)R&R#!

8R0  HHY377D	Y3J!J$++D1 '(E1 KK+C

8R0H,I+J K"#345VC@S<T;UU`b
 .// 	"LLJ3q6(STb>!	"s8   A%I (I +I /EI >AI 	J$J<JJfiltersc           	         	 t        j                  d      }t        j                  d      }t        j                  d      }t        |||g      st        j	                  d       dg iS | j                  |      }| d| d}|dd	}	||d
d}
|rg }|j                  d      r|j                  dd|d   id       |j                  d      r,t        |d   t              r|j                  dd|d   id       |j                  d      r|j                  dd|d   id       |j                  d      r|j                  dd|d   id       |rd|i|
d<   t        j                  ||
|	      }|j                          |j                         }t        j                  dt        |j                  dg              d       |S # t         $ r/}t        j#                  dt%        |              dg icY d}~S d}~ww xY w)zISearch resumes in Qdrant with advanced filtering by skills, country, etc.r9   r:   r8   r;   r/   r<   rg   r   r>   Trh   r6   rq   rr   rZ   any	educationr]   min_experience_yearsr\   gte)rs   rangerp   ru   r   z$Qdrant search with filters returned z resultsz(Error searching with filters in Qdrant: N)r   r   rH   r#   rI   r3   rb   r}   
isinstancelistr%   r&   r'   r   rN   r)   r*   r$   r+   )r   rd   r   re   r9   r:   rO   r!   r-   r   r.   filter_conditionsr"   r/   r0   s                  r   search_with_filterszEmbedder.search_with_filters]  s"   I	" "		*= >YY'78N ii(@AO)>?KLP !"~% ..u5I&'q(9HC) 2G
 "+5$OG $&! ;;45%,,#8&-w7L/M%N ;;x(Z8I4-P%,, (E78;L3MN
 ;;{+%,,#6&-w{/C%D ;;56%,,#5&+W5K-L%M %)/1B(CGH%}}SwHH%%']]_FKK6s6::hPR;S7T6UU]^ M 	"LLCCF8LMb>!	"s%   A%G  (EG   	G8	$G3-G83G8)NrU   rU   )NN)r[   )r[   N)Nr[   )__name__
__module____qualname__r   r+   r1   r3   r   rR   dictrc   rJ   rk   r   r    r   r   r   r      s    ]
!s !F-c - #%<< < 	<
 < !<D !ZZ Z 	Z
 Zx" "C "@ [_]"]"/3]"<?]"TW]"~K" K"t K"3 K"r   r   )numpynpwarningsr%   r   dotenvr   loggingr,   float64r   filterwarnings	getLoggerr   r#   r   r   r   r   <module>r      sk       	    r8

BI   / : 
		8	$P" P"r   