1- import replicate
1+ import os
22import time
33import json
44import logging
55from datetime import datetime
6+ from pathlib import Path
7+
8+ import replicate
9+
10+
11+ # ============================================================
12+ # Output directory (for GitHub Actions artifacts)
13+ # ============================================================
14+ OUTPUT_DIR = Path (os .getenv ("BENCHMARK_OUTPUT_DIR" , "benchmark_results_flux_text2img" ))
15+ OUTPUT_DIR .mkdir (parents = True , exist_ok = True )
16+
17+ LOG_FILE = OUTPUT_DIR / "benchmark_flux_lora_text2img.log"
618
7- # ---------------------------------------------------------
8- # Logging Setup
9- # ---------------------------------------------------------
1019logging .basicConfig (
1120 level = logging .INFO ,
1221 format = "%(asctime)s - %(levelname)s - %(message)s" ,
13- handlers = [logging .FileHandler ("benchmark_flux_lora_text2img.log" ), logging .StreamHandler ()],
22+ handlers = [logging .FileHandler (LOG_FILE ), logging .StreamHandler ()],
1423)
1524logger = logging .getLogger (__name__ )
1625
1726
18- # ---------------------------------------------------------
27+ # ============================================================
1928# Benchmark Function
20- # ---------------------------------------------------------
29+ # ============================================================
2130def benchmark_flux_lora_text2img (
2231 num_runs = 3 ,
2332 prompt = "A majestic dragon soaring above a futuristic city." ,
2433 trigger_word = "Painting" ,
2534):
2635 """
27- Benchmark for Flux Fast LoRA (text-to- image) variant .
28- Only uses prompt + trigger_word as required by schema.
36+ Benchmark Flux Fast LoRA (text → image).
37+ Only uses: prompt + trigger_word ( schema compliant) .
2938 """
3039
3140 deployment_id = (
3241 "paragekbote/flux-fast-lora-hotswap:"
3342 "a958687317369721e1ce66e5436fa989bcff2e40a13537d9b4aa4c6af4a34539"
3443 )
3544
36- # Schema-compliant input
45+ # Replicate client using secure API token (required)
46+ client = replicate .Client (api_token = os .environ ["REPLICATE_API_TOKEN" ])
47+
3748 input_params = {
3849 "prompt" : prompt ,
3950 "trigger_word" : trigger_word ,
4051 }
4152
53+ # Header logging
4254 logger .info ("=" * 90 )
4355 logger .info ("FLUX FAST LORA (TEXT → IMAGE) BENCHMARK" )
4456 logger .info ("=" * 90 )
@@ -50,44 +62,45 @@ def benchmark_flux_lora_text2img(
5062
5163 results = {
5264 "deployment_id" : deployment_id ,
53- "deployment_name" : "Flux-Fast-LoRA-Text2Img " ,
65+ "deployment_name" : "flux-fast-lora-text2img " ,
5466 "timestamp" : datetime .now ().isoformat (),
5567 "input_params" : input_params ,
5668 "runs" : [],
5769 }
5870
5971 run_times = []
6072
61- # ---------------------------------------------------------
73+ # ============================================================
6274 # Execute Runs
63- # ---------------------------------------------------------
75+ # ============================================================
6476 for run_num in range (1 , num_runs + 1 ):
6577 logger .info (f"--- Run { run_num } /{ num_runs } ---" )
6678
6779 try :
6880 start = time .time ()
6981
70- # Replicate returns a File object for images
71- output_file = replicate .run (deployment_id , input = input_params )
82+ # Replicate returns a single File object for image output
83+ output_file = client .run (deployment_id , input = input_params )
84+
85+ # Read image bytes
7286 img_bytes = output_file .read ()
7387
7488 elapsed = time .time () - start
7589 run_times .append (elapsed )
7690
77- # Save to disk
78- out_path = f"flux_lora_text2img_run_{ run_num } .png"
79- with open (out_path , "wb" ) as f :
80- f .write (img_bytes )
91+ # Save image output
92+ img_path = OUTPUT_DIR / f"flux_lora_text2img_run_{ run_num } .png"
93+ img_path .write_bytes (img_bytes )
8194
8295 logger .info (f"✓ Completed in { elapsed :.2f} s" )
83- logger .info (f" Generated: { out_path } " )
96+ logger .info (f" Generated: { img_path } " )
8497 logger .info (f" URL: { output_file .url ()} " )
8598
8699 results ["runs" ].append (
87100 {
88101 "run_number" : run_num ,
89102 "elapsed_time" : elapsed ,
90- "output_file" : out_path ,
103+ "output_file" : str ( img_path ) ,
91104 "file_url" : output_file .url (),
92105 "status" : "success" ,
93106 }
@@ -97,85 +110,91 @@ def benchmark_flux_lora_text2img(
97110 err = str (e )
98111 logger .error (f"✗ Run failed: { err } " )
99112
100- results ["runs" ].append ({
101- "run_number" : run_num ,
102- "status" : "failed" ,
103- "error" : err
104- })
113+ results ["runs" ].append (
114+ {
115+ "run_number" : run_num ,
116+ "status" : "failed" ,
117+ "error" : err ,
118+ }
119+ )
105120
106- # ---------------------------------------------------------
121+ # ============================================================
107122 # Statistics
108- # ---------------------------------------------------------
123+ # ============================================================
109124 if run_times :
110- avg_t = sum (run_times ) / len (run_times )
111- min_t = min (run_times )
112- max_t = max (run_times )
125+ avg_time = sum (run_times ) / len (run_times )
126+ min_time = min (run_times )
127+ max_time = max (run_times )
113128
114- std = (sum ((t - avg_t ) ** 2 for t in run_times ) / len (run_times )) ** 0.5
115- cv = (std / avg_t * 100 ) if avg_t else 0
129+ std_dev = (sum ((t - avg_time ) ** 2 for t in run_times ) / len (run_times )) ** 0.5
130+ cv = (std_dev / avg_time * 100 ) if avg_time else 0
116131
117- cold = run_times [0 ]
118- warm = run_times [1 :]
119- warm_avg = sum (warm ) / len (warm ) if warm else None
132+ cold_start = run_times [0 ]
133+ warm_times = run_times [1 :]
134+ warm_avg = sum (warm_times ) / len (warm_times ) if warm_times else None
120135
121136 results ["statistics" ] = {
122137 "successful_runs" : len (run_times ),
123138 "failed_runs" : num_runs - len (run_times ),
124- "avg_latency" : avg_t ,
125- "min_latency" : min_t ,
126- "max_latency" : max_t ,
127- "std_dev_latency" : std ,
139+ "avg_latency" : avg_time ,
140+ "min_latency" : min_time ,
141+ "max_latency" : max_time ,
142+ "std_dev_latency" : std_dev ,
128143 "latency_cv_percent" : cv ,
129- "cold_start_latency" : cold ,
144+ "cold_start_latency" : cold_start ,
130145 "warm_avg_latency" : warm_avg ,
131- "cold_vs_warm_ratio" : cold / warm_avg if warm_avg else None ,
146+ "cold_vs_warm_ratio" : cold_start / warm_avg if warm_avg else None ,
132147 }
133148
134- # Insights
135149 insights = []
136150
137- if warm_avg and cold > warm_avg * 1.5 :
138- insights .append (f"Cold start significantly slower ({ cold :.2f} s vs warm { warm_avg :.2f} s)." )
151+ if warm_avg and cold_start > warm_avg * 1.5 :
152+ insights .append (
153+ f"Cold start significantly slower ({ cold_start :.2f} s vs warm { warm_avg :.2f} s)."
154+ )
139155
140156 if cv < 20 :
141157 insights .append (f"Stable performance (CV { cv :.1f} %)." )
142158 elif cv > 50 :
143159 insights .append (f"High latency variability (CV { cv :.1f} %)." )
144160
145- if avg_t < 4 :
146- insights .append ("Extremely fast text-to- image generation." )
147- elif avg_t < 8 :
161+ if avg_time < 4 :
162+ insights .append ("Extremely fast image generation." )
163+ elif avg_time < 8 :
148164 insights .append ("Good generation speed." )
149165 else :
150- insights .append ("Slow generation — possible cold backend or high load ." )
166+ insights .append ("Slow generation — backend cold or overloaded ." )
151167
152168 results ["insights" ] = insights
153169
154- # Log summary
170+ # Summary log
155171 logger .info ("\n " + "=" * 90 )
156172 logger .info ("BENCHMARK SUMMARY" )
157173 logger .info ("=" * 90 )
158- for k , v in results ["statistics" ].items ():
159- logger .info (f"{ k } : { v } " )
174+
175+ for key , val in results ["statistics" ].items ():
176+ logger .info (f"{ key } : { val } " )
177+
160178 logger .info ("\n Insights:" )
161- for i in insights :
162- logger .info (f" • { i } " )
179+ for insight in insights :
180+ logger .info (f" • { insight } " )
181+
163182 logger .info ("=" * 90 )
164183
165- # ---------------------------------------------------------
166- # Save JSON
167- # ---------------------------------------------------------
168- with open ( "flux_lora_text2img_benchmark.json" , "w" ) as f :
169- json .dump (results , f , indent = 2 )
184+ # ============================================================
185+ # Save JSON Results
186+ # ============================================================
187+ json_path = OUTPUT_DIR / "flux_lora_text2img_benchmark.json"
188+ json_path . write_text ( json .dumps (results , indent = 2 ) )
170189
171- logger .info ("\n ✓ Saved: flux_lora_text2img_benchmark.json " )
172- logger .info ("✓ Logs: benchmark_flux_lora_text2img.log \n " )
190+ logger .info (f "\n ✓ JSON saved to { json_path } " )
191+ logger .info (f "✓ Logs saved to { LOG_FILE } \n " )
173192
174193 return results
175194
176195
177- # ---------------------------------------------------------
178- # Run the benchmark
179- # ---------------------------------------------------------
196+ # ============================================================
197+ # Execute
198+ # ============================================================
180199if __name__ == "__main__" :
181200 benchmark_flux_lora_text2img (num_runs = 3 )
0 commit comments