hyperforge-static 1.0.0.post20__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.
- hyperforge_static-1.0.0.post20/PKG-INFO +19 -0
- hyperforge_static-1.0.0.post20/README.md +1 -0
- hyperforge_static-1.0.0.post20/pyproject.toml +38 -0
- hyperforge_static-1.0.0.post20/setup.cfg +4 -0
- hyperforge_static-1.0.0.post20/src/hyperforge_static/__init__.py +3 -0
- hyperforge_static-1.0.0.post20/src/hyperforge_static/agent.py +96 -0
- hyperforge_static-1.0.0.post20/src/hyperforge_static/config.py +33 -0
- hyperforge_static-1.0.0.post20/src/hyperforge_static.egg-info/PKG-INFO +19 -0
- hyperforge_static-1.0.0.post20/src/hyperforge_static.egg-info/SOURCES.txt +11 -0
- hyperforge_static-1.0.0.post20/src/hyperforge_static.egg-info/dependency_links.txt +1 -0
- hyperforge_static-1.0.0.post20/src/hyperforge_static.egg-info/requires.txt +1 -0
- hyperforge_static-1.0.0.post20/src/hyperforge_static.egg-info/top_level.txt +1 -0
- hyperforge_static-1.0.0.post20/tests/test_static.py +79 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hyperforge_static
|
|
3
|
+
Version: 1.0.0.post20
|
|
4
|
+
Summary: Static Context Hyperforge agent
|
|
5
|
+
Author-email: Nuclia <nucliadb@nuclia.com>
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://progress.com
|
|
8
|
+
Project-URL: Repository, https://github.com/nuclia/forge
|
|
9
|
+
Classifier: Programming Language :: Python
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
14
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
15
|
+
Requires-Python: <4,>=3.10
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
Requires-Dist: hyperforge
|
|
18
|
+
|
|
19
|
+
# Advanced Generation Hyperforge agents
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Advanced Generation Hyperforge agents
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "hyperforge_static"
|
|
7
|
+
version = "1.0.0.post20"
|
|
8
|
+
license = "Apache-2.0"
|
|
9
|
+
description = "Static Context Hyperforge agent"
|
|
10
|
+
authors = [{ name = "Nuclia", email = "nucliadb@nuclia.com" }]
|
|
11
|
+
readme = "README.md"
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Programming Language :: Python",
|
|
14
|
+
"Programming Language :: Python :: 3.10",
|
|
15
|
+
"Programming Language :: Python :: 3.11",
|
|
16
|
+
"Programming Language :: Python :: 3.12",
|
|
17
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
18
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
19
|
+
]
|
|
20
|
+
requires-python = ">=3.10, <4"
|
|
21
|
+
dependencies = ["hyperforge"]
|
|
22
|
+
|
|
23
|
+
[dependency-groups]
|
|
24
|
+
# these dependencies are actually in the src/ folder (under
|
|
25
|
+
# src/nucliadb_utils/tests/), but only used when the module is imported
|
|
26
|
+
dev = [
|
|
27
|
+
"pytest",
|
|
28
|
+
"pytest-benchmark",
|
|
29
|
+
"pytest-docker-fixtures>=1.4.2",
|
|
30
|
+
"pytest-lazy-fixtures",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[project.urls]
|
|
34
|
+
Homepage = "https://progress.com"
|
|
35
|
+
Repository = "https://github.com/nuclia/forge"
|
|
36
|
+
|
|
37
|
+
[tool.pytest.ini_options]
|
|
38
|
+
asyncio_mode = "auto"
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
from time import time
|
|
2
|
+
from typing import Any, ClassVar, Dict, List, Optional, Tuple
|
|
3
|
+
from uuid import uuid4
|
|
4
|
+
|
|
5
|
+
from hyperforge.agent import Agent
|
|
6
|
+
from hyperforge.configure import agent
|
|
7
|
+
from hyperforge.context.agent import ContextAgent
|
|
8
|
+
from hyperforge.definition import FunctionDefinition
|
|
9
|
+
from hyperforge.manager import Manager
|
|
10
|
+
from hyperforge.memory.memory import Chunk, Context, QuestionMemory
|
|
11
|
+
|
|
12
|
+
from hyperforge_static.config import StaticAgentConfig
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@agent(
|
|
16
|
+
id="static",
|
|
17
|
+
agent_type="context",
|
|
18
|
+
title="Static Context",
|
|
19
|
+
description="Provide static context to answer questions.",
|
|
20
|
+
config_schema=StaticAgentConfig,
|
|
21
|
+
)
|
|
22
|
+
class StaticAgent(ContextAgent, Agent[StaticAgentConfig]):
|
|
23
|
+
__published_functions__: ClassVar[Dict[str, FunctionDefinition]] = {
|
|
24
|
+
"static_context": FunctionDefinition(
|
|
25
|
+
name="static_context",
|
|
26
|
+
description="Provide static context to answer questions.",
|
|
27
|
+
parameters={},
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async def static_context(
|
|
32
|
+
self,
|
|
33
|
+
memory: QuestionMemory,
|
|
34
|
+
manager: Manager,
|
|
35
|
+
question: Optional[str] = "",
|
|
36
|
+
question_uuid: Optional[str] = None,
|
|
37
|
+
) -> Context:
|
|
38
|
+
if question_uuid is None:
|
|
39
|
+
question_uuid = uuid4().hex
|
|
40
|
+
|
|
41
|
+
context = Context(
|
|
42
|
+
agent_id=self.config.id if self.config.id else "static_context",
|
|
43
|
+
original_question_uuid=memory.original_question_uuid,
|
|
44
|
+
actual_question_uuid=question_uuid,
|
|
45
|
+
question=question,
|
|
46
|
+
source="static_context",
|
|
47
|
+
agent="static_context",
|
|
48
|
+
title=self.config.title if self.config.title else "Static Context",
|
|
49
|
+
)
|
|
50
|
+
if self.config.context:
|
|
51
|
+
context.chunks.append(
|
|
52
|
+
Chunk(
|
|
53
|
+
chunk_id=uuid4().hex,
|
|
54
|
+
text=self.config.context,
|
|
55
|
+
origin_agent=self.config.module,
|
|
56
|
+
)
|
|
57
|
+
)
|
|
58
|
+
if self.config.structured:
|
|
59
|
+
context.structured.append(self.config.structured)
|
|
60
|
+
return context
|
|
61
|
+
|
|
62
|
+
async def _get_question_context(
|
|
63
|
+
self,
|
|
64
|
+
memory: QuestionMemory,
|
|
65
|
+
manager: Manager,
|
|
66
|
+
question_uuid: str,
|
|
67
|
+
question: str,
|
|
68
|
+
flow_id: str,
|
|
69
|
+
extra_context: Optional[Dict[str, Any]] = None,
|
|
70
|
+
) -> List[Tuple[str, str]]:
|
|
71
|
+
t0 = time()
|
|
72
|
+
error = None
|
|
73
|
+
|
|
74
|
+
context = await self.static_context(
|
|
75
|
+
memory=memory,
|
|
76
|
+
manager=manager,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
await memory.add_step(
|
|
80
|
+
step_module=self.config.module,
|
|
81
|
+
step_title=self.step_title("Static context"),
|
|
82
|
+
step_agent_path=f"/context/{self.config.id if self.config.id else 'default'}",
|
|
83
|
+
step_value=" Static context retrieval",
|
|
84
|
+
timeit=time() - t0,
|
|
85
|
+
input_nuclia_tokens=0,
|
|
86
|
+
output_nuclia_tokens=0,
|
|
87
|
+
error=error,
|
|
88
|
+
)
|
|
89
|
+
missing = await self.save_ctx_and_return_missing(
|
|
90
|
+
context=context,
|
|
91
|
+
question=question,
|
|
92
|
+
memory=memory,
|
|
93
|
+
manager=manager,
|
|
94
|
+
flow_id=flow_id,
|
|
95
|
+
)
|
|
96
|
+
return [missing] if missing is not None else []
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from typing import Literal, Optional, Tuple
|
|
2
|
+
|
|
3
|
+
from hyperforge.context.config import ContextAgentConfig
|
|
4
|
+
from hyperforge.utils import WidgetType
|
|
5
|
+
from pydantic import Field
|
|
6
|
+
from pydantic.config import ConfigDict
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class StaticAgentConfig(ContextAgentConfig):
|
|
10
|
+
model_config = ConfigDict(title="Static data")
|
|
11
|
+
module: Literal["static"] = "static"
|
|
12
|
+
published_functions: Optional[Tuple[str, ...]] = Field(
|
|
13
|
+
default=("static_context",),
|
|
14
|
+
title="Published functions",
|
|
15
|
+
description="List of functions published by this agent to be used by other agents in the chain",
|
|
16
|
+
json_schema_extra={
|
|
17
|
+
"widget": WidgetType.NOT_SHOWN,
|
|
18
|
+
},
|
|
19
|
+
)
|
|
20
|
+
context: Optional[str] = Field(
|
|
21
|
+
None,
|
|
22
|
+
description="Static context to be used by the agent",
|
|
23
|
+
json_schema_extra={
|
|
24
|
+
"widget": WidgetType.EXPANDABLE_TEXTAREA,
|
|
25
|
+
},
|
|
26
|
+
)
|
|
27
|
+
structured: Optional[str] = Field(
|
|
28
|
+
None,
|
|
29
|
+
description="Structured data in JSON format to be used by the agent",
|
|
30
|
+
json_schema_extra={
|
|
31
|
+
"widget": WidgetType.EXPANDABLE_TEXTAREA,
|
|
32
|
+
},
|
|
33
|
+
)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hyperforge_static
|
|
3
|
+
Version: 1.0.0.post20
|
|
4
|
+
Summary: Static Context Hyperforge agent
|
|
5
|
+
Author-email: Nuclia <nucliadb@nuclia.com>
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://progress.com
|
|
8
|
+
Project-URL: Repository, https://github.com/nuclia/forge
|
|
9
|
+
Classifier: Programming Language :: Python
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
14
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
15
|
+
Requires-Python: <4,>=3.10
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
Requires-Dist: hyperforge
|
|
18
|
+
|
|
19
|
+
# Advanced Generation Hyperforge agents
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/hyperforge_static/__init__.py
|
|
4
|
+
src/hyperforge_static/agent.py
|
|
5
|
+
src/hyperforge_static/config.py
|
|
6
|
+
src/hyperforge_static.egg-info/PKG-INFO
|
|
7
|
+
src/hyperforge_static.egg-info/SOURCES.txt
|
|
8
|
+
src/hyperforge_static.egg-info/dependency_links.txt
|
|
9
|
+
src/hyperforge_static.egg-info/requires.txt
|
|
10
|
+
src/hyperforge_static.egg-info/top_level.txt
|
|
11
|
+
tests/test_static.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
hyperforge
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
hyperforge_static
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from unittest.mock import MagicMock
|
|
2
|
+
from uuid import uuid4
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
from hyperforge.manager import Manager
|
|
6
|
+
from hyperforge.memory.memory import EphemeralSessionMemory
|
|
7
|
+
from hyperforge.models import MemoryConfig, Rules
|
|
8
|
+
from hyperforge_static.agent import StaticAgent
|
|
9
|
+
from hyperforge_static.config import StaticAgentConfig
|
|
10
|
+
|
|
11
|
+
pytestmark = pytest.mark.asyncio
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
async def test_static_agent():
|
|
15
|
+
# 1. Create a mocked manager
|
|
16
|
+
manager = MagicMock(spec=Manager)
|
|
17
|
+
|
|
18
|
+
# 2. Create the configuration for StaticAgent
|
|
19
|
+
config = StaticAgentConfig(
|
|
20
|
+
id="test-static",
|
|
21
|
+
title="Static Context",
|
|
22
|
+
context="This is a test static context text.",
|
|
23
|
+
structured="{'key': 'value'}",
|
|
24
|
+
prune_context=False,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
# 3. Create the StaticAgent instance
|
|
28
|
+
agent = StaticAgent(config=config)
|
|
29
|
+
|
|
30
|
+
# 4. Set up EphemeralSessionMemory and QuestionMemory
|
|
31
|
+
session = EphemeralSessionMemory.from_config(
|
|
32
|
+
config=MemoryConfig(), agent_id="test", workflow_id="test", rules=Rules()
|
|
33
|
+
)
|
|
34
|
+
session.init("test-session")
|
|
35
|
+
memory = session.start_question("What is the static context?")
|
|
36
|
+
flow_id = uuid4().hex
|
|
37
|
+
|
|
38
|
+
# 5. Call static_context directly
|
|
39
|
+
context = await agent.static_context(
|
|
40
|
+
memory=memory,
|
|
41
|
+
manager=manager,
|
|
42
|
+
question="What is the static context?",
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
# 6. Assert static_context returns Context with correct values
|
|
46
|
+
assert context is not None
|
|
47
|
+
assert context.agent_id == "test-static"
|
|
48
|
+
assert context.title == "Static Context"
|
|
49
|
+
assert len(context.chunks) == 1
|
|
50
|
+
assert context.chunks[0].text == "This is a test static context text."
|
|
51
|
+
assert len(context.structured) == 1
|
|
52
|
+
assert context.structured[0] == "{'key': 'value'}"
|
|
53
|
+
|
|
54
|
+
# 7. Call _get_question_context
|
|
55
|
+
missing = await agent._get_question_context(
|
|
56
|
+
memory=memory,
|
|
57
|
+
manager=manager,
|
|
58
|
+
question_uuid=memory.original_question_uuid,
|
|
59
|
+
question="What is the static context?",
|
|
60
|
+
flow_id=flow_id,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
# 8. Assertions on the memory state and missing questions
|
|
64
|
+
assert (
|
|
65
|
+
missing == []
|
|
66
|
+
) # Since no validation/fallback model is used, should return empty list
|
|
67
|
+
|
|
68
|
+
# Check that context is saved to memory under the given flow_id
|
|
69
|
+
saved_contexts = memory.get_agent_contexts(flow_id=flow_id, agent_id="test-static")
|
|
70
|
+
assert len(saved_contexts) == 1
|
|
71
|
+
assert saved_contexts[0].chunks[0].text == "This is a test static context text."
|
|
72
|
+
assert saved_contexts[0].structured[0] == "{'key': 'value'}"
|
|
73
|
+
|
|
74
|
+
# Verify step was added to memory
|
|
75
|
+
assert len(memory.steps) == 1
|
|
76
|
+
step = memory.steps[0]
|
|
77
|
+
assert step.module == "static"
|
|
78
|
+
assert "Static context" in step.title
|
|
79
|
+
assert step.value == " Static context retrieval"
|