llama-index-tools-openapi 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,52 @@
1
+ Metadata-Version: 2.1
2
+ Name: llama-index-tools-openapi
3
+ Version: 0.0.1
4
+ Summary: llama-index tools openapi integration
5
+ License: MIT
6
+ Author: Your Name
7
+ Author-email: you@example.com
8
+ Requires-Python: >=3.8.1,<3.12
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.9
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Requires-Dist: llama-index-core (>=0.9.32,<0.10.0)
15
+ Description-Content-Type: text/markdown
16
+
17
+ # OpenAPI Tool
18
+
19
+ This tool loads an OpenAPI spec and allow the Agent to retrieve endpoints and details about endpoints. The RequestsToolSpec can also be laoded into the agent to allow the agent to hit the nessecary endpoints with a REST request.
20
+
21
+ ## Usage
22
+
23
+ This tool has more extensive example usage documented in a Jupyter notebook [here](https://github.com/emptycrown/llama-hub/tree/main/llama_hub/tools/notebooks/openapi_and_requests.ipynb)
24
+
25
+ Here's an example usage of the OpenAPIToolSpec.
26
+
27
+ ```python
28
+ from llama_hub.tools.openapi import OpenAPIToolSpec
29
+ from llama_index.agent import OpenAIAgent
30
+
31
+ f = requests.get(
32
+ "https://raw.githubusercontent.com/APIs-guru/openapi-directory/main/APIs/openai.com/1.2.0/openapi.yaml"
33
+ ).text
34
+ open_api_spec = yaml.safe_load(f)
35
+ # OR
36
+ open_spec = OpenAPIToolSpec(
37
+ url="https://raw.githubusercontent.com/APIs-guru/openapi-directory/main/APIs/openai.com/1.2.0/openapi.yaml"
38
+ )
39
+
40
+
41
+ tool_spec = OpenAPIToolSpec(open_api_spec)
42
+
43
+ agent = OpenAIAgent.from_tools(tool_spec.to_tool_list())
44
+
45
+ agent.chat("What is the base url for the API")
46
+ agent.chat("What parameters does the x endpoint need?")
47
+ ```
48
+
49
+ `load_openapi_spec`: Returns the parsed OpenAPI spec that the class was initialized with
50
+
51
+ This loader is designed to be used as a way to load data as a Tool in a Agent. See [here](https://github.com/emptycrown/llama-hub/tree/main) for examples.
52
+
@@ -0,0 +1,35 @@
1
+ # OpenAPI Tool
2
+
3
+ This tool loads an OpenAPI spec and allow the Agent to retrieve endpoints and details about endpoints. The RequestsToolSpec can also be laoded into the agent to allow the agent to hit the nessecary endpoints with a REST request.
4
+
5
+ ## Usage
6
+
7
+ This tool has more extensive example usage documented in a Jupyter notebook [here](https://github.com/emptycrown/llama-hub/tree/main/llama_hub/tools/notebooks/openapi_and_requests.ipynb)
8
+
9
+ Here's an example usage of the OpenAPIToolSpec.
10
+
11
+ ```python
12
+ from llama_hub.tools.openapi import OpenAPIToolSpec
13
+ from llama_index.agent import OpenAIAgent
14
+
15
+ f = requests.get(
16
+ "https://raw.githubusercontent.com/APIs-guru/openapi-directory/main/APIs/openai.com/1.2.0/openapi.yaml"
17
+ ).text
18
+ open_api_spec = yaml.safe_load(f)
19
+ # OR
20
+ open_spec = OpenAPIToolSpec(
21
+ url="https://raw.githubusercontent.com/APIs-guru/openapi-directory/main/APIs/openai.com/1.2.0/openapi.yaml"
22
+ )
23
+
24
+
25
+ tool_spec = OpenAPIToolSpec(open_api_spec)
26
+
27
+ agent = OpenAIAgent.from_tools(tool_spec.to_tool_list())
28
+
29
+ agent.chat("What is the base url for the API")
30
+ agent.chat("What parameters does the x endpoint need?")
31
+ ```
32
+
33
+ `load_openapi_spec`: Returns the parsed OpenAPI spec that the class was initialized with
34
+
35
+ This loader is designed to be used as a way to load data as a Tool in a Agent. See [here](https://github.com/emptycrown/llama-hub/tree/main) for examples.
@@ -0,0 +1,6 @@
1
+ # __init__.py
2
+ from llama_index.tools.openapi.base import (
3
+ OpenAPIToolSpec,
4
+ )
5
+
6
+ __all__ = ["OpenAPIToolSpec"]
@@ -0,0 +1,117 @@
1
+ """OpenAPI Tool."""
2
+
3
+ from typing import List, Optional
4
+
5
+ import requests
6
+
7
+ from llama_index.core.schema import Document
8
+ from llama_index.core.tools.tool_spec.base import BaseToolSpec
9
+
10
+
11
+ class OpenAPIToolSpec(BaseToolSpec):
12
+ """OpenAPI Tool
13
+
14
+ This tool can be used to parse an OpenAPI spec for endpoints and operations
15
+ Use the RequestsToolSpec to automate requests to the openapi server
16
+ """
17
+
18
+ spec_functions = ["load_openapi_spec"]
19
+
20
+ def __init__(self, spec: Optional[dict] = None, url: Optional[str] = None):
21
+ import yaml
22
+
23
+ if spec and url:
24
+ raise ValueError("Only provide one of OpenAPI dict or url")
25
+ elif spec:
26
+ pass
27
+ elif url:
28
+ response = requests.get(url).text
29
+ spec = yaml.safe_load(response)
30
+ else:
31
+ raise ValueError("You must provide a url or OpenAPI spec as a dict")
32
+
33
+ parsed_spec = self.process_api_spec(spec)
34
+ self.spec = Document(text=str(parsed_spec))
35
+
36
+ def load_openapi_spec(self) -> List[Document]:
37
+ """
38
+ You are an AI agent specifically designed to retrieve information by making web requests to an API based on an OpenAPI specification.
39
+
40
+ Here's a step-by-step guide to assist you in answering questions:
41
+
42
+ 1. Determine the base URL required for making the request
43
+
44
+ 2. Identify the relevant paths necessary to address the question
45
+
46
+ 3. Find the required parameters for making the request
47
+
48
+ 4. Perform the necessary requests to obtain the answer
49
+
50
+ Returns:
51
+ Document: A List of Document objects.
52
+ """
53
+ return [self.spec]
54
+
55
+ def process_api_spec(self, spec: dict) -> dict:
56
+ """Perform simplification and reduction on an OpenAPI specification.
57
+
58
+ The goal is to create a more concise and efficient representation
59
+ for retrieval purposes.
60
+ """
61
+
62
+ def reduce_details(details: dict) -> dict:
63
+ reduced = {}
64
+ if details.get("description"):
65
+ reduced["description"] = details.get("description")
66
+ if details.get("parameters"):
67
+ reduced["parameters"] = [
68
+ param
69
+ for param in details.get("parameters", [])
70
+ if param.get("required")
71
+ ]
72
+ if "200" in details["responses"]:
73
+ reduced["responses"] = details["responses"]["200"]
74
+ return reduced
75
+
76
+ def dereference_openapi(openapi_doc):
77
+ """Dereferences a Swagger/OpenAPI document by resolving all $ref pointers."""
78
+ try:
79
+ import jsonschema
80
+ except ImportError:
81
+ raise ImportError(
82
+ "The jsonschema library is required to parse OpenAPI documents. "
83
+ "Please install it with `pip install jsonschema`."
84
+ )
85
+
86
+ resolver = jsonschema.RefResolver.from_schema(openapi_doc)
87
+
88
+ def _dereference(obj):
89
+ if isinstance(obj, dict):
90
+ if "$ref" in obj:
91
+ with resolver.resolving(obj["$ref"]) as resolved:
92
+ return _dereference(resolved)
93
+ return {k: _dereference(v) for k, v in obj.items()}
94
+ elif isinstance(obj, list):
95
+ return [_dereference(item) for item in obj]
96
+ else:
97
+ return obj
98
+
99
+ dereferenced_doc = _dereference(openapi_doc)
100
+ return dereferenced_doc
101
+
102
+ spec = dereference_openapi(spec)
103
+ endpoints = []
104
+ for route, operations in spec["paths"].items():
105
+ for operation, details in operations.items():
106
+ if operation in ["get", "post", "patch"]:
107
+ endpoint_name = f"{operation.upper()} {route}"
108
+ description = details.get("description")
109
+ endpoints.append(
110
+ (endpoint_name, description, reduce_details(details))
111
+ )
112
+
113
+ return {
114
+ "servers": spec["servers"],
115
+ "description": spec["info"].get("description"),
116
+ "endpoints": endpoints,
117
+ }
@@ -0,0 +1,49 @@
1
+ [build-system]
2
+ requires = ["poetry-core"]
3
+ build-backend = "poetry.core.masonry.api"
4
+
5
+ [tool.codespell]
6
+ check-filenames = true
7
+ check-hidden = true
8
+ # Feel free to un-skip examples, and experimental, you will just need to
9
+ # work through many typos (--write-changes and --interactive will help)
10
+ skip = "*.csv,*.html,*.json,*.jsonl,*.pdf,*.txt,*.ipynb"
11
+
12
+ [tool.mypy]
13
+ disallow_untyped_defs = true
14
+ # Remove venv skip when integrated with pre-commit
15
+ exclude = ["_static", "build", "examples", "notebooks", "venv"]
16
+ ignore_missing_imports = true
17
+ python_version = "3.8"
18
+
19
+ [tool.poetry]
20
+ name = "llama-index-tools-openapi"
21
+ version = "0.0.1"
22
+ description = "llama-index tools openapi integration"
23
+ authors = ["Your Name <you@example.com>"]
24
+ license = "MIT"
25
+ readme = "README.md"
26
+ packages = [{include = "llama_index/"}]
27
+
28
+ [tool.poetry.dependencies]
29
+ python = ">=3.8.1,<3.12"
30
+ llama-index-core = "^0.9.32"
31
+
32
+ [tool.poetry.group.dev.dependencies]
33
+ black = {extras = ["jupyter"], version = "<=23.9.1,>=23.7.0"}
34
+ codespell = {extras = ["toml"], version = ">=v2.2.6"}
35
+ ipython = "8.10.0"
36
+ jupyter = "^1.0.0"
37
+ mypy = "0.991"
38
+ pre-commit = "3.2.0"
39
+ pylint = "2.15.10"
40
+ pytest = "7.2.1"
41
+ pytest-mock = "3.11.1"
42
+ ruff = "0.0.292"
43
+ tree-sitter-languages = "^1.8.0"
44
+ types-Deprecated = ">=0.1.0"
45
+ types-PyYAML = "^6.0.12.12"
46
+ types-protobuf = "^4.24.0.4"
47
+ types-redis = "4.5.5.0"
48
+ types-requests = "2.28.11.8" # TODO: unpin when mypy>0.991
49
+ types-setuptools = "67.1.0.0"