
    iG                       d Z ddlmZ ddlZddlmZ ddlmZ ddlm	Z	m
Z
 ddlmZ ddlmZmZmZ dd	lmZ dd
lmZmZmZ  e	ddg      Z G d de      Z G d de      Zd%dZd&dZd'dZej;                  d      d(d       Z G d de      Z G d de      Z  G d de      Z!d)dZ"ej;                  d      d*d       Z#d+d Z$ G d! d"e      Z%ej;                  d#      d,d$       Z&y)-u  Drafting endpoints — tarifname, istemler, özet.

Sprint 3:
- POST /api/v1/llm/draft-description: intake JSON → tarifname taslağı (Opus 4.7, SSE)
- POST /api/v1/llm/draft-claims: tarifname + intake → istemler JSON (Sonnet 4.6)
- POST /api/v1/llm/draft-abstract: tarifname → özet (Haiku 4.5, max 150 kelime)

Her endpoint TürkPatent sistem prompt'unu cache_control ile gönderir —
tekrar çağrılarda ~0.1x maliyet.

Model tiering (CLAUDE.md "LLM cost discipline"):
- Opus 4.7: tarifname (karmaşık akıl yürütme)
- Sonnet 4.6: istemler (yapı + dil, orta karmaşıklık)
- Haiku 4.5: özet (150 kelime altı sıkıştırma, basit)
    )annotationsN)AsyncIterator)APIError)	APIRouterHTTPException)StreamingResponse)	BaseModelFieldValidationError)get_settings)LLMNotConfiguredErrorget_anthropic_clientload_turkpatent_system_promptz/llmllm)prefixtagsc                  *   e Zd ZU dZ ed      Zded<    ed      Zded<    ed      Zded<    ed      Z	ded<    ed      Z
ded	<    ed      Zded
<    ed      Zded<    ed      Zded<    ed      Zded<    ed      Zded<   y)InventionIntakeu  Buluş anlatımı 10-soru formu — frontend'deki questions.ts ile aynı anahtarlar.

    Laravel tarafı null değerler gönderebilir (DB'de cast edilmeyen JSON alanları)
    ya da alan tamamen eksik olabilir; her iki durumda da boş string olarak kabul ederiz.
     )default
str | Nonetechnical_fieldproblem	prior_artsolutionnovelty
advantagesindustrial_applicability
variationsterminologyexample_useN)__name__
__module____qualname____doc__r
   r   __annotations__r   r   r   r   r   r   r   r    r!        //var/www/ai.patentyazar.com/app/api/drafting.pyr   r   %   s     #("3OZ3+GZ+!"-Iz- ,Hj,+GZ+"2.J
.+0+<j<"2.J
.#B/K/#B/K/r(   r   c                      e Zd ZU  eddd      Zded<   ded<    ed	d
      Zded<    edd      Zded<   d	Zded<    eddd      Z	ded<   y	)DraftDescriptionRequest.      
min_length
max_lengthstrtitler   intakeN2   )r   r0   r   reference_codeTRz^(TR|EP|US|PCT)$)r   patternjurisdictionmodel@    >  r   geleint
max_tokens)
r"   r#   r$   r
   r2   r&   r5   r8   r9   rA   r'   r(   r)   r+   r+   8   s[    sqS9E39!&t!CNJCd4GHL#HE:DTe<J<r(   r+   c                >    d|  dt        j                  |d       dS )Nzevent: z
