langfuse-haystack 0.0.3__tar.gz → 0.0.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (20) hide show
  1. langfuse_haystack-0.0.4/PKG-INFO +114 -0
  2. langfuse_haystack-0.0.4/README.md +91 -0
  3. {langfuse_haystack-0.0.3 → langfuse_haystack-0.0.4}/example/basic_rag.py +6 -8
  4. {langfuse_haystack-0.0.3 → langfuse_haystack-0.0.4}/example/chat.py +4 -8
  5. langfuse_haystack-0.0.4/pydoc/config.yml +30 -0
  6. {langfuse_haystack-0.0.3 → langfuse_haystack-0.0.4}/pyproject.toml +4 -5
  7. langfuse_haystack-0.0.4/src/haystack_integrations/components/connectors/langfuse/__init__.py +6 -0
  8. langfuse_haystack-0.0.4/src/haystack_integrations/components/connectors/langfuse/langfuse_connector.py +82 -0
  9. {langfuse_haystack-0.0.3 → langfuse_haystack-0.0.4}/src/haystack_integrations/tracing/langfuse/tracer.py +30 -6
  10. langfuse_haystack-0.0.4/tests/test_tracing.py +57 -0
  11. langfuse_haystack-0.0.3/PKG-INFO +0 -45
  12. langfuse_haystack-0.0.3/README.md +0 -22
  13. langfuse_haystack-0.0.3/src/haystack_integrations/components/others/langfuse/__about__.py +0 -1
  14. langfuse_haystack-0.0.3/src/haystack_integrations/components/others/langfuse/__init__.py +0 -3
  15. langfuse_haystack-0.0.3/src/haystack_integrations/components/others/langfuse/component.py +0 -16
  16. {langfuse_haystack-0.0.3 → langfuse_haystack-0.0.4}/.gitignore +0 -0
  17. {langfuse_haystack-0.0.3 → langfuse_haystack-0.0.4}/LICENSE.txt +0 -0
  18. {langfuse_haystack-0.0.3 → langfuse_haystack-0.0.4}/example/requirements.txt +0 -0
  19. {langfuse_haystack-0.0.3 → langfuse_haystack-0.0.4}/src/haystack_integrations/tracing/langfuse/__init__.py +0 -0
  20. {langfuse_haystack-0.0.3 → langfuse_haystack-0.0.4}/tests/__init__.py +0 -0
