o
    f j#m                     @   sb  d dl Z d dlZd dlZd dlmZ d dlmZ d dlmZ d dl	m
Z
 d dlmZ d dlmZ d dlmZ d d	lmZ d d
lmZ edd ee ddZedZdedefddZdedefddZdedefddZdededefddZdededed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defd$d%Z!ded!edefd&d'Z"dS )(    N)Path)OpenAI)load_dotenv)extract_document)validate_extraction)detect_exceptions)perform_rca)generate_capa)generate_full_reportT)overrideOPENAI_API_KEY)api_keyuploadsextractionsreturnc                 C   s   |  dg }tdd |D d tdd |D d tdd |D d dd |D dd |D d	d |D d
d |D dd |D tdd |D i d	S )Nfilesc                 s   $    | ]}| d r| d V  qdS )batch_idNget.0e r   )/var/www/html/fyndo/pharma/fyndo/agent.py	<genexpr>      " zflatten.<locals>.<genexpr>c                 s   r   )product_nameNr   r   r   r   r   r      r   c                 s   r   )plantNr   r   r   r   r   r      r   c                 S   "   g | ]}| d g D ]}|q
qS )
parametersr   )r   r   pr   r   r   
<listcomp>      " zflatten.<locals>.<listcomp>c                 S   r   )lims_resultsr   )r   r   lr   r   r   r"       r#   c                 S   r   )equipment_readingsr   )r   r   eqr   r   r   r"   !   r#   c                 S   r   )maintenance_recordsr   )r   r   mr   r   r   r"   "   r#   c                 S   r   )
sop_limitsr   )r   r   sr   r   r   r"   #   r#   c                 s   sF    | ]}| d i  ds| d i  di  dr| d V  qdS )deviation_detailsdeviation_iddeviation_recordDeviation_IDNr   r   r   r   r   r   %   s    )	r   r   r   r    r$   r&   r(   r*   r,   )r   next)r   r   r   r   r   flatten   s   r1   uploaded_filesc                    s   t d dd | D }ttj| I dH }|t|d}t|}t dt|d  dt|d	  d
t|d  dt|d   ||dS )u*   Tool 1 — Extract all data from all filesu9   [AGENT TOOL] extract_files — reading all uploaded filesc                 S   s   g | ]
}t t|d   qS filename)r   
UPLOAD_DIRr   fr   r   r   r"   4   s    z&tool_extract_files.<locals>.<listcomp>N)r   total_filesu"   [AGENT TOOL] extracted — params:r    z lims:r$   z equipment:r&   z maintenance:r(   )combinedflat)printlistasynciogatherlenr1   )r2   tasksr   r9   r:   r   r   r   tool_extract_files1   s   @
rA   r:   c              
      sn  t d t| I dH }i }| dg D ]}t|dddd }|d}|r/|r/|||< q|dg D ]&}|d	s\t|dddd }||pY|rXt| d
 nd|d	< q6i }| dg D ].}t|dd  t|dd }	t|dd }
 rd|	v sd|
v rd| < qe|dg D ] }t|dd  t fdd| D d}|r||d< qt	dd |dg D }t	dd |dg D }|dr||d d< ||d d< | di }|d|}|dp|d}|dkr|drd|d d< |drd|d d< t d |di d!d
 d"| d#|di d  |S )$u/   Tool 2 — Detect all exceptions from flat dataz[AGENT TOOL] detect_exceptionsNr&   	timestamp    operator_id
exceptionsoperatorr   r*   parameter_namecriticalityaction_if_exceededcriticalzstop immediatelyCritical	parameterc                 3   s(    | ]\}}| v s |v r|V  qd S )Nr   )r   kvparamr   r   r   Y      & z)tool_detect_exceptions.<locals>.<genexpr>severityc                 s   "    | ]}| d dkrdV  qdS )rS   rL      Nr   r   r   r   r   r   ]        c                 s   rT   )rS   MajorrU   Nr   r   r   r   r   r   ^   rV   summarymajorr,   r.   Severity
risk_level
batch_risklevelu(   [AGENT TOOL] exceptions found — total:total_exceptionsz
 critical:z risk:)
r;   r   r   strr<   valueslowerr0   itemssum)r:   resultop_mapr'   tsopexsop_criticalitysoprI   actionmatchedrK   rY   	deviation
dev_recordreal_severityr   rP   r   tool_detect_exceptions<   sX   

&

8rp   rF   c              
      s  t d | dg }| dg }g }|D ]D}t|dd }t|dd }d|v s?d|v s?d	|v s?d
