bug: Blocking sync HTTP call inside DatasetClient.run_experiment()

当你在 Langfuse Python SDK 中调用 DatasetClient.run_experiment() 并传入 async task 时,SDK 内部仍会执行同步 HTTP 调用(如 dataset_run_items.create ),阻塞事件循环并导致 bug: Blocking

快速结论:当你在 Langfuse Python SDK 中调用 DatasetClient.run_experiment() 并传入 async task 时,SDK 内部仍会执行同步 HTTP 调用(如 dataset_run_items.create),阻塞事件循环并导致 bug: Blocking sync HTTP call inside DatasetClient.run_experiment()。优先排查 SDK 版本以及实验流程中是否存在同步阻塞调用。

适用环境:Langfuse 自托管 v3.111.0;langfuse-python 3.6.1;使用异步 OpenAI 客户端(AsyncOpenAI)与 get_dataset().run_experiment()。Issue 未提供操作系统、Python、CUDA、显卡信息。

最快修复方案:暂无确认的一步修复方案。Issue 中讨论的可优先尝试方式是:将同步阻塞调用放入线程池执行(如 asyncio.to_thread 或 concurrent.futures.ThreadPoolExecutor),避免阻塞事件循环。

注意事项:线程池方案属于 Issue 中建议的 workaround,并非 SDK 官方修复;截至 Issue 关闭时,Python SDK 仍未提供 async 版本的 run_experiment 及相关方法,官方 cookbook 也只展示同步用法。使用线程池可能带来额外资源开销,并需自行管理并发。

问题场景

用户在自托管 Langfuse v3.111.0 上注册了一个包含约 1000 条样本的数据集,然后使用 langfuse-python 3.6.1 调用 dataset.run_experiment(),并传入一个 async task(内部使用 AsyncOpenAI 的 client.chat.completions.create)以及 max_concurrency=100。用户期望实验按异步并发方式运行,但执行过程被 SDK 内部的同步 HTTP 调用阻塞,无法实现真正的异步并发。

报错原文

bug: Blocking sync HTTP call inside DatasetClient.run_experiment()

# Link to dataset run if this is a dataset item
if hasattr(item, "id") and hasattr(item, "dataset_id"):
    try:
        dataset_run_item = self.api.dataset_run_items.create( # This line
            request=CreateDatasetRunItemRequest(
                runName=experiment_run_name,
                runDescription=experiment_description,
                metadata=experiment_metadata,
                datasetItemId=item.id,  # type: ignore
                traceId=trace_id,
                observationId=span.id,
            )
        )

        dataset_run_id = dataset_run_item.dataset_run_id

    except Exception as e:
        langfuse_logger.error(f"Failed to create dataset run item: {e}")

原因分析

最可能的原因是:Langfuse Python SDK 的 DatasetClient.run_experiment() 及其相关方法(例如 dataset_run_items.create)是同步实现,即使传入的是 async task 也不会改变这一行为。当在异步工作流中调用这些同步 HTTP 方法时,会阻塞事件循环,导致 max_concurrency 无法发挥预期的并发效果。Issue 中同时指出,官方文档和 cookbook 只展示了同步用法,未提及 async/await 支持或相关 workaround;JavaScript SDK 支持异步模式,但 Python SDK 当时没有对应实现。

环境排查

  • 确认 langfuse-python 的实际版本(Issue 中为 3.6.1),检查是否已有 async 相关更新。
  • 确认 Langfuse 自托管版本(Issue 中为 v3.111.0)。
  • 确认触发问题的代码路径:DatasetClient.run_experiment() 是否传入 async task,以及 task 中是否使用 AsyncOpenAI 等异步客户端。
  • 确认实验数据集规模与 max_concurrency 设置,用于判断阻塞对并发的影响程度。
  • 操作系统、Python 版本、CUDA、显卡等信息在 Issue 中未提供,暂不作为排查依据。

解决步骤

  1. 确认你使用的 langfuse-python 版本是否为 3.6.1 或同类版本,并检查后续版本说明中是否新增 async 支持。Issue 中未确认官方已修复,因此不能假定升级即可解决。
  2. 如果必须在异步流程中运行实验,可优先尝试将同步阻塞调用移出事件循环,例如使用 asyncio.to_thread 包装,或使用 concurrent.futures.ThreadPoolExecutor 执行 run_experiment() 及其内部同步调用。该方式来自 Issue 讨论中的 workaround 建议,并非官方修复方案。
  3. 检查是否可以直接将 run_experiment() 放在独立线程中执行,而不是在主事件循环内直接调用,从而避免同步 HTTP 调用阻塞 async task 的调度。
  4. 关注 Langfuse Python SDK 是否发布 async 版本的 run_experiment 或 dataset_run_items.create,如有更新再考虑替换现有 workaround。

验证方法

在采用线程池或 asyncio.to_thread 等方式后,观察实验运行期间事件循环是否仍被阻塞:async task 是否能按预期并发调度,max_concurrency 是否产生实际效果,以及是否不再出现同步 HTTP 调用长时间占用事件循环的情况。如果问题仍存在,说明当前 workaround 未覆盖对应的阻塞路径,需要继续检查 SDK 内部调用链。

参考来源

langfuse/langfuse #9711

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 29139

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注