Python v3 → v4
Python SDK v4 引入了 以 observation 为中心的数据模型。在该模型中,关联属性(user_id、session_id、metadata、tags)会传播到每个 observation,而不再仅存在于 trace 上。这使得无需昂贵的 join 即可进行单表查询,在大规模场景下能显著提升查询性能。
这改变了你设置 trace 属性的方式:你不再用 update_current_trace() 命令式地更新 trace 对象,而是使用 propagate_attributes()——一个 context manager,会自动把属性应用到当前以及在其作用域内创建的所有子 observation。
v4 改变了默认的 OpenTelemetry 导出行为:Litefuse 不再默认导出所有 span。如果你之前依赖非 LLM span(HTTP、DB、队列、框架内部)被转发,请在升级前先看下方第一项破坏性变更。
破坏性变更
智能默认 span 过滤替代 export-all 行为
在之前的版本中,默认导出所有 OpenTelemetry span 会引入大量来自基础设施和非 LLM instrumentation 的噪音(HTTP、DB、队列、框架内部)。为了让 trace 更聚焦、更有用,v4 引入了智能默认 span 过滤器。
默认情况下,只要满足以下任意一条,v4 就会导出该 span:
- span 由 Litefuse 创建(
langfuse-sdk) - span 拥有
gen_ai.*属性 - span 的 instrumentation scope 匹配已知的 LLM scope 前缀(例如
openinference、langsmith、haystack、litellm)
在 v4 之前,未被屏蔽的 instrumentation scope 默认都会被导出。
保持 v4 之前的 “导出全部” 行为
from langfuse import Langfuse
langfuse = Langfuse(should_export_span=lambda span: True)在默认行为基础上组合自定义过滤器
from langfuse import Langfuse
from langfuse.span_filter import is_default_export_span
langfuse = Langfuse(
should_export_span=lambda span: (
is_default_export_span(span)
or (
span.instrumentation_scope is not None
and span.instrumentation_scope.name.startswith("my_framework")
)
)
)Python 兼容性提示:blocked_instrumentation_scopes 已弃用
blocked_instrumentation_scopes 在 v4 中仍可用,但已被弃用,并将在未来版本移除。请迁移到 should_export_span。
用 should_export_span 表达等价的拒绝列表行为:
from langfuse import Langfuse
from langfuse.span_filter import is_default_export_span
blocked = {"sqlite", "requests"}
langfuse = Langfuse(
should_export_span=lambda span: (
is_default_export_span(span)
and (
span.instrumentation_scope is None
or span.instrumentation_scope.name not in blocked
)
)
)如果同时设置了 blocked_instrumentation_scopes 和 should_export_span,被屏蔽的 scope 仍然胜出(硬性否决)。
可能的 trace 树副作用与调试方法
当中间或父 span 被丢弃,但子 span 仍被导出时,过滤可能破坏 trace 树。如果 trace 看起来断开,请启用 SDK debug 日志查看被丢弃的 span,然后将所需 scope 加入回调的白名单。
- Python debug 模式:使用
Langfuse(debug=True)或设置LANGFUSE_DEBUG="True"。 - 参见 SDK 进阶功能 和 关于不需要的 span 的 OpenTelemetry 故障排查。
update_current_trace() 拆分为 3 个方法
在新模型中,关联属性(user_id、session_id、metadata、tags)必须存在于每个 observation 上,而不仅仅在 trace 上。这就是为什么它们被移到 propagate_attributes()——一个 context manager,会自动把这些属性应用到当前以及其作用域内创建的所有子 observation。
v3:
langfuse.update_current_trace(
name="trace-name",
user_id="user-123",
session_id="session-abc",
version="1.0",
input={"query": "hello"},
output={"result": "world"},
metadata={"key": "value"},
tags=["tag1"],
public=True,
)v4(拆分后):
from langfuse import observe, propagate_attributes, get_client
langfuse = get_client()
@observe()
def my_function():
# (a) Correlating attributes → propagate_attributes() context manager
with propagate_attributes(
trace_name="trace-name", # note: 'name' is now 'trace_name'
user_id="user-123",
session_id="session-abc",
version="1.0",
metadata={"key": "value"},
tags=["tag1"],
):
result = call_llm("hello")
# (b) Trace I/O (deprecated, only for legacy trace-level LLM-as-a-judge configurations)
langfuse.set_current_trace_io(input={"query": "hello"}, output={"result": result})
# (c) Public flag
langfuse.set_current_trace_as_public()关键差异:
| 属性 | v3 | v4 |
|---|---|---|
name | update_current_trace(name=...) | propagate_attributes(trace_name=...) |
user_id、session_id、tags、version | update_current_trace(...) | propagate_attributes(...) |
metadata | update_current_trace(metadata=any) | propagate_attributes(metadata=dict[str,str]) |
input、output | update_current_trace(...) | set_current_trace_io(...)(已弃用) |
public | update_current_trace(public=True) | set_current_trace_as_public() |
release | update_current_trace(release=...) | 已移除——使用 LANGFUSE_RELEASE 环境变量 |
environment | update_current_trace(environment=...) | 已移除——使用 LANGFUSE_TRACING_ENVIRONMENT 环境变量 |
set_current_trace_io() 已被弃用,仅为兼容依赖 trace 输入/输出的 trace 级 LLM-as-a-judge 评估器而保留。新代码请直接在根 observation 上设置输入/输出。
span.update_trace() 拆分为 3 个方法
同样的拆分适用于 observation 级的 update_trace() 方法。
v3:
span.update_trace(
name="trace-name",
user_id="user-123",
session_id="session-abc",
input={"query": "hello"},
output={"result": "world"},
public=True,
)v4:
from langfuse import get_client, propagate_attributes
langfuse = get_client()
with langfuse.start_as_current_observation(as_type="span", name="my-operation") as span:
with propagate_attributes(trace_name="trace-name", user_id="user-123", session_id="session-abc"):
result = call_llm("hello")
span.set_trace_io(input={"query": "hello"}, output={"result": result}) # deprecated
span.set_trace_as_public()Public API 命名空间重映射(api.*)
在 v4 中,高性能 Public API 资源现在是默认值。v2 别名已被移除。
| v3 / 过渡期名称 | v4 名称 |
|---|---|
langfuse.api.observations_v_2 | langfuse.api.observations |
langfuse.api.score_v_2 | langfuse.api.scores |
langfuse.api.metrics_v_2 | langfuse.api.metrics |
langfuse.api.observations(旧版 v1) | langfuse.api.legacy.observations_v1 |
langfuse.api.score(旧版 v1) | langfuse.api.legacy.score_v1 |
langfuse.api.metrics(旧版 v1) | langfuse.api.legacy.metrics_v1 |
如果你仍需要旧版 v1 行为,请切换到对应的 langfuse.api.legacy.<resource>_v1 命名空间。
如果你使用自托管 Litefuse,暂时不要使用新的默认方法 langfuse.api.observations 或 langfuse.api.metrics。它们现在指向 Observations v2 和 Metrics v2 endpoint,这些目前在自托管部署中尚不可用。请改用 langfuse.api.legacy.observations_v1 和 langfuse.api.legacy.metrics_v1。
start_span() / start_generation() → start_observation()
在新模型中,observation 是核心概念。带有 as_type 参数的统一 start_observation() API 取代了原本的多个独立方法。
| v3 | v4 |
|---|---|
langfuse.start_span(name="x") | langfuse.start_observation(name="x") |
langfuse.start_as_current_span(name="x") | langfuse.start_as_current_observation(name="x") |
langfuse.start_generation(name="x", model="gpt-4") | langfuse.start_observation(name="x", as_type="generation", model="gpt-4") |
langfuse.start_as_current_generation(name="x", model="gpt-4") | langfuse.start_as_current_observation(name="x", as_type="generation", model="gpt-4") |
span.start_span(name="x") | span.start_observation(name="x") |
span.start_as_current_span(name="x") | span.start_as_current_observation(name="x") |
span.start_generation(name="x") | span.start_observation(name="x", as_type="generation") |
span.start_as_current_generation(name="x") | span.start_as_current_observation(name="x", as_type="generation") |
DatasetItemClient.run() 已移除 → 改用 Experiment SDK
Experiment SDK(dataset.run_experiment())会在底层处理实验属性的传播(运行元数据、dataset item 关联)。
v3:
for item in dataset.items:
with item.run(run_name="my-run", run_metadata={...}) as span:
result = my_llm(item.input)
span.update(output=result)v4:
from langfuse import get_client
dataset = get_client().get_dataset("my-dataset")
def my_task(*, item, **kwargs):
return my_llm(item.input)
dataset.run_experiment(name="my-run", task=my_task)DatasetItem 对象仍然保有相同的数据属性(id、input、expected_output、metadata 等),但 run() 方法已被移除。
LangChain CallbackHandler:移除了 update_trace 参数
handler 内部现在使用 propagate_attributes()。update_trace 参数不再存在——传入它会抛出 TypeError。
v3:
from langfuse.langchain import CallbackHandler
handler = CallbackHandler(update_trace=True, trace_context={...})v4:
handler = CallbackHandler(trace_context={...})你仍可以通过用 propagate_attributes() 包裹 LangChain 调用的外层 span 来设置 trace 属性(user_id、session_id、tags 等)。参见 v2 → v3 迁移指南中的 LangChain 集成示例,或自定义 trace 属性文档。
已移除的类型
以下类型已从 langfuse.types 中移除:
| 已移除的类型 | 描述 |
|---|---|
TraceMetadata | 包含 name、user_id、session_id、version、release、metadata、tags、public 的 TypedDict |
ObservationParams | 在 TraceMetadata 基础上扩展了 observation 字段的 TypedDict |
MapValue、ModelUsage、PromptClient | 不再从 langfuse.types 重新导出,请改从 langfuse.model 导入 |
不再支持 Pydantic v1
SDK 现在要求 Pydantic v2。如果你的应用仍在使用 Pydantic v1,必须改用 pydantic.v1 兼容垫片。
校验变更
- propagated
metadata:现在是dict[str, str],每个值长度上限 200 字符(之前是Any)。非字符串值会被强制转为字符串。超过长度上限的值会被丢弃并记录警告。 user_id、session_id:作为字符串校验,最大长度 200 字符。超过长度上限的值会被丢弃并记录警告。
迁移清单
- 审计依赖非 LLM OpenTelemetry span 的 trace/仪表盘:在 v4 默认过滤器下它们可能不再出现
- 如有需要,设置
should_export_span=lambda span: True以保持 v4 之前的 “导出所有 span” 行为 - 如果你仍在使用
blocked_instrumentation_scopes,请在该弃用项移除前迁移到should_export_span的组合方式 - 搜索
update_current_trace→ 拆分为propagate_attributes()+set_current_trace_io()(仅在依赖旧版 trace 级 LLM-as-a-judge 配置时)+set_current_trace_as_public() - 搜索
.update_trace(→ 在 observation 对象上做相同拆分 - 搜索
start_span/start_generation→ 替换为start_observation - 搜索
item.run(→ 替换为dataset.run_experiment() - 搜索
CallbackHandler(update_trace=→ 移除该参数 - 确认 metadata 的值是
dict[str, str],且每个值长度 ≤200 - 如果仍在 Pydantic v1,请升级到 v2
- 搜索
api.observations_v_2/api.score_v_2/api.metrics_v_2→ 替换为api.observations/api.scores/api.metrics - 搜索
api.observations/api.score/api.metrics上的旧版 v1 用法 → 改为api.legacy.observations_v1/api.legacy.score_v1/api.legacy.metrics_v1 - 如果你自托管 Litefuse,暂时不要使用
api.observations或api.metrics;在 Observations v2 和 Metrics v2 在自托管部署中可用之前,请使用api.legacy.observations_v1和api.legacy.metrics_v1 - 移除剩余的所有
*_v_2别名引用(在 v4 中已被移除)