easy-agent-sdk 0.1.2__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.
- easy_agent_sdk-0.1.2/LICENSE +21 -0
- easy_agent_sdk-0.1.2/MANIFEST.in +6 -0
- easy_agent_sdk-0.1.2/PKG-INFO +220 -0
- easy_agent_sdk-0.1.2/README.md +185 -0
- easy_agent_sdk-0.1.2/README_CN.md +185 -0
- easy_agent_sdk-0.1.2/easy_agent_sdk.egg-info/PKG-INFO +220 -0
- easy_agent_sdk-0.1.2/easy_agent_sdk.egg-info/SOURCES.txt +46 -0
- easy_agent_sdk-0.1.2/easy_agent_sdk.egg-info/dependency_links.txt +1 -0
- easy_agent_sdk-0.1.2/easy_agent_sdk.egg-info/requires.txt +8 -0
- easy_agent_sdk-0.1.2/easy_agent_sdk.egg-info/top_level.txt +1 -0
- easy_agent_sdk-0.1.2/easyagent/__init__.py +20 -0
- easy_agent_sdk-0.1.2/easyagent/agent/__init__.py +4 -0
- easy_agent_sdk-0.1.2/easyagent/agent/base.py +50 -0
- easy_agent_sdk-0.1.2/easyagent/agent/react_agent.py +137 -0
- easy_agent_sdk-0.1.2/easyagent/agent/tool_agent.py +39 -0
- easy_agent_sdk-0.1.2/easyagent/config/__init__.py +1 -0
- easy_agent_sdk-0.1.2/easyagent/config/base.py +90 -0
- easy_agent_sdk-0.1.2/easyagent/config/config_example.yaml +47 -0
- easy_agent_sdk-0.1.2/easyagent/debug/__init__.py +1 -0
- easy_agent_sdk-0.1.2/easyagent/debug/log.py +122 -0
- easy_agent_sdk-0.1.2/easyagent/memory/__init__.py +7 -0
- easy_agent_sdk-0.1.2/easyagent/memory/base.py +29 -0
- easy_agent_sdk-0.1.2/easyagent/memory/sliding_window.py +57 -0
- easy_agent_sdk-0.1.2/easyagent/memory/step_window.py +77 -0
- easy_agent_sdk-0.1.2/easyagent/memory/summary.py +217 -0
- easy_agent_sdk-0.1.2/easyagent/model/__init__.py +1 -0
- easy_agent_sdk-0.1.2/easyagent/model/base.py +25 -0
- easy_agent_sdk-0.1.2/easyagent/model/litellm_model.py +83 -0
- easy_agent_sdk-0.1.2/easyagent/model/schema.py +75 -0
- easy_agent_sdk-0.1.2/easyagent/pipeline/__init__.py +1 -0
- easy_agent_sdk-0.1.2/easyagent/pipeline/base.py +102 -0
- easy_agent_sdk-0.1.2/easyagent/prompt/__init__.py +11 -0
- easy_agent_sdk-0.1.2/easyagent/prompt/memory.py +75 -0
- easy_agent_sdk-0.1.2/easyagent/prompt/react.py +40 -0
- easy_agent_sdk-0.1.2/easyagent/py.typed +0 -0
- easy_agent_sdk-0.1.2/easyagent/test/__init__.py +1 -0
- easy_agent_sdk-0.1.2/easyagent/test/test_agent.py +62 -0
- easy_agent_sdk-0.1.2/easyagent/test/test_log_save.py +118 -0
- easy_agent_sdk-0.1.2/easyagent/test/test_model.py +20 -0
- easy_agent_sdk-0.1.2/easyagent/test/test_serper.py +25 -0
- easy_agent_sdk-0.1.2/easyagent/tool/__init__.py +6 -0
- easy_agent_sdk-0.1.2/easyagent/tool/base.py +17 -0
- easy_agent_sdk-0.1.2/easyagent/tool/manager.py +67 -0
- easy_agent_sdk-0.1.2/easyagent/tool/web/__init__.py +3 -0
- easy_agent_sdk-0.1.2/easyagent/tool/web/serper.py +92 -0
- easy_agent_sdk-0.1.2/pyproject.toml +63 -0
- easy_agent_sdk-0.1.2/requirements.txt +2 -0
- easy_agent_sdk-0.1.2/setup.cfg +4 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Yiran Peng
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: easy-agent-sdk
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: A lightweight AI Agent framework built on LiteLLM with ReAct reasoning, tool calling, and smart memory.
|
|
5
|
+
Author-email: Yiran Peng <amagipeng@gmail.com>
|
|
6
|
+
Maintainer-email: Yiran Peng <amagipeng@gmail.com>
|
|
7
|
+
License: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/SNHuan/EasyAgent
|
|
9
|
+
Project-URL: Documentation, https://github.com/SNHuan/EasyAgent#readme
|
|
10
|
+
Project-URL: Repository, https://github.com/SNHuan/EasyAgent
|
|
11
|
+
Project-URL: Bug Tracker, https://github.com/SNHuan/EasyAgent/issues
|
|
12
|
+
Project-URL: Changelog, https://github.com/SNHuan/EasyAgent/releases
|
|
13
|
+
Keywords: agent,llm,react,ai,litellm,openai,claude,gpt,tool-calling
|
|
14
|
+
Classifier: Development Status :: 3 - Alpha
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
+
Classifier: Typing :: Typed
|
|
24
|
+
Requires-Python: >=3.12
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: litellm>=1.80.0
|
|
28
|
+
Requires-Dist: pydantic>=2.12.5
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
31
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
32
|
+
Requires-Dist: build; extra == "dev"
|
|
33
|
+
Requires-Dist: twine; extra == "dev"
|
|
34
|
+
Dynamic: license-file
|
|
35
|
+
|
|
36
|
+
# EasyAgent
|
|
37
|
+
|
|
38
|
+
[](https://badge.fury.io/py/easy-agent-sdk)
|
|
39
|
+
[](https://opensource.org/licenses/MIT)
|
|
40
|
+
[](https://www.python.org/downloads/)
|
|
41
|
+
|
|
42
|
+
English | [简体中文](README_CN.md)
|
|
43
|
+
|
|
44
|
+
A lightweight AI Agent framework built on LiteLLM, featuring multi-model support, tool calling, and intelligent memory management.
|
|
45
|
+
|
|
46
|
+
> **~809 lines of code, production-ready Agent capabilities** — Multi-model adapters, tool calling, smart memory, ReAct reasoning, DAG pipelines, debug tracing.
|
|
47
|
+
|
|
48
|
+
## Features
|
|
49
|
+
|
|
50
|
+
- **Multi-Model Support** - Unified interface via LiteLLM for OpenAI, Anthropic, Gemini, and more
|
|
51
|
+
- **Tool Calling** - Protocol-based tool definition with `@register_tool` decorator
|
|
52
|
+
- **Memory** - Sliding window + auto-summarization strategies for context management
|
|
53
|
+
- **ReAct Loop** - Standard think → act → observe reasoning cycle
|
|
54
|
+
- **DAG Pipeline** - Directed Acyclic Graph workflow orchestration with parallel execution
|
|
55
|
+
- **Debug Friendly** - Colored logging, token usage and cost tracking
|
|
56
|
+
|
|
57
|
+
## Installation
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pip install easy-agent-sdk
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**From source:**
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
git clone https://github.com/SNHuan/EasyAgent.git
|
|
67
|
+
cd EasyAgent
|
|
68
|
+
pip install -e ".[dev]"
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Quick Start
|
|
72
|
+
|
|
73
|
+
### 1. Configuration
|
|
74
|
+
|
|
75
|
+
Create a config file `config.yaml`:
|
|
76
|
+
|
|
77
|
+
```yaml
|
|
78
|
+
debug: true
|
|
79
|
+
summary_model: gpt-4o-mini
|
|
80
|
+
|
|
81
|
+
models:
|
|
82
|
+
gpt-4o-mini:
|
|
83
|
+
api_type: openai
|
|
84
|
+
base_url: https://api.openai.com/v1
|
|
85
|
+
api_key: sk-xxx
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Set environment variable:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
export EA_DEFAULT_CONFIG=/path/to/config.yaml
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### 2. Define Tools
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from easyagent.tool import register_tool
|
|
98
|
+
|
|
99
|
+
@register_tool
|
|
100
|
+
class GetWeather:
|
|
101
|
+
name = "get_weather"
|
|
102
|
+
type = "function"
|
|
103
|
+
description = "Get the weather for a city."
|
|
104
|
+
parameters = {
|
|
105
|
+
"type": "object",
|
|
106
|
+
"properties": {"city": {"type": "string", "description": "City name"}},
|
|
107
|
+
"required": ["city"],
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
def init(self) -> None:
|
|
111
|
+
pass
|
|
112
|
+
|
|
113
|
+
def execute(self, city: str) -> str:
|
|
114
|
+
return f"The weather in {city} is sunny, 25°C."
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### 3. Create Agent
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
import asyncio
|
|
121
|
+
from easyagent.agent import ReactAgent
|
|
122
|
+
from easyagent.config.base import ModelConfig
|
|
123
|
+
from easyagent.model.litellm_model import LiteLLMModel
|
|
124
|
+
|
|
125
|
+
config = ModelConfig.load()
|
|
126
|
+
model = LiteLLMModel(**config.get_model("gpt-4o-mini"))
|
|
127
|
+
|
|
128
|
+
agent = ReactAgent(
|
|
129
|
+
model=model,
|
|
130
|
+
tools=["get_weather"],
|
|
131
|
+
system_prompt="You are a helpful assistant.",
|
|
132
|
+
max_iterations=10,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
result = asyncio.run(agent.run("What's the weather in Beijing?"))
|
|
136
|
+
print(result)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Core Components
|
|
140
|
+
|
|
141
|
+
### Agent
|
|
142
|
+
|
|
143
|
+
| Class | Description |
|
|
144
|
+
|-------|-------------|
|
|
145
|
+
| `ReactAgent` | ReAct loop: think → act → observe |
|
|
146
|
+
| `ToolAgent` | Tool registration and execution |
|
|
147
|
+
|
|
148
|
+
### Memory
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
from easyagent.memory import SlidingWindowMemory, SummaryMemory
|
|
152
|
+
|
|
153
|
+
# Sliding window
|
|
154
|
+
memory = SlidingWindowMemory(max_messages=20, max_tokens=4000)
|
|
155
|
+
|
|
156
|
+
# Auto-summary for long tasks
|
|
157
|
+
memory = SummaryMemory(task_id="task_001", reserve_ratio=0.3)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Pipeline
|
|
161
|
+
|
|
162
|
+
DAG-based workflow with parallel execution:
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
import asyncio
|
|
166
|
+
from easyagent.pipeline.base import BaseNode, BasePipeline, NodeContext
|
|
167
|
+
|
|
168
|
+
class FetchData(BaseNode):
|
|
169
|
+
async def execute(self, ctx: NodeContext) -> None:
|
|
170
|
+
ctx.data = "raw_data"
|
|
171
|
+
|
|
172
|
+
class ProcessA(BaseNode):
|
|
173
|
+
async def execute(self, ctx: NodeContext) -> None:
|
|
174
|
+
ctx.result_a = f"{ctx.data}_A"
|
|
175
|
+
|
|
176
|
+
class ProcessB(BaseNode):
|
|
177
|
+
async def execute(self, ctx: NodeContext) -> None:
|
|
178
|
+
ctx.result_b = f"{ctx.data}_B"
|
|
179
|
+
|
|
180
|
+
fetch = FetchData()
|
|
181
|
+
process_a = ProcessA()
|
|
182
|
+
process_b = ProcessB()
|
|
183
|
+
|
|
184
|
+
fetch >> [process_a, process_b] # Parallel branches
|
|
185
|
+
|
|
186
|
+
pipeline = BasePipeline(root=fetch)
|
|
187
|
+
ctx = asyncio.run(pipeline.run())
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Debug
|
|
191
|
+
|
|
192
|
+
```python
|
|
193
|
+
from easyagent.debug.log import LogCollector, Logger
|
|
194
|
+
|
|
195
|
+
log = Logger("MyApp")
|
|
196
|
+
|
|
197
|
+
with LogCollector() as collector:
|
|
198
|
+
log.info("Step 1")
|
|
199
|
+
log.info("Step 2")
|
|
200
|
+
|
|
201
|
+
print(collector.to_text())
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Project Structure
|
|
205
|
+
|
|
206
|
+
```
|
|
207
|
+
easyagent/
|
|
208
|
+
├── agent/ # ReactAgent, ToolAgent
|
|
209
|
+
├── model/ # LiteLLMModel, Message, ToolCall
|
|
210
|
+
├── memory/ # SlidingWindowMemory, SummaryMemory
|
|
211
|
+
├── tool/ # ToolManager, @register_tool
|
|
212
|
+
├── pipeline/ # BaseNode, BasePipeline
|
|
213
|
+
├── config/ # ModelConfig
|
|
214
|
+
├── prompt/ # Prompt templates
|
|
215
|
+
└── debug/ # Logger, LogCollector
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## License
|
|
219
|
+
|
|
220
|
+
[MIT License](LICENSE) © 2025 Yiran Peng
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# EasyAgent
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/py/easy-agent-sdk)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://www.python.org/downloads/)
|
|
6
|
+
|
|
7
|
+
English | [简体中文](README_CN.md)
|
|
8
|
+
|
|
9
|
+
A lightweight AI Agent framework built on LiteLLM, featuring multi-model support, tool calling, and intelligent memory management.
|
|
10
|
+
|
|
11
|
+
> **~809 lines of code, production-ready Agent capabilities** — Multi-model adapters, tool calling, smart memory, ReAct reasoning, DAG pipelines, debug tracing.
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- **Multi-Model Support** - Unified interface via LiteLLM for OpenAI, Anthropic, Gemini, and more
|
|
16
|
+
- **Tool Calling** - Protocol-based tool definition with `@register_tool` decorator
|
|
17
|
+
- **Memory** - Sliding window + auto-summarization strategies for context management
|
|
18
|
+
- **ReAct Loop** - Standard think → act → observe reasoning cycle
|
|
19
|
+
- **DAG Pipeline** - Directed Acyclic Graph workflow orchestration with parallel execution
|
|
20
|
+
- **Debug Friendly** - Colored logging, token usage and cost tracking
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pip install easy-agent-sdk
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**From source:**
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
git clone https://github.com/SNHuan/EasyAgent.git
|
|
32
|
+
cd EasyAgent
|
|
33
|
+
pip install -e ".[dev]"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Quick Start
|
|
37
|
+
|
|
38
|
+
### 1. Configuration
|
|
39
|
+
|
|
40
|
+
Create a config file `config.yaml`:
|
|
41
|
+
|
|
42
|
+
```yaml
|
|
43
|
+
debug: true
|
|
44
|
+
summary_model: gpt-4o-mini
|
|
45
|
+
|
|
46
|
+
models:
|
|
47
|
+
gpt-4o-mini:
|
|
48
|
+
api_type: openai
|
|
49
|
+
base_url: https://api.openai.com/v1
|
|
50
|
+
api_key: sk-xxx
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Set environment variable:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
export EA_DEFAULT_CONFIG=/path/to/config.yaml
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 2. Define Tools
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
from easyagent.tool import register_tool
|
|
63
|
+
|
|
64
|
+
@register_tool
|
|
65
|
+
class GetWeather:
|
|
66
|
+
name = "get_weather"
|
|
67
|
+
type = "function"
|
|
68
|
+
description = "Get the weather for a city."
|
|
69
|
+
parameters = {
|
|
70
|
+
"type": "object",
|
|
71
|
+
"properties": {"city": {"type": "string", "description": "City name"}},
|
|
72
|
+
"required": ["city"],
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
def init(self) -> None:
|
|
76
|
+
pass
|
|
77
|
+
|
|
78
|
+
def execute(self, city: str) -> str:
|
|
79
|
+
return f"The weather in {city} is sunny, 25°C."
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 3. Create Agent
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
import asyncio
|
|
86
|
+
from easyagent.agent import ReactAgent
|
|
87
|
+
from easyagent.config.base import ModelConfig
|
|
88
|
+
from easyagent.model.litellm_model import LiteLLMModel
|
|
89
|
+
|
|
90
|
+
config = ModelConfig.load()
|
|
91
|
+
model = LiteLLMModel(**config.get_model("gpt-4o-mini"))
|
|
92
|
+
|
|
93
|
+
agent = ReactAgent(
|
|
94
|
+
model=model,
|
|
95
|
+
tools=["get_weather"],
|
|
96
|
+
system_prompt="You are a helpful assistant.",
|
|
97
|
+
max_iterations=10,
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
result = asyncio.run(agent.run("What's the weather in Beijing?"))
|
|
101
|
+
print(result)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Core Components
|
|
105
|
+
|
|
106
|
+
### Agent
|
|
107
|
+
|
|
108
|
+
| Class | Description |
|
|
109
|
+
|-------|-------------|
|
|
110
|
+
| `ReactAgent` | ReAct loop: think → act → observe |
|
|
111
|
+
| `ToolAgent` | Tool registration and execution |
|
|
112
|
+
|
|
113
|
+
### Memory
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
from easyagent.memory import SlidingWindowMemory, SummaryMemory
|
|
117
|
+
|
|
118
|
+
# Sliding window
|
|
119
|
+
memory = SlidingWindowMemory(max_messages=20, max_tokens=4000)
|
|
120
|
+
|
|
121
|
+
# Auto-summary for long tasks
|
|
122
|
+
memory = SummaryMemory(task_id="task_001", reserve_ratio=0.3)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Pipeline
|
|
126
|
+
|
|
127
|
+
DAG-based workflow with parallel execution:
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
import asyncio
|
|
131
|
+
from easyagent.pipeline.base import BaseNode, BasePipeline, NodeContext
|
|
132
|
+
|
|
133
|
+
class FetchData(BaseNode):
|
|
134
|
+
async def execute(self, ctx: NodeContext) -> None:
|
|
135
|
+
ctx.data = "raw_data"
|
|
136
|
+
|
|
137
|
+
class ProcessA(BaseNode):
|
|
138
|
+
async def execute(self, ctx: NodeContext) -> None:
|
|
139
|
+
ctx.result_a = f"{ctx.data}_A"
|
|
140
|
+
|
|
141
|
+
class ProcessB(BaseNode):
|
|
142
|
+
async def execute(self, ctx: NodeContext) -> None:
|
|
143
|
+
ctx.result_b = f"{ctx.data}_B"
|
|
144
|
+
|
|
145
|
+
fetch = FetchData()
|
|
146
|
+
process_a = ProcessA()
|
|
147
|
+
process_b = ProcessB()
|
|
148
|
+
|
|
149
|
+
fetch >> [process_a, process_b] # Parallel branches
|
|
150
|
+
|
|
151
|
+
pipeline = BasePipeline(root=fetch)
|
|
152
|
+
ctx = asyncio.run(pipeline.run())
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Debug
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
from easyagent.debug.log import LogCollector, Logger
|
|
159
|
+
|
|
160
|
+
log = Logger("MyApp")
|
|
161
|
+
|
|
162
|
+
with LogCollector() as collector:
|
|
163
|
+
log.info("Step 1")
|
|
164
|
+
log.info("Step 2")
|
|
165
|
+
|
|
166
|
+
print(collector.to_text())
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Project Structure
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
easyagent/
|
|
173
|
+
├── agent/ # ReactAgent, ToolAgent
|
|
174
|
+
├── model/ # LiteLLMModel, Message, ToolCall
|
|
175
|
+
├── memory/ # SlidingWindowMemory, SummaryMemory
|
|
176
|
+
├── tool/ # ToolManager, @register_tool
|
|
177
|
+
├── pipeline/ # BaseNode, BasePipeline
|
|
178
|
+
├── config/ # ModelConfig
|
|
179
|
+
├── prompt/ # Prompt templates
|
|
180
|
+
└── debug/ # Logger, LogCollector
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## License
|
|
184
|
+
|
|
185
|
+
[MIT License](LICENSE) © 2025 Yiran Peng
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# EasyAgent
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/py/easy-agent-sdk)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://www.python.org/downloads/)
|
|
6
|
+
|
|
7
|
+
[English](README.md) | 中文
|
|
8
|
+
|
|
9
|
+
轻量级 AI Agent 框架,基于 LiteLLM 构建,支持多模型、工具调用和智能记忆管理。
|
|
10
|
+
|
|
11
|
+
> **~809 行代码,完整实现生产级 Agent 能力** — 多模型适配、工具调用、智能记忆、ReAct 推理、DAG 流水线、调试追踪。
|
|
12
|
+
|
|
13
|
+
## 特性
|
|
14
|
+
|
|
15
|
+
- **多模型支持** - 通过 LiteLLM 统一接口,支持 OpenAI、Anthropic、Gemini 等
|
|
16
|
+
- **工具调用** - 基于 Protocol 的工具定义,`@register_tool` 装饰器自动注册
|
|
17
|
+
- **记忆模块** - 滑动窗口 + 自动摘要两种策略,自动管理上下文长度
|
|
18
|
+
- **ReAct 循环** - think → act → observe 标准推理循环
|
|
19
|
+
- **DAG Pipeline** - 基于有向无环图的流水线编排,支持节点并行执行
|
|
20
|
+
- **调试友好** - 彩色日志输出,token 消耗和成本追踪
|
|
21
|
+
|
|
22
|
+
## 安装
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pip install easy-agent-sdk
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**从源码安装:**
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
git clone https://github.com/SNHuan/EasyAgent.git
|
|
32
|
+
cd EasyAgent
|
|
33
|
+
pip install -e ".[dev]"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## 快速开始
|
|
37
|
+
|
|
38
|
+
### 1. 配置
|
|
39
|
+
|
|
40
|
+
创建配置文件 `config.yaml`:
|
|
41
|
+
|
|
42
|
+
```yaml
|
|
43
|
+
debug: true
|
|
44
|
+
summary_model: gpt-4o-mini
|
|
45
|
+
|
|
46
|
+
models:
|
|
47
|
+
gpt-4o-mini:
|
|
48
|
+
api_type: openai
|
|
49
|
+
base_url: https://api.openai.com/v1
|
|
50
|
+
api_key: sk-xxx
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
设置环境变量:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
export EA_DEFAULT_CONFIG=/path/to/config.yaml
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 2. 定义工具
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
from easyagent.tool import register_tool
|
|
63
|
+
|
|
64
|
+
@register_tool
|
|
65
|
+
class GetWeather:
|
|
66
|
+
name = "get_weather"
|
|
67
|
+
type = "function"
|
|
68
|
+
description = "获取城市天气"
|
|
69
|
+
parameters = {
|
|
70
|
+
"type": "object",
|
|
71
|
+
"properties": {"city": {"type": "string", "description": "城市名"}},
|
|
72
|
+
"required": ["city"],
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
def init(self) -> None:
|
|
76
|
+
pass
|
|
77
|
+
|
|
78
|
+
def execute(self, city: str) -> str:
|
|
79
|
+
return f"{city}天气晴朗,25°C。"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 3. 创建 Agent
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
import asyncio
|
|
86
|
+
from easyagent.agent import ReactAgent
|
|
87
|
+
from easyagent.config.base import ModelConfig
|
|
88
|
+
from easyagent.model.litellm_model import LiteLLMModel
|
|
89
|
+
|
|
90
|
+
config = ModelConfig.load()
|
|
91
|
+
model = LiteLLMModel(**config.get_model("gpt-4o-mini"))
|
|
92
|
+
|
|
93
|
+
agent = ReactAgent(
|
|
94
|
+
model=model,
|
|
95
|
+
tools=["get_weather"],
|
|
96
|
+
system_prompt="你是一个有帮助的助手。",
|
|
97
|
+
max_iterations=10,
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
result = asyncio.run(agent.run("北京天气怎么样?"))
|
|
101
|
+
print(result)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## 核心组件
|
|
105
|
+
|
|
106
|
+
### Agent
|
|
107
|
+
|
|
108
|
+
| 类 | 说明 |
|
|
109
|
+
|---|------|
|
|
110
|
+
| `ReactAgent` | ReAct 循环:think → act → observe |
|
|
111
|
+
| `ToolAgent` | 工具注册和执行 |
|
|
112
|
+
|
|
113
|
+
### Memory
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
from easyagent.memory import SlidingWindowMemory, SummaryMemory
|
|
117
|
+
|
|
118
|
+
# 滑动窗口
|
|
119
|
+
memory = SlidingWindowMemory(max_messages=20, max_tokens=4000)
|
|
120
|
+
|
|
121
|
+
# 自动摘要(长任务)
|
|
122
|
+
memory = SummaryMemory(task_id="task_001", reserve_ratio=0.3)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Pipeline
|
|
126
|
+
|
|
127
|
+
基于 DAG 的流水线,支持并行执行:
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
import asyncio
|
|
131
|
+
from easyagent.pipeline.base import BaseNode, BasePipeline, NodeContext
|
|
132
|
+
|
|
133
|
+
class FetchData(BaseNode):
|
|
134
|
+
async def execute(self, ctx: NodeContext) -> None:
|
|
135
|
+
ctx.data = "raw_data"
|
|
136
|
+
|
|
137
|
+
class ProcessA(BaseNode):
|
|
138
|
+
async def execute(self, ctx: NodeContext) -> None:
|
|
139
|
+
ctx.result_a = f"{ctx.data}_A"
|
|
140
|
+
|
|
141
|
+
class ProcessB(BaseNode):
|
|
142
|
+
async def execute(self, ctx: NodeContext) -> None:
|
|
143
|
+
ctx.result_b = f"{ctx.data}_B"
|
|
144
|
+
|
|
145
|
+
fetch = FetchData()
|
|
146
|
+
process_a = ProcessA()
|
|
147
|
+
process_b = ProcessB()
|
|
148
|
+
|
|
149
|
+
fetch >> [process_a, process_b] # 并行分支
|
|
150
|
+
|
|
151
|
+
pipeline = BasePipeline(root=fetch)
|
|
152
|
+
ctx = asyncio.run(pipeline.run())
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Debug
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
from easyagent.debug.log import LogCollector, Logger
|
|
159
|
+
|
|
160
|
+
log = Logger("MyApp")
|
|
161
|
+
|
|
162
|
+
with LogCollector() as collector:
|
|
163
|
+
log.info("Step 1")
|
|
164
|
+
log.info("Step 2")
|
|
165
|
+
|
|
166
|
+
print(collector.to_text())
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## 项目结构
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
easyagent/
|
|
173
|
+
├── agent/ # ReactAgent, ToolAgent
|
|
174
|
+
├── model/ # LiteLLMModel, Message, ToolCall
|
|
175
|
+
├── memory/ # SlidingWindowMemory, SummaryMemory
|
|
176
|
+
├── tool/ # ToolManager, @register_tool
|
|
177
|
+
├── pipeline/ # BaseNode, BasePipeline
|
|
178
|
+
├── config/ # ModelConfig
|
|
179
|
+
├── prompt/ # Prompt 模板
|
|
180
|
+
└── debug/ # Logger, LogCollector
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## 许可证
|
|
184
|
+
|
|
185
|
+
[MIT License](LICENSE) © 2025 Yiran Peng
|