
    exiq                       d dl Z d dlZd dlZd dlmZmZ d dlmZ d dlmZ d dl	m
Z
 d dlmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z;m<Z<m=Z=m>Z>m?Z?m@Z@mAZAmBZBmCZCmDZDmEZEmFZFmGZGmHZHmIZImJZJmKZKmLZLmMZMmNZNmOZOmPZPmQZQm,Z,mRZR d dlSmTZT d dlUmVZV d d	lWmXZX 	 d dlYZY G d
 d      Z[ e[       Z\y# eZ$ r dZYY w xY w)    N)DictList)datetime)settings)MatchResult)Haddress_document_promptlease_documents_promptrealestate_document_promptvehicle_promptretirement_promptcreditor_promptpriority_unsecured_claim_promptinsurance_promptexecutory_contract_promptthird_party_claim_promptemployment_promptnet_income_promptgross_overtime_promptrental_income_promptroyalties_income_promptpension_income_promptfamily_support_income_promptsecurity_income_prompt#social_security_act_benefits_promptpublic_assistance_promptother_income_promptspouse_income_promptrent_home_records_promptutilities_records_prompttransportation_records_prompt vehicle_insurance_records_prompttaxes_records_prompt#installment_payments_records_promptalimony_support_records_promptinsurance_records_prompt'retirement_contributions_records_promptother_expenses_records_prompt insider_payment_documents_prompt*paid_transferred_property_documents_prompt-paid_transfer_help_creditors_documents_prompt1sold_traded_transferred_property_documents_prompt'owe_money_to_creditors_documents_prompt2property_taken_as_collateral_debt_documents_promptcourt_action_documents_prompt%property_repossessed_documents_prompt/creditors_legal_process_claims_documents_prompt.gave_gifts_over_600_last_year_documents_prompt5financial_accounts_changed_last_year_documents_prompthousing_mortgage_records_prompt$public_transportation_records_prompt$secured_debt_payments_records_prompt'other_necessary_expenses_records_promptpriority_claims_records_prompt'charitable_contributions_records_prompt"additional_security_records_prompt home_energy_costs_records_prompt#education_dependents_records_prompt$elderly_disabled_care_records_prompt*health_disability_insurance_records_prompt!telecommunications_records_prompt*healthcare_beyond_standards_records_prompt!childcare_expenses_records_prompt!education_expenses_records_prompt%court_ordered_payments_records_promptlife_insurance_records_prompt%involuntary_deductions_records_prompt vehicle_ownership_records_prompt"healthcare_expenses_records_prompt housing_insurance_records_prompt vehicle_operation_records_prompttaxes_actual_records_prompt#spouse_business_pl_documents_prompt#self_employment_pl_documents_prompt!creditor_payment_documents_prompt insider_benefit_documents_promptr(   "insider_payment_documents_prompt_2)logger)get_pdf_parser)pusher_clientc                      e Zd ZdZddZddededededed	efd
Zd	efdZd	efdZ	d	efdZ
ded	efdZd	efdZ	 ddededed	ee   fdZddededed	ee   fdZddededed	ee   fdZd	efdZddededed	ee   fdZd	efdZddededed	ee   fdZdeded	ee   fdZd deded	ee   fdZddededed	efdZy)!AzureOpenAIClientzRAzure OpenAI client for document-driven structured verification and classificationNc                 n   t         j                  | _        t         j                  | _        t         j
                  | _        t         j                  | _        | j                   d| j                   d| j                   | _	        ||nd| _
        ||nd| _        ||nd| _        ||| _        y ddi| _        y )Nz/openai/deployments/z/chat/completions?api-version=i  g333333?g      ?typejson_object)r   AZURE_OPENAI_ENDPOINTendpointAZURE_OPENAI_KEYapi_keyAZURE_OPENAI_DEPLOYMENT
