
    Oj                       U d Z ddlmZ ddlZddlZdZg dg dg dg dg d	g d
g dg dg dd	Zded<   g dZ	dZ
dZdZdddddddddddddZd(dZ ej                  d ej                         Zd)d!Z G d" d#      Zdad$ed%<   d&ad*d'Zy)+u4  Semantic intent router — the fast brain-in-the-middle.

Claude is a thinker, not a light switch. This layer classifies every final
transcript in ~1ms (model2vec static embeddings, pure numpy, CPU) and decides
what KIND of utterance it is:

  reflex intents  (volume_up, mute_sound, next_track, open_app, ...)
      -> executed instantly in-process, no LLM round-trip
  everything else -> flows to Claude unchanged

It matches MEANING, not keywords: "increase the volume", "crank it up",
"I can't hear this" all land on volume_up; "I don't want to hear this" lands
on mute. Each intent is defined by example phrases; an utterance is embedded
and compared to every example (cosine). It only fires when CONFIDENT — best
score >= THRESHOLD and clearly ahead of both the runner-up intent and a set
of "conversation" decoy examples — otherwise it stays out of the way and
Claude handles the nuance. When unsure, think; when sure, act.

Multipliers are parsed separately ("three times", "a lot", "way up" scale
volume presses). Falls back cleanly if model2vec isn't installed.
    )annotationsNzminishlab/potion-base-8M)z	volume upzturn the volume upzincrease the volumelouderzmake it louderz
turn it upzcrank up the volumezraise the volumezit's too quietzpump up the volumezturn the sound upzbump the volume up)zvolume downzturn the volume downzdecrease the volumequieterzlower the volumezturn it downzit's too loudzmake it quieterznot so loudzbring the volume downzturn the sound down)
mutezmute the soundzmute the audiosilencezi don't want to hear thiszshut the sound offzkill the soundzmute everythingzno soundzturn the sound off)unmutezunmute the soundzsound back onzturn the sound onzgive me the sound back)pausezpause the musiczpause the songzstop the musiczhold the musiczpause playbackzstop playing)playresumezresume the musiczkeep playingunpausezcontinue the musiczplay it again)	nextz	next songz
next trackskipzskip this songzskip this onezplay the next onezput on the next songzi don't like this song)zprevious songzprevious trackzgo back a songzplay the last songzput the previous one back on)
zopen discordzopen chromezlaunch steamzstart spotifyzopen notepadzopen the browserzlaunch the gamezopen whatsappzstart teamszopen file explorer)		volume_upvolume_down
mute_soundunmute_soundpause_mediaresume_media
next_track
prev_trackopen_appzdict[str, list[str]]INTENTS)zwhat's the volume of a spherezwhy did the music stopzwhat song is thisz%open discord and tell saad i'm comingz$open chrome and search for somethingz(can you fix the volume issue in the codezwhat apps are open right nowzhow do i open a file in pythonz%turn down the brightness of my futureztell me about the next stepszwhat should i play nextz#pause for a second and listen to mezlet me teach you a workflowz*take a screenshot and tell me what you seezi can't hear youzi can't hear jarviszi can't hear you jarviszi can't hear anything you sayz#you're breaking up i can't hear youzare you there i can't hear yougףp=
?gQ?
                           	   )oneoncetwotwicethreefourfivesixseveneightninetenc                   | j                         t        j                  ddj                  t              z   dz         }|rX|j                  d      }|j                         rt        |      nt        j                  |d      }t        dt        |d            S t        fddD              ryt        fd	d
D              ryy)zHow hard to apply a volume intent: '3 times'/'ten times' scale it,
    'a lot'/'way'/'max' big, 'a bit'/'slightly' small. Default 1.z(\d+||z)\s*(?:times|x)\br   r   c              3  &   K   | ]  }|v  
 y wN .0wts     :/Users/ahmed/devFolder/Ultron/claude-voice/voice/intent.py	<genexpr>zmultiplier.<locals>.<genexpr>~   s     
