不用框架,从零构建AI代理
仅使用OpenAI API和Python创建一个聊天机器人代理,能够使用计算器或知识库等工具,不依赖任何框架。这将为你提供关于代理系统工作原理的基础和内部细节。

代理并不复杂!
我们的目标是,仅使用OpenAI API和Python创建一个聊天机器人代理,能够使用计算器或知识库等工具,不依赖任何框架。这将为你提供关于代理系统工作原理的基础和内部细节。

如果你刚刚起步并想了解一些代理的基本知识,可以参考这篇文章 。
1、高层次想法
我们将构建一个AI代理,它可以:
- 接受用户输入
- 决定使用哪个工具(计算器、知识库或无需工具)
- 手动执行该工具(没有自动魔法)
- 返回响应
我们将模拟OpenAI函数调用,但控制工具选择和执行流程。
2、什么是代理,为什么需要它?
一个AI代理是一个系统,它可以:
- 感知输入(例如用户的消息)
- 决定行动方案(例如进行计算、搜索事实)
- 使用工具(例如函数、API)执行任务
- 返回有意义的输出
代理之所以有用,是因为它们可以:
- 使用外部工具
- 维持多轮对话上下文(虽然完整的记忆需要存储对话历史)
- 如果需要扩展,可以轻松添加新功能以实现可扩展性。
3、规划你的代理
在编码之前,我们需要决定以下内容:
- 我们的代理应该使用哪些工具?
- 工具的调用是由LLM还是我们的Python代码控制?
- 代理如何维护状态或记忆?
- 我们是使用OpenAI内置的函数调用,还是自己模拟?
我们将通过结构化提示使用OpenAI的常规ChatCompletion
API来提取工具选择和输入,从而模拟自己的函数调用。
4、关键概念与组件
组件及其作用:
- LLM → 处理和解释查询的语言模型
- 提示 → 告诉LLM如何表现以及我们期望什么
- 工具选择器 → 解析用户输入并决定使用哪个工具
- 工具运行器 → 执行计算器或知识搜索
- 推理循环 → 管理对话、上下文和回复
5、模型层与应用层
层级及其职责:
- 模型层(LLM) → 理解自然语言并路由意图
- 应用程序层(例如:Python代码) → 执行工具、管理流程、发送响应
这种分离允许你轻松地替换工具、提示或模型。

