hyperpocket-llamaindex 0.0.1__tar.gz → 0.1.9__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
@@ -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