data: F)ensure_asciiz

)jsondumps)eventdatas     r)   _sserH   A   s#    UG8DJJt%$H#INNr(   c                   d| j                    d| j                   g}| j                  r|j                  d| j                          |j                  d       |j                  d       |j                  d       dddd	d
dddddd
}| j                  j                         }|j                         D ]b  \  }}|j                  |      xs dj                         }|j                  d|        |j                  |r|nd       |j                  d       d |j                  d       |j                  d       |j                  d       dj                  |      S )uV   Intake JSON'u Claude'a okunabilir yapılandırılmış kullanıcı mesajı olarak ver.   Patent başlığı: zHedef ofis: u   İç referans: r   u0   ## Buluş Anlatımı (10-soru formu yanıtları)z1. Teknik alanu   2. Çözülen problemu   3. Bilinen önceki çözümleru   4. Önerilen çözümu   5. Yenilik noktasız6. Teknik avantajlaru   7. Endüstriyel uygulama alanıu!   8. Alternatif uygulama biçimleriu    9. Özel terimler / kısaltmalaru   10. Somut örnek kullanım)
r   r   r   r   r   r   r   r   r    r!   z### u,   _[kullanıcı tarafından tamamlanacaktır]_z---uw  Yukarıdaki buluş anlatımından, TürkPatent formatına uygun 8-bölümlü bir tarifname **taslağı** üret. Markdown olarak yaz; bölüm başlıklarını `##` ile ver. Her bölümü 2-5 paragraf olacak şekilde doldur. Referans numaralarını parantez içinde tutarlı kullan. Eksik bilgi varsa `[kullanıcı tarafından tamamlanacaktır]` placeholder'ı koy — uydurma.
)
r2   r8   r5   appendr3   
model_dumpitemsgetstripjoin)reqpartslabelsr3   keylabelvalues          r)   _build_user_messagerX   E   sO    syyk*
s''()E s'9'9&:;<	LL	LLCD	LL ,*5+(,$E993F ZZ""$Flln 
UC&B--/tE7^$eU)WXR	 
LL	LL	LL	i 99Ur(   c                 K   	 t               }| j                  xs d}t               }t        |       }	 |j                  j                  || j                  d|ddidgd|d	gdd
i      4 d {   }t        d|| j                  | j                  d       |2 3 d {   }|j                  dk(  r@|j                  j                  dk(  s2t        dd|j                  j                  i       X|j                  dk(  sht        |j                   dd       }|dk(  rt        di        |dk(  st        di        # t        $ r$}t        ddt        |      i       Y d }~y d }~ww xY w7 7 6 |j#                          d {  7  }	t        d|	j$                  |	j&                  j(                  |	j&                  j*                  t        |	j&                  dd      xs dt        |	j&                  dd      xs ddd       d d d       d {  7   y # 1 d {  7  sw Y   y xY w# t,        $ r3}t        dd|j.                   |j0                  d       Y d }~y d }~ww xY ww)Nerrormessagezclaude-opus-4-7texttype	ephemeralr]   r\   cache_controluserrolecontentadaptive)r9   rA   systemmessagesthinkingstart)r9   r8   r2   content_block_delta
text_deltadeltacontent_block_startrh   thinking_start
text_startendcache_creation_input_tokensr   cache_read_input_tokensinput_tokensoutput_tokensrq   rr   )stop_reasonusage   Anthropic API hatası: )r[   status)r   r   rH   r1   r9   r   rX   rg   streamrA   r8   r2   r]   rl   r\   getattrcontent_blockget_final_messagerv   rw   rt   ru   r   r[   status_code)
rR   clientexcr9   system_promptuser_messagerz   rF   
block_typefinals
             r)   _stream_descriptionr   p   s~    %' II**E13M&s+L>
??))~~ #)&,k%:  &,?@j) * 
 5	 5	 "$'$4$4 YY   & 
5 
5e::!66{{''<7"7VU[[5E5E,FGGZZ#88!()<)<fd!KJ!Z/"#3R88#v-"<44W ! 7YC1225	.
5v !22444E#(#4#4(-(@(@).)B)B7>!KK)F8 8 3:!KK)BA4 4  I5	 5	 5	 5	 5	l  
4S[[MB//
 	
 	

s   I7
E %I7;H8 /E70H8 3*H#E<!E:"E<%)H#5H#1H#7H#	E4E/*I7/E44I77H8 :E<<H#FB H#H8 HH8 "I7#H5)H,*H51H8 4I75H8 8	I4)I/*I7/I44I7z/draft-descriptionc                   K   t               }|j                  st        dd      t        t	        |       dddd      S w)	u   Buluş anlatımı JSON'undan TürkPatent tarifname taslağı üretir.

    Output: Markdown, 8 TürkPatent bölümü içerir. Her AI çıktısı "taslak"tır —
    son inceleme vekile aittir.
      :   LLM servisi konfigüre edilmemiş (ANTHROPIC_API_KEY yok).r~   detailztext/event-streamzno-cacheno)zCache-ControlzX-Accel-Buffering)
media_typeheaders)r   anthropic_api_keyr   r   r   )requestsettingss     r)   draft_descriptionr      sP      ~H%%O
 	

 G$&'!%
 s   >A c                      e Zd ZU dZ eddd      Zded<    edd	      Zd
ed<    edd      Zded<    eddd      Z	d
ed<   y)	ClaimItemu   Tek bir istem kalemı..   r-   )r>   r?   r@   numberz^(independent|dependent)$)r7   r1   r]   N)r   r>   z
int | Noneparent
   i  r.   r\   )
