我来为你设计一个在Mac上基于Ollama和phi3:mini的完整Agent/Subagent例子。这个例子会模拟一个简单的"任务分解与执行"工作流,让你直观感受多智能体协作。
🎯 示例场景:智能任务处理器
我们将创建一个主Agent,它接收用户复杂任务,然后协调两个Subagent:
- 分解专家Subagent:专门拆分复杂任务为具体步骤
- 执行专家Subagent:专门执行具体步骤并报告结果
📁 项目结构
phi3_agent_demo/
├── main.py # 主程序
├── agents.py # Agent类定义
├── requirements.txt # 依赖包
└── README.md # 说明文档
1. 首先安装必要依赖
bash
# 创建项目目录
mkdir phi3_agent_demo && cd phi3_agent_demo
# 创建requirements.txt
echo "requests>=2.31.0
python-dotenv>=1.0.0" > requirements.txt
# 安装依赖
pip install -r requirements.txt
2. 创建Agent核心代码
agents.py - 定义Agent基类和具体Agent
python
import requests
import json
import time
from typing import Dict, List, Any, Optional
class BaseAgent:
"""Agent基类,封装与Ollama的通信"""
def __init__(self, name: str, model: str = "phi3:mini", system_prompt: str = ""):
self.name = name
self.model = model
self.system_prompt = system_prompt
self.ollama_url = "http://localhost:11434/api/generate"
def query_llm(self, prompt: str, max_tokens: int = 500) -> str:
"""向Ollama发送查询"""
payload = {
"model": self.model,
"prompt": f"{self.system_prompt}\n\n用户指令: {prompt}",
"stream": False,
"options": {
"temperature": 0.3,
"num_predict": max_tokens
}
}
try:
response = requests.post(self.ollama_url, json=payload, timeout=30)
response.raise_for_status()
result = response.json()
return result.get("response", "").strip()
except requests.exceptions.RequestException as e:
return f"错误: 无法连接Ollama服务 - {str(e)}"
def process(self, input_data: Any) -> Any:
"""处理输入,子类需要重写"""
raise NotImplementedError("子类必须实现process方法")
class TaskDecomposerAgent(BaseAgent):
"""任务分解专家 - Subagent 1: 专门拆分复杂任务"""
def __init__(self):
system_prompt = """你是一个专业的任务分解专家。你的工作是将用户提出的复杂任务拆解为具体的、可执行的步骤。
输出格式要求:
1. 始终以JSON格式输出,包含一个"steps"数组
2. 每个步骤是一个对象,包含"id"、"description"和"type"字段
3. type可以是:research(研究)、calculate(计算)、write(写作)、review(审查)等
示例:
{"steps": [
{"id": 1, "description": "搜索相关主题的最新信息", "type": "research"},
{"id": 2, "description": "计算关键数据指标", "type": "calculate"}
]}
现在开始处理用户任务:"""
super().__init__("任务分解专家", system_prompt=system_prompt)
def process(self, complex_task: str) -> List[Dict[str, Any]]:
print(f"🔍 [{self.name}] 正在分析任务: {complex_task}")
prompt = f"请将以下任务分解为具体步骤:\n\n任务: {complex_task}"
response = self.query_llm(prompt)
# 尝试解析JSON响应
try:
# 提取JSON部分(模型有时会在JSON前后添加文本)
import re
json_match = re.search(r'\{.*\}', response, re.DOTALL)
if json_match:
json_str = json_match.group()
result = json.loads(json_str)
steps = result.get("steps", [])
print(f"✅ [{self.name}] 分解完成,共{len(steps)}个步骤")
for step in steps:
print(f" - 步骤{step['id']}: {step['description']} ({step['type']})")
return steps
else:
# 如果无法解析为JSON,创建默认步骤
return [{"id": 1, "description": response[:100], "type": "general"}]
except json.JSONDecodeError:
print(f"⚠️ [{self.name}] JSON解析失败,使用原始响应")
return [{"id": 1, "description": response[:100], "type": "general"}]
class TaskExecutorAgent(BaseAgent):
"""任务执行专家 - Subagent 2: 专门执行具体任务"""
def __init__(self, expertise: str = "general"):
self.expertise = expertise
system_prompt = f"""你是一个专业的{expertise}任务执行专家。你的工作是具体执行分配给你的任务步骤。
你需要:
1. 理解任务要求
2. 执行具体操作(思考、计算、分析等)
3. 提供清晰的执行结果
输出格式:
{{"status": "success|partial|failed", "result": "具体执行结果", "details": "详细说明"}}
现在请执行以下任务:"""
super().__init__(f"{expertise}执行专家", system_prompt=system_prompt)
def process(self, task_step: Dict[str, Any]) -> Dict[str, Any]:
step_id = task_step.get("id", 0)
description = task_step.get("description", "")
step_type = task_step.get("type", "general")
print(f"🛠️ [{self.name}] 正在执行步骤{step_id}: {description}")
prompt = f"任务类型: {step_type}\n任务描述: {description}\n\n请执行此任务并报告结果:"
response = self.query_llm(prompt)
# 尝试解析响应中的JSON
try:
import re
json_match = re.search(r'\{.*\}', response, re.DOTALL)
if json_match:
result = json.loads(json_match.group())
else:
result = {"status": "success", "result": response, "details": "模型返回了非JSON格式"}
except:
result = {"status": "partial", "result": response[:200], "details": "响应解析异常"}
print(f"✅ [{self.name}] 步骤{step_id}完成,状态: {result.get('status', 'unknown')}")
return result
class OrchestratorAgent(BaseAgent):
"""主协调Agent - 负责管理整个工作流"""
def __init__(self):
system_prompt = """你是智能任务协调员,负责协调多个专家完成复杂任务。
你的工作流程:
1. 接收用户的复杂任务
2. 调用任务分解专家拆解任务
3. 为每个步骤分配合适的执行专家
4. 汇总所有结果并生成最终报告
现在开始协调:"""
super().__init__("主协调员", system_prompt=system_prompt)
# 初始化Subagents
self.decomposer = TaskDecomposerAgent()
# 根据任务类型创建不同的执行专家
self.executors = {
"research": TaskExecutorAgent("研究"),
"calculate": TaskExecutorAgent("计算"),
"write": TaskExecutorAgent("写作"),
"review": TaskExecutorAgent("审查"),
"general": TaskExecutorAgent("综合")
}
def process(self, user_task: str) -> Dict[str, Any]:
print(f"\n🎯 [{self.name}] 接收任务: {user_task}")
print("=" * 50)
# 阶段1: 任务分解
print("📋 阶段1: 任务分解")
steps = self.decomposer.process(user_task)
if not steps:
return {"status": "failed", "error": "任务分解失败"}
# 阶段2: 并行执行各步骤
print(f"\n🚀 阶段2: 执行{len(steps)}个步骤")
results = []
for step in steps:
step_type = step.get("type", "general")
executor = self.executors.get(step_type, self.executors["general"])
# 执行当前步骤
step_result = executor.process(step)
step_result["step_info"] = step
results.append(step_result)
# 添加小延迟,避免请求过快
time.sleep(1)
# 阶段3: 汇总结果
print(f"\n📊 阶段3: 汇总{len(results)}个步骤的结果")
final_result = self._summarize_results(user_task, results)
return final_result
def _summarize_results(self, original_task: str, step_results: List[Dict]) -> Dict[str, Any]:
"""汇总所有步骤的结果"""
prompt = f"""原始任务: {original_task}
已完成的所有步骤结果:
{json.dumps(step_results, indent=2, ensure_ascii=False)}
请基于以上执行结果,生成最终的任务完成报告。
报告应包含:总体完成情况、关键发现、下一步建议。
请用JSON格式输出:
{{"overall_status": "completed|partial|failed", "summary": "总体摘要", "key_findings": ["发现1", "发现2"], "next_steps": ["建议1", "建议2"]}}"""
response = self.query_llm(prompt)
try:
import re
json_match = re.search(r'\{.*\}', response, re.DOTALL)
if json_match:
summary = json.loads(json_match.group())
else:
summary = {"overall_status": "completed", "summary": response[:300]}
except:
summary = {"overall_status": "completed", "summary": "任务执行完成"}
return {
"original_task": original_task,
"step_results": step_results,
"final_summary": summary
}
3. 主程序入口
main.py - 运行演示
python
#!/usr/bin/env python3
"""
基于Ollama phi3:mini的多智能体演示
确保Ollama服务已运行: ollama serve
"""
import sys
from agents import OrchestratorAgent
import json
def check_ollama():
"""检查Ollama服务是否运行"""
import requests
try:
response = requests.get("http://localhost:11434/api/tags", timeout=5)
return response.status_code == 200
except:
return False
def main():
print("=" * 60)
print("🤖 基于Ollama phi3:mini的多智能体演示")
print("=" * 60)
# 检查Ollama服务
print("🔍 检查Ollama服务...")
if not check_ollama():
print("❌ 错误: Ollama服务未运行!")
print("请先启动Ollama服务:")
print(" 1. 打开新终端窗口")
print(" 2. 运行: ollama serve")
print(" 3. 保持终端打开,然后重新运行此程序")
return
print("✅ Ollama服务正常")
# 创建主协调Agent
print("\n🚀 初始化多智能体系统...")
orchestrator = OrchestratorAgent()
# 示例任务列表
sample_tasks = [
"帮我规划一个周末杭州旅行行程,包括景点、美食和预算",
"分析苹果公司2024年第一季度的财务表现和未来展望",
"写一篇关于人工智能在教育领域应用的短文",
"制定一个学习Python编程的3个月计划"
]
print("\n📝 示例任务:")
for i, task in enumerate(sample_tasks, 1):
print(f" {i}. {task[:50]}...")
while True:
print("\n" + "=" * 50)
print("请选择:")
print(" 1-4: 运行示例任务")
print(" 5: 输入自定义任务")
print(" 0: 退出")
choice = input("\n请选择 (0-5): ").strip()
if choice == "0":
print("👋 再见!")
break
elif choice in ["1", "2", "3", "4"]:
task_index = int(choice) - 1
user_task = sample_tasks[task_index]
elif choice == "5":
user_task = input("请输入你的任务: ").strip()
if not user_task:
print("⚠️ 任务不能为空")
continue
else:
print("⚠️ 无效选择")
continue
print(f"\n📨 任务: {user_task}")
print("⏳ 开始处理...")
# 执行任务
final_result = orchestrator.process(user_task)
# 显示结果
print("\n" + "=" * 50)
print("📋 最终报告")
print("=" * 50)
summary = final_result.get("final_summary", {})
print(f"📈 总体状态: {summary.get('overall_status', 'unknown')}")
print(f"📝 摘要: {summary.get('summary', '')[:200]}...")
if 'key_findings' in summary:
print("\n🔑 关键发现:")
for finding in summary['key_findings']:
print(f" • {finding}")
# 保存详细结果到文件
output_file = f"task_result_{int(time.time())}.json"
with open(output_file, 'w', encoding='utf-8') as f:
json.dump(final_result, f, indent=2, ensure_ascii=False)
print(f"\n💾 详细结果已保存到: {output_file}")
if __name__ == "__main__":
import time
main()
4. 创建配置文件
.env (可选,用于未来扩展)
env
OLLAMA_HOST=http://localhost:11434
DEFAULT_MODEL=phi3:mini
MAX_TOKENS=1000
5. 运行演示
bash
# 1. 确保Ollama服务运行(在新终端中)
ollama serve
# 2. 确保phi3:mini模型已下载
ollama list
# 如果没看到phi3:mini,运行: ollama pull phi3:mini
# 3. 在另一个终端中,运行演示程序
cd phi3_agent_demo
python main.py
6. 示例运行输出
当你运行程序并选择任务时,会看到类似输出:
🎯 [主协调员] 接收任务: 帮我规划一个周末杭州旅行行程
📋 阶段1: 任务分解
🔍 [任务分解专家] 正在分析任务...
✅ [任务分解专家] 分解完成,共4个步骤
- 步骤1: 搜索杭州主要景点 (research)
- 步骤2: 计算交通和住宿预算 (calculate)
- 步骤3: 撰写详细行程安排 (write)
- 步骤4: 审查并优化计划 (review)
🚀 阶段2: 执行4个步骤
🛠️ [研究执行专家] 正在执行步骤1...
✅ [研究执行专家] 步骤1完成,状态: success
🛠️ [计算执行专家] 正在执行步骤2...
...
📊 阶段3: 汇总结果
📋 最终报告
总体状态: completed
摘要: 已成功规划杭州周末行程...
🔧 故障排查
-
Ollama连接失败:
bash# 检查Ollama是否运行 curl http://localhost:11434/api/tags # 如果没有响应,重启Ollama pkill ollama ollama serve & -
模型未找到:
bash# 列出已安装模型 ollama list # 如果phi3:mini不存在,下载它 ollama pull phi3:mini -
响应速度慢:
- phi3:mini在CPU上运行可能较慢,这是正常的
- 可以尝试减小
MAX_TOKENS或增加步骤间延迟
🎯 这个例子展示了什么?
- 角色分工:主Agent协调,Subagent专业执行
- 工作流管理:分解→执行→汇总的标准流程
- 上下文隔离:每个Agent有自己的系统提示和专长
- 错误处理:基本的异常处理和降级方案
- 结果整合:最终报告生成和持久化
你可以基于这个框架扩展更多Subagent,添加工具调用(如网络搜索、文件操作),或实现更复杂的协作逻辑。这是理解多智能体系统的绝佳起点!