agentic-blocks 0.1.24__tar.gz → 0.1.25__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.
- {agentic_blocks-0.1.24/src/agentic_blocks.egg-info → agentic_blocks-0.1.25}/PKG-INFO +1 -1
- {agentic_blocks-0.1.24 → agentic_blocks-0.1.25}/pyproject.toml +1 -1
- agentic_blocks-0.1.25/src/agentic_blocks/agent.py +104 -0
- agentic_blocks-0.1.24/src/agentic_blocks/agent.py → agentic_blocks-0.1.25/src/agentic_blocks/agent_rich.py +52 -28
- agentic_blocks-0.1.25/src/agentic_blocks/utils/logger.py +14 -0
- agentic_blocks-0.1.25/src/agentic_blocks/utils/rich_logger.py +59 -0
- {agentic_blocks-0.1.24 → agentic_blocks-0.1.25/src/agentic_blocks.egg-info}/PKG-INFO +1 -1
- {agentic_blocks-0.1.24 → agentic_blocks-0.1.25}/src/agentic_blocks.egg-info/SOURCES.txt +3 -0
- {agentic_blocks-0.1.24 → agentic_blocks-0.1.25}/LICENSE +0 -0
- {agentic_blocks-0.1.24 → agentic_blocks-0.1.25}/README.md +0 -0
- {agentic_blocks-0.1.24 → agentic_blocks-0.1.25}/setup.cfg +0 -0
- {agentic_blocks-0.1.24 → agentic_blocks-0.1.25}/src/agentic_blocks/__init__.py +0 -0
- {agentic_blocks-0.1.24 → agentic_blocks-0.1.25}/src/agentic_blocks/llm.py +0 -0
- {agentic_blocks-0.1.24 → agentic_blocks-0.1.25}/src/agentic_blocks/mcp_client.py +0 -0
- {agentic_blocks-0.1.24 → agentic_blocks-0.1.25}/src/agentic_blocks/messages.py +0 -0
- {agentic_blocks-0.1.24 → agentic_blocks-0.1.25}/src/agentic_blocks/utils/tools_utils.py +0 -0
- {agentic_blocks-0.1.24 → agentic_blocks-0.1.25}/src/agentic_blocks/visualization/visualize.py +0 -0
- {agentic_blocks-0.1.24 → agentic_blocks-0.1.25}/src/agentic_blocks.egg-info/dependency_links.txt +0 -0
- {agentic_blocks-0.1.24 → agentic_blocks-0.1.25}/src/agentic_blocks.egg-info/requires.txt +0 -0
- {agentic_blocks-0.1.24 → agentic_blocks-0.1.25}/src/agentic_blocks.egg-info/top_level.txt +0 -0
@@ -14,7 +14,7 @@ agentic_blocks = []
|
|
14
14
|
|
15
15
|
[project]
|
16
16
|
name = "agentic-blocks"
|
17
|
-
version = "0.1.
|
17
|
+
version = "0.1.25"
|
18
18
|
description = "Simple building blocks for agentic AI systems with MCP client and conversation management"
|
19
19
|
readme = "README.md"
|
20
20
|
requires-python = ">=3.11"
|
@@ -0,0 +1,104 @@
|
|
1
|
+
from pocketflow import Node, Flow
|
2
|
+
from agentic_blocks.utils.tools_utils import (
|
3
|
+
create_tool_registry,
|
4
|
+
execute_pending_tool_calls,
|
5
|
+
)
|
6
|
+
from agentic_blocks.utils.logger import get_logger
|
7
|
+
from agentic_blocks import call_llm, Messages
|
8
|
+
|
9
|
+
logger = get_logger(__name__)
|
10
|
+
|
11
|
+
|
12
|
+
class Agent:
|
13
|
+
def __init__(self, system_prompt: str, tools: list):
|
14
|
+
self.system_prompt = system_prompt
|
15
|
+
self.tools = tools
|
16
|
+
self.tool_registry = create_tool_registry(tools)
|
17
|
+
|
18
|
+
# Create nodes
|
19
|
+
self.llm_node = self._create_llm_node()
|
20
|
+
self.tool_node = self._create_tool_node()
|
21
|
+
self.answer_node = self._create_answer_node()
|
22
|
+
|
23
|
+
# Set up flow
|
24
|
+
self.llm_node - "tool_node" >> self.tool_node
|
25
|
+
self.tool_node - "llm_node" >> self.llm_node
|
26
|
+
self.llm_node - "answer_node" >> self.answer_node
|
27
|
+
|
28
|
+
self.flow = Flow(self.llm_node)
|
29
|
+
|
30
|
+
def _create_llm_node(self):
|
31
|
+
class LLMNode(Node):
|
32
|
+
def __init__(self, system_prompt, tools):
|
33
|
+
super().__init__()
|
34
|
+
self.system_prompt = system_prompt
|
35
|
+
self.tools = tools
|
36
|
+
|
37
|
+
def prep(self, shared):
|
38
|
+
messages = shared["messages"]
|
39
|
+
return messages
|
40
|
+
|
41
|
+
def exec(self, messages) -> Messages:
|
42
|
+
latest_message = messages.get_messages()[-1]
|
43
|
+
if latest_message["role"] == "user":
|
44
|
+
logger.info(f'message: "{latest_message["content"]}"')
|
45
|
+
|
46
|
+
response = call_llm(messages=messages, tools=self.tools)
|
47
|
+
# logger.info(f'response: "{response["content"] or "tool_calls"}"')
|
48
|
+
messages.add_response_message(response)
|
49
|
+
return messages
|
50
|
+
|
51
|
+
def post(self, shared, prep_res, messages):
|
52
|
+
if messages.has_pending_tool_calls():
|
53
|
+
return "tool_node"
|
54
|
+
else:
|
55
|
+
return "answer_node"
|
56
|
+
|
57
|
+
return LLMNode(self.system_prompt, self.tools)
|
58
|
+
|
59
|
+
def _create_tool_node(self):
|
60
|
+
class ToolNode(Node):
|
61
|
+
def __init__(self, tool_registry):
|
62
|
+
super().__init__()
|
63
|
+
self.tool_registry = tool_registry
|
64
|
+
|
65
|
+
def prep(self, shared):
|
66
|
+
return shared["messages"]
|
67
|
+
|
68
|
+
def exec(self, messages: Messages) -> Messages:
|
69
|
+
tool_calls = messages.get_pending_tool_calls()
|
70
|
+
for tool_call in tool_calls:
|
71
|
+
logger.info(
|
72
|
+
f'tool_call: "{tool_call["tool_name"]}({tool_call["arguments"]})"'
|
73
|
+
)
|
74
|
+
|
75
|
+
tool_responses = execute_pending_tool_calls(
|
76
|
+
messages, self.tool_registry
|
77
|
+
)
|
78
|
+
messages.add_tool_responses(tool_responses)
|
79
|
+
return messages
|
80
|
+
|
81
|
+
def post(self, shared, prep_res, messages):
|
82
|
+
return "llm_node"
|
83
|
+
|
84
|
+
return ToolNode(self.tool_registry)
|
85
|
+
|
86
|
+
def _create_answer_node(self):
|
87
|
+
class AnswerNode(Node):
|
88
|
+
def prep(self, shared):
|
89
|
+
messages = shared["messages"]
|
90
|
+
shared["answer"] = messages.get_messages()[-1]["content"]
|
91
|
+
return messages
|
92
|
+
|
93
|
+
return AnswerNode()
|
94
|
+
|
95
|
+
def invoke(self, user_prompt: str) -> str:
|
96
|
+
messages = Messages(user_prompt=user_prompt)
|
97
|
+
logger.info(f'message: "{user_prompt}"')
|
98
|
+
if self.system_prompt:
|
99
|
+
messages.add_system_message(self.system_prompt)
|
100
|
+
|
101
|
+
shared = {"messages": messages}
|
102
|
+
self.flow.run(shared)
|
103
|
+
|
104
|
+
return shared["answer"]
|
@@ -4,18 +4,17 @@ from agentic_blocks.utils.tools_utils import (
|
|
4
4
|
execute_pending_tool_calls,
|
5
5
|
)
|
6
6
|
from agentic_blocks import call_llm, Messages
|
7
|
-
|
7
|
+
|
8
|
+
|
9
|
+
from rich.console import Group, Console
|
10
|
+
from rich.json import JSON
|
11
|
+
from rich.live import Live
|
12
|
+
from rich.markdown import Markdown
|
13
|
+
from rich.status import Status
|
14
|
+
from rich.text import Text
|
8
15
|
from rich.box import HEAVY
|
9
|
-
from rich.
|
10
|
-
from
|
11
|
-
|
12
|
-
console = Console(
|
13
|
-
style="black on bright_white",
|
14
|
-
force_terminal=True,
|
15
|
-
width=None,
|
16
|
-
legacy_windows=False,
|
17
|
-
color_system="truecolor",
|
18
|
-
)
|
16
|
+
from rich.panel import Panel
|
17
|
+
from agentic_blocks.utils.rich_logger import print_response
|
19
18
|
|
20
19
|
|
21
20
|
class Agent:
|
@@ -88,6 +87,9 @@ class Agent:
|
|
88
87
|
tool_panel = self.agent.create_panel(formatted_call, "Tool Calls")
|
89
88
|
self.agent.panels.append(tool_panel)
|
90
89
|
|
90
|
+
self.agent.live_log.update(Group(*self.agent.panels))
|
91
|
+
self.agent.live_log.refresh()
|
92
|
+
|
91
93
|
tool_responses = execute_pending_tool_calls(
|
92
94
|
messages, self.tool_registry
|
93
95
|
)
|
@@ -118,21 +120,6 @@ class Agent:
|
|
118
120
|
|
119
121
|
return shared["answer"]
|
120
122
|
|
121
|
-
def print_response(self, user_prompt: str, stream: bool = False):
|
122
|
-
# Reset panels and start with message
|
123
|
-
self.panels = []
|
124
|
-
message_panel = self.create_panel(user_prompt, "Message")
|
125
|
-
self.panels.append(message_panel)
|
126
|
-
|
127
|
-
# Always collect all panels first
|
128
|
-
response = self.invoke(user_prompt)
|
129
|
-
response_panel = self.create_panel(response, "Response")
|
130
|
-
self.panels.append(response_panel)
|
131
|
-
|
132
|
-
# Print all panels as a group (no gaps)
|
133
|
-
panel_group = Group(*self.panel)
|
134
|
-
console.print(panel_group)
|
135
|
-
|
136
123
|
def create_panel(self, content, title, border_style="blue"):
|
137
124
|
return Panel(
|
138
125
|
content,
|
@@ -140,6 +127,43 @@ class Agent:
|
|
140
127
|
title_align="left",
|
141
128
|
border_style=border_style,
|
142
129
|
box=HEAVY,
|
143
|
-
expand=True,
|
144
|
-
padding=(1, 1),
|
130
|
+
expand=True,
|
131
|
+
padding=(1, 1),
|
145
132
|
)
|
133
|
+
|
134
|
+
def print_response(self, user_prompt: str):
|
135
|
+
messages = Messages(user_prompt=user_prompt)
|
136
|
+
if self.system_prompt:
|
137
|
+
messages.add_system_message(self.system_prompt)
|
138
|
+
|
139
|
+
shared = {"messages": messages}
|
140
|
+
|
141
|
+
with Live(console=Console(), auto_refresh=False) as self.live_log:
|
142
|
+
status = Status("Thinking...", spinner="aesthetic", speed=0.4)
|
143
|
+
self.live_log.update(status)
|
144
|
+
self.live_log.refresh() # Explicit refresh for Jupyter
|
145
|
+
|
146
|
+
self.panels = [status]
|
147
|
+
|
148
|
+
message_panel = self.create_panel(
|
149
|
+
content=Text(user_prompt, style="green"),
|
150
|
+
title="Message",
|
151
|
+
border_style="cyan",
|
152
|
+
)
|
153
|
+
|
154
|
+
self.panels.append(message_panel)
|
155
|
+
self.live_log.update(Group(*self.panels))
|
156
|
+
self.live_log.refresh()
|
157
|
+
|
158
|
+
self.flow.run(shared)
|
159
|
+
response = shared["answer"]
|
160
|
+
|
161
|
+
response_panel = self.create_panel(
|
162
|
+
content=Text(response, style="bold blue"),
|
163
|
+
title="Response",
|
164
|
+
border_style="green",
|
165
|
+
)
|
166
|
+
|
167
|
+
self.panels.append(response_panel)
|
168
|
+
self.live_log.update(Group(*self.panels))
|
169
|
+
self.live_log.refresh()
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import logging
|
2
|
+
|
3
|
+
# Auto-configure logging when module is imported
|
4
|
+
logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
|
5
|
+
|
6
|
+
# Suppress HTTP request logs
|
7
|
+
logging.getLogger("openai").setLevel(logging.WARNING)
|
8
|
+
logging.getLogger("httpx").setLevel(logging.WARNING)
|
9
|
+
logging.getLogger("urllib3").setLevel(logging.WARNING)
|
10
|
+
|
11
|
+
|
12
|
+
def get_logger(name):
|
13
|
+
"""Get a logger with the given name."""
|
14
|
+
return logging.getLogger(name)
|
@@ -0,0 +1,59 @@
|
|
1
|
+
import time
|
2
|
+
from rich.console import Group, Console
|
3
|
+
from rich.json import JSON
|
4
|
+
from rich.live import Live
|
5
|
+
from rich.markdown import Markdown
|
6
|
+
from rich.status import Status
|
7
|
+
from rich.text import Text
|
8
|
+
from rich.box import HEAVY
|
9
|
+
from rich.panel import Panel
|
10
|
+
|
11
|
+
# Create a console instance for Jupyter
|
12
|
+
|
13
|
+
|
14
|
+
def create_panel(content, title, border_style="blue"):
|
15
|
+
return Panel(
|
16
|
+
content,
|
17
|
+
title=title,
|
18
|
+
title_align="left",
|
19
|
+
border_style=border_style,
|
20
|
+
box=HEAVY,
|
21
|
+
expand=True,
|
22
|
+
padding=(1, 1),
|
23
|
+
)
|
24
|
+
|
25
|
+
|
26
|
+
def print_response(user_prompt):
|
27
|
+
with Live(console=Console(), auto_refresh=False) as live_log:
|
28
|
+
status = Status("Thinking...", spinner="aesthetic", speed=0.4)
|
29
|
+
live_log.update(status)
|
30
|
+
live_log.refresh() # Explicit refresh for Jupyter
|
31
|
+
|
32
|
+
# Create panels
|
33
|
+
panels = [status]
|
34
|
+
|
35
|
+
message_panel = create_panel(
|
36
|
+
content=Text(user_prompt, style="green"),
|
37
|
+
title="Message",
|
38
|
+
border_style="cyan",
|
39
|
+
)
|
40
|
+
|
41
|
+
panels.append(message_panel)
|
42
|
+
live_log.update(Group(*panels))
|
43
|
+
live_log.refresh() # Explicit refresh for Jupyter
|
44
|
+
|
45
|
+
# Add some delay to see the display
|
46
|
+
|
47
|
+
for i in range(3):
|
48
|
+
time.sleep(2)
|
49
|
+
|
50
|
+
# Add a response panel
|
51
|
+
response_panel = create_panel(
|
52
|
+
content=Text("Response: " + str(i), style="bold blue"),
|
53
|
+
title="Response",
|
54
|
+
border_style="green",
|
55
|
+
)
|
56
|
+
|
57
|
+
panels.append(response_panel)
|
58
|
+
live_log.update(Group(*panels))
|
59
|
+
live_log.refresh()
|
@@ -3,6 +3,7 @@ README.md
|
|
3
3
|
pyproject.toml
|
4
4
|
src/agentic_blocks/__init__.py
|
5
5
|
src/agentic_blocks/agent.py
|
6
|
+
src/agentic_blocks/agent_rich.py
|
6
7
|
src/agentic_blocks/llm.py
|
7
8
|
src/agentic_blocks/mcp_client.py
|
8
9
|
src/agentic_blocks/messages.py
|
@@ -11,5 +12,7 @@ src/agentic_blocks.egg-info/SOURCES.txt
|
|
11
12
|
src/agentic_blocks.egg-info/dependency_links.txt
|
12
13
|
src/agentic_blocks.egg-info/requires.txt
|
13
14
|
src/agentic_blocks.egg-info/top_level.txt
|
15
|
+
src/agentic_blocks/utils/logger.py
|
16
|
+
src/agentic_blocks/utils/rich_logger.py
|
14
17
|
src/agentic_blocks/utils/tools_utils.py
|
15
18
|
src/agentic_blocks/visualization/visualize.py
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{agentic_blocks-0.1.24 → agentic_blocks-0.1.25}/src/agentic_blocks/visualization/visualize.py
RENAMED
File without changes
|
{agentic_blocks-0.1.24 → agentic_blocks-0.1.25}/src/agentic_blocks.egg-info/dependency_links.txt
RENAMED
File without changes
|
File without changes
|
File without changes
|