
    E|jf                       d dl Z d dlZd dlZd dlZd dlZd dlZd dlmZmZmZ d dl	m
Z
 d dlZd dlZd dlmZmZmZmZmZmZmZmZ d dlmZmZ d dlmZ d dlmZmZmZ d dl m!Z" d d	l#m$Z$ d d
l%m&Z&m'Z' d dl(m)Z)m*Z*m+Z+ d dl,m-Z- d dl.m/Z/ d dl0m1Z1m2Z2 d dl3m4Z4 d dl5m6Z6 d dl7m8Z8 d dl9m:Z: d dl;m<Z< d dl=m>Z> d dl?m@Z@ d dlAmBZB d dlCmDZD d dlEmFZF d dlGmHZH d dlImJZJ d dlKmLZLmMZMmNZNmOZOmPZPmQZQmRZRmSZS d dlTmUZVmWZXmYZZm[Z\m]Z^m_Z_m`Z`maZambZbmcZcmdZd d dlemfZf d dlgmhZhmiZimjZj d dlkmlZlmmZmmnZn enemelfZo ej                  eq      Zr e       Zsd Ztd Zud!Zvd"Zwd#Zxd$Zyd%Zzd&e{d'e|fd(Z}d)Z~d*Zd+Zd,Zd-Zh d.Zd/Z G d0 d1e&      Z G d2 d3e&      Z G d4 d5e&      Zd6ed7ej                  d'eeeee   f   fd8Zdd9ee   d:ee   dz  d'efd;Zd6ed<ej                  d'ee   fd=Zd>eDdz  d?ej                  d@ed'dfdAZesj%                  dB       edCdDE       edFdGE       ee)       ee*      fdHedIed6efdJ       Zesj)                  dB       ee)       ee*      fdKed6efdL       Zesj%                  dM       ee)       ee*      fd<ej                  d6efdN       Zesj%                  dO       ee)       ee*      fd<ej                  d6efdP       Zesj)                  dQ       ee)       ee*      fd<ej                  dKed6efdR       Zesj)                  dS       e        ee)       ee*      fd<ej                  dKed6efdT       Z G dU dVe&      Zesj7                  dW       ee)       ee*      fd<ej                  dKed6efdX       Zesj)                  dY       ee)       ee*      fd<ej                  d6efdZ       Zesj)                  d[       ee)       ee*      fd<ej                  d6efd\       Z G d] d^e&      Zesj)                  d_       ee)       ee*      fd<ej                  dKed6ed`efda       Zesj)                  db       edc       ee)       ee*      fd<ej                  dded6ed`efde       Zesj)                  df       ee)       ee*      fd<ej                  d6efdg       Zesj)                  dh       edc       edi       edB       ee)       ee*      fd<ej                  ddedjedked6ed`efdl       Z G dm dne&      Z G do dpe&      Zd6edqe1d>eDd@edree   dsed'efdtZesj)                  du       edc       edi       ee)       ee*      fd<ej                  ddedjed6efdv       Zesj)                  dw       ee)       ee*      fd<ej                  dKed6efdx       Zd6edqe1d?ej                  d>eDd@edyee   d'efdzZd{Zd|Zd}ed'efd~Z G d d      Zded6edqe1d?ej                  d>eDdedjed'dfdZded6edqe1d?ej                  d>eDdjed'efdZd6edqe1d?ej                  d>eDdedjedede jf                  d'dfdZesjk                  d       ee)      fded<ej                  d6efd       Zesj%                  d       ee)       ee*      fd<ej                  d6efd       Z G d de&      Zesj7                  d       ee)       ee*      fd<ej                  de{dKed6ed`ef
d       Z G d de&      Zesj)                  d       ee)       ee*      fd<ej                  dKed6ed`efd       Zy)    N)datetime	timedeltatimezone)Optional)	APIRouterDependsHTTPExceptionQuery
UploadFileFileForm	WebSocket)JSONResponseResponse)AsyncSession)selectfuncdelete)insert)IntegrityError)	BaseModelfield_validator)get_dbget_current_staffdecode_staff_token)settings)Patient)IntakeSessionSessionContributor)QuestionResponse)PatientSummary)User)MstrRole)MstrDepartment)MstrQuestion)QuestionDeptMap)ActiveSession)PatientLock)PatientRecord)ConversationUtterance)ConversationCustomQuestion)get_first_questionget_next_questiongenerate_summaryextract_from_imagetransliterate_to_romanextract_patient_answerclassify_and_map_utterancessegment_and_map_utterance)transcribe_audiotranscribe_audio_diarizedtranslate_to_englishtranslate_to_languagetext_to_speechSUPPORTED_LANGUAGESSarvamStreamSessionpcm_to_wav_bytesSTREAM_SAMPLE_RATESTREAM_RECONNECT_ATTEMPTSSTREAM_RECONNECT_BACKOFF_S)error_codes)ACTIVEFIRST_ROUND_COMPLETE	COMPLETED)SR_CONSULTANTADMINSUPER_ADMINi     g333333?   g      ?g      @attemptreturnc                 <    t        t        d| dz
  z  z  t              S )NrF      )minCLASSIFY_RETRY_BASE_BACKOFF_SCLASSIFY_RETRY_MAX_BACKOFF_S)rH   s    5/var/www/html/ai-nims-dev/backend/app/api/sessions.py_classify_retry_backoff_srP   H   s    ,gk0BCEabb    i1  i4  i9  iG  i  >   n/anot sure	not known
don't knowdoesn't knowi don't knownot applicablenanonilnoneunknownz[IMPLICITLY_ANSWERED]c                   >    e Zd ZU eed<    ed      ed               Zy)StartSessionRequest	patientIdc                     |j                         }	 t        j                  |       |S # t        $ r t        d      w xY w)NzpatientId must be a valid UUIDstripuuidUUID
ValueErrorclsvs     rO   validate_patient_idz'StartSessionRequest.validate_patient_ida   sC     GGI	?IIaL   	?=>>	?   ) >N)__name__
__module____qualname__str__annotations__r   classmethodrj    rQ   rO   r_   r_   ^   s&    N[!  "rQ   r_   c                   H    e Zd ZU dZee   ed<    ed      ed               Z	y)CompleteSessionRequestNadditionalNotec                     |;|j                         }t        |      t        kD  rt        dt         d      |r|S d S |S NzadditionalNote max  charsrc   lenMAX_NOTE_LENGTHrf   rg   s     rO   
strip_notez!CompleteSessionRequest.strip_noteo   H     =	A1v' #66Gv!NOO1#t#rQ   
rl   rm   rn   ru   r   ro   rp   r   rq   r|   rr   rQ   rO   rt   rt   l   s0    $(NHSM(%&  'rQ   rt   c                       e Zd ZU dZee   ed<   dZee   ed<   eed<   dZeed<   dZ	eed<    e
d      ed	               Z e
d      ed
               Z e
d      ed               Zy)RespondRequestN
questionIdquestionTexttextTEXT	inputTypete-INinputLanguagec                     |j                         }|st        d      t        |      t        kD  rt        dt         d      |S )Nztext cannot be emptyz	text max rx   )rc   rf   rz   MAX_ANSWER_TEXT_LENGTHrg   s     rO   text_not_emptyzRespondRequest.text_not_empty   sF     GGI344q6**y)?(@GHHrQ   c                 $    |dvrt        d      |S )N)VOICEr   zinputType must be VOICE or TEXTrf   rg   s     rO   validate_input_typez"RespondRequest.validate_input_type   s     %%>??rQ   c                 *    |r|j                         S dS )NENGLISH)rc   rg   s     rO   validate_input_languagez&RespondRequest.validate_input_language   s     qwwy,9,rQ   )rl   rm   rn   r   r   ro   rp   r   r   r   r   rq   r   r   r   rr   rQ   rO   r   r   z   s     $J$"&L(3-&
IIs M3 V   [!  "
 _%-  &-rQ   r   dbdept_idc                 >  K   | j                  t        t              j                  t        j                  |k(               d{   }|j                         }|st        dt        j                  dd      | j                  t        t              j                  t        t        j                  t        j                  k(        j                  t        j                  |k(        j                  t        j                  dk(        j                  t        j                                d{   }|j#                         j%                         D cg c]$  }t'        |j                        |j(                  d& }}|j*                  |j,                  |fS 7 O7 kc c}w w)zCReturns (llm_system_prompt, llm_summary_prompt, questions) from DB.N  zDepartment not founderrormessagestatus_codedetailTidr   )executer   r$   wherer   scalar_one_or_noner	   r?   DEPARTMENT_NOT_FOUNDr%   joinr&   question_iddepartment_id	is_activeorder_bysequence_numberscalarsallro   r   llm_system_promptllm_summary_prompt)r   r   resultdeptq_resultq	questionss          rO   _get_dept_contextr      sC    ::f^4::>;L;LPW;WXYYF$$&D(==J`a
 	
 ZZ|	o::looM	N	,,7	8	|%%-	.	/11	2 H !!#'') 144y!&&)I  !!4#:#:IEE% Zs7   AFFC%F*F+$F)F8FFFall_questionsextra_excludedc                     | D ch c]$  }|j                   st        |j                         & }}|r||z  }|D cg c]  }|d   |vs| c}S c c}w c c}w )Nr   )r   ro   )	responsesr   r   r	asked_idsr   s         rO   _remaining_questions_forr      sY    -6H!--Q]]#HIH^#	$A!$y(@AAA I Bs   AAAA
session_idc           
        K   | j                  t        t        t        t              j                  t        t        j                  t        j                  k(        j                  t        t        j                  t        j                  k(        j                  t        j                  |k(        j                  t        j                               d {   }|j                         }|D cg c]C  \  }}}|j                  |j                  |j                  j!                         |j                  dE c}}}S 7 gc c}}}w w)N)	staffNamerolejoinedAtsequenceNumber)r   r   r   r"   r#   r   staff_idr   role_idr   r   r   r   r   name	joined_at	isoformat)r   r   r   rowscontributoruserr   s          rO   _build_intake_historyr      s     ::!42	d&//477:	;	h3	4	!,,
:	;	$44	5 F ::<D (,  $Kt II#--779)99		
 s%   CED9E,AD;4E;Elockr   nowc                     | r>| j                   |kD  r.| j                  |k7  rt        dt        j                  dd      y y y )N  z2This patient is being seen by another staff memberr   r   )
expires_atr   r	   r?   SESSION_IN_USE)r   r   r   s      rO   $_ensure_lock_not_held_by_other_staffr      sE    #%$--8*C(77Dxy
 	
 +D%trQ    	createdAtz ^(name|id|age|gender|createdAt)$)patterndescz^(asc|desc)$sort_byorderc                   K   t        j                  |d         }t        t        j                  t        j                  t        j                        j                  d            j                  t        j                        j                         }t        t        j                  t        j                  j                  d            j                  t        t        j                  t        j                  k(        j                  t        j                   dk(        j                         }|j#                  t        t$        t&        t(        t        j*                  |j,                  j.                  d      j                  d      |j,                  j0                        j                  t&        t$        j2                  t&        j                  k(        j                  t(        t$        j4                  t(        j                  k(        j7                  |t$        j                  |j,                  j                  k(        j7                  |t$        j                  |j,                  j                  k(        j                  t$        j4                  |k(        j9                  t        j*                  |j,                  j.                  d      j;                         t$        j<                  j;                                      d {   }|j?                         }tA               }	g }
|D ]H  \  }}}}}|jB                  |	vs|	jE                  |jB                         |
jG                  |||||f       J |dk(  }d d	 d
 d d d}|
jI                  ||    |       |
D cg c]  \  }}}}}tK        |j                        |j                  |jB                  |jL                  |jN                  |j                  |j<                  jQ                         |jR                  jU                         |dkD  |d
 c}}}}}tW        |
      dS 7 Cc c}}}}}w w)NdepartmentIdcnt
staff_namerK   r   response_countr   c                 D    | d   j                   xs dj                         S NrK   r   )r   lowerr   s    rO   <lambda>zlist_sessions.<locals>.<lambda>  s    !		R668 rQ   c                 D    | d   j                   xs dj                         S r   )daily_idr   r   s    rO   r   zlist_sessions.<locals>.<lambda>  s    ! 3::< rQ   c                 B    | d   j                   | d   j                   S dS )NrK   r   )ager   s    rO   r   zlist_sessions.<locals>.<lambda>  s    1Q488+?qtxx Q rQ   c                 D    | d   j                   xs dj                         S r   )genderr   r   s    rO   r   zlist_sessions.<locals>.<lambda>  s    ! 1r88: rQ   c                      | d   j                   S )Nr   )
started_atr   s    rO   r   zlist_sessions.<locals>.<lambda>  s    qt rQ   )r   r   r   r   r   )keyreverse)
r   patientNamedailyPatientIdr   r   
departmentr   statushasResponsesr   )sessionstotal),rd   re   r   r    r   r   countr   labelgroup_bysubqueryr"   r   r   responded_by_staff_idr   r   r   r   r   r$   coalescecr   r   
patient_idr   	outerjoinr   r   r   r   setr   addappendsortro   r   r   r   r   r   rz   )r   r   r   staffr   response_countsfirst_responderr   r   seenunique_rowssessionpatientr   r   r   r   sort_key_maps                     rO   list_sessionsr     sR     iin-.G 	''JJ'**+11%8	
 
