Skip to content

Commit cdf85d2

Browse files
committed
implement trace_id observability
1 parent 35ae79e commit cdf85d2

File tree

4 files changed

+105
-47
lines changed

4 files changed

+105
-47
lines changed

codeflash/api/aiservice.py

Lines changed: 41 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,11 @@ def optimize_python_code( # noqa: D417
118118
source_code: str,
119119
dependency_code: str,
120120
trace_id: str,
121-
num_candidates: int = 10,
122121
experiment_metadata: ExperimentMetadata | None = None,
123122
*,
124123
is_async: bool = False,
125124
model: str | None = None,
125+
call_sequence: int | None = None,
126126
) -> list[OptimizedCandidate]:
127127
"""Optimize the given python code for performance by making a request to the Django endpoint.
128128
@@ -131,9 +131,9 @@ def optimize_python_code( # noqa: D417
131131
- source_code (str): The python code to optimize.
132132
- dependency_code (str): The dependency code used as read-only context for the optimization
133133
- trace_id (str): Trace id of optimization run
134-
- num_candidates (int): Number of optimization variants to generate. Default is 10.
135134
- experiment_metadata (Optional[ExperimentalMetadata, None]): Any available experiment metadata for this optimization
136135
- model (str | None): Model name to use ("gpt-4.1" or "claude-sonnet-4-5"). Default is None (server default).
136+
- call_sequence (int | None): Sequence number for multi-model calls (1, 2, 3...). Default is None.
137137
138138
Returns
139139
-------
@@ -146,21 +146,19 @@ def optimize_python_code( # noqa: D417
146146
payload = {
147147
"source_code": source_code,
148148
"dependency_code": dependency_code,
149-
"num_variants": num_candidates,
150149
"trace_id": trace_id,
151150
"python_version": platform.python_version(),
152151
"experiment_metadata": experiment_metadata,
153152
"codeflash_version": codeflash_version,
154153
"current_username": get_last_commit_author_if_pr_exists(None),
155154
"repo_owner": git_repo_owner,
156155
"repo_name": git_repo_name,
157-
"n_candidates": num_candidates,
158156
"is_async": is_async,
159157
"model": model,
158+
"call_sequence": call_sequence,
160159
}
160+
logger.debug(f"Sending optimize request: model={model}, trace_id={trace_id}, call_sequence={call_sequence}")
161161

162-
logger.info("!lsp|Generating optimized candidates…")
163-
console.rule()
164162
try:
165163
response = self.make_ai_service_request("/optimize", payload=payload, timeout=60)
166164
except requests.exceptions.RequestException as e:
@@ -170,17 +168,16 @@ def optimize_python_code( # noqa: D417
170168

171169
if response.status_code == 200:
172170
optimizations_json = response.json()["optimizations"]
173-
console.rule()
174171
end_time = time.perf_counter()
175172
logger.debug(f"!lsp|Generating possible optimizations took {end_time - start_time:.2f} seconds.")
173+
logger.debug(f"Backend returned {len(optimizations_json)} optimization(s)")
176174
return self._get_valid_candidates(optimizations_json, OptimizedCandidateSource.OPTIMIZE, model=model)
177175
try:
178176
error = response.json()["error"]
179177
except Exception:
180178
error = response.text
181179
logger.error(f"Error generating optimized candidates: {response.status_code} - {error}")
182180
ph("cli-optimize-error-response", {"response_status_code": response.status_code, "error": error})
183-
console.rule()
184181
return []
185182

186183
def optimize_python_code_line_profiler( # noqa: D417
@@ -189,9 +186,9 @@ def optimize_python_code_line_profiler( # noqa: D417
189186
dependency_code: str,
190187
trace_id: str,
191188
line_profiler_results: str,
192-
num_candidates: int = 10,
193189
experiment_metadata: ExperimentMetadata | None = None,
194190
model: str | None = None,
191+
call_sequence: int | None = None,
195192
) -> list[OptimizedCandidate]:
196193
"""Optimize the given python code for performance by making a request to the Django endpoint.
197194
@@ -200,9 +197,9 @@ def optimize_python_code_line_profiler( # noqa: D417
200197
- source_code (str): The python code to optimize.
201198
- dependency_code (str): The dependency code used as read-only context for the optimization
202199
- trace_id (str): Trace id of optimization run
203-
- num_candidates (int): Number of optimization variants to generate. Default is 10.
204200
- experiment_metadata (Optional[ExperimentalMetadata, None]): Any available experiment metadata for this optimization
205201
- model (str | None): Model name to use ("gpt-4.1" or "claude-sonnet-4-5"). Default is None (server default).
202+
- call_sequence (int | None): Sequence number for multi-model calls (1, 2, 3...). Default is None.
206203
207204
Returns
208205
-------
@@ -212,21 +209,18 @@ def optimize_python_code_line_profiler( # noqa: D417
212209
payload = {
213210
"source_code": source_code,
214211
"dependency_code": dependency_code,
215-
"num_variants": num_candidates,
216212
"line_profiler_results": line_profiler_results,
217213
"trace_id": trace_id,
218214
"python_version": platform.python_version(),
219215
"experiment_metadata": experiment_metadata,
220216
"codeflash_version": codeflash_version,
221217
"lsp_mode": is_LSP_enabled(),
222-
"n_candidates_lp": num_candidates,
223218
"model": model,
219+
"call_sequence": call_sequence,
224220
}
225221

226-
console.rule()
227222
if line_profiler_results == "":
228223
logger.info("No LineProfiler results were provided, Skipping optimization.")
229-
console.rule()
230224
return []
231225
try:
232226
response = self.make_ai_service_request("/optimize-line-profiler", payload=payload, timeout=60)
@@ -237,18 +231,14 @@ def optimize_python_code_line_profiler( # noqa: D417
237231

238232
if response.status_code == 200:
239233
optimizations_json = response.json()["optimizations"]
240-
logger.info(
241-
f"!lsp|Generated {len(optimizations_json)} candidate optimizations using line profiler information."
242-
)
243-
console.rule()
234+
logger.debug(f"Backend returned {len(optimizations_json)} LP optimization(s)")
244235
return self._get_valid_candidates(optimizations_json, OptimizedCandidateSource.OPTIMIZE_LP, model=model)
245236
try:
246237
error = response.json()["error"]
247238
except Exception:
248239
error = response.text
249240
logger.error(f"Error generating optimized candidates: {response.status_code} - {error}")
250241
ph("cli-optimize-error-response", {"response_status_code": response.status_code, "error": error})
251-
console.rule()
252242
return []
253243

254244
def optimize_python_code_multi_model(
@@ -260,32 +250,34 @@ def optimize_python_code_multi_model(
260250
experiment_metadata: ExperimentMetadata | None = None,
261251
*,
262252
is_async: bool = False,
263-
) -> list[OptimizedCandidate]:
253+
sequence_offset: int = 0,
254+
) -> tuple[list[OptimizedCandidate], int]:
264255
"""Generate optimizations using multiple models in parallel."""
256+
logger.info("Generating optimized candidates…")
257+
console.rule()
258+
265259
futures: list[tuple[concurrent.futures.Future[list[OptimizedCandidate]], str]] = []
266-
call_index = 0
267260

261+
call_index = 0
268262
for model_name, num_calls in model_distribution:
269263
for _ in range(num_calls):
270-
call_trace_id = f"{base_trace_id[:-4]}M{call_index:02d}"
264+
call_trace_id = f"{base_trace_id[:-3]}0{call_index:02x}"
265+
call_sequence = sequence_offset + call_index + 1
271266
call_index += 1
272-
273267
future = multi_model_executor.submit(
274268
self.optimize_python_code,
275269
source_code,
276270
dependency_code,
277271
call_trace_id,
278-
num_candidates=1, # Each call returns 1 candidate
279-
experiment_metadata=experiment_metadata,
272+
experiment_metadata,
280273
is_async=is_async,
281274
model=model_name,
275+
call_sequence=call_sequence,
282276
)
283277
futures.append((future, model_name))
284278

285-
# Wait for all calls to complete
286279
concurrent.futures.wait([f for f, _ in futures])
287280

288-
# Collect results
289281
all_candidates: list[OptimizedCandidate] = []
290282
for future, model_name in futures:
291283
try:
@@ -295,7 +287,8 @@ def optimize_python_code_multi_model(
295287
logger.warning(f"Model {model_name} call failed: {e}")
296288
continue
297289

298-
return all_candidates
290+
console.rule()
291+
return all_candidates, call_index
299292

300293
def optimize_python_code_line_profiler_multi_model(
301294
self,
@@ -305,25 +298,29 @@ def optimize_python_code_line_profiler_multi_model(
305298
line_profiler_results: str,
306299
model_distribution: list[tuple[str, int]],
307300
experiment_metadata: ExperimentMetadata | None = None,
308-
) -> list[OptimizedCandidate]:
301+
sequence_offset: int = 0,
302+
) -> tuple[list[OptimizedCandidate], int]:
309303
"""Generate line profiler optimizations using multiple models in parallel."""
304+
logger.info("Generating optimized candidates with line profiler…")
305+
console.rule()
306+
310307
futures: list[tuple[concurrent.futures.Future[list[OptimizedCandidate]], str]] = []
311-
call_index = 0
312308

309+
call_index = 0
313310
for model_name, num_calls in model_distribution:
314311
for _ in range(num_calls):
315-
call_trace_id = f"{base_trace_id[:-4]}L{call_index:02d}"
312+
call_trace_id = f"{base_trace_id[:-3]}1{call_index:02x}"
313+
call_sequence = sequence_offset + call_index + 1
316314
call_index += 1
317-
318315
future = multi_model_executor.submit(
319316
self.optimize_python_code_line_profiler,
320317
source_code,
321318
dependency_code,
322319
call_trace_id,
323320
line_profiler_results,
324-
num_candidates=1,
325-
experiment_metadata=experiment_metadata,
326-
model=model_name,
321+
experiment_metadata,
322+
model_name,
323+
call_sequence,
327324
)
328325
futures.append((future, model_name))
329326

@@ -338,7 +335,8 @@ def optimize_python_code_line_profiler_multi_model(
338335
logger.warning(f"Line profiler model {model_name} call failed: {e}")
339336
continue
340337

341-
return all_candidates
338+
console.rule()
339+
return all_candidates, call_index
342340

343341
def optimize_python_code_refinement(self, request: list[AIServiceRefinerRequest]) -> list[OptimizedCandidate]:
344342
"""Optimize the given python code for performance by making a request to the Django endpoint.
@@ -366,6 +364,7 @@ def optimize_python_code_refinement(self, request: list[AIServiceRefinerRequest]
366364
"trace_id": opt.trace_id,
367365
"function_references": opt.function_references,
368366
"python_version": platform.python_version(),
367+
"call_sequence": opt.call_sequence,
369368
}
370369
for opt in request
371370
]
@@ -455,6 +454,7 @@ def get_new_explanation( # noqa: D417
455454
throughput_improvement: str | None = None,
456455
function_references: str | None = None,
457456
codeflash_version: str = codeflash_version,
457+
call_sequence: int | None = None,
458458
) -> str:
459459
"""Optimize the given python code for performance by making a request to the Django endpoint.
460460
@@ -500,6 +500,7 @@ def get_new_explanation( # noqa: D417
500500
"throughput_improvement": throughput_improvement,
501501
"function_references": function_references,
502502
"codeflash_version": codeflash_version,
503+
"call_sequence": call_sequence,
503504
}
504505
logger.info("loading|Generating explanation")
505506
console.rule()
@@ -627,6 +628,7 @@ def generate_regression_tests( # noqa: D417
627628
test_timeout: int,
628629
trace_id: str,
629630
test_index: int,
631+
call_sequence: int | None = None,
630632
) -> tuple[str, str, str] | None:
631633
"""Generate regression tests for the given function by making a request to the Django endpoint.
632634
@@ -662,6 +664,7 @@ def generate_regression_tests( # noqa: D417
662664
"python_version": platform.python_version(),
663665
"codeflash_version": codeflash_version,
664666
"is_async": function_to_optimize.is_async,
667+
"call_sequence": call_sequence,
665668
}
666669
try:
667670
response = self.make_ai_service_request("/testgen", payload=payload, timeout=90)
@@ -702,6 +705,7 @@ def get_optimization_review(
702705
replay_tests: str,
703706
concolic_tests: str, # noqa: ARG002
704707
calling_fn_details: str,
708+
call_sequence: int | None = None,
705709
) -> str:
706710
"""Compute the optimization review of current Pull Request.
707711
@@ -748,6 +752,7 @@ def get_optimization_review(
748752
"codeflash_version": codeflash_version,
749753
"calling_fn_details": calling_fn_details,
750754
"python_version": platform.python_version(),
755+
"call_sequence": call_sequence,
751756
}
752757
console.rule()
753758
try:

codeflash/models/models.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class AIServiceRefinerRequest:
4646
original_line_profiler_results: str
4747
optimized_line_profiler_results: str
4848
function_references: str | None = None
49+
call_sequence: int | None = None
4950

5051

5152
class TestDiffScope(str, Enum):

0 commit comments

Comments
 (0)