
    @iP                     |    S r SSKrSSKrSSKJrJrJr  SSKJr  SSK	J
r
  \R                  " \5      r " S S5      rg)z6Intent encoder for understanding user goals using LLM.    N)DictAnyOptional)IntentPrompt)	LLMClientc                       \ rS rSrSrSS\S\\   4S jjrS\	S\\
\	\4      4S	 jrS
\
\	\4   S\
\	\4   4S jrS\	S\\
\	\4      4S jrSrg)IntentEncoder   z0Encoder for understanding user intent using LLM.N
llm_clientavailable_poi_typesc                 Z    Xl         U=(       d    / U l        [        R                  U l        g)zInitialize intent encoder.

Args:
    llm_client: LLM client instance
    available_poi_types: List of actual POI types in the dataset
N)llmr   r   INTENT_PROMPTprompt_template)selfr   r   s      E   /home/ubuntu/codebase/yexijia/保研/iCoLoc/src/llm/intent_encoder.py__init__IntentEncoder.__init__   s$     #6#<" +99    queryreturnc                 0    [         R                  SUSS  S35        U R                  (       aM  [         R                  S[        U R                  5       S35        [        R
                  " XR                  5      nO.[         R                  S5        U R                  R                  US9n[         R                  S	5        S
nU R                  R                  X#S9n[         R                  S[        U5       35        [         R                  S5        U R                  U5      nUc  [         R                  SUSS  35        g[         R                  S[        UR                  5       5       35        U R                  (       ax  [         R                  S5        [        UR                  S/ 5      5      nU R!                  U5      n[        UR                  S/ 5      5      n[         R                  SU SU S35        UR                  SS5      n[        UR                  S/ 5      5      n	[         R                  SU SU	 35        [         R                  SUR                  S/ 5       35        U$ ! ["         a!  n
[         R%                  SU
 3SS9   Sn
A
gSn
A
ff = f)u  Parse user query to extract intent.

This method implements Stage0 intent understanding:
1. User ambiguous query (e.g., "我想开个烧烤店")
2. LLM analyzes query and extracts structured intent
3. Returns structured intent with business type, pattern preferences, etc.

Args:
    query: User's natural language query
    
Returns:
    Dictionary containing parsed intent, or None if parsing fails
z8IntentEncoder: Starting intent understanding for query: Nd   z...z$IntentEncoder: Building prompt with z available POI typesz;IntentEncoder: Building prompt without POI type constraints)r   z6IntentEncoder: Calling LLM for intent understanding...z/You are an expert in spatial business analysis.)systemz(IntentEncoder: LLM raw response length: z@IntentEncoder: Extracting structured intent from LLM response...z?IntentEncoder: Failed to extract valid JSON from LLM response:    z0IntentEncoder: Extracted intent JSON with keys: z?IntentEncoder: Validating patterns against dataset POI types...pattern_preferencez#IntentEncoder: Pattern validation: u    → z valid patternsbusinesszN/Az6IntentEncoder: Successfully parsed intent - Business: z, Patterns: z#IntentEncoder: Preferred patterns: z%IntentEncoder: Error parsing intent: T)exc_info)loggerinfor   lenr   build_intent_promptr   formatr   generatedebug_extract_jsonwarninglistkeysget_validate_patterns	Exceptionerror)r   r   prompt
system_msgraw_responseintent_jsonoriginal_countvalidated_countr   pattern_countes              r   parseIntentEncoder.parse   sR   -	KKRSXY]Z]S^R__bcd ''B3tG_G_C`Baauvw%99%AYAYZYZ--4454A KKPQJJ88,,V,GLLLCCDUCVWX KKZ[,,\:K"!`amnroras`tuvKKJ4P[P`P`PbKcJdef '']^!$[__5I2%N!O"55kB"%koo6JB&O"PA.AQQVWfVggvwx #z59H0Db IJMKKPQYPZZfgtfuvwKK=kooNbdf>g=hij 	LL@DtLT	s   D=I*  D)I* *
J4JJr1   c                    SU;  a  U$ / n[        U R                  5      nUS    H  n[        U[        5      (       d  M  U Vs/ s H#  n[        U[        5      (       d  M  XS;   d  M!  UPM%     nn[        U5      S:  a  UR                  U5        Ml  [        U5      S:X  d  M}  [        R                  SU 35        M     X!S'   [        U5      S:X  a  [        R                  S5        U$ s  snf )zValidate and filter pattern_preference to only include valid POI types.

Args:
    intent_json: Parsed intent JSON
    
Returns:
    Validated intent JSON with filtered patterns
r         zSkipping single POI pattern: r   zbNo valid patterns found after filtering. Original patterns may have used POI types not in dataset.)
setr   
isinstancer(   strr!   appendr   r%   r'   )r   r1   valid_patternspoi_setpatternpoi
valid_poiss          r   r+    IntentEncoder._validate_patternsX   s      {2d../"#78Ggt,, *1\#JsC4H#S^#J\ :!#%%j1ZA% <ZLIJ 9 -;()~!#NN  A ]s   C( C('C(textc                     UR                  S5      nUS:X  a  gSnUn[        U[        U5      5       H+  nX   S:X  a  US-  nM  X   S:X  d  M  US-  nUS:X  d  M)  Un  O   US:w  a  [        R	                  S5        gXUS-    n[
        R                  " U5      n[        U[        5      (       d  gSU;   ag  [        US   [        5      (       d  / US'   U$ US    Vs/ s H4  n[        U[        5      (       a  UO[        U[        5      (       a  U/O/ PM6     snUS'   U$ s  snf ! [
        R                   a"  n	[        R	                  S	U	 35         Sn	A	gSn	A	f[         a"  n	[        R                  S
U	 35         Sn	A	gSn	A	ff = f)zExtract JSON object from LLM response.

Args:
    text: Raw LLM response text
    
Returns:
    Parsed JSON dictionary, or None if extraction fails
{Nr   r:   }z!Unmatched braces in JSON responser   zJSON decode error: zError extracting JSON: )findranger!   r   r'   jsonloadsr<   dictr(   r=   JSONDecodeErrorr,   r-   )
r   rE   	start_idxbrace_countend_idxijson_strintent_datapr5   s
             r   r&   IntentEncoder._extract_json}   s   1	 		#IB KG9c$i07c>1$KW^1$K"a'"# 1 aBCgk2H**X.K k400 ${2!+.B"CTJJ8:K 45  "--A!B9!BA (400Z3=O=OqcUWW!B9K 45
 9 ## 	NN045 	LL21#67	sX   D% 1D% 	D% !D% >2D% 1$D% D% ;D D%  D% %F9EF#F  F)r   r   r   )N)__name__
__module____qualname____firstlineno____doc__r   r   r(   r   r=   r   r   r6   r+   r&   __static_attributes__ r   r   r	   r	      s    :	:9 	:8D> 	:;3 ;8DcN#; ;z#d38n #c3h #J:# :(4S>*B :r   r	   )r\   rL   loggingtypingr   r   r   llm.intent_promptr   
llm.clientr   	getLoggerrX   r   r	   r^   r   r   <module>rd      s6    <   & & *  			8	$j jr   