Agent是什么?
很多书把Agent这个概念写得很抽象:感知、决策、执行......一串术语下来,让人摸不着头脑。
其实,从实操层面,Agent可以简单理解为:
Agent=自主决策的循环+可调用的工具+本地知识库或数据库+边界
其中,本地知识库或数据库并不是所有Agent的必须项,但在很多业务场景中,它能让Agent的回答更精准、更贴合个人或企业需求。
自主决策的循环,是指拥有大模型的循环语句,比如:
def run_agent(task: str, max_steps: int = 5):
messages = [{"role": "user", "content": task}]
for step in range(max_steps):
# 1. 让模型决定下一步:直接回答,还是调用工具
response = call_llm(messages)
# 2. 如果模型要调用工具
if response.tool_call:
tool_name = response.tool_call.name
args = response.tool_call.args
result = TOOLS[tool_name](**args) # 执行工具
messages.append(response.message) # 记录模型决策
messages.append({"role": "tool", "content": result}) # 回传结果
else:
# 3. 模型给出最终答案,结束
return response.content
return "达到最大步数,未完成"
在上面循环代码中,call_llm就是在调用大模型。
工具可以是系统自带的,比如计算器,也可以是自己写的程序。
Agent的设计大部分时候是为了实现业务需求,或者贴合我们的个人需求,简化日常操作,比如收集信息、发送邮件、查找信息等。这就需要我们个人的知识库或者本地数据库,通过RAG来获取更精准的回复。
大模型本身是有局限性的。
它本质上做的是概率生成,擅长语义逻辑和连贯表达,但并不保证事实准确性和计算精确性。
面对复杂的计算或者不了解的事实,它可能会编造内容,也就是出现AI幻觉。
因此,Agent的设计需要设置边界条件,比如邮件它写好了不能直接发出去,需要人工复核。
可以这样理解:
- 大模型赋予了循环一个大脑,拥有大模型的循环可以理解为能决策的大脑。
- 工具是手,通过工具,大脑能和现实世界产生交互。
- 本地数据库/知识库就像是外部记忆或私有经验,让智能体的言行更符合现实期望。
- 安全边界就像是行为准则,明确哪些行为不能越界,哪些操作必须人工确认。
这四者使得我们可以使用自然语言给程序下指令,就能获得我们期望的结果,这就是智能体Agent。
是不是所有加了AI的程序都可以称为Agent?
不是。
必须是控制流由LLM自主决定的,才能称为Agent。
像有输入、输出,也内置了AI,但是流程固定,只能称为工具,或者AI工作流。
┌──────────────────────────────────────────────┐
│ AI 工作流:流程固定 │
├──────────────────────────────────────────────┤
│ │
│ 用户输入 │
│ │ │
│ ▼ │
│ 步骤 1:调用 LLM(摘要/分类/抽取) │
│ │ │
│ ▼ │
│ 步骤 2:调用工具/API │
│ │ │
│ ▼ │
│ 步骤 3:固定后处理 │
│ │ │
│ ▼ │
│ 输出结果 │
│ │
│ 控制流:开发者写死 │
│ LLM 角色:只参与其中某一步 │
│ │
└──────────────────────────────────────────────┘
┌──────────────────────────────────────────────┐
│ Agent:控制流由 LLM 决定 │
├──────────────────────────────────────────────┤
│ │
│ 用户输入 │
│ │ │
│ ▼ │
│ ┌──────────────────────────────┐ │
│ │ LLM 决策循环 │ │
│ │ │ │
│ │ LLM 判断下一步: │ │
│ │ ├─ 直接回答 ──► 输出答案 │ │
│ │ └─ 调用工具 ──► 执行工具 │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ 工具结果回传 │ │
│ │ │ │ │
│ │ └────────┘ │
│ └──────────────────────────────┘ │
│ │
│ 工具集:搜索/数据库/计算/发邮件 │
│ 知识库:本地数据库 / RAG │
│ 边界:只读、人工复核、白名单 │
│ │
└──────────────────────────────────────────────┘
使用Openmanus构建一个最小化Agent
Openmanus是一个Agent开发框架,它内置了很多工具和模型调用命令,使得Agent开发更加简单易行。
以获取我本地的个人支出数据,最终回答"2024年度的总支出"为例。
1. 系统与版本要求
操作系统:Windows
Python:必须3.12(Openmanus要求>=3.12)
包管理:推荐uv(更快,自带python版本管理)
2. 创建虚拟环境(Python 3.12)
# 用 uv 创建 3.12 环境(uv 会自动准备 3.12,无需手动安装)
uv venv --python 3.12
# 激活(Windows Git Bash)
source .venv/Scripts/activate
# 确认版本
python --version # 应为 Python 3.12.x
3. 获取Openmanus开源代码、安装依赖
git clone https://github.com/FoundationAgents/OpenManus.git
cd OpenManus
uv pip install -r requirements.txt
4. 配置 LLM
4.1 复制配置模板
cp config/config.example.toml config/config.toml
4.2 填写LLM段
以deepseek为例,
[llm]
model = "deepseek-chat" # 必须支持 function calling
base_url = "https://api.deepseek.com"
api_key = "sk-你的密钥"
max_tokens = 8192
temperature = 0.0
5. 启动验证
python main.py
成功标志:出现 Enter your prompt:
输入:帮我计算3*7+5
提示:✨ Manus's thoughts: I'll calculate that for you.
🧰 Tools being prepared: 'python_execute'
🔧 Tool arguments: {"code": "print(3*7+5)"}
🎯 Tool 'python_execute' completed its mission! Result: 26
说明框架、LLM、工具调用链路全部跑通。
6. 接入本地PostgreSQL
6.1 编写数据库工具
新建app/tool/query_expense.py:
from app.tool.base import BaseTool, ToolResult
import psycopg2
import os
class QueryExpense(BaseTool):
"""查询本地 PostgreSQL 支出数据库的工具。"""
name: str = "query_expense"
description: str = (
"查询本地 PostgreSQL 数据库中的支出记录。"
"输入一条 SQL SELECT 语句,返回查询结果。"
"可用表(均在 public schema):"
"ods_records_1(date, type, category, amount) ------ 2024 年数据;"
"ods_records_2(date, type, category, amount) ------ 2023 年数据;"
"records2(date, type, category, amount) ------ 2023 年数据(副本)。"
"其中 amount 为金额,category 为分类,type 为类型,date 为日期(DATE 类型)。"
"仅接受 SELECT 查询。"
)
parameters: dict = {
"type": "object",
"properties": {
"sql": {"type": "string", "description": "要执行的 SELECT 查询语句"}
},
"required": ["sql"],
}
async def execute(self, sql: str) -> ToolResult:
if not sql.strip().upper().startswith("SELECT"):
return ToolResult(error="仅允许执行 SELECT 查询")
conn = None
try:
conn = psycopg2.connect(
dbname=os.getenv("PG_DBNAME"),
user=os.getenv("PG_USER"),
password=os.getenv("PG_PASSWORD"),
host=os.getenv("PG_HOST", "localhost"),
port=os.getenv("PG_PORT", "5432"),
client_encoding=os.getenv("PG_CLIENT_ENCODING", "UTF8"),
)
cur = conn.cursor()
cur.execute(sql)
rows = cur.fetchall()
columns = [desc[0] for desc in cur.description] if cur.description else []
if not rows:
return ToolResult(output="查询结果为空")
output_lines = [" | ".join(columns)]
output_lines.append("-" * 40)
for row in rows:
output_lines.append(" | ".join(str(v) for v in row))
return ToolResult(output="\n".join(output_lines))
except psycopg2.Error as e:
return ToolResult(error=f"数据库错误:{e}")
except Exception as e:
return ToolResult(error=f"执行失败:{e}")
finally:
if conn:
conn.close()
6.2 注册工具
app/tool/__init__.py 末尾加:
from app.tool.query_expense import QueryExpense
app/agent/manus.py 里,找到 ToolCollection(...),加入:
from app.tool.query_expense import QueryExpense
self.available_tools = ToolCollection(
...,
QueryExpense(), # 加这行
)
6.3 安装驱动
uv pip install psycopg2-binary
6.4 配置数据库连接
export PG_DBNAME="你的库名"
export PG_USER="postgres"
export PG_PASSWORD="你的真实密码"
export PG_HOST="localhost"
export PG_PORT="5432"
7. 最终结果
Enter your prompt: 查一下 2024 年支出
Agent自动生成SQL并执行返回了我想要的结果。
在这个数据查询的例子中,有拥有大模型的循环、工具调用、数据库接入就是一个比较完整的、最小化可行的智能体。