
    /cjV                     4   d Z ddlZi dddddddddd	d
dddddddddddddddddddddd d!d"d#d$d%d&d'Zd(d)d*d+d,d-d.d/d0Zd1d2d3d4Zi d5dd6d	d7dd8dd9dd:dd;dd<dd=dd>dd?dd@ddAddBd!dCd"dDd#dEd$d%d&d(d)dFdGdHdIdJdKdLdMdNdOdPZh dQZi dRdSdTdSdUdSdVdSdWdXdYdXdZdXd[dXd\dXd]dXd^dXd_dXd`dXdadadbdadcdddedddddddddddSdfZdSdSdXdXdXdXdXdadgZdh Z	di Z
dj Zdk Zdl Zdm Zdn Zdo ZdpdqdrZdsZdtZdu Zdv Zdw Zdx ZdzdyZdS ){uP  
Tier 0 faithfulness assessment — deterministic, no LLM, no network.

Checks each AI turn's factual number/ID/date claims against the injected
context (e.g. [OUTGOING], [AGENTDATA], [EXTENSIONS], agent_data) plus what
the caller has already said. A claim is "grounded" if its value appears in
that combined grounding set; otherwise it is flagged as unsupported.

This module is pure and side-effect-free: it does not touch the network,
the model, or any session state. It is called post-call and its result is
attached to the saved conversation log. English spoken/digit forms are
fully supported; Chinese and Malay currency/duration digit forms are
best-effort (digit sequences work in all languages).

Design notes:
  - Only "material" numbers are checked: currency (ringgit/sen/RM),
    durations (days/months), counts with a unit (payments/instalments),
    percentages, dates (day + month), and long digit IDs (accounts/phones/
    IC spelled as digit words or written as digits). Bare numbers with no
    unit (e.g. "one moment") are ignored to keep false positives low.
  - A wrong value that happens to also appear elsewhere in the context can
    be missed (PASS is "clean on mechanical checks", not "provably correct").
    A FAIL is high-confidence: a concrete value with a material unit that is
    nowhere in the context or prior caller speech.
    Nzeroohnoughtone   two   three   four   five   six   seven   eight   nine	   ten
   eleven   twelve   thirteen   fourteen                  )fifteensixteen	seventeeneighteennineteen      (   2   <   F   P   Z   )twentythirtyfortyfiftysixtyseventyeightyninetyd   i  i@B )hundredthousandmillionfirstsecondthirdfourthfifthsixthseventheighthninthtentheleventhtwelfth
thirteenth
fourteenth	fifteenth	sixteenthseventeenth                              )
eighteenth
nineteenth	twentieth	thirtiethzthirty-firstztwenty-firstztwenty-secondztwenty-thirdztwenty-fourthztwenty-fifthztwenty-sixthztwenty-seventhztwenty-eighthztwenty-ninth>   junmacmaymeijulyjuneogosapriljulaimarchaugustjanuarijanuaryoctoberoktoberdecemberdisemberfebruarifebruarynovember	septemberringgitmoneysenrmmyrdaydurationdaysmonthmonthsyearyearsharibulantahunpercentperatuspaymentcountpayments)
instalmentinstalmentsinstallmentinstallmentszringgit.)u   令吉u   仙u   天u   日u   个月u   月u   年u   巴仙c                 P    t          j        d|                                           S )z:Lowercase word tokens, keeping hyphenated ordinals intact.z[a-z]+(?:-[a-z]+)?|\d+)refindalllower)texts    J/home/m1-ai/DEPLOYMENTS/AI-PHONE/ZACK-UPDATE/fixing_leaked/faithfulness.py_tokr   M   s    :/>>>    c                    | sdS d}d}d}| D ]o}|t           v r|t           |         z  }d}|t          v r|t          |         z  }d}:|dk    r
|pddz  }d}J|dv r||pdt          |         z  z  }d}d}h|d	k    ro |sdS ||z   S )
z9Convert a run of English number words to an int, or None.Nr   FTr=   r   r<   )r>   r?   and)_EN_ONES_EN_TENS
_EN_SCALES)tokenstotalcurrentsawts        r   _en_words_to_numberr   R   s     tEG
C  ==x{"G$CC(]]x{"G$CC)^^|!s*G$CC)))gljm33EqW##%ZZ t7?r   c                 .    t          j        dd|           S )z>Strip separators from a digit-ish string, return plain digits.z\D )r   sub)ss    r   _norm_digitsr   k   s    6%Qr   c                 F    t          |           }|rt          |          ndS )z0Digit string -> int value (no decimal handling).N)r   int)	digit_strds     r   	_to_valuer   p   s$    YA 3q666D r   c                    t                      }t                      }g }t          j        d|           D ]}|                    d          }t	          |                    d          d                   }|r7|                    t          |                     |                    |           d|v rm|                    dd          \  }}t	          |          }	|dz   dd         }|	r5|                    t          |	          dz  t          |          z              |r%|                    t          |          dz             t          j        d	|           D ]L}t	          |                    d                    }
t          |
          d
