
    0i                       d Z ddlmZ ddlZddlmZ ddlmZmZ ddl	m
Z
 ddlmZ ddlmZmZmZmZmZmZmZmZmZmZ  ed	d
g      Z G d de      Z G d de      Z G d de      Z	 	 	 	 ddZej;                  de      dd       Zy)ui  Prior-art search + benzerlik analizi tek endpoint'te.

POST /api/v1/prior-art/search:
- Input: query (doğal dil) + invention_summary + kaynak seçimi
- EPO ve/veya Google Patents paralel arama
- Birleştir, dedup (patent_no bazlı), limit'le
- Claude Haiku 4.5 ile her hit için similarity_score + rationale
- similarity_score'a göre DESC rank'lenmiş sonuç
    )annotationsN)	APIRouter)	BaseModelField)get_settings)LLMNotConfiguredError)
AnalysisErrorAnalysisItemEspacenetAuthErrorEspacenetClientEspacenetErrorEspacenetNotConfiguredGooglePatentsClientGooglePatentsErrorPriorArtHitanalyze_prior_artz
/prior-artz	prior-art)prefixtagsc                      e Zd ZU  eddd      Zded<    edddd	
      Zded<    ed      Zded<    ed      Zded<    eddd      Z	ded<   y)PriorArtSearchRequest.   i  )
min_length
max_lengthstrquery   i  u,   Buluşun kısa özeti — AI skorlama için.)r   r   descriptioninvention_summaryT)defaultboolinclude_epoinclude_google
         )r   geleintlimit_per_sourceN)
__name__
__module____qualname__r   r   __annotations__r   r!   r"   r)        0/var/www/ai.patentyazar.com/app/api/prior_art.pyr   r   $   sg    sqS9E39"B	s  d+K+ .ND.!"r:c:r/   r   c                      e Zd ZU dZded<   ded<   dZded<   dZded<   dZded	<   dZd
ed<   dZ	ded<   dZ
ded<   dZd
ed<   dZded<   dZded<   dZded<   dZded<   y)PriorArtSearchHitu.   Hit + analiz birleşimi (frontend'e tek obje).r   source	patent_noNz
str | Nonetitleabstract	applicantzlist[str] | None	inventorsfiling_datepublication_datecpc_classesurlz
int | Nonesimilarity_score
risk_level	rationale)r*   r+   r,   __doc__r-   r5   r6   r7   r8   r9   r:   r;   r<   r=   r>   r?   r.   r/   r0   r2   r2   1   s    8 KNE:Hj Iz "&I&"K"#'j'$(K!(C#'j'!J
! Iz r/   r2   c                  @    e Zd ZU ded<   ded<   ded<   ded<   d	ed
<   y)PriorArtSearchResponser   r   zdict[str, int]source_countsr(   
total_hitsr    analyzedzlist[PriorArtSearchHit]hitsN)r*   r+   r,   r-   r.   r/   r0   rB   rB   E   s    J!!ON
!!r/   rB   c                     i }| D ]U  }|D ]N  }|j                   j                         }||vr|||<   '||   j                  dk(  s:|j                  dk(  sJ|||<   P W t        |j	                               S )u   Birden fazla kaynağın hit'lerini patent_no bazlı dedup eder.

    Aynı patent hem EPO hem Google'dan gelirse EPO kaydı tutulur (daha güvenilir).
    googleepo)r4   upperr3   listvalues)	hit_listsseenrF   hitkeys        r0   _merge_and_deduprQ   M   s     $&D   	 C--%%'C$S	c!!X-#**2ES		   r/   z/search)response_modelc                   K   t               }g }g }i }g }t        |j                  xr |j                        } j                  rS|rQt        |j                  |j                        d fd}|j                  t        j                   |                    n j                  r|sd|d<    j                  r:t               d fd}|j                  t        j                   |                    |rt        j                  |ddi d{   }	d}
 j                  rQ|rO|	|
   }|
dz  }
t        |t              r|}n2t        |t        t        z        rd|d<   nt        |t               rd|d<    j                  r-|	|
   }t        |t              r|}nt        |t"              rd|d	<   t%        |      |d
<   t%        |      |d<   t'        ||      }i }d}|rG|j(                  r;	 t+         j,                  |       d{   }|D ci c]  }|j.                  | }}d}g }|D ]  }|j5                  |j.                        }|j                  t7        |j8                  |j.                  |j:                  |j<                  |j>                  |j@                  |jB                  |jD                  |jF                  |jH                  |r|jJ                  nd|r|jL                  nd|r|jN                  nd              |jQ                  d        tS         jT                  |t%        |      ||      S 7 !7 3c c}w # t0        t2        f$ r d}Y .w xY ww)z)Prior-art arama + AI similarity skorlama.c                    K   	  j                  j                  j                         d {    j                          d {    S 7 7 #  j                          d {  7   w xY wwN)limitsearchr   r)   close)
epo_clientrequests   r0   _epozprior_art_search.<locals>._epoq   sZ     )'..w}}GD\D\.]] &&((( ^(j&&(((I   A.*A AA A.AA.A A.A+$A'%A++A.r   	epo_errorc                    K   	  j                  j                  j                         d {    j                          d {    S 7 7 #  j                          d {  7   w xY wwrU   rW   )google_clientr[   s   r0   _googlez!prior_art_search.<locals>._google   sZ     ,*11'--wG_G_1``#))+++ a+m))+++r]   return_exceptionsTNr$   google_errorrI   rH   F)r3   r4   r5   r6   r7   r8   r9   r:   r;   r<   r=   r>   r?   c                @    | j                   d u | j                   xs d fS )Nr   )r=   )hs    r0   <lambda>z"prior_art_search.<locals>.<lambda>   s%    !3!3t!;q?Q?Q?VUV=W X r/   )rP   )r   rC   rD   rE   rF   )returnlist[PriorArtHit])+r   r    epo_ops_keyepo_ops_secretr!   r   appendasynciocreate_taskr"   r   gather
isinstancerK   r   r   r   r   lenrQ   anthropic_api_keyr   r   r4   r   r	   getr2   r3   r5   r6   r7   r8   r9   r:   r;   r<   r=   r>   r?   sortrB   r   )r[   settingsepo_hitsgoogle_hitsrC   tasksepo_configuredr\   ra   resultsidxresmergedanalyses_by_patentrE   analysesacombinedrO   analysisrZ   r`   s   `                   @@r0   prior_art_searchr   `   s     ~H #%H%'K$&M "E (..J83J3JKN~$X%9%98;R;RS
	) 	W((01			^%&k" +-	, 	W((34 FFF>#,C1HC#t$C!7:L!LM-.k*C0-.k*!!#,C#t$!C!3401n-x=M%!+.M( h4F 35H(,,	.w/H/H&QQH:B!CQ!++q.!C!CH )+H 
%))#--8zz--ii----OO!$!5!5OOGG>F!:!:D2:8..08(,,d	

* MMXMY!mm#x=  G> R!C%}5 	H	s\   DML.CM%L9 >L1?L9 L4L9 DM1L9 4L9 9M
MMM)rM   rh   rg   rh   )r[   r   rg   rB   )r@   
__future__r   rl   fastapir   pydanticr   r   
app.configr   app.services.llmr   app.services.prior_artr	   r
   r   r   r   r   r   r   r   r   routerr   r2   rB   rQ   postr   r.   r/   r0   <module>r      s    #   % # 2   
,k]	;
;I 
;!	 !("Y "!& Y'=>m ?mr/   