"--	.	  	''IIOOL)	
 
d$::dggE	F	//14	5	  ::}g~}}_..22A6<<=MN  ++	- 
g}//7::=	>	nm99^=N=NN	O	?M$4$48I8I8T8T$T	U	?M$4$48I8I8T8T$T	U	}**g5	6	MM/++//388:$$))+

 F ::<D
 UDKDH [@*nj4'HHW%%&*njYZ[
 voG8<F:.L g.@$ MX
 
 I*nj '**o&||")"2"2{{!..(oo$//99;!....0 !/ 2'
" [!% KL
s,   K0Q2P539Q-A#QBP8"Q8	Qbodyc                   K   t        j                  |d         }t        j                  |d         }t        j                  t        j
                        }|t        t        j                        z   }t        j                  | j                        }|j                  t        t              j                  t        j                  |k(               d {   }|j                         }	|	st!        dt"        j$                  dd      |j                  t        t&              j                  t&        j(                  |k(               d {   }
|
j                         }|r@|j*                  t,        k(  r-|j.                  |k7  rt!        dt"        j0                  d	d      |r1|j*                  t,        k7  rt!        dt"        j2                  d
d      |r|j                  t        t4              j                  t4        j(                  |	j                  k(               d {   }|j                         }t7        |||       |j                  t9        t4              j;                  t        j<                         |	j                  ||      j?                  dg||d             d {    |j                  t        t@              j                  t@        jB                  |k(               d {   }|j                         }|r|j                  |_"        ||_#        |j                  t        tH              j                  tH        jD                  |j                  k(  tH        jB                  |k(               d {   }|j                         s|j                  t        tK        jL                               j                  tH        jD                  |j                  k(               d {   }|jO                         dz   }|jQ                  tI        t        j<                         |j                  ||             |jS                          d {    tU        ||j                         d {   }|j                  t        tV        tX        jZ                  j]                  d            j_                  tX        tV        j`                  tX        j                  k(        j                  tV        jD                  |j                  k(        jc                  tV        jd                               d {   }|jg                         }|D cg c]  \  }}|	 }}}|D cg c]S  \  }}|jh                  tj        k7  r;|jl                  |jn                  |jh                  |jd                  |jp                  |dU }}}ts        ||j.                         d {   \  }}}|j                  t        tt              j                  tt        jD                  |j                  k(               d {   }|jw                         jg                         D cg c]  }|jx                  s|jx                   }}d }t{               } |r|D cg c].  }|jh                  tj        k7  r|jn                  |jh                  d0 }!}t}        |	jZ                  |	j~                  |	j                  |	j                  d|!t        d t        |      D        d      |||xs d        d {   }"t{        |"j                  dg             } |D ch c]$  }|jl                  st        |jl                        & }#}|D $ci c]  }$|$d   |$d    }%}$t        d |D        d      }&t        t        | |#z
              D ]c  \  }'}(|%j                  |(      })|)s|jQ                  tW        t        j<                         |j                  |(|)tj        ddd |&|'z   dz   |!
             e |"d"   s|"d#   }|r|d   nd |_I        |jS                          d {    n|j                  rd |j                  d$}t        d%t        |j                        d&|	j                  |	jZ                  |	j~                  |	j                  d'||d |t        ||| (      |t        j                  d)
*      S ts        ||       d {   \  }}}t'        t        j<                         |	j                  |t,        +      }|jQ                  |       	 |j                          d {    |jQ                  tI        t        j<                         |j                  |d             |j                  t9        t4              j;                  t        j<                         |	j                  ||      j?                  dg||d             d {    |j                  t        t@              j                  t@        jB                  |k(               d {   }|j                         }|r|j                  |_"        ||_#        |jS                          d {    t        |	jZ                  |	j~                  |	j                  |	j                  d||-       d {   }*|*d.   d   |_I        |jS                          d {    tU        ||j                         d {   }t        j                  d/|	j                  |j                         t        d0t        |j                        d1|	j                  |	jZ                  |	j~                  |	j                  |	jF                  j                         d2||*d.   |j                  j                         t        g |      |t        j                  d3	*      S 7 
7 
l7 	7 	7 7 G7 7 z7 _7 c c}}w c c}}w 7 7 c c}w c c}w 7 c c}w c c}$w 7 7 ,7 # t        $ r8 |j                          d {  7   t!        dt"        j0                  d,d      w xY w7 u7 27 7 7 7 vw)4Nr   subminutesr   zPatient not foundr   r   r   z@This patient already has an active session in another departmentz,Intake is already completed for this patientr   r   r   r   r   )r   r   )index_elementsset_rK   r   r   r   r   r   )r   r   answerr   	isFlaggedrespondedByStaffNamequestionr  r   r   r   r   c              3   \   K   | ]$  }|j                   t        k7  s|j                    & y wNtranscribed_text_IMPLICIT_MARKER.0r   s     rO   	<genexpr>z!create_session.<locals>.<genexpr>  3       $C1[\[m[m  rB  \BA$6$6  $C   ,,r   patient_infoconversationlatest_answersystem_promptr   patient_records
skippedIdsr   r   c              3   4   K   | ]  }|j                     y wr  r   r  s     rO   r  z!create_session.<locals>.<genexpr>  s     D1,,D   r   defaultr   r   F
r   r   r   question_textr  
input_typeinput_language
is_flaggedr   r   intakeCompletenextQuestionr      RESUMEDdailyIdr   r   r   r   )
	sessionIdr   r  intakeHistoryr   resumeFromQuestionr1  remainingQuestionsr   streamingEnabled)r   content)r   r   r   r   uW   Session creation for this patient conflicted with a concurrent request — please retry)r   r#  r   firstQuestionz"Session created for patient %s: %s   CREATED)r5  r   r   r   	expiresAt)	r7  r   r  r8  r=  r   r:  r   r;  )Urd   re   r   r   r   utcr   r   SESSION_LOCK_TTL_MINUTESr`   r   r   r   r   r   r   r	   r?   PATIENT_NOT_FOUNDr   r   r   r@   r   r   SESSION_COMPLETEDr(   r   	pg_insertvaluesuuid4on_conflict_do_updater'   r   r   r   r   r   r   scalarr   commitr   r    r"   r   r   r   r   r   r   r   r  r  r   r,  r/  r   r)   r   extracted_textr   r-   r   r   r   nextreversedgetro   max	enumeratesortedpending_questionr   r   CONVERSATION_STREAMING_ENABLEDflushr   rollbackr,   loggerinfor   
created_at)+r  r   r   r   r   r   lock_expiresr   patient_resultr  existingr  lock_resultr   active_resultactive_slotexisting_contributorcount_resultnext_seqintake_historyresponses_resultall_response_rowsr   _all_responsesr   r   r#  r   
rec_resultsession_recordsnext_questionskipped_idsr!  
llm_resultexisting_idsr   questions_mapmax_seqi
skipped_idq_textfirsts+                                              rO   create_sessionrs  9  s
     iin-.Gyyu&H
,,x||
$C8+L+LMML4>>*J ::wgjjJ67 N //1G(::GZ[
 	
 ZZ}##M$<$<
$JK H ))+G7>>V+0E0E0P$33]
 	
 7>>V+(::Guv
 	
 JJ;%%k&<&<

&JK
 
 --/,T8SA jjk"Vtzz|

XZfVg"" ,~"*,G # 
 	
 	
 !jj=!''(>(>((JK
 
 $668%,ZZK"%1K" &(ZZ%&,,"--;"++x7&
  
 $668!#tzz|$**+=+H+HGJJ+VW" L $**,q0HFF%::<"::! (	  iik  5RDD "$#TYY__\%BCT$(>>$''IJU#..'**<=X&667	"
 
 -002'89tq!99 "3
 :!!%55  mm !,,"#"3"3\\(2
	 
 ->b'BWBW,X&X#q) ::=!''(@(@GJJ(NO
 

 6@5G5G5I5M5M5OdSTScSc1++dd
  # '%%)99 __8J8JKL 
  1&-ll7;;RYR`R`nun~n~)"  $C@W  $C  EG  H+# / 74  J jnn\2>?K8EW1C.WLW9BCAQtWai/CMCDmDaPG!*6+2L+M!N :&**:6FF+::<#*::$.&,)9#)'0#((/!a.6  ./ *> :@M}V'<SWG$))+%%#'1I1IJM _#&//#LL";;%nn	 "0&&* -&>}ihs&t&$,$K$K
 	
, ):"g(F"FM1i ::<::	G FF7O
hhj FF::<::	  **+	4::<GJJVb	c		(>&lC 
 

   **}##M$:$:h$FG M  224K!(!-
))+ %LL;;nn((	
 $	 	E  %_5f=G
))+0WZZ@@N
KK4gjj'**MWZZ"++{{!..$//99; ,"?3 ++557":2y"I" ( G G
 }.
	

 
 	 E
 :
 'Y
 e
 XC( 6 #G 	 

 kkm$33t
 	
	

* 	 @s  Cqn2A5q	n5
Cq!n8"Bq(n;)Aq.n>/Bq:o;A-q(o)A$qoq+o
,B=q)o*qoqAo/qoAqo $qo"o"$q93o',A!qo,#q1o/o/q o40Aq7A7q.o9/B!qo<Aqp -o?.p 2BqqAqq	AqqAqq$qqqq Cq5q8q;q>qqqq
qqqq"q/q<q?p qp!$qq	qqqqqz/{session_id}c                   K   t        j                  |d         }t        j                  t        j
                        }|t        t        j                        z   }|j                  t        t        t              j                  t        t        j                  t        j                  k(        j!                  t        j                  | k(               d {   }|j#                         }|st%        dt&        j(                  dd      |\  }}	t+        ||j                         d {   }
|j                  t        t,        t.        j0                  j3                  d            j                  t.        t,        j4                  t.        j                  k(        j!                  t,        j6                  |j                  k(        j9                  t,        j:                               d {   }|j=                         }|D cg c]  \  }}|	 }}}|D cg c]  \  }}|j>                  t@        k7  r~|jB                  |jD                  |j>                  |j:                  |jF                  |jH                  |jJ                  |jL                  jO                         tQ        |j4                        |d
 }}}tS        ||jT                         d {   \  }}}d }d }tW               }|jX                  tZ        t\        fv rq|j                  t        t^              j!                  t^        j6                  |j                  k(               d {   }|ja                         }|r|jb                  }n|j                  t        td              j!                  td        j                  |	j                  k(               d {   }|ja                         }tg        |||       |r||_4        ||_5        n:|jm                  te        t        jn                         |	j                  ||	             |j                  t        tp              j!                  tp        jh                  |k(               d {   }|ja                         }|r|j                  |_        ||_5        |j                  t        tr              j!                  tr        j6                  |j                  k(  tr        jh                  |k(               d {   }|ja                         s|j                  t        tu        jv                               j!                  tr        j6                  |j                  k(               d {   }|jm                  ts        t        jn                         |j                  ||jy                         d
z                |j{                          d {    |	j0                  |	j|                  |	j~                  |	j                  d}|j                  rd |j                  d}nW	 |j                  t        t              j!                  t        j6                  |j                  k(        j9                  t        jL                               d {   } | j                         j=                         D cg c]  }|j                  s|j                   }!}|r|D cg c].  }|j>                  t@        k7  r|jD                  |j>                  d0 }"}t        ||"t        d t        |      D        d      |||!xs d        d {   }#tW        |#j                  dg             }|D ch c]$  }|jB                  stQ        |jB                        & }$}|D %ci c]  }%|%d   |%d    }&}%t        d |D        d      }'t        t        ||$z
              D ]c  \  }(})|&j                  |)      }*|*s|jm                  t-        t        jn                         |j                  |)|*t@        ddd|'|(z   d
