From 0a909461eddcde602e2628e3ef60176dab4fcc01 Mon Sep 17 00:00:00 2001 From: Vladimir Blagojevic Date: Thu, 27 Nov 2025 16:29:19 +0100 Subject: [PATCH 1/9] Update code snippets in docs --- docs-website/scripts/test_python_snippets.py | 19 +++++++++++--- haystack/components/audio/whisper_local.py | 2 +- haystack/components/audio/whisper_remote.py | 5 ++-- .../builders/chat_prompt_builder.py | 25 ++++++------------- 4 files changed, 28 insertions(+), 23 deletions(-) diff --git a/docs-website/scripts/test_python_snippets.py b/docs-website/scripts/test_python_snippets.py index 3a524f59df..662232523f 100755 --- a/docs-website/scripts/test_python_snippets.py +++ b/docs-website/scripts/test_python_snippets.py @@ -331,12 +331,25 @@ def run_snippet(snippet: Snippet, timeout_seconds: int, cwd: str, skip_unsafe: b stderr=completed.stderr, ) except subprocess.TimeoutExpired as exc: + # Handle stderr which might be bytes or str + stderr_text = exc.stderr + if stderr_text is None: + stderr_text = "" + elif isinstance(stderr_text, bytes): + stderr_text = stderr_text.decode("utf-8", errors="replace") + stderr_text = stderr_text + f"\n[timeout after {timeout_seconds}s]" + + # Handle stdout which might be bytes or str + stdout_text = exc.stdout + if stdout_text is not None and isinstance(stdout_text, bytes): + stdout_text = stdout_text.decode("utf-8", errors="replace") + return ExecutionResult( snippet=snippet, status=ExecutionStatus.FAILED, reason=f"timeout after {timeout_seconds}s", - stdout=exc.stdout or None, - stderr=(exc.stderr or "") + f"\n[timeout after {timeout_seconds}s]", + stdout=stdout_text, + stderr=stderr_text, ) @@ -414,7 +427,7 @@ def main(argv: Optional[list[str]] = None) -> int: "(defaults to docs and versioned_docs)" ), ) - parser.add_argument("--timeout-seconds", type=int, default=30, help="Timeout per snippet execution (seconds)") + parser.add_argument("--timeout-seconds", type=int, default=600, help="Timeout per snippet execution (seconds)") parser.add_argument( "--allow-unsafe", action="store_true", help="Allow execution of snippets with potentially unsafe patterns" ) diff --git a/haystack/components/audio/whisper_local.py b/haystack/components/audio/whisper_local.py index 66bf2a3d0d..bb7a963612 100644 --- a/haystack/components/audio/whisper_local.py +++ b/haystack/components/audio/whisper_local.py @@ -46,7 +46,7 @@ class LocalWhisperTranscriber: whisper = LocalWhisperTranscriber(model="small") whisper.warm_up() - transcription = whisper.run(sources=["path/to/audio/file"]) + transcription = whisper.run(sources=["test/test_files/audio/answer.wav"]) ``` """ diff --git a/haystack/components/audio/whisper_remote.py b/haystack/components/audio/whisper_remote.py index b8ff4f19fc..83593aebb8 100644 --- a/haystack/components/audio/whisper_remote.py +++ b/haystack/components/audio/whisper_remote.py @@ -30,9 +30,10 @@ class RemoteWhisperTranscriber: ```python from haystack.components.audio import RemoteWhisperTranscriber + from haystack.utils import Secret - whisper = RemoteWhisperTranscriber(api_key=Secret.from_token(""), model="tiny") - transcription = whisper.run(sources=["path/to/audio/file"]) + whisper = RemoteWhisperTranscriber(api_key=Secret.from_env_var("OPENAI_API_KEY"), model="whisper-1") + transcription = whisper.run(sources=["test/test_files/audio/answer.wav"]) ``` """ diff --git a/haystack/components/builders/chat_prompt_builder.py b/haystack/components/builders/chat_prompt_builder.py index aba2780fa7..2d5f6a56f1 100644 --- a/haystack/components/builders/chat_prompt_builder.py +++ b/haystack/components/builders/chat_prompt_builder.py @@ -75,7 +75,7 @@ class ChatPromptBuilder: # no parameter init, we don't use any runtime template variables prompt_builder = ChatPromptBuilder() - llm = OpenAIChatGenerator(api_key=Secret.from_token(""), model="gpt-4o-mini") + llm = OpenAIChatGenerator(api_key=Secret.from_env_var("OPENAI_API_KEY"), model="gpt-5-mini") pipe = Pipeline() pipe.add_component("prompt_builder", prompt_builder) @@ -90,27 +90,17 @@ class ChatPromptBuilder: res = pipe.run(data={"prompt_builder": {"template_variables": {"location": location, "language": language}, "template": messages}}) print(res) + # Output example (truncated): + # {'llm': {'replies': [ChatMessage(...)]}} - >> {'llm': {'replies': [ChatMessage(_role=, _content=[TextContent(text= - "Berlin is the capital city of Germany and one of the most vibrant - and diverse cities in Europe. Here are some key things to know...Enjoy your time exploring the vibrant and dynamic - capital of Germany!")], _name=None, _meta={'model': 'gpt-4o-mini', - 'index': 0, 'finish_reason': 'stop', 'usage': {'prompt_tokens': 27, 'completion_tokens': 681, 'total_tokens': - 708}})]}} - - messages = [system_message, ChatMessage.from_user("What's the weather forecast for {{location}} in the next - {{day_count}} days?")] + messages = [system_message, ChatMessage.from_user("What's the forecast for {{location}}, next {{day_count}} days?")] res = pipe.run(data={"prompt_builder": {"template_variables": {"location": location, "day_count": "5"}, "template": messages}}) print(res) - >> {'llm': {'replies': [ChatMessage(_role=, _content=[TextContent(text= - "Here is the weather forecast for Berlin in the next 5 - days:\\n\\nDay 1: Mostly cloudy with a high of 22°C (72°F) and...so it's always a good idea to check for updates - closer to your visit.")], _name=None, _meta={'model': 'gpt-4o-mini', - 'index': 0, 'finish_reason': 'stop', 'usage': {'prompt_tokens': 37, 'completion_tokens': 201, - 'total_tokens': 238}})]}} + # Output example (truncated): + # {'llm': {'replies': [ChatMessage(...)]}} ``` #### String prompt template @@ -131,7 +121,8 @@ class ChatPromptBuilder: {% endmessage %} \"\"\" - images = [ImageContent.from_file_path("apple.jpg"), ImageContent.from_file_path("orange.jpg")] + images = [ImageContent.from_file_path("test/test_files/images/apple.jpg"), + ImageContent.from_file_path("test/test_files/images/haystack-logo.png")] builder = ChatPromptBuilder(template=template) builder.run(user_name="John", images=images) From 18733fa828ebedfe5b20903bcf0080abc198ad9e Mon Sep 17 00:00:00 2001 From: Vladimir Blagojevic Date: Thu, 27 Nov 2025 16:37:09 +0100 Subject: [PATCH 2/9] Add reno note --- ...x-pydoc-examples-audio-builders-7b1d2d945099bb16.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 releasenotes/notes/fix-pydoc-examples-audio-builders-7b1d2d945099bb16.yaml diff --git a/releasenotes/notes/fix-pydoc-examples-audio-builders-7b1d2d945099bb16.yaml b/releasenotes/notes/fix-pydoc-examples-audio-builders-7b1d2d945099bb16.yaml new file mode 100644 index 0000000000..b338d61b49 --- /dev/null +++ b/releasenotes/notes/fix-pydoc-examples-audio-builders-7b1d2d945099bb16.yaml @@ -0,0 +1,9 @@ +--- +fixes: + - | + Fixed pydoc examples in audio and builder components to be valid executable scripts. + Added missing ``Secret`` import in ``RemoteWhisperTranscriber`` example, fixed unterminated + string literals in ``ChatPromptBuilder`` examples, and updated file paths to use actual test + files instead of placeholders. API key examples now use environment variables instead of + hardcoded placeholders. This ensures all documentation examples can be tested and executed + successfully. From 3e20eec3d9a3f4edc1305ebef03826ad7571e0ff Mon Sep 17 00:00:00 2001 From: Vladimir Blagojevic Date: Fri, 28 Nov 2025 13:19:47 +0100 Subject: [PATCH 3/9] Revert "Add reno note" This reverts commit 18733fa828ebedfe5b20903bcf0080abc198ad9e. --- ...x-pydoc-examples-audio-builders-7b1d2d945099bb16.yaml | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 releasenotes/notes/fix-pydoc-examples-audio-builders-7b1d2d945099bb16.yaml diff --git a/releasenotes/notes/fix-pydoc-examples-audio-builders-7b1d2d945099bb16.yaml b/releasenotes/notes/fix-pydoc-examples-audio-builders-7b1d2d945099bb16.yaml deleted file mode 100644 index b338d61b49..0000000000 --- a/releasenotes/notes/fix-pydoc-examples-audio-builders-7b1d2d945099bb16.yaml +++ /dev/null @@ -1,9 +0,0 @@ ---- -fixes: - - | - Fixed pydoc examples in audio and builder components to be valid executable scripts. - Added missing ``Secret`` import in ``RemoteWhisperTranscriber`` example, fixed unterminated - string literals in ``ChatPromptBuilder`` examples, and updated file paths to use actual test - files instead of placeholders. API key examples now use environment variables instead of - hardcoded placeholders. This ensures all documentation examples can be tested and executed - successfully. From 91021fdfd295d1e020f1ea1987a02e41e152f72f Mon Sep 17 00:00:00 2001 From: Vladimir Blagojevic Date: Thu, 11 Dec 2025 11:45:05 +0100 Subject: [PATCH 4/9] PR feedback --- haystack/components/audio/whisper_remote.py | 2 +- haystack/components/builders/chat_prompt_builder.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/haystack/components/audio/whisper_remote.py b/haystack/components/audio/whisper_remote.py index 83593aebb8..4780d93864 100644 --- a/haystack/components/audio/whisper_remote.py +++ b/haystack/components/audio/whisper_remote.py @@ -32,7 +32,7 @@ class RemoteWhisperTranscriber: from haystack.components.audio import RemoteWhisperTranscriber from haystack.utils import Secret - whisper = RemoteWhisperTranscriber(api_key=Secret.from_env_var("OPENAI_API_KEY"), model="whisper-1") + whisper = RemoteWhisperTranscriber(model="whisper-1") transcription = whisper.run(sources=["test/test_files/audio/answer.wav"]) ``` """ diff --git a/haystack/components/builders/chat_prompt_builder.py b/haystack/components/builders/chat_prompt_builder.py index bbad7bff01..8d5355c2e0 100644 --- a/haystack/components/builders/chat_prompt_builder.py +++ b/haystack/components/builders/chat_prompt_builder.py @@ -75,7 +75,7 @@ class ChatPromptBuilder: # no parameter init, we don't use any runtime template variables prompt_builder = ChatPromptBuilder() - llm = OpenAIChatGenerator(api_key=Secret.from_env_var("OPENAI_API_KEY"), model="gpt-5-mini") + llm = OpenAIChatGenerator(model="gpt-5-mini") pipe = Pipeline() pipe.add_component("prompt_builder", prompt_builder) From 3041e0443d50eb2945d44f500aac59c598297755 Mon Sep 17 00:00:00 2001 From: Vladimir Blagojevic Date: Thu, 11 Dec 2025 11:46:06 +0100 Subject: [PATCH 5/9] Minor fix --- haystack/components/audio/whisper_remote.py | 1 - 1 file changed, 1 deletion(-) diff --git a/haystack/components/audio/whisper_remote.py b/haystack/components/audio/whisper_remote.py index 4780d93864..3371afab91 100644 --- a/haystack/components/audio/whisper_remote.py +++ b/haystack/components/audio/whisper_remote.py @@ -30,7 +30,6 @@ class RemoteWhisperTranscriber: ```python from haystack.components.audio import RemoteWhisperTranscriber - from haystack.utils import Secret whisper = RemoteWhisperTranscriber(model="whisper-1") transcription = whisper.run(sources=["test/test_files/audio/answer.wav"]) From b68eaece2f4116ea61c57d7abe632d0ba07cf659 Mon Sep 17 00:00:00 2001 From: Vladimir Blagojevic Date: Thu, 11 Dec 2025 12:53:43 +0100 Subject: [PATCH 6/9] No Secrets between us --- haystack/components/builders/chat_prompt_builder.py | 1 - 1 file changed, 1 deletion(-) diff --git a/haystack/components/builders/chat_prompt_builder.py b/haystack/components/builders/chat_prompt_builder.py index 8d5355c2e0..78c39971c6 100644 --- a/haystack/components/builders/chat_prompt_builder.py +++ b/haystack/components/builders/chat_prompt_builder.py @@ -71,7 +71,6 @@ class ChatPromptBuilder: from haystack.components.generators.chat import OpenAIChatGenerator from haystack.dataclasses import ChatMessage from haystack import Pipeline - from haystack.utils import Secret # no parameter init, we don't use any runtime template variables prompt_builder = ChatPromptBuilder() From 1f1cc5d545160946201efd0c7055385cce651c53 Mon Sep 17 00:00:00 2001 From: Vladimir Blagojevic Date: Thu, 11 Dec 2025 14:32:25 +0100 Subject: [PATCH 7/9] Comments format update --- haystack/components/builders/chat_prompt_builder.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/haystack/components/builders/chat_prompt_builder.py b/haystack/components/builders/chat_prompt_builder.py index 78c39971c6..2856640ad5 100644 --- a/haystack/components/builders/chat_prompt_builder.py +++ b/haystack/components/builders/chat_prompt_builder.py @@ -98,12 +98,12 @@ class ChatPromptBuilder: "template": messages}}) print(res) - >> {'llm': {'replies': [ChatMessage(_role=, _content=[TextContent(text= - "Here is the weather forecast for Berlin in the next 5 - days:\\n\\nDay 1: Mostly cloudy with a high of 22°C (72°F) and...so it's always a good idea to check for updates - closer to your visit.")], _name=None, _meta={'model': 'gpt-5-mini', - 'index': 0, 'finish_reason': 'stop', 'usage': {'prompt_tokens': 37, 'completion_tokens': 201, - 'total_tokens': 238}})]}} + # Output example (truncated): + # {'llm': {'replies': [ChatMessage(_role=, _content=[TextContent(text= + # "Here is the weather forecast for Berlin in the next 5 days:\\n\\nDay 1: Mostly cloudy with a high of 22°C (72°F) + # and...so it's always a good idea to check for updates closer to your visit.")], _name=None, + # _meta={'model': 'gpt-5-mini', 'index': 0, 'finish_reason': 'stop', + # 'usage': {'prompt_tokens': 37, 'completion_tokens': 201, 'total_tokens': 238}})]}} ``` #### String prompt template From 2c21ce4c7eb262f25d74c4119dae29c4a90e3bc1 Mon Sep 17 00:00:00 2001 From: Vladimir Blagojevic Date: Thu, 11 Dec 2025 14:44:03 +0100 Subject: [PATCH 8/9] Restore output format --- .../builders/chat_prompt_builder.py | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/haystack/components/builders/chat_prompt_builder.py b/haystack/components/builders/chat_prompt_builder.py index 2856640ad5..c16cf498a7 100644 --- a/haystack/components/builders/chat_prompt_builder.py +++ b/haystack/components/builders/chat_prompt_builder.py @@ -89,21 +89,26 @@ class ChatPromptBuilder: res = pipe.run(data={"prompt_builder": {"template_variables": {"location": location, "language": language}, "template": messages}}) print(res) - # Output example (truncated): - # {'llm': {'replies': [ChatMessage(...)]}} + >> {'llm': {'replies': [ChatMessage(_role=, _content=[TextContent(text= + "Berlin is the capital city of Germany and one of the most vibrant + and diverse cities in Europe. Here are some key things to know...Enjoy your time exploring the vibrant and dynamic + capital of Germany!")], _name=None, _meta={'model': 'gpt-5-mini', + 'index': 0, 'finish_reason': 'stop', 'usage': {'prompt_tokens': 27, 'completion_tokens': 681, 'total_tokens': + 708}})]}} - messages = [system_message, ChatMessage.from_user("What's the forecast for {{location}}, next {{day_count}} days?")] + messages = [system_message, ChatMessage.from_user("What's the weather forecast for {{location}} in the next + {{day_count}} days?")] res = pipe.run(data={"prompt_builder": {"template_variables": {"location": location, "day_count": "5"}, "template": messages}}) print(res) - # Output example (truncated): - # {'llm': {'replies': [ChatMessage(_role=, _content=[TextContent(text= - # "Here is the weather forecast for Berlin in the next 5 days:\\n\\nDay 1: Mostly cloudy with a high of 22°C (72°F) - # and...so it's always a good idea to check for updates closer to your visit.")], _name=None, - # _meta={'model': 'gpt-5-mini', 'index': 0, 'finish_reason': 'stop', - # 'usage': {'prompt_tokens': 37, 'completion_tokens': 201, 'total_tokens': 238}})]}} + >> {'llm': {'replies': [ChatMessage(_role=, _content=[TextContent(text= + "Here is the weather forecast for Berlin in the next 5 + days:\\n\\nDay 1: Mostly cloudy with a high of 22°C (72°F) and...so it's always a good idea to check for updates + closer to your visit.")], _name=None, _meta={'model': 'gpt-5-mini', + 'index': 0, 'finish_reason': 'stop', 'usage': {'prompt_tokens': 37, 'completion_tokens': 201, + 'total_tokens': 238}})]}} ``` #### String prompt template From 3d42fa2f2f1211cbb71ed144eb4723018b1975cd Mon Sep 17 00:00:00 2001 From: Vladimir Blagojevic Date: Thu, 11 Dec 2025 14:51:27 +0100 Subject: [PATCH 9/9] Script output, needs to be commented --- .../builders/chat_prompt_builder.py | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/haystack/components/builders/chat_prompt_builder.py b/haystack/components/builders/chat_prompt_builder.py index c16cf498a7..d3cb0b3afc 100644 --- a/haystack/components/builders/chat_prompt_builder.py +++ b/haystack/components/builders/chat_prompt_builder.py @@ -89,12 +89,12 @@ class ChatPromptBuilder: res = pipe.run(data={"prompt_builder": {"template_variables": {"location": location, "language": language}, "template": messages}}) print(res) - >> {'llm': {'replies': [ChatMessage(_role=, _content=[TextContent(text= - "Berlin is the capital city of Germany and one of the most vibrant - and diverse cities in Europe. Here are some key things to know...Enjoy your time exploring the vibrant and dynamic - capital of Germany!")], _name=None, _meta={'model': 'gpt-5-mini', - 'index': 0, 'finish_reason': 'stop', 'usage': {'prompt_tokens': 27, 'completion_tokens': 681, 'total_tokens': - 708}})]}} + # >> {'llm': {'replies': [ChatMessage(_role=, _content=[TextContent(text= + # "Berlin is the capital city of Germany and one of the most vibrant + # and diverse cities in Europe. Here are some key things to know...Enjoy your time exploring the vibrant and dynamic + # capital of Germany!")], _name=None, _meta={'model': 'gpt-5-mini', + # 'index': 0, 'finish_reason': 'stop', 'usage': {'prompt_tokens': 27, 'completion_tokens': 681, 'total_tokens': + # 708}})]}} messages = [system_message, ChatMessage.from_user("What's the weather forecast for {{location}} in the next {{day_count}} days?")] @@ -103,12 +103,12 @@ class ChatPromptBuilder: "template": messages}}) print(res) - >> {'llm': {'replies': [ChatMessage(_role=, _content=[TextContent(text= - "Here is the weather forecast for Berlin in the next 5 - days:\\n\\nDay 1: Mostly cloudy with a high of 22°C (72°F) and...so it's always a good idea to check for updates - closer to your visit.")], _name=None, _meta={'model': 'gpt-5-mini', - 'index': 0, 'finish_reason': 'stop', 'usage': {'prompt_tokens': 37, 'completion_tokens': 201, - 'total_tokens': 238}})]}} + # >> {'llm': {'replies': [ChatMessage(_role=, _content=[TextContent(text= + # "Here is the weather forecast for Berlin in the next 5 + # days:\\n\\nDay 1: Mostly cloudy with a high of 22°C (72°F) and...so it's always a good idea to check for updates + # closer to your visit.")], _name=None, _meta={'model': 'gpt-5-mini', + # 'index': 0, 'finish_reason': 'stop', 'usage': {'prompt_tokens': 37, 'completion_tokens': 201, + # 'total_tokens': 238}})]}} ``` #### String prompt template