composio-langchain 0.1.40__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.
- composio_langchain-0.1.40/MANIFEST.in +0 -0
- composio_langchain-0.1.40/PKG-INFO +27 -0
- composio_langchain-0.1.40/README.md +5 -0
- composio_langchain-0.1.40/composio_langchain/__init__.py +2 -0
- composio_langchain-0.1.40/composio_langchain/composio_tool_spec.py +117 -0
- composio_langchain-0.1.40/composio_langchain/pydantic_utils.py +91 -0
- composio_langchain-0.1.40/composio_langchain.egg-info/PKG-INFO +27 -0
- composio_langchain-0.1.40/composio_langchain.egg-info/SOURCES.txt +12 -0
- composio_langchain-0.1.40/composio_langchain.egg-info/dependency_links.txt +1 -0
- composio_langchain-0.1.40/composio_langchain.egg-info/requires.txt +9 -0
- composio_langchain-0.1.40/composio_langchain.egg-info/top_level.txt +1 -0
- composio_langchain-0.1.40/pyproject.toml +18 -0
- composio_langchain-0.1.40/setup.cfg +4 -0
- composio_langchain-0.1.40/setup.py +31 -0
|
File without changes
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: composio_langchain
|
|
3
|
+
Version: 0.1.40
|
|
4
|
+
Summary: Use Composio to get an array of tools with your LangChain agent.
|
|
5
|
+
Home-page: https://github.com/SamparkAI/composio_sdk
|
|
6
|
+
Author: Karan
|
|
7
|
+
Author-email: karan@composio.dev
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.7
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
Requires-Dist: requests
|
|
14
|
+
Requires-Dist: jsonschema
|
|
15
|
+
Requires-Dist: argparse
|
|
16
|
+
Requires-Dist: nest_asyncio
|
|
17
|
+
Requires-Dist: langchain===0.1.0
|
|
18
|
+
Requires-Dist: langchain-openai===0.0.2.post1
|
|
19
|
+
Requires-Dist: langchainhub==0.1.15
|
|
20
|
+
Requires-Dist: pydantic===2.6.4
|
|
21
|
+
Requires-Dist: composio_core===0.1.40
|
|
22
|
+
|
|
23
|
+
Composio <> LangChain
|
|
24
|
+
Use Composio to get an array of tools with your LangChain agent.
|
|
25
|
+
|
|
26
|
+
# Usage
|
|
27
|
+
Inside your LangChain codebase:
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import types
|
|
2
|
+
from typing import List, Annotated
|
|
3
|
+
from .pydantic_utils import json_schema_to_model
|
|
4
|
+
from langchain_core.tools import StructuredTool
|
|
5
|
+
from composio import ComposioCore, App, Action
|
|
6
|
+
from typing import List
|
|
7
|
+
from inspect import Parameter, Signature
|
|
8
|
+
from pydantic import create_model, Field
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
schema_type_python_type_dict = {
|
|
12
|
+
'string': str,
|
|
13
|
+
'number': float,
|
|
14
|
+
'boolean': bool,
|
|
15
|
+
'integer': int,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
fallback_values = {
|
|
19
|
+
'string': "",
|
|
20
|
+
'number': 0.0,
|
|
21
|
+
'integer': 0.0,
|
|
22
|
+
'boolean': False,
|
|
23
|
+
'object': {},
|
|
24
|
+
'array': []
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
def pydantic_model_from_param_schema(param_schema):
|
|
28
|
+
fields = {}
|
|
29
|
+
param_title = param_schema['title'].replace(" ", "")
|
|
30
|
+
required_props = param_schema.get('required', [])
|
|
31
|
+
schema_params_object = param_schema.get('properties', {})
|
|
32
|
+
for prop_name, prop_info in schema_params_object.items():
|
|
33
|
+
prop_type = prop_info["type"]
|
|
34
|
+
prop_title = prop_info['title'].replace(" ", "")
|
|
35
|
+
prop_default = prop_info.get('default', fallback_values[prop_type])
|
|
36
|
+
if prop_type in schema_type_python_type_dict:
|
|
37
|
+
signature_prop_type = schema_type_python_type_dict[prop_type]
|
|
38
|
+
else:
|
|
39
|
+
signature_prop_type = pydantic_model_from_param_schema(prop_info)
|
|
40
|
+
|
|
41
|
+
if prop_name in required_props:
|
|
42
|
+
fields[prop_name] = (signature_prop_type,
|
|
43
|
+
Field(...,
|
|
44
|
+
title=prop_title,
|
|
45
|
+
description=prop_info.get('description',
|
|
46
|
+
prop_info.get('desc',
|
|
47
|
+
prop_title))
|
|
48
|
+
))
|
|
49
|
+
else:
|
|
50
|
+
fields[prop_name] = (signature_prop_type,
|
|
51
|
+
Field(title=prop_title,
|
|
52
|
+
default=prop_default
|
|
53
|
+
))
|
|
54
|
+
fieldModel = create_model(param_title, **fields)
|
|
55
|
+
return fieldModel
|
|
56
|
+
|
|
57
|
+
def get_signature_format_from_schema_params(
|
|
58
|
+
schema_params
|
|
59
|
+
):
|
|
60
|
+
parameters = []
|
|
61
|
+
required_params = schema_params.get('required', [])
|
|
62
|
+
schema_params_object = schema_params.get('properties', {})
|
|
63
|
+
for param_name, param_schema in schema_params_object.items():
|
|
64
|
+
param_type = param_schema['type']
|
|
65
|
+
param_title = param_schema['title'].replace(" ", "")
|
|
66
|
+
|
|
67
|
+
if param_type in schema_type_python_type_dict:
|
|
68
|
+
signature_param_type = schema_type_python_type_dict[param_type]
|
|
69
|
+
else:
|
|
70
|
+
signature_param_type = pydantic_model_from_param_schema(param_schema)
|
|
71
|
+
|
|
72
|
+
param_default = param_schema.get('default', fallback_values[param_type])
|
|
73
|
+
param_annotation = Annotated[signature_param_type, param_schema.get('description',
|
|
74
|
+
param_schema.get('desc',
|
|
75
|
+
param_title))]
|
|
76
|
+
param = Parameter(
|
|
77
|
+
name=param_name,
|
|
78
|
+
kind=Parameter.POSITIONAL_OR_KEYWORD,
|
|
79
|
+
annotation=param_annotation,
|
|
80
|
+
default=Parameter.empty if param_name in required_params else param_default
|
|
81
|
+
)
|
|
82
|
+
parameters.append(param)
|
|
83
|
+
return parameters
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def ComposioTool(client : ComposioCore, action_schema: dict[str, any]) -> StructuredTool:
|
|
87
|
+
name = action_schema["name"]
|
|
88
|
+
description = action_schema["description"]
|
|
89
|
+
parameters = json_schema_to_model(action_schema["parameters"])
|
|
90
|
+
appName = action_schema["appName"]
|
|
91
|
+
func_params = get_signature_format_from_schema_params(action_schema["parameters"])
|
|
92
|
+
action_signature = Signature(parameters=func_params)
|
|
93
|
+
placeholder_function = lambda **kwargs: client.execute_action(client.get_action_enum(name, appName), kwargs)
|
|
94
|
+
action_func = types.FunctionType(
|
|
95
|
+
placeholder_function.__code__,
|
|
96
|
+
globals=globals(),
|
|
97
|
+
name=name,
|
|
98
|
+
closure=placeholder_function.__closure__
|
|
99
|
+
)
|
|
100
|
+
action_func.__signature__ = action_signature
|
|
101
|
+
action_func.__doc__ = description
|
|
102
|
+
return StructuredTool.from_function(
|
|
103
|
+
name=name,
|
|
104
|
+
description=description,
|
|
105
|
+
args_schema=parameters,
|
|
106
|
+
return_schema=True,
|
|
107
|
+
# TODO use execute action here
|
|
108
|
+
func = action_func
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
client = ComposioCore()
|
|
112
|
+
|
|
113
|
+
def ComposioToolset(apps: List[App] = [], actions: List[Action] = []) -> List[StructuredTool]:
|
|
114
|
+
if len(apps) >0 and len(actions) > 0:
|
|
115
|
+
raise ValueError("You must provide either a list of tools or a list of actions, not both")
|
|
116
|
+
actions_list = client.sdk.get_list_of_actions(apps, actions)
|
|
117
|
+
return [ComposioTool(client, action) for action in actions_list]
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
from langchain.pydantic_v1 import BaseModel, Field, create_model
|
|
2
|
+
from typing import Any, Dict, List, Optional, Type
|
|
3
|
+
|
|
4
|
+
def json_schema_to_model(json_schema: Dict[str, Any]) -> Type[BaseModel]:
|
|
5
|
+
"""
|
|
6
|
+
Converts a JSON schema to a Pydantic BaseModel class.
|
|
7
|
+
|
|
8
|
+
Args:
|
|
9
|
+
json_schema: The JSON schema to convert.
|
|
10
|
+
|
|
11
|
+
Returns:
|
|
12
|
+
A Pydantic BaseModel class.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
# Extract the model name from the schema title.
|
|
16
|
+
model_name = json_schema.get('title')
|
|
17
|
+
|
|
18
|
+
# Extract the field definitions from the schema properties.
|
|
19
|
+
field_definitions = {
|
|
20
|
+
name: json_schema_to_pydantic_field(name, prop, json_schema.get('required', []) )
|
|
21
|
+
for name, prop in json_schema.get('properties', {}).items()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
# Create the BaseModel class using create_model().
|
|
25
|
+
return create_model(model_name, **field_definitions)
|
|
26
|
+
|
|
27
|
+
def json_schema_to_pydantic_field(name: str, json_schema: Dict[str, Any], required: List[str]) -> Any:
|
|
28
|
+
"""
|
|
29
|
+
Converts a JSON schema property to a Pydantic field definition.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
name: The field name.
|
|
33
|
+
json_schema: The JSON schema property.
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
A Pydantic field definition.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
# Get the field type.
|
|
40
|
+
type_ = json_schema_to_pydantic_type(json_schema)
|
|
41
|
+
|
|
42
|
+
# Get the field description.
|
|
43
|
+
description = json_schema.get('description')
|
|
44
|
+
|
|
45
|
+
# Get the field examples.
|
|
46
|
+
examples = json_schema.get('examples', [])
|
|
47
|
+
|
|
48
|
+
# Create a Field object with the type, description, and examples.
|
|
49
|
+
# The 'required' flag will be set later when creating the model.
|
|
50
|
+
return (type_, Field(description=description, examples=examples, default=... if name in required else None))
|
|
51
|
+
|
|
52
|
+
def json_schema_to_pydantic_type(json_schema: Dict[str, Any]) -> Any:
|
|
53
|
+
"""
|
|
54
|
+
Converts a JSON schema type to a Pydantic type.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
json_schema: The JSON schema to convert.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
A Pydantic type.
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
type_ = json_schema.get('type')
|
|
64
|
+
|
|
65
|
+
if type_ == 'string':
|
|
66
|
+
return str
|
|
67
|
+
elif type_ == 'integer':
|
|
68
|
+
return int
|
|
69
|
+
elif type_ == 'number':
|
|
70
|
+
return float
|
|
71
|
+
elif type_ == 'boolean':
|
|
72
|
+
return bool
|
|
73
|
+
elif type_ == 'array':
|
|
74
|
+
items_schema = json_schema.get('items')
|
|
75
|
+
if items_schema:
|
|
76
|
+
item_type = json_schema_to_pydantic_type(items_schema)
|
|
77
|
+
return List[item_type]
|
|
78
|
+
else:
|
|
79
|
+
return List
|
|
80
|
+
elif type_ == 'object':
|
|
81
|
+
# Handle nested models.
|
|
82
|
+
properties = json_schema.get('properties')
|
|
83
|
+
if properties:
|
|
84
|
+
nested_model = json_schema_to_model(json_schema)
|
|
85
|
+
return nested_model
|
|
86
|
+
else:
|
|
87
|
+
return Dict
|
|
88
|
+
elif type_ == 'null':
|
|
89
|
+
return Optional[Any] # Use Optional[Any] for nullable fields
|
|
90
|
+
else:
|
|
91
|
+
raise ValueError(f'Unsupported JSON schema type: {type_}')
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: composio_langchain
|
|
3
|
+
Version: 0.1.40
|
|
4
|
+
Summary: Use Composio to get an array of tools with your LangChain agent.
|
|
5
|
+
Home-page: https://github.com/SamparkAI/composio_sdk
|
|
6
|
+
Author: Karan
|
|
7
|
+
Author-email: karan@composio.dev
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.7
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
Requires-Dist: requests
|
|
14
|
+
Requires-Dist: jsonschema
|
|
15
|
+
Requires-Dist: argparse
|
|
16
|
+
Requires-Dist: nest_asyncio
|
|
17
|
+
Requires-Dist: langchain===0.1.0
|
|
18
|
+
Requires-Dist: langchain-openai===0.0.2.post1
|
|
19
|
+
Requires-Dist: langchainhub==0.1.15
|
|
20
|
+
Requires-Dist: pydantic===2.6.4
|
|
21
|
+
Requires-Dist: composio_core===0.1.40
|
|
22
|
+
|
|
23
|
+
Composio <> LangChain
|
|
24
|
+
Use Composio to get an array of tools with your LangChain agent.
|
|
25
|
+
|
|
26
|
+
# Usage
|
|
27
|
+
Inside your LangChain codebase:
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
MANIFEST.in
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
setup.py
|
|
5
|
+
composio_langchain/__init__.py
|
|
6
|
+
composio_langchain/composio_tool_spec.py
|
|
7
|
+
composio_langchain/pydantic_utils.py
|
|
8
|
+
composio_langchain.egg-info/PKG-INFO
|
|
9
|
+
composio_langchain.egg-info/SOURCES.txt
|
|
10
|
+
composio_langchain.egg-info/dependency_links.txt
|
|
11
|
+
composio_langchain.egg-info/requires.txt
|
|
12
|
+
composio_langchain.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
composio_langchain
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
dynamic = ["classifiers", "version", "readme", "authors", "requires-python", "description"]
|
|
3
|
+
dependencies = [
|
|
4
|
+
"requests",
|
|
5
|
+
"jsonschema",
|
|
6
|
+
"argparse",
|
|
7
|
+
"nest_asyncio",
|
|
8
|
+
"langchain===0.1.0",
|
|
9
|
+
"langchain-openai===0.0.2.post1",
|
|
10
|
+
"langchainhub==0.1.15",
|
|
11
|
+
"pydantic===2.6.4",
|
|
12
|
+
"composio_core===0.1.40"
|
|
13
|
+
]
|
|
14
|
+
name = "composio_langchain"
|
|
15
|
+
|
|
16
|
+
[build-system]
|
|
17
|
+
requires = [ "setuptools>=42", "wheel"]
|
|
18
|
+
build-backend = "setuptools.build_meta"
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from setuptools import setup
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def get_current_dir():
|
|
6
|
+
return os.path.dirname(os.path.realpath(__file__))
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def resolve_paths(*paths):
|
|
10
|
+
return os.path.join(*paths)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
readme_path = resolve_paths(get_current_dir(), "README.md")
|
|
14
|
+
|
|
15
|
+
setup(
|
|
16
|
+
name="composio_langchain",
|
|
17
|
+
version="0.1.40",
|
|
18
|
+
author="Karan",
|
|
19
|
+
author_email="karan@composio.dev",
|
|
20
|
+
description="Use Composio to get an array of tools with your LangChain agent.",
|
|
21
|
+
long_description=open(readme_path).read(),
|
|
22
|
+
long_description_content_type="text/markdown",
|
|
23
|
+
url="https://github.com/SamparkAI/composio_sdk",
|
|
24
|
+
classifiers=[
|
|
25
|
+
"Programming Language :: Python :: 3",
|
|
26
|
+
"License :: OSI Approved :: Apache Software License",
|
|
27
|
+
"Operating System :: OS Independent",
|
|
28
|
+
],
|
|
29
|
+
python_requires=">=3.7",
|
|
30
|
+
include_package_data=True,
|
|
31
|
+
)
|