z   |
             e |j{                          d {    |#d   s&|#d   }n t        ||||!xs d        d {   }+|+d   }|j                  t        t              j!                  t        j6                  |j                  k(        j9                  t        jL                               d {   }.|.j                         j=                         D cg c]?  }|j                  |j                  |j                  |jL                  jO                         d'A }/}tQ        |j                        |jX                  |j                  jO                         |j                  r|j                  jO                         nd d(|	j                  |	j0                  |	j|                  |	j~                  d)|
||||/t        |||*      t        j                  d+	S 7 	7 7 c c}}w c c}}w 7 97 7 T7 7  7 7 U7 c c}w c c}w 7 c c}w c c}%w 7 7 # t        $ r},t        |,      j                  }-d |-v sd!tQ        |,      v rt%        d"t&        j                  d#d      t        j                  d$tQ        |,             t%        d%t&        j                  d&d      d },~,ww xY w7 c c}w w),Nr  r	  r   Session not foundr   r   r   )
r   r   r  r   r   r   r  r   respondedByStaffIdr  r  rK   r  r  r   r  c              3   \   K   | ]$  }|j                   t        k7  s|j                    & y wr  r  r  s     rO   r  zget_session.<locals>.<genexpr>  s3       ,K1cdcucu  zJ  dJA,>,>  ,Kr  r   r  r%  r   r   c              3   4   K   | ]  }|j                     y wr  r'  r  s     rO   r  zget_session.<locals>.<genexpr>  s     "L1#4#4"Lr(  r   r)  r   r   Fr+  r0  r1  r   r#  r   r$  r=  RateLimitError429  +Service is not available. Please try again.z"LLM call failed in get_session: %s  z"Failed to determine next question.)	imageDatamimeTypeextractedTextr   )r   r   	startedAtcompletedAtr4  r6  )	r  r  r8  r   summaryTextr1  patientRecordsr:  r;  )Yrd   re   r   r   r   rA  r   r   rB  r   r   r   r   r   r   r   r   rr  r	   r?   SESSION_NOT_FOUNDr   r    r"   r   r   r   r   r   r   r   r  r  r   r,  r-  r.  r/  rX  r   ro   r   r   r   r   rA   rB   r!   r   summary_textr(   r   r   r   r   rG  r'   r   r   r   rI  rJ  r   r   r   rR  r)   r   rK  r-   rL  rM  rN  rO  rP  rQ  r,   	Exceptiontyperl   INTERNAL_ERRORrV  r   
image_data	mime_typer   completed_atr   rS  )0r   r   r   r   r   rY  r   rowr  r  rb  rc  rd  r   re  rf  r   r   r#  r   r  ri  join_skipped_idssummary_resultsummary_rowr\  r   r]  r^  r_  r`  r   rg  rh  conversation_so_farrk  rl  r   join_questions_maprn  ro  rp  rq  rr  excexc_typerecords_resultr$  s0                                                   rO   get_sessionr  \  s	     yyu&H
,,x||
$C8+L+LMML::}g&	g}//7::=	>	}:-	. F
 ,,.C(::GZ[
 	

 GW0WZZ@@NZZ!>?	d$::dggE	F	**gjj8	9	"22	3	  ),,.#4541aQ5M5 / Az!11 --OO((//--//1"%a&=&=">$.	
I " ):"g>S>S(T"TM1iLM!$~~.	::!zz>"(()B)Bgjj)PQ 
 
 %779&33L JJ;%%k&<&<

&JK
 
 --/,T8SA$DM*DOFF;::<"::!'	  !jj=!''(>(>((JK
 
 $668%,ZZK"%1K"%'ZZ%&,,"--;"++x7&
  
 $668!#tzz|$**+=+H+HGJJ+VW" L FF%::<"::! , 3 3 5 9	  iik 'W[[GNNhohxhxy###'1I1IJM?#%::=)U=33wzzABXm667$ 

 >H=O=O=Q=U=U=W"l[\[k[k1#3#3"l"l  "/+--1AA &'__@R@RS+' +
 (9%1%8&*  ,KQ^H_  ,K  MO  'P&3"+(7(?4( "J (+:>>,+K'L$@M#_1QRQ^Q^C$6#_L#_FO)P!D'1V9*<)P&)P!"Lm"LVWXG)26:J\:Y3Z)[ :!3!7!7
!C!FF#3#'::<+2::,6.41A+1/8+007!a6>$  ))+%%%&67(2>(B"4%1&3"+(7(?4	# E %*/$:M ::}	}''7::5	6	-**	+ N  '')--/  --//1		
O  gjj/nn ++557?F?S?S7//99;Y]	
 ''LL;;nn	
 (#%)6}i`pq$CC' s A 6" #U

$
 
 	
 #m+
" $`)P" &  9--#x/5CH3D'$')4)C)CP}~  A3s8L# #%0%?%?Lpq 
s  Ckg.Ak'g1(B=k%g4&k?g7kBg=.k
hA9khA0k5h	6B-k#h$Bk/h0A-khA"k hAkA(h8 :h;$h8 h1h?	h8 3h ;4h8 /h%0#h8 h(%h(<h8 h-Ah8 Ah8 8h29%h8 h5	h8 (A(kk
$k5Ak9B6k1k4k7kk	kkkkkh8 h8 (h8 5h8 8	kBkkkkz/{session_id}/summaryc                   K   |j                  t        t              j                  t        j                  | k(               d {   }|j                         }|st        dt        j                  dd      |j                  t        t              j                  t        j                  |j                  k(               d {   }|j                         }|st        dt        j                  dd      t        |j                        |j                  |j                  |j                  |j                   j#                         dS 7 7 w)Nr   ru  r   r   z"Summary not found for this session)r7  r  ru   generationLatencyMsgeneratedAt)r   r   r   r   r   r   r	   r?   r  r!   r   SUMMARY_NOT_FOUNDro   r  additional_notegeneration_latency_msgenerated_atr   )r   r   r   session_resultr  r  summarys          rO   get_summaryr  8  s#     ::}##M$4$4
$BC N //1G(::GZ[
 	

 ::~$$^%>%>'**%LM N //1G(::Gkl
 	
 _++!11&<<++557 )s&   AEE
A?EEBEEz/{session_id}/respondc                 L  K   t        j                  |d         }t        j                  t        j
                        }|j                  t        t        t              j                  t        t        j                  t        j                  k(        j                  t        j                  | k(               d {   }|j                         }|st        dt         j"                  dd      |\  }}	|j$                  t&        k7  rt        dt         j(                  dd      |j                  t        t*              j                  t*        j                  |	j                  k(               d {   }
|
j-                         }|r|j.                  |k  s|j0                  |k7  rt        dt         j2                  d	d      |j                  t        t5        j6                               j                  t8        j:                  |j                  k(               d {   }|j=                         }t?        ||j@                         d {   \  }}}|D ci c]  }|d
   |d    }}|D ci c]'  }|d   jC                         jE                         |d
   ) }}|jF                  xs1 |jI                  |jJ                  xs d      xs |jJ                  xs d}|jJ                  xs- |jI                  |jC                         jE                               }|jL                  }|jN                  dk(  r|r	 tQ        ||jL                         d {   }|stT        jW                  d       |j                  t        t8              j                  t8        j:                  |j                  k(        jY                  t8        jZ                               d {   }|rt]        |      nd |j^                  xs |dta        |jc                         je                         |      d|ddS |}|jC                         jE                         tf        v }|j                  t        t8              j                  t8        j:                  |j                  k(        jY                  t8        jZ                  ji                               jk                  d             d {   }|j-                         }|d uxrX |jl                  jC                         |jC                         k(  xr+ |jn                  jC                         |jC                         k(  }|sW|jq                  t9        t        jr                         |j                  ||||jN                  |jt                  ||dz   |
             ||rdndz   }|tw        tx        jz                        z   }||_        |j                  t        t|              j                  t|        j0                  |k(               d {   }|j-                         } | r|| _        |j                          d {    |j                  t        t8              j                  t8        j:                  |j                  k(        jY                  t8        jZ                               d {   }!|!jc                         je                         }"|"D #cg c].  }#|#jn                  t        k7  r|#jl                  |#jn                  d0 }$}#|	j                  |	j                  |	j                  |	j                  d}%|j                  t        t              j                  t        j:                  |j                  k(        jY                  t        j                               d {   }&|&jc                         je                         D #cg c]  }#|#j                  s|#j                   }'}#t        |%|$||||'xs d |jt                         d {   }(t        |(jI                  dg             })t        t        |)            D ]m  \  }*}+|jI                  |+      },|,s|jq                  t9        t        jr                         |j                  |+|,t        d|jt                  d||*z   dz   |
             o |(d   sG|(d   xs i jI                  d      s/ta        |"||)      }-|-r|-d   d
   |-d   d   d|(d<   n
d|(d<   d |(d<   |(d   rd |_/        |j                          d {    |j                  t        t8              j                  t8        j:                  |j                  k(  t8        j                  dk(        jY                  t8        jZ                               d {   }.|.jc                         je                         }/d d||/D #cg c]9  }#|#jn                  t        k7  r$|#jl                  |#jn                  |#jZ                  d; c}#ta        |"||)      d S |(d   d   |_/        |j                          d {    |(d   ta        |"||)      d||dS 7 	7 7 07 c c}w c c}w 7 # tR        $ r |jL                  }Y &w xY w7 7 7 {7 M7 c c}#w 7 c c}#w 7 7 7 c c}#w 7 zw)!Nr  r   ru  r   r   r   Session is already completed  7Patient lock lost. Please re-acquire before responding.r   r   r   r   zBNo valid patient response in voice transcript; re-asking question.r   F)r1  r:  r0  totalResponsesr  rK   r+  r   r	  r  r  r   r!  r"  r#  r   r$  languager%  r   r0  r1  r6  T)r   
answerTextr   )r1  r0  r  flaggedQuestionsr:  )Mrd   re   r   r   r   rA  r   r   r   r   r   r   r   r   rr  r	   r?   r  r   r@   rD  r(   r   r   r   SESSION_LOCK_LOSTr   r   r    r   rI  r   r   rc   r   r   rN  r   r   r   r1   r  rV  rW  r   r   ro   rR  r   r   r   FLAGGED_PHRASESr   limitr,  r  r   rG  r   r   r   rB  r'   rJ  r  r   r   r   r   r)   rX  rK  r-   r   rP  rQ  r/  )0r   r  r   r   r   r   r   r  r  r  r\  r   r`  r   r#  re  r   r   _qmap_text_to_idr,  r   answer_text	extractedno_answer_resultr/  latest_resp_resultlatest_respalready_savedtotal_responsesnew_expiresr]  r^  history_resultrf  r   r!  r   r  r$  rk  rj  ro  rp  rq  	remainingflagged_resultflaggeds0                                                   rO   respondr  ]  s_	     yyu&H
,,x||
$C ::}g&	g}//7::=	>	}:-	. F
 ,,.C(::GZ[
 	

 GW~~(::Gef
 	
 

{!!+"8"8GJJ"FG K ))+D4??c)T]]h-F(::  HA  B
 	
 tzz|""#3#>#>'**#LM L "((*N ):"g>S>S(T"TM1i)23AQtWai3E3?HI!1V9??$**,ag5IKI%%b4??3Hb)IbT__b`bM//S[__]5H5H5J5P5P5R%SK ))K~~ ]	"4]DIINNI KK\]%'ZZ'('22gjj@A*::;&   /:#k*t#44E! '??O?W?W?Y?]?]?_aj&k"'"0"	 	   ""$**,?J  "zz 	**gjj8	9	"22779	:	q	   %779K4 	H%%++-1D1D1FF	H((..0K4E4E4GG  
zz|zz#'(~~--!*Q."*
 	 %]BO 	(*K*KLLK!DO**}##M$:$:h$FG M  224K!,
))+ :: 	**gjj8	9	"22	3 N
 #**,002M !11 __0B0BCL  {{..$$	L ::}	}''7::5	6	-**	+ N
 2@1G1G1I1M1M1OdASTScScq''dOd(!!!#'/4## J jnn\267K"6+#67 ::&FF#::<"::&$!1!#11  /! 3a 7&. & &'N1K1Qr0V0VW]0^,]IVab	09!T0BIVWLY_L`)aJ~&+/J'()-J~& "##' iik!zz#$U ++wzz9 ++t3 X&667 
 
 !((*..0 !"- !! %%)99 %&OO"#"4"4&'&7&7! #;=)do"p
 	
   *.9&AG
))+ #>26}i`kl) , #U3I O 	"		I	" 0@ 
 eV 	
! s  B5j$7i8B5j$-i.B+j$i	-j$ij$i$j$*,iBj$0i 	i
i A?j$i8C;j$	i;
D9j$i>0j$4j5A,j$!j"&j$3j;Bj$j$j$9jj%j$>j?Aj$Cj$jA>j$j)j$7>j
52j$'j"(j$j$	j$j$
j$i i51j$4i55j$;j$>j$j$j$j$j$j$j$j$z/{session_id}/completec           
      Z  K   t        j                  |d         }|j                  t        t        t
              j                  t
        t        j                  t
        j                  k(        j                  t        j                  | k(               d {   }|j                         }|st        dt        j                  dd      |\  }}|j                  d      }	|j                  t         k(  rt        dt        j"                  dd      |j                  t$        k(  r&|	t&        vrt        dt        j(                  d	d      |j                  t*        t$        fvrt        dt        j(                  d
d      |j                  t        t,              j                  t,        j.                  |j                  k(        j1                  t,        j2                               d {   }
|
j5                         j7                         }|st        dt        j8                  dd      |D cg c].  }|j:                  t<        k7  r|j>                  |j:                  d0 }}|j                  t        t@              j                  t@        j.                  |j                  k(        j1                  t@        jB                               d {   }|j5                         j7                         D cg c]  }|jD                  s|jD                   }}|jF                  |jH                  |jJ                  |jL                  d}tO        jP                  tR        jT                        }|	t&        v rt         nt$        }||_        ||_+        |jY                          d {    t[        ||j\                         d {   \  }}}tO        jP                  tR        jT                        }t_        ||ta        |jb                        ||xs d        d {   }te        tO        jP                  tR        jT                        |z
  jg                         dz        }|j                  t        th              j                  th        j.                  |j                  k(               d {   }|jk                         }|r ||_6        ||_7        |jp                  |_9        nE|ju                  ti        t        jv                         |j                  ||jp                  |             |j                  t        tx              j                  tx        j                  |j                  k(               d {   }|jk                         }|r|j{                  |       d {    |j                  t        t|              j                  t|        j~                  |k(               d {   }|jk                         }|r|j{                  |       d {    |j                          d {    t        j                  d|        ta        |j                        |j                         ||jp                  |j                         |t        ||      dS 7 7 c c}w 7 c c}w 7 7 7 7 7 ;7 7 7 7 w)Nr  r   ru  r   r   r     r  z,Session is awaiting senior consultant reviewSession is not activez+Cannot complete a session with no responsesr  r  r   r!  intake_datesummary_promptr$    )r   r   r  r  r  zSession completed: %s)	summaryIdr   r  ru   r  	latencyMsr:  )Frd   re   r   r   r   r   r   r   r   r   rr  r	   r?   r  rN  r   rB   rD  rA   REVIEWER_ROLE_KEYSSESSION_NOT_ACTIVEr@   r    r   r   r   r   r   NO_RESPONSESr  r  r,  r)   rX  rK  r   r   r   r   r   r   r   rA  r  rT  r   r   r.   ro   r  inttotal_secondsr!   r   r  r  ru   r  r   rG  r(   r   r'   r   rJ  rV  rW  r   r   r   )r   r  r   r   r   r   r  r  r  r   r  rf  r   r!  r  r$  r   r   
new_statusre  r  r   
start_timer  
latency_msexisting_summaryr[  r\  r   r]  r^  s                                  rO   complete_sessionr  R  sx     yyu&H ::}g&	g}//7::=	>	}:-	. F
 ,,.C(::GZ[
 	

 GW99VD~~"(::Gef
 	

 ~~--$>P2P(;;Hvw
 	

 ~~f&:;;(;;H_`
 	
 :: 	**gjj8	9	"22	3 N
 #**,002M(55Bop
 	
 !11 __0B0BCL  ::}	}''7::5	6	-**	+ N
 2@1G1G1I1M1M1OdASTScScq''dOd {{..$$	L ,,x||
$C"&88>RJGNG
((* *;2w?T?T)U#U A~yhll+J)!!++,%'/4 L hll8<<0:=LLNQUUVJ  ZZ~$$^%>%>'**%LM   224H ,)3&#'#6#6 
~zz|zz% //",
 	 

{!!+"8"8GJJ"FG K ))+Diio**}##M$:$:h$FG M  224Kii$$$
))+
KK'4 _""$#--}}6}iP yF
 e  $V$
 	
 	%s   BZ+Z EZ+'Z(AZ+.3Z!A*Z+Z$Z+0ZZB	Z+ZZ+7Z8AZ+ZBZ+ZCZ+$Z%*Z+Z"AZ+Z%*Z+ Z'Z+Z)A(Z+Z+Z+Z+Z+Z+Z+Z+"Z+%Z+'Z+)Z+c                   ^    e Zd ZU dZee   ed<    ed      edee   dee   fd              Z	y)UpdateNoteRequestNru   ri   rI   c                     |;|j                         }t        |      t        kD  rt        dt         d      |r|S d S |S rw   ry   rg   s     rO   r|   zUpdateNoteRequest.strip_note  r}   rQ   r~   rr   rQ   rO   r  r    sF    $(NHSM(%&8C= Xc]   'rQ   r  z/{session_id}/notec                 l  K   |j                  t        t              j                  t        j                  | k(               d {   }|j                         }|st        dt        j                  dd      |j                  |_
        |j                          d {    d|j                  iS 7 k7 w)Nr   zSession summary not foundr   r   ru   )r   r   r!   r   r   r   r	   r?   r  ru   r  rJ  )r   r  r   r   r   r  s         rO   update_session_noter    s      ::~$$^%>%>*%LM F '')G(::Gbc
 	

 #11G
))+d1122 s%   AB4B0AB4B2B42B4z/{session_id}/ask-morec           	      :  K   t        j                  |d         }t        j                  t        j
                        }|t        t        j                        z   }|j                  t        t        t              j                  t        t        j                  t        j                  k(        j!                  t        j                  | k(               d {   }|j#                         }|st%        dt&        j(                  dd      |\  }}	|j*                  t,        t.        fvrt%        dt&        j0                  dd      |j                  t        t3        j4                               j7                  t8              j!                  t8        j:                  |kD               d {   }
|
j=                         }|t        j>                  k\  rt%        d	t&        j@                  d
d      tB        |_        d |_"        |jG                          d {    |j                  t        tH              j!                  tH        jJ                  |j                  k(  tH        jL                  |k(               d {   }|jO                         s|j                  t        t3        j4                               j!                  tH        jJ                  |j                  k(               d {   }
|jQ                  tI        t        jR                         |j                  ||
j=                         dz                |j                  t        tT              j!                  tT        j                  |	j                  k(               d {   }|jO                         }|r||_&        ||_        n:|jQ                  tU        t        jR                         |	j                  ||             |j                  t        t8              j!                  t8        jL                  |k(               d {   }|jO                         }|r|j                  |_%        ||_        |jW                          d {    |j                  t        tX              j!                  tX        jJ                  |j                  k(        j[                  tX        j\                               d {   }|j_                         ja                         }|D cg c]O  }|jb                  td        k7  r:|jf                  |jh                  |jb                  |j\                  |jj                  dQ }}tm        ||jn                         d {   \  }}}|tq        ||      dS 7 7 7 o7 7 7 7 o7 07 c c}w 7 6w)Nr  r	  r   ru  r   r   r  zSession is not completedr|  z5Maximum concurrent sessions reached. Try again later.rK   r  r  )r   r   r  r   r  )conversationHistoryr:  )9rd   re   r   r   r   rA  r   r   rB  r   r   r   r   r   r   r   r   rr  r	   r?   r  r   rA   rB   SESSION_NOT_COMPLETEDr   r   select_fromr'   r   rI  MAX_CONCURRENT_SESSIONSMAX_SESSIONS_REACHEDr@   r  rT  r   r   r   r   r   rG  r(   rJ  r    r   r   r   r   r  r  r   r,  r/  r   r   r   )r   r   r   r   r   rY  r   r  r  r  r`  active_countr_  r\  r   r]  r^  r  rf  r   conversation_historyre  r   s                          rO   ask_morer    s     yyu&H
,,x||
$C8+L+LMML::}g&	g}//7::=	>	}:-	. F
 ,,.C(::GZ[
 	

 GW~~2I>>(>>Kef
 	
 tzz|((7==$$s*	
 L
  &&(Lx777(==  KB  C
 	
 GNG
((* "$!"(())WZZ7''83	
"   224ZZ4::< &&'9'D'D

'RS
 
 	!zz|zz(//1A5	
 	 

{!!+"8"8GJJ"FG K ))+D &
{zz|zz#	
 	 **}##M$:$:h$FG M  224K!(!-
))+:: 	**gjj8	9	"22	3 N
 #**,002M
  !11 }}aooQRQcQc,,1<<	I  .b'2G2GHHOAq)  46}iP E* 
   Is   CVU:CV&U='A*VV A!V3V4A-V!V"BV<V	=B VVAVV A,VV&V3AVV"V#V=V VVV	VVVVVz$/{session_id}/ask-more/next-questionc           	         K   |j                  t        t        t              j	                  t        t        j
                  t        j                  k(        j                  t        j                  | k(               d {   }|j                         }|st        dt        j                  dd      |\  }}|j                  t        k7  rt        dt        j                  dd      |j                  t        t              j                  t        j                   |j                  k(        j#                  t        j$                               d {   }|j'                         j)                         }t+        ||j,                         d {   \  }	}
}|D cg c].  }|j.                  t0        k7  r|j2                  |j.                  d0 }}|j                  t        t4              j                  t4        j                   |j                  k(        j#                  t4        j6                               d {   }|j'                         j)                         D cg c]  }|j8                  s|j8                   }}t;        |j<                  |j>                  |j@                  |jB                  d||r|d	   j.                  nd
|	||xs d        d {   }|d   rd n|d   }d|iS 7 k7 7 bc c}w 7 c c}w 7 )w)Nr   ru  r   r   r  r  r  r  r   r  r0  r1  )"r   r   r   r   r   r   r   r   rr  r	   r?   r  r   r@   r  r    r   r   r   r   r   r   r   r  r  r,  r)   rX  rK  r-   r   r   r   r   )r   r   r   r   r  r  r  r  rf  r#  re  r   r   conversation_for_llmr  r$  rk  ri  s                     rO   ask_more_next_questionr    s     ::}g&	g}//7::=	>	}:-	. F
 ,,.C(::GZ[
 	

 GW~~(;;H_`
 	

 :: 	**gjj8	9	"22	3 N
 #**,002M(9"g>S>S(T"TM1i !11 __0B0BC  ::}	}''7::5	6	-**	+ N
 2@1G1G1I1M1M1OdASTScScq''dOd(%ll7;;'..fmfvfvw)<ImB'88r#'/4 J ''78Dj>XMM**g( #U
 es{   A:K><K'=CK>K*;K>K-K>3K0A*K>5K56$K>K7,K7:AK>K<K>*K>-K>0K>7K>c                   B    e Zd ZU dZeed<    ed      ed               Zy)CurrentQuestionRequestr   r  c                 H    t        j                  d|      st        d      |S )Nz^[a-z]{2}-[A-Z]{2}$zHlanguage must be a valid language code (e.g. te-IN, hi-IN, kn-IN, ta-IN))rematchrf   rg   s     rO   validate_languagez(CurrentQuestionRequest.validate_language  s$     xx.2ghhrQ   N)	rl   rm   rn   r  ro   rp   r   rq   r  rr   rQ   rO   r  r    s+    HcZ   !rQ   r  z/{session_id}/current-questioncurrent_staffc           
        K   |j                  t        t        t              j	                  t        t        j
                  t        j                  k(        j                  t        j                  | k(               d {   }|j                         }|st        dt        j                  dd      |\  }}|j                  t        t              j                  t        j                  |j                  k(        j                  t        j                               d {   }|j!                         j#                         }	|j$                  |j&                  |j(                  |j*                  d}
t-        ||j.                         d {   \  }}}|j                  t        t0              j                  t0        j                  |j                  k(        j                  t0        j2                               d {   }|j!                         j#                         D cg c]  }|j4                  s|j4                   }}	 |	r|	D cg c].  }|j6                  t8        k7  r|j:                  |j6                  d0 }}t=        |
|t?        d tA        |	      D        d      |||xs d |jB                  	       d {   }|jE                  d
      xs d}n.tG        |
|||xs d |jB                         d {   }|d   d   }d|iS 7 7 7 7 c c}w c c}w 7 b7 (# tH        $ rB}tJ        jM                  dtO        |             t        dt        jP                  dd      d }~ww xY ww)Nr   ru  r   r   r  r  c              3   \   K   | ]$  }|j                   t        k7  s|j                    & y wr  r  r  s     rO   r  z'get_current_question.<locals>.<genexpr>  r  r  r   r  r1  )r   r#  r   r$  r  r=  r   z'LLM call failed in current-question: %sr~  zFailed to generate questionr  ))r   r   r   r   r   r   r   r   rr  r	   r?   r  r    r   r   r   r   r   r   r   r   r   r   r   r)   rX  rK  r  r  r,  r-   rL  rM  r  rN  r,   r  rV  r   ro   r  )r   r  r   r  r   r  r  r  r  rf  r   r#  re  r   cur_q_records_resultr   cur_q_recordsr!  rk  r,  rr  r  s                         rO   get_current_questionr    s     ::}g&	g}//7::=	>	}:-	. F
 ,,.Ck>[>[h{4|}}GW:: 	**gjj8	9	"22	3 N
 #**,002M#LLdkdtdtuL(9"g>S>S(T"TM1i!#}	}''7::5	6	-**	+" 
 0D/K/K/M/Q/Q/Sh!WXWgWgQ%%hMhE '%%)99 __8J8JKL 
  1))"  $C@W  $C  EG  H+# - 5  J 'NN>:@bM,)+# - 5 E "/26:M
 &&s #U
 i
  E>CIk>X>X  fC  5D  E  	EEs   A:M/<L=B!M/L
A*M/	L
A0M/:L;$M/L1L?M/L! 3L;?L! :L;;L! 6L7L! M/
M/M/M/M/L! L! !	M,*=M''M,,M/z/{session_id}/extract-record.filec           
      
  K   |j                  t        t              j                  t        j                  | k(               d {   }|j                         }|st        dt        j                  dd      |j                  t        t        fv rt        dt        j                  dd      |j                          d {   }t        j                  |      j!                  d      }|j"                  xs d}	 t%        ||       d {   }		 |j5                  t7        t9        j:                         | |||	             |j=                          d {    d }	 |j                  t        t>              j                  t>        j                  |j@                  k(               d {   }|j                         }|j                  t        tB              j                  tB        jD                  |j                  k(        jG                  tB        jH                               d {   }|jK                         jM                         }|j                  t        t6              j                  t6        jD                  |j                  k(        jG                  t6        jN                               d {   }|jK                         jM                         D cg c]  }|jP                  s|jP                   }}tS        ||jT                         d {   \  }}}|r|jV                  nd|r|jX                  nd|r|jZ                  nd|r|j\                  ndd}|r{|D cg c].  }|j^                  t`        k7  r|jb                  |j^                  d0 }}te        ||tg        d ti        |      D        d      |||xs d        d {   }|d   s&|d   }n tk        ||||xs d        d {   }|d   }t0        jm                  d|        |	|dS 7 7 Q7 # t&        $ r}
