ni.agentkit 0.3.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. agentkit/__init__.py +57 -0
  2. agentkit/_cli.py +72 -0
  3. agentkit/agents/__init__.py +0 -0
  4. agentkit/agents/agent.py +364 -0
  5. agentkit/agents/base_agent.py +59 -0
  6. agentkit/agents/orchestrators.py +62 -0
  7. agentkit/docs/Architecture.md +536 -0
  8. agentkit/docs/QuickStart.md +806 -0
  9. agentkit/docs/README.md +119 -0
  10. agentkit/docs/Reference.md +576 -0
  11. agentkit/docs/TestReport.md +80 -0
  12. agentkit/examples/__init__.py +0 -0
  13. agentkit/examples/ollama/01_basic_chat.py +34 -0
  14. agentkit/examples/ollama/02_tool_calling.py +70 -0
  15. agentkit/examples/ollama/03_skill_usage.py +86 -0
  16. agentkit/examples/ollama/04_multi_agent.py +84 -0
  17. agentkit/examples/ollama/05_guardrail.py +101 -0
  18. agentkit/examples/ollama/06_orchestration.py +123 -0
  19. agentkit/examples/ollama/07_sync_async_stream.py +180 -0
  20. agentkit/examples/ollama/08_memory.py +201 -0
  21. agentkit/examples/ollama/README.md +51 -0
  22. agentkit/examples/ollama/__init__.py +0 -0
  23. agentkit/examples/quickstart.py +204 -0
  24. agentkit/examples/standard/01_basic_chat.py +33 -0
  25. agentkit/examples/standard/02_tool_calling.py +70 -0
  26. agentkit/examples/standard/03_skill_usage.py +89 -0
  27. agentkit/examples/standard/04_multi_agent.py +87 -0
  28. agentkit/examples/standard/05_guardrail.py +104 -0
  29. agentkit/examples/standard/06_orchestration.py +122 -0
  30. agentkit/examples/standard/07_sync_async_stream.py +171 -0
  31. agentkit/examples/standard/08_memory.py +140 -0
  32. agentkit/examples/standard/README.md +31 -0
  33. agentkit/examples/standard/__init__.py +0 -0
  34. agentkit/examples/test_ollama.py +272 -0
  35. agentkit/llm/__init__.py +0 -0
  36. agentkit/llm/adapters/__init__.py +0 -0
  37. agentkit/llm/adapters/anthropic_adapter.py +192 -0
  38. agentkit/llm/adapters/google_adapter.py +184 -0
  39. agentkit/llm/adapters/ollama_adapter.py +250 -0
  40. agentkit/llm/adapters/openai_adapter.py +183 -0
  41. agentkit/llm/adapters/openai_compatible.py +35 -0
  42. agentkit/llm/base.py +66 -0
  43. agentkit/llm/cache.py +121 -0
  44. agentkit/llm/middleware.py +133 -0
  45. agentkit/llm/registry.py +138 -0
  46. agentkit/llm/types.py +191 -0
  47. agentkit/memory/__init__.py +0 -0
  48. agentkit/memory/base.py +47 -0
  49. agentkit/memory/mem0_provider.py +48 -0
  50. agentkit/runner/__init__.py +0 -0
  51. agentkit/runner/context.py +47 -0
  52. agentkit/runner/events.py +36 -0
  53. agentkit/runner/runner.py +105 -0
  54. agentkit/safety/__init__.py +0 -0
  55. agentkit/safety/guardrails.py +55 -0
  56. agentkit/safety/permissions.py +41 -0
  57. agentkit/skills/__init__.py +0 -0
  58. agentkit/skills/loader.py +90 -0
  59. agentkit/skills/models.py +106 -0
  60. agentkit/skills/registry.py +48 -0
  61. agentkit/tools/__init__.py +0 -0
  62. agentkit/tools/base_tool.py +44 -0
  63. agentkit/tools/function_tool.py +118 -0
  64. agentkit/tools/skill_toolset.py +199 -0
  65. agentkit/utils/__init__.py +0 -0
  66. agentkit/utils/schema.py +83 -0
  67. ni_agentkit-0.3.1.dist-info/METADATA +157 -0
  68. ni_agentkit-0.3.1.dist-info/RECORD +72 -0
  69. ni_agentkit-0.3.1.dist-info/WHEEL +5 -0
  70. ni_agentkit-0.3.1.dist-info/entry_points.txt +2 -0
  71. ni_agentkit-0.3.1.dist-info/licenses/LICENSE +21 -0
  72. ni_agentkit-0.3.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,806 @@
