/ src / __pycache__ / hr_automation.cpython-312.pyc
hr_automation.cpython-312.pyc
  1  2  �~�i�Q�	��UddlZddlZddlmZddlZddlmZddlmZddlm	Z	ddl
  3  mZmZddl
mZddlmZmZdd	lmZmZdd
  4  lmZddlmZddlmZmZmZdd
l�ddlmZddl m!Z!m"Z"ddl#m$Z$ejJjMejJjOejJjOejJjQe)����ddl*Z*e*jVe*jX��e*jZe.�Z/de0fd�Z1de2de2fd�Z3de2de2fd�Z4de2de2fd�Z5de2de2fd�Z6de2de2fd�Z7de2de2fd�Z8de2de2fd�Z9de2de2fd�Z:de2de;fd�Z<de2de2fd�Z=d�Z>d e?d!e!fd"�Z@d e?d!e!fd#�ZAe.d$k(�rzejJjOejJjQe)��ZBejJjOeB�ZCejJj�eCd%d&�ZEd'ZFe"d(eFd)�*�ZGe!d+d+eG�,�ZHd-d.eEd/�ZIe?eJd <eAeIeH�0�ZKeLd1eK���eLd2�eLd3eKd4j�d5��d6��eLd7eKd8���eLd9eKd:���eKd;D�cgc]}|j���c}ZOeOeKd;<ee)�j��j�j�ZCeCd<zZReRd=zZSeRj�d>d>�?�eUeSd@dA�B�5ZVej�eKeVdCdD�E�ddd�yycc}w#1swYyxYw)F�N)�datetime)�BytesIO)�Path)�Config)�HumanMessage�	AIMessage)�ChatPromptTemplate)�JsonOutputParser�StrOutputParser)�
  5  StateGraph�END)�RetryPolicy)�GCSUploader)�create_summary_llm�create_evaluation_llm�create_job_skills_llm)�*)�extract_cv_data)�	HRJobPost�JobApplication)�map_job_to_candidate_skills)�level�returnc��	tjjtj�s't
  6  j
dtj���ytjst
  7  j
d�y	t�t
  8  jd�y#t$r+}t
  9  j
dt|����Yd}~yd}~wwxYw#t$r+}t
 10  j
dt|����Yd}~yd}~wwxYw)	z�
 11      Check if Google Services are properly configured
 12  
 13      Returns:
 14          True if Google Services are available, False otherwise
 15      u(⚠️ Google credentials not found at: Fu%⚠️ GOOGLE_SHEET_ID not configuredu0✅ Google Services are available and configuredTu.⚠️ Google Services initialization failed: Nu'⚠️ Error checking Google Services: )�os�path�existsr�GOOGLE_CREDENTIALS_PATH�logger�warning�GOOGLE_SHEET_ID�GoogleServices�info�	Exception�str)�es ��/Users/furqan/Documents/AI HR Automation/LangGraph Solution/AI HR Automation - LangGraph Python Project/PythonProject/agentic-ai-hr-automation/src/hr_automation.py�check_google_services_availabler((s�����w�w�~�~�f�<�<�=��N�N�E�f�Fd�Fd�Ee�f�g���%�%��N�N�B�C��	����K�K�J�K����	��N�N�K�C�PQ�F�8�T�U���	�������@��Q���I�J����sB�AC�%C�=B�	C�&!C�C�C�C�	D�!D�D�statec�T�	d|vr�|dr�tjd|d���t|dd�5}|j�}ddd�	|d�dt	j
 16  �j
d��d�}ttj�}t�}|j||�}|d	|d
 17  <tjd|d
 18  ���td�
�g|d<|St#d��#1swY��xYw#t$rQ}tjdt|����d|d
 19  <|dj!dt|����Yd}~|Sd}~wwxYw#t$rD}dt|���}tj%|d��|dj!|�Yd}~|Sd}~wwxYw)zGraph Node - Upload CV file�cv_file_pathzProcessing local CV file: �rbN�candidate_name�_CV_z
%Y%m%d_%H%M%Sz.pdf�
 20  signed_url�cv_linku!✅ CV uploaded to Google Cloud: zCV uploaded��content�messagesu)⚠️ Could not upload to Google Cloud: ��errorszGoogle Drive upload failed: zNo CV file path or URL providedzDownload error: T��exc_info)rr#�open�readr�now�strftimerr�GOOGLE_CLOUD_STORAGE_BUCKETr�
 21  upload_pdfrr$r r%�append�
 22  ValueError�error)	r)�f�cv_bytes�filename�google_cloud�	pdf_bytes�
uploaded_filer&�	error_msgs	         r'�upload_cv_noderHKs���*��U�"�u�^�'<��K�K�4�U�>�5J�4K�L�M��e�N�+�T�2�a��6�6�8��3�
P�#�$4�5�6�d�8�<�<�>�;R�;R�Sb�;c�:d�dh�i��*�6�+M�+M�N��#�H�-�	� ,� 7� 7�	�(� K�
�#0��#>��i� ����?��i�@P�?Q�R�S�%1�-�%H�$I��j�!��L��>�?�?�'3�2���
P����!J�3�q�6�(�S�T�#%��i� ��h��&�&�)E�c�!�f�X�'N�O�O��L��
P���*�&�s�1�v�h�/�	����Y���.�
�h����y�)�)��L��*�sZ�3E�C1�E�BC=�&E�1C:�6E�=	E�AE�E�E�E�	F'�#9F"�"F'c��0K�	d}d|vr
 23  |dr|d}t|��d{���}||d<t|dtd���|S7�$#t$rA}|dj	d	t|����i|d<t
d
 24  t|�����d}~wwxYw�w)z3Graph Node: Extract cv information using LlamaIndexr4r+N�extracted_cv_datar3zCV data extractedr1r5z Personal data extraction error: zExtract CV Data Failed: )r�add_messagesrr$r>r%r?)r)r+�cv_datar&s    r'�extract_cv_data_noderMos�����>����U�"�u�^�'<� ��0�L�'��5�5��%,��!�"��U�:�&�	�:M�(N�O��L�6���>�
�h����!A�#�a�&��J�K�%'��!�"��3�C��F�8�<�=�=��>�s8�B�A	�A�"A	�B�A	�		B�<B�B�Bc�*�	t�}tt��}tjddg�}||z|z}|j|d|j
�d��}td|���|ds*|ds%|d	jd
 25  �tgg��|d<nt|d|d��|d<t|d
td���|S#t$r;}|d	jdt|����tgg��|d<Yd}~|Sd}~wwxYw)zjGraph Node - Extract skills from Job Description.
 26      To compare with candidate skills later : SkillsMatch��pydantic_object)�systema4
 27          You are a precise data extraction system.
 28  
 29          TASK:
 30          Extract skills from the job description and categorize them into:
 31          1. tech_skills
 32          2. soft_skills
 33  
 34          DEFINITIONS:
 35          - tech_skills: programming languages, frameworks, tools, platforms, databases, APIs, automation tools, cloud services
 36          - soft_skills: communication, collaboration, leadership, problem-solving, time management, adaptability, teamwork
 37  
 38          OUTPUT RULES:
 39          - Return VALID JSON ONLY
 40          - No markdown
 41          - No explanations
 42          - Do NOT add extra fields
 43          - Do NOT include duplicates
 44          - Normalize skills into short canonical names
 45          - Follow this exact JSON structure:
 46  
 47          OUTPUT FORMAT INSTRUCTION:
 48          {format_instructions}
 49          
 50          
 51          )�userz<
 52          JOB DESCRIPTION:
 53          {job_description}
 54          �job_description)rS�format_instructions�LLM Result: �tech_skills�soft_skillsr5z(No skills extracted from job description)rVrW�
 55  job_skillsr3zJob Skills data extractedr1z7skills extraction failed for job description -  error: N)
rr
 56  �	JobSkillsr	�
from_messages�invoke�get_format_instructions�printr>rKrr$r%�r)�llm�parser�prompt�chain�resultr&s       r'�extract_job_skills_noderd�sH��?
 57  �#�%��!�)�<��#�1�1�

�4

