核心可观测性SDK升级指引Python v3 → v4

Python v3 → v4

Python SDK v4 引入了 以 observation 为中心的数据模型。在该模型中,关联属性(user_idsession_idmetadatatags)会传播到每个 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 前缀(例如 openinferencelangsmithhaystacklitellm

在 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_scopesshould_export_span,被屏蔽的 scope 仍然胜出(硬性否决)。

可能的 trace 树副作用与调试方法

当中间或父 span 被丢弃,但子 span 仍被导出时,过滤可能破坏 trace 树。如果 trace 看起来断开,请启用 SDK debug 日志查看被丢弃的 span,然后将所需 scope 加入回调的白名单。

update_current_trace() 拆分为 3 个方法

在新模型中,关联属性(user_idsession_idmetadatatags)必须存在于每个 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()

关键差异:

属性v3v4
nameupdate_current_trace(name=...)propagate_attributes(trace_name=...)
user_idsession_idtagsversionupdate_current_trace(...)propagate_attributes(...)
metadataupdate_current_trace(metadata=any)propagate_attributes(metadata=dict[str,str])
inputoutputupdate_current_trace(...)set_current_trace_io(...)(已弃用)
publicupdate_current_trace(public=True)set_current_trace_as_public()
releaseupdate_current_trace(release=...)已移除——使用 LANGFUSE_RELEASE 环境变量
environmentupdate_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()

对于集成(LangChainOpenAI),传入的 trace 属性现在只会传播到子节点——不会再冒泡到 trace 上。

Public API 命名空间重映射(api.*

在 v4 中,高性能 Public API 资源现在是默认值。v2 别名已被移除。

v3 / 过渡期名称v4 名称
langfuse.api.observations_v_2langfuse.api.observations
langfuse.api.score_v_2langfuse.api.scores
langfuse.api.metrics_v_2langfuse.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.observationslangfuse.api.metrics。它们现在指向 Observations v2 和 Metrics v2 endpoint,这些目前在自托管部署中尚不可用。请改用 langfuse.api.legacy.observations_v1langfuse.api.legacy.metrics_v1

start_span() / start_generation()start_observation()

在新模型中,observation 是核心概念。带有 as_type 参数的统一 start_observation() API 取代了原本的多个独立方法。

v3v4
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 SDKdataset.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 对象仍然保有相同的数据属性(idinputexpected_outputmetadata 等),但 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_idsession_idtags 等)。参见 v2 → v3 迁移指南中的 LangChain 集成示例,或自定义 trace 属性文档

已移除的类型

以下类型已从 langfuse.types 中移除:

已移除的类型描述
TraceMetadata包含 nameuser_idsession_idversionreleasemetadatatagspublic 的 TypedDict
ObservationParamsTraceMetadata 基础上扩展了 observation 字段的 TypedDict
MapValueModelUsagePromptClient不再从 langfuse.types 重新导出,请改从 langfuse.model 导入

不再支持 Pydantic v1

SDK 现在要求 Pydantic v2。如果你的应用仍在使用 Pydantic v1,必须改用 pydantic.v1 兼容垫片

校验变更

  • propagated metadata:现在是 dict[str, str],每个值长度上限 200 字符(之前是 Any)。非字符串值会被强制转为字符串。超过长度上限的值会被丢弃并记录警告。
  • user_idsession_id:作为字符串校验,最大长度 200 字符。超过长度上限的值会被丢弃并记录警告。

迁移清单

  1. 审计依赖非 LLM OpenTelemetry span 的 trace/仪表盘:在 v4 默认过滤器下它们可能不再出现
  2. 如有需要,设置 should_export_span=lambda span: True 以保持 v4 之前的 “导出所有 span” 行为
  3. 如果你仍在使用 blocked_instrumentation_scopes,请在该弃用项移除前迁移到 should_export_span 的组合方式
  4. 搜索 update_current_trace → 拆分为 propagate_attributes() + set_current_trace_io()(仅在依赖旧版 trace 级 LLM-as-a-judge 配置时)+ set_current_trace_as_public()
  5. 搜索 .update_trace( → 在 observation 对象上做相同拆分
  6. 搜索 start_span / start_generation → 替换为 start_observation
  7. 搜索 item.run( → 替换为 dataset.run_experiment()
  8. 搜索 CallbackHandler(update_trace= → 移除该参数
  9. 确认 metadata 的值是 dict[str, str],且每个值长度 ≤200
  10. 如果仍在 Pydantic v1,请升级到 v2
  11. 搜索 api.observations_v_2 / api.score_v_2 / api.metrics_v_2 → 替换为 api.observations / api.scores / api.metrics
  12. 搜索 api.observations / api.score / api.metrics 上的旧版 v1 用法 → 改为 api.legacy.observations_v1 / api.legacy.score_v1 / api.legacy.metrics_v1
  13. 如果你自托管 Litefuse,暂时不要使用 api.observationsapi.metrics;在 Observations v2 和 Metrics v2 在自托管部署中可用之前,请使用 api.legacy.observations_v1api.legacy.metrics_v1
  14. 移除剩余的所有 *_v_2 别名引用(在 v4 中已被移除)
这个页面对你有帮助吗?