1
+ # AgentKit 快速入门教程
2
+
3
+ > 本教程将带你从零开始,通过 8 个由简到繁的示例,掌握 AgentKit 的核心用法。
4
+
5
+ ---
6
+
7
+ ## 目录
8
+
9
+ - [环境准备](#环境准备)
10
+ - [安装依赖](#1-安装依赖)
11
+ - [配置模型](#2-配置模型)
12
+ - [关于运行环境](#4-关于运行环境)
13
+ - [同步与异步](#5-同步与异步)
14
+ - [示例 1:最简 Agent — 纯对话](#示例-1最简-agent--纯对话)
15
+ - [示例 2:带工具的 Agent — Function Calling](#示例-2带工具的-agent--function-calling)
16
+ - [示例 3:带 Skill 的 Agent — 领域知识包](#示例-3带-skill-的-agent--领域知识包)
17
+ - [示例 4:多 Agent 协作 — Handoff 与 as_tool](#示例-4多-agent-协作--handoff-与-as_tool)
18
+ - [示例 5:安全护栏 — Guardrail 与权限控制](#示例-5安全护栏--guardrail-与权限控制)
19
+ - [示例 6:编排 Agent — 流水线与循环](#示例-6编排-agent--流水线与循环)
20
+ - [示例 7:同步/异步/流式运行](#示例-7同步异步流式运行)
21
+ - [示例 8:记忆系统 — 跨会话长期记忆](#示例-8记忆系统--跨会话长期记忆)
22
+ - [性能提示](#性能提示)
23
+ - [使用不同的 LLM](#使用不同的-llm)
24
+ - [下一步](#下一步)
25
+
26
+ ---
27
+
28
+ ## 环境准备
29
+
30
+ ### 1. 安装依赖
31
+
32
+ ```bash
33
+ pip install pydantic>=2.0 aiohttp>=3.9.0
34
+ ```
35
+
36
+ ### 2. 配置模型
37
+
38
+ AgentKit 支持多种 LLM。选择一种即可:
39
+
40
+ **方式 A:本地 Ollama(推荐入门,无需 API Key)**
41
+
42
+ ```bash
43
+ # 安装 Ollama: https://ollama.com
44
+ ollama pull qwen3.5:cloud
45
+ ```
46
+
47
+ **方式 B:OpenAI**
48
+
49
+ ```bash
50
+ pip install openai>=1.0.0
51
+ export OPENAI_API_KEY="sk-..."
52
+ ```
53
+
54
+ **方式 C:DeepSeek(国内推荐)**
55
+
56
+ ```bash
57
+ pip install openai>=1.0.0
58
+ export DEEPSEEK_API_KEY="sk-..."
59
+ ```
60
+
61
+ ### 3. 验证安装
62
+
63
+ ```python
64
+ from agentkit import Agent, Runner, function_tool
65
+ print("✅ AgentKit 安装成功")
66
+ ```
67
+
68
+ ### 4. 关于运行环境
69
+
70
+ > 💡 **AgentKit 是纯 Python 框架,不需要 Docker。** 直接在本地 Python 环境运行即可。
71
+ >
72
+ > Docker 仅在 Skill 脚本沙箱执行的最高安全级别(Level 3)时才需要,大部分场景完全用不到。详见 [Architecture.md](Architecture.md) 中的安全机制说明。
73
+
74
+ ### 5. 同步与异步
75
+
76
+ AgentKit 底层是异步的,但提供了三种运行方式:
77
+
78
+ ```python
79
+ # 方式 1:同步运行(最简单,推荐入门使用)
80
+ result = Runner.run_sync(agent, input="你好")
81
+
82
+ # 方式 2:异步运行(推荐生产环境)
83
+ import asyncio
84
+ async def main():
85
+ result = await Runner.run(agent, input="你好")
86
+ asyncio.run(main())
87
+
88
+ # 方式 3:流式运行(实时获取事件)
89
+ async def main():
90
+ async for event in Runner.run_streamed(agent, input="你好"):
91
+ if event.type == "final_output":
92
+ print(event.data)
93
+ ```
94
+
95
+ | 方式 | 适用场景 |
96
+ |------|---------|
97
+ | `Runner.run_sync()` | 脚本、快速测试、学习入门 |
98
+ | `await Runner.run()` | Web 服务、并发任务 |
99
+ | `Runner.run_streamed()` | 实时展示进度、聊天界面 |
100
+
101
+ > 本教程的示例统一使用 `Runner.run_sync()` 以保持简洁。
102
+
103
+ ---
104
+
105
+ ## 示例 1:最简 Agent — 纯对话
106
+
107
+ 最简单的 Agent 只需要三个参数:名称、指令、模型。
108
+
109
+ ```python
110
+ from agentkit import Agent, Runner
111
+
112
+ agent = Agent(
113
+ name="assistant",
114
+ instructions="你是一个有帮助的中文助手。回答尽量简洁。",
115
+ model="ollama/qwen3.5:cloud", # 替换为你使用的模型
116
+ )
117
+
118
+ # 同步运行
119
+ result = Runner.run_sync(agent, input="什么是量子计算?请用一句话解释。")
120
+
121
+ if result.success:
122
+ print(f"回复: {result.final_output}")
123
+ else:
124
+ print(f"错误: {result.error}")
125
+ ```
126
+
127
+ **要点**:
128
+ - `Agent` 是一个声明式配置对象,不需要继承任何类
129
+ - `Runner.run_sync()` 是同步入口,内部使用 `asyncio.run()`
130
+ - `result.success` 检查是否成功,`result.final_output` 获取输出
131
+
132
+ ### 异步运行
133
+
134
+ ```python
135
+ import asyncio
136
+
137
+ async def main():
138
+ result = await Runner.run(agent, input="你好")
139
+ print(result.final_output)
140
+
141
+ asyncio.run(main())
142
+ ```
143
+
144
+ ---
145
+
146
+ ## 示例 2:带工具的 Agent — Function Calling
147
+
148
+ 用 `@function_tool` 装饰器将 Python 函数变成 LLM 可调用的工具。
149
+
150
+ ```python
151
+ from agentkit import Agent, Runner, function_tool
152
+
153
+ # 用装饰器定义工具 —— 一行搞定
154
+ @function_tool
155
+ def add(a: int, b: int) -> str:
156
+ """两个数字相加"""
157
+ return str(a + b)
158
+
159
+ @function_tool
160
+ def multiply(a: int, b: int) -> str:
161
+ """两个数字相乘"""
162
+ return str(a * b)
163
+
164
+ @function_tool
165
+ def get_weather(city: str) -> str:
166
+ """获取指定城市的天气信息"""
167
+ weather_data = {
168
+ "北京": "晴,25°C",
169
+ "上海": "多云,22°C",
170
+ "深圳": "阵雨,28°C",
171
+ }
172
+ return weather_data.get(city, f"{city}:暂无数据")
173
+
174
+ # 创建带工具的 Agent
175
+ agent = Agent(
176
+ name="smart-assistant",
177
+ instructions="你是一个全能助手。可以做数学计算和查天气。根据用户需求选择合适的工具。",
178
+ model="ollama/qwen3.5:cloud",
179
+ tools=[add, multiply, get_weather], # 直接传入工具列表
180
+ )
181
+
182
+ result = Runner.run_sync(agent, input="请计算 15 + 27 的结果")
183
+ print(result.final_output) # "42" 或 "15 + 27 = 42"
184
+
185
+ result = Runner.run_sync(agent, input="北京今天天气如何?")
186
+ print(result.final_output) # "北京今天晴,气温25°C"
187
+ ```
188
+
189
+ **要点**:
190
+ - `@function_tool` 自动从函数签名推断 JSON Schema,从 docstring 提取描述
191
+ - 支持 `needs_approval=True`(需要人工审批)和 `timeout=30`(超时秒数)
192
+ - 工具函数可以是同步或异步的
193
+
194
+ ### 带参数的装饰器
195
+
196
+ ```python
197
+ @function_tool(needs_approval=True, timeout=30)
198
+ async def send_email(to: str, subject: str, body: str) -> str:
199
+ """发送邮件(需要人工确认)"""
200
+ # ... 实际发送逻辑
201
+ return "邮件已发送"
202
+ ```
203
+
204
+ ---
205
+
206
+ ## 示例 3:带 Skill 的 Agent — 领域知识包
207
+
208
+ **Skill 是 AgentKit 的核心创新**——它是"指令 + 资源 + 脚本"的打包体,代表一个领域的专业知识。
209
+
210
+ ### 方式 A:代码中直接定义 Skill
211
+
212
+ ```python
213
+ from agentkit import Agent, Runner, Skill, SkillFrontmatter, function_tool
214
+
215
+ # 定义一个天气分析 Skill
216
+ weather_skill = Skill(
217
+ frontmatter=SkillFrontmatter(
218
+ name="weather-analysis",
219
+ description="天气分析技能,查询天气并给出穿衣建议",
220
+ ),
221
+ instructions="""## 天气分析步骤
222
+
223
+ 1. 使用 get_weather 工具查询用户指定城市的天气
224
+ 2. 根据天气情况给出穿衣建议:
225
+ - 温度 > 30°C:建议穿短袖
226
+ - 温度 20-30°C:建议穿薄外套
227
+ - 温度 < 20°C:建议穿厚外套
228
+ 3. 用简洁的中文回复用户""",
229
+ )
230
+
231
+ @function_tool
232
+ def get_weather(city: str) -> str:
233
+ """获取指定城市的天气信息"""
234
+ return {"北京": "晴,25°C", "深圳": "阵雨,28°C"}.get(city, f"{city}:暂无数据")
235
+
236
+ # 创建带 Skill 的 Agent
237
+ agent = Agent(
238
+ name="skill-agent",
239
+ instructions="你是一个智能助手,可以使用专业技能来完成任务。",
240
+ model="ollama/qwen3.5:cloud",
241
+ skills=[weather_skill], # ⭐ Skill 一等公民
242
+ tools=[get_weather],
243
+ )
244
+
245
+ result = Runner.run_sync(agent, input="深圳今天适合穿什么衣服?")
246
+ print(result.final_output)
247
+ # 输出类似:"深圳今天阵雨,气温28°C,建议穿薄外套。"
248
+ ```
249
+
250
+ ### 方式 B:从目录加载 Skill
251
+
252
+ 创建 Skill 目录结构:
253
+
254
+ ```
255
+ skills/weather-analysis/
256
+ ├── SKILL.md # 必须
257
+ ├── references/ # 可选
258
+ │ └── clothing_guide.md
259
+ └── scripts/ # 可选
260
+ └── analyze.py
261
+ ```
262
+
263
+ `SKILL.md` 内容:
264
+
265
+ ```markdown
266
+ ---
267
+ name: weather-analysis
268
+ description: 天气分析技能,查询天气并给出穿衣建议
269
+ metadata:
270
+ additional_tools:
271
+ - get_weather
272
+ ---
273
+
274
+ ## 天气分析步骤
275
+
276
+ 1. 使用 get_weather 工具查询天气
277
+ 2. 读取 references/clothing_guide.md 获取穿衣建议规则
278
+ 3. 用简洁的中文回复用户
279
+ ```
280
+
281
+ 加载并使用:
282
+
283
+ ```python
284
+ from agentkit import Agent, Runner, load_skill_from_dir
285
+
286
+ weather_skill = load_skill_from_dir("./skills/weather-analysis")
287
+
288
+ agent = Agent(
289
+ name="skill-agent",
290
+ model="ollama/qwen3.5:cloud",
291
+ skills=[weather_skill],
292
+ )
293
+ ```
294
+
295
+ ### Skill 三级加载机制
296
+
297
+ AgentKit 的 Skill 采用三级渐进式加载,避免浪费 token:
298
+
299
+ | 级别 | 内容 | 加载时机 | Token 开销 |
300
+ |------|------|---------|-----------|
301
+ | **L1** | name + description | Agent 启动时自动注入 | ~100 词/Skill |
302
+ | **L2** | SKILL.md 详细指令 | LLM 调用 `load_skill` 时 | ~500 行 |
303
+ | **L3** | references/assets/scripts | 指令要求时按需加载 | 不限 |
304
+
305
+ ---
306
+
307
+ ## 示例 4:多 Agent 协作 — Handoff 与 as_tool
308
+
309
+ AgentKit 支持两种 Agent 协作模式:
310
+
311
+ ### 模式 A:as_tool(委派)
312
+
313
+ 一个 Agent 把另一个 Agent 当作工具调用。调用后控制权返回原 Agent。
314
+
315
+ ```python
316
+ from agentkit import Agent, Runner
317
+
318
+ # 专家 Agent
319
+ researcher = Agent(
320
+ name="researcher",
321
+ instructions="你是一个研究助手。收到问题后,给出简短的研究结论。",
322
+ model="ollama/qwen3.5:cloud",
323
+ )
324
+
325
+ # 主管 Agent,把研究员当工具用
326
+ manager = Agent(
327
+ name="manager",
328
+ instructions="你是项目经理。需要研究信息时调用 research 工具。综合研究结果给出建议。",
329
+ model="ollama/qwen3.5:cloud",
330
+ tools=[
331
+ researcher.as_tool("research", "调用研究助手获取研究信息"),
332
+ ],
333
+ )
334
+
335
+ result = Runner.run_sync(manager, input="帮我调研 Python 异步编程的最佳实践")
336
+ print(result.final_output)
337
+ ```
338
+
339
+ ### 模式 B:Handoff(转介)
340
+
341
+ 一个 Agent 把整个对话移交给另一个 Agent,控制权完全转移。
342
+
343
+ ```python
344
+ billing_agent = Agent(
345
+ name="billing",
346
+ instructions="你是账单专家,处理所有账单相关问题。",
347
+ model="ollama/qwen3.5:cloud",
348
+ )
349
+
350
+ tech_agent = Agent(
351
+ name="tech",
352
+ instructions="你是技术支持,处理所有技术问题。",
353
+ model="ollama/qwen3.5:cloud",
354
+ )
355
+
356
+ triage_agent = Agent(
357
+ name="triage",
358
+ instructions="你是客服分诊员。根据用户问题,转交给合适的专家。账单问题转给billing,技术问题转给tech。",
359
+ model="ollama/qwen3.5:cloud",
360
+ handoffs=[billing_agent, tech_agent],
361
+ )
362
+
363
+ result = Runner.run_sync(triage_agent, input="我的账单金额好像不对")
364
+ print(f"最终由 {result.last_agent} 处理: {result.final_output}")
365
+ ```
366
+
367
+ ### 两种模式对比
368
+
369
+ | | Handoff(转介) | as_tool(委派) |
370
+ |--|---------------|---------------|
371
+ | **控制权** | 完全转移 | 调用后返回 |
372
+ | **对话历史** | 目标收到完整历史 | 目标只收到任务输入 |
373
+ | **类比** | 把患者转到专科 | 打电话问专家一个问题 |
374
+
375
+ ---
376
+
377
+ ## 示例 5:安全护栏 — Guardrail 与权限控制
378
+
379
+ ### 输入护栏
380
+
381
+ ```python
382
+ from agentkit import Agent, Runner, input_guardrail, GuardrailResult
383
+
384
+ @input_guardrail
385
+ async def block_sensitive_words(ctx):
386
+ """检查输入是否包含敏感词"""
387
+ sensitive = ["密码", "身份证", "银行卡号"]
388
+ for word in sensitive:
389
+ if word in ctx.input:
390
+ return GuardrailResult(triggered=True, reason=f"包含敏感词: {word}")
391
+ return GuardrailResult(triggered=False)
392
+
393
+ agent = Agent(
394
+ name="safe-agent",
395
+ instructions="你是一个安全的助手。",
396
+ model="ollama/qwen3.5:cloud",
397
+ input_guardrails=[block_sensitive_words],
398
+ )
399
+
400
+ result = Runner.run_sync(agent, input="请告诉我你的密码")
401
+ print(result.error) # "输入被安全护栏拦截: 包含敏感词: 密码"
402
+ ```
403
+
404
+ ### 输出护栏
405
+
406
+ ```python
407
+ from agentkit import output_guardrail, GuardrailResult
408
+
409
+ @output_guardrail
410
+ async def check_factual_accuracy(ctx, output):
411
+ """检查输出是否存在问题"""
412
+ if "我不确定" in str(output):
413
+ return GuardrailResult(triggered=True, reason="输出包含不确定内容")
414
+ return GuardrailResult(triggered=False)
415
+
416
+ agent = Agent(
417
+ name="safe-agent",
418
+ output_guardrails=[check_factual_accuracy],
419
+ # ...
420
+ )
421
+ ```
422
+
423
+ ### 权限控制
424
+
425
+ ```python
426
+ from agentkit import PermissionPolicy
427
+
428
+ agent = Agent(
429
+ name="controlled-agent",
430
+ model="ollama/qwen3.5:cloud",
431
+ tools=[send_email, read_file, delete_file],
432
+ permission_policy=PermissionPolicy(
433
+ mode="ask", # "allow_all" / "deny_all" / "ask"
434
+ allowed_tools={"read_file"}, # 白名单:只允许 read_file
435
+ ),
436
+ )
437
+ ```
438
+
439
+ ---
440
+
441
+ ## 示例 6:编排 Agent — 流水线与循环
442
+
443
+ ### 顺序执行(SequentialAgent)
444
+
445
+ ```python
446
+ from agentkit import Agent, SequentialAgent, Runner
447
+
448
+ pipeline = SequentialAgent(
449
+ name="report-pipeline",
450
+ sub_agents=[
451
+ Agent(name="extractor", instructions="从用户输入中提取关键数据点", model="ollama/qwen3.5:cloud"),
452
+ Agent(name="analyzer", instructions="分析提取的数据,找出趋势和规律", model="ollama/qwen3.5:cloud"),
453
+ Agent(name="reporter", instructions="将分析结果写成一段简洁的报告", model="ollama/qwen3.5:cloud"),
454
+ ],
455
+ )
456
+
457
+ result = Runner.run_sync(pipeline, input="今年Q1销售额1000万,Q2增长到1500万,Q3下降到1200万")
458
+ ```
459
+
460
+ ### 并行执行(ParallelAgent)
461
+
462
+ ```python
463
+ from agentkit import ParallelAgent
464
+
465
+ parallel = ParallelAgent(
466
+ name="multi-analysis",
467
+ sub_agents=[
468
+ Agent(name="financial", instructions="分析财务数据", model="ollama/qwen3.5:cloud"),
469
+ Agent(name="market", instructions="分析市场趋势", model="ollama/qwen3.5:cloud"),
470
+ Agent(name="risk", instructions="分析风险因素", model="ollama/qwen3.5:cloud"),
471
+ ],
472
+ )
473
+ ```
474
+
475
+ ### 循环执行(LoopAgent)
476
+
477
+ ```python
478
+ from agentkit import LoopAgent
479
+
480
+ review_loop = LoopAgent(
481
+ name="code-review",
482
+ max_iterations=5,
483
+ sub_agents=[
484
+ Agent(name="coder", instructions="根据反馈编写或修改代码", model="ollama/qwen3.5:cloud"),
485
+ Agent(name="reviewer", instructions="审查代码。如果通过则发出 escalate 信号,否则给出修改建议", model="ollama/qwen3.5:cloud"),
486
+ ],
487
+ )
488
+ ```
489
+
490
+ ---
491
+
492
+ ## 示例 7:同步/异步/流式运行
493
+
494
+ 前面的示例统一使用 `Runner.run_sync()` 保持简洁。本示例展示 Runner 的三种运行方式及其适用场景。
495
+
496
+ ### 方式 1:同步运行(最简单)
497
+
498
+ ```python
499
+ from agentkit import Agent, Runner, function_tool
500
+
501
+ @function_tool
502
+ def get_weather(city: str) -> str:
503
+ """获取天气"""
504
+ return {"北京": "晴,25°C", "上海": "多云,22°C"}.get(city, f"{city}:暂无数据")
505
+
506
+ agent = Agent(
507
+ name="assistant",
508
+ instructions="你是一个简洁的中文助手。",
509
+ model="ollama/qwen3.5:cloud",
510
+ tools=[get_weather],
511
+ )
512
+
513
+ # 一行搞定,内部自动处理 asyncio
514
+ result = Runner.run_sync(agent, input="北京今天天气如何?")
515
+ print(result.final_output)
516
+ ```
517
+
518
+ `run_sync()` 适合**脚本、快速测试、学习入门**。
519
+
520
+ ### 方式 2:异步运行(推荐生产环境)
521
+
522
+ ```python
523
+ import asyncio
524
+
525
+ async def main():
526
+ result = await Runner.run(agent, input="上海今天天气如何?")
527
+ print(result.final_output)
528
+
529
+ asyncio.run(main())
530
+ ```
531
+
532
+ 异步的核心优势——**并发执行多个请求**:
533
+
534
+ ```python
535
+ async def concurrent_demo():
536
+ queries = ["1+1等于几?", "北京天气如何?", "什么是 Python?"]
537
+
538
+ # asyncio.gather 并发执行 3 个请求
539
+ results = await asyncio.gather(*[
540
+ Runner.run(agent, input=q) for q in queries
541
+ ])
542
+
543
+ for q, r in zip(queries, results):
544
+ print(f" [{q}] → {r.final_output}")
545
+
546
+ asyncio.run(concurrent_demo())
547
+ ```
548
+
549
+ > 3 个请求并发总耗时 ≈ 单个请求的时间,而非 3 倍。
550
+
551
+ ### 方式 3:流式运行(实时事件)
552
+
553
+ ```python
554
+ import asyncio
555
+
556
+ async def stream_demo():
557
+ async for event in Runner.run_streamed(agent, input="北京今天天气如何?"):
558
+ if event.type == "llm_response":
559
+ has_tools = "有工具调用" if event.data.has_tool_calls else "纯文本"
560
+ print(f"🤖 LLM 响应 ({has_tools})")
561
+ elif event.type == "tool_result":
562
+ tool_name = event.data.get("tool", "?")
563
+ print(f"🔧 工具 {tool_name} → {event.data.get('result', '')}")
564
+ elif event.type == "final_output":
565
+ print(f"✅ 最终输出: {event.data}")
566
+
567
+ asyncio.run(stream_demo())
568
+ ```
569
+
570
+ 适合**聊天界面、进度展示**——每个事件实时推送。
571
+
572
+ ### 三种方式对比
573
+
574
+ | 方式 | API | 适用场景 |
575
+ |------|-----|---------|
576
+ | **同步** | `Runner.run_sync(agent, input=...)` | 脚本、快速测试 |
577
+ | **异步** | `await Runner.run(agent, input=...)` | Web 服务、并发任务 |
578
+ | **流式** | `async for event in Runner.run_streamed(...)` | 聊天 UI、进度展示 |
579
+
580
+ > ⚠️ **注意**:`run_sync()` 内部调用 `asyncio.run()`,不能在已有事件循环中使用。如果你的代码已经是 `async` 的,请直接用 `await Runner.run()`。
581
+
582
+ ---
583
+
584
+ ## 示例 8:记忆系统 — 跨会话长期记忆
585
+
586
+ 默认情况下,Agent 每次运行都是无状态的。配上记忆后,Agent 可以记住用户的偏好和历史。
587
+
588
+ ### 无需外部依赖的 SimpleMemory
589
+
590
+ ```python
591
+ from agentkit import Agent, Runner, BaseMemoryProvider, Memory
592
+
593
+ class SimpleMemory(BaseMemoryProvider):
594
+ """轻量内存记忆——适合开发测试"""
595
+ def __init__(self):
596
+ self._store, self._counter = [], 0
597
+
598
+ async def add(self, content, *, user_id=None, agent_id=None, metadata=None):
599
+ self._counter += 1
600
+ m = Memory(id=str(self._counter), content=content)
601
+ self._store.append(m)
602
+ return [m]
603
+
604
+ async def search(self, query, *, user_id=None, agent_id=None, limit=10):
605
+ # 简单关键词匹配(生产环境用 Mem0 的向量搜索)
606
+ query_words = set(query)
607
+ scored = [(len(query_words & set(m.content)), m) for m in self._store]
608
+ scored.sort(reverse=True, key=lambda x: x[0])
609
+ return [m for s, m in scored[:limit] if s > 0]
610
+
611
+ async def get_all(self, *, user_id=None, agent_id=None):
612
+ return list(self._store)
613
+
614
+ async def delete(self, memory_id):
615
+ self._store = [m for m in self._store if m.id != memory_id]
616
+ return True
617
+
618
+ # 给 Agent 配上记忆
619
+ memory = SimpleMemory()
620
+
621
+ agent = Agent(
622
+ name="personal-assistant",
623
+ instructions="你是一个贴心的个人助手。根据记忆来个性化回答。",
624
+ model="ollama/qwen3.5:cloud",
625
+ memory=memory, # ← 加上这一行
626
+ )
627
+
628
+ # 第 1 轮:告诉偏好
629
+ Runner.run_sync(agent, input="我叫小明,我喜欢喝咖啡,讨厌喝茶", user_id="krix")
630
+
631
+ # 第 2 轮:Agent 会记住偏好,推荐咖啡而不是茶
632
+ result = Runner.run_sync(agent, input="帮我推荐一杯饮料", user_id="krix")
633
+ print(result.final_output) # "推荐拿铁!" — 基于记忆推荐
634
+ ```
635
+
636
+ **要点**:
637
+ - 默认不开启记忆,需要给 `Agent` 传 `memory=...` 参数
638
+ - 配好后**不需要写额外代码**——框架自动在对话前检索记忆、对话后存储记忆
639
+ - `user_id` 用于多用户隔离
640
+
641
+ ### 生产环境使用 Mem0
642
+
643
+ ```bash
644
+ pip install mem0ai
645
+ docker run -p 6333:6333 qdrant/qdrant # 启动向量数据库
646
+ ```
647
+
648
+ ```python
649
+ from agentkit.memory.mem0_provider import Mem0Provider
650
+
651
+ memory = Mem0Provider({
652
+ "vector_store": {
653
+ "provider": "qdrant",
654
+ "config": {"collection_name": "my_agent", "host": "localhost", "port": 6333}
655
+ }
656
+ })
657
+
658
+ agent = Agent(memory=memory, ...) # 替换 SimpleMemory 即可
659
+ ```
660
+
661
+ Mem0 相比 SimpleMemory 的优势:**语义搜索**(理解意思而非关键词)、**持久化**(重启不丢失)、**智能提取**(从对话中自动抽取关键信息)。
662
+
663
+ ---
664
+
665
+ ## 性能提示
666
+
667
+ 当你感觉 Agent 响应较慢时,可以尝试以下优化:
668
+
669
+ ### Thinking 模式
670
+
671
+ qwen3.5 等模型支持「深度思考」。OllamaAdapter **默认开启** thinking,可按需关闭:
672
+
673
+ ```python
674
+ from agentkit.llm.registry import LLMRegistry
675
+
676
+ # 默认开启 thinking
677
+ llm = LLMRegistry.create("ollama/qwen3.5:cloud")
678
+
679
+ # 关闭 thinking(纯对话场景可能更快,但工具调用场景 cloud 模型可能反而更慢)
680
+ llm.config.extra_params["think"] = False
681
+ agent = Agent(model=llm, instructions="你是助手")
682
+ ```
683
+
684
+ > ⚠️ cloud 模型 thinking 本身很快,关闭后效果因场景而异,建议先测试。
685
+
686
+ ### 启用缓存
687
+
688
+ LLM 响应缓存**默认已开启**,对相同问题直接返回缓存结果。缓存绑定 Agent 实例,不同 Agent 之间互不影响。
689
+
690
+ ```python
691
+ # 默认已开启,无需额外配置
692
+ agent = Agent(model="ollama/qwen3.5:cloud", ...)
693
+
694
+ # 需要关闭时:
695
+ agent = Agent(model="ollama/qwen3.5:cloud", enable_cache=False, ...)
696
+ ```
697
+
698
+ > ⚠️ 仅缓存纯文本回复,不缓存工具调用响应(因为工具结果可能变化)。
699
+
700
+ ### 记忆写入模式
701
+
702
+ ```python
703
+ # 默认:异步写入(不阻塞返回,Web 服务推荐)
704
+ agent = Agent(memory=my_memory, memory_async_write=True, ...)
705
+
706
+ # 同步写入(等写完再返回,多轮串行对话推荐)
707
+ agent = Agent(memory=my_memory, memory_async_write=False, ...)
708
+ ```
709
+
710
+ > ⚠️ 异步模式下,下一轮对话可能读不到上一轮刚存的记忆。多轮串行对话建议设为 `False`。
711
+
712
+ 更多细节请参考 [Architecture.md — 性能优化](Architecture.md#性能优化)。
713
+
714
+ ---
715
+
716
+ ## 使用不同的 LLM
717
+
718
+ 只需修改 `model` 参数即可切换 LLM,无需改动其他代码:
719
+
720
+ ```python
721
+ # 本地 Ollama
722
+ agent = Agent(model="ollama/qwen3.5:cloud", ...)
723
+
724
+ # OpenAI
725
+ agent = Agent(model="gpt-4o", ...)
726
+
727
+ # Anthropic Claude
728
+ agent = Agent(model="claude-sonnet-4-20250514", ...)
729
+
730
+ # Google Gemini
731
+ agent = Agent(model="gemini-2.5-flash", ...)
732
+
733
+ # 通义千问 / 智谱 / 百川 / Azure
734
+ agent = Agent(model="deepseek/deepseek-chat", ...)
735
+ agent = Agent(model="qwen/qwen-max", ...)
736
+ agent = Agent(model="zhipu/glm-4", ...)
737
+ agent = Agent(model="baichuan/baichuan2-turbo", ...)
738
+ agent = Agent(model="azure/your-deployment", ...)
739
+ ```
740
+
741
+ ### 精细配置
742
+
743
+ ```python
744
+ from agentkit import LLMConfig
745
+
746
+ agent = Agent(
747
+ model=LLMConfig(
748
+ model="gpt-4o",
749
+ temperature=0.3,
750
+ max_tokens=4096,
751
+ fallback_models=["gpt-4o-mini"], # 失败时自动降级
752
+ ),
753
+ ...
754
+ )
755
+ ```
756
+
757
+ ### 设置全局默认模型
758
+
759
+ ```python
760
+ from agentkit import LLMRegistry
761
+
762
+ LLMRegistry.set_default("ollama/qwen3.5:cloud")
763
+
764
+ # 之后创建的 Agent 如果不指定 model,将使用这个默认模型
765
+ agent = Agent(name="assistant", instructions="...")
766
+ ```
767
+
768
+ ---
769
+
770
+ ## 完整示例源码
771
+
772
+ 以上所有示例均提供了可直接运行的独立源码文件,分为两个版本:
773
+
774
+ ### 📁 `examples/standard/` — 标准版(使用 OpenAI GPT-4o,需要 API Key)
775
+
776
+ | 文件 | 对应示例 |
777
+ |------|---------|
778
+ | [`01_basic_chat.py`](../examples/standard/01_basic_chat.py) | 示例 1:最简 Agent |
779
+ | [`02_tool_calling.py`](../examples/standard/02_tool_calling.py) | 示例 2:工具调用 |
780
+ | [`03_skill_usage.py`](../examples/standard/03_skill_usage.py) | 示例 3:Skill 使用 |
781
+ | [`04_multi_agent.py`](../examples/standard/04_multi_agent.py) | 示例 4:多 Agent 协作 |
782
+ | [`05_guardrail.py`](../examples/standard/05_guardrail.py) | 示例 5:安全护栏 |
783
+ | [`06_orchestration.py`](../examples/standard/06_orchestration.py) | 示例 6:编排 Agent |
784
+ | [`07_sync_async_stream.py`](../examples/standard/07_sync_async_stream.py) | 示例 7:同步/异步/流式运行 |
785
+ | [`08_memory.py`](../examples/standard/08_memory.py) | 示例 8:记忆系统 |
786
+
787
+ ### 📁 `examples/ollama/` — Ollama 本地版(无需 API Key,完全本地运行)
788
+
789
+ | 文件 | 对应示例 |
790
+ |------|---------|
791
+ | [`01_basic_chat.py`](../examples/ollama/01_basic_chat.py) | 示例 1:最简 Agent |
792
+ | [`02_tool_calling.py`](../examples/ollama/02_tool_calling.py) | 示例 2:工具调用 |
793
+ | [`03_skill_usage.py`](../examples/ollama/03_skill_usage.py) | 示例 3:Skill 使用 |
794
+ | [`04_multi_agent.py`](../examples/ollama/04_multi_agent.py) | 示例 4:多 Agent 协作 |
795
+ | [`05_guardrail.py`](../examples/ollama/05_guardrail.py) | 示例 5:安全护栏 |
796
+ | [`06_orchestration.py`](../examples/ollama/06_orchestration.py) | 示例 6:编排 Agent |
797
+ | [`07_sync_async_stream.py`](../examples/ollama/07_sync_async_stream.py) | 示例 7:同步/异步/流式运行 |
798
+ | [`08_memory.py`](../examples/ollama/08_memory.py) | 示例 8:记忆系统 |
799
+
800
+ ---
801
+
802
+ ## 下一步
803
+
804
+ - 📐 阅读 **[Architecture.md](Architecture.md)** 了解框架的六层架构设计
805
+ - 📚 阅读 **[Reference.md](Reference.md)** 查看完整的 API 参考手册
806
+ - 🔬 查看 `examples/` 目录中的更多示例代码