KJa16J   )za lotzway maxzall the waymuchr   c              3  &   K   | ]  }|v  
 y wr2   r3   r4   s     r8   r9   zmultiplier.<locals>.<genexpr>   s     
IHa16Hr:   )za bitlittleslighttouchtadr   )lowerresearchjoin	_WORD_NUMgroupisdigitintgetr;   minany)textmrawnr7   s       @r8   
multiplierrQ   u   s     	

A
		(SXXi003GGKAggajCH9==a+@1c!Rj!!

KJ
KK

IH
II    zt^(?:please\s+|jarvis[,\s]+|can\s+you\s+|could\s+you\s+)?(?:open|launch|start|run|fire\s+up|bring\s+up)\s+(?:the\s+)?c                    t         j                  d| j                         j                  d            }t	        j                  dd|t        j
                        j                         }|xs dS )z/Pull the app name out of an open_app utterance. z.!?z\s+(?:for me|please|now|up)$)flagsN)
_APP_STRIPsubstriprstriprC   I)rM   r7   s     r8   app_namer[      sO    r4::<..u56A
.ARTTBHHJA9rR   c                       e Zd ZdZddZddZy)IntentRouterz;Embeds intent examples once; classifies utterances in ~1ms.c                J   ddl m} |j                  t              | _        g | _        g }t        j                         D ]8  \  }}|D ].  }| j
                  j                  |       |j                  |       0 : t        |      }|j                  t               t        j                  | j                  j                  |      t        j                        }|t        j                   t        j"                  j%                  |dd      d      z  }|d | | _        ||d  | _        y )Nr   )StaticModeldtyper   T)axiskeepdims&.>)	model2vecr_   from_pretrained_MODEL_NAME_model_labelsr   itemsappendlenextendDECOYSnpasarrayencodefloat32maximumlinalgnorm_intent_emb
_decoy_emb)selfr_   examplesnamephrasespdecoy_startembs           r8   __init__zIntentRouter.__init__   s    )!11+>"$ $]]_MD'##D)"  - (mjj++H5RZZHrzz"))..1t.DdKK|,kl+rR   c                   |xs dj                         }|r t        |j                               t        kD  ryt	        j
                  | j                  j                  |j                         g      t        j                        d   }|t        t        t        j                  j                  |            d      z  }| j                  |z  }t        t	        j                   |            }t        ||         }t        t	        j                  | j"                  |z              }|t$        k  s||z
  t&        k  rd|fS | j(                  |   |fS )zReturn (intent, confidence) or (None, score) when the brain
        should handle it. Confident = clears THRESHOLD, beats decoys.rT   )Ng        r`   r   rd   N)rX   rl   split	MAX_WORDSro   rp   rh   rq   rB   rr   r;   floatrt   ru   rv   rI   argmaxrw   	THRESHOLDMARGINri   )rx   rM   r7   vintent_scoresbest_ibest
decoy_bests           r8   classifyzIntentRouter.classify   s    ZR C	NY.JJt{{))1779+6ZZ))*,	Sryy~~a()400((1,RYY}-.]6*+266$//A"567
)tj069:||F#T))rR   N)returnNone)rM   strr   ztuple[str | None, float])__name__
__module____qualname____doc__r   r   r3   rR   r8   r]   r]      s    E, *rR   r]   IntentRouter | None_routerFc                     t         t        s	 t               a t         S t         S # t        $ r } dat	        d|  d       Y d} ~ t         S d} ~ ww xY w)z4Lazy singleton; None when model2vec isn't available.NTz  intent router unavailable (u   ) — regex reflexes only)r   _router_failedr]   	Exceptionprint)es    r8   
get_routerr      sW     ~	P"nG N7N  	P!N1!4MNOON	Ps   
$ 	AAA)rM   r   r   rI   )rM   r   r   z
str | None)r   r   )r   
__future__r   rC   numpyro   rg   r   __annotations__rn   r   r   r   rF   rQ   compilerZ   rV   r[   r]   r   r   r   r3   rR   r8   <module>r      s   , # 	 (

O,!	 ,`
2 			qQ!a!r#	
  RZZDEGTTK

"* "*J  $	 #	rR   