《本地Llama Agent开发:让大模型学会调用工具》
LlamaAI本地部署实战专栏第8篇
前面我们已经完成了本地LLM、CUDA加速、API服务以及Hybrid RAG。
现在进入一个更重要的阶段:
让大模型从“会回答问题”升级到“能够执行任务”。
一、从Chatbot到Agent
到目前为止,我们的系统已经可以:
用户
↓
本地Llama
↓
RAG检索
↓
知识库
↓
生成答案
例如:
RTX 4060运行7B模型需要多少显存?
Llama可以根据知识库回答。
但是如果用户说:
帮我查看一下当前项目目录有哪些文件。
普通LLM只能告诉你:
我无法直接访问你的电脑。
为什么?
因为:
LLM本身只是一个模型,它不会自动获得操作系统权限。
二、Agent到底是什么?
AI Agent可以简单理解为:
LLM + Tools + Decision Loop
也就是:
大语言模型
+
工具
+
执行循环
传统Chatbot:
用户
↓
LLM
↓
答案
Agent:
用户
↓
LLM
↓
判断任务
↓
选择工具
↓
执行工具
↓
获得结果
↓
再次交给LLM
↓
继续执行
↓
最终答案
因此:
Chatbot负责“回答”。
而:
Agent负责“完成任务”。
三、一个最简单的Agent例子
用户:
帮我计算 123 × 456。
普通LLM:
123 × 456 = 56088
Agent:
用户
↓
LLM
↓
发现需要计算
↓
调用Calculator工具
↓
得到56088
↓
LLM
↓
返回答案
区别就在于:
LLM
↓
Tool
四、Agent的核心组成
一个完整Agent通常包含:
┌────────────────────┐
│ User │
└─────────┬──────────┘
↓
┌────────────────────┐
│ LLM │
└─────────┬──────────┘
↓
Tool Selection
↓
┌────────────────────┐
│ Tools │
│ │
│ 文件读取 │
│ 搜索 │
│ Python │
│ 数据库 │
│ API │
└─────────┬──────────┘
↓
Tool Result
↓
LLM
↓
Final Answer
其中最重要的是:
Tool Calling。
五、什么是Tool Calling?
Tool Calling可以理解成:
LLM告诉程序:“我需要调用哪个工具,以及参数是什么。”
例如我们定义:
def calculator(a, b):
return a + b
告诉LLM:
工具名称:
calculator
参数:
a
b
用户:
计算12+30。
LLM可能返回:
{
"tool": "calculator",
"arguments": {
"a": 12,
"b": 30
}
}
程序看到以后:
calculator(12, 30)
得到:
42
然后把:
42
重新交给LLM。
最终:
答案是42。
六、Agent并不是“模型自己执行程序”
这里一定要理解一个概念。
LLM不能直接:
删除文件
执行Shell
读取数据库
真正执行操作的是:
你的程序
所以实际关系:
LLM
│
│ Tool Call
↓
Agent Runtime
│
↓
Tool
│
↓
操作系统
LLM只是:
决策者。
Python/C++程序才是:
执行者。
七、先实现一个Calculator Agent
为了理解Agent,我们先不用复杂框架。
直接Python实现。
定义工具:
def calculator(a, b, operation):
if operation == "add":
return a + b
if operation == "sub":
return a - b
if operation == "mul":
return a * b
if operation == "div":
return a / b
return "unknown operation"
工具描述:
calculator_tool = {
"name": "calculator",
"description": "执行基础数学计算",
"parameters": {
"a": "number",
"b": "number",
"operation": "string"
}
}
八、Agent工作循环
核心逻辑其实非常简单:
while True:
response = llm(messages)
if response需要调用工具:
tool_result = execute_tool(
response
)
messages.append(
tool_result
)
else:
return response
这就是Agent最核心的:
循环(Loop)。
九、Agent为什么需要循环?
假设用户:
帮我读取项目README,然后总结项目用了哪些技术。
Agent可能执行:
第1轮:
LLM
↓
调用read_file
↓
README.md
得到:
README内容
然后:
第2轮:
README
↓
LLM
↓
分析内容
最终:
项目使用:
Python
FastAPI
FAISS
llama.cpp
如果没有循环:
LLM
↓
只能执行一次
复杂任务就无法完成。
十、让Agent读取本地文件
我们定义:
def read_file(path):
with open(
path,
"r",
encoding="utf-8"
) as f:
return f.read()
现在Agent拥有:
read_file()
工具。
用户:
读取README.md并告诉我项目使用什么技术。
Agent:
用户
↓
LLM
↓
read_file("README.md")
↓
获得文件内容
↓
LLM分析
↓
答案
十一、再增加一个目录工具
定义:
import os
def list_files(path):
return os.listdir(path)
现在Agent拥有:
Tools:
list_files
read_file
calculator
用户:
找一下项目里有哪些Python文件。
Agent:
list_files()
↓
获得文件列表
↓
找到.py文件
↓
回答
十二、Agent + RAG
现在开始把前面两篇连接起来。
之前:
用户
↓
RAG
↓
知识库
↓
Llama
现在:
用户
↓
Agent
↓
判断是否需要知识
↓
RAG Tool
↓
FAISS + BM25
↓
返回资料
↓
Llama
于是:
RAG不再只是固定流程,而可以成为Agent的一个工具。
例如:
用户:
根据公司的技术文档,告诉我GPU部署要求。
Agent:
LLM
↓
需要查知识库
↓
调用search_knowledge
↓
BM25 + FAISS
↓
Reranker
↓
返回相关文档
↓
LLM
↓
答案
十三、最终Agent架构
现在系统开始变得有意思了:
用户
↓
Agent
↓
LLM
↓
┌─────────┼─────────┐
↓ ↓ ↓
RAG 文件 Calculator
↓ ↓ ↓
FAISS File IO Python
↓ ↓ ↓
└─────────┼─────────┘
↓
LLM
↓
答案
这就是:
Tool-augmented LLM。
十四、如何让本地Llama调用工具?
前面我们已经在第5篇中启动了:
llama-server
现在:
Python Agent
↓
OpenAI-compatible API
↓
llama-server
↓
本地Llama
Python:
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:8080/v1",
api_key="none"
)
然后给模型传递工具定义。
概念上:
tools = [
{
"type": "function",
"function": {
"name": "calculator",
"description": "执行数学计算",
"parameters": {
"type": "object",
"properties": {
"a": {
"type": "number"
},
"b": {
"type": "number"
}
}
}
}
}
]
然后:
response = client.chat.completions.create(
model="local-model",
messages=messages,
tools=tools
)
模型如果决定调用工具,就会返回对应的Tool Call。
十五、Agent Runtime到底做什么?
这是工程实现中非常重要的一层。
不要把所有东西:
LLM
+
Tool
+
业务逻辑
全部写在一起。
推荐架构:
agent/
│
├── agent.py
│
├── runtime.py
│
└── tools/
│
├── calculator.py
├── file.py
├── rag.py
└── search.py
agent.py
负责:
决策。
runtime.py
负责:
执行Tool Call。
tools/
负责:
具体功能。
这样以后增加工具:
weather.py
database.py
email.py
browser.py
不会影响Agent核心逻辑。
十六、Agent最重要的安全问题
这里必须特别注意:
不要让本地LLM拥有无限系统权限。
例如千万不要直接:
os.system(
llm_generated_command
)
因为模型可能生成:
rm -rf /
或者其他危险命令。
十七、正确的Tool设计原则
不要给:
execute_any_command()
这种无限权限工具。
应该设计成:
read_file()
list_files()
search_document()
calculate()
限制:
允许访问目录:
/home/user/project/
而不是:
整个磁盘
这叫:
Least Privilege(最小权限原则)
十八、Agent执行流程完整示例
用户:
帮我看看项目里有没有README,如果有就总结一下。
第一步:
User
↓
LLM
第二步:
LLM决定:
需要查看文件
第三步:
list_files()
得到:
main.py
README.md
requirements.txt
第四步:
read_file("README.md")
第五步:
得到:
README内容
第六步:
README
↓
LLM
第七步:
总结项目
最终:
项目主要使用:
Python
FAISS
llama.cpp
FastAPI
十九、Agent + RAG + llama.cpp
现在把整个专栏前面的内容全部串起来。
用户
↓
Agent
↓
本地Llama
↓
┌────────────┼────────────┐
↓ ↓ ↓
RAG Tool File Tool Calc Tool
↓ ↓ ↓
BM25 + FAISS 文件系统 Calculator
↓ ↓ ↓
Reranker 结果 结果
└────────────┼────────────┘
↓
Llama
↓
答案
这时候已经具备:
知识检索
+
工具调用
+
任务规划
+
结果分析
二十、Agent和传统Chatbot的区别
| 能力 | Chatbot | Agent |
|---|---|---|
| 文本回答 | ✅ | ✅ |
| 知识库检索 | 可选 | ✅ |
| 工具调用 | ❌ | ✅ |
| 多步骤任务 | 弱 | ✅ |
| 文件操作 | ❌ | ✅ |
| 自动决策 | 有限 | ✅ |
| 任务循环 | ❌ | ✅ |
所以:
LLM
↓
Chatbot
进一步:
LLM + RAG
↓
Knowledge Assistant
再进一步:
LLM + RAG + Tools + Loop
↓
AI Agent
二十一、Agent并不等于“让模型自由发挥”
这是开发Agent时一个非常容易出现的误区。
一个可靠Agent应该是:
明确工具
+
明确参数
+
明确权限
+
明确执行流程
+
明确停止条件
而不是:
把电脑权限全部交给LLM
工业级Agent真正关注的不是:
模型能不能自己思考。
而是:
模型能否在受控环境中可靠完成任务。
二十二、什么时候应该使用Agent?
并不是所有任务都需要Agent。
例如:
用户:
什么是Transformer?
直接:
Llama
就够了。
用户:
根据我的PDF回答问题。
使用:
RAG
更合适。
用户:
搜索我的知识库,然后读取指定文件,再计算结果,最后生成报告。
这时候才真正适合:
Agent
因此:
简单问答
↓
LLM
知识问答
↓
RAG
复杂任务
↓
Agent
二十三、本篇总结
这一篇我们完成了从:
本地LLM
到:
本地AI Agent
的关键升级。
核心知识:
1. Agent
LLM + Tools + Loop
2. Tool Calling
LLM
↓
选择工具
↓
参数
↓
程序执行
↓
结果
↓
LLM
3. Agent Runtime
负责:
解析Tool Call
↓
执行工具
↓
返回结果
4. RAG Tool
把之前的:
BM25
+
FAISS
+
Reranker
封装成Agent可以调用的工具。
二十四、现在我们的LlamaAI已经变成什么了?
回顾整个专栏:
第1篇
认识本地AI
↓
第2篇
编译llama.cpp
↓
第3篇
运行GGUF模型
↓
第4篇
CUDA GPU加速
↓
第5篇
OpenAI兼容API
↓
第6篇
RAG知识库
↓
第7篇
BM25 + FAISS + Reranker
↓
第8篇
AI Agent
现在已经形成:
Local AI
│
┌───────────┴───────────┐
↓ ↓
LLM RAG
│ │
llama.cpp BM25 + FAISS
│ │
CUDA Reranker
│ │
└───────────┬───────────┘
↓
Agent
│
Tool Calling
│
┌───────────┼───────────┐
↓ ↓ ↓
File Code Search
这已经是一个完整的本地AI应用基础架构。
下一篇预告
《llama.cpp性能优化实战:从显存、KV Cache到Token/s》
前面我们一直在追求:
让模型跑起来。
下一篇开始追求:
让模型跑得更快、更省显存、更稳定。
将重点分析:
- Token/s到底是什么
- Prompt Processing和Token Generation
- KV Cache原理
- Context Size对显存的影响
- Batch Size如何影响性能
- GPU Offload
- Flash Attention
- Quantization量化
- CPU线程优化
- 多用户并发
- 如何使用
nvidia-smi和性能指标定位瓶颈
最终我们会建立一套完整的:
模型
↓
显存
↓
CUDA
↓
KV Cache
↓
Batch
↓
Token/s
本地LLM性能优化体系。
更多推荐



所有评论(0)