Skip to content

Update 43_Building_a_Tool_Calling_Agent.ipynb #397

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 25, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 27 additions & 20 deletions tutorials/43_Building_a_Tool_Calling_Agent.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@
"source": [
"## Using Agent with a Pipeline as Tool\n",
"\n",
"Now, for a more sophisticated example, let's build a research assistant that can search the web, fetch content from links, and generate comprehensive answers. In contrast to our previous Agent, we now want to follow the links on the search engine results page and access their content. We'll start with a Haystack Pipeline that the Agent can use as a tool:"
"Now, for a more sophisticated example, let's build a research assistant that can search the web, fetch content from links, and generate comprehensive answers. In contrast to our previous Agent, we now want to follow the links on the search engine results page, access their content and parse their content through [OutputAdapter](https://docs.haystack.deepset.ai/docs/outputadapter). We'll start with a Haystack Pipeline that the Agent can use as a tool:"
]
},
{
Expand All @@ -204,8 +204,8 @@
"outputs": [],
"source": [
"from haystack.components.builders.answer_builder import AnswerBuilder\n",
"from haystack.components.builders.chat_prompt_builder import ChatPromptBuilder\n",
"from haystack.components.converters.html import HTMLToDocument\n",
"from haystack.components.converters.output_adapter import OutputAdapter\n",
"from haystack.components.fetchers.link_content import LinkContentFetcher\n",
"from haystack.components.websearch.serper_dev import SerperDevWebSearch\n",
"from haystack.dataclasses import ChatMessage\n",
Expand All @@ -217,29 +217,24 @@
"search_pipeline.add_component(\"fetcher\", LinkContentFetcher(timeout=3, raise_on_failure=False, retry_attempts=2))\n",
"search_pipeline.add_component(\"converter\", HTMLToDocument())\n",
"search_pipeline.add_component(\n",
" \"builder\",\n",
" ChatPromptBuilder(\n",
" template=[\n",
" ChatMessage.from_user(\n",
" \"\"\"\n",
"{% for doc in docs %}\n",
" {% if doc.content %}\n",
" \"output_adapter\",\n",
" OutputAdapter(\n",
" template=\"\"\"\n",
"{%- for doc in docs -%}\n",
" {%- if doc.content -%}\n",
" <search-result url=\"{{ doc.meta.url }}\">\n",
" {{ doc.content|truncate(25000) }}\n",
" </search-result>\n",
" {% endif %}\n",
"{% endfor %}\n",
"\"\"\"\n",
" )\n",
" ],\n",
" variables=[\"docs\"],\n",
" required_variables=[\"docs\"],\n",
" {%- endif -%}\n",
"{%- endfor -%}\n",
"\"\"\",\n",
" output_type=str,\n",
" ),\n",
")\n",
"\n",
"search_pipeline.connect(\"search.links\", \"fetcher.urls\")\n",
"search_pipeline.connect(\"fetcher.streams\", \"converter.sources\")\n",
"search_pipeline.connect(\"converter.documents\", \"builder.docs\")"
"search_pipeline.connect(\"converter.documents\", \"output_adapter.docs\")"
]
},
{
Expand All @@ -250,7 +245,11 @@
"source": [
"### Creating a Tool from a Pipeline\n",
"\n",
"As the next step, create a `SuperComponent` with the `search_pipeline` and convert it into a tool with `ComponentTool`. Then, you can initialize the Agent with the created `search_tool`\n",
"Next, wrap the `search_pipeline` inside a [`SuperComponent`](https://docs.haystack.deepset.ai/docs/supercomponents) and turn it into a tool using `ComponentTool`. The `ComponentTool` automatically creates LLM-compatible tool schemas based on the component’s input sockets. \n",
"\n",
"To control what data the `ComponentTool` should receive and returns, you can optionally define `input_mapping` and `output_mapping`. For example, this lets you ensure that only the `\"query\"` input of the `search_pipeline` is mentioned in LLM-compatible tool schema, and only `\"search_result\"` is returned from the `SuperComponent`.\n",
"\n",
"Finally, you can initialize the Agent with the resulting `search_tool`.\n",
"\n",
"> 💡 Learn alternative ways of creating tools in [`Tool`](https://docs.haystack.deepset.ai/docs/tool) and [`MCPTool`](https://docs.haystack.deepset.ai/docs/mcptool) documentation pages."
]
Expand All @@ -268,9 +267,17 @@
"from haystack.components.agents import Agent\n",
"from haystack.components.generators.chat import OpenAIChatGenerator\n",
"\n",
"search_component = SuperComponent(pipeline=search_pipeline)\n",
"search_component = SuperComponent(\n",
" pipeline=search_pipeline,\n",
" input_mapping={\"query\": [\"search.query\"]},\n",
" output_mapping={\"output_adapter.output\": \"search_result\"},\n",
")\n",
"\n",
"search_tool = ComponentTool(\n",
" name=\"search\", description=\"Use this tool to search for information on the internet.\", component=search_component\n",
" name=\"search\",\n",
" description=\"Use this tool to search for information on the internet.\",\n",
" component=search_component,\n",
" outputs_to_string={\"source\": \"search_result\"},\n",
")\n",
"\n",
"agent = Agent(\n",
Expand Down