flock-core 0.3.1__py3-none-any.whl → 0.3.3__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.

Potentially problematic release.


This version of flock-core might be problematic. Click here for more details.

@@ -0,0 +1,55 @@
1
+ from typing import Any
2
+
3
+ from pydantic import Field
4
+
5
+ from flock.core.flock_agent import FlockAgent
6
+ from flock.core.flock_evaluator import FlockEvaluator, FlockEvaluatorConfig
7
+ from flock.core.mixin.dspy_integration import DSPyIntegrationMixin
8
+ from flock.core.mixin.prompt_parser import PromptParserMixin
9
+ from flock.modules.zep.zep_module import ZepModule, ZepModuleConfig
10
+
11
+
12
+ class ZepEvaluatorConfig(FlockEvaluatorConfig):
13
+ zep_url: str = "http://localhost:8000"
14
+ zep_api_key: str = "apikey"
15
+ min_fact_rating: float = Field(
16
+ default=0.7, description="Minimum rating for facts to be considered"
17
+ )
18
+
19
+
20
+ class ZepEvaluator(FlockEvaluator, DSPyIntegrationMixin, PromptParserMixin):
21
+ """Evaluator that uses DSPy for generation."""
22
+
23
+ config: ZepEvaluatorConfig = Field(
24
+ default_factory=ZepEvaluatorConfig,
25
+ description="Evaluator configuration",
26
+ )
27
+
28
+ async def evaluate(
29
+ self, agent: FlockAgent, inputs: dict[str, Any], tools: list[Any]
30
+ ) -> dict[str, Any]:
31
+ """Simple evaluator that uses Zep.
32
+
33
+ if inputs contain "query", it searches memory for the query and returns the facts.
34
+ if inputs contain "data", it adds the data to memory
35
+ """
36
+ result = {}
37
+ zep = ZepModule(
38
+ name=self.name,
39
+ config=ZepModuleConfig(
40
+ zep_api_key=self.config.zep_api_key,
41
+ zep_url=self.config.zep_url,
42
+ min_fact_rating=self.config.min_fact_rating,
43
+ ),
44
+ )
45
+ client = zep.get_client()
46
+ if "query" in inputs:
47
+ query = inputs["query"]
48
+ facts = zep.search_memory(query, client)
49
+ result = {"facts": facts}
50
+
51
+ if "data" in inputs:
52
+ data = inputs["data"]
53
+ zep.add_to_memory(data, client)
54
+ result = {"message": "Data added to memory"}
55
+ return result
@@ -0,0 +1,177 @@
1
+ import uuid
2
+ from typing import Any
3
+
4
+ from pydantic import Field
5
+ from zep_python.client import Zep
6
+ from zep_python.types import Message as ZepMessage, SessionSearchResult
7
+
8
+ from flock.core.flock_agent import FlockAgent
9
+ from flock.core.flock_module import FlockModule, FlockModuleConfig
10
+ from flock.core.logging.logging import get_logger
11
+
12
+ logger = get_logger("module.zep")
13
+
14
+
15
+ class ZepModuleConfig(FlockModuleConfig):
16
+ """Configuration for the Zep module."""
17
+
18
+ zep_url: str = "http://localhost:8000"
19
+ zep_api_key: str = "apikey"
20
+ min_fact_rating: float = Field(
21
+ default=0.7, description="Minimum rating for facts to be considered"
22
+ )
23
+ enable_read: bool = True
24
+ enable_write: bool = False
25
+
26
+
27
+ class ZepModule(FlockModule):
28
+ """Module that adds Zep capabilities to a Flock agent."""
29
+
30
+ name: str = "zep"
31
+ config: ZepModuleConfig = ZepModuleConfig()
32
+ session_id: str | None = None
33
+ user_id: str | None = None
34
+
35
+ def __init__(self, name, config: ZepModuleConfig) -> None:
36
+ """Initialize Zep module."""
37
+ super().__init__(name=name, config=config)
38
+ logger.debug("Initializing Zep module")
39
+ zep_client = Zep(
40
+ base_url=self.config.zep_url, api_key=self.config.zep_api_key
41
+ )
42
+ self.user_id = self.name
43
+ self._setup_user(zep_client)
44
+ self.session_id = str(uuid.uuid4())
45
+ self._setup_session(zep_client)
46
+
47
+ def _setup_user(self, zep_client: Zep) -> None:
48
+ """Set up user in Zep."""
49
+ if not zep_client or not self.user_id:
50
+ raise ValueError("Zep service or user_id not initialized")
51
+
52
+ try:
53
+ user = zep_client.user.get(user_id=self.user_id)
54
+ if not user:
55
+ zep_client.user.add(user_id=self.user_id)
56
+ except Exception:
57
+ zep_client.user.add(user_id=self.user_id)
58
+
59
+ def _setup_session(self, zep_client: Zep) -> None:
60
+ """Set up new session."""
61
+ if not zep_client or not self.user_id or not self.session_id:
62
+ raise ValueError(
63
+ "Zep service, user_id, or session_id not initialized"
64
+ )
65
+
66
+ zep_client.memory.add_session(
67
+ user_id=self.user_id,
68
+ session_id=self.session_id,
69
+ )
70
+
71
+ def get_client(self) -> Zep:
72
+ """Get Zep client."""
73
+ return Zep(
74
+ base_url=self.config.zep_url, api_key=self.config.zep_api_key
75
+ )
76
+
77
+ def get_memory(self, zep_client: Zep) -> str | None:
78
+ """Get memory for the current session."""
79
+ if not zep_client or not self.session_id:
80
+ logger.error("Zep service or session_id not initialized")
81
+ return None
82
+
83
+ try:
84
+ memory = zep_client.memory.get(
85
+ self.session_id, min_rating=self.config.min_fact_rating
86
+ )
87
+ if memory:
88
+ return f"{memory.relevant_facts}"
89
+ except Exception as e:
90
+ logger.error(f"Error fetching memory: {e}")
91
+ return None
92
+
93
+ return None
94
+
95
+ def split_text(
96
+ self, text: str | None, max_length: int = 1000
97
+ ) -> list[ZepMessage]:
98
+ """Split text into smaller chunks."""
99
+ result: list[ZepMessage] = []
100
+ if not text:
101
+ return result
102
+ if len(text) <= max_length:
103
+ return [ZepMessage(role="user", content=text, role_type="user")]
104
+ for i in range(0, len(text), max_length):
105
+ result.append(
106
+ ZepMessage(
107
+ role="user",
108
+ content=text[i : i + max_length],
109
+ role_type="user",
110
+ )
111
+ )
112
+ return result
113
+
114
+ def add_to_memory(self, text: str, zep_client: Zep) -> None:
115
+ """Add text to memory."""
116
+ if not zep_client or not self.session_id:
117
+ logger.error("Zep service or session_id not initialized")
118
+ return
119
+
120
+ messages = self.split_text(text)
121
+ zep_client.memory.add(session_id=self.session_id, messages=messages)
122
+
123
+ def search_memory(
124
+ self, query: str, zep_client: Zep
125
+ ) -> list[SessionSearchResult]:
126
+ """Search memory for a query."""
127
+ if not zep_client or not self.user_id:
128
+ logger.error("Zep service or user_id not initialized")
129
+ return []
130
+
131
+ response = zep_client.memory.search_sessions(
132
+ text=query,
133
+ user_id=self.user_id,
134
+ search_scope="facts",
135
+ min_fact_rating=self.config.min_fact_rating,
136
+ )
137
+ if not response.results:
138
+ return []
139
+ return response.results
140
+
141
+ async def post_evaluate(
142
+ self, agent: FlockAgent, inputs: dict[str, Any], result: dict[str, Any]
143
+ ) -> dict[str, Any]:
144
+ """Format and display the output."""
145
+ if not self.config.enable_write:
146
+ return result
147
+ logger.debug("Saving data to memory")
148
+ zep_client = Zep(
149
+ base_url=self.config.zep_url, api_key=self.config.zep_api_key
150
+ )
151
+ self.add_to_memory(str(result), zep_client)
152
+ return result
153
+
154
+ async def pre_evaluate(
155
+ self, agent: FlockAgent, inputs: dict[str, Any]
156
+ ) -> dict[str, Any]:
157
+ """Format and display the output."""
158
+ if not self.config.enable_read:
159
+ return inputs
160
+
161
+ zep_client = Zep(
162
+ base_url=self.config.zep_url, api_key=self.config.zep_api_key
163
+ )
164
+
165
+ logger.debug("Searching memory")
166
+ facts = self.search_memory(str(inputs), zep_client)
167
+
168
+ # Add memory to inputs
169
+ facts_str = ""
170
+ if facts:
171
+ for fact in facts:
172
+ facts_str += fact.fact.fact + "\n"
173
+ logger.debug("Found facts in memory: {}", facts_str)
174
+ agent.input = agent.input + ", memory"
175
+ inputs["memory"] = facts_str
176
+
177
+ return inputs
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flock-core
3
- Version: 0.3.1
3
+ Version: 0.3.3
4
4
  Summary: Declarative LLM Orchestration at Scale