|v s?d|v rY||d|d|d|d|dd qdd |D }| |||dd d}	t|	I dH }
dd | di gD }tdd |D d}tdd |D d}i }| dg D ]}t|dddd }|d}|r|r|||< q|
di d g D ]6}|dst|dddd }||p|rt| d! nd|d< t|d"pd	d#r||d"< q|
d$g D ]A}|ds't|dddd }||p$|r#t| d! nd|d< t|d%p/d	d#s;|d%s?||d%< q| d&i }|d'|}|d(d)ks\|d*d)krh|
d+rhd)|
d+ d,< | dg }d-d |D }|r|
d$du rg |
d$< |dd. D ]?}|pd|dd|ddp|ddt|dd|d/dd0}d1d |
d$ D }|d|vr|
d$ | qt d2|
d+i d, d3t
|
d$g   |
S )4u&   Tool 3 — Perform root cause analysisz[AGENT TOOL] perform_rcar(   r&   observationrC   statusoverduedrift	oxidationurgentcalibrationwork_order_idmaintenance_dateaction_taken)rx   ry   rq   rz   rr   c                 S   s(   g | ]}t |d d dv r|qS )rr   rC   )ALERT	DEVIATION)r_   r   upperr   r   r   r   r"      s   ( z$tool_perform_rca.<locals>.<listcomp>N   )extracted_datarF   key_maintenance_recordsalert_equipment_readingsc                 S   s   g | ]}| d dqS )r4   rC   r   r6   r   r   r   r"      s    r    c                 s        | ]}d t |v r|V  qdS )	EquipmentNr_   r6   r   r   r   r          z#tool_perform_rca.<locals>.<genexpr>zEquipment_Log.csvc                 s   r   )MaintenanceNr   r6   r   r   r   r      r   zMaintenance_Log.csvrB   rD   rE   cluster_contextvertical_timeliner   source_filefile_supporting_evidencer4   r,   r.   rZ   rL   rS   investigation_summaryr[   c                 S   sp   g | ]4}d t |dd v s4dt |dd v s4dt |dd v s4dt |dd v r|qS )rs   rr   rC   rt   rq   rv   rw   r_   r   ra   r   r)   r   r   r   r"      s       performed_by)r4   	referencedetailrB   rE   c                 S   s   g | ]}| d qS )r   r   r   r   r   r   r"      s    u   [AGENT TOOL] rca done — risk:z
 evidence:)r;   r   r_   ra   appendr   r0   r<   r`   
startswithr?   )r:   rF   maintenance	equipmentkey_maintenancer)   obsrr   alert_readings	rca_inputrd   
real_files
equip_file
maint_filere   r'   rf   rg   itemevrm   rn   key_recordsmaint_evexistingr   r   r   tool_perform_rcaq   s   (	


&*( 

.r   rcac           	         s   t d | ||d}t|I dH }| di }|d|}|dp'|d}|dp1|d	}|r8||d< |rO||d	< |d
rO||d
 d< d|d
 d< t d|d d|d	  |S )u   Tool 4 — Generate CAPA planz[AGENT TOOL] generate_capa)r   rF   r   Nr,   r.   r/   r-   rZ   rS   impact_assessmentpre_capa_riskLowresidual_risku(   [AGENT TOOL] capa done — deviation_id:z
 severity:)r;   r	   r   )	r:   rF   r   
capa_inputrd   rm   rn   real_dev_idro   r   r   r   tool_generate_capa   s"   
 r   capabase_urlc           *         s  t d | |||d}t||I dH }| di }|d|}|dp)|d}	|	r7|dr7|	|d d< i }
| d	g D ]}t|d
ddd }|d}|rZ|rZ||
|< q?|
ret|
 d nd}|di dr|d d }|dd| }|dd| }||d d< | dg }tdd |D d}|r:|dd}ddl}t|dd}|	d|}|r|
d}d| d}nd}|di d r|d d  }t|d!d}d"D ]}|||}q|r|d#||}|d$||}||d!< t|d%d}|r|d#||}||d%< |di d&r:t|d d& }d"D ]	}|||}q*||d d&< | di }|d|}|d'i }t|d(d}|	d)||j}|r|
d d*} |di d r|d d  }t|d!d}|d+d,|  |}|d-|  d.|}||d!< |d/i }!|!d0d}"|"rt|di }#d1|#v r|di }$d2D ]H}%|$|%rt|$|% tr|$|%  D ]\}&}'t|'trd1|'v r|d3|"|'|$|% |&< qҐqt|$|% tr|d3|"|$|% |$|%< q|d4r|d3|"|d4 |d4< |di d5r6|d d5 D ]}(|(d6d7v r4d8|(d6< q&|d9rP|d9 D ]})|)d6d:krNd;|)d6< q@t d<|di d=  |S )>u(   Tool 5 — Generate final report and PDFz[AGENT TOOL] generate_report)r   rF   r   r   Nr,   r.   rZ   rS   report_metadatar&   rB   rC   rD   rE   r   Unknownsectionsdeviation_descriptionzoperator ID was not recordedzoperator ID: z The operator ID was not recordedzOperator ID: r(   c                 s   s(    | ]}d t |ddv r|V  qdS )0401rx   rC   N)r_   r   r   r   r   r   r     rR   z'tool_generate_report.<locals>.<genexpr>rx   zWO-2024-0401rq   z[+](\d+\.?\d+|\d+)rU   +u   °Croot_cause_analysisprobable_cause)zWO-2024-0456zWO-2024-045zWO-2024-046u   [+]\d+\.?\d*°Cz[+]\d+\.?\d*\s*degrees?
conclusioncapa_summaryEquipment_DetailsCalibration_Statusz(\d+)\s*days?\s*past\s*duez dayszoverdue by \d+ dayszoverdue by z\d+ days? overduez overdueLinked_RecordsOOS_ReferenceOOS)r   r   r   executive_summaryz0OOS[-\s]?\d{4}[-\s]?\d{4}|OOS[-\s]?\d{4}|OOS-\d+ai_generated_summaryregulatory_compliancerr   )zNon-CompliantfailzUnder Reviewcompliance_checklistr   warnu!   [AGENT TOOL] report done — ref:ref_id)r;   r
   r   r_   r<   r`   replacer0   researchgroupsub
