
    ˆj              
         d Z ddlmZ ddlZddlZddlZddlZddlm	Z	m
Z
 ddlmZmZmZ  ej                  d      Z G d de      Zdd	Z	 	 	 d	 	 	 	 	 	 	 	 	 dd
Z	 	 	 d	 	 	 	 	 	 	 	 	 ddZdddZedk(  rLddlZej2                  dd xs ddgZ ee      Z eee      D ]  \  ZZ eed e e       dedd           yy)uX  client.py - 아누 공용 임베딩 서비스 얇은 파이썬 클라이언트.

원칙: 서비스 미기동/오류 시 **조용한 폴백 금지**. 항상 명시적 예외를 던진다.
(0 벡터나 None 을 돌려주면 하위 파이프라인이 "임베딩이 된 것처럼" 오동작한다.)

사용:
    from client import embed_texts, embed_one
    vecs = embed_texts(["안녕하세요", "보험 상담"])   # -> list[list[float]] (각 768)
    vec = embed_one("실손의료비")                      # -> list[float] (768)

표준 라이브러리만 사용하므로 추가 의존성이 없다.
    )annotationsN)AnyOptional)CLIENT_BASE_URLCLIENT_TIMEOUTEMBEDDING_DIMzanu-embedding.clientc                      e Zd ZdZy)EmbeddingServiceErroruX   임베딩 서비스 호출 실패 (연결 불가, HTTP 오류, 응답 불변식 위반).N)__name__
__module____qualname____doc__     services/embedding/client.pyr
   r
      s    br   r
   c           	        t        j                  |d      j                  d      }t        j                  j                  | |ddid      }	 t        j                  j                  ||      5 }|j                         j                  d      }d	d	d	       	 t        j$                        }	t)        |	t*              st        d|        |	S # 1 sw Y   ?xY w# t        j                  j                  $ r|}d
}	 |j                         j                  dd      }n# t        $ r d
}Y nw xY wt        j                  d| |j                  |       t        d|j                   d|  d|       |d	}~wt        j                  j                  $ rC}t        j                  d| |j                          t        d|  d|j                    d      |d	}~wt"        $ r/}t        j                  d| |       t        d|  d| d      |d	}~ww xY w# t         j&                  $ r*}t        j                  d|        t        d|        |d	}~ww xY w)uQ   JSON POST 를 수행하고 파싱된 dict 를 반환합니다. 실패 시 예외.F)ensure_asciiutf-8zContent-Typezapplication/jsonPOST)dataheadersmethodtimeoutN replace)errorsu9   임베딩 서비스 HTTP 오류: url=%s status=%s body=%su   임베딩 서비스 HTTP u    오류: url=z detail=u3   임베딩 서비스 연결 실패: url=%s reason=%su7   임베딩 서비스에 연결할 수 없습니다: url=z reason=u9    (서비스 기동: systemctl --user start anu-embedding)u6   임베딩 서비스 타임아웃: url=%s timeout=%.1fsu&   임베딩 서비스 타임아웃: url=z	 timeout=su5   임베딩 서비스 응답 JSON 파싱 실패: url=%su.   임베딩 서비스 응답 파싱 실패: url=u:   임베딩 서비스 응답이 객체가 아닙니다: url=)jsondumpsencodeurllibrequestRequesturlopenreaddecodeerror	HTTPError	Exceptionloggercoder
   URLErrorreasonTimeoutErrorloadsJSONDecodeError
isinstancedict)
urlpayloadr   r   reqrespbodyexcdetailparseds
             r   
_post_jsonr<      sF   ::gE299'BD
..
 
 !34	 ! Cp^^##C#9 	/T99;%%g.D	/,eD!
 fd##&`ad`e$fggM=	/ 	/<<!! 		XXZ&&wy&AF 	F	PRUWZW_W_agh#'zse8F8T
	 <<   JCQTQ[Q[\#EcU(SVS]S]R^ _G H
 	  pMsT[\#&LSEQZ[bZccd$efloop  eLcR#&TUXTY$Z[addes   !C . CC H CC H5E,8!DE,D(%E,'D((AE,, H>G

H*H  HI%I  Ic           
     $   t        | t              r| st        d      t        d | D              rt        d      |xs t        j                  d       d}t        || |d||nt              }|j                  d      }t        |t              st        dt        |             t        |      t        |       k7  r#t        d	t        |        d