k    r|                    |
           Mt          |           }d}|t          |          k     r||         t          v s||         t          v r|}g }|t          |          k     r||         t          v s*||         t          v s||         t          v s||         dk    rl|                    ||                    |dz  }|t          |          k     r9||         t          v B||         t          v Q||         t          v `||         dk    lt          |          }||                    |           |}n|dz  }|t          |          k     |||fS )zCollect every numeric value + long digit string from grounding text.
    Returns (values: set of int, money_cents: set of int, digit_runs: list).z\d[\d,]*(?:\.\d+)?r   .r   00Nr	   r<   z\d+(?:[-\s]\d+)+r   r   )setr   finditergroupr   splitaddr   appendlenr   r   r   r   r   )r   valuesmoney_cents
digit_runsmrawdigitswholefracwdjoinedtoksijrunvals                   r   _extract_grounding_numbersr   x   s    UUF%%KJ [.55 3 3ggajjciinnQ/00 	&JJs6{{###f%%%#::))C++KE4e$$B4K!$D ;B#D		 9::: 3Fc 1222 [,d33 & &aggajj))v;;!f%%% ::D	A
c$ii--7h$q'X"5"5ACc$ii--T!W%8%8DGx<O<O(,Q:(=(=aEAQAQ

47###Q!VQ c$ii--T!W%8%8DGx<O<O(,Q:(=(=aEAQAQ%c**C

3AAFA c$ii-- ;
**r   c           	         g }|                                  }t          j        d|          }d}|t          |          k     rO||         t          v r&t          ||                  dk     rg }|}|t          |          k     r||         t          v rt          ||                  dk     rq|                    t          t          ||                                       |dz  }|t          |          k     r&||         t          v rt          ||                  dk     qt          |          dk    rM|                    d                    |||                   ddd                    |          d	d
           |}J|dz  }|t          |          k     Ot          j        d|          D ]&}t          ||
                    d          d           't          j        d|          D ]c}|
                    d          |
                    d          }	}t                              |	          p	|	dk    rdnd}
|
rt          |||
           dt          j        d|          D ]&}t          ||
                    d          d           't          j        d|          D ]?}|
                    d          }|                    |t          |          d|d	d
           @t          j        d|          D ]B}|
                    d          t          v r$t          ||
                    d          d           Ct          |           }d}|t          |          k     r||         }|t          v s|t           v s
|t"          v r|}g }|t          |          k     r||         t          v s*||         t           v s||         t$          v s||         dk    rl|                    ||                    |dz  }|t          |          k     r9||         t          v B||         t           v Q||         t$          v `||         dk    l|t"          v r|t          |          k    s|s{t"          |         }|||dz            }t'          d |D                       s|r7|d         dk    r+|                    |||dz  t          |          dd
           ||k    r|dz   n|}t)          |          }|)|t          |          k     r||         dv r7|dz  }|dz   }|t          |          k     r||         dk    r|dz  }g }|t          |          k     ro||         t          v s||         t           v rQ|                    ||                    |dz  }|t          |          k     r||         t          v B||         t           v Q|rt)          |          nd}|t          |          k     r||         dk    r||pdz  }|dz  }|                    d                    |||                   ||t          |          dd
           |}t                              ||                   }
