hyperforge-conditional 1.0.0.post19__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.
- hyperforge_conditional/__init__.py +11 -0
- hyperforge_conditional/conditional.py +235 -0
- hyperforge_conditional/context_agent.py +159 -0
- hyperforge_conditional/generation_agent.py +48 -0
- hyperforge_conditional/postprocess_agent.py +47 -0
- hyperforge_conditional/preprocess_agent.py +47 -0
- hyperforge_conditional-1.0.0.post19.dist-info/METADATA +19 -0
- hyperforge_conditional-1.0.0.post19.dist-info/RECORD +10 -0
- hyperforge_conditional-1.0.0.post19.dist-info/WHEEL +5 -0
- hyperforge_conditional-1.0.0.post19.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from .context_agent import ContextConditional
|
|
2
|
+
from .generation_agent import GenerationConditional
|
|
3
|
+
from .postprocess_agent import PostprocessConditional
|
|
4
|
+
from .preprocess_agent import PreprocessConditional
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
"ContextConditional",
|
|
8
|
+
"GenerationConditional",
|
|
9
|
+
"PreprocessConditional",
|
|
10
|
+
"PostprocessConditional",
|
|
11
|
+
]
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from time import time
|
|
3
|
+
from typing import Any, Dict, List, Literal, Optional, cast
|
|
4
|
+
|
|
5
|
+
from hyperforge.agent import Agent, AgentConfig
|
|
6
|
+
from hyperforge.configure import get_agent_config_klass, get_agent_klass
|
|
7
|
+
from hyperforge.manager import Manager
|
|
8
|
+
from hyperforge.memory.memory import QuestionMemory
|
|
9
|
+
from hyperforge.trace import trace_agent
|
|
10
|
+
from hyperforge.utils import WidgetType
|
|
11
|
+
from pydantic import BaseModel, Field, field_serializer, field_validator
|
|
12
|
+
|
|
13
|
+
from hyperforge import PROMPT_ENVIRONMENT
|
|
14
|
+
|
|
15
|
+
CONDITIONAL_AGENT = """
|
|
16
|
+
Given a prompt that indicates a condition , assess whether a given text fulfills it or not.
|
|
17
|
+
# PROMPT:
|
|
18
|
+
{{prompt}}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# TEXT:
|
|
22
|
+
{{text}}
|
|
23
|
+
|
|
24
|
+
{% if similarity %}
|
|
25
|
+
# SIMILAR QUERIES:
|
|
26
|
+
Similar queries that also fulfill that condition
|
|
27
|
+
{% for similar in similarity_examples %}
|
|
28
|
+
- {{similar}}
|
|
29
|
+
{% endfor -%}
|
|
30
|
+
{% endif %}
|
|
31
|
+
|
|
32
|
+
# Important rules to follow
|
|
33
|
+
|
|
34
|
+
{% for rule in rules %}
|
|
35
|
+
{{rule}}
|
|
36
|
+
{% endfor -%}
|
|
37
|
+
|
|
38
|
+
# Output definition:
|
|
39
|
+
|
|
40
|
+
Your output should always follow the following schema in a JSON format (Not markdon, please, start with b...).
|
|
41
|
+
|
|
42
|
+
{{json_schema}}
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
CONDITIONAL_AGENT_TEMPLATE = PROMPT_ENVIRONMENT.from_string(CONDITIONAL_AGENT)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
CONDITIONAL_SCHEMA = {
|
|
49
|
+
"title": "yes_no",
|
|
50
|
+
"description": "Choose yes or no, depending on whether the condition is fulfilled",
|
|
51
|
+
"parameters": {
|
|
52
|
+
"type": "object",
|
|
53
|
+
"properties": {
|
|
54
|
+
"yes": {"type": "boolean"},
|
|
55
|
+
"reason": {"type": "string", "description": "reasoning behind the answer"},
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class ConditionalAgentConfig(AgentConfig):
|
|
62
|
+
then: List[AgentConfig] = Field(
|
|
63
|
+
default_factory=list,
|
|
64
|
+
title="Then",
|
|
65
|
+
description="List of agents to run in case the condition is valid",
|
|
66
|
+
)
|
|
67
|
+
else_: List[AgentConfig] = Field(
|
|
68
|
+
default_factory=list,
|
|
69
|
+
title="Else",
|
|
70
|
+
description="List of agents to run in case the condition is not valid",
|
|
71
|
+
)
|
|
72
|
+
prompt: Optional[str] = Field(
|
|
73
|
+
default=None,
|
|
74
|
+
title="Condition Prompt",
|
|
75
|
+
description="Prompt to evaluate the condition",
|
|
76
|
+
json_schema_extra={
|
|
77
|
+
"show_in_node": True,
|
|
78
|
+
"widget": WidgetType.EXPANDABLE_TEXTAREA,
|
|
79
|
+
},
|
|
80
|
+
)
|
|
81
|
+
has_keywords: Optional[List[str]] = Field(
|
|
82
|
+
default=None,
|
|
83
|
+
title="Keywords",
|
|
84
|
+
description="List of keywords to evaluate the condition",
|
|
85
|
+
)
|
|
86
|
+
similarity: Optional[List[str]] = Field(
|
|
87
|
+
default=None,
|
|
88
|
+
title="Similar Queries",
|
|
89
|
+
description="List of similar queries to evaluate the condition",
|
|
90
|
+
)
|
|
91
|
+
on: Literal["QUESTION", "ANSWER", "CONTEXT"] = Field(
|
|
92
|
+
default="QUESTION",
|
|
93
|
+
title="Evaluate condition on",
|
|
94
|
+
description="Source to evaluate the condition on. ",
|
|
95
|
+
)
|
|
96
|
+
model: str = Field(
|
|
97
|
+
default="chatgpt-o3-mini",
|
|
98
|
+
title="Generative model",
|
|
99
|
+
description="Model used to assess the condition",
|
|
100
|
+
json_schema_extra={"widget": WidgetType.MODEL_SELECT},
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
@field_serializer("then", "else_")
|
|
104
|
+
def serialize_conditional_agent(
|
|
105
|
+
self, field: list[BaseModel]
|
|
106
|
+
) -> Optional[List[Dict[str, Any]]]:
|
|
107
|
+
if field is None:
|
|
108
|
+
return field
|
|
109
|
+
return [agent.model_dump() for agent in field]
|
|
110
|
+
|
|
111
|
+
@field_validator("then", "else_", mode="before")
|
|
112
|
+
@classmethod
|
|
113
|
+
def is_conditional_agent(cls, value: list[Dict[str, Any]]) -> list[BaseModel]:
|
|
114
|
+
if value is None:
|
|
115
|
+
return value
|
|
116
|
+
result = []
|
|
117
|
+
for agent_cfg in value:
|
|
118
|
+
module = agent_cfg.get("module")
|
|
119
|
+
if module is None:
|
|
120
|
+
raise ValueError("Invalid agent config: missing 'module' field")
|
|
121
|
+
|
|
122
|
+
agent_config_klass = get_agent_config_klass(module)
|
|
123
|
+
agent_config_instance = agent_config_klass.model_validate(agent_cfg)
|
|
124
|
+
result.append(agent_config_instance)
|
|
125
|
+
return result # type: ignore
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class Conditional:
|
|
129
|
+
then: Optional[list[Agent]] = None
|
|
130
|
+
else_: Optional[list[Agent]] = None
|
|
131
|
+
arag_step: str
|
|
132
|
+
config: Any
|
|
133
|
+
agent_id: Any
|
|
134
|
+
|
|
135
|
+
async def conditional_from_config(self, config: ConditionalAgentConfig):
|
|
136
|
+
agent_module = None
|
|
137
|
+
then_agents_obj_list = []
|
|
138
|
+
for then_agent in config.then:
|
|
139
|
+
if then_agent:
|
|
140
|
+
agent_module = then_agent.module
|
|
141
|
+
if agent_module is None:
|
|
142
|
+
raise Exception("No agent found")
|
|
143
|
+
|
|
144
|
+
agent_klass = get_agent_klass(agent_module)
|
|
145
|
+
# We dump and load to create the agent via from_config
|
|
146
|
+
then_agents_obj_list.append((agent_klass, then_agent))
|
|
147
|
+
|
|
148
|
+
agent_id = None
|
|
149
|
+
else_agents_obj_list = []
|
|
150
|
+
for else_agent in config.else_:
|
|
151
|
+
if else_agent is not None:
|
|
152
|
+
agent_id = else_agent.module
|
|
153
|
+
if agent_id is None:
|
|
154
|
+
raise Exception("No agent found")
|
|
155
|
+
|
|
156
|
+
agent_class = get_agent_klass(agent_id)
|
|
157
|
+
# We dump and load to create the agent via from_config
|
|
158
|
+
else_agents_obj_list.append((agent_class, else_agent))
|
|
159
|
+
|
|
160
|
+
self.then = await asyncio.gather(
|
|
161
|
+
*[klass.from_config(cfg) for klass, cfg in then_agents_obj_list]
|
|
162
|
+
)
|
|
163
|
+
self.else_ = (
|
|
164
|
+
await asyncio.gather(
|
|
165
|
+
*[klass.from_config(cfg) for klass, cfg in else_agents_obj_list]
|
|
166
|
+
)
|
|
167
|
+
if else_agents_obj_list
|
|
168
|
+
else None
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
async def make_decision(
|
|
172
|
+
self,
|
|
173
|
+
question: str,
|
|
174
|
+
memory: QuestionMemory,
|
|
175
|
+
manager: Manager,
|
|
176
|
+
title: Optional[str] = None,
|
|
177
|
+
) -> bool:
|
|
178
|
+
t0 = time()
|
|
179
|
+
config: ConditionalAgentConfig = cast(ConditionalAgentConfig, self.config)
|
|
180
|
+
|
|
181
|
+
prompt = CONDITIONAL_AGENT_TEMPLATE.render(
|
|
182
|
+
prompt=config.prompt,
|
|
183
|
+
rules=memory.get_rules(),
|
|
184
|
+
text=question,
|
|
185
|
+
similarity_examples=config.similarity,
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
sources, input, output = await manager.execute_json(
|
|
189
|
+
prompt=prompt,
|
|
190
|
+
schema=CONDITIONAL_SCHEMA,
|
|
191
|
+
user_id="conditional",
|
|
192
|
+
model=config.model,
|
|
193
|
+
tracking=memory.get_tracking_info(),
|
|
194
|
+
)
|
|
195
|
+
condition = sources.get("yes", False)
|
|
196
|
+
reason = sources.get("reason")
|
|
197
|
+
|
|
198
|
+
await memory.add_step(
|
|
199
|
+
step_module=config.module,
|
|
200
|
+
step_title=f"{title}: Condition check",
|
|
201
|
+
step_value=str(condition),
|
|
202
|
+
step_reason=reason,
|
|
203
|
+
timeit=time() - t0,
|
|
204
|
+
input_nuclia_tokens=input,
|
|
205
|
+
output_nuclia_tokens=output,
|
|
206
|
+
step_agent_path=f"/{self.arag_step}/{self.agent_id}",
|
|
207
|
+
)
|
|
208
|
+
return condition
|
|
209
|
+
|
|
210
|
+
@trace_agent
|
|
211
|
+
async def __call__(
|
|
212
|
+
self,
|
|
213
|
+
memory: QuestionMemory,
|
|
214
|
+
manager: Manager,
|
|
215
|
+
):
|
|
216
|
+
question = ""
|
|
217
|
+
if self.config.on == "QUESTION" and memory.actual_question:
|
|
218
|
+
question = memory.actual_question
|
|
219
|
+
elif self.config.on == "ANSWER" and memory.final_answer:
|
|
220
|
+
question = memory.final_answer
|
|
221
|
+
elif self.config.on == "CONTEXT":
|
|
222
|
+
question = "\n".join([x.summary for x in memory.contexts])
|
|
223
|
+
|
|
224
|
+
condition = await self.make_decision(
|
|
225
|
+
memory=memory,
|
|
226
|
+
manager=manager,
|
|
227
|
+
question=question,
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
if condition and self.then is not None:
|
|
231
|
+
for then_agent in self.then:
|
|
232
|
+
await then_agent(memory, manager) # type: ignore
|
|
233
|
+
elif condition is False and self.else_ is not None:
|
|
234
|
+
for else_agent in self.else_:
|
|
235
|
+
await else_agent(memory, manager) # type: ignore
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
from typing import Any, Dict, Literal, Optional, cast
|
|
2
|
+
from uuid import uuid4
|
|
3
|
+
|
|
4
|
+
from hyperforge.agent import Agent
|
|
5
|
+
from hyperforge.configure import agent
|
|
6
|
+
from hyperforge.context.agent import ContextAgent, trace_agent
|
|
7
|
+
from hyperforge.context.config import ContextAgentConfig
|
|
8
|
+
from hyperforge.manager import Manager
|
|
9
|
+
from hyperforge.memory.memory import Chunk, Context, QuestionMemory
|
|
10
|
+
from pydantic import Field
|
|
11
|
+
from pydantic.config import ConfigDict
|
|
12
|
+
|
|
13
|
+
from hyperforge_conditional.conditional import (
|
|
14
|
+
Conditional,
|
|
15
|
+
ConditionalAgentConfig,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ContextConditionalAgentConfig(ConditionalAgentConfig, ContextAgentConfig):
|
|
20
|
+
model_config = ConfigDict(title="Condition")
|
|
21
|
+
module: Literal["context_conditional"] = "context_conditional"
|
|
22
|
+
on: Literal["QUESTION", "CONTEXT"] = Field( # type: ignore
|
|
23
|
+
default="QUESTION",
|
|
24
|
+
title="Evaluate condition on",
|
|
25
|
+
description="Source to evaluate the condition on. CONTEXT is only valid when this agent is used as a next agent in a chain.",
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@agent(
|
|
30
|
+
id="context_conditional",
|
|
31
|
+
agent_type="context",
|
|
32
|
+
title="Context Conditional",
|
|
33
|
+
description="Use Context Conditional to get information from the internet to answer questions.",
|
|
34
|
+
config_schema=ContextConditionalAgentConfig,
|
|
35
|
+
)
|
|
36
|
+
class ContextConditional(
|
|
37
|
+
ContextAgent, Conditional, Agent[ContextConditionalAgentConfig]
|
|
38
|
+
):
|
|
39
|
+
arag_step: str = "context"
|
|
40
|
+
|
|
41
|
+
async def inner_from_config(
|
|
42
|
+
self, config: ContextConditionalAgentConfig, agent_id: Optional[str] = None
|
|
43
|
+
):
|
|
44
|
+
# Build then and else branches
|
|
45
|
+
await self.context_from_config(config)
|
|
46
|
+
await self.conditional_from_config(config)
|
|
47
|
+
|
|
48
|
+
async def __call__(self, memory: QuestionMemory, manager: Manager):
|
|
49
|
+
await Conditional.__call__(self, memory, manager)
|
|
50
|
+
|
|
51
|
+
@trace_agent
|
|
52
|
+
async def get_question_context(
|
|
53
|
+
self,
|
|
54
|
+
memory: QuestionMemory,
|
|
55
|
+
manager: Manager,
|
|
56
|
+
question_uuid: str,
|
|
57
|
+
question: str,
|
|
58
|
+
flow_id: str,
|
|
59
|
+
extra_context: Optional[Dict[str, Any]] = None,
|
|
60
|
+
):
|
|
61
|
+
self.config: ContextConditionalAgentConfig # type: ignore
|
|
62
|
+
if extra_context is not None:
|
|
63
|
+
question, question_uuid = await self.rephrase(
|
|
64
|
+
memory=memory,
|
|
65
|
+
manager=manager,
|
|
66
|
+
question_uuid=question_uuid,
|
|
67
|
+
question=question,
|
|
68
|
+
contexts=extra_context,
|
|
69
|
+
model=self.config.rephrase_model,
|
|
70
|
+
module=self.config.module,
|
|
71
|
+
user_id="next_rephrase",
|
|
72
|
+
ident=self.agent_id,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
conditional_subject = question
|
|
76
|
+
# Previous context only used when selected and extra context is provided - that is, the conditional comes after a next agent in the flow
|
|
77
|
+
if self.config.on == "CONTEXT" and extra_context is not None:
|
|
78
|
+
conditional_subject = "\n".join(extra_context.values())
|
|
79
|
+
|
|
80
|
+
# condition checking and branching
|
|
81
|
+
condition = await self.make_decision(
|
|
82
|
+
memory=memory,
|
|
83
|
+
manager=manager,
|
|
84
|
+
question=conditional_subject,
|
|
85
|
+
)
|
|
86
|
+
selected_agents: list[Agent] = [
|
|
87
|
+
agent for agent in (self.then if condition else self.else_) or []
|
|
88
|
+
]
|
|
89
|
+
for selected_agent in selected_agents:
|
|
90
|
+
await cast(ContextAgent, selected_agent).get_question_context(
|
|
91
|
+
memory, manager, question_uuid, question, flow_id=flow_id
|
|
92
|
+
)
|
|
93
|
+
# If fallback is configured, we check if there are missing questions taking into account the executed agents contexts/summaries
|
|
94
|
+
if self.fallback is not None:
|
|
95
|
+
conditional_context = Context(
|
|
96
|
+
agent_id=self.agent_id,
|
|
97
|
+
original_question_uuid=memory.original_question_uuid,
|
|
98
|
+
actual_question_uuid=question_uuid,
|
|
99
|
+
question=question,
|
|
100
|
+
agent="Conditional",
|
|
101
|
+
title="Summarizing Conditional Agents Contexts",
|
|
102
|
+
source="conditional",
|
|
103
|
+
chunks=[],
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
for agent in selected_agents:
|
|
107
|
+
conditional_context.chunks.extend(
|
|
108
|
+
[
|
|
109
|
+
Chunk(
|
|
110
|
+
chunk_id=agent.agent_id,
|
|
111
|
+
text=summary,
|
|
112
|
+
origin_agent=self.config.module,
|
|
113
|
+
)
|
|
114
|
+
for summary in memory.get_agent_answer_summaries(
|
|
115
|
+
flow_id=flow_id, agent_id=agent.agent_id
|
|
116
|
+
)
|
|
117
|
+
]
|
|
118
|
+
)
|
|
119
|
+
(
|
|
120
|
+
_,
|
|
121
|
+
missing_question,
|
|
122
|
+
_,
|
|
123
|
+
) = await self.validate_ctx_and_answer(
|
|
124
|
+
memory,
|
|
125
|
+
manager,
|
|
126
|
+
conditional_context,
|
|
127
|
+
question=question,
|
|
128
|
+
)
|
|
129
|
+
if missing_question is not None and missing_question.strip() != "":
|
|
130
|
+
await self.fallback.get_question_context(
|
|
131
|
+
memory,
|
|
132
|
+
manager,
|
|
133
|
+
question_uuid=uuid4().hex,
|
|
134
|
+
question=missing_question,
|
|
135
|
+
flow_id=flow_id,
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
if self.next_agent is not None:
|
|
139
|
+
extra_context = extra_context or {}
|
|
140
|
+
for agent in ( # type: ignore
|
|
141
|
+
selected_agents + [self.fallback]
|
|
142
|
+
if self.fallback is not None
|
|
143
|
+
else selected_agents
|
|
144
|
+
):
|
|
145
|
+
if agent:
|
|
146
|
+
answer_summaries = memory.get_agent_answer_summaries(
|
|
147
|
+
flow_id=flow_id, agent_id=agent.agent_id
|
|
148
|
+
)
|
|
149
|
+
if answer_summaries:
|
|
150
|
+
extra_context[agent.agent_id] = "\n".join(answer_summaries)
|
|
151
|
+
|
|
152
|
+
await self.next_agent.get_question_context(
|
|
153
|
+
memory,
|
|
154
|
+
manager,
|
|
155
|
+
question_uuid,
|
|
156
|
+
question,
|
|
157
|
+
extra_context=extra_context,
|
|
158
|
+
flow_id=flow_id,
|
|
159
|
+
)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from typing import List, Literal, Optional
|
|
2
|
+
|
|
3
|
+
from hyperforge.agent import Agent, AgentConfig
|
|
4
|
+
from hyperforge.configure import agent
|
|
5
|
+
from hyperforge.manager import Manager
|
|
6
|
+
from hyperforge.memory.memory import QuestionMemory
|
|
7
|
+
from pydantic import Field
|
|
8
|
+
from pydantic.config import ConfigDict
|
|
9
|
+
|
|
10
|
+
from hyperforge_conditional.conditional import (
|
|
11
|
+
Conditional,
|
|
12
|
+
ConditionalAgentConfig,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class GenerationConditionalAgentConfig(ConditionalAgentConfig):
|
|
17
|
+
model_config = ConfigDict(title="Condition")
|
|
18
|
+
module: Literal["generation_conditional"] = "generation_conditional"
|
|
19
|
+
then: List["AgentConfig"] = Field(
|
|
20
|
+
default_factory=list,
|
|
21
|
+
title="Then",
|
|
22
|
+
description="List of agents to run in case the condition is valid",
|
|
23
|
+
)
|
|
24
|
+
else_: List["AgentConfig"] = Field(
|
|
25
|
+
default_factory=list,
|
|
26
|
+
title="Else",
|
|
27
|
+
description="List of agents to run in case the condition is not valid",
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@agent(
|
|
32
|
+
id="generation_conditional",
|
|
33
|
+
agent_type="generation",
|
|
34
|
+
title="Generation Conditional",
|
|
35
|
+
description="Conditional generation agent that decides which generation strategy to use based on the context.",
|
|
36
|
+
config_schema=GenerationConditionalAgentConfig,
|
|
37
|
+
)
|
|
38
|
+
class GenerationConditional(Agent[GenerationConditionalAgentConfig], Conditional):
|
|
39
|
+
arag_step: str = "generation"
|
|
40
|
+
|
|
41
|
+
async def inner_from_config(
|
|
42
|
+
self, config: GenerationConditionalAgentConfig, agent_id: Optional[str] = None
|
|
43
|
+
):
|
|
44
|
+
# Build then and else branches
|
|
45
|
+
await self.conditional_from_config(config)
|
|
46
|
+
|
|
47
|
+
async def __call__(self, memory: QuestionMemory, manager: Manager):
|
|
48
|
+
await Conditional.__call__(self, memory, manager)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from typing import List, Literal, Optional
|
|
2
|
+
|
|
3
|
+
from hyperforge.agent import Agent, AgentConfig
|
|
4
|
+
from hyperforge.configure import agent
|
|
5
|
+
from hyperforge.manager import Manager
|
|
6
|
+
from hyperforge.memory.memory import QuestionMemory
|
|
7
|
+
from pydantic import Field
|
|
8
|
+
from pydantic.config import ConfigDict
|
|
9
|
+
|
|
10
|
+
from hyperforge_conditional.conditional import (
|
|
11
|
+
Conditional,
|
|
12
|
+
ConditionalAgentConfig,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class PostprocessConditionalAgentConfig(ConditionalAgentConfig):
|
|
17
|
+
model_config = ConfigDict(title="Condition")
|
|
18
|
+
module: Literal["post_conditional"] = "post_conditional"
|
|
19
|
+
then: List["AgentConfig"] = Field(
|
|
20
|
+
default_factory=list,
|
|
21
|
+
title="Then",
|
|
22
|
+
description="List of agents to run in case the condition is valid",
|
|
23
|
+
)
|
|
24
|
+
else_: List["AgentConfig"] = Field(
|
|
25
|
+
default_factory=list,
|
|
26
|
+
title="Else",
|
|
27
|
+
description="List of agents to run in case the condition is not valid",
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@agent(
|
|
32
|
+
id="postprocess_conditional",
|
|
33
|
+
agent_type="postprocess",
|
|
34
|
+
title="Postprocess Conditional",
|
|
35
|
+
description="Agent that performs conditional postprocessing.",
|
|
36
|
+
config_schema=PostprocessConditionalAgentConfig,
|
|
37
|
+
)
|
|
38
|
+
class PostprocessConditional(Agent[PostprocessConditionalAgentConfig], Conditional):
|
|
39
|
+
arag_step: str = "postprocess"
|
|
40
|
+
|
|
41
|
+
async def inner_from_config(
|
|
42
|
+
self, config: PostprocessConditionalAgentConfig, agent_id: Optional[str] = None
|
|
43
|
+
):
|
|
44
|
+
await self.conditional_from_config(config)
|
|
45
|
+
|
|
46
|
+
async def __call__(self, memory: QuestionMemory, manager: Manager):
|
|
47
|
+
await Conditional.__call__(self, memory, manager)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from typing import List, Literal, Optional
|
|
2
|
+
|
|
3
|
+
from hyperforge.agent import Agent, AgentConfig
|
|
4
|
+
from hyperforge.configure import agent
|
|
5
|
+
from hyperforge.manager import Manager
|
|
6
|
+
from hyperforge.memory.memory import QuestionMemory
|
|
7
|
+
from pydantic import Field
|
|
8
|
+
from pydantic.config import ConfigDict
|
|
9
|
+
|
|
10
|
+
from hyperforge_conditional.conditional import (
|
|
11
|
+
Conditional,
|
|
12
|
+
ConditionalAgentConfig,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class PreprocessConditionalAgentConfig(ConditionalAgentConfig):
|
|
17
|
+
model_config = ConfigDict(title="Condition")
|
|
18
|
+
module: Literal["pre_conditional"] = "pre_conditional"
|
|
19
|
+
then: List[AgentConfig] = Field(
|
|
20
|
+
default_factory=list,
|
|
21
|
+
title="Then",
|
|
22
|
+
description="List of agents to run in case the condition is valid",
|
|
23
|
+
)
|
|
24
|
+
else_: List[AgentConfig] = Field(
|
|
25
|
+
default_factory=list,
|
|
26
|
+
title="Else",
|
|
27
|
+
description="List of agents to run in case the condition is not valid",
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@agent(
|
|
32
|
+
id="preprocess_conditional",
|
|
33
|
+
agent_type="preprocess",
|
|
34
|
+
title="Preprocess Conditional",
|
|
35
|
+
description="Conditional preprocessing agent that decides which preprocessing strategy to use based on the context.",
|
|
36
|
+
config_schema=PreprocessConditionalAgentConfig,
|
|
37
|
+
)
|
|
38
|
+
class PreprocessConditional(Agent[PreprocessConditionalAgentConfig], Conditional):
|
|
39
|
+
arag_step: str = "preprocess"
|
|
40
|
+
|
|
41
|
+
async def inner_from_config(
|
|
42
|
+
self, config: PreprocessConditionalAgentConfig, agent_id: Optional[str] = None
|
|
43
|
+
):
|
|
44
|
+
await self.conditional_from_config(config)
|
|
45
|
+
|
|
46
|
+
async def __call__(self, memory: QuestionMemory, manager: Manager):
|
|
47
|
+
await Conditional.__call__(self, memory, manager)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hyperforge_conditional
|
|
3
|
+
Version: 1.0.0.post19
|
|
4
|
+
Summary: Conditional 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
|
+
# Conditional Hyperforge agents
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
hyperforge_conditional/__init__.py,sha256=u0ZZtOSOL0xIypljmJjGiHMI-6G_oGcichP8aS9Mn1U,333
|
|
2
|
+
hyperforge_conditional/conditional.py,sha256=_dKSf_ctilRrz7pWpu4ZHgRFf59ZKu1IclFho_MdLHc,7513
|
|
3
|
+
hyperforge_conditional/context_agent.py,sha256=h0JkRpNoJ9yHIODXC9aqsk0inRGiWhLdiw31m89VWGE,6035
|
|
4
|
+
hyperforge_conditional/generation_agent.py,sha256=uKYqcyE-0vCqhlGrH3Vx9KRU_RisEVummvT9sX8PMmI,1669
|
|
5
|
+
hyperforge_conditional/postprocess_agent.py,sha256=6-a8IohFUM8oJvvcmVcKHHVcCCLEwCTuSUc_6sm1Nk8,1578
|
|
6
|
+
hyperforge_conditional/preprocess_agent.py,sha256=yuKOkwtgsGz4EhH6uzuTXjVP8vQDTF0HV7oUDpmvlUQ,1618
|
|
7
|
+
hyperforge_conditional-1.0.0.post19.dist-info/METADATA,sha256=GU-4xk1w7ksUeItEV2LJqoSlfYjU9awkFC57P6vMJdw,737
|
|
8
|
+
hyperforge_conditional-1.0.0.post19.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
9
|
+
hyperforge_conditional-1.0.0.post19.dist-info/top_level.txt,sha256=L7vLEjAFnCSkTy4XqjBicrm8-5rGiy99fCnuPmEllx0,23
|
|
10
|
+
hyperforge_conditional-1.0.0.post19.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
hyperforge_conditional
|