mirror of
				https://github.com/hwchase17/langchain.git
				synced 2025-10-31 07:41:40 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			243 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			243 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| {
 | |
|  "cells": [
 | |
|   {
 | |
|    "cell_type": "markdown",
 | |
|    "id": "85fb2c03-ab88-4c8c-97e3-a7f2954555ab",
 | |
|    "metadata": {},
 | |
|    "source": [
 | |
|     "# OpenAPI Agent\n",
 | |
|     "\n",
 | |
|     "This notebook showcases an agent designed to interact with an OpenAPI spec and make a correct API request based on the information it has gathered from the spec.\n",
 | |
|     "\n",
 | |
|     "In the below example, we are using the OpenAPI spec for the OpenAI API, which you can find [here](https://github.com/openai/openai-openapi/blob/master/openapi.yaml)."
 | |
|    ]
 | |
|   },
 | |
|   {
 | |
|    "cell_type": "markdown",
 | |
|    "id": "893f90fd-f8f6-470a-a76d-1f200ba02e2f",
 | |
|    "metadata": {},
 | |
|    "source": [
 | |
|     "## Initialization"
 | |
|    ]
 | |
|   },
 | |
|   {
 | |
|    "cell_type": "code",
 | |
|    "execution_count": 1,
 | |
|    "id": "ff988466-c389-4ec6-b6ac-14364a537fd5",
 | |
|    "metadata": {
 | |
|     "tags": []
 | |
|    },
 | |
|    "outputs": [],
 | |
|    "source": [
 | |
|     "import os\n",
 | |
|     "import yaml\n",
 | |
|     "\n",
 | |
|     "from langchain.agents import create_openapi_agent\n",
 | |
|     "from langchain.agents.agent_toolkits import OpenAPIToolkit\n",
 | |
|     "from langchain.llms.openai import OpenAI\n",
 | |
|     "from langchain.requests import RequestsWrapper\n",
 | |
|     "from langchain.tools.json.tool import JsonSpec"
 | |
|    ]
 | |
|   },
 | |
|   {
 | |
|    "cell_type": "code",
 | |
|    "execution_count": 2,
 | |
|    "id": "9ecd1ba0-3937-4359-a41e-68605f0596a1",
 | |
|    "metadata": {
 | |
|     "tags": []
 | |
|    },
 | |
|    "outputs": [],
 | |
|    "source": [
 | |
|     "with open(\"openai_openapi.yml\") as f:\n",
 | |
|     "    data = yaml.load(f, Loader=yaml.FullLoader)\n",
 | |
|     "json_spec=JsonSpec(dict_=data, max_value_length=4000)\n",
 | |
|     "headers = {\n",
 | |
|     "    \"Authorization\": f\"Bearer {os.getenv('OPENAI_API_KEY')}\"\n",
 | |
|     "}\n",
 | |
|     "requests_wrapper=RequestsWrapper(headers=headers)\n",
 | |
|     "openapi_toolkit = OpenAPIToolkit.from_llm(OpenAI(temperature=0), json_spec, requests_wrapper, verbose=True)\n",
 | |
|     "openapi_agent_executor = create_openapi_agent(\n",
 | |
|     "    llm=OpenAI(temperature=0),\n",
 | |
|     "    toolkit=openapi_toolkit,\n",
 | |
|     "    verbose=True\n",
 | |
|     ")"
 | |
|    ]
 | |
|   },
 | |
|   {
 | |
|    "cell_type": "markdown",
 | |
|    "id": "f111879d-ae84-41f9-ad82-d3e6b72c41ba",
 | |
|    "metadata": {},
 | |
|    "source": [
 | |
|     "## Example: agent capable of analyzing OpenAPI spec and making requests"
 | |
|    ]
 | |
|   },
 | |
|   {
 | |
|    "cell_type": "code",
 | |
|    "execution_count": 3,
 | |
|    "id": "548db7f7-337b-4ba8-905c-e7fd58c01799",
 | |
|    "metadata": {
 | |
|     "tags": []
 | |
|    },
 | |
|    "outputs": [
 | |
|     {
 | |
|      "name": "stdout",
 | |
|      "output_type": "stream",
 | |
|      "text": [
 | |
|       "\n",
 | |
|       "\n",
 | |
|       "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
 | |
|       "\u001b[32;1m\u001b[1;3mAction: json_explorer\n",
 | |
|       "Action Input: What is the base url for the API?\u001b[0m\n",
 | |
|       "\n",
 | |
|       "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
 | |
|       "\u001b[32;1m\u001b[1;3mAction: json_spec_list_keys\n",
 | |
|       "Action Input: data\u001b[0m\n",
 | |
|       "Observation: \u001b[36;1m\u001b[1;3m['openapi', 'info', 'servers', 'tags', 'paths', 'components', 'x-oaiMeta']\u001b[0m\n",
 | |
|       "Thought:\u001b[32;1m\u001b[1;3m I should look at the servers key to see what the base url is\n",
 | |
|       "Action: json_spec_list_keys\n",
 | |
|       "Action Input: data[\"servers\"][0]\u001b[0m\n",
 | |
|       "Observation: \u001b[36;1m\u001b[1;3mValueError('Value at path `data[\"servers\"][0]` is not a dict, get the value directly.')\u001b[0m\n",
 | |
|       "Thought:\u001b[32;1m\u001b[1;3m I should get the value of the servers key\n",
 | |
|       "Action: json_spec_get_value\n",
 | |
|       "Action Input: data[\"servers\"][0]\u001b[0m\n",
 | |
|       "Observation: \u001b[33;1m\u001b[1;3m{'url': 'https://api.openai.com/v1'}\u001b[0m\n",
 | |
|       "Thought:\u001b[32;1m\u001b[1;3m I now know the base url for the API\n",
 | |
|       "Final Answer: The base url for the API is https://api.openai.com/v1\u001b[0m\n",
 | |
|       "\n",
 | |
|       "\u001b[1m> Finished chain.\u001b[0m\n",
 | |
|       "\n",
 | |
|       "Observation: \u001b[33;1m\u001b[1;3mThe base url for the API is https://api.openai.com/v1\u001b[0m\n",
 | |
|       "Thought:\u001b[32;1m\u001b[1;3m I should find the path for the /completions endpoint.\n",
 | |
|       "Action: json_explorer\n",
 | |
|       "Action Input: What is the path for the /completions endpoint?\u001b[0m\n",
 | |
|       "\n",
 | |
|       "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
 | |
|       "\u001b[32;1m\u001b[1;3mAction: json_spec_list_keys\n",
 | |
|       "Action Input: data\u001b[0m\n",
 | |
|       "Observation: \u001b[36;1m\u001b[1;3m['openapi', 'info', 'servers', 'tags', 'paths', 'components', 'x-oaiMeta']\u001b[0m\n",
 | |
|       "Thought:\u001b[32;1m\u001b[1;3m I should look at the paths key to see what endpoints exist\n",
 | |
|       "Action: json_spec_list_keys\n",
 | |
|       "Action Input: data[\"paths\"]\u001b[0m\n",
 | |
|       "Observation: \u001b[36;1m\u001b[1;3m['/engines', '/engines/{engine_id}', '/completions', '/edits', '/images/generations', '/images/edits', '/images/variations', '/embeddings', '/engines/{engine_id}/search', '/files', '/files/{file_id}', '/files/{file_id}/content', '/answers', '/classifications', '/fine-tunes', '/fine-tunes/{fine_tune_id}', '/fine-tunes/{fine_tune_id}/cancel', '/fine-tunes/{fine_tune_id}/events', '/models', '/models/{model}', '/moderations']\u001b[0m\n",
 | |
|       "Thought:\u001b[32;1m\u001b[1;3m I now know the path for the /completions endpoint\n",
 | |
|       "Final Answer: data[\"paths\"][2]\u001b[0m\n",
 | |
|       "\n",
 | |
|       "\u001b[1m> Finished chain.\u001b[0m\n",
 | |
|       "\n",
 | |
|       "Observation: \u001b[33;1m\u001b[1;3mdata[\"paths\"][2]\u001b[0m\n",
 | |
|       "Thought:\u001b[32;1m\u001b[1;3m I should find the required parameters for the POST request.\n",
 | |
|       "Action: json_explorer\n",
 | |
|       "Action Input: What are the required parameters for a POST request to the /completions endpoint?\u001b[0m\n",
 | |
|       "\n",
 | |
|       "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
 | |
|       "\u001b[32;1m\u001b[1;3mAction: json_spec_list_keys\n",
 | |
|       "Action Input: data\u001b[0m\n",
 | |
|       "Observation: \u001b[36;1m\u001b[1;3m['openapi', 'info', 'servers', 'tags', 'paths', 'components', 'x-oaiMeta']\u001b[0m\n",
 | |
|       "Thought:\u001b[32;1m\u001b[1;3m I should look at the paths key to see what endpoints exist\n",
 | |
|       "Action: json_spec_list_keys\n",
 | |
|       "Action Input: data[\"paths\"]\u001b[0m\n",
 | |
|       "Observation: \u001b[36;1m\u001b[1;3m['/engines', '/engines/{engine_id}', '/completions', '/edits', '/images/generations', '/images/edits', '/images/variations', '/embeddings', '/engines/{engine_id}/search', '/files', '/files/{file_id}', '/files/{file_id}/content', '/answers', '/classifications', '/fine-tunes', '/fine-tunes/{fine_tune_id}', '/fine-tunes/{fine_tune_id}/cancel', '/fine-tunes/{fine_tune_id}/events', '/models', '/models/{model}', '/moderations']\u001b[0m\n",
 | |
|       "Thought:\u001b[32;1m\u001b[1;3m I should look at the /completions endpoint to see what parameters are required\n",
 | |
|       "Action: json_spec_list_keys\n",
 | |
|       "Action Input: data[\"paths\"][\"/completions\"]\u001b[0m\n",
 | |
|       "Observation: \u001b[36;1m\u001b[1;3m['post']\u001b[0m\n",
 | |
|       "Thought:\u001b[32;1m\u001b[1;3m I should look at the post key to see what parameters are required\n",
 | |
|       "Action: json_spec_list_keys\n",
 | |
|       "Action Input: data[\"paths\"][\"/completions\"][\"post\"]\u001b[0m\n",
 | |
|       "Observation: \u001b[36;1m\u001b[1;3m['operationId', 'tags', 'summary', 'requestBody', 'responses', 'x-oaiMeta']\u001b[0m\n",
 | |
|       "Thought:\u001b[32;1m\u001b[1;3m I should look at the requestBody key to see what parameters are required\n",
 | |
|       "Action: json_spec_list_keys\n",
 | |
|       "Action Input: data[\"paths\"][\"/completions\"][\"post\"][\"requestBody\"]\u001b[0m\n",
 | |
|       "Observation: \u001b[36;1m\u001b[1;3m['required', 'content']\u001b[0m\n",
 | |
|       "Thought:\u001b[32;1m\u001b[1;3m I should look at the content key to see what parameters are required\n",
 | |
|       "Action: json_spec_list_keys\n",
 | |
|       "Action Input: data[\"paths\"][\"/completions\"][\"post\"][\"requestBody\"][\"content\"]\u001b[0m\n",
 | |
|       "Observation: \u001b[36;1m\u001b[1;3m['application/json']\u001b[0m\n",
 | |
|       "Thought:\u001b[32;1m\u001b[1;3m I should look at the application/json key to see what parameters are required\n",
 | |
|       "Action: json_spec_list_keys\n",
 | |
|       "Action Input: data[\"paths\"][\"/completions\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"]\u001b[0m\n",
 | |
|       "Observation: \u001b[36;1m\u001b[1;3m['schema']\u001b[0m\n",
 | |
|       "Thought:\u001b[32;1m\u001b[1;3m I should look at the schema key to see what parameters are required\n",
 | |
|       "Action: json_spec_list_keys\n",
 | |
|       "Action Input: data[\"paths\"][\"/completions\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"][\"schema\"]\u001b[0m\n",
 | |
|       "Observation: \u001b[36;1m\u001b[1;3m['$ref']\u001b[0m\n",
 | |
|       "Thought:\u001b[32;1m\u001b[1;3m I should look at the $ref key to see what parameters are required\n",
 | |
|       "Action: json_spec_list_keys\n",
 | |
|       "Action Input: data[\"paths\"][\"/completions\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"][\"schema\"][\"$ref\"]\u001b[0m\n",
 | |
|       "Observation: \u001b[36;1m\u001b[1;3mValueError('Value at path `data[\"paths\"][\"/completions\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"][\"schema\"][\"$ref\"]` is not a dict, get the value directly.')\u001b[0m\n",
 | |
|       "Thought:\u001b[32;1m\u001b[1;3m I should look at the $ref key to get the value directly\n",
 | |
|       "Action: json_spec_get_value\n",
 | |
|       "Action Input: data[\"paths\"][\"/completions\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"][\"schema\"][\"$ref\"]\u001b[0m\n",
 | |
|       "Observation: \u001b[33;1m\u001b[1;3m#/components/schemas/CreateCompletionRequest\u001b[0m\n",
 | |
|       "Thought:\u001b[32;1m\u001b[1;3m I should look at the CreateCompletionRequest schema to see what parameters are required\n",
 | |
|       "Action: json_spec_list_keys\n",
 | |
|       "Action Input: data[\"components\"][\"schemas\"][\"CreateCompletionRequest\"]\u001b[0m\n",
 | |
|       "Observation: \u001b[36;1m\u001b[1;3m['type', 'properties', 'required']\u001b[0m\n",
 | |
|       "Thought:\u001b[32;1m\u001b[1;3m I should look at the required key to see what parameters are required\n",
 | |
|       "Action: json_spec_get_value\n",
 | |
|       "Action Input: data[\"components\"][\"schemas\"][\"CreateCompletionRequest\"][\"required\"]\u001b[0m\n",
 | |
|       "Observation: \u001b[33;1m\u001b[1;3m['model']\u001b[0m\n",
 | |
|       "Thought:\u001b[32;1m\u001b[1;3m I now know the final answer\n",
 | |
|       "Final Answer: The required parameters for a POST request to the /completions endpoint are 'model'.\u001b[0m\n",
 | |
|       "\n",
 | |
|       "\u001b[1m> Finished chain.\u001b[0m\n",
 | |
|       "\n",
 | |
|       "Observation: \u001b[33;1m\u001b[1;3mThe required parameters for a POST request to the /completions endpoint are 'model'.\u001b[0m\n",
 | |
|       "Thought:\u001b[32;1m\u001b[1;3m I now know the parameters needed to make the request.\n",
 | |
|       "Action: requests_post\n",
 | |
|       "Action Input: { \"url\": \"https://api.openai.com/v1/completions\", \"data\": { \"model\": \"davinci\", \"prompt\": \"tell me a joke\" } }\u001b[0m\n",
 | |
|       "Observation: \u001b[33;1m\u001b[1;3m{\"id\":\"cmpl-6oeEcNETfq8TOuIUQvAct6NrBXihs\",\"object\":\"text_completion\",\"created\":1677529082,\"model\":\"davinci\",\"choices\":[{\"text\":\"\\n\\n\\n\\nLove is a battlefield\\n\\n\\n\\nIt's me...And some\",\"index\":0,\"logprobs\":null,\"finish_reason\":\"length\"}],\"usage\":{\"prompt_tokens\":4,\"completion_tokens\":16,\"total_tokens\":20}}\n",
 | |
|       "\u001b[0m\n",
 | |
|       "Thought:\u001b[32;1m\u001b[1;3m I now know the final answer.\n",
 | |
|       "Final Answer: Love is a battlefield. It's me...And some.\u001b[0m\n",
 | |
|       "\n",
 | |
|       "\u001b[1m> Finished chain.\u001b[0m\n"
 | |
|      ]
 | |
|     },
 | |
|     {
 | |
|      "data": {
 | |
|       "text/plain": [
 | |
|        "\"Love is a battlefield. It's me...And some.\""
 | |
|       ]
 | |
|      },
 | |
|      "execution_count": 3,
 | |
|      "metadata": {},
 | |
|      "output_type": "execute_result"
 | |
|     }
 | |
|    ],
 | |
|    "source": [
 | |
|     "openapi_agent_executor.run(\"Make a post request to openai /completions. The prompt should be 'tell me a joke.'\")"
 | |
|    ]
 | |
|   },
 | |
|   {
 | |
|    "cell_type": "code",
 | |
|    "execution_count": null,
 | |
|    "id": "6ec9582b",
 | |
|    "metadata": {},
 | |
|    "outputs": [],
 | |
|    "source": []
 | |
|   }
 | |
|  ],
 | |
|  "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.9"
 | |
|   }
 | |
|  },
 | |
|  "nbformat": 4,
 | |
|  "nbformat_minor": 5
 | |
| }
 |