|
rP|                    d                    |||dz                      ||dz  t          |          |
d
           |dz   }g||         t          v s||         dk    rF|                    d                    |||                   ||dz  t          |          dd
           ||k    r|n|dz   }n|dz  }|t          |          k     t+                      }g }|D ]G}|d         |d         |d         f}||vr*|                    |           |                    |           H|S )zdReturn a list of claim dicts from one AI turn.
    Each: {raw, value, cents, digits, unit_category}.u   [a-z]+|\d+|[一-鿿]r   r   r   r    Nr   idr   valuecentsr   unit_categoryz!(?:rm|myr)\s*(\d[\d,]*(?:\.\d+)?)ru   z (\d[\d,]*(?:\.\d+)?)\s*([a-z%]+)r	   %r   z(\d[\d,]*(?:\.\d+)?)\s*%z\b(\d{4,})\bz\b(\d{1,2})\s+([a-z]+)dater   c              3   (   K   | ]}|t           v V  d S N)_MONTHS).0xs     r   	<genexpr>z"_extract_claims.<locals>.<genexpr>   s&      11qG|111111r   ofr<   )rt   rw   rx   rv   r   r   r   )r   r   r   r   r   r   strjoinr   _add_writtenr   _UNITSgetr   r   r   r   _EN_ORDINALr   anyr   r   r   )r   claimsr   toks_allr   r   r   r   numunitcatr   r   r   r   nxtr   kr   rv   seenuniqueckeys                           r   _extract_claimsr      s    FJJLLE z1599H	A
c(mm

A;(""x'<r'A'ACAc(mm##x(?(?HXVW[DY\^D^D^

3x455666Q c(mm##x(?(?HXVW[DY\^D^D^3xx1}}chhx!}&=&=(,t)+N N O O O 	Q c(mm

  [=uEE 2 2VQWWQZZ1111[<eDD + +GGAJJ

TjjF99 	+c***[4e<< 4 4VQWWQZZ3333[%00 A Afs6{{T!'$@ @ 	A 	A 	A 	A [2E:: 5 5771::  V444 ::D	A
c$ii--G==AMMQ+-=-=ACc$ii--T!W%8%8DGx<O<O(,Q:(=(=aEAQAQ

47###Q!VQ c$ii--T!W%8%8DGx<O<O(,Q:(=(=aEAQAQ KQ#d))^^3^!!n1QU7m11S11111 Qc Qc!fnnMM!cC#I-0XX#P #P Q Q Q!VVAEE%c**C1s4yy==7666#IEAA3t99}}aE)9)9QCc$ii--T!W-@-@DGxDWDW

47+++Q!VQ c$ii--T!W-@-@DGxDWDW69@-c222qC3t99}}aE)9)9#(+Q!VQMM#((4!9*=*=,1SXX4;#= #= > > > Ajja)) MM#((4!a%=*A*AC,/#IS47#9 #9 : : : AA7g%%aDMM#((4!9*=*=,/#IS4:#< #< = = = UUAAAFAc c$ii--h 55DF  !1X;'
;d??HHSMMMMM!Mr   c                 p   t          |                    d          d                   }|sd S t          |          }d|v rV|                    dd          \  }}|dz   d d         }t          t          |                    dz  t          |          z   }n|dz  }|                     |||||d           d S )Nr   r   r   r   r	   r<   r   )r   r   r   r   )r   r   categoryr   r   r   r   r   s           r   r   r     s    #))C..+,,F KKE
czziiQ''ttRaR L''((3.T:
MM##h@ @ A A A A Ar   c                    | d         }|                      d          pd}|                      d          }|                      d          }|dk    r^|||v rdS t          |          d	k    rA|D ]>}t          |          t          |          k    r|                    |          s||v r dS ?d
S |dk    r|||v rdS |||v rdS d
S |||v rdS d
S )z=True if the claim's value is supported by the grounding sets.r   r   r   r   r   r   NTr   Fru   )r   r   endswith)	claimr   r   r   r   r   r   r   r   s	            r   _is_groundedr   -  s   

 CYYx  &BF
))G

