Skip to content

Commit 3e0fa96

Browse files
authored
fix(experiment): replace escaped newlines with actual newlines in format output (#1547)
The ExperimentResult.format() method and related logging calls used escaped newlines (\\n → literal \n in output) instead of actual newline characters, causing the formatted output to display \n literally rather than producing line breaks.
1 parent c45f6ff commit 3e0fa96

File tree

1 file changed

+26
-26
lines changed

1 file changed

+26
-26
lines changed

langfuse/experiment.py

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ def format(self, *, include_item_results: bool = False) -> str:
458458

459459
# Or create summary report
460460
summary = result.format() # Aggregate view only
461-
print(f"Experiment Summary:\\n{summary}")
461+
print(f"Experiment Summary:\n{summary}")
462462
```
463463

464464
Integration with logging systems:
@@ -467,11 +467,11 @@ def format(self, *, include_item_results: bool = False) -> str:
467467
logger = logging.getLogger("experiments")
468468

469469
# Log summary after experiment
470-
logger.info(f"Experiment completed:\\n{result.format()}")
470+
logger.info(f"Experiment completed:\n{result.format()}")
471471

472472
# Log detailed results for failed experiments
473473
if any(eval['value'] < threshold for eval in result.run_evaluations):
474-
logger.warning(f"Poor performance detected:\\n{result.format(include_item_results=True)}")
474+
logger.warning(f"Poor performance detected:\n{result.format(include_item_results=True)}")
475475
```
476476
"""
477477
if not self.item_results:
@@ -482,7 +482,7 @@ def format(self, *, include_item_results: bool = False) -> str:
482482
# Individual results section
483483
if include_item_results:
484484
for i, result in enumerate(self.item_results):
485-
output += f"\\n{i + 1}. Item {i + 1}:\\n"
485+
output += f"\n{i + 1}. Item {i + 1}:\n"
486486

487487
# Extract and display input
488488
item_input = None
@@ -492,7 +492,7 @@ def format(self, *, include_item_results: bool = False) -> str:
492492
item_input = result.item.input
493493

494494
if item_input is not None:
495-
output += f" Input: {_format_value(item_input)}\\n"
495+
output += f" Input: {_format_value(item_input)}\n"
496496

497497
# Extract and display expected output
498498
expected_output = None
@@ -502,36 +502,36 @@ def format(self, *, include_item_results: bool = False) -> str:
502502
expected_output = result.item.expected_output
503503

504504
if expected_output is not None:
505-
output += f" Expected: {_format_value(expected_output)}\\n"
506-
output += f" Actual: {_format_value(result.output)}\\n"
505+
output += f" Expected: {_format_value(expected_output)}\n"
506+
output += f" Actual: {_format_value(result.output)}\n"
507507

508508
# Display evaluation scores
509509
if result.evaluations:
510-
output += " Scores:\\n"
510+
output += " Scores:\n"
511511
for evaluation in result.evaluations:
512512
score = evaluation.value
513513
if isinstance(score, (int, float)):
514514
score = f"{score:.3f}"
515515
output += f" • {evaluation.name}: {score}"
516516
if evaluation.comment:
517-
output += f"\\n 💭 {evaluation.comment}"
518-
output += "\\n"
517+
output += f"\n 💭 {evaluation.comment}"
518+
output += "\n"
519519

520520
# Display trace link if available
521521
if result.trace_id:
522-
output += f"\\n Trace ID: {result.trace_id}\\n"
522+
output += f"\n Trace ID: {result.trace_id}\n"
523523
else:
524-
output += f"Individual Results: Hidden ({len(self.item_results)} items)\\n"
525-
output += "💡 Set include_item_results=True to view them\\n"
524+
output += f"Individual Results: Hidden ({len(self.item_results)} items)\n"
525+
output += "💡 Set include_item_results=True to view them\n"
526526

527527
# Experiment overview section
528-
output += f"\\n{'─' * 50}\\n"
528+
output += f"\n{'─' * 50}\n"
529529
output += f"🧪 Experiment: {self.name}"
530530
output += f"\n📋 Run name: {self.run_name}"
531531
if self.description:
532532
output += f" - {self.description}"
533533

534-
output += f"\\n{len(self.item_results)} items"
534+
output += f"\n{len(self.item_results)} items"
535535

536536
# Collect unique evaluation names across all items
537537
evaluation_names = set()
@@ -540,14 +540,14 @@ def format(self, *, include_item_results: bool = False) -> str:
540540
evaluation_names.add(evaluation.name)
541541

542542
if evaluation_names:
543-
output += "\\nEvaluations:"
543+
output += "\nEvaluations:"
544544
for eval_name in evaluation_names:
545-
output += f"\\n • {eval_name}"
546-
output += "\\n"
545+
output += f"\n • {eval_name}"
546+
output += "\n"
547547

548548
# Calculate and display average scores
549549
if evaluation_names:
550-
output += "\\nAverage Scores:"
550+
output += "\nAverage Scores:"
551551
for eval_name in evaluation_names:
552552
scores = []
553553
for result in self.item_results:
@@ -559,24 +559,24 @@ def format(self, *, include_item_results: bool = False) -> str:
559559

560560
if scores:
561561
avg = sum(scores) / len(scores)
562-
output += f"\\n • {eval_name}: {avg:.3f}"
563-
output += "\\n"
562+
output += f"\n • {eval_name}: {avg:.3f}"
563+
output += "\n"
564564

565565
# Display run-level evaluations
566566
if self.run_evaluations:
567-
output += "\\nRun Evaluations:"
567+
output += "\nRun Evaluations:"
568568
for run_eval in self.run_evaluations:
569569
score = run_eval.value
570570
if isinstance(score, (int, float)):
571571
score = f"{score:.3f}"
572-
output += f"\\n • {run_eval.name}: {score}"
572+
output += f"\n • {run_eval.name}: {score}"
573573
if run_eval.comment:
574-
output += f"\\n 💭 {run_eval.comment}"
575-
output += "\\n"
574+
output += f"\n 💭 {run_eval.comment}"
575+
output += "\n"
576576

577577
# Add dataset run URL if available
578578
if self.dataset_run_url:
579-
output += f"\\n🔗 Dataset Run:\\n {self.dataset_run_url}"
579+
output += f"\n🔗 Dataset Run:\n {self.dataset_run_url}"
580580

581581
return output
582582

0 commit comments

Comments
 (0)