diff --git a/docs-website/reference/haystack-api/agents_api.md b/docs-website/reference/haystack-api/agents_api.md index 834e303e5a..c58debc2a0 100644 --- a/docs-website/reference/haystack-api/agents_api.md +++ b/docs-website/reference/haystack-api/agents_api.md @@ -28,7 +28,7 @@ This is an example agent that: ```python from haystack.components.agents import Agent -from haystack.components.generators.chat import OpenAIChatGenerator +from haystack.components.generators.chat import OpenAIResponsesChatGenerator from haystack.components.generators.utils import print_streaming_chunk from haystack.dataclasses import ChatMessage from haystack.tools import tool @@ -59,7 +59,7 @@ agent = Agent( "You are a helpful assistant. Use the 'search' tool to find information " "about a user's question and the 'calculator' tool to perform math." ), - chat_generator=OpenAIChatGenerator(), + chat_generator=OpenAIResponsesChatGenerator(), tools=[search, calculator], streaming_callback=print_streaming_chunk, ) @@ -80,7 +80,7 @@ This is especially useful when embedding the Agent in a pipeline. ```python from haystack.components.agents import Agent -from haystack.components.generators.chat import OpenAIChatGenerator +from haystack.components.generators.chat import OpenAIResponsesChatGenerator from haystack.tools import tool from typing import Annotated @@ -95,7 +95,7 @@ def translate( return f"[Translated '{text}' to {target_language}]" agent = Agent( - chat_generator=OpenAIChatGenerator(), + chat_generator=OpenAIResponsesChatGenerator(), tools=[translate], system_prompt="You are a helpful translation assistant.", user_prompt="""{% message role="user"%} @@ -134,7 +134,7 @@ required tool has been called. ```python from haystack.components.agents import Agent from haystack.components.agents.state import State -from haystack.components.generators.chat import OpenAIChatGenerator +from haystack.components.generators.chat import OpenAIResponsesChatGenerator from haystack.dataclasses import ChatMessage from haystack.hooks import hook from haystack.tools import tool @@ -156,7 +156,7 @@ def require_save(state: State) -> None: agent = Agent( - chat_generator=OpenAIChatGenerator(), + chat_generator=OpenAIResponsesChatGenerator(), tools=[save_result], hooks={"on_exit": [require_save]}, ) diff --git a/docs-website/reference/haystack-api/builders_api.md b/docs-website/reference/haystack-api/builders_api.md index d8a867273a..e907de0351 100644 --- a/docs-website/reference/haystack-api/builders_api.md +++ b/docs-website/reference/haystack-api/builders_api.md @@ -378,7 +378,7 @@ with the contents of the retrieved documents and a query. The rendered prompt is ```python from haystack import Pipeline, Document from haystack.utils import Secret -from haystack.components.generators.chat import OpenAIChatGenerator +from haystack.components.generators.chat import OpenAIResponsesChatGenerator from haystack.components.builders.prompt_builder import PromptBuilder # in a real world use case documents could come from a retriever, web, or any other source @@ -395,7 +395,7 @@ prompt_template = """ """ p = Pipeline() p.add_component(instance=PromptBuilder(template=prompt_template), name="prompt_builder") -p.add_component(instance=OpenAIChatGenerator(api_key=Secret.from_env_var("OPENAI_API_KEY")), name="llm") +p.add_component(instance=OpenAIResponsesChatGenerator(api_key=Secret.from_env_var("OPENAI_API_KEY")), name="llm") p.connect("prompt_builder", "llm") question = "Where does Joe live?" diff --git a/docs-website/reference/haystack-api/extractors_api.md b/docs-website/reference/haystack-api/extractors_api.md index 24e5907334..f4e51f1a01 100644 --- a/docs-website/reference/haystack-api/extractors_api.md +++ b/docs-website/reference/haystack-api/extractors_api.md @@ -22,8 +22,8 @@ Response handling: - If the LLM returns a **JSON object with multiple keys**, the value of `document_content` (if present) is written to content and all other keys are merged into the document's metadata. -The ChatGenerator can be configured to return JSON (e.g. `response_format={"type": "json_object"}` -in `generation_kwargs`). +The ChatGenerator can be configured to return JSON. For example, with the OpenAIResponsesChatGenerator, pass +`{"text": {"format": {"type": "json_schema", ...}}}` in `generation_kwargs` as shown in the usage example below. Documents that fail extraction are returned in `failed_documents` with `content_extraction_error` in metadata. @@ -31,7 +31,7 @@ Documents that fail extraction are returned in `failed_documents` with `content_ ```python from haystack import Document -from haystack.components.generators.chat import OpenAIChatGenerator +from haystack.components.generators.chat import OpenAIResponsesChatGenerator from haystack.components.extractors.image import LLMDocumentContentExtractor prompt = """ @@ -43,12 +43,13 @@ Extract metadata about the image like source of the image, date of creation, etc Return this metadata as additional key-value pairs in the same JSON object. """ -chat_generator = OpenAIChatGenerator( +chat_generator = OpenAIResponsesChatGenerator( generation_kwargs={ - "response_format": { - "type": "json_schema", - "json_schema": { + "text": { + "format": { + "type": "json_schema", "name": "entity_extraction", + "strict": False, "schema": { "type": "object", "properties": { @@ -100,7 +101,8 @@ Initialize the LLMDocumentContentExtractor component. **Parameters:** - **chat_generator** (ChatGenerator) – A ChatGenerator that supports vision input. Optionally configured for JSON - (e.g. `response_format={"type": "json_object"}` in `generation_kwargs`). + (e.g. `{"text": {"format": {"type": "json_schema", ...}}}` in `generation_kwargs` when using the + OpenAIResponsesChatGenerator). - **prompt** (str) – Prompt for extraction. Must not contain Jinja variables. - **file_path_meta_field** (str) – The metadata field in the Document that contains the file path to the image or PDF. - **root_path** (str | None) – The root directory path where document files are located. If provided, file paths in @@ -232,7 +234,7 @@ extract metadata by using the `metadata_extraction_response` and `metadata_extra ```python from haystack import Document from haystack.components.extractors.llm_metadata_extractor import LLMMetadataExtractor -from haystack.components.generators.chat import OpenAIChatGenerator +from haystack.components.generators.chat import OpenAIResponsesChatGenerator NER_PROMPT = ''' -Goal- @@ -278,15 +280,13 @@ docs = [ Document(content="Hugging Face is a company that was founded in New York, USA and is known for its Transformers library") ] -chat_generator = OpenAIChatGenerator( +chat_generator = OpenAIResponsesChatGenerator( generation_kwargs={ - "max_completion_tokens": 500, - "temperature": 0.0, - "seed": 0, - "response_format": { - "type": "json_schema", - "json_schema": { + "text": { + "format": { + "type": "json_schema", "name": "entity_extraction", + "strict": True, "schema": { "type": "object", "properties": { @@ -357,8 +357,9 @@ Initializes the LLMMetadataExtractor. which points to a single document in the list of documents. For example, to access the content of the document, use `{{ document.content }}` in the prompt. - **chat_generator** (ChatGenerator) – a ChatGenerator instance which represents the LLM. In order for the component to work, - the LLM should be configured to return a JSON object. For example, when using the OpenAIChatGenerator, you - should pass `{"response_format": {"type": "json_object"}}` in the `generation_kwargs`. + the LLM should be configured to return a JSON object. For example, when using the + OpenAIResponsesChatGenerator, you should pass `{"text": {"format": {"type": "json_schema", ...}}}` in the + `generation_kwargs`. - **expected_keys** (list\[str\] | None) – The keys expected in the JSON output from the LLM. - **page_range** (list\[str | int\] | None) – A range of pages to extract metadata from. For example, page_range=['1', '3'] will extract metadata from the first and third pages of each document. It also accepts printable range strings, e.g.: diff --git a/docs-website/reference/haystack-api/generators_api.md b/docs-website/reference/haystack-api/generators_api.md index 3fc6bd5ea9..e20f3856d6 100644 --- a/docs-website/reference/haystack-api/generators_api.md +++ b/docs-website/reference/haystack-api/generators_api.md @@ -607,10 +607,10 @@ without tool usage. It processes messages and returns a single response from the ```python from haystack.components.generators.chat import LLM -from haystack.components.generators.chat import OpenAIChatGenerator +from haystack.components.generators.chat import OpenAIResponsesChatGenerator llm = LLM( - chat_generator=OpenAIChatGenerator(), + chat_generator=OpenAIResponsesChatGenerator(), system_prompt="You are a helpful translation assistant.", user_prompt="Summarize the following document: {{ document }}", required_variables=["document"], diff --git a/docs-website/reference/haystack-api/hooks_api.md b/docs-website/reference/haystack-api/hooks_api.md index 6ea8345c9d..eb84934c2e 100644 --- a/docs-website/reference/haystack-api/hooks_api.md +++ b/docs-website/reference/haystack-api/hooks_api.md @@ -22,11 +22,11 @@ not included. ```python from haystack.components.agents import Agent -from haystack.components.generators.chat import OpenAIChatGenerator +from haystack.components.generators.chat import OpenAIResponsesChatGenerator from haystack.hooks.budget import TokenBudgetHook agent = Agent( - chat_generator=OpenAIChatGenerator(), + chat_generator=OpenAIResponsesChatGenerator(), tools=[web_search], hooks={"before_llm": [TokenBudgetHook(max_total_tokens=100_000)]}, ) @@ -817,7 +817,7 @@ paths, construct a `FunctionHook` directly with both `function` and `async_funct ```python from haystack.components.agents import Agent -from haystack.components.generators.chat import OpenAIChatGenerator +from haystack.components.generators.chat import OpenAIResponsesChatGenerator from haystack.hooks import hook from haystack.components.agents.state import State from haystack.dataclasses import ChatMessage @@ -839,7 +839,11 @@ def require_save(state: State) -> None: state.set("messages", [ChatMessage.from_system("You must call `save` before finishing.")]) state.set("continue_run", True) -agent = Agent(chat_generator=OpenAIChatGenerator(), tools=[weather_tool, save], hooks={"on_exit": [require_save]}) +agent = Agent( + chat_generator=OpenAIResponsesChatGenerator(), + tools=[weather_tool, save], + hooks={"on_exit": [require_save]}, +) ``` **Parameters:** @@ -918,7 +922,7 @@ Register it on an `Agent` to confirm, modify, or reject tool calls before they r ```python from haystack.components.agents import Agent -from haystack.components.generators.chat import OpenAIChatGenerator +from haystack.components.generators.chat import OpenAIResponsesChatGenerator from haystack.tools import tool from haystack.hooks.human_in_the_loop import ( AlwaysAskPolicy, @@ -941,7 +945,7 @@ hook = ConfirmationHook( ) } ) -agent = Agent(chat_generator=OpenAIChatGenerator(), tools=[delete_file], hooks={"before_tool": [hook]}) +agent = Agent(chat_generator=OpenAIResponsesChatGenerator(), tools=[delete_file], hooks={"before_tool": [hook]}) ``` A key may be a single tool name, a tuple of tool names sharing one strategy, or the wildcard `"*"` which applies diff --git a/docs-website/reference/haystack-api/joiners_api.md b/docs-website/reference/haystack-api/joiners_api.md index 0507c18ace..c72af5b440 100644 --- a/docs-website/reference/haystack-api/joiners_api.md +++ b/docs-website/reference/haystack-api/joiners_api.md @@ -40,7 +40,7 @@ from haystack.components.joiners import AnswerJoiner from haystack.core.pipeline import Pipeline -from haystack.components.generators.chat import OpenAIChatGenerator +from haystack.components.generators.chat import OpenAIResponsesChatGenerator from haystack.dataclasses import ChatMessage @@ -49,8 +49,8 @@ messages = [ChatMessage.from_system("You are a helpful, respectful and honest as ChatMessage.from_user(query)] pipe = Pipeline() -pipe.add_component("llm_1", OpenAIChatGenerator()) -pipe.add_component("llm_2", OpenAIChatGenerator()) +pipe.add_component("llm_1", OpenAIResponsesChatGenerator()) +pipe.add_component("llm_2", OpenAIResponsesChatGenerator()) pipe.add_component("aba", AnswerBuilder()) pipe.add_component("abb", AnswerBuilder()) pipe.add_component("joiner", AnswerJoiner()) @@ -441,7 +441,7 @@ Usage example: ```python from haystack.components.builders import ChatPromptBuilder -from haystack.components.generators.chat import OpenAIChatGenerator +from haystack.components.generators.chat import OpenAIResponsesChatGenerator from haystack.dataclasses import ChatMessage from haystack import Pipeline from haystack.components.joiners import ListJoiner @@ -459,8 +459,8 @@ feedback_message = [ChatMessage.from_system(feedback_prompt)] prompt_builder = ChatPromptBuilder(template=user_message) feedback_prompt_builder = ChatPromptBuilder(template=feedback_message) -llm = OpenAIChatGenerator() -feedback_llm = OpenAIChatGenerator() +llm = OpenAIResponsesChatGenerator() +feedback_llm = OpenAIResponsesChatGenerator() pipe = Pipeline() pipe.add_component("prompt_builder", prompt_builder) @@ -554,9 +554,6 @@ from haystack.components.joiners import StringJoiner from haystack.components.builders import PromptBuilder from haystack.core.pipeline import Pipeline -from haystack.components.generators.chat import OpenAIChatGenerator -from haystack.dataclasses import ChatMessage - string_1 = "What's Natural Language Processing?" string_2 = "What is life?" diff --git a/docs-website/reference/haystack-api/pipeline_api.md b/docs-website/reference/haystack-api/pipeline_api.md index cdf31b06e9..b561beb051 100644 --- a/docs-website/reference/haystack-api/pipeline_api.md +++ b/docs-website/reference/haystack-api/pipeline_api.md @@ -72,7 +72,7 @@ Usage: from haystack import Pipeline, Document from haystack.components.builders.answer_builder import AnswerBuilder from haystack.components.builders.chat_prompt_builder import ChatPromptBuilder -from haystack.components.generators.chat import OpenAIChatGenerator +from haystack.components.generators.chat import OpenAIResponsesChatGenerator from haystack.components.retrievers.in_memory import InMemoryBM25Retriever from haystack.dataclasses import ChatMessage from haystack.document_stores.in_memory import InMemoryDocumentStore @@ -105,7 +105,7 @@ prompt_builder = ChatPromptBuilder( variables=["question", "documents"] ) -llm = OpenAIChatGenerator() +llm = OpenAIResponsesChatGenerator() rag_pipeline = Pipeline() rag_pipeline.add_component("retriever", retriever) rag_pipeline.add_component("prompt_builder", prompt_builder) @@ -198,7 +198,7 @@ from haystack.dataclasses import ChatMessage from haystack.utils import Secret from haystack.document_stores.in_memory import InMemoryDocumentStore from haystack.components.retrievers.in_memory import InMemoryBM25Retriever -from haystack.components.generators.chat import OpenAIChatGenerator +from haystack.components.generators.chat import OpenAIResponsesChatGenerator from haystack.components.builders.prompt_builder import PromptBuilder from haystack import Pipeline import asyncio @@ -227,7 +227,7 @@ prompt_template = [ # Create and connect pipeline components retriever = InMemoryBM25Retriever(document_store=document_store) prompt_builder = ChatPromptBuilder(template=prompt_template) -llm = OpenAIChatGenerator() +llm = OpenAIResponsesChatGenerator() rag_pipeline = Pipeline() rag_pipeline.add_component("retriever", retriever) @@ -303,7 +303,7 @@ import asyncio from haystack import Document from haystack.components.builders import ChatPromptBuilder -from haystack.components.generators.chat import OpenAIChatGenerator +from haystack.components.generators.chat import OpenAIResponsesChatGenerator from haystack.components.retrievers.in_memory import InMemoryBM25Retriever from haystack import Pipeline from haystack.dataclasses import ChatMessage @@ -332,7 +332,7 @@ prompt_template = [ retriever = InMemoryBM25Retriever(document_store=document_store) prompt_builder = ChatPromptBuilder(template=prompt_template) -llm = OpenAIChatGenerator() +llm = OpenAIResponsesChatGenerator() rag_pipeline = Pipeline() rag_pipeline.add_component("retriever", retriever) @@ -354,13 +354,8 @@ data = { results = asyncio.run(run_inner(data, include_outputs_from={"retriever", "llm"})) -print(results["llm"]["replies"]) -# [ChatMessage(_role=, _content=[TextContent(text='Jean lives in Paris.')], -# _name=None, _meta={'model': 'gpt-5-mini', 'index': 0, 'finish_reason': 'stop', 'usage': -# {'completion_tokens': 6, 'prompt_tokens': 69, 'total_tokens': 75, -# 'completion_tokens_details': CompletionTokensDetails(accepted_prediction_tokens=0, -# audio_tokens=0, reasoning_tokens=0, rejected_prediction_tokens=0), 'prompt_tokens_details': -# PromptTokensDetails(audio_tokens=0, cached_tokens=0)}})] +print(results["llm"]["replies"][0].text) +# >> Jean lives in Paris. ``` **Parameters:** @@ -434,7 +429,7 @@ Usage: import asyncio from haystack.components.builders import ChatPromptBuilder -from haystack.components.generators.chat import OpenAIChatGenerator +from haystack.components.generators.chat import OpenAIResponsesChatGenerator from haystack import Pipeline from haystack.dataclasses import ChatMessage @@ -443,7 +438,7 @@ pipe.add_component( "prompt_builder", ChatPromptBuilder(template=[ChatMessage.from_user("Tell me about {{topic}}")]), ) -pipe.add_component("llm", OpenAIChatGenerator()) +pipe.add_component("llm", OpenAIResponsesChatGenerator()) pipe.connect("prompt_builder.prompt", "llm.messages") async def main(): diff --git a/docs-website/reference/haystack-api/tools_api.md b/docs-website/reference/haystack-api/tools_api.md index 2ca42ba11c..f15d7a33ff 100644 --- a/docs-website/reference/haystack-api/tools_api.md +++ b/docs-website/reference/haystack-api/tools_api.md @@ -228,7 +228,7 @@ from haystack import component from haystack.tools import ComponentTool from haystack.utils import Secret from haystack.components.agents import Agent -from haystack.components.generators.chat import OpenAIChatGenerator +from haystack.components.generators.chat import OpenAIResponsesChatGenerator from haystack.dataclasses import ChatMessage from haystack_integrations.components.websearch.serperdev import SerperDevWebSearch @@ -242,8 +242,8 @@ tool = ComponentTool( description="Search the web for current information on any topic" # Optional: defaults to component docstring ) -# Create an Agent with an OpenAIChatGenerator and the tool -agent = Agent(chat_generator=OpenAIChatGenerator(), tools=[tool]) +# Create an Agent with an OpenAIResponsesChatGenerator and the tool +agent = Agent(chat_generator=OpenAIResponsesChatGenerator(), tools=[tool]) message = ChatMessage.from_user("Use the web search tool to find information about Nikola Tesla") @@ -861,7 +861,7 @@ without any discovery mechanism. from typing import Annotated from haystack.components.agents import Agent -from haystack.components.generators.chat import OpenAIChatGenerator +from haystack.components.generators.chat import OpenAIResponsesChatGenerator from haystack.dataclasses import ChatMessage from haystack.tools import SearchableToolset, tool @@ -887,7 +887,7 @@ def convert_currency( # `search_tools` tool and must search to load the others (set it higher for larger catalogs). toolset = SearchableToolset(catalog=[get_weather, search_web, convert_currency], search_threshold=2) -agent = Agent(chat_generator=OpenAIChatGenerator(), tools=toolset) +agent = Agent(chat_generator=OpenAIResponsesChatGenerator(), tools=toolset) # The agent is initially provided only with the search_tools tool and will use it to find relevant tools. result = agent.run(messages=[ChatMessage.from_user("What's the weather in Milan?")]) @@ -1067,14 +1067,14 @@ A skill is a directory (or equivalent storage unit) containing a `SKILL.md` file ```python from haystack.components.agents import Agent -from haystack.components.generators.chat import OpenAIChatGenerator +from haystack.components.generators.chat import OpenAIResponsesChatGenerator from haystack.dataclasses import ChatMessage from haystack.tools import SkillToolset from haystack.skill_stores.file_system import FileSystemSkillStore store = FileSystemSkillStore("skills/") skills_toolset = SkillToolset(store) -agent = Agent(chat_generator=OpenAIChatGenerator(), tools=skills_toolset) +agent = Agent(chat_generator=OpenAIResponsesChatGenerator(), tools=skills_toolset) result = agent.run(messages=[ChatMessage.from_user("Fill in this PDF form for me.")]) ``` @@ -1346,7 +1346,7 @@ Toolset serves two main purposes: from typing import Annotated from haystack.tools import tool, Toolset from haystack.components.agents import Agent -from haystack.components.generators.chat import OpenAIChatGenerator +from haystack.components.generators.chat import OpenAIResponsesChatGenerator # Create tools with the @tool decorator (the recommended way) @tool @@ -1363,7 +1363,7 @@ def subtract(a: Annotated[int, "first number"], b: Annotated[int, "second number math_toolset = Toolset([add, subtract]) # Use the toolset with an Agent -agent = Agent(chat_generator=OpenAIChatGenerator(), tools=math_toolset) +agent = Agent(chat_generator=OpenAIResponsesChatGenerator(), tools=math_toolset) ``` 2. Base class for dynamic tool loading: diff --git a/docs-website/reference/haystack-api/validators_api.md b/docs-website/reference/haystack-api/validators_api.md index 8fc994ad61..7f2ad90961 100644 --- a/docs-website/reference/haystack-api/validators_api.md +++ b/docs-website/reference/haystack-api/validators_api.md @@ -37,7 +37,7 @@ Usage example: ```python from haystack import Pipeline -from haystack.components.generators.chat import OpenAIChatGenerator +from haystack.components.generators.chat import OpenAIResponsesChatGenerator from haystack.components.joiners import BranchJoiner from haystack.components.validators import JsonSchemaValidator from haystack import component @@ -53,7 +53,9 @@ class MessageProducer: p = Pipeline() -p.add_component("llm", OpenAIChatGenerator(generation_kwargs={"response_format": {"type": "json_object"}})) +p.add_component( + "llm", OpenAIResponsesChatGenerator(generation_kwargs={"text": {"format": {"type": "json_object"}}}) +) p.add_component("schema_validator", JsonSchemaValidator()) p.add_component("joiner_for_llm", BranchJoiner(list[ChatMessage])) p.add_component("message_producer", MessageProducer())