t)        |
      j*                  }d	|v sd
t-        |
      v rt        dt        j.                  dd      t0        j3                  dt-        |
             t        dt        j.                  dd      d }
~
ww xY w7 V# t&        $ rB}
t0        j3                  dt-        |
             t        dt        j.                  dd      d }
~
ww xY w7 T7 7 Rc c}w 7 c c}w 7 M7 *# t&        $ r*}
t0        j3                  dt-        |
             Y d }
~
Qd }
~
ww xY ww)Nr   ru  r   r   r  z,Cannot upload records to a completed sessionzutf-8z
image/jpegrz  r{  r|  r}  zImage extraction failed: %sr~  z!Failed to extract data from image)r   r   r  r  rK  z!Failed to save patient record: %szFailed to save patient recordr   r  r  c              3   \   K   | ]$  }|j                   t        k7  s|j                    & y wr  r  r  s     rO   r  z)extract_patient_record.<locals>.<genexpr>j  s%     #~1WXWiWim}W}A$6$6#~r  r  r0  r1  ry  r=  z7Failed to get next question after record extraction: %sz(Patient record extracted for session: %s)r  r1  )7r   r   r   r   r   r   r	   r?   r  r   rA   rB   rD  readbase64	b64encodedecodecontent_typer/   r  r  rl   ro   r  rV  r   r   r)   rd   rG  rJ  r   r   r    r   r   r   r   r   rX  rK  r   r   r   r   r   r   r  r  r,  r-   rL  rM  r,   rW  )r   r  r   r  r   r  contentsbase64_imager  rK  r  r  ri  	pt_resultptresp_resultr   rg  r   all_recordsr#  re  r   pt_infor!  rk  rr  s                              rO   extract_patient_recordr    s     ::}##M$4$4
$BC F '')G(::GZ[
 	
 ~~.	::(::Guv
 	

 YY[ H##H-44W=L!!1\I
1,	JJ

}zz|!#)
 	 iik M3Z**VG_%:%:7::I[I[;[%\]]	))+JJ#$U#..'**<=X&667
 

  '')--/	::=!U=++wzz9:Xm../
 


 2<1C1C1E1I1I1K`AqO_O_q''``,=b'BWBW,X&X#q)!BGGr266R#%bii2')r	
  #%%)99 __8J8JKL 
  1$)"#~@S#~  AC  D+# + 3t  J ./ *> :,$+# + 3t	 E "/2M KK:JG+]KKS !
 K 
9%%x'5CH+<!,!;!;Huv  	2CH=(77Dgh
 	

* 	 
8#c(C(77Dcd
 	

 ^


 a&X
  ZNPSTWPXYYZsE  AUPA=UP8U<P PP AR. R+R. UAT (S<)A<T %S?&B
T 0T1$T T'T5T T
AT 3T4T T%T +T,	T 5UUP 	R("BR##R((U+R. .	S97=S44S99U<T ?T T T T T 	U!U UUUz/{session_id}/heartbeatc                 x  K   t        j                  |d         }t        j                  t        j
                        }|t        t        j                        z   }|j                  t        t        t              j                  t        t        j                  t        j                  k(        j!                  t        j                  | k(               d {   }|j#                         }|sddiS |\  }}	|j$                  t&        k7  rddiS |j                  t        t(              j!                  t(        j                  |	j                  k(               d {   }
|
j+                         }|r||_        ||_        n:|j1                  t)        t        j2                         |	j                  ||             |j                  t        t4              j!                  t4        j,                  |k(               d {   }|j+                         }|r||_        |j7                          d {    ddiS 7 ]7 7 >7 w)Nr  r	  okFr  T)rd   re   r   r   r   rA  r   r   rB  r   r   r   r   r   r   r   r   rr  r   r@   r(   r   r   r   r   rG  r'   rJ  )r   r   r   r   r   rY  r   r  r  r  r\  r   r]  r^  s                 rO   heartbeat_sessionr     s     yyu&H
,,x||
$C8+L+LMML::}g&	g}//7::=	>	}:-	. F
 ,,.Ce}GW~~e}

6+#6#<#<[=S=SW^WaWa=a#bccK))+D &
{djjlwzzHamno**VM%:%@%@AWAW[cAc%deeM224K!-
))+$<5 d f
 sJ   CH:H1BH:H4B H:7H680H:(H8)	H:4H:6H:8H:z/{session_id}/transcriber   r  r  c           	      t  K   |j                          d {   }t        j                  t        j                        }t
        j                  d|t        |             d }d}	|}
t        dt        dz         D ]  }	 t        j                  t        j                        }t        ||j                  xs d|j                  xs d|       d {   \  }	}
t        t        j                  t        j                        |z
  j                         dz        }t
        j                  d|||	       d } n |t'        dt(        j*                  dd      	 |	r.|	j-                  d      dk\  rt
        j                  d|	       ddiS |	r|
r|
dk7  rt        j                  t        j                        }t/        |	|
       d {   }	t        t        j                  t        j                        |z
  j                         dz        }t
        j                  d||	       t        t        j                  t        j                        |z
  j                         dz        }t
        j                  d|       d|	iS 7 \7 # t        $ rH}t!        t!        |dd       d	d       }t
        j#                  d
|t%        |      |d       |}Y d }~Md }~ww xY w7 # t        $ r]}t!        t!        |dd       d	d       }t
        j#                  dt%        |      |d       t'        dt(        j*                  dd      d }~ww xY ww)Nu8   Transcribe request — language: %s, file size: %d bytesr   rK   z	audio.wav	audio/wavr  z6[Latency] Sarvam STT attempt %d: %dms | transcript: %rresponser   z4Sarvam STT attempt %d failed: %s | response body: %sTexc_infor~  Transcription failedr   r   
rF   z,Multi-speaker filtered on raw transcript: %r
transcripten-INz-[Latency] Sarvam Translate: %dms | result: %rz1Sarvam translation failed: %s | response body: %sz)[Latency] Total transcribe pipeline: %dms)r  r   r   r   rA  rV  warningrz   rangeMAX_TRANSCRIPTION_ATTEMPTSsarvam_transcribefilenamer  r  r  r  getattrr   ro   r	   r?   r  r   sarvam_translate)r   r  r  r  r   r  audio_bytest_startlast_excr  detected_langrH   t_stt_startt_stt_msr  r  t_translate_startt_translate_ms
t_total_mss                      rO   transcribe_session_audior    s     		#Kll8<<(G
NNMxY\]hYij!%HJM6:; 	",,x||4K.?,!!0[	/ )%J HLL6DSSUX\\]HNNSU\^fhrsH$ (77DZ[
 	


***40A5NNI:V "%%-MW,D (X\\ :/
MJJJ (,,x||"<?P"P!_!_!adh!hiNNNJN\fg hll8<<07:IIKdRSJ
NN>
K*%%c $)  	73
D964HDLLOQXZ]^aZbdhswLxH	$ K  
wsJ5vtDH#c(TXcgh(77DZ[
 	

s   L8I2A#L8;AI8I5A!I8-#L8/K  L8;K <K=AK AL85I88	K	=K>L8K		L8K 	L5AL00L55L8c                   H    e Zd ZU eed<   eed<    ed      ed               Zy)ClassifyUtteranceRefutteranceId	speakerIdc                     |j                         }	 t        j                  |       |S # t        $ r t        d      w xY w)Nz utteranceId must be a valid UUIDrb   rg   s     rO   validate_utterance_idz*ClassifyUtteranceRef.validate_utterance_id  sF     GGI	AIIaL   	A?@@	Ark   N)rl   rm   rn   ro   rp   r   rq   r   rr   rQ   rO   r  r    s,    N]#  $rQ   r  c                   D    e Zd ZU ee   ed<    ed      ed               Zy)"ClassifyConversationSegmentRequest
utterancesc                      |st        d      |S )Nzutterances cannot be emptyr   rg   s     rO   utterances_not_emptyz7ClassifyConversationSegmentRequest.utterances_not_empty  s     9::rQ   N)	rl   rm   rn   listr  rp   r   rq   r%  rr   rQ   rO   r"  r"    s-    )**\"  #rQ   r"  r  entriesr  c           
      4  K   |t        t        j                        z   |_        |st	        | |j
                         d{   \  }}}| j                  t        t              j                  t        j                  |j                  k(               d{   }|j                         j                         }	| j                          d{    g t        |	|      dS | j                  t        t         j                        j                  t         j                  |j                  k(        j#                                d{    | j                  t        t%        j&                               j                  t(        j                  |j                  k(               d{   }
|
j+                         }g }t-        |      D ]c  \  }}t)        t/        j0                         |j                  ||z   dz   d|d   |d      }| j3                  |       |j5                  ||d	   f       e | j                          d{    d
|D cg c]3  \  }}t7        |j                        |j8                  ||j:                  d5 c}}iS 7 B7 7 7 J7 7 Uc c}}w w)u  Persists STT entries (list of {"speakerId", "text"}) as PENDING placeholder
    utterances, claiming their sequence numbers. Shared by the batch
    /conversation-segment/transcribe endpoint below and the real-time
    conversation-stream WebSocket — the two differ only in how `entries` were produced
    (a Sarvam batch job vs. a live streaming connection), not in how they're persisted.r	  Nr#  r:  rK   UNKNOWNr   PENDING)r   r   r   speaker_roleraw_transcriptr  mapping_statusr  r#  )r  r   r  r   )r   r   rB  r   r   r   r   r   r    r   r   r   r   r   rJ  r   r   with_for_updater   r   r*   rI  rP  rd   rG  r   r   ro   r   r-  )r   r  r   r   r'  r  re  r   r  current_responsesutterance_count_resultutterance_countplaceholder_rowsro  entryplaceholder
speaker_ids                    rO   _persist_conversation_entriesr7    sY     Ih.O.OPPDO 1"g6K6K LL1i!zz#$**+;+F+F'**+TU 
 
 +22488:iik":;Li"X
 	
 **} &&}'7'77::'EFVVX   $&::tzz|""#8#C#Cwzz#QR$  -335O ACg& C5+zz|zz+a/!3" ="$
 	{eK.@ ABC ))+ 	 ,<
 (Z  #;>>2"-"="='#22	

 
[ M
 	0 
s   >J JAJJ5J
JA6JJAJJ BJ:J;
J8J=JJJJJJJz-/{session_id}/conversation-segment/transcribec                   K   t        j                  |d         }t        j                  t        j
                        }|j                  t        t        t              j                  t        t        j                  t        j                  k(        j                  t        j                  | k(               d {   }|j                         }|st        dt         j"                  dd      |\  }	}
|	j$                  t&        k7  rt        dt         j(                  dd      |j                  t        t*              j                  t*        j                  |
j                  k(               d {   }|j-                         }|r|j.                  |k  s|j0                  |k7  rt        dt         j2                  d	d      |j5                          d {   }	 t6        j8                  r6t;        ||j<                  xs d
|j>                  xs d|       d {   \  }}nMtA        ||j<                  xs d
|j>                  xs d|       d {   \  }}|jC                         rd|dgng }|r&|dk7  r!|D ]  }tE        |d   |       d {   |d<    tQ        ||	||||       d {   S 7 7 B7 7 7 i7 -# tF        $ rD}tH        jK                  dtM        |      d       t        dt         jN                  dd      d }~ww xY w7 bw)Nr  r   ru  r   r   r   r  r  r  zsegment.wavr  0r  r   r	  r   z#Conversation segment STT failed: %sTr  r~  r  ))rd   re   r   r   r   rA  r   r   r   r   r   r   r   r   rr  r	   r?   r  r   r@   rD  r(   r   r   r   r  r  r    CONVERSATION_DIARIZATION_ENABLEDsarvam_transcribe_diarizedr  r  r  rc   r  r  rV  r   ro   r  r7  )r   r  r  r   r   r   r   r   r  r  r  r\  r   r  r'  r  r  r4  r  s                      rO   transcribe_conversation_segmentr=  T  s     yyu&H
,,x||
$C::}g&	g}//7::=	>	}:-	. F
 ,,.C(::GZ[
 	
 GW~~(::Gef
 	

 

{!!+"8"8GJJ"FG K ))+D4??c)T]]h-F(::  HA  B
 	

 		#K
44+ET]];mT=N=N=]R]_g, &"G] /@T]];mT=N=N=]R]_g/ )%J CMBRBRBTS*=>Z\G]g5  U&6uV}m&T TfU /r7D#wP]^^^e& $&) !U 
:CHtT(77DZ[
 	

 _s   B5L7J,8B5L-J/.A%LJ2L=J: J45J: J6=J: 
J8	J: L'L
(L/L2L4J: 6J: 8J: :	L?LLLz+/{session_id}/conversation-segment/classifyc                 ,  K   t        j                  |d         }t        j                  t        j
                        }|j                  t        t        t              j                  t        t        j                  t        j                  k(        j                  t        j                  | k(               d {   }|j                         }|st        dt         j"                  dd      |\  }}	|j$                  t&        k7  rt        dt         j(                  dd      |j                  t        t*              j                  t*        j                  |	j                  k(               d {   }
|
j-                         }|r|j.                  |k  s|j0                  |k7  rt        dt         j2                  d	d      |j4                  D cg c]  }|j6                  |j8                  d
 }}t;        ||||||       d {   S 7 Q7 c c}w 7 w)Nr  r   ru  r   r   r   r  r  r  r  r  )rd   re   r   r   r   rA  r   r   r   r   r   r   r   r   rr  r	   r?   r  r   r@   rD  r(   r   r   r   r  r#  r  r   _classify_and_persist_utterances)r   r  r   r   r   r   r   r  r  r  r\  r   uutterance_refss                 rO   classify_conversation_segmentrC    s     yyu&H
,,x||
$C::}g&	g}//7::=	>	}:-	. F
 ,,.C(::GZ[
 	
 GW~~(::Gef
 	

 

{!!+"8"8GJJ"FG K ))+D4??c)T]]h-F(::  HA  B
 	

 Y]XgXghSTamm!++NhNh1"gxsTbccc=& icsD   B5H7H8B5H-H.A H H.HHHHHrB  c                   K   |D cg c]  }t        j                  |d          }}|D ci c]  }|d   |d    }}| j                  t        t              j                  t        j                  j                  |      t        j                  |j                  k(  t        j                  dk(               d{   }	|	j                         j                         D 
ci c]  }
|
j                  |
 }}
t        |      t        |      k7  rt        dt        j                  dd      |D cg c]  }||   	 }}|D 
cg c]'  }
|t!        |
j                           |
j"                  d	) }}
|d
   j$                  }t'        | |j(                         d{   \  }}}|d
   j*                  }| j                  t        t              j                  t        j                  |j                  k(  t        j*                  |k  t        j                  dk7        j-                  t        j*                  j/                               j1                  t2                     d{   }|j                         j                         }t5        |      D cg c]  }|j6                  |j"                  d }}|r|d
   nd}|r|j6                  |j"                  dnd}|D ci c]  }|d   |d    }}g }g }g }d}t8        j:                  }t=        d|dz         D ]z  } 	 t8        j>                  rJtA        ||||       d{   }!tC        ||!      D "#cg c]  \  }"}#|#d   |"d   |#d   |#d   |#d   d }}"}#ntE        |d
   d   |||       d{   } n | j                  t        tZ        j                        j                  tZ        j                  |j                  k(        j]                                d{    | j                  t        t_        j`                               j                  tb        j                  |j                  k(               d{   }&|&je                         }'| j                  t        t_        j`                               j                  t        j                  |j                  k(               d{   }(|(je                         dz   })|duxr" tg        |      xr |d
   d   |j6                  k(  }*|*r|d
   }+|+d   D ,cg c]  },|,d   th        k\  r|, }-},|-r|-d
   nd}.|-rdn|+d   d k(  rd nd!}/|jj                  }0|0rb| j                  tm        tb              j                  tb        j                  |j                  k(  tb        jn                  |0k(               d{    |j"                  jq                          d"|+d   js                          ju                         }1|1|_        |.r|.d#   nd|_5        |.r|.d   nd|_;        |/|_	        |+d   r |jy                  |j                  |+d   f       g }2|-D ]Q  },|j{                  |,d#   d$      }3|2jy                  |,d#   |3|,d%   |,d   d&       |jy                  |,d#   |3|,d%   d'       S |jy                  |+d   |1|j*                  |2d(       | jm                  |d
          d{    |dd }4|dd }5n|}4|}5t}        |4      D ]  \  }6}7|7d   D ,cg c]  },|,d   th        k\  r|, }-},|-r|-d
   nd}.|-rdn|7d   d k(  rd nd!}/|6t        |5      k  rK|5|6   }8|7d   |8_        |.r|.d#   nd|8_5        |.r|.d   nd|8_;        |/|8_	        |8j                  }9|8j*                  }:n\t        j~                         }9|)}:|)dz  })| j                  t	        |9|j                  |:|7d   |7d   ||.r|.d#   nd|.r|.d   nd|/)	             |7d   r|jy                  |9|7d   f       g }2|-D ]Q  },|j{                  |,d#   d$      }3|2jy                  |,d#   |3|,d%   |,d   d&       |jy                  |,d#   |3|,d%   d'       S |jy                  |7d   |7d   |:|2d(        |5t        |4      d D ]	  };d!|;_	         | j                          d{    |D ]J  \  }9}<| j                  t        t        j~                         |j                  |j(                  |9|<*             L t}        |      D ]y  \  }6}| j                  tc        t        j~                         |j                  |d#   |d+   |d%   d,||d%   ju                         j                         t        v |'|6z   dz   |-
             { |t        t8        j                  .      z   |_G        | j                          d{    | j                  t        tb              j                  tb        j                  |j                  k(               d{   }=|=j                         j                         }>|t        |>|      d/S c c}w c c}w 7 	}c c}