deploymentAZURE_OPENAI_VERSIONapi_versionurl
max_tokenstemperaturetop_presponse_format)selfr`   ra   rb   rc   s        F/var/www/html/BankruptcyAI-uat/bankruptcy-ai/src/utils/azure_openai.py__init__zAzureOpenAIClient.__init___   s     6600"::#88mm_$88IIghlhxhxgyz )3(>*D*5*A;s#/US
2A2MTZ\iSj    	file_typepayloadfile_urlextracted_text
request_idreturnc                 1  K   t        j                  d| d|        d}|r%d}t        j                  dt        |       d       nt        j                  d|        	 t               }t        j                  d       |j	                  |      }t        j                  d	t        |       d
       |j                  |      }t        |      dkD  }t        j                  dt        |       d       t        dt        |       d|dd  d       |dk(  r:t        j                  d       | j                         }
| j                  |||      }nl|dk(  r:t        j                  d       | j                         }
| j                  |||      }n-|dk(  r%| j                         }
| j                  |||      }n|dk(  r%| j                         }
| j                  |||      }n|dk(  r:t        j                  d       | j                         }
| j!                  |||      }n|dk(  r0t        j                  d       t"        }
| j%                  |||      }ne|d k(  r:t        j                  d!       | j'                         }
| j)                  |||      }n&|d"k(  r0t        j                  d#       t*        }
| j%                  |||      }n|d$k(  r0t        j                  d%       t,        }
| j%                  |||      }n|d&k(  r0t        j                  d'       t.        }
| j%                  |||      }n|d(k(  r0t        j                  d)       t.        }
| j%                  |||      }nR|d*k(  r0t        j                  d+       t.        }
| j%                  |||      }n|d,k(  r0t        j                  d-       t0        }
| j%                  |||      }n|d.k(  r0t        j                  d/       t2        }
| j%                  |||      }n|d0k(  r0t        j                  d1       t4        }
| j%                  |||      }n~|d2k(  r0t        j                  d3       t6        }
| j%                  |||      }nI|d4k(  r0t        j                  d5       t8        }
| j%                  |||      }n|d6k(  r0t        j                  d7       t:        }
| j%                  |||      }n|d8v r0t        j                  d9       t<        }
| j%                  |||      }n|d:k(  r0t        j                  d;       t>        }
| j%                  |||      }nv|d<k(  r0t        j                  d=       t@        }
| j%                  |||      }nA|d>k(  r0t        j                  d?       tB        }
| j%                  |||      }n|d@k(  r0t        j                  dA       tD        }
| j%                  |||      }n|dBk(  r7t        j                  dCtF                tF        }
| j%                  |||      }n|dDk(  r0t        j                  dE       tH        }
| j%                  |||      }nf|dFk(  r0t        j                  dG       tJ        }
| j%                  |||      }n1|dHk(  r0t        j                  dI       tL        }
| j%                  |||      }
n|dJk(  r0t        j                  dK       tN        }
| j%                  |||      }
n|dLk(  r0t        j                  dM       tP        }
| j%                  |||      }
n|dNk(  r0t        j                  dO       tR        }
| j%                  |||      }
n]|dPk(  r0t        j                  dQ       tT        }
| j%                  |||      }
n(|dRk(  r0t        j                  dS       tV        }
| j%                  |||      }	n|dTk(  r0t        j                  dU       tX        }
| j%                  |||      }	n|dVk(  r0t        j                  dW       tZ        }
| j%                  |||      }	n|dXk(  r0t        j                  dY       t\        }
| j%                  |||      }	nT|dZk(  r0t        j                  d[       t^        }
| j%                  |||      }	n|d\k(  r0t        j                  d]       t`        }
| j%                  |||      }n|d^k(  r0t        j                  d_       tb        }
| j%                  |||      }n|d`k(  r0t        j                  da       td        }
| j%                  |||      }n|dbk(  r0t        j                  dc       tf        }
| j%                  |||      }nK|ddk(  r0t        j                  de       th        }
| j%                  |||      }n|dfk(  r0t        j                  dg       tj        }
| j%                  |||      }n|dhk(  r0t        j                  di       tl        }
| j%                  |||      }n|djk(  r0t        j                  dk       tn        }
| j%                  |||      }nw|dlk(  r0t        j                  dm       tp        }
| j%                  |||      }nB|dnk(  r0t        j                  do       tr        }
| j%                  |||      }n|dpk(  r0t        j                  dq       tt        }
| j%                  |||      }n|drk(  r0t        j                  ds       tv        }
| j%                  |||      }n|dtk(  r0t        j                  du       tx        }
| j%                  |||      }nn|dvk(  r0t        j                  dw       tz        }
| j%                  |||      }n9|dxk(  r0t        j                  dy       t|        }
| j%                  |||      }n|dzk(  r0t        j                  d{       t~        }
| j%                  |||      }n|d|k(  r0t        j                  d}       t        }
| j%                  |||      }n|d~k(  r0t        j                  d       t        }
| j%                  |||      }ne|dk(  r0t        j                  d       t        }
| j%                  |||      }n0|dk(  r0t        j                  d       t        }
| j%                  |||      }n|dk(  r0t        j                  d       t        }
| j%                  |||      }n|dk(  r0t        j                  d       t        }
| j%                  |||      }n|dk(  r0t        j                  d       t        }
| j%                  |||      }n\|dk(  r0t        j                  d       t        }
| j%                  |||      }n'|dk(  r0t        j                  d       t        }
| j%                  |||      }n|dk(  r0t        j                  d       t        }
| j%                  |||      }n|dk(  r0t        j                  d       t        }
| j%                  |||      }n|dk(  r0t        j                  d       t        }
| j%                  |||      }nS|dk(  r0t        j                  d       t        }
| j%                  |||      }n|dk(  r0t        j                  d       t        }
| j%                  |||      }n|dk(  r0t        j                  d       t        }
| j%                  |||      }n|dk(  r0t        j                  d       t        }
| j%                  |||      }n|dk(  r0t        j                  d       t        }
| j%                  |||      }nJ|dk(  r0t        j                  d       t        }
| j%                  |||      }n|dk(  r0t        j                  d       t        }
| j%                  |||      }n|dk(  r0t        j                  d       t        }
| j%                  |||      }n|dk(  r0t        j                  d       t        }
| j%                  |||      }nv|dk(  r0t        j                  d       t        }
| j%                  |||      }nA|dk(  r0t        j                  d       t        }
| j%                  |||      }n|dk(  r/t        j                  d       t        }
| j%                  |||      }n|dk(  r/t        j                  d       t        }
| j%                  |||      }n|dk(  r/t        j                  d       t        }
| j%                  |||      }np|ddk(  r/t        j                  de       t        }
| j%                  |||      }n<t        j                  d| d       | j                  |      }
| j                  ||      }t        |
t              r|
dd nt        |
      dd }t        j                  d| d| d       t        dd        t        d|        t        dt        |
t              rt        |
      nd        t        d| d       t        d d       |dk(  r|j                  d      D cg c]#  }|j                         s|j                         % }}g }|D cg c]  }|j                  d      dk(  s| }}|j                  |       t        |      D ]  \  }}|j                         j                  d      rLt        t        d      	 | j                  |d       d{   }|D ]  }|j                  d|ddÜdĜ        q|j                  d|ddÜdĜ        |}n|j                         j                  d      rt        t        d      	 | j                  |d       d{   }t        |t              rd|dȜg}n$|D cg c]  }|j                  d      dk(  s| }}||D cg c]
  }d|ddÜdĜ c}z   }| j                  | j                  | j                  | j                  | j                  d|
d˜d|d˜gd͜}| j                  ddϜ}	 t        j                  dЫ       t        j                         4 d{   }|j                  | j                  ||ѫ      4 d{   }|j                  s3|j                          d{   }t        j                  d| d|j                   d|        d|j                         v rt        rN|rL	 t        j                  d|        t        j                  dddd|dڜ       t        j                  d|        dddddg ddddgd||j                  dcddd      d{    cddd      d{    S dddd|j                   d|dd  g ddddgd||j                  dcddd      d{    cddd      d{    S |j                          d{   }|d   d   d   d   }t        j                  |      }||d<   t        j                  d       |cddd      d{    cddd      d{    S # t        $ r6}	t        j                  d|	 d       t        d|	        d}d}Y d}	~	d}	~	ww xY wc c}w c c}w 7 # t        $ r(}|j                  dd| d| d| dȜ       Y d}~d}~ww xY w7 Ac c}w c c}w # t        $ r}t        d|       d}~ww xY w7 7 p7 N# t        $ r&}t        j                  d| d|        Y d}~d}~ww xY w7 7 7 7 r7 \7 7 # 1 d{  7  sw Y   nxY wddd      d{  7   y# 1 d{  7  sw Y   yxY w# t        $ r"}	dt        |	      j                         v rt        j                  d| d       t        r|r~	 t        j                  d|        t        j                  dddd|dڜ       t        j                  d|        n1# t        $ r%}t        j                  d| d|        Y d}~nd}~ww xY wdddddg ddddgd|dcY d}	~	S t        j                  dt        |	              dddddt        |	       g ddddt        |	       gd|dcY d}	~	S d}	~	ww xY ww)a  Generic document verification entry point.

        For now supports file_type == 'residence_documents' which performs
        name + address field matching, haze detection, and document type classification.
        
        Args:
            file_type: Document type for prompt selection
            payload: Data to verify against
            file_url: Document URL (can be empty if extracted_text provided)
            extracted_text: Pre-extracted text (from chunking). If provided, skips LlamaParse.
        zVerifying document: z | URL: FTz'[Chunk Mode] Using pre-extracted text (z chars)z$STARTING LlamaParse extraction for: z3LlamaParse instance created, calling parse_url()...z LlamaParse parse_url() returned z
 documentsr   zLlamaParse SUCCESS: Extracted z# chars - Will be sent to Vision APIzLLAMAPARSE EXTRACTED TEXT (z	 chars): N   z...zLlamaParse extraction FAILED: z. No text extraction available.zLLAMAPARSE FAILED: residence_documentszMATCHED: residence_documentsbilling_address_documentz!MATCHED: billing_address_documentvehicle_documentbank_statementbusiness_documentszMATCHED: business_documentsaddress_documentszMATCHED: address_documentsssn_documentszMATCHED: ssn_documentslease_documentszMATCHED: lease_documentsreal_estate_documentszMATCHED: real_estate_documentsrecreational_vehicle_documentsz'MATCHED: recreational_vehicle_documentsvehicle_documentszMATCHED: vehicle_documentsequipment_documentszMATCHED: equipment_documentsretirement_documentszMATCHED: retirement_documentscreditor_documentszMATCHED: creditor_documents"priority_unsecured_claim_documentsz+MATCHED: priority_unsecured_claim_documentsinsurance_policieszMATCHED: insurance_policiesexecutory_contract_documentsz%MATCHED: executory_contract_documentsthird_party_claim_documentsz$MATCHED: third_party_claim_documents)employment_documentsspouse_employment_documentszMATCHED: employment_documentsnet_income_documentszMATCHED: net_income_documentsgross_overtime_documentsz!MATCHED: gross_overtime_documentsrental_income_documentsz MATCHED: rental_income_documentsroyalties_income_documentsz#MATCHED: royalties_income_documentspension_income_documentszPension Income Prompt: family_support_income_documentsz(MATCHED: family_support_income_documentssecurity_income_documentsz"MATCHED: security_income_documents&social_security_act_benefits_documentsz/MATCHED: social_security_act_benefits_documentspublic_assistance_documentsz$MATCHED: public_assistance_documentsother_income_documentszMATCHED: other_income_documentsspouse_income_documentsz MATCHED: spouse_income_documentsrent_home_recordszMATCHED: rent_home_recordsutilities_recordszMATCHED: utilities_recordstransportation_recordszMATCHED: transportation_recordsvehicle_insurance_recordsz"MATCHED: vehicle_insurance_recordstaxes_recordszMATCHED: taxes_recordsinstallment_payments_recordsz%MATCHED: installment_payments_recordsalimony_support_recordsz MATCHED: alimony_support_recordsinsurance_recordszMATCHED: insurance_records retirement_contributions_recordsz)MATCHED: retirement_contributions_recordsother_expenses_recordszMATCHED: other_expenses_recordsinsider_payment_documentsz"MATCHED: insider_payment_documents#paid_transferred_property_documentsz,MATCHED: paid_transferred_property_documents&paid_transfer_help_creditors_documentsz/MATCHED: paid_transfer_help_creditors_documents*sold_traded_transferred_property_documentsz3MATCHED: sold_traded_transferred_property_documents owe_money_to_creditors_documentsz)MATCHED: owe_money_to_creditors_documents+property_taken_as_collateral_debt_documentsz4MATCHED: property_taken_as_collateral_debt_documentscourt_action_documentszMATCHED: court_action_documentsproperty_repossessed_documentsz'MATCHED: property_repossessed_documents(creditors_legal_process_claims_documentsz1MATCHED: creditors_legal_process_claims_documents'gave_gifts_over_600_last_year_documentsz0MATCHED: gave_gifts_over_600_last_year_documents.financial_accounts_changed_last_year_documentsz7MATCHED: financial_accounts_changed_last_year_documentshousing_mortgage_recordsz!MATCHED: housing_mortgage_recordspublic_transportation_recordsz&MATCHED: public_transportation_recordssecured_debt_payments_recordsz&MATCHED: secured_debt_payments_records other_necessary_expenses_recordsz)MATCHED: other_necessary_expenses_recordspriority_claims_recordsz MATCHED: priority_claims_records charitable_contributions_recordsz)MATCHED: charitable_contributions_recordsadditional_security_recordsz$MATCHED: additional_security_recordshome_energy_costs_recordsz"MATCHED: home_energy_costs_recordseducation_dependents_recordsz%MATCHED: education_dependents_recordselderly_disabled_care_recordsz&MATCHED: elderly_disabled_care_records#health_disability_insurance_recordsz,MATCHED: health_disability_insurance_recordstelecommunications_recordsz#MATCHED: telecommunications_records#healthcare_beyond_standards_recordsz,MATCHED: healthcare_beyond_standards_recordschildcare_expenses_recordsz#MATCHED: childcare_expenses_recordseducation_expenses_recordsz#MATCHED: education_expenses_recordscourt_ordered_payments_recordsz'MATCHED: court_ordered_payments_recordslife_insurance_recordszMATCHED: life_insurance_recordsinvoluntary_deductions_recordsz'MATCHED: involuntary_deductions_recordsvehicle_ownership_recordsz"MATCHED: vehicle_ownership_recordshealthcare_expenses_recordsz$MATCHED: healthcare_expenses_recordshousing_insurance_recordsz"MATCHED: housing_insurance_recordsvehicle_operation_recordsz"MATCHED: vehicle_operation_recordstaxes_actual_recordszMATCHED: taxes_actual_recordsspouse_business_pl_documentsz%MATCHED: spouse_business_pl_documentsself_employment_pl_documentsz%MATCHED: self_employment_pl_documentscreditor_payment_documentsz#MATCHED: creditor_payment_documentsinsider_benefit_documentsz"MATCHED: insider_benefit_documentszUnsupported file type z for document verification.z[PROMPT SELECTED] file_type='z' | prompt_preview: 
z<============================================================z[PROMPT] file_type: z[PROMPT] system_prompt length: N/Az[PROMPT] preview: ,rU   textz.pdfzDPDF provided but PyMuPDF not installed. Add PyMuPDF to requirements.   )	max_pages	image_urlhighr_   detailrU   r   zFILE_INDEX z URL z PDF_CONVERSION_ERROR rU   r   z"Failed to process PDF for vision: system)rolecontentuser)modelr`   ra   rb   rc   messageszapplication/json)zapi-keyzContent-TypezCCalling Azure OpenAI Vision API (with LlamaParse-extracted text)...)headersjsonzAzure OpenAI API error for : z - 	jailbreakz8[JAILBREAK] Sending Pusher notification for request_id: znotification-channelznotification-eventzPlease verify the document)statusmessagerl   zB[JAILBREAK] Pusher notification sent successfully for request_id: z6[JAILBREAK] Pusher notification failed for request_id content_filterz.Verification failed. Content filter triggered.zPlease check the document.z0%ErrorzContent filter triggered)successerror
error_typer   overall_feedback_textanalysis_resultsoverall_matchconfidence_scoredocument_typemismatch_summaryis_hazy_llamaparse_success
error_code	api_errorz-Verification failed. Azure OpenAI API error: zAPI Error: zAPI request failedchoicesr   r   r   zVerification completezContent filter triggered for z: jailbreak detectedz3Content filter triggered: Please check the documentzGPlease check the document. The content was flagged by security filters.z/Document verification blocked by content filter)r   r   r   r   r   r   r   r   r   r   r   r   zFailed to analyze document: system_errorz-Verification failed. Analysis error occurred.zAnalysis error: )|rO   infolenrP   	parse_urlget_textprint	Exceptionr   !_create_residence_document_prompt_create_residence_user_message_create_vehicle_document_prompt_create_vehicle_user_message_create_bank_statement_prompt#_create_bank_statement_user_message _create_business_document_prompt_create_business_user_messager   _create_response_message_create_address_document_prompt_create_address_user_messager	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   r8   r9   r:   r;   r<   r=   r>   r?   r@   rA   rB   rC   rD   rE   rF   rG   rH   rI   rJ   rK   rL   rM   rN   warning_create_generic_prompt_create_generic_user_message
isinstancestrsplitstripgetextend	enumeratelowerendswithfitz_pdf_url_to_data_imagesappendr\   r`   ra   rb   rc   rZ   aiohttpClientSessionpostr_   okr   criticalr   rQ   triggerr   loads)rd   rh   ri   rj   rk   rl   llamaparse_successparser	documentsesystem_promptuser_messageprompt_previewuurlsrebuiltbtext_blocksidx
pdf_imagesdata_uripdf_errbodyr   sessionresponse
error_text
pusher_errresultr   analysis_results                                  re   verify_documentz!AzureOpenAIClient.verify_documentm   s     	*9+XhZHI #!%KKA#nBUAVV]^_ KK>xjIJ+')QS",,X6	>s9~>NjYZ!'!;%(%81%<"<S=P<QQtuv3C4G3H	R`aebeRfQggjkl --KK68 BBDM>>wR`aL44KK;= BBDM>>wR`aL,, @@BM<<WhP^_L** >>@MCCGXWefL..KK57 AACM==gxQ_`L--KK463M88(N[L/)KK02 @@BM<<WhP^_L++KK242M88(N[L11KK8:6M88(N[L::KKAC*M88(N[L--KK46*M88(N[L//KK68*M88(N[L00KK79-M88(N[L..KK57+M88(N[L>>KKEG;M88(N[L..KK57,M88(N[L88KK?A5M88(N[L77KK>@4M88(N[LQQKK79-M88(N[L00KK79-M88(N[L44KK;=1M88(N[L33KK:<0M88(N[L66KK=?3M88(N[L44KK12G1HIJ1M88(N[L;;KKBD8M88(N[L55KK<>2M88(N[LBBKKIK?M88(N[L77KK>@4M88(N[L22KK9;/M88(N[L33KK:<0M88(N[L--KK464M88(N[L--KK464M88(N[L22KK9;9M88(N[L55KK<><M88(N[L/)KK020M88(N[L88KK?A?M88(N[L33KK:<:M88(N[L..KK464M88(N[L==KKCECM88(N[L22KK9;9M88(N[L55KK<><M88(N[L??KKFHFM88(N[LBBKKIKIM88(N[LFFKKMOMM88(N[L<<KKCECM88(N[LGGKKNPNM88(N[L22KK9;9M88(N[L::KKACAM88(N[LDDKKKMKM88(N[LCCKKJLJM88(N[LJJKKQSQM88(N[L44KK;=;M88(N[L99KK@B@M88(N[L99KK@B@M88(N[L<<KKCECM88(N[L33KK:<:M88(N[L<<KKCECM88(N[L77KK>@>M88(N[L55KK<><M88(N[L88KK?A?M88(N[L99KK@B@M88(N[L??KKFHFM88(N[L66KK=?=M88(N[L??KKFHFM88(N[L66KK=?=M88(N[L66KK=?=M88(N[L::KKACAM88(N[L22KK9;9M88(N[L::KKACAM88(N[L55KK<><M88(N[L77KK>@>M88(N[L55KK<><M88(N[L55KK<><M88(N[L00KK797M88(N[L88KK?A?M88(N[L88KK?A?M88(N[L66KK=?=M88(N[L55KK<><M88(N[L55KK<>>M88(N[L NN3I;>YZ[ 77	BM<<WhOL 1;=#0Nt,TWXeTfgkhkTl3I;>RSaRbbefg6(m$YK01/jQ^`cFdM0Bjo/pqr">"2#67m (('/~~c':H!aggiAGGIHDH"$G&2NaeeFmv6M1NKNNN;'#D/ eQ779%%f-|'(noo}+/+G+GUV+G+W%W
(2 tH#NNKV^jpNq+rst NNKa[aFb#cde #L ~~((0<#$jkkT'+'C'CHXY'C'Z!ZJ ",406'M&N 3?&ZQ!%%-SYBYq&Z&Z#.(22$ "-8W];^_2 $L __//++ZZ#33!m<L9

 ||.

u	KK]_,,. ?+ ?+'"<<'<M >+ >+QY#;;+3==?%:
*Ei[PRS[SbSbRccfgqfr(st '**:*:*<<,	!F$*KK2jkujv0w$x$1$9$9:PRf272N6@i& %'
 %+KK2tu  uA  1B  %C ,0)-.>+[9U461648185O4P+07I.6oo$+>+ >+ >+?+ ?+ ?+P (,%)*5)VW_WfWfVg'h7B:dsCSBT5U02-204-41E0F',3E*2// M>+ >+ >+?+ ?+ ?+n $,==?2F$Y/29=iHG '+jj&9O=OO$9:KK"79*}>+ >+ >+?+ ?+ ?+e  +=aS@_`a+A3/0!%%*"+^ I O &X % }+cURWXYWZZpqxpy@z'{||} "[ '[2 ! T#&H	$RSST6?+>+%: (1 !F$*LL3ijtiuuw  yC  xD  2E  %F  %F!F#>+?+>+?+n 3m>+?+>+ >+ >+?+ ?+ ?+ ?+ ?+B  1	c!flln,!>ykI]^_ !Z	z&^_i^j$kl%--.DFZ&+'\*4] 
 &hisht$uv$ z']^h]iiklvkw%xyyz
  $!"2O-v(*%*(,%,)Z([$+=  OO:3q6(CD  ,J+GAx)P$&!&$(!('7Ax%@$A '9 I1	s  AAc B1AY4 AE%AcI6AZ6JAZ6JAcJ&AZ;K AZ;KAAcLA[L/A[ L0"A[MAAcN A\ N6A[7N7A\ OA[:O0A[:O4A\ O;A[?P
A\ PAAcQ"-A^/ RA\#RA^/ R#A^R6A\&R7A^R:!A]3SA\)SAA]3T#AA\,U.A]3VA^VA]VA^VA^/ V%A]!V&A^/ V*AcV+-A]3WA^W$A]$W%A^W)A^/ W5A]'W6A^/ W:AcW;A]3XA]*XAA]3YA^YA]-YA^Y"A^/ Y.A]0Y/A^/ Y3AcY4	AZ3Y=+AZ.Z(AcZ.AZ3Z3Ac[ A[[	A[4[A[/[)Ac[/A[4[4Ac[7A\ [:
A\ \	A\ \A\\A\ \ Ac\#A^/ \&A^\)A]3\,	A]\5A]]A]3]A]]A]3]A^]!A^/ ]$A^]'A^/ ]*A]3]-A^]0A^/ ]3A^	]9A]<]:A^	^A^^A^/ ^A^^A^/ ^Ac^A^,^ A^#^!A^,^(A^/ ^+Ac^,A^/ ^/
Ac^9<Ac_6AAaaAca	Aa0aAa+a&Aca+Aa0a0AcbAcbAcbAAccAccAccAccAcc                      y)Na  
                        You are an expert KYC document analyzer. You will receive an image/PDF of ANY real estate supporting document, such as:
                        - Property deed
                        - Ownership certificate
                        - Real estate transfer document
                        - Title document
                        - Property valuation statement

                        Your job:
                        1. Extract any visible ownership information (owner name, share percentage, property value, etc.).
                        2. Match ONLY the provided fields. If a field was NOT provided, do not mark it as required.
                        3. If any field is not found in the document, set found_in_document to null and is_match to false.
                        4. Detect if the document image is hazy/blurred (is_hazy true/false).
                        5. Classify the document_type concisely (e.g., "Real Estate Deed", "Property Title Certificate", "Ownership Document", "Unknown").
                        6. Provide overall_match = true only if all provided fields match. If a provided field is missing or mismatch, overall_match = false.
                        7. Provide confidence_score as a percentage.
                        8. Provide mismatch_summary listing only mismatched or missing fields.

                        Return ONLY valid JSON as below:

                        {
                        "analysis_results": [
                            {
                            "field_name": "first_name",
                            "provided_value": "...",
                            "found_in_document": "... or null",
                            "is_match": true/false,
                            "confidence": "high|medium|low"
                            },
                            {
                            "field_name": "last_name",
                            "provided_value": "...",
                            "found_in_document": "... or null",
                            "is_match": true/false,
                            "confidence": "high|medium|low"
                            },
                            {
                            "field_name": "name",
                            "provided_value": "...",
                            "found_in_document": "... or null",
                            "is_match": true/false,
                            "confidence": "high|medium|low"
                            },
                            {
                            "field_name": "share",
                            "provided_value": "...",
                            "found_in_document": "... or null",
                            "is_match": true/false,
                            "confidence": "high|medium|low"
                            },
                            {
                            "field_name": "value",
                            "provided_value": "...",
                            "found_in_document": "... or null",
                            "is_match": true/false,
                            "confidence": "high|medium|low"
                            }
                        ],
                        "overall_match": true/false,
                        "confidence_score": "85%",
                        "document_type": "Real Estate Deed",
                        "mismatch_summary": ["value mismatch"],
                        "is_hazy": false,
                        "additional_notes": "optional"
                        }

                        Rules:
                        - Only match fields that are provided in the input JSON.
                        - Do not assume any field is mandatory.
                        - Missing value is considered mismatch.
                        - Partial similarity counts as mismatch.
                        - Document classification must be truthful even if file_type differs.
                         rd   s    re   "_create_realestate_document_promptz4AzureOpenAIClient._create_realestate_document_prompt  s    Hrg   c                      y)Nu7	  You are an expert KYC document analyzer.
                You will receive an image/PDF and a JSON input containing the exact fields that must be verified.
                Your responsibilities:
                1. Extract and verify following fields provided in the JSON:
                - first_name
                - middle_name
                - last_name
                - to_date
                - from_date
                - full_address


                2. For each provided field:
                - Extract the value from the document.
                3. GENERIC ENHANCED EXTRACTION RULE (applies to ALL FIELDS):
                ------------------------------------------------------------
                If the exact field value is NOT found:
                - Attempt to extract the closest semantically related text.
                4. Detect document clarity:
                - is_hazy = true/false
                5. STRICT JSON RESPONSE FORMAT (MANDATORY):
                {
                "analysis_results": [
                    {
                    "field_name": "... or null",
                    "provided_value": "...",
                    "found_in_document": "... or null",
                    "is_match": true/false,
                    "partial_match": true/false,
                    "confidence": "high|medium|low"
                    }
                ],
                "overall_match": true/false,
                "document_type": "...",
                "confidence_score": "0-100%",
                "mismatch_summary": ["..."],
                "is_hazy": false,
                "extracted_financials": {
                    "extracted_claim_amount": "... or null",
                    "extracted_collateral_value": "... or null"
                }
                }
                ENFORCEMENT RULES:
                - MANDATORY: Return analysis for EVERY field present in input JSON. Missing any field from analysis_results is strictly forbidden.
                - Return ONLY fields present in input JSON.
                - Never hallucinate missing values.
                - If document is unrelated → classify as "Unknown Document" and mark all fields mismatched.
                - Output STRICT JSON only.
                - Don't return null value in found_in_document, always return closest match text
                r(  r)  s    re   r   z1AzureOpenAIClient._create_address_document_prompt#  s    1rg   c                      y)z`System prompt for residence document verification including haze + document type classification.a  You are an expert KYC document analyzer. Task: Given an image/PDF of a potential residence or identity document and provided structured personal & address data, you must:
                1. Extract any visible personal name components and address components.
                2. For each provided field, state if found, and whether it matches (exact, partial, no match, not found).
                3. Detect if the document image is hazy/blurred/low-quality (return true/false as is_hazy based on readability of text, artifacts, lighting, focus).
                4. Classify the document type with a concise label (e.g., 'US Driver License', 'US Utility Bill', 'Indian Aadhaar Card', 'Indian PAN Card', 'Residence Lease', 'Bank Statement', 'Unknown', ).
                5. Provide an overall_match boolean: true only if all mandatory fields (first_name, last_name, city, state, zip_code, street_name, house_number) are matches (partial counts as mismatch).
                6. Provide a confidence_score as a percentage string based on clarity + number of matches.
                7. Populate mismatch_summary with short strings for each mismatch.

                JSON RESPONSE REQUIRED (no extra text) with structure:
                {
                    "analysis_results": [
                        {"field_name": "first_name", "provided_value": "...", "found_in_document": "... or null", "is_match": true/false, "confidence": "high|medium|low"},
                        ...
                    ],
                    "overall_match": true/false,
                    "confidence_score": "85%",
                    "document_type": "US Driver License",
                    "mismatch_summary": ["city mismatch"],
                    "is_hazy": false,
                    "additional_notes": "optional notes"
                }
                Rules:
                - Partial spell differences or abbreviations count as mismatch (list them).
                - If a field isn't present, found_in_document = null and is_match = false.
                - is_hazy true only if significant portions of text are unreadable.
                - document_type must be one short label.
                r(  r)  s    re   r   z3AzureOpenAIClient._create_residence_document_promptY  s    rg   c                     d| dS )Nz1You are a document analyzer. File type category: z. Extract key data and classify document. Return a JSON object with keys: analysis_results, overall_match, confidence_score, document_type, mismatch_summary, is_hazy, additional_notes.r(  )rd   rh   s     re   r   z(AzureOpenAIClient._create_generic_promptx  s    C+ AA 	Brg   c                      y)Nu
  You are an expert financial document analyzer. 
                You will receive an image/PDF and a JSON input containing the exact fields that must be verified.

                    Your responsibilities:

                    1. Extract and verify following fields provided in the JSON:
                    - first_name
                    - middle_name
                    - last_name
                    - bank_name
                    - account_type
                    - balance

                    2. For each provided field:
                    - Extract the value from the document.
                    
                    3. GENERIC ENHANCED EXTRACTION RULE (applies to ALL FIELDS):
                    ------------------------------------------------------------
                    If the exact field value is NOT found:
                    - Attempt to extract the closest semantically related text.

                    4. Detect document clarity:
                    - is_hazy = true/false

                    5. STRICT JSON RESPONSE FORMAT (MANDATORY):

                    {
                    "analysis_results": [
                        {
                        "field_name": "... or null",
                        "provided_value": "...",
                        "found_in_document": "... or null",
                        "is_match": true/false,
                        "partial_match": true/false,
                        "confidence": "high|medium|low"
                        }
                    ],
                    "overall_match": true/false,
                    "document_type": "...",
                    "confidence_score": "0-100%",
                    "mismatch_summary": ["..."],
                    "is_hazy": false,
                    "extracted_financials": {
                        "extracted_claim_amount": "... or null",
                        "extracted_collateral_value": "... or null"
                    }
                    }

                    ENFORCEMENT RULES:
                    
                    - Return ONLY fields present in input JSON.
                    - Never hallucinate missing values.
                    - For 'amount' field: confidence should be "low" if exact value/attribute name not found, "medium" if partial/full match.
                    - If document is unrelated → classify as "Unknown Document" and mark all fields mismatched.
                    - Output STRICT JSON only.
                    - Don't return null value in found_in_document, always return closest match text
            r(  r)  s    re   r   z/AzureOpenAIClient._create_bank_statement_prompt}  s    8rg   datac                    dg}|rX|j                  d       |j                  d       |j                  |dd        |j                  d       |j                  d       |j                         D ];  \  }}|j                  dd      j                         }|j                  | d	|        = |j                  d
       dj	                  |      }d|dd|dddgS )z
        Dynamically builds the user message for bank statement verification.
        Only includes fields provided by the client.
        z"Bank Statement Verification Input: !--- LLAMAPARSE EXTRACTED TEXT ---N  --- END LLAMAPARSE TEXT ---_ r   )Return JSON only per system instructions.r   r   r   r   r   r   r   r  itemsreplacetitlejoin	rd   r/  rj   rk   lineskeyvalue
pretty_keyr   s	            re   r   z5AzureOpenAIClient._create_bank_statement_user_message  s    
 66 LLLL<=LL./LL67LL**, 	3JCS#.446JLLJ<r%12	3
 	@Ayy T* x6/RS
 	
rg   c                    dg}|rX|j                  d       |j                  d       |j                  |d d        |j                  d       |j                  d       |j                  d|j                  dd              |j                  d	|j                  d
d              |j                  d|j                  dd              |j                  d|j                  dd              |j                  d|j                  dd              |j                  d|j                  dd              |j                  d|j                  dd              |j                  d|j                  dd              |j                  d|j                  dd              |j                  d       dj                  |      }d|dd|ddd gS )!Nz&Residence Document Verification Input:r1  r2  r3  r4  First Name: 
first_namer   Middle Name: middle_nameLast Name: 	last_namezCity: cityzState: statezCounty: countyz
ZIP Code: zip_codezStreet Name: street_namezHouse Number: house_numberr7  r   r   r   r   r   r   r   )r  r   r<  rd   r/  rj   rk   r>  r   s         re   r   z0AzureOpenAIClient._create_residence_user_message  s   9: LLLL<=LL./LL67LL|DHH\%$@#ABC}TXXmB%?$@AB{488K#>"?@Avdhhve4567wtxx6789x% 89:;z$((:e"<!=>?}TXXmE%B$CDE~dhh~e&D%EFG@AyyT* x6/RS
 	
rg   c                    dg}|rX|j                  d       |j                  d       |j                  |dd        |j                  d       |j                  d       |j                         D ];  \  }}|j                  dd      j                         }|j                  | d	|        = |j                  d
       dj	                  |      }d|dd|dddgS )z
        Dynamically builds the user message for residence/identity verification.
        Only includes fields provided by the client. Prevents forcing unnecessary fields.
        Document Verification Input:r1  r2  Nr3  r4  r5  r6  r   r7  r   r   r   r   r   r   r   r8  r=  s	            re   r   z.AzureOpenAIClient._create_address_user_message  s     00 LLLL<=LL./LL67LL**, 	3JCS#.446JLLJ<r%12	3
 	@Ayy T* x6/RS
 	