�73
 58  ���B���v�%�����$�%6�7�#)�#A�#A�#C�
 59  ���
 60  	��V�H�%�&��m�$�V�M�-B��(�O�"�"�#M�N�"+���#�E�,��
 61  #,�"�=�1�"�=�1�#�E�,��
 62  	�U�:�&�	�:U�(V�W��L���
 63  �
�h����!X�Y\�]^�Y_�X`�a�b�'���
 64  ��l��
 65  �L��
 66  �s�C
 67  C�	D�0D
�
Dc���	|dstd��t�}tjddg�}||zt	�z}|jdt
j|dd��i�}||d<|d	jtd
 68  ���|S#t$rA}|djd
t|����d|d<tdt|�����d}~wwxYw)z'Graph Node - Generate candidate summaryrJz*Data not found: extracted_cv_data is empty)rQaYou are an expert HR assistant. 
 69              Create a concise professional summary of this candidate in maximum 200 words.
 70              Focus on their key strengths, experience level, skills, and notable qualifications.
 71              Write in third person, professional tone.)rRzCV JSON DATA: {cv_data}rL���indent�summaryr3zSummary generatedr1r5zSummary generation error: r4zGenerate Summary Node Failed: N)r?rr	rZrr[�json�dumpsr>rr$r%)r)r_rarbrir&s      r'�generate_summary_noderl�s���D��(�)��I�J�J� �"��#�1�1�
:�
4�3
 72  �������0�0���,�,��t�z�z�%�(;�"<�Q�G� 
 73  ���#��i��
�j�� � ��3F�!G�H��L��
�D�
�h����!;�C��F�8�D�E���i���9�#�a�&��B�C�C��	D�s�BB�	C�<C�Cc	���	t�}tt��}tjddg�}||z|z}|j|dt
j|dd��|d|d	|d
 74  |j�d��}td|���||d
<|djtd|d�d����|S#t$r3}|djdt|����ddd�|d
<Yd}~|Sd}~wwxYw)zGGraph Node - Evaluate candidate against ideal profile (Job Description)rO)rQu�You are a senior HR specialist and technical recruiter.
 75  
 76          TASK:
 77          Evaluate how well the candidate matches the provided job description.
 78          
 79          INPUTS:
 80          1. Candidate professional summary
 81          2. Candidate CV Data (JSON Format), including skills, experience, education etc.
 82          3. Job Title
 83          4. Job Description
 84          5. Required Job Skills
 85          
 86          SCORING RULES:
 87          - 90–100: Excellent fit
 88          - 75–89: Strong fit
 89          - 55–74: Moderate fit
 90          - Below 55: Weak fit
 91          - Base the score primarily on technical skill alignment and relevant experience
 92          - Penalize missing core skills
 93          - Do NOT reward unrelated experience
 94          - Do NOT invent or assume skills
 95          
 96          HR REASONING RULES:
 97          - Explain the score in 4–6 concise sentences
 98          - Focus on strengths and gaps relative to the JD
 99          - Use professional, neutral HR language
100          - Avoid bias-related language
101          
102          OUTPUT RULES:
103          - Return VALID JSON ONLY
104          - No markdown, no explanations outside JSON
105          - Follow the output structure exactly
106          
107          OUTPUT JSON FORMAT:
108          {format_instructions}
109          
110          
111                      )rRaSUMMARY: 
112          {summary}
113          
114          CANDIDATE CV JSON DATA: 
115          {cv_data}
116          
117          ---
118          JOB TITLE:
119          {job_title}
120          
121          JOB DESCRIPTION:
122          {job_description}
123          
124          REQUIRED JOB SKILLS:
125          {job_skills}
126          
127          rirJrfrg�	job_titlerSrX)rirLrnrSrXrTrU�
128  evaluationr3zCandidate evaluated: Score �scorez/100r1r5zEvaluation error: rzEvaluation failed)rp�	reasoningN)rr
129  �CandidateEvaluationr	rZr[rjrkr\r]r>rr$r%r^s       r'�evaluate_candidate_noders�s6��LM�#�%��!�2E�F��#�1�1�%
�L
�O73�7��r���v�%������Y�'��z�z�%�(;�"<�Q�G��{�+�$�%6�7���-�#)�#A�#A�#C�

130  ���	��V�H�%�&�$��l��
�j�� � ��5P�QW�X_�Q`�Pa�ae�3f�!g�h��L��	�M�
�h����!3�C��F�8�<�=�()�8K�L��l���L��	M�s�B;B?�?	C;�(C6�6C;c�"�	|d}|dd}|dd}t|j|j||��}||d<|S#t$rD}dt	|���}t
131  j
|d�	�|d
132  j|�Yd}~|Sd}~wwxYw)NrXrJrVrW)�job_tech_skills�job_soft_skills�candidate_tech_skills�candidate_soft_skills�skills_matchzskills match error: Tr6r5)rrVrWr$r%rr@r>)r)rXrwrxrcr&rGs       r'�skills_match_noderz=s���*��<�(�
133  � %�&9� :�=� I�� %�&9� :�=� I��,�Z�=S�=S�eo�e{�e{�EZ�sH�I�� &��n���L���*�*�3�q�6�(�3�	����Y���.�
�h����y�)�)��L��*�s�=A�	B�
134  9B	�	Bc���	t�sJtjd�tjd�|dj	td���|St
�}|d|d|d|d	jd
135  d�|d	jdd�tj|d	jd
g��tj|d	jdg��tj|d	jdg��|d|djdd�|djdd�|dg}|jtjtj|�|dj	td���tjd�|S#t$rD}dt|���}tj!|d��|dj	|�Yd}~|Sd}~wwxYw)z$Node - Save results to Google Sheetsu<⚠️ Google Sheets not configured, skipping save to sheetsz6Results can be accessed from the returned state objectr3z,Google Sheets not configured, data not savedr1�	timestampr-�candidate_emailrJ�phone�N/A�location�skills�work_experience�	educationrirorprrqr4r0zData saved to Google Sheetsu,✅ Data saved to Google Sheets successfullyzSheets save error: Tr6r5N)r(rr r#r>rr"�getrjrk�append_to_sheetrr!�
136  SHEET_NAMEr$r%r@)r)�google_services�row_datar&rGs     r'�save_to_sheets_noder�Ms���%*�.�0��N�N�Y�Z��K�K�P�Q��*��$�$�Y�7e�%f�g��L�(�*��
�+���"�#��#�$��%�&�*�*�7�E�:��%�&�*�*�:�u�=��J�J�u�0�1�5�5�h��C�D��J�J�u�0�1�5�5�6G��L�M��J�J�u�0�1�5�5�k�2�F�G��)���,��#�#�G�Q�/��,��#�#�K��4��)��

137  ��	�'�'��"�"�����	
138  �	�j�� � ��3P�!Q�R����B�C��L���*�)�#�a�&��2�	����Y���.�
�h����y�)�)��L��*�s�AF�EF�	G,�(9G'�'G,c�t�|djdd�}|dk\rd|d<n
139  |dk\rd|d<||d	<|d
140  kD|d<|S)Nrorpr�Pu⭐ Exceptional�tag�Au
141  ✅ Strong�evaluation_score�7�	notify_hr)r�)r)rps  r'�score_decision_noder�zsW���,��#�#�G�Q�/�E���{�(��e��	�"��#��e�� %�E�
142  �����E�+���L�c��|drdSdS)Nr��end�)r)s r'�route_on_scorer��s����,�;�7�%�7r�c	��tj|dd��}d|djdd��d|�d|d	�d
143  |d�d�	|d
<|S)Nrorfrgz@A new candidate matched with job profile. 
144      Evaluated Score: rprz"/100. 
145      Evaluation Detail:
146      z!
147      - - - - - - - 
148      Summary: riz.
149      CV Link: r0z.
150      �notification_message)rjrkr�)r)�formatted_evals  r'�fan_out_notificationsr��sx���Z�Z��l� 3�A�>�N�)��L�)�-�-�g�u�=�>�?�����I��
� ��I��
� �
%�E�
151   �!��Lr�c��tt�}|jdt�|jdt�|jdt
152  �|jdt�td��}|jdt|��|jd	t�|jd
153  t�|jdt�|jdt�|jd
t�|jdt�|jdt�|j!d�|j#dd�|j#dd�|j#dd�|j#dd�|j#dd	�|j#d	d�|j%dt&dt(d��|j#dd
�|j#dd�|j#dd�|j#d
t(�|j#dt(�|j#dt(�|j+�S)zCreate the LangGraph workflow�	upload_cvrMrd�generate_summaryrf)�max_attempts�evaluate)�retry_policyrz�save_results�score_decisionr��
154  send_email�
155  send_slack�
send_whatsapp)r�r�)r�
156  AgentState�add_noderHrMrdrlrrsrzr�r�r��send_hr_email_node�send_slack_notification_noder��set_entry_point�add_edge�add_conditional_edgesr�r
�compile)�graph�
157  retry_onces  r'�create_hr_workflowr��s���
�z�"�E�
158  �N�N�;��/�	�N�N�)�+?�@�	�N�N�,�.E�F�	�N�N�%�'<�=��!�,�J�	�N�N�:�6�Z�N�P�	�N�N�&�(9�:�	�N�N�>�#6�7�	�N�N�#�%8�9�	�N�N�*�,A�B�	�N�N�<�!3�4�	�N�N�<�!=�>�	�N�N�?�M�2�
159  ���+�&�	�N�N�;� 6�7�	�N�N�)�+D�E�	�N�N�,�.@�A�	�N�N�%�z�2�	�N�N�:�2�3�	�N�N�&�(8�9�
160  �����0��	
161  ��
162  �N�N�*�L�9�	�N�N�*�L�9�	�N�N�*�O�<�
163  �N�N�<��%�	�N�N�<��%�	�N�N�?�C�(��=�=�?�r��candidate_data�hr_job_postc��6K�t||��d{���S7��w)a
164      Process a Job Form submission
165  
166      Args:
167          candidate_data: Dictionary containing form response data
168          Expected keys: 'name', 'email', and either 'cv_file_url' or 'cv_file_path'
169  
170          hr_job_post (HRJobPost): Validated Pydantic model for the job.
171  
172      N)�process_candidate�r�r�s  r'�"process_job_application_submissionr��s����#�>�;�?�?�?�?�s���c���K�|dstd��t|d|dd|jd�xsdidd|jj|jj
173  |jj|jjitj�jd�gg��}t�}|j|��d{���}|S7��w)	a&
174      Main function to process a candidate application
175  
176      Args:
177         candidate_data: Dictionary containing form response data
178         hr_job_post: Validated Pydantic model for the job.
179  
180      Returns:
181          Final state with all processing results
182  
183      Note: cv_file_path must be provided
184      r+zcv_file_path must be provided�name�emailr4z%Y-%m-%d %H:%M:%S)r-r}�cv_file_urlr+rJr0rirnrS�job_description_html�hr_emailror|r5r3N)r?r�r��job_application�title�description�description_html�hrr�rr:r;r��ainvoke)r�r��
initial_state�app�final_states     r'r�r��s������.�)��8�9�9��%�f�-�&�w�/��#�'�'��7�=�2�����-�-�3�3�#�3�3�?�?�(�8�8�I�I����%�%���,�,�.�)�)�*=�>����M�&�
185  �C����M�2�2�K���3�s�CC�C�C�__main__�resumeszjohn_doe_resume.pdfa2We are looking for a Senior AI Automation Engineer to design, develop, and maintain Python-based automation agents that streamline workflows, orchestrate system interactions, and reduce operational overhead.
186      This role focuses on building intelligent, event-driven automation, not QA or test automation.zSenior AI Engineerr4)r�r�r��)�id�ulidr�zjohn doezjohn.doe@domain.com)r-r}r+r�zResult: zProcessing Complete!zScore: rorpz/10z	Summary: rizErrors: r5r3�outputszagent_final_state.jsonT)�parents�exist_ok�wzutf-8)�encoding�F)rh�ensure_ascii)Xrrjr�sys�ior�pathlibr�
187  src.configr�langchain_core.messagesrr�langchain_core.promptsr	�langchain_core.output_parsersr
188  r�langgraph.graphrr
�langgraph.typesr�src.google_cloudr�src.llm_providerrrr�src.notifications�src.data_extractionr�src.fastapi_apirr�src.skills_matchrrr>�dirname�abspath�__file__�logging�basicConfig�INFO�	getLogger�__name__r�boolr(r�rHrMrdrlrsrzr�r�r%r�r�r��dictr�r��
189  script_dir�project_root�join�
local_cv_pathrSr�r�r��__annotations__rcr]r�r2�messages_content�resolve�parent�
190  output_dir�output_file�mkdirr8rA�dump)�msgs0r'�<module>r�sn��
191  ���
192  ����;�5�K�+�'�(�]�]��/�5�8����������������������0I� J�K�L������'�,�,�'�	��	�	�8�	$�����F!�*�!��!�H�j��Z��&D�:�D�*�D�N���
193  ��BP�:�P�*�P�f�Z��J�� )�z�)�j�)�Z	�z�	�j�	�8�*�8��8�
194  ���
195  ��&8�x@�T�@�PY�@�$(�D�(�y�(�`�z�������������!:�;�J��7�7�?�?�:�.�L��G�G�L�L��y�:O�P�M�f�O�%�+?�_�oq�r�O��q�a��H�K�.8�Mb�uB�D�N�D�D�
�$���F�
196  
197  �H�V�H�
198  ��	�
199   �!�	�G�F�<�(�,�,�W�5�6�c�
200  :�;�	�I�f�Y�'�(�
201  )�*�	�H�V�H�%�&�
202  '�(�06�j�/A�B�/A�����/A�B��)�F�:����>�)�)�+�2�2�9�9�L��	�)�J��7�7�K����T�D��1�
203  �k�3��	1�Q���	�	�&�!�A�E�:�
204  2�	1�Y��@C�
205  2�	1�s�(K6�K;�;L