+
    Eyj$                       R t ^ RIHt ^ RIt^ RIt^ RIHt ^ RIHt ^ RI	H
t
HtHtHt ^ RIHt ^ RIHtHt ^ RIHtHt ^ R	IHtHtHtHt ^ R
IHt ]
! RR.R7      t]P<                  ! R]P>                  ]P@                  ,          4      t! ! R R]4      t" ! R R]4      t# ! R R]4      t$ ! R R]4      t%R R lt&Rt']PQ                  R4      R R l4       t)Rt*^t+]PQ                  R4      R R  l4       t,R# )!u  Tarifname/istemler metinlerinden bahsedilen şekilleri çıkarma.

Akış:
  1. Regex ile "Şekil N" + "(NNN)" referansları yakala (unique liste)
  2. Tespit edilen her şekil için Claude Haiku'ya bağlamı gönder, şu yanıtları iste:
     - title: kısa başlık ("Sistem mimarisi")
     - description: 1-2 cümle açıklama
     - mermaid_suggestion: başlangıç noktası Mermaid kaynağı (boş olabilir)

Tek LLM çağrısı, structured output, ~$0.005/patent.
)annotationsN)	Annotated)APIError)	APIRouterFileHTTPException
UploadFile)Response)ImageImageOps)	BaseModelField)LLMNotConfiguredErrorget_anthropic_clientresolvesystem_block)record_usagez/figuresfigures)prefixtagsu  
    \b
    (?: Ş[eE][kK][iİ][lL] | ŞEKİL | FIG\.? | Figure )   # "Şekil" / "FIG" varyasyonları
    \s*
    (\d{1,2})                                           # numara 1-99
    (?: [-–][A-Za-z] )?                                 # opsiyonel "-A", "-B"
    \b
    c                  v    ] tR t^1t$ ]! RRRR7      tR]R&   ]! RRRR7      tR]R	&   ]! R
^R7      tR]R&   Rt	R
# )ExtractFiguresRequest i u   Tarifname taslağı (markdown))default
max_lengthdescriptionstrr   iP  u%   İstemler tam metin (numaralı liste)claimsNr   r   
str | Nonetitle )
__name__
__module____qualname____firstlineno__r   r   __annotations__r   r    __static_attributes__r!       [/Users/zincirx/Documents/projelerim/patentyazar/backend-python/app/api/figure_extraction.pyr   r   1   sK    4K 
 ;FC 
 ds;E:;r(   r   c                      ] tR t^?t$ ]! R^^cR7      tR]R&   ]! R^^dR7      tR]R&   ]! R^
RR7      tR]R	&   ]! R
RR7      t	R]R&   Rt
R# )FigureSuggestion.)geleintnumber
min_lengthr   r   r      r   r   i  r   mermaid_suggestionr!   N)r"   r#   r$   r%   r   r/   r&   r    r   r3   r'   r!   r(   r)   r+   r+   ?   sM    b)FC)sqS9E39SRC@K@#B4@@r(   r+   c                  8    ] tR t^Ft$ ]! R^ ^R7      tR]R&   RtR# )FiguresSuggestionSet.r0   list[FigureSuggestion]r   r!   N)r"   r#   r$   r%   r   r   r&   r'   r!   r(   r)   r5   r5   F   s    &+CA"&MG#Mr(   r5   c                  V    ] tR t^Jt$ R]R&   R]R&   ]! RR7      tR]R&   R	tR
]R&   RtR	# )ExtractFiguresResponser6   r   	list[int]detected_numbersz&'ai' veya 'regex-only' veya 'fallback')r   r   sourceNr   modelr!   )	r"   r#   r$   r%   r&   r   r;   r<   r'   r!   r(   r)   r8   r8   J   s(    ##$LMFCME:r(   r8   c                    V ^8  d   QhRRRR/# )   textsr   returnr9   r!   )formats   "r)   __annotate__rB   Q   s      C I r(   c                 <   \        4       pV  Fj  pV'       g   K  \        P                  V4       FD  p \        VP	                  ^4      4      p^Tu;8:  d   ^c8:  d   M K1  VP                  V4       KD  KF  	  Kl  	  \        V4      #   \        \        3 d     Kk  i ; i)uB   Tüm metinlerden benzersiz şekil numaralarını sıralı çıkar.)	set_FIG_PATTERNfinditerr.   groupadd
ValueError
IndexErrorsorted)r?   seentextmns   *    r)   _extract_figure_numbersrP   Q   s    UD&&t,A
O<R<<HHQK   -  $< 
+ s   +B BBBu  Sen bir patent vekili asistanısın. Görevin: bir Türk patent başvurusunun tarifname ve istem metinlerinden, bahsedilen her şekil için kısa bir başlık, 1-2 cümle açıklama ve Mermaid diyagram önerisi üretmek.

