ni.agentkit 0.6.2__tar.gz → 0.7.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.
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/PKG-INFO +3 -3
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/README.md +2 -2
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/__init__.py +1 -1
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/docs/Architecture.md +10 -2
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/docs/QuickStart.md +109 -24
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/docs/README.md +3 -2
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/docs/Reference.md +45 -0
- ni_agentkit-0.7.0/docs/TestReport.md +92 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/01_basic_chat.py +10 -9
- ni_agentkit-0.7.0/examples/ollama/05_human_in_the_loop.py +42 -0
- ni_agentkit-0.7.0/examples/ollama/08a_memory_simple_provider.py +59 -0
- ni_agentkit-0.7.0/examples/ollama/08b_memory_mem0_provider.py +57 -0
- ni_agentkit-0.7.0/examples/ollama/08c_memory_file_provider.py +102 -0
- ni_agentkit-0.7.0/examples/ollama/09c_nebula_graph_tool.py +76 -0
- ni_agentkit-0.7.0/examples/ollama/19_hitl_deterministic.py +57 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/README.md +1 -0
- ni_agentkit-0.7.0/examples/standard/08a_memory_simple_provider.py +59 -0
- ni_agentkit-0.7.0/examples/standard/08b_memory_mem0_provider.py +49 -0
- ni_agentkit-0.7.0/examples/standard/08c_memory_file_provider.py +102 -0
- ni_agentkit-0.7.0/examples/standard/09c_nebula_graph_tool.py +72 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/README.md +1 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/ni.agentkit.egg-info/PKG-INFO +3 -3
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/ni.agentkit.egg-info/SOURCES.txt +21 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/pyproject.toml +1 -1
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/runner/events.py +32 -2
- ni_agentkit-0.7.0/tests/test_graph_repository.py +83 -0
- ni_agentkit-0.6.2/docs/TestReport.md +0 -80
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/LICENSE +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/_cli.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/agents/__init__.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/agents/agent.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/agents/base_agent.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/agents/orchestrators.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/__init__.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/02_tool_calling.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/03_skill_usage.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/04_multi_agent.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/05_guardrail.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/06_orchestration.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/07_sync_async_stream.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/08_memory.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/09a_structured_data_sql.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/09b_structured_data_graph.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/10_skill_lifecycle.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/11_orchestration_enhancement.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/12_run_context_serialization.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/13_human_in_the_loop.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/14_event_standardization.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/15_multi_tenant_isolation.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/16_lifecycle_hooks.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/17_checkpoint_handoff_resume.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/18_model_cosplay.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/ollama/__init__.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/quickstart.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/01_basic_chat.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/02_tool_calling.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/03_skill_usage.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/04_multi_agent.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/05_guardrail.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/06_orchestration.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/07_sync_async_stream.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/08_memory.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/09a_structured_data_sql.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/09b_structured_data_graph.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/10_skill_lifecycle.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/11_orchestration_enhancement.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/12_run_context_serialization.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/13_human_in_the_loop.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/14_event_standardization.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/15_multi_tenant_isolation.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/16_lifecycle_hooks.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/17_checkpoint_handoff_resume.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/18_model_cosplay.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/standard/__init__.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/examples/test_ollama.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/llm/__init__.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/llm/adapters/__init__.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/llm/adapters/anthropic_adapter.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/llm/adapters/google_adapter.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/llm/adapters/ollama_adapter.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/llm/adapters/openai_adapter.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/llm/adapters/openai_compatible.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/llm/base.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/llm/cache.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/llm/middleware.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/llm/registry.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/llm/types.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/memory/__init__.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/memory/base.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/memory/mem0_provider.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/ni.agentkit.egg-info/dependency_links.txt +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/ni.agentkit.egg-info/entry_points.txt +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/ni.agentkit.egg-info/requires.txt +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/ni.agentkit.egg-info/top_level.txt +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/runner/__init__.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/runner/context.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/runner/context_store.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/runner/runner.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/safety/__init__.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/safety/guardrails.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/safety/permissions.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/setup.cfg +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/skills/__init__.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/skills/loader.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/skills/models.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/skills/registry.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/tests/test_after_callback.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/tests/test_quickstart_core.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/tests/test_runner_checkpoint_resume.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/tools/__init__.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/tools/base_tool.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/tools/function_tool.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/tools/nebula_tool.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/tools/skill_toolset.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/tools/sqlite_tool.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/tools/structured_data.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/utils/__init__.py +0 -0
- {ni_agentkit-0.6.2 → ni_agentkit-0.7.0}/utils/schema.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ni.agentkit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: A Python-native Agent framework with first-class Skill support and multi-LLM adapter
|
|
5
5
|
Author-email: Krix Tam <krix.tam@qq.com>
|
|
6
6
|
License: MIT
|
|
@@ -153,8 +153,8 @@ python "$(python -c "import agentkit, os; print(os.path.join(agentkit.get_exampl
|
|
|
153
153
|
|
|
154
154
|
```bash
|
|
155
155
|
dist/
|
|
156
|
-
├── ni_agentkit-0.
|
|
157
|
-
└── ni_agentkit-0.
|
|
156
|
+
├── ni_agentkit-0.7.0-py3-none-any.whl # pip install 用这个
|
|
157
|
+
└── ni_agentkit-0.7.0.tar.gz # 源码分发
|
|
158
158
|
```
|
|
159
159
|
|
|
160
160
|
## 📄 License
|
|
@@ -111,8 +111,8 @@ python "$(python -c "import agentkit, os; print(os.path.join(agentkit.get_exampl
|
|
|
111
111
|
|
|
112
112
|
```bash
|
|
113
113
|
dist/
|
|
114
|
-
├── ni_agentkit-0.
|
|
115
|
-
└── ni_agentkit-0.
|
|
114
|
+
├── ni_agentkit-0.7.0-py3-none-any.whl # pip install 用这个
|
|
115
|
+
└── ni_agentkit-0.7.0.tar.gz # 源码分发
|
|
116
116
|
```
|
|
117
117
|
|
|
118
118
|
## 📄 License
|
|
@@ -31,7 +31,7 @@ from .tools.function_tool import FunctionTool, function_tool
|
|
|
31
31
|
from .tools.structured_data import ResultFormatter, StructuredDataTool
|
|
32
32
|
from .tools.sqlite_tool import SQLiteTool, SQLiteResultFormatter
|
|
33
33
|
|
|
34
|
-
__version__ = "0.
|
|
34
|
+
__version__ = "0.7.0"
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
def get_docs_dir() -> str:
|
|
@@ -575,6 +575,14 @@ agentkit/
|
|
|
575
575
|
│ ├── structured_data.py # StructuredDataTool / ResultFormatter
|
|
576
576
|
│ ├── sqlite_tool.py # SQLiteTool
|
|
577
577
|
│ ├── nebula_tool.py # NebulaGraphTool
|
|
578
|
+
│ ├── graph/ # 统一图接口层(Adapter/Repository/Tool)
|
|
579
|
+
│ │ ├── protocols.py # GraphAdapter 协议
|
|
580
|
+
│ │ ├── repository.py # GraphRepository(统一访问入口)
|
|
581
|
+
│ │ ├── factory.py # create_graph_repository* 工厂
|
|
582
|
+
│ │ ├── networkx_adapter.py
|
|
583
|
+
│ │ ├── litegraph_adapter.py
|
|
584
|
+
│ │ ├── nebula_adapter.py
|
|
585
|
+
│ │ └── tool.py # GraphQueryTool
|
|
578
586
|
│ └── skill_toolset.py # SkillToolset(4 个桥接工具)
|
|
579
587
|
│
|
|
580
588
|
├── skills/ # Skill 层
|
|
@@ -612,8 +620,8 @@ agentkit/
|
|
|
612
620
|
│ └── schema.py # 函数签名 → JSON Schema
|
|
613
621
|
│
|
|
614
622
|
├── examples/ # 示例
|
|
615
|
-
│ ├── standard/ # 标准版示例(01-18,含 9A/9B)
|
|
616
|
-
│ ├── ollama/ # Ollama 版示例(01-
|
|
623
|
+
│ ├── standard/ # 标准版示例(01-18,含 8A/8B/8C、9A/9B/9C)
|
|
624
|
+
│ ├── ollama/ # Ollama 版示例(01-19,含 8A/8B/8C、9A/9B/9C)
|
|
617
625
|
│ ├── quickstart.py
|
|
618
626
|
│ └── test_ollama.py
|
|
619
627
|
│
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# AgentKit 快速入门教程
|
|
2
2
|
|
|
3
|
-
> 本教程将带你从零开始,通过 18 组由简到繁的示例(含 9A/9B),掌握 AgentKit 的核心用法。
|
|
3
|
+
> 本教程将带你从零开始,通过 18 组由简到繁的示例(含 8A/8B/8C、9A/9B/9C),掌握 AgentKit 的核心用法。
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
- [示例 8:记忆系统 — 跨会话长期记忆](#示例-8记忆系统--跨会话长期记忆)
|
|
22
22
|
- [示例 9A:关系型数据库 — 防止 SQL 注入的参数化 Tool](#示例-9a关系型数据库--防止-sql-注入的参数化-tool)
|
|
23
23
|
- [示例 9B:图数据库 — 配合 Mock 运行的 NebulaGraphTool](#示例-9b图数据库--配合-mock-运行的-nebulagraphtool)
|
|
24
|
+
- [示例 9C:NebulaGraphTool 最小可执行示例(工具层直调)](#示例-9cnebulagraphtool-最小可执行示例工具层直调)
|
|
24
25
|
- [示例 10:Skill 生命周期 — 管理外部资源连接池](#示例-10skill-生命周期--管理外部资源连接池)
|
|
25
26
|
- [示例 11:编排增强 — 循环退出条件与并行提前终止](#示例-11编排增强--循环退出条件与并行提前终止)
|
|
26
27
|
- [示例 12:RunContext 序列化与共享状态](#示例-12runcontext-序列化与共享状态)
|
|
@@ -608,60 +609,45 @@ asyncio.run(stream_demo())
|
|
|
608
609
|
|
|
609
610
|
默认情况下,Agent 每次运行都是无状态的。配上记忆后,Agent 可以记住用户的偏好和历史。
|
|
610
611
|
|
|
611
|
-
###
|
|
612
|
+
### 8A:SimpleMemory
|
|
612
613
|
|
|
613
614
|
```python
|
|
614
615
|
from agentkit import Agent, Runner, BaseMemoryProvider, Memory
|
|
615
616
|
|
|
616
617
|
class SimpleMemory(BaseMemoryProvider):
|
|
617
|
-
"""轻量内存记忆——适合开发测试"""
|
|
618
618
|
def __init__(self):
|
|
619
619
|
self._store, self._counter = [], 0
|
|
620
|
-
|
|
621
620
|
async def add(self, content, *, user_id=None, agent_id=None, metadata=None):
|
|
622
621
|
self._counter += 1
|
|
623
622
|
m = Memory(id=str(self._counter), content=content)
|
|
624
623
|
self._store.append(m)
|
|
625
624
|
return [m]
|
|
626
|
-
|
|
627
625
|
async def search(self, query, *, user_id=None, agent_id=None, limit=10):
|
|
628
|
-
# 简单关键词匹配(生产环境用 Mem0 的向量搜索)
|
|
629
626
|
query_words = set(query)
|
|
630
627
|
scored = [(len(query_words & set(m.content)), m) for m in self._store]
|
|
631
628
|
scored.sort(reverse=True, key=lambda x: x[0])
|
|
632
629
|
return [m for s, m in scored[:limit] if s > 0]
|
|
633
|
-
|
|
634
630
|
async def get_all(self, *, user_id=None, agent_id=None):
|
|
635
631
|
return list(self._store)
|
|
636
|
-
|
|
637
632
|
async def delete(self, memory_id):
|
|
638
633
|
self._store = [m for m in self._store if m.id != memory_id]
|
|
639
634
|
return True
|
|
640
635
|
|
|
641
|
-
# 给 Agent 配上记忆
|
|
642
636
|
memory = SimpleMemory()
|
|
643
|
-
|
|
644
637
|
agent = Agent(
|
|
645
638
|
name="personal-assistant",
|
|
646
639
|
instructions="你是一个贴心的个人助手。根据记忆来个性化回答。",
|
|
647
640
|
model="ollama/qwen3.5:cloud",
|
|
648
|
-
memory=memory,
|
|
641
|
+
memory=memory,
|
|
642
|
+
memory_async_write=False,
|
|
649
643
|
)
|
|
650
644
|
|
|
651
|
-
# 第 1 轮:告诉偏好
|
|
652
645
|
Runner.run_sync(agent, input="我叫小明,我喜欢喝咖啡,讨厌喝茶", user_id="krix")
|
|
653
|
-
|
|
654
|
-
# 第 2 轮:Agent 会记住偏好,推荐咖啡而不是茶
|
|
655
646
|
result = Runner.run_sync(agent, input="帮我推荐一杯饮料", user_id="krix")
|
|
656
|
-
print(result.final_output) #
|
|
647
|
+
print(result.final_output) # 基于记忆推荐
|
|
657
648
|
```
|
|
658
649
|
|
|
659
|
-
|
|
660
|
-
- 默认不开启记忆,需要给 `Agent` 传 `memory=...` 参数
|
|
661
|
-
- 配好后**不需要写额外代码**——框架自动在对话前检索记忆、对话后存储记忆
|
|
662
|
-
- `user_id` 用于多用户隔离
|
|
663
|
-
|
|
664
|
-
### 生产环境使用 Mem0
|
|
650
|
+
### 8B:Mem0Provider(生产级)
|
|
665
651
|
|
|
666
652
|
```bash
|
|
667
653
|
pip install mem0ai
|
|
@@ -678,11 +664,47 @@ memory = Mem0Provider({
|
|
|
678
664
|
}
|
|
679
665
|
})
|
|
680
666
|
|
|
681
|
-
agent = Agent(memory=memory, ...)
|
|
667
|
+
agent = Agent(memory=memory, ...) # 先构建 memory,再注入 Agent
|
|
682
668
|
```
|
|
683
669
|
|
|
684
670
|
Mem0 相比 SimpleMemory 的优势:**语义搜索**(理解意思而非关键词)、**持久化**(重启不丢失)、**智能提取**(从对话中自动抽取关键信息)。
|
|
685
671
|
|
|
672
|
+
### 8C:自定义 Memory(文件持久化)
|
|
673
|
+
|
|
674
|
+
```python
|
|
675
|
+
import json
|
|
676
|
+
from pathlib import Path
|
|
677
|
+
from agentkit import BaseMemoryProvider, Memory, Agent
|
|
678
|
+
|
|
679
|
+
class FileMemoryProvider(BaseMemoryProvider):
|
|
680
|
+
def __init__(self, file_path: str):
|
|
681
|
+
self.path = Path(file_path)
|
|
682
|
+
self.records = json.loads(self.path.read_text()) if self.path.exists() else []
|
|
683
|
+
async def add(self, content, *, user_id=None, agent_id=None, metadata=None):
|
|
684
|
+
new_id = str(len(self.records) + 1)
|
|
685
|
+
self.records.append({"id": new_id, "content": content, "user_id": user_id})
|
|
686
|
+
self.path.write_text(json.dumps(self.records, ensure_ascii=False, indent=2))
|
|
687
|
+
return [Memory(id=new_id, content=content)]
|
|
688
|
+
async def search(self, query, *, user_id=None, agent_id=None, limit=10):
|
|
689
|
+
q = query.lower()
|
|
690
|
+
out = [r for r in self.records if q in r["content"].lower()]
|
|
691
|
+
return [Memory(id=r["id"], content=r["content"]) for r in out[:limit]]
|
|
692
|
+
async def get_all(self, *, user_id=None, agent_id=None):
|
|
693
|
+
return [Memory(id=r["id"], content=r["content"]) for r in self.records]
|
|
694
|
+
async def delete(self, memory_id):
|
|
695
|
+
self.records = [r for r in self.records if r["id"] != memory_id]
|
|
696
|
+
self.path.write_text(json.dumps(self.records, ensure_ascii=False, indent=2))
|
|
697
|
+
return True
|
|
698
|
+
|
|
699
|
+
memory = FileMemoryProvider("/tmp/agentkit_memory.json")
|
|
700
|
+
agent = Agent(memory=memory, ...)
|
|
701
|
+
```
|
|
702
|
+
|
|
703
|
+
**要点**:
|
|
704
|
+
- 默认不开启记忆,需要给 `Agent` 传 `memory=...` 参数
|
|
705
|
+
- `SimpleMemory` 适合开发测试,`Mem0Provider` 适合生产语义检索
|
|
706
|
+
- 自定义 `FileMemoryProvider` 可实现轻量持久化(进程重启后仍可读取)
|
|
707
|
+
|
|
686
708
|
---
|
|
687
709
|
|
|
688
710
|
## 示例 9A:关系型数据库 — 防止 SQL 注入的参数化 Tool
|
|
@@ -803,6 +825,63 @@ if __name__ == "__main__":
|
|
|
803
825
|
|
|
804
826
|
---
|
|
805
827
|
|
|
828
|
+
## 示例 9C:NebulaGraphTool 最小可执行示例(工具层直调)
|
|
829
|
+
|
|
830
|
+
如果你想先验证 `NebulaGraphTool` 本身(参数校验、查询模板拼接、formatter 输出)是否工作正常,可以不经过 LLM,直接调用工具执行。
|
|
831
|
+
|
|
832
|
+
```python
|
|
833
|
+
import asyncio
|
|
834
|
+
from typing import Any
|
|
835
|
+
from pydantic import BaseModel, Field
|
|
836
|
+
from agentkit.runner.context import RunContext
|
|
837
|
+
from agentkit.tools.nebula_tool import NebulaGraphTool
|
|
838
|
+
from agentkit.tools.structured_data import ResultFormatter
|
|
839
|
+
|
|
840
|
+
class MockSession:
|
|
841
|
+
def execute(self, query: str):
|
|
842
|
+
print(f"[MockSession] execute gql => {query}")
|
|
843
|
+
return "mock_result_set"
|
|
844
|
+
def release(self): pass
|
|
845
|
+
|
|
846
|
+
class MockConnectionPool:
|
|
847
|
+
def get_session(self, user, password):
|
|
848
|
+
return MockSession()
|
|
849
|
+
|
|
850
|
+
class MockNebulaFormatter(ResultFormatter):
|
|
851
|
+
def format(self, raw_result: Any) -> Any:
|
|
852
|
+
return {"summary": "Query succeeded (mock)", "data": [{"friend_name": "Bob"}]}
|
|
853
|
+
|
|
854
|
+
class PersonQueryArgs(BaseModel):
|
|
855
|
+
name: str = Field(..., pattern=r"^[A-Za-z0-9_]+$")
|
|
856
|
+
|
|
857
|
+
nebula_tool = NebulaGraphTool(
|
|
858
|
+
name="find_person_friends",
|
|
859
|
+
description="查询某个人在图谱中的朋友关系",
|
|
860
|
+
parameters_schema=PersonQueryArgs,
|
|
861
|
+
query_template='MATCH (v:person)-[:friend]->(e:person) WHERE id(v) == "{name}" RETURN e.name AS friend_name;',
|
|
862
|
+
space_name="social_graph",
|
|
863
|
+
connection_pool=MockConnectionPool(),
|
|
864
|
+
formatter=MockNebulaFormatter(),
|
|
865
|
+
)
|
|
866
|
+
|
|
867
|
+
async def main():
|
|
868
|
+
payload = await nebula_tool.execute(RunContext(input="demo"), {"name": "Alice_001"})
|
|
869
|
+
print(payload)
|
|
870
|
+
|
|
871
|
+
if __name__ == "__main__":
|
|
872
|
+
asyncio.run(main())
|
|
873
|
+
```
|
|
874
|
+
|
|
875
|
+
运行文件:
|
|
876
|
+
- `examples/standard/09c_nebula_graph_tool.py`
|
|
877
|
+
- `examples/ollama/09c_nebula_graph_tool.py`
|
|
878
|
+
|
|
879
|
+
**要点**:
|
|
880
|
+
- 该示例不依赖真实 Nebula 集群,也不依赖 LLM,可用于本地快速验证 Tool 行为。
|
|
881
|
+
- 后续接入真实 Nebula 时,只需替换 `connection_pool` 与(可选)`formatter`。
|
|
882
|
+
|
|
883
|
+
---
|
|
884
|
+
|
|
806
885
|
## 示例 10:Skill 生命周期 — 管理外部资源连接池
|
|
807
886
|
|
|
808
887
|
当 Skill 依赖外部资源(如数据库连接池、长期会话句柄)时,你需要确保在使用前正确初始化,并在结束时安全释放。
|
|
@@ -1159,9 +1238,12 @@ agent = Agent(name="assistant", instructions="...")
|
|
|
1159
1238
|
| [`05_guardrail.py`](../examples/standard/05_guardrail.py) | 示例 5:安全护栏 |
|
|
1160
1239
|
| [`06_orchestration.py`](../examples/standard/06_orchestration.py) | 示例 6:编排 Agent |
|
|
1161
1240
|
| [`07_sync_async_stream.py`](../examples/standard/07_sync_async_stream.py) | 示例 7:同步/异步/流式运行 |
|
|
1162
|
-
| [`
|
|
1241
|
+
| [`08a_memory_simple_provider.py`](../examples/standard/08a_memory_simple_provider.py) | 示例 8A:记忆系统(SimpleMemory) |
|
|
1242
|
+
| [`08b_memory_mem0_provider.py`](../examples/standard/08b_memory_mem0_provider.py) | 示例 8B:记忆系统(Mem0Provider) |
|
|
1243
|
+
| [`08c_memory_file_provider.py`](../examples/standard/08c_memory_file_provider.py) | 示例 8C:记忆系统(文件持久化) |
|
|
1163
1244
|
| [`09a_structured_data_sql.py`](../examples/standard/09a_structured_data_sql.py) | 示例 9A:关系型数据库 |
|
|
1164
1245
|
| [`09b_structured_data_graph.py`](../examples/standard/09b_structured_data_graph.py) | 示例 9B:图数据库 |
|
|
1246
|
+
| [`09c_nebula_graph_tool.py`](../examples/standard/09c_nebula_graph_tool.py) | 示例 9C:NebulaGraphTool 最小可执行示例 |
|
|
1165
1247
|
| [`10_skill_lifecycle.py`](../examples/standard/10_skill_lifecycle.py) | 示例 10:Skill 生命周期 |
|
|
1166
1248
|
| [`11_orchestration_enhancement.py`](../examples/standard/11_orchestration_enhancement.py) | 示例 11:编排增强 |
|
|
1167
1249
|
| [`12_run_context_serialization.py`](../examples/standard/12_run_context_serialization.py) | 示例 12:RunContext 序列化与共享状态 |
|
|
@@ -1183,9 +1265,12 @@ agent = Agent(name="assistant", instructions="...")
|
|
|
1183
1265
|
| [`05_guardrail.py`](../examples/ollama/05_guardrail.py) | 示例 5:安全护栏 |
|
|
1184
1266
|
| [`06_orchestration.py`](../examples/ollama/06_orchestration.py) | 示例 6:编排 Agent |
|
|
1185
1267
|
| [`07_sync_async_stream.py`](../examples/ollama/07_sync_async_stream.py) | 示例 7:同步/异步/流式运行 |
|
|
1186
|
-
| [`
|
|
1268
|
+
| [`08a_memory_simple_provider.py`](../examples/ollama/08a_memory_simple_provider.py) | 示例 8A:记忆系统(SimpleMemory) |
|
|
1269
|
+
| [`08b_memory_mem0_provider.py`](../examples/ollama/08b_memory_mem0_provider.py) | 示例 8B:记忆系统(Mem0Provider) |
|
|
1270
|
+
| [`08c_memory_file_provider.py`](../examples/ollama/08c_memory_file_provider.py) | 示例 8C:记忆系统(文件持久化) |
|
|
1187
1271
|
| [`09a_structured_data_sql.py`](../examples/ollama/09a_structured_data_sql.py) | 示例 9A:关系型数据库 |
|
|
1188
1272
|
| [`09b_structured_data_graph.py`](../examples/ollama/09b_structured_data_graph.py) | 示例 9B:图数据库 |
|
|
1273
|
+
| [`09c_nebula_graph_tool.py`](../examples/ollama/09c_nebula_graph_tool.py) | 示例 9C:NebulaGraphTool 最小可执行示例 |
|
|
1189
1274
|
| [`10_skill_lifecycle.py`](../examples/ollama/10_skill_lifecycle.py) | 示例 10:Skill 生命周期 |
|
|
1190
1275
|
| [`11_orchestration_enhancement.py`](../examples/ollama/11_orchestration_enhancement.py) | 示例 11:编排增强 |
|
|
1191
1276
|
| [`12_run_context_serialization.py`](../examples/ollama/12_run_context_serialization.py) | 示例 12:RunContext 序列化与共享状态 |
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> Python 原生的 Agent 开发框架,内置一等公民级别的 Skill 支持和自研多模型适配层。
|
|
4
4
|
|
|
5
5
|
[](https://python.org)
|
|
6
|
-
[]()
|
|
7
7
|
[]()
|
|
8
8
|
|
|
9
9
|
---
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
| **双协作模式** | Handoff(控制权转移)+ as_tool(Agent 当工具调用),灵活覆盖所有协作场景 |
|
|
18
18
|
| **编排 Agent** | SequentialAgent / ParallelAgent / LoopAgent,组合出任意复杂的工作流。支持 Loop 动态退出条件与 Parallel 提前取消增强 |
|
|
19
19
|
| **@function_tool** | 一行装饰器把 Python 函数变成 LLM 工具,自动推断 JSON Schema。内建 `StructuredDataTool` 防止数据库注入 |
|
|
20
|
+
| **图数据统一接口层** | 提供 `GraphAdapter + GraphRepository + GraphQueryTool`,开发/测试可切换 `networkx/litegraph`,生产可切换 `nebula` |
|
|
20
21
|
| **安全内置** | Input/Output 双向 Guardrail + 三层权限控制;`run_skill_script` 当前为占位执行(SandboxExecutor 预留扩展) |
|
|
21
22
|
| **记忆系统** | Mem0 集成,跨会话长期记忆 |
|
|
22
23
|
| **9 个回调点** | before/after × agent/model/tool/handoff + error,任何环节可拦截定制 |
|
|
@@ -70,7 +71,7 @@ print(result.final_output)
|
|
|
70
71
|
|
|
71
72
|
| 文档 | 说明 |
|
|
72
73
|
|------|------|
|
|
73
|
-
| **[QuickStart.md](QuickStart.md)** | 详细入门教程,包含 18 组从简到繁的完整示例(含 9A/9B) |
|
|
74
|
+
| **[QuickStart.md](QuickStart.md)** | 详细入门教程,包含 18 组从简到繁的完整示例(含 8A/8B/8C、9A/9B/9C) |
|
|
74
75
|
| **[Architecture.md](Architecture.md)** | 架构设计说明:六层分层、设计原则、核心流程 |
|
|
75
76
|
| **[Reference.md](Reference.md)** | 完整 API 参考手册:所有类、方法、参数说明 |
|
|
76
77
|
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
- [FunctionTool](#functiontool)
|
|
22
22
|
- [BaseTool / BaseToolset](#basetool--basetoolset)
|
|
23
23
|
- [StructuredDataTool (结构化数据源)](#structureddatatool-结构化数据源)
|
|
24
|
+
- [Graph 统一接口层(Adapter / Repository / Tool)](#graph-统一接口层adapter--repository--tool)
|
|
24
25
|
- [Skill 类](#skill-类)
|
|
25
26
|
- [Skill](#skill)
|
|
26
27
|
- [SkillFrontmatter](#skillfrontmatter)
|
|
@@ -443,6 +444,50 @@ from agentkit.tools.nebula_tool import NebulaGraphTool
|
|
|
443
444
|
|
|
444
445
|
---
|
|
445
446
|
|
|
447
|
+
### Graph 统一接口层(Adapter / Repository / Tool)
|
|
448
|
+
|
|
449
|
+
用于在开发/测试/生产环境之间切换图后端,统一业务侧调用方式。
|
|
450
|
+
|
|
451
|
+
```python
|
|
452
|
+
from agentkit.tools.graph import (
|
|
453
|
+
GraphRepository,
|
|
454
|
+
GraphQueryTool,
|
|
455
|
+
NodeSpec,
|
|
456
|
+
EdgeSpec,
|
|
457
|
+
QuerySpec,
|
|
458
|
+
create_graph_repository,
|
|
459
|
+
create_graph_repository_from_env,
|
|
460
|
+
)
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
**核心模型**:
|
|
464
|
+
|
|
465
|
+
| 类型 | 关键字段 | 说明 |
|
|
466
|
+
|------|----------|------|
|
|
467
|
+
| `NodeSpec` | `node_id`、`label`、`properties` | 节点写入规范 |
|
|
468
|
+
| `EdgeSpec` | `source_id`、`target_id`、`edge_type`、`directed`、`properties` | 边写入规范 |
|
|
469
|
+
| `QuerySpec` | `operation`、`node_id/source_id/target_id`、`filters`、`limit` | 图查询参数规范(`neighbors/shortest_path/find_nodes/edges`) |
|
|
470
|
+
| `GraphResult` | `backend`、`rows`、`summary`、`meta` | 统一查询返回结构 |
|
|
471
|
+
|
|
472
|
+
**适配器与仓储**:
|
|
473
|
+
|
|
474
|
+
| 组件 | 说明 |
|
|
475
|
+
|------|------|
|
|
476
|
+
| `GraphAdapter` | 适配器协议,统一 `upsert_node/upsert_edge/query/healthcheck/close` |
|
|
477
|
+
| `NetworkXAdapter` | 开发态图后端,可选本地 JSON 持久化 |
|
|
478
|
+
| `LiteGraphAdapter` | 基于 SQLite 的轻量图后端,适合测试与单机场景 |
|
|
479
|
+
| `NebulaAdapter` | Nebula 生产后端适配器 |
|
|
480
|
+
| `GraphRepository` | 业务统一入口,屏蔽底层后端差异 |
|
|
481
|
+
| `create_graph_repository` | 按 `backend` + `config` 创建仓储 |
|
|
482
|
+
| `create_graph_repository_from_env` | 按环境变量快速创建仓储(`AGENTKIT_GRAPH_*`) |
|
|
483
|
+
|
|
484
|
+
**Tool 集成**:
|
|
485
|
+
|
|
486
|
+
- `GraphQueryTool` 继承 `StructuredDataTool`,参数 Schema 固定为 `GraphQueryArgs`,底层通过 `GraphRepository.query()` 执行并返回标准化 `dict`。
|
|
487
|
+
- 默认支持后端:`networkx` / `litegraph` / `nebula`。
|
|
488
|
+
|
|
489
|
+
---
|
|
490
|
+
|
|
446
491
|
## Skill 类
|
|
447
492
|
|
|
448
493
|
### Skill
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# AgentKit 示例测试报告
|
|
2
|
+
|
|
3
|
+
> 测试时间:`2026-04-27`
|
|
4
|
+
> 测试环境:`macOS (Apple Silicon)`
|
|
5
|
+
> 模型:Ollama `qwen3.5:cloud`
|
|
6
|
+
> AgentKit 版本:v0.7.0
|
|
7
|
+
> Thinking 模式:开启(默认)
|
|
8
|
+
> LLM 调用模式:非流式(默认)
|
|
9
|
+
> 缓存:开启(默认)
|
|
10
|
+
> 执行脚本:`examples/test_ollama.py`
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 测试结果
|
|
15
|
+
|
|
16
|
+
| # | 示例 | 文件 | 耗时 | 状态 | 说明 |
|
|
17
|
+
|---|------|------|-----:|:----:|------|
|
|
18
|
+
| 1 | 基础对话 | `01_basic_chat.py` | 102.10s | ✅ | 运行通过 |
|
|
19
|
+
| 2 | 工具调用 | `02_tool_calling.py` | 21.27s | ✅ | 运行通过 |
|
|
20
|
+
| 3 | Skill 使用 | `03_skill_usage.py` | 62.60s | ✅ | 运行通过 |
|
|
21
|
+
| 4 | 多 Agent 协作 | `04_multi_agent.py` | 194.60s | ✅ | 运行通过 |
|
|
22
|
+
| 5 | 安全护栏 | `05_guardrail.py` | 8.23s | ✅ | 运行通过 |
|
|
23
|
+
| 5H | HITL 工具触发(Playground 专用) | `05_human_in_the_loop.py` | 0.28s | ✅ | 运行通过 |
|
|
24
|
+
| 6 | 编排 Agent | `06_orchestration.py` | 523.64s | ✅ | 运行通过(本轮最慢) |
|
|
25
|
+
| 7 | 同步/异步/流式 | `07_sync_async_stream.py` | 19.73s | ✅ | 运行通过 |
|
|
26
|
+
| 8 | 记忆系统(综合) | `08_memory.py` | 485.15s | ✅ | 运行通过 |
|
|
27
|
+
| 8A | SimpleMemory | `08a_memory_simple_provider.py` | 30.39s | ✅ | 运行通过 |
|
|
28
|
+
| 8B | Mem0Provider | `08b_memory_mem0_provider.py` | 0.25s | ✅ | 运行通过 |
|
|
29
|
+
| 8C | 文件持久化 Memory | `08c_memory_file_provider.py` | 58.73s | ✅ | 运行通过 |
|
|
30
|
+
| 9A | 结构化数据(SQL) | `09a_structured_data_sql.py` | 7.88s | ✅ | 运行通过 |
|
|
31
|
+
| 9B | 结构化数据(图) | `09b_structured_data_graph.py` | 6.65s | ✅ | 运行通过 |
|
|
32
|
+
| 9C | NebulaGraphTool(直调) | `09c_nebula_graph_tool.py` | 0.32s | ✅ | 运行通过 |
|
|
33
|
+
| 10 | Skill 生命周期 | `10_skill_lifecycle.py` | 2.86s | ✅ | 运行通过 |
|
|
34
|
+
| 11 | 编排增强 | `11_orchestration_enhancement.py` | 70.51s | ✅ | 运行通过 |
|
|
35
|
+
| 12 | 序列化协议 | `12_run_context_serialization.py` | 0.27s | ✅ | 运行通过 |
|
|
36
|
+
| 13 | Human in the Loop | `13_human_in_the_loop.py` | 5.81s | ✅ | 运行通过 |
|
|
37
|
+
| 14 | Event 标准化 | `14_event_standardization.py` | 9.74s | ✅ | 运行通过 |
|
|
38
|
+
| 15 | 多租户隔离 | `15_multi_tenant_isolation.py` | 0.31s | ✅ | 运行通过 |
|
|
39
|
+
| 16 | 生命周期 Hooks | `16_lifecycle_hooks.py` | 0.26s | ✅ | 运行通过 |
|
|
40
|
+
| 17 | Checkpoint + Handoff + Resume | `17_checkpoint_handoff_resume.py` | 0.17s | ✅ | 运行通过 |
|
|
41
|
+
| 18 | ModelCosplay | `18_model_cosplay.py` | 0.17s | ✅ | 运行通过 |
|
|
42
|
+
| 19 | HITL 确定性触发 | `19_hitl_deterministic.py` | 0.17s | ✅ | 运行通过(本轮最快) |
|
|
43
|
+
| | **合计** | | **1612.09s** | **25/25** | |
|
|
44
|
+
|
|
45
|
+
## 耗时分析
|
|
46
|
+
|
|
47
|
+
- **最快示例**:19 HITL 确定性触发(0.17s)
|
|
48
|
+
- **最慢示例**:6 编排 Agent(523.64s)
|
|
49
|
+
- **耗时集中区间**:涉及多轮推理/记忆写入/编排循环的示例耗时显著更高
|
|
50
|
+
|
|
51
|
+
## 各示例 LLM 调用次数估算
|
|
52
|
+
|
|
53
|
+
| # | 示例 | LLM 调用次数 | 说明 |
|
|
54
|
+
|---|------|:-----------:|------|
|
|
55
|
+
| 1 | 基础对话 | 1 | 单次对话 |
|
|
56
|
+
| 2 | 工具调用 | ~6 | 多次工具调用与回复生成 |
|
|
57
|
+
| 3 | Skill 使用 | ~9 | load_skill + 工具调用 + 回复 |
|
|
58
|
+
| 4 | 多 Agent 协作 | ~8 | as_tool + handoff 链路 |
|
|
59
|
+
| 5 | 安全护栏 | ~3 | 拦截与放行混合路径 |
|
|
60
|
+
| 5H | HITL 工具触发(Playground 专用) | ~0 | 仅触发挂起事件,不走 LLM |
|
|
61
|
+
| 6 | 编排 Agent | ~12 | Sequential + Parallel + Loop |
|
|
62
|
+
| 7 | 同步/异步/流式 | ~7 | 三种运行模式覆盖 |
|
|
63
|
+
| 8 | 记忆系统(综合) | ~10 | 记忆读写与多轮对话 |
|
|
64
|
+
| 8A | SimpleMemory | ~2 | 轻量关键词检索 |
|
|
65
|
+
| 8B | Mem0Provider | ~0 | 未配置 `OPENAI_API_KEY` 时自动跳过 |
|
|
66
|
+
| 8C | 文件持久化 Memory | ~2 | 本地文件读写 + 记忆检索 |
|
|
67
|
+
| 9A | 结构化数据(SQL) | ~2 | 参数化查询 + 汇总 |
|
|
68
|
+
| 9B | 结构化数据(图) | ~2 | 图查询 + 汇总 |
|
|
69
|
+
| 9C | NebulaGraphTool(直调) | 0 | Mock 连接池直调,不依赖 LLM |
|
|
70
|
+
| 10 | Skill 生命周期 | 1 | 单轮校验 |
|
|
71
|
+
| 11 | 编排增强 | ~4 | loop_condition + early_exit |
|
|
72
|
+
| 12 | RunContext 序列化 | 0 | 纯本地序列化 |
|
|
73
|
+
| 13 | HITL 断点续跑 | ~3 | 挂起 + 恢复 |
|
|
74
|
+
| 14 | 事件协议标准化 | 1 | 标准事件输出 |
|
|
75
|
+
| 15 | 多租户隔离 | ~3 | 多会话隔离验证 |
|
|
76
|
+
| 16 | 生命周期 Hooks | ~2 | Hook 链路验证 |
|
|
77
|
+
| 17 | Checkpoint Handoff 恢复 | 0 | 自定义事件流,不依赖 LLM |
|
|
78
|
+
| 18 | ModelCosplay | 0 | 仅验证模型改写开关与运行时覆盖逻辑,不调用 LLM |
|
|
79
|
+
| 19 | HITL 确定性触发 | 0 | 自定义事件流,不依赖 LLM |
|
|
80
|
+
|
|
81
|
+
## 已知问题
|
|
82
|
+
|
|
83
|
+
| 问题 | 严重程度 | 说明 |
|
|
84
|
+
|------|:--------:|------|
|
|
85
|
+
| 运行异常 | - | 无,25 个示例全部通过 |
|
|
86
|
+
|
|
87
|
+
## 运行方式
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
# 在 agentkit 目录执行
|
|
91
|
+
python examples/test_ollama.py
|
|
92
|
+
```
|
|
@@ -21,14 +21,15 @@ agent = Agent(
|
|
|
21
21
|
)
|
|
22
22
|
|
|
23
23
|
# 同步运行
|
|
24
|
-
|
|
24
|
+
if __name__ == "__main__":
|
|
25
|
+
result = Runner.run_sync(agent, input="什么是量子计算?请用一句话解释。")
|
|
25
26
|
|
|
26
|
-
if result.success:
|
|
27
|
-
|
|
28
|
-
else:
|
|
29
|
-
|
|
27
|
+
if result.success:
|
|
28
|
+
print(f"✅ 回复: {result.final_output}")
|
|
29
|
+
else:
|
|
30
|
+
print(f"❌ 错误: {result.error}")
|
|
30
31
|
|
|
31
|
-
# 查看事件流
|
|
32
|
-
print("\n📋 事件流:")
|
|
33
|
-
for event in result.events:
|
|
34
|
-
|
|
32
|
+
# 查看事件流
|
|
33
|
+
print("\n📋 事件流:")
|
|
34
|
+
for event in result.events:
|
|
35
|
+
print(f" [{event.type}] {str(event.data)[:80]}")
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""
|
|
2
|
+
示例 5(Playground/HITL 专用):Human-in-the-loop Agent(Ollama 版)
|
|
3
|
+
|
|
4
|
+
用途:
|
|
5
|
+
- 提供一个可被 AgentHub `entry` 直接加载的 `agent` 实例;
|
|
6
|
+
- 在工具执行前通过 `request_human_input(...)` 触发挂起,便于在 Playground 中演示 HITL。
|
|
7
|
+
"""
|
|
8
|
+
import os
|
|
9
|
+
import sys
|
|
10
|
+
|
|
11
|
+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", ".."))
|
|
12
|
+
|
|
13
|
+
from agentkit import Agent
|
|
14
|
+
from agentkit.tools.base_tool import request_human_input
|
|
15
|
+
from agentkit.tools.function_tool import FunctionTool
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def confirm_action(action: str) -> str:
|
|
19
|
+
"""敏感操作执行前请求人工确认。"""
|
|
20
|
+
request_human_input(f"即将执行敏感操作: {action},请确认 (approve/reject)")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def execute_action(action: str) -> str:
|
|
24
|
+
"""执行操作(示例返回)。"""
|
|
25
|
+
return f"操作 '{action}' 已执行。"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
confirm_tool = FunctionTool.from_function(confirm_action)
|
|
29
|
+
execute_tool = FunctionTool.from_function(execute_action)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
agent = Agent(
|
|
33
|
+
name="hitl-agent",
|
|
34
|
+
instructions=(
|
|
35
|
+
"你是一个需要人工审批的运维助手。"
|
|
36
|
+
"当用户要求执行敏感操作时,必须先调用 confirm_action 请求人工确认;"
|
|
37
|
+
"收到确认后再调用 execute_action。"
|
|
38
|
+
),
|
|
39
|
+
# 使用纯本地模型,避免 cloud 变体在未鉴权/网络抖动时触发远端 502。
|
|
40
|
+
model="ollama/qwen3.5:4b",
|
|
41
|
+
tools=[confirm_tool, execute_tool],
|
|
42
|
+
)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", ".."))
|
|
6
|
+
|
|
7
|
+
from agentkit import Agent, BaseMemoryProvider, Memory, Runner
|
|
8
|
+
|
|
9
|
+
MODEL = "ollama/qwen3.5:cloud"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class SimpleMemory(BaseMemoryProvider):
|
|
13
|
+
def __init__(self) -> None:
|
|
14
|
+
self._store: list[Memory] = []
|
|
15
|
+
self._counter = 0
|
|
16
|
+
|
|
17
|
+
async def add(self, content, *, user_id=None, agent_id=None, metadata=None):
|
|
18
|
+
self._counter += 1
|
|
19
|
+
item = Memory(id=str(self._counter), content=content)
|
|
20
|
+
self._store.append(item)
|
|
21
|
+
return [item]
|
|
22
|
+
|
|
23
|
+
async def search(self, query, *, user_id=None, agent_id=None, limit=10):
|
|
24
|
+
query_chars = set(query)
|
|
25
|
+
scored: list[tuple[int, Memory]] = []
|
|
26
|
+
for item in self._store:
|
|
27
|
+
overlap = len(query_chars & set(item.content))
|
|
28
|
+
if overlap > 0:
|
|
29
|
+
scored.append((overlap, item))
|
|
30
|
+
scored.sort(reverse=True, key=lambda x: x[0])
|
|
31
|
+
return [m for _, m in scored[:limit]]
|
|
32
|
+
|
|
33
|
+
async def get_all(self, *, user_id=None, agent_id=None):
|
|
34
|
+
return list(self._store)
|
|
35
|
+
|
|
36
|
+
async def delete(self, memory_id):
|
|
37
|
+
self._store = [m for m in self._store if m.id != memory_id]
|
|
38
|
+
return True
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
async def main() -> None:
|
|
42
|
+
print("=== 示例 8A:SimpleMemory ===")
|
|
43
|
+
memory = SimpleMemory()
|
|
44
|
+
agent = Agent(
|
|
45
|
+
name="remembering",
|
|
46
|
+
instructions="你是贴心助手。根据记忆回答,回答简洁。",
|
|
47
|
+
model=MODEL,
|
|
48
|
+
memory=memory,
|
|
49
|
+
memory_async_write=False,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
await Runner.run(agent, input="我叫小明,喜欢咖啡,讨厌茶。", user_id="user_001")
|
|
53
|
+
result = await Runner.run(agent, input="帮我推荐一杯饮料。", user_id="user_001")
|
|
54
|
+
print("推荐:", result.final_output)
|
|
55
|
+
print("记忆条数:", len(await memory.get_all()))
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
if __name__ == "__main__":
|
|
59
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", ".."))
|
|
6
|
+
|
|
7
|
+
from agentkit import Agent, Runner
|
|
8
|
+
|
|
9
|
+
MODEL = "ollama/qwen3.5:cloud"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
async def main() -> None:
|
|
13
|
+
print("=== 示例 8B:Mem0Provider ===")
|
|
14
|
+
try:
|
|
15
|
+
from agentkit.memory.mem0_provider import Mem0Provider
|
|
16
|
+
except Exception:
|
|
17
|
+
print("未安装 mem0ai,跳过运行。")
|
|
18
|
+
print("安装: pip install mem0ai")
|
|
19
|
+
print("并启动 qdrant: docker run -p 6333:6333 qdrant/qdrant")
|
|
20
|
+
return
|
|
21
|
+
|
|
22
|
+
if not os.getenv("OPENAI_API_KEY"):
|
|
23
|
+
print("未设置 OPENAI_API_KEY,跳过运行。")
|
|
24
|
+
return
|
|
25
|
+
|
|
26
|
+
try:
|
|
27
|
+
memory = Mem0Provider(
|
|
28
|
+
{
|
|
29
|
+
"vector_store": {
|
|
30
|
+
"provider": "qdrant",
|
|
31
|
+
"config": {
|
|
32
|
+
"collection_name": "agentkit_quickstart",
|
|
33
|
+
"host": "localhost",
|
|
34
|
+
"port": 6333,
|
|
35
|
+
},
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
)
|
|
39
|
+
except Exception as exc:
|
|
40
|
+
print(f"Mem0 初始化失败,跳过运行: {exc}")
|
|
41
|
+
return
|
|
42
|
+
|
|
43
|
+
agent = Agent(
|
|
44
|
+
name="mem0-assistant",
|
|
45
|
+
instructions="你是贴心助手。根据记忆回答,回答简洁。",
|
|
46
|
+
model=MODEL,
|
|
47
|
+
memory=memory,
|
|
48
|
+
memory_async_write=False,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
await Runner.run(agent, input="记住:我喜欢低糖拿铁。", user_id="user_001")
|
|
52
|
+
result = await Runner.run(agent, input="给我推荐一杯饮料。", user_id="user_001")
|
|
53
|
+
print("推荐:", result.final_output)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
if __name__ == "__main__":
|
|
57
|
+
asyncio.run(main())
|