jl-ecms-client 0.2.8__py3-none-any.whl → 0.2.23__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.
Potentially problematic release.
This version of jl-ecms-client might be problematic. Click here for more details.
- {jl_ecms_client-0.2.8.dist-info → jl_ecms_client-0.2.23.dist-info}/METADATA +6 -1
- jl_ecms_client-0.2.23.dist-info/RECORD +67 -0
- mirix/__init__.py +41 -0
- mirix/client/client.py +1 -1
- mirix/constants.py +251 -0
- mirix/errors.py +238 -0
- mirix/functions/__init__.py +0 -0
- mirix/functions/ast_parsers.py +113 -0
- mirix/functions/function_sets/__init__.py +1 -0
- mirix/functions/function_sets/base.py +330 -0
- mirix/functions/function_sets/extras.py +271 -0
- mirix/functions/function_sets/memory_tools.py +933 -0
- mirix/functions/functions.py +199 -0
- mirix/functions/helpers.py +311 -0
- mirix/functions/schema_generator.py +511 -0
- mirix/helpers/json_helpers.py +3 -3
- mirix/log.py +163 -0
- mirix/schemas/agent.py +1 -1
- mirix/schemas/block.py +1 -1
- mirix/schemas/embedding_config.py +0 -3
- mirix/schemas/enums.py +12 -0
- mirix/schemas/episodic_memory.py +1 -1
- mirix/schemas/knowledge_vault.py +1 -1
- mirix/schemas/memory.py +1 -1
- mirix/schemas/message.py +1 -1
- mirix/schemas/mirix_request.py +1 -1
- mirix/schemas/procedural_memory.py +1 -1
- mirix/schemas/providers.py +1 -1
- mirix/schemas/resource_memory.py +1 -1
- mirix/schemas/sandbox_config.py +1 -3
- mirix/schemas/semantic_memory.py +1 -1
- mirix/schemas/tool.py +241 -241
- mirix/schemas/user.py +3 -3
- mirix/settings.py +280 -0
- mirix/system.py +261 -0
- jl_ecms_client-0.2.8.dist-info/RECORD +0 -53
- mirix/client/constants.py +0 -60
- {jl_ecms_client-0.2.8.dist-info → jl_ecms_client-0.2.23.dist-info}/WHEEL +0 -0
- {jl_ecms_client-0.2.8.dist-info → jl_ecms_client-0.2.23.dist-info}/licenses/LICENSE +0 -0
- {jl_ecms_client-0.2.8.dist-info → jl_ecms_client-0.2.23.dist-info}/top_level.txt +0 -0
mirix/schemas/agent.py
CHANGED
|
@@ -3,7 +3,7 @@ from typing import Any, Dict, List, Optional, Union
|
|
|
3
3
|
|
|
4
4
|
from pydantic import BaseModel, Field, field_validator
|
|
5
5
|
|
|
6
|
-
from mirix.
|
|
6
|
+
from mirix.constants import DEFAULT_EMBEDDING_CHUNK_SIZE
|
|
7
7
|
from mirix.helpers import ToolRulesSolver
|
|
8
8
|
from mirix.schemas.block import CreateBlock
|
|
9
9
|
from mirix.schemas.embedding_config import EmbeddingConfig
|
mirix/schemas/block.py
CHANGED
|
@@ -3,7 +3,7 @@ from typing import Optional
|
|
|
3
3
|
from pydantic import BaseModel, Field, model_validator
|
|
4
4
|
from typing_extensions import Self
|
|
5
5
|
|
|
6
|
-
from mirix.
|
|
6
|
+
from mirix.constants import CORE_MEMORY_BLOCK_CHAR_LIMIT
|
|
7
7
|
from mirix.schemas.mirix_base import MirixBase
|
|
8
8
|
|
|
9
9
|
# block of the LLM context
|
mirix/schemas/enums.py
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
class ToolType(str, Enum):
|
|
5
|
+
"""Types of tools in Mirix"""
|
|
6
|
+
CUSTOM = "custom"
|
|
7
|
+
MIRIX_CORE = "mirix_core"
|
|
8
|
+
MIRIX_CODER_CORE = "mirix_coder_core"
|
|
9
|
+
MIRIX_MEMORY_CORE = "mirix_memory_core"
|
|
10
|
+
MIRIX_EXTRA = "mirix_extra"
|
|
11
|
+
MIRIX_MCP = "mirix_mcp"
|
|
12
|
+
MIRIX_MULTI_AGENT_CORE = "mirix_multi_agent_core"
|
|
13
|
+
USER_DEFINED = "user_defined"
|
|
14
|
+
|
|
15
|
+
|
|
4
16
|
class ProviderType(str, Enum):
|
|
5
17
|
anthropic = "anthropic"
|
|
6
18
|
|
mirix/schemas/episodic_memory.py
CHANGED
|
@@ -4,7 +4,7 @@ from typing import Any, Dict, List, Optional
|
|
|
4
4
|
from pydantic import Field, field_validator
|
|
5
5
|
|
|
6
6
|
from mirix.client.utils import get_utc_time
|
|
7
|
-
from mirix.
|
|
7
|
+
from mirix.constants import MAX_EMBEDDING_DIM
|
|
8
8
|
from mirix.schemas.embedding_config import EmbeddingConfig
|
|
9
9
|
from mirix.schemas.mirix_base import MirixBase
|
|
10
10
|
|
mirix/schemas/knowledge_vault.py
CHANGED
|
@@ -4,7 +4,7 @@ from typing import Any, Dict, List, Optional
|
|
|
4
4
|
from pydantic import Field, field_validator
|
|
5
5
|
|
|
6
6
|
from mirix.client.utils import get_utc_time
|
|
7
|
-
from mirix.
|
|
7
|
+
from mirix.constants import MAX_EMBEDDING_DIM
|
|
8
8
|
from mirix.schemas.embedding_config import EmbeddingConfig
|
|
9
9
|
from mirix.schemas.mirix_base import MirixBase
|
|
10
10
|
|
mirix/schemas/memory.py
CHANGED
|
@@ -7,7 +7,7 @@ from pydantic import BaseModel, Field
|
|
|
7
7
|
if TYPE_CHECKING:
|
|
8
8
|
from mirix.schemas.agent import AgentState
|
|
9
9
|
|
|
10
|
-
from mirix.
|
|
10
|
+
from mirix.constants import CORE_MEMORY_BLOCK_CHAR_LIMIT
|
|
11
11
|
from mirix.schemas.block import Block
|
|
12
12
|
from mirix.schemas.message import Message
|
|
13
13
|
from mirix.schemas.openai.chat_completion_request import Tool
|
mirix/schemas/message.py
CHANGED
|
@@ -10,7 +10,7 @@ from typing import Any, Dict, List, Literal, Optional, Union
|
|
|
10
10
|
|
|
11
11
|
from pydantic import BaseModel, Field, field_validator
|
|
12
12
|
|
|
13
|
-
from mirix.
|
|
13
|
+
from mirix.constants import (
|
|
14
14
|
DEFAULT_MESSAGE_TOOL,
|
|
15
15
|
DEFAULT_MESSAGE_TOOL_KWARG,
|
|
16
16
|
TOOL_CALL_ID_MAX_LEN,
|
mirix/schemas/mirix_request.py
CHANGED
|
@@ -2,7 +2,7 @@ from typing import List
|
|
|
2
2
|
|
|
3
3
|
from pydantic import BaseModel, Field
|
|
4
4
|
|
|
5
|
-
from mirix.
|
|
5
|
+
from mirix.constants import DEFAULT_MESSAGE_TOOL, DEFAULT_MESSAGE_TOOL_KWARG
|
|
6
6
|
from mirix.schemas.message import MessageCreate
|
|
7
7
|
|
|
8
8
|
|
|
@@ -4,7 +4,7 @@ from typing import Any, Dict, List, Optional
|
|
|
4
4
|
from pydantic import Field, field_validator
|
|
5
5
|
|
|
6
6
|
from mirix.client.utils import get_utc_time
|
|
7
|
-
from mirix.
|
|
7
|
+
from mirix.constants import MAX_EMBEDDING_DIM
|
|
8
8
|
from mirix.schemas.embedding_config import EmbeddingConfig
|
|
9
9
|
from mirix.schemas.mirix_base import MirixBase
|
|
10
10
|
|
mirix/schemas/providers.py
CHANGED
|
@@ -3,7 +3,7 @@ from typing import List, Optional
|
|
|
3
3
|
|
|
4
4
|
from pydantic import Field, model_validator
|
|
5
5
|
|
|
6
|
-
from mirix.
|
|
6
|
+
from mirix.constants import LLM_MAX_TOKENS, MIN_CONTEXT_WINDOW
|
|
7
7
|
from mirix.llm_api.azure_openai import (
|
|
8
8
|
get_azure_chat_completions_endpoint,
|
|
9
9
|
get_azure_embeddings_endpoint,
|
mirix/schemas/resource_memory.py
CHANGED
|
@@ -3,7 +3,7 @@ from typing import Any, Dict, List, Optional
|
|
|
3
3
|
|
|
4
4
|
from pydantic import Field, field_validator
|
|
5
5
|
|
|
6
|
-
from mirix.
|
|
6
|
+
from mirix.constants import MAX_EMBEDDING_DIM
|
|
7
7
|
from mirix.schemas.embedding_config import EmbeddingConfig
|
|
8
8
|
from mirix.schemas.mirix_base import MirixBase
|
|
9
9
|
from mirix.client.utils import get_utc_time
|
mirix/schemas/sandbox_config.py
CHANGED
|
@@ -8,12 +8,9 @@ from pydantic import BaseModel, Field, model_validator
|
|
|
8
8
|
from mirix.schemas.agent import AgentState
|
|
9
9
|
from mirix.schemas.mirix_base import MirixBase, OrmMetadataBase
|
|
10
10
|
from mirix.settings import tool_settings
|
|
11
|
-
from mirix.log import get_logger
|
|
12
11
|
|
|
13
12
|
|
|
14
13
|
# Sandbox Config
|
|
15
|
-
|
|
16
|
-
logger = get_logger(__name__)
|
|
17
14
|
class SandboxType(str, Enum):
|
|
18
15
|
E2B = "e2b"
|
|
19
16
|
LOCAL = "local"
|
|
@@ -73,6 +70,7 @@ class E2BSandboxConfig(BaseModel):
|
|
|
73
70
|
Assign a default template value if the template field is not provided.
|
|
74
71
|
"""
|
|
75
72
|
if data.get("template") is None:
|
|
73
|
+
# Use configured template if available
|
|
76
74
|
data["template"] = tool_settings.e2b_sandbox_template_id
|
|
77
75
|
return data
|
|
78
76
|
|
mirix/schemas/semantic_memory.py
CHANGED
|
@@ -3,7 +3,7 @@ from typing import Any, Dict, List, Optional
|
|
|
3
3
|
|
|
4
4
|
from pydantic import Field, field_validator
|
|
5
5
|
|
|
6
|
-
from mirix.
|
|
6
|
+
from mirix.constants import MAX_EMBEDDING_DIM
|
|
7
7
|
from mirix.schemas.embedding_config import EmbeddingConfig
|
|
8
8
|
from mirix.schemas.mirix_base import MirixBase
|
|
9
9
|
from mirix.client.utils import get_utc_time
|
mirix/schemas/tool.py
CHANGED
|
@@ -1,241 +1,241 @@
|
|
|
1
|
-
from typing import TYPE_CHECKING, Any, Dict, List, Optional
|
|
2
|
-
|
|
3
|
-
from pydantic import Field, model_validator
|
|
4
|
-
|
|
5
|
-
from mirix.
|
|
6
|
-
COMPOSIO_TOOL_TAG_NAME,
|
|
7
|
-
FUNCTION_RETURN_CHAR_LIMIT,
|
|
8
|
-
MIRIX_CORE_TOOL_MODULE_NAME,
|
|
9
|
-
MIRIX_EXTRA_TOOL_MODULE_NAME,
|
|
10
|
-
MIRIX_MEMORY_TOOL_MODULE_NAME,
|
|
11
|
-
)
|
|
12
|
-
from mirix.functions.functions import (
|
|
13
|
-
derive_openai_json_schema,
|
|
14
|
-
get_json_schema_from_module,
|
|
15
|
-
)
|
|
16
|
-
from mirix.functions.helpers import generate_langchain_tool_wrapper
|
|
17
|
-
from mirix.functions.schema_generator import generate_schema_from_args_schema_v2
|
|
18
|
-
from mirix.
|
|
19
|
-
from mirix.schemas.mirix_base import MirixBase
|
|
20
|
-
|
|
21
|
-
if TYPE_CHECKING:
|
|
22
|
-
try:
|
|
23
|
-
from langchain_core.tools import BaseTool as LangChainBaseTool
|
|
24
|
-
except ImportError:
|
|
25
|
-
LangChainBaseTool = Any # type: ignore
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
class BaseTool(MirixBase):
|
|
29
|
-
__id_prefix__ = "tool"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
class Tool(BaseTool):
|
|
33
|
-
"""
|
|
34
|
-
Representation of a tool, which is a function that can be called by the agent.
|
|
35
|
-
|
|
36
|
-
Parameters:
|
|
37
|
-
id (str): The unique identifier of the tool.
|
|
38
|
-
name (str): The name of the function.
|
|
39
|
-
tags (List[str]): Metadata tags.
|
|
40
|
-
source_code (str): The source code of the function.
|
|
41
|
-
json_schema (Dict): The JSON schema of the function.
|
|
42
|
-
|
|
43
|
-
"""
|
|
44
|
-
|
|
45
|
-
id: str = BaseTool.generate_id_field()
|
|
46
|
-
tool_type: ToolType = Field(ToolType.CUSTOM, description="The type of the tool.")
|
|
47
|
-
description: Optional[str] = Field(None, description="The description of the tool.")
|
|
48
|
-
source_type: Optional[str] = Field(None, description="The type of the source code.")
|
|
49
|
-
organization_id: Optional[str] = Field(
|
|
50
|
-
None,
|
|
51
|
-
description="The unique identifier of the organization associated with the tool.",
|
|
52
|
-
)
|
|
53
|
-
name: Optional[str] = Field(None, description="The name of the function.")
|
|
54
|
-
tags: List[str] = Field([], description="Metadata tags.")
|
|
55
|
-
|
|
56
|
-
# code
|
|
57
|
-
source_code: Optional[str] = Field(
|
|
58
|
-
None, description="The source code of the function."
|
|
59
|
-
)
|
|
60
|
-
json_schema: Optional[Dict] = Field(
|
|
61
|
-
None, description="The JSON schema of the function."
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
# tool configuration
|
|
65
|
-
return_char_limit: int = Field(
|
|
66
|
-
FUNCTION_RETURN_CHAR_LIMIT,
|
|
67
|
-
description="The maximum number of characters in the response.",
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
# metadata fields
|
|
71
|
-
created_by_id: Optional[str] = Field(
|
|
72
|
-
None, description="The id of the user that made this Tool."
|
|
73
|
-
)
|
|
74
|
-
last_updated_by_id: Optional[str] = Field(
|
|
75
|
-
None, description="The id of the user that made this Tool."
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
@model_validator(mode="after")
|
|
79
|
-
def populate_missing_fields(self):
|
|
80
|
-
"""
|
|
81
|
-
Populate missing fields: name, description, and json_schema.
|
|
82
|
-
"""
|
|
83
|
-
|
|
84
|
-
if self.tool_type == ToolType.CUSTOM:
|
|
85
|
-
# If it's a custom tool, we need to ensure source_code is present
|
|
86
|
-
if not self.source_code:
|
|
87
|
-
raise ValueError(
|
|
88
|
-
f"Custom tool with id={self.id} is missing source_code field."
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
# Always derive json_schema for freshest possible json_schema
|
|
92
|
-
# TODO: Instead of checking the tag, we should having `COMPOSIO` as a specific ToolType
|
|
93
|
-
# TODO: We skip this for Composio bc composio json schemas are derived differently
|
|
94
|
-
if COMPOSIO_TOOL_TAG_NAME not in self.tags:
|
|
95
|
-
self.json_schema = derive_openai_json_schema(
|
|
96
|
-
source_code=self.source_code
|
|
97
|
-
)
|
|
98
|
-
elif self.tool_type in {ToolType.MIRIX_CORE}:
|
|
99
|
-
# If it's mirix core tool, we generate the json_schema on the fly here
|
|
100
|
-
self.json_schema = get_json_schema_from_module(
|
|
101
|
-
module_name=MIRIX_CORE_TOOL_MODULE_NAME, function_name=self.name
|
|
102
|
-
)
|
|
103
|
-
elif self.tool_type in {ToolType.MIRIX_MEMORY_CORE}:
|
|
104
|
-
self.json_schema = get_json_schema_from_module(
|
|
105
|
-
module_name=MIRIX_MEMORY_TOOL_MODULE_NAME, function_name=self.name
|
|
106
|
-
)
|
|
107
|
-
elif self.tool_type in {ToolType.MIRIX_EXTRA}:
|
|
108
|
-
self.json_schema = get_json_schema_from_module(
|
|
109
|
-
module_name=MIRIX_EXTRA_TOOL_MODULE_NAME, function_name=self.name
|
|
110
|
-
)
|
|
111
|
-
elif self.tool_type in {ToolType.MIRIX_MCP}:
|
|
112
|
-
# MCP tools have their json_schema already provided by MCP tool registry
|
|
113
|
-
# Skip validation since these are auto-generated tools
|
|
114
|
-
if not self.json_schema:
|
|
115
|
-
raise ValueError(f"MCP tool {self.name} is missing json_schema field")
|
|
116
|
-
|
|
117
|
-
# Derive name from the JSON schema if not provided
|
|
118
|
-
if not self.name:
|
|
119
|
-
# TODO: This in theory could error, but name should always be on json_schema
|
|
120
|
-
# TODO: Make JSON schema a typed pydantic object
|
|
121
|
-
self.name = self.json_schema.get("name")
|
|
122
|
-
|
|
123
|
-
# Derive description from the JSON schema if not provided
|
|
124
|
-
if not self.description:
|
|
125
|
-
# TODO: This in theory could error, but description should always be on json_schema
|
|
126
|
-
# TODO: Make JSON schema a typed pydantic object
|
|
127
|
-
self.description = self.json_schema.get("description")
|
|
128
|
-
|
|
129
|
-
return self
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
class ToolCreate(MirixBase):
|
|
133
|
-
name: Optional[str] = Field(
|
|
134
|
-
None,
|
|
135
|
-
description="The name of the function (auto-generated from source_code if not provided).",
|
|
136
|
-
)
|
|
137
|
-
description: Optional[str] = Field(None, description="The description of the tool.")
|
|
138
|
-
tags: List[str] = Field([], description="Metadata tags.")
|
|
139
|
-
source_code: str = Field(..., description="The source code of the function.")
|
|
140
|
-
source_type: str = Field("python", description="The source type of the function.")
|
|
141
|
-
json_schema: Optional[Dict] = Field(
|
|
142
|
-
None,
|
|
143
|
-
description="The JSON schema of the function (auto-generated from source_code if not provided)",
|
|
144
|
-
)
|
|
145
|
-
return_char_limit: int = Field(
|
|
146
|
-
FUNCTION_RETURN_CHAR_LIMIT,
|
|
147
|
-
description="The maximum number of characters in the response.",
|
|
148
|
-
)
|
|
149
|
-
|
|
150
|
-
@classmethod
|
|
151
|
-
def from_langchain(
|
|
152
|
-
cls,
|
|
153
|
-
langchain_tool: "LangChainBaseTool",
|
|
154
|
-
additional_imports_module_attr_map: dict[str, str] = None,
|
|
155
|
-
) -> "ToolCreate":
|
|
156
|
-
"""
|
|
157
|
-
Class method to create an instance of Tool from a Langchain tool (must be from langchain_community.tools).
|
|
158
|
-
|
|
159
|
-
Args:
|
|
160
|
-
langchain_tool (LangChainBaseTool): An instance of a LangChain BaseTool (BaseTool from LangChain)
|
|
161
|
-
additional_imports_module_attr_map (dict[str, str]): A mapping of module names to attribute name. This is used internally to import all the required classes for the langchain tool. For example, you would pass in `{"langchain_community.utilities": "WikipediaAPIWrapper"}` for `from langchain_community.tools import WikipediaQueryRun`. NOTE: You do NOT need to specify the tool import here, that is done automatically for you.
|
|
162
|
-
|
|
163
|
-
Returns:
|
|
164
|
-
Tool: A Mirix Tool initialized with attributes derived from the provided LangChain BaseTool object.
|
|
165
|
-
"""
|
|
166
|
-
description = langchain_tool.description
|
|
167
|
-
source_type = "python"
|
|
168
|
-
tags = ["langchain"]
|
|
169
|
-
# NOTE: langchain tools may come from different packages
|
|
170
|
-
wrapper_func_name, wrapper_function_str = generate_langchain_tool_wrapper(
|
|
171
|
-
langchain_tool, additional_imports_module_attr_map
|
|
172
|
-
)
|
|
173
|
-
json_schema = generate_schema_from_args_schema_v2(
|
|
174
|
-
langchain_tool.args_schema, name=wrapper_func_name, description=description
|
|
175
|
-
)
|
|
176
|
-
|
|
177
|
-
return cls(
|
|
178
|
-
name=wrapper_func_name,
|
|
179
|
-
description=description,
|
|
180
|
-
source_type=source_type,
|
|
181
|
-
tags=tags,
|
|
182
|
-
source_code=wrapper_function_str,
|
|
183
|
-
json_schema=json_schema,
|
|
184
|
-
)
|
|
185
|
-
|
|
186
|
-
@classmethod
|
|
187
|
-
def load_default_langchain_tools(cls) -> List["ToolCreate"]:
|
|
188
|
-
# For now, we only support wikipedia tool
|
|
189
|
-
from langchain_community.tools import WikipediaQueryRun
|
|
190
|
-
from langchain_community.utilities import WikipediaAPIWrapper
|
|
191
|
-
|
|
192
|
-
wikipedia_tool = ToolCreate.from_langchain(
|
|
193
|
-
WikipediaQueryRun(api_wrapper=WikipediaAPIWrapper()),
|
|
194
|
-
{"langchain_community.utilities": "WikipediaAPIWrapper"},
|
|
195
|
-
)
|
|
196
|
-
|
|
197
|
-
return [wikipedia_tool]
|
|
198
|
-
|
|
199
|
-
@classmethod
|
|
200
|
-
def load_default_composio_tools(cls) -> List["ToolCreate"]:
|
|
201
|
-
pass
|
|
202
|
-
|
|
203
|
-
# TODO: Disable composio tools for now
|
|
204
|
-
# TODO: Naming is causing issues
|
|
205
|
-
# calculator = ToolCreate.from_composio(action_name=Action.MATHEMATICAL_CALCULATOR.name)
|
|
206
|
-
# serp_news = ToolCreate.from_composio(action_name=Action.SERPAPI_NEWS_SEARCH.name)
|
|
207
|
-
# serp_google_search = ToolCreate.from_composio(action_name=Action.SERPAPI_SEARCH.name)
|
|
208
|
-
# serp_google_maps = ToolCreate.from_composio(action_name=Action.SERPAPI_GOOGLE_MAPS_SEARCH.name)
|
|
209
|
-
|
|
210
|
-
return []
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
class ToolUpdate(MirixBase):
|
|
214
|
-
description: Optional[str] = Field(None, description="The description of the tool.")
|
|
215
|
-
name: Optional[str] = Field(None, description="The name of the function.")
|
|
216
|
-
tags: Optional[List[str]] = Field(None, description="Metadata tags.")
|
|
217
|
-
source_code: Optional[str] = Field(
|
|
218
|
-
None, description="The source code of the function."
|
|
219
|
-
)
|
|
220
|
-
source_type: Optional[str] = Field(None, description="The type of the source code.")
|
|
221
|
-
json_schema: Optional[Dict] = Field(
|
|
222
|
-
None,
|
|
223
|
-
description="The JSON schema of the function (auto-generated from source_code if not provided)",
|
|
224
|
-
)
|
|
225
|
-
return_char_limit: Optional[int] = Field(
|
|
226
|
-
None, description="The maximum number of characters in the response."
|
|
227
|
-
)
|
|
228
|
-
|
|
229
|
-
class Config:
|
|
230
|
-
extra = "ignore" # Allows extra fields without validation errors
|
|
231
|
-
# TODO: Remove this, and clean usage of ToolUpdate everywhere else
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
class ToolRunFromSource(MirixBase):
|
|
235
|
-
source_code: str = Field(..., description="The source code of the function.")
|
|
236
|
-
args: Dict[str, Any] = Field(..., description="The arguments to pass to the tool.")
|
|
237
|
-
env_vars: Dict[str, str] = Field(
|
|
238
|
-
None, description="The environment variables to pass to the tool."
|
|
239
|
-
)
|
|
240
|
-
name: Optional[str] = Field(None, description="The name of the tool to run.")
|
|
241
|
-
source_type: Optional[str] = Field(None, description="The type of the source code.")
|
|
1
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional
|
|
2
|
+
|
|
3
|
+
from pydantic import Field, model_validator
|
|
4
|
+
|
|
5
|
+
from mirix.constants import (
|
|
6
|
+
COMPOSIO_TOOL_TAG_NAME,
|
|
7
|
+
FUNCTION_RETURN_CHAR_LIMIT,
|
|
8
|
+
MIRIX_CORE_TOOL_MODULE_NAME,
|
|
9
|
+
MIRIX_EXTRA_TOOL_MODULE_NAME,
|
|
10
|
+
MIRIX_MEMORY_TOOL_MODULE_NAME,
|
|
11
|
+
)
|
|
12
|
+
from mirix.functions.functions import (
|
|
13
|
+
derive_openai_json_schema,
|
|
14
|
+
get_json_schema_from_module,
|
|
15
|
+
)
|
|
16
|
+
from mirix.functions.helpers import generate_langchain_tool_wrapper
|
|
17
|
+
from mirix.functions.schema_generator import generate_schema_from_args_schema_v2
|
|
18
|
+
from mirix.schemas.enums import ToolType
|
|
19
|
+
from mirix.schemas.mirix_base import MirixBase
|
|
20
|
+
|
|
21
|
+
if TYPE_CHECKING:
|
|
22
|
+
try:
|
|
23
|
+
from langchain_core.tools import BaseTool as LangChainBaseTool
|
|
24
|
+
except ImportError:
|
|
25
|
+
LangChainBaseTool = Any # type: ignore
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class BaseTool(MirixBase):
|
|
29
|
+
__id_prefix__ = "tool"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class Tool(BaseTool):
|
|
33
|
+
"""
|
|
34
|
+
Representation of a tool, which is a function that can be called by the agent.
|
|
35
|
+
|
|
36
|
+
Parameters:
|
|
37
|
+
id (str): The unique identifier of the tool.
|
|
38
|
+
name (str): The name of the function.
|
|
39
|
+
tags (List[str]): Metadata tags.
|
|
40
|
+
source_code (str): The source code of the function.
|
|
41
|
+
json_schema (Dict): The JSON schema of the function.
|
|
42
|
+
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
id: str = BaseTool.generate_id_field()
|
|
46
|
+
tool_type: ToolType = Field(ToolType.CUSTOM, description="The type of the tool.")
|
|
47
|
+
description: Optional[str] = Field(None, description="The description of the tool.")
|
|
48
|
+
source_type: Optional[str] = Field(None, description="The type of the source code.")
|
|
49
|
+
organization_id: Optional[str] = Field(
|
|
50
|
+
None,
|
|
51
|
+
description="The unique identifier of the organization associated with the tool.",
|
|
52
|
+
)
|
|
53
|
+
name: Optional[str] = Field(None, description="The name of the function.")
|
|
54
|
+
tags: List[str] = Field([], description="Metadata tags.")
|
|
55
|
+
|
|
56
|
+
# code
|
|
57
|
+
source_code: Optional[str] = Field(
|
|
58
|
+
None, description="The source code of the function."
|
|
59
|
+
)
|
|
60
|
+
json_schema: Optional[Dict] = Field(
|
|
61
|
+
None, description="The JSON schema of the function."
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
# tool configuration
|
|
65
|
+
return_char_limit: int = Field(
|
|
66
|
+
FUNCTION_RETURN_CHAR_LIMIT,
|
|
67
|
+
description="The maximum number of characters in the response.",
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
# metadata fields
|
|
71
|
+
created_by_id: Optional[str] = Field(
|
|
72
|
+
None, description="The id of the user that made this Tool."
|
|
73
|
+
)
|
|
74
|
+
last_updated_by_id: Optional[str] = Field(
|
|
75
|
+
None, description="The id of the user that made this Tool."
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
@model_validator(mode="after")
|
|
79
|
+
def populate_missing_fields(self):
|
|
80
|
+
"""
|
|
81
|
+
Populate missing fields: name, description, and json_schema.
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
if self.tool_type == ToolType.CUSTOM:
|
|
85
|
+
# If it's a custom tool, we need to ensure source_code is present
|
|
86
|
+
if not self.source_code:
|
|
87
|
+
raise ValueError(
|
|
88
|
+
f"Custom tool with id={self.id} is missing source_code field."
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
# Always derive json_schema for freshest possible json_schema
|
|
92
|
+
# TODO: Instead of checking the tag, we should having `COMPOSIO` as a specific ToolType
|
|
93
|
+
# TODO: We skip this for Composio bc composio json schemas are derived differently
|
|
94
|
+
if COMPOSIO_TOOL_TAG_NAME not in self.tags:
|
|
95
|
+
self.json_schema = derive_openai_json_schema(
|
|
96
|
+
source_code=self.source_code
|
|
97
|
+
)
|
|
98
|
+
elif self.tool_type in {ToolType.MIRIX_CORE}:
|
|
99
|
+
# If it's mirix core tool, we generate the json_schema on the fly here
|
|
100
|
+
self.json_schema = get_json_schema_from_module(
|
|
101
|
+
module_name=MIRIX_CORE_TOOL_MODULE_NAME, function_name=self.name
|
|
102
|
+
)
|
|
103
|
+
elif self.tool_type in {ToolType.MIRIX_MEMORY_CORE}:
|
|
104
|
+
self.json_schema = get_json_schema_from_module(
|
|
105
|
+
module_name=MIRIX_MEMORY_TOOL_MODULE_NAME, function_name=self.name
|
|
106
|
+
)
|
|
107
|
+
elif self.tool_type in {ToolType.MIRIX_EXTRA}:
|
|
108
|
+
self.json_schema = get_json_schema_from_module(
|
|
109
|
+
module_name=MIRIX_EXTRA_TOOL_MODULE_NAME, function_name=self.name
|
|
110
|
+
)
|
|
111
|
+
elif self.tool_type in {ToolType.MIRIX_MCP}:
|
|
112
|
+
# MCP tools have their json_schema already provided by MCP tool registry
|
|
113
|
+
# Skip validation since these are auto-generated tools
|
|
114
|
+
if not self.json_schema:
|
|
115
|
+
raise ValueError(f"MCP tool {self.name} is missing json_schema field")
|
|
116
|
+
|
|
117
|
+
# Derive name from the JSON schema if not provided
|
|
118
|
+
if not self.name:
|
|
119
|
+
# TODO: This in theory could error, but name should always be on json_schema
|
|
120
|
+
# TODO: Make JSON schema a typed pydantic object
|
|
121
|
+
self.name = self.json_schema.get("name")
|
|
122
|
+
|
|
123
|
+
# Derive description from the JSON schema if not provided
|
|
124
|
+
if not self.description:
|
|
125
|
+
# TODO: This in theory could error, but description should always be on json_schema
|
|
126
|
+
# TODO: Make JSON schema a typed pydantic object
|
|
127
|
+
self.description = self.json_schema.get("description")
|
|
128
|
+
|
|
129
|
+
return self
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
class ToolCreate(MirixBase):
|
|
133
|
+
name: Optional[str] = Field(
|
|
134
|
+
None,
|
|
135
|
+
description="The name of the function (auto-generated from source_code if not provided).",
|
|
136
|
+
)
|
|
137
|
+
description: Optional[str] = Field(None, description="The description of the tool.")
|
|
138
|
+
tags: List[str] = Field([], description="Metadata tags.")
|
|
139
|
+
source_code: str = Field(..., description="The source code of the function.")
|
|
140
|
+
source_type: str = Field("python", description="The source type of the function.")
|
|
141
|
+
json_schema: Optional[Dict] = Field(
|
|
142
|
+
None,
|
|
143
|
+
description="The JSON schema of the function (auto-generated from source_code if not provided)",
|
|
144
|
+
)
|
|
145
|
+
return_char_limit: int = Field(
|
|
146
|
+
FUNCTION_RETURN_CHAR_LIMIT,
|
|
147
|
+
description="The maximum number of characters in the response.",
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
@classmethod
|
|
151
|
+
def from_langchain(
|
|
152
|
+
cls,
|
|
153
|
+
langchain_tool: "LangChainBaseTool",
|
|
154
|
+
additional_imports_module_attr_map: dict[str, str] = None,
|
|
155
|
+
) -> "ToolCreate":
|
|
156
|
+
"""
|
|
157
|
+
Class method to create an instance of Tool from a Langchain tool (must be from langchain_community.tools).
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
langchain_tool (LangChainBaseTool): An instance of a LangChain BaseTool (BaseTool from LangChain)
|
|
161
|
+
additional_imports_module_attr_map (dict[str, str]): A mapping of module names to attribute name. This is used internally to import all the required classes for the langchain tool. For example, you would pass in `{"langchain_community.utilities": "WikipediaAPIWrapper"}` for `from langchain_community.tools import WikipediaQueryRun`. NOTE: You do NOT need to specify the tool import here, that is done automatically for you.
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
Tool: A Mirix Tool initialized with attributes derived from the provided LangChain BaseTool object.
|
|
165
|
+
"""
|
|
166
|
+
description = langchain_tool.description
|
|
167
|
+
source_type = "python"
|
|
168
|
+
tags = ["langchain"]
|
|
169
|
+
# NOTE: langchain tools may come from different packages
|
|
170
|
+
wrapper_func_name, wrapper_function_str = generate_langchain_tool_wrapper(
|
|
171
|
+
langchain_tool, additional_imports_module_attr_map
|
|
172
|
+
)
|
|
173
|
+
json_schema = generate_schema_from_args_schema_v2(
|
|
174
|
+
langchain_tool.args_schema, name=wrapper_func_name, description=description
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
return cls(
|
|
178
|
+
name=wrapper_func_name,
|
|
179
|
+
description=description,
|
|
180
|
+
source_type=source_type,
|
|
181
|
+
tags=tags,
|
|
182
|
+
source_code=wrapper_function_str,
|
|
183
|
+
json_schema=json_schema,
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
@classmethod
|
|
187
|
+
def load_default_langchain_tools(cls) -> List["ToolCreate"]:
|
|
188
|
+
# For now, we only support wikipedia tool
|
|
189
|
+
from langchain_community.tools import WikipediaQueryRun
|
|
190
|
+
from langchain_community.utilities import WikipediaAPIWrapper
|
|
191
|
+
|
|
192
|
+
wikipedia_tool = ToolCreate.from_langchain(
|
|
193
|
+
WikipediaQueryRun(api_wrapper=WikipediaAPIWrapper()),
|
|
194
|
+
{"langchain_community.utilities": "WikipediaAPIWrapper"},
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
return [wikipedia_tool]
|
|
198
|
+
|
|
199
|
+
@classmethod
|
|
200
|
+
def load_default_composio_tools(cls) -> List["ToolCreate"]:
|
|
201
|
+
pass
|
|
202
|
+
|
|
203
|
+
# TODO: Disable composio tools for now
|
|
204
|
+
# TODO: Naming is causing issues
|
|
205
|
+
# calculator = ToolCreate.from_composio(action_name=Action.MATHEMATICAL_CALCULATOR.name)
|
|
206
|
+
# serp_news = ToolCreate.from_composio(action_name=Action.SERPAPI_NEWS_SEARCH.name)
|
|
207
|
+
# serp_google_search = ToolCreate.from_composio(action_name=Action.SERPAPI_SEARCH.name)
|
|
208
|
+
# serp_google_maps = ToolCreate.from_composio(action_name=Action.SERPAPI_GOOGLE_MAPS_SEARCH.name)
|
|
209
|
+
|
|
210
|
+
return []
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
class ToolUpdate(MirixBase):
|
|
214
|
+
description: Optional[str] = Field(None, description="The description of the tool.")
|
|
215
|
+
name: Optional[str] = Field(None, description="The name of the function.")
|
|
216
|
+
tags: Optional[List[str]] = Field(None, description="Metadata tags.")
|
|
217
|
+
source_code: Optional[str] = Field(
|
|
218
|
+
None, description="The source code of the function."
|
|
219
|
+
)
|
|
220
|
+
source_type: Optional[str] = Field(None, description="The type of the source code.")
|
|
221
|
+
json_schema: Optional[Dict] = Field(
|
|
222
|
+
None,
|
|
223
|
+
description="The JSON schema of the function (auto-generated from source_code if not provided)",
|
|
224
|
+
)
|
|
225
|
+
return_char_limit: Optional[int] = Field(
|
|
226
|
+
None, description="The maximum number of characters in the response."
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
class Config:
|
|
230
|
+
extra = "ignore" # Allows extra fields without validation errors
|
|
231
|
+
# TODO: Remove this, and clean usage of ToolUpdate everywhere else
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class ToolRunFromSource(MirixBase):
|
|
235
|
+
source_code: str = Field(..., description="The source code of the function.")
|
|
236
|
+
args: Dict[str, Any] = Field(..., description="The arguments to pass to the tool.")
|
|
237
|
+
env_vars: Dict[str, str] = Field(
|
|
238
|
+
None, description="The environment variables to pass to the tool."
|
|
239
|
+
)
|
|
240
|
+
name: Optional[str] = Field(None, description="The name of the tool to run.")
|
|
241
|
+
source_type: Optional[str] = Field(None, description="The type of the source code.")
|