Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-langfuse for openSUSE:Factory
checked in at 2026-05-18 17:47:03
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-langfuse (Old)
and /work/SRC/openSUSE:Factory/.python-langfuse.new.1966 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-langfuse"
Mon May 18 17:47:03 2026 rev:9 rq:1353629 version:4.6.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-langfuse/python-langfuse.changes
2026-04-25 21:42:57.687487090 +0200
+++
/work/SRC/openSUSE:Factory/.python-langfuse.new.1966/python-langfuse.changes
2026-05-18 17:47:18.054527801 +0200
@@ -1,0 +2,9 @@
+Sun May 17 21:13:42 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 4.6.1:
+ * feat(ci): add RunnerContext and RegressionError for
+ experiment GH action
+ * ci: allow prerelease branch releases
+ * fix(openai): handle Azure stream chunks without delta
+
+-------------------------------------------------------------------
Old:
----
langfuse-4.5.1.tar.gz
New:
----
langfuse-4.6.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-langfuse.spec ++++++
--- /var/tmp/diff_new_pack.pZoEYV/_old 2026-05-18 17:47:18.714555075 +0200
+++ /var/tmp/diff_new_pack.pZoEYV/_new 2026-05-18 17:47:18.718555241 +0200
@@ -18,7 +18,7 @@
%{?sle15_python_module_pythons}
Name: python-langfuse
-Version: 4.5.1
+Version: 4.6.1
Release: 0
Summary: A client library for accessing langfuse
License: MIT
++++++ langfuse-4.5.1.tar.gz -> langfuse-4.6.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/langfuse-4.5.1/PKG-INFO new/langfuse-4.6.1/PKG-INFO
--- old/langfuse-4.5.1/PKG-INFO 1970-01-01 01:00:00.000000000 +0100
+++ new/langfuse-4.6.1/PKG-INFO 1970-01-01 01:00:00.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: langfuse
-Version: 4.5.1
+Version: 4.6.1
Summary: A client library for accessing langfuse
Author: langfuse
Author-email: langfuse <[email protected]>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/langfuse-4.5.1/langfuse/__init__.py
new/langfuse-4.6.1/langfuse/__init__.py
--- old/langfuse-4.5.1/langfuse/__init__.py 1970-01-01 01:00:00.000000000
+0100
+++ new/langfuse-4.6.1/langfuse/__init__.py 1970-01-01 01:00:00.000000000
+0100
@@ -8,7 +8,7 @@
EvaluatorStats,
MapperFunction,
)
-from langfuse.experiment import Evaluation
+from langfuse.experiment import Evaluation, RegressionError, RunnerContext
from ._client import client as _client_module
from ._client.attributes import LangfuseOtelSpanAttributes
@@ -63,6 +63,8 @@
"EvaluatorStats",
"BatchEvaluationResumeToken",
"BatchEvaluationResult",
+ "RunnerContext",
+ "RegressionError",
"__version__",
"is_default_export_span",
"is_langfuse_span",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/langfuse-4.5.1/langfuse/experiment.py
new/langfuse-4.6.1/langfuse/experiment.py
--- old/langfuse-4.5.1/langfuse/experiment.py 1970-01-01 01:00:00.000000000
+0100
+++ new/langfuse-4.6.1/langfuse/experiment.py 1970-01-01 01:00:00.000000000
+0100
@@ -6,7 +6,9 @@
"""
import asyncio
+from datetime import datetime
from typing import (
+ TYPE_CHECKING,
Any,
Awaitable,
Dict,
@@ -15,12 +17,17 @@
Protocol,
TypedDict,
Union,
+ overload,
)
from langfuse.api import DatasetItem
from langfuse.logger import langfuse_logger as logger
from langfuse.types import ExperimentScoreType
+if TYPE_CHECKING:
+ from langfuse._client.client import Langfuse
+ from langfuse.batch_evaluation import CompositeEvaluatorFunction
+
class LocalExperimentItem(TypedDict, total=False):
"""Structure for local experiment data items (not from Langfuse datasets).
@@ -1049,3 +1056,152 @@
)
return langfuse_evaluator
+
+
+class RunnerContext:
+ """Wraps :meth:`Langfuse.run_experiment` with CI-injected defaults.
+
+ Intended for use with the ``langfuse/experiment-action`` GitHub Action
+ (https://github.com/langfuse/experiment-action). The action builds a
+ ``RunnerContext`` before invoking the user's ``experiment(context)``
+ function. Defaults set here (dataset, metadata tags) are applied when
+ the user omits them on the :meth:`run_experiment` call; users can
+ override any default by passing the corresponding argument explicitly.
+ """
+
+ def __init__(
+ self,
+ *,
+ client: "Langfuse",
+ data: Optional[ExperimentData] = None,
+ dataset_version: Optional[datetime] = None,
+ metadata: Optional[Dict[str, str]] = None,
+ ):
+ """Build a ``RunnerContext`` populated with defaults for
``run_experiment``.
+
+ Typically called by the ``langfuse/experiment-action`` GitHub Action,
+ not by end users directly. Every field except ``client`` is optional:
+ fields left as ``None`` simply mean the corresponding argument must be
+ supplied on the :meth:`run_experiment` call.
+
+ Args:
+ client: Initialized Langfuse SDK client used to execute the
+ experiment. The action creates this from the
+ ``langfuse_public_key`` / ``langfuse_secret_key`` /
+ ``langfuse_base_url`` inputs.
+ data: Default dataset items to run the experiment on. Accepts
+ either ``List[LocalExperimentItem]`` or ``List[DatasetItem]``.
+ Injected by the action when ``dataset_name`` is configured.
+ If ``None``, the user must pass ``data=`` to
+ :meth:`run_experiment`.
+ dataset_version: Optional pinned dataset version. Injected by the
+ action when ``dataset_version`` is configured.
+ metadata: Default metadata attached to every experiment trace and
+ the dataset run. The action injects GitHub-sourced tags (SHA,
+ PR link, workflow run link, branch, GH user, etc.). Merged
+ with any ``metadata`` passed to :meth:`run_experiment`, with
+ user-supplied keys winning on collision.
+ """
+ self.client = client
+ self.data = data
+ self.dataset_version = dataset_version
+ self.metadata = metadata
+
+ def run_experiment(
+ self,
+ *,
+ name: str,
+ run_name: Optional[str] = None,
+ description: Optional[str] = None,
+ data: Optional[ExperimentData] = None,
+ task: TaskFunction,
+ evaluators: List[EvaluatorFunction] = [],
+ composite_evaluator: Optional["CompositeEvaluatorFunction"] = None,
+ run_evaluators: List[RunEvaluatorFunction] = [],
+ max_concurrency: int = 50,
+ metadata: Optional[Dict[str, str]] = None,
+ _dataset_version: Optional[datetime] = None,
+ ) -> ExperimentResult:
+ resolved_data = data if data is not None else self.data
+ if resolved_data is None:
+ raise ValueError(
+ "`data` must be provided either on the RunnerContext or the
run_experiment call"
+ )
+
+ resolved_dataset_version = (
+ _dataset_version if _dataset_version is not None else
self.dataset_version
+ )
+
+ merged_metadata: Optional[Dict[str, str]]
+ if self.metadata is None and metadata is None:
+ merged_metadata = None
+ else:
+ merged_metadata = {**(self.metadata or {}), **(metadata or {})}
+
+ return self.client.run_experiment(
+ name=name,
+ run_name=run_name,
+ description=description,
+ data=resolved_data,
+ task=task,
+ evaluators=evaluators,
+ composite_evaluator=composite_evaluator,
+ run_evaluators=run_evaluators,
+ max_concurrency=max_concurrency,
+ metadata=merged_metadata,
+ _dataset_version=resolved_dataset_version,
+ )
+
+
+class RegressionError(Exception):
+ """Raised by a user's ``experiment`` function to signal a CI gate failure.
+
+ Intended for use with the ``langfuse/experiment-action`` GitHub Action
+ (https://github.com/langfuse/experiment-action). The action catches this
+ exception and, when ``should_fail_on_error`` is enabled, fails the
+ workflow run and renders a callout in the PR comment using
+ ``metric``/``value``/``threshold`` if supplied, otherwise ``str(exc)``.
+
+ Callers choose one of three forms:
+
+ - ``RegressionError(result=r)`` — minimal, generic message.
+ - ``RegressionError(result=r, message="...")`` — free-form message.
+ - ``RegressionError(result=r, metric="acc", value=0.7, threshold=0.9)`` —
+ structured; ``metric`` and ``value`` must be provided together so the
+ action can render a targeted callout without ``None`` placeholders.
+ """
+
+ @overload
+ def __init__(self, *, result: ExperimentResult) -> None: ...
+ @overload
+ def __init__(self, *, result: ExperimentResult, message: str) -> None: ...
+ @overload
+ def __init__(
+ self,
+ *,
+ result: ExperimentResult,
+ metric: str,
+ value: float,
+ threshold: Optional[float] = None,
+ message: Optional[str] = None,
+ ) -> None: ...
+ def __init__(
+ self,
+ *,
+ result: ExperimentResult,
+ metric: Optional[str] = None,
+ value: Optional[float] = None,
+ threshold: Optional[float] = None,
+ message: Optional[str] = None,
+ ):
+ self.result = result
+ self.metric = metric
+ self.value = value
+ self.threshold = threshold
+ if message is not None:
+ formatted = message
+ elif metric is not None and value is not None:
+ formatted = f"Regression on `{metric}`: {value} (threshold
{threshold})"
+ else:
+ formatted = "Experiment regression detected"
+ super().__init__(formatted)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/langfuse-4.5.1/langfuse/openai.py
new/langfuse-4.6.1/langfuse/openai.py
--- old/langfuse-4.5.1/langfuse/openai.py 1970-01-01 01:00:00.000000000
+0100
+++ new/langfuse-4.6.1/langfuse/openai.py 1970-01-01 01:00:00.000000000
+0100
@@ -640,7 +640,9 @@
chunk = chunk.__dict__
model = model or chunk.get("model", None) or None
- usage = chunk.get("usage", None)
+ chunk_usage = chunk.get("usage", None)
+ if chunk_usage is not None:
+ usage = chunk_usage
choices = chunk.get("choices", [])
@@ -649,11 +651,16 @@
choice = choice.__dict__
if resource.type == "chat":
delta = choice.get("delta", None)
- finish_reason = choice.get("finish_reason", None)
+ choice_finish_reason = choice.get("finish_reason", None)
+ if choice_finish_reason is not None:
+ finish_reason = choice_finish_reason
- if _is_openai_v1():
+ if _is_openai_v1() and delta is not None:
delta = delta.__dict__
+ if delta is None:
+ delta = {}
+
if delta.get("role", None) is not None:
completion["role"] = delta["role"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/langfuse-4.5.1/pyproject.toml
new/langfuse-4.6.1/pyproject.toml
--- old/langfuse-4.5.1/pyproject.toml 1970-01-01 01:00:00.000000000 +0100
+++ new/langfuse-4.6.1/pyproject.toml 1970-01-01 01:00:00.000000000 +0100
@@ -1,6 +1,6 @@
[project]
name = "langfuse"
-version = "4.5.1"
+version = "4.6.1"
description = "A client library for accessing langfuse"
readme = "README.md"
authors = [{ name = "langfuse", email = "[email protected]" }]