From 8eb05c20773066024288175a6b2955dbc2fd5ae8 Mon Sep 17 00:00:00 2001 From: Stefano Fiorucci Date: Wed, 5 Aug 2026 14:24:09 +0200 Subject: [PATCH] chore: use ruff for formatting Python snippets in docs (#12245) --- .pre-commit-config.yaml | 13 +- .../concepts/data-classes/filecontent.mdx | 4 +- .../concepts/pipelines/pipeline-loops.mdx | 18 ++- .../development/tracing/custom-tracer.mdx | 50 +++---- .../development/tracing/opentelemetry.mdx | 8 +- .../document-stores/arcadedbdocumentstore.mdx | 10 +- .../docs/memory-stores/cogneememorystore.mdx | 4 +- .../docs/memory-stores/mem0memorystore.mdx | 4 +- .../converters/imagefiletodocument.mdx | 1 - .../converters/imagefiletoimagecontent.mdx | 1 - .../converters/outputadapter.mdx | 1 - .../embedders/edenaidocumentembedder.mdx | 4 +- .../embedders/edenaitextembedder.mdx | 8 +- .../embedders/mistraltextembedder.mdx | 1 - .../generators/anthropicchatgenerator.mdx | 17 ++- .../anthropicfoundrychatgenerator.mdx | 18 ++- .../generators/edenaichatgenerator.mdx | 5 +- .../embeddingbaseddocumentsplitter.mdx | 1 - .../preprocessors/pythoncodesplitter.mdx | 10 +- .../retrievers/azureaisearchbm25retriever.mdx | 1 - .../retrievers/elasticsearchbm25retriever.mdx | 1 - .../retrievers/elasticsearchsqlretriever.mdx | 4 +- .../retrievers/opensearchsqlretriever.mdx | 4 +- .../retrievers/sqlalchemytableretriever.mdx | 12 +- .../writers/cogneewriter.mdx | 4 +- docs-website/docs/tools/tool.mdx | 6 +- docs-website/ruff.toml | 15 ++ .../concepts/secret-management.mdx | 1 - .../version-2.18/development/tracing.mdx | 71 +++++----- .../converters/imagefiletodocument.mdx | 1 - .../converters/imagefiletoimagecontent.mdx | 1 - .../converters/outputadapter.mdx | 1 - .../embedders/mistraltextembedder.mdx | 1 - .../generators/anthropicchatgenerator.mdx | 17 ++- .../choosing-the-right-generator.mdx | 1 - .../generators/vertexaicodegenerator.mdx | 5 +- .../generators/vertexaitextgenerator.mdx | 5 +- .../retrievers/azureaisearchbm25retriever.mdx | 1 - .../retrievers/elasticsearchbm25retriever.mdx | 1 - .../concepts/secret-management.mdx | 1 - .../version-2.19/development/tracing.mdx | 71 +++++----- .../converters/imagefiletodocument.mdx | 1 - .../converters/imagefiletoimagecontent.mdx | 1 - .../converters/outputadapter.mdx | 1 - .../embedders/mistraltextembedder.mdx | 1 - .../generators/anthropicchatgenerator.mdx | 17 ++- .../choosing-the-right-generator.mdx | 1 - .../generators/vertexaicodegenerator.mdx | 5 +- .../generators/vertexaitextgenerator.mdx | 5 +- .../retrievers/azureaisearchbm25retriever.mdx | 1 - .../retrievers/elasticsearchbm25retriever.mdx | 1 - .../concepts/pipelines/pipeline-loops.mdx | 18 ++- .../concepts/secret-management.mdx | 1 - .../version-2.20/development/tracing.mdx | 71 +++++----- .../converters/imagefiletodocument.mdx | 1 - .../converters/imagefiletoimagecontent.mdx | 1 - .../converters/outputadapter.mdx | 1 - .../embedders/mistraltextembedder.mdx | 1 - .../generators/anthropicchatgenerator.mdx | 17 ++- .../choosing-the-right-generator.mdx | 1 - .../retrievers/azureaisearchbm25retriever.mdx | 1 - .../retrievers/elasticsearchbm25retriever.mdx | 1 - .../concepts/pipelines/pipeline-loops.mdx | 18 ++- .../concepts/secret-management.mdx | 1 - .../version-2.21/development/tracing.mdx | 71 +++++----- .../converters/imagefiletodocument.mdx | 1 - .../converters/imagefiletoimagecontent.mdx | 1 - .../converters/outputadapter.mdx | 1 - .../embedders/mistraltextembedder.mdx | 1 - .../generators/anthropicchatgenerator.mdx | 17 ++- .../choosing-the-right-generator.mdx | 1 - .../retrievers/azureaisearchbm25retriever.mdx | 1 - .../retrievers/elasticsearchbm25retriever.mdx | 1 - .../concepts/pipelines/pipeline-loops.mdx | 18 ++- .../concepts/secret-management.mdx | 1 - .../version-2.22/development/tracing.mdx | 71 +++++----- .../converters/imagefiletodocument.mdx | 1 - .../converters/imagefiletoimagecontent.mdx | 1 - .../converters/outputadapter.mdx | 1 - .../embedders/mistraltextembedder.mdx | 1 - .../generators/anthropicchatgenerator.mdx | 17 ++- .../choosing-the-right-generator.mdx | 1 - .../embeddingbaseddocumentsplitter.mdx | 1 - .../retrievers/azureaisearchbm25retriever.mdx | 1 - .../retrievers/elasticsearchbm25retriever.mdx | 1 - .../concepts/pipelines/pipeline-loops.mdx | 18 ++- .../concepts/secret-management.mdx | 1 - .../version-2.23/development/tracing.mdx | 71 +++++----- .../converters/imagefiletodocument.mdx | 1 - .../converters/imagefiletoimagecontent.mdx | 1 - .../converters/outputadapter.mdx | 1 - .../embedders/mistraltextembedder.mdx | 1 - .../generators/anthropicchatgenerator.mdx | 17 ++- .../choosing-the-right-generator.mdx | 1 - .../embeddingbaseddocumentsplitter.mdx | 1 - .../retrievers/azureaisearchbm25retriever.mdx | 1 - .../retrievers/elasticsearchbm25retriever.mdx | 1 - .../version-2.23/tools/tool.mdx | 6 +- .../concepts/pipelines/pipeline-loops.mdx | 18 ++- .../version-2.24/development/tracing.mdx | 71 +++++----- .../document-stores/valkeydocumentstore.mdx | 32 +++-- .../converters/imagefiletodocument.mdx | 1 - .../converters/imagefiletoimagecontent.mdx | 1 - .../converters/outputadapter.mdx | 1 - .../embedders/mistraltextembedder.mdx | 1 - .../generators/anthropicchatgenerator.mdx | 17 ++- .../choosing-the-right-generator.mdx | 1 - .../embeddingbaseddocumentsplitter.mdx | 1 - .../retrievers/azureaisearchbm25retriever.mdx | 1 - .../retrievers/elasticsearchbm25retriever.mdx | 1 - .../version-2.24/tools/tool.mdx | 6 +- .../concepts/pipelines/pipeline-loops.mdx | 18 ++- .../version-2.25/development/tracing.mdx | 71 +++++----- .../document-stores/arcadedbdocumentstore.mdx | 10 +- .../document-stores/valkeydocumentstore.mdx | 32 +++-- .../converters/imagefiletodocument.mdx | 1 - .../converters/imagefiletoimagecontent.mdx | 1 - .../converters/outputadapter.mdx | 1 - .../embedders/mistraltextembedder.mdx | 1 - .../fetchers/linkcontentfetcher.mdx | 8 +- .../generators/anthropicchatgenerator.mdx | 17 ++- .../choosing-the-right-generator.mdx | 1 - .../embeddingbaseddocumentsplitter.mdx | 1 - .../retrievers/arcadedbembeddingretriever.mdx | 20 ++- .../retrievers/azureaisearchbm25retriever.mdx | 1 - .../retrievers/elasticsearchbm25retriever.mdx | 1 - .../version-2.25/tools/tool.mdx | 6 +- .../concepts/pipelines/pipeline-loops.mdx | 18 ++- .../version-2.26/development/tracing.mdx | 71 +++++----- .../document-stores/arcadedbdocumentstore.mdx | 10 +- .../document-stores/valkeydocumentstore.mdx | 32 +++-- .../converters/imagefiletodocument.mdx | 1 - .../converters/imagefiletoimagecontent.mdx | 1 - .../converters/kreuzbergconverter.mdx | 4 +- .../converters/outputadapter.mdx | 1 - .../embedders/mistraltextembedder.mdx | 1 - .../fetchers/linkcontentfetcher.mdx | 8 +- .../generators/anthropicchatgenerator.mdx | 17 ++- .../choosing-the-right-generator.mdx | 1 - .../embeddingbaseddocumentsplitter.mdx | 1 - .../retrievers/arcadedbembeddingretriever.mdx | 20 ++- .../retrievers/azureaisearchbm25retriever.mdx | 1 - .../retrievers/elasticsearchbm25retriever.mdx | 1 - .../version-2.26/tools/tool.mdx | 6 +- .../concepts/pipelines/pipeline-loops.mdx | 18 ++- .../version-2.27/development/tracing.mdx | 71 +++++----- .../document-stores/arcadedbdocumentstore.mdx | 10 +- .../document-stores/valkeydocumentstore.mdx | 32 +++-- .../converters/imagefiletodocument.mdx | 1 - .../converters/imagefiletoimagecontent.mdx | 1 - .../converters/kreuzbergconverter.mdx | 4 +- .../converters/outputadapter.mdx | 1 - .../embedders/mistraltextembedder.mdx | 1 - .../fetchers/linkcontentfetcher.mdx | 8 +- .../generators/anthropicchatgenerator.mdx | 17 ++- .../choosing-the-right-generator.mdx | 1 - .../embeddingbaseddocumentsplitter.mdx | 1 - .../retrievers/arcadedbembeddingretriever.mdx | 20 ++- .../retrievers/azureaisearchbm25retriever.mdx | 1 - .../retrievers/elasticsearchbm25retriever.mdx | 1 - .../version-2.27/tools/tool.mdx | 6 +- .../concepts/pipelines/pipeline-loops.mdx | 18 ++- .../version-2.28/development/tracing.mdx | 71 +++++----- .../document-stores/arcadedbdocumentstore.mdx | 10 +- .../document-stores/valkeydocumentstore.mdx | 32 +++-- .../converters/imagefiletodocument.mdx | 1 - .../converters/imagefiletoimagecontent.mdx | 1 - .../converters/kreuzbergconverter.mdx | 4 +- .../converters/outputadapter.mdx | 1 - .../embedders/mistraltextembedder.mdx | 1 - .../fetchers/linkcontentfetcher.mdx | 8 +- .../generators/anthropicchatgenerator.mdx | 17 ++- .../generators/ollamachatgenerator.mdx | 6 +- .../generators/openaigenerator.mdx | 20 +-- .../embeddingbaseddocumentsplitter.mdx | 1 - .../retrievers/arcadedbembeddingretriever.mdx | 20 ++- .../retrievers/azureaisearchbm25retriever.mdx | 1 - .../retrievers/elasticsearchbm25retriever.mdx | 1 - .../version-2.28/tools/tool.mdx | 6 +- .../concepts/data-classes/filecontent.mdx | 4 +- .../concepts/pipelines/pipeline-loops.mdx | 18 ++- .../version-2.29/development/tracing.mdx | 71 +++++----- .../document-stores/arcadedbdocumentstore.mdx | 10 +- .../converters/imagefiletodocument.mdx | 1 - .../converters/imagefiletoimagecontent.mdx | 1 - .../converters/outputadapter.mdx | 1 - .../embedders/mistraltextembedder.mdx | 1 - .../generators/anthropicchatgenerator.mdx | 17 ++- .../embeddingbaseddocumentsplitter.mdx | 1 - .../retrievers/azureaisearchbm25retriever.mdx | 1 - .../retrievers/elasticsearchbm25retriever.mdx | 1 - .../version-2.29/tools/tool.mdx | 6 +- .../concepts/data-classes/filecontent.mdx | 4 +- .../concepts/pipelines/pipeline-loops.mdx | 18 ++- .../development/tracing/custom-tracer.mdx | 50 +++---- .../development/tracing/opentelemetry.mdx | 8 +- .../document-stores/arcadedbdocumentstore.mdx | 10 +- .../memory-stores/cogneememorystore.mdx | 4 +- .../memory-stores/mem0memorystore.mdx | 4 +- .../converters/imagefiletodocument.mdx | 1 - .../converters/imagefiletoimagecontent.mdx | 1 - .../converters/outputadapter.mdx | 1 - .../embedders/mistraltextembedder.mdx | 1 - .../generators/anthropicchatgenerator.mdx | 17 ++- .../anthropicfoundrychatgenerator.mdx | 18 ++- .../embeddingbaseddocumentsplitter.mdx | 1 - .../preprocessors/pythoncodesplitter.mdx | 10 +- .../retrievers/azureaisearchbm25retriever.mdx | 1 - .../retrievers/elasticsearchbm25retriever.mdx | 1 - .../retrievers/sqlalchemytableretriever.mdx | 12 +- .../writers/cogneewriter.mdx | 4 +- .../version-2.30/tools/tool.mdx | 6 +- .../concepts/data-classes/filecontent.mdx | 4 +- .../concepts/pipelines/pipeline-loops.mdx | 18 ++- .../development/tracing/custom-tracer.mdx | 50 +++---- .../development/tracing/opentelemetry.mdx | 8 +- .../document-stores/arcadedbdocumentstore.mdx | 10 +- .../memory-stores/cogneememorystore.mdx | 4 +- .../memory-stores/mem0memorystore.mdx | 4 +- .../converters/imagefiletodocument.mdx | 1 - .../converters/imagefiletoimagecontent.mdx | 1 - .../converters/outputadapter.mdx | 1 - .../embedders/mistraltextembedder.mdx | 1 - .../generators/anthropicchatgenerator.mdx | 17 ++- .../anthropicfoundrychatgenerator.mdx | 18 ++- .../embeddingbaseddocumentsplitter.mdx | 1 - .../preprocessors/pythoncodesplitter.mdx | 10 +- .../retrievers/azureaisearchbm25retriever.mdx | 1 - .../retrievers/elasticsearchbm25retriever.mdx | 1 - .../retrievers/elasticsearchsqlretriever.mdx | 4 +- .../retrievers/opensearchsqlretriever.mdx | 4 +- .../retrievers/sqlalchemytableretriever.mdx | 12 +- .../writers/cogneewriter.mdx | 4 +- .../version-2.31/tools/tool.mdx | 6 +- .../concepts/data-classes/filecontent.mdx | 4 +- .../concepts/pipelines/pipeline-loops.mdx | 18 ++- .../development/tracing/custom-tracer.mdx | 50 +++---- .../development/tracing/opentelemetry.mdx | 8 +- .../document-stores/arcadedbdocumentstore.mdx | 10 +- .../memory-stores/cogneememorystore.mdx | 4 +- .../memory-stores/mem0memorystore.mdx | 4 +- .../converters/imagefiletodocument.mdx | 1 - .../converters/imagefiletoimagecontent.mdx | 1 - .../converters/outputadapter.mdx | 1 - .../embedders/edenaidocumentembedder.mdx | 4 +- .../embedders/edenaitextembedder.mdx | 8 +- .../embedders/mistraltextembedder.mdx | 1 - .../generators/anthropicchatgenerator.mdx | 17 ++- .../anthropicfoundrychatgenerator.mdx | 18 ++- .../generators/edenaichatgenerator.mdx | 5 +- .../embeddingbaseddocumentsplitter.mdx | 1 - .../preprocessors/pythoncodesplitter.mdx | 10 +- .../retrievers/azureaisearchbm25retriever.mdx | 1 - .../retrievers/elasticsearchbm25retriever.mdx | 1 - .../retrievers/elasticsearchsqlretriever.mdx | 4 +- .../retrievers/opensearchsqlretriever.mdx | 4 +- .../retrievers/sqlalchemytableretriever.mdx | 12 +- .../writers/cogneewriter.mdx | 4 +- .../versioned_docs/version-3.0/tools/tool.mdx | 6 +- pyproject.toml | 4 +- scripts/ruff_format_docs.py | 128 ------------------ 261 files changed, 1535 insertions(+), 1129 deletions(-) create mode 100644 docs-website/ruff.toml delete mode 100644 scripts/ruff_format_docs.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f8ef28602f..2d64e3ca80 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -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 diff --git a/docs-website/docs/concepts/data-classes/filecontent.mdx b/docs-website/docs/concepts/data-classes/filecontent.mdx index 5f2c5f40a1..5b2a49136b 100644 --- a/docs-website/docs/concepts/data-classes/filecontent.mdx +++ b/docs-website/docs/concepts/data-classes/filecontent.mdx @@ -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) diff --git a/docs-website/docs/concepts/pipelines/pipeline-loops.mdx b/docs-website/docs/concepts/pipelines/pipeline-loops.mdx index 562cf6eb8f..ef07b0bcec 100644 --- a/docs-website/docs/concepts/pipelines/pipeline-loops.mdx +++ b/docs-website/docs/concepts/pipelines/pipeline-loops.mdx @@ -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. diff --git a/docs-website/docs/development/tracing/custom-tracer.mdx b/docs-website/docs/development/tracing/custom-tracer.mdx index a28d0461d0..31e47dab6f 100644 --- a/docs-website/docs/development/tracing/custom-tracer.mdx +++ b/docs-website/docs/development/tracing/custom-tracer.mdx @@ -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: diff --git a/docs-website/docs/development/tracing/opentelemetry.mdx b/docs-website/docs/development/tracing/opentelemetry.mdx index 8cf184b47c..de0ec4c247 100644 --- a/docs-website/docs/development/tracing/opentelemetry.mdx +++ b/docs-website/docs/development/tracing/opentelemetry.mdx @@ -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) diff --git a/docs-website/docs/document-stores/arcadedbdocumentstore.mdx b/docs-website/docs/document-stores/arcadedbdocumentstore.mdx index 1de48066de..12d251e270 100644 --- a/docs-website/docs/document-stores/arcadedbdocumentstore.mdx +++ b/docs-website/docs/document-stores/arcadedbdocumentstore.mdx @@ -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()) ``` diff --git a/docs-website/docs/memory-stores/cogneememorystore.mdx b/docs-website/docs/memory-stores/cogneememorystore.mdx index 691ae52c86..b036758a9b 100644 --- a/docs-website/docs/memory-stores/cogneememorystore.mdx +++ b/docs-website/docs/memory-stores/cogneememorystore.mdx @@ -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", ) diff --git a/docs-website/docs/memory-stores/mem0memorystore.mdx b/docs-website/docs/memory-stores/mem0memorystore.mdx index 199b0b5177..ce0537e0b4 100644 --- a/docs-website/docs/memory-stores/mem0memorystore.mdx +++ b/docs-website/docs/memory-stores/mem0memorystore.mdx @@ -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, diff --git a/docs-website/docs/pipeline-components/converters/imagefiletodocument.mdx b/docs-website/docs/pipeline-components/converters/imagefiletodocument.mdx index 0227f69972..0fc5698c71 100644 --- a/docs-website/docs/pipeline-components/converters/imagefiletodocument.mdx +++ b/docs-website/docs/pipeline-components/converters/imagefiletodocument.mdx @@ -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() diff --git a/docs-website/docs/pipeline-components/converters/imagefiletoimagecontent.mdx b/docs-website/docs/pipeline-components/converters/imagefiletoimagecontent.mdx index 1c8867a3d2..935ea4783f 100644 --- a/docs-website/docs/pipeline-components/converters/imagefiletoimagecontent.mdx +++ b/docs-website/docs/pipeline-components/converters/imagefiletoimagecontent.mdx @@ -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)) diff --git a/docs-website/docs/pipeline-components/converters/outputadapter.mdx b/docs-website/docs/pipeline-components/converters/outputadapter.mdx index 729f0ee82b..68b7e8eb0a 100644 --- a/docs-website/docs/pipeline-components/converters/outputadapter.mdx +++ b/docs-website/docs/pipeline-components/converters/outputadapter.mdx @@ -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 diff --git a/docs-website/docs/pipeline-components/embedders/edenaidocumentembedder.mdx b/docs-website/docs/pipeline-components/embedders/edenaidocumentembedder.mdx index da0d46b904..54d17ef60a 100644 --- a/docs-website/docs/pipeline-components/embedders/edenaidocumentembedder.mdx +++ b/docs-website/docs/pipeline-components/embedders/edenaidocumentembedder.mdx @@ -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") diff --git a/docs-website/docs/pipeline-components/embedders/edenaitextembedder.mdx b/docs-website/docs/pipeline-components/embedders/edenaitextembedder.mdx index 80a912be93..89cfa5ca4c 100644 --- a/docs-website/docs/pipeline-components/embedders/edenaitextembedder.mdx +++ b/docs-website/docs/pipeline-components/embedders/edenaitextembedder.mdx @@ -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?"}}) diff --git a/docs-website/docs/pipeline-components/embedders/mistraltextembedder.mdx b/docs-website/docs/pipeline-components/embedders/mistraltextembedder.mdx index bab018a749..97ce5775db 100644 --- a/docs-website/docs/pipeline-components/embedders/mistraltextembedder.mdx +++ b/docs-website/docs/pipeline-components/embedders/mistraltextembedder.mdx @@ -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, ) diff --git a/docs-website/docs/pipeline-components/generators/anthropicchatgenerator.mdx b/docs-website/docs/pipeline-components/generators/anthropicchatgenerator.mdx index fc4dc37e5e..866690da8f 100644 --- a/docs-website/docs/pipeline-components/generators/anthropicchatgenerator.mdx +++ b/docs-website/docs/pipeline-components/generators/anthropicchatgenerator.mdx @@ -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 diff --git a/docs-website/docs/pipeline-components/generators/anthropicfoundrychatgenerator.mdx b/docs-website/docs/pipeline-components/generators/anthropicfoundrychatgenerator.mdx index 6657e5654d..287f8efad3 100644 --- a/docs-website/docs/pipeline-components/generators/anthropicfoundrychatgenerator.mdx +++ b/docs-website/docs/pipeline-components/generators/anthropicfoundrychatgenerator.mdx @@ -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()) diff --git a/docs-website/docs/pipeline-components/generators/edenaichatgenerator.mdx b/docs-website/docs/pipeline-components/generators/edenaichatgenerator.mdx index 8cf6dac6a0..676ebc0050 100644 --- a/docs-website/docs/pipeline-components/generators/edenaichatgenerator.mdx +++ b/docs-website/docs/pipeline-components/generators/edenaichatgenerator.mdx @@ -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, + }, }, ) diff --git a/docs-website/docs/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx b/docs-website/docs/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx index 942436fe3f..3eba5bd091 100644 --- a/docs-website/docs/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx +++ b/docs-website/docs/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx @@ -43,7 +43,6 @@ pip install sentence-transformers-haystack ``` ```python - from haystack import Document from haystack_integrations.components.embedders.sentence_transformers import ( SentenceTransformersDocumentEmbedder, diff --git a/docs-website/docs/pipeline-components/preprocessors/pythoncodesplitter.mdx b/docs-website/docs/pipeline-components/preprocessors/pythoncodesplitter.mdx index f90c9eb61f..98dea51cf0 100644 --- a/docs-website/docs/pipeline-components/preprocessors/pythoncodesplitter.mdx +++ b/docs-website/docs/pipeline-components/preprocessors/pythoncodesplitter.mdx @@ -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")) diff --git a/docs-website/docs/pipeline-components/retrievers/azureaisearchbm25retriever.mdx b/docs-website/docs/pipeline-components/retrievers/azureaisearchbm25retriever.mdx index a04347b218..62dc9ab31d 100644 --- a/docs-website/docs/pipeline-components/retrievers/azureaisearchbm25retriever.mdx +++ b/docs-website/docs/pipeline-components/retrievers/azureaisearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/docs/pipeline-components/retrievers/elasticsearchbm25retriever.mdx b/docs-website/docs/pipeline-components/retrievers/elasticsearchbm25retriever.mdx index a02c6cbdfe..d1ec0b925a 100644 --- a/docs-website/docs/pipeline-components/retrievers/elasticsearchbm25retriever.mdx +++ b/docs-website/docs/pipeline-components/retrievers/elasticsearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/docs/pipeline-components/retrievers/elasticsearchsqlretriever.mdx b/docs-website/docs/pipeline-components/retrievers/elasticsearchsqlretriever.mdx index 23dde93a9d..7431fd00c4 100644 --- a/docs-website/docs/pipeline-components/retrievers/elasticsearchsqlretriever.mdx +++ b/docs-website/docs/pipeline-components/retrievers/elasticsearchsqlretriever.mdx @@ -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."), diff --git a/docs-website/docs/pipeline-components/retrievers/opensearchsqlretriever.mdx b/docs-website/docs/pipeline-components/retrievers/opensearchsqlretriever.mdx index c43cf09082..8e094d2264 100644 --- a/docs-website/docs/pipeline-components/retrievers/opensearchsqlretriever.mdx +++ b/docs-website/docs/pipeline-components/retrievers/opensearchsqlretriever.mdx @@ -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."), diff --git a/docs-website/docs/pipeline-components/retrievers/sqlalchemytableretriever.mdx b/docs-website/docs/pipeline-components/retrievers/sqlalchemytableretriever.mdx index b7c29b5e78..2fd64f3205 100644 --- a/docs-website/docs/pipeline-components/retrievers/sqlalchemytableretriever.mdx +++ b/docs-website/docs/pipeline-components/retrievers/sqlalchemytableretriever.mdx @@ -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", diff --git a/docs-website/docs/pipeline-components/writers/cogneewriter.mdx b/docs-website/docs/pipeline-components/writers/cogneewriter.mdx index 4e516268dd..dd01774cff 100644 --- a/docs-website/docs/pipeline-components/writers/cogneewriter.mdx +++ b/docs-website/docs/pipeline-components/writers/cogneewriter.mdx @@ -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", ) ``` diff --git a/docs-website/docs/tools/tool.mdx b/docs-website/docs/tools/tool.mdx index 1c6a8c1055..af7e591593 100644 --- a/docs-website/docs/tools/tool.mdx +++ b/docs-website/docs/tools/tool.mdx @@ -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, diff --git a/docs-website/ruff.toml b/docs-website/ruff.toml new file mode 100644 index 0000000000..88f4283d9a --- /dev/null +++ b/docs-website/ruff.toml @@ -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 diff --git a/docs-website/versioned_docs/version-2.18/concepts/secret-management.mdx b/docs-website/versioned_docs/version-2.18/concepts/secret-management.mdx index 7017cff0bd..511bb9bbd7 100644 --- a/docs-website/versioned_docs/version-2.18/concepts/secret-management.mdx +++ b/docs-website/versioned_docs/version-2.18/concepts/secret-management.mdx @@ -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() diff --git a/docs-website/versioned_docs/version-2.18/development/tracing.mdx b/docs-website/versioned_docs/version-2.18/development/tracing.mdx index ca75d94632..bdb39bb178 100644 --- a/docs-website/versioned_docs/version-2.18/development/tracing.mdx +++ b/docs-website/versioned_docs/version-2.18/development/tracing.mdx @@ -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) ``` diff --git a/docs-website/versioned_docs/version-2.18/pipeline-components/converters/imagefiletodocument.mdx b/docs-website/versioned_docs/version-2.18/pipeline-components/converters/imagefiletodocument.mdx index 0f91f1a1c8..fc6c0c81b3 100644 --- a/docs-website/versioned_docs/version-2.18/pipeline-components/converters/imagefiletodocument.mdx +++ b/docs-website/versioned_docs/version-2.18/pipeline-components/converters/imagefiletodocument.mdx @@ -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() diff --git a/docs-website/versioned_docs/version-2.18/pipeline-components/converters/imagefiletoimagecontent.mdx b/docs-website/versioned_docs/version-2.18/pipeline-components/converters/imagefiletoimagecontent.mdx index d827f285d1..a03c03f685 100644 --- a/docs-website/versioned_docs/version-2.18/pipeline-components/converters/imagefiletoimagecontent.mdx +++ b/docs-website/versioned_docs/version-2.18/pipeline-components/converters/imagefiletoimagecontent.mdx @@ -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)) diff --git a/docs-website/versioned_docs/version-2.18/pipeline-components/converters/outputadapter.mdx b/docs-website/versioned_docs/version-2.18/pipeline-components/converters/outputadapter.mdx index bc64158ec0..1d5fa8d31d 100644 --- a/docs-website/versioned_docs/version-2.18/pipeline-components/converters/outputadapter.mdx +++ b/docs-website/versioned_docs/version-2.18/pipeline-components/converters/outputadapter.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.18/pipeline-components/embedders/mistraltextembedder.mdx b/docs-website/versioned_docs/version-2.18/pipeline-components/embedders/mistraltextembedder.mdx index 48f63a22b1..bf0c17fe91 100644 --- a/docs-website/versioned_docs/version-2.18/pipeline-components/embedders/mistraltextembedder.mdx +++ b/docs-website/versioned_docs/version-2.18/pipeline-components/embedders/mistraltextembedder.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.18/pipeline-components/generators/anthropicchatgenerator.mdx b/docs-website/versioned_docs/version-2.18/pipeline-components/generators/anthropicchatgenerator.mdx index cbfc3d64ae..d8757a080f 100644 --- a/docs-website/versioned_docs/version-2.18/pipeline-components/generators/anthropicchatgenerator.mdx +++ b/docs-website/versioned_docs/version-2.18/pipeline-components/generators/anthropicchatgenerator.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.18/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx b/docs-website/versioned_docs/version-2.18/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx index da3e56bc2b..e388844007 100644 --- a/docs-website/versioned_docs/version-2.18/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx +++ b/docs-website/versioned_docs/version-2.18/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.18/pipeline-components/generators/vertexaicodegenerator.mdx b/docs-website/versioned_docs/version-2.18/pipeline-components/generators/vertexaicodegenerator.mdx index 7abc699f65..67597bd099 100644 --- a/docs-website/versioned_docs/version-2.18/pipeline-components/generators/vertexaicodegenerator.mdx +++ b/docs-website/versioned_docs/version-2.18/pipeline-components/generators/vertexaicodegenerator.mdx @@ -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. diff --git a/docs-website/versioned_docs/version-2.18/pipeline-components/generators/vertexaitextgenerator.mdx b/docs-website/versioned_docs/version-2.18/pipeline-components/generators/vertexaitextgenerator.mdx index 7b1819d0ee..3692890508 100644 --- a/docs-website/versioned_docs/version-2.18/pipeline-components/generators/vertexaitextgenerator.mdx +++ b/docs-website/versioned_docs/version-2.18/pipeline-components/generators/vertexaitextgenerator.mdx @@ -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). diff --git a/docs-website/versioned_docs/version-2.18/pipeline-components/retrievers/azureaisearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.18/pipeline-components/retrievers/azureaisearchbm25retriever.mdx index d690c92c19..70a174f3ea 100644 --- a/docs-website/versioned_docs/version-2.18/pipeline-components/retrievers/azureaisearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.18/pipeline-components/retrievers/azureaisearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.18/pipeline-components/retrievers/elasticsearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.18/pipeline-components/retrievers/elasticsearchbm25retriever.mdx index 2234b2275b..dd58720273 100644 --- a/docs-website/versioned_docs/version-2.18/pipeline-components/retrievers/elasticsearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.18/pipeline-components/retrievers/elasticsearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.19/concepts/secret-management.mdx b/docs-website/versioned_docs/version-2.19/concepts/secret-management.mdx index 7017cff0bd..511bb9bbd7 100644 --- a/docs-website/versioned_docs/version-2.19/concepts/secret-management.mdx +++ b/docs-website/versioned_docs/version-2.19/concepts/secret-management.mdx @@ -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() diff --git a/docs-website/versioned_docs/version-2.19/development/tracing.mdx b/docs-website/versioned_docs/version-2.19/development/tracing.mdx index ca75d94632..bdb39bb178 100644 --- a/docs-website/versioned_docs/version-2.19/development/tracing.mdx +++ b/docs-website/versioned_docs/version-2.19/development/tracing.mdx @@ -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) ``` diff --git a/docs-website/versioned_docs/version-2.19/pipeline-components/converters/imagefiletodocument.mdx b/docs-website/versioned_docs/version-2.19/pipeline-components/converters/imagefiletodocument.mdx index bad400c51d..8c3db584c9 100644 --- a/docs-website/versioned_docs/version-2.19/pipeline-components/converters/imagefiletodocument.mdx +++ b/docs-website/versioned_docs/version-2.19/pipeline-components/converters/imagefiletodocument.mdx @@ -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() diff --git a/docs-website/versioned_docs/version-2.19/pipeline-components/converters/imagefiletoimagecontent.mdx b/docs-website/versioned_docs/version-2.19/pipeline-components/converters/imagefiletoimagecontent.mdx index 37f941791d..87e367bc65 100644 --- a/docs-website/versioned_docs/version-2.19/pipeline-components/converters/imagefiletoimagecontent.mdx +++ b/docs-website/versioned_docs/version-2.19/pipeline-components/converters/imagefiletoimagecontent.mdx @@ -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)) diff --git a/docs-website/versioned_docs/version-2.19/pipeline-components/converters/outputadapter.mdx b/docs-website/versioned_docs/version-2.19/pipeline-components/converters/outputadapter.mdx index 8ddd451028..21c6018d5a 100644 --- a/docs-website/versioned_docs/version-2.19/pipeline-components/converters/outputadapter.mdx +++ b/docs-website/versioned_docs/version-2.19/pipeline-components/converters/outputadapter.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.19/pipeline-components/embedders/mistraltextembedder.mdx b/docs-website/versioned_docs/version-2.19/pipeline-components/embedders/mistraltextembedder.mdx index c2cd48c59a..dadad5329e 100644 --- a/docs-website/versioned_docs/version-2.19/pipeline-components/embedders/mistraltextembedder.mdx +++ b/docs-website/versioned_docs/version-2.19/pipeline-components/embedders/mistraltextembedder.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.19/pipeline-components/generators/anthropicchatgenerator.mdx b/docs-website/versioned_docs/version-2.19/pipeline-components/generators/anthropicchatgenerator.mdx index 2d54b2710c..e9d22a0907 100644 --- a/docs-website/versioned_docs/version-2.19/pipeline-components/generators/anthropicchatgenerator.mdx +++ b/docs-website/versioned_docs/version-2.19/pipeline-components/generators/anthropicchatgenerator.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.19/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx b/docs-website/versioned_docs/version-2.19/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx index da3e56bc2b..e388844007 100644 --- a/docs-website/versioned_docs/version-2.19/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx +++ b/docs-website/versioned_docs/version-2.19/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.19/pipeline-components/generators/vertexaicodegenerator.mdx b/docs-website/versioned_docs/version-2.19/pipeline-components/generators/vertexaicodegenerator.mdx index 39f5276596..5535f305ba 100644 --- a/docs-website/versioned_docs/version-2.19/pipeline-components/generators/vertexaicodegenerator.mdx +++ b/docs-website/versioned_docs/version-2.19/pipeline-components/generators/vertexaicodegenerator.mdx @@ -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. diff --git a/docs-website/versioned_docs/version-2.19/pipeline-components/generators/vertexaitextgenerator.mdx b/docs-website/versioned_docs/version-2.19/pipeline-components/generators/vertexaitextgenerator.mdx index 8b12265144..2e454705b3 100644 --- a/docs-website/versioned_docs/version-2.19/pipeline-components/generators/vertexaitextgenerator.mdx +++ b/docs-website/versioned_docs/version-2.19/pipeline-components/generators/vertexaitextgenerator.mdx @@ -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). diff --git a/docs-website/versioned_docs/version-2.19/pipeline-components/retrievers/azureaisearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.19/pipeline-components/retrievers/azureaisearchbm25retriever.mdx index 4b791bf930..e5e26ae3b3 100644 --- a/docs-website/versioned_docs/version-2.19/pipeline-components/retrievers/azureaisearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.19/pipeline-components/retrievers/azureaisearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.19/pipeline-components/retrievers/elasticsearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.19/pipeline-components/retrievers/elasticsearchbm25retriever.mdx index 5493e709e8..d4a0b3d747 100644 --- a/docs-website/versioned_docs/version-2.19/pipeline-components/retrievers/elasticsearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.19/pipeline-components/retrievers/elasticsearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.20/concepts/pipelines/pipeline-loops.mdx b/docs-website/versioned_docs/version-2.20/concepts/pipelines/pipeline-loops.mdx index 04c0796655..49d5c3ed35 100644 --- a/docs-website/versioned_docs/version-2.20/concepts/pipelines/pipeline-loops.mdx +++ b/docs-website/versioned_docs/version-2.20/concepts/pipelines/pipeline-loops.mdx @@ -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. diff --git a/docs-website/versioned_docs/version-2.20/concepts/secret-management.mdx b/docs-website/versioned_docs/version-2.20/concepts/secret-management.mdx index 7017cff0bd..511bb9bbd7 100644 --- a/docs-website/versioned_docs/version-2.20/concepts/secret-management.mdx +++ b/docs-website/versioned_docs/version-2.20/concepts/secret-management.mdx @@ -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() diff --git a/docs-website/versioned_docs/version-2.20/development/tracing.mdx b/docs-website/versioned_docs/version-2.20/development/tracing.mdx index 0f54e7f362..15365650b5 100644 --- a/docs-website/versioned_docs/version-2.20/development/tracing.mdx +++ b/docs-website/versioned_docs/version-2.20/development/tracing.mdx @@ -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) ``` diff --git a/docs-website/versioned_docs/version-2.20/pipeline-components/converters/imagefiletodocument.mdx b/docs-website/versioned_docs/version-2.20/pipeline-components/converters/imagefiletodocument.mdx index efdf7b2559..b5e178cbcc 100644 --- a/docs-website/versioned_docs/version-2.20/pipeline-components/converters/imagefiletodocument.mdx +++ b/docs-website/versioned_docs/version-2.20/pipeline-components/converters/imagefiletodocument.mdx @@ -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() diff --git a/docs-website/versioned_docs/version-2.20/pipeline-components/converters/imagefiletoimagecontent.mdx b/docs-website/versioned_docs/version-2.20/pipeline-components/converters/imagefiletoimagecontent.mdx index 88fe3c4b17..0e0328e522 100644 --- a/docs-website/versioned_docs/version-2.20/pipeline-components/converters/imagefiletoimagecontent.mdx +++ b/docs-website/versioned_docs/version-2.20/pipeline-components/converters/imagefiletoimagecontent.mdx @@ -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)) diff --git a/docs-website/versioned_docs/version-2.20/pipeline-components/converters/outputadapter.mdx b/docs-website/versioned_docs/version-2.20/pipeline-components/converters/outputadapter.mdx index 8ddd451028..21c6018d5a 100644 --- a/docs-website/versioned_docs/version-2.20/pipeline-components/converters/outputadapter.mdx +++ b/docs-website/versioned_docs/version-2.20/pipeline-components/converters/outputadapter.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.20/pipeline-components/embedders/mistraltextembedder.mdx b/docs-website/versioned_docs/version-2.20/pipeline-components/embedders/mistraltextembedder.mdx index c2cd48c59a..dadad5329e 100644 --- a/docs-website/versioned_docs/version-2.20/pipeline-components/embedders/mistraltextembedder.mdx +++ b/docs-website/versioned_docs/version-2.20/pipeline-components/embedders/mistraltextembedder.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.20/pipeline-components/generators/anthropicchatgenerator.mdx b/docs-website/versioned_docs/version-2.20/pipeline-components/generators/anthropicchatgenerator.mdx index 788fb1cd50..566301f72e 100644 --- a/docs-website/versioned_docs/version-2.20/pipeline-components/generators/anthropicchatgenerator.mdx +++ b/docs-website/versioned_docs/version-2.20/pipeline-components/generators/anthropicchatgenerator.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.20/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx b/docs-website/versioned_docs/version-2.20/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx index da3e56bc2b..e388844007 100644 --- a/docs-website/versioned_docs/version-2.20/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx +++ b/docs-website/versioned_docs/version-2.20/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.20/pipeline-components/retrievers/azureaisearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.20/pipeline-components/retrievers/azureaisearchbm25retriever.mdx index fbe7834c56..3faac75cd2 100644 --- a/docs-website/versioned_docs/version-2.20/pipeline-components/retrievers/azureaisearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.20/pipeline-components/retrievers/azureaisearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.20/pipeline-components/retrievers/elasticsearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.20/pipeline-components/retrievers/elasticsearchbm25retriever.mdx index 5588e8cbc2..29500e7bd0 100644 --- a/docs-website/versioned_docs/version-2.20/pipeline-components/retrievers/elasticsearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.20/pipeline-components/retrievers/elasticsearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.21/concepts/pipelines/pipeline-loops.mdx b/docs-website/versioned_docs/version-2.21/concepts/pipelines/pipeline-loops.mdx index 04c0796655..49d5c3ed35 100644 --- a/docs-website/versioned_docs/version-2.21/concepts/pipelines/pipeline-loops.mdx +++ b/docs-website/versioned_docs/version-2.21/concepts/pipelines/pipeline-loops.mdx @@ -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. diff --git a/docs-website/versioned_docs/version-2.21/concepts/secret-management.mdx b/docs-website/versioned_docs/version-2.21/concepts/secret-management.mdx index 7017cff0bd..511bb9bbd7 100644 --- a/docs-website/versioned_docs/version-2.21/concepts/secret-management.mdx +++ b/docs-website/versioned_docs/version-2.21/concepts/secret-management.mdx @@ -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() diff --git a/docs-website/versioned_docs/version-2.21/development/tracing.mdx b/docs-website/versioned_docs/version-2.21/development/tracing.mdx index 0f54e7f362..15365650b5 100644 --- a/docs-website/versioned_docs/version-2.21/development/tracing.mdx +++ b/docs-website/versioned_docs/version-2.21/development/tracing.mdx @@ -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) ``` diff --git a/docs-website/versioned_docs/version-2.21/pipeline-components/converters/imagefiletodocument.mdx b/docs-website/versioned_docs/version-2.21/pipeline-components/converters/imagefiletodocument.mdx index efdf7b2559..b5e178cbcc 100644 --- a/docs-website/versioned_docs/version-2.21/pipeline-components/converters/imagefiletodocument.mdx +++ b/docs-website/versioned_docs/version-2.21/pipeline-components/converters/imagefiletodocument.mdx @@ -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() diff --git a/docs-website/versioned_docs/version-2.21/pipeline-components/converters/imagefiletoimagecontent.mdx b/docs-website/versioned_docs/version-2.21/pipeline-components/converters/imagefiletoimagecontent.mdx index 88fe3c4b17..0e0328e522 100644 --- a/docs-website/versioned_docs/version-2.21/pipeline-components/converters/imagefiletoimagecontent.mdx +++ b/docs-website/versioned_docs/version-2.21/pipeline-components/converters/imagefiletoimagecontent.mdx @@ -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)) diff --git a/docs-website/versioned_docs/version-2.21/pipeline-components/converters/outputadapter.mdx b/docs-website/versioned_docs/version-2.21/pipeline-components/converters/outputadapter.mdx index 8ddd451028..21c6018d5a 100644 --- a/docs-website/versioned_docs/version-2.21/pipeline-components/converters/outputadapter.mdx +++ b/docs-website/versioned_docs/version-2.21/pipeline-components/converters/outputadapter.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.21/pipeline-components/embedders/mistraltextembedder.mdx b/docs-website/versioned_docs/version-2.21/pipeline-components/embedders/mistraltextembedder.mdx index c2cd48c59a..dadad5329e 100644 --- a/docs-website/versioned_docs/version-2.21/pipeline-components/embedders/mistraltextembedder.mdx +++ b/docs-website/versioned_docs/version-2.21/pipeline-components/embedders/mistraltextembedder.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.21/pipeline-components/generators/anthropicchatgenerator.mdx b/docs-website/versioned_docs/version-2.21/pipeline-components/generators/anthropicchatgenerator.mdx index 788fb1cd50..566301f72e 100644 --- a/docs-website/versioned_docs/version-2.21/pipeline-components/generators/anthropicchatgenerator.mdx +++ b/docs-website/versioned_docs/version-2.21/pipeline-components/generators/anthropicchatgenerator.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.21/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx b/docs-website/versioned_docs/version-2.21/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx index da3e56bc2b..e388844007 100644 --- a/docs-website/versioned_docs/version-2.21/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx +++ b/docs-website/versioned_docs/version-2.21/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.21/pipeline-components/retrievers/azureaisearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.21/pipeline-components/retrievers/azureaisearchbm25retriever.mdx index fbe7834c56..3faac75cd2 100644 --- a/docs-website/versioned_docs/version-2.21/pipeline-components/retrievers/azureaisearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.21/pipeline-components/retrievers/azureaisearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.21/pipeline-components/retrievers/elasticsearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.21/pipeline-components/retrievers/elasticsearchbm25retriever.mdx index 5588e8cbc2..29500e7bd0 100644 --- a/docs-website/versioned_docs/version-2.21/pipeline-components/retrievers/elasticsearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.21/pipeline-components/retrievers/elasticsearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.22/concepts/pipelines/pipeline-loops.mdx b/docs-website/versioned_docs/version-2.22/concepts/pipelines/pipeline-loops.mdx index 04c0796655..49d5c3ed35 100644 --- a/docs-website/versioned_docs/version-2.22/concepts/pipelines/pipeline-loops.mdx +++ b/docs-website/versioned_docs/version-2.22/concepts/pipelines/pipeline-loops.mdx @@ -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. diff --git a/docs-website/versioned_docs/version-2.22/concepts/secret-management.mdx b/docs-website/versioned_docs/version-2.22/concepts/secret-management.mdx index 7017cff0bd..511bb9bbd7 100644 --- a/docs-website/versioned_docs/version-2.22/concepts/secret-management.mdx +++ b/docs-website/versioned_docs/version-2.22/concepts/secret-management.mdx @@ -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() diff --git a/docs-website/versioned_docs/version-2.22/development/tracing.mdx b/docs-website/versioned_docs/version-2.22/development/tracing.mdx index 0f54e7f362..15365650b5 100644 --- a/docs-website/versioned_docs/version-2.22/development/tracing.mdx +++ b/docs-website/versioned_docs/version-2.22/development/tracing.mdx @@ -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) ``` diff --git a/docs-website/versioned_docs/version-2.22/pipeline-components/converters/imagefiletodocument.mdx b/docs-website/versioned_docs/version-2.22/pipeline-components/converters/imagefiletodocument.mdx index efdf7b2559..b5e178cbcc 100644 --- a/docs-website/versioned_docs/version-2.22/pipeline-components/converters/imagefiletodocument.mdx +++ b/docs-website/versioned_docs/version-2.22/pipeline-components/converters/imagefiletodocument.mdx @@ -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() diff --git a/docs-website/versioned_docs/version-2.22/pipeline-components/converters/imagefiletoimagecontent.mdx b/docs-website/versioned_docs/version-2.22/pipeline-components/converters/imagefiletoimagecontent.mdx index 88fe3c4b17..0e0328e522 100644 --- a/docs-website/versioned_docs/version-2.22/pipeline-components/converters/imagefiletoimagecontent.mdx +++ b/docs-website/versioned_docs/version-2.22/pipeline-components/converters/imagefiletoimagecontent.mdx @@ -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)) diff --git a/docs-website/versioned_docs/version-2.22/pipeline-components/converters/outputadapter.mdx b/docs-website/versioned_docs/version-2.22/pipeline-components/converters/outputadapter.mdx index 8ddd451028..21c6018d5a 100644 --- a/docs-website/versioned_docs/version-2.22/pipeline-components/converters/outputadapter.mdx +++ b/docs-website/versioned_docs/version-2.22/pipeline-components/converters/outputadapter.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.22/pipeline-components/embedders/mistraltextembedder.mdx b/docs-website/versioned_docs/version-2.22/pipeline-components/embedders/mistraltextembedder.mdx index c2cd48c59a..dadad5329e 100644 --- a/docs-website/versioned_docs/version-2.22/pipeline-components/embedders/mistraltextembedder.mdx +++ b/docs-website/versioned_docs/version-2.22/pipeline-components/embedders/mistraltextembedder.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.22/pipeline-components/generators/anthropicchatgenerator.mdx b/docs-website/versioned_docs/version-2.22/pipeline-components/generators/anthropicchatgenerator.mdx index 788fb1cd50..566301f72e 100644 --- a/docs-website/versioned_docs/version-2.22/pipeline-components/generators/anthropicchatgenerator.mdx +++ b/docs-website/versioned_docs/version-2.22/pipeline-components/generators/anthropicchatgenerator.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.22/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx b/docs-website/versioned_docs/version-2.22/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx index da3e56bc2b..e388844007 100644 --- a/docs-website/versioned_docs/version-2.22/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx +++ b/docs-website/versioned_docs/version-2.22/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.22/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx b/docs-website/versioned_docs/version-2.22/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx index 7759dec447..e1a8ee843d 100644 --- a/docs-website/versioned_docs/version-2.22/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx +++ b/docs-website/versioned_docs/version-2.22/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.22/pipeline-components/retrievers/azureaisearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.22/pipeline-components/retrievers/azureaisearchbm25retriever.mdx index fbe7834c56..3faac75cd2 100644 --- a/docs-website/versioned_docs/version-2.22/pipeline-components/retrievers/azureaisearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.22/pipeline-components/retrievers/azureaisearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.22/pipeline-components/retrievers/elasticsearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.22/pipeline-components/retrievers/elasticsearchbm25retriever.mdx index 5588e8cbc2..29500e7bd0 100644 --- a/docs-website/versioned_docs/version-2.22/pipeline-components/retrievers/elasticsearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.22/pipeline-components/retrievers/elasticsearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.23/concepts/pipelines/pipeline-loops.mdx b/docs-website/versioned_docs/version-2.23/concepts/pipelines/pipeline-loops.mdx index 04c0796655..49d5c3ed35 100644 --- a/docs-website/versioned_docs/version-2.23/concepts/pipelines/pipeline-loops.mdx +++ b/docs-website/versioned_docs/version-2.23/concepts/pipelines/pipeline-loops.mdx @@ -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. diff --git a/docs-website/versioned_docs/version-2.23/concepts/secret-management.mdx b/docs-website/versioned_docs/version-2.23/concepts/secret-management.mdx index 7017cff0bd..511bb9bbd7 100644 --- a/docs-website/versioned_docs/version-2.23/concepts/secret-management.mdx +++ b/docs-website/versioned_docs/version-2.23/concepts/secret-management.mdx @@ -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() diff --git a/docs-website/versioned_docs/version-2.23/development/tracing.mdx b/docs-website/versioned_docs/version-2.23/development/tracing.mdx index 0f54e7f362..15365650b5 100644 --- a/docs-website/versioned_docs/version-2.23/development/tracing.mdx +++ b/docs-website/versioned_docs/version-2.23/development/tracing.mdx @@ -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) ``` diff --git a/docs-website/versioned_docs/version-2.23/pipeline-components/converters/imagefiletodocument.mdx b/docs-website/versioned_docs/version-2.23/pipeline-components/converters/imagefiletodocument.mdx index efdf7b2559..b5e178cbcc 100644 --- a/docs-website/versioned_docs/version-2.23/pipeline-components/converters/imagefiletodocument.mdx +++ b/docs-website/versioned_docs/version-2.23/pipeline-components/converters/imagefiletodocument.mdx @@ -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() diff --git a/docs-website/versioned_docs/version-2.23/pipeline-components/converters/imagefiletoimagecontent.mdx b/docs-website/versioned_docs/version-2.23/pipeline-components/converters/imagefiletoimagecontent.mdx index 88fe3c4b17..0e0328e522 100644 --- a/docs-website/versioned_docs/version-2.23/pipeline-components/converters/imagefiletoimagecontent.mdx +++ b/docs-website/versioned_docs/version-2.23/pipeline-components/converters/imagefiletoimagecontent.mdx @@ -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)) diff --git a/docs-website/versioned_docs/version-2.23/pipeline-components/converters/outputadapter.mdx b/docs-website/versioned_docs/version-2.23/pipeline-components/converters/outputadapter.mdx index 8ddd451028..21c6018d5a 100644 --- a/docs-website/versioned_docs/version-2.23/pipeline-components/converters/outputadapter.mdx +++ b/docs-website/versioned_docs/version-2.23/pipeline-components/converters/outputadapter.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.23/pipeline-components/embedders/mistraltextembedder.mdx b/docs-website/versioned_docs/version-2.23/pipeline-components/embedders/mistraltextembedder.mdx index c2cd48c59a..dadad5329e 100644 --- a/docs-website/versioned_docs/version-2.23/pipeline-components/embedders/mistraltextembedder.mdx +++ b/docs-website/versioned_docs/version-2.23/pipeline-components/embedders/mistraltextembedder.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.23/pipeline-components/generators/anthropicchatgenerator.mdx b/docs-website/versioned_docs/version-2.23/pipeline-components/generators/anthropicchatgenerator.mdx index 788fb1cd50..566301f72e 100644 --- a/docs-website/versioned_docs/version-2.23/pipeline-components/generators/anthropicchatgenerator.mdx +++ b/docs-website/versioned_docs/version-2.23/pipeline-components/generators/anthropicchatgenerator.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.23/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx b/docs-website/versioned_docs/version-2.23/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx index da3e56bc2b..e388844007 100644 --- a/docs-website/versioned_docs/version-2.23/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx +++ b/docs-website/versioned_docs/version-2.23/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.23/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx b/docs-website/versioned_docs/version-2.23/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx index 7759dec447..e1a8ee843d 100644 --- a/docs-website/versioned_docs/version-2.23/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx +++ b/docs-website/versioned_docs/version-2.23/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.23/pipeline-components/retrievers/azureaisearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.23/pipeline-components/retrievers/azureaisearchbm25retriever.mdx index fbe7834c56..3faac75cd2 100644 --- a/docs-website/versioned_docs/version-2.23/pipeline-components/retrievers/azureaisearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.23/pipeline-components/retrievers/azureaisearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.23/pipeline-components/retrievers/elasticsearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.23/pipeline-components/retrievers/elasticsearchbm25retriever.mdx index 5588e8cbc2..29500e7bd0 100644 --- a/docs-website/versioned_docs/version-2.23/pipeline-components/retrievers/elasticsearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.23/pipeline-components/retrievers/elasticsearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.23/tools/tool.mdx b/docs-website/versioned_docs/version-2.23/tools/tool.mdx index 72f5e3a917..1248cdaef3 100644 --- a/docs-website/versioned_docs/version-2.23/tools/tool.mdx +++ b/docs-website/versioned_docs/version-2.23/tools/tool.mdx @@ -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, diff --git a/docs-website/versioned_docs/version-2.24/concepts/pipelines/pipeline-loops.mdx b/docs-website/versioned_docs/version-2.24/concepts/pipelines/pipeline-loops.mdx index 04c0796655..49d5c3ed35 100644 --- a/docs-website/versioned_docs/version-2.24/concepts/pipelines/pipeline-loops.mdx +++ b/docs-website/versioned_docs/version-2.24/concepts/pipelines/pipeline-loops.mdx @@ -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. diff --git a/docs-website/versioned_docs/version-2.24/development/tracing.mdx b/docs-website/versioned_docs/version-2.24/development/tracing.mdx index 0f54e7f362..15365650b5 100644 --- a/docs-website/versioned_docs/version-2.24/development/tracing.mdx +++ b/docs-website/versioned_docs/version-2.24/development/tracing.mdx @@ -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) ``` diff --git a/docs-website/versioned_docs/version-2.24/document-stores/valkeydocumentstore.mdx b/docs-website/versioned_docs/version-2.24/document-stores/valkeydocumentstore.mdx index 66b607fad3..fa15ace1f1 100644 --- a/docs-website/versioned_docs/version-2.24/document-stores/valkeydocumentstore.mdx +++ b/docs-website/versioned_docs/version-2.24/document-stores/valkeydocumentstore.mdx @@ -39,7 +39,7 @@ document_store = ValkeyDocumentStore( nodes_list=[("localhost", 6379)], index_name="my_documents", embedding_dim=768, - distance_metric="cosine" + distance_metric="cosine", ) ``` @@ -73,12 +73,14 @@ document_store = ValkeyDocumentStore( nodes_list=[("localhost", 6379)], index_name="my_documents", embedding_dim=768, - distance_metric="cosine" + distance_metric="cosine", ) indexing = Pipeline() indexing.add_component("converter", MarkdownToDocument()) -indexing.add_component("splitter", DocumentSplitter(split_by="sentence", split_length=2)) +indexing.add_component( + "splitter", DocumentSplitter(split_by="sentence", split_length=2) +) indexing.add_component("embedder", SentenceTransformersDocumentEmbedder()) indexing.add_component("writer", DocumentWriter(document_store)) indexing.connect("converter", "splitter") @@ -106,11 +108,13 @@ document_store = ValkeyDocumentStore( nodes_list=[("localhost", 6379)], index_name="my_documents", embedding_dim=768, - distance_metric="cosine" + distance_metric="cosine", ) prompt_template = [ - ChatMessage.from_system("Answer the question based on the provided context. If the context does not include an answer, reply with 'I don't know'."), + ChatMessage.from_system( + "Answer the question based on the provided context. If the context does not include an answer, reply with 'I don't know'." + ), ChatMessage.from_user( "Query: {{query}}\n" "Documents:\n{% for doc in documents %}{{ doc.content }}\n{% endfor %}\n" @@ -120,9 +124,21 @@ prompt_template = [ query_pipeline = Pipeline() query_pipeline.add_component("text_embedder", SentenceTransformersTextEmbedder()) -query_pipeline.add_component("retriever", ValkeyEmbeddingRetriever(document_store=document_store)) -query_pipeline.add_component("prompt_builder", ChatPromptBuilder(template=prompt_template, required_variables=["query", "documents"])) -query_pipeline.add_component("generator", OpenAIChatGenerator(api_key=Secret.from_token("YOUR_OPENAI_API_KEY"), model="gpt-4o")) +query_pipeline.add_component( + "retriever", ValkeyEmbeddingRetriever(document_store=document_store) +) +query_pipeline.add_component( + "prompt_builder", + ChatPromptBuilder( + template=prompt_template, required_variables=["query", "documents"] + ), +) +query_pipeline.add_component( + "generator", + OpenAIChatGenerator( + api_key=Secret.from_token("YOUR_OPENAI_API_KEY"), model="gpt-4o" + ), +) query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding") query_pipeline.connect("retriever.documents", "prompt_builder.documents") query_pipeline.connect("prompt_builder.messages", "generator.messages") diff --git a/docs-website/versioned_docs/version-2.24/pipeline-components/converters/imagefiletodocument.mdx b/docs-website/versioned_docs/version-2.24/pipeline-components/converters/imagefiletodocument.mdx index efdf7b2559..b5e178cbcc 100644 --- a/docs-website/versioned_docs/version-2.24/pipeline-components/converters/imagefiletodocument.mdx +++ b/docs-website/versioned_docs/version-2.24/pipeline-components/converters/imagefiletodocument.mdx @@ -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() diff --git a/docs-website/versioned_docs/version-2.24/pipeline-components/converters/imagefiletoimagecontent.mdx b/docs-website/versioned_docs/version-2.24/pipeline-components/converters/imagefiletoimagecontent.mdx index 88fe3c4b17..0e0328e522 100644 --- a/docs-website/versioned_docs/version-2.24/pipeline-components/converters/imagefiletoimagecontent.mdx +++ b/docs-website/versioned_docs/version-2.24/pipeline-components/converters/imagefiletoimagecontent.mdx @@ -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)) diff --git a/docs-website/versioned_docs/version-2.24/pipeline-components/converters/outputadapter.mdx b/docs-website/versioned_docs/version-2.24/pipeline-components/converters/outputadapter.mdx index 8ddd451028..21c6018d5a 100644 --- a/docs-website/versioned_docs/version-2.24/pipeline-components/converters/outputadapter.mdx +++ b/docs-website/versioned_docs/version-2.24/pipeline-components/converters/outputadapter.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.24/pipeline-components/embedders/mistraltextembedder.mdx b/docs-website/versioned_docs/version-2.24/pipeline-components/embedders/mistraltextembedder.mdx index c2cd48c59a..dadad5329e 100644 --- a/docs-website/versioned_docs/version-2.24/pipeline-components/embedders/mistraltextembedder.mdx +++ b/docs-website/versioned_docs/version-2.24/pipeline-components/embedders/mistraltextembedder.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.24/pipeline-components/generators/anthropicchatgenerator.mdx b/docs-website/versioned_docs/version-2.24/pipeline-components/generators/anthropicchatgenerator.mdx index 788fb1cd50..566301f72e 100644 --- a/docs-website/versioned_docs/version-2.24/pipeline-components/generators/anthropicchatgenerator.mdx +++ b/docs-website/versioned_docs/version-2.24/pipeline-components/generators/anthropicchatgenerator.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.24/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx b/docs-website/versioned_docs/version-2.24/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx index da3e56bc2b..e388844007 100644 --- a/docs-website/versioned_docs/version-2.24/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx +++ b/docs-website/versioned_docs/version-2.24/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.24/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx b/docs-website/versioned_docs/version-2.24/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx index 7759dec447..e1a8ee843d 100644 --- a/docs-website/versioned_docs/version-2.24/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx +++ b/docs-website/versioned_docs/version-2.24/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.24/pipeline-components/retrievers/azureaisearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.24/pipeline-components/retrievers/azureaisearchbm25retriever.mdx index fbe7834c56..3faac75cd2 100644 --- a/docs-website/versioned_docs/version-2.24/pipeline-components/retrievers/azureaisearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.24/pipeline-components/retrievers/azureaisearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.24/pipeline-components/retrievers/elasticsearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.24/pipeline-components/retrievers/elasticsearchbm25retriever.mdx index 5588e8cbc2..29500e7bd0 100644 --- a/docs-website/versioned_docs/version-2.24/pipeline-components/retrievers/elasticsearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.24/pipeline-components/retrievers/elasticsearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.24/tools/tool.mdx b/docs-website/versioned_docs/version-2.24/tools/tool.mdx index 72f5e3a917..1248cdaef3 100644 --- a/docs-website/versioned_docs/version-2.24/tools/tool.mdx +++ b/docs-website/versioned_docs/version-2.24/tools/tool.mdx @@ -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, diff --git a/docs-website/versioned_docs/version-2.25/concepts/pipelines/pipeline-loops.mdx b/docs-website/versioned_docs/version-2.25/concepts/pipelines/pipeline-loops.mdx index 04c0796655..49d5c3ed35 100644 --- a/docs-website/versioned_docs/version-2.25/concepts/pipelines/pipeline-loops.mdx +++ b/docs-website/versioned_docs/version-2.25/concepts/pipelines/pipeline-loops.mdx @@ -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. diff --git a/docs-website/versioned_docs/version-2.25/development/tracing.mdx b/docs-website/versioned_docs/version-2.25/development/tracing.mdx index 91f946dbc7..12dfbb7782 100644 --- a/docs-website/versioned_docs/version-2.25/development/tracing.mdx +++ b/docs-website/versioned_docs/version-2.25/development/tracing.mdx @@ -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 @@ -175,36 +180,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: @@ -297,12 +306,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) ``` diff --git a/docs-website/versioned_docs/version-2.25/document-stores/arcadedbdocumentstore.mdx b/docs-website/versioned_docs/version-2.25/document-stores/arcadedbdocumentstore.mdx index 1de48066de..12d251e270 100644 --- a/docs-website/versioned_docs/version-2.25/document-stores/arcadedbdocumentstore.mdx +++ b/docs-website/versioned_docs/version-2.25/document-stores/arcadedbdocumentstore.mdx @@ -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()) ``` diff --git a/docs-website/versioned_docs/version-2.25/document-stores/valkeydocumentstore.mdx b/docs-website/versioned_docs/version-2.25/document-stores/valkeydocumentstore.mdx index 66b607fad3..fa15ace1f1 100644 --- a/docs-website/versioned_docs/version-2.25/document-stores/valkeydocumentstore.mdx +++ b/docs-website/versioned_docs/version-2.25/document-stores/valkeydocumentstore.mdx @@ -39,7 +39,7 @@ document_store = ValkeyDocumentStore( nodes_list=[("localhost", 6379)], index_name="my_documents", embedding_dim=768, - distance_metric="cosine" + distance_metric="cosine", ) ``` @@ -73,12 +73,14 @@ document_store = ValkeyDocumentStore( nodes_list=[("localhost", 6379)], index_name="my_documents", embedding_dim=768, - distance_metric="cosine" + distance_metric="cosine", ) indexing = Pipeline() indexing.add_component("converter", MarkdownToDocument()) -indexing.add_component("splitter", DocumentSplitter(split_by="sentence", split_length=2)) +indexing.add_component( + "splitter", DocumentSplitter(split_by="sentence", split_length=2) +) indexing.add_component("embedder", SentenceTransformersDocumentEmbedder()) indexing.add_component("writer", DocumentWriter(document_store)) indexing.connect("converter", "splitter") @@ -106,11 +108,13 @@ document_store = ValkeyDocumentStore( nodes_list=[("localhost", 6379)], index_name="my_documents", embedding_dim=768, - distance_metric="cosine" + distance_metric="cosine", ) prompt_template = [ - ChatMessage.from_system("Answer the question based on the provided context. If the context does not include an answer, reply with 'I don't know'."), + ChatMessage.from_system( + "Answer the question based on the provided context. If the context does not include an answer, reply with 'I don't know'." + ), ChatMessage.from_user( "Query: {{query}}\n" "Documents:\n{% for doc in documents %}{{ doc.content }}\n{% endfor %}\n" @@ -120,9 +124,21 @@ prompt_template = [ query_pipeline = Pipeline() query_pipeline.add_component("text_embedder", SentenceTransformersTextEmbedder()) -query_pipeline.add_component("retriever", ValkeyEmbeddingRetriever(document_store=document_store)) -query_pipeline.add_component("prompt_builder", ChatPromptBuilder(template=prompt_template, required_variables=["query", "documents"])) -query_pipeline.add_component("generator", OpenAIChatGenerator(api_key=Secret.from_token("YOUR_OPENAI_API_KEY"), model="gpt-4o")) +query_pipeline.add_component( + "retriever", ValkeyEmbeddingRetriever(document_store=document_store) +) +query_pipeline.add_component( + "prompt_builder", + ChatPromptBuilder( + template=prompt_template, required_variables=["query", "documents"] + ), +) +query_pipeline.add_component( + "generator", + OpenAIChatGenerator( + api_key=Secret.from_token("YOUR_OPENAI_API_KEY"), model="gpt-4o" + ), +) query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding") query_pipeline.connect("retriever.documents", "prompt_builder.documents") query_pipeline.connect("prompt_builder.messages", "generator.messages") diff --git a/docs-website/versioned_docs/version-2.25/pipeline-components/converters/imagefiletodocument.mdx b/docs-website/versioned_docs/version-2.25/pipeline-components/converters/imagefiletodocument.mdx index efdf7b2559..b5e178cbcc 100644 --- a/docs-website/versioned_docs/version-2.25/pipeline-components/converters/imagefiletodocument.mdx +++ b/docs-website/versioned_docs/version-2.25/pipeline-components/converters/imagefiletodocument.mdx @@ -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() diff --git a/docs-website/versioned_docs/version-2.25/pipeline-components/converters/imagefiletoimagecontent.mdx b/docs-website/versioned_docs/version-2.25/pipeline-components/converters/imagefiletoimagecontent.mdx index 88fe3c4b17..0e0328e522 100644 --- a/docs-website/versioned_docs/version-2.25/pipeline-components/converters/imagefiletoimagecontent.mdx +++ b/docs-website/versioned_docs/version-2.25/pipeline-components/converters/imagefiletoimagecontent.mdx @@ -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)) diff --git a/docs-website/versioned_docs/version-2.25/pipeline-components/converters/outputadapter.mdx b/docs-website/versioned_docs/version-2.25/pipeline-components/converters/outputadapter.mdx index 8ddd451028..21c6018d5a 100644 --- a/docs-website/versioned_docs/version-2.25/pipeline-components/converters/outputadapter.mdx +++ b/docs-website/versioned_docs/version-2.25/pipeline-components/converters/outputadapter.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.25/pipeline-components/embedders/mistraltextembedder.mdx b/docs-website/versioned_docs/version-2.25/pipeline-components/embedders/mistraltextembedder.mdx index c2cd48c59a..dadad5329e 100644 --- a/docs-website/versioned_docs/version-2.25/pipeline-components/embedders/mistraltextembedder.mdx +++ b/docs-website/versioned_docs/version-2.25/pipeline-components/embedders/mistraltextembedder.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.25/pipeline-components/fetchers/linkcontentfetcher.mdx b/docs-website/versioned_docs/version-2.25/pipeline-components/fetchers/linkcontentfetcher.mdx index 3634c1facc..4b5410a7cc 100644 --- a/docs-website/versioned_docs/version-2.25/pipeline-components/fetchers/linkcontentfetcher.mdx +++ b/docs-website/versioned_docs/version-2.25/pipeline-components/fetchers/linkcontentfetcher.mdx @@ -69,7 +69,13 @@ def is_unsafe_url(url: str) -> bool: except ValueError: # Hostname (not a raw IP). Apply your own domain allowlist policy here. Filter out "LOCALHOST" etc. return False - return ip.is_private or ip.is_loopback or ip.is_link_local or ip.is_reserved or any(ip in net for net in PRIVATE_RANGES) + return ( + ip.is_private + or ip.is_loopback + or ip.is_link_local + or ip.is_reserved + or any(ip in net for net in PRIVATE_RANGES) + ) ``` diff --git a/docs-website/versioned_docs/version-2.25/pipeline-components/generators/anthropicchatgenerator.mdx b/docs-website/versioned_docs/version-2.25/pipeline-components/generators/anthropicchatgenerator.mdx index 788fb1cd50..566301f72e 100644 --- a/docs-website/versioned_docs/version-2.25/pipeline-components/generators/anthropicchatgenerator.mdx +++ b/docs-website/versioned_docs/version-2.25/pipeline-components/generators/anthropicchatgenerator.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.25/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx b/docs-website/versioned_docs/version-2.25/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx index da3e56bc2b..e388844007 100644 --- a/docs-website/versioned_docs/version-2.25/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx +++ b/docs-website/versioned_docs/version-2.25/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.25/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx b/docs-website/versioned_docs/version-2.25/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx index bdcb52ece1..1d579d6da5 100644 --- a/docs-website/versioned_docs/version-2.25/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx +++ b/docs-website/versioned_docs/version-2.25/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.25/pipeline-components/retrievers/arcadedbembeddingretriever.mdx b/docs-website/versioned_docs/version-2.25/pipeline-components/retrievers/arcadedbembeddingretriever.mdx index 42c3c77400..2610aafdfc 100644 --- a/docs-website/versioned_docs/version-2.25/pipeline-components/retrievers/arcadedbembeddingretriever.mdx +++ b/docs-website/versioned_docs/version-2.25/pipeline-components/retrievers/arcadedbembeddingretriever.mdx @@ -40,7 +40,9 @@ Ensure ArcadeDB is running, for example via Docker, and credentials are set (`AR ```python from haystack_integrations.document_stores.arcadedb import ArcadeDBDocumentStore -from haystack_integrations.components.retrievers.arcadedb import ArcadeDBEmbeddingRetriever +from haystack_integrations.components.retrievers.arcadedb import ( + ArcadeDBEmbeddingRetriever, +) document_store = ArcadeDBDocumentStore( url="http://localhost:2480", @@ -65,7 +67,9 @@ from haystack.components.embedders import ( SentenceTransformersDocumentEmbedder, ) from haystack_integrations.document_stores.arcadedb import ArcadeDBDocumentStore -from haystack_integrations.components.retrievers.arcadedb import ArcadeDBEmbeddingRetriever +from haystack_integrations.components.retrievers.arcadedb import ( + ArcadeDBEmbeddingRetriever, +) document_store = ArcadeDBDocumentStore( url="http://localhost:2480", @@ -76,8 +80,12 @@ document_store = ArcadeDBDocumentStore( documents = [ Document(content="There are over 7,000 languages spoken around the world today."), - Document(content="Elephants have been observed to recognize themselves in mirrors."), - Document(content="Bioluminescent waves can be seen in the Maldives and Puerto Rico."), + Document( + content="Elephants have been observed to recognize themselves in mirrors." + ), + Document( + content="Bioluminescent waves can be seen in the Maldives and Puerto Rico." + ), ] document_embedder = SentenceTransformersDocumentEmbedder() @@ -95,6 +103,8 @@ query_pipeline.add_component( ) query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding") -result = query_pipeline.run({"text_embedder": {"text": "How many languages are there?"}}) +result = query_pipeline.run( + {"text_embedder": {"text": "How many languages are there?"}} +) print(result["retriever"]["documents"][0]) ``` diff --git a/docs-website/versioned_docs/version-2.25/pipeline-components/retrievers/azureaisearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.25/pipeline-components/retrievers/azureaisearchbm25retriever.mdx index fbe7834c56..3faac75cd2 100644 --- a/docs-website/versioned_docs/version-2.25/pipeline-components/retrievers/azureaisearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.25/pipeline-components/retrievers/azureaisearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.25/pipeline-components/retrievers/elasticsearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.25/pipeline-components/retrievers/elasticsearchbm25retriever.mdx index 5588e8cbc2..29500e7bd0 100644 --- a/docs-website/versioned_docs/version-2.25/pipeline-components/retrievers/elasticsearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.25/pipeline-components/retrievers/elasticsearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.25/tools/tool.mdx b/docs-website/versioned_docs/version-2.25/tools/tool.mdx index 72f5e3a917..1248cdaef3 100644 --- a/docs-website/versioned_docs/version-2.25/tools/tool.mdx +++ b/docs-website/versioned_docs/version-2.25/tools/tool.mdx @@ -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, diff --git a/docs-website/versioned_docs/version-2.26/concepts/pipelines/pipeline-loops.mdx b/docs-website/versioned_docs/version-2.26/concepts/pipelines/pipeline-loops.mdx index 04c0796655..49d5c3ed35 100644 --- a/docs-website/versioned_docs/version-2.26/concepts/pipelines/pipeline-loops.mdx +++ b/docs-website/versioned_docs/version-2.26/concepts/pipelines/pipeline-loops.mdx @@ -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. diff --git a/docs-website/versioned_docs/version-2.26/development/tracing.mdx b/docs-website/versioned_docs/version-2.26/development/tracing.mdx index 91f946dbc7..12dfbb7782 100644 --- a/docs-website/versioned_docs/version-2.26/development/tracing.mdx +++ b/docs-website/versioned_docs/version-2.26/development/tracing.mdx @@ -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 @@ -175,36 +180,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: @@ -297,12 +306,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) ``` diff --git a/docs-website/versioned_docs/version-2.26/document-stores/arcadedbdocumentstore.mdx b/docs-website/versioned_docs/version-2.26/document-stores/arcadedbdocumentstore.mdx index 1de48066de..12d251e270 100644 --- a/docs-website/versioned_docs/version-2.26/document-stores/arcadedbdocumentstore.mdx +++ b/docs-website/versioned_docs/version-2.26/document-stores/arcadedbdocumentstore.mdx @@ -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()) ``` diff --git a/docs-website/versioned_docs/version-2.26/document-stores/valkeydocumentstore.mdx b/docs-website/versioned_docs/version-2.26/document-stores/valkeydocumentstore.mdx index 66b607fad3..fa15ace1f1 100644 --- a/docs-website/versioned_docs/version-2.26/document-stores/valkeydocumentstore.mdx +++ b/docs-website/versioned_docs/version-2.26/document-stores/valkeydocumentstore.mdx @@ -39,7 +39,7 @@ document_store = ValkeyDocumentStore( nodes_list=[("localhost", 6379)], index_name="my_documents", embedding_dim=768, - distance_metric="cosine" + distance_metric="cosine", ) ``` @@ -73,12 +73,14 @@ document_store = ValkeyDocumentStore( nodes_list=[("localhost", 6379)], index_name="my_documents", embedding_dim=768, - distance_metric="cosine" + distance_metric="cosine", ) indexing = Pipeline() indexing.add_component("converter", MarkdownToDocument()) -indexing.add_component("splitter", DocumentSplitter(split_by="sentence", split_length=2)) +indexing.add_component( + "splitter", DocumentSplitter(split_by="sentence", split_length=2) +) indexing.add_component("embedder", SentenceTransformersDocumentEmbedder()) indexing.add_component("writer", DocumentWriter(document_store)) indexing.connect("converter", "splitter") @@ -106,11 +108,13 @@ document_store = ValkeyDocumentStore( nodes_list=[("localhost", 6379)], index_name="my_documents", embedding_dim=768, - distance_metric="cosine" + distance_metric="cosine", ) prompt_template = [ - ChatMessage.from_system("Answer the question based on the provided context. If the context does not include an answer, reply with 'I don't know'."), + ChatMessage.from_system( + "Answer the question based on the provided context. If the context does not include an answer, reply with 'I don't know'." + ), ChatMessage.from_user( "Query: {{query}}\n" "Documents:\n{% for doc in documents %}{{ doc.content }}\n{% endfor %}\n" @@ -120,9 +124,21 @@ prompt_template = [ query_pipeline = Pipeline() query_pipeline.add_component("text_embedder", SentenceTransformersTextEmbedder()) -query_pipeline.add_component("retriever", ValkeyEmbeddingRetriever(document_store=document_store)) -query_pipeline.add_component("prompt_builder", ChatPromptBuilder(template=prompt_template, required_variables=["query", "documents"])) -query_pipeline.add_component("generator", OpenAIChatGenerator(api_key=Secret.from_token("YOUR_OPENAI_API_KEY"), model="gpt-4o")) +query_pipeline.add_component( + "retriever", ValkeyEmbeddingRetriever(document_store=document_store) +) +query_pipeline.add_component( + "prompt_builder", + ChatPromptBuilder( + template=prompt_template, required_variables=["query", "documents"] + ), +) +query_pipeline.add_component( + "generator", + OpenAIChatGenerator( + api_key=Secret.from_token("YOUR_OPENAI_API_KEY"), model="gpt-4o" + ), +) query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding") query_pipeline.connect("retriever.documents", "prompt_builder.documents") query_pipeline.connect("prompt_builder.messages", "generator.messages") diff --git a/docs-website/versioned_docs/version-2.26/pipeline-components/converters/imagefiletodocument.mdx b/docs-website/versioned_docs/version-2.26/pipeline-components/converters/imagefiletodocument.mdx index efdf7b2559..b5e178cbcc 100644 --- a/docs-website/versioned_docs/version-2.26/pipeline-components/converters/imagefiletodocument.mdx +++ b/docs-website/versioned_docs/version-2.26/pipeline-components/converters/imagefiletodocument.mdx @@ -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() diff --git a/docs-website/versioned_docs/version-2.26/pipeline-components/converters/imagefiletoimagecontent.mdx b/docs-website/versioned_docs/version-2.26/pipeline-components/converters/imagefiletoimagecontent.mdx index 88fe3c4b17..0e0328e522 100644 --- a/docs-website/versioned_docs/version-2.26/pipeline-components/converters/imagefiletoimagecontent.mdx +++ b/docs-website/versioned_docs/version-2.26/pipeline-components/converters/imagefiletoimagecontent.mdx @@ -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)) diff --git a/docs-website/versioned_docs/version-2.26/pipeline-components/converters/kreuzbergconverter.mdx b/docs-website/versioned_docs/version-2.26/pipeline-components/converters/kreuzbergconverter.mdx index 19659f2eed..6e3fa31050 100644 --- a/docs-website/versioned_docs/version-2.26/pipeline-components/converters/kreuzbergconverter.mdx +++ b/docs-website/versioned_docs/version-2.26/pipeline-components/converters/kreuzbergconverter.mdx @@ -70,7 +70,9 @@ document_store = InMemoryDocumentStore() pipeline = Pipeline() pipeline.add_component("converter", KreuzbergConverter()) -pipeline.add_component("splitter", DocumentSplitter(split_by="sentence", split_length=5)) +pipeline.add_component( + "splitter", DocumentSplitter(split_by="sentence", split_length=5) +) pipeline.add_component("writer", DocumentWriter(document_store=document_store)) pipeline.connect("converter", "splitter") diff --git a/docs-website/versioned_docs/version-2.26/pipeline-components/converters/outputadapter.mdx b/docs-website/versioned_docs/version-2.26/pipeline-components/converters/outputadapter.mdx index 8ddd451028..21c6018d5a 100644 --- a/docs-website/versioned_docs/version-2.26/pipeline-components/converters/outputadapter.mdx +++ b/docs-website/versioned_docs/version-2.26/pipeline-components/converters/outputadapter.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.26/pipeline-components/embedders/mistraltextembedder.mdx b/docs-website/versioned_docs/version-2.26/pipeline-components/embedders/mistraltextembedder.mdx index c2cd48c59a..dadad5329e 100644 --- a/docs-website/versioned_docs/version-2.26/pipeline-components/embedders/mistraltextembedder.mdx +++ b/docs-website/versioned_docs/version-2.26/pipeline-components/embedders/mistraltextembedder.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.26/pipeline-components/fetchers/linkcontentfetcher.mdx b/docs-website/versioned_docs/version-2.26/pipeline-components/fetchers/linkcontentfetcher.mdx index 3634c1facc..4b5410a7cc 100644 --- a/docs-website/versioned_docs/version-2.26/pipeline-components/fetchers/linkcontentfetcher.mdx +++ b/docs-website/versioned_docs/version-2.26/pipeline-components/fetchers/linkcontentfetcher.mdx @@ -69,7 +69,13 @@ def is_unsafe_url(url: str) -> bool: except ValueError: # Hostname (not a raw IP). Apply your own domain allowlist policy here. Filter out "LOCALHOST" etc. return False - return ip.is_private or ip.is_loopback or ip.is_link_local or ip.is_reserved or any(ip in net for net in PRIVATE_RANGES) + return ( + ip.is_private + or ip.is_loopback + or ip.is_link_local + or ip.is_reserved + or any(ip in net for net in PRIVATE_RANGES) + ) ``` diff --git a/docs-website/versioned_docs/version-2.26/pipeline-components/generators/anthropicchatgenerator.mdx b/docs-website/versioned_docs/version-2.26/pipeline-components/generators/anthropicchatgenerator.mdx index 788fb1cd50..566301f72e 100644 --- a/docs-website/versioned_docs/version-2.26/pipeline-components/generators/anthropicchatgenerator.mdx +++ b/docs-website/versioned_docs/version-2.26/pipeline-components/generators/anthropicchatgenerator.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.26/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx b/docs-website/versioned_docs/version-2.26/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx index da3e56bc2b..e388844007 100644 --- a/docs-website/versioned_docs/version-2.26/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx +++ b/docs-website/versioned_docs/version-2.26/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.26/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx b/docs-website/versioned_docs/version-2.26/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx index bdcb52ece1..1d579d6da5 100644 --- a/docs-website/versioned_docs/version-2.26/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx +++ b/docs-website/versioned_docs/version-2.26/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.26/pipeline-components/retrievers/arcadedbembeddingretriever.mdx b/docs-website/versioned_docs/version-2.26/pipeline-components/retrievers/arcadedbembeddingretriever.mdx index 42c3c77400..2610aafdfc 100644 --- a/docs-website/versioned_docs/version-2.26/pipeline-components/retrievers/arcadedbembeddingretriever.mdx +++ b/docs-website/versioned_docs/version-2.26/pipeline-components/retrievers/arcadedbembeddingretriever.mdx @@ -40,7 +40,9 @@ Ensure ArcadeDB is running, for example via Docker, and credentials are set (`AR ```python from haystack_integrations.document_stores.arcadedb import ArcadeDBDocumentStore -from haystack_integrations.components.retrievers.arcadedb import ArcadeDBEmbeddingRetriever +from haystack_integrations.components.retrievers.arcadedb import ( + ArcadeDBEmbeddingRetriever, +) document_store = ArcadeDBDocumentStore( url="http://localhost:2480", @@ -65,7 +67,9 @@ from haystack.components.embedders import ( SentenceTransformersDocumentEmbedder, ) from haystack_integrations.document_stores.arcadedb import ArcadeDBDocumentStore -from haystack_integrations.components.retrievers.arcadedb import ArcadeDBEmbeddingRetriever +from haystack_integrations.components.retrievers.arcadedb import ( + ArcadeDBEmbeddingRetriever, +) document_store = ArcadeDBDocumentStore( url="http://localhost:2480", @@ -76,8 +80,12 @@ document_store = ArcadeDBDocumentStore( documents = [ Document(content="There are over 7,000 languages spoken around the world today."), - Document(content="Elephants have been observed to recognize themselves in mirrors."), - Document(content="Bioluminescent waves can be seen in the Maldives and Puerto Rico."), + Document( + content="Elephants have been observed to recognize themselves in mirrors." + ), + Document( + content="Bioluminescent waves can be seen in the Maldives and Puerto Rico." + ), ] document_embedder = SentenceTransformersDocumentEmbedder() @@ -95,6 +103,8 @@ query_pipeline.add_component( ) query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding") -result = query_pipeline.run({"text_embedder": {"text": "How many languages are there?"}}) +result = query_pipeline.run( + {"text_embedder": {"text": "How many languages are there?"}} +) print(result["retriever"]["documents"][0]) ``` diff --git a/docs-website/versioned_docs/version-2.26/pipeline-components/retrievers/azureaisearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.26/pipeline-components/retrievers/azureaisearchbm25retriever.mdx index fbe7834c56..3faac75cd2 100644 --- a/docs-website/versioned_docs/version-2.26/pipeline-components/retrievers/azureaisearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.26/pipeline-components/retrievers/azureaisearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.26/pipeline-components/retrievers/elasticsearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.26/pipeline-components/retrievers/elasticsearchbm25retriever.mdx index 5588e8cbc2..29500e7bd0 100644 --- a/docs-website/versioned_docs/version-2.26/pipeline-components/retrievers/elasticsearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.26/pipeline-components/retrievers/elasticsearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.26/tools/tool.mdx b/docs-website/versioned_docs/version-2.26/tools/tool.mdx index 72f5e3a917..1248cdaef3 100644 --- a/docs-website/versioned_docs/version-2.26/tools/tool.mdx +++ b/docs-website/versioned_docs/version-2.26/tools/tool.mdx @@ -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, diff --git a/docs-website/versioned_docs/version-2.27/concepts/pipelines/pipeline-loops.mdx b/docs-website/versioned_docs/version-2.27/concepts/pipelines/pipeline-loops.mdx index 04c0796655..49d5c3ed35 100644 --- a/docs-website/versioned_docs/version-2.27/concepts/pipelines/pipeline-loops.mdx +++ b/docs-website/versioned_docs/version-2.27/concepts/pipelines/pipeline-loops.mdx @@ -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. diff --git a/docs-website/versioned_docs/version-2.27/development/tracing.mdx b/docs-website/versioned_docs/version-2.27/development/tracing.mdx index 91f946dbc7..12dfbb7782 100644 --- a/docs-website/versioned_docs/version-2.27/development/tracing.mdx +++ b/docs-website/versioned_docs/version-2.27/development/tracing.mdx @@ -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 @@ -175,36 +180,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: @@ -297,12 +306,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) ``` diff --git a/docs-website/versioned_docs/version-2.27/document-stores/arcadedbdocumentstore.mdx b/docs-website/versioned_docs/version-2.27/document-stores/arcadedbdocumentstore.mdx index 1de48066de..12d251e270 100644 --- a/docs-website/versioned_docs/version-2.27/document-stores/arcadedbdocumentstore.mdx +++ b/docs-website/versioned_docs/version-2.27/document-stores/arcadedbdocumentstore.mdx @@ -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()) ``` diff --git a/docs-website/versioned_docs/version-2.27/document-stores/valkeydocumentstore.mdx b/docs-website/versioned_docs/version-2.27/document-stores/valkeydocumentstore.mdx index 66b607fad3..fa15ace1f1 100644 --- a/docs-website/versioned_docs/version-2.27/document-stores/valkeydocumentstore.mdx +++ b/docs-website/versioned_docs/version-2.27/document-stores/valkeydocumentstore.mdx @@ -39,7 +39,7 @@ document_store = ValkeyDocumentStore( nodes_list=[("localhost", 6379)], index_name="my_documents", embedding_dim=768, - distance_metric="cosine" + distance_metric="cosine", ) ``` @@ -73,12 +73,14 @@ document_store = ValkeyDocumentStore( nodes_list=[("localhost", 6379)], index_name="my_documents", embedding_dim=768, - distance_metric="cosine" + distance_metric="cosine", ) indexing = Pipeline() indexing.add_component("converter", MarkdownToDocument()) -indexing.add_component("splitter", DocumentSplitter(split_by="sentence", split_length=2)) +indexing.add_component( + "splitter", DocumentSplitter(split_by="sentence", split_length=2) +) indexing.add_component("embedder", SentenceTransformersDocumentEmbedder()) indexing.add_component("writer", DocumentWriter(document_store)) indexing.connect("converter", "splitter") @@ -106,11 +108,13 @@ document_store = ValkeyDocumentStore( nodes_list=[("localhost", 6379)], index_name="my_documents", embedding_dim=768, - distance_metric="cosine" + distance_metric="cosine", ) prompt_template = [ - ChatMessage.from_system("Answer the question based on the provided context. If the context does not include an answer, reply with 'I don't know'."), + ChatMessage.from_system( + "Answer the question based on the provided context. If the context does not include an answer, reply with 'I don't know'." + ), ChatMessage.from_user( "Query: {{query}}\n" "Documents:\n{% for doc in documents %}{{ doc.content }}\n{% endfor %}\n" @@ -120,9 +124,21 @@ prompt_template = [ query_pipeline = Pipeline() query_pipeline.add_component("text_embedder", SentenceTransformersTextEmbedder()) -query_pipeline.add_component("retriever", ValkeyEmbeddingRetriever(document_store=document_store)) -query_pipeline.add_component("prompt_builder", ChatPromptBuilder(template=prompt_template, required_variables=["query", "documents"])) -query_pipeline.add_component("generator", OpenAIChatGenerator(api_key=Secret.from_token("YOUR_OPENAI_API_KEY"), model="gpt-4o")) +query_pipeline.add_component( + "retriever", ValkeyEmbeddingRetriever(document_store=document_store) +) +query_pipeline.add_component( + "prompt_builder", + ChatPromptBuilder( + template=prompt_template, required_variables=["query", "documents"] + ), +) +query_pipeline.add_component( + "generator", + OpenAIChatGenerator( + api_key=Secret.from_token("YOUR_OPENAI_API_KEY"), model="gpt-4o" + ), +) query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding") query_pipeline.connect("retriever.documents", "prompt_builder.documents") query_pipeline.connect("prompt_builder.messages", "generator.messages") diff --git a/docs-website/versioned_docs/version-2.27/pipeline-components/converters/imagefiletodocument.mdx b/docs-website/versioned_docs/version-2.27/pipeline-components/converters/imagefiletodocument.mdx index efdf7b2559..b5e178cbcc 100644 --- a/docs-website/versioned_docs/version-2.27/pipeline-components/converters/imagefiletodocument.mdx +++ b/docs-website/versioned_docs/version-2.27/pipeline-components/converters/imagefiletodocument.mdx @@ -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() diff --git a/docs-website/versioned_docs/version-2.27/pipeline-components/converters/imagefiletoimagecontent.mdx b/docs-website/versioned_docs/version-2.27/pipeline-components/converters/imagefiletoimagecontent.mdx index 88fe3c4b17..0e0328e522 100644 --- a/docs-website/versioned_docs/version-2.27/pipeline-components/converters/imagefiletoimagecontent.mdx +++ b/docs-website/versioned_docs/version-2.27/pipeline-components/converters/imagefiletoimagecontent.mdx @@ -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)) diff --git a/docs-website/versioned_docs/version-2.27/pipeline-components/converters/kreuzbergconverter.mdx b/docs-website/versioned_docs/version-2.27/pipeline-components/converters/kreuzbergconverter.mdx index 19659f2eed..6e3fa31050 100644 --- a/docs-website/versioned_docs/version-2.27/pipeline-components/converters/kreuzbergconverter.mdx +++ b/docs-website/versioned_docs/version-2.27/pipeline-components/converters/kreuzbergconverter.mdx @@ -70,7 +70,9 @@ document_store = InMemoryDocumentStore() pipeline = Pipeline() pipeline.add_component("converter", KreuzbergConverter()) -pipeline.add_component("splitter", DocumentSplitter(split_by="sentence", split_length=5)) +pipeline.add_component( + "splitter", DocumentSplitter(split_by="sentence", split_length=5) +) pipeline.add_component("writer", DocumentWriter(document_store=document_store)) pipeline.connect("converter", "splitter") diff --git a/docs-website/versioned_docs/version-2.27/pipeline-components/converters/outputadapter.mdx b/docs-website/versioned_docs/version-2.27/pipeline-components/converters/outputadapter.mdx index 8ddd451028..21c6018d5a 100644 --- a/docs-website/versioned_docs/version-2.27/pipeline-components/converters/outputadapter.mdx +++ b/docs-website/versioned_docs/version-2.27/pipeline-components/converters/outputadapter.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.27/pipeline-components/embedders/mistraltextembedder.mdx b/docs-website/versioned_docs/version-2.27/pipeline-components/embedders/mistraltextembedder.mdx index c2cd48c59a..dadad5329e 100644 --- a/docs-website/versioned_docs/version-2.27/pipeline-components/embedders/mistraltextembedder.mdx +++ b/docs-website/versioned_docs/version-2.27/pipeline-components/embedders/mistraltextembedder.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.27/pipeline-components/fetchers/linkcontentfetcher.mdx b/docs-website/versioned_docs/version-2.27/pipeline-components/fetchers/linkcontentfetcher.mdx index 3634c1facc..4b5410a7cc 100644 --- a/docs-website/versioned_docs/version-2.27/pipeline-components/fetchers/linkcontentfetcher.mdx +++ b/docs-website/versioned_docs/version-2.27/pipeline-components/fetchers/linkcontentfetcher.mdx @@ -69,7 +69,13 @@ def is_unsafe_url(url: str) -> bool: except ValueError: # Hostname (not a raw IP). Apply your own domain allowlist policy here. Filter out "LOCALHOST" etc. return False - return ip.is_private or ip.is_loopback or ip.is_link_local or ip.is_reserved or any(ip in net for net in PRIVATE_RANGES) + return ( + ip.is_private + or ip.is_loopback + or ip.is_link_local + or ip.is_reserved + or any(ip in net for net in PRIVATE_RANGES) + ) ``` diff --git a/docs-website/versioned_docs/version-2.27/pipeline-components/generators/anthropicchatgenerator.mdx b/docs-website/versioned_docs/version-2.27/pipeline-components/generators/anthropicchatgenerator.mdx index 788fb1cd50..566301f72e 100644 --- a/docs-website/versioned_docs/version-2.27/pipeline-components/generators/anthropicchatgenerator.mdx +++ b/docs-website/versioned_docs/version-2.27/pipeline-components/generators/anthropicchatgenerator.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.27/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx b/docs-website/versioned_docs/version-2.27/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx index da3e56bc2b..e388844007 100644 --- a/docs-website/versioned_docs/version-2.27/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx +++ b/docs-website/versioned_docs/version-2.27/pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.27/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx b/docs-website/versioned_docs/version-2.27/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx index bdcb52ece1..1d579d6da5 100644 --- a/docs-website/versioned_docs/version-2.27/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx +++ b/docs-website/versioned_docs/version-2.27/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.27/pipeline-components/retrievers/arcadedbembeddingretriever.mdx b/docs-website/versioned_docs/version-2.27/pipeline-components/retrievers/arcadedbembeddingretriever.mdx index 42c3c77400..2610aafdfc 100644 --- a/docs-website/versioned_docs/version-2.27/pipeline-components/retrievers/arcadedbembeddingretriever.mdx +++ b/docs-website/versioned_docs/version-2.27/pipeline-components/retrievers/arcadedbembeddingretriever.mdx @@ -40,7 +40,9 @@ Ensure ArcadeDB is running, for example via Docker, and credentials are set (`AR ```python from haystack_integrations.document_stores.arcadedb import ArcadeDBDocumentStore -from haystack_integrations.components.retrievers.arcadedb import ArcadeDBEmbeddingRetriever +from haystack_integrations.components.retrievers.arcadedb import ( + ArcadeDBEmbeddingRetriever, +) document_store = ArcadeDBDocumentStore( url="http://localhost:2480", @@ -65,7 +67,9 @@ from haystack.components.embedders import ( SentenceTransformersDocumentEmbedder, ) from haystack_integrations.document_stores.arcadedb import ArcadeDBDocumentStore -from haystack_integrations.components.retrievers.arcadedb import ArcadeDBEmbeddingRetriever +from haystack_integrations.components.retrievers.arcadedb import ( + ArcadeDBEmbeddingRetriever, +) document_store = ArcadeDBDocumentStore( url="http://localhost:2480", @@ -76,8 +80,12 @@ document_store = ArcadeDBDocumentStore( documents = [ Document(content="There are over 7,000 languages spoken around the world today."), - Document(content="Elephants have been observed to recognize themselves in mirrors."), - Document(content="Bioluminescent waves can be seen in the Maldives and Puerto Rico."), + Document( + content="Elephants have been observed to recognize themselves in mirrors." + ), + Document( + content="Bioluminescent waves can be seen in the Maldives and Puerto Rico." + ), ] document_embedder = SentenceTransformersDocumentEmbedder() @@ -95,6 +103,8 @@ query_pipeline.add_component( ) query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding") -result = query_pipeline.run({"text_embedder": {"text": "How many languages are there?"}}) +result = query_pipeline.run( + {"text_embedder": {"text": "How many languages are there?"}} +) print(result["retriever"]["documents"][0]) ``` diff --git a/docs-website/versioned_docs/version-2.27/pipeline-components/retrievers/azureaisearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.27/pipeline-components/retrievers/azureaisearchbm25retriever.mdx index fbe7834c56..3faac75cd2 100644 --- a/docs-website/versioned_docs/version-2.27/pipeline-components/retrievers/azureaisearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.27/pipeline-components/retrievers/azureaisearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.27/pipeline-components/retrievers/elasticsearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.27/pipeline-components/retrievers/elasticsearchbm25retriever.mdx index 5588e8cbc2..29500e7bd0 100644 --- a/docs-website/versioned_docs/version-2.27/pipeline-components/retrievers/elasticsearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.27/pipeline-components/retrievers/elasticsearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.27/tools/tool.mdx b/docs-website/versioned_docs/version-2.27/tools/tool.mdx index 72f5e3a917..1248cdaef3 100644 --- a/docs-website/versioned_docs/version-2.27/tools/tool.mdx +++ b/docs-website/versioned_docs/version-2.27/tools/tool.mdx @@ -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, diff --git a/docs-website/versioned_docs/version-2.28/concepts/pipelines/pipeline-loops.mdx b/docs-website/versioned_docs/version-2.28/concepts/pipelines/pipeline-loops.mdx index 04c0796655..49d5c3ed35 100644 --- a/docs-website/versioned_docs/version-2.28/concepts/pipelines/pipeline-loops.mdx +++ b/docs-website/versioned_docs/version-2.28/concepts/pipelines/pipeline-loops.mdx @@ -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. diff --git a/docs-website/versioned_docs/version-2.28/development/tracing.mdx b/docs-website/versioned_docs/version-2.28/development/tracing.mdx index 91f946dbc7..12dfbb7782 100644 --- a/docs-website/versioned_docs/version-2.28/development/tracing.mdx +++ b/docs-website/versioned_docs/version-2.28/development/tracing.mdx @@ -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 @@ -175,36 +180,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: @@ -297,12 +306,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) ``` diff --git a/docs-website/versioned_docs/version-2.28/document-stores/arcadedbdocumentstore.mdx b/docs-website/versioned_docs/version-2.28/document-stores/arcadedbdocumentstore.mdx index 1de48066de..12d251e270 100644 --- a/docs-website/versioned_docs/version-2.28/document-stores/arcadedbdocumentstore.mdx +++ b/docs-website/versioned_docs/version-2.28/document-stores/arcadedbdocumentstore.mdx @@ -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()) ``` diff --git a/docs-website/versioned_docs/version-2.28/document-stores/valkeydocumentstore.mdx b/docs-website/versioned_docs/version-2.28/document-stores/valkeydocumentstore.mdx index 66b607fad3..fa15ace1f1 100644 --- a/docs-website/versioned_docs/version-2.28/document-stores/valkeydocumentstore.mdx +++ b/docs-website/versioned_docs/version-2.28/document-stores/valkeydocumentstore.mdx @@ -39,7 +39,7 @@ document_store = ValkeyDocumentStore( nodes_list=[("localhost", 6379)], index_name="my_documents", embedding_dim=768, - distance_metric="cosine" + distance_metric="cosine", ) ``` @@ -73,12 +73,14 @@ document_store = ValkeyDocumentStore( nodes_list=[("localhost", 6379)], index_name="my_documents", embedding_dim=768, - distance_metric="cosine" + distance_metric="cosine", ) indexing = Pipeline() indexing.add_component("converter", MarkdownToDocument()) -indexing.add_component("splitter", DocumentSplitter(split_by="sentence", split_length=2)) +indexing.add_component( + "splitter", DocumentSplitter(split_by="sentence", split_length=2) +) indexing.add_component("embedder", SentenceTransformersDocumentEmbedder()) indexing.add_component("writer", DocumentWriter(document_store)) indexing.connect("converter", "splitter") @@ -106,11 +108,13 @@ document_store = ValkeyDocumentStore( nodes_list=[("localhost", 6379)], index_name="my_documents", embedding_dim=768, - distance_metric="cosine" + distance_metric="cosine", ) prompt_template = [ - ChatMessage.from_system("Answer the question based on the provided context. If the context does not include an answer, reply with 'I don't know'."), + ChatMessage.from_system( + "Answer the question based on the provided context. If the context does not include an answer, reply with 'I don't know'." + ), ChatMessage.from_user( "Query: {{query}}\n" "Documents:\n{% for doc in documents %}{{ doc.content }}\n{% endfor %}\n" @@ -120,9 +124,21 @@ prompt_template = [ query_pipeline = Pipeline() query_pipeline.add_component("text_embedder", SentenceTransformersTextEmbedder()) -query_pipeline.add_component("retriever", ValkeyEmbeddingRetriever(document_store=document_store)) -query_pipeline.add_component("prompt_builder", ChatPromptBuilder(template=prompt_template, required_variables=["query", "documents"])) -query_pipeline.add_component("generator", OpenAIChatGenerator(api_key=Secret.from_token("YOUR_OPENAI_API_KEY"), model="gpt-4o")) +query_pipeline.add_component( + "retriever", ValkeyEmbeddingRetriever(document_store=document_store) +) +query_pipeline.add_component( + "prompt_builder", + ChatPromptBuilder( + template=prompt_template, required_variables=["query", "documents"] + ), +) +query_pipeline.add_component( + "generator", + OpenAIChatGenerator( + api_key=Secret.from_token("YOUR_OPENAI_API_KEY"), model="gpt-4o" + ), +) query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding") query_pipeline.connect("retriever.documents", "prompt_builder.documents") query_pipeline.connect("prompt_builder.messages", "generator.messages") diff --git a/docs-website/versioned_docs/version-2.28/pipeline-components/converters/imagefiletodocument.mdx b/docs-website/versioned_docs/version-2.28/pipeline-components/converters/imagefiletodocument.mdx index efdf7b2559..b5e178cbcc 100644 --- a/docs-website/versioned_docs/version-2.28/pipeline-components/converters/imagefiletodocument.mdx +++ b/docs-website/versioned_docs/version-2.28/pipeline-components/converters/imagefiletodocument.mdx @@ -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() diff --git a/docs-website/versioned_docs/version-2.28/pipeline-components/converters/imagefiletoimagecontent.mdx b/docs-website/versioned_docs/version-2.28/pipeline-components/converters/imagefiletoimagecontent.mdx index 88fe3c4b17..0e0328e522 100644 --- a/docs-website/versioned_docs/version-2.28/pipeline-components/converters/imagefiletoimagecontent.mdx +++ b/docs-website/versioned_docs/version-2.28/pipeline-components/converters/imagefiletoimagecontent.mdx @@ -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)) diff --git a/docs-website/versioned_docs/version-2.28/pipeline-components/converters/kreuzbergconverter.mdx b/docs-website/versioned_docs/version-2.28/pipeline-components/converters/kreuzbergconverter.mdx index 19659f2eed..6e3fa31050 100644 --- a/docs-website/versioned_docs/version-2.28/pipeline-components/converters/kreuzbergconverter.mdx +++ b/docs-website/versioned_docs/version-2.28/pipeline-components/converters/kreuzbergconverter.mdx @@ -70,7 +70,9 @@ document_store = InMemoryDocumentStore() pipeline = Pipeline() pipeline.add_component("converter", KreuzbergConverter()) -pipeline.add_component("splitter", DocumentSplitter(split_by="sentence", split_length=5)) +pipeline.add_component( + "splitter", DocumentSplitter(split_by="sentence", split_length=5) +) pipeline.add_component("writer", DocumentWriter(document_store=document_store)) pipeline.connect("converter", "splitter") diff --git a/docs-website/versioned_docs/version-2.28/pipeline-components/converters/outputadapter.mdx b/docs-website/versioned_docs/version-2.28/pipeline-components/converters/outputadapter.mdx index 8ddd451028..21c6018d5a 100644 --- a/docs-website/versioned_docs/version-2.28/pipeline-components/converters/outputadapter.mdx +++ b/docs-website/versioned_docs/version-2.28/pipeline-components/converters/outputadapter.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.28/pipeline-components/embedders/mistraltextembedder.mdx b/docs-website/versioned_docs/version-2.28/pipeline-components/embedders/mistraltextembedder.mdx index c2cd48c59a..dadad5329e 100644 --- a/docs-website/versioned_docs/version-2.28/pipeline-components/embedders/mistraltextembedder.mdx +++ b/docs-website/versioned_docs/version-2.28/pipeline-components/embedders/mistraltextembedder.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.28/pipeline-components/fetchers/linkcontentfetcher.mdx b/docs-website/versioned_docs/version-2.28/pipeline-components/fetchers/linkcontentfetcher.mdx index 3634c1facc..4b5410a7cc 100644 --- a/docs-website/versioned_docs/version-2.28/pipeline-components/fetchers/linkcontentfetcher.mdx +++ b/docs-website/versioned_docs/version-2.28/pipeline-components/fetchers/linkcontentfetcher.mdx @@ -69,7 +69,13 @@ def is_unsafe_url(url: str) -> bool: except ValueError: # Hostname (not a raw IP). Apply your own domain allowlist policy here. Filter out "LOCALHOST" etc. return False - return ip.is_private or ip.is_loopback or ip.is_link_local or ip.is_reserved or any(ip in net for net in PRIVATE_RANGES) + return ( + ip.is_private + or ip.is_loopback + or ip.is_link_local + or ip.is_reserved + or any(ip in net for net in PRIVATE_RANGES) + ) ``` diff --git a/docs-website/versioned_docs/version-2.28/pipeline-components/generators/anthropicchatgenerator.mdx b/docs-website/versioned_docs/version-2.28/pipeline-components/generators/anthropicchatgenerator.mdx index 788fb1cd50..566301f72e 100644 --- a/docs-website/versioned_docs/version-2.28/pipeline-components/generators/anthropicchatgenerator.mdx +++ b/docs-website/versioned_docs/version-2.28/pipeline-components/generators/anthropicchatgenerator.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.28/pipeline-components/generators/ollamachatgenerator.mdx b/docs-website/versioned_docs/version-2.28/pipeline-components/generators/ollamachatgenerator.mdx index d16e1964cf..3dbf37755c 100644 --- a/docs-website/versioned_docs/version-2.28/pipeline-components/generators/ollamachatgenerator.mdx +++ b/docs-website/versioned_docs/version-2.28/pipeline-components/generators/ollamachatgenerator.mdx @@ -118,9 +118,9 @@ generator = OllamaChatGenerator( ) response = generator.run( - messages=[ChatMessage.from_user( - "What's the weather in Berlin? Use the get_weather tool." - )] + messages=[ + ChatMessage.from_user("What's the weather in Berlin? Use the get_weather tool.") + ] ) # Final reconstructed message: tool_calls populated, text is None diff --git a/docs-website/versioned_docs/version-2.28/pipeline-components/generators/openaigenerator.mdx b/docs-website/versioned_docs/version-2.28/pipeline-components/generators/openaigenerator.mdx index 5bab2c5f4b..7891fdce85 100644 --- a/docs-website/versioned_docs/version-2.28/pipeline-components/generators/openaigenerator.mdx +++ b/docs-website/versioned_docs/version-2.28/pipeline-components/generators/openaigenerator.mdx @@ -104,7 +104,12 @@ from haystack import Document from haystack.utils import Secret docstore = InMemoryDocumentStore() -docstore.write_documents([Document(content="Rome is the capital of Italy"), Document(content="Paris is the capital of France")]) +docstore.write_documents( + [ + Document(content="Rome is the capital of Italy"), + Document(content="Paris is the capital of France"), + ] +) query = "What is the capital of France?" @@ -122,18 +127,13 @@ pipe = Pipeline() pipe.add_component("retriever", InMemoryBM25Retriever(document_store=docstore)) pipe.add_component("prompt_builder", PromptBuilder(template=template)) -pipe.add_component("llm", OpenAIGenerator(api_key=Secret.from_env_var("OPENAI_API_KEY"))) +pipe.add_component( + "llm", OpenAIGenerator(api_key=Secret.from_env_var("OPENAI_API_KEY")) +) pipe.connect("retriever", "prompt_builder.documents") pipe.connect("prompt_builder", "llm") -res=pipe.run({ - "prompt_builder": { - "query": query - }, - "retriever": { - "query": query - } -}) +res = pipe.run({"prompt_builder": {"query": query}, "retriever": {"query": query}}) print(res) ``` diff --git a/docs-website/versioned_docs/version-2.28/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx b/docs-website/versioned_docs/version-2.28/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx index bdcb52ece1..1d579d6da5 100644 --- a/docs-website/versioned_docs/version-2.28/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx +++ b/docs-website/versioned_docs/version-2.28/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.28/pipeline-components/retrievers/arcadedbembeddingretriever.mdx b/docs-website/versioned_docs/version-2.28/pipeline-components/retrievers/arcadedbembeddingretriever.mdx index 42c3c77400..2610aafdfc 100644 --- a/docs-website/versioned_docs/version-2.28/pipeline-components/retrievers/arcadedbembeddingretriever.mdx +++ b/docs-website/versioned_docs/version-2.28/pipeline-components/retrievers/arcadedbembeddingretriever.mdx @@ -40,7 +40,9 @@ Ensure ArcadeDB is running, for example via Docker, and credentials are set (`AR ```python from haystack_integrations.document_stores.arcadedb import ArcadeDBDocumentStore -from haystack_integrations.components.retrievers.arcadedb import ArcadeDBEmbeddingRetriever +from haystack_integrations.components.retrievers.arcadedb import ( + ArcadeDBEmbeddingRetriever, +) document_store = ArcadeDBDocumentStore( url="http://localhost:2480", @@ -65,7 +67,9 @@ from haystack.components.embedders import ( SentenceTransformersDocumentEmbedder, ) from haystack_integrations.document_stores.arcadedb import ArcadeDBDocumentStore -from haystack_integrations.components.retrievers.arcadedb import ArcadeDBEmbeddingRetriever +from haystack_integrations.components.retrievers.arcadedb import ( + ArcadeDBEmbeddingRetriever, +) document_store = ArcadeDBDocumentStore( url="http://localhost:2480", @@ -76,8 +80,12 @@ document_store = ArcadeDBDocumentStore( documents = [ Document(content="There are over 7,000 languages spoken around the world today."), - Document(content="Elephants have been observed to recognize themselves in mirrors."), - Document(content="Bioluminescent waves can be seen in the Maldives and Puerto Rico."), + Document( + content="Elephants have been observed to recognize themselves in mirrors." + ), + Document( + content="Bioluminescent waves can be seen in the Maldives and Puerto Rico." + ), ] document_embedder = SentenceTransformersDocumentEmbedder() @@ -95,6 +103,8 @@ query_pipeline.add_component( ) query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding") -result = query_pipeline.run({"text_embedder": {"text": "How many languages are there?"}}) +result = query_pipeline.run( + {"text_embedder": {"text": "How many languages are there?"}} +) print(result["retriever"]["documents"][0]) ``` diff --git a/docs-website/versioned_docs/version-2.28/pipeline-components/retrievers/azureaisearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.28/pipeline-components/retrievers/azureaisearchbm25retriever.mdx index fbe7834c56..3faac75cd2 100644 --- a/docs-website/versioned_docs/version-2.28/pipeline-components/retrievers/azureaisearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.28/pipeline-components/retrievers/azureaisearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.28/pipeline-components/retrievers/elasticsearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.28/pipeline-components/retrievers/elasticsearchbm25retriever.mdx index 5588e8cbc2..29500e7bd0 100644 --- a/docs-website/versioned_docs/version-2.28/pipeline-components/retrievers/elasticsearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.28/pipeline-components/retrievers/elasticsearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.28/tools/tool.mdx b/docs-website/versioned_docs/version-2.28/tools/tool.mdx index dae55f4c74..dbbe3346c0 100644 --- a/docs-website/versioned_docs/version-2.28/tools/tool.mdx +++ b/docs-website/versioned_docs/version-2.28/tools/tool.mdx @@ -236,9 +236,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. @@ -250,7 +248,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, diff --git a/docs-website/versioned_docs/version-2.29/concepts/data-classes/filecontent.mdx b/docs-website/versioned_docs/version-2.29/concepts/data-classes/filecontent.mdx index 5f2c5f40a1..5b2a49136b 100644 --- a/docs-website/versioned_docs/version-2.29/concepts/data-classes/filecontent.mdx +++ b/docs-website/versioned_docs/version-2.29/concepts/data-classes/filecontent.mdx @@ -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) diff --git a/docs-website/versioned_docs/version-2.29/concepts/pipelines/pipeline-loops.mdx b/docs-website/versioned_docs/version-2.29/concepts/pipelines/pipeline-loops.mdx index 04c0796655..49d5c3ed35 100644 --- a/docs-website/versioned_docs/version-2.29/concepts/pipelines/pipeline-loops.mdx +++ b/docs-website/versioned_docs/version-2.29/concepts/pipelines/pipeline-loops.mdx @@ -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. diff --git a/docs-website/versioned_docs/version-2.29/development/tracing.mdx b/docs-website/versioned_docs/version-2.29/development/tracing.mdx index 91f946dbc7..12dfbb7782 100644 --- a/docs-website/versioned_docs/version-2.29/development/tracing.mdx +++ b/docs-website/versioned_docs/version-2.29/development/tracing.mdx @@ -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 @@ -175,36 +180,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: @@ -297,12 +306,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) ``` diff --git a/docs-website/versioned_docs/version-2.29/document-stores/arcadedbdocumentstore.mdx b/docs-website/versioned_docs/version-2.29/document-stores/arcadedbdocumentstore.mdx index 1de48066de..12d251e270 100644 --- a/docs-website/versioned_docs/version-2.29/document-stores/arcadedbdocumentstore.mdx +++ b/docs-website/versioned_docs/version-2.29/document-stores/arcadedbdocumentstore.mdx @@ -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()) ``` diff --git a/docs-website/versioned_docs/version-2.29/pipeline-components/converters/imagefiletodocument.mdx b/docs-website/versioned_docs/version-2.29/pipeline-components/converters/imagefiletodocument.mdx index 07ce1d9305..c1c4afd18b 100644 --- a/docs-website/versioned_docs/version-2.29/pipeline-components/converters/imagefiletodocument.mdx +++ b/docs-website/versioned_docs/version-2.29/pipeline-components/converters/imagefiletodocument.mdx @@ -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() diff --git a/docs-website/versioned_docs/version-2.29/pipeline-components/converters/imagefiletoimagecontent.mdx b/docs-website/versioned_docs/version-2.29/pipeline-components/converters/imagefiletoimagecontent.mdx index 1c8867a3d2..935ea4783f 100644 --- a/docs-website/versioned_docs/version-2.29/pipeline-components/converters/imagefiletoimagecontent.mdx +++ b/docs-website/versioned_docs/version-2.29/pipeline-components/converters/imagefiletoimagecontent.mdx @@ -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)) diff --git a/docs-website/versioned_docs/version-2.29/pipeline-components/converters/outputadapter.mdx b/docs-website/versioned_docs/version-2.29/pipeline-components/converters/outputadapter.mdx index 729f0ee82b..68b7e8eb0a 100644 --- a/docs-website/versioned_docs/version-2.29/pipeline-components/converters/outputadapter.mdx +++ b/docs-website/versioned_docs/version-2.29/pipeline-components/converters/outputadapter.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.29/pipeline-components/embedders/mistraltextembedder.mdx b/docs-website/versioned_docs/version-2.29/pipeline-components/embedders/mistraltextembedder.mdx index bab018a749..97ce5775db 100644 --- a/docs-website/versioned_docs/version-2.29/pipeline-components/embedders/mistraltextembedder.mdx +++ b/docs-website/versioned_docs/version-2.29/pipeline-components/embedders/mistraltextembedder.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.29/pipeline-components/generators/anthropicchatgenerator.mdx b/docs-website/versioned_docs/version-2.29/pipeline-components/generators/anthropicchatgenerator.mdx index fc4dc37e5e..866690da8f 100644 --- a/docs-website/versioned_docs/version-2.29/pipeline-components/generators/anthropicchatgenerator.mdx +++ b/docs-website/versioned_docs/version-2.29/pipeline-components/generators/anthropicchatgenerator.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.29/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx b/docs-website/versioned_docs/version-2.29/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx index e80ce7c52e..a7a625560a 100644 --- a/docs-website/versioned_docs/version-2.29/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx +++ b/docs-website/versioned_docs/version-2.29/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx @@ -37,7 +37,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 diff --git a/docs-website/versioned_docs/version-2.29/pipeline-components/retrievers/azureaisearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.29/pipeline-components/retrievers/azureaisearchbm25retriever.mdx index 9cdf510366..3b36501e89 100644 --- a/docs-website/versioned_docs/version-2.29/pipeline-components/retrievers/azureaisearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.29/pipeline-components/retrievers/azureaisearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.29/pipeline-components/retrievers/elasticsearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.29/pipeline-components/retrievers/elasticsearchbm25retriever.mdx index cfbd1d357b..577bbb34d2 100644 --- a/docs-website/versioned_docs/version-2.29/pipeline-components/retrievers/elasticsearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.29/pipeline-components/retrievers/elasticsearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.29/tools/tool.mdx b/docs-website/versioned_docs/version-2.29/tools/tool.mdx index dae55f4c74..dbbe3346c0 100644 --- a/docs-website/versioned_docs/version-2.29/tools/tool.mdx +++ b/docs-website/versioned_docs/version-2.29/tools/tool.mdx @@ -236,9 +236,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. @@ -250,7 +248,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, diff --git a/docs-website/versioned_docs/version-2.30/concepts/data-classes/filecontent.mdx b/docs-website/versioned_docs/version-2.30/concepts/data-classes/filecontent.mdx index 5f2c5f40a1..5b2a49136b 100644 --- a/docs-website/versioned_docs/version-2.30/concepts/data-classes/filecontent.mdx +++ b/docs-website/versioned_docs/version-2.30/concepts/data-classes/filecontent.mdx @@ -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) diff --git a/docs-website/versioned_docs/version-2.30/concepts/pipelines/pipeline-loops.mdx b/docs-website/versioned_docs/version-2.30/concepts/pipelines/pipeline-loops.mdx index 04c0796655..49d5c3ed35 100644 --- a/docs-website/versioned_docs/version-2.30/concepts/pipelines/pipeline-loops.mdx +++ b/docs-website/versioned_docs/version-2.30/concepts/pipelines/pipeline-loops.mdx @@ -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. diff --git a/docs-website/versioned_docs/version-2.30/development/tracing/custom-tracer.mdx b/docs-website/versioned_docs/version-2.30/development/tracing/custom-tracer.mdx index a28d0461d0..31e47dab6f 100644 --- a/docs-website/versioned_docs/version-2.30/development/tracing/custom-tracer.mdx +++ b/docs-website/versioned_docs/version-2.30/development/tracing/custom-tracer.mdx @@ -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: diff --git a/docs-website/versioned_docs/version-2.30/development/tracing/opentelemetry.mdx b/docs-website/versioned_docs/version-2.30/development/tracing/opentelemetry.mdx index 39d7e08d23..be83f2841c 100644 --- a/docs-website/versioned_docs/version-2.30/development/tracing/opentelemetry.mdx +++ b/docs-website/versioned_docs/version-2.30/development/tracing/opentelemetry.mdx @@ -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) diff --git a/docs-website/versioned_docs/version-2.30/document-stores/arcadedbdocumentstore.mdx b/docs-website/versioned_docs/version-2.30/document-stores/arcadedbdocumentstore.mdx index 1de48066de..12d251e270 100644 --- a/docs-website/versioned_docs/version-2.30/document-stores/arcadedbdocumentstore.mdx +++ b/docs-website/versioned_docs/version-2.30/document-stores/arcadedbdocumentstore.mdx @@ -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()) ``` diff --git a/docs-website/versioned_docs/version-2.30/memory-stores/cogneememorystore.mdx b/docs-website/versioned_docs/version-2.30/memory-stores/cogneememorystore.mdx index 691ae52c86..b036758a9b 100644 --- a/docs-website/versioned_docs/version-2.30/memory-stores/cogneememorystore.mdx +++ b/docs-website/versioned_docs/version-2.30/memory-stores/cogneememorystore.mdx @@ -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", ) diff --git a/docs-website/versioned_docs/version-2.30/memory-stores/mem0memorystore.mdx b/docs-website/versioned_docs/version-2.30/memory-stores/mem0memorystore.mdx index 199b0b5177..ce0537e0b4 100644 --- a/docs-website/versioned_docs/version-2.30/memory-stores/mem0memorystore.mdx +++ b/docs-website/versioned_docs/version-2.30/memory-stores/mem0memorystore.mdx @@ -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, diff --git a/docs-website/versioned_docs/version-2.30/pipeline-components/converters/imagefiletodocument.mdx b/docs-website/versioned_docs/version-2.30/pipeline-components/converters/imagefiletodocument.mdx index 07ce1d9305..c1c4afd18b 100644 --- a/docs-website/versioned_docs/version-2.30/pipeline-components/converters/imagefiletodocument.mdx +++ b/docs-website/versioned_docs/version-2.30/pipeline-components/converters/imagefiletodocument.mdx @@ -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() diff --git a/docs-website/versioned_docs/version-2.30/pipeline-components/converters/imagefiletoimagecontent.mdx b/docs-website/versioned_docs/version-2.30/pipeline-components/converters/imagefiletoimagecontent.mdx index 1c8867a3d2..935ea4783f 100644 --- a/docs-website/versioned_docs/version-2.30/pipeline-components/converters/imagefiletoimagecontent.mdx +++ b/docs-website/versioned_docs/version-2.30/pipeline-components/converters/imagefiletoimagecontent.mdx @@ -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)) diff --git a/docs-website/versioned_docs/version-2.30/pipeline-components/converters/outputadapter.mdx b/docs-website/versioned_docs/version-2.30/pipeline-components/converters/outputadapter.mdx index 729f0ee82b..68b7e8eb0a 100644 --- a/docs-website/versioned_docs/version-2.30/pipeline-components/converters/outputadapter.mdx +++ b/docs-website/versioned_docs/version-2.30/pipeline-components/converters/outputadapter.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.30/pipeline-components/embedders/mistraltextembedder.mdx b/docs-website/versioned_docs/version-2.30/pipeline-components/embedders/mistraltextembedder.mdx index bab018a749..97ce5775db 100644 --- a/docs-website/versioned_docs/version-2.30/pipeline-components/embedders/mistraltextembedder.mdx +++ b/docs-website/versioned_docs/version-2.30/pipeline-components/embedders/mistraltextembedder.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.30/pipeline-components/generators/anthropicchatgenerator.mdx b/docs-website/versioned_docs/version-2.30/pipeline-components/generators/anthropicchatgenerator.mdx index fc4dc37e5e..866690da8f 100644 --- a/docs-website/versioned_docs/version-2.30/pipeline-components/generators/anthropicchatgenerator.mdx +++ b/docs-website/versioned_docs/version-2.30/pipeline-components/generators/anthropicchatgenerator.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.30/pipeline-components/generators/anthropicfoundrychatgenerator.mdx b/docs-website/versioned_docs/version-2.30/pipeline-components/generators/anthropicfoundrychatgenerator.mdx index 6657e5654d..287f8efad3 100644 --- a/docs-website/versioned_docs/version-2.30/pipeline-components/generators/anthropicfoundrychatgenerator.mdx +++ b/docs-website/versioned_docs/version-2.30/pipeline-components/generators/anthropicfoundrychatgenerator.mdx @@ -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()) diff --git a/docs-website/versioned_docs/version-2.30/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx b/docs-website/versioned_docs/version-2.30/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx index e80ce7c52e..a7a625560a 100644 --- a/docs-website/versioned_docs/version-2.30/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx +++ b/docs-website/versioned_docs/version-2.30/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx @@ -37,7 +37,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 diff --git a/docs-website/versioned_docs/version-2.30/pipeline-components/preprocessors/pythoncodesplitter.mdx b/docs-website/versioned_docs/version-2.30/pipeline-components/preprocessors/pythoncodesplitter.mdx index f90c9eb61f..98dea51cf0 100644 --- a/docs-website/versioned_docs/version-2.30/pipeline-components/preprocessors/pythoncodesplitter.mdx +++ b/docs-website/versioned_docs/version-2.30/pipeline-components/preprocessors/pythoncodesplitter.mdx @@ -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")) diff --git a/docs-website/versioned_docs/version-2.30/pipeline-components/retrievers/azureaisearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.30/pipeline-components/retrievers/azureaisearchbm25retriever.mdx index 9cdf510366..3b36501e89 100644 --- a/docs-website/versioned_docs/version-2.30/pipeline-components/retrievers/azureaisearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.30/pipeline-components/retrievers/azureaisearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.30/pipeline-components/retrievers/elasticsearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.30/pipeline-components/retrievers/elasticsearchbm25retriever.mdx index cfbd1d357b..577bbb34d2 100644 --- a/docs-website/versioned_docs/version-2.30/pipeline-components/retrievers/elasticsearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.30/pipeline-components/retrievers/elasticsearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.30/pipeline-components/retrievers/sqlalchemytableretriever.mdx b/docs-website/versioned_docs/version-2.30/pipeline-components/retrievers/sqlalchemytableretriever.mdx index b7c29b5e78..2fd64f3205 100644 --- a/docs-website/versioned_docs/version-2.30/pipeline-components/retrievers/sqlalchemytableretriever.mdx +++ b/docs-website/versioned_docs/version-2.30/pipeline-components/retrievers/sqlalchemytableretriever.mdx @@ -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", diff --git a/docs-website/versioned_docs/version-2.30/pipeline-components/writers/cogneewriter.mdx b/docs-website/versioned_docs/version-2.30/pipeline-components/writers/cogneewriter.mdx index 4e516268dd..dd01774cff 100644 --- a/docs-website/versioned_docs/version-2.30/pipeline-components/writers/cogneewriter.mdx +++ b/docs-website/versioned_docs/version-2.30/pipeline-components/writers/cogneewriter.mdx @@ -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", ) ``` diff --git a/docs-website/versioned_docs/version-2.30/tools/tool.mdx b/docs-website/versioned_docs/version-2.30/tools/tool.mdx index dae55f4c74..dbbe3346c0 100644 --- a/docs-website/versioned_docs/version-2.30/tools/tool.mdx +++ b/docs-website/versioned_docs/version-2.30/tools/tool.mdx @@ -236,9 +236,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. @@ -250,7 +248,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, diff --git a/docs-website/versioned_docs/version-2.31/concepts/data-classes/filecontent.mdx b/docs-website/versioned_docs/version-2.31/concepts/data-classes/filecontent.mdx index 5f2c5f40a1..5b2a49136b 100644 --- a/docs-website/versioned_docs/version-2.31/concepts/data-classes/filecontent.mdx +++ b/docs-website/versioned_docs/version-2.31/concepts/data-classes/filecontent.mdx @@ -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) diff --git a/docs-website/versioned_docs/version-2.31/concepts/pipelines/pipeline-loops.mdx b/docs-website/versioned_docs/version-2.31/concepts/pipelines/pipeline-loops.mdx index 04c0796655..49d5c3ed35 100644 --- a/docs-website/versioned_docs/version-2.31/concepts/pipelines/pipeline-loops.mdx +++ b/docs-website/versioned_docs/version-2.31/concepts/pipelines/pipeline-loops.mdx @@ -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. diff --git a/docs-website/versioned_docs/version-2.31/development/tracing/custom-tracer.mdx b/docs-website/versioned_docs/version-2.31/development/tracing/custom-tracer.mdx index a28d0461d0..31e47dab6f 100644 --- a/docs-website/versioned_docs/version-2.31/development/tracing/custom-tracer.mdx +++ b/docs-website/versioned_docs/version-2.31/development/tracing/custom-tracer.mdx @@ -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: diff --git a/docs-website/versioned_docs/version-2.31/development/tracing/opentelemetry.mdx b/docs-website/versioned_docs/version-2.31/development/tracing/opentelemetry.mdx index 39d7e08d23..be83f2841c 100644 --- a/docs-website/versioned_docs/version-2.31/development/tracing/opentelemetry.mdx +++ b/docs-website/versioned_docs/version-2.31/development/tracing/opentelemetry.mdx @@ -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) diff --git a/docs-website/versioned_docs/version-2.31/document-stores/arcadedbdocumentstore.mdx b/docs-website/versioned_docs/version-2.31/document-stores/arcadedbdocumentstore.mdx index 1de48066de..12d251e270 100644 --- a/docs-website/versioned_docs/version-2.31/document-stores/arcadedbdocumentstore.mdx +++ b/docs-website/versioned_docs/version-2.31/document-stores/arcadedbdocumentstore.mdx @@ -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()) ``` diff --git a/docs-website/versioned_docs/version-2.31/memory-stores/cogneememorystore.mdx b/docs-website/versioned_docs/version-2.31/memory-stores/cogneememorystore.mdx index 691ae52c86..b036758a9b 100644 --- a/docs-website/versioned_docs/version-2.31/memory-stores/cogneememorystore.mdx +++ b/docs-website/versioned_docs/version-2.31/memory-stores/cogneememorystore.mdx @@ -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", ) diff --git a/docs-website/versioned_docs/version-2.31/memory-stores/mem0memorystore.mdx b/docs-website/versioned_docs/version-2.31/memory-stores/mem0memorystore.mdx index 199b0b5177..ce0537e0b4 100644 --- a/docs-website/versioned_docs/version-2.31/memory-stores/mem0memorystore.mdx +++ b/docs-website/versioned_docs/version-2.31/memory-stores/mem0memorystore.mdx @@ -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, diff --git a/docs-website/versioned_docs/version-2.31/pipeline-components/converters/imagefiletodocument.mdx b/docs-website/versioned_docs/version-2.31/pipeline-components/converters/imagefiletodocument.mdx index 0227f69972..0fc5698c71 100644 --- a/docs-website/versioned_docs/version-2.31/pipeline-components/converters/imagefiletodocument.mdx +++ b/docs-website/versioned_docs/version-2.31/pipeline-components/converters/imagefiletodocument.mdx @@ -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() diff --git a/docs-website/versioned_docs/version-2.31/pipeline-components/converters/imagefiletoimagecontent.mdx b/docs-website/versioned_docs/version-2.31/pipeline-components/converters/imagefiletoimagecontent.mdx index 1c8867a3d2..935ea4783f 100644 --- a/docs-website/versioned_docs/version-2.31/pipeline-components/converters/imagefiletoimagecontent.mdx +++ b/docs-website/versioned_docs/version-2.31/pipeline-components/converters/imagefiletoimagecontent.mdx @@ -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)) diff --git a/docs-website/versioned_docs/version-2.31/pipeline-components/converters/outputadapter.mdx b/docs-website/versioned_docs/version-2.31/pipeline-components/converters/outputadapter.mdx index 729f0ee82b..68b7e8eb0a 100644 --- a/docs-website/versioned_docs/version-2.31/pipeline-components/converters/outputadapter.mdx +++ b/docs-website/versioned_docs/version-2.31/pipeline-components/converters/outputadapter.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.31/pipeline-components/embedders/mistraltextembedder.mdx b/docs-website/versioned_docs/version-2.31/pipeline-components/embedders/mistraltextembedder.mdx index bab018a749..97ce5775db 100644 --- a/docs-website/versioned_docs/version-2.31/pipeline-components/embedders/mistraltextembedder.mdx +++ b/docs-website/versioned_docs/version-2.31/pipeline-components/embedders/mistraltextembedder.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.31/pipeline-components/generators/anthropicchatgenerator.mdx b/docs-website/versioned_docs/version-2.31/pipeline-components/generators/anthropicchatgenerator.mdx index fc4dc37e5e..866690da8f 100644 --- a/docs-website/versioned_docs/version-2.31/pipeline-components/generators/anthropicchatgenerator.mdx +++ b/docs-website/versioned_docs/version-2.31/pipeline-components/generators/anthropicchatgenerator.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-2.31/pipeline-components/generators/anthropicfoundrychatgenerator.mdx b/docs-website/versioned_docs/version-2.31/pipeline-components/generators/anthropicfoundrychatgenerator.mdx index 6657e5654d..287f8efad3 100644 --- a/docs-website/versioned_docs/version-2.31/pipeline-components/generators/anthropicfoundrychatgenerator.mdx +++ b/docs-website/versioned_docs/version-2.31/pipeline-components/generators/anthropicfoundrychatgenerator.mdx @@ -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()) diff --git a/docs-website/versioned_docs/version-2.31/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx b/docs-website/versioned_docs/version-2.31/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx index 942436fe3f..3eba5bd091 100644 --- a/docs-website/versioned_docs/version-2.31/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx +++ b/docs-website/versioned_docs/version-2.31/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx @@ -43,7 +43,6 @@ pip install sentence-transformers-haystack ``` ```python - from haystack import Document from haystack_integrations.components.embedders.sentence_transformers import ( SentenceTransformersDocumentEmbedder, diff --git a/docs-website/versioned_docs/version-2.31/pipeline-components/preprocessors/pythoncodesplitter.mdx b/docs-website/versioned_docs/version-2.31/pipeline-components/preprocessors/pythoncodesplitter.mdx index f90c9eb61f..98dea51cf0 100644 --- a/docs-website/versioned_docs/version-2.31/pipeline-components/preprocessors/pythoncodesplitter.mdx +++ b/docs-website/versioned_docs/version-2.31/pipeline-components/preprocessors/pythoncodesplitter.mdx @@ -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")) diff --git a/docs-website/versioned_docs/version-2.31/pipeline-components/retrievers/azureaisearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.31/pipeline-components/retrievers/azureaisearchbm25retriever.mdx index 9cdf510366..3b36501e89 100644 --- a/docs-website/versioned_docs/version-2.31/pipeline-components/retrievers/azureaisearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.31/pipeline-components/retrievers/azureaisearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.31/pipeline-components/retrievers/elasticsearchbm25retriever.mdx b/docs-website/versioned_docs/version-2.31/pipeline-components/retrievers/elasticsearchbm25retriever.mdx index cfbd1d357b..577bbb34d2 100644 --- a/docs-website/versioned_docs/version-2.31/pipeline-components/retrievers/elasticsearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-2.31/pipeline-components/retrievers/elasticsearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-2.31/pipeline-components/retrievers/elasticsearchsqlretriever.mdx b/docs-website/versioned_docs/version-2.31/pipeline-components/retrievers/elasticsearchsqlretriever.mdx index 23dde93a9d..7431fd00c4 100644 --- a/docs-website/versioned_docs/version-2.31/pipeline-components/retrievers/elasticsearchsqlretriever.mdx +++ b/docs-website/versioned_docs/version-2.31/pipeline-components/retrievers/elasticsearchsqlretriever.mdx @@ -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."), diff --git a/docs-website/versioned_docs/version-2.31/pipeline-components/retrievers/opensearchsqlretriever.mdx b/docs-website/versioned_docs/version-2.31/pipeline-components/retrievers/opensearchsqlretriever.mdx index c43cf09082..8e094d2264 100644 --- a/docs-website/versioned_docs/version-2.31/pipeline-components/retrievers/opensearchsqlretriever.mdx +++ b/docs-website/versioned_docs/version-2.31/pipeline-components/retrievers/opensearchsqlretriever.mdx @@ -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."), diff --git a/docs-website/versioned_docs/version-2.31/pipeline-components/retrievers/sqlalchemytableretriever.mdx b/docs-website/versioned_docs/version-2.31/pipeline-components/retrievers/sqlalchemytableretriever.mdx index b7c29b5e78..2fd64f3205 100644 --- a/docs-website/versioned_docs/version-2.31/pipeline-components/retrievers/sqlalchemytableretriever.mdx +++ b/docs-website/versioned_docs/version-2.31/pipeline-components/retrievers/sqlalchemytableretriever.mdx @@ -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", diff --git a/docs-website/versioned_docs/version-2.31/pipeline-components/writers/cogneewriter.mdx b/docs-website/versioned_docs/version-2.31/pipeline-components/writers/cogneewriter.mdx index 4e516268dd..dd01774cff 100644 --- a/docs-website/versioned_docs/version-2.31/pipeline-components/writers/cogneewriter.mdx +++ b/docs-website/versioned_docs/version-2.31/pipeline-components/writers/cogneewriter.mdx @@ -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", ) ``` diff --git a/docs-website/versioned_docs/version-2.31/tools/tool.mdx b/docs-website/versioned_docs/version-2.31/tools/tool.mdx index dae55f4c74..dbbe3346c0 100644 --- a/docs-website/versioned_docs/version-2.31/tools/tool.mdx +++ b/docs-website/versioned_docs/version-2.31/tools/tool.mdx @@ -236,9 +236,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. @@ -250,7 +248,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, diff --git a/docs-website/versioned_docs/version-3.0/concepts/data-classes/filecontent.mdx b/docs-website/versioned_docs/version-3.0/concepts/data-classes/filecontent.mdx index 5f2c5f40a1..5b2a49136b 100644 --- a/docs-website/versioned_docs/version-3.0/concepts/data-classes/filecontent.mdx +++ b/docs-website/versioned_docs/version-3.0/concepts/data-classes/filecontent.mdx @@ -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) diff --git a/docs-website/versioned_docs/version-3.0/concepts/pipelines/pipeline-loops.mdx b/docs-website/versioned_docs/version-3.0/concepts/pipelines/pipeline-loops.mdx index 562cf6eb8f..ef07b0bcec 100644 --- a/docs-website/versioned_docs/version-3.0/concepts/pipelines/pipeline-loops.mdx +++ b/docs-website/versioned_docs/version-3.0/concepts/pipelines/pipeline-loops.mdx @@ -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. diff --git a/docs-website/versioned_docs/version-3.0/development/tracing/custom-tracer.mdx b/docs-website/versioned_docs/version-3.0/development/tracing/custom-tracer.mdx index a28d0461d0..31e47dab6f 100644 --- a/docs-website/versioned_docs/version-3.0/development/tracing/custom-tracer.mdx +++ b/docs-website/versioned_docs/version-3.0/development/tracing/custom-tracer.mdx @@ -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: diff --git a/docs-website/versioned_docs/version-3.0/development/tracing/opentelemetry.mdx b/docs-website/versioned_docs/version-3.0/development/tracing/opentelemetry.mdx index 8cf184b47c..de0ec4c247 100644 --- a/docs-website/versioned_docs/version-3.0/development/tracing/opentelemetry.mdx +++ b/docs-website/versioned_docs/version-3.0/development/tracing/opentelemetry.mdx @@ -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) diff --git a/docs-website/versioned_docs/version-3.0/document-stores/arcadedbdocumentstore.mdx b/docs-website/versioned_docs/version-3.0/document-stores/arcadedbdocumentstore.mdx index 1de48066de..12d251e270 100644 --- a/docs-website/versioned_docs/version-3.0/document-stores/arcadedbdocumentstore.mdx +++ b/docs-website/versioned_docs/version-3.0/document-stores/arcadedbdocumentstore.mdx @@ -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()) ``` diff --git a/docs-website/versioned_docs/version-3.0/memory-stores/cogneememorystore.mdx b/docs-website/versioned_docs/version-3.0/memory-stores/cogneememorystore.mdx index 691ae52c86..b036758a9b 100644 --- a/docs-website/versioned_docs/version-3.0/memory-stores/cogneememorystore.mdx +++ b/docs-website/versioned_docs/version-3.0/memory-stores/cogneememorystore.mdx @@ -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", ) diff --git a/docs-website/versioned_docs/version-3.0/memory-stores/mem0memorystore.mdx b/docs-website/versioned_docs/version-3.0/memory-stores/mem0memorystore.mdx index 199b0b5177..ce0537e0b4 100644 --- a/docs-website/versioned_docs/version-3.0/memory-stores/mem0memorystore.mdx +++ b/docs-website/versioned_docs/version-3.0/memory-stores/mem0memorystore.mdx @@ -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, diff --git a/docs-website/versioned_docs/version-3.0/pipeline-components/converters/imagefiletodocument.mdx b/docs-website/versioned_docs/version-3.0/pipeline-components/converters/imagefiletodocument.mdx index 0227f69972..0fc5698c71 100644 --- a/docs-website/versioned_docs/version-3.0/pipeline-components/converters/imagefiletodocument.mdx +++ b/docs-website/versioned_docs/version-3.0/pipeline-components/converters/imagefiletodocument.mdx @@ -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() diff --git a/docs-website/versioned_docs/version-3.0/pipeline-components/converters/imagefiletoimagecontent.mdx b/docs-website/versioned_docs/version-3.0/pipeline-components/converters/imagefiletoimagecontent.mdx index 1c8867a3d2..935ea4783f 100644 --- a/docs-website/versioned_docs/version-3.0/pipeline-components/converters/imagefiletoimagecontent.mdx +++ b/docs-website/versioned_docs/version-3.0/pipeline-components/converters/imagefiletoimagecontent.mdx @@ -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)) diff --git a/docs-website/versioned_docs/version-3.0/pipeline-components/converters/outputadapter.mdx b/docs-website/versioned_docs/version-3.0/pipeline-components/converters/outputadapter.mdx index 729f0ee82b..68b7e8eb0a 100644 --- a/docs-website/versioned_docs/version-3.0/pipeline-components/converters/outputadapter.mdx +++ b/docs-website/versioned_docs/version-3.0/pipeline-components/converters/outputadapter.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-3.0/pipeline-components/embedders/edenaidocumentembedder.mdx b/docs-website/versioned_docs/version-3.0/pipeline-components/embedders/edenaidocumentembedder.mdx index da0d46b904..54d17ef60a 100644 --- a/docs-website/versioned_docs/version-3.0/pipeline-components/embedders/edenaidocumentembedder.mdx +++ b/docs-website/versioned_docs/version-3.0/pipeline-components/embedders/edenaidocumentembedder.mdx @@ -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") diff --git a/docs-website/versioned_docs/version-3.0/pipeline-components/embedders/edenaitextembedder.mdx b/docs-website/versioned_docs/version-3.0/pipeline-components/embedders/edenaitextembedder.mdx index 80a912be93..89cfa5ca4c 100644 --- a/docs-website/versioned_docs/version-3.0/pipeline-components/embedders/edenaitextembedder.mdx +++ b/docs-website/versioned_docs/version-3.0/pipeline-components/embedders/edenaitextembedder.mdx @@ -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?"}}) diff --git a/docs-website/versioned_docs/version-3.0/pipeline-components/embedders/mistraltextembedder.mdx b/docs-website/versioned_docs/version-3.0/pipeline-components/embedders/mistraltextembedder.mdx index bab018a749..97ce5775db 100644 --- a/docs-website/versioned_docs/version-3.0/pipeline-components/embedders/mistraltextembedder.mdx +++ b/docs-website/versioned_docs/version-3.0/pipeline-components/embedders/mistraltextembedder.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-3.0/pipeline-components/generators/anthropicchatgenerator.mdx b/docs-website/versioned_docs/version-3.0/pipeline-components/generators/anthropicchatgenerator.mdx index fc4dc37e5e..866690da8f 100644 --- a/docs-website/versioned_docs/version-3.0/pipeline-components/generators/anthropicchatgenerator.mdx +++ b/docs-website/versioned_docs/version-3.0/pipeline-components/generators/anthropicchatgenerator.mdx @@ -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 diff --git a/docs-website/versioned_docs/version-3.0/pipeline-components/generators/anthropicfoundrychatgenerator.mdx b/docs-website/versioned_docs/version-3.0/pipeline-components/generators/anthropicfoundrychatgenerator.mdx index 6657e5654d..287f8efad3 100644 --- a/docs-website/versioned_docs/version-3.0/pipeline-components/generators/anthropicfoundrychatgenerator.mdx +++ b/docs-website/versioned_docs/version-3.0/pipeline-components/generators/anthropicfoundrychatgenerator.mdx @@ -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()) diff --git a/docs-website/versioned_docs/version-3.0/pipeline-components/generators/edenaichatgenerator.mdx b/docs-website/versioned_docs/version-3.0/pipeline-components/generators/edenaichatgenerator.mdx index 8cf6dac6a0..676ebc0050 100644 --- a/docs-website/versioned_docs/version-3.0/pipeline-components/generators/edenaichatgenerator.mdx +++ b/docs-website/versioned_docs/version-3.0/pipeline-components/generators/edenaichatgenerator.mdx @@ -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, + }, }, ) diff --git a/docs-website/versioned_docs/version-3.0/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx b/docs-website/versioned_docs/version-3.0/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx index 942436fe3f..3eba5bd091 100644 --- a/docs-website/versioned_docs/version-3.0/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx +++ b/docs-website/versioned_docs/version-3.0/pipeline-components/preprocessors/embeddingbaseddocumentsplitter.mdx @@ -43,7 +43,6 @@ pip install sentence-transformers-haystack ``` ```python - from haystack import Document from haystack_integrations.components.embedders.sentence_transformers import ( SentenceTransformersDocumentEmbedder, diff --git a/docs-website/versioned_docs/version-3.0/pipeline-components/preprocessors/pythoncodesplitter.mdx b/docs-website/versioned_docs/version-3.0/pipeline-components/preprocessors/pythoncodesplitter.mdx index f90c9eb61f..98dea51cf0 100644 --- a/docs-website/versioned_docs/version-3.0/pipeline-components/preprocessors/pythoncodesplitter.mdx +++ b/docs-website/versioned_docs/version-3.0/pipeline-components/preprocessors/pythoncodesplitter.mdx @@ -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")) diff --git a/docs-website/versioned_docs/version-3.0/pipeline-components/retrievers/azureaisearchbm25retriever.mdx b/docs-website/versioned_docs/version-3.0/pipeline-components/retrievers/azureaisearchbm25retriever.mdx index a04347b218..62dc9ab31d 100644 --- a/docs-website/versioned_docs/version-3.0/pipeline-components/retrievers/azureaisearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-3.0/pipeline-components/retrievers/azureaisearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-3.0/pipeline-components/retrievers/elasticsearchbm25retriever.mdx b/docs-website/versioned_docs/version-3.0/pipeline-components/retrievers/elasticsearchbm25retriever.mdx index a02c6cbdfe..d1ec0b925a 100644 --- a/docs-website/versioned_docs/version-3.0/pipeline-components/retrievers/elasticsearchbm25retriever.mdx +++ b/docs-website/versioned_docs/version-3.0/pipeline-components/retrievers/elasticsearchbm25retriever.mdx @@ -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, ) diff --git a/docs-website/versioned_docs/version-3.0/pipeline-components/retrievers/elasticsearchsqlretriever.mdx b/docs-website/versioned_docs/version-3.0/pipeline-components/retrievers/elasticsearchsqlretriever.mdx index 23dde93a9d..7431fd00c4 100644 --- a/docs-website/versioned_docs/version-3.0/pipeline-components/retrievers/elasticsearchsqlretriever.mdx +++ b/docs-website/versioned_docs/version-3.0/pipeline-components/retrievers/elasticsearchsqlretriever.mdx @@ -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."), diff --git a/docs-website/versioned_docs/version-3.0/pipeline-components/retrievers/opensearchsqlretriever.mdx b/docs-website/versioned_docs/version-3.0/pipeline-components/retrievers/opensearchsqlretriever.mdx index c43cf09082..8e094d2264 100644 --- a/docs-website/versioned_docs/version-3.0/pipeline-components/retrievers/opensearchsqlretriever.mdx +++ b/docs-website/versioned_docs/version-3.0/pipeline-components/retrievers/opensearchsqlretriever.mdx @@ -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."), diff --git a/docs-website/versioned_docs/version-3.0/pipeline-components/retrievers/sqlalchemytableretriever.mdx b/docs-website/versioned_docs/version-3.0/pipeline-components/retrievers/sqlalchemytableretriever.mdx index c28d3a7654..2642b73728 100644 --- a/docs-website/versioned_docs/version-3.0/pipeline-components/retrievers/sqlalchemytableretriever.mdx +++ b/docs-website/versioned_docs/version-3.0/pipeline-components/retrievers/sqlalchemytableretriever.mdx @@ -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", diff --git a/docs-website/versioned_docs/version-3.0/pipeline-components/writers/cogneewriter.mdx b/docs-website/versioned_docs/version-3.0/pipeline-components/writers/cogneewriter.mdx index 4e516268dd..dd01774cff 100644 --- a/docs-website/versioned_docs/version-3.0/pipeline-components/writers/cogneewriter.mdx +++ b/docs-website/versioned_docs/version-3.0/pipeline-components/writers/cogneewriter.mdx @@ -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", ) ``` diff --git a/docs-website/versioned_docs/version-3.0/tools/tool.mdx b/docs-website/versioned_docs/version-3.0/tools/tool.mdx index 1c6a8c1055..af7e591593 100644 --- a/docs-website/versioned_docs/version-3.0/tools/tool.mdx +++ b/docs-website/versioned_docs/version-3.0/tools/tool.mdx @@ -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, diff --git a/pyproject.toml b/pyproject.toml index 19d3c63c88..477423d3b2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -66,7 +66,7 @@ dependencies = [ installer = "uv" dependencies = [ "pre-commit", - "ruff>=0.15.0", # RUF104 (unmatched-suppression-comment) added in 0.15.0 + "ruff>=0.16.0", "toml", "reno", # dulwich is a reno dependency, they pin it at >=0.15.0 so pip takes ton of time to resolve the dependency tree. @@ -207,8 +207,6 @@ module = ["haystack.testing.*"] disallow_incomplete_defs = false [tool.ruff] -# "*.md": ruff formats Python code blocks inside Markdown; our docs (including the generated -# docs-website API reference) are not managed by ruff. exclude = ["*.md", "e2e/**", "proposals"] line-length = 120 diff --git a/scripts/ruff_format_docs.py b/scripts/ruff_format_docs.py deleted file mode 100644 index bbd7b36948..0000000000 --- a/scripts/ruff_format_docs.py +++ /dev/null @@ -1,128 +0,0 @@ -# SPDX-FileCopyrightText: 2022-present deepset GmbH -# -# SPDX-License-Identifier: Apache-2.0 - -""" -Pre-commit hook that runs ruff format on Python code blocks in Markdown/MDX files. - -Uses the ruff configuration from pyproject.toml automatically. -""" - -import argparse -import logging -import os -import re -import subprocess -import sys -import tempfile - -logger = logging.getLogger(__name__) -logger.setLevel(logging.INFO) -handler = logging.StreamHandler(sys.stderr) -handler.setFormatter(logging.Formatter("%(message)s")) -logger.addHandler(handler) - -# ANSI color codes (disabled when stderr is not a terminal) -_USE_COLOR = hasattr(sys.stderr, "isatty") and sys.stderr.isatty() - -PYTHON_FENCE_RE = re.compile( - r"(?P^```python\s*\n)" - r"(?P.*?)" - r"(?P^```\s*$)", - re.MULTILINE | re.DOTALL, -) - - -def _color(code: str, text: str) -> str: - """Colorize the text""" - if _USE_COLOR: - return f"\033[{code}m{text}\033[0m" - return text - - -def _find_tool(name: str) -> str: - """Find a tool installed in the same virtualenv as the running Python.""" - return os.path.join(os.path.dirname(sys.executable), name) - - -def _ruff(code: str, *, line_length: int) -> str: - return subprocess.run( - [ - _find_tool("ruff"), - "format", - f"--line-length={line_length}", - "--config", - "format.skip-magic-trailing-comma = false", - "--stdin-filename", - "block.py", - "-", - ], - input=code, - capture_output=True, - text=True, - check=True, - ).stdout - - -def _add_trailing_commas(code: str) -> str: - """Add trailing commas to multi-line expressions using add-trailing-comma.""" - with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f: - f.write(code) - tmpfile = f.name - try: - subprocess.run([_find_tool("add-trailing-comma"), tmpfile], capture_output=True, check=False) - with open(tmpfile) as f: - return f.read() - finally: - os.unlink(tmpfile) - - -def _format_code_block(match: re.Match, *, line_length: int, path: str) -> str: - """Format a single code block""" - code = match.group("code") - try: - # 1. ruff format (may create new multi-line expressions) - # 2. add trailing commas to all multi-line expressions - # 3. ruff format again (respects trailing commas, ensures stable output) - formatted = _ruff(_add_trailing_commas(_ruff(code, line_length=line_length)), line_length=line_length) - except subprocess.CalledProcessError as exc: - snippet = code.strip().splitlines() - preview = "\n".join(snippet[:5]) - if len(snippet) > 5: - preview += f"\n... ({len(snippet) - 5} more lines)" - logger.warning( - "%s %s\n%s\n%s %s", - _color("33", "WARNING:"), - _color("1", path), - _color("2", preview), - _color("31", "ruff stderr:"), - exc.stderr.strip(), - ) - return match.group(0) - return match.group("before") + formatted + match.group("after") - - -def main() -> int: - """Main entrypoint""" - parser = argparse.ArgumentParser() - parser.add_argument("--line-length", type=int, default=120) - parser.add_argument("files", nargs="*") - args = parser.parse_args() - - ret = 0 - for path in args.files: - with open(path) as f: - original = f.read() - new = PYTHON_FENCE_RE.sub( - lambda m, path=path: _format_code_block(m, line_length=args.line_length, path=path), original - ) - if new != original: - with open(path, "w") as f: - f.write(new) - logger.debug("%s %s", _color("32", "Rewriting:"), _color("1", path)) - ret = 1 - return ret - - -if __name__ == "__main__": - raise SystemExit(main())