@@ -0,0 +1,114 @@
1
+ Metadata-Version: 2.3
2
+ Name: langfuse-haystack
3
+ Version: 0.0.4
4
+ Project-URL: Documentation, https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/langfuse#readme
5
+ Project-URL: Issues, https://github.com/deepset-ai/haystack-core-integrations/issues
6
+ Project-URL: Source, https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/langfuse
7
+ Author-email: deepset GmbH <info@deepset.ai>
8
+ License-Expression: Apache-2.0
9
+ License-File: LICENSE.txt
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Programming Language :: Python
12
+ Classifier: Programming Language :: Python :: 3.8
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: Implementation :: CPython
18
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
19
+ Requires-Python: >=3.8
20
+ Requires-Dist: haystack-ai
21
+ Requires-Dist: langfuse
22
+ Description-Content-Type: text/markdown
23
+
24
+ # langfuse-haystack
25
+
26
+ [![PyPI - Version](https://img.shields.io/pypi/v/langfuse-haystack.svg)](https://pypi.org/project/langfuse-haystack)
27
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/langfuse-haystack.svg)](https://pypi.org/project/langfuse-haystack)
28
+
29
+ langfuse-haystack integrates tracing capabilities into [Haystack](https://github.com/deepset-ai/haystack) (2.x) pipelines using [Langfuse](https://langfuse.com/). This package enhances the visibility of pipeline runs by capturing comprehensive details of the execution traces, including API calls, context data, prompts, and more. Whether you're monitoring model performance, pinpointing areas for improvement, or creating datasets for fine-tuning and testing from your pipeline executions, langfuse-haystack is the right tool for you.
30
+ ## Features
31
+
32
+ - Easy integration with Haystack pipelines
33
+ - Capture the full context of the execution
34
+ - Track model usage and cost
35
+ - Collect user feedback
36
+ - Identify low-quality outputs
37
+ - Build fine-tuning and testing datasets
38
+
39
+ ## Installation
40
+
41
+ To install langfuse-haystack, run the following command:
42
+
43
+ ```sh
44
+ pip install langfuse-haystack
45
+ ```
46
+
47
+ ## Usage
48
+
49
+ To enable tracing in your Haystack pipeline, add the `LangfuseConnector` to your pipeline.
50
+ You also need to set the `LANGFUSE_SECRET_KEY` and `LANGFUSE_PUBLIC_KEY` environment variables in order to connect to Langfuse account.
51
+ You can get these keys by signing up for an account on the Langfuse website.
52
+
53
+ Here's an example:
54
+
55
+ ```python
56
+ import os
57
+
58
+ os.environ["LANGFUSE_HOST"] = "https://cloud.langfuse.com"
59
+ os.environ["TOKENIZERS_PARALLELISM"] = "false"
60
+ os.environ["HAYSTACK_CONTENT_TRACING_ENABLED"] = "true"
61
+
62
+ from haystack.components.builders import DynamicChatPromptBuilder
63
+ from haystack.components.generators.chat import OpenAIChatGenerator
64
+ from haystack.dataclasses import ChatMessage
65
+ from haystack import Pipeline
66
+
67
+ from haystack_integrations.components.connectors.langfuse import LangfuseConnector
68
+
69
+ if __name__ == "__main__":
70
+ pipe = Pipeline()
71
+ pipe.add_component("tracer", LangfuseConnector("Chat example"))
72
+ pipe.add_component("prompt_builder", DynamicChatPromptBuilder())
73
+ pipe.add_component("llm", OpenAIChatGenerator(model="gpt-3.5-turbo"))
74
+
75
+ pipe.connect("prompt_builder.prompt", "llm.messages")
76
+
77
+ messages = [
78
+ ChatMessage.from_system("Always respond in German even if some input data is in other languages."),
79
+ ChatMessage.from_user("Tell me about {{location}}"),
80
+ ]
81
+
82
+ response = pipe.run(
83
+ data={"prompt_builder": {"template_variables": {"location": "Berlin"}, "prompt_source": messages}}
84
+ )
85
+ print(response["llm"]["replies"][0])
86
+ print(response["tracer"]["trace_url"])
87
+ ```
88
+
89
+ In this example, we add the `LangfuseConnector` to the pipeline with the name "tracer". Each run of the pipeline produces one trace viewable on the Langfuse website with a specific URL. The trace captures the entire execution context, including the prompts, completions, and metadata.
90
+
91
+ ## Trace Visualization
92
+
93
+ Langfuse provides a user-friendly interface to visualize and analyze the traces generated by your Haystack pipeline. Login into your Langfuse account and navigate to the trace URL to view the trace details.
94
+
95
+ ## Contributing
96
+
97
+ `hatch` is the best way to interact with this project. To install it, run:
98
+ ```sh
99
+ pip install hatch
100
+ ```
101
+
102
+ With `hatch` installed, run all the tests:
103
+ ```
104
+ hatch run test
105
+ ```
106
+
107
+ Run the linters `ruff` and `mypy`:
108
+ ```
109
+ hatch run lint:all
110
+ ```
111
+
112
+ ## License
113
+
114
+ `langfuse-haystack` is distributed under the terms of the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) license.
@@ -0,0 +1,91 @@
1
+ # langfuse-haystack
2
+
3
+ [![PyPI - Version](https://img.shields.io/pypi/v/langfuse-haystack.svg)](https://pypi.org/project/langfuse-haystack)
4
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/langfuse-haystack.svg)](https://pypi.org/project/langfuse-haystack)
5
+
6
+ langfuse-haystack integrates tracing capabilities into [Haystack](https://github.com/deepset-ai/haystack) (2.x) pipelines using [Langfuse](https://langfuse.com/). This package enhances the visibility of pipeline runs by capturing comprehensive details of the execution traces, including API calls, context data, prompts, and more. Whether you're monitoring model performance, pinpointing areas for improvement, or creating datasets for fine-tuning and testing from your pipeline executions, langfuse-haystack is the right tool for you.
7
+ ## Features
8
+
9
+ - Easy integration with Haystack pipelines
10
+ - Capture the full context of the execution
11
+ - Track model usage and cost
12
+ - Collect user feedback
13
+ - Identify low-quality outputs
14
+ - Build fine-tuning and testing datasets
15
+
16
+ ## Installation
17
+
18
+ To install langfuse-haystack, run the following command:
19
+
20
+ ```sh
21
+ pip install langfuse-haystack
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ To enable tracing in your Haystack pipeline, add the `LangfuseConnector` to your pipeline.
27
+ You also need to set the `LANGFUSE_SECRET_KEY` and `LANGFUSE_PUBLIC_KEY` environment variables in order to connect to Langfuse account.
28
+ You can get these keys by signing up for an account on the Langfuse website.
29
+
30
+ Here's an example:
31
+
32
+ ```python
33
+ import os
34
+
35
+ os.environ["LANGFUSE_HOST"] = "https://cloud.langfuse.com"
36
+ os.environ["TOKENIZERS_PARALLELISM"] = "false"
37
+ os.environ["HAYSTACK_CONTENT_TRACING_ENABLED"] = "true"
38
+
39
+ from haystack.components.builders import DynamicChatPromptBuilder
40
+ from haystack.components.generators.chat import OpenAIChatGenerator
41
+ from haystack.dataclasses import ChatMessage
42
+ from haystack import Pipeline
43
+
44
+ from haystack_integrations.components.connectors.langfuse import LangfuseConnector
45
+
46
+ if __name__ == "__main__":
47
+ pipe = Pipeline()
48
+ pipe.add_component("tracer", LangfuseConnector("Chat example"))
49
+ pipe.add_component("prompt_builder", DynamicChatPromptBuilder())
50
+ pipe.add_component("llm", OpenAIChatGenerator(model="gpt-3.5-turbo"))
51
+
52
+ pipe.connect("prompt_builder.prompt", "llm.messages")
53
+
54
+ messages = [
55
+ ChatMessage.from_system("Always respond in German even if some input data is in other languages."),
56
+ ChatMessage.from_user("Tell me about {{location}}"),
57
+ ]
58
+
59
+ response = pipe.run(
60
+ data={"prompt_builder": {"template_variables": {"location": "Berlin"}, "prompt_source": messages}}
61
+ )
62
+ print(response["llm"]["replies"][0])
63
+ print(response["tracer"]["trace_url"])
64
+ ```
65
+
66
+ In this example, we add the `LangfuseConnector` to the pipeline with the name "tracer". Each run of the pipeline produces one trace viewable on the Langfuse website with a specific URL. The trace captures the entire execution context, including the prompts, completions, and metadata.
67
+
68
+ ## Trace Visualization
69
+
70
+ Langfuse provides a user-friendly interface to visualize and analyze the traces generated by your Haystack pipeline. Login into your Langfuse account and navigate to the trace URL to view the trace details.
71
+
72
+ ## Contributing
73
+
74
+ `hatch` is the best way to interact with this project. To install it, run:
75
+ ```sh
76
+ pip install hatch
77
+ ```
78
+
79
+ With `hatch` installed, run all the tests:
80
+ ```
81
+ hatch run test
82
+ ```
83
+
84
+ Run the linters `ruff` and `mypy`:
85
+ ```
86
+ hatch run lint:all
87
+ ```
88
+
89
+ ## License
90
+
91
+ `langfuse-haystack` is distributed under the terms of the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) license.
@@ -1,19 +1,16 @@
1
1
  import os
2
2
 
3
- os.environ["LANGFUSE_HOST"] = "https://cloud.langfuse.com"
4
3
  os.environ["TOKENIZERS_PARALLELISM"] = "false"
5
4
  os.environ["HAYSTACK_CONTENT_TRACING_ENABLED"] = "true"
6
5
 
7
6
  from datasets import load_dataset
8
-
9
- from haystack.document_stores.in_memory import InMemoryDocumentStore
10
7
  from haystack import Document, Pipeline
8
+ from haystack.components.builders import PromptBuilder
11
9
  from haystack.components.embedders import SentenceTransformersDocumentEmbedder, SentenceTransformersTextEmbedder
12
- from haystack.components.retrievers import InMemoryEmbeddingRetriever
13
10
  from haystack.components.generators import OpenAIGenerator
14
- from haystack.components.builders import PromptBuilder
15
-
16
- from haystack_integrations.components.others.langfuse import LangfuseComponent
11
+ from haystack.components.retrievers import InMemoryEmbeddingRetriever
12
+ from haystack.document_stores.in_memory import InMemoryDocumentStore
13
+ from haystack_integrations.components.connectors.langfuse import LangfuseConnector
17
14
 
18
15
 
19
16
  def get_pipeline(document_store: InMemoryDocumentStore):
@@ -35,7 +32,7 @@ def get_pipeline(document_store: InMemoryDocumentStore):
35
32
 
36
33
  basic_rag_pipeline = Pipeline()
37
34
  # Add components to your pipeline
38
- basic_rag_pipeline.add_component("tracer", LangfuseComponent("Basic RAG Pipeline"))
35
+ basic_rag_pipeline.add_component("tracer", LangfuseConnector("Basic RAG Pipeline"))
39
36
  basic_rag_pipeline.add_component(
40
37
  "text_embedder", SentenceTransformersTextEmbedder(model="sentence-transformers/all-MiniLM-L6-v2")
41
38
  )
@@ -65,3 +62,4 @@ if __name__ == "__main__":
65
62
  response = pipeline.run({"text_embedder": {"text": question}, "prompt_builder": {"question": question}})
66
63
 
67
64
  print(response["llm"]["replies"][0])
65
+ print(response["tracer"]["trace_url"])
@@ -1,22 +1,17 @@
1
1
  import os
2
2
 
3
- os.environ["LANGFUSE_HOST"] = "https://cloud.langfuse.com"
4
- os.environ["TOKENIZERS_PARALLELISM"] = "false"
5
3
  os.environ["HAYSTACK_CONTENT_TRACING_ENABLED"] = "true"
6
4
 
5
+ from haystack import Pipeline
7
6
  from haystack.components.builders import DynamicChatPromptBuilder
8
7
  from haystack.components.generators.chat import OpenAIChatGenerator
9
8
  from haystack.dataclasses import ChatMessage
10
- from haystack import Pipeline
11
- from haystack.utils import Secret
12
-
13
- from haystack_integrations.components.others.langfuse import LangfuseComponent
14
-
9
+ from haystack_integrations.components.connectors.langfuse import LangfuseConnector
15
10
 
16
11
  if __name__ == "__main__":
17
12
 
18
13
  pipe = Pipeline()
19
- pipe.add_component("tracer", LangfuseComponent("Chat example"))
14
+ pipe.add_component("tracer", LangfuseConnector("Chat example"))
20
15
  pipe.add_component("prompt_builder", DynamicChatPromptBuilder())
21
16
  pipe.add_component("llm", OpenAIChatGenerator(model="gpt-3.5-turbo"))
22
17
 
@@ -31,3 +26,4 @@ if __name__ == "__main__":
31
26
  data={"prompt_builder": {"template_variables": {"location": "Berlin"}, "prompt_source": messages}}
32
27
  )
33
28
  print(response["llm"]["replies"][0])
29
+ print(response["tracer"]["trace_url"])
@@ -0,0 +1,30 @@
1
+ loaders:
2
+ - type: haystack_pydoc_tools.loaders.CustomPythonLoader
3
+ search_path: [../src]
4
+ modules: [
5
+ "haystack_integrations.components.connectors.langfuse.langfuse_connector",
6
+ "haystack_integrations.tracing.langfuse.tracer",
7
+ ]
8
+ ignore_when_discovered: ["__init__"]
9
+ processors:
10
+ - type: filter
11
+ expression:
12
+ documented_only: true
13
+ do_not_filter_modules: false
14
+ skip_empty_modules: true
15
+ - type: smart
16
+ - type: crossref
17
+ renderer:
18
+ type: haystack_pydoc_tools.renderers.ReadmePreviewRenderer
19
+ excerpt: Langfuse integration for Haystack
20
+ category_slug: integrations-api
21
+ title: langfuse
22
+ slug: integrations-langfuse
23
+ order: 135
24
+ markdown:
25
+ descriptive_class_title: false
26
+ classdef_code_block: false
27
+ descriptive_module_title: true
28
+ add_method_class_prefix: true
29
+ add_member_class_prefix: false
30
+ filename: _readme_langfuse.md
@@ -1,5 +1,5 @@
1
1
  [build-system]
2
- requires = ["hatchling"]
2
+ requires = ["hatchling", "hatch-vcs"]
3
3
  build-backend = "hatchling.build"
4
4
 
5
5
  [project]
@@ -38,10 +38,8 @@ Source = "https://github.com/deepset-ai/haystack-core-integrations/tree/main/int
38
38
  packages = ["src/haystack_integrations"]
39
39
 
40
40
  [tool.hatch.version]
41
- # Remove the following line and uncomment the others to enable git versioning
42
- path = "src/haystack_integrations/components/others/langfuse/__about__.py"
43
- # source = "vcs"
44
- # tag-pattern = 'integrations\/langfuse-v(?P<version>.*)'
41
+ source = "vcs"
42
+ tag-pattern = 'integrations\/langfuse-v(?P<version>.*)'
45
43
 
46
44
 
47
45
  [tool.hatch.version.raw-options]
@@ -52,6 +50,7 @@ git_describe_command = 'git describe --tags --match="integrations/langfuse-v[0-9
52
50
  dependencies = [
53
51
  "coverage[toml]>=6.5",
54
52
  "pytest",
53
+ "haystack-pydoc-tools",
55
54
  ]
56
55
  [tool.hatch.envs.default.scripts]
57
56
  test = "pytest {args:tests}"
@@ -0,0 +1,6 @@
1
+ # SPDX-FileCopyrightText: 2023-present deepset GmbH <info@deepset.ai>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+ from .langfuse_connector import LangfuseConnector
5
+
6
+ __all__ = ["LangfuseConnector"]
@@ -0,0 +1,82 @@
1
+ from haystack import component, tracing
2
+ from haystack_integrations.tracing.langfuse import LangfuseTracer
3
+
4
+ from langfuse import Langfuse
5
+
6
+
7
+ @component
8
+ class LangfuseConnector:
9
+ """
10
+ LangfuseConnector connects Haystack LLM framework with Langfuse in order to enable the tracing of operations
11
+ and data flow within various components of a pipeline.
12
+
13
+ Simply add this component to your pipeline, but *do not* connect it to any other component. The LangfuseConnector
14
+ will automatically trace the operations and data flow within the pipeline.
15
+
16
+ Note that you need to set the `LANGFUSE_SECRET_KEY` and `LANGFUSE_PUBLIC_KEY` environment variables in order
17
+ to use this component. The `LANGFUSE_SECRET_KEY` and `LANGFUSE_PUBLIC_KEY` are the secret and public keys provided
18
+ by Langfuse. You can get these keys by signing up for an account on the Langfuse website.
19
+
20
+ In addition, you need to set the `HAYSTACK_CONTENT_TRACING_ENABLED` environment variable to `true` in order to
21
+ enable Haystack tracing in your pipeline.
22
+
23
+ Here is an example of how to use it:
24
+
25
+ ```python
26
+ import os
27
+
28
+ os.environ["HAYSTACK_CONTENT_TRACING_ENABLED"] = "true"
29
+
30
+ from haystack import Pipeline
31
+ from haystack.components.builders import DynamicChatPromptBuilder
32
+ from haystack.components.generators.chat import OpenAIChatGenerator
33
+ from haystack.dataclasses import ChatMessage
34
+ from haystack_integrations.components.connectors.langfuse import LangfuseConnector
35
+
36
+ if __name__ == "__main__":
37
+
38
+ pipe = Pipeline()
39
+ pipe.add_component("tracer", LangfuseConnector("Chat example"))
40
+ pipe.add_component("prompt_builder", DynamicChatPromptBuilder())
41
+ pipe.add_component("llm", OpenAIChatGenerator(model="gpt-3.5-turbo"))
42
+
43
+ pipe.connect("prompt_builder.prompt", "llm.messages")
44
+
45
+ messages = [
46
+ ChatMessage.from_system("Always respond in German even if some input data is in other languages."),
47
+ ChatMessage.from_user("Tell me about {{location}}"),
48
+ ]
49
+
50
+ response = pipe.run(
51
+ data={"prompt_builder": {"template_variables": {"location": "Berlin"}, "prompt_source": messages}}
52
+ )
53
+ print(response["llm"]["replies"][0])
54
+ print(response["tracer"]["trace_url"])
55
+ ```
56
+
57
+ """
58
+
59
+ def __init__(self, name: str, public: bool = False):
60
+ """
61
+ Initialize the LangfuseConnector component.
62
+
63
+ :param name: The name of the pipeline or component. This name will be used to identify the tracing run on the
64
+ Langfuse dashboard.
65
+ :param public: Whether the tracing data should be public or private. If set to `True`, the tracing data will be
66
+ publicly accessible to anyone with the tracing URL. If set to `False`, the tracing data will be private and
67
+ only accessible to the Langfuse account owner. The default is `False`.
68
+ """
69
+ self.name = name
70
+ self.tracer = LangfuseTracer(tracer=Langfuse(), name=name, public=public)
71
+ tracing.enable_tracing(self.tracer)
72
+
73
+ @component.output_types(name=str, trace_url=str)
74
+ def run(self):
75
+ """
76
+ Runs the LangfuseConnector component.
77
+
78
+ :returns: A dictionary with the following keys:
79
+ - `name`: The name of the tracing component.
80
+ - `trace_url`: The URL to the tracing data.
81
+ """
82
+ return {"name": self.name, "trace_url": self.tracer.get_trace_url()}
@@ -1,6 +1,7 @@
1
1
  import contextlib
2
2
  from typing import Any, Dict, Iterator, Optional, Union
3
3
 
4
+ from haystack.dataclasses import ChatMessage
4
5
  from haystack.tracing import Span, Tracer, tracer
5
6
  from haystack.tracing import utils as tracing_utils
6
7
 
@@ -11,7 +12,7 @@ class LangfuseSpan(Span):
11
12
  def __init__(self, span: "Union[langfuse.client.StatefulSpanClient, langfuse.client.StatefulTraceClient]") -> None:
12
13
  self._span = span
13
14
  # locally cache tags
14
- self._data = {}
15
+ self._data: Dict[str, Any] = {}
15
16
 
16
17
  def set_tag(self, key: str, value: Any) -> None:
17
18
  coerced_value = tracing_utils.coerce_tag_value(value)
@@ -21,16 +22,18 @@ class LangfuseSpan(Span):
21
22
  def set_content_tag(self, key: str, value: Any) -> None:
22
23
  if not tracer.is_content_tracing_enabled:
23
24
  return
24
-
25
25
  if key.endswith(".input"):
26
26
  if "messages" in value:
27
- messages = [m.to_openai_format() for m in value["messages"]]
27
+ messages = [self.to_openai_format(m) for m in value["messages"]]
28
28
  self._span.update(input=messages)
29
29
  else:
30
30
  self._span.update(input=value)
31
31
  elif key.endswith(".output"):
32
32
  if "replies" in value:
33
- replies = [m.to_openai_format() for m in value["replies"]]
33
+ if all(isinstance(r, ChatMessage) for r in value["replies"]):
34
+ replies = [self.to_openai_format(m) for m in value["replies"]]
35
+ else:
36
+ replies = value["replies"]
34
37
  self._span.update(output=replies)
35
38
  else:
36
39
  self._span.update(output=value)
@@ -43,12 +46,23 @@ class LangfuseSpan(Span):
43
46
  def get_correlation_data_for_logs(self) -> Dict[str, Any]:
44
47
  return {}
45
48
 
49
+ def to_openai_format(self, m: ChatMessage) -> Dict[str, Any]:
50
+ """
51
+ Remove after haystack 2.0.1 has been released and use the `to_openai_format` method from the ChatMessage class
52
+ """
53
+ msg = {"role": m.role.value, "content": m.content}
54
+ if m.name:
55
+ msg["name"] = m.name
56
+
57
+ return msg
58
+
46
59
 
47
60
  class LangfuseTracer(Tracer):
48
- def __init__(self, tracer: "langfuse.Langfuse", name: str = "Haystack") -> None:
61
+ def __init__(self, tracer: "langfuse.Langfuse", name: str = "Haystack", public: bool = False) -> None:
49
62
  self._tracer = tracer
50
63
  self._context: list[LangfuseSpan] = []
51
64
  self._name = name
65
+ self._public = public
52
66
 
53
67
  @contextlib.contextmanager
54
68
  def trace(self, operation_name: str, tags: Optional[Dict[str, Any]] = None) -> Iterator[Span]:
@@ -78,6 +92,13 @@ class LangfuseTracer(Tracer):
78
92
  meta = replies[0].meta
79
93
  span._span.update(usage=meta.get("usage"), model=meta.get("model"))
80
94
 
95
+ pipeline_input = tags.get("haystack.pipeline.input_data", None)
96
+ if pipeline_input:
97
+ span._span.update(input=tags["haystack.pipeline.input_data"])
98
+ pipeline_output = tags.get("haystack.pipeline.output_data", None)
99
+ if pipeline_output:
100
+ span._span.update(output=tags["haystack.pipeline.output_data"])
101
+
81
102
  span.raw_span().end()
82
103
  self._context.pop()
83
104
  self._tracer.flush()
@@ -85,5 +106,8 @@ class LangfuseTracer(Tracer):
85
106
  def current_span(self) -> Span:
86
107
  if not self._context:
87
108
  # The root span has to be a trace
88
- self._context.append(LangfuseSpan(self._tracer.trace(name=self._name)))
109
+ self._context.append(LangfuseSpan(self._tracer.trace(name=self._name, public=self._public)))
89
110
  return self._context[-1]
111
+
112
+ def get_trace_url(self) -> str:
113
+ return self._tracer.get_trace_url()
@@ -0,0 +1,57 @@
1
+ import os
2
+
3
+ # don't remove (or move) this env var setting from here, it's needed to turn tracing on
4
+ os.environ["HAYSTACK_CONTENT_TRACING_ENABLED"] = "true"
5
+
6
+ from urllib.parse import urlparse
7
+
8
+ import pytest
9
+ import requests
10
+
11
+ from haystack import Pipeline
12
+ from haystack.components.builders import DynamicChatPromptBuilder
13
+ from haystack.components.generators.chat import OpenAIChatGenerator
14
+ from haystack.dataclasses import ChatMessage
15
+ from requests.auth import HTTPBasicAuth
16
+
17
+ from haystack_integrations.components.connectors.langfuse import LangfuseConnector
18
+
19
+
20
+ @pytest.mark.integration
21
+ @pytest.mark.skipif(
22
+ not os.environ.get("LANGFUSE_SECRET_KEY", None) and not os.environ.get("LANGFUSE_PUBLIC_KEY", None),
23
+ reason="Export an env var called LANGFUSE_SECRET_KEY and LANGFUSE_PUBLIC_KEY containing Langfuse credentials.",
24
+ )
25
+ def test_tracing_integration():
26
+
27
+ pipe = Pipeline()
28
+ pipe.add_component("tracer", LangfuseConnector(name="Chat example", public=True)) # public so anyone can verify run
29
+ pipe.add_component("prompt_builder", DynamicChatPromptBuilder())
30
+ pipe.add_component("llm", OpenAIChatGenerator(model="gpt-3.5-turbo"))
31
+
32
+ pipe.connect("prompt_builder.prompt", "llm.messages")
33
+
34
+ messages = [
35
+ ChatMessage.from_system("Always respond in German even if some input data is in other languages."),
36
+ ChatMessage.from_user("Tell me about {{location}}"),
37
+ ]
38
+
39
+ response = pipe.run(
40
+ data={"prompt_builder": {"template_variables": {"location": "Berlin"}, "prompt_source": messages}}
41
+ )
42
+ assert "Berlin" in response["llm"]["replies"][0].content
43
+ assert response["tracer"]["trace_url"]
44
+ url = "https://cloud.langfuse.com/api/public/traces/"
45
+ trace_url = response["tracer"]["trace_url"]
46
+ parsed_url = urlparse(trace_url)
47
+ # trace id is the last part of the path (after the last '/')
48
+ uuid = os.path.basename(parsed_url.path)
49
+ try:
50
+ # GET request with Basic Authentication on the Langfuse API
51
+ response = requests.get(
52
+ url + uuid, auth=HTTPBasicAuth(os.environ.get("LANGFUSE_PUBLIC_KEY"), os.environ.get("LANGFUSE_SECRET_KEY"))
53
+ )
54
+
55
+ assert response.status_code == 200, f"Failed to retrieve data from Langfuse API: {response.status_code}"
56
+ except requests.exceptions.RequestException as e:
57
+ assert False, f"Failed to retrieve data from Langfuse API: {e}"
@@ -1,45 +0,0 @@
1
- Metadata-Version: 2.3
2
- Name: langfuse-haystack
3
- Version: 0.0.3
4
- Project-URL: Documentation, https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/langfuse#readme
5
- Project-URL: Issues, https://github.com/deepset-ai/haystack-core-integrations/issues
6
- Project-URL: Source, https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/langfuse
7
- Author-email: deepset GmbH <info@deepset.ai>
8
- License-Expression: Apache-2.0
9
- License-File: LICENSE.txt
10
- Classifier: Development Status :: 4 - Beta
11
- Classifier: Programming Language :: Python
12
- Classifier: Programming Language :: Python :: 3.8
13
- Classifier: Programming Language :: Python :: 3.9
14
- Classifier: Programming Language :: Python :: 3.10
15
- Classifier: Programming Language :: Python :: 3.11
16
- Classifier: Programming Language :: Python :: 3.12
17
- Classifier: Programming Language :: Python :: Implementation :: CPython
18
- Classifier: Programming Language :: Python :: Implementation :: PyPy
19
- Requires-Python: >=3.8
20
- Requires-Dist: haystack-ai
21
- Requires-Dist: langfuse
22
- Description-Content-Type: text/markdown
23
-
24
- # langfuse
25
-
26
- [![PyPI - Version](https://img.shields.io/pypi/v/langfuse-haystack.svg)](https://pypi.org/project/langfuse-haystack)
27
- [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/langfuse-haystack.svg)](https://pypi.org/project/langfuse-haystack)
28
-
29
- -----
30
-
31
- **Table of Contents**
32
-
33
- - [langfuse](#langfuse)
34
- - [Installation](#installation)
35
- - [License](#license)
36
-
37
- ## Installation
38
-
39
- ```console
40
- pip install langfuse-haystack
41
- ```
42
-
43
- ## License
44
-
45
- `langfuse` is distributed under the terms of the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) license.
@@ -1,22 +0,0 @@
1
- # langfuse
2
-
3
- [![PyPI - Version](https://img.shields.io/pypi/v/langfuse-haystack.svg)](https://pypi.org/project/langfuse-haystack)
4
- [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/langfuse-haystack.svg)](https://pypi.org/project/langfuse-haystack)
5
-
6
- -----
7
-
8
- **Table of Contents**
9
-
10
- - [langfuse](#langfuse)
11
- - [Installation](#installation)
12
- - [License](#license)
13
-
14
- ## Installation
15
-
16
- ```console
17
- pip install langfuse-haystack
18
- ```
19
-
20
- ## License
21
-
22
- `langfuse` is distributed under the terms of the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) license.
@@ -1,3 +0,0 @@
1
- from .component import LangfuseComponent
2
-
3
- __all__ = ["LangfuseComponent"]
@@ -1,16 +0,0 @@
1
- from haystack import tracing, component
2
-
3
- from haystack_integrations.tracing.langfuse import LangfuseTracer
4
-
5
- from langfuse import Langfuse
6
-
7
-
8
- @component
9
- class LangfuseComponent:
10
- def __init__(self, name: str):
11
- self.name = name
12
- tracing.enable_tracing(LangfuseTracer(Langfuse(), name))
13
-
14
- @component.output_types(name=str)
15
- def run(self):
16
- return {"name": self.name}