-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Tool openapi integration #151
base: main
Are you sure you want to change the base?
Conversation
Pull Request Test Coverage Report for Build 12434882747Details
💛 - Coveralls |
Before I add more tests @anakin87 please have a look to see if you like the general direction of this approach. I've designed it to require minimal plug-in point to our new |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, I like this lightweight approach (mostly due to the fact that we are moving the logic to an external library).
Before moving on, I'd like @julian-risch to take a look.
with LazyImport(message="Run 'pip install openapi-llm'") as openapi_llm_import: | ||
from openapi_llm.client.config import ClientConfig | ||
from openapi_llm.client.openapi import OpenAPIClient | ||
from openapi_llm.core.spec import OpenAPISpecification |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, I see that offloading most of the logic in Vladimir's library results for us in less maintenance effort (and I am happy about that).
Nevertheless, I see some risks. @julian-risch what's your take on this aspect?
@classmethod | ||
def from_openapi_spec(cls, spec: Union[str, Path], **kwargs: OpenAPIKwargs) -> List["Tool"]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Differently from @from_function
class method, this method returns a list of Tools.
Calling Tool.from_openapi_spec
and getting a list of Tools seems a bit confusing from a semantic point of view.
Maybe is it better to create a function (not a class method): something like create_tools_from_openapi_spec
.
WDYT? Do you have better ideas?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, good point. I also see a separatecreate_tools_from_openapi_spec
function as a viable alternative but let me see if there is even better approach.
@@ -237,3 +327,41 @@ def deserialize_tools_inplace(data: Dict[str, Any], key: str = "tools"): | |||
deserialized_tools.append(Tool.from_dict(tool)) | |||
|
|||
data[key] = deserialized_tools | |||
|
|||
|
|||
def _standardize_tool_definition(llm_specific_tool_def: Dict[str, Any]) -> Optional[Dict[str, Any]]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This utility function only ensures compatibility between Haystack and the new library. I don't expect to use it elsewhere in Haystack if we do things right.
Could it be moved to the library?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. I'll move it.
Refactored it @anakin87 @julian-risch |
:returns: Tool instance for the specified operation | ||
:raises ValueError: If the OpenAPI specification is invalid or cannot be loaded | ||
""" | ||
from haystack_experimental.tools.openapi import _create_tool_from_openapi_spec |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Circular dep between these two otherwise
Here is another idea to think about if we are to follow the Tool.from pattern. This method requires openapi spec and operation name and creates only one Tool just like other from methods. Just an idea.... |
Why:
Creates
Tool
instances from OpenAPI specifications, enabling the invocation of tools based on OpenAPI JSON or YAML formats.What:
from_openapi_spec
class method in theTool
class, enabling tool creation from OpenAPI specifications provided as URLs, file paths, or string content.OpenAPIKwargs
TypedDict to encapsulate configuration options for OpenAPI integration, including API credentials and allowed operations.OpenAPITool
How can it be used:
How did you test it:
from_openapi_spec
method's functionality and verify that tool attributes align with the OpenAPI definitions.Notes for the reviewer:
from_openapi_spec
method to ensure comprehensive handling of various input types (URLs, file paths, string content).