Langfuse 入门:Trace、Prompt、Dataset、Experiment、Evaluator

Langfuse 入门:Trace、Prompt、Dataset、Experiment、Evaluator

Langfuse 可以理解成:

LLM / Agent 的日志监控 + Prompt 管理 + 自动化评测平台。

核心就 5 个东西:

text 复制代码
Trace       看 Agent 怎么跑
Prompt      管理 Prompt 版本
Dataset     准备测试数据
Experiment  批量执行测试
Evaluator   定义评分规则

1. Trace:记录 Agent 整个执行过程

如果使用 LangChain / LangGraph,最常见就是挂 CallbackHandler。Langfuse 可以自动捕获 LLM、Tool、Retriever 等执行步骤。

python 复制代码
from langfuse.langchain import CallbackHandler

langfuse_handler = CallbackHandler()

result = graph.invoke(
    {
        "messages": [
            {"role": "user", "content": "北京天气怎么样?"}
        ]
    },
    config={
        "callbacks": [langfuse_handler]
    }
)

如果你的 Agent 有 Tool:

python 复制代码
from langchain_core.tools import tool


@tool
def get_weather(city: str):
    """查询城市天气"""
    return f"{city}今天晴天,28℃"


tools = [get_weather]

model_with_tools = model.bind_tools(tools)

LangGraph:

python 复制代码
from langgraph.prebuilt import ToolNode

tool_node = ToolNode(tools)

模型真的调用了 get_weather 后,Langfuse Trace 中可以看到类似:

text 复制代码
Agent
│
├── ChatModel
│    └── tool_call
│         └── get_weather(city="北京")
│
├── get_weather
│    ├── input
│    ├── output
│    └── latency
│
└── ChatModel
     └── final answer

因此 Trace 主要用来查:

text 复制代码
模型输入
模型输出
Tool 调用了什么
Tool 参数是什么
Tool 返回了什么
哪里报错
耗时
Token
Agent 执行路径

2. Prompt:不要把 Prompt 全写死在代码里

例如以前:

python 复制代码
SYSTEM_PROMPT = """
你是一个 Java 后端专家。
回答问题时需要给出原因和解决方案。
"""

可以改成在 Langfuse 创建:

python 复制代码
from langfuse import get_client

langfuse = get_client()

langfuse.create_prompt(
    name="backend-agent",
    type="chat",
    prompt=[
        {
            "role": "system",
            "content": "你是一个 {{role}},回答需要简洁准确。"
        },
        {
            "role": "user",
            "content": "{{question}}"
        }
    ],
    labels=["production"]
)

同名 Prompt 再创建时,会形成新的版本。

例如:

text 复制代码
backend-agent

v1
你是一个 Java 专家...

v2
你是一个 Java 后端专家...

v3
你是一个有生产事故经验的 Java 后端专家...

运行时获取:

python 复制代码
prompt = langfuse.get_prompt(
    "backend-agent",
    type="chat"
)

然后替换变量:

python 复制代码
messages = prompt.compile(
    role="Java 后端专家",
    question="Redis 大 Key 怎么解决?"
)

Langfuse Prompt 使用 {``{variable}} 作为变量占位符。

最终:

python 复制代码
result = graph.invoke(
    {"messages": messages},
    config={
        "callbacks": [langfuse_handler]
    }
)

这样以后可以测试:

text 复制代码
Prompt v1
vs
Prompt v2
vs
Prompt v3

到底哪个效果更好。


3. Dataset:Agent 的测试数据

Dataset 不是 Few-shot。

它更像:

AI 项目的测试用例集合。

例如创建 Dataset:

python 复制代码
from langfuse import get_client

langfuse = get_client()

langfuse.create_dataset(
    name="middleware-agent-test",
    description="中间件 Agent 测试集"
)

添加测试数据:

python 复制代码
langfuse.create_dataset_item(
    dataset_name="middleware-agent-test",
    input={
        "question": "中国的首都是哪里?"
    },
    expected_output={
        "answer": "北京"
    }
)

再加入:

python 复制代码
langfuse.create_dataset_item(
    dataset_name="middleware-agent-test",
    input={
        "question": "法国的首都是哪里?"
    },
    expected_output={
        "answer": "巴黎"
    }
)

最后 Dataset 相当于:

text 复制代码
input                           expected_output
--------------------------------------------------
中国的首都是哪里?                北京
法国的首都是哪里?                巴黎
日本的首都是哪里?                东京

注意:

text 复制代码
Few-shot
↓
给模型看的例子
↓
帮助模型回答


Dataset
↓
给测试系统的数据
↓
检查模型回答得好不好

4. Evaluator:定义怎么算正确

Evaluator 就是你的断言 / 评分规则

例如最简单的包含判断:

python 复制代码
from langfuse import Evaluation


def accuracy_evaluator(
    *,
    input,
    output,
    expected_output,
    metadata,
    **kwargs
):
    expected = expected_output["answer"]

    if expected.lower() in output.lower():
        return Evaluation(
            name="accuracy",
            value=1.0,
            comment="回答正确"
        )

    return Evaluation(
        name="accuracy",
        value=0.0,
        comment="回答错误"
    )

Langfuse Experiment 的 evaluator 会拿到:

text 复制代码
input
output
expected_output
metadata

然后返回 Evaluation,最后形成 Score。

例如:

text 复制代码
input:
中国的首都是哪里?

expected_output:
北京

Agent output:
中国的首都是北京。

        ↓

accuracy_evaluator()

        ↓

Score = 1.0