KURAL­LAR:
1. Tarifnamede hangi numaralı şekiller bahsediliyorsa yalnızca onları ver. Uydurma.
2. Her şekil için:
   - title: 3-8 kelimelik Türkçe başlık (örn. "Sistem mimarisi", "İşlem akışı")
   - description: şeklin NE GÖSTERDİĞİNİ 1-2 cümleyle anlatan Türkçe özet
   - mermaid_suggestion: başlangıç noktası Mermaid kaynağı (flowchart TD, sequenceDiagram, classDiagram, vb.) — boş da bırakabilirsin, ama olabilirse koy (4-10 node yeter)
3. Mermaid blok'u içinde emoji, renk, stil YOK. Default mermaid siyah-beyaz render edilecek.
4. Referans numaraları (Şekil 1'deki (210) gibi) Mermaid'de "Kapı (210)" formatında parentheses ile verilir.

Çıktı: yalnızca structured JSON.
z/extractc                    V ^8  d   QhRRRR/# )r>   reqr   r@   r8   r!   )rA   s   "r)   rB   rB   y   s$     U] U]4 U]9O U]r(   c                @  "   \        V P                  V P                  4      pV'       g   \        . . RR7      #  \	        4       pRP                  R	 T 4       4      pR
T RT P                  '       d   T P                  R,          MR RT P                  '       d   T P                  R,          MR RT R2	p\        R4      p TP                  P                  TP                  TP                  \        TP                  \        4      RRRT/.\        RR/R7      G Rj  xL
 p\!        TP                  TP"                  TP$                  R7       TP&                  p\)        T4      p	TP*                   U
u. uF  qP,                  T	9   g   K  T
NK  	  pp
T U
u0 uF  qP,                  kK  	  pp
T F,  pY<9  g   K  TP/                  \        TRT 2RRR7      4       K.  	  TP1                  R R7       \        TTRTP                  R7      #   \
         d8    \        T Uu. uF  p\        TRT 2RRR7      NK  	  Mu upi upTRR7      u # i ; i EL2u up
i u up
i   \2         d   p\5        R R!T 2R"7      ThRp?i\6         d   p\5        R#R$T 2R"7      ThRp?ii ; i5i)%u3   Metinlerden bahsedilen şekillerin listesini üret.z
regex-only)r   r:   r;      Şekil u#   Açıklama AI olmadan üretilemedi.r   )r/   r    r   r3   fallbackz, c              3  ,   "   T F
  pR V 2x  K  	  R# 5i)rT   Nr!   ).0rO   s   & r)   	<genexpr>"extract_figures.<locals>.<genexpr>   s     9171#s   u"   Tespit edilen şekil numaraları: z

## Tarifname metni
:Ni@  Nu   (boş)u   

## İstemler
:Ni N  NuL   

Yukarıdaki metinlerde yalnızca şu numaralı şekiller bahsedilmiştir: u?   .
Her biri için title, description, mermaid_suggestion üret.
figure_extractionroleusercontenttypedisabled)r<   
max_tokenssystemmessagesoutput_formatthinkingN)r<   usageendpointu:   Bu şekil tarifnamede bahsedilmiş ama AI detay üretmedi.c                    V P                   # )N)r/   )fs   &r)   <lambda>!extract_figures.<locals>.<lambda>   s    AHHr(   )keyai)r   r:   r;   r<   i  zAnthropic API error: status_codedetailr2   zFigure extraction failed: )rP   r   r   r8   r   r   r+   joinr   rb   parser<   r`   r   SYSTEM_PROMPTr5   r   re   taskparsed_outputrD   r   r/   appendsortr   r   	Exception)rR   detectedclientrO   nums_strctxspecrespparseddetected_setrh   filteredpresent_numberses   &             r)   extract_figuresr   x   s     's