w c c}w c c}
w 7 7 c c}w c c}w 7 $c c}#}"w 7 # tF        $ r}$tI        |$      jJ                  }%| |k  rNtL        jO                  d| |t!        |$             tQ        jR                  tU        |              d{  7   Y d}$~$d|%v sdt!        |$      v rt        dt        jV                  dd      tL        jY                  d|t!        |$      d       t        dt        jV                  dd      d}$~$ww xY w7 ]7 7 c c},w 7 7 c c},w 7 7 7 qw)0uG  utterance_refs: list of {"utteranceId": str, "speakerId": str}. Shared by the batch
    /conversation-segment/classify endpoint above and the conversation-stream WebSocket —
    once an utterance is a PENDING placeholder row, classification doesn't care whether the
    audio behind it came from a batch job or a live stream.r  r  r+  Nr  z;One or more utterances were not found or already classifiedr   r   r:  r   )speakerRoler   r   r   rK   rE  mappingscustomQuestioncontinuesFromPrevious)rE  r   rF  rG  rH  z8Conversation classify attempt %d/%d failed, retrying: %srz  r{  r|  r}  zBConversation utterance classification failed after %d attempts: %sTr  r~  z&Failed to process conversation segment
confidenceMAPPED
SMALL_TALKUNMAPPED r   r   r  )r   r   r  rI  )r   r   r  )rE  r  r   mappedQuestions)	r   r   r   r,  r-  r  mapped_question_idmapping_confidencer.  )r   r   r   utterance_idr,  r   r   r+  r	  r)  )Jrd   re   r   r   r*   r   r   in_r   r.  r   r   rz   r	   r?   VALIDATION_ERRORro   r-  r  r   r   r   r   r   r   CONVERSATION_RECENT_CONTEXT_SIZErM  r,  r   CLASSIFY_MAX_ATTEMPTSr  r;  r2   zipr3   r  r  rl   rV  r
  asynciosleeprP   r  r   r   r/  r   r   r    rI  bool)CONVERSATION_MAPPING_CONFIDENCE_THRESHOLDrO  r   r   rstriplstriprc   rP  r   rN  rP  rG  r   rT  r+   r   r  r   rB  r   rJ  r   )?r   r  r   r   r   rB  rA  utterance_idsspeaker_ids_by_idpending_resultr  pending_by_iduidpending_rowsr'  r  re  r   min_sequencerecent_resultrecent_rowsr   recent_contextmerge_targetprevious_utterancer   qmappending_custom_questionspending_responsesutterances_outsegmentsmax_attemptsrH   classificationser   r  r  response_count_resultr   extra_count_resultnext_extra_sequenceshould_mergesegmconfident_mappingsprimary_mappingr.  old_question_idmerged_textmapped_questionsr,  remaining_segmentsremaining_placeholdersro  segmentr5  rQ  r   leftovercustom_question_textrefreshed_resultrefreshed_responsess?                                                                  rO   r@  r@    s     ;IIQTYYq/0IMICQRa=)1[>9RR::$%++!$$((7!,,

