o
    GiH6                     @   s  U d Z ddlZddlZddlZddlZddlmZ ddlmZmZ ddl	m
Z
mZ ddl	Z	ejejd edZedZd	Zi Zeeef ed
< i Zeeef ed< g Zeed< dddddii dZi Zeeef ed< G dd dZde
jde
jfddZde
jde
jfddZ de
jde
jfddZ!de
jde
jfddZ"de
jde
jfd d!Z#de
j$fd"d#Z%e&d$kre'ed%d&Z(e)d'e(  e% Z*e
j+e*d(e(d) dS dS )*zh
ElevenLabs ConvAI Server
Provides WebSocket endpoint for real-time voice conversations with ElevenLabs
    N)datetime)DictSet)web	WSMsgType)levelelevenlabs_serverELEVENLABS_API_KEYz#https://api.elevenlabs.io/v1/convaiactive_sessionssession_metricsmetrics_historygQ?gQ?)eleven_monolingualeleven_multilingualultrag{Gz?)ttssttllmsession_costsc                   @   s.   e Zd ZdZdd ZdejdejfddZdS )	ElevenLabsConvAIHandlerz6Handles WebSocket connections to ElevenLabs ConvAI APIc                 C   s   t  | _d| _d S )Nr   )setactive_connectionssession_count)self r   ^/var/www/html/vikas/2025-Nov-21-Voicebot/BackEnd/agent-starter-python/src/elevenlabs_server.py__init__1   s   
z ElevenLabsConvAIHandler.__init__requestreturnc              
      sZ  t  |I dH  d| j |  jd7  _t  ddt< dddddddddt< | j	
 td  t d	t }zz_t 4 I dH J}||4 I dH + d
t d<  fdd} fdd}t| | I dH  W d  I dH  n1 I dH sw   Y  W d  I dH  n1 I dH sw   Y  W n( ty } ztd|  dt d< t|t d< W Y d}~nd}~ww W | j	 tv rdt d< t  t d< ti t d< td  S | j	 tv r$dt d< t  t d< ti t d< td  w )z<Handle WebSocket connection for real-time voice conversationNsession_   
connecting)
started_atstatusr   )stt_costtts_costllm_cost
total_cost
turn_countstt_characterstts_characters
llm_tokenszNew WebSocket connection: z/ws?api_key=	connectedr"   c                     sp   2 z13 d H W } | j tjkr| j} |I d H  q| j tjkr+ | jI d H  q| j tjkr4 d S q6 d S )N)typer   TEXTdatasend_strBINARY
send_bytesERROR)msgtext)elevenlabs_wswsr   r   forward_to_elevenlabsY   s   zGElevenLabsConvAIHandler.handle_websocket.<locals>.forward_to_elevenlabsc                     s   2 z3 d H W } | j tjkrzt| j}tvrg t< t t	 
 |dd|d |ddks<d|v r|di }|dd}|dkrht d  |7  < t d  |d	 td
 d  7  < |dd}|dkrt d  |7  < t d  |d	 td d  7  < |dd}|dkrt d  |7  < t d t d  t d  t d< |ddks|ddkrt d  d7  < W n   Y | jI d H  q| j tjkr| jI d H  q| j tjkr d S q6 d S )Nr,   unknown)	timestampr,   r.   usagecharacter_countr   r(   r#   i  r   r   tts_character_countr)   r$   r   r   llm_token_countr*   r%   r&   agent_responseturn_endr'   r   )r,   r   r-   jsonloadsr.   r   appendr   now	isoformatgetr   ELEVENLABS_PRICINGr/   r0   r1   r2   )r3   r.   r:   	stt_chars	tts_charsr*   r5   
session_idr6   r   r   forward_to_cliente   sV   

$$



zCElevenLabsConvAIHandler.handle_websocket.<locals>.forward_to_clientzWebSocket error: errordisconnectedended_atcostszWebSocket closed: )r   WebSocketResponsepreparer   r   rC   rD   r
   r   r   addloggerinfoELEVENLABS_CONVAI_URLr	   aiohttpClientSession
ws_connectasynciogather	ExceptionrL   strdiscardrE   )r   r   elevenlabs_ws_urlsessionr7   rK   er   rI   r   handle_websocket5   sj   


