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.
@@ -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
1
+ Metadata-Version: 2.4
2
2
  Name: hyperpocket-llamaindex
3
- Version: 0.0.1
4
- Summary:
5
- Author: moon
6
- Author-email: moon@vessl.ai
7
- Requires-Python: >=3.11,<4.0
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