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 = 56088Agent:
用户 ↓ 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 ↓ 本地LlamaPython:
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.pyagent.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 + Loop2. Tool Calling
LLM ↓ 选择工具 ↓ 参数 ↓ 程序执行 ↓ 结果 ↓ LLM3. 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性能优化体系。