设计一个通用的Python框架,使大模型API能够自动思考问题、调用工具、反思迭代,并最终输出满足用户需求的结果。
框架设计思路
这个框架需要实现以下核心功能:
问题分析:理解用户输入的问题步骤规划:将问题分解为可执行的步骤工具调用:根据需要调用适当的工具反思评估:评估当前进展是否满足用户需求迭代优化:如果不满足需求,继续思考下一步
框架实现代码
下面是一个完整的Python框架实现:
import os
import json
import time
import requests
from typing import Dict, List, Any, Optional, Union, Callable
class Tool:
"""工具基类,所有工具都应继承此类"""
def __init__(self, name: str, description: str):
self.name = name
self.description = description
def execute(self, **kwargs) -> Dict[str, Any]:
"""执行工具功能,需要在子类中实现"""
raise NotImplementedError("Tool子类必须实现execute方法")
def to_dict(self) -> Dict[str, Any]:
"""返回工具的描述信息,用于API调用"""
return {
"name": self.name,
"description": self.description
}
class SearchTool(Tool):
"""搜索工具,用于获取互联网信息"""
def __init__(self, api_key: str = None):
super().__init__(
name="search",
description="搜索互联网获取信息,参数:query (搜索查询字符串)"
)
self.api_key = api_key
def execute(self, query: str) -> Dict[str, Any]:
"""执行搜索操作"""
print(f"正在搜索: {query}")
# 这里应该是实际的搜索API调用
# 为了演示,返回模拟数据
return {
"status": "success",
"results": [
{
"title": f"搜索结果 - {query}",
"content": f"这是关于 {query} 的搜索结果示例。在实际应用中,这里应该返回真实的搜索结果。"
}
]
}
class CodeRunnerTool(Tool):
"""代码运行工具,用于执行Python代码"""
def __init__(self):
super().__init__(
name="run_code",
description="运行Python代码,参数:code (要执行的Python代码字符串)"
)
def execute(self, code: str) -> Dict[str, Any]:
"""执行Python代码"""
print("正在运行代码...")
try:
# 创建一个安全的本地环境来执行代码
local_vars = {}
# 注意:在实际应用中,应该使用更安全的沙箱环境
exec(code, {}, local_vars)
return {
"status": "success",
"result": str(local_vars.get('result', '代码执行成功,但没有返回值'))
}
except Exception as e:
return {
"status": "error",
"error": str(e)
}
class PDFGeneratorTool(Tool):
"""PDF生成工具,用于创建PDF报告"""
def __init__(self, output_dir: str = "output"):
super().__init__(
name="generate_pdf",
description="生成PDF报告,参数:content (报告内容), title (报告标题), charts (可选,图表文件路径列表)"
)
self.output_dir = output_dir
if not os.path.exists(output_dir):
os.makedirs(output_dir)
def execute(self, content: str, title: str = "自动生成报告", charts: List[str] = None) -> Dict[str, Any]:
"""生成PDF报告"""
print("正在生成PDF报告...")
# 这里应该是实际的PDF生成代码
# 为了演示,只返回成功信息
filename = f"report_{int(time.time())}.pdf"
filepath = os.path.join(self.output_dir, filename)
# 模拟PDF生成
with open(filepath, 'w') as f:
f.write(f"标题: {title}\n\n")
f.write(content)
if charts:
f.write("\n\n图表列表:\n")
for chart in charts:
f.write(f"- {chart}\n")
return {
"status": "success",
"filename": filename,
"filepath": filepath
}
class AutoAgent:
"""自动代理类,负责协调大模型API和工具调用"""
def __init__(self, api_key: str, model: str = "gpt-4", max_iterations: int = 10):
self.api_key = api_key
self.model = model
self.max_iterations = max_iterations
self.conversation_history = []
self.tools = {}
self.tool_descriptions = []
def register_tool(self, tool: Tool) -> None:
"""注册工具"""
self.tools[tool.name] = tool
self.tool_descriptions.append(tool.to_dict())
def add_message(self, role: str, content: Union[str, Dict[str, Any]]) -> None:
"""添加消息到对话历史"""
self.conversation_history.append({"role": role, "content": content})
def call_llm_api(self, messages: List[Dict[str, Any]], functions: List[Dict[str, Any]] = None) -> Dict[str, Any]:
"""调用大模型API"""
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {self.api_key}"
}
payload = {
"model": self.model,
"messages": messages,
"temperature": 0.7
}
if functions:
payload["functions"] = functions
payload["function_call"] = "auto"
try:
response = requests.post(
"https://api.openai.com/v1/chat/completions",
headers=headers,
json=payload
)
return response.json()
except Exception as e:
print(f"API调用错误: {e}")
return None
def execute_tool(self, tool_name: str, params: Dict[str, Any]) -> Dict[str, Any]:
"""执行指定的工具"""
if tool_name in self.tools:
return self.tools[tool_name].execute(**params)
else:
return {"status": "error", "error": f"未知工具: {tool_name}"}
def solve_problem(self, problem: str) -> Dict[str, Any]:
"""解决问题的主要流程"""
print(f"开始解决问题: {problem}")
# 初始化对话
self.conversation_history = []
# 设置系统提示
self.add_message("system", """
你是一个自动解决问题的AI助手。你需要:
1. 分析问题并制定解决方案
2. 使用提供的工具收集信息和处理数据
3. 反思你的进展并迭代改进
4. 最终生成一个完整的解决方案
在每一步,你都应该:
- 思考:分析当前状态和下一步行动
- 行动:调用适当的工具
- 观察:分析工具返回的结果
- 反思:评估进展并调整计划
请一步一步地解决问题,并在每一步清晰地解释你的思考过程。
""")
# 添加用户问题
self.add_message("user", problem)
# 准备工具函数描述
functions = []
for tool in self.tools.values():
tool_dict = {
"name": tool.name,
"description": tool.description,
"parameters": {
"type": "object",
"properties": {}
}
}
# 根据工具名称添加参数
if tool.name == "search":
tool_dict["parameters"]["properties"]["query"] = {
"type": "string",
"description": "搜索查询"
}
tool_dict["parameters"]["required"] = ["query"]
elif tool.name == "run_code":
tool_dict["parameters"]["properties"]["code"] = {
"type": "string",
"description": "要执行的Python代码"
}
tool_dict["parameters"]["required"] = ["code"]
elif tool.name == "generate_pdf":
tool_dict["parameters"]["properties"] = {
"content": {
"type": "string",
"description": "PDF内容"
},
"title": {
"type": "string",
"description": "报告标题"
},
"charts": {
"type": "array",
"items": {
"type": "string"
},
"description": "图表文件路径列表"
}
}
tool_dict["parameters"]["required"] = ["content"]
functions.append(tool_dict)
# 迭代解决问题
final_result = None
for iteration in range(self.max_iterations):
print(f"\n--- 迭代 {iteration + 1} ---")
# 调用LLM获取下一步行动
response = self.call_llm_api(self.conversation_history, functions)
if not response or "choices" not in response:
print("API返回错误,终止迭代")
break
message = response["choices"][0]["message"]
# 检查是否调用工具
if "function_call" in message:
function_call = message["function_call"]
tool_name = function_call["name"]
tool_params = json.loads(function_call["arguments"])
print(f"调用工具: {tool_name}")
self.add_message("assistant", message)
# 执行工具调用
tool_result = self.execute_tool(tool_name, tool_params)
# 添加工具结果到对话
self.add_message("function", {
"name": tool_name,
"content": json.dumps(tool_result)
})
# 如果是生成PDF的工具调用,可能是最终步骤
if tool_name == "generate_pdf" and tool_result["status"] == "success":
print(f"已生成PDF报告: {tool_result['filename']}")
final_result = tool_result
# 获取最终总结
self.add_message("user", "请总结你完成的工作和生成的报告内容。")
final_response = self.call_llm_api(self.conversation_history)
if final_response and "choices" in final_response:
final_message = final_response["choices"][0]["message"]["content"]
print("\n最终总结:")
print(final_message)
# 检查是否满足用户需求
self.add_message("user", "你认为当前的解决方案是否满足了用户的需求?如果是,请说明理由;如果不是,请说明还需要做什么。")
eval_response = self.call_llm_api(self.conversation_history)
if eval_response and "choices" in eval_response:
eval_message = eval_response["choices"][0]["message"]["content"]
print("\n需求满足评估:")
print(eval_message)
# 简单判断是否满足需求
if "满足" in eval_message and "不" not in eval_message[:eval_message.find("满足")]:
print("✅ 解决方案已满足用户需求,终止迭代")
break
else:
print("❌ 解决方案尚未满足用户需求,继续迭代")
self.add_message("assistant", eval_response["choices"][0]["message"])
self.add_message("user", "请继续完善解决方案,直到满足用户需求。")
else:
# 模型返回了文本回复而不是工具调用
content = message["content"]
print(f"AI思考: {content[:100]}...")
self.add_message("assistant", message)
# 提示模型继续解决问题
self.add_message("user", "请继续解决问题,必要时调用适当的工具。")
if iteration >= self.max_iterations - 1:
print("达到最大迭代次数,终止")
return final_result
def create_auto_agent(api_key: str) -> AutoAgent:
"""创建并配置自动代理"""
agent = AutoAgent(api_key)
# 注册工具
agent.register_tool(SearchTool())
agent.register_tool(CodeRunnerTool())
agent.register_tool(PDFGeneratorTool())
return agent
# 使用示例
if __name__ == "__main__":
# 替换为你的API密钥
api_key = "your_openai_api_key"
# 创建自动代理
agent = create_auto_agent(api_key)
# 定义问题
problem = """
我需要收集价格在1500-2000元范围内的最新手机品牌和参数数据,并形成一个可视化的报告。
报告应包含:
1. 这个价格区间的主要手机品牌和型号
2. 各品牌手机的主要参数对比(如处理器、内存、电池容量、屏幕等)
3. 性价比分析
4. 数据可视化图表
"""
# 解决问题
result = agent.solve_problem(problem)
if result:
print(f"\n问题已解决,最终报告: {result['filepath']}")
else:
print("\n未能完全解决问题") 框架扩展:添加更多工具
您可以轻松扩展这个框架,添加更多自定义工具:
from auto_agent_framework import Tool
import matplotlib.pyplot as plt
import pandas as pd
import requests
from bs4 import BeautifulSoup
class WebScraperTool(Tool):
"""网页抓取工具,用于从网页获取数据"""
def __init__(self):
super().__init__(
name="web_scraper",
description="从指定URL抓取网页内容,参数:url (网页地址)"
)
def execute(self, url: str) -> Dict[str, Any]:
"""抓取网页内容"""
print(f"正在抓取网页: {url}")
try:
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
}
response = requests.get(url, headers=headers)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'html.parser')
# 提取页面标题和正文内容
title = soup.title.string if soup.title else "无标题"
# 提取正文段落
paragraphs = [p.text for p in soup.find_all('p')]
content = "\n".join(paragraphs)
return {
"status": "success",
"title": title,
"content": content[:1000] + "..." if len(content) > 1000 else content
}
except Exception as e:
return {
"status": "error",
"error": str(e)
}
class DataVisualizationTool(Tool):
"""数据可视化工具,用于创建图表"""
def __init__(self, output_dir: str = "charts"):
super().__init__(
name="visualize_data",
description="创建数据可视化图表,参数:data (数据字典或JSON字符串), chart_type (图表类型: bar, line, pie, scatter), title (图表标题)"
)
self.output_dir = output_dir
if not os.path.exists(output_dir):
os.makedirs(output_dir)
def execute(self, data: Union[Dict, str], chart_type: str, title: str) -> Dict[str, Any]:
"""创建数据可视化图表"""
print(f"正在创建{chart_type}图表: {title}")
try:
# 如果数据是字符串,尝试解析为JSON
if isinstance(data, str):
data = json.loads(data)
# 创建DataFrame
df = pd.DataFrame(data)
# 创建图表
plt.figure(figsize=(10, 6))
if chart_type == "bar":
df.plot(kind='bar')
elif chart_type == "line":
df.plot(kind='line')
elif chart_type == "pie":
df.plot(kind='pie', y=df.columns[1], autopct='%1.1f%%')
elif chart_type == "scatter":
df.plot(kind='scatter', x=df.columns[0], y=df.columns[1])
else:
return {
"status": "error",
"error": f"不支持的图表类型: {chart_type}"
}
plt.title(title)
plt.tight_layout()
# 保存图表
filename = f"{chart_type}_{int(time.time())}.png"
filepath = os.path.join(self.output_dir, filename)
plt.savefig(filepath)
plt.close()
return {
"status": "success",
"chart_type": chart_type,
"title": title,
"filepath": filepath
}
except Exception as e:
return {
"status": "error",
"error": str(e)
} 使用示例
下面是一个完整的使用示例,展示如何使用这个框架解决您提到的手机数据收集和报告生成问题:
from auto_agent_framework import create_auto_agent
from additional_tools import WebScraperTool, DataVisualizationTool
# 替换为你的API密钥
api_key = "your_openai_api_key"
# 创建自动代理
agent = create_auto_agent(api_key)
# 注册额外的工具
agent.register_tool(WebScraperTool())
agent.register_tool(DataVisualizationTool())
# 定义问题
problem = """
我需要收集价格在1500-2000元范围内的最新手机品牌和参数数据,并形成一个可视化的报告。
报告应包含:
1. 这个价格区间的主要手机品牌和型号
2. 各品牌手机的主要参数对比(如处理器、内存、电池容量、屏幕等)
3. 性价比分析
4. 数据可视化图表
"""
# 解决问题
result = agent.solve_problem(problem)
if result:
print(f"\n问题已解决,最终报告: {result['filepath']}")
# 可以自动打开生成的PDF
import os
os.system(f"start {result['filepath']}") # Windows系统
# 对于Mac: os.system(f"open {result['filepath']}")
# 对于Linux: os.system(f"xdg-open {result['filepath']}")
else:
print("\n未能完全解决问题") 框架核心组件解析1. 工具抽象层
- Tool 基类定义了所有工具的通用接口
- 每个具体工具(如 SearchTool 、 CodeRunnerTool )实现特定功能- 工具注册机制允许动态添加新工具
2. 对话管理
- 维护与大模型的对话历史
- 支持多轮交互和上下文理解
3. 迭代反思机制
- 每次工具调用后评估进展
- 通过提问"是否满足用户需求"进行自我评估
- 根据评估结果决定是否继续迭代
4. 工具调用流程
- 大模型决定调用哪个工具
- 框架执行工具并返回结果
- 结果被添加到对话历史中供下一轮决策使用
扩展建议
1. 增强安全性- 为代码执行工具添加沙箱环境
- 实现更严格的参数验证
- 添加用户权限控制
2. 提高效率
- 实现并行工具调用
- 添加缓存机制减少重复API调用
- 优化对话历史管理,减少token消耗
3. 增强评估能力
- 添加更细致的评估标准
- 实现基于用户反馈的学习机制
- 支持多维度评估(准确性、完整性、效率等)
4. 用户交互
- 添加中间结果展示
- 支持用户干预和引导
- 实现进度报告和估计完成时间
总结
这个框架实现了一个完整的自动思考、工具调用和反思迭代的系统,可以用于解决各种复杂问题。它的核心优势在于:
1. 模块化设计 :易于扩展和定制
2. 自主决策 :大模型自主决定下一步行动
3. 反思迭代 :通过自我评估不断改进解决方案
4. 工具灵活性 :可以根据需要添加各种工具
通过这个框架,您可以让大模型API自动解决各种复杂问题,从数据收集、分析到报告生成,全程自动化完成。网友回复


