Got APIs? Wanna make it work with large language models?
Convert an OpenAPI spec to LangGraph tools 🪄
- LangChain is a framework for developing apps powered by large language models (LLMs).
- LangGraph, introduced by
LangChain
starting from v0.2, facilitates building Agent-based apps that leverage and extend an LLM to perform tasks outside of its traditional domain. The heart of an agent is Tool calls. - OpenAPI Specification (OAS) is a standard format for defining APIs, allowing both humans and machines to understand the capabilities of a service without accessing its source code, documentation, or network traffic.
Companies worldwide have invested billions 💰💰💰 into developing APIs. In the new AI era, a question begs, how to leverage the power of natural language processing to consume the APIs while minimizing costs and maximizing existing investments.
openapi2tools addresses the challenge by converting and encapsulating an OpenAPI specification JSON into a domain-specific LangGraph agent
, with each API represented as a tool
.
The full source code for the openapi2tools tool can be found at here.
It also can be installed with pip,
pip install openapi2tools
After installation, you run the tool in a command line to generate an agent source file from a OpenAPI JSON (example json)
openapi2tools <your_openapi_json_file> <output_python_file_name>
In the screen recoding below, a user talked to a chatbot using natural language. (The left side of the screen is the output of the mock service.)
The MockServer folder implements a REST API based service and provides an OpenAPI JSON (openapi.json). openapi2tools is supposed to run against the openapi.json
to generate a fully encapsulated Agent (moviesApi.py).
The Chatbot folder contains an example implementation of a Chatbot (movies.py). It then utilizes the Agent
generated above to call (a.k.a. Tool calls
) the Mockserver
, when a user chats with an OpenAI model.
- an engineered ChatPrompt
prompt = ChatPromptTemplate.from_messages([
('system',
'''
generate an overview from the `info.description`
forEach api in openapi.json:
generate a tool capability from `api.operationId` and `api.summary`
'''
),
('placeholder', '{messages}')
])
- a list of tools
# for each api in openapi.json,
# generate a tool in the following format,
'''
@tool
def `api.operationId` (`api.parameter list`) -> `api.response(HTTP 200)':
`api.summary` as tool description
response = requests call with `api.method` (`api.path`, `api.query`, `api.requestBody`)
error handling from the listOf(`api.responses`)
...
tools = [
the api.operationId list
]
'''
- a class constructor to bind the prompt with an llm
def __init__(self, llm):
self.runnable = MoviesApi.prompt | llm.bind_tools(MoviesApi.tools)
- an invoker to process a tool call
def __call__(self, state, config: RunnableConfig):
...
result = self.runnable.invoke(state)
return {'messages': result}
- Support REST API only
- Supporting more authentication methods - currently only bearer token is implemented here.
- Not sure how to support a HTTP body with arrays or embedded objects - currently expect a flat body schema.
This is an ongoing project, your contributions are extremely appreciated. Please create a Pull Request. 🍻🍻