9*(O
z(ElevenLabsConvAIHandler.handle_websocketN)	__name__
__module____qualname____doc__r   r   RequestrP   ra   r   r   r   r   r   .   s    r   r   r   c                    s   t dt  dS )zHealth check endpointok)r"   r9   )r   json_responser   rC   rD   r   r   r   r   health_check   s
   
rj   c                    sJ  t  }d}d}t D ]\}}|D ]}d|di v r)||d d 7 }|d7 }qq|dkr3|| nd}d}d}	d}
d}t D ]$\}}||dd7 }|	|dd7 }	|
|dd7 }
||dd7 }qAi }t D ]8\}}t|ddd	t|ddd	t|ddd	t|d
dd	|dd|dd|ddd||< qltdd t	 D tt|t|d|
 t|d	t|	d	t|
d	t||	 |
 d	dd|dkrt|| d	nd|dkrt|	| d	nd|dkrt|
| d	nd|dkrt||	 |
 | d	ndddt|d}t| ttdkr td t|S )zEMetrics endpoint showing active sessions, latency, and cost breakdownr   latencyr.   r   r#   r$   r%   r'      r&   r(   r)   )r#   r$   r%   r&   r'   r(   r)   c                 S   s   g | ]}| d dkr|qS )r"   r+   )rE   ).0sr   r   r   
<listcomp>   s    z#metrics_handler.<locals>.<listcomp>   USD)r   r   r   totalcurrency)r   r   r   rr   )rr   per_turn_average)r
   total_sessionstotal_turnsaverage_end_to_end_latency_msr9   cost_breakdownsessionsr   d   )r   rC   r   itemsrE   r   roundlenr
   valuesrD   r   rB   popr   rh   )r   current_timetotal_latencylatency_countrJ   metricsmetricavg_latencytotal_stt_costtotal_tts_costtotal_llm_costrv   	cost_datasession_cost_breakdownmetrics_datar   r   r   metrics_handler   sn   


"


r   c              
      s  t  d}trdtini }z[t 4 I dH E}|j||d4 I dH "}| I dH }t|W  d  I dH  W  d  I dH  W S 1 I dH sKw   Y  W d  I dH  W dS 1 I dH sbw   Y  W dS  ty } zt	
d|  tjdt|iddW  Y d}~S d}~ww )	z#List available LLMs from ElevenLabs	/llm/list
xi-api-keyN)headerszError fetching LLM list: rL     r"   )rU   r	   rV   rW   rE   r@   r   rh   r[   rS   rL   r\   )r   urlr   r_   responser.   r`   r   r   r   	list_llms  s"   
2"r   c              
      s@  z	|   I dH }W n   i }Y t d}trdtini }z\t 4 I dH F}|j|||d4 I dH "}|  I dH }t|W  d  I dH  W  d  I dH  W S 1 I dH s\w   Y  W d  I dH  W dS 1 I dH ssw   Y  W dS  ty } zt	
d|  tjdt|iddW  Y d}~S d}~ww )	zCalculate LLM usage/costN/llm-usage/calculater   )r@   r   zError calculating LLM usage: rL   r   r   )r@   rU   r	   rV   rW   postr   rh   r[   rS   rL   r\   )r   r.   r   r   r_   r   resultr`   r   r   r   calculate_llm_usage  s*   
2"r   c              
      s"   t ddddddddd	d
S )z!Index handler showing server infozElevenLabs ConvAI Serverz1.0.0/ws//health/metricsr   r   )	websockethealthr   r   calculate_usagerunning)nameversion	endpointsr"   )r   rh   ri   r   r   r   index_handler(  s   r   c                  C   sh   t  } t }| jdt | jdt | jdt | jdt | j	dt
 | jd|j | S )z,Create and configure the aiohttp application/r   r   r   r   r   )r   Applicationr   routeradd_getr   rj   r   r   add_postr   ra   )apphandlerr   r   r   
create_app8  s   r   __main__PORT8080z*Starting ElevenLabs ConvAI Server on port z0.0.0.0)hostport),re   rY   r@   osloggingr   typingr   r   rV   r   r   basicConfigINFO	getLoggerrS   getenvr	   rU   r
   r\   dict__annotations__r   listr   rF   r   r   rf   Responserj   r   r   r   r   r   r   rb   intr   rT   r   run_appr   r   r   r   <module>   sL    

 J