5
5
  Author-email: Andre Ratzenberger <andre.ratzenberger@whiteduck.de>
6
6
  License-File: LICENSE
@@ -34,6 +34,7 @@ Requires-Dist: temporalio>=1.9.0
34
34
  Requires-Dist: tiktoken>=0.8.0
35
35
  Requires-Dist: toml>=0.10.2
36
36
  Requires-Dist: tqdm>=4.67.1
37
+ Requires-Dist: zep-python>=2.0.2
37
38
  Provides-Extra: all-tools
38
39
  Requires-Dist: docling>=2.18.0; extra == 'all-tools'
39
40
  Requires-Dist: markdownify>=0.14.1; extra == 'all-tools'
@@ -44,12 +44,14 @@ flock/core/util/input_resolver.py,sha256=g9vDPdY4OH-G7qjas5ksGEHueokHGFPMoLOvC-n
44
44
  flock/core/util/serializable.py,sha256=SymJ0YrjBx48mOBItYSqoRpKuzIc4vKWRS6ScTzre7s,2573
45
45
  flock/evaluators/declarative/declarative_evaluator.py,sha256=f8ldgZZp94zC4CoGzBufKvbvtckCGBe9EHTOoAZfZK0,1695
46
46
  flock/evaluators/natural_language/natural_language_evaluator.py,sha256=6nVEeh8_uwv_h-d3FWlA0GbzDzRtdhvxCGKirHtyvOU,2012