CIIgE d{{?sf}}4v;;!!    s88s6{{**V0D0D*RU44u g~~+!5!54?sf}}4u 3&==t5r   )search_extension)	view_cart)dial_extensioncheckout)z"ok": falsez
"ok":falsez	api errorzapi call failed)sorryapologunablecannotzcan'tcouldnerrorunfortunatelyissueproblemz	try againtroubleznot ablezout of stockz	not foundzno zonly u   抱歉u   无法u   失败u   问题u	   找不到u   没有u   缺货maaftidakmasalahgagaltiadac                     i }| pg D ]E}	 |                     di           }|                     d          }|r|||<   6# t          $ r Y Bw xY w|S )z(Index tool definitions by function name.functionname)r   AttributeError)	tool_defsoutr   fnr  s        r   _tool_defs_mapr  c  sx    
C_"  	z2&&B66&>>D D	 	 	 	H	Js   2=
A
	A
c           
         g }|pi                      di           pi }|                     di           pi }|                     dg           pg }|D ]<}||vs|                     |          dv r|                    d|  d| ddd	           =|pi                                 D ]a\  }}	|                     |          }
|
rEt          |
t                    r0d
|
v r,|	|
d
         vr"|                    d|  d| d|	 ddd	           b|S )z?Required-field and enum validation. Returns list of flag dicts.
parameters
propertiesrequired)Nr   tool_schemaz: missing required argument ""	violation)
claim_typespokenverdictenumr   z="z" not in allowed values)r   r   items
isinstancedict)r  argsfn_defflagsparamspropsr
  fieldr   r   specs              r   _check_tool_schemar  q  sj   Elb117RFJJ|R((.BEzz*b))/RH 3 3: = =LL'+$R$R%$R$R$R%02 2 3 3 3 ZR&&(( 7 7Syy~~ 	7JtT** 	7v~~$v,&&M+/(U(U#(U(U(U(U(U)46 6 7 7 7 Lr   c           
      D   g }|pi                                  D ]\  }}t          j        dt          |                    D ]^}t	          |          dk     rd|t          |          dd}	t          |	|||          s"|                    d|  d| d| |d	d
           _|S )u   Material numeric argument values (3+ digit runs) must be grounded in
    context, prior caller speech, or prior tool results. Small numbers
    (quantities etc.) are intent-arithmetic — deliberately not checked.z\d+r   r   N)r   r   r   r   tool_argr   =unsupported)r  r  r   r  )r  r   r   r   r   r   r   r   )
