手搓一个会自己干活的AI助手:聊聊LLM、RAG、MCP、Skill和Agent
大家好,我是阿浪
不知道大家有没有过这种时刻——对着 ChatGPT 问一个稍微复杂点的问题,它给你的回答漂亮得像个满分作文,但仔细一琢磨,全是正确的废话。比如你问“明天去长沙玩穿什么衣服”,它能给你列出温差、湿度、紫外线指数,但就是给不出一个确定的结论。
我一度觉得,AI 就像一个知识渊博但生活不能自理的天才:脑子好使,但没有手、没有脚,也不会自己查资料。
直到最近我把这几个东西串起来——LLM、RAG、MCP、Skill、Agent——我才发现,原来我们离“AI 自己干活”只差一层窗户纸。
今天我就用我自己的折腾经历,把这五个词掰开揉碎讲清楚,顺便附上我手写的完整代码,让你也能五分钟搭一个会自己查天气、搜攻略、规划路线的“旅行小管家”。
从“大脑”到“打工人”,一层层拆解
第一步:LLM
LLM(大语言模型)就是一切的基础。你可以把它理解成你大学里那个上知天文下知地理、但从不离开宿舍的学霸室友。
他读过几万本书(训练数据),逻辑推理能力一流,你问什么他都能接住。但他的问题也很明显:
- 知识截止日期:他不知道今年发生了什么;
- 爱瞎编:对不知道的事,他会极其自信地胡说八道;
- 不会动手:你让他帮你订个外卖,他只能告诉你“可以打开美团 App”,但他自己不会点。
所以,LLM 是大脑,但只有大脑不够——得给它配记忆、配手脚。
我自己的一点感受:很多人一上来就吹 LLM 多神奇,但真正用起来你会发现,它最大的价值不是“全知”,而是“理解任务并拆解任务”。这一步才是后面所有事情的基础。
第二步:RAG
RAG(检索增强生成)是我觉得目前最实用的技术,没有之一。
它的思路特别朴素:不让 AI 凭记忆瞎答,而是让它先翻书,再回答。
具体做法就是:你把一堆文档(公司制度、产品手册、旅游攻略)存进一个向量数据库,用户提问时,系统先去数据库里搜索最相关的几段内容,然后把这几段内容和问题一起喂给 LLM,让 LLM“看着答案抄”。
这样一来:
- 回答有据可查,胡编乱造的概率大大降低;
- 知识可以实时更新,你只需更新文档库,不用重新训练模型;
- 还能引用来源,用户能看见答案是从哪来的。
我自己的实践:用 ChromaDB 存了一堆长沙美食攻略,问“推荐几家本地人常去的粉店”,它直接帮我从文档里摘出三条街的老字号,还附带店面照片的描述——效果吊打直接问 LLM。
**代码片段(RAG 检索核心)**:
import chromadb
from sentence_transformers import SentenceTransformer
# 初始化向量数据库
client = chromadb.PersistentClient(path="./travel_db")
collection = client.get_or_create_collection("guides")
# 嵌入模型(把文本转成向量)
encoder = SentenceTransformer('all-MiniLM-L6-v2')
# 存入文档(示例)
docs = [
"倒萨倒萨倒萨",
"2313213",
"13dsaldsad。"
]
embeddings = encoder.encode(docs).tolist()
collection.add(
documents=docs,
embeddings=embeddings,
ids=[f"doc{i}" for i in range(len(docs))]
)
# 检索函数
def retrieve(query, top_k=2):
query_vec = encoder.encode([query]).tolist()
results = collection.query(query_embeddings=query_vec, n_results=top_k)
return results['documents'][0]
我的个人看法:RAG 是让 AI“诚实”的第一步。没有 RAG 的 AI 像在闭卷考试,有了 RAG 就是开卷考,差距巨大。
第三步:MCP
MCP(模型上下文协议)是今年才火起来的东西,但它解决的问题我一直觉得是 AI 落地的最大拦路虎——怎么让 AI 调用外部工具。
以前,你想让 AI 查天气,你得自己写代码调 API,然后把结果拼进 prompt 里再发给 AI,来回折腾。MCP 做的事情很简单:它定义了一套标准化的接口规范,让 AI 可以用同样的“手势”去调用不同的工具——查数据库、发邮件、操作 Excel、调用爬虫,都可以统一起来。
你可以把 MCP 想象成电脑上的 USB-C 接口:不管你是接硬盘、显示器还是充电器,插上同一个口就能用。AI 不再需要为每个工具学习不同的“方言”,只要遵循 MCP 协议,就能调用任何支持该协议的服务。
我自己最受触动的一点:MCP 的出现让我觉得“万能 AI 助手”不再是科幻。以前每个工具都要单独适配,现在只要服务方愿意提供 MCP 接口,AI 就能像搭积木一样组合使用。
第四步:Skill
Skill 就是具体的“动作单元”,比如“查天气”是一个 Skill,“发邮件”是一个 Skill,“计算路线距离”也是一个 Skill。
Skill 和 MCP 的关系很简单:MCP 是插座的规格,Skill 是插在上面的具体电器。一个 MCP 服务器可以挂载多个 Skill,AI 通过 MCP 协议去调用这些 Skill。
我自己写代码时,会把每个 Skill 封装成一个独立的函数,输入输出都严格定义,这样无论 LLM 怎么折腾,都不会把参数传错。
**代码示例(定义两个 Skill)**:
# Skill 1: 查天气(模拟调用API)
def get_weather(city: str) -> str:
# 实际中这里会调用真实天气API
weather_data = {
"长沙": "多云转晴,25-32℃,南风3级",
"北京": "晴,22-35℃,北风2级",
"上海": "小雨,24-28℃,东风4级"
}
return weather_data.get(city, f"未找到{city}的天气数据")
# Skill 2: 计算两点间驾车距离(模拟)
def calc_distance(origin: str, dest: str) -> str:
# 实际会调地图API
if origin == "长沙" and dest == "岳阳":
return "约160公里,开车约2小时"
else:
return f"{origin}到{dest}的距离待查询"
# 技能注册表(给LLM用的说明书)
skills = {
"get_weather": {
"func": get_weather,
"description": "查询某个城市的天气",
"params": {"city": "城市名称(中文)"}
},
"calc_distance": {
"func": calc_distance,
"description": "计算两个城市之间的驾车距离和时间",
"params": {"origin": "起点城市", "dest": "终点城市"}
}
}
第五步:Agent —— 那个会自己干活的“数字员工”
终于到了最激动人心的部分——Agent。
Agent 不是单一技术,而是把上面所有东西组装起来的一个自主系统。它的工作流程就像我们人类处理任务:
- 理解目标:LLM 读懂用户说的“帮我规划周末去长沙玩”;
- 拆解任务:分成“查天气”、“搜景点”、“订路线”;
- 调用工具:通过 MCP 调用对应的 Skill(查天气、搜攻略);
- 获取信息:用 RAG 从知识库检索美食攻略;
- 生成计划:综合所有信息,给出一份完整的行程单;
- 自我纠错:如果某一步失败,自己重试或换方案。
我花了一个下午用 Python 简单实现了这样一个 Agent,它虽然粗糙,但当我看到它真的自己去查了天气、检索了文档、然后打印出一份包含“上午橘子洲,中午周记粉店,下午岳麓山”的行程表时,我后背发凉——这不是照抄模板,而是它自己“思考”出来的。
核心代码:一个极简 Agent 的完整实现
下面是我手写的完整代码,你可以直接复制运行(需要安装 openai、chromadb、sentence-transformers,并替换你的 OpenAI API Key)。
import json
import re
from openai import OpenAI
from sentence_transformers import SentenceTransformer
import chromadb
# ---------- 1. 初始化RAG ----------
client_db = chromadb.PersistentClient(path="./agent_db")
collection = client_db.get_or_create_collection("travel")
encoder = SentenceTransformer('all-MiniLM-L6-v2')
# 预置旅行文档
docs = [
"qqqqqqqqqqq。",
"3213213213213。",
"ewqewqe。"
]
embeddings = encoder.encode(docs).tolist()
collection.add(documents=docs, embeddings=embeddings, ids=[f"d{i}" for i in range(len(docs))])
def rag_retrieve(query):
q_vec = encoder.encode([query]).tolist()
res = collection.query(query_embeddings=q_vec, n_results=2)
return "\n".join(res['documents'][0])
# ---------- 2. 定义Skill ----------
def get_weather(city):
data = {"长沙":"25-32℃,多云", "北京":"22-35℃,晴", "上海":"24-28℃,小雨"}
return data.get(city, "未知天气")
def calc_time(city):
data = {"长沙":"2天足够", "北京":"建议4天", "上海":"3天"}
return data.get(city, "待查询")
skills_map = {
"weather": {"func": get_weather, "desc": "查询城市天气", "params": ["city"]},
"time": {"func": calc_time, "desc": "建议游玩天数", "params": ["city"]}
}
# ---------- 3. 定义MCP调用器 ----------
def call_skill(skill_name, params):
skill = skills_map.get(skill_name)
if not skill:
return f"没有这个技能:{skill_name}"
return skill["func"](**params)
# ---------- 4. Agent主循环 ----------
client = OpenAI(api_key="你的key") # 替换
def agent(user_query):
# 第一轮:让LLM分析任务,决定调什么工具
tools_desc = "\n".join([f"- {k}: {v['desc']}, 参数:{v['params']}" for k,v in skills_map.items()])
system_prompt = f"""
你是一个旅行规划助手。用户会提出需求,你需要:
1. 如果需要实时信息(天气、时间),调用工具,工具列表:
{tools_desc}
2. 如果需要背景知识,使用下面检索到的资料。
请按JSON格式输出:
{{"need_tools": [{{"name": "工具名", "params": {{"参数名": "值"}}}}], "rag_query": "检索词"}}
不要输出其他内容。
"""
# 先做一次RAG检索
rag_info = rag_retrieve(user_query)
user_msg = f"用户问题:{user_query}\n\n资料参考:{rag_info}"
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "system", "content": system_prompt}, {"role": "user", "content": user_msg}]
)
try:
plan = json.loads(response.choices[0].message.content)
except:
plan = {"need_tools": [], "rag_query": user_query}
# 执行工具调用
tool_results = []
for tool in plan.get("need_tools", []):
result = call_skill(tool["name"], tool["params"])
tool_results.append(f"{tool['name']}结果:{result}")
# 第二轮:综合生成最终回答
final_prompt = f"""
用户想:{user_query}
检索到的资料:{rag_info}
工具返回信息:{'; '.join(tool_results) if tool_results else '无'}
请根据以上信息,用口语化、热情的语气,给用户一份详细的游玩建议(包括路线、美食、注意事项)。
"""
final_response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": final_prompt}]
)
return final_response.choices[0].message.content
# ---------- 5. 测试 ----------
if __name__ == "__main__":
print("===== 智能旅行Agent启动 =====")
query = "我想周末去长沙玩两天,有什么推荐?"
print(f"用户:{query}")
answer = agent(query)
print(f"Agent:\n{answer}")
运行结果示例(我自己跑出来的):
用户:我想周末去长沙玩两天,有什么推荐?
Agent:
周末去长沙两天时间刚刚好!第一天上午先去橘子洲,傍晚看夕阳特别美;中午去太平街吃糖油粑粑和臭豆腐,排队也值得。第二天爬岳麓山,坐缆车上山,俯瞰湘江全景。注意湖南省博物馆要提前一周预约,如果没约上可以改成去李自健美术馆。天气多云 25-32℃,短袖加防晒衣就够啦。祝玩得开心!
流程图:Agent 大脑里到底发生了什么
我用 简单 画了一张流程图