47
+ flock/evaluators/zep/zep_evaluator.py,sha256=hEHQdgIwGsbC4ci9RvtdA2k7f4M0yznIok4v4XltNwg,1885
47
48
  flock/modules/callback/callback_module.py,sha256=hCCw-HNYjK4aHnUQfvw26ZP1Q_jdlKb9kDh3BHzbCQA,2916
48
49
  flock/modules/memory/memory_module.py,sha256=2grdmvw7FJWZvz0IjgASbDPCfyS1w4gWkRzOWtK7BFM,8214
49
50
  flock/modules/memory/memory_parser.py,sha256=2S7CmVEsm22gD7-MiFj4318FTg8wd_jB-RKMwXI14WM,4369
50
51
  flock/modules/memory/memory_storage.py,sha256=CNcLDMmvv0x7Z3YMKr6VveS_VCa7rKPw8l2d-XgqokA,27246
51
52
  flock/modules/output/output_module.py,sha256=_Hid4ycGEl14m7GEsVGE9wp88SYkQ3eq_x4avUQcTWI,6985
52
53
  flock/modules/performance/metrics_module.py,sha256=K5z5bizIjA4ZEUjBk5ShwTR9ZElR-Vmqa7H38dJ3z_0,16735
54
+ flock/modules/zep/zep_module.py,sha256=BIJ5K-hg2bLeJmGKoDcVY1rVN7_0yYETiSaVrO-gtMI,5830
53
55
  flock/platform/docker_tools.py,sha256=fpA7-6rJBjPOUBLdQP4ny2QPgJ_042nmqRn5GtKnoYw,1445
54
56
  flock/platform/jaeger_install.py,sha256=MyOMJQx4TQSMYvdUJxfiGSo3YCtsfkbNXcAcQ9bjETA,2898
55
57
  flock/themes/3024-day.toml,sha256=uOVHqEzSyHx0WlUk3D0lne4RBsNBAPCTy3C58yU7kEY,667
@@ -393,8 +395,8 @@ flock/workflow/activities.py,sha256=2zcYyDoCuYs9oQbnhLjCzBUdEi7d5IEIemKJ7TV_B8w,
393
395
  flock/workflow/agent_activities.py,sha256=NhBZscflEf2IMfSRa_pBM_TRP7uVEF_O0ROvWZ33eDc,963
394
396
  flock/workflow/temporal_setup.py,sha256=VWBgmBgfTBjwM5ruS_dVpA5AVxx6EZ7oFPGw4j3m0l0,1091
395
397
  flock/workflow/workflow.py,sha256=I9MryXW_bqYVTHx-nl2epbTqeRy27CAWHHA7ZZA0nAk,1696
396
- flock_core-0.3.1.dist-info/METADATA,sha256=lctsSseYD8ZeFnzowlqwFLw9uJf6wTe_asp-ynomji4,20398
397
- flock_core-0.3.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
398
- flock_core-0.3.1.dist-info/entry_points.txt,sha256=rWaS5KSpkTmWySURGFZk6PhbJ87TmvcFQDi2uzjlagQ,37
399
- flock_core-0.3.1.dist-info/licenses/LICENSE,sha256=iYEqWy0wjULzM9GAERaybP4LBiPeu7Z1NEliLUdJKSc,1072
400
- flock_core-0.3.1.dist-info/RECORD,,
398
+ flock_core-0.3.3.dist-info/METADATA,sha256=DmDTXx-eJoRlsZbhPGsyX-OEBZ16ahgDPFKb5N0YFBk,20431
399
+ flock_core-0.3.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
400
+ flock_core-0.3.3.dist-info/entry_points.txt,sha256=rWaS5KSpkTmWySURGFZk6PhbJ87TmvcFQDi2uzjlagQ,37
401
+ flock_core-0.3.3.dist-info/licenses/LICENSE,sha256=iYEqWy0wjULzM9GAERaybP4LBiPeu7Z1NEliLUdJKSc,1072
402
+ flock_core-0.3.3.dist-info/RECORD,,