From 0e5f5743cafbff24c99713cacee0f13627409ede Mon Sep 17 00:00:00 2001 From: Harrison Chase Date: Mon, 13 Feb 2023 19:39:43 -0800 Subject: [PATCH] add notebook --- .../implementations/openapi-agent.ipynb | 2074 +++++++++++++++++ 1 file changed, 2074 insertions(+) create mode 100644 docs/modules/agents/implementations/openapi-agent.ipynb diff --git a/docs/modules/agents/implementations/openapi-agent.ipynb b/docs/modules/agents/implementations/openapi-agent.ipynb new file mode 100644 index 00000000000..1107c2d8527 --- /dev/null +++ b/docs/modules/agents/implementations/openapi-agent.ipynb @@ -0,0 +1,2074 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "fb982d23", + "metadata": {}, + "outputs": [], + "source": [ + "import yaml" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "69bf3a0d", + "metadata": {}, + "outputs": [], + "source": [ + "with open('openmeteo.yml') as f:\n", + " openapispec = yaml.safe_load(f)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "98e70708", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "dict_keys(['openapi', 'info', 'paths'])" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "openapispec.keys()" + ] + }, + { + "cell_type": "code", + "execution_count": 86, + "id": "5120ce39", + "metadata": {}, + "outputs": [], + "source": [ + "import json" + ] + }, + { + "cell_type": "code", + "execution_count": 150, + "id": "596fc64f", + "metadata": {}, + "outputs": [], + "source": [ + "class OpenAPISpec:\n", + " \n", + " def __init__(self, spec_dict: dict):\n", + " from openapi_spec_validator import validate_spec\n", + " validate_spec(spec_dict)\n", + " self.spec_dict = spec_dict\n", + " \n", + " @classmethod\n", + " def from_filename(cls, filename: str):\n", + " from openapi_spec_validator.readers import read_from_filename\n", + "\n", + " spec_dict, _ = read_from_filename(filename)\n", + " return cls(spec_dict)\n", + " \n", + " def get_paths(self, *args):\n", + " paths = []\n", + " for p, v in self.spec_dict['paths'].items():\n", + " _strs = [f\"Name: {p}\"]\n", + " if \"description\" in v['get']:\n", + " _strs.append(f\"Description: {v['get']['description']}\")\n", + " if \"servers\" in v:\n", + " _strs.append(f\"Servers: {v['servers']}\")\n", + " _str = \"\\n\".join(_strs)\n", + " paths.append(_str)\n", + " return \"\\n\\n\".join(paths)\n", + " \n", + " def get_parameters(self, path: str):\n", + " params = self.spec_dict['paths'][path]['get']['parameters']\n", + " return \", \".join([p['name'] for p in params])\n", + " \n", + " def get_param_spec(self, path_param_string: str):\n", + " json_string = json.loads(path_param_string)\n", + " path, param = json_string['path'], json_string['parameter_name']\n", + " params = self.spec_dict['paths'][path]['get']['parameters']\n", + " param_dict = {p['name']: p for p in params}\n", + " return str(param_dict[param])" + ] + }, + { + "cell_type": "code", + "execution_count": 151, + "id": "7494d560", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Get fish data in JSON format. \\n\\nThe {fishID} parameter is optional and can be removed to get all the fish data.'" + ] + }, + "execution_count": 151, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spec.spec_dict['paths']['/v1/fish/{fishID}']['get']['description']" + ] + }, + { + "cell_type": "code", + "execution_count": 152, + "id": "ea6e2b59", + "metadata": {}, + "outputs": [], + "source": [ + "spec = OpenAPISpec.from_filename('/Users/harrisonchase/Downloads/swagger.json')" + ] + }, + { + "cell_type": "code", + "execution_count": 204, + "id": "f918e999", + "metadata": {}, + "outputs": [], + "source": [ + "from openapi3 import OpenAPI\n", + "import yaml\n", + "\n", + "# load the spec file and read the yaml\n", + "with open('/Users/harrisonchase/Downloads/swagger.json') as f:\n", + " spec = yaml.safe_load(f.read())\n", + "\n", + "# parse the spec into python - this will raise if the spec is invalid\n", + "api = OpenAPI(spec)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "54ebd669", + "metadata": {}, + "outputs": [], + "source": [ + "def deslotify(obj):\n", + " if not hasattr(obj, \"__slots__\"):\n", + " return obj\n", + " return {s: deslotify(getattr(obj, s)) for s in obj.__slots__ if hasattr(obj, s) and getattr(obj, s) is not None}\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 194, + "id": "e2709339", + "metadata": {}, + "outputs": [ + { + "ename": "AttributeError", + "evalue": "'str' object has no attribute '__slots__'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[194], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mfoo\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[38;5;18;43m__slots__\u001b[39;49m\n", + "\u001b[0;31mAttributeError\u001b[0m: 'str' object has no attribute '__slots__'" + ] + } + ], + "source": [ + "\"foo\".__slots__" + ] + }, + { + "cell_type": "code", + "execution_count": 202, + "id": "37f3174e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Get fish data in JSON format. \\n\\nThe {fishID} parameter is optional and can be removed to get all the fish data.'" + ] + }, + "execution_count": 202, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "obj = api.paths['/v1/fish/{fishID}']\n", + "obj.get.description" + ] + }, + { + "cell_type": "code", + "execution_count": 153, + "id": "4fc55d29", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'/v1/fish/{fishID}': {'parameters': [{'schema': {'type': 'string'},\n", + " 'name': 'fishID',\n", + " 'in': 'path',\n", + " 'description': \"Either the file-name of a fish or it's ID.\",\n", + " 'required': True}],\n", + " 'get': {'summary': 'Fish',\n", + " 'tags': ['Fish'],\n", + " 'responses': {'200': {'description': 'OK',\n", + " 'content': {'application/json': {'schema': {'type': 'object',\n", + " 'properties': {'id': {'type': 'integer',\n", + " 'description': 'Number of the fish (as found in the critterpedia).'},\n", + " 'file-name': {'type': 'string',\n", + " 'description': 'Name of the image files.'},\n", + " 'name': {'type': 'object',\n", + " 'description': 'Name of the fish in different languages.',\n", + " 'required': ['name-USen',\n", + " 'name-CNzh',\n", + " 'name-EUde',\n", + " 'name-EUes',\n", + " 'name-EUfr',\n", + " 'name-EUit',\n", + " 'name-JPja',\n", + " 'name-KRko',\n", + " 'name-EUnl',\n", + " 'name-EUru',\n", + " 'name-EUen',\n", + " 'name-USes',\n", + " 'name-USfr',\n", + " 'name-TWzh'],\n", + " 'properties': {'name-USen': {'type': 'string',\n", + " 'description': 'English'},\n", + " 'name-CNzh': {'type': 'string',\n", + " 'description': 'Simplified Chinese'},\n", + " 'name-EUde': {'type': 'string', 'description': 'German'},\n", + " 'name-EUes': {'type': 'string', 'description': 'Spanish'},\n", + " 'name-EUfr': {'type': 'string', 'description': 'French'},\n", + " 'name-EUit': {'type': 'string', 'description': 'Italian'},\n", + " 'name-JPja': {'type': 'string', 'description': 'Japanese'},\n", + " 'name-KRko': {'type': 'string', 'description': 'Korean'},\n", + " 'name-EUnl': {'type': 'string', 'description': 'Dutch'},\n", + " 'name-EUru': {'type': 'string', 'description': 'Russian'},\n", + " 'name-EUen': {'type': 'string', 'description': 'Non US English'},\n", + " 'name-USes': {'type': 'string',\n", + " 'description': 'Latin American Spanish'},\n", + " 'name-USfr': {'type': 'string', 'description': 'Canadian French'},\n", + " 'name-TWzh': {'type': 'string',\n", + " 'description': 'Traditional Chinese'}}},\n", + " 'availability': {'type': 'object',\n", + " 'description': 'When and where to find the fish.',\n", + " 'required': ['isAllDay', 'isAllYear', 'location', 'rarity'],\n", + " 'properties': {'month-northern': {'type': 'string',\n", + " 'description': 'Month for the Northern hemisphere, empty if isAllYear is true.'},\n", + " 'month-southern': {'type': 'string',\n", + " 'description': 'Month for the Southern hemisphere, empty if isAllYear is true.'},\n", + " 'time': {'type': 'string',\n", + " 'description': 'Time of availability, empty is isAllDay is true.'},\n", + " 'isAllDay': {'type': 'boolean',\n", + " 'description': 'Is the fish available at any hour?'},\n", + " 'isAllYear': {'type': 'boolean',\n", + " 'description': 'Is the fish available at any day?'},\n", + " 'location': {'type': 'string',\n", + " 'description': 'Location of the fish.'},\n", + " 'rarity': {'type': 'string', 'description': 'Rarity of the fish.'},\n", + " 'month-array-northern': {'type': 'array',\n", + " 'description': 'Array containing the month when the critter is available in the Northern Hemisphere.',\n", + " 'items': {'type': 'number'}},\n", + " 'month-array-southern': {'type': 'array',\n", + " 'description': 'Array containing the month when the critter is available in the Southern Hemisphere.',\n", + " 'items': {'type': 'number'}},\n", + " 'time-array': {'type': 'array',\n", + " 'description': 'Array containing the hours when the critter is available during the day (24h format).',\n", + " 'items': {'type': 'number'}}}},\n", + " 'shadow': {'type': 'string',\n", + " 'description': 'Size and/or shape of the shadow.'},\n", + " 'price': {'type': 'number', 'description': 'Selling price.'},\n", + " 'price-cj': {'type': 'number',\n", + " 'description': 'Selling price from C.J.'},\n", + " 'catch-phrase': {'type': 'string',\n", + " 'description': 'Phrase (or often pun) when the fish is caught.'},\n", + " 'museum-phrase': {'type': 'string',\n", + " 'description': 'Description from Blathers.'},\n", + " 'alt-catch-phrase': {'type': 'array',\n", + " 'description': 'Alternate catch phrases, when available.',\n", + " 'items': {'type': 'string'}},\n", + " 'icon_uri': {'type': 'string', 'description': 'URI for icon'},\n", + " 'image_uri': {'type': 'string', 'description': 'URI for image'}},\n", + " 'required': ['id',\n", + " 'file-name',\n", + " 'name',\n", + " 'availability',\n", + " 'shadow',\n", + " 'price',\n", + " 'price-cj',\n", + " 'catch-phrase',\n", + " 'museum-phrase',\n", + " 'icon_uri',\n", + " 'image_uri']},\n", + " 'examples': {'/v1/fish/1': {'value': {'id': 1,\n", + " 'file-name': 'bitterling',\n", + " 'name': {'name-USen': 'bitterling',\n", + " 'name-EUen': 'bitterling',\n", + " 'name-EUde': 'Bitterling',\n", + " 'name-EUes': 'amarguillo',\n", + " 'name-USes': 'amarguillo',\n", + " 'name-EUfr': 'bouvière',\n", + " 'name-USfr': 'bouvière',\n", + " 'name-EUit': 'rodeo',\n", + " 'name-EUnl': 'bittervoorn',\n", + " 'name-CNzh': '红目鲫',\n", + " 'name-TWzh': '紅目鯽',\n", + " 'name-JPja': 'タナゴ',\n", + " 'name-KRko': '납줄개',\n", + " 'name-EUru': 'горчак'},\n", + " 'availability': {'month-northern': '11-3',\n", + " 'month-southern': '5-9',\n", + " 'time': '',\n", + " 'isAllDay': True,\n", + " 'isAllYear': False,\n", + " 'location': 'River',\n", + " 'rarity': 'Common',\n", + " 'month-array-northern': [11, 12, 1, 2, 3],\n", + " 'month-array-southern': [5, 6, 7, 8, 9],\n", + " 'time-array': [0,\n", + " 1,\n", + " 2,\n", + " 3,\n", + " 4,\n", + " 5,\n", + " 6,\n", + " 7,\n", + " 8,\n", + " 9,\n", + " 10,\n", + " 11,\n", + " 12,\n", + " 13,\n", + " 14,\n", + " 15,\n", + " 16,\n", + " 17,\n", + " 18,\n", + " 19,\n", + " 20,\n", + " 21,\n", + " 22,\n", + " 23]},\n", + " 'shadow': 'Smallest (1)',\n", + " 'price': 900,\n", + " 'price-cj': 1350,\n", + " 'catch-phrase': \"I caught a bitterling! It's mad at me, but only a little.\",\n", + " 'museum-phrase': \"Bitterlings hide their eggs inside large bivalves—like clams—where the young can stay safe until grown. The bitterling isn't being sneaky. No, their young help keep the bivalve healthy by eating invading parasites! It's a wonderful bit of evolutionary deal making, don't you think? Each one keeping the other safe... Though eating parasites does not sound like a happy childhood... Is that why the fish is so bitter?\",\n", + " 'image_uri': 'https://acnhapi.com/v1/images/fish/1',\n", + " 'icon_uri': 'https://acnhapi.com/v1/icons/fish/1'}}}}}},\n", + " '404': {'description': 'Not Found'}},\n", + " 'operationId': 'get-fish-fishID',\n", + " 'description': 'Get fish data in JSON format. \\n\\nThe {fishID} parameter is optional and can be removed to get all the fish data.'}},\n", + " '/v1/sea/{seaID}': {'parameters': [{'schema': {'type': 'string'},\n", + " 'name': 'seaID',\n", + " 'in': 'path',\n", + " 'description': \"Either the file-name of a sea creature or it's ID.\",\n", + " 'required': True}],\n", + " 'get': {'summary': 'Sea Creatures',\n", + " 'tags': ['Sea Creatures'],\n", + " 'responses': {'200': {'description': 'OK',\n", + " 'content': {'application/json': {'schema': {'type': 'object',\n", + " 'properties': {'id': {'type': 'integer',\n", + " 'description': 'Number of the sea creature (as found in the critterpedia).'},\n", + " 'file-name': {'type': 'string',\n", + " 'description': 'Name of the image files.'},\n", + " 'name': {'type': 'object',\n", + " 'description': 'Name of the sea creature in different languages.',\n", + " 'required': ['name-USen',\n", + " 'name-CNzh',\n", + " 'name-EUde',\n", + " 'name-EUes',\n", + " 'name-EUfr',\n", + " 'name-EUit',\n", + " 'name-JPja',\n", + " 'name-KRko',\n", + " 'name-EUnl',\n", + " 'name-EUru',\n", + " 'name-EUen',\n", + " 'name-USes',\n", + " 'name-USfr',\n", + " 'name-TWzh'],\n", + " 'properties': {'name-USen': {'type': 'string',\n", + " 'description': 'English'},\n", + " 'name-CNzh': {'type': 'string',\n", + " 'description': 'Simplified Chinese'},\n", + " 'name-EUde': {'type': 'string', 'description': 'German'},\n", + " 'name-EUes': {'type': 'string', 'description': 'Spanish'},\n", + " 'name-EUfr': {'type': 'string', 'description': 'French'},\n", + " 'name-EUit': {'type': 'string', 'description': 'Italian'},\n", + " 'name-JPja': {'type': 'string', 'description': 'Japanese'},\n", + " 'name-KRko': {'type': 'string', 'description': 'Korean'},\n", + " 'name-EUnl': {'type': 'string', 'description': 'Dutch'},\n", + " 'name-EUru': {'type': 'string', 'description': 'Russian'},\n", + " 'name-EUen': {'type': 'string', 'description': 'Non US English'},\n", + " 'name-USes': {'type': 'string',\n", + " 'description': 'Latin American Spanish'},\n", + " 'name-USfr': {'type': 'string', 'description': 'Canadian French'},\n", + " 'name-TWzh': {'type': 'string',\n", + " 'description': 'Traditional Chinese'}}},\n", + " 'availability': {'type': 'object',\n", + " 'description': 'When to find the sea creature.',\n", + " 'required': ['isAllDay', 'isAllYear', 'location', 'rarity'],\n", + " 'properties': {'month-northern': {'type': 'string',\n", + " 'description': 'Month for the Northern hemisphere, empty if isAllYear is true.'},\n", + " 'month-southern': {'type': 'string',\n", + " 'description': 'Month for the Southern hemisphere, empty if isAllYear is true.'},\n", + " 'time': {'type': 'string',\n", + " 'description': 'Time of availability, empty is isAllDay is true.'},\n", + " 'isAllDay': {'type': 'boolean',\n", + " 'description': 'Is the sea creature available at any hour?'},\n", + " 'isAllYear': {'type': 'boolean',\n", + " 'description': 'Is the sea creature available at any day?'},\n", + " 'month-array-northern': {'type': 'array',\n", + " 'description': 'Array containing the month when the critter is available in the Northern Hemisphere.',\n", + " 'items': {'type': 'number'}},\n", + " 'month-array-southern': {'type': 'array',\n", + " 'description': 'Array containing the month when the critter is available in the Southern Hemisphere.',\n", + " 'items': {'type': 'number'}},\n", + " 'time-array': {'type': 'array',\n", + " 'description': 'Array containing the hours when the critter is available during the day (24h format).',\n", + " 'items': {'type': 'number'}}}},\n", + " 'speed': {'type': 'string',\n", + " 'description': 'Speed of the sea creature'},\n", + " 'shadow': {'type': 'string', 'description': 'Size of the shadow.'},\n", + " 'price': {'type': 'number', 'description': 'Selling price.'},\n", + " 'catch-phrase': {'type': 'string',\n", + " 'description': 'Catch phrase of the sea creature'},\n", + " 'icon_uri': {'type': 'string', 'description': 'URI for icon'},\n", + " 'image_uri': {'type': 'string', 'description': 'URI for image'},\n", + " 'museum-phrase': {'type': 'string',\n", + " 'description': 'Facts from Blathers'}},\n", + " 'required': ['id',\n", + " 'file-name',\n", + " 'name',\n", + " 'availability',\n", + " 'speed',\n", + " 'shadow',\n", + " 'price',\n", + " 'catch-phrase',\n", + " 'icon_uri',\n", + " 'image_uri',\n", + " 'museum-phrase']},\n", + " 'examples': {'/v1/sea/1': {'value': {'id': 1,\n", + " 'file-name': 'seaweed',\n", + " 'name': {'name-USen': 'seaweed',\n", + " 'name-EUen': 'seaweed',\n", + " 'name-EUnl': 'zeewier',\n", + " 'name-EUde': 'Wakame-Alge',\n", + " 'name-EUes': 'alga wakame',\n", + " 'name-USes': 'alga wakame',\n", + " 'name-EUfr': 'wakame',\n", + " 'name-USfr': 'wakamé',\n", + " 'name-EUit': 'alga wakame',\n", + " 'name-CNzh': '裙带菜',\n", + " 'name-TWzh': '裙帶菜',\n", + " 'name-JPja': 'ワカメ',\n", + " 'name-KRko': '미역',\n", + " 'name-EUru': 'морские водоросли'},\n", + " 'availability': {'month-northern': '10-7',\n", + " 'month-southern': '4-1',\n", + " 'time': '',\n", + " 'isAllDay': True,\n", + " 'isAllYear': False,\n", + " 'month-array-northern': [10, 11, 12, 1, 2, 3, 4, 5, 6, 7],\n", + " 'month-array-southern': [4, 5, 6, 7, 8, 9, 10, 11, 12, 1],\n", + " 'time-array': [0,\n", + " 1,\n", + " 2,\n", + " 3,\n", + " 4,\n", + " 5,\n", + " 6,\n", + " 7,\n", + " 8,\n", + " 9,\n", + " 10,\n", + " 11,\n", + " 12,\n", + " 13,\n", + " 14,\n", + " 15,\n", + " 16,\n", + " 17,\n", + " 18,\n", + " 19,\n", + " 20,\n", + " 21,\n", + " 22,\n", + " 23]},\n", + " 'speed': 'Stationary',\n", + " 'shadow': 'Large',\n", + " 'price': 600,\n", + " 'catch-phrase': \"I got some seaweed! I couldn't kelp myself.\",\n", + " 'image_uri': 'https://acnhapi.com/v1/images/sea/1',\n", + " 'icon_uri': 'https://acnhapi.com/v1/icons/sea/1',\n", + " 'museum-phrase': \"Let it be known that seaweed is a misnomer of the highest order! That is, it is not a noxious weed so much as it is a marine algae most beneficial to life on land and sea. Seaweed, you see, provides essential habitat and food for all manner of marine creatures. And it creates a great deal of the oxygen we land lovers love to breath too, hoo! And yet, I can't help but shudder when the slimy stuff touches my toes during a swim. Hoot! The horror!\"}}}}}},\n", + " '404': {'description': 'Not Found'}},\n", + " 'operationId': 'get-sea-seaID',\n", + " 'description': 'Get sea creature data in JSON format. \\n\\nThe {seaID} parameter is optional and can be removed to get all the sea creature data.'}},\n", + " '/v1/bugs/{bugID}': {'parameters': [{'schema': {'type': 'string'},\n", + " 'name': 'bugID',\n", + " 'in': 'path',\n", + " 'description': \"Either the file-name of a bug or it's ID.\",\n", + " 'required': True}],\n", + " 'get': {'summary': 'Bugs',\n", + " 'responses': {'200': {'description': 'OK',\n", + " 'content': {'application/json': {'schema': {'type': 'object',\n", + " 'properties': {'id': {'type': 'number'},\n", + " 'file-name': {'type': 'string'},\n", + " 'name': {'type': 'object',\n", + " 'description': 'Name of the bug in different languages.',\n", + " 'required': ['name-USen',\n", + " 'name-CNzh',\n", + " 'name-EUde',\n", + " 'name-EUes',\n", + " 'name-EUfr',\n", + " 'name-EUit',\n", + " 'name-JPja',\n", + " 'name-KRko',\n", + " 'name-EUnl',\n", + " 'name-EUru',\n", + " 'name-EUen',\n", + " 'name-USes',\n", + " 'name-USfr',\n", + " 'name-TWzh'],\n", + " 'properties': {'name-USen': {'type': 'string',\n", + " 'description': 'English'},\n", + " 'name-CNzh': {'type': 'string',\n", + " 'description': 'Simplified Chinese'},\n", + " 'name-EUde': {'type': 'string', 'description': 'German'},\n", + " 'name-EUes': {'type': 'string', 'description': 'Spanish'},\n", + " 'name-EUfr': {'type': 'string', 'description': 'French'},\n", + " 'name-EUit': {'type': 'string', 'description': 'Italian'},\n", + " 'name-JPja': {'type': 'string', 'description': 'Japanese'},\n", + " 'name-KRko': {'type': 'string', 'description': 'Korean'},\n", + " 'name-EUnl': {'type': 'string', 'description': 'Dutch'},\n", + " 'name-EUru': {'type': 'string', 'description': 'Russian'},\n", + " 'name-EUen': {'type': 'string', 'description': 'Non US English'},\n", + " 'name-USes': {'type': 'string',\n", + " 'description': 'Latin American Spanish'},\n", + " 'name-USfr': {'type': 'string', 'description': 'Canadian French'},\n", + " 'name-TWzh': {'type': 'string',\n", + " 'description': 'Traditional Chinese'}}},\n", + " 'availability': {'type': 'object',\n", + " 'description': 'When and where to find the bug.',\n", + " 'required': ['isAllDay', 'isAllYear', 'location', 'rarity'],\n", + " 'properties': {'month-northern': {'type': 'string',\n", + " 'description': 'Month for the Northern hemisphere, empty if isAllYear is true.'},\n", + " 'month-southern': {'type': 'string',\n", + " 'description': 'Month for the Southern hemisphere, empty if isAllYear is true.'},\n", + " 'time': {'type': 'string',\n", + " 'description': 'Time of availability, empty is isAllDay is true.'},\n", + " 'isAllDay': {'type': 'boolean',\n", + " 'description': 'Is the bug available at any hour?'},\n", + " 'isAllYear': {'type': 'boolean',\n", + " 'description': 'Is the bug available at any day?'},\n", + " 'location': {'type': 'string',\n", + " 'description': 'Location of the bug.'},\n", + " 'rarity': {'type': 'string', 'description': 'Rarity of the bug.'},\n", + " 'month-array-northern': {'type': 'array',\n", + " 'description': 'Array containing the month when the critter is available in the Northern Hemisphere.',\n", + " 'items': {'type': 'number'}},\n", + " 'month-array-southern': {'type': 'array',\n", + " 'description': 'Array containing the month when the critter is available in the Southern Hemisphere.',\n", + " 'items': {'type': 'number'}},\n", + " 'time-array': {'type': 'array',\n", + " 'description': 'Array containing the hours when the critter is available during the day (24h format).',\n", + " 'items': {'type': 'number'}}}},\n", + " 'price': {'type': 'string', 'description': 'Selling price.'},\n", + " 'price-flick': {'type': 'string',\n", + " 'description': 'Selling price from Flick.'},\n", + " 'catch-phrase': {'type': 'string',\n", + " 'description': 'Phrase (or often pun) when the bug is caught.'},\n", + " 'museum-phrase': {'type': 'string',\n", + " 'description': 'Description from Blathers.'},\n", + " 'alt-catch-phrase': {'type': 'array',\n", + " 'description': 'Alternate catch phrases, when available.',\n", + " 'items': {'type': 'string'}},\n", + " 'icon_uri': {'type': 'string', 'description': 'URI for icon'},\n", + " 'image_uri': {'type': 'string', 'description': 'URI for image'}},\n", + " 'required': ['id',\n", + " 'file-name',\n", + " 'name',\n", + " 'availability',\n", + " 'price',\n", + " 'price-flick',\n", + " 'catch-phrase',\n", + " 'museum-phrase',\n", + " 'icon_uri',\n", + " 'image_uri']},\n", + " 'examples': {'/v1/bugs/1': {'value': {'id': 1,\n", + " 'file-name': 'common_butterfly',\n", + " 'name': {'name-USen': 'common butterfly',\n", + " 'name-EUen': 'common butterfly',\n", + " 'name-EUde': 'Kohlweißling',\n", + " 'name-EUes': 'mariposa común',\n", + " 'name-USes': 'mariposa común',\n", + " 'name-EUfr': 'piéride de la rave',\n", + " 'name-USfr': 'piéride de la rave',\n", + " 'name-EUit': 'farfalla comune',\n", + " 'name-EUnl': 'koolwitje',\n", + " 'name-CNzh': '白粉蝶',\n", + " 'name-TWzh': '白粉蝶',\n", + " 'name-JPja': 'モンシロチョウ',\n", + " 'name-KRko': '배추흰나비',\n", + " 'name-EUru': 'белянка'},\n", + " 'availability': {'month-northern': '9-6',\n", + " 'month-southern': '3-12',\n", + " 'time': '4am - 7pm',\n", + " 'isAllDay': False,\n", + " 'isAllYear': False,\n", + " 'location': 'Flying',\n", + " 'rarity': 'Common',\n", + " 'month-array-northern': [9, 10, 11, 12, 1, 2, 3, 4, 5, 6],\n", + " 'month-array-southern': [3, 4, 5, 6, 7, 8, 9, 10, 11, 12],\n", + " 'time-array': [4,\n", + " 5,\n", + " 6,\n", + " 7,\n", + " 8,\n", + " 9,\n", + " 10,\n", + " 11,\n", + " 12,\n", + " 13,\n", + " 14,\n", + " 15,\n", + " 16,\n", + " 17,\n", + " 18]},\n", + " 'price': 160,\n", + " 'price-flick': 240,\n", + " 'catch-phrase': 'I caught a common butterfly! They often flutter by!',\n", + " 'museum-phrase': \"The common butterfly would have you believe it is but a beautiful friend flitting prettily about the flowers. Bah, I say! They may seem innocent things with their pretty white wings, but they hide a dark side! The common butterfly caterpillar is called a cabbage worm, you see, and it's a most voracious pest. The ravenous beasts chew through cabbage, broccoli, kale and the like with a devastating gusto. And my feathers! Their green coloring is truly GROSS! A hoo-rrific hue, I say.\",\n", + " 'image_uri': 'https://acnhapi.com/v1/images/bugs/1',\n", + " 'icon_uri': 'https://acnhapi.com/v1/icons/bugs/1'}}}}}},\n", + " '404': {'description': 'Not Found'}},\n", + " 'operationId': 'get-bugs-bugID',\n", + " 'description': 'Get bugs data in JSON format. \\n\\nThe {bugID} parameter is optional and can be removed to get all the bugs data.',\n", + " 'tags': ['Bugs']}},\n", + " '/v1/fossils/{fossilName}': {'parameters': [{'schema': {'type': 'string'},\n", + " 'name': 'fossilName',\n", + " 'in': 'path',\n", + " 'description': 'The file-name of a fossil.',\n", + " 'required': True}],\n", + " 'get': {'summary': 'Fossils',\n", + " 'responses': {'200': {'description': 'OK',\n", + " 'content': {'application/json': {'schema': {'type': 'object',\n", + " 'properties': {'file-name': {'type': 'string',\n", + " 'description': 'Name of the image files.'},\n", + " 'name': {'type': 'object',\n", + " 'description': 'Name of the fossil in different languages.',\n", + " 'required': ['name-USen',\n", + " 'name-CNzh',\n", + " 'name-EUde',\n", + " 'name-EUes',\n", + " 'name-EUfr',\n", + " 'name-EUit',\n", + " 'name-JPja',\n", + " 'name-KRko',\n", + " 'name-EUnl',\n", + " 'name-EUru',\n", + " 'name-EUen',\n", + " 'name-USes',\n", + " 'name-USfr',\n", + " 'name-TWzh'],\n", + " 'properties': {'name-USen': {'type': 'string',\n", + " 'description': 'English'},\n", + " 'name-CNzh': {'type': 'string',\n", + " 'description': 'Simplified Chinese'},\n", + " 'name-EUde': {'type': 'string', 'description': 'German'},\n", + " 'name-EUes': {'type': 'string', 'description': 'Spanish'},\n", + " 'name-EUfr': {'type': 'string', 'description': 'French'},\n", + " 'name-EUit': {'type': 'string', 'description': 'Italian'},\n", + " 'name-JPja': {'type': 'string', 'description': 'Japanese'},\n", + " 'name-KRko': {'type': 'string', 'description': 'Korean'},\n", + " 'name-EUnl': {'type': 'string', 'description': 'Dutch'},\n", + " 'name-EUru': {'type': 'string', 'description': 'Russian'},\n", + " 'name-EUen': {'type': 'string',\n", + " 'description': 'Non American English'},\n", + " 'name-USes': {'type': 'string',\n", + " 'description': 'Latin American Spanish'},\n", + " 'name-USfr': {'type': 'string', 'description': 'Canadian French'},\n", + " 'name-TWzh': {'type': 'string',\n", + " 'description': 'Traditional Chinese'}}},\n", + " 'price': {'type': 'number', 'description': 'Selling price.'},\n", + " 'museum-phrase': {'type': 'string',\n", + " 'description': 'Description from Blathers.'},\n", + " 'image_uri': {'type': 'string', 'description': 'URI for icon'}},\n", + " 'required': ['file-name',\n", + " 'name',\n", + " 'price',\n", + " 'museum-phrase',\n", + " 'image_uri']},\n", + " 'examples': {'/v1/fossils/amber': {'value': {'file-name': 'amber',\n", + " 'name': {'name-USen': 'amber',\n", + " 'name-EUen': 'amber',\n", + " 'name-EUde': 'Bernstein',\n", + " 'name-EUes': 'ámbar',\n", + " 'name-USes': 'ámbar',\n", + " 'name-EUfr': 'ambre',\n", + " 'name-USfr': 'ambre',\n", + " 'name-EUit': 'ambra',\n", + " 'name-EUnl': 'barnsteen',\n", + " 'name-CNzh': '琥珀',\n", + " 'name-TWzh': '琥珀',\n", + " 'name-JPja': 'コハク',\n", + " 'name-KRko': '호박',\n", + " 'name-EUru': 'янтарь'},\n", + " 'price': 1200,\n", + " 'museum-phrase': 'Amber is formed from the sap of ancient trees that hardened over time. Because of its beauty, it has often been traded and used as jewelry throughout history. However, individual specimens may contain ancient plants or insects trapped inside them! These are valuable resources for learning about ancient eras, such as when the dinosaurs roamed... And this is why they are sometimes displayed in certain...ahem... exceptional museums! Like mine.',\n", + " 'image_uri': 'https://acnhapi.com/v1/images/fossils/amber'}}}}}},\n", + " '404': {'description': 'Not Found'}},\n", + " 'operationId': 'get-fossils-fossilName',\n", + " 'description': 'Get fossil data in JSON format. \\n\\nThe {fossilName} parameter is optional and can be removed to get all the fossils data.',\n", + " 'tags': ['Fossils']}},\n", + " '/v1/villagers/{villagerID}': {'parameters': [{'schema': {'type': 'string'},\n", + " 'name': 'villagerID',\n", + " 'in': 'path',\n", + " 'description': \"Either the file-name of a villager or it's ID.\",\n", + " 'required': True}],\n", + " 'get': {'summary': 'Villagers',\n", + " 'responses': {'200': {'description': 'OK',\n", + " 'content': {'application/json': {'schema': {'type': 'object',\n", + " 'properties': {'id': {'type': 'number',\n", + " 'description': 'ID of the villager.'},\n", + " 'file-name': {'type': 'string',\n", + " 'description': 'Name of the image files.'},\n", + " 'name': {'type': 'object',\n", + " 'description': 'Name of the villager in different languages.',\n", + " 'required': ['name-USen',\n", + " 'name-CNzh',\n", + " 'name-EUde',\n", + " 'name-EUes',\n", + " 'name-EUfr',\n", + " 'name-EUit',\n", + " 'name-JPja',\n", + " 'name-KRko',\n", + " 'name-EUnl',\n", + " 'name-EUru',\n", + " 'name-EUen',\n", + " 'name-USes',\n", + " 'name-USfr',\n", + " 'name-TWzh'],\n", + " 'properties': {'name-USen': {'type': 'string',\n", + " 'description': 'English'},\n", + " 'name-CNzh': {'type': 'string',\n", + " 'description': 'Simplified Chinese'},\n", + " 'name-EUde': {'type': 'string', 'description': 'German'},\n", + " 'name-EUes': {'type': 'string', 'description': 'Spanish'},\n", + " 'name-EUfr': {'type': 'string', 'description': 'French'},\n", + " 'name-EUit': {'type': 'string', 'description': 'Italian'},\n", + " 'name-JPja': {'type': 'string', 'description': 'Japanese'},\n", + " 'name-KRko': {'type': 'string', 'description': 'Korean'},\n", + " 'name-EUnl': {'type': 'string', 'description': 'Dutch'},\n", + " 'name-EUru': {'type': 'string', 'description': 'Russian'},\n", + " 'name-EUen': {'type': 'string',\n", + " 'description': 'Non American English'},\n", + " 'name-USes': {'type': 'string',\n", + " 'description': 'Latin American Spanish'},\n", + " 'name-USfr': {'type': 'string', 'description': 'Canadian French'},\n", + " 'name-TWzh': {'type': 'string',\n", + " 'description': 'Traditional Chinese'}}},\n", + " 'personality': {'type': 'string',\n", + " 'description': 'The personality of the villager.'},\n", + " 'birthday': {'type': 'string',\n", + " 'description': 'Birthday of the villager in Day/Month format.'},\n", + " 'species': {'type': 'string',\n", + " 'description': 'Species of the villager.'},\n", + " 'gender': {'type': 'string',\n", + " 'description': 'Gender of the villager, either \"Male\" or \"Female\".'},\n", + " 'catch-phrase': {'type': 'string',\n", + " 'description': 'The catch phrase of a villager.'},\n", + " 'birthday-string': {'type': 'string',\n", + " 'description': 'String of the birthday (Day/Month format).'},\n", + " 'icon_uri': {'type': 'string', 'description': 'URI for icon'},\n", + " 'image_uri': {'type': 'string', 'description': 'URI for image'}},\n", + " 'required': ['id',\n", + " 'file-name',\n", + " 'name',\n", + " 'personality',\n", + " 'birthday',\n", + " 'species',\n", + " 'gender',\n", + " 'catch-phrase',\n", + " 'birthday-string',\n", + " 'icon_uri',\n", + " 'image_uri']},\n", + " 'examples': {'/v1/villagers/1': {'value': {'id': 1,\n", + " 'file-name': 'ant00',\n", + " 'name': {'name-USen': 'Cyrano',\n", + " 'name-EUen': 'Cyrano',\n", + " 'name-EUde': 'Theo',\n", + " 'name-EUes': 'Cirano',\n", + " 'name-USes': 'Cirano',\n", + " 'name-EUfr': 'Cyrano',\n", + " 'name-USfr': 'Cyrano',\n", + " 'name-EUit': 'Cirano',\n", + " 'name-EUnl': 'Cyrano',\n", + " 'name-CNzh': '阳明',\n", + " 'name-TWzh': '陽明',\n", + " 'name-JPja': 'さくらじま',\n", + " 'name-KRko': '사지마',\n", + " 'name-EUru': 'Сирано'},\n", + " 'personality': 'Cranky',\n", + " 'birthday-string': 'March 9th',\n", + " 'birthday': '9/3',\n", + " 'species': 'Anteater',\n", + " 'gender': 'Male',\n", + " 'catch-phrase': 'ah-CHOO',\n", + " 'icon_uri': 'https://acnhapi.com/v1/icons/villagers/1',\n", + " 'image_uri': 'https://acnhapi.com/v1/images/villagers/1'}}}}}},\n", + " '404': {'description': 'Not Found'}},\n", + " 'operationId': 'get-villagers-villagerID',\n", + " 'description': 'Get villager data in JSON format. \\n\\nThe {villagerID} parameter is optional and can be removed to get all the villagers data.',\n", + " 'tags': ['Villagers']}},\n", + " '/v1/icons/fish/{fishID}': {'parameters': [{'schema': {'type': 'string'},\n", + " 'name': 'fishID',\n", + " 'in': 'path',\n", + " 'required': True,\n", + " 'description': \"Either the file-name of a fish or it's ID.\"}],\n", + " 'get': {'summary': 'Fish icons',\n", + " 'responses': {'200': {'description': 'OK'},\n", + " '404': {'description': 'Not Found'}},\n", + " 'operationId': 'get-icons-fish-fishID',\n", + " 'description': 'Get fish icons in PNG format. \\n\\nThe {fishID} parameter can be found using the /v1/fish/ endpoint.',\n", + " 'tags': ['Icons']}},\n", + " '/v1/icons/bugs/{bugID}': {'parameters': [{'schema': {'type': 'string'},\n", + " 'name': 'bugID',\n", + " 'in': 'path',\n", + " 'required': True,\n", + " 'description': \"Either the file-name of a bug or it's ID.\"}],\n", + " 'get': {'summary': 'Bugs icons',\n", + " 'responses': {'200': {'description': 'OK'},\n", + " '404': {'description': 'Not Found'}},\n", + " 'operationId': 'get-icons-bugs-bugsID',\n", + " 'description': 'Get bugs icons in PNG format. \\n\\nThe {bugID} parameter can be found using the /v1/bugs/ endpoint.',\n", + " 'tags': ['Icons']}},\n", + " '/v1/icons/villagers/{villagerID}': {'parameters': [{'schema': {'type': 'string'},\n", + " 'name': 'villagerID',\n", + " 'in': 'path',\n", + " 'required': True,\n", + " 'description': \"Either the file-name of a villager or it's ID.\"}],\n", + " 'get': {'summary': 'Villager icons',\n", + " 'responses': {'200': {'description': 'OK'},\n", + " '404': {'description': 'Not Found'}},\n", + " 'operationId': 'get-icons-villagers-villagerID',\n", + " 'description': 'Get villager icons in PNG format. \\n\\nThe {villagerID} parameter can be found using the /v1/villagers/ endpoint.',\n", + " 'tags': ['Icons']}},\n", + " '/v1/images/fish/{fishID}': {'parameters': [{'schema': {'type': 'string'},\n", + " 'name': 'fishID',\n", + " 'in': 'path',\n", + " 'required': True,\n", + " 'description': \"Either the file-name of a fish or it's ID.\"}],\n", + " 'get': {'summary': 'Fish images',\n", + " 'responses': {'200': {'description': 'OK'},\n", + " '404': {'description': 'Not Found'}},\n", + " 'operationId': 'get-images-fish-fishID',\n", + " 'description': 'Get fish images in PNG format. \\n\\nThe {fishID} parameter can be found using the /v1/fish/ endpoint.',\n", + " 'tags': ['Images']}},\n", + " '/v1/images/bugs/{bugID}': {'parameters': [{'schema': {'type': 'string'},\n", + " 'name': 'bugID',\n", + " 'in': 'path',\n", + " 'required': True,\n", + " 'description': \"Either the file-name of a bug or it's ID.\"}],\n", + " 'get': {'summary': 'Bugs images',\n", + " 'responses': {'200': {'description': 'OK'},\n", + " '404': {'description': 'Not Found'}},\n", + " 'operationId': 'get-images-bugs-bugID',\n", + " 'description': 'Get bugs images in PNG format. \\n\\nThe {bugID} parameter can be found using the /v1/bugs/ endpoint.',\n", + " 'tags': ['Images']}},\n", + " '/v1/images/villagers/{villagerID}': {'parameters': [{'schema': {'type': 'string'},\n", + " 'name': 'villagerID',\n", + " 'in': 'path',\n", + " 'required': True,\n", + " 'description': \"Either the file-name of a villager or it's ID.\"}],\n", + " 'get': {'summary': 'Villager images',\n", + " 'tags': ['Images'],\n", + " 'responses': {'200': {'description': 'OK'},\n", + " '404': {'description': 'Not Found'}},\n", + " 'operationId': 'get-images-villagers-villagerID',\n", + " 'description': 'Get villager images in PNG format. \\n\\nThe {villagerID} parameter can be found using the /v1/villagers/ endpoint.'}},\n", + " '/v1/images/fossils/{fossilName}': {'parameters': [{'schema': {'type': 'string'},\n", + " 'name': 'fossilName',\n", + " 'in': 'path',\n", + " 'required': True,\n", + " 'description': 'The file-name of a fossil.'}],\n", + " 'get': {'summary': 'Fossils images',\n", + " 'tags': ['Images'],\n", + " 'responses': {'200': {'description': 'OK'},\n", + " '404': {'description': 'Not Found'}},\n", + " 'operationId': 'get-images-fossils-fossilName',\n", + " 'description': 'Get fossil images in PNG format. \\n\\nThe {fossilName} parameter can be found using the /v1/fossils/ endpoint.'}},\n", + " '/v1/songs/{songID}': {'parameters': [{'schema': {'type': 'string'},\n", + " 'name': 'songID',\n", + " 'in': 'path',\n", + " 'required': True}],\n", + " 'get': {'summary': 'Songs',\n", + " 'tags': ['Songs'],\n", + " 'responses': {'200': {'description': 'OK',\n", + " 'content': {'application/json': {'schema': {'type': 'object',\n", + " 'properties': {'id': {'type': 'boolean',\n", + " 'description': 'ID of the song.'},\n", + " 'file-name': {'type': 'string',\n", + " 'description': 'String to access the MP3 and the song cover files.'},\n", + " 'name': {'type': 'object',\n", + " 'description': 'Translations of the song.',\n", + " 'required': ['name-USen',\n", + " 'name-CNzh',\n", + " 'name-EUde',\n", + " 'name-EUes',\n", + " 'name-EUfr',\n", + " 'name-EUit',\n", + " 'name-JPja',\n", + " 'name-KRko',\n", + " 'name-EUnl',\n", + " 'name-EUru',\n", + " 'name-EUen',\n", + " 'name-USes',\n", + " 'name-USfr',\n", + " 'name-TWzh'],\n", + " 'properties': {'name-USen': {'type': 'string',\n", + " 'description': 'English'},\n", + " 'name-CNzh': {'type': 'string',\n", + " 'description': 'Simplified Chinese'},\n", + " 'name-EUde': {'type': 'string', 'description': 'German'},\n", + " 'name-EUes': {'type': 'string', 'description': 'Spanish'},\n", + " 'name-EUfr': {'type': 'string', 'description': 'French'},\n", + " 'name-EUit': {'type': 'string', 'description': 'Italian'},\n", + " 'name-JPja': {'type': 'string', 'description': 'Japanese'},\n", + " 'name-KRko': {'type': 'string', 'description': 'Korean'},\n", + " 'name-EUnl': {'type': 'string', 'description': 'Dutch'},\n", + " 'name-EUru': {'type': 'string', 'description': 'Russian'},\n", + " 'name-EUen': {'type': 'string',\n", + " 'description': 'Non American English'},\n", + " 'name-USes': {'type': 'string',\n", + " 'description': 'Latin American Spanish'},\n", + " 'name-USfr': {'type': 'string', 'description': 'Canadian French'},\n", + " 'name-TWzh': {'type': 'string',\n", + " 'description': 'Traditional Chinese'}}},\n", + " 'buy-price': {'type': 'number',\n", + " 'nullable': True,\n", + " 'description': \"Price at which the song is sold, is null if the song can't be purchased\"},\n", + " 'sell-price': {'type': 'number', 'description': 'Selling price.'},\n", + " 'isOrderable': {'type': 'boolean',\n", + " 'description': 'Can the song be ordered from the catalogue?'},\n", + " 'image_uri': {'type': 'string', 'description': 'URI for image'},\n", + " 'music_uri': {'type': 'string', 'description': 'URI for music'}},\n", + " 'required': ['id',\n", + " 'file-name',\n", + " 'name',\n", + " 'buy-price',\n", + " 'sell-price',\n", + " 'isOrderable',\n", + " 'image_uri',\n", + " 'music_uri']},\n", + " 'examples': {'/v1/songs/1': {'value': {'id': 1,\n", + " 'file-name': 'mjk_Keiji',\n", + " 'name': {'name-USen': 'Agent K.K.',\n", + " 'name-EUen': 'Agent K.K.',\n", + " 'name-EUde': 'Agent K.K.',\n", + " 'name-EUes': 'Agente Totakeke',\n", + " 'name-USes': 'Agente Totakeke',\n", + " 'name-EUfr': 'Agent Kéké',\n", + " 'name-USfr': 'Agent Kéké',\n", + " 'name-EUit': 'Agente K.K.',\n", + " 'name-EUnl': 'Agent K.K.',\n", + " 'name-CNzh': 'K.K.刑警',\n", + " 'name-TWzh': 'K.K.刑警',\n", + " 'name-JPja': 'けけけいじ',\n", + " 'name-KRko': 'K.K.형사',\n", + " 'name-EUru': 'Агент К. К.'},\n", + " 'buy-price': 3200,\n", + " 'sell-price': 800,\n", + " 'isOrderable': True,\n", + " 'music_uri': 'https://acnhapi.com/v1/music/1',\n", + " 'image_uri': 'https://acnhapi.com/v1/images/songs/1'}}}}}},\n", + " '404': {'description': 'Not Found'}},\n", + " 'operationId': 'get-songs-songID',\n", + " 'description': 'Get K.K. songs data in JSON format. \\n\\nThe {songID} parameter is optional and can be removed to get all the songs data.'}},\n", + " '/v1/images/songs/{songID}': {'parameters': [{'schema': {'type': 'string'},\n", + " 'name': 'songID',\n", + " 'in': 'path',\n", + " 'required': True}],\n", + " 'get': {'responses': {'200': {'description': 'OK'},\n", + " '404': {'description': 'Not Found'}},\n", + " 'summary': 'Song images',\n", + " 'tags': ['Images'],\n", + " 'operationId': 'get-images-songs-songID',\n", + " 'description': 'Get song cover images in PNG format. \\n\\nThe {songID} parameter can be found using the /v1/songs/ endpoint.'}},\n", + " '/v1/music/{songID}': {'parameters': [{'schema': {'type': 'string'},\n", + " 'name': 'songID',\n", + " 'in': 'path',\n", + " 'required': True}],\n", + " 'get': {'summary': 'Music',\n", + " 'tags': ['Music'],\n", + " 'responses': {'200': {'description': 'OK'},\n", + " '404': {'description': 'Not Found'}},\n", + " 'operationId': 'get-music-songID',\n", + " 'description': 'Get K.K. songs data in MP3 format. \\n\\nThe {songID} parameter can be found using the /songs/ endpoint.'}},\n", + " '/v1/art/{artID}': {'parameters': [{'schema': {'type': 'string'},\n", + " 'name': 'artID',\n", + " 'in': 'path',\n", + " 'required': True}],\n", + " 'get': {'summary': 'Art',\n", + " 'tags': ['Art'],\n", + " 'responses': {'200': {'description': 'OK',\n", + " 'content': {'application/json': {'schema': {'type': 'object',\n", + " 'properties': {'id': {'type': 'number'},\n", + " 'file-name': {'type': 'string'},\n", + " 'name': {'type': 'object',\n", + " 'description': 'Name of the art in different languages.',\n", + " 'required': ['name-en',\n", + " 'name-eneu',\n", + " 'name-de',\n", + " 'name-sp',\n", + " 'name-spus',\n", + " 'name-fr',\n", + " 'name-frus',\n", + " 'name-it',\n", + " 'name-nl',\n", + " 'name-cn',\n", + " 'name-tw',\n", + " 'name-jp',\n", + " 'name-kr',\n", + " 'name-ru'],\n", + " 'properties': {'name-en': {'type': 'string',\n", + " 'description': 'English'},\n", + " 'name-eneu': {'type': 'string',\n", + " 'description': 'Non American English'},\n", + " 'name-de': {'type': 'string', 'description': 'German'},\n", + " 'name-sp': {'type': 'string', 'description': 'Spanish'},\n", + " 'name-spus': {'type': 'string',\n", + " 'description': 'Latin American Spanish'},\n", + " 'name-fr': {'type': 'string', 'description': 'French'},\n", + " 'name-frus': {'type': 'string', 'description': 'Canadian French'},\n", + " 'name-it': {'type': 'string', 'description': 'Italian'},\n", + " 'name-nl': {'type': 'string', 'description': 'Dutch'},\n", + " 'name-cn': {'type': 'string', 'description': 'Simplified Chinese'},\n", + " 'name-tw': {'type': 'string', 'description': 'Traditional Chinese'},\n", + " 'name-jp': {'type': 'string', 'description': 'Japanese'},\n", + " 'name-kr': {'type': 'string', 'description': 'Korean'},\n", + " 'name-ru': {'type': 'string', 'description': 'Russian'}}},\n", + " 'hasFake': {'type': 'boolean', 'description': 'Can the art be fake.'},\n", + " 'buy-price': {'type': 'number',\n", + " 'description': 'Price at which Redd sells the art'},\n", + " 'sell-price': {'type': 'number',\n", + " 'description': 'Price it which the art will sell (if genuine)'},\n", + " 'image_uri': {'type': 'string', 'description': 'URI for image'},\n", + " 'museum-desc': {'type': 'string',\n", + " 'description': 'Description inside the museum'}},\n", + " 'required': ['id',\n", + " 'file-name',\n", + " 'name',\n", + " 'hasFake',\n", + " 'buy-price',\n", + " 'sell-price',\n", + " 'image_uri',\n", + " 'museum-desc']},\n", + " 'examples': {'/v1/art/1': {'value': {'id': 1,\n", + " 'file-name': 'academic_painting',\n", + " 'name': {'name-USen': 'academic painting',\n", + " 'name-EUen': 'academic painting',\n", + " 'name-EUde': 'Wissenschaftsgemälde',\n", + " 'name-EUes': 'cuadro anatómico',\n", + " 'name-USes': 'cuadro anatómico',\n", + " 'name-EUfr': 'toile académique',\n", + " 'name-USfr': 'toile académique',\n", + " 'name-EUit': 'quadro accademico',\n", + " 'name-EUnl': 'academische schilderij',\n", + " 'name-CNzh': '学术性的名画',\n", + " 'name-TWzh': '學術性的名畫',\n", + " 'name-JPja': 'アカデミックなめいが',\n", + " 'name-KRko': '아카데믹한 명화',\n", + " 'name-EUru': 'академическая картина'},\n", + " 'hasFake': True,\n", + " 'buy-price': 4980,\n", + " 'sell-price': 1245,\n", + " 'image_uri': 'https://acnhapi.com/v1/images/art/academic_painting',\n", + " 'museum-desc': 'This drawing is based on the \"ideal\" human-body ratio, as stated in \"De architectura.\" \"De architectura\" was a treatise by Vitruvius, an architect from the early 1st century BCE.'}}}}}},\n", + " '404': {'description': 'Not Found'}},\n", + " 'operationId': 'get-art-artID',\n", + " 'description': 'Get art data in JSON format. \\n\\nThe {artID} parameter is optional and can be removed to get all the art data.'}},\n", + " '/v1/icons/art/{artID}': {'parameters': [{'schema': {'type': 'string'},\n", + " 'name': 'artID',\n", + " 'in': 'path',\n", + " 'required': True}],\n", + " 'get': {'summary': 'Your GET endpoint',\n", + " 'tags': ['Icons'],\n", + " 'responses': {'200': {'description': 'OK'},\n", + " '404': {'description': 'Not Found'}},\n", + " 'operationId': 'get-icons-art-artID',\n", + " 'description': 'Get art icons in PNG format. \\n\\nThe {artID} parameter can be found using the /art/ endpoint.'}},\n", + " '/v1/hourly/{songID}': {'parameters': [{'schema': {'type': 'string'},\n", + " 'name': 'songID',\n", + " 'in': 'path',\n", + " 'required': True}],\n", + " 'get': {'summary': 'Hourly music',\n", + " 'tags': ['Hourly music'],\n", + " 'responses': {'200': {'description': 'OK'},\n", + " '404': {'description': 'Not Found'}},\n", + " 'operationId': 'get-v1-hourly-songID',\n", + " 'description': 'Get hourly songs data in MP3 format. \\n\\nThe {songID} parameter can be found using the /backgroundmusic/ endpoint.'}},\n", + " '/v1/backgroundmusic/{songID}': {'parameters': [{'schema': {'type': 'string'},\n", + " 'name': 'songID',\n", + " 'in': 'path',\n", + " 'required': True}],\n", + " 'get': {'summary': 'BGM',\n", + " 'tags': ['BGM'],\n", + " 'responses': {'200': {'description': 'OK',\n", + " 'content': {'application/json': {'schema': {'type': 'object',\n", + " 'properties': {'id': {'type': 'string',\n", + " 'description': 'ID of the song.'},\n", + " 'file-name': {'type': 'string',\n", + " 'description': 'File name of the song'},\n", + " 'hour': {'type': 'number',\n", + " 'description': 'Hour in 24h format at which the song plays'},\n", + " 'weather': {'type': 'string', 'description': 'Weather'},\n", + " 'music_uri': {'type': 'string', 'description': 'URI for music'}},\n", + " 'required': ['id', 'file-name', 'hour', 'weather', 'music_uri']},\n", + " 'examples': {'/v1/backgroundmusic/1': {'value': {'id': 1,\n", + " 'file-name': 'BGM_24Hour_00_Rainy',\n", + " 'hour': 0,\n", + " 'weather': 'Rainy'}}}}}},\n", + " '404': {'description': 'Not Found'}},\n", + " 'operationId': 'get-v1-backgroundmusic-songID',\n", + " 'description': 'Get hourly songs data in JSON format. \\n\\nThe {songID} parameter is optional and can be removed to get all the songs data.'}},\n", + " '/v1/houseware/{housewareID}': {'parameters': [{'schema': {'type': 'string'},\n", + " 'name': 'housewareID',\n", + " 'in': 'path',\n", + " 'required': True}],\n", + " 'get': {'summary': 'Houseware',\n", + " 'tags': ['Items'],\n", + " 'responses': {'200': {'description': 'OK',\n", + " 'content': {'application/json': {'schema': {'type': 'array',\n", + " 'description': 'Returns an array of variant for the furniture specified as housewareID',\n", + " 'items': {'type': 'object',\n", + " 'description': 'A variant object',\n", + " 'properties': {'variant': {'type': 'string',\n", + " 'nullable': True,\n", + " 'description': 'Name of the variant, null if the furniture only has one.'},\n", + " 'body-title': {'type': 'string',\n", + " 'nullable': True,\n", + " 'description': 'Type of body variant'},\n", + " 'pattern': {'type': 'string',\n", + " 'nullable': True,\n", + " 'description': 'Name of the pattern variant'},\n", + " 'pattern-title': {'type': 'string',\n", + " 'nullable': True,\n", + " 'description': 'Type of the pattern variant'},\n", + " 'isDIY': {'type': 'boolean',\n", + " 'description': 'Can the item be crafted?'},\n", + " 'canCustomizeBody': {'type': 'boolean',\n", + " 'description': 'Can you customize the body?'},\n", + " 'canCustomizePattern': {'type': 'boolean',\n", + " 'description': 'Can you customize the pattern?'},\n", + " 'kit-cost': {'type': 'number',\n", + " 'nullable': True,\n", + " 'description': \"Number of kit required to customize, null if can't be customized\"},\n", + " 'color-1': {'type': 'string', 'description': 'Primary color'},\n", + " 'color-2': {'type': 'string', 'description': 'Secondary color'},\n", + " 'size': {'type': 'string', 'description': 'Size of the item'},\n", + " 'miles-price': {'type': 'number',\n", + " 'nullable': True,\n", + " 'description': 'Number of miles to purchase the item at the Nook Stop'},\n", + " 'source': {'type': 'string',\n", + " 'description': 'Where to get the item from, separated by a \";\" if there are multiple sources.'},\n", + " 'source-detail': {'type': 'string',\n", + " 'description': 'Details on said sources'},\n", + " 'version': {'type': 'string',\n", + " 'description': 'Version of the game the item was introduced in.'},\n", + " 'hha-concept-1': {'type': 'string',\n", + " 'nullable': True,\n", + " 'description': 'First HHA theme.'},\n", + " 'hha-concept-2': {'type': 'string',\n", + " 'nullable': True,\n", + " 'description': 'First HHA theme.'},\n", + " 'hha-series': {'type': 'string',\n", + " 'nullable': True,\n", + " 'description': 'Second HHA theme.'},\n", + " 'hha-set': {'type': 'string',\n", + " 'nullable': True,\n", + " 'description': 'HHA set the item is in'},\n", + " 'isInteractive': {'type': 'boolean',\n", + " 'description': 'Can you interact with the item?'},\n", + " 'tag': {'type': 'string',\n", + " 'description': 'Tag associated with the object.'},\n", + " 'isOutdoor': {'type': 'boolean',\n", + " 'description': 'Can the item be placed outdoors?'},\n", + " 'speaker-type': {'type': 'string',\n", + " 'nullable': True,\n", + " 'description': 'Type of speaker, null if not a speaker'},\n", + " 'lighting-type': {'type': 'string',\n", + " 'nullable': True,\n", + " 'description': 'Type of lighting, null if not a light source'},\n", + " 'isCatalog': {'type': 'boolean',\n", + " 'description': 'Can the item be ordered from the catalog?'},\n", + " 'file-name': {'type': 'string',\n", + " 'description': 'Name of the file for the image endpoint'},\n", + " 'variant-id': {'type': 'string',\n", + " 'nullable': True,\n", + " 'description': 'ID of the variant, null if the item doesnt have variants.'},\n", + " 'internal-id': {'type': 'number',\n", + " 'description': 'Internal ID of the objects (in the game)'},\n", + " 'name': {'type': 'object',\n", + " 'required': ['name-USen',\n", + " 'name-EUde',\n", + " 'name-EUes',\n", + " 'name-USes',\n", + " 'name-EUfr',\n", + " 'name-USfr',\n", + " 'name-EUit',\n", + " 'name-EUnl',\n", + " 'name-CNzh',\n", + " 'name-TWzh',\n", + " 'name-JPja',\n", + " 'name-KRko',\n", + " 'name-EUru',\n", + " 'name-EUen'],\n", + " 'description': 'Translations',\n", + " 'properties': {'name-USen': {'type': 'string',\n", + " 'description': 'American English'},\n", + " 'name-EUde': {'type': 'string', 'description': 'German'},\n", + " 'name-EUes': {'type': 'string', 'description': 'Spanish'},\n", + " 'name-USes': {'type': 'string',\n", + " 'description': 'Latin American Spanish'},\n", + " 'name-EUfr': {'type': 'string', 'description': 'French'},\n", + " 'name-USfr': {'type': 'string', 'description': 'Canadian French'},\n", + " 'name-EUit': {'type': 'string', 'description': 'Italian'},\n", + " 'name-EUnl': {'type': 'string', 'description': 'Dutch'},\n", + " 'name-CNzh': {'type': 'string',\n", + " 'description': 'Simplified Chinese'},\n", + " 'name-TWzh': {'type': 'string',\n", + " 'description': 'Traditional Chinese'},\n", + " 'name-JPja': {'type': 'string', 'description': 'Japanese'},\n", + " 'name-KRko': {'type': 'string', 'description': 'Korean'},\n", + " 'name-EUru': {'type': 'string', 'description': 'Russian'},\n", + " 'name-EUen': {'type': 'string', 'description': 'English'}}},\n", + " 'buy-price': {'type': 'number',\n", + " 'nullable': True,\n", + " 'description': 'Price at which the item is purchased'},\n", + " 'sell-price': {'type': 'number',\n", + " 'nullable': True,\n", + " 'description': 'Price at which the item is sold'},\n", + " 'image_uri': {'type': 'string', 'description': 'URI for image'}},\n", + " 'required': ['variant',\n", + " 'body-title',\n", + " 'pattern',\n", + " 'pattern-title',\n", + " 'canCustomizeBody',\n", + " 'canCustomizePattern',\n", + " 'kit-cost',\n", + " 'color-1',\n", + " 'color-2',\n", + " 'size',\n", + " 'miles-price',\n", + " 'source',\n", + " 'source-detail',\n", + " 'version',\n", + " 'hha-concept-1',\n", + " 'hha-concept-2',\n", + " 'hha-series',\n", + " 'hha-set',\n", + " 'isInteractive',\n", + " 'tag',\n", + " 'isOutdoor',\n", + " 'speaker-type',\n", + " 'lighting-type',\n", + " 'isCatalog',\n", + " 'file-name',\n", + " 'variant-id',\n", + " 'internal-id',\n", + " 'name',\n", + " 'buy-price',\n", + " 'sell-price',\n", + " 'image_uri']}},\n", + " 'examples': {'/v1/houseware/alto_saxophone': {'value': [{'variant': None,\n", + " 'body-title': None,\n", + " 'pattern': None,\n", + " 'pattern-title': None,\n", + " 'isDIY': False,\n", + " 'canCustomizeBody': False,\n", + " 'canCustomizePattern': False,\n", + " 'kit-cost': None,\n", + " 'color-1': 'Yellow',\n", + " 'color-2': 'Yellow',\n", + " 'size': '1x1',\n", + " 'miles-price': None,\n", + " 'source': \"Nook's Cranny\",\n", + " 'source-detail': \"Available in Nook's Cranny (upgraded only), in the unique furniture slot\",\n", + " 'version': '1.0.0',\n", + " 'hha-concept-1': 'music',\n", + " 'hha-concept-2': None,\n", + " 'hha-series': None,\n", + " 'hha-set': None,\n", + " 'isInteractive': True,\n", + " 'tag': 'Musical Instrument',\n", + " 'isOutdoor': False,\n", + " 'speaker-type': None,\n", + " 'lighting-type': None,\n", + " 'isCatalog': True,\n", + " 'file-name': 'FtrAltosax',\n", + " 'variant-id': None,\n", + " 'internal-id': 846,\n", + " 'name': {'name-USen': 'alto saxophone',\n", + " 'name-EUen': 'alto saxophone',\n", + " 'name-EUde': 'Saxofon',\n", + " 'name-EUes': 'saxofón',\n", + " 'name-USes': 'saxofón',\n", + " 'name-EUfr': 'saxophone alto',\n", + " 'name-USfr': 'saxophone alto',\n", + " 'name-EUit': 'sax contralto',\n", + " 'name-EUnl': 'altsaxofoon',\n", + " 'name-CNzh': '中音萨克斯风',\n", + " 'name-TWzh': '中音薩克斯風',\n", + " 'name-JPja': 'アルトサックス',\n", + " 'name-KRko': '알토 색소폰',\n", + " 'name-EUru': 'альтовый саксофон'},\n", + " 'buy-price': 3400,\n", + " 'sell-price': 850,\n", + " 'image_uri': 'https://acnhapi.com/v1/images/furniture/FtrAltosax'}]}}}}},\n", + " '404': {'description': 'Not Found'}},\n", + " 'operationId': 'get-v1-houseware-housewareName',\n", + " 'description': 'Get houseware data in JSON format. \\n\\nThe {housewareID} parameter is optional and can be removed to get all the housewareID data.'}},\n", + " '/v1/wallmounted/{wallmountedID}': {'parameters': [{'schema': {'type': 'string'},\n", + " 'name': 'wallmountedID',\n", + " 'in': 'path',\n", + " 'required': True}],\n", + " 'get': {'summary': 'Wallmounted',\n", + " 'tags': ['Items'],\n", + " 'responses': {'200': {'description': 'OK'},\n", + " '404': {'description': 'Not Found'}}}},\n", + " '/v1/misc/{miscID}': {'parameters': [{'schema': {'type': 'string'},\n", + " 'name': 'miscID',\n", + " 'in': 'path',\n", + " 'required': True}],\n", + " 'get': {'summary': 'Misc',\n", + " 'tags': ['Items'],\n", + " 'responses': {'200': {'description': 'OK'},\n", + " '404': {'description': 'Not Found'}},\n", + " 'operationId': 'get-v1-misc-miscID',\n", + " 'description': 'see /v1/houseware endpoint.'}},\n", + " '/v1/images/funiture/{furnitureFileName}': {'parameters': [{'schema': {'type': 'string'},\n", + " 'name': 'furnitureFileName',\n", + " 'in': 'path',\n", + " 'required': True}],\n", + " 'get': {'summary': 'Furniture images',\n", + " 'tags': ['Images'],\n", + " 'responses': {'200': {'description': 'OK'},\n", + " '404': {'description': 'Not Found'}},\n", + " 'operationId': 'get-v1-images-funiture-furnitureFileName',\n", + " 'description': 'Get furniture images in PNG format. \\n\\nThe {furnitureFileName} parameter can be found using the file-name key in an houseware/wallmounted/misc variant object (eg: FtrJewelrystand_Remake_0_0).'}}}" + ] + }, + "execution_count": 153, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spec.spec_dict['paths']" + ] + }, + { + "cell_type": "code", + "execution_count": 154, + "id": "b12dcb3d", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.agents import ZeroShotAgent, Tool, AgentExecutor\n", + "from langchain import OpenAI, LLMChain" + ] + }, + { + "cell_type": "code", + "execution_count": 169, + "id": "a58a7ec5", + "metadata": {}, + "outputs": [], + "source": [ + "tools = [\n", + " Tool(\n", + " name = \"List Paths\",\n", + " func=spec.get_paths,\n", + " description=\"Can be used to list all available paths for this API spec. Input should be an empty string (it's not used).\"\n", + " ),\n", + " Tool(\n", + " name = \"Get Params\",\n", + " func=spec.get_parameters,\n", + " description=\"Get parameters for a given path. The input should be exactly ones of the paths available to this API spec, including any parameter placeholders.\"\n", + " ),\n", + " Tool(\n", + " name = \"Get Param Spec\",\n", + " func=spec.get_param_spec,\n", + " description='Get specification for a particular parameter for a particular path. The input should be valid json in the format `{{\"path\": path, \"parameter_name\": parameter_name}}` where \"path\" is a path available to this API spec and \"parameter_name\" is a parameter available for this path.'\n", + " ),\n", + " \n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 170, + "id": "0f79d245", + "metadata": {}, + "outputs": [], + "source": [ + "prefix = \"\"\"You are an agent designed to interact with a particular API.\n", + "Your goal is to return a final answer of a particular URL with parameters that can be called to answer a particular question.\n", + "You have access to the following tools which help you learn more about the API you are interacting with.\n", + "Only use the below tools. Only use the information returned by the below tools to construct your final answer.\"\"\"\n", + "suffix = \"\"\"Begin!\"\n", + "\n", + "Question: {input}\n", + "{agent_scratchpad}\"\"\"\n", + "\n", + "prompt = ZeroShotAgent.create_prompt(\n", + " tools, \n", + " prefix=prefix, \n", + " suffix=suffix, \n", + " input_variables=[\"input\", \"agent_scratchpad\"]\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 171, + "id": "015fa4c4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "You are an agent designed to interact with a particular API.\n", + "Your goal is to return a final answer of a particular URL with parameters that can be called to answer a particular question.\n", + "You have access to the following tools which help you learn more about the API you are interacting with.\n", + "Only use the below tools. Only use the information returned by the below tools to construct your final answer.\n", + "\n", + "List Paths: Can be used to list all available paths for this API spec. Input should be an empty string (it's not used).\n", + "Get Params: Get parameters for a given path. The input should be exactly ones of the paths available to this API spec, including any parameter placeholders.\n", + "Get Param Spec: Get specification for a particular parameter for a particular path. The input should be valid json in the format `{{\"path\": path, \"parameter_name\": parameter_name}}` where \"path\" is a path available to this API spec and \"parameter_name\" is a parameter available for this path.\n", + "\n", + "Use the following format:\n", + "\n", + "Question: the input question you must answer\n", + "Thought: you should always think about what to do\n", + "Action: the action to take, should be one of [List Paths, Get Params, Get Param Spec]\n", + "Action Input: the input to the action\n", + "Observation: the result of the action\n", + "... (this Thought/Action/Action Input/Observation can repeat N times)\n", + "Thought: I now know the final answer\n", + "Final Answer: the final answer to the original input question\n", + "\n", + "Begin!\"\n", + "\n", + "Question: {input}\n", + "{agent_scratchpad}\n" + ] + } + ], + "source": [ + "print(prompt.template)" + ] + }, + { + "cell_type": "code", + "execution_count": 172, + "id": "0ccca808", + "metadata": {}, + "outputs": [], + "source": [ + "llm_chain = LLMChain(llm=OpenAI(temperature=0), prompt=prompt)" + ] + }, + { + "cell_type": "code", + "execution_count": 173, + "id": "a386fb24", + "metadata": {}, + "outputs": [], + "source": [ + "tool_names = [tool.name for tool in tools]\n", + "agent = ZeroShotAgent(llm_chain=llm_chain, allowed_tools=tool_names)" + ] + }, + { + "cell_type": "code", + "execution_count": 174, + "id": "f8a0bbcd", + "metadata": {}, + "outputs": [], + "source": [ + "agent_executor = AgentExecutor.from_agent_and_tools(agent=agent, tools=tools, verbose=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 175, + "id": "7cd5ae88", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n", + "\u001b[32;1m\u001b[1;3mThought: I need to find out what parameters I need to call the API\n", + "Action: List Paths\n", + "Action Input: \"\"\u001b[0m\n", + "Observation: \u001b[36;1m\u001b[1;3mName: /v1/fish/{fishID}\n", + "Description: Get fish data in JSON format. \n", + "\n", + "The {fishID} parameter is optional and can be removed to get all the fish data.\n", + "\n", + "Name: /v1/sea/{seaID}\n", + "Description: Get sea creature data in JSON format. \n", + "\n", + "The {seaID} parameter is optional and can be removed to get all the sea creature data.\n", + "\n", + "Name: /v1/bugs/{bugID}\n", + "Description: Get bugs data in JSON format. \n", + "\n", + "The {bugID} parameter is optional and can be removed to get all the bugs data.\n", + "\n", + "Name: /v1/fossils/{fossilName}\n", + "Description: Get fossil data in JSON format. \n", + "\n", + "The {fossilName} parameter is optional and can be removed to get all the fossils data.\n", + "\n", + "Name: /v1/villagers/{villagerID}\n", + "Description: Get villager data in JSON format. \n", + "\n", + "The {villagerID} parameter is optional and can be removed to get all the villagers data.\n", + "\n", + "Name: /v1/icons/fish/{fishID}\n", + "Description: Get fish icons in PNG format. \n", + "\n", + "The {fishID} parameter can be found using the /v1/fish/ endpoint.\n", + "\n", + "Name: /v1/icons/bugs/{bugID}\n", + "Description: Get bugs icons in PNG format. \n", + "\n", + "The {bugID} parameter can be found using the /v1/bugs/ endpoint.\n", + "\n", + "Name: /v1/icons/villagers/{villagerID}\n", + "Description: Get villager icons in PNG format. \n", + "\n", + "The {villagerID} parameter can be found using the /v1/villagers/ endpoint.\n", + "\n", + "Name: /v1/images/fish/{fishID}\n", + "Description: Get fish images in PNG format. \n", + "\n", + "The {fishID} parameter can be found using the /v1/fish/ endpoint.\n", + "\n", + "Name: /v1/images/bugs/{bugID}\n", + "Description: Get bugs images in PNG format. \n", + "\n", + "The {bugID} parameter can be found using the /v1/bugs/ endpoint.\n", + "\n", + "Name: /v1/images/villagers/{villagerID}\n", + "Description: Get villager images in PNG format. \n", + "\n", + "The {villagerID} parameter can be found using the /v1/villagers/ endpoint.\n", + "\n", + "Name: /v1/images/fossils/{fossilName}\n", + "Description: Get fossil images in PNG format. \n", + "\n", + "The {fossilName} parameter can be found using the /v1/fossils/ endpoint.\n", + "\n", + "Name: /v1/songs/{songID}\n", + "Description: Get K.K. songs data in JSON format. \n", + "\n", + "The {songID} parameter is optional and can be removed to get all the songs data.\n", + "\n", + "Name: /v1/images/songs/{songID}\n", + "Description: Get song cover images in PNG format. \n", + "\n", + "The {songID} parameter can be found using the /v1/songs/ endpoint.\n", + "\n", + "Name: /v1/music/{songID}\n", + "Description: Get K.K. songs data in MP3 format. \n", + "\n", + "The {songID} parameter can be found using the /songs/ endpoint.\n", + "\n", + "Name: /v1/art/{artID}\n", + "Description: Get art data in JSON format. \n", + "\n", + "The {artID} parameter is optional and can be removed to get all the art data.\n", + "\n", + "Name: /v1/icons/art/{artID}\n", + "Description: Get art icons in PNG format. \n", + "\n", + "The {artID} parameter can be found using the /art/ endpoint.\n", + "\n", + "Name: /v1/hourly/{songID}\n", + "Description: Get hourly songs data in MP3 format. \n", + "\n", + "The {songID} parameter can be found using the /backgroundmusic/ endpoint.\n", + "\n", + "Name: /v1/backgroundmusic/{songID}\n", + "Description: Get hourly songs data in JSON format. \n", + "\n", + "The {songID} parameter is optional and can be removed to get all the songs data.\n", + "\n", + "Name: /v1/houseware/{housewareID}\n", + "Description: Get houseware data in JSON format. \n", + "\n", + "The {housewareID} parameter is optional and can be removed to get all the housewareID data.\n", + "\n", + "Name: /v1/wallmounted/{wallmountedID}\n", + "\n", + "Name: /v1/misc/{miscID}\n", + "Description: see /v1/houseware endpoint.\n", + "\n", + "Name: /v1/images/funiture/{furnitureFileName}\n", + "Description: Get furniture images in PNG format. \n", + "\n", + "The {furnitureFileName} parameter can be found using the file-name key in an houseware/wallmounted/misc variant object (eg: FtrJewelrystand_Remake_0_0).\u001b[0m\n", + "Thought:\u001b[32;1m\u001b[1;3m I need to find out what parameters I need to call the /v1/fish/ endpoint\n", + "Action: Get Params\n", + "Action Input: /v1/fish/\u001b[0m" + ] + }, + { + "ename": "KeyError", + "evalue": "'/v1/fish/'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[175], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43magent_executor\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mHow rare is a barracuda?\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/workplace/langchain/langchain/chains/base.py:226\u001b[0m, in \u001b[0;36mChain.run\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 224\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(args) \u001b[38;5;241m!=\u001b[39m \u001b[38;5;241m1\u001b[39m:\n\u001b[1;32m 225\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m`run` supports only one positional argument.\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m--> 226\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43margs\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m[\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moutput_keys[\u001b[38;5;241m0\u001b[39m]]\n\u001b[1;32m 228\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m kwargs \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m args:\n\u001b[1;32m 229\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m(kwargs)[\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moutput_keys[\u001b[38;5;241m0\u001b[39m]]\n", + "File \u001b[0;32m~/workplace/langchain/langchain/chains/base.py:142\u001b[0m, in \u001b[0;36mChain.__call__\u001b[0;34m(self, inputs, return_only_outputs)\u001b[0m\n\u001b[1;32m 140\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (\u001b[38;5;167;01mKeyboardInterrupt\u001b[39;00m, \u001b[38;5;167;01mException\u001b[39;00m) \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 141\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcallback_manager\u001b[38;5;241m.\u001b[39mon_chain_error(e, verbose\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mverbose)\n\u001b[0;32m--> 142\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m e\n\u001b[1;32m 143\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcallback_manager\u001b[38;5;241m.\u001b[39mon_chain_end(outputs, verbose\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mverbose)\n\u001b[1;32m 144\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mprep_outputs(inputs, outputs, return_only_outputs)\n", + "File \u001b[0;32m~/workplace/langchain/langchain/chains/base.py:139\u001b[0m, in \u001b[0;36mChain.__call__\u001b[0;34m(self, inputs, return_only_outputs)\u001b[0m\n\u001b[1;32m 133\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcallback_manager\u001b[38;5;241m.\u001b[39mon_chain_start(\n\u001b[1;32m 134\u001b[0m {\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mname\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__class__\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__name__\u001b[39m},\n\u001b[1;32m 135\u001b[0m inputs,\n\u001b[1;32m 136\u001b[0m verbose\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mverbose,\n\u001b[1;32m 137\u001b[0m )\n\u001b[1;32m 138\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 139\u001b[0m outputs \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_call\u001b[49m\u001b[43m(\u001b[49m\u001b[43minputs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 140\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (\u001b[38;5;167;01mKeyboardInterrupt\u001b[39;00m, \u001b[38;5;167;01mException\u001b[39;00m) \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 141\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcallback_manager\u001b[38;5;241m.\u001b[39mon_chain_error(e, verbose\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mverbose)\n", + "File \u001b[0;32m~/workplace/langchain/langchain/agents/agent.py:423\u001b[0m, in \u001b[0;36mAgentExecutor._call\u001b[0;34m(self, inputs)\u001b[0m\n\u001b[1;32m 421\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (\u001b[38;5;167;01mKeyboardInterrupt\u001b[39;00m, \u001b[38;5;167;01mException\u001b[39;00m) \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 422\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcallback_manager\u001b[38;5;241m.\u001b[39mon_tool_error(e, verbose\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mverbose)\n\u001b[0;32m--> 423\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m e\n\u001b[1;32m 424\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 425\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcallback_manager\u001b[38;5;241m.\u001b[39mon_tool_start(\n\u001b[1;32m 426\u001b[0m {\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mname\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mN/A\u001b[39m\u001b[38;5;124m\"\u001b[39m}, output, color\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mgreen\u001b[39m\u001b[38;5;124m\"\u001b[39m, verbose\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mverbose\n\u001b[1;32m 427\u001b[0m )\n", + "File \u001b[0;32m~/workplace/langchain/langchain/agents/agent.py:418\u001b[0m, in \u001b[0;36mAgentExecutor._call\u001b[0;34m(self, inputs)\u001b[0m\n\u001b[1;32m 410\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcallback_manager\u001b[38;5;241m.\u001b[39mon_tool_start(\n\u001b[1;32m 411\u001b[0m {\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mname\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;28mstr\u001b[39m(tool\u001b[38;5;241m.\u001b[39mfunc)[:\u001b[38;5;241m60\u001b[39m] \u001b[38;5;241m+\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m...\u001b[39m\u001b[38;5;124m\"\u001b[39m},\n\u001b[1;32m 412\u001b[0m output,\n\u001b[1;32m 413\u001b[0m color\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mgreen\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m 414\u001b[0m verbose\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mverbose,\n\u001b[1;32m 415\u001b[0m )\n\u001b[1;32m 416\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 417\u001b[0m \u001b[38;5;66;03m# We then call the tool on the tool input to get an observation\u001b[39;00m\n\u001b[0;32m--> 418\u001b[0m observation \u001b[38;5;241m=\u001b[39m \u001b[43mtool\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfunc\u001b[49m\u001b[43m(\u001b[49m\u001b[43moutput\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtool_input\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 419\u001b[0m color \u001b[38;5;241m=\u001b[39m color_mapping[output\u001b[38;5;241m.\u001b[39mtool]\n\u001b[1;32m 420\u001b[0m return_direct \u001b[38;5;241m=\u001b[39m tool\u001b[38;5;241m.\u001b[39mreturn_direct\n", + "Cell \u001b[0;32mIn[150], line 28\u001b[0m, in \u001b[0;36mOpenAPISpec.get_parameters\u001b[0;34m(self, path)\u001b[0m\n\u001b[1;32m 27\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mget_parameters\u001b[39m(\u001b[38;5;28mself\u001b[39m, path: \u001b[38;5;28mstr\u001b[39m):\n\u001b[0;32m---> 28\u001b[0m params \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mspec_dict\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mpaths\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m[\u001b[49m\u001b[43mpath\u001b[49m\u001b[43m]\u001b[49m[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mget\u001b[39m\u001b[38;5;124m'\u001b[39m][\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mparameters\u001b[39m\u001b[38;5;124m'\u001b[39m]\n\u001b[1;32m 29\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m, \u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;241m.\u001b[39mjoin([p[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mname\u001b[39m\u001b[38;5;124m'\u001b[39m] \u001b[38;5;28;01mfor\u001b[39;00m p \u001b[38;5;129;01min\u001b[39;00m params])\n", + "\u001b[0;31mKeyError\u001b[0m: '/v1/fish/'" + ] + } + ], + "source": [ + "agent_executor.run(\"How rare is a barracuda?\")" + ] + }, + { + "cell_type": "code", + "execution_count": 149, + "id": "f7711b2e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "> \u001b[0;32m/var/folders/bm/ylzhm36n075cslb9fvvbgq640000gn/T/ipykernel_405/293112481.py\u001b[0m(18)\u001b[0;36mget_paths\u001b[0;34m()\u001b[0m\n", + "\u001b[0;32m 16 \u001b[0;31m \u001b[0mpaths\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m 17 \u001b[0;31m \u001b[0;32mfor\u001b[0m \u001b[0mp\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mspec_dict\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'paths'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m---> 18 \u001b[0;31m \u001b[0m_str\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34mf\"Name: {p}\\nDescription: {v['get']['description']}\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m 19 \u001b[0;31m \u001b[0mpaths\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0m_str\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m 20 \u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0;34m\"\\n\\n\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpaths\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\n", + "ipdb> v\n", + "{'parameters': [{'schema': {'type': 'string'}, 'name': 'wallmountedID', 'in': 'path', 'required': True}], 'get': {'summary': 'Wallmounted', 'tags': ['Items'], 'responses': {'200': {'description': 'OK'}, '404': {'description': 'Not Found'}}}}\n", + "ipdb> p\n", + "*** SyntaxError: unexpected EOF while parsing\n", + "ipdb> u\n", + "> \u001b[0;32m/Users/harrisonchase/workplace/langchain/langchain/agents/agent.py\u001b[0m(418)\u001b[0;36m_call\u001b[0;34m()\u001b[0m\n", + "\u001b[0;32m 416 \u001b[0;31m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m 417 \u001b[0;31m \u001b[0;31m# We then call the tool on the tool input to get an observation\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m--> 418 \u001b[0;31m \u001b[0mobservation\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtool\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0moutput\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtool_input\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m 419 \u001b[0;31m \u001b[0mcolor\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcolor_mapping\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0moutput\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtool\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m 420 \u001b[0;31m \u001b[0mreturn_direct\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtool\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreturn_direct\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\n", + "ipdb> d\n", + "> \u001b[0;32m/var/folders/bm/ylzhm36n075cslb9fvvbgq640000gn/T/ipykernel_405/293112481.py\u001b[0m(18)\u001b[0;36mget_paths\u001b[0;34m()\u001b[0m\n", + "\u001b[0;32m 16 \u001b[0;31m \u001b[0mpaths\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m 17 \u001b[0;31m \u001b[0;32mfor\u001b[0m \u001b[0mp\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mspec_dict\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'paths'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m---> 18 \u001b[0;31m \u001b[0m_str\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34mf\"Name: {p}\\nDescription: {v['get']['description']}\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m 19 \u001b[0;31m \u001b[0mpaths\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0m_str\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m 20 \u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0;34m\"\\n\\n\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpaths\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\n", + "ipdb> v\n", + "{'parameters': [{'schema': {'type': 'string'}, 'name': 'wallmountedID', 'in': 'path', 'required': True}], 'get': {'summary': 'Wallmounted', 'tags': ['Items'], 'responses': {'200': {'description': 'OK'}, '404': {'description': 'Not Found'}}}}\n", + "ipdb> q\n" + ] + } + ], + "source": [ + "%debug" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "id": "143bfc22", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Name: /v1/forecast\n", + "Description: 7 day weather variables in hourly and daily resolution for given WGS84 latitude and longitude coordinates. Available worldwide.\n" + ] + } + ], + "source": [ + "print(spec.get_paths())" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "id": "da20365b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'hourly, daily, latitude, longitude, current_weather, temperature_unit, windspeed_unit, timeformat, timezone, past_days'" + ] + }, + "execution_count": 63, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spec.get_parameters(\"/v1/forecast\")" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "id": "9004a42d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "\"{'name': 'current_weather', 'in': 'query', 'schema': {'type': 'boolean'}}\"" + ] + }, + "execution_count": 64, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spec.get_param_spec(\"/v1/forecast, current_weather\")" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "id": "decfc26e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'name': 'windspeed_unit',\n", + " 'in': 'query',\n", + " 'schema': {'type': 'string',\n", + " 'default': 'kmh',\n", + " 'enum': ['kmh', 'ms', 'mph', 'kn']}}" + ] + }, + "execution_count": 47, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spec_dict['paths']['/v1/forecast']['get']['parameters'][6]" + ] + }, + { + "cell_type": "code", + "execution_count": 229, + "id": "9465dc65", + "metadata": {}, + "outputs": [], + "source": [ + "import re\n", + "def parse_items(text):\n", + " _res = re.findall(r'\\[.*?\\]', text)\n", + " res = []\n", + " for r in _res:\n", + " val = r[1:-1]\n", + " if val[0] != '\"':\n", + " val = int(val)\n", + " else:\n", + " val = val[1:-1]\n", + " res.append(val)\n", + " return res" + ] + }, + { + "cell_type": "code", + "execution_count": 300, + "id": "61824d1f", + "metadata": {}, + "outputs": [], + "source": [ + "class JsonObj:\n", + " \n", + " def __init__(self, _dict: dict):\n", + " self.dict = _dict\n", + " \n", + " def keys(self, text: str):\n", + " try:\n", + " items = parse_items(text)\n", + " val = self.dict\n", + " for i in items:\n", + " val = val[i]\n", + " return str(val.keys())\n", + " except Exception as e:\n", + " return repr(e)\n", + " \n", + " def value(self, text: str):\n", + " try:\n", + " items = parse_items(text)\n", + " val = self.dict\n", + " for i in items:\n", + " val = val[i]\n", + " \n", + " if isinstance(val, dict) and len(str(val)) > 200:\n", + " return \"Value is a large dictionary, should explore its keys directly\"\n", + " val = str(val)\n", + " if len(val) > 200:\n", + " val = val[:200] + \"...\"\n", + " return val\n", + " except Exception as e:\n", + " return repr(e)" + ] + }, + { + "cell_type": "code", + "execution_count": 301, + "id": "568b272b", + "metadata": {}, + "outputs": [], + "source": [ + "obj = JsonObj(spec)" + ] + }, + { + "cell_type": "code", + "execution_count": 302, + "id": "5c35a46c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Value is a large dictionary, should explore its keys directly'" + ] + }, + "execution_count": 302, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "obj.value('data')" + ] + }, + { + "cell_type": "code", + "execution_count": 303, + "id": "cccba9f5", + "metadata": {}, + "outputs": [], + "source": [ + "tools = [\n", + " Tool(\n", + " name = \"List Keys\",\n", + " func=obj.keys,\n", + " description=\"Can be used to list all keys. Before calling this you should be SURE that the path to this exists.\"\n", + " ),\n", + " Tool(\n", + " name = \"See Value\",\n", + " func=obj.value,\n", + " description=\"Can be used to see stringified value. Before calling this you should be SURE that the path to this exists.\"\n", + " ),\n", + " \n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b4dec43f", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 304, + "id": "21074ceb", + "metadata": {}, + "outputs": [], + "source": [ + "prefix = \"\"\"You are an agent designed to interact with JSON.\n", + "Your goal is to return a final answer by interacting with the JSON.\n", + "You have access to the following tools which help you learn more about the JSON you are interacting with.\n", + "Only use the below tools. Only use the information returned by the below tools to construct your final answer.\n", + "Your input to the tools should be in the form of `data[\"key\"][0]` where `data` is the JSON blob you are interacting with, and the syntax used is Python. \n", + "You should only use keys that you know for a fact exist. You must validate that a key exists by seeing it previously when calling `List Keys`. If you have not seen a key in one of those responses, you cannot use it.\"\"\"\n", + "suffix = \"\"\"Begin!\"\n", + "\n", + "Question: {input}\n", + "Thought: I should look at the keys that exist in data to see what I have access to\n", + "{agent_scratchpad}\"\"\"\n", + "\n", + "prompt = ZeroShotAgent.create_prompt(\n", + " tools, \n", + " prefix=prefix, \n", + " suffix=suffix, \n", + " input_variables=[\"input\", \"agent_scratchpad\"]\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 305, + "id": "588cf1dc", + "metadata": {}, + "outputs": [], + "source": [ + "llm_chain = LLMChain(llm=OpenAI(temperature=0), prompt=prompt)" + ] + }, + { + "cell_type": "code", + "execution_count": 306, + "id": "c9e17aca", + "metadata": {}, + "outputs": [], + "source": [ + "tool_names = [tool.name for tool in tools]\n", + "agent = ZeroShotAgent(llm_chain=llm_chain, allowed_tools=tool_names)" + ] + }, + { + "cell_type": "code", + "execution_count": 307, + "id": "8a0df4de", + "metadata": {}, + "outputs": [], + "source": [ + "agent_executor = AgentExecutor.from_agent_and_tools(agent=agent, tools=tools, verbose=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 309, + "id": "320b79ef", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n", + "\u001b[32;1m\u001b[1;3mAction: List Keys\n", + "Action Input: data\u001b[0m\n", + "Observation: \u001b[36;1m\u001b[1;3mdict_keys(['openapi', 'info', 'servers', 'paths', 'components', 'security'])\u001b[0m\n", + "Thought:\u001b[32;1m\u001b[1;3m I should look at the paths key to see what endpoints exist\n", + "Action: List Keys\n", + "Action Input: data[\"paths\"]\u001b[0m\n", + "Observation: \u001b[36;1m\u001b[1;3mdict_keys(['/v1/fish/{fishID}', '/v1/sea/{seaID}', '/v1/bugs/{bugID}', '/v1/fossils/{fossilName}', '/v1/villagers/{villagerID}', '/v1/icons/fish/{fishID}', '/v1/icons/bugs/{bugID}', '/v1/icons/villagers/{villagerID}', '/v1/images/fish/{fishID}', '/v1/images/bugs/{bugID}', '/v1/images/villagers/{villagerID}', '/v1/images/fossils/{fossilName}', '/v1/songs/{songID}', '/v1/images/songs/{songID}', '/v1/music/{songID}', '/v1/art/{artID}', '/v1/icons/art/{artID}', '/v1/hourly/{songID}', '/v1/backgroundmusic/{songID}', '/v1/houseware/{housewareID}', '/v1/wallmounted/{wallmountedID}', '/v1/misc/{miscID}', '/v1/images/funiture/{furnitureFileName}'])\u001b[0m\n", + "Thought:\u001b[32;1m\u001b[1;3m I should look at the /v1/bugs/{bugID} endpoint to see what it does\n", + "Action: See Value\n", + "Action Input: data[\"paths\"][\"/v1/bugs/{bugID}\"]\u001b[0m\n", + "Observation: \u001b[33;1m\u001b[1;3mValue is a large dictionary, should explore its keys directly\u001b[0m\n", + "Thought:\u001b[32;1m\u001b[1;3m I should look at the get key to see what it does\n", + "Action: List Keys\n", + "Action Input: data[\"paths\"][\"/v1/bugs/{bugID}\"][\"get\"]\u001b[0m\n", + "Observation: \u001b[36;1m\u001b[1;3mdict_keys(['summary', 'responses', 'operationId', 'description', 'tags'])\u001b[0m\n", + "Thought:\u001b[32;1m\u001b[1;3m I should look at the description key to see what it does\n", + "Action: See Value\n", + "Action Input: data[\"paths\"][\"/v1/bugs/{bugID}\"][\"get\"][\"description\"]\u001b[0m\n", + "Observation: \u001b[33;1m\u001b[1;3mGet bugs data in JSON format. \n", + "\n", + "The {bugID} parameter is optional and can be removed to get all the bugs data.\u001b[0m\n", + "Thought:\u001b[32;1m\u001b[1;3m I now know the final answer\n", + "Final Answer: The /v1/bugs/{bugID} endpoint returns all the bugs data in JSON format. The {bugID} parameter is optional and can be removed to get all the bugs data.\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "'The /v1/bugs/{bugID} endpoint returns all the bugs data in JSON format. The {bugID} parameter is optional and can be removed to get all the bugs data.'" + ] + }, + "execution_count": 309, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "agent_executor.run(\"what does the bugs endpoint do?\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fcf7bc35", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9f1ce55f", + "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.9.1" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}