hyperpocket-llamaindex 0.0.1__tar.gz → 0.1.9__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.
- hyperpocket_llamaindex-0.1.9/.gitignore +157 -0
- {hyperpocket_llamaindex-0.0.1 → hyperpocket_llamaindex-0.1.9}/PKG-INFO +7 -13
- hyperpocket_llamaindex-0.1.9/__init__.py +0 -0
- hyperpocket_llamaindex-0.1.9/hyperpocket_llamaindex/pocket_llamaindex.py +73 -0
- hyperpocket_llamaindex-0.1.9/pyproject.toml +36 -0
- hyperpocket_llamaindex-0.1.9/tests/__init__.py +0 -0
- hyperpocket_llamaindex-0.1.9/tests/test_pocket_llamaindex_no_profile.py +137 -0
- hyperpocket_llamaindex-0.1.9/tests/test_pocket_llamaindex_use_profile.py +137 -0
- hyperpocket_llamaindex-0.1.9/uv.lock +2324 -0
- hyperpocket_llamaindex-0.0.1/hyperpocket_llamaindex/pocket_llamaindex.py +0 -44
- hyperpocket_llamaindex-0.0.1/pyproject.toml +0 -16
- {hyperpocket_llamaindex-0.0.1 → hyperpocket_llamaindex-0.1.9}/README.md +0 -0
- {hyperpocket_llamaindex-0.0.1 → hyperpocket_llamaindex-0.1.9}/hyperpocket_llamaindex/__init__.py +0 -0
@@ -0,0 +1,157 @@
|
|
1
|
+
.vs/
|
2
|
+
.vscode/
|
3
|
+
.idea/
|
4
|
+
# Byte-compiled / optimized / DLL files
|
5
|
+
__pycache__/
|
6
|
+
*.py[cod]
|
7
|
+
*$py.class
|
8
|
+
|
9
|
+
# C extensions
|
10
|
+
*.so
|
11
|
+
|
12
|
+
# Distribution / packaging
|
13
|
+
.Python
|
14
|
+
build/
|
15
|
+
develop-eggs/
|
16
|
+
dist/
|
17
|
+
downloads/
|
18
|
+
eggs/
|
19
|
+
.eggs/
|
20
|
+
lib/
|
21
|
+
lib64/
|
22
|
+
parts/
|
23
|
+
sdist/
|
24
|
+
var/
|
25
|
+
wheels/
|
26
|
+
pip-wheel-metadata/
|
27
|
+
share/python-wheels/
|
28
|
+
*.egg-info/
|
29
|
+
.installed.cfg
|
30
|
+
*.egg
|
31
|
+
MANIFEST
|
32
|
+
|
33
|
+
# Google GitHub Actions credentials files created by:
|
34
|
+
# https://github.com/google-github-actions/auth
|
35
|
+
#
|
36
|
+
# That action recommends adding this gitignore to prevent accidentally committing keys.
|
37
|
+
gha-creds-*.json
|
38
|
+
|
39
|
+
# PyInstaller
|
40
|
+
# Usually these files are written by a python script from a template
|
41
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
42
|
+
*.manifest
|
43
|
+
*.spec
|
44
|
+
|
45
|
+
# Unit test / coverage reports
|
46
|
+
htmlcov/
|
47
|
+
.tox/
|
48
|
+
.nox/
|
49
|
+
.coverage
|
50
|
+
.coverage.*
|
51
|
+
.cache
|
52
|
+
nosetests.xml
|
53
|
+
coverage.xml
|
54
|
+
*.cover
|
55
|
+
*.py,cover
|
56
|
+
.hypothesis/
|
57
|
+
.pytest_cache/
|
58
|
+
|
59
|
+
# Translations
|
60
|
+
*.mo
|
61
|
+
*.pot
|
62
|
+
|
63
|
+
# Django stuff:
|
64
|
+
*.log
|
65
|
+
local_settings.py
|
66
|
+
db.sqlite3
|
67
|
+
db.sqlite3-journal
|
68
|
+
|
69
|
+
# Flask stuff:
|
70
|
+
instance/
|
71
|
+
.webassets-cache
|
72
|
+
|
73
|
+
# Scrapy stuff:
|
74
|
+
.scrapy
|
75
|
+
|
76
|
+
|
77
|
+
# Jupyter Notebook
|
78
|
+
.ipynb_checkpoints
|
79
|
+
notebooks/
|
80
|
+
|
81
|
+
# IPython
|
82
|
+
profile_default/
|
83
|
+
ipython_config.py
|
84
|
+
|
85
|
+
# pyenv
|
86
|
+
.python-version
|
87
|
+
|
88
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
89
|
+
__pypackages__/
|
90
|
+
|
91
|
+
# Celery stuff
|
92
|
+
celerybeat-schedule
|
93
|
+
celerybeat.pid
|
94
|
+
|
95
|
+
# SageMath parsed files
|
96
|
+
*.sage.py
|
97
|
+
|
98
|
+
# Environments
|
99
|
+
.env
|
100
|
+
.envrc
|
101
|
+
.venv*
|
102
|
+
venv*
|
103
|
+
env/
|
104
|
+
ENV/
|
105
|
+
env.bak/
|
106
|
+
|
107
|
+
# Spyder project settings
|
108
|
+
.spyderproject
|
109
|
+
.spyproject
|
110
|
+
|
111
|
+
# Rope project settings
|
112
|
+
.ropeproject
|
113
|
+
|
114
|
+
# mkdocs documentation
|
115
|
+
/site
|
116
|
+
|
117
|
+
# mypy
|
118
|
+
.mypy_cache/
|
119
|
+
.mypy_cache_test/
|
120
|
+
.dmypy.json
|
121
|
+
dmypy.json
|
122
|
+
|
123
|
+
# Pyre type checker
|
124
|
+
.pyre/
|
125
|
+
|
126
|
+
# macOS display setting files
|
127
|
+
.DS_Store
|
128
|
+
|
129
|
+
# Wandb directory
|
130
|
+
wandb/
|
131
|
+
|
132
|
+
# asdf tool versions
|
133
|
+
.tool-versions
|
134
|
+
/.ruff_cache/
|
135
|
+
|
136
|
+
*.pkl
|
137
|
+
*.bin
|
138
|
+
|
139
|
+
# integration test artifacts
|
140
|
+
data_map*
|
141
|
+
\[('_type', 'fake'), ('stop', None)]
|
142
|
+
|
143
|
+
# Replit files
|
144
|
+
*replit*
|
145
|
+
|
146
|
+
|
147
|
+
prof
|
148
|
+
virtualenv/
|
149
|
+
|
150
|
+
# Ignore dynaconf secret files
|
151
|
+
**/.secrets.toml
|
152
|
+
*.xml
|
153
|
+
*.iml
|
154
|
+
pocket.lock
|
155
|
+
.log/
|
156
|
+
.pocket/
|
157
|
+
_build/
|
@@ -1,16 +1,10 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: hyperpocket-llamaindex
|
3
|
-
Version: 0.
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
Requires-
|
8
|
-
Classifier: Programming Language :: Python :: 3
|
9
|
-
Classifier: Programming Language :: Python :: 3.11
|
10
|
-
Classifier: Programming Language :: Python :: 3.12
|
11
|
-
Classifier: Programming Language :: Python :: 3.13
|
12
|
-
Requires-Dist: hyperpocket (==0.0.3)
|
13
|
-
Requires-Dist: llama-index (>=0.12.5,<0.13.0)
|
3
|
+
Version: 0.1.9
|
4
|
+
Author-email: Hyperpocket Team <hyperpocket@vessl.ai>
|
5
|
+
Requires-Python: >=3.10
|
6
|
+
Requires-Dist: hyperpocket>=0.0.3
|
7
|
+
Requires-Dist: llama-index>=0.12.5
|
14
8
|
Description-Content-Type: text/markdown
|
15
9
|
|
16
10
|
## Anthropic extensions
|
@@ -56,4 +50,4 @@ llm = OpenAI()
|
|
56
50
|
agent = FunctionCallingAgent.from_tools(
|
57
51
|
tools=tools, llm=llm, verbose=True
|
58
52
|
)
|
59
|
-
```
|
53
|
+
```
|
File without changes
|
@@ -0,0 +1,73 @@
|
|
1
|
+
from typing import List, Optional
|
2
|
+
|
3
|
+
from pydantic import BaseModel
|
4
|
+
|
5
|
+
try:
|
6
|
+
from llama_index.core.tools import FunctionTool, BaseTool, ToolMetadata
|
7
|
+
except ImportError:
|
8
|
+
raise ImportError(
|
9
|
+
"You need to install llama-index to use pocket llamaindex"
|
10
|
+
)
|
11
|
+
|
12
|
+
from hyperpocket import Pocket
|
13
|
+
from hyperpocket.tool import Tool
|
14
|
+
|
15
|
+
|
16
|
+
class PocketLlamaindex(Pocket):
|
17
|
+
def get_tools(self, use_profile: Optional[bool] = None) -> List[BaseTool]:
|
18
|
+
if use_profile is not None:
|
19
|
+
self.use_profile = use_profile
|
20
|
+
|
21
|
+
tools = [self.get_tool(pk) for pk in self.core.tools.values()]
|
22
|
+
return tools
|
23
|
+
|
24
|
+
def get_tool(self, pocket_tool: Tool) -> BaseTool:
|
25
|
+
def _invoke(**kwargs) -> str:
|
26
|
+
if self.use_profile:
|
27
|
+
body = kwargs["body"]
|
28
|
+
thread_id = kwargs.pop("thread_id", "default")
|
29
|
+
profile = kwargs.pop("profile", "default")
|
30
|
+
else:
|
31
|
+
body = kwargs
|
32
|
+
thread_id = "default"
|
33
|
+
profile = "default"
|
34
|
+
|
35
|
+
if isinstance(body, BaseModel):
|
36
|
+
body = body.model_dump()
|
37
|
+
|
38
|
+
result, interrupted = self.invoke_with_state(pocket_tool.name, body=body, thread_id=thread_id,
|
39
|
+
profile=profile, **kwargs)
|
40
|
+
say = result
|
41
|
+
if interrupted:
|
42
|
+
say = f'{say}\n\nThe tool execution interrupted. Please talk to me to resume.'
|
43
|
+
return say
|
44
|
+
|
45
|
+
async def _ainvoke(**kwargs) -> str:
|
46
|
+
if self.use_profile:
|
47
|
+
body = kwargs["body"]
|
48
|
+
thread_id = kwargs.pop("thread_id", "default")
|
49
|
+
profile = kwargs.pop("profile", "default")
|
50
|
+
else:
|
51
|
+
body = kwargs
|
52
|
+
thread_id = "default"
|
53
|
+
profile = "default"
|
54
|
+
|
55
|
+
if isinstance(body, BaseModel):
|
56
|
+
body = body.model_dump()
|
57
|
+
|
58
|
+
result, interrupted = await self.ainvoke_with_state(pocket_tool.name, body=body,
|
59
|
+
thread_id=thread_id, profile=profile, **kwargs)
|
60
|
+
say = result
|
61
|
+
if interrupted:
|
62
|
+
say = f'{say}\n\nThe tool execution interrupted. Please talk to me to resume.'
|
63
|
+
return say
|
64
|
+
|
65
|
+
return FunctionTool.from_defaults(
|
66
|
+
fn=_invoke,
|
67
|
+
async_fn=_ainvoke,
|
68
|
+
tool_metadata=ToolMetadata(
|
69
|
+
name=pocket_tool.name,
|
70
|
+
description=pocket_tool.get_description(use_profile=self.use_profile),
|
71
|
+
fn_schema=pocket_tool.schema_model(use_profile=self.use_profile),
|
72
|
+
)
|
73
|
+
)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
|
2
|
+
[project]
|
3
|
+
name = "hyperpocket-llamaindex"
|
4
|
+
version = "0.1.9"
|
5
|
+
description = ""
|
6
|
+
authors = [{ name = "Hyperpocket Team", email = "hyperpocket@vessl.ai" }]
|
7
|
+
requires-python = ">=3.10"
|
8
|
+
readme = "README.md"
|
9
|
+
dependencies = ["llama-index>=0.12.5", "hyperpocket>=0.0.3"]
|
10
|
+
|
11
|
+
[tool.uv.sources]
|
12
|
+
hyperpocket = { path = "../../hyperpocket", editable = true }
|
13
|
+
|
14
|
+
[dependency-groups]
|
15
|
+
dev = ["pytest>=8.3.4", "ruff>=0.8.6"]
|
16
|
+
|
17
|
+
[build-system]
|
18
|
+
requires = ["hatchling"]
|
19
|
+
build-backend = "hatchling.build"
|
20
|
+
|
21
|
+
[tool.ruff.lint]
|
22
|
+
select = [
|
23
|
+
"E", # pycodestyle errors,
|
24
|
+
"F", # pyflakes errors,
|
25
|
+
"I", # isort errors,
|
26
|
+
]
|
27
|
+
ignore = [
|
28
|
+
"E501", # line too long, handled by formatting
|
29
|
+
]
|
30
|
+
|
31
|
+
[tool.ruff]
|
32
|
+
line-length = 88
|
33
|
+
target-version = "py310"
|
34
|
+
|
35
|
+
[tool.ruff.lint.per-file-ignores]
|
36
|
+
"__init__.py" = ["F401"]
|
File without changes
|
@@ -0,0 +1,137 @@
|
|
1
|
+
import ast
|
2
|
+
import json
|
3
|
+
from unittest.async_case import IsolatedAsyncioTestCase
|
4
|
+
|
5
|
+
from llama_index.agent.openai import OpenAIAgent
|
6
|
+
from llama_index.llms.openai import OpenAI
|
7
|
+
from pydantic import BaseModel
|
8
|
+
|
9
|
+
from hyperpocket.config import config, secret
|
10
|
+
from hyperpocket.tool import from_git
|
11
|
+
from hyperpocket_llamaindex import PocketLlamaindex
|
12
|
+
|
13
|
+
|
14
|
+
class TestPocketLlamaindexNoProfile(IsolatedAsyncioTestCase):
|
15
|
+
|
16
|
+
async def asyncSetUp(self):
|
17
|
+
config.public_server_port = "https"
|
18
|
+
config.public_hostname = "localhost"
|
19
|
+
config.public_server_port = 8001
|
20
|
+
config.internal_server_port = 8000
|
21
|
+
config.enable_local_callback_proxy = True
|
22
|
+
|
23
|
+
self.pocket = PocketLlamaindex(
|
24
|
+
tools=[
|
25
|
+
from_git("https://github.com/vessl-ai/hyperawesometools", "main",
|
26
|
+
"managed-tools/none/simple-echo-tool"),
|
27
|
+
self.add,
|
28
|
+
self.sub_pydantic_args
|
29
|
+
],
|
30
|
+
use_profile=False
|
31
|
+
)
|
32
|
+
|
33
|
+
self.llm = OpenAI(model="gpt-4o", api_key=secret["OPENAI_API_KEY"])
|
34
|
+
|
35
|
+
async def asyncTearDown(self):
|
36
|
+
self.pocket._teardown_server()
|
37
|
+
|
38
|
+
async def test_agent_no_profile(self):
|
39
|
+
# given
|
40
|
+
agent = OpenAIAgent.from_tools(
|
41
|
+
tools=self.pocket.get_tools(),
|
42
|
+
llm=OpenAI(model="gpt-4o", api_key=secret["OPENAI_API_KEY"]),
|
43
|
+
verbose=True
|
44
|
+
)
|
45
|
+
|
46
|
+
# when
|
47
|
+
agent.query("add 1, 2")
|
48
|
+
agent.query("sub 1, 2")
|
49
|
+
agent.query("echo 'hello world'")
|
50
|
+
|
51
|
+
async def test_function_tool_no_profile(self):
|
52
|
+
# when
|
53
|
+
response = self.llm.chat_with_tools(user_msg="add 1, 2", tools=self.pocket.get_tools(), verbose=True)
|
54
|
+
message = response.message
|
55
|
+
tool_calls = message.additional_kwargs["tool_calls"]
|
56
|
+
|
57
|
+
tool_name = tool_calls[0].function.name
|
58
|
+
args = tool_calls[0].function.arguments
|
59
|
+
args = json.loads(args)
|
60
|
+
|
61
|
+
result = await self.pocket.ainvoke(tool_name=tool_name, body=args)
|
62
|
+
|
63
|
+
# then
|
64
|
+
self.assertEqual(tool_name, "add")
|
65
|
+
self.assertEqual(args, {
|
66
|
+
"a": 1,
|
67
|
+
"b": 2,
|
68
|
+
})
|
69
|
+
self.assertEqual(result, '3')
|
70
|
+
|
71
|
+
async def test_pydantic_function_tool_no_profile(self):
|
72
|
+
# when
|
73
|
+
response = self.llm.chat_with_tools(user_msg="sub 1, 2", tools=self.pocket.get_tools(), verbose=True)
|
74
|
+
tool_calls = response.message.additional_kwargs["tool_calls"]
|
75
|
+
|
76
|
+
tool_name = tool_calls[0].function.name
|
77
|
+
args = tool_calls[0].function.arguments
|
78
|
+
args = json.loads(args)
|
79
|
+
|
80
|
+
result = await self.pocket.ainvoke(tool_name=tool_name, body=args)
|
81
|
+
|
82
|
+
# then
|
83
|
+
self.assertEqual(tool_name, "sub_pydantic_args")
|
84
|
+
self.assertEqual(args, {
|
85
|
+
"a": {"first": 1},
|
86
|
+
"b": {"second": 2},
|
87
|
+
})
|
88
|
+
self.assertEqual(result, '-1')
|
89
|
+
|
90
|
+
async def test_wasm_tool_no_profile(self):
|
91
|
+
# when
|
92
|
+
response = self.llm.chat_with_tools(user_msg="echo 'hello world'", tools=self.pocket.get_tools(), verbose=True)
|
93
|
+
tool_calls = response.message.additional_kwargs["tool_calls"]
|
94
|
+
|
95
|
+
tool_name = tool_calls[0].function.name
|
96
|
+
args = tool_calls[0].function.arguments
|
97
|
+
args = json.loads(args)
|
98
|
+
|
99
|
+
result = await self.pocket.ainvoke(tool_name=tool_name, body=args)
|
100
|
+
output = ast.literal_eval(result)
|
101
|
+
|
102
|
+
# then
|
103
|
+
self.assertEqual(tool_name, "simple_echo_text")
|
104
|
+
self.assertEqual(args, {
|
105
|
+
"text": "hello world"
|
106
|
+
})
|
107
|
+
self.assertTrue(output["stdout"].startswith("echo message : hello world"))
|
108
|
+
|
109
|
+
@staticmethod
|
110
|
+
def add(a: int, b: int) -> int:
|
111
|
+
"""
|
112
|
+
Add two numbers
|
113
|
+
|
114
|
+
Args:
|
115
|
+
a(int): first number
|
116
|
+
b(int): second number
|
117
|
+
|
118
|
+
"""
|
119
|
+
|
120
|
+
return a + b
|
121
|
+
|
122
|
+
class FirstNumber(BaseModel):
|
123
|
+
first: int
|
124
|
+
|
125
|
+
class SecondNumber(BaseModel):
|
126
|
+
second: int
|
127
|
+
|
128
|
+
@staticmethod
|
129
|
+
def sub_pydantic_args(a: FirstNumber, b: SecondNumber):
|
130
|
+
"""
|
131
|
+
sub two numbers
|
132
|
+
|
133
|
+
Args:
|
134
|
+
a(FirstNumber): first number
|
135
|
+
b(SecondNumber): second number
|
136
|
+
"""
|
137
|
+
return a.first - b.second
|
@@ -0,0 +1,137 @@
|
|
1
|
+
import ast
|
2
|
+
import json
|
3
|
+
from unittest.async_case import IsolatedAsyncioTestCase
|
4
|
+
|
5
|
+
from llama_index.agent.openai import OpenAIAgent
|
6
|
+
from llama_index.llms.openai import OpenAI
|
7
|
+
from pydantic import BaseModel
|
8
|
+
|
9
|
+
from hyperpocket.config import config, secret
|
10
|
+
from hyperpocket.tool import from_git
|
11
|
+
from hyperpocket_llamaindex import PocketLlamaindex
|
12
|
+
|
13
|
+
|
14
|
+
class TestPocketLlamaindexUseProfile(IsolatedAsyncioTestCase):
|
15
|
+
|
16
|
+
async def asyncSetUp(self):
|
17
|
+
config.public_server_port = "https"
|
18
|
+
config.public_hostname = "localhost"
|
19
|
+
config.public_server_port = 8001
|
20
|
+
config.internal_server_port = 8000
|
21
|
+
config.enable_local_callback_proxy = True
|
22
|
+
|
23
|
+
self.pocket = PocketLlamaindex(
|
24
|
+
tools=[
|
25
|
+
from_git("https://github.com/vessl-ai/hyperawesometools", "main",
|
26
|
+
"managed-tools/none/simple-echo-tool"),
|
27
|
+
self.add,
|
28
|
+
self.sub_pydantic_args
|
29
|
+
],
|
30
|
+
use_profile=True
|
31
|
+
)
|
32
|
+
|
33
|
+
self.llm = OpenAI(model="gpt-4o", api_key=secret["OPENAI_API_KEY"])
|
34
|
+
|
35
|
+
async def asyncTearDown(self):
|
36
|
+
self.pocket._teardown_server()
|
37
|
+
|
38
|
+
async def test_agent_use_profile(self):
|
39
|
+
# given
|
40
|
+
agent = OpenAIAgent.from_tools(
|
41
|
+
tools=self.pocket.get_tools(),
|
42
|
+
llm=OpenAI(model="gpt-4o", api_key=secret["OPENAI_API_KEY"]),
|
43
|
+
verbose=True
|
44
|
+
)
|
45
|
+
|
46
|
+
# when
|
47
|
+
agent.query("add 1, 2")
|
48
|
+
agent.query("sub 1, 2")
|
49
|
+
agent.query("echo 'hello world'")
|
50
|
+
|
51
|
+
async def test_function_tool(self):
|
52
|
+
# when
|
53
|
+
response = self.llm.chat_with_tools(user_msg="add 1, 2", tools=self.pocket.get_tools(), verbose=True)
|
54
|
+
message = response.message
|
55
|
+
tool_calls = message.additional_kwargs["tool_calls"]
|
56
|
+
|
57
|
+
tool_name = tool_calls[0].function.name
|
58
|
+
args = tool_calls[0].function.arguments
|
59
|
+
args = json.loads(args)
|
60
|
+
|
61
|
+
result = await self.pocket.ainvoke(tool_name=tool_name, **args)
|
62
|
+
|
63
|
+
# then
|
64
|
+
self.assertEqual(tool_name, "add")
|
65
|
+
self.assertEqual(args["body"], {
|
66
|
+
"a": 1,
|
67
|
+
"b": 2,
|
68
|
+
})
|
69
|
+
self.assertEqual(result, '3')
|
70
|
+
|
71
|
+
async def test_pydantic_function_tool(self):
|
72
|
+
# when
|
73
|
+
response = self.llm.chat_with_tools(user_msg="sub 1, 2", tools=self.pocket.get_tools(), verbose=True)
|
74
|
+
tool_calls = response.message.additional_kwargs["tool_calls"]
|
75
|
+
|
76
|
+
tool_name = tool_calls[0].function.name
|
77
|
+
args = tool_calls[0].function.arguments
|
78
|
+
args = json.loads(args)
|
79
|
+
|
80
|
+
result = await self.pocket.ainvoke(tool_name=tool_name, **args)
|
81
|
+
|
82
|
+
# then
|
83
|
+
self.assertEqual(tool_name, "sub_pydantic_args")
|
84
|
+
self.assertEqual(args["body"], {
|
85
|
+
"a": {"first": 1},
|
86
|
+
"b": {"second": 2},
|
87
|
+
})
|
88
|
+
self.assertEqual(result, '-1')
|
89
|
+
|
90
|
+
async def test_wasm_tool(self):
|
91
|
+
# when
|
92
|
+
response = self.llm.chat_with_tools(user_msg="echo 'hello world'", tools=self.pocket.get_tools(), verbose=True)
|
93
|
+
tool_calls = response.message.additional_kwargs["tool_calls"]
|
94
|
+
|
95
|
+
tool_name = tool_calls[0].function.name
|
96
|
+
args = tool_calls[0].function.arguments
|
97
|
+
args = json.loads(args)
|
98
|
+
|
99
|
+
result = await self.pocket.ainvoke(tool_name=tool_name, **args)
|
100
|
+
output = ast.literal_eval(result)
|
101
|
+
|
102
|
+
# then
|
103
|
+
self.assertEqual(tool_name, "simple_echo_text")
|
104
|
+
self.assertEqual(args["body"], {
|
105
|
+
"text": "hello world"
|
106
|
+
})
|
107
|
+
self.assertTrue(output["stdout"].startswith("echo message : hello world"))
|
108
|
+
|
109
|
+
@staticmethod
|
110
|
+
def add(a: int, b: int) -> int:
|
111
|
+
"""
|
112
|
+
Add two numbers
|
113
|
+
|
114
|
+
Args:
|
115
|
+
a(int): first number
|
116
|
+
b(int): second number
|
117
|
+
|
118
|
+
"""
|
119
|
+
|
120
|
+
return a + b
|
121
|
+
|
122
|
+
class FirstNumber(BaseModel):
|
123
|
+
first: int
|
124
|
+
|
125
|
+
class SecondNumber(BaseModel):
|
126
|
+
second: int
|
127
|
+
|
128
|
+
@staticmethod
|
129
|
+
def sub_pydantic_args(a: FirstNumber, b: SecondNumber):
|
130
|
+
"""
|
131
|
+
sub two numbers
|
132
|
+
|
133
|
+
Args:
|
134
|
+
a(FirstNumber): first number
|
135
|
+
b(SecondNumber): second number
|
136
|
+
"""
|
137
|
+
return a.first - b.second
|