mirror of
https://github.com/hwchase17/langchain.git
synced 2025-10-26 05:10:22 +00:00
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>
350 lines
14 KiB
Plaintext
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
|
|
}
|