rg   c                     t         S )aT  System prompt for vehicle document verification.you are an expert vehicle document analyzer.
        You will receive an image/PDF of a vehicle-related document (e.g., registration card, title certificate, insurance card) along with a JSON input containing the exact fields that must be verified

        Focus on:
        - Extract and compare following fields (first_name, middle_name, last_name) if present.
        - if middle name is not provided, dont change provided_value to N/A, keep it as send by user.
        - Matching provided fields (year, maker, model, mileage, current_value, vehicle_number).
        - Extracting vehicle registration/plate number and confirming match.
        - Extracting model and confirming match.
        - Detecting document expiry date (e.g., registration card validity) and whether it's expired as of today.
        - Classifying the document type (e.g., 'Vehicle Registration Card', 'Insurance Card', 'Title Certificate').
        - Haze/quality detection.

        JSON response must include analysis_results per provided fields and vehicle_details block.
        )r   r)  s    re   r   z1AzureOpenAIClient._create_vehicle_document_prompt4  s
      rg   c                    dg}|rX|j                  d       |j                  d       |j                  |d d        |j                  d       |j                  d       |j                  d|j                  dd       d|j                  d	d       d
|j                  dd       d|j                  dd       d|j                  dd       d|j                  dd       d|j                  dd       d|j                  dd       d|j                  d|j                  dd             dg
       dj                  |      }d|dd|ddd gS )!Nz$Vehicle Document Verification Input:r1  r2  r3  r4  zOwner First Name: rD  zOwner Middle Name: rF  zOwner Last Name: rH  zYear: yearzMaker: makerzModel: r   z	Mileage: mileagezCurrent Value: current_valuezVehicle Number: number