r"   r#   r$   r%   r
   r   r&   r]   r   r\   r'   r(   r)   r   r      sN     c*FC*c#?@D#@t2FJ2cbT:D#:r(   r   c                  2    e Zd ZU dZ eddd      Zded<   y)	
ClaimsListu?   Claude'dan yapılandırılmış çıktı olarak alınacak kök..r   r4   r.   list[ClaimItem]claimsN)r"   r#   r$   r%   r
   r   r&   r'   r(   r)   r   r      s    I#CA"EFOEr(   r   c                      e Zd ZU  eddd      Zded<    eddd      Zded<   d	ed
<    eddd      Zded<   dZded<   y)DraftClaimsRequest.r,   r-   r.   r1   r2   8 description_markdownr   r3   r:   i   r<   r=   r@   rA   Nr   r9   	r"   r#   r$   r
   r2   r&   r   rA   r9   r'   r(   r)   r   r      sN    sqS9E39 %cce L#L DSU;J;E:r(   r   c                    | j                   j                         }d| j                   d| j                   d|j	                  d      xs d d|j	                  d      xs d d|j	                  d	      xs d d
|j	                  d      xs d dS )NrJ   u   

## Tarifname taslağı

u.   

## Buluş anlatımı (özet)
- Teknik alan: r   u   —u   
- Çözüm: r   z
- Yenilik: r   z
- Varyasyonlar: r   u  

---

Yukarıdaki tarifname ve anlatımdan TürkPatent formatına uygun istem taslağı üret.
Kurallar:
1. İstem 1 BAĞIMSIZ ve TEK CÜMLE olmalı.
2. Numaralar 1'den başlar, atlanmaz, sürekli artar.
3. Bağımlı istemler yalnızca daha düşük numaralı isteme referans verir.
4. 'Tercihen', 'opsiyonel', 'genellikle' yumuşatıcıları yasak.
5. Referans numaraları tarifname ile tutarlı olmalı.
6. Bağımsız istem buluşun ÖZÜNÜ kapsamalı — dar da geniş de tutmayın.

Çıktı: yalnızca `claims` alanı içeren JSON obje, her kalemde `number`, `type` (independent|dependent), `parent` (bağımlılar için), `text`.)r3   rM   r2   r   rO   )rR   r3   s     r)   _build_claims_user_messager      s    ZZ""$F
syyk *%##
$ % **%67@5A Bzz*-67 8jj+4u5 6!::l3<u= >\	\r(   z/draft-claimsc           	     n  K   t               }|j                  st        dd      	 t               }| j                  xs d}t               }	 |j                  j                  || j                  d|ddid	gd
t        |       dgt        ddi       d{   }|j*                  }|t        dd      |j,                  dk(  rt        dd      t/        |j0                         |j0                  D 	cg c]  }	|	j3                          c}	|j4                  j6                  |j4                  j8                  t;        |j4                  dd      xs dt;        |j4                  dd      xs dd|ddS # t        $ r}t        dt        |            |d}~ww xY w7 # t        $ r }t        dd|j                         |d}~wt        $ ra}ddl}|j#                  t$              j'                  d|j)                         dd        t        dd|j)                         dd        |d}~ww xY wc c}	w w)u   Tarifname + intake → yapılandırılmış istemler JSON array.

    Sonnet 4.6 + output_config ile şema-doğrulanmış JSON döner.
    Stream kullanılmaz — istemler kısa, full response bekletmek UI için daha temiz.
    r   r   r   Nzclaude-sonnet-4-6r\   r]   r^   r_   ra   rb   disabled)r9   rA   rf   rg   output_formatrh     rx   r   z#Claims schema validation failed: %sr,   uR   Claude JSON çıktısı şemaya uymadı (muhtemelen max_tokens aşıldı). Detay:    uD   Claude yapılandırılmış çıktı üretemedi (parse_output None).rA   ul   Claude max_tokens limitine ulaştı; istem üretimi eksik kalmış olabilir. max_tokens değerini artırın.rq   rr   rs   T)r   rw   r9   is_draft)r   r   r   r   r   r1   r9   r   rg   parserA   r   r   r   r[   r   logging	getLoggerr"   warningerrorsparsed_outputrv   _validate_claims_structurer   rM   rw   rt   ru   r{   )
r   r   r   r   r9   r   responser   parsedcs
             r)   draft_claimsr     se     ~H%%O
 	

G%' MM00E13M$..)) #)&,k%:  &2LW2UVW$ j) / 
 
