+
    h?                        R t ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIHt ^ RI	H
t
 ^ RIHt ^ RIHtHt ^ RIHtHt ^ RIHt ]! 4        ]
! ]P*                  ! R4      R	7      t ! R
 R]4      tRtRtR tR tR R ltR!R R lltR t]R8X  d   ^ RI t ]!! ] PD                  4      ^8  d   ] PD                  ^,          R8X  d   Rt#]$! R]# R24       RR/t%]PL                  ! ]#]%^R7      t']'PP                  ^8X  dI   ]! ]#]'PR                  4      t*]$! R#4       ]$! R4       ]$! R"4       ]$! ]PV                  ! ]*^RR7      4       R# ]$! R]'PP                   24       R# ]! 4        R# R# )$z
GPT Analysis with Structured Outputs
Uses OpenAI's structured outputs feature for guaranteed valid JSON responses
Combines with pre-extracted property facts for higher quality and lower cost
N)Path)OpenAI)load_dotenv)	BaseModelField)LiteralOptional)PropertyFactsExtractorOPENAI_API_KEY)api_keyc                   f  a  ] tR t^t o Rt]! ^^RR7      t]! ^RR7      t]! ^^RR7      t]! ^RR7      t	]! ^^RR7      t
]! ^R	R7      t]! ^^R
R7      t]! ^RR7      t]! ^^RR7      t]! ^RR7      t]! ^^RR7      t]! ^RR7      t]! RR7      t]! ^RR7      t]! RRR7      tV 3R ltRtV tR# )PropertyCriteriaz2Structured schema for property evaluation criteriazjRegenerative market garden potential: soil quality, sun exposure, water access, size (1=poor, 5=excellent))geledescriptionz)Brief explanation for market garden score)
max_lengthr   zqGuest accommodation/B&B potential: tranquility, setting, accessibility, existing facilities (1=poor, 5=excellent)z/Brief explanation for guest accommodation scorez_Workshop/food processing potential: existing buildings, space, facilities (1=poor, 5=excellent)z$Brief explanation for workshop scorezfIndependent rental units potential: separate buildings, conversion possibilities (1=poor, 5=excellent)z(Brief explanation for rental units scorezeLocation quality: distance to coast/cities/airports, accessibility, area appeal (1=poor, 5=excellent)z$Brief explanation for location scorezbLocal market access: farmers markets, farm shops, direct sales opportunities (1=poor, 5=excellent)z(Brief explanation for local market scorezOverall investment risk: Laag=low renovation/clear usage, Gemiddeld=moderate work needed, Hoog=major renovation or unclear viability)r   z%Brief explanation for risk assessmenti,  zDConcise overall assessment highlighting key strengths and weaknessesc                   < V ^8  d   Qh/ S[ ;R&   S[;R&   S[ ;R&   S[;R&   S[ ;R&   S[;R&   S[ ;R&   S[;R&   S[ ;R	&   S[;R
&   S[ ;R&   S[;R&   S[R,          ;R&   S[;R&   S[;R&   # )   market_gardenmarket_garden_reasoningguest_accommodationguest_accommodation_reasoningworkshopworkshop_reasoningrental_unitsrental_units_reasoninglocationlocation_reasoninglocal_marketlocal_market_reasoningrisk_profilerisk_reasoningoverall_assessment)Laag	GemiddeldHoog)intstrr   )format__classdict__s   "f/Users/jonathan/Documents/Zakelijk/ClaudeOS/03_Lab/farmmatch/scraper/analyze_with_structured_output.py__annotate__PropertyCriteria.__annotate__   s         !       $' ! *  + 2  3 <  = D   E N  O V  W `  a h   i r 56 s x  y B  C      N)__name__
__module____qualname____firstlineno____doc__r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   __annotate_func____static_attributes____classdictcell__)r)   s   @r*   r   r      s6    < AM $)?$
  % H  */E*!
 uH $:
 |L #(>#
 {H $:
 xL #(>#
 :? [:L  ;N
 $ZC  r-   r   a  You are an expert in evaluating rural properties for regenerative agriculture and sustainable lifestyle projects.

Analyze this property for the following use cases:
1. **Regenerative market garden** - Growing vegetables/herbs using sustainable methods
2. **Guest accommodation** - Short-stay rentals, B&B, retreat hosting
3. **Workshop/food processing** - Value-added production (jams, preserves, etc.)
4. **Rental income** - Long-term or short-term rental units
5. **Location appeal** - Proximity to attractions, accessibility
6. **Local market access** - Ability to sell products locally

{property_facts}

{custom_criteria_data}

Evaluate each criterion on a 1-5 scale:
- 1 = Very poor / Not viable
- 2 = Poor / Significant limitations
- 3 = Acceptable / Some limitations
- 4 = Good / Minor limitations
- 5 = Excellent / Ideal conditions

Assess risk based on:
- **Laag** (Low): Property is move-in ready or requires minimal work, clear value proposition
- **Gemiddeld** (Medium): Some renovation needed, moderate uncertainty
- **Hoog** (High): Major renovation required, significant uncertainty, or questionable viability

Provide practical, realistic assessments based on the facts provided.z gpt_cost_tracker_structured.jsonc                     \         P                  P                  \        4      '       d:   \	        \        R4      ;_uu_ 4       p \
        P                  ! V 4      uuRRR4       # RRR^ R. /#   + '       g   i     L; i)zLoad cost tracking datarN
total_cost        total_requestsruns)ospathexistsCOST_TRACKER_FILEopenjsonload)fs    r*   load_cost_trackerrE      s]    	ww~~'((#S))Q99Q< *) 	c!  *)s   A++A;	c                    \        \        R4      ;_uu_ 4       p\        P                  ! W^R7       RRR4       R#   + '       g   i     R# ; i)zSave cost tracking dataw)indentN)rA   r@   rB   dump)trackerrD   s   & r*   save_cost_trackerrK      s/    		%	%		'Q' 
&	%	%	%s	   <A	c                    RRRRR/RRRRR//pVP                  W#R,          4      pV R	,          VR,          ,          pVR	,          VR,          ,          pWV,           # )
zEstimate cost for GPT modelsgpt-4o-miniinputg333333?outputg333333?zgpt-4o      @g      $@i@B get)input_tokensoutput_tokensmodelpricingrates
input_costoutput_costs   &&&    r*   estimate_costrZ      sk     	x67D(E2G
 KK}56E*eGn<J 9,h?K##r-   c                ^    V ^8  d   QhR\         R\         R\        \        ,          R\        /# )r   urlhtml_contentcustom_datareturn)r'   r   dict)r(   s   "r*   r+   r+      s4     D DS D D(SW. Ddh Dr-   c                   \        R4       \        W4      pVP                  4       pVP                  4       p\        R\	        V4       R24       RpV'       d   VP                  R^ 4      ^ 8  dw   RVP                  R^ 4      R RVP                  R	R
4       RVP                  RR
4       RVP                  RR
4       RVP                  RR
4       RVP                  RR
4       R2p\        P                  TV'       d   TMRR7      p\        R4       \        P                  ! 4       p\        P                  P                  P                  P                  RRRRR/RRRV/.\        RR7      p	\        P                  ! 4       V,
          p
V	P                  ^ ,          P                   P"                  pV	P$                  P&                  pV	P$                  P(                  p\+        WRR7      p\        R VR! R"V R#V R$24       \        R%V
R& R'24       R(RKR)RLR*^R+^R,^/pR-R.R/R0R1R.R2R3R4R5R6R3/pR7pR7pVP-                  4        F=  w  pp\/        VV4      pV\1        V4      ,          V,          pVV,          pVV,          pK?  	  R8R9R:R;R<R=/pVP                  VP2                  R;4      pV^ 8  d   \5        VV,          V,          ^4      M^ pR>V R?VR@R-VP6                  R/VP8                  R1VP:                  R2VP<                  R4VP>                  R6VP@                  /RAR-VPB                  R/VPD                  R1VPF                  R2VPH                  R4VPJ                  R6VPL                  RBVPN                  /RCVP2                  RDVPP                  REVRFRGVRHVRIV/RJV
/	# )Mz
Analyze property using structured outputs

Args:
    url: Property URL
    html_content: Raw HTML from property page
    custom_data: Optional custom criteria data

Returns:
    Dictionary with analysis results including structured criteria
u&      📄 Extracting structured facts...u      📊 Extracted z characters of structured data custom_scorez?
OBJECTIVE DATA (Climate & Location):
- Custom criteria score: z.1fz/5.0
- Growing season length: growing_season_dayszN/Az days
- Annual sunshine: annual_sunshine_hoursz hours
- Frost-free period: frost_free_daysz days
- Distance to coast: distance_to_coast_kmz km
- Airport distance: nearest_airport_kmz6 km

Consider this objective data in your assessment.
z%[No objective climate data available])property_factscustom_criteria_datau6      🤖 Calling GPT-4o-mini with structured outputs...rM   rolesystemcontentzrYou are an expert property evaluator for regenerative agriculture projects. Provide honest, practical assessments.userg333333?)rU   messagesresponse_formattemperature)rU   u      💰 Cost: $.6fz (z in + z out tokens)u      ⏱️  Duration: z.2fs12345r   g       @r   rP   r   r   g      ?r   g      @r   r:   r#   g      ?r$   g?r%   gffffff?r\   structured_factscriteria	reasoningriskr    r"   weighted_scoretokensrN   rO   costduration_seconds))printr	   extract_allto_prompt_textlenrR   STRUCTURED_PROMPT_TEMPLATEr(   timeclientbetachatcompletionsparser   choicesmessageparsedusageprompt_tokenscompletion_tokensrZ   itemsgetattrr'   r    roundr   r   r   r   r   r   r   r   r   r   r   r   r!   r"   )r\   r]   r^   	extractorfactsri   custom_textfinal_prompt
start_time
completiondurationrz   rS   rT   r   score_weightscriteria_weightstotal_scoretotal_weight	criterionweightscore_valueweightedrisk_factorsrisk_factorr}   s   &&&                       r*   analyze_property_structuredr      s    
24&|9I!!#E --/N	s>233Q
RS K{~q9A=%//.!<SA B%//*?GH IOO$;UCD E!oo&7?@ A!oo&<eDE F __%95AB C
 .44%,7[=d 5 L 
BDJ!!--33   P
 <	
 ) 4 J  yy{Z'H !!!$,,33H ##11L$$66MMJD	OD:R~VM?,
WX	!(3q
12 "c2sAsAsA>MsCC KL-335	6h	2 [!12V;x	 6 Cc63?L""8#8#8#>KMY\]M]UK,6+EqIcdN 	sEX33!8#?#?))H11))H11
 	X==!8#I#I33H;;33H;;H++
 	--h99.\mD

 	H9 r-   c                 <   Rp RpRp/ p\         P                  P                  V4      '       de    \        VR4      ;_uu_ 4       p\        P
                  ! V4      pV Uu/ uF  qfR,          VbK  	  pp\        R\        V4       R24       RRR4       \        P                  ! V 4      p\        4       p	\         P                  P                  V4      '       dO   \        P                  ! V4      p
\        V
R
,          P                  4       4      p	\        R\        V	4       R24       RR/p\        4       pR\        P                  ! R4      R^ RRR^ R^ /p. p\        V4      \        V	4      ,
          p\        RV R24       \!        VP#                  4       ^4       EF  w  ppVP$                  pVV	9   d    \        RV R\        V4       RV 24       K9   \        RV R\        V4       RV 24       \&        P(                  ! VV^R7      pVP*                  ^8w  d   \        RVP*                   R24       K  VP)                  V/ 4      p\-        VVP.                  V4      pVR;;,          ^,          uu&   VR;;,          VR ,          R!,          ,          uu&   VR;;,          VR ,          R",          ,          uu&   VR;;,          VR ,          R#,          ,          uu&   VP1                  R
VR$VR%,          P)                  R&R'4      R(VR%,          P)                  R)/ 4      P)                  R*R'4      R+VR%,          P)                  R,4      R-VR.,          R-,          R/VR.,          R/,          R0VR.,          R0,          R1VR.,          R1,          R)VR.,          R),          R2VR.,          R2,          R3VR3,          R4VR4,          R5VR6,          /4       V'       dC   \        P2                  ! V4      pVP5                  VR7R8R97       \        R:\        V4       R;24       \        P6                  ! ^4       EK  	  V'       dC   \        P2                  ! V4      pVP5                  VR7R8R97       \        R=\        V4       R>24       V'       d   \9        R? V 4       4      M^ VR@&   VRA,          P1                  V4       VR;;,          VR,          ,          uu&   VRB;;,          VR,          ,          uu&   \;        V4       \        RN4       \        RC4       \        RM4       \        RDVR,           24       \        REVR,          RF 24       \        RGVR,          \=        ^VR,          4      ,          RF 24       \        RHVR,          RI 24       \        RJVR,          RI 24       \        RKVR,          RL 24       \        RM4       R# u upi   + '       g   i     EL:; i  \         d   p\        R	T 24        Rp?EL\Rp?ii ; i  \         d   p\        R<T 24        Rp?EK}  Rp?ii ; i)Oz8Analyze all properties from CSV using structured outputszextracted_property_urls.csvzanalysis_output_structured.csvzenriched_data.jsonr8   r\   u   📊 Loaded z# properties from enriched_data.jsonNu+   ⚠️  Could not load enriched_data.json: URLu   📚 z properties already analyzed
User-AgentDMozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15	timestampz%Y-%m-%d %H:%M:%Sproperties_analyzedr9   r:   tokens_inputtokens_outputu&   
🚀 Starting structured analysis of z properties
u	   ⏭️  [/z] Already analyzed: u   
🔎 [z] Analyzing: headerstimeoutu      ❌ HTTP z - skippingr~   r   rN   rO   Titelry   titlerb   Locatier   fullPrijspricer   rz   r   r   r   r   r    r"   zGewogen Scorer}   Fzutf-8)indexencodingu      💾 Progress saved (z properties)u      ❌ Error: u   
✅ Analysis complete! z properties analyzedc              3   D   "   T F  qP                  R ^ 4      x  K  	  R# 5i)r   NrQ   ).0r8   s   & r*   	<genexpr>)analyze_all_properties.<locals>.<genexpr>  s     &UWuu-?'C'CWs    r   r<   r;   u   💰 COST REPORTzProperties analyzed: zTotal cost: $rr   zAverage per property: $zInput tokens: ,zOutput tokens: z
All-time total: $z.4fF======================================================================G
======================================================================)r=   r>   r?   rA   rB   rC   r   r   	Exceptionpdread_csvsettolistrE   r   strftime	enumerate
itertuplesr   requestsrR   status_coder   textappend	DataFrameto_csvsleepsumrK   max)
input_fileoutput_fileenriched_fileproperty_data_by_urlrD   enriched_datapropedfanalyzed_urlsexisting_dfr   cost_trackerrun_dataresultstotal_to_analyzeidxrowr\   responser^   analysis
results_dfs                          r*   analyze_all_propertiesr   +  s    /J2K(M 	ww~~m$$	EmS))Q $		!FS'TmdUT(9m$'TS)=%>$??bcd * 
Z	 B EM	ww~~k""kk+.K.5578c-())EFG 	\G
 %&LT]]#67qcH G2w]!33	34D3E]