vehicle_nor7  r   r   r   r   r   r   r   r  r  r   r<  rO  s         re   r   z.AzureOpenAIClient._create_vehicle_user_messageF  sh   78 LLLL<=LL./LL67LL ,r!: ;<!$((="<!=>R 89:TXXfR()*dhhwr*+,dhhwr*+,2./0dhhr:;<txx$((<2KLMN7
 	 yyT* x6/RS
 	
rg   c                      y)NuV	  You are an expert business document analyzer.
                You will receive an image/PDF and a JSON input containing the exact fields that must be verified.
                Your responsibilities:
                1. Extract and verify following fields provided in the JSON:
                - first_name
                - middle_name
                - last_name
                - ein
                - business_type
                - location
                - business_name
                2. For each provided field:
                - Extract the value from the document.
                3. GENERIC ENHANCED EXTRACTION RULE (applies to ALL FIELDS):
                ------------------------------------------------------------
                If the exact field value is NOT found:
                - Attempt to extract the closest semantically related text.
                4. Detect document clarity:
                - is_hazy = true/false
                5. STRICT JSON RESPONSE FORMAT (MANDATORY):
                {
                "analysis_results": [
                    {
                    "field_name": "... or null",
                    "provided_value": "...",
                    "found_in_document": "... or null",
                    "is_match": true/false,
                    "partial_match": true/false,
                    "confidence": "high|medium|low"
                    }
                ],
                "overall_match": true/false,
                "document_type": "...",
                "confidence_score": "0-100%",
                "mismatch_summary": ["..."],
                "is_hazy": false,
                "extracted_financials": {
                    "extracted_claim_amount": "... or null",
                    "extracted_collateral_value": "... or null"
                }
                }
                ENFORCEMENT RULES:
                - MANDATORY: Return analysis for EVERY field present in input JSON. Missing any field from analysis_results is strictly forbidden.
                - Return ONLY fields present in input JSON.
                - Never hallucinate missing values.
                - If document is unrelated → classify as "Unknown Document" and mark all fields mismatched.
                - Output STRICT JSON only.
                - Don't return null value in found_in_document, always return closest match text
                r(  r)  s    re   r   z2AzureOpenAIClient._create_business_document_promptc  s    0rg   c                 T   dg}|rX|j                  d       |j                  d       |j                  |d d         |j                  d       |j                  d       |j                  d|j                  dd       d|j                  dd       d	|j                  d