这个流程里最妙的一步是第 5 步——Agent 不是线性走完就结束,它会在用户反馈时重新进入规划环节,这就是“自主性”的体现。
我踩过的坑和真实感悟
写这个 Agent 的过程中,我踩了两个大坑,分享出来帮你省点时间:
- LLM 的“工具调用”指令一定要极其明确
第一次我让 LLM 自由发挥,它一会儿输出 JSON,一会儿输出纯文本,解析老报错。后来我把系统提示词写成“只输出 JSON,不要解释”,世界清净了。 - RAG 检索质量决定一切
如果文档分块太粗,检索到的内容会偏离主题;如果太细,又会丢失上下文。我试了几次发现,每个文档块控制在 100~200 字是最优的。 - 不要把 Agent 想得太神
它本质上还是一个“概率机器”,只是通过工程手段把犯错概率压低了。当工具调用链超过 3 层时,错误累积就很明显了。所以目前我只让 Agent 做最多两次工具调用,再多就分步骤人工介入。
但我依然很兴奋——因为这套架构让我看到了“通用人工智能助理”的雏形。它不再是一个聊天窗口,而是一个能行动的实体。未来每家企业都会有自己的 Agent,它们之间甚至能互相通信、协作完成项目。
写在最后
如果你现在去翻各类技术论坛,会发现每个人都在争论“Agent 到底有没有用”。我的亲身实验告诉我:有用,但别指望它马上取代人类。
它更像一个刚入职的实习生——热情、学得快、能帮你干不少杂活,但偶尔也会犯低级错误。你需要给它清晰的指令、可靠的工具(Skill)、干净的知识库(RAG),以及一套统一的指挥系统(MCP)。
我今天分享的代码只有一百多行,但它已经能把“周末去长沙玩”这种模糊需求变成一份可执行的行程单。如果你换个场景——比如变成“帮我整理本月销售数据并生成周报”——只需要换掉 Skill 和 RAG 文档库,Agent 照样能干活。
这才是 AI 最迷人的地方:它不是一个产品,而是一套可以无限组合的积木。
更多推荐




所有评论(0)