https://www.flyingfish.vc/blog/back-to-basics
6、最小代理架构
用户输入
↓
LLM 工具选择器(决定使用哪个工具及输入)
↓
Python 工具执行器(运行计算器或知识搜索)
↓
最终响应
7、实现步骤
7.1 工具定义
import openai
import os
openai.api_key = os.getenv("OPENAI_API_KEY")
import re
def calculate_expression(expression):
safe_expr = re.sub(r'[^0-9+\-\*/(). ]', '', expression)
if safe_expr.strip() == "":
return None
try:
return eval(safe_expr)
except:
return None
knowledge_base = {
"python": "Python is a programming language known for its readability.",
"openai": "OpenAI is the company that created ChatGPT.",
"ai": "AI stands for Artificial Intelligence, which simulates human intelligence."
}
# 我们只是模拟了知识检索,在真实世界中,这将是你的知识检索器
def search_knowledge(query):
q = query.lower()
for keyword, value in knowledge_base.items():
if keyword in q:
return value
return None
7.2 模拟函数调用(LLM作为工具路由器)
我们不使用OpenAI内置的函数调用,而是要求LLM:
- 决定使用哪个工具:
calculator
、knowledge_search
或none
- 返回我们自行解析的JSON样式的结构
代理如何知道使用知识库?
代理在以下情况下使用知识库:
- 用户提出事实性或信息性问题
- 我们的系统提示告诉它:“如果问题是事实性的,请选择
knowledge_search
。” - LLM理解类似以下查询的语义:
- “Python是什么?”
- “谁是OpenAI?”
- “告诉我关于AI。”
它会响应如下:
{ "tool": "knowledge_search", "input": "What is Python?" }
如果它找不到匹配项(例如,“法国的首都是什么?”),LLM可能会回复"tool": "none"
,然后我们回退到常规聊天响应。
def query_openai_tool_selector(user_input):
messages = [
{
"role": "system",
"content": (
"You're an AI assistant. Based on the user's message, "
"decide which tool to use: 'calculator', 'knowledge_search', or 'none'. "
"Respond ONLY with a JSON object like this:\n"
"{ \"tool\": \"calculator\", \"input\": \"5 * (4 + 3)\" }\n"
"or\n"
"{ \"tool\": \"none\", \"input\": \"Hello!\" }"
)
},
{"role": "user", "content": user_input}
]
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=messages
)
try:
tool_call = eval(response.choices[0].message['content'])
return tool_call.get("tool"), tool_call.get("input")
except:
return "none", user_input
7.3 工具执行与响应处理
def query_openai(user_input):
tool, tool_input = query_openai_tool_selector(user_input)
if tool == "calculator":
result = calculate_expression(tool_input)
return f"The result is: {result}" if result else "I couldn't compute that."
elif tool == "knowledge_search":
result = search_knowledge(tool_input)
return result if result else "I couldn't find relevant information."
else:
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": user_input}
]
)
return response.choices[0].message['content']
7.4 如何运转
用户: "7 * (2 + 3)是多少?"
↓
LLM(工具选择器): { "tool": "calculator", "input": "7 * (2 + 3)" }
↓
Python 工具: calculate_expression("7 * (2 + 3)") → 35
↓
最终回复: "结果是: 35"
8、完整最终代理代码
import openai, re, os
openai.api_key = os.getenv("OPENAI_API_KEY")
def calculate_expression(expression):
safe_expr = re.sub(r'[^0-9+\-\*/(). ]', '', expression)
if safe_expr.strip() == "":
return None
try:
return eval(safe_expr)
except:
return None
knowledge_base = {
"python": "Python is a programming language known for its readability.",
"openai": "OpenAI is the company that created ChatGPT.",
"ai": "AI stands for Artificial Intelligence, which simulates human intelligence."
}
# 这只是模拟的知识检索
def search_knowledge(query):
q = query.lower()
for keyword, value in knowledge_base.items():
if keyword in q:
return value
return None
def query_openai_tool_selector(user_input):
messages = [
{
"role": "system",
"content": (
"You're an AI assistant. Based on the user's message, "
"decide which tool to use: 'calculator', 'knowledge_search', or 'none'. "
"Respond ONLY with a JSON object like this:\n"
"{ \"tool\": \"calculator\", \"input\": \"5 * (4 + 3)\" }\n"
"or\n"
"{ \"tool\": \"none\", \"input\": \"Hello!\" }"
)
},
{"role": "user", "content": user_input}
]
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=messages
)
try:
tool_call = eval(response.choices[0].message['content'])
return tool_call.get("tool"), tool_call.get("input")
except:
return "none", user_input
def query_openai(user_input):
tool, tool_input = query_openai_tool_selector(user_input)
if tool == "calculator":
result = calculate_expression(tool_input)
return f"The result is: {result}" if result else "I couldn't compute that."
elif tool == "knowledge_search":
result = search_knowledge(tool_input)
return result if result else "I couldn't find relevant information."
else:
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": user_input}
]
)
return response.choices[0].message['content']
``````markdown
t = query_openai_tool_selector(user_input)
if tool == "calculator":
result = calculate_expression(tool_input)
return f"结果是: {result}" if result else "我无法计算那个。"
elif tool == "knowledge_search":
result = search_knowledge(tool_input)
return result if result else "我找不到相关的信息。"
else:
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "你是一个有用的助手。"},
{"role": "user", "content": user_input}
]
)
return response.choices[0].message['content']
print("欢迎!问我任何问题。输入'quit'退出。")
while True:
user_input = input("你: ")
if user_input.lower() == "quit":
print("助手: 再见!")
break
print("助手:", query_openai(user_input))
9、结束语
你现在有了一个功能齐全的AI代理,它:
- 理解用户输入
- 使用LLM输出智能地选择工具
- 手动执行函数而不依赖OpenAI的内置工具调用
- 保持逻辑清晰和控制
你可以在此基础上进行哪些改进:
- 添加更多工具(天气、提醒、文件处理等)
- 添加更多推理和规划能力
- 添加上下文记忆(例如,
memory = []
) - 构建Web界面(Streamlit、Flask、React)
- 将其连接到你的业务逻辑和API
原文链接:Building AI Agents from Scratch -No Frameworks
汇智网翻译整理,转载请标明出处
