chore: use ruff for formatting Python snippets in docs (#12245)

This commit is contained in:
Stefano Fiorucci
2026-08-05 14:24:09 +02:00
committed by GitHub
parent ae02b58367
commit 8eb05c2077
261 changed files with 1535 additions and 1129 deletions
+2 -11
View File
@@ -17,24 +17,15 @@ repos:
args: [--markdown-linebreak-ext=md, --markdown-linebreak-ext=mdx]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.2
rev: v0.16.0
hooks:
- id: ruff-check
args: [ --fix ]
- id: ruff-format
types_or: [python, pyi, jupyter, mdx]
- repo: local
hooks:
- id: ruff-format-docs
name: ruff-format-docs
language: python
entry: python scripts/ruff_format_docs.py --line-length=88
files: ^docs-website/.*\.mdx$
types: [text]
additional_dependencies:
- ruff
- add-trailing-comma
- id: release-note-backticks
name: release-note-backticks
language: python
@@ -99,7 +99,9 @@ After adding `FileContent` to a `ChatMessage`, use the `file` and `files` proper
from haystack.dataclasses import ChatMessage, FileContent
file_content = FileContent.from_file_path("data/invoice.pdf")
message = ChatMessage.from_user(content_parts=[file_content, "Extract the invoice total."])
message = ChatMessage.from_user(
content_parts=[file_content, "Extract the invoice total."]
)
print(message.file)
print(message.files)
@@ -211,14 +211,20 @@ If your pipeline seems stuck or runs longer than expected, here are common cause
```python
# Problematic: user input goes directly to a component inside the loop
result = pipe.run({
"generator": {"prompt": query}, # This input persists and may retrigger the loop
})
result = pipe.run(
{
"generator": {
"prompt": query
}, # This input persists and may retrigger the loop
}
)
# Better: use an entry-point component outside the loop
result = pipe.run({
"prompt_builder": {"query": query}, # Entry point feeds into the loop once
})
result = pipe.run(
{
"prompt_builder": {"query": query}, # Entry point feeds into the loop once
}
)
```
See [Greedy vs. Lazy Variadic Sockets](#greedy-vs-lazy-variadic-sockets-in-loops) for details on how inputs are consumed.
@@ -40,36 +40,40 @@ If your tracing backend isn't supported out of the box, you can connect it to Ha
from haystack.tracing import utils as tracing_utils
import opentelemetry.trace
class OpenTelemetrySpan(Span):
def __init__(self, span: opentelemetry.trace.Span) -> None:
self._span = span
def set_tag(self, key: str, value: Any) -> None:
# Tracing backends usually don't support any tag value
# `coerce_tag_value` forces the value to either be a Python
# primitive (int, float, boolean, str) or tries to dump it as string.
coerced_value = tracing_utils.coerce_tag_value(value)
self._span.set_attribute(key, coerced_value)
class OpenTelemetrySpan(Span):
def __init__(self, span: opentelemetry.trace.Span) -> None:
self._span = span
def set_tag(self, key: str, value: Any) -> None:
# Tracing backends usually don't support any tag value
# `coerce_tag_value` forces the value to either be a Python
# primitive (int, float, boolean, str) or tries to dump it as string.
coerced_value = tracing_utils.coerce_tag_value(value)
self._span.set_attribute(key, coerced_value)
class OpenTelemetryTracer(Tracer):
def __init__(self, tracer: opentelemetry.trace.Tracer) -> None:
self._tracer = tracer
def __init__(self, tracer: opentelemetry.trace.Tracer) -> None:
self._tracer = tracer
@contextlib.contextmanager
def trace(self, operation_name: str, tags: Optional[Dict[str, Any]] = None) -> Iterator[Span]:
with self._tracer.start_as_current_span(operation_name) as span:
span = OpenTelemetrySpan(span)
if tags:
span.set_tags(tags)
@contextlib.contextmanager
def trace(
self, operation_name: str, tags: Optional[Dict[str, Any]] = None
) -> Iterator[Span]:
with self._tracer.start_as_current_span(operation_name) as span:
span = OpenTelemetrySpan(span)
if tags:
span.set_tags(tags)
yield span
yield span
def current_span(self) -> Optional[Span]:
current_span = trace.get_current_span()
if isinstance(current_span, NonRecordingSpan):
return None
def current_span(self) -> Optional[Span]:
current_span = trace.get_current_span()
if isinstance(current_span, NonRecordingSpan):
return None
return OpenTelemetrySpan(current_span)
return OpenTelemetrySpan(current_span)
```
2. Tell Haystack to use your custom tracer:
@@ -132,12 +132,12 @@ Use [Jaeger](https://www.jaegertracing.io/docs/1.6/getting-started/) as a lightw
from haystack_integrations.tracing.opentelemetry import OpenTelemetryTracer
# Service name is required for most backends
resource = Resource(attributes={
ResourceAttributes.SERVICE_NAME: "haystack"
})
resource = Resource(attributes={ResourceAttributes.SERVICE_NAME: "haystack"})
tracer_provider = TracerProvider(resource=resource)
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces"))
processor = BatchSpanProcessor(
OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces")
)
tracer_provider.add_span_processor(processor)
trace.set_tracer_provider(tracer_provider)
@@ -57,10 +57,12 @@ document_store = ArcadeDBDocumentStore(
recreate_type=True,
)
document_store.write_documents([
Document(content="This is first", embedding=[0.0] * 768),
Document(content="This is second", embedding=[0.1, 0.2, 0.3] + [0.0] * 765),
])
document_store.write_documents(
[
Document(content="This is first", embedding=[0.0] * 768),
Document(content="This is second", embedding=[0.1, 0.2, 0.3] + [0.0] * 765),
]
)
print(document_store.count_documents())
```
@@ -102,7 +102,9 @@ store.add_memories(
# Write transient session context to the session cache.
store.add_memories(
messages=[ChatMessage.from_user("Alice is currently debugging a vector store issue.")],
messages=[
ChatMessage.from_user("Alice is currently debugging a vector store issue.")
],
session_id="alice_session_1",
)
@@ -79,7 +79,9 @@ Mem0 supports narrowing the scope of reads and writes with `user_id`, `run_id`,
```python
store.add_memories(
messages=[ChatMessage.from_user("Alice is working on a documentation search system.")],
messages=[
ChatMessage.from_user("Alice is working on a documentation search system.")
],
user_id="alice",
run_id="docs-assistant-session-1",
infer=True,
@@ -44,7 +44,6 @@ Optionally, you can provide metadata using the `meta` parameter. This can be a s
This component is primarily meant to be used in pipelines.
```python
from haystack.components.converters.image import ImageFileToDocument
converter = ImageFileToDocument()
@@ -42,7 +42,6 @@ This component is often used in query pipelines just before a `ChatPromptBuilder
### On its own
```python
from haystack.components.converters.image import ImageFileToImageContent
converter = ImageFileToImageContent(detail="high", size=(800, 600))
@@ -101,7 +101,6 @@ assert result["output_adapter"]["output"] == "Haystack"
You can also define your own custom filters, which can then be added to an `OutputAdapter` instance through its init method and used in templates. Here’s an example of this approach:
```python
from haystack import Pipeline, component, Document
from haystack.components.converters import OutputAdapter
@@ -78,7 +78,9 @@ document_store = InMemoryDocumentStore()
indexing_pipeline = Pipeline()
indexing_pipeline.add_component("converter", TextFileToDocument())
indexing_pipeline.add_component("embedder", EdenAIDocumentEmbedder(model="openai/text-embedding-3-small"))
indexing_pipeline.add_component(
"embedder", EdenAIDocumentEmbedder(model="openai/text-embedding-3-small")
)
indexing_pipeline.add_component("writer", DocumentWriter(document_store=document_store))
indexing_pipeline.connect("converter", "embedder")
@@ -93,8 +93,12 @@ documents_with_embeddings = document_embedder.run(documents)["documents"]
document_store.write_documents(documents_with_embeddings)
query_pipeline = Pipeline()
query_pipeline.add_component("text_embedder", EdenAITextEmbedder(model="openai/text-embedding-3-small"))
query_pipeline.add_component("retriever", InMemoryEmbeddingRetriever(document_store=document_store))
query_pipeline.add_component(
"text_embedder", EdenAITextEmbedder(model="openai/text-embedding-3-small")
)
query_pipeline.add_component(
"retriever", InMemoryEmbeddingRetriever(document_store=document_store)
)
query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding")
result = query_pipeline.run({"text_embedder": {"text": "Who lives in Berlin?"}})
@@ -55,7 +55,6 @@ Remember to set the`MISTRAL_API_KEY` as an environment variable first or pass it
Here is how you can use the component on its own:
```python
from haystack_integrations.components.embedders.mistral.text_embedder import (
MistralTextEmbedder,
)
@@ -111,18 +111,27 @@ from haystack.dataclasses import ChatMessage
generation_kwargs = {"extra_headers": {"anthropic-beta": "prompt-caching-2024-07-31"}}
claude_llm = AnthropicChatGenerator(
api_key=Secret.from_env_var("ANTHROPIC_API_KEY"), generation_kwargs=generation_kwargs
api_key=Secret.from_env_var("ANTHROPIC_API_KEY"),
generation_kwargs=generation_kwargs,
)
system_message = ChatMessage.from_system("Replace with some long text documents, code or instructions")
system_message = ChatMessage.from_system(
"Replace with some long text documents, code or instructions"
)
system_message.meta["cache_control"] = {"type": "ephemeral"}
messages = [system_message, ChatMessage.from_user("A query about the long text for example")]
messages = [
system_message,
ChatMessage.from_user("A query about the long text for example"),
]
result = claude_llm.run(messages)
# and now invoke again with
messages = [system_message, ChatMessage.from_user("Another query about the long text etc")]
messages = [
system_message,
ChatMessage.from_user("Another query about the long text etc"),
]
result = claude_llm.run(messages)
# and so on, either invoking component directly or in the pipeline
@@ -80,7 +80,9 @@ You can stream output as it's generated. Pass a callback to `streaming_callback`
```python
from haystack.components.generators.utils import print_streaming_chunk
from haystack.dataclasses import ChatMessage
from haystack_integrations.components.generators.anthropic import AnthropicFoundryChatGenerator
from haystack_integrations.components.generators.anthropic import (
AnthropicFoundryChatGenerator,
)
generator = AnthropicFoundryChatGenerator(
resource="my-resource",
@@ -102,13 +104,17 @@ See [Streaming Support](guides-to-generators/choosing-the-right-generator.mdx#st
```python
import asyncio
from haystack.dataclasses import ChatMessage
from haystack_integrations.components.generators.anthropic import AnthropicFoundryChatGenerator
from haystack_integrations.components.generators.anthropic import (
AnthropicFoundryChatGenerator,
)
async def main():
generator = AnthropicFoundryChatGenerator(resource="my-resource")
result = await generator.run_async([ChatMessage.from_user("Hello!")])
print(result["replies"][0].text)
asyncio.run(main())
```
@@ -125,7 +131,9 @@ pip install anthropic-haystack
```python
from haystack.dataclasses import ChatMessage
from haystack.utils import Secret
from haystack_integrations.components.generators.anthropic import AnthropicFoundryChatGenerator
from haystack_integrations.components.generators.anthropic import (
AnthropicFoundryChatGenerator,
)
generator = AnthropicFoundryChatGenerator(
model="claude-sonnet-4-5",
@@ -143,7 +151,9 @@ print(response)
from haystack import Pipeline
from haystack.components.builders import ChatPromptBuilder
from haystack.dataclasses import ChatMessage
from haystack_integrations.components.generators.anthropic import AnthropicFoundryChatGenerator
from haystack_integrations.components.generators.anthropic import (
AnthropicFoundryChatGenerator,
)
pipe = Pipeline()
pipe.add_component("prompt_builder", ChatPromptBuilder())
@@ -118,7 +118,10 @@ question = "What is Eden AI?"
result = rag_pipeline.run(
{
"fetcher": {"urls": ["https://www.edenai.co/"]},
"prompt_builder": {"template_variables": {"query": question}, "template": messages},
"prompt_builder": {
"template_variables": {"query": question},
"template": messages,
},
},
)
@@ -43,7 +43,6 @@ pip install sentence-transformers-haystack
```
```python
from haystack import Document
from haystack_integrations.components.embedders.sentence_transformers import (
SentenceTransformersDocumentEmbedder,
@@ -112,7 +112,11 @@ result = splitter.run(
)
for chunk in result["documents"]:
print(chunk.meta["start_line"], chunk.meta["end_line"], chunk.meta.get("include_classes"))
print(
chunk.meta["start_line"],
chunk.meta["end_line"],
chunk.meta.get("include_classes"),
)
```
### With docstring stripping for RAG
@@ -145,7 +149,9 @@ splitter = PythonCodeSplitter(
max_effective_lines=100,
strip_docstrings=True,
)
result = splitter.run(documents=[Document(content=source, meta={"file_name": "my_module.py"})])
result = splitter.run(
documents=[Document(content=source, meta={"file_name": "my_module.py"})]
)
for chunk in result["documents"]:
print(chunk.content)
print(chunk.meta.get("docstrings"))
@@ -81,7 +81,6 @@ retriever.run(query="How many languages are spoken around the world today?")
The below example shows how to use the `AzureAISearchBM25Retriever` in a RAG pipeline. Set your `OPENAI_API_KEY` as an environment variable and then run the following code:
```python
from haystack_integrations.components.retrievers.azure_ai_search import (
AzureAISearchBM25Retriever,
)
@@ -92,7 +92,6 @@ retriever.run(query="How many languages are spoken around the world today?")
Set your `OPENAI_API_KEY` as an environment variable and then run the following code:
```python
from haystack_integrations.components.retrievers.elasticsearch import (
ElasticsearchBM25Retriever,
)
@@ -74,7 +74,9 @@ from haystack_integrations.document_stores.elasticsearch import (
)
from haystack.document_stores.types import DuplicatePolicy
document_store = ElasticsearchDocumentStore(hosts="http://localhost:9200/", index="my_index")
document_store = ElasticsearchDocumentStore(
hosts="http://localhost:9200/", index="my_index"
)
documents = [
Document(content="There are over 7,000 languages spoken around the world today."),
@@ -74,7 +74,9 @@ from haystack_integrations.document_stores.opensearch import (
)
from haystack.document_stores.types import DuplicatePolicy
document_store = OpenSearchDocumentStore(hosts="http://localhost:9200", index="my_index")
document_store = OpenSearchDocumentStore(
hosts="http://localhost:9200", index="my_index"
)
documents = [
Document(content="There are over 7,000 languages spoken around the world today."),
@@ -63,7 +63,9 @@ pip install psycopg2-binary
A self-contained example using an in-memory SQLite database seeded via `init_script`:
```python
from haystack_integrations.components.retrievers.sqlalchemy import SQLAlchemyTableRetriever
from haystack_integrations.components.retrievers.sqlalchemy import (
SQLAlchemyTableRetriever,
)
retriever = SQLAlchemyTableRetriever(
drivername="sqlite",
@@ -83,7 +85,9 @@ Connecting to a real backend looks the same — swap the driver and pass connect
```python
from haystack.utils import Secret
from haystack_integrations.components.retrievers.sqlalchemy import SQLAlchemyTableRetriever
from haystack_integrations.components.retrievers.sqlalchemy import (
SQLAlchemyTableRetriever,
)
retriever = SQLAlchemyTableRetriever(
drivername="postgresql+psycopg2",
@@ -105,7 +109,9 @@ from haystack.utils import Secret
from haystack.components.builders import ChatPromptBuilder
from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.dataclasses import ChatMessage
from haystack_integrations.components.retrievers.sqlalchemy import SQLAlchemyTableRetriever
from haystack_integrations.components.retrievers.sqlalchemy import (
SQLAlchemyTableRetriever,
)
retriever = SQLAlchemyTableRetriever(
drivername="postgresql+psycopg2",
@@ -83,7 +83,9 @@ To write to the session cache instead of the permanent graph, pass a `session_id
```python
session_writer = CogneeWriter(memory_store=store, session_id="alice_session_1")
session_writer.run(
messages=[ChatMessage.from_user("Alice is currently debugging a vector store issue.")],
messages=[
ChatMessage.from_user("Alice is currently debugging a vector store issue.")
],
user_id="a1b2c3d4-e5f6-7890-abcd-ef1234567890",
)
```
+2 -4
View File
@@ -238,9 +238,7 @@ By default, a tool's return value is converted to a string using a default handl
You can use `outputs_to_string` to customize this behavior using one of two formats:
1. **Single output format**: Use `source`, `handler`, and/or `raw_result` at the root level.
```python
{
"source": "docs", "handler": format_documents, "raw_result": False
}
{"source": "docs", "handler": format_documents, "raw_result": False}
```
- `source`: (Optional) Specifies the key to extract from the tool's output dictionary. If omitted, the entire result is passed to the handler.
- `handler`: (Optional) A function that takes the output (or the extracted source value) and returns the final result.
@@ -252,7 +250,7 @@ You can use `outputs_to_string` to customize this behavior using one of two form
```python
{
"formatted_docs": {"source": "docs", "handler": format_documents},
"summary": {"source": "summary_text", "handler": str.upper}
"summary": {"source": "summary_text", "handler": str.upper},
}
```
Each entry defines a `source` key and can optionally include a `handler`. The individual outputs are processed,
+15
View File
@@ -0,0 +1,15 @@
# Ruff configuration for the docs website.
#
# It applies to the Python code blocks embedded in .mdx pages, and is picked up automatically by both `hatch run fmt`
# and the ruff-format pre-commit hook, so the two always agree on what gets formatted.
extend = "../pyproject.toml"
extension = { "mdx" = "markdown" }
line-length = 88
extend-exclude = ["node_modules", "build", ".docusaurus", "scripts"]
[format]
skip-magic-trailing-comma = false
@@ -138,7 +138,6 @@ new_env_secret = Secret.from_dict(env_secret_dict)
Both types of secrets can be resolved to their actual values using the `resolve_value` method. This method returns the token or the value of the environment variable.
```python
## Resolve the token-based secret
token_value = api_key_secret.resolve_value()
@@ -66,17 +66,22 @@ To use OpenTelemetry as your tracing backend, follow these steps:
from opentelemetry.semconv.resource import ResourceAttributes
# Service name is required for most backends
resource = Resource(attributes={
ResourceAttributes.SERVICE_NAME: "haystack" # Correct constant
})
resource = Resource(
attributes={
ResourceAttributes.SERVICE_NAME: "haystack" # Correct constant
}
)
tracer_provider = TracerProvider(resource=resource)
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces"))
processor = BatchSpanProcessor(
OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces")
)
tracer_provider.add_span_processor(processor)
trace.set_tracer_provider(tracer_provider)
# Tell Haystack to auto-detect the configured tracer
import haystack.tracing
haystack.tracing.auto_enable_tracing()
# Explicitly tell Haystack to use your tracer
@@ -156,36 +161,40 @@ To use your custom tracing backend with Haystack, follow these steps:
from haystack.tracing import utils as tracing_utils
import opentelemetry.trace
class OpenTelemetrySpan(Span):
def __init__(self, span: opentelemetry.trace.Span) -> None:
self._span = span
def set_tag(self, key: str, value: Any) -> None:
# Tracing backends usually don't support any tag value
# `coerce_tag_value` forces the value to either be a Python
# primitive (int, float, boolean, str) or tries to dump it as string.
coerced_value = tracing_utils.coerce_tag_value(value)
self._span.set_attribute(key, coerced_value)
class OpenTelemetrySpan(Span):
def __init__(self, span: opentelemetry.trace.Span) -> None:
self._span = span
def set_tag(self, key: str, value: Any) -> None:
# Tracing backends usually don't support any tag value
# `coerce_tag_value` forces the value to either be a Python
# primitive (int, float, boolean, str) or tries to dump it as string.
coerced_value = tracing_utils.coerce_tag_value(value)
self._span.set_attribute(key, coerced_value)
class OpenTelemetryTracer(Tracer):
def __init__(self, tracer: opentelemetry.trace.Tracer) -> None:
self._tracer = tracer
def __init__(self, tracer: opentelemetry.trace.Tracer) -> None:
self._tracer = tracer
@contextlib.contextmanager
def trace(self, operation_name: str, tags: Optional[Dict[str, Any]] = None) -> Iterator[Span]:
with self._tracer.start_as_current_span(operation_name) as span:
span = OpenTelemetrySpan(span)
if tags:
span.set_tags(tags)
@contextlib.contextmanager
def trace(
self, operation_name: str, tags: Optional[Dict[str, Any]] = None
) -> Iterator[Span]:
with self._tracer.start_as_current_span(operation_name) as span:
span = OpenTelemetrySpan(span)
if tags:
span.set_tags(tags)
yield span
yield span
def current_span(self) -> Optional[Span]:
current_span = trace.get_current_span()
if isinstance(current_span, NonRecordingSpan):
return None
def current_span(self) -> Optional[Span]:
current_span = trace.get_current_span()
if isinstance(current_span, NonRecordingSpan):
return None
return OpenTelemetrySpan(current_span)
return OpenTelemetrySpan(current_span)
```
2. Tell Haystack to use your custom tracer:
@@ -279,12 +288,12 @@ Use [Jaeger](https://www.jaegertracing.io/docs/1.6/getting-started/) as a lightw
from opentelemetry.sdk.trace.export import BatchSpanProcessor
# Service name is required for most backends
resource = Resource(attributes={
ResourceAttributes.SERVICE_NAME: "haystack"
})
resource = Resource(attributes={ResourceAttributes.SERVICE_NAME: "haystack"})
tracer_provider = TracerProvider(resource=resource)
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces"))
processor = BatchSpanProcessor(
OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces")
)
tracer_provider.add_span_processor(processor)
trace.set_tracer_provider(tracer_provider)
```
@@ -39,7 +39,6 @@ Optionally, you can provide metadata using the `meta` parameter. This can be a s
This component is primarily meant to be used in pipelines.
```python
from haystack.components.converters.image import ImageFileToDocument
converter = ImageFileToDocument()
@@ -37,7 +37,6 @@ This component is often used in query pipelines just before a `ChatPromptBuilder
### On its own
```python
from haystack.components.converters.image import ImageFileToImageContent
converter = ImageFileToImageContent(detail="high", size=(800, 600))
@@ -96,7 +96,6 @@ assert result["output_adapter"]["output"] == "Haystack"
You can also define your own custom filters, which can then be added to an `OutputAdapter` instance through its init method and used in templates. Here’s an example of this approach:
```python
from haystack import Pipeline, component, Document
from haystack.components.converters import OutputAdapter
@@ -50,7 +50,6 @@ Remember to set the`MISTRAL_API_KEY` as an environment variable first or pass it
Here is how you can use the component on its own:
```python
from haystack_integrations.components.embedders.mistral.text_embedder import (
MistralTextEmbedder,
)
@@ -78,18 +78,27 @@ from haystack.dataclasses import ChatMessage
generation_kwargs = {"extra_headers": {"anthropic-beta": "prompt-caching-2024-07-31"}}
claude_llm = AnthropicChatGenerator(
api_key=Secret.from_env_var("ANTHROPIC_API_KEY"), generation_kwargs=generation_kwargs
api_key=Secret.from_env_var("ANTHROPIC_API_KEY"),
generation_kwargs=generation_kwargs,
)
system_message = ChatMessage.from_system("Replace with some long text documents, code or instructions")
system_message = ChatMessage.from_system(
"Replace with some long text documents, code or instructions"
)
system_message.meta["cache_control"] = {"type": "ephemeral"}
messages = [system_message, ChatMessage.from_user("A query about the long text for example")]
messages = [
system_message,
ChatMessage.from_user("A query about the long text for example"),
]
result = claude_llm.run(messages)
## and now invoke again with
messages = [system_message, ChatMessage.from_user("Another query about the long text etc")]
messages = [
system_message,
ChatMessage.from_user("Another query about the long text etc"),
]
result = claude_llm.run(messages)
## and so on, either invoking component directly or in the pipeline
@@ -141,7 +141,6 @@ Here are the components that support shared hosted models in Haystack:
Here is an example using OctoAI and [`OpenAIChatGenerator`](../openaichatgenerator.mdx):
```python
from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.utils import Secret
from haystack.dataclasses import ChatMessage
@@ -37,7 +37,9 @@ pip install google-vertex-haystack
Basic usage:
````python
from haystack_integrations.components.generators.google_vertex import VertexAICodeGenerator
from haystack_integrations.components.generators.google_vertex import (
VertexAICodeGenerator,
)
generator = VertexAICodeGenerator()
@@ -45,7 +47,6 @@ result = generator.run(prefix="def to_json(data):")
for answer in result["replies"]:
print(answer)
````
You can also set other parameters like the number of output tokens, temperature, stop sequences, and the number of candidates.
@@ -39,13 +39,14 @@ pip install google-vertex-haystack
Basic usage:
````python
from haystack_integrations.components.generators.google_vertex import VertexAITextGenerator
from haystack_integrations.components.generators.google_vertex import (
VertexAITextGenerator,
)
generator = VertexAITextGenerator()
res = generator.run("Tell me a good interview question for a software engineer.")
print(res["replies"][0])
````
You can also set other parameters like the number of answers generated, temperature to control the randomness, and stop sequences to stop generation. For a full list of possible parameters, see the documentation of [`TextGenerationModel.predict()`](https://cloud.google.com/python/docs/reference/aiplatform/latest/vertexai.language_models.TextGenerationModel#vertexai_language_models_TextGenerationModel_predict).
@@ -76,7 +76,6 @@ retriever.run(query="How many languages are spoken around the world today?")
The below example shows how to use the `AzureAISearchBM25Retriever` in a RAG pipeline. Set your `OPENAI_API_KEY` as an environment variable and then run the following code:
```python
from haystack_integrations.components.retrievers.azure_ai_search import (
AzureAISearchBM25Retriever,
)
@@ -87,7 +87,6 @@ retriever.run(query="How many languages are spoken around the world today?")
Set your `OPENAI_API_KEY` as an environment variable and then run the following code:
```python
from haystack_integrations.components.retrievers.elasticsearch import (
ElasticsearchBM25Retriever,
)
@@ -138,7 +138,6 @@ new_env_secret = Secret.from_dict(env_secret_dict)
Both types of secrets can be resolved to their actual values using the `resolve_value` method. This method returns the token or the value of the environment variable.
```python
## Resolve the token-based secret
token_value = api_key_secret.resolve_value()
@@ -66,17 +66,22 @@ To use OpenTelemetry as your tracing backend, follow these steps:
from opentelemetry.semconv.resource import ResourceAttributes
# Service name is required for most backends
resource = Resource(attributes={
ResourceAttributes.SERVICE_NAME: "haystack" # Correct constant
})
resource = Resource(
attributes={
ResourceAttributes.SERVICE_NAME: "haystack" # Correct constant
}
)
tracer_provider = TracerProvider(resource=resource)
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces"))
processor = BatchSpanProcessor(
OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces")
)
tracer_provider.add_span_processor(processor)
trace.set_tracer_provider(tracer_provider)
# Tell Haystack to auto-detect the configured tracer
import haystack.tracing
haystack.tracing.auto_enable_tracing()
# Explicitly tell Haystack to use your tracer
@@ -156,36 +161,40 @@ To use your custom tracing backend with Haystack, follow these steps:
from haystack.tracing import utils as tracing_utils
import opentelemetry.trace
class OpenTelemetrySpan(Span):
def __init__(self, span: opentelemetry.trace.Span) -> None:
self._span = span
def set_tag(self, key: str, value: Any) -> None:
# Tracing backends usually don't support any tag value
# `coerce_tag_value` forces the value to either be a Python
# primitive (int, float, boolean, str) or tries to dump it as string.
coerced_value = tracing_utils.coerce_tag_value(value)
self._span.set_attribute(key, coerced_value)
class OpenTelemetrySpan(Span):
def __init__(self, span: opentelemetry.trace.Span) -> None:
self._span = span
def set_tag(self, key: str, value: Any) -> None:
# Tracing backends usually don't support any tag value
# `coerce_tag_value` forces the value to either be a Python
# primitive (int, float, boolean, str) or tries to dump it as string.
coerced_value = tracing_utils.coerce_tag_value(value)
self._span.set_attribute(key, coerced_value)
class OpenTelemetryTracer(Tracer):
def __init__(self, tracer: opentelemetry.trace.Tracer) -> None:
self._tracer = tracer
def __init__(self, tracer: opentelemetry.trace.Tracer) -> None:
self._tracer = tracer
@contextlib.contextmanager
def trace(self, operation_name: str, tags: Optional[Dict[str, Any]] = None) -> Iterator[Span]:
with self._tracer.start_as_current_span(operation_name) as span:
span = OpenTelemetrySpan(span)
if tags:
span.set_tags(tags)
@contextlib.contextmanager
def trace(
self, operation_name: str, tags: Optional[Dict[str, Any]] = None
) -> Iterator[Span]:
with self._tracer.start_as_current_span(operation_name) as span:
span = OpenTelemetrySpan(span)
if tags:
span.set_tags(tags)
yield span
yield span
def current_span(self) -> Optional[Span]:
current_span = trace.get_current_span()
if isinstance(current_span, NonRecordingSpan):
return None
def current_span(self) -> Optional[Span]:
current_span = trace.get_current_span()
if isinstance(current_span, NonRecordingSpan):
return None
return OpenTelemetrySpan(current_span)
return OpenTelemetrySpan(current_span)
```
2. Tell Haystack to use your custom tracer:
@@ -279,12 +288,12 @@ Use [Jaeger](https://www.jaegertracing.io/docs/1.6/getting-started/) as a lightw
from opentelemetry.sdk.trace.export import BatchSpanProcessor
# Service name is required for most backends
resource = Resource(attributes={
ResourceAttributes.SERVICE_NAME: "haystack"
})
resource = Resource(attributes={ResourceAttributes.SERVICE_NAME: "haystack"})
tracer_provider = TracerProvider(resource=resource)
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces"))
processor = BatchSpanProcessor(
OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces")
)
tracer_provider.add_span_processor(processor)
trace.set_tracer_provider(tracer_provider)
```
@@ -43,7 +43,6 @@ Optionally, you can provide metadata using the `meta` parameter. This can be a s
This component is primarily meant to be used in pipelines.
```python
from haystack.components.converters.image import ImageFileToDocument
converter = ImageFileToDocument()
@@ -41,7 +41,6 @@ This component is often used in query pipelines just before a `ChatPromptBuilder
### On its own
```python
from haystack.components.converters.image import ImageFileToImageContent
converter = ImageFileToImageContent(detail="high", size=(800, 600))
@@ -100,7 +100,6 @@ assert result["output_adapter"]["output"] == "Haystack"
You can also define your own custom filters, which can then be added to an `OutputAdapter` instance through its init method and used in templates. Here’s an example of this approach:
```python
from haystack import Pipeline, component, Document
from haystack.components.converters import OutputAdapter
@@ -54,7 +54,6 @@ Remember to set the`MISTRAL_API_KEY` as an environment variable first or pass it
Here is how you can use the component on its own:
```python
from haystack_integrations.components.embedders.mistral.text_embedder import (
MistralTextEmbedder,
)
@@ -111,18 +111,27 @@ from haystack.dataclasses import ChatMessage
generation_kwargs = {"extra_headers": {"anthropic-beta": "prompt-caching-2024-07-31"}}
claude_llm = AnthropicChatGenerator(
api_key=Secret.from_env_var("ANTHROPIC_API_KEY"), generation_kwargs=generation_kwargs
api_key=Secret.from_env_var("ANTHROPIC_API_KEY"),
generation_kwargs=generation_kwargs,
)
system_message = ChatMessage.from_system("Replace with some long text documents, code or instructions")
system_message = ChatMessage.from_system(
"Replace with some long text documents, code or instructions"
)
system_message.meta["cache_control"] = {"type": "ephemeral"}
messages = [system_message, ChatMessage.from_user("A query about the long text for example")]
messages = [
system_message,
ChatMessage.from_user("A query about the long text for example"),
]
result = claude_llm.run(messages)
## and now invoke again with
messages = [system_message, ChatMessage.from_user("Another query about the long text etc")]
messages = [
system_message,
ChatMessage.from_user("Another query about the long text etc"),
]
result = claude_llm.run(messages)
## and so on, either invoking component directly or in the pipeline
@@ -141,7 +141,6 @@ Here are the components that support shared hosted models in Haystack:
Here is an example using OctoAI and [`OpenAIChatGenerator`](../openaichatgenerator.mdx):
```python
from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.utils import Secret
from haystack.dataclasses import ChatMessage
@@ -41,7 +41,9 @@ pip install google-vertex-haystack
Basic usage:
````python
from haystack_integrations.components.generators.google_vertex import VertexAICodeGenerator
from haystack_integrations.components.generators.google_vertex import (
VertexAICodeGenerator,
)
generator = VertexAICodeGenerator()
@@ -49,7 +51,6 @@ result = generator.run(prefix="def to_json(data):")
for answer in result["replies"]:
print(answer)
````
You can also set other parameters like the number of output tokens, temperature, stop sequences, and the number of candidates.
@@ -43,13 +43,14 @@ pip install google-vertex-haystack
Basic usage:
````python
from haystack_integrations.components.generators.google_vertex import VertexAITextGenerator
from haystack_integrations.components.generators.google_vertex import (
VertexAITextGenerator,
)
generator = VertexAITextGenerator()
res = generator.run("Tell me a good interview question for a software engineer.")
print(res["replies"][0])
````
You can also set other parameters like the number of answers generated, temperature to control the randomness, and stop sequences to stop generation. For a full list of possible parameters, see the documentation of [`TextGenerationModel.predict()`](https://cloud.google.com/python/docs/reference/aiplatform/latest/vertexai.language_models.TextGenerationModel#vertexai_language_models_TextGenerationModel_predict).
@@ -80,7 +80,6 @@ retriever.run(query="How many languages are spoken around the world today?")
The below example shows how to use the `AzureAISearchBM25Retriever` in a RAG pipeline. Set your `OPENAI_API_KEY` as an environment variable and then run the following code:
```python
from haystack_integrations.components.retrievers.azure_ai_search import (
AzureAISearchBM25Retriever,
)
@@ -91,7 +91,6 @@ retriever.run(query="How many languages are spoken around the world today?")
Set your `OPENAI_API_KEY` as an environment variable and then run the following code:
```python
from haystack_integrations.components.retrievers.elasticsearch import (
ElasticsearchBM25Retriever,
)
@@ -211,14 +211,20 @@ If your pipeline seems stuck or runs longer than expected, here are common cause
```python
# Problematic: user input goes directly to a component inside the loop
result = pipe.run({
"generator": {"prompt": query}, # This input persists and may retrigger the loop
})
result = pipe.run(
{
"generator": {
"prompt": query
}, # This input persists and may retrigger the loop
}
)
# Better: use an entry-point component outside the loop
result = pipe.run({
"prompt_builder": {"query": query}, # Entry point feeds into the loop once
})
result = pipe.run(
{
"prompt_builder": {"query": query}, # Entry point feeds into the loop once
}
)
```
See [Greedy vs. Lazy Variadic Sockets](#greedy-vs-lazy-variadic-sockets-in-loops) for details on how inputs are consumed.
@@ -138,7 +138,6 @@ new_env_secret = Secret.from_dict(env_secret_dict)
Both types of secrets can be resolved to their actual values using the `resolve_value` method. This method returns the token or the value of the environment variable.
```python
## Resolve the token-based secret
token_value = api_key_secret.resolve_value()
@@ -66,17 +66,22 @@ To use OpenTelemetry as your tracing backend, follow these steps:
from opentelemetry.semconv.resource import ResourceAttributes
# Service name is required for most backends
resource = Resource(attributes={
ResourceAttributes.SERVICE_NAME: "haystack" # Correct constant
})
resource = Resource(
attributes={
ResourceAttributes.SERVICE_NAME: "haystack" # Correct constant
}
)
tracer_provider = TracerProvider(resource=resource)
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces"))
processor = BatchSpanProcessor(
OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces")
)
tracer_provider.add_span_processor(processor)
trace.set_tracer_provider(tracer_provider)
# Tell Haystack to auto-detect the configured tracer
import haystack.tracing
haystack.tracing.auto_enable_tracing()
# Explicitly tell Haystack to use your tracer
@@ -153,36 +158,40 @@ To use your custom tracing backend with Haystack, follow these steps:
from haystack.tracing import utils as tracing_utils
import opentelemetry.trace
class OpenTelemetrySpan(Span):
def __init__(self, span: opentelemetry.trace.Span) -> None:
self._span = span
def set_tag(self, key: str, value: Any) -> None:
# Tracing backends usually don't support any tag value
# `coerce_tag_value` forces the value to either be a Python
# primitive (int, float, boolean, str) or tries to dump it as string.
coerced_value = tracing_utils.coerce_tag_value(value)
self._span.set_attribute(key, coerced_value)
class OpenTelemetrySpan(Span):
def __init__(self, span: opentelemetry.trace.Span) -> None:
self._span = span
def set_tag(self, key: str, value: Any) -> None:
# Tracing backends usually don't support any tag value
# `coerce_tag_value` forces the value to either be a Python
# primitive (int, float, boolean, str) or tries to dump it as string.
coerced_value = tracing_utils.coerce_tag_value(value)
self._span.set_attribute(key, coerced_value)
class OpenTelemetryTracer(Tracer):
def __init__(self, tracer: opentelemetry.trace.Tracer) -> None:
self._tracer = tracer
def __init__(self, tracer: opentelemetry.trace.Tracer) -> None:
self._tracer = tracer
@contextlib.contextmanager
def trace(self, operation_name: str, tags: Optional[Dict[str, Any]] = None) -> Iterator[Span]:
with self._tracer.start_as_current_span(operation_name) as span:
span = OpenTelemetrySpan(span)
if tags:
span.set_tags(tags)
@contextlib.contextmanager
def trace(
self, operation_name: str, tags: Optional[Dict[str, Any]] = None
) -> Iterator[Span]:
with self._tracer.start_as_current_span(operation_name) as span:
span = OpenTelemetrySpan(span)
if tags:
span.set_tags(tags)
yield span
yield span
def current_span(self) -> Optional[Span]:
current_span = trace.get_current_span()
if isinstance(current_span, NonRecordingSpan):
return None
def current_span(self) -> Optional[Span]:
current_span = trace.get_current_span()
if isinstance(current_span, NonRecordingSpan):
return None
return OpenTelemetrySpan(current_span)
return OpenTelemetrySpan(current_span)
```
2. Tell Haystack to use your custom tracer:
@@ -275,12 +284,12 @@ Use [Jaeger](https://www.jaegertracing.io/docs/1.6/getting-started/) as a lightw
from opentelemetry.sdk.trace.export import BatchSpanProcessor
# Service name is required for most backends
resource = Resource(attributes={
ResourceAttributes.SERVICE_NAME: "haystack"
})
resource = Resource(attributes={ResourceAttributes.SERVICE_NAME: "haystack"})
tracer_provider = TracerProvider(resource=resource)
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces"))
processor = BatchSpanProcessor(
OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces")
)
tracer_provider.add_span_processor(processor)
trace.set_tracer_provider(tracer_provider)
```
@@ -43,7 +43,6 @@ Optionally, you can provide metadata using the `meta` parameter. This can be a s
This component is primarily meant to be used in pipelines.
```python
from haystack.components.converters.image import ImageFileToDocument
converter = ImageFileToDocument()
@@ -41,7 +41,6 @@ This component is often used in query pipelines just before a `ChatPromptBuilder
### On its own
```python
from haystack.components.converters.image import ImageFileToImageContent
converter = ImageFileToImageContent(detail="high", size=(800, 600))
@@ -100,7 +100,6 @@ assert result["output_adapter"]["output"] == "Haystack"
You can also define your own custom filters, which can then be added to an `OutputAdapter` instance through its init method and used in templates. Here’s an example of this approach:
```python
from haystack import Pipeline, component, Document
from haystack.components.converters import OutputAdapter
@@ -54,7 +54,6 @@ Remember to set the`MISTRAL_API_KEY` as an environment variable first or pass it
Here is how you can use the component on its own:
```python
from haystack_integrations.components.embedders.mistral.text_embedder import (
MistralTextEmbedder,
)
@@ -110,18 +110,27 @@ from haystack.dataclasses import ChatMessage
generation_kwargs = {"extra_headers": {"anthropic-beta": "prompt-caching-2024-07-31"}}
claude_llm = AnthropicChatGenerator(
api_key=Secret.from_env_var("ANTHROPIC_API_KEY"), generation_kwargs=generation_kwargs
api_key=Secret.from_env_var("ANTHROPIC_API_KEY"),
generation_kwargs=generation_kwargs,
)
system_message = ChatMessage.from_system("Replace with some long text documents, code or instructions")
system_message = ChatMessage.from_system(
"Replace with some long text documents, code or instructions"
)
system_message.meta["cache_control"] = {"type": "ephemeral"}
messages = [system_message, ChatMessage.from_user("A query about the long text for example")]
messages = [
system_message,
ChatMessage.from_user("A query about the long text for example"),
]
result = claude_llm.run(messages)
## and now invoke again with
messages = [system_message, ChatMessage.from_user("Another query about the long text etc")]
messages = [
system_message,
ChatMessage.from_user("Another query about the long text etc"),
]
result = claude_llm.run(messages)
## and so on, either invoking component directly or in the pipeline
@@ -141,7 +141,6 @@ Here are the components that support shared hosted models in Haystack:
Here is an example using OctoAI and [`OpenAIChatGenerator`](../openaichatgenerator.mdx):
```python
from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.utils import Secret
from haystack.dataclasses import ChatMessage
@@ -80,7 +80,6 @@ retriever.run(query="How many languages are spoken around the world today?")
The below example shows how to use the `AzureAISearchBM25Retriever` in a RAG pipeline. Set your `OPENAI_API_KEY` as an environment variable and then run the following code:
```python
from haystack_integrations.components.retrievers.azure_ai_search import (
AzureAISearchBM25Retriever,
)
@@ -91,7 +91,6 @@ retriever.run(query="How many languages are spoken around the world today?")
Set your `OPENAI_API_KEY` as an environment variable and then run the following code:
```python
from haystack_integrations.components.retrievers.elasticsearch import (
ElasticsearchBM25Retriever,
)
@@ -211,14 +211,20 @@ If your pipeline seems stuck or runs longer than expected, here are common cause
```python
# Problematic: user input goes directly to a component inside the loop
result = pipe.run({
"generator": {"prompt": query}, # This input persists and may retrigger the loop
})
result = pipe.run(
{
"generator": {
"prompt": query
}, # This input persists and may retrigger the loop
}
)
# Better: use an entry-point component outside the loop
result = pipe.run({
"prompt_builder": {"query": query}, # Entry point feeds into the loop once
})
result = pipe.run(
{
"prompt_builder": {"query": query}, # Entry point feeds into the loop once
}
)
```
See [Greedy vs. Lazy Variadic Sockets](#greedy-vs-lazy-variadic-sockets-in-loops) for details on how inputs are consumed.
@@ -138,7 +138,6 @@ new_env_secret = Secret.from_dict(env_secret_dict)
Both types of secrets can be resolved to their actual values using the `resolve_value` method. This method returns the token or the value of the environment variable.
```python
## Resolve the token-based secret
token_value = api_key_secret.resolve_value()
@@ -66,17 +66,22 @@ To use OpenTelemetry as your tracing backend, follow these steps:
from opentelemetry.semconv.resource import ResourceAttributes
# Service name is required for most backends
resource = Resource(attributes={
ResourceAttributes.SERVICE_NAME: "haystack" # Correct constant
})
resource = Resource(
attributes={
ResourceAttributes.SERVICE_NAME: "haystack" # Correct constant
}
)
tracer_provider = TracerProvider(resource=resource)
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces"))
processor = BatchSpanProcessor(
OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces")
)
tracer_provider.add_span_processor(processor)
trace.set_tracer_provider(tracer_provider)
# Tell Haystack to auto-detect the configured tracer
import haystack.tracing
haystack.tracing.auto_enable_tracing()
# Explicitly tell Haystack to use your tracer
@@ -153,36 +158,40 @@ To use your custom tracing backend with Haystack, follow these steps:
from haystack.tracing import utils as tracing_utils
import opentelemetry.trace
class OpenTelemetrySpan(Span):
def __init__(self, span: opentelemetry.trace.Span) -> None:
self._span = span
def set_tag(self, key: str, value: Any) -> None:
# Tracing backends usually don't support any tag value
# `coerce_tag_value` forces the value to either be a Python
# primitive (int, float, boolean, str) or tries to dump it as string.
coerced_value = tracing_utils.coerce_tag_value(value)
self._span.set_attribute(key, coerced_value)
class OpenTelemetrySpan(Span):
def __init__(self, span: opentelemetry.trace.Span) -> None:
self._span = span
def set_tag(self, key: str, value: Any) -> None:
# Tracing backends usually don't support any tag value
# `coerce_tag_value` forces the value to either be a Python
# primitive (int, float, boolean, str) or tries to dump it as string.
coerced_value = tracing_utils.coerce_tag_value(value)
self._span.set_attribute(key, coerced_value)
class OpenTelemetryTracer(Tracer):
def __init__(self, tracer: opentelemetry.trace.Tracer) -> None:
self._tracer = tracer
def __init__(self, tracer: opentelemetry.trace.Tracer) -> None:
self._tracer = tracer
@contextlib.contextmanager
def trace(self, operation_name: str, tags: Optional[Dict[str, Any]] = None) -> Iterator[Span]:
with self._tracer.start_as_current_span(operation_name) as span:
span = OpenTelemetrySpan(span)
if tags:
span.set_tags(tags)
@contextlib.contextmanager
def trace(
self, operation_name: str, tags: Optional[Dict[str, Any]] = None
) -> Iterator[Span]:
with self._tracer.start_as_current_span(operation_name) as span:
span = OpenTelemetrySpan(span)
if tags:
span.set_tags(tags)
yield span
yield span
def current_span(self) -> Optional[Span]:
current_span = trace.get_current_span()
if isinstance(current_span, NonRecordingSpan):
return None
def current_span(self) -> Optional[Span]:
current_span = trace.get_current_span()
if isinstance(current_span, NonRecordingSpan):
return None
return OpenTelemetrySpan(current_span)
return OpenTelemetrySpan(current_span)
```
2. Tell Haystack to use your custom tracer:
@@ -275,12 +284,12 @@ Use [Jaeger](https://www.jaegertracing.io/docs/1.6/getting-started/) as a lightw
from opentelemetry.sdk.trace.export import BatchSpanProcessor
# Service name is required for most backends
resource = Resource(attributes={
ResourceAttributes.SERVICE_NAME: "haystack"
})
resource = Resource(attributes={ResourceAttributes.SERVICE_NAME: "haystack"})
tracer_provider = TracerProvider(resource=resource)
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces"))
processor = BatchSpanProcessor(
OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces")
)
tracer_provider.add_span_processor(processor)
trace.set_tracer_provider(tracer_provider)
```
@@ -43,7 +43,6 @@ Optionally, you can provide metadata using the `meta` parameter. This can be a s
This component is primarily meant to be used in pipelines.
```python
from haystack.components.converters.image import ImageFileToDocument
converter = ImageFileToDocument()
@@ -41,7 +41,6 @@ This component is often used in query pipelines just before a `ChatPromptBuilder
### On its own
```python
from haystack.components.converters.image import ImageFileToImageContent
converter = ImageFileToImageContent(detail="high", size=(800, 600))
@@ -100,7 +100,6 @@ assert result["output_adapter"]["output"] == "Haystack"
You can also define your own custom filters, which can then be added to an `OutputAdapter` instance through its init method and used in templates. Here’s an example of this approach:
```python
from haystack import Pipeline, component, Document
from haystack.components.converters import OutputAdapter
@@ -54,7 +54,6 @@ Remember to set the`MISTRAL_API_KEY` as an environment variable first or pass it
Here is how you can use the component on its own:
```python
from haystack_integrations.components.embedders.mistral.text_embedder import (
MistralTextEmbedder,
)
@@ -110,18 +110,27 @@ from haystack.dataclasses import ChatMessage
generation_kwargs = {"extra_headers": {"anthropic-beta": "prompt-caching-2024-07-31"}}
claude_llm = AnthropicChatGenerator(
api_key=Secret.from_env_var("ANTHROPIC_API_KEY"), generation_kwargs=generation_kwargs
api_key=Secret.from_env_var("ANTHROPIC_API_KEY"),
generation_kwargs=generation_kwargs,
)
system_message = ChatMessage.from_system("Replace with some long text documents, code or instructions")
system_message = ChatMessage.from_system(
"Replace with some long text documents, code or instructions"
)
system_message.meta["cache_control"] = {"type": "ephemeral"}
messages = [system_message, ChatMessage.from_user("A query about the long text for example")]
messages = [
system_message,
ChatMessage.from_user("A query about the long text for example"),
]
result = claude_llm.run(messages)
## and now invoke again with
messages = [system_message, ChatMessage.from_user("Another query about the long text etc")]
messages = [
system_message,
ChatMessage.from_user("Another query about the long text etc"),
]
result = claude_llm.run(messages)
## and so on, either invoking component directly or in the pipeline
@@ -141,7 +141,6 @@ Here are the components that support shared hosted models in Haystack:
Here is an example using OctoAI and [`OpenAIChatGenerator`](../openaichatgenerator.mdx):
```python
from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.utils import Secret
from haystack.dataclasses import ChatMessage
@@ -80,7 +80,6 @@ retriever.run(query="How many languages are spoken around the world today?")
The below example shows how to use the `AzureAISearchBM25Retriever` in a RAG pipeline. Set your `OPENAI_API_KEY` as an environment variable and then run the following code:
```python
from haystack_integrations.components.retrievers.azure_ai_search import (
AzureAISearchBM25Retriever,
)
@@ -91,7 +91,6 @@ retriever.run(query="How many languages are spoken around the world today?")
Set your `OPENAI_API_KEY` as an environment variable and then run the following code:
```python
from haystack_integrations.components.retrievers.elasticsearch import (
ElasticsearchBM25Retriever,
)
@@ -211,14 +211,20 @@ If your pipeline seems stuck or runs longer than expected, here are common cause
```python
# Problematic: user input goes directly to a component inside the loop
result = pipe.run({
"generator": {"prompt": query}, # This input persists and may retrigger the loop
})
result = pipe.run(
{
"generator": {
"prompt": query
}, # This input persists and may retrigger the loop
}
)
# Better: use an entry-point component outside the loop
result = pipe.run({
"prompt_builder": {"query": query}, # Entry point feeds into the loop once
})
result = pipe.run(
{
"prompt_builder": {"query": query}, # Entry point feeds into the loop once
}
)
```
See [Greedy vs. Lazy Variadic Sockets](#greedy-vs-lazy-variadic-sockets-in-loops) for details on how inputs are consumed.
@@ -138,7 +138,6 @@ new_env_secret = Secret.from_dict(env_secret_dict)
Both types of secrets can be resolved to their actual values using the `resolve_value` method. This method returns the token or the value of the environment variable.
```python
## Resolve the token-based secret
token_value = api_key_secret.resolve_value()
@@ -66,17 +66,22 @@ To use OpenTelemetry as your tracing backend, follow these steps:
from opentelemetry.semconv.resource import ResourceAttributes
# Service name is required for most backends
resource = Resource(attributes={
ResourceAttributes.SERVICE_NAME: "haystack" # Correct constant
})
resource = Resource(
attributes={
ResourceAttributes.SERVICE_NAME: "haystack" # Correct constant
}
)
tracer_provider = TracerProvider(resource=resource)
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces"))
processor = BatchSpanProcessor(
OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces")
)
tracer_provider.add_span_processor(processor)
trace.set_tracer_provider(tracer_provider)
# Tell Haystack to auto-detect the configured tracer
import haystack.tracing
haystack.tracing.auto_enable_tracing()
# Explicitly tell Haystack to use your tracer
@@ -153,36 +158,40 @@ To use your custom tracing backend with Haystack, follow these steps:
from haystack.tracing import utils as tracing_utils
import opentelemetry.trace
class OpenTelemetrySpan(Span):
def __init__(self, span: opentelemetry.trace.Span) -> None:
self._span = span
def set_tag(self, key: str, value: Any) -> None:
# Tracing backends usually don't support any tag value
# `coerce_tag_value` forces the value to either be a Python
# primitive (int, float, boolean, str) or tries to dump it as string.
coerced_value = tracing_utils.coerce_tag_value(value)
self._span.set_attribute(key, coerced_value)
class OpenTelemetrySpan(Span):
def __init__(self, span: opentelemetry.trace.Span) -> None:
self._span = span
def set_tag(self, key: str, value: Any) -> None:
# Tracing backends usually don't support any tag value
# `coerce_tag_value` forces the value to either be a Python
# primitive (int, float, boolean, str) or tries to dump it as string.
coerced_value = tracing_utils.coerce_tag_value(value)
self._span.set_attribute(key, coerced_value)
class OpenTelemetryTracer(Tracer):
def __init__(self, tracer: opentelemetry.trace.Tracer) -> None:
self._tracer = tracer
def __init__(self, tracer: opentelemetry.trace.Tracer) -> None:
self._tracer = tracer
@contextlib.contextmanager
def trace(self, operation_name: str, tags: Optional[Dict[str, Any]] = None) -> Iterator[Span]:
with self._tracer.start_as_current_span(operation_name) as span:
span = OpenTelemetrySpan(span)
if tags:
span.set_tags(tags)
@contextlib.contextmanager
def trace(
self, operation_name: str, tags: Optional[Dict[str, Any]] = None
) -> Iterator[Span]:
with self._tracer.start_as_current_span(operation_name) as span:
span = OpenTelemetrySpan(span)
if tags:
span.set_tags(tags)
yield span
yield span
def current_span(self) -> Optional[Span]:
current_span = trace.get_current_span()
if isinstance(current_span, NonRecordingSpan):
return None
def current_span(self) -> Optional[Span]:
current_span = trace.get_current_span()
if isinstance(current_span, NonRecordingSpan):
return None
return OpenTelemetrySpan(current_span)
return OpenTelemetrySpan(current_span)
```
2. Tell Haystack to use your custom tracer:
@@ -275,12 +284,12 @@ Use [Jaeger](https://www.jaegertracing.io/docs/1.6/getting-started/) as a lightw
from opentelemetry.sdk.trace.export import BatchSpanProcessor
# Service name is required for most backends
resource = Resource(attributes={
ResourceAttributes.SERVICE_NAME: "haystack"
})
resource = Resource(attributes={ResourceAttributes.SERVICE_NAME: "haystack"})
tracer_provider = TracerProvider(resource=resource)
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces"))
processor = BatchSpanProcessor(
OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces")
)
tracer_provider.add_span_processor(processor)
trace.set_tracer_provider(tracer_provider)
```
@@ -43,7 +43,6 @@ Optionally, you can provide metadata using the `meta` parameter. This can be a s
This component is primarily meant to be used in pipelines.
```python
from haystack.components.converters.image import ImageFileToDocument
converter = ImageFileToDocument()
@@ -41,7 +41,6 @@ This component is often used in query pipelines just before a `ChatPromptBuilder
### On its own
```python
from haystack.components.converters.image import ImageFileToImageContent
converter = ImageFileToImageContent(detail="high", size=(800, 600))
@@ -100,7 +100,6 @@ assert result["output_adapter"]["output"] == "Haystack"
You can also define your own custom filters, which can then be added to an `OutputAdapter` instance through its init method and used in templates. Here’s an example of this approach:
```python
from haystack import Pipeline, component, Document
from haystack.components.converters import OutputAdapter
@@ -54,7 +54,6 @@ Remember to set the`MISTRAL_API_KEY` as an environment variable first or pass it
Here is how you can use the component on its own:
```python
from haystack_integrations.components.embedders.mistral.text_embedder import (
MistralTextEmbedder,
)
@@ -110,18 +110,27 @@ from haystack.dataclasses import ChatMessage
generation_kwargs = {"extra_headers": {"anthropic-beta": "prompt-caching-2024-07-31"}}
claude_llm = AnthropicChatGenerator(
api_key=Secret.from_env_var("ANTHROPIC_API_KEY"), generation_kwargs=generation_kwargs
api_key=Secret.from_env_var("ANTHROPIC_API_KEY"),
generation_kwargs=generation_kwargs,
)
system_message = ChatMessage.from_system("Replace with some long text documents, code or instructions")
system_message = ChatMessage.from_system(
"Replace with some long text documents, code or instructions"
)
system_message.meta["cache_control"] = {"type": "ephemeral"}
messages = [system_message, ChatMessage.from_user("A query about the long text for example")]
messages = [
system_message,
ChatMessage.from_user("A query about the long text for example"),
]
result = claude_llm.run(messages)
## and now invoke again with
messages = [system_message, ChatMessage.from_user("Another query about the long text etc")]
messages = [
system_message,
ChatMessage.from_user("Another query about the long text etc"),
]
result = claude_llm.run(messages)
## and so on, either invoking component directly or in the pipeline
@@ -141,7 +141,6 @@ Here are the components that support shared hosted models in Haystack:
Here is an example using OctoAI and [`OpenAIChatGenerator`](../openaichatgenerator.mdx):
```python
from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.utils import Secret
from haystack.dataclasses import ChatMessage
@@ -36,7 +36,6 @@ This component is inspired by [5 Levels of Text Splitting](https://github.com/Fu
### On its own
```python
from haystack import Document
from haystack.components.embedders import SentenceTransformersDocumentEmbedder
from haystack.components.preprocessors import EmbeddingBasedDocumentSplitter
@@ -80,7 +80,6 @@ retriever.run(query="How many languages are spoken around the world today?")
The below example shows how to use the `AzureAISearchBM25Retriever` in a RAG pipeline. Set your `OPENAI_API_KEY` as an environment variable and then run the following code:
```python
from haystack_integrations.components.retrievers.azure_ai_search import (
AzureAISearchBM25Retriever,
)
@@ -91,7 +91,6 @@ retriever.run(query="How many languages are spoken around the world today?")
Set your `OPENAI_API_KEY` as an environment variable and then run the following code:
```python
from haystack_integrations.components.retrievers.elasticsearch import (
ElasticsearchBM25Retriever,
)
@@ -211,14 +211,20 @@ If your pipeline seems stuck or runs longer than expected, here are common cause
```python
# Problematic: user input goes directly to a component inside the loop
result = pipe.run({
"generator": {"prompt": query}, # This input persists and may retrigger the loop
})
result = pipe.run(
{
"generator": {
"prompt": query
}, # This input persists and may retrigger the loop
}
)
# Better: use an entry-point component outside the loop
result = pipe.run({
"prompt_builder": {"query": query}, # Entry point feeds into the loop once
})
result = pipe.run(
{
"prompt_builder": {"query": query}, # Entry point feeds into the loop once
}
)
```
See [Greedy vs. Lazy Variadic Sockets](#greedy-vs-lazy-variadic-sockets-in-loops) for details on how inputs are consumed.
@@ -138,7 +138,6 @@ new_env_secret = Secret.from_dict(env_secret_dict)
Both types of secrets can be resolved to their actual values using the `resolve_value` method. This method returns the token or the value of the environment variable.
```python
## Resolve the token-based secret
token_value = api_key_secret.resolve_value()
@@ -66,17 +66,22 @@ To use OpenTelemetry as your tracing backend, follow these steps:
from opentelemetry.semconv.resource import ResourceAttributes
# Service name is required for most backends
resource = Resource(attributes={
ResourceAttributes.SERVICE_NAME: "haystack" # Correct constant
})
resource = Resource(
attributes={
ResourceAttributes.SERVICE_NAME: "haystack" # Correct constant
}
)
tracer_provider = TracerProvider(resource=resource)
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces"))
processor = BatchSpanProcessor(
OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces")
)
tracer_provider.add_span_processor(processor)
trace.set_tracer_provider(tracer_provider)
# Tell Haystack to auto-detect the configured tracer
import haystack.tracing
haystack.tracing.auto_enable_tracing()
# Explicitly tell Haystack to use your tracer
@@ -153,36 +158,40 @@ To use your custom tracing backend with Haystack, follow these steps:
from haystack.tracing import utils as tracing_utils
import opentelemetry.trace
class OpenTelemetrySpan(Span):
def __init__(self, span: opentelemetry.trace.Span) -> None:
self._span = span
def set_tag(self, key: str, value: Any) -> None:
# Tracing backends usually don't support any tag value
# `coerce_tag_value` forces the value to either be a Python
# primitive (int, float, boolean, str) or tries to dump it as string.
coerced_value = tracing_utils.coerce_tag_value(value)
self._span.set_attribute(key, coerced_value)
class OpenTelemetrySpan(Span):
def __init__(self, span: opentelemetry.trace.Span) -> None:
self._span = span
def set_tag(self, key: str, value: Any) -> None:
# Tracing backends usually don't support any tag value
# `coerce_tag_value` forces the value to either be a Python
# primitive (int, float, boolean, str) or tries to dump it as string.
coerced_value = tracing_utils.coerce_tag_value(value)
self._span.set_attribute(key, coerced_value)
class OpenTelemetryTracer(Tracer):
def __init__(self, tracer: opentelemetry.trace.Tracer) -> None:
self._tracer = tracer
def __init__(self, tracer: opentelemetry.trace.Tracer) -> None:
self._tracer = tracer
@contextlib.contextmanager
def trace(self, operation_name: str, tags: Optional[Dict[str, Any]] = None) -> Iterator[Span]:
with self._tracer.start_as_current_span(operation_name) as span:
span = OpenTelemetrySpan(span)
if tags:
span.set_tags(tags)
@contextlib.contextmanager
def trace(
self, operation_name: str, tags: Optional[Dict[str, Any]] = None
) -> Iterator[Span]:
with self._tracer.start_as_current_span(operation_name) as span:
span = OpenTelemetrySpan(span)
if tags:
span.set_tags(tags)
yield span
yield span
def current_span(self) -> Optional[Span]:
current_span = trace.get_current_span()
if isinstance(current_span, NonRecordingSpan):
return None
def current_span(self) -> Optional[Span]:
current_span = trace.get_current_span()
if isinstance(current_span, NonRecordingSpan):
return None
return OpenTelemetrySpan(current_span)
return OpenTelemetrySpan(current_span)
```
2. Tell Haystack to use your custom tracer:
@@ -275,12 +284,12 @@ Use [Jaeger](https://www.jaegertracing.io/docs/1.6/getting-started/) as a lightw
from opentelemetry.sdk.trace.export import BatchSpanProcessor
# Service name is required for most backends
resource = Resource(attributes={
ResourceAttributes.SERVICE_NAME: "haystack"
})
resource = Resource(attributes={ResourceAttributes.SERVICE_NAME: "haystack"})
tracer_provider = TracerProvider(resource=resource)
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces"))
processor = BatchSpanProcessor(
OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces")
)
tracer_provider.add_span_processor(processor)
trace.set_tracer_provider(tracer_provider)
```
@@ -43,7 +43,6 @@ Optionally, you can provide metadata using the `meta` parameter. This can be a s
This component is primarily meant to be used in pipelines.
```python
from haystack.components.converters.image import ImageFileToDocument
converter = ImageFileToDocument()
@@ -41,7 +41,6 @@ This component is often used in query pipelines just before a `ChatPromptBuilder
### On its own
```python
from haystack.components.converters.image import ImageFileToImageContent
converter = ImageFileToImageContent(detail="high", size=(800, 600))
@@ -100,7 +100,6 @@ assert result["output_adapter"]["output"] == "Haystack"
You can also define your own custom filters, which can then be added to an `OutputAdapter` instance through its init method and used in templates. Here’s an example of this approach:
```python
from haystack import Pipeline, component, Document
from haystack.components.converters import OutputAdapter
@@ -54,7 +54,6 @@ Remember to set the`MISTRAL_API_KEY` as an environment variable first or pass it
Here is how you can use the component on its own:
```python
from haystack_integrations.components.embedders.mistral.text_embedder import (
MistralTextEmbedder,
)
@@ -110,18 +110,27 @@ from haystack.dataclasses import ChatMessage
generation_kwargs = {"extra_headers": {"anthropic-beta": "prompt-caching-2024-07-31"}}
claude_llm = AnthropicChatGenerator(
api_key=Secret.from_env_var("ANTHROPIC_API_KEY"), generation_kwargs=generation_kwargs
api_key=Secret.from_env_var("ANTHROPIC_API_KEY"),
generation_kwargs=generation_kwargs,
)
system_message = ChatMessage.from_system("Replace with some long text documents, code or instructions")
system_message = ChatMessage.from_system(
"Replace with some long text documents, code or instructions"
)
system_message.meta["cache_control"] = {"type": "ephemeral"}
messages = [system_message, ChatMessage.from_user("A query about the long text for example")]
messages = [
system_message,
ChatMessage.from_user("A query about the long text for example"),
]
result = claude_llm.run(messages)
## and now invoke again with
messages = [system_message, ChatMessage.from_user("Another query about the long text etc")]
messages = [
system_message,
ChatMessage.from_user("Another query about the long text etc"),
]
result = claude_llm.run(messages)
## and so on, either invoking component directly or in the pipeline
@@ -141,7 +141,6 @@ Here are the components that support shared hosted models in Haystack:
Here is an example using OctoAI and [`OpenAIChatGenerator`](../openaichatgenerator.mdx):
```python
from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.utils import Secret
from haystack.dataclasses import ChatMessage
@@ -36,7 +36,6 @@ This component is inspired by [5 Levels of Text Splitting](https://github.com/Fu
### On its own
```python
from haystack import Document
from haystack.components.embedders import SentenceTransformersDocumentEmbedder
from haystack.components.preprocessors import EmbeddingBasedDocumentSplitter
@@ -80,7 +80,6 @@ retriever.run(query="How many languages are spoken around the world today?")
The below example shows how to use the `AzureAISearchBM25Retriever` in a RAG pipeline. Set your `OPENAI_API_KEY` as an environment variable and then run the following code:
```python
from haystack_integrations.components.retrievers.azure_ai_search import (
AzureAISearchBM25Retriever,
)
@@ -91,7 +91,6 @@ retriever.run(query="How many languages are spoken around the world today?")
Set your `OPENAI_API_KEY` as an environment variable and then run the following code:
```python
from haystack_integrations.components.retrievers.elasticsearch import (
ElasticsearchBM25Retriever,
)
@@ -131,9 +131,7 @@ By default, a tool's return value is converted to a string using a default handl
You can use `outputs_to_string` to customize this behavior using one of two formats:
1. **Single output format**: Use `source`, `handler`, and/or `raw_result` at the root level.
```python
{
"source": "docs", "handler": format_documents, "raw_result": False
}
{"source": "docs", "handler": format_documents, "raw_result": False}
```
- `source`: (Optional) Specifies the key to extract from the tool's output dictionary. If omitted, the entire result is passed to the handler.
- `handler`: (Optional) A function that takes the output (or the extracted source value) and returns the final result.
@@ -145,7 +143,7 @@ You can use `outputs_to_string` to customize this behavior using one of two form
```python
{
"formatted_docs": {"source": "docs", "handler": format_documents},
"summary": {"source": "summary_text", "handler": str.upper}
"summary": {"source": "summary_text", "handler": str.upper},
}
```
Each entry defines a `source` key and can optionally include a `handler`. The individual outputs are processed,
@@ -211,14 +211,20 @@ If your pipeline seems stuck or runs longer than expected, here are common cause
```python
# Problematic: user input goes directly to a component inside the loop
result = pipe.run({
"generator": {"prompt": query}, # This input persists and may retrigger the loop
})
result = pipe.run(
{
"generator": {
"prompt": query
}, # This input persists and may retrigger the loop
}
)
# Better: use an entry-point component outside the loop
result = pipe.run({
"prompt_builder": {"query": query}, # Entry point feeds into the loop once
})
result = pipe.run(
{
"prompt_builder": {"query": query}, # Entry point feeds into the loop once
}
)
```
See [Greedy vs. Lazy Variadic Sockets](#greedy-vs-lazy-variadic-sockets-in-loops) for details on how inputs are consumed.
@@ -66,17 +66,22 @@ To use OpenTelemetry as your tracing backend, follow these steps:
from opentelemetry.semconv.resource import ResourceAttributes
# Service name is required for most backends
resource = Resource(attributes={
ResourceAttributes.SERVICE_NAME: "haystack" # Correct constant
})
resource = Resource(
attributes={
ResourceAttributes.SERVICE_NAME: "haystack" # Correct constant
}
)
tracer_provider = TracerProvider(resource=resource)
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces"))
processor = BatchSpanProcessor(
OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces")
)
tracer_provider.add_span_processor(processor)
trace.set_tracer_provider(tracer_provider)
# Tell Haystack to auto-detect the configured tracer
import haystack.tracing
haystack.tracing.auto_enable_tracing()
# Explicitly tell Haystack to use your tracer
@@ -153,36 +158,40 @@ To use your custom tracing backend with Haystack, follow these steps:
from haystack.tracing import utils as tracing_utils
import opentelemetry.trace
class OpenTelemetrySpan(Span):
def __init__(self, span: opentelemetry.trace.Span) -> None:
self._span = span
def set_tag(self, key: str, value: Any) -> None:
# Tracing backends usually don't support any tag value
# `coerce_tag_value` forces the value to either be a Python
# primitive (int, float, boolean, str) or tries to dump it as string.
coerced_value = tracing_utils.coerce_tag_value(value)
self._span.set_attribute(key, coerced_value)
class OpenTelemetrySpan(Span):
def __init__(self, span: opentelemetry.trace.Span) -> None:
self._span = span
def set_tag(self, key: str, value: Any) -> None:
# Tracing backends usually don't support any tag value
# `coerce_tag_value` forces the value to either be a Python
# primitive (int, float, boolean, str) or tries to dump it as string.
coerced_value = tracing_utils.coerce_tag_value(value)
self._span.set_attribute(key, coerced_value)
class OpenTelemetryTracer(Tracer):
def __init__(self, tracer: opentelemetry.trace.Tracer) -> None:
self._tracer = tracer
def __init__(self, tracer: opentelemetry.trace.Tracer) -> None:
self._tracer = tracer
@contextlib.contextmanager
def trace(self, operation_name: str, tags: Optional[Dict[str, Any]] = None) -> Iterator[Span]:
with self._tracer.start_as_current_span(operation_name) as span:
span = OpenTelemetrySpan(span)
if tags:
span.set_tags(tags)
@contextlib.contextmanager
def trace(
self, operation_name: str, tags: Optional[Dict[str, Any]] = None
) -> Iterator[Span]:
with self._tracer.start_as_current_span(operation_name) as span:
span = OpenTelemetrySpan(span)
if tags:
span.set_tags(tags)
yield span
yield span
def current_span(self) -> Optional[Span]:
current_span = trace.get_current_span()
if isinstance(current_span, NonRecordingSpan):
return None
def current_span(self) -> Optional[Span]:
current_span = trace.get_current_span()
if isinstance(current_span, NonRecordingSpan):
return None
return OpenTelemetrySpan(current_span)
return OpenTelemetrySpan(current_span)
```
2. Tell Haystack to use your custom tracer:
@@ -275,12 +284,12 @@ Use [Jaeger](https://www.jaegertracing.io/docs/1.6/getting-started/) as a lightw
from opentelemetry.sdk.trace.export import BatchSpanProcessor
# Service name is required for most backends
resource = Resource(attributes={
ResourceAttributes.SERVICE_NAME: "haystack"
})
resource = Resource(attributes={ResourceAttributes.SERVICE_NAME: "haystack"})
tracer_provider = TracerProvider(resource=resource)
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces"))
processor = BatchSpanProcessor(
OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces")
)
tracer_provider.add_span_processor(processor)
trace.set_tracer_provider(tracer_provider)
```

Some files were not shown because too many files have changed in this diff Show More