aixtools 0.7.8__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.
Potentially problematic release.
This version of aixtools might be problematic. Click here for more details.
- aixtools-0.7.8/PKG-INFO +1121 -0
- aixtools-0.7.8/README.md +1080 -0
- aixtools-0.7.8/aixtools/.chainlit/config.toml +113 -0
- aixtools-0.7.8/aixtools/.chainlit/translations/bn.json +214 -0
- aixtools-0.7.8/aixtools/.chainlit/translations/en-US.json +214 -0
- aixtools-0.7.8/aixtools/.chainlit/translations/gu.json +214 -0
- aixtools-0.7.8/aixtools/.chainlit/translations/he-IL.json +214 -0
- aixtools-0.7.8/aixtools/.chainlit/translations/hi.json +214 -0
- aixtools-0.7.8/aixtools/.chainlit/translations/ja.json +214 -0
- aixtools-0.7.8/aixtools/.chainlit/translations/kn.json +214 -0
- aixtools-0.7.8/aixtools/.chainlit/translations/ml.json +214 -0
- aixtools-0.7.8/aixtools/.chainlit/translations/mr.json +214 -0
- aixtools-0.7.8/aixtools/.chainlit/translations/nl.json +214 -0
- aixtools-0.7.8/aixtools/.chainlit/translations/ta.json +214 -0
- aixtools-0.7.8/aixtools/.chainlit/translations/te.json +214 -0
- aixtools-0.7.8/aixtools/.chainlit/translations/zh-CN.json +214 -0
- aixtools-0.7.8/aixtools/__init__.py +11 -0
- aixtools-0.7.8/aixtools/_version.py +34 -0
- aixtools-0.7.8/aixtools/a2a/app.py +243 -0
- aixtools-0.7.8/aixtools/a2a/auth_middleware.py +46 -0
- aixtools-0.7.8/aixtools/a2a/auth_push_notification_sender.py +65 -0
- aixtools-0.7.8/aixtools/a2a/context_middleware.py +47 -0
- aixtools-0.7.8/aixtools/a2a/google_sdk/__init__.py +0 -0
- aixtools-0.7.8/aixtools/a2a/google_sdk/pydantic_ai_adapter/agent_executor.py +269 -0
- aixtools-0.7.8/aixtools/a2a/google_sdk/pydantic_ai_adapter/storage.py +26 -0
- aixtools-0.7.8/aixtools/a2a/google_sdk/remote_agent_connection.py +104 -0
- aixtools-0.7.8/aixtools/a2a/google_sdk/store/__init__.py +0 -0
- aixtools-0.7.8/aixtools/a2a/google_sdk/store/alembic.ini +148 -0
- aixtools-0.7.8/aixtools/a2a/google_sdk/store/config.py +3 -0
- aixtools-0.7.8/aixtools/a2a/google_sdk/store/ensure_database.py +176 -0
- aixtools-0.7.8/aixtools/a2a/google_sdk/store/migrations/env.py +97 -0
- aixtools-0.7.8/aixtools/a2a/google_sdk/store/migrations/script.py.mako +28 -0
- aixtools-0.7.8/aixtools/a2a/google_sdk/store/migrations/versions/68c6975ed20b_added_a2a_sdk_task_table.py +44 -0
- aixtools-0.7.8/aixtools/a2a/google_sdk/utils.py +116 -0
- aixtools-0.7.8/aixtools/a2a/utils.py +116 -0
- aixtools-0.7.8/aixtools/agents/__init__.py +12 -0
- aixtools-0.7.8/aixtools/agents/agent.py +264 -0
- aixtools-0.7.8/aixtools/agents/agent_batch.py +71 -0
- aixtools-0.7.8/aixtools/agents/context/data_models.py +56 -0
- aixtools-0.7.8/aixtools/agents/context/processors/audio.py +214 -0
- aixtools-0.7.8/aixtools/agents/context/processors/code.py +83 -0
- aixtools-0.7.8/aixtools/agents/context/processors/common.py +134 -0
- aixtools-0.7.8/aixtools/agents/context/processors/document.py +147 -0
- aixtools-0.7.8/aixtools/agents/context/processors/image.py +109 -0
- aixtools-0.7.8/aixtools/agents/context/processors/json.py +182 -0
- aixtools-0.7.8/aixtools/agents/context/processors/spreadsheet.py +443 -0
- aixtools-0.7.8/aixtools/agents/context/processors/table_detector/char_grid/char_grid_detector_col.py +82 -0
- aixtools-0.7.8/aixtools/agents/context/processors/table_detector/char_grid/char_grid_detector_flood.py +92 -0
- aixtools-0.7.8/aixtools/agents/context/processors/table_detector/char_grid/char_grid_detector_row.py +74 -0
- aixtools-0.7.8/aixtools/agents/context/processors/table_detector/char_grid/table_detector_sheet_char.py +282 -0
- aixtools-0.7.8/aixtools/agents/context/processors/table_detector/char_grid/table_header_detector_char.py +177 -0
- aixtools-0.7.8/aixtools/agents/context/processors/table_detector/char_grid/table_merger.py +53 -0
- aixtools-0.7.8/aixtools/agents/context/processors/table_detector/table_detector_base.py +94 -0
- aixtools-0.7.8/aixtools/agents/context/processors/table_detector/table_detector_char.py +30 -0
- aixtools-0.7.8/aixtools/agents/context/processors/table_detector/table_region.py +173 -0
- aixtools-0.7.8/aixtools/agents/context/processors/table_detector/worksheet_as_char.py +310 -0
- aixtools-0.7.8/aixtools/agents/context/processors/tabular.py +306 -0
- aixtools-0.7.8/aixtools/agents/context/processors/text.py +183 -0
- aixtools-0.7.8/aixtools/agents/context/processors/xml.py +124 -0
- aixtools-0.7.8/aixtools/agents/context/processors/yaml.py +87 -0
- aixtools-0.7.8/aixtools/agents/context/reader.py +281 -0
- aixtools-0.7.8/aixtools/agents/nodes_to_md.py +201 -0
- aixtools-0.7.8/aixtools/agents/nodes_to_message.py +30 -0
- aixtools-0.7.8/aixtools/agents/nodes_to_str.py +109 -0
- aixtools-0.7.8/aixtools/agents/print_nodes.py +54 -0
- aixtools-0.7.8/aixtools/agents/prompt.py +270 -0
- aixtools-0.7.8/aixtools/app.py +143 -0
- aixtools-0.7.8/aixtools/auth/__init__.py +0 -0
- aixtools-0.7.8/aixtools/auth/auth.py +293 -0
- aixtools-0.7.8/aixtools/chainlit.md +14 -0
- aixtools-0.7.8/aixtools/compliance/__init__.py +9 -0
- aixtools-0.7.8/aixtools/compliance/private_data.py +137 -0
- aixtools-0.7.8/aixtools/compliance/utils.py +44 -0
- aixtools-0.7.8/aixtools/context.py +23 -0
- aixtools-0.7.8/aixtools/db/__init__.py +17 -0
- aixtools-0.7.8/aixtools/db/database.py +110 -0
- aixtools-0.7.8/aixtools/db/vector_db.py +115 -0
- aixtools-0.7.8/aixtools/evals/__init__.py +0 -0
- aixtools-0.7.8/aixtools/evals/__main__.py +74 -0
- aixtools-0.7.8/aixtools/evals/dataset.py +87 -0
- aixtools-0.7.8/aixtools/evals/discovery.py +186 -0
- aixtools-0.7.8/aixtools/evals/run_evals.py +98 -0
- aixtools-0.7.8/aixtools/google/client.py +25 -0
- aixtools-0.7.8/aixtools/log_view/__init__.py +17 -0
- aixtools-0.7.8/aixtools/log_view/app.py +195 -0
- aixtools-0.7.8/aixtools/log_view/display.py +285 -0
- aixtools-0.7.8/aixtools/log_view/export.py +51 -0
- aixtools-0.7.8/aixtools/log_view/filters.py +41 -0
- aixtools-0.7.8/aixtools/log_view/log_utils.py +26 -0
- aixtools-0.7.8/aixtools/log_view/node_summary.py +229 -0
- aixtools-0.7.8/aixtools/logfilters/__init__.py +7 -0
- aixtools-0.7.8/aixtools/logfilters/context_filter.py +72 -0
- aixtools-0.7.8/aixtools/logging/__init__.py +30 -0
- aixtools-0.7.8/aixtools/logging/log_objects.py +240 -0
- aixtools-0.7.8/aixtools/logging/logging_config.py +161 -0
- aixtools-0.7.8/aixtools/logging/mcp_log_models.py +102 -0
- aixtools-0.7.8/aixtools/logging/mcp_logger.py +172 -0
- aixtools-0.7.8/aixtools/logging/model_patch_logging.py +87 -0
- aixtools-0.7.8/aixtools/logging/open_telemetry.py +36 -0
- aixtools-0.7.8/aixtools/mcp/__init__.py +15 -0
- aixtools-0.7.8/aixtools/mcp/client.py +306 -0
- aixtools-0.7.8/aixtools/mcp/example_client.py +30 -0
- aixtools-0.7.8/aixtools/mcp/example_server.py +22 -0
- aixtools-0.7.8/aixtools/mcp/exceptions.py +5 -0
- aixtools-0.7.8/aixtools/mcp/fast_mcp_log.py +31 -0
- aixtools-0.7.8/aixtools/mcp/faulty_mcp.py +319 -0
- aixtools-0.7.8/aixtools/mcp/middleware.py +54 -0
- aixtools-0.7.8/aixtools/mcp/server.py +76 -0
- aixtools-0.7.8/aixtools/model_patch/model_patch.py +63 -0
- aixtools-0.7.8/aixtools/server/__init__.py +23 -0
- aixtools-0.7.8/aixtools/server/app_mounter.py +90 -0
- aixtools-0.7.8/aixtools/server/path.py +153 -0
- aixtools-0.7.8/aixtools/server/utils.py +120 -0
- aixtools-0.7.8/aixtools/testing/__init__.py +9 -0
- aixtools-0.7.8/aixtools/testing/agent_mock.py +143 -0
- aixtools-0.7.8/aixtools/testing/aix_test_model.py +186 -0
- aixtools-0.7.8/aixtools/testing/mock_tool.py +66 -0
- aixtools-0.7.8/aixtools/testing/model_patch_cache.py +279 -0
- aixtools-0.7.8/aixtools/tools/doctor/__init__.py +3 -0
- aixtools-0.7.8/aixtools/tools/doctor/mcp_tool_doctor.py +79 -0
- aixtools-0.7.8/aixtools/tools/doctor/tool_doctor.py +65 -0
- aixtools-0.7.8/aixtools/tools/doctor/tool_recommendation.py +49 -0
- aixtools-0.7.8/aixtools/utils/__init__.py +35 -0
- aixtools-0.7.8/aixtools/utils/chainlit/cl_agent_show.py +82 -0
- aixtools-0.7.8/aixtools/utils/chainlit/cl_utils.py +168 -0
- aixtools-0.7.8/aixtools/utils/config.py +274 -0
- aixtools-0.7.8/aixtools/utils/config_util.py +95 -0
- aixtools-0.7.8/aixtools/utils/crypto.py +42 -0
- aixtools-0.7.8/aixtools/utils/enum_with_description.py +37 -0
- aixtools-0.7.8/aixtools/utils/files.py +17 -0
- aixtools-0.7.8/aixtools/utils/persisted_dict.py +99 -0
- aixtools-0.7.8/aixtools/utils/utils.py +199 -0
- aixtools-0.7.8/aixtools/vault/__init__.py +7 -0
- aixtools-0.7.8/aixtools/vault/vault.py +159 -0
- aixtools-0.7.8/aixtools.egg-info/SOURCES.txt +134 -0
- aixtools-0.7.8/pyproject.toml +92 -0
- aixtools-0.7.8/setup.cfg +4 -0
aixtools-0.7.8/PKG-INFO
ADDED
|
@@ -0,0 +1,1121 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aixtools
|
|
3
|
+
Version: 0.7.8
|
|
4
|
+
Summary: Tools for AI exploration and debugging
|
|
5
|
+
Requires-Python: >=3.11.2
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: a2a-sdk>=0.3.1
|
|
8
|
+
Requires-Dist: alembic>=1.17.1
|
|
9
|
+
Requires-Dist: cachebox>=5.0.1
|
|
10
|
+
Requires-Dist: chainlit>=2.5.5
|
|
11
|
+
Requires-Dist: colorlog>=6.9.0
|
|
12
|
+
Requires-Dist: fasta2a>=0.5.0
|
|
13
|
+
Requires-Dist: fastmcp>=2.13.0
|
|
14
|
+
Requires-Dist: hvac>=2.3.0
|
|
15
|
+
Requires-Dist: ipykernel>=6.29.5
|
|
16
|
+
Requires-Dist: langchain-chroma>=0.2.3
|
|
17
|
+
Requires-Dist: langchain-ollama>=0.3.2
|
|
18
|
+
Requires-Dist: langchain-openai>=0.3.14
|
|
19
|
+
Requires-Dist: markitdown[docx,pdf,pptx,xls,xlsx]>=0.1.3
|
|
20
|
+
Requires-Dist: mcp>=1.20.0
|
|
21
|
+
Requires-Dist: mypy>=1.18.2
|
|
22
|
+
Requires-Dist: pandas>=2.2.3
|
|
23
|
+
Requires-Dist: psycopg2-binary>=2.9.11
|
|
24
|
+
Requires-Dist: pydantic-evals>=0.4.10
|
|
25
|
+
Requires-Dist: pydantic-ai>=1.11.1
|
|
26
|
+
Requires-Dist: pyjwt>=2.10.1
|
|
27
|
+
Requires-Dist: pylint>=3.3.7
|
|
28
|
+
Requires-Dist: rich>=14.0.0
|
|
29
|
+
Requires-Dist: ruff>=0.11.6
|
|
30
|
+
Requires-Dist: sqlalchemy>=2.0.44
|
|
31
|
+
Requires-Dist: streamlit>=1.44.1
|
|
32
|
+
Requires-Dist: tiktoken>=0.9.0
|
|
33
|
+
Requires-Dist: openpyxl>=3.1.5
|
|
34
|
+
Requires-Dist: xlrd>=2.0.2
|
|
35
|
+
Requires-Dist: odfpy>=1.4.1
|
|
36
|
+
Requires-Dist: watchdog>=6.0.0
|
|
37
|
+
Provides-Extra: test
|
|
38
|
+
Requires-Dist: pyyaml; extra == "test"
|
|
39
|
+
Provides-Extra: feature
|
|
40
|
+
Requires-Dist: logfire; extra == "feature"
|
|
41
|
+
|
|
42
|
+
# AIXtools
|
|
43
|
+
|
|
44
|
+
AIXtools is a comprehensive Python library for AI agent development, debugging, and deployment. It provides a complete toolkit for building, testing, and monitoring AI agents with support for multiple model providers, advanced logging, and agent-to-agent communication.
|
|
45
|
+
|
|
46
|
+
## Capabilities
|
|
47
|
+
|
|
48
|
+
- **[Installation](#installation)**
|
|
49
|
+
- **[Environment Configuration](#environment-configuration)**
|
|
50
|
+
- **[Agents](#agents)** - Core agent functionality
|
|
51
|
+
- Basic Agent Usage
|
|
52
|
+
- Agent Development & Management
|
|
53
|
+
- Agent Batch Processing
|
|
54
|
+
- Node Debugging and Visualization
|
|
55
|
+
- **[Context Engineering](#context-engineering)** - Transform files into agent-readable content
|
|
56
|
+
- File Type Processors
|
|
57
|
+
- Configuration
|
|
58
|
+
- Processing Examples
|
|
59
|
+
- **[Agent-to-Agent Communication](#a2a-agent-to-agent-communication)** - Inter-agent communication framework
|
|
60
|
+
- Core Features
|
|
61
|
+
- Google SDK Integration
|
|
62
|
+
- Remote Agent Connections
|
|
63
|
+
- **[Testing & Tools](#testing--tools)** - Comprehensive testing utilities
|
|
64
|
+
- Running Tests
|
|
65
|
+
- Testing Utilities
|
|
66
|
+
- Mock Tool System
|
|
67
|
+
- Model Patch Caching
|
|
68
|
+
- Agent Mock
|
|
69
|
+
- FaultyMCP Testing Server
|
|
70
|
+
- MCP Tool Doctor
|
|
71
|
+
- Tool Doctor
|
|
72
|
+
- Evaluations
|
|
73
|
+
- **[Logging & Debugging](#logging--debugging)** - Advanced logging and debugging
|
|
74
|
+
- Basic Logging
|
|
75
|
+
- Log Viewing Application
|
|
76
|
+
- Object Logging
|
|
77
|
+
- MCP Logging
|
|
78
|
+
- **[Databases](#databases)** - Traditional and vector database support
|
|
79
|
+
- **[Chainlit & HTTP Server](#chainlit--http-server)** - Web interfaces and server framework
|
|
80
|
+
- Chainlit Integration
|
|
81
|
+
- HTTP Server Framework
|
|
82
|
+
- **[Programming Utilities](#programming-utilities)** - Essential utilities
|
|
83
|
+
- Persisted Dictionary
|
|
84
|
+
- Enum with Description
|
|
85
|
+
- Context Management
|
|
86
|
+
- Configuration Management
|
|
87
|
+
- File Utilities
|
|
88
|
+
- Chainlit Utilities
|
|
89
|
+
|
|
90
|
+
## Installation
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
uv add aixtools
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Updating**
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
uv add --upgrade aixtools
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Environment Configuration
|
|
103
|
+
|
|
104
|
+
AIXtools requires environment variables for model providers.
|
|
105
|
+
|
|
106
|
+
**IMPORTANT:** Create a `.env` file based on `.env_template`:
|
|
107
|
+
|
|
108
|
+
Here is an example configuration:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
# Model family (azure, openai, or ollama)
|
|
112
|
+
MODEL_FAMILY=azure
|
|
113
|
+
MODEL_TIMEOUT=120
|
|
114
|
+
|
|
115
|
+
# Azure OpenAI
|
|
116
|
+
AZURE_OPENAI_ENDPOINT=https://your_endpoint.openai.azure.com
|
|
117
|
+
AZURE_OPENAI_API_VERSION=2024-06-01
|
|
118
|
+
AZURE_OPENAI_API_KEY=your_secret_key
|
|
119
|
+
AZURE_MODEL_NAME=gpt-4o
|
|
120
|
+
|
|
121
|
+
# OpenAI
|
|
122
|
+
OPENAI_MODEL_NAME=gpt-4.5-preview
|
|
123
|
+
OPENAI_API_KEY=openai_api_key
|
|
124
|
+
|
|
125
|
+
# Ollama
|
|
126
|
+
OLLAMA_MODEL_NAME=llama3.2:3b-instruct-fp16
|
|
127
|
+
OLLAMA_LOCAL_URL=http://localhost:11434/v1
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Agents
|
|
131
|
+
|
|
132
|
+
### Basic Agent Usage
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
from aixtools.agents.agent import get_agent, run_agent
|
|
136
|
+
|
|
137
|
+
async def main():
|
|
138
|
+
agent = get_agent(system_prompt="You are a helpful assistant.")
|
|
139
|
+
result, nodes = await run_agent(agent, "Explain quantum computing")
|
|
140
|
+
print(result)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Agent Development & Management
|
|
144
|
+
|
|
145
|
+
The agent system provides a unified interface for creating and managing AI agents across different model providers.
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
from aixtools.agents.agent import get_agent, run_agent
|
|
149
|
+
|
|
150
|
+
# Create an agent with default model
|
|
151
|
+
agent = get_agent(system_prompt="You are a helpful assistant.")
|
|
152
|
+
|
|
153
|
+
# Run the agent
|
|
154
|
+
result, nodes = await run_agent(agent, "Tell me about AI")
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Node Debugging and Visualization
|
|
158
|
+
|
|
159
|
+
The `print_nodes` module provides a clean, indented output for easy reading of the node from agent execution.
|
|
160
|
+
|
|
161
|
+
```python
|
|
162
|
+
from aixtools.agents.print_nodes import print_nodes, print_node
|
|
163
|
+
from aixtools.agents.agent import get_agent, run_agent
|
|
164
|
+
|
|
165
|
+
agent = get_agent(system_prompt="You are a helpful assistant.")
|
|
166
|
+
result, nodes = await run_agent(agent, "Explain quantum computing")
|
|
167
|
+
# Print all execution nodes for debugging
|
|
168
|
+
print_nodes(nodes)
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
**Features:**
|
|
172
|
+
- Node Type Detection: Automatically handles different node types (`UserPromptNode`, `CallToolsNode`, `ModelRequestNode`, `End`)
|
|
173
|
+
- Formatted Output: Provides clean, indented output for easy reading
|
|
174
|
+
- Tool Call Visualization: Shows tool names and arguments for tool calls
|
|
175
|
+
- Text Content Display: Formats text parts with proper indentation
|
|
176
|
+
- Model Request Summary: Shows character count for model requests to avoid verbose output
|
|
177
|
+
|
|
178
|
+
**Node Types Supported:**
|
|
179
|
+
- `UserPromptNode` - Displays user prompts with indentation
|
|
180
|
+
- `CallToolsNode` - Shows tool calls with names and arguments
|
|
181
|
+
- `ModelRequestNode` - Summarizes model requests with character count
|
|
182
|
+
- `End` - Marks the end of execution (output suppressed by default)
|
|
183
|
+
|
|
184
|
+
### Agent Batch Processing
|
|
185
|
+
|
|
186
|
+
Process multiple agent queries simultaneously with built-in concurrency control and result aggregation.
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
from aixtools.agents.agent_batch import agent_batch, AgentQueryParams
|
|
190
|
+
|
|
191
|
+
# Create query parameters
|
|
192
|
+
query_parameters = [
|
|
193
|
+
AgentQueryParams(prompt="What is the meaning of life"),
|
|
194
|
+
AgentQueryParams(prompt="Who is the prime minister of Canada")
|
|
195
|
+
]
|
|
196
|
+
|
|
197
|
+
# Run queries in batches
|
|
198
|
+
async for result in agent_batch(query_parameters):
|
|
199
|
+
print(result)
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Context Engineering
|
|
203
|
+
|
|
204
|
+
Transform file formats into agent-readable content with enforced size limits to prevent context overflow. The main entry point is the `read_file()` function in `aixtools/agents/context/reader.py`, which provides automatic file type detection and delegates to specialized processors for each file type.
|
|
205
|
+
|
|
206
|
+
### Basic Usage
|
|
207
|
+
|
|
208
|
+
The `read_file()` function in `reader.py` is the main interface for processing files. It automatically detects file types and applies appropriate truncation strategies.
|
|
209
|
+
|
|
210
|
+
```python
|
|
211
|
+
from aixtools.agents.context.reader import read_file
|
|
212
|
+
from pathlib import Path
|
|
213
|
+
|
|
214
|
+
# Read a file with automatic type detection and truncation
|
|
215
|
+
result = read_file(Path("data.csv"))
|
|
216
|
+
|
|
217
|
+
if result.success:
|
|
218
|
+
print(f"File type: {result.file_type}")
|
|
219
|
+
print(f"Content length: {len(result.content)}")
|
|
220
|
+
print(f"Truncation info: {result.truncation_info}")
|
|
221
|
+
print(result.content)
|
|
222
|
+
|
|
223
|
+
# Optionally specify custom tokenizer and limits
|
|
224
|
+
result = read_file(
|
|
225
|
+
Path("large_file.json"),
|
|
226
|
+
max_tokens_per_file=10000,
|
|
227
|
+
max_total_output=100000
|
|
228
|
+
)
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Architecture
|
|
232
|
+
|
|
233
|
+
The context engineering system is organized with `reader.py` as the main interface:
|
|
234
|
+
- `reader.py` - Main `read_file()` function with file type detection and processing coordination
|
|
235
|
+
- `config.py` - Configurable size limits and thresholds
|
|
236
|
+
- `processors/` - Specialized processors for each file type (text, code, JSON, CSV, PDF, etc.)
|
|
237
|
+
- `data_models.py` - Data classes for results and metadata
|
|
238
|
+
|
|
239
|
+
### Supported File Types
|
|
240
|
+
|
|
241
|
+
- Text files (`.txt`, `.log`, `.md`)
|
|
242
|
+
- Code files (Python, JavaScript, etc.)
|
|
243
|
+
- Structured data (`JSON`, `YAML`, `XML`)
|
|
244
|
+
- Tabular data (`CSV`, `TSV`)
|
|
245
|
+
- Documents (`PDF`, `DOCX`)
|
|
246
|
+
- Spreadsheets (`.xlsx`, `.xls`, `.ods`)
|
|
247
|
+
- Images (`PNG`, `JPEG`, `GIF`, `WEBP`)
|
|
248
|
+
- Audio files
|
|
249
|
+
|
|
250
|
+
### Key Features
|
|
251
|
+
|
|
252
|
+
- Automatic file type detection based on MIME types and extensions
|
|
253
|
+
- Token-based truncation with configurable limits per file
|
|
254
|
+
- Intelligent content sampling (head + tail rows for tabular data)
|
|
255
|
+
- Structure-aware truncation for `JSON`, `YAML`, and `XML`
|
|
256
|
+
- Markdown conversion for documents using `markitdown`
|
|
257
|
+
- Binary content support for images with metadata extraction
|
|
258
|
+
- Comprehensive error handling with partial results when possible
|
|
259
|
+
|
|
260
|
+
### Configuration
|
|
261
|
+
|
|
262
|
+
All limits are configurable via environment variables:
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
# Output limits
|
|
266
|
+
MAX_TOKENS_PER_FILE=5000
|
|
267
|
+
MAX_TOTAL_OUTPUT=50000
|
|
268
|
+
|
|
269
|
+
# Text truncation
|
|
270
|
+
MAX_LINES=200
|
|
271
|
+
MAX_LINE_LENGTH=1000
|
|
272
|
+
|
|
273
|
+
# Tabular truncation
|
|
274
|
+
MAX_COLUMNS=50
|
|
275
|
+
DEFAULT_ROWS_HEAD=20
|
|
276
|
+
DEFAULT_ROWS_MIDDLE=10
|
|
277
|
+
DEFAULT_ROWS_TAIL=10
|
|
278
|
+
MAX_CELL_LENGTH=500
|
|
279
|
+
|
|
280
|
+
# Images
|
|
281
|
+
MAX_IMAGE_ATTACHMENT_SIZE=2097152 # 2MB
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Processing Examples
|
|
285
|
+
|
|
286
|
+
The recommended approach is to use the `read_file()` function which automatically handles file type detection and processing. However, you can also use individual processors directly for specific file types.
|
|
287
|
+
|
|
288
|
+
#### Using read_file() (Recommended)
|
|
289
|
+
|
|
290
|
+
```python
|
|
291
|
+
from aixtools.agents.context.reader import read_file
|
|
292
|
+
from pathlib import Path
|
|
293
|
+
|
|
294
|
+
# Process any file type automatically
|
|
295
|
+
result = read_file(Path("data.csv"))
|
|
296
|
+
if result.success:
|
|
297
|
+
print(result.content)
|
|
298
|
+
|
|
299
|
+
# Works with all supported types
|
|
300
|
+
pdf_result = read_file(Path("report.pdf"))
|
|
301
|
+
excel_result = read_file(Path("workbook.xlsx"))
|
|
302
|
+
json_result = read_file(Path("config.json"))
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
#### Processing Tabular Data Directly
|
|
306
|
+
|
|
307
|
+
```python
|
|
308
|
+
from aixtools.agents.context.processors.tabular import process_tabular
|
|
309
|
+
from pathlib import Path
|
|
310
|
+
|
|
311
|
+
# Process specific row range from large CSV
|
|
312
|
+
result = process_tabular(
|
|
313
|
+
file_path=Path("large_data.csv"),
|
|
314
|
+
start_row=100,
|
|
315
|
+
end_row=200,
|
|
316
|
+
max_columns=20,
|
|
317
|
+
max_cell_length=500
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
print(f"Rows shown: {result.truncation_info.rows_shown}")
|
|
321
|
+
print(f"Columns shown: {result.truncation_info.columns_shown}")
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
#### Processing Spreadsheets Directly
|
|
325
|
+
|
|
326
|
+
```python
|
|
327
|
+
from aixtools.agents.context.processors.spreadsheet import process_spreadsheet
|
|
328
|
+
from pathlib import Path
|
|
329
|
+
|
|
330
|
+
# Process Excel file with multiple sheets
|
|
331
|
+
result = process_spreadsheet(
|
|
332
|
+
file_path=Path("workbook.xlsx"),
|
|
333
|
+
max_sheets=3,
|
|
334
|
+
max_rows_per_sheet_head=20,
|
|
335
|
+
max_rows_per_sheet_tail=10
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
# Content includes all processed sheets with truncation info
|
|
339
|
+
print(result.content)
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
#### Processing Documents Directly
|
|
343
|
+
|
|
344
|
+
```python
|
|
345
|
+
from aixtools.agents.context.processors.document import process_document
|
|
346
|
+
from pathlib import Path
|
|
347
|
+
|
|
348
|
+
# Convert PDF to markdown and truncate
|
|
349
|
+
result = process_document(
|
|
350
|
+
file_path=Path("report.pdf"),
|
|
351
|
+
max_lines=200,
|
|
352
|
+
max_line_length=1000
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
if result.was_extracted:
|
|
356
|
+
print("Document successfully converted to markdown")
|
|
357
|
+
print(result.content)
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### Output Format
|
|
361
|
+
|
|
362
|
+
All processors return consistent output with metadata:
|
|
363
|
+
|
|
364
|
+
```
|
|
365
|
+
File: data.csv
|
|
366
|
+
Columns: 8 (of 20000 total)
|
|
367
|
+
Rows: 20 (of 1000000 total)
|
|
368
|
+
|
|
369
|
+
col1,col2,...,col8
|
|
370
|
+
value1,value2,...
|
|
371
|
+
...
|
|
372
|
+
|
|
373
|
+
Truncated: columns: 8 of 20000, rows: 20 of 1000000, 45 cells
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
The context engineering system ensures agents receive properly formatted, size-limited content that fits within token budgets while preserving the most relevant information from each file type.
|
|
377
|
+
|
|
378
|
+
## A2A (Agent-to-Agent Communication)
|
|
379
|
+
|
|
380
|
+
The `A2A` module provides a comprehensive framework for enabling sophisticated communication between AI agents across different environments and platforms. It includes Google SDK integration, `PydanticAI` adapters, and `FastA2A` application conversion capabilities.
|
|
381
|
+
|
|
382
|
+
### Core Features
|
|
383
|
+
|
|
384
|
+
**Agent Application Conversion**
|
|
385
|
+
- Convert `PydanticAI` agents into `FastA2A` applications (deprecated)
|
|
386
|
+
- Support for session metadata extraction and context management
|
|
387
|
+
- Custom worker classes with enhanced data part support
|
|
388
|
+
- Automatic handling of user and session identification
|
|
389
|
+
|
|
390
|
+
**Remote Agent Connections**
|
|
391
|
+
- Establish connections between agents across different environments
|
|
392
|
+
- Asynchronous message sending with task polling capabilities
|
|
393
|
+
- Terminal state detection and error handling
|
|
394
|
+
- Support for various message types including text, files, and data
|
|
395
|
+
|
|
396
|
+
**Google SDK Integration**
|
|
397
|
+
- Native integration with Google's A2A SDK
|
|
398
|
+
- Card-based agent representation and discovery
|
|
399
|
+
- `PydanticAI` adapter for seamless Google SDK compatibility
|
|
400
|
+
- Storage and execution management for agent interactions
|
|
401
|
+
|
|
402
|
+
### Basic Usage
|
|
403
|
+
|
|
404
|
+
Enable sophisticated agent interactions with Google SDK integration and `PydanticAI` adapters.
|
|
405
|
+
|
|
406
|
+
```python
|
|
407
|
+
from aixtools.a2a.google_sdk.remote_agent_connection import RemoteAgentConnection
|
|
408
|
+
from aixtools.a2a.app import agent_to_a2a
|
|
409
|
+
|
|
410
|
+
# Convert a PydanticAI agent to FastA2A application
|
|
411
|
+
a2a_app = agent_to_a2a(
|
|
412
|
+
agent=my_agent,
|
|
413
|
+
name="MyAgent",
|
|
414
|
+
description="A helpful AI assistant",
|
|
415
|
+
skills=[{"name": "chat", "description": "General conversation"}]
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
# Connect agents across different environments
|
|
419
|
+
connection = RemoteAgentConnection(card=agent_card, client=a2a_client)
|
|
420
|
+
response = await connection.send_message_with_polling(message)
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### Postgres DB Store for A2A agent
|
|
424
|
+
|
|
425
|
+
See implementation: `aixtools/a2a/google_sdk/store`
|
|
426
|
+
|
|
427
|
+
#### Alembic
|
|
428
|
+
|
|
429
|
+
In order to take full control of the database schema management Alembic is used for handling database migrations.
|
|
430
|
+
Thus make sure, that google-sdk Store objects are being created with parameter create_table=False
|
|
431
|
+
```python
|
|
432
|
+
from a2a.server.tasks import DatabaseTaskStore
|
|
433
|
+
|
|
434
|
+
...
|
|
435
|
+
|
|
436
|
+
task_store=DatabaseTaskStore(engine=db_engine, create_table=False)
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
#### Setup of database and applying migrations (manual if needed):
|
|
440
|
+
|
|
441
|
+
configure POSTGRES_URL env variable
|
|
442
|
+
```.dotenv
|
|
443
|
+
POSTGRES_URL=postgresql+asyncpg://user:password@localhost:5432/a2a_magic_db
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
```shell
|
|
448
|
+
# from scope of your a2a service
|
|
449
|
+
|
|
450
|
+
#activate your virtual environment
|
|
451
|
+
kzwk877@degfqx35d621DD a2a_magic_service % source .venv/bin/activate
|
|
452
|
+
# set the PATH_TO_ALEMBIC_CONFIG environment variable to point to the alembic configuration directory
|
|
453
|
+
(a2a_magic_service) kzwk877@degfqx35d621DD a2a_magic_service % export PATH_TO_ALEMBIC_CONFIG="$(pwd)/.venv/lib/python3.12/site-packages/aixtools/a2a/google_sdk/store"
|
|
454
|
+
# Make sure that database is existed
|
|
455
|
+
(a2a_magic_service) kzwk877@degfqx35d621DD a2a_magic_service % uv run "${PATH_TO_ALEMBIC_CONFIG}/ensure_database.py"
|
|
456
|
+
2025-11-11 10:08:51.501 WARNING [root] Looking for '.env' file in default directory
|
|
457
|
+
2025-11-11 10:08:52.750 INFO [root] Using .env file at '/PATH_TO_A2A_SERVICE/a2a_magic_service/.env'
|
|
458
|
+
2025-11-11 10:08:52.751 INFO [root] Using MAIN_PROJECT_DIR='/PATH_TO_A2A_SERVICE/a2a_magic_service'
|
|
459
|
+
2025-11-11 10:08:52.752 WARNING [root] Using DATA_DIR='/app/data'
|
|
460
|
+
2025-11-11 10:08:52.757 INFO [__main__] Starting database creation script...
|
|
461
|
+
...
|
|
462
|
+
2025-11-11 10:08:52.821 INFO [__main__] Creating database 'a2a_magic_db'...
|
|
463
|
+
2025-11-11 10:08:52.904 INFO [__main__] Database 'a2a_magic_db' created successfully
|
|
464
|
+
...
|
|
465
|
+
2025-11-11 10:08:52.921 INFO [__main__] Database creation script completed successfully!
|
|
466
|
+
# Apply alembic migrations
|
|
467
|
+
(a2a_magic_service) kzwk877@degfqx35d621DD a2a_magic_service % alembic --config "${PATH_TO_ALEMBIC_CONFIG}/alembic.ini" upgrade head
|
|
468
|
+
2025-11-11 10:11:34.185 WARNING [root] Looking for '.env' file in default directory
|
|
469
|
+
2025-11-11 10:11:35.046 WARNING [root] Looking for '.env' file at '/PATH_TO_A2A_SERVICE/a2a_magic_service'
|
|
470
|
+
2025-11-11 10:11:35.047 INFO [root] Using .env file at '/PATH_TO_A2A_SERVICE/a2a_magic_service/.env'
|
|
471
|
+
2025-11-11 10:11:35.048 INFO [root] Using MAIN_PROJECT_DIR='/PATH_TO_A2A_SERVICE/a2a_magic_service'
|
|
472
|
+
2025-11-11 10:11:35.049 WARNING [root] Using DATA_DIR='/app/data'
|
|
473
|
+
2025-11-11 10:11:35.054 INFO [env_py] Using database URL for migrations: postgresql://user:password@localhost:5432/a2a_magic_db
|
|
474
|
+
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
|
|
475
|
+
INFO [alembic.runtime.migration] Will assume transactional DDL.
|
|
476
|
+
INFO [alembic.runtime.migration] Running upgrade -> 68c6975ed20b, Added a2a-sdk Task table
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
#### Schema modifications
|
|
480
|
+
|
|
481
|
+
if new schema modifications has been introduced with new versions of a2a sdk suggested way
|
|
482
|
+
to create new alembic migrations would be:
|
|
483
|
+
|
|
484
|
+
- launch a2a service with passed parameter to `DatabaseStore` `create_table=True`
|
|
485
|
+
- make sure that all new tables/columns are created in
|
|
486
|
+
the database (possibly an new request to a2a server needs to be made)
|
|
487
|
+
- create new alembic migration script
|
|
488
|
+
```shell
|
|
489
|
+
(a2a_magic_service) kzwk877@degfqx35d621DD % alembic --config "${PATH_TO_ALEMBIC_CONFIG}/alembic.ini" revision --autogenerate -m "New table introduced"
|
|
490
|
+
```
|
|
491
|
+
- review the generated migration script
|
|
492
|
+
- apply and test
|
|
493
|
+
|
|
494
|
+
## Databases
|
|
495
|
+
|
|
496
|
+
### Database Integration
|
|
497
|
+
|
|
498
|
+
Support for both traditional and vector databases with seamless integration.
|
|
499
|
+
|
|
500
|
+
```python
|
|
501
|
+
from aixtools.db.database import Database
|
|
502
|
+
from aixtools.db.vector_db import VectorDB
|
|
503
|
+
|
|
504
|
+
# Traditional database
|
|
505
|
+
db = Database("sqlite:///app.db")
|
|
506
|
+
|
|
507
|
+
# Vector database for embeddings
|
|
508
|
+
vector_db = VectorDB()
|
|
509
|
+
vector_db.add_documents(documents)
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
## Logging & Debugging
|
|
513
|
+
|
|
514
|
+
AixTools provides functionality for logging and debugging.
|
|
515
|
+
|
|
516
|
+
### Basic Logging and Debugging
|
|
517
|
+
|
|
518
|
+
```python
|
|
519
|
+
from aixtools.agents.agent import get_agent, run_agent
|
|
520
|
+
|
|
521
|
+
async def main():
|
|
522
|
+
# Create an agent
|
|
523
|
+
agent = get_agent(system_prompt="You are a helpful assistant.")
|
|
524
|
+
|
|
525
|
+
# Run agent - logging is automatic via ObjectLogger
|
|
526
|
+
result, nodes = await run_agent(
|
|
527
|
+
agent,
|
|
528
|
+
"Explain quantum computing",
|
|
529
|
+
debug=True, # Enable debug logging
|
|
530
|
+
log_model_requests=True # Log model requests/responses
|
|
531
|
+
)
|
|
532
|
+
|
|
533
|
+
print(f"Result: {result}")
|
|
534
|
+
print(f"Logged {len(nodes)} nodes")
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
### Log Viewing Application
|
|
538
|
+
|
|
539
|
+
Interactive `Streamlit` application for analyzing logged objects and debugging agent behavior.
|
|
540
|
+
|
|
541
|
+
**Features:**
|
|
542
|
+
- Log file selection and filtering
|
|
543
|
+
- Node visualization with expand/collapse
|
|
544
|
+
- Export capabilities to `JSON`
|
|
545
|
+
- Regex pattern matching
|
|
546
|
+
- Real-time log monitoring
|
|
547
|
+
|
|
548
|
+
```bash
|
|
549
|
+
# Run the log viewer
|
|
550
|
+
log_view
|
|
551
|
+
|
|
552
|
+
# Or specify custom log directory
|
|
553
|
+
log_view /path/to/logs
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
### Object Logging & Debugging
|
|
557
|
+
|
|
558
|
+
Advanced logging system with object serialization and visual debugging tools.
|
|
559
|
+
|
|
560
|
+
```python
|
|
561
|
+
from aixtools.logging.log_objects import ObjectLogger
|
|
562
|
+
|
|
563
|
+
# Log any pickleable object
|
|
564
|
+
with ObjectLogger() as logger:
|
|
565
|
+
logger.log({"message": "Hello, world!"})
|
|
566
|
+
logger.log(agent_response)
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
### MCP Logging
|
|
570
|
+
|
|
571
|
+
AIXtools provides MCP support for both client and server implementations with easier logging for debugging purposes.
|
|
572
|
+
|
|
573
|
+
**Example:**
|
|
574
|
+
|
|
575
|
+
Let's assume we have an MCP server that runs an agent tool.
|
|
576
|
+
|
|
577
|
+
Note that the `ctx: Context` parameter is passed to `run_agent()`, this will enable logging to the MCP client.
|
|
578
|
+
|
|
579
|
+
```python
|
|
580
|
+
@mcp.tool
|
|
581
|
+
async def my_tool_with_agent(query: str, ctx: Context) -> str:
|
|
582
|
+
""" A tool that uses an gents to process the query """
|
|
583
|
+
agent = get_agent()
|
|
584
|
+
async with get_qb_agent() as agent:
|
|
585
|
+
ret, nodes = await run_agent(agent=agent, prompt=query, ctx=ctx) # Enable MCP logging
|
|
586
|
+
return str(ret)
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
On the client side, you can create an agent connected to the MCP server, the nodes from the MCP server will show on the `STDOUT` so you can see what's going on the MCP server's agent loop.
|
|
590
|
+
|
|
591
|
+
```python
|
|
592
|
+
mcp = get_mcp_client("http://localhost:8000") # Get an MCP client with a default log handler that prints to STDOUT
|
|
593
|
+
agent = get_agent(toolsets=[mcp])
|
|
594
|
+
async with agent:
|
|
595
|
+
# The messages from the MCP server will be printed to the STDOUT
|
|
596
|
+
ret, nodes = await run_agent(agent, prompt="...")
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
#### MCP Server Logging
|
|
600
|
+
|
|
601
|
+
Create MCP servers with built-in logging capabilities.
|
|
602
|
+
|
|
603
|
+
```python
|
|
604
|
+
from aixtools.mcp.fast_mcp_log import FastMcpLog
|
|
605
|
+
|
|
606
|
+
# Use FastMCP server with logging
|
|
607
|
+
mcp = FastMcpLog("Demo")
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
## Testing & Tools
|
|
611
|
+
|
|
612
|
+
AIXtools provides comprehensive testing utilities and diagnostic tools for AI agent development and debugging.
|
|
613
|
+
|
|
614
|
+
### Running Tests
|
|
615
|
+
|
|
616
|
+
Execute the test suite using the provided scripts:
|
|
617
|
+
|
|
618
|
+
```bash
|
|
619
|
+
# Run all tests
|
|
620
|
+
./scripts/test.sh
|
|
621
|
+
|
|
622
|
+
# Run unit tests only
|
|
623
|
+
./scripts/test_unit.sh
|
|
624
|
+
|
|
625
|
+
# Run integration tests only
|
|
626
|
+
./scripts/test_integration.sh
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
### Testing Utilities
|
|
630
|
+
|
|
631
|
+
The testing module provides mock tools, model patching, and test utilities for comprehensive agent testing.
|
|
632
|
+
|
|
633
|
+
```python
|
|
634
|
+
from aixtools.testing.mock_tool import MockTool
|
|
635
|
+
from aixtools.testing.model_patch_cache import ModelPatchCache
|
|
636
|
+
from aixtools.testing.aix_test_model import AixTestModel
|
|
637
|
+
|
|
638
|
+
# Create mock tools for testing
|
|
639
|
+
mock_tool = MockTool(name="test_tool", response="mock response")
|
|
640
|
+
|
|
641
|
+
# Use model patch caching for consistent test results
|
|
642
|
+
cache = ModelPatchCache()
|
|
643
|
+
cached_response = cache.get_cached_response("test_prompt")
|
|
644
|
+
|
|
645
|
+
# Test model for controlled testing scenarios
|
|
646
|
+
test_model = AixTestModel()
|
|
647
|
+
```
|
|
648
|
+
|
|
649
|
+
### Mock Tool System
|
|
650
|
+
|
|
651
|
+
Create and manage mock tools for testing agent behavior without external dependencies.
|
|
652
|
+
|
|
653
|
+
```python
|
|
654
|
+
from aixtools.testing.mock_tool import MockTool
|
|
655
|
+
|
|
656
|
+
# Create a mock tool with predefined responses
|
|
657
|
+
mock_calculator = MockTool(
|
|
658
|
+
name="calculator",
|
|
659
|
+
description="Performs mathematical calculations",
|
|
660
|
+
response_map={
|
|
661
|
+
"2+2": "4",
|
|
662
|
+
"10*5": "50"
|
|
663
|
+
}
|
|
664
|
+
)
|
|
665
|
+
|
|
666
|
+
# Use in agent testing
|
|
667
|
+
agent = get_agent(tools=[mock_calculator])
|
|
668
|
+
result = await run_agent(agent, "What is 2+2?")
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
### Model Patch Caching
|
|
672
|
+
|
|
673
|
+
Cache model responses for consistent testing and development workflows.
|
|
674
|
+
|
|
675
|
+
```python
|
|
676
|
+
from aixtools.testing.model_patch_cache import ModelPatchCache
|
|
677
|
+
|
|
678
|
+
# Initialize cache
|
|
679
|
+
cache = ModelPatchCache(cache_dir="./test_cache")
|
|
680
|
+
|
|
681
|
+
# Cache responses for specific prompts
|
|
682
|
+
cache.cache_response("test prompt", "cached response")
|
|
683
|
+
|
|
684
|
+
# Retrieve cached responses
|
|
685
|
+
response = cache.get_cached_response("test prompt")
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
### Model Patching System
|
|
689
|
+
|
|
690
|
+
Dynamic model behavior modification for testing and debugging.
|
|
691
|
+
|
|
692
|
+
```python
|
|
693
|
+
from aixtools.model_patch.model_patch import ModelPatch
|
|
694
|
+
|
|
695
|
+
# Apply patches to models for testing
|
|
696
|
+
with ModelPatch() as patch:
|
|
697
|
+
patch.apply_response_override("test response")
|
|
698
|
+
result = await agent.run("test prompt")
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
### Agent Mock
|
|
702
|
+
|
|
703
|
+
Replay previously recorded agent runs without executing the actual agent. Useful for testing, debugging, and creating reproducible test cases.
|
|
704
|
+
|
|
705
|
+
```python
|
|
706
|
+
from aixtools.testing.agent_mock import AgentMock
|
|
707
|
+
from aixtools.agents.agent import get_agent, run_agent
|
|
708
|
+
|
|
709
|
+
# Run an agent and capture its execution
|
|
710
|
+
agent = get_agent(system_prompt="You are a helpful assistant.")
|
|
711
|
+
result, nodes = await run_agent(agent, "Explain quantum computing")
|
|
712
|
+
|
|
713
|
+
# Create a mock agent from the recorded nodes
|
|
714
|
+
agent_mock = AgentMock(nodes=nodes, result_output=result)
|
|
715
|
+
|
|
716
|
+
# Save the mock for later use
|
|
717
|
+
agent_mock.save(Path("test_data/quantum_mock.pkl"))
|
|
718
|
+
|
|
719
|
+
# Load and replay the mock agent
|
|
720
|
+
loaded_mock = AgentMock.load(Path("test_data/quantum_mock.pkl"))
|
|
721
|
+
result, nodes = await run_agent(loaded_mock, "any prompt") # Returns recorded nodes
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
### FaultyMCP Testing Server
|
|
725
|
+
|
|
726
|
+
A specialized MCP server designed for testing error handling and resilience in MCP client implementations. `FaultyMCP` simulates various failure scenarios including network errors, server crashes, and random exceptions.
|
|
727
|
+
|
|
728
|
+
**Features:**
|
|
729
|
+
- Configurable error probabilities for different request types
|
|
730
|
+
- HTTP 404 error injection for `POST`/`DELETE` requests
|
|
731
|
+
- Server crash simulation on `GET` requests
|
|
732
|
+
- Random exception throwing in tool operations
|
|
733
|
+
- MCP-specific error simulation (`ValidationError`, `ResourceError`, etc.)
|
|
734
|
+
- Safe mode for controlled testing
|
|
735
|
+
|
|
736
|
+
```python
|
|
737
|
+
from aixtools.mcp.faulty_mcp import run_server_on_port, config
|
|
738
|
+
|
|
739
|
+
# Configure error probabilities
|
|
740
|
+
config.prob_on_post_404 = 0.3 # 30% chance of 404 on POST
|
|
741
|
+
config.prob_on_get_crash = 0.1 # 10% chance of crash on GET
|
|
742
|
+
config.prob_in_list_tools_throw = 0.2 # 20% chance of exception in tools/list
|
|
743
|
+
|
|
744
|
+
# Run the faulty server
|
|
745
|
+
run_server_on_port()
|
|
746
|
+
```
|
|
747
|
+
|
|
748
|
+
**Command Line Usage:**
|
|
749
|
+
|
|
750
|
+
```bash
|
|
751
|
+
# Run with default error probabilities
|
|
752
|
+
python -m aixtools.mcp.faulty_mcp
|
|
753
|
+
|
|
754
|
+
# Run in safe mode (no errors by default)
|
|
755
|
+
python -m aixtools.mcp.faulty_mcp --safe-mode
|
|
756
|
+
|
|
757
|
+
# Custom configuration
|
|
758
|
+
python -m aixtools.mcp.faulty_mcp \
|
|
759
|
+
--port 8888 \
|
|
760
|
+
--prob-on-post-404 0.2 \
|
|
761
|
+
--prob-on-get-crash 0.1 \
|
|
762
|
+
--prob-in-list-tools-throw 0.3
|
|
763
|
+
```
|
|
764
|
+
|
|
765
|
+
**Available Test Tools:**
|
|
766
|
+
- `add(a, b)` - Reliable addition operation
|
|
767
|
+
- `multiply(a, b)` - Reliable multiplication operation
|
|
768
|
+
- `always_error()` - Always throws an exception
|
|
769
|
+
- `random_throw_exception(a, b, prob)` - Randomly throws exceptions
|
|
770
|
+
- `freeze_server(seconds)` - Simulates server freeze
|
|
771
|
+
- `throw_404_exception()` - Throws HTTP 404 error
|
|
772
|
+
|
|
773
|
+
### MCP Tool Doctor
|
|
774
|
+
|
|
775
|
+
Analyze tools from MCP (Model Context Protocol) servers and receive AI-powered recommendations for improvement.
|
|
776
|
+
|
|
777
|
+
```python
|
|
778
|
+
from aixtools.tools.doctor.mcp_tool_doctor import tool_doctor_mcp
|
|
779
|
+
from pydantic_ai.mcp import MCPServerStreamableHTTP, MCPServerStdio
|
|
780
|
+
|
|
781
|
+
# Analyze HTTP MCP server
|
|
782
|
+
recommendations = await tool_doctor_mcp(mcp_url='http://127.0.0.1:8000/mcp')
|
|
783
|
+
for rec in recommendations:
|
|
784
|
+
print(rec)
|
|
785
|
+
|
|
786
|
+
# Analyze STDIO MCP server
|
|
787
|
+
server = MCPServerStdio(command='fastmcp', args=['run', 'my_server.py'])
|
|
788
|
+
recommendations = await tool_doctor_mcp(mcp_server=server, verbose=True)
|
|
789
|
+
```
|
|
790
|
+
|
|
791
|
+
**Command Line Usage:**
|
|
792
|
+
|
|
793
|
+
```bash
|
|
794
|
+
# Analyze HTTP MCP server (default)
|
|
795
|
+
tool_doctor_mcp
|
|
796
|
+
|
|
797
|
+
# Analyze specific HTTP MCP server
|
|
798
|
+
tool_doctor_mcp --mcp-url http://localhost:9000/mcp --verbose
|
|
799
|
+
|
|
800
|
+
# Analyze STDIO MCP server
|
|
801
|
+
tool_doctor_mcp --stdio-command fastmcp --stdio-args run my_server.py --debug
|
|
802
|
+
```
|
|
803
|
+
|
|
804
|
+
**Available options:**
|
|
805
|
+
- `--mcp-url URL` - URL of HTTP MCP server (default: `http://127.0.0.1:8000/mcp`)
|
|
806
|
+
- `--stdio-command CMD` - Command to run STDIO MCP server
|
|
807
|
+
- `--stdio-args ARGS` - Arguments for STDIO MCP server command
|
|
808
|
+
- `--verbose` - Enable verbose output
|
|
809
|
+
- `--debug` - Enable debug output
|
|
810
|
+
|
|
811
|
+
### Tool Doctor
|
|
812
|
+
|
|
813
|
+
Analyze tool usage patterns from agent logs and get optimization recommendations.
|
|
814
|
+
|
|
815
|
+
```python
|
|
816
|
+
from aixtools.tools.doctor.tool_doctor import ToolDoctor
|
|
817
|
+
from aixtools.tools.doctor.tool_recommendation import ToolRecommendation
|
|
818
|
+
|
|
819
|
+
# Analyze tool usage patterns
|
|
820
|
+
doctor = ToolDoctor()
|
|
821
|
+
analysis = doctor.analyze_tools(agent_logs)
|
|
822
|
+
|
|
823
|
+
# Get tool recommendations
|
|
824
|
+
recommendation = ToolRecommendation()
|
|
825
|
+
suggestions = recommendation.recommend_tools(agent_context)
|
|
826
|
+
```
|
|
827
|
+
|
|
828
|
+
### Evaluations
|
|
829
|
+
|
|
830
|
+
Run comprehensive Agent/LLM evaluations using the built-in evaluation discovery based on `Pydantic-AI` framework with AIXtools enhancements.
|
|
831
|
+
|
|
832
|
+
```bash
|
|
833
|
+
# Run all evaluations
|
|
834
|
+
python -m aixtools.evals
|
|
835
|
+
|
|
836
|
+
# Run evaluations with filtering
|
|
837
|
+
python -m aixtools.evals --filter "specific_test"
|
|
838
|
+
|
|
839
|
+
# Run with verbose output and detailed reporting
|
|
840
|
+
python -m aixtools.evals --verbose --include-input --include-output --include-reasons
|
|
841
|
+
|
|
842
|
+
# Specify custom evaluations directory
|
|
843
|
+
python -m aixtools.evals --evals-dir /path/to/evals
|
|
844
|
+
|
|
845
|
+
# Set minimum assertions threshold
|
|
846
|
+
python -m aixtools.evals --min-assertions 0.8
|
|
847
|
+
```
|
|
848
|
+
|
|
849
|
+
**Command Line Options:**
|
|
850
|
+
- `--evals-dir` - Directory containing `eval_*.py` files (default: `evals`)
|
|
851
|
+
- `--filter` - Filter to run only matching evaluations
|
|
852
|
+
- `--include-input` - Include input in report output (default: `True`)
|
|
853
|
+
- `--include-output` - Include output in report output (default: `True`)
|
|
854
|
+
- `--include-evaluator-failures` - Include evaluator failures in report
|
|
855
|
+
- `--include-reasons` - Include reasons in report output
|
|
856
|
+
- `--min-assertions` - Minimum assertions average required for success (default: `1.0`)
|
|
857
|
+
- `--verbose` - Print detailed information about discovery and processing
|
|
858
|
+
|
|
859
|
+
The evaluation system discovers and runs all `Dataset` objects from `eval_*.py` files in the specified directory, similar to test runners but specifically designed for LLM evaluations using `pydantic_evals`.
|
|
860
|
+
|
|
861
|
+
**Discovery Mechanism**
|
|
862
|
+
|
|
863
|
+
The evaluation framework uses an automatic discovery system:
|
|
864
|
+
|
|
865
|
+
1. **File Discovery**: Scans the specified directory for files matching the pattern `eval_*.py`
|
|
866
|
+
2. **Dataset Discovery**: Within each file, looks for variables named `dataset_*` that are instances of `pydantic_evals.Dataset`
|
|
867
|
+
3. **Target Function Discovery**: Within the same file looks for function or async function named `target_*`. There must be 1 target function per file.
|
|
868
|
+
4. **Function Discovery**: Looks for functions with specific prefixes:
|
|
869
|
+
- Functions prefixed with `scorer_*`, `evaluator_*` for custom scorer and evaluator functions that will be used for each dataset in that file
|
|
870
|
+
5. **Filtering**: Supports filtering by module name, file name, dataset name, or fully qualified name
|
|
871
|
+
|
|
872
|
+
**Example Evaluation File Structure:**
|
|
873
|
+
|
|
874
|
+
```python
|
|
875
|
+
# eval_math_operations.py
|
|
876
|
+
from pydantic_evals import Dataset, Case
|
|
877
|
+
|
|
878
|
+
# This dataset will be discovered automatically
|
|
879
|
+
dataset_addition = Dataset(
|
|
880
|
+
name="Addition Tests",
|
|
881
|
+
cases=[
|
|
882
|
+
Case(input="What is 2 + 2?", expected="4"),
|
|
883
|
+
Case(input="What is 10 + 5?", expected="15"),
|
|
884
|
+
],
|
|
885
|
+
evaluators=[...]
|
|
886
|
+
)
|
|
887
|
+
|
|
888
|
+
# This function will be used as the evaluation target
|
|
889
|
+
async def target_math_agent(input_text: str) -> str:
|
|
890
|
+
# Your agent run logic here
|
|
891
|
+
agent = get_agent(system_prompt="You are a math assistant.")
|
|
892
|
+
result, _ = await run_agent(agent, input_text)
|
|
893
|
+
return result
|
|
894
|
+
|
|
895
|
+
# This function will be used as evaluator for all datasets (optional)
|
|
896
|
+
def evaluator_check_output(ctx: EvaluatorContext) -> bool:
|
|
897
|
+
# Your result evaluation logic here
|
|
898
|
+
return ctx.output == ctx.expected_output
|
|
899
|
+
```
|
|
900
|
+
|
|
901
|
+
The discovery system will:
|
|
902
|
+
- Find `eval_math_operations.py` in the `evals` directory
|
|
903
|
+
- Discover `dataset_addition` as an evaluation dataset
|
|
904
|
+
- Use `evaluate_math_agent` as the target function for evaluation
|
|
905
|
+
- Run each case through the target function and evaluate results
|
|
906
|
+
|
|
907
|
+
#### Name-Based Discovery
|
|
908
|
+
|
|
909
|
+
The evaluation system uses name-based discovery for all components:
|
|
910
|
+
|
|
911
|
+
**Target Functions** (exactly one required per eval file):
|
|
912
|
+
- Purpose: The main function being evaluated - processes inputs and returns outputs
|
|
913
|
+
- Naming: Functions named `target_*` (e.g., `target_my_function`)
|
|
914
|
+
- Signature: `def target_name(inputs: InputType) -> OutputType` or `async def target_name(inputs: InputType) -> OutputType`
|
|
915
|
+
- Example: `async def target_math_agent(input_text: str) -> str`
|
|
916
|
+
|
|
917
|
+
**Scoring Functions** (optional):
|
|
918
|
+
- Purpose: Determine if evaluation results meet success criteria
|
|
919
|
+
- Naming: Functions named `scorer_*` (e.g., `scorer_custom`)
|
|
920
|
+
- Signature: `def scorer_name(report: EvaluationReport, dataset: AixDataset, min_score: float = 1.0, verbose: bool = False) -> bool`
|
|
921
|
+
- Example: `def scorer_accuracy_threshold(report, dataset, min_score=0.8, verbose=False) -> bool`
|
|
922
|
+
|
|
923
|
+
**Evaluator Functions** (optional):
|
|
924
|
+
- Purpose: Custom evaluation logic for comparing outputs with expected results
|
|
925
|
+
- Naming: Functions named `evaluator_*` (e.g., `evaluator_check_output`)
|
|
926
|
+
- Signature: `def evaluator_name(ctx: EvaluatorContext) -> EvaluatorOutput` or `async def evaluator_name(ctx: EvaluatorContext) -> EvaluatorOutput`
|
|
927
|
+
- Example: `def evaluator_exact_match(ctx) -> EvaluatorOutput`
|
|
928
|
+
|
|
929
|
+
This name-based approach works seamlessly with both synchronous and asynchronous functions.
|
|
930
|
+
|
|
931
|
+
#### Scoring System
|
|
932
|
+
|
|
933
|
+
The framework includes a custom scoring system with `average_assertions` as the default scorer. This scorer checks if the average assertion score meets a minimum threshold and provides detailed pass/fail reporting.
|
|
934
|
+
|
|
935
|
+
## Chainlit & HTTP Server
|
|
936
|
+
|
|
937
|
+
### Chainlit Integration
|
|
938
|
+
|
|
939
|
+
Ready-to-use `Chainlit` application for interactive agent interfaces.
|
|
940
|
+
|
|
941
|
+
```python
|
|
942
|
+
# Run the Chainlit app
|
|
943
|
+
# Configuration in aixtools/chainlit.md
|
|
944
|
+
# Main app in aixtools/app.py
|
|
945
|
+
```
|
|
946
|
+
|
|
947
|
+
### HTTP Server Framework
|
|
948
|
+
|
|
949
|
+
AIXtools provides an HTTP server framework for deploying agents and tools as web services.
|
|
950
|
+
|
|
951
|
+
```python
|
|
952
|
+
from aixtools.server.app_mounter import mount_app
|
|
953
|
+
from aixtools.server import create_server
|
|
954
|
+
|
|
955
|
+
# Create and configure server
|
|
956
|
+
server = create_server()
|
|
957
|
+
|
|
958
|
+
# Mount applications and endpoints
|
|
959
|
+
mount_app(server, "/agent", agent_app)
|
|
960
|
+
mount_app(server, "/tools", tools_app)
|
|
961
|
+
|
|
962
|
+
# Run server
|
|
963
|
+
server.run(host="0.0.0.0", port=8000)
|
|
964
|
+
```
|
|
965
|
+
|
|
966
|
+
**Features:**
|
|
967
|
+
- Application mounting system for modular service composition
|
|
968
|
+
- Integration with `Chainlit` for agent interfaces
|
|
969
|
+
- RESTful API support
|
|
970
|
+
- Middleware support for authentication and logging
|
|
971
|
+
|
|
972
|
+
## Programming Utilities
|
|
973
|
+
|
|
974
|
+
AIXtools provides essential programming utilities for configuration management, data persistence, file operations, and context handling.
|
|
975
|
+
|
|
976
|
+
### Persisted Dictionary
|
|
977
|
+
|
|
978
|
+
Persistent key-value storage with automatic serialization and file-based persistence.
|
|
979
|
+
|
|
980
|
+
```python
|
|
981
|
+
from aixtools.utils.persisted_dict import PersistedDict
|
|
982
|
+
|
|
983
|
+
# Create a persistent dictionary
|
|
984
|
+
cache = PersistedDict("cache.json")
|
|
985
|
+
|
|
986
|
+
# Store and retrieve data
|
|
987
|
+
cache["user_preferences"] = {"theme": "dark", "language": "en"}
|
|
988
|
+
cache["session_data"] = {"last_login": "2024-01-01"}
|
|
989
|
+
|
|
990
|
+
# Data is automatically saved to file
|
|
991
|
+
print(cache["user_preferences"]) # Persists across program restarts
|
|
992
|
+
```
|
|
993
|
+
|
|
994
|
+
### Enum with Description
|
|
995
|
+
|
|
996
|
+
Enhanced `Enum` classes with built-in descriptions for better documentation and user interfaces.
|
|
997
|
+
|
|
998
|
+
```python
|
|
999
|
+
from aixtools.utils.enum_with_description import EnumWithDescription
|
|
1000
|
+
|
|
1001
|
+
class ModelType(EnumWithDescription):
|
|
1002
|
+
GPT4 = ("gpt-4", "OpenAI GPT-4 model")
|
|
1003
|
+
CLAUDE = ("claude-3", "Anthropic Claude-3 model")
|
|
1004
|
+
LLAMA = ("llama-2", "Meta LLaMA-2 model")
|
|
1005
|
+
|
|
1006
|
+
# Access enum values and descriptions
|
|
1007
|
+
print(ModelType.GPT4.value) # "gpt-4"
|
|
1008
|
+
print(ModelType.GPT4.description) # "OpenAI GPT-4 model"
|
|
1009
|
+
|
|
1010
|
+
# Get all descriptions
|
|
1011
|
+
for model in ModelType:
|
|
1012
|
+
print(f"{model.value}: {model.description}")
|
|
1013
|
+
```
|
|
1014
|
+
|
|
1015
|
+
### Context Management
|
|
1016
|
+
|
|
1017
|
+
Centralized context management for sharing state across components.
|
|
1018
|
+
|
|
1019
|
+
```python
|
|
1020
|
+
from aixtools.context import Context
|
|
1021
|
+
|
|
1022
|
+
# Create and use context
|
|
1023
|
+
context = Context()
|
|
1024
|
+
context.set("user_id", "12345")
|
|
1025
|
+
context.set("session_data", {"preferences": {"theme": "dark"}})
|
|
1026
|
+
|
|
1027
|
+
# Retrieve context data
|
|
1028
|
+
user_id = context.get("user_id")
|
|
1029
|
+
session_data = context.get("session_data")
|
|
1030
|
+
|
|
1031
|
+
# Context can be passed between components
|
|
1032
|
+
def process_request(ctx: Context):
|
|
1033
|
+
user_id = ctx.get("user_id")
|
|
1034
|
+
# Process with user context
|
|
1035
|
+
```
|
|
1036
|
+
|
|
1037
|
+
### Configuration Management
|
|
1038
|
+
|
|
1039
|
+
Robust configuration handling with environment variable support and validation.
|
|
1040
|
+
|
|
1041
|
+
```python
|
|
1042
|
+
from aixtools.utils.config import Config
|
|
1043
|
+
from aixtools.utils.config_util import load_config
|
|
1044
|
+
|
|
1045
|
+
# Load configuration from environment and files
|
|
1046
|
+
config = load_config()
|
|
1047
|
+
|
|
1048
|
+
# Access configuration values
|
|
1049
|
+
model_name = config.get("MODEL_NAME", "gpt-4")
|
|
1050
|
+
api_key = config.get("API_KEY")
|
|
1051
|
+
timeout = config.get("TIMEOUT", 30, int)
|
|
1052
|
+
|
|
1053
|
+
# Configuration with validation
|
|
1054
|
+
class AppConfig(Config):
|
|
1055
|
+
model_name: str = "gpt-4"
|
|
1056
|
+
max_tokens: int = 1000
|
|
1057
|
+
temperature: float = 0.7
|
|
1058
|
+
|
|
1059
|
+
app_config = AppConfig()
|
|
1060
|
+
```
|
|
1061
|
+
|
|
1062
|
+
### File Utilities
|
|
1063
|
+
|
|
1064
|
+
Enhanced file operations with `Path` support and utility functions.
|
|
1065
|
+
|
|
1066
|
+
```python
|
|
1067
|
+
from aixtools.utils.files import read_file, write_file, ensure_directory
|
|
1068
|
+
from pathlib import Path
|
|
1069
|
+
|
|
1070
|
+
# Read and write files with automatic encoding handling
|
|
1071
|
+
content = read_file("data.txt")
|
|
1072
|
+
write_file("output.txt", "Hello, world!")
|
|
1073
|
+
|
|
1074
|
+
# Ensure directories exist
|
|
1075
|
+
data_dir = Path("data/logs")
|
|
1076
|
+
ensure_directory(data_dir)
|
|
1077
|
+
|
|
1078
|
+
# Work with file paths
|
|
1079
|
+
config_path = Path("config") / "settings.json"
|
|
1080
|
+
if config_path.exists():
|
|
1081
|
+
config_data = read_file(config_path)
|
|
1082
|
+
```
|
|
1083
|
+
|
|
1084
|
+
### Chainlit Utilities
|
|
1085
|
+
|
|
1086
|
+
Specialized utilities for `Chainlit` integration and agent display.
|
|
1087
|
+
|
|
1088
|
+
```python
|
|
1089
|
+
from aixtools.utils.chainlit.cl_agent_show import show_agent_response
|
|
1090
|
+
from aixtools.utils.chainlit.cl_utils import format_message
|
|
1091
|
+
|
|
1092
|
+
# Display agent responses in Chainlit
|
|
1093
|
+
await show_agent_response(
|
|
1094
|
+
response="Hello, how can I help you?",
|
|
1095
|
+
metadata={"model": "gpt-4", "tokens": 150}
|
|
1096
|
+
)
|
|
1097
|
+
|
|
1098
|
+
# Format messages for Chainlit display
|
|
1099
|
+
formatted_msg = format_message(
|
|
1100
|
+
content="Processing your request...",
|
|
1101
|
+
message_type="info"
|
|
1102
|
+
)
|
|
1103
|
+
```
|
|
1104
|
+
|
|
1105
|
+
### General Utilities
|
|
1106
|
+
|
|
1107
|
+
Common utility functions for everyday programming tasks.
|
|
1108
|
+
|
|
1109
|
+
```python
|
|
1110
|
+
from aixtools.utils.utils import safe_json_loads, timestamp_now, hash_string
|
|
1111
|
+
|
|
1112
|
+
# Safe JSON parsing
|
|
1113
|
+
data = safe_json_loads('{"key": "value"}', default={})
|
|
1114
|
+
|
|
1115
|
+
# Get current timestamp
|
|
1116
|
+
now = timestamp_now()
|
|
1117
|
+
|
|
1118
|
+
# Generate hash for strings
|
|
1119
|
+
file_hash = hash_string("content to hash")
|
|
1120
|
+
```
|
|
1121
|
+
|