IGNORECASEjsondumps
isinstancedictrb   )*r:   rF   r   r   r   report_inputrd   rm   rn   ro   re   r'   rf   rg   first_operatordescr(   	breakdownwo_idr   r   drift_matchnum
real_driftrca_secprobablewrong_wor   capa_sum
eq_details
cal_statusoverdue_matchreal_overduelinkedreal_oosrca_textr   section_keyrN   rO   regr   r   r   r   tool_generate_report   s   


r   c                    s\  t d g }d}t }|dg D ]}|dr||d  q|dg D ]}|dr4||d  q&|dg D ]}|dg D ]}	||	 qCq;t| }
d	|
v s[d
|
v r`|d d|
v sld|
v sld|
v rq|d d|
v s}d|
v s}d|
v r|d d|
v rd|
v r|d t|dk r|dt| d |d8 }t dt| dt|dkrdnd  | di }|d |}|d!p|d"}|d#pi d$}|d%kr|d%kr|d&|  |d'8 }|d#d(urd%|d# d$< nd$d%i|d#< t d)| d*| d||krdnd+  t	d,d- |d.g D }|d/kr4|| d0 |d18 }t d2| d|d/kr@dnd3  | d4g }t|  d v p|d5 v p|d6 v p|d v p|t
 fd7d-|D p|t
 fd8d-|D }|s|r|d9 |d18 }t d:| d|rdnd  d;d< | d=g D }d|
 v pd|
 v pd|
 v }|r|s|t| d> |d18 }t d?| d|rdnd  |dg }t
d@d- |D }|s|dA |d18 }t dB| d|rdnd3  t dC| dDt|  |r#|D ]
}t dE|  q||dFk||dFkdGS )Hzl
    Agent checks its own work before generating CAPA.
    Returns confidence score and any gaps found.
    z+[AGENT REFLECT] Starting self reflection...d   r   r4   	five_whysevidence_sourceroot_cause_candidatesevidence_refsr   eqp_granequipment_datar   
work_orderzwo-maintenance_datalimsassayoos	lims_datarm   zdev-deviation_data   zOnly u%    evidence sources — need at least 3   z"[AGENT REFLECT] Evidence sources: u    — OKWEAKr,   r.   rZ   rS   r   r[   rL   uB   Risk level mismatch — Deviation JSON says Critical but RCA says    Nz[AGENT REFLECT] Risk level: z vs Deviation JSON: FIXEDc                 s   s    | ]
}| d sdV  qdS )rG   rU   Nr   )r   rh   r   r   r   r     s    zself_reflect.<locals>.<genexpr>rF   r   z exceptions have null operator
   z [AGENT REFLECT] Null operators: ISSUEr(   rw   z
work orderc                 3   s(    | ]}t |d d  v V  qdS )rx   rC   Nr   r   rca_text_lowerr   r   r     rR   c                 3   sH    | ]}t |d d  dd v rdt |dd v V  qdS )rq   rC   Nr   rs   rr   r   r   r   r   r   r     s     z6Maintenance records not sufficiently referenced in RCAz([AGENT REFLECT] Maintenance referenced: c                 S   s   g | ]}| d dkr|qS )rr   Failr   )r   r%   r   r   r   r"     s    z self_reflect.<locals>.<listcomp>r$   z# LIMS failures not mentioned in RCAz'[AGENT REFLECT] LIMS impact mentioned: c                 s   s    | ]}| d V  qdS )is_rootNr   )r   wr   r   r   r     s    z No root why identified in 5 Whysz([AGENT REFLECT] 5 Whys root identified: z[AGENT REFLECT] Score: u   /100 — Issues: u   [AGENT REFLECT] → F   )score	confidentissuesproceed)r;   setr   addr   r   ra   r?   r   rc   any)r:   rF   r   r  r   sources_usedr   r   rcrefr   rm   rn   ro   rca_risknull_operatorsr   maintenance_referenced
lims_failsrca_mentions_limsr   has_rootissuer   r   r   self_reflectn  s   





((
"
	
(
r  c                    sh  t d t d t ddd | D   t d g }t d |d t| I d	H }|d
 }|d }t d t dt|d   t dt|d   t dt|d   t dt|d   t dt|d   t dt|d   |dt|d  dt|d  dt|d  d t d |d t|I d	H }tdd  |d!g D }t d"|  |d#| d$ t d% |d& t|I d	H }|d'i d(d)}	|d'i d*d)}
t d+|	 d,|
  |d-|	 d.|
 d/ t d0 |d1 t	||I d	H }|d2i d3}t d4|  |d5|  t d6 |d7 t
|||}t d8|d9  d: |d;|d9  d: |d< st d=|d9  d> |d?|d9   t	||I d	H }t
|||}t d@|d9  d: |dA|d9  d: t dB |dC t|||I d	H }t dDt|dEg  dF |dGt|dEg  dH t dI |dJ t|||||I d	H }t dK|dL  |dM|dL  t d t dN t dO|d9  d: t dP|dQ  t dR|dSi dT  t dU|dL  t d ||d9 |dV |dQ|dW||||||dX|dLdYdZS )[u   
    ReAct Agent — runs full pharma investigation with reasoning and self reflection.
    No predefined file names. Adapts to whatever files are uploaded.
    z3
==================================================z*[AGENT] Starting ReAct Investigation Agentz[AGENT] Files to investigate: c                 S   s   g | ]}|d  qS r3   r   r6   r   r   r   r"     s    z+run_investigation_agent.<locals>.<listcomp>z3==================================================
u5   [AGENT] Phase 1 — Extracting data from all files...z!Phase 1: Extracting all file dataNr9   r:   z[AGENT] Data available:z  Parameters:    r    z  LIMS Results:  r$   z  Equipment:     r&   z  Maintenance:   r(   z  SOP Limits:    r*   z  Deviation:     r,   zExtracted: z	 params, z LIMS, z equipment readingsu-   
[AGENT] Phase 2 — Validating parameters...zPhase 2: Validating parametersc                 s   rT   )validation_statusr|   rU   Nr   )r   rr   r   r   r     rV   z*run_investigation_agent.<locals>.<genexpr>validation_rowsu.   [AGENT] Validation done — deviations found: zValidation: z deviations foundu,   
[AGENT] Phase 3 — Detecting exceptions...zPhase 3: Detecting exceptionsrX   r^   r   rK   z[AGENT] Exceptions: total=z
 critical=zExceptions: z total, z	 criticalu6   
[AGENT] Phase 4 — Performing root cause analysis...zPhase 4: Root cause analysisr   r[   u!   [AGENT] RCA done — risk level: zRCA: risk level = u'   
[AGENT] Phase 5 — Self reflection...zPhase 5: Self reflectionz[AGENT] Reflection score: r   z/100zSelf reflection score: r  z
[AGENT] Confidence too low (z&). Re-running RCA with more context...u"   Re-running RCA — confidence was z![AGENT] Re-run reflection score: zRe-run reflection score: u,   
[AGENT] Phase 6 — Generating CAPA plan...zPhase 6: Generating CAPAu   [AGENT] CAPA done — capa_actionsz actionszCAPA: z actions generatedu/   
[AGENT] Phase 7 — Generating final report...zPhase 7: Generating reportu   [AGENT] Report done — pdf_filenamezReport: z[AGENT] Investigation Completez[AGENT] Confidence: z[AGENT] Batch: r   z[AGENT] Severity: r   rS   z[AGENT] PDF: r  r   download_url	completed)	agent_logconfidence_scorereflection_issuesr   r   validaterF   r   r   reportr  r  rr   )r;   r   rA   r?   boolr   rc   r   rp   r   r  r   r   )r2   r   r  
extractionr9   r:   validate_resultdeviations_foundrF   total_excritical_exr   risk
reflectionr   r  r   r   r   run_investigation_agent  s   
6






r&  )#osr   r=   pathlibr   openair   dotenvr   extractr   r  r   rF   r   r   r   r   r	   r  r
   getenvclientr5   r   r1   r<   rA   rp   r   r   r_   r   r  r&  r   r   r   r   <module>   s0    
5]" 
k