CH%
 	

%'$ yy999H0
 ;  OOO : ; zzzFx 0 1KKS* U
C &'D)]__****

M:vy#67.j) + 
 
 	****YY	

 (,'9'98}%~~J~!\1IAA~J-56X88X6A'$  'sm$`+-	  	,-%%**	
 	
 ! 
% " "A !#A3- E')	 " &
 	

@
  K6&  X6KA34OPVWW ]6PQRPS4TU[\\]s   7J
H	 -J2'J&JAI IAI 2I	II I)
I 8AI J	IH9
8IJ
IJI 
I J&I77JJJJJi  z/convert-bwc                    V ^8  d   QhRRRR/# )r>   filezAnnotated[UploadFile, File()]r@   r	   r!   )rA   s   "r)   rB   rB      s     1? 1?; 1? 1?r(   c                  "   V P                   '       d"   V P                   P                  R4      '       g   \        RRR7      hV P                  4       G Rj  xL
 p\	        V4      R8  d   \        RRR7      h \
        P                  ! \        P                  ! V4      4      p\        P                  ! V4      pTP                  R9   dM   \
        P                  ! R	TP                  R4      pTP                  Y"P!                  4       R,          R
7       TpM"TP                  R	8w  d   TP#                  R	4      pTP#                  R4      pTP                  w  rg\%        Yg4      \&        8  dW   \&        \%        Yg4      ,          pTP)                  \+        Yh,          4      \+        Yx,          4      3\
        P,                  4      pTP/                  R R4      p	\        P                  ! 4       p
T	P1                  T
RRR7       T
P3                  4       p\5        TRR7      #  EL  \         d   p\        RRT 2R7      ThRp?ii ; i5i)u  Yüklenen PNG/JPG'yi TürkPatent uyumlu siyah-beyaza çevir ve PNG olarak dön.

İşlem:
  1. Görseli yükle, EXIF rotasyonunu normalize et
  2. Grayscale'a çevir
  3. Threshold ile pure B/W (1-bit değil — 8-bit gray, ama sadece 0 ve 255)
     Not: Pure 1-bit render sonucu TürkPatent için kabul edilir ama metin
     kenarlarında aliasing olur. Grayscale threshold daha temiz.
  4. Boyut sınırı — çok büyükse oransal küçült
  5. PNG olarak byte stream döndür
zimage/i  u   Geçersiz dosya tipirm   Ni  u   Dosya 5 MB üzerindeu   Görsel açılamadı: RGB)maskLc                     V \         8  d   ^# ^ # )   )_BW_THRESHOLD)ps   &r)   ri   convert_to_bw.<locals>.<lambda>  s    Q%6c=A=r(   PNGT)rA   optimizez	image/png)r]   
media_typei  P )RGBALA)r   r   r   )content_type
startswithr   readlenr
   openioBytesIOr   exif_transposerw   modenewsizepastesplitconvertmax_MAX_DIMENSIONresizer.   LANCZOSpointsavegetvaluer	   )r   rawimgr   bggraywhscalebwout	png_bytess   &           r)   convert_to_bwr      s     D$5$5$@$@$J$J4JKK		
C
3x/!4JKKYjjC)%%c*
 xx>!YYuchh8
99;r?+	U	kk%  ;;sD 99DA
1y>!Q*{{C	NC	N;U]]K 
=s	CB
**,CGGCG-II+>>E   Y6LQC4PQWXXYs<   3I IH!I9A H 9E"IH>(H99H>>I)-__doc__
__future__r   r   retypingr   	anthropicr   fastapir   r   r   r   fastapi.responsesr	   PILr
   r   pydanticr   r   app.services.llmr   r   r   r   app.services.llm.usage_logr   routercompileVERBOSEUNICODErE   r   r+   r5   r8   rP   rr   postr   r   r   r   r!   r(   r)   <module>r      s   
 # 	 	   > > &  %  4	*I;	7 zz JJ
<I <Ay AN9 NY  . ZU] U]r  ]1? 1?r(   