llama-index-tools-openapi 0.0.1__py3-none-any.whl
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,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,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,5 @@
|
|
|
1
|
+
llama_index/tools/openapi/__init__.py,sha256=fh3NOSZQz1J1lr1R0XBAu_bxFkAS2bUcnOXlQJIw3D4,113
|
|
2
|
+
llama_index/tools/openapi/base.py,sha256=QSBwHnWtVlNmjS4Hq4u49_pnECncBoH_RygzJRVQK44,4200
|
|
3
|
+
llama_index_tools_openapi-0.0.1.dist-info/METADATA,sha256=q72LumcqUDtPtgLKPUlMQOPTsuAAT_fSSv4eZYKZtdg,1922
|
|
4
|
+
llama_index_tools_openapi-0.0.1.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
|
5
|
+
llama_index_tools_openapi-0.0.1.dist-info/RECORD,,
|