r  r  r   r   r   r  r   r   r   r   s
             r   _check_tool_args_groundedr!    s     EZR&&(( 
9 
9S:fc#hh// 		9 		9C3xx!||&*c!#hh7 7Ev{JGG 9J+/(=(=#(=(=(=(=(+)68 8 9 9 9		9 Lr   c                     | rt          | t                    sdS |                                 t          fdt          D                       S )NFc              3       K   | ]}|v V  	d S r    r   r   lows     r   r   z#_result_is_error.<locals>.<genexpr>  s'      00AqCx000000r   )r  r   r   r   _ERROR_MARKERS)resultr&  s    @r   _result_is_errorr)    sQ     FC00 u
,,..C0000000000r   c                    t          |pd          \  }}}t          |          t          |          t          |          t          |          t	          |pg d           }d}t                      dg d}	fd}
t          | pg           D ]\  }}|t          |          k     rj||                             dd          |k    rJ |
||         |           |dz  }|t          |          k     r ||                             dd          |k    J|                    d	          pd                                }|                    d
          pd}|dk    r3t          |          \  }}}|z  |z  	                    |           |dk    r`|                                t          fdt          D                       s*                    |d         dd          ddd           d|	dz  }	t          |          D ]b}t          |          sN                    ||d         |d         |                    d          |                    d          dd           c|t          |          k     r9 |
||         t          | pg                      |dz  }|t          |          k     9|	t          |          t                    rdnddS )u  Assess an entire conversation.

    Args:
        messages: list of {'speaker': 'ai'|'user'|'system', 'text': str}
        context_text: the resolved injected context (OUTGOING/AGENTDATA/etc.)
        tool_events: optional list of
            {'msg_index': int, 'name': str, 'arguments': dict, 'result': str|None}
            in call order. msg_index is the conversation_log position at the
            time the tool ran (used to interleave with speech turns).
        tool_defs: optional list of tool definitions ({'function': {...}}
            format) used for required-field/enum validation.

    Returns a result dict (no timestamp — caller stamps it):
        {checked_turns, tool_calls_checked, flagged_count, status, flags}
    r   c                 .    |                      dd          S )N	msg_indexr   )r   )es    r   <lambda>z%assess_conversation.<locals>.<lambda>  s    QUU;5J5J r   )r   r   Nc           	         |                      d          pd}|                      d          pi }t          |t                    s-	 ddl}|                    |          }n# t
          $ r i }Y nw xY w|                      d          }t                               |d          D ]&}|vr                     ||d| d	| d
d           '|v r9t          |||                   D ]!}||d<   ||d<                       |           "t          ||          D ]!}||d<   ||d<                       |           "
                    |           d                    d |                                D                       }t          |t                    r|d|z   z  }t          |          \  }	}
}                    |	                               |
                               |           t#          |          r| ||ddS dS )zESequence + schema + arg checks, then fold args/result into grounding.r  r   	argumentsr   Nr(  r$  tool_sequencez called without prior r  turntoolr  r  r  r3  r4  r   c              3   4   K   | ]}t          |          V  d S r   )r   )r   vs     r   r   z=assess_conversation.<locals>._ingest_event.<locals>.<genexpr>  s(      ==!s1vv======r   )eventat_idxr  )r   r  r  jsonloads	ExceptionSEQUENCE_RULESr   r  r!  r   r   r   r   r   updateextendr)  )evr8  r  r  _jsonr(  prereqfground_textgvgcgrdefs_mapr   r  r   pending_error
seen_toolsr   s               r   _ingest_eventz*assess_conversation.<locals>._ingest_event  sj    vvf~~#vvk""(b$%% 	$$$${{4((   !!$((r22 	7 	7FZ''fd,;+/(O(Ov(O(O)46 6 7 7 7 8'dHTNCC    "&	 &	Q*4v{JWW 	 	AAfIAfILLOOOOt hh==t{{}}=====fc"" 	(3<'K/<<
Bb2"F## 	J&(FDIIMMM	J 	Js   A   A/.A/r,  r   speakerr   useraic              3       K   | ]}|v V  	d S r   r$  r%  s     r   r   z&assess_conversation.<locals>.<genexpr>  s'      66AqCx666666r   r  tool_error_ignoredz4 returned an error; the reply did not acknowledge itr  r2  r   r   r   r   r   )r3  r  r  r   r   r  FAILPASS)checked_turnstool_calls_checkedflagged_countstatusr  )r   r   listr  sorted	enumerater   r   r   r>  r   _ACK_MARKERSr   r   r   )messagescontext_texttool_eventsr  base_values
base_cents	base_runseventsev_ptrcheckedrJ  idxmsgrK  r   uvucurr   rG  r   r  r&  r   rH  rI  r   s                      @@@@@@@@r   assess_conversationrh    s     *DLDVTV)W)W&KY Fj//KiJi((HK%2+J+JKKKFFJMEG(J (J (J (J (J (J (J (J (J (J (JT hn"-- & &Ss6{{""vf~'9'9+q'I'IS'P'PM&.#...aKF s6{{""vf~'9'9+q'I'IS'P'P 779%%+2244wwv$"f3D99JBBbLF2Kb!!!d?? $**,,C666666666 7c=3H,@,9&,A *T *T *T)4	6 6 7 7 7
 !M1$T** 		 		Ev{JGG "'"8#El"YYw//#ii11,    		 3v;;

fVnc(.b&9&9:::! 3v;;


 !!&kkU!-&&v  r   )NN)__doc__r   r   r   r   r   r   r   	_ZH_UNITSr   r   r   r   r   r   r   r   r<  r'  rY  r  r  r!  r)  rh  r$  r   r   <module>rk     s2   4 
			
AQ !%*A/4a9@!
Aq$+Q07<BA 
2  &r ,6r <Fr brr   Bb2R2  $7CC
	Q	!	$a	)11	6=q	Q	1	&	+2A	7>	 	 r	 $0	 6B2	 		 !"		 '4R		 HJ2BRR2r	 	 	  	
w	
w	
(,g	
7<g	
	:	
z	
+2J	
 j	
 !*	
 /6z	
 J		
  		
 .5j		

 y	

 $Y	
 w	
 #G	
 <C7G	
 	
 	
 wz*!*Z " "	
? ? ?
  2     
! ! !2+ 2+ 2+nl l l^A A A  H ,  O    *  &1 1 1} } } } } }r   