:!00I=	
 N -;,B,B,D,H,H,JKSSVVS[KMK
=S//(99  GD  E
 	
 3@@3M#&@L@dpq]`.s366{;SEWEWXqGq O,,M-b'2G2GHHOAq)?22L**$%	!,,

:!11L@!00I=


 
'77<<>	?	/	0	 	M  '')--/K +& 0@0@AN  &1;q>dL  %11<;V;VW! 
 )221AdGQvY2D2
  "N H11LL1,- #"	88(CG^]fhz({"{ !$G_ =
 1 ()'76XYZdXe*+,<*=XYZqXr  ";71:f;M~_hj|!}}#V **} &&}'7'77::'EFVVX   #%**tzz|""#3#>#>'**#LM#  +113N
  "zztzz|""#8#C#Cwzz#QR   -3359 	D  	DN	DQK&,*C*CC  qk:
"KK 
 
 4F,Q/4%7cR_N`dpNpl  wA '99**'(..$//7::=$00OC   &44;;=>aF@R@R@T?UV\\^&1#KZ/,*G`d'KZ/,*G`d'&4# $++\__cBR>S,TU# 	A HHQ|_b9M##o -H+o	%  $$o -H+& 	 	}-%*::/	
 	 iiQ(((%ab\!-ab!1%!- 23 <
7z*
"KK 
 
 4F,Q/4%7gVcNdhtNtl  {Es)**03K'.}'=K$N]_\-JcgK*N]_\-JcgK*)7K&&>>L)99O  ::<L1O1$FF(":: /$]3&v&DS?<#@Y]DS?<#@Y]-
 
 #$$++\7CS;T,UV# 	A HHQ|_b9M##o -H+o	%  $$o -H+& 	 	"=1!&/-/	
 	o<B +3/A+B+CD -",- ((*.F **
)zz|zz!//%.
 	 +, 1
zz|zz,N+x[({((*002oE*Q.2"*
 	 Ih.O.OPPDO
))+ZZ &&'7'B'Bgjj'PQ  +22488: %67JIV q	 JR L Aq I	( 3( #| ~ 	Cy))H%N\3s8 mm$=g$FGGG8+uC/@# #%0%?%?Lyz  LLTc#h    !,!;!;Hpq %	:&
R 	)
F : s  m.h,m.h1A=m.9h6:$m.h92;m.-h>9m.?,i+*m.iCm.i/m.
 i*,m.i&,m.!i$4i5i$!i)i$i!i$	A&m./m0Am.mA-m.;m<Am.
mBm.%m&D#m.	m
,m.6m Fm.m%Dm.*m(+Am.:m+;<m.9m.m.
m.i$i$$	m	-Am	k
mm.A/mm		m.m.m.m.m. m.(m.+m.i,  )i  i  r  c                    t        | t        j                        r| j                  j                  dv ryt        | t
        j                  j                        r(| j                  | j                  j                  t        v S y)N)i  i  TF)
isinstancehttpxHTTPStatusErrorr  r   
websockets
exceptionsConnectionClosedrcvdcode_FATAL_SARVAM_WS_CLOSE_CODES)r  s    rO   _is_fatal_sarvam_errorr  	  s\    #u,,-#,,2J2Jj2X#z,,==>388CWxx}} <<<rQ   c                   $    e Zd ZdZefdedefdZy)_ConversationStreamStateu   Shared between the two concurrent relay tasks below (browser->Sarvam and
    Sarvam->browser) plus the periodic lock-refresh task — all touch the same Sarvam
    session and the same "are we mid-outage" bookkeeping.r  sample_ratec                     || _         t        ||      | _        t               | _        d| _        d| _        d | _        d | _        t        j                         | _        t        j                         | _        y )N)r  r  F)r  r:   stream	bytearrayoutage_buffer	in_outagegive_upfatal_errorutterance_started_atrW  Lockreconnect_lockdb_lock)selfr  r  s      rO   __init__z!_ConversationStreamState.__init__,	  sc    
 ')8U&[ (, 37!%lln ||~rQ   N)rl   rm   rn   __doc__r<   ro   r  r  rr   rQ   rO   r  r  '	  s     = :L & &3 &rQ   r  state	pcm_bytesc                   K   	 t        || j                        }t        |dd|       d{   \  }}	|j                         }|sy|	r|	dk7  rt	        ||	       d{   }| j
                  4 d{    t        j                  t        j                        }
