Files
langchain/docs/docs/integrations/tools/requests.ipynb
Oskar Stark 0d2cea747c docs: streamline LangSmith teasing (#30302)
This can only be reviewed by [hiding
whitespaces](https://github.com/langchain-ai/langchain/pull/30302/files?diff=unified&w=1).

The motivation behind this PR is to get my hands on the docs and make
the LangSmith teasing short and clear.

Right now I don't know how to do it, but this could be an include in the
future.

---------

Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2025-03-28 15:13:22 -04:00

350 lines
14 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"id": "cfe4185a-34dc-4cdc-b831-001954f2d6e8",
"metadata": {},
"source": [
"# Requests Toolkit\n",
"\n",
"We can use the Requests [toolkit](/docs/concepts/tools/#toolkits) to construct agents that generate HTTP requests.\n",
"\n",
"For detailed documentation of all API toolkit features and configurations head to the API reference for [RequestsToolkit](https://python.langchain.com/api_reference/community/agent_toolkits/langchain_community.agent_toolkits.openapi.toolkit.RequestsToolkit.html).\n",
"\n",
"## ⚠️ Security note ⚠️\n",
"There are inherent risks in giving models discretion to execute real-world actions. Take precautions to mitigate these risks:\n",
"\n",
"- Make sure that permissions associated with the tools are narrowly-scoped (e.g., for database operations or API requests);\n",
"- When desired, make use of human-in-the-loop workflows."
]
},
{
"cell_type": "markdown",
"id": "d968e982-f370-4614-8469-c1bc71ee3e32",
"metadata": {},
"source": [
"## Setup\n",
"\n",
"### Installation\n",
"\n",
"This toolkit lives in the `langchain-community` package:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f74f05fb-3f24-4c0b-a17f-cf4edeedbb9a",
"metadata": {},
"outputs": [],
"source": [
"%pip install -qU langchain-community"
]
},
{
"cell_type": "markdown",
"id": "36a178eb-1f2c-411e-bf25-0240ead4c62a",
"metadata": {},
"source": "To enable automated tracing of individual tools, set your [LangSmith](https://docs.smith.langchain.com/) API key:"
},
{
"cell_type": "code",
"execution_count": null,
"id": "8e68d0cd-6233-481c-b048-e8d95cba4c35",
"metadata": {},
"outputs": [],
"source": [
"# os.environ[\"LANGSMITH_API_KEY\"] = getpass.getpass(\"Enter your LangSmith API key: \")\n",
"# os.environ[\"LANGSMITH_TRACING\"] = \"true\""
]
},
{
"cell_type": "markdown",
"id": "a7e2f64a-a72e-4fef-be52-eaf7c5072d24",
"metadata": {},
"source": [
"## Instantiation\n",
"\n",
"First we will demonstrate a minimal example.\n",
"\n",
"**NOTE**: There are inherent risks in giving models discretion to execute real-world actions. We must \"opt-in\" to these risks by setting `allow_dangerous_request=True` to use these tools.\n",
"**This can be dangerous for calling unwanted requests**. Please make sure your custom OpenAPI spec (yaml) is safe and that permissions associated with the tools are narrowly-scoped."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "018bd070-9fc8-459b-8d28-b4a3e283e640",
"metadata": {},
"outputs": [],
"source": [
"ALLOW_DANGEROUS_REQUEST = True"
]
},
{
"cell_type": "markdown",
"id": "a024f7b3-5437-4878-bd16-c4783bff394c",
"metadata": {},
"source": [
"We can use the [JSONPlaceholder](https://jsonplaceholder.typicode.com) API as a testing ground.\n",
"\n",
"Let's create (a subset of) its API spec:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "2dcbcf92-2ad5-49c3-94ac-91047ccc8c5b",
"metadata": {},
"outputs": [],
"source": [
"from typing import Any, Dict, Union\n",
"\n",
"import requests\n",
"import yaml\n",
"\n",
"\n",
"def _get_schema(response_json: Union[dict, list]) -> dict:\n",
" if isinstance(response_json, list):\n",
" response_json = response_json[0] if response_json else {}\n",
" return {key: type(value).__name__ for key, value in response_json.items()}\n",
"\n",
"\n",
"def _get_api_spec() -> str:\n",
" base_url = \"https://jsonplaceholder.typicode.com\"\n",
" endpoints = [\n",
" \"/posts\",\n",
" \"/comments\",\n",
" ]\n",
" common_query_parameters = [\n",
" {\n",
" \"name\": \"_limit\",\n",
" \"in\": \"query\",\n",
" \"required\": False,\n",
" \"schema\": {\"type\": \"integer\", \"example\": 2},\n",
" \"description\": \"Limit the number of results\",\n",
" }\n",
" ]\n",
" openapi_spec: Dict[str, Any] = {\n",
" \"openapi\": \"3.0.0\",\n",
" \"info\": {\"title\": \"JSONPlaceholder API\", \"version\": \"1.0.0\"},\n",
" \"servers\": [{\"url\": base_url}],\n",
" \"paths\": {},\n",
" }\n",
" # Iterate over the endpoints to construct the paths\n",
" for endpoint in endpoints:\n",
" response = requests.get(base_url + endpoint)\n",
" if response.status_code == 200:\n",
" schema = _get_schema(response.json())\n",
" openapi_spec[\"paths\"][endpoint] = {\n",
" \"get\": {\n",
" \"summary\": f\"Get {endpoint[1:]}\",\n",
" \"parameters\": common_query_parameters,\n",
" \"responses\": {\n",
" \"200\": {\n",
" \"description\": \"Successful response\",\n",
" \"content\": {\n",
" \"application/json\": {\n",
" \"schema\": {\"type\": \"object\", \"properties\": schema}\n",
" }\n",
" },\n",
" }\n",
" },\n",
" }\n",
" }\n",
" return yaml.dump(openapi_spec, sort_keys=False)\n",
"\n",
"\n",
"api_spec = _get_api_spec()"
]
},
{
"cell_type": "markdown",
"id": "db3d6148-ae65-4a1d-91a6-59ee3e4e6efa",
"metadata": {},
"source": [
"Next we can instantiate the toolkit. We require no authorization or other headers for this API:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "63a630b3-45bb-4525-865b-083f322b944b",
"metadata": {},
"outputs": [],
"source": [
"from langchain_community.agent_toolkits.openapi.toolkit import RequestsToolkit\n",
"from langchain_community.utilities.requests import TextRequestsWrapper\n",
"\n",
"toolkit = RequestsToolkit(\n",
" requests_wrapper=TextRequestsWrapper(headers={}),\n",
" allow_dangerous_requests=ALLOW_DANGEROUS_REQUEST,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "f4224a64-843a-479d-8a7b-84719e4b9d0c",
"metadata": {},
"source": [
"## Tools\n",
"\n",
"View available tools:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "70ea0f4e-9f10-4906-894b-08df832fd515",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[RequestsGetTool(requests_wrapper=TextRequestsWrapper(headers={}, aiosession=None, auth=None, response_content_type='text', verify=True), allow_dangerous_requests=True),\n",
" RequestsPostTool(requests_wrapper=TextRequestsWrapper(headers={}, aiosession=None, auth=None, response_content_type='text', verify=True), allow_dangerous_requests=True),\n",
" RequestsPatchTool(requests_wrapper=TextRequestsWrapper(headers={}, aiosession=None, auth=None, response_content_type='text', verify=True), allow_dangerous_requests=True),\n",
" RequestsPutTool(requests_wrapper=TextRequestsWrapper(headers={}, aiosession=None, auth=None, response_content_type='text', verify=True), allow_dangerous_requests=True),\n",
" RequestsDeleteTool(requests_wrapper=TextRequestsWrapper(headers={}, aiosession=None, auth=None, response_content_type='text', verify=True), allow_dangerous_requests=True)]"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tools = toolkit.get_tools()\n",
"\n",
"tools"
]
},
{
"cell_type": "markdown",
"id": "a21a6ca4-d650-4b7d-a944-1a8771b5293a",
"metadata": {},
"source": [
"- [RequestsGetTool](https://python.langchain.com/api_reference/community/tools/langchain_community.tools.requests.tool.RequestsGetTool.html)\n",
"- [RequestsPostTool](https://python.langchain.com/api_reference/community/tools/langchain_community.tools.requests.tool.RequestsPostTool.html)\n",
"- [RequestsPatchTool](https://python.langchain.com/api_reference/community/tools/langchain_community.tools.requests.tool.RequestsPatchTool.html)\n",
"- [RequestsPutTool](https://python.langchain.com/api_reference/community/tools/langchain_community.tools.requests.tool.RequestsPutTool.html)\n",
"- [RequestsDeleteTool](https://python.langchain.com/api_reference/community/tools/langchain_community.tools.requests.tool.RequestsDeleteTool.html)"
]
},
{
"cell_type": "markdown",
"id": "e2dbb304-abf2-472a-9130-f03150a40549",
"metadata": {},
"source": [
"## Use within an agent"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "db062da7-f22c-4f36-9df8-1da96c9f7538",
"metadata": {},
"outputs": [],
"source": [
"from langchain_openai import ChatOpenAI\n",
"from langgraph.prebuilt import create_react_agent\n",
"\n",
"llm = ChatOpenAI(model=\"gpt-4o-mini\")\n",
"\n",
"system_message = \"\"\"\n",
"You have access to an API to help answer user queries.\n",
"Here is documentation on the API:\n",
"{api_spec}\n",
"\"\"\".format(api_spec=api_spec)\n",
"\n",
"agent_executor = create_react_agent(llm, tools, prompt=system_message)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "c1e47be9-374a-457c-928a-48f02b5530e3",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"================================\u001b[1m Human Message \u001b[0m=================================\n",
"\n",
"Fetch the top two posts. What are their titles?\n",
"==================================\u001b[1m Ai Message \u001b[0m==================================\n",
"Tool Calls:\n",
" requests_get (call_RV2SOyzCnV5h2sm4WPgG8fND)\n",
" Call ID: call_RV2SOyzCnV5h2sm4WPgG8fND\n",
" Args:\n",
" url: https://jsonplaceholder.typicode.com/posts?_limit=2\n",
"=================================\u001b[1m Tool Message \u001b[0m=================================\n",
"Name: requests_get\n",
"\n",
"[\n",
" {\n",
" \"userId\": 1,\n",
" \"id\": 1,\n",
" \"title\": \"sunt aut facere repellat provident occaecati excepturi optio reprehenderit\",\n",
" \"body\": \"quia et suscipit\\nsuscipit recusandae consequuntur expedita et cum\\nreprehenderit molestiae ut ut quas totam\\nnostrum rerum est autem sunt rem eveniet architecto\"\n",
" },\n",
" {\n",
" \"userId\": 1,\n",
" \"id\": 2,\n",
" \"title\": \"qui est esse\",\n",
" \"body\": \"est rerum tempore vitae\\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\\nqui aperiam non debitis possimus qui neque nisi nulla\"\n",
" }\n",
"]\n",
"==================================\u001b[1m Ai Message \u001b[0m==================================\n",
"\n",
"The titles of the top two posts are:\n",
"1. \"sunt aut facere repellat provident occaecati excepturi optio reprehenderit\"\n",
"2. \"qui est esse\"\n"
]
}
],
"source": [
"example_query = \"Fetch the top two posts. What are their titles?\"\n",
"\n",
"events = agent_executor.stream(\n",
" {\"messages\": [(\"user\", example_query)]},\n",
" stream_mode=\"values\",\n",
")\n",
"for event in events:\n",
" event[\"messages\"][-1].pretty_print()"
]
},
{
"cell_type": "markdown",
"id": "01ec4886-de3d-4fda-bd05-e3f254810969",
"metadata": {},
"source": [
"## API reference\n",
"\n",
"For detailed documentation of all API toolkit features and configurations head to the API reference for [RequestsToolkit](https://python.langchain.com/api_reference/community/agent_toolkits/langchain_community.agent_toolkits.openapi.toolkit.RequestsToolkit.html)."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.4"
}
},
"nbformat": 4,
"nbformat_minor": 5
}