t        |             t        |      D ]o  \  }}t        |t              rt        |      t        k7  s)t        |t              rt        |      nt        |      j                  }	t        d| d|	 dt                |D 
cg c]  }|D 
cg c]  }
t!        |
       c}
 c}
}S c c}
w c c}
}w )u&  텍스트 목록을 임베딩합니다.

    Returns:
        len(texts) 개의 768차원 float 리스트.

    Raises:
        ValueError: texts 가 비어 있거나 문자열 배열이 아닌 경우.
        EmbeddingServiceError: 서비스 미기동/HTTP 오류/차원 불변식 위반.
    uC   texts 는 1개 이상의 문자열을 담은 list 여야 합니다.c              3  >   K   | ]  }t        |t                 y w)N)r2   str).0ts     r   	<genexpr>zembed_texts.<locals>.<genexpr>[   s     
1az!S!!
1s   u8   texts 의 모든 원소는 문자열이어야 합니다./z/embed)texts	normalize
embeddingsu2   응답에 embeddings 배열이 없습니다: keys=u)   응답 벡터 개수 불일치: expected=z actual=u.   임베딩 차원 불변식 위반: embeddings[z] dimension=z
 expected=)r2   list
ValueErroranyr   rstripr<   r   getr
   sortedlen	enumerater   typer   float)rD   rE   base_urlr   r4   r;   rF   idxvecactualvs              r   embed_textsrV   J   s{    eT"%^__

15
11STT)/11#67v
>Ci0&NF L)Jj$'#&XY_`fYgXh$ijj
:#e*$#7E
|8CPZOK\]
 	
 j) S#t$CM(A!+C!6SXDI<N<NF'@\RXQYYcdqcrs  0::s#!U1X#::#:s   #	F,F>FFc                ~    t        | t              r| j                         st        d      t	        | g|||      d   S )uH   단일 텍스트를 임베딩하여 768차원 벡터를 반환합니다.u;   text 는 비어 있지 않은 문자열이어야 합니다.)rE   rQ   r   r   )r2   r?   striprH   rV   )textrE   rQ   r   s       r   	embed_onerZ   u   s;     dC 

VWWvXwWXYZZr   c                   | xs t         j                  d       d}	 t        j                  j	                  |||nt
              5 }t        j                  |j                         j                  d            cddd       S # 1 sw Y   yxY w# t        j                  j                  t        t        j                  f$ r.}t        j                  d||       t        d| d|       |d}~ww xY w)	uJ   서비스 health 를 조회합니다. 미기동 시 EmbeddingServiceError.rC   z/healthNr   r   u%   health 조회 실패: url=%s error=%su.   임베딩 서비스 health 조회 실패: url=z error=)r   rJ   r"   r#   r%   r   r   r0   r&   r'   r(   r-   r/   r1   r+   r
   )rQ   r   r4   r7   r9   s        r   healthr\      s    )/11#67w
?Cq^^##G$7^ $ 
 	;::diik009:	; 	; 	; LL!!<1E1EF q<c3G#&TUXTYY`ad`e$fgmppqs5   )B 2B9	B BB B 2C/)C**C/__main__   u   안녕하세요u   실손의료비 보장 범위z -> dim=z head=   )r4   r?   r5   dict[str, Any]r   rP   returnr`   )TNN)
rD   z	list[str]rE   boolrQ   Optional[str]r   Optional[float]ra   zlist[list[float]])
rY   r?   rE   rb   rQ   rc   r   rd   ra   zlist[float])NN)rQ   rc   r   rd   ra   r`   )!r   
__future__r   r   loggingurllib.errorr"   urllib.requesttypingr   r   settingsr   r   r   	getLoggerr+   RuntimeErrorr
   r<   rV   rZ   r\   r   sysargvargsvectorsziptext_argvectorprintrM   r   r   r   <module>ru      sK   #       C C			1	2cL c(Z "#	(;(;(; (; 	(;
 (;Z "#		[
	[	[ 	[ 		[
 	[
q z88AB<O-/NOD$Gg. F&HS[Mr
|DEF r   