d       d|j                  dd       d|j                  d|j                  dd             d|j                  dd       d|j                  dd       dg       dj                  |      }d|dd|dddgS )Nz%Business Document Verification Input:r1  r2  r4  rC  rD  rE  rF  rG  rH  zEIN: einzBusiness Type: business_typerU   z
Location: locationzBusiness Name: business_namer7  r   r   r   r   r   r   r   rZ  rO  s         re   r   z/AzureOpenAIClient._create_business_user_message  s:   89 LLLL<=LL*+LL67LL488L456DHH]2678$((;r234DHHU2&'(dhh8KLMN*R012dhhr:;<7	
 		 yyT* x6/RS
 	
rg   c                 $    dd| ddd|dddgS )	Nr   zGeneric file_type input: z. Return structured JSON.r   r   r   r   r   r(  )rd   r/  rj   s      re   r   z.AzureOpenAIClient._create_generic_user_message  s,    '@F_%`a x6/RS
 	
rg   pdf_urlr   c                   K   t        j                         4 d{   }|j                  |      4 d{   }|j                  st	        d|j
                         |j                          d{   }ddd      d{    ddd      d{    	 t        j                  d      }g }t        |      D ]i  \  }	}
|	|k\  r n_|
j                  d      }|j                  d      }t        j                  |      j                  d	      }d
| }|j                  |       k |st	        d      |S 7 7 7 7 # 1 d{  7  sw Y   xY w7 # 1 d{  7  sw Y   xY w# t        $ r}t	        d|       d}~ww xY ww)zwDownload a PDF from URL and convert up to max_pages to PNG data URIs.
        Uses PyMuPDF; raises if conversion fails.NzFailed to download PDF: pdf)streamfiletypezUnable to open PDF:    )dpipngzutf-8zdata:image/png;base64,zNo pages converted from PDF.)r  r	  r   r  r   r   readr  openr  
