tinyagent-py 0.0.1__py3-none-any.whl → 0.0.4__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.
- hooks/__init__.py +4 -0
- hooks/agno_storage_hook.py +128 -0
- hooks/gradio_callback.py +966 -0
- hooks/logging_manager.py +213 -0
- hooks/rich_ui_callback.py +559 -0
- storage/__init__.py +7 -0
- storage/agno_storage.py +114 -0
- storage/base.py +49 -0
- storage/json_file_storage.py +30 -0
- storage/postgres_storage.py +201 -0
- storage/redis_storage.py +48 -0
- storage/sqlite_storage.py +156 -0
- tinyagent_py-0.0.4.dist-info/METADATA +252 -0
- tinyagent_py-0.0.4.dist-info/RECORD +17 -0
- {tinyagent_py-0.0.1.dist-info → tinyagent_py-0.0.4.dist-info}/WHEEL +1 -1
- tinyagent_py-0.0.4.dist-info/top_level.txt +2 -0
- tinyagent/__init__.py +0 -4
- tinyagent/mcp_client.py +0 -52
- tinyagent/tiny_agent.py +0 -247
- tinyagent_py-0.0.1.dist-info/METADATA +0 -79
- tinyagent_py-0.0.1.dist-info/RECORD +0 -8
- tinyagent_py-0.0.1.dist-info/top_level.txt +0 -1
- {tinyagent_py-0.0.1.dist-info → tinyagent_py-0.0.4.dist-info}/licenses/LICENSE +0 -0
hooks/logging_manager.py
ADDED
@@ -0,0 +1,213 @@
|
|
1
|
+
import logging
|
2
|
+
from typing import Dict, Optional, Union, List
|
3
|
+
|
4
|
+
class LoggingManager:
|
5
|
+
"""
|
6
|
+
A hook for TinyAgent that provides granular logging control for different modules.
|
7
|
+
|
8
|
+
This allows setting different log levels for each module in the TinyAgent ecosystem
|
9
|
+
without affecting external libraries like httpx.
|
10
|
+
"""
|
11
|
+
|
12
|
+
def __init__(self, default_level: int = logging.INFO, silence_others: bool = True):
|
13
|
+
"""
|
14
|
+
Initialize the LoggingManager.
|
15
|
+
|
16
|
+
Args:
|
17
|
+
default_level: Default logging level for all modules
|
18
|
+
silence_others: If True, silence all non-tinyagent loggers by default
|
19
|
+
"""
|
20
|
+
self.default_level = default_level
|
21
|
+
self.module_loggers: Dict[str, logging.Logger] = {}
|
22
|
+
self.module_levels: Dict[str, int] = {}
|
23
|
+
|
24
|
+
# Grab the root logger
|
25
|
+
self.root_logger = logging.getLogger()
|
26
|
+
self.external_logger_levels: Dict[str, int] = {}
|
27
|
+
|
28
|
+
if silence_others:
|
29
|
+
# 1) store its original level
|
30
|
+
self.root_logger_original_level = self.root_logger.level
|
31
|
+
# 2) strip away _any_ existing handlers (e.g. from basicConfig in libs)
|
32
|
+
for h in list(self.root_logger.handlers):
|
33
|
+
self.root_logger.removeHandler(h)
|
34
|
+
# 3) raise level so that only WARNING+ pass through by default
|
35
|
+
self.root_logger.setLevel(logging.WARNING)
|
36
|
+
|
37
|
+
def get_logger(self, module_name: str) -> logging.Logger:
|
38
|
+
"""
|
39
|
+
Get or create a logger for a specific module.
|
40
|
+
|
41
|
+
Args:
|
42
|
+
module_name: Name of the module (e.g., 'tinyagent.tiny_agent')
|
43
|
+
|
44
|
+
Returns:
|
45
|
+
A configured logger for the module
|
46
|
+
"""
|
47
|
+
if module_name in self.module_loggers:
|
48
|
+
return self.module_loggers[module_name]
|
49
|
+
|
50
|
+
# Create a new logger
|
51
|
+
logger = logging.getLogger(module_name)
|
52
|
+
|
53
|
+
# Set level from configured module levels or default
|
54
|
+
level = self.module_levels.get(module_name, self.default_level)
|
55
|
+
logger.setLevel(level)
|
56
|
+
|
57
|
+
# Ensure propagation is enabled for tinyagent loggers
|
58
|
+
if module_name.startswith('tinyagent'):
|
59
|
+
logger.propagate = True
|
60
|
+
|
61
|
+
# Store the logger
|
62
|
+
self.module_loggers[module_name] = logger
|
63
|
+
|
64
|
+
return logger
|
65
|
+
|
66
|
+
def set_level(self, module_name: str, level: Union[int, str]) -> None:
|
67
|
+
"""
|
68
|
+
Set the logging level for a specific module.
|
69
|
+
|
70
|
+
Args:
|
71
|
+
module_name: Name of the module (e.g., 'tinyagent.tiny_agent')
|
72
|
+
level: Logging level (can be int or string like 'DEBUG')
|
73
|
+
"""
|
74
|
+
# Convert string level to int if needed
|
75
|
+
if isinstance(level, str):
|
76
|
+
level = getattr(logging, level.upper())
|
77
|
+
|
78
|
+
# Store the level setting
|
79
|
+
self.module_levels[module_name] = level
|
80
|
+
|
81
|
+
# Update existing logger if it exists
|
82
|
+
if module_name in self.module_loggers:
|
83
|
+
self.module_loggers[module_name].setLevel(level)
|
84
|
+
|
85
|
+
def set_levels(self, config: Dict[str, Union[int, str]]) -> None:
|
86
|
+
"""
|
87
|
+
Set multiple logging levels at once.
|
88
|
+
|
89
|
+
Args:
|
90
|
+
config: Dictionary mapping module names to levels
|
91
|
+
"""
|
92
|
+
for module_name, level in config.items():
|
93
|
+
self.set_level(module_name, level)
|
94
|
+
|
95
|
+
def silence_external_loggers(self, logger_names: List[str], level: int = logging.WARNING) -> None:
|
96
|
+
"""
|
97
|
+
Silence external loggers (like httpx) by setting them to a higher level.
|
98
|
+
|
99
|
+
Args:
|
100
|
+
logger_names: List of external logger names to silence
|
101
|
+
level: Level to set for these loggers (default: WARNING)
|
102
|
+
"""
|
103
|
+
for name in logger_names:
|
104
|
+
logger = logging.getLogger(name)
|
105
|
+
# Store original level
|
106
|
+
self.external_logger_levels[name] = logger.level
|
107
|
+
# Set new level
|
108
|
+
logger.setLevel(level)
|
109
|
+
|
110
|
+
def restore_external_loggers(self) -> None:
|
111
|
+
"""Restore external loggers to their original levels."""
|
112
|
+
for name, level in self.external_logger_levels.items():
|
113
|
+
logging.getLogger(name).setLevel(level)
|
114
|
+
|
115
|
+
# Restore root logger level if we changed it
|
116
|
+
if hasattr(self, 'root_logger_original_level'):
|
117
|
+
self.root_logger.setLevel(self.root_logger_original_level)
|
118
|
+
|
119
|
+
def configure_handler(self, handler: logging.Handler,
|
120
|
+
format_string: Optional[str] = None,
|
121
|
+
level: Optional[int] = None) -> None:
|
122
|
+
"""
|
123
|
+
Configure a logging handler with format and level.
|
124
|
+
|
125
|
+
Args:
|
126
|
+
handler: The handler to configure
|
127
|
+
format_string: Optional format string for the handler
|
128
|
+
level: Optional level for the handler
|
129
|
+
"""
|
130
|
+
if format_string:
|
131
|
+
formatter = logging.Formatter(format_string)
|
132
|
+
handler.setFormatter(formatter)
|
133
|
+
|
134
|
+
if level is not None:
|
135
|
+
handler.setLevel(level)
|
136
|
+
|
137
|
+
# Add to root logger if not already present
|
138
|
+
if handler not in self.root_logger.handlers:
|
139
|
+
self.root_logger.addHandler(handler)
|
140
|
+
|
141
|
+
|
142
|
+
async def run_example():
|
143
|
+
"""Example usage of LoggingManager with TinyAgent."""
|
144
|
+
import os
|
145
|
+
import sys
|
146
|
+
from tinyagent import TinyAgent
|
147
|
+
from tinyagent.hooks.rich_ui_callback import RichUICallback
|
148
|
+
|
149
|
+
# Create the logging manager with silence_others=True
|
150
|
+
log_manager = LoggingManager(default_level=logging.INFO, silence_others=True)
|
151
|
+
|
152
|
+
# Configure different levels for different modules
|
153
|
+
log_manager.set_levels({
|
154
|
+
'tinyagent.tiny_agent': logging.INFO,
|
155
|
+
'tinyagent.mcp_client': logging.INFO,
|
156
|
+
'tinyagent.hooks.rich_ui_callback': logging.DEBUG, # Debug for RichUICallback
|
157
|
+
'tinyagent.hooks.logging_manager': logging.DEBUG, # Debug for this module
|
158
|
+
})
|
159
|
+
|
160
|
+
# Explicitly silence specific external loggers if needed
|
161
|
+
log_manager.silence_external_loggers(['httpx', 'asyncio', 'litellm', 'openai'], logging.WARNING)
|
162
|
+
|
163
|
+
# Add a console handler with custom format
|
164
|
+
console_handler = logging.StreamHandler(sys.stdout)
|
165
|
+
log_manager.configure_handler(
|
166
|
+
console_handler,
|
167
|
+
format_string='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
168
|
+
level=logging.DEBUG
|
169
|
+
)
|
170
|
+
|
171
|
+
# Get module-specific loggers
|
172
|
+
agent_logger = log_manager.get_logger('tinyagent.tiny_agent')
|
173
|
+
ui_logger = log_manager.get_logger('tinyagent.hooks.rich_ui_callback')
|
174
|
+
mcp_logger = log_manager.get_logger('tinyagent.mcp_client')
|
175
|
+
log_manager_logger = log_manager.get_logger('tinyagent.hooks.logging_manager')
|
176
|
+
|
177
|
+
log_manager_logger.debug("Starting LoggingManager example")
|
178
|
+
agent_logger.info("Initializing TinyAgent")
|
179
|
+
|
180
|
+
# Get API key from environment
|
181
|
+
api_key = os.environ.get("OPENAI_API_KEY")
|
182
|
+
if not api_key:
|
183
|
+
agent_logger.error("Please set the OPENAI_API_KEY environment variable")
|
184
|
+
return
|
185
|
+
|
186
|
+
# Initialize the agent with our logger
|
187
|
+
agent = TinyAgent(model="gpt-4.1-mini", api_key=api_key, logger=agent_logger)
|
188
|
+
|
189
|
+
# Add the Rich UI callback with our logger
|
190
|
+
rich_ui = RichUICallback(
|
191
|
+
markdown=True,
|
192
|
+
show_message=True,
|
193
|
+
show_thinking=True,
|
194
|
+
show_tool_calls=True,
|
195
|
+
logger=ui_logger # Pass DEBUG level logger to RichUICallback
|
196
|
+
)
|
197
|
+
agent.add_callback(rich_ui)
|
198
|
+
|
199
|
+
# Run the agent with a user query
|
200
|
+
user_input = "What is the capital of France?"
|
201
|
+
agent_logger.info(f"Running agent with input: {user_input}")
|
202
|
+
result = await agent.run(user_input)
|
203
|
+
|
204
|
+
agent_logger.info(f"Final result: {result}")
|
205
|
+
|
206
|
+
# Clean up
|
207
|
+
await agent.close()
|
208
|
+
log_manager_logger.debug("Example completed")
|
209
|
+
|
210
|
+
|
211
|
+
if __name__ == "__main__":
|
212
|
+
import asyncio
|
213
|
+
asyncio.run(run_example())
|