t        ||||
d|dg|	       d{   }|d   rSt        ||||t        j                  t        j                        |d   D cg c]  }|d   |d	   d
 c}       d{    ddd      d{    y7 7 7 7 sc c}w 7 "7 # 1 d{  7  sw Y   yxY w# t        $ rq}t        |      r;t        |      | _        d| _        t"        j%                  dt        |             Y d}~yt"        j%                  dt        |      d       Y d}~yd}~ww xY ww)u  Audio captured while the backend<->Sarvam leg was down, submitted once through the
    batch STT path instead of replayed into the freshly reconnected live stream — bursting
    stale audio into a live connection would confuse Sarvam's own real-time VAD timing.zoutage-gap.wavr  Nr	  r9  r:  r#  r  r  r?  Tz>Sarvam batch fallback hit a fatal account error, giving up: %sz?Failed to submit Sarvam-outage audio gap via batch fallback: %sr  )r;   r  r  rc   r  r  r   r   r   rA  r7  r@  r  r  ro   r  r  rV  r   )r  r   r  r   r   r  r  	wav_bytesr  r  r   	persistedrA  r  s                 rO   _submit_outage_bufferr  C	  s    q$Y0A0AB	*;IGWYdfn*o$o!
M%%'
]g5/
MJJJ== 		 		,,x||,C;GT3sJ)O(PR_ I &64hll1K]fgs]tuXYQ}%5AkNSu  		 		 		 %p
 K		 v		 		 		 		  q!#&
 !$CE EMLLY[^_b[cd 	VX[\_X`koppqs   G'E DE GE D E 1D"2E 5;D/0D$1;D/,D&>
D/D+	D/E D-E GE  E "E $D/&D/-E /E5D86E=E  GE 	F>AF9G!F94G9F>>Gc                   K   | j                   4 d{    | j                  s	 ddd      d{    y| j                  rd| _        	 ddd      d{    yt	        t
        d      D ]  \  }}	 | j                  j                          d{    d| _        | j                  r[t        | j                        }t               | _        t        | ||||||       d{    | j                  r ddd      d{    y ddd      d{    y d| _        	 ddd      d{    y7 7 7 7 7 X7 =7 -# t        $ r}	t        |	      rMt        |	      | _        d| _        t        j!                  dt        |	             Y d}	~	 ddd      d{  7   yt        j#                  d|t$        t        |	             t'        j(                  |       d{  7   Y d}	~	}d}	~	ww xY w7 # 1 d{  7  sw Y   yxY ww)u  Called by whichever relay task first notices the Sarvam connection died. Only one
    caller actually retries — guarded by reconnect_lock — since both directions share the
    one underlying Sarvam connection and would otherwise both try to reconnect at once.NTFrK   )startz@Sarvam stream reconnect hit a fatal account error, giving up: %sz0Sarvam stream reconnect attempt %d/%d failed: %s)r  r  r  r  rP  r>   r  connectr  bytesr  r  r  r  ro   rV  r   r
  r=   rW  rX  )
r  r   r  r   r   r  rH   backoffbufferedr  s
             rO   _recover_sarvam_streamr  k	  s     ## " "" " "  !EM" " " !**DA N 	-GW-ll**,,,"'&&$U%8%89H*3+E'/r7HdT\^fggg}}  %)" " "* +" " "	-2 E" " " " " -
 h" ",  
-)#.(+CE%$(EMLL!cehilemn 7" " "8 F6C mmG,,,
--" " " "s2  HD/HG3HD2HG3
HD5HG33D?D7AD? D9!D?1G32H=D;>HG3HD=H	G3H)G1*H2H5H7D?9D?;H=H?	G.AG)	G3HFH =G)G 
G)#G3)G..G31H3H9G<:HHr   	websocketr  c           
      |  K   t        j                         }t        j                  d|       |4 d{    t	        j
                  t        j                        }	t        | |||	d|dg|       d{   }
|
d   s't        j                  d       	 ddd      d{    y|
d   D cg c]  }|d   |d   d	 }}t        j                         }	 t        | |||t	        j
                  t        j                        |       d{   }t        j                  dt        j                         |z
         ddd      d{    |j                  ddi       d{    t        j                  dt        j                         |z
         y7 ]7 !7 c c}w 7 # t        $ rx}t        j                  d
t        j                         |z
  |j                         |j                  d|j                  d       d{  7   Y d}~ddd      d{  7   yd}~ww xY w7 # 1 d{  7  sw Y   xY w7 ڭw)uS  Runs once per Sarvam END_SPEECH — persists the finished utterance as a PENDING
    placeholder, then classifies it, same two-step shape as the batch path. Awaited inline
    (never spawned as a background task) so classify calls for one session stay strictly
    ordered, matching the batch /classify endpoint's own sequencing guarantee.z#Stream utterance finalize start: %rNr9  r:  r#  uC   Stream utterance had nothing to persist — nothing sent to browserr  r  r?  z0Stream utterance classify failed after %.2fs: %sclassify_failed)r  r   z$Stream utterance classified in %.2fsr  	utteranceu>   Stream utterance sent to browser — total finalize time %.2fs)time	monotonicrV  rW  r   r   r   rA  r7  r@  r	   r
  r   	send_json)r   r  r   r   r   r  r  r  r  r   r  rA  rB  t_before_classify
classifiedr  s                   rO   _finalize_stream_utterancer  	  s     nnG
KK5t<  b bll8<<(7s3%E$F
 
	 &KK]^b b b U^^jTk
OPAm,1[>J
 
 !NN,		?GXtX\\(,,-G  J 	:DNN<LO`<`a-b b0 

v{AjA
BBB
KKPRVR`R`RbelRlm3b
b

  	NNBDNNDTWhDhjmjtjt %%/@CJJ&WXXX+b b b 	!b b b b0 Cs   1H<FH<;H%2F3H%H<FH<#H%*F<H%4FFF+H%7H<H#H<H: 1H<H%H<H%F	H (AH?H HH%	H<HH<H  H%#H<%H7+H.,H73H<z!/{session_id}/conversation-streamc                 @   K    j                          d {    	 t        j                   j                         d       d {   }t        |t              r%|j                  d      dk7  s|j                  d      s j                  t               d {    y 	 t        |d          d {   }t        j                  |d
         t        j                   t"        j$                        }j'                  t)        t*        t,              j/                  t,        t*        j0                  t,        j2                  k(        j5                  t*        j2                  |k(               d {   }|j7                         }|s; j                  ddd	       d {     j                  t8               d {    y |\  }j:                  t<        k7  r; j                  ddd	       d {     j                  t>               d {    y j'                  t)        t@              j5                  t@        j0                  |j2                  k(               d {   }	|	jC                         rjD                  |k  sjF                  k7  r; j                  ddd	       d {     j                  tH               d {    y |j                  d      xs dtK        |j                  d      xs tL              }
tO        |
      	 jP                  jS                          d {     j                  ddi       d {    fd} fd}fd} fd}t        j^                   |             t        j^                   |             t        j^                   |             t        j^                   |             g}	 t        j`                  |t        jb                         d {   \  }}|D ]  }|je                           |D ]6  }|jg                         }|stT        jW                  dtY        |      |       8 	 jP                  j                          d {    	 jh                  rkd}jj                  r"tT        jW                  djj                         d} j                  d|d	       d {     j                  t\               d {    n j                          d {    y y 7 7 # t        $ r"  j                  t               d {  7   Y y w xY w7 7 # t        $ r?  j                  ddd	       d {  7    j                  t               d {  7   Y y w xY w7 &7 7 7 7 7 E7 7 7 }# t        $ rv}tT        jW                  dtY        |      d       t[        |      rdnd} j                  d|d	       d {  7    j                  t\               d {  7   Y d }~y d }~ww xY w7 7 47 7 i7 N7 8# t        $ r Y y w xY w# jP                  j                          d {  7   	 jh                  rmd}jj                  r"tT        jW                  djj                         d} j                  d|d	       d {  7    j                  t\               d {  7   w  j                          d {  7   w # t        $ r Y w w xY wxY ww)Ng      $@)timeout)r  r  authtokenauth_failedINVALID_TOKEN)r  reasonr  r  rD  r  r  r   
sampleRatez Sarvam stream connect failed: %sTr  SARVAM_QUOTA_EXCEEDEDSARVAM_UNAVAILABLEfallback_requiredreadyc                    K   	 t        j                  t               d {    j                  4 d {    t	        j
                  t        j                        t        t        j                        z   _         j                          d {    d d d       d {    7 7 r7 7 # 1 d {  7  sw Y   xY ww)Nr	  )rW  rX  _LOCK_REFRESH_INTERVAL_Sr  r   r   r   rA  r   r   rB  r   rJ  )r   r   r  s   rO   refresh_lock_periodicallyz6conversation_stream.<locals>.refresh_lock_periodically
  s     -- 8999}} " ""*,,x||"<yQYQrQr?s"siik!!" " 9"!" " " "sg   CB'CB)CAB/B+B/C!B-"C)C+B/-C/C5B86C=Cc            	        K   	 	j                          d {   } | d   dk(  ry | j                  d      }|s6j                  rj                  j	                  |       ^j
                  .t        j                         _        t        j                  d       	 j                  j                  |       d {    7 7 # t        $ r}d_        j                  j	                  |       t        |      r;t        |      _        t        j!                  dt        |             d_        Y d }~y t%               d {  7  sY d }~y Y d }~d }~ww xY ww)NTr  zwebsocket.disconnectr  zStream utterance audio started6Sarvam stream hit a fatal account error, giving up: %s)receiverN  r  r  extendr  r  r  rV  rW  r  
send_audior  r  ro   r  r   r  r  )
r   r  r  r   r  r   r  r   r  r  s
      rO   relay_browser_to_sarvamz4conversation_stream.<locals>.relay_browser_to_sarvam
  s1    %--//Gv"88!++g.K##**;7))1-1^^-=*<=ll--k::: / ; 	"&##**;7)#.(+CE%LL!Y[^_b[cd$(EM3E2wRVX`aaa b	se   E!CBE!C ;C<C  E!C 	EA#E1E!6E	E
E
E!EE!c                    K   	 t        j                  d       d{    j                  +t        j                         j                  z
  } | t
        j                  k\  rRt        j                  d|        t        j                         _        	 j                  j                          d{    7 7 # t        $ r)}t        j                  dt        |             Y d}~2d}~ww xY ww)up  Watchdog for the case Sarvam's own VAD never finds a gap at all (a continuous
        talker): if audio has been flowing for too long with no transcript.final event yet,
        logs it and restarts the clock so this fires at most once per STREAM_MAX_UTTERANCE_SECONDS
        window rather than every tick.

        NOTE: the speech-to-text-realtime endpoint's flush() only takes effect under
        endpointing="manual" — SarvamStreamSession runs endpointing="vad" (see its
        docstring), so the call below is a documented no-op today. It's left in place as
        the hook to act on if this watchdog needs real teeth again — e.g. by switching to
        endpointing="manual" and driving speech_start/speech_end explicitly, or by tuning
        silence_duration_ms/threshold on connect() so Sarvam's VAD itself cuts the boundary
        sooner for continuous talkers.g      ?Nz=Stream utterance stalled %.2fs with no transcript.final eventz;Stall-flush failed, leaving recovery to the relay tasks: %s)rW  rX  r  r  r  r   STREAM_MAX_UTTERANCE_SECONDSrV  r
  r  rT  r  ro   )elapsedr  r  s     rO   force_flush_stalled_utterancez:conversation_stream.<locals>.force_flush_stalled_utterance(
  s      --$$$))1nn&)C)CCG(???^`gh-1^^-=*l,,,,... $ /  l NN#`befibjkk	lsL   C/B6A4C/B: 0B81B: 5C/8B: :	C,C'"C/'C,,C/c                    K   	 
j                   ry 	 
j                  j                         2 3 d {   } | j                  d      }|dk(  r5| j                  d      xs d}|s7j	                  d|d       d {    T|dk(  r| j                  d      xs dj                         }
j                  r!t        j                         
j                  z
  nd	}t        j                  d
||       d 
_        |st        	|
j                         d {    |dk(  rt        j                  d       |dk(  st        j                  d|        | j                  d      s=| j                  d      xs | j                  d      xs d
_        d
_          y 7 o7 (7 6 n# t        $ r}
j                   rY d }~y d
_        t#        |      r;t%        |      
_        t        j'                  dt%        |             d
_         Y d }~y t)        
	       d {  7  sY d }~y Y d }~nd }~ww xY w9w)NTeventztranscript.partialr   r   partial)r  r   ztranscript.finalg        z0Stream transcript.final after %.2fs of audio: %rzvad.speech_endz3Stream vad.speech_end received (informational only)r   zSarvam stream error event: %sis_fatalr   r  zfatal Sarvam stream errorr  )r  r  eventsrN  r  rc   r  r  r  rV  rW  r  r  r
  r  r  r  r  ro   r   r  )r  