实际 Agent 可以定义很多 Evaluator:

python 复制代码
def tool_success_evaluator(...):
    # Tool 是否成功
    ...


def json_valid_evaluator(...):
    # 输出 JSON 是否符合要求
    ...


def latency_evaluator(...):
    # 延迟是否超标
    ...


def rag_relevance_evaluator(...):
    # 检索结果是否相关
    ...

复杂语义问题还可以使用 LLM-as-a-Judge。


5. Experiment:真正把 Dataset 跑一遍

Experiment 才是执行测试的地方。

先定义:

python 复制代码
dataset = langfuse.get_dataset(
    "middleware-agent-test"
)

然后定义 Agent 执行函数:

python 复制代码
def task(*, item, **kwargs):
    question = item.input["question"]

    result = graph.invoke(
        {
            "messages": [
                {
                    "role": "user",
                    "content": question
                }
            ]
        },
        config={
            "callbacks": [langfuse_handler]
        }
    )

    return result["messages"][-1].content

然后运行:

python 复制代码
result = dataset.run_experiment(
    name="agent-v1",
    task=task,
    evaluators=[
        accuracy_evaluator
    ]
)

print(result.format())

Experiment Runner 会:

text 复制代码
遍历 Dataset
    ↓
调用 task()
    ↓
执行 Agent
    ↓
得到 output
    ↓
调用 Evaluator
    ↓
得到 Score

这正是 Langfuse 官方 Experiment SDK 的核心工作方式。


6. Prompt + Dataset + Experiment 串起来

真正项目里通常这样:

python 复制代码
def task(*, item, **kwargs):
    # 1. Dataset
    question = item.input["question"]

    # 2. Prompt
    prompt = langfuse.get_prompt(
        "backend-agent",
        type="chat"
    )

    messages = prompt.compile(
        role="Java 后端专家",
        question=question
    )

    # 3. Agent
    result = graph.invoke(
        {
            "messages": messages
        },
        config={
            "callbacks": [langfuse_handler]
        }
    )

    # 4. actual output
    return result["messages"][-1].content

然后:

python 复制代码
dataset = langfuse.get_dataset(
    "middleware-agent-test"
)

result = dataset.run_experiment(
    name="backend-agent-prompt-v2",
    task=task,
    evaluators=[
        accuracy_evaluator
    ]
)

print(result.format())

完整流程就是:

text 复制代码
Dataset
input
  │
  ↓
Prompt.compile()
  │
  ↓
LangGraph Agent
  │
  ├────────────→ Trace
  │              看 LLM / Tool / Error
  ↓
actual_output
  │
  ├── expected_output
  │
  ↓
Evaluator
  │
  ↓
Score

7. 为什么要做 Experiment?

假设你现在改了 Prompt:

text 复制代码
Prompt V1
你是一个 Java 专家

改成:

text 复制代码
Prompt V2
你是一名拥有大型分布式系统生产经验的 Java 后端专家,
回答问题时必须说明原因、解决方案和注意事项。

不要靠:

"感觉 V2 好像更强。"

而是直接:

python 复制代码
dataset.run_experiment(
    name="prompt-v1",
    ...
)

再:

python 复制代码
dataset.run_experiment(
    name="prompt-v2",
    ...
)

最后比较:

text 复制代码
             accuracy    tool_success

Prompt V1      0.76          0.91

Prompt V2      0.87          0.98

Langfuse 的 Experiment 可以在同一个 Dataset 上重复执行,并在 UI 中比较不同实验结果。


8. 最后记这五句话就行

text 复制代码
Trace
= 日志 / 链路追踪
= Agent 到底执行了什么


Prompt
= Prompt 版本管理
= 哪个 Prompt 效果更好


Dataset
= AI 测试用例
= input + expected_output


Experiment
= 批量执行测试用例
= 跑一次完整 Eval


Evaluator
= 断言 / 评分规则
= 怎么判断 Output 好不好

整体:

text 复制代码
                ┌──── Trace
                │
Dataset → Agent ┼──── LLM
   ↑            ├──── Tool
   │            └──── Output
   │                    ↓
expected_output ─→ Evaluator
                        ↓
                       Score

一句话:

Langfuse = 给 Agent 加上"链路日志 + Prompt 版本管理 + 自动化测试"。

它和传统后端其实非常像:

text 复制代码
传统后端                     Agent

日志 / APM             →    Trace

配置中心               →    Prompt Management

测试数据               →    Dataset

自动化测试             →    Experiment

Assert                  →    Evaluator

测试结果               →    Score
相关推荐
vipbic1 小时前
一个前端的 9 天重构:我是怎么用 Codex 重做航栈的
前端·javascript·后端
TechWayfarer1 小时前
批量查IP归属地,在线API、脚本、离线库怎么选?三种方案实测对比
网络·python·网络协议·tcp/ip
七牛开发者2 小时前
为什么 Go 很适合 AI 辅助开发?
数据库·人工智能·python·elasticsearch·log4j
河南凹凸环境艺术设计3 小时前
性价比高的民宿酒店设计企业
大数据·人工智能·python
Eason_Lou3 小时前
【无标题】
前端·vue.js·html
_codemonster3 小时前
npm run dev 是在开发模式运行,怎么在生产环境运行
前端·npm·node.js
kyriewen3 小时前
我受够了复制报错去问 AI,花一下午给控制台做了个调试助手
前端·javascript·ai编程
IT_陈寒4 小时前
Redis的DEL命令竟然没删掉数据?我踩的这个坑你得知道
前端·人工智能·后端