get_pixmaptobytesbase64	b64encodedecoder  )rd   rb  r   r   resp	pdf_bytesdocr  imagesipagepix	png_bytesb64r  s                  re   r  z)AzureOpenAIClient._pdf_url_to_data_images  s}     ((* 	. 	.g{{7+ . .tww#&>t{{m$LMM"&))+-	. .	. 	.
	8))9u=C  ~ 	$GAtI~//c/*CE*I""9-44W=C/u5HMM(#	$ :;;)	.. .. . . .	. 	. 	. 	.  	821#677	8s   FD6FED9E8E 1D<2E 6ED>EFEFE, .B	F9E<E >E E	E	E	EFE)E E)%F,	F5FFFc                    dg}|rU|j                  d       |j                  d       |j                  |       |j                  d       |j                  d       |j                         D ];  \  }}|j                  dd      j                         }|j                  | d|        = |j                  d       d	j	                  |      }t        |       |S )
a  
        Dynamically builds the user message for residence/identity verification.
        Only includes fields provided by the client. Prevents forcing unnecessary fields.
        Includes LlamaParse-extracted text if available for better accuracy.
        rQ  r1  r2  r4  r5  r6  r   r7  r   )r  r9  r:  r;  r<  r   r=  s	            re   r   z*AzureOpenAIClient._create_response_message  s     00 LLLL<=LL(LL67LL**, 	3JCS#.446JLLJ<r%12	3
 	@Ayydrg   )NNNN)NN)N)r   )__name__
__module____qualname____doc__rf   r   r   r&  r*  r   r   r   r   r   r   r   r   r   r   r   r   r   intr  r   r(  rg   re   rS   rS   \   s   \kf	s f	T f	S f	be f	z} f	  JN f	RIC IZ2 2l3 >B B B
Is IX&
 
 
]` 
lpqulv 
:
4 
3 
X[ 
gklpgq 
8
 
 
VY 
eijneo 
> $
 
 
VY 
eijneo 
:2# 2h
$ 
# 
WZ 
fjkofp 
6
 
 
d 
S S QUVYQZ 4T S RU ad rg   rS   )]r  r   rn  typingr   r   r   src.core.configr   $src.modules.prompt.schemas.responsesr   src.modules.prompt.promptsr   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   r8   r9   r:   r;   r<   r=   r>   r?   r@   rA   rB   rC   rD   rE   rF   rG   rH   rI   rJ   rK   rL   rM   rN   src.core.loggingrO   src.utils.pdf_parserrP   src.utils.pusher_configrQ   r  ImportErrorrS   azure_openai_clientr(  rg   re   <module>r     s         $ <I I I I I I I I I I I I I I I I I I IT $ / 1
P Pr$ () {$  Ds   C$ $C.-C.