LangfuseLangfuse Python SDK 4.15.4 · Python 3.10+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
38 small wins to finish your pathNext lesson

Comparing prompts on a Langfuse dataset

dataset.run_experiment links every run to the dataset, and a run evaluator scores the run as a whole. Two runs with two prompts give two numbers to compare.

Lesson 26 ran on a list in your code. Run on a dataset stored in Langfuse, each run is recorded against the dataset, so runs made weeks apart, by different people, can be compared side by side. This lesson compares two candidate system prompts.

A model that follows instructions

A prompt comparison needs a model that reads its prompt. The stand-in from lesson 6 ignores the system message, so it learns two instructions: to thank the customer, and to never share order details.

Exampleshop_model.py, the new lines in reply
    rules = messages[0]["content"].lower() if messages[0]["role"] == "system" else ""
    ...
    elif lookup and "never share" in rules:
        text = "I cannot share order details."
    ...
    if "thank" in rules:
        text = "Thanks for waiting. " + text

The full file is lesson 6's with these lines added: rules is the lowercased system message, the new elif sits before the not-found case, and the thank-you check runs right before the usage count. Save it; lessons from here on use this version.

Two runs on one dataset

Examplecompare.py, after the setup lines, from desk import answer, lesson 25's dataset lines and lesson 26's fixed evaluator
def average(*, item_results, **kwargs):
    values = [e.value for row in item_results for e in row.evaluations]
    return Evaluation(name="average", value=sum(values) / len(values))


def compare(system, run_name):
    def task(*, item, **kwargs):
        return answer(item.input, system=system)

    result = dataset.run_experiment(name="desk-prompts", run_name=run_name, task=task,
                                    evaluators=[contains_expected], run_evaluators=[average])
    print(run_name, "average:", round(result.run_evaluations[0].value, 2))

A run evaluator receives every item's result and returns one evaluation for the whole run, here the average. The task gets a dataset item, so the ticket is item.input. run_name names each run; without one the SDK makes one from the name and the time.

Examplecompare.py, continued
dataset = langfuse.get_dataset("desk-tickets")
compare("Answer in one short sentence. Thank the customer.", "thank-the-customer")
compare("Answer in one short sentence. Never share order details.", "never-share")

langfuse.flush()
print([r for r in local_langfuse.REQUESTS if "run-items" in r])
print([(s["name"], s.get("datasetRunId"), s["value"]) for s in local_langfuse.SCORES if s.get("datasetRunId")])
Example
python compare.py

The polite prompt kept every expected phrase, because the thanks is added in front. The secretive one refused to share the A17 and B22 details, so only the refund case passed. REQUESTS shows a dataset run item created for each case, linking its trace to the dataset. The run averages were stored as scores on each dataset run, which is what Langfuse's comparison view lines up.

One experiment run over a dataset
dataset desk-ticketsWhere is my order A17?expects: shipped on 3 MarchIs B22 on its way?expects: could not find B22I want a refund for A17expects: need approvalyour taskanswer(item.input, system=...)your evaluatorcontains-expected, 1.0 or 0.0your run evaluatorthe average over the runscores in Langfuseper item, and per runruns to compareproduction 1.0, candidate 0.33
Hover or tap a piece to see what it is and which lesson built it.
Follow one run

Pick one to watch it run, step by step.

The dataset, the task, the evaluator and the run evaluator are the four pieces you supply; the run, the traces and the scores are what Langfuse keeps.

Try it yourself
  • Add a third prompt that asks for both instructions and compare.
  • Fetch the dataset with version= set to a past time and run on it.
  • Print result.format() for one run.

You understood something today that you didn't yesterday.