STbmmoq1Sgg -IcU!CG9,@FG1	HSE3r7)=>?  ||C"EH##s*X%9%9$:+FG /223;K 33{SH *+q0+\"hx&8&@@"^$(:7(CC$_%();H)EE% NNs"4599'2F8$67;;JKOOPVXZ["4599'B*!5o!F%x
';<Q'RHZ0< 4^ DHZ0< 4^ D 8$h/C&D*:!; " \\'2
!!+UW!M0WlKL JJqMk 2x \\'*
+UWE)#g,7KLM Za3&UW&U#UfgH )(<"88!"h/D&EE"l#	/	
	(O	!(+@"A!B
CD	M(<05
67	#H\$:3q(K`Ba;b$bcf#g
hi	N8N3A6
78	OH_5a8
9:	\ :3?
@A	(Oi (U *))  	E?sCDD	Ep  	N1#&'	sg   W V;V60V;
W A W65G/W66V;;W	W W W3W..W36XXX__main__testzJhttps://www.properstar.com/property-for-sale/france/lot-et-garonne/7837046zTesting with URL: 
r   r   r   zANALYSIS RESULTF)rH   ensure_asciizFailed to fetch: HTTP )rM   )Nr   r   ),r3   r=   rB   r   r   pandasr   pathlibr   openair   dotenvr   pydanticr   r   typingr   r   extract_property_factsr	   getenvr   r   r   r@   rE   rK   rZ   r   r   r/   sysr   argvtest_urlr   r   rR   r   r   r   resultdumpsr.   r-   r*   <module>r      sZ   
        % $ 9 			"23	4Dy DRI < 7 	(

$DRAH z
388}qSXXa[F2_"8*B/0 `
 <<'2F3&08==IF/"#$(O$**VAEBC*8+?+?*@AB 	 / r-   