H !) 6 6F~Y
 	

 |+2
 	
 v}}- ,2==9a1<<>9$NN77%^^99+28>>C`bc+d ,'.x~~?XZ['\'a`a
   ! GCH=3FG
   ,S[[M:
 	  (#++13::<3C	
 **,r*+-
 	F :sy   $H5
E1 H5AF FF AH53H0
A'H51	F:FFH5F 	H-%G  H-AH((H--H5c           	        | st        dd      | d   j                  dk7  rt        dd      t        | d      D ]2  \  }}|j                  |k7  st        dd	| d
|j                   d       | D ]z  }|j                  dk(  s|j                  t        dd|j                   d      |j                  |j                  k\  sTt        dd|j                   d|j                   d       y)uP   TürkPatent kuralları: ilk istem bağımsız + sürekli numara + geri-referans.r   u   Claude hiç istem üretmedi.r   r   independentuL   İstem 1 bağımsız olmalı; üretilen yapı TürkPatent kuralına uymuyor.r   )ri   uH   İstem numaralandırması bozuk — sırayla 1,2,3... olmalı (beklenen z, gelen z).	dependentNu   Bağımlı istem u    parent alanı taşımıyor.z% kendine veya ileri numaraya (parent=z) referans veriyor.)r   r]   	enumerater   r   )r   expected_numclaims      r)   r   r   i  s   4RSSay~~&a
 	
  )q9 e<<<'!!-hu||nBH   ::$||## #.u||n<XY  ||u||+# #+ELL> :##(<<.0CE r(   c                  |    e Zd ZU  eddd      Zded<    eddd      Zded<    ed	d
d      Zded<   dZded<   y)DraftAbstractRequest.r,   r-   r.   r1   r2   r   r   i  d   r;   r=   r@   rA   Nr   r9   r   r'   r(   r)   r   r     sF    sqS9E39 %cce L#LCCD9J9E:r(   r   z/draft-abstractc                  K   t               }|j                  st        dd      	 t               }| j                  xs d}t               }d| j                   d| j                   d}	 |j                  j                  || j                  d	|d
didgd|dg       d{   }d}|j                  D ]   }	t!        |	d
d      d	k(  s|	j"                  } n |j%                         }t'        |j)                               }
||
|
dk  |j*                  j,                  |j*                  j.                  t!        |j*                  dd      xs dt!        |j*                  dd      xs dd|ddS # t        $ r}t        dt        |            |d}~ww xY w7 # t        $ r }t        dd|j                         |d}~ww xY ww)u   Tarifnameden TürkPatent özeti (max 150 kelime) üretir.

    Haiku 4.5 — format kontrolü + sıkıştırma görevi, en ucuz model yeter.
    r   r   r   Nzclaude-haiku-4-5rJ   z

## Tarifname

u   

---

Yukarıdaki tarifnameden TürkPatent kurallarına uygun **özet** üret.
- Tek paragraf, alt başlıksız.
- **Maksimum 150 kelime** (sıkı limit).
- İstem dili tekrarlanmasın.
- Yalnızca özet metnini döndür, başka açıklama yazma.r\   r]   r^   r_   ra   rb   )r9   rA   rf   rg   r   rx   r      rq   r   rr   rs   T)abstract
word_countwithin_limitrw   r9   r   )r   r   r   r   r   r1   r9   r   r2   r   rg   createrA   r   r[   rd   r{   r\   rP   lensplitrw   rt   ru   )r   r   r   r   r9   r   r   r   abstract_textblockr   s              r)   draft_abstractr     s     ~H%%O
 	
G%' MM//E13M w}}o .''
( )G	G //)) #)&,k%:  &,?@ 0 
 
& M!! 5&$'61!JJM "'')M]((*+J! "c)$NN77%^^99+28>>C`bc+d ,'.x~~?XZ['\'a`a
  ] ! GCH=3FG&
  ,S[[M:
 	sd   $G 
E* 7G )7F  F!F %!G B#G *	F3F

FG F 	F=F88F==G )rF   r1   rG   dictreturnr1   )rR   r+   r   r1   )rR   r+   r   zAsyncIterator[str])r   r+   r   r   )rR   r   r   r1   )r   r   r   r   )r   r   r   None)r   r   r   r   )'r%   
__future__r   rD   collections.abcr   	anthropicr   fastapir   r   fastapi.responsesr   pydanticr	   r
   r   
app.configr   app.services.llmr   r   r   routerr   r+   rH   rX   r   postr   r   r   r   r   r   r   r   r   r'   r(   r)   <module>r      s    #  )  , / 6 6 #  
&w	/0i 0&=i =O(VJ
Z !" #8;	 ;F F 2 _Y Yx%Z9  H  Hr(   