agent2 0.1.0__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.
- agent2-0.1.0/.gitignore +2 -0
- agent2-0.1.0/PKG-INFO +100 -0
- agent2-0.1.0/README.md +72 -0
- agent2-0.1.0/examples/01_single_agent.py +49 -0
- agent2-0.1.0/examples/02_tool_use.py +88 -0
- agent2-0.1.0/examples/03_planning.py +42 -0
- agent2-0.1.0/examples/04_memory.py +101 -0
- agent2-0.1.0/examples/05_multi_agent.py +127 -0
- agent2-0.1.0/pyproject.toml +40 -0
- agent2-0.1.0/src/agent2/__init__.py +6 -0
- agent2-0.1.0/src/agent2/agent/__init__.py +21 -0
- agent2-0.1.0/src/agent2/agent/base.py +131 -0
- agent2-0.1.0/src/agent2/agent/planner.py +251 -0
- agent2-0.1.0/src/agent2/agent/react.py +104 -0
- agent2-0.1.0/src/agent2/agent/reflection.py +117 -0
- agent2-0.1.0/src/agent2/app/__init__.py +1 -0
- agent2-0.1.0/src/agent2/app/chat.py +208 -0
- agent2-0.1.0/src/agent2/app/config.py +164 -0
- agent2-0.1.0/src/agent2/crew/__init__.py +13 -0
- agent2-0.1.0/src/agent2/crew/base.py +65 -0
- agent2-0.1.0/src/agent2/crew/debate.py +122 -0
- agent2-0.1.0/src/agent2/crew/sequential.py +54 -0
- agent2-0.1.0/src/agent2/crew/supervisor.py +140 -0
- agent2-0.1.0/src/agent2/llm/__init__.py +126 -0
- agent2-0.1.0/src/agent2/llm/anthropic.py +176 -0
- agent2-0.1.0/src/agent2/llm/base.py +85 -0
- agent2-0.1.0/src/agent2/llm/google.py +179 -0
- agent2-0.1.0/src/agent2/llm/message.py +177 -0
- agent2-0.1.0/src/agent2/llm/ollama.py +45 -0
- agent2-0.1.0/src/agent2/llm/openai.py +180 -0
- agent2-0.1.0/src/agent2/memory/__init__.py +11 -0
- agent2-0.1.0/src/agent2/memory/base.py +76 -0
- agent2-0.1.0/src/agent2/memory/longterm.py +230 -0
- agent2-0.1.0/src/agent2/memory/working.py +147 -0
- agent2-0.1.0/src/agent2/tools/__init__.py +18 -0
- agent2-0.1.0/src/agent2/tools/base.py +168 -0
- agent2-0.1.0/src/agent2/tools/builtin/__init__.py +7 -0
- agent2-0.1.0/src/agent2/tools/builtin/file_ops.py +70 -0
- agent2-0.1.0/src/agent2/tools/builtin/python_exec.py +78 -0
- agent2-0.1.0/src/agent2/tools/builtin/web_search.py +45 -0
- agent2-0.1.0/src/agent2/tools/registry.py +72 -0
- agent2-0.1.0/src/agent2/utils/__init__.py +1 -0
- agent2-0.1.0/src/agent2/utils/config.py +61 -0
- agent2-0.1.0/src/agent2/utils/logging.py +194 -0
- agent2-0.1.0/uv.lock +862 -0
agent2-0.1.0/.gitignore
ADDED
agent2-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: agent2
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A modular agent system framework for learning and research
|
|
5
|
+
Requires-Python: >=3.14
|
|
6
|
+
Requires-Dist: httpx>=0.27
|
|
7
|
+
Requires-Dist: openai>=2.44.0
|
|
8
|
+
Requires-Dist: pydantic-settings>=2.0
|
|
9
|
+
Requires-Dist: pydantic>=2.0
|
|
10
|
+
Requires-Dist: rich>=13.0
|
|
11
|
+
Provides-Extra: all-llm
|
|
12
|
+
Requires-Dist: anthropic>=0.30; extra == 'all-llm'
|
|
13
|
+
Requires-Dist: google-genai>=1.0; extra == 'all-llm'
|
|
14
|
+
Requires-Dist: openai>=1.30; extra == 'all-llm'
|
|
15
|
+
Provides-Extra: anthropic
|
|
16
|
+
Requires-Dist: anthropic>=0.30; extra == 'anthropic'
|
|
17
|
+
Provides-Extra: dev
|
|
18
|
+
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
19
|
+
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
|
|
20
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
21
|
+
Provides-Extra: google
|
|
22
|
+
Requires-Dist: google-genai>=1.0; extra == 'google'
|
|
23
|
+
Provides-Extra: memory
|
|
24
|
+
Requires-Dist: numpy>=1.26; extra == 'memory'
|
|
25
|
+
Provides-Extra: openai
|
|
26
|
+
Requires-Dist: openai>=1.30; extra == 'openai'
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# Agent2 — 模块化 Agent 系统框架
|
|
30
|
+
|
|
31
|
+
一个从零构建的 Python Agent 系统框架,用于深入理解 AI Agent 的核心架构和设计模式。
|
|
32
|
+
|
|
33
|
+
## 核心特性
|
|
34
|
+
|
|
35
|
+
| 特性 | 说明 |
|
|
36
|
+
|------|------|
|
|
37
|
+
| 🧠 **LLM 抽象层** | 统一接口支持 OpenAI / Anthropic / Google / Ollama |
|
|
38
|
+
| 🔧 **工具系统** | `@tool` 装饰器自动生成 JSON Schema,支持同步/异步 |
|
|
39
|
+
| 🔄 **ReAct 模式** | Thought → Action → Observation 推理循环 |
|
|
40
|
+
| 📋 **Plan-and-Execute** | 先规划后执行,支持动态重规划 |
|
|
41
|
+
| 🪞 **自我反思** | ReflectionMixin 添加输出自评和迭代改进 |
|
|
42
|
+
| 💾 **记忆系统** | 短期 (WorkingMemory) + 长期 (LongTermMemory/TF-IDF) |
|
|
43
|
+
| 👥 **多 Agent 编排** | 顺序/监督者/辩论 三种协作模式 |
|
|
44
|
+
|
|
45
|
+
## 快速开始
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# 安装
|
|
49
|
+
uv pip install -e "."
|
|
50
|
+
|
|
51
|
+
# 安装 LLM 提供商 SDK(按需)
|
|
52
|
+
uv pip install -e ".[openai]" # OpenAI
|
|
53
|
+
uv pip install -e ".[all-llm]" # 所有 LLM
|
|
54
|
+
|
|
55
|
+
# 设置 API Key
|
|
56
|
+
export AGENT2_OPENAI_API_KEY=sk-...
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 最简示例
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
import asyncio
|
|
63
|
+
from agent2.llm import create_llm
|
|
64
|
+
from agent2.agent import ReActAgent
|
|
65
|
+
from agent2.tools.builtin import python_exec
|
|
66
|
+
|
|
67
|
+
async def main():
|
|
68
|
+
llm = create_llm("openai", model="gpt-4o-mini")
|
|
69
|
+
agent = ReActAgent("assistant", llm=llm, tools=[python_exec])
|
|
70
|
+
result = await agent.run("What is 2^100?")
|
|
71
|
+
print(result)
|
|
72
|
+
|
|
73
|
+
asyncio.run(main())
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## 示例
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
uv run examples/01_single_agent.py # 单 Agent ReAct
|
|
80
|
+
uv run examples/02_tool_use.py # 自定义工具
|
|
81
|
+
uv run examples/03_planning.py # Plan-and-Execute
|
|
82
|
+
uv run examples/04_memory.py # 记忆系统(无需 API Key)
|
|
83
|
+
uv run examples/05_multi_agent.py # 多 Agent 协作
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## 架构
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
agent2/
|
|
90
|
+
├── llm/ # LLM 抽象层 — 统一多提供商接口
|
|
91
|
+
├── tools/ # 工具系统 — @tool 装饰器 + Registry
|
|
92
|
+
├── agent/ # Agent 核心 — ReAct / Planner / Reflection
|
|
93
|
+
├── memory/ # 记忆系统 — Working / LongTerm
|
|
94
|
+
├── crew/ # 多 Agent — Sequential / Supervisor / Debate
|
|
95
|
+
└── utils/ # 配置 + 日志
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## License
|
|
99
|
+
|
|
100
|
+
MIT
|
agent2-0.1.0/README.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Agent2 — 模块化 Agent 系统框架
|
|
2
|
+
|
|
3
|
+
一个从零构建的 Python Agent 系统框架,用于深入理解 AI Agent 的核心架构和设计模式。
|
|
4
|
+
|
|
5
|
+
## 核心特性
|
|
6
|
+
|
|
7
|
+
| 特性 | 说明 |
|
|
8
|
+
|------|------|
|
|
9
|
+
| 🧠 **LLM 抽象层** | 统一接口支持 OpenAI / Anthropic / Google / Ollama |
|
|
10
|
+
| 🔧 **工具系统** | `@tool` 装饰器自动生成 JSON Schema,支持同步/异步 |
|
|
11
|
+
| 🔄 **ReAct 模式** | Thought → Action → Observation 推理循环 |
|
|
12
|
+
| 📋 **Plan-and-Execute** | 先规划后执行,支持动态重规划 |
|
|
13
|
+
| 🪞 **自我反思** | ReflectionMixin 添加输出自评和迭代改进 |
|
|
14
|
+
| 💾 **记忆系统** | 短期 (WorkingMemory) + 长期 (LongTermMemory/TF-IDF) |
|
|
15
|
+
| 👥 **多 Agent 编排** | 顺序/监督者/辩论 三种协作模式 |
|
|
16
|
+
|
|
17
|
+
## 快速开始
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# 安装
|
|
21
|
+
uv pip install -e "."
|
|
22
|
+
|
|
23
|
+
# 安装 LLM 提供商 SDK(按需)
|
|
24
|
+
uv pip install -e ".[openai]" # OpenAI
|
|
25
|
+
uv pip install -e ".[all-llm]" # 所有 LLM
|
|
26
|
+
|
|
27
|
+
# 设置 API Key
|
|
28
|
+
export AGENT2_OPENAI_API_KEY=sk-...
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### 最简示例
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
import asyncio
|
|
35
|
+
from agent2.llm import create_llm
|
|
36
|
+
from agent2.agent import ReActAgent
|
|
37
|
+
from agent2.tools.builtin import python_exec
|
|
38
|
+
|
|
39
|
+
async def main():
|
|
40
|
+
llm = create_llm("openai", model="gpt-4o-mini")
|
|
41
|
+
agent = ReActAgent("assistant", llm=llm, tools=[python_exec])
|
|
42
|
+
result = await agent.run("What is 2^100?")
|
|
43
|
+
print(result)
|
|
44
|
+
|
|
45
|
+
asyncio.run(main())
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## 示例
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
uv run examples/01_single_agent.py # 单 Agent ReAct
|
|
52
|
+
uv run examples/02_tool_use.py # 自定义工具
|
|
53
|
+
uv run examples/03_planning.py # Plan-and-Execute
|
|
54
|
+
uv run examples/04_memory.py # 记忆系统(无需 API Key)
|
|
55
|
+
uv run examples/05_multi_agent.py # 多 Agent 协作
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## 架构
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
agent2/
|
|
62
|
+
├── llm/ # LLM 抽象层 — 统一多提供商接口
|
|
63
|
+
├── tools/ # 工具系统 — @tool 装饰器 + Registry
|
|
64
|
+
├── agent/ # Agent 核心 — ReAct / Planner / Reflection
|
|
65
|
+
├── memory/ # 记忆系统 — Working / LongTerm
|
|
66
|
+
├── crew/ # 多 Agent — Sequential / Supervisor / Debate
|
|
67
|
+
└── utils/ # 配置 + 日志
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## License
|
|
71
|
+
|
|
72
|
+
MIT
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Example 01: Single Agent — Basic ReAct pattern.
|
|
2
|
+
|
|
3
|
+
Demonstrates:
|
|
4
|
+
- Creating an LLM instance
|
|
5
|
+
- Creating a ReAct agent with tools
|
|
6
|
+
- Running a task and observing the Thought/Action/Observation loop
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
export AGENT2_OPENAI_API_KEY=sk-...
|
|
10
|
+
uv run examples/01_single_agent.py
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import os
|
|
14
|
+
import asyncio
|
|
15
|
+
|
|
16
|
+
from agent2.llm import create_llm
|
|
17
|
+
from agent2.agent import ReActAgent
|
|
18
|
+
from agent2.tools.builtin import python_exec
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
async def main():
|
|
22
|
+
# 1. Create an LLM — switch provider by changing the first argument
|
|
23
|
+
#llm = create_llm("openai", model="gpt-4o-mini")
|
|
24
|
+
#llm = create_llm("ollama", model="gemma4:e2b")
|
|
25
|
+
llm = create_llm("deepseek")
|
|
26
|
+
|
|
27
|
+
# 2. Create a ReAct agent with a code execution tool
|
|
28
|
+
agent = ReActAgent(
|
|
29
|
+
"CodeAssistant",
|
|
30
|
+
llm=llm,
|
|
31
|
+
system_prompt=(
|
|
32
|
+
"You are a helpful coding assistant. You can execute Python code "
|
|
33
|
+
"to verify your answers. Always show your reasoning."
|
|
34
|
+
),
|
|
35
|
+
tools=[python_exec],
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
# 3. Run a task
|
|
39
|
+
result = await agent.run(
|
|
40
|
+
"What is the sum of the first 100 prime numbers? Use Python to calculate it."
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
print("\n" + "=" * 60)
|
|
44
|
+
print("FINAL RESULT:")
|
|
45
|
+
print(result)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
if __name__ == "__main__":
|
|
49
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""Example 02: Tool Use — defining and using custom tools.
|
|
2
|
+
|
|
3
|
+
Demonstrates:
|
|
4
|
+
- @tool decorator for creating tools from functions
|
|
5
|
+
- ToolRegistry for managing multiple tools
|
|
6
|
+
- Agent using tools to solve problems
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
export AGENT2_OPENAI_API_KEY=sk-...
|
|
10
|
+
uv run examples/02_tool_use.py
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import asyncio
|
|
14
|
+
import math
|
|
15
|
+
|
|
16
|
+
from agent2.llm import create_llm
|
|
17
|
+
from agent2.agent import ReActAgent
|
|
18
|
+
from agent2.tools import tool, ToolRegistry
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# ── Define custom tools ─────────────────────────────────────────────
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@tool(description="Calculate basic math expressions. Supports +, -, *, /, **, sqrt.")
|
|
25
|
+
def calculator(expression: str) -> str:
|
|
26
|
+
"""Evaluate a math expression safely."""
|
|
27
|
+
allowed = {
|
|
28
|
+
"sqrt": math.sqrt,
|
|
29
|
+
"sin": math.sin,
|
|
30
|
+
"cos": math.cos,
|
|
31
|
+
"tan": math.tan,
|
|
32
|
+
"pi": math.pi,
|
|
33
|
+
"e": math.e,
|
|
34
|
+
"abs": abs,
|
|
35
|
+
"round": round,
|
|
36
|
+
}
|
|
37
|
+
try:
|
|
38
|
+
result = eval(expression, {"__builtins__": {}}, allowed)
|
|
39
|
+
return f"{expression} = {result}"
|
|
40
|
+
except Exception as e:
|
|
41
|
+
return f"Error: {e}"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@tool(description="Get the current date and time.")
|
|
45
|
+
def get_current_time() -> str:
|
|
46
|
+
"""Return the current date and time."""
|
|
47
|
+
from datetime import datetime
|
|
48
|
+
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@tool(description="Convert temperature between Celsius and Fahrenheit.")
|
|
52
|
+
def convert_temperature(value: float, from_unit: str) -> str:
|
|
53
|
+
"""Convert temperature. from_unit should be 'C' or 'F'."""
|
|
54
|
+
if from_unit.upper() == "C":
|
|
55
|
+
result = value * 9 / 5 + 32
|
|
56
|
+
return f"{value}°C = {result:.1f}°F"
|
|
57
|
+
elif from_unit.upper() == "F":
|
|
58
|
+
result = (value - 32) * 5 / 9
|
|
59
|
+
return f"{value}°F = {result:.1f}°C"
|
|
60
|
+
else:
|
|
61
|
+
return f"Unknown unit: {from_unit}. Use 'C' or 'F'."
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
# ── Main ────────────────────────────────────────────────────────────
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
async def main():
|
|
68
|
+
llm = create_llm("deepseek")
|
|
69
|
+
|
|
70
|
+
# Create agent with multiple custom tools
|
|
71
|
+
agent = ReActAgent(
|
|
72
|
+
"ToolDemo",
|
|
73
|
+
llm=llm,
|
|
74
|
+
tools=[calculator, get_current_time, convert_temperature],
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
# Test with a task requiring multiple tools
|
|
78
|
+
result = await agent.run(
|
|
79
|
+
"What is the current time? Also, what is 37°C in Fahrenheit? "
|
|
80
|
+
"And what is the square root of 144?"
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
print("\n" + "=" * 60)
|
|
84
|
+
print("RESULT:", result)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
if __name__ == "__main__":
|
|
88
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Example 03: Planning — Plan-and-Execute pattern.
|
|
2
|
+
|
|
3
|
+
Demonstrates:
|
|
4
|
+
- PlannerAgent that separates planning from execution
|
|
5
|
+
- Dynamic re-planning based on intermediate results
|
|
6
|
+
- Multi-step task decomposition
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
export AGENT2_OPENAI_API_KEY=sk-...
|
|
10
|
+
uv run examples/03_planning.py
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import asyncio
|
|
14
|
+
|
|
15
|
+
from agent2.llm import create_llm
|
|
16
|
+
from agent2.agent import PlannerAgent
|
|
17
|
+
from agent2.tools.builtin import web_search, python_exec
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
async def main():
|
|
21
|
+
llm = create_llm("deepseek")
|
|
22
|
+
|
|
23
|
+
agent = PlannerAgent(
|
|
24
|
+
"Researcher",
|
|
25
|
+
llm=llm,
|
|
26
|
+
tools=[web_search, python_exec],
|
|
27
|
+
enable_replan=True,
|
|
28
|
+
max_step_iterations=3,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
result = await agent.run(
|
|
32
|
+
"Compare the population of Tokyo, New York, and London. "
|
|
33
|
+
"Which city is the most densely populated? "
|
|
34
|
+
"Show the calculations."
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
print("\n" + "=" * 60)
|
|
38
|
+
print("RESULT:", result)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
if __name__ == "__main__":
|
|
42
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""Example 04: Memory — working memory and long-term memory.
|
|
2
|
+
|
|
3
|
+
Demonstrates:
|
|
4
|
+
- WorkingMemory for conversation history management
|
|
5
|
+
- LongTermMemory for semantic search (TF-IDF based)
|
|
6
|
+
- Integrating memory with agents
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
uv run examples/04_memory.py
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import asyncio
|
|
13
|
+
|
|
14
|
+
from agent2.memory import WorkingMemory, LongTermMemory
|
|
15
|
+
from agent2.llm.message import Message
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
async def demo_working_memory():
|
|
19
|
+
"""Demonstrate working memory (conversation history)."""
|
|
20
|
+
print("=" * 60)
|
|
21
|
+
print("Working Memory Demo")
|
|
22
|
+
print("=" * 60)
|
|
23
|
+
|
|
24
|
+
memory = WorkingMemory(max_messages=10)
|
|
25
|
+
|
|
26
|
+
# Simulate a conversation
|
|
27
|
+
await memory.add("What is machine learning?", role="user")
|
|
28
|
+
await memory.add(
|
|
29
|
+
"Machine learning is a subset of AI that enables systems to learn from data.",
|
|
30
|
+
role="assistant",
|
|
31
|
+
)
|
|
32
|
+
await memory.add("What are the main types?", role="user")
|
|
33
|
+
await memory.add(
|
|
34
|
+
"The main types are: supervised learning, unsupervised learning, "
|
|
35
|
+
"and reinforcement learning.",
|
|
36
|
+
role="assistant",
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
# Search memory
|
|
40
|
+
results = await memory.search("types of learning")
|
|
41
|
+
print(f"\nSearch for 'types of learning': {len(results)} results")
|
|
42
|
+
for r in results:
|
|
43
|
+
print(f" [{r.score:.2f}] {r.content[:80]}...")
|
|
44
|
+
|
|
45
|
+
# Get messages ready for LLM
|
|
46
|
+
messages = memory.get_messages_for_llm("You are a helpful AI.")
|
|
47
|
+
print(f"\nMessages for LLM: {len(messages)} messages")
|
|
48
|
+
for m in messages:
|
|
49
|
+
print(f" [{m.role.value}] {(m.content or '')[:60]}...")
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
async def demo_long_term_memory():
|
|
53
|
+
"""Demonstrate long-term memory (semantic search)."""
|
|
54
|
+
print("\n" + "=" * 60)
|
|
55
|
+
print("Long-Term Memory Demo")
|
|
56
|
+
print("=" * 60)
|
|
57
|
+
|
|
58
|
+
memory = LongTermMemory(embedding_provider="tfidf")
|
|
59
|
+
|
|
60
|
+
# Store some knowledge
|
|
61
|
+
facts = [
|
|
62
|
+
"Python is a high-level programming language created by Guido van Rossum.",
|
|
63
|
+
"Rust is a systems programming language focused on safety and performance.",
|
|
64
|
+
"JavaScript is primarily used for web development in browsers.",
|
|
65
|
+
"Machine learning uses algorithms to learn patterns from data.",
|
|
66
|
+
"Docker is a platform for containerizing applications.",
|
|
67
|
+
"Kubernetes orchestrates container deployment at scale.",
|
|
68
|
+
"PostgreSQL is a powerful open-source relational database.",
|
|
69
|
+
"Redis is an in-memory data store used for caching.",
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
print("\nStoring facts...")
|
|
73
|
+
for fact in facts:
|
|
74
|
+
await memory.add(fact)
|
|
75
|
+
print(f"Stored {memory.size} items")
|
|
76
|
+
|
|
77
|
+
# Search for related information
|
|
78
|
+
queries = [
|
|
79
|
+
"programming language for web",
|
|
80
|
+
"database systems",
|
|
81
|
+
"container orchestration",
|
|
82
|
+
]
|
|
83
|
+
|
|
84
|
+
for query in queries:
|
|
85
|
+
print(f"\n🔍 Search: '{query}'")
|
|
86
|
+
results = await memory.search(query, top_k=3)
|
|
87
|
+
for r in results:
|
|
88
|
+
print(f" [{r.score:.3f}] {r.content}")
|
|
89
|
+
|
|
90
|
+
# Get formatted context for prompt injection
|
|
91
|
+
context = await memory.get_context("What language should I use for AI?")
|
|
92
|
+
print(f"\n📋 Context for RAG:\n{context}")
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
async def main():
|
|
96
|
+
await demo_working_memory()
|
|
97
|
+
await demo_long_term_memory()
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
if __name__ == "__main__":
|
|
101
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"""Example 05: Multi-Agent — crew orchestration patterns.
|
|
2
|
+
|
|
3
|
+
Demonstrates:
|
|
4
|
+
- SequentialCrew: pipeline-style execution
|
|
5
|
+
- SupervisorCrew: supervisor delegates to workers
|
|
6
|
+
- DebateCrew: agents debate and reach consensus
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
export AGENT2_OPENAI_API_KEY=sk-...
|
|
10
|
+
uv run examples/05_multi_agent.py
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import asyncio
|
|
14
|
+
|
|
15
|
+
from agent2.llm import create_llm
|
|
16
|
+
from agent2.agent import ReActAgent
|
|
17
|
+
from agent2.crew import SequentialCrew, SupervisorCrew, DebateCrew
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
async def demo_sequential():
|
|
21
|
+
"""Sequential pipeline: Research → Write → Edit."""
|
|
22
|
+
print("\n" + "=" * 60)
|
|
23
|
+
print("Sequential Crew Demo")
|
|
24
|
+
print("=" * 60)
|
|
25
|
+
|
|
26
|
+
llm = create_llm("deepseek")
|
|
27
|
+
|
|
28
|
+
researcher = ReActAgent(
|
|
29
|
+
"researcher",
|
|
30
|
+
llm=llm,
|
|
31
|
+
system_prompt="You are a research expert. Gather key facts and data points.",
|
|
32
|
+
)
|
|
33
|
+
writer = ReActAgent(
|
|
34
|
+
"writer",
|
|
35
|
+
llm=llm,
|
|
36
|
+
system_prompt="You are a professional writer. Create clear, engaging content from research.",
|
|
37
|
+
)
|
|
38
|
+
editor = ReActAgent(
|
|
39
|
+
"editor",
|
|
40
|
+
llm=llm,
|
|
41
|
+
system_prompt="You are an editor. Polish the writing for clarity and accuracy.",
|
|
42
|
+
)
|
|
43
|
+
translator = ReActAgent(
|
|
44
|
+
"translator",
|
|
45
|
+
llm=llm,
|
|
46
|
+
system_prompt="You are an translator. Translate the writing into Chinese.",
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
crew = SequentialCrew("content_pipeline", agents=[researcher, writer, editor, translator])
|
|
50
|
+
result = await crew.run("Write a brief explanation of how neural networks work")
|
|
51
|
+
print(f"\nFinal output:\n{result}")
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
async def demo_supervisor():
|
|
55
|
+
"""Supervisor delegates to specialized workers."""
|
|
56
|
+
print("\n" + "=" * 60)
|
|
57
|
+
print("Supervisor Crew Demo")
|
|
58
|
+
print("=" * 60)
|
|
59
|
+
|
|
60
|
+
llm = create_llm("openai", model="gpt-4o-mini")
|
|
61
|
+
|
|
62
|
+
analyst = ReActAgent(
|
|
63
|
+
"analyst",
|
|
64
|
+
llm=llm,
|
|
65
|
+
system_prompt="You are a data analyst. Focus on numbers, trends, and insights.",
|
|
66
|
+
)
|
|
67
|
+
strategist = ReActAgent(
|
|
68
|
+
"strategist",
|
|
69
|
+
llm=llm,
|
|
70
|
+
system_prompt="You are a strategy consultant. Focus on actionable recommendations.",
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
crew = SupervisorCrew(
|
|
74
|
+
"consulting_team",
|
|
75
|
+
agents=[analyst, strategist],
|
|
76
|
+
supervisor_llm=llm,
|
|
77
|
+
)
|
|
78
|
+
result = await crew.run("What should a startup focus on in its first year?")
|
|
79
|
+
print(f"\nFinal output:\n{result}")
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
async def demo_debate():
|
|
83
|
+
"""Agents with different perspectives debate."""
|
|
84
|
+
print("\n" + "=" * 60)
|
|
85
|
+
print("Debate Crew Demo")
|
|
86
|
+
print("=" * 60)
|
|
87
|
+
|
|
88
|
+
llm = create_llm("openai", model="gpt-4o-mini")
|
|
89
|
+
|
|
90
|
+
optimist = ReActAgent(
|
|
91
|
+
"optimist",
|
|
92
|
+
llm=llm,
|
|
93
|
+
system_prompt=(
|
|
94
|
+
"You are an optimistic technology enthusiast. "
|
|
95
|
+
"You focus on opportunities, benefits, and positive outcomes."
|
|
96
|
+
),
|
|
97
|
+
)
|
|
98
|
+
critic = ReActAgent(
|
|
99
|
+
"critic",
|
|
100
|
+
llm=llm,
|
|
101
|
+
system_prompt=(
|
|
102
|
+
"You are a critical thinker and devil's advocate. "
|
|
103
|
+
"You focus on risks, limitations, and potential problems."
|
|
104
|
+
),
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
crew = DebateCrew(
|
|
108
|
+
"tech_debate",
|
|
109
|
+
agents=[optimist, critic],
|
|
110
|
+
synthesizer_llm=llm,
|
|
111
|
+
rounds=1,
|
|
112
|
+
)
|
|
113
|
+
result = await crew.run("Should companies fully adopt AI for customer service?")
|
|
114
|
+
print(f"\nFinal output:\n{result}")
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
async def main():
|
|
118
|
+
# Run one demo at a time to keep output readable
|
|
119
|
+
# Uncomment the one you want to try:
|
|
120
|
+
|
|
121
|
+
await demo_sequential()
|
|
122
|
+
# await demo_supervisor()
|
|
123
|
+
# await demo_debate()
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
if __name__ == "__main__":
|
|
127
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "agent2"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "A modular agent system framework for learning and research"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.14"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"pydantic>=2.0",
|
|
9
|
+
"pydantic-settings>=2.0",
|
|
10
|
+
"httpx>=0.27",
|
|
11
|
+
"rich>=13.0",
|
|
12
|
+
"openai>=2.44.0",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
[project.optional-dependencies]
|
|
16
|
+
openai = ["openai>=1.30"]
|
|
17
|
+
anthropic = ["anthropic>=0.30"]
|
|
18
|
+
google = ["google-genai>=1.0"]
|
|
19
|
+
all-llm = ["openai>=1.30", "anthropic>=0.30", "google-genai>=1.0"]
|
|
20
|
+
memory = ["numpy>=1.26"]
|
|
21
|
+
dev = ["pytest>=8.0", "pytest-asyncio>=0.24", "mypy>=1.10"]
|
|
22
|
+
|
|
23
|
+
[build-system]
|
|
24
|
+
requires = ["hatchling"]
|
|
25
|
+
build-backend = "hatchling.build"
|
|
26
|
+
|
|
27
|
+
[[tool.uv.index]]
|
|
28
|
+
url = "https://pypi.tuna.tsinghua.edu.cn/simple"
|
|
29
|
+
default = true
|
|
30
|
+
|
|
31
|
+
[tool.hatch.build.targets.wheel]
|
|
32
|
+
packages = ["src/agent2"]
|
|
33
|
+
|
|
34
|
+
[tool.pytest.ini_options]
|
|
35
|
+
asyncio_mode = "auto"
|
|
36
|
+
testpaths = ["tests"]
|
|
37
|
+
|
|
38
|
+
[tool.mypy]
|
|
39
|
+
python_version = "3.14"
|
|
40
|
+
strict = true
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Agent module — reasoning cores for LLM-powered agents.
|
|
2
|
+
|
|
3
|
+
Available agent types:
|
|
4
|
+
|
|
5
|
+
- :class:`ReActAgent` — Thought → Action → Observation loop
|
|
6
|
+
- :class:`PlannerAgent` — Plan-and-Execute pattern
|
|
7
|
+
- :class:`ReflectionMixin` — Self-critique mixin for any agent
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from agent2.agent.base import BaseAgent, MaxIterationsExceeded
|
|
11
|
+
from agent2.agent.react import ReActAgent
|
|
12
|
+
from agent2.agent.planner import PlannerAgent
|
|
13
|
+
from agent2.agent.reflection import ReflectionMixin
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"BaseAgent",
|
|
17
|
+
"MaxIterationsExceeded",
|
|
18
|
+
"ReActAgent",
|
|
19
|
+
"PlannerAgent",
|
|
20
|
+
"ReflectionMixin",
|
|
21
|
+
]
|