event_typer  recognize_elapsedr  r   r  r   r  r   r  r  s        rO   relay_sarvam_to_browserz4conversation_stream.<locals>.relay_sarvam_to_browserE
  s    }}*#(<<#6#6#8 # #%!&7!3J!%99%*YYv%6%<"
%"+"5"5yR\6]"^^^#'99&+ii&7&=2%D%D%F
  %99 !NN,u/I/II?B * NPacm 6:2%"< "GXtZS\^c^k^k#   $'77$YZ#w.'FN 99Z0 16		)0D0x		RXHY0x]xE-,0EM"=#
 _# $9>  
=="&)#.(+CE%LL!Y[^_b[cd$(EM3E2wRVX`aaa b
G s   H>F* F(F F(.F* $F* ;F#<A<F* 9F* F&&F* 'F* *5F* H> F(#F* &F* (F* )H>*	H93H4?H>AH4H>H4$H'%H4*
H>4H99H>)return_whenz-Conversation stream task ended with error: %su@   Conversation stream giving up — fatal Sarvam account error: %s)6acceptrW  wait_forreceive_jsonr  closeWS_CODE_AUTH_FAILEDr  dictrN  r   r	   r  rd   re   r   r   r   rA  r   r   r   r   r   r   r   r   rr  WS_CODE_NOT_FOUNDr   r@   WS_CODE_CONFLICTr(   r   r   r   WS_CODE_LOCK_LOSTr  r<   r  r  r  rV  r   ro   r  WS_CODE_FALLBACK_REQUIREDcreate_taskwaitFIRST_COMPLETEDcancel	exceptionr  r  )r  r   r   auth_msgr   r   r   r  r  r\  r  r  r  r  r  r  r  tasksdonependingtr  r   r  r   r  s   ` `                  @@@@@rO   conversation_streamr  	  s     


 )))*@*@*BDQQ
 h%f)=)Gx||\cOdoo#6o777('):B?? yyu&H
,,x||
$C::}g&	g}//7::=	>	}:-	. F
 ,,.C!!=DW"XYYYoo#4o555GW~~!!=DW"XYYYoo#3o444

6+#6#<#<[=S=SW^WaWa=a#bccK))+D4??c)T]]h-F!!=DW"XYYYoo#4o555||J'27Hhll<0F4FGK$X{;Ell""$$$ 

vw/
000" 6l:. .b 	3563565789;<	E%ll5g>U>UVVg 	AHHJ	 	fA++-CLcRUhade	f
 ll  """	}}-$$LL!cejevevw4F))3FRX*YZZZoo+DoEEEoo''' FG  R oo#6o777
 	8 @ !!=O"TUUUoo#6o777 	Z5
 	Z4 d 	Z5 	% 7SDQ,B3,G(Ma!!+>&"QRRRoo#<o=== 1p W 	# [E' 		 ll  """	}}-$$LL!cejevevw4F))3FRX*YZZZoo+DoEEEoo''' 		s  \T\(T TT A\U\%U 7U8U <B4\0V1-\V\<V=4\1V2\V"A\ V%!A\,V(-\
V+A\V1 1V.2V1 6\X3B\(Y X65Y 9#Y \:X9;\ AY X<Y 1X?2Y 
YY \T "U9T<:U?\U\U  V+U.,V
VV\V\\\\"\%\(\+\.V1 1	X0:AX+XX+ X#!X+&\+X00\6Y 9\<Y ?Y Y 	Y\Y\\2Y53\9A\[\+[.,\1\2\\\\	\\\\\z"/{session_id}/conversation-historyc                   K   |j                  t        t              j                  t        j                  | k(               d {   }|j                         st        dt        j                  dd      |j                  t        t              j                  t        j                  | k(  t        j                  dk7        j                  t        j                               d {   }d|j                         j                         D cg c]&  }|j                   |j"                  |j                  d( c}iS 7 7 Vc c}w w)Nr   ru  r   r   r+  r#  )rE  r  r   )r   r   r   r   r   r   r	   r?   r  r*   r   r.  r   r   r   r   r,  r-  )r   r   r   r  utterances_resultrA  s         rO   get_conversation_historyr  
  s&     ::}##M$4$4
$BC N ,,.(::GZ[
 	

 !jj$%	!,,
: "00I=

 
'77	8
 
 	 '..0446
 	  !~~.."#"3"3
	 	)

s7   AED<B"E'D>(%E+E 8E>E Ec                   >    e Zd ZU eed<    ed      ed               Zy)UpdateResponseRequestr  c                 @    |j                         }|st        d      |S )Nzanswer cannot be empty)rc   rf   rg   s     rO   validate_answerz%UpdateResponseRequest.validate_answer
  s#     GGI566rQ   N)rl   rm   rn   ro   rp   r   rq   r  rr   rQ   rO   r  r  
  s&    KX  rQ   r  z)/{session_id}/responses/{sequence_number}r   c                 ^
  K   |j                  t        t              j                  t        j                  | k(               d {   }|j                         }|st        dt        j                  dd      |j                  t        t              j                  t        j                  | k(        j                  t        j                  |k(               d {   }|j                         }|st        dt        j                  dd      |j                  |_        |j                          d {    |j                  t         t"        fvr||j                  d dS |j                  t        t$              j                  t$        j                  |j&                  k(               d {   }	|	j                         }
|j                  t        t              j                  t        j                  | k(        j)                  t        j                               d {   }|j+                         j-                         }|D cg c].  }|j                  t.        k7  r|j0                  |j                  d0 }}|
j2                  |
j4                  |
j6                  |
j8                  d}|j                  t        t:              j                  t:        j                  | k(        j)                  t:        j<                               d {   }|j+                         j-                         D cg c]  }|j>                  s|j>                   }}tA        ||jB                         d {   \  }}}	 tE        jF                  tH        jJ                        }tM        ||tO        |
jP                        ||xs d 	       d {   }tS        tE        jF                  tH        jJ                        |z
  jU                         d
z        }|j                  t        t\              j                  t\        j                  | k(               d {   }|j                         }|r||_/        ||_0        n0|jc                  t]        te        jf                         | ||             |j                          d {    ||j                  |dS 7 ~7 7 7  7 c c}w 7 c c}w 7 w7 ## tV        $ r9}tX        j[                  dtO        |             ||j                  d dcY d }~S d }~ww xY w7 7 }w)Nr   ru  r   r   zResponse not found)r   r  r  r  r  r  r  z3Summary regeneration failed after response edit: %s)r   r   r  r  )4r   r   r   r   r   r   r	   r?   r  r    r   r   r  r  rJ  r   rA   rB   r   r   r   r   r   r  r,  r   r   r   r   r)   rX  rK  r   r   r   r   r   rA  r.   ro   r  r  r  r  rV  r   r!   r  r  r   rd   rG  )r   r   r  r   r  r  r  response_resultr  rZ  r  all_responses_resultrf  r   r!  r   r  r$  re  r  r  r  r  r  existing_resultr[  s                             rO   update_responser  
  sQ     ::}##M$4$4
$BC N //1G(::GZ[
 	

 JJ 	**j8	9	//?B	C O
 113H(::G[\
 	

 !%H
))+ ~~2I>>"1T[[Y]^^::wgjjG,>,>>? N //1G!# 	**j8	9	"22	3" 
 )002668M !11 __0B0BCL  {{..$$	L ::}	}'':5	6	-**	+ N
 2@1G1G1I1M1M1OdASTScScq''dOd!22w7L7L!MMA~q_\\(,,/
-%%G//0)+3t
 
 (,,x||4zAPPRUYYZ

 JJ~$$^%>%>*%LM O 113H ,)3&
~zz|!%",	
 	 ))+-Uabb{ 

 eM
  _JCPSHU"1T[[Y]^^_ s  AT-SBT-SAT-3S4A7T-+S,A2T-S&T-3S8BT-S$T-,S>ST-'S(T-1AS$ >S!?AS$ AT-T)A(T--T+.T-T-T-T-T-T-T-!S$ $	T&-.T!T&T-!T&&T-+T-c                   L    e Zd ZU eed<   dZeed<    ed      ed               Zy)SpeakRequestr   r   r  c                 X    |t         vr!t        ddj                  t                      |S )Nzlanguage must be one of: z, )r9   rf   r   rg   s     rO   r  zSpeakRequest.validate_language<  s0     ''8CV9W8XYZZrQ   N)	rl   rm   rn   ro   rp   r  r   rq   r  rr   rQ   rO   r  r  8  s0    
IHcZ   !rQ   r  z/{session_id}/speakc                 V  K   	 t        |j                  |j                         d {   }t        ||j                         d {   }t        |d      S 7 /7 # t        $ rB}t
        j                  dt        |             t        dt        j                  dd      d }~ww xY ww)NzTTS failed: %sr~  zmUnable to read this question aloud in the selected language. Please try again or choose a different language.r   r   r  )r<  
media_type)sarvam_translate_to_langr   r  
sarvam_ttsr  rV  r   ro   r	   r?   r  r   )r   r  r   r  
translatedr  r  s          rO   
speak_textr  D  s     
3DIIt}}MM
&z4==AA KK@@ NA 
%s3x0(77  Et  u
 	

sJ   B)#A AA AA 
B)A A 	B&$=B!!B&&B)r  )rW  r  loggingr  r  rd   r   r   r   typingr   r  websockets.exceptionsr  fastapir   r   r	   r
   r   r   r   r   fastapi.responsesr   r   sqlalchemy.ext.asyncior   
sqlalchemyr   r   r   sqlalchemy.dialects.postgresqlr   rE  sqlalchemy.excr   pydanticr   r   app.core.depsr   r   r   app.core.configr   app.models.patientr   app.models.intake_sessionr   r   app.models.question_responser    app.models.patient_summaryr!   app.models.userr"   app.models.mstr_roler#   app.models.mstr_departmentr$   app.models.mstr_questionr%   app.models.question_dept_mapr&   app.models.active_sessionr'   app.models.patient_lockr(   app.models.patient_recordr)   !app.models.conversation_utterancer*   'app.models.conversation_custom_questionr+   app.services.geminir,   r-   r.   r/   r0   r1   r2   r3   app.services.sarvamr4   r  r5   r<  r6   r  r7   r  r8   r  r9   r:   r;   r<   r=   r>   app.constantsr?   app.constants.session_statusr@   rA   rB   app.constants.role_keysrC   rD   rE   r  	getLoggerrl   rV  routerr   r{   r  rZ  rT  rM   rN   r  floatrP   r  r  r  r  r  r  r  r_   rt   r   re   tuplero   r&  r  r   r   r   r   r   rN  r  postrs  r  r  r  r  r  patchr  r  r  r  r  r  r   r  r  r"  r7  r=  rC  r@  r  r  r  rY  r  r  r  r  r  r  r  r  r  r  r  r  r  r  rr   rQ   rO   <module>r'     s
      	   2 2    _ _ _ 4 / + + > ) / G G $ & G 9 5   ) 5 1 8 3 / 3 C N  
    & P P E E!5-8 			8	$	  ,/ )#$   !$ " cs cu c
        + 
) Y -Y -@F Ftyy FU3PSUYZ^U_K_E` F2BtDz BSVWZS[^bSb Bnr BL dii DQUJ ,
{T/A 
TYY 
]e 
jn 
 B.PQv~6v
#
$	UUU 	U Ut R v
#
$]
]] ]D	 O v
#
$V		VV Vv #$ v
#
$		 %H $% v
#
$	o		o
o 	o &oh %& $:#;v
#
$	M		M
 M 	M 'Md	  "# v
#
$	3		3
3 	3 $3. %& v
#
$n		nn 'nf 34 v
#
$8+		8+8+ 58+zY  -. v!"34	?'		?'
 ?' 	?' 	?' /?'H +, Cyv!"34	oL		oL
oL 	oL 	oL -oLh &' v
#
$#		## (#P '( CyMHv!"349&		9&
9& 9& 	9&
 	9& 9& )9&|9  *CC,C4?CFNC$ZC(+C 
CL <= CyMv
#
$<_		<_
<_ <_ 		<_ ><_N :; v
#
$	'd		'd
,'d 	'd <'dTCC,C8<		CITC	C#':C 
CZ
    , 	 d & &8%q#%q)5%q@M%qii%q*%q7<%qHK%q 
%qP)#))5)@M)ii)*)69) 
)X)n)n,)n8<		)nIT)n
)n)n)2)n=D\\)n 
)nX 56 vLL		L 	L 7Lj 01 v
#
$"		"" 2"R	I 	 9:
 v!"34ec		ecec  ec 		ec
 ec ;ecP	9 	 "# v!"34	A		A
A 	A 	A $ArQ   