大家好,我是阿浪

不知道大家有没有过这种时刻——对着 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 不是单一技术,而是把上面所有东西组装起来的一个​自主系统​。它的工作流程就像我们人类处理任务:

  1. 理解目标​:LLM 读懂用户说的“帮我规划周末去长沙玩”;
  2. 拆解任务​:分成“查天气”、“搜景点”、“订路线”;
  3. 调用工具​:通过 MCP 调用对应的 Skill(查天气、搜攻略);
  4. 获取信息​:用 RAG 从知识库检索美食攻略;
  5. 生成计划​:综合所有信息,给出一份完整的行程单;
  6. 自我纠错​:如果某一步失败,自己重试或换方案。

我花了一个下午用 Python 简单实现了这样一个 Agent,它虽然粗糙,但当我看到它真的自己去查了天气、检索了文档、然后打印出一份包含“上午橘子洲,中午周记粉店,下午岳麓山”的行程表时,我后背发凉——这不是照抄模板,而是它自己“思考”出来的。

核心代码:一个极简 Agent 的完整实现

下面是我手写的完整代码,你可以直接复制运行(需要安装 openaichromadbsentence-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 大脑里到底发生了什么

我用 简单 画了一张流程图

c07904cd88f8c013d9a42e19166310ed_750.png

这个流程里最妙的一步是​第 5 步​——Agent 不是线性走完就结束,它会在用户反馈时重新进入规划环节,这就是“自主性”的体现。

我踩过的坑和真实感悟

写这个 Agent 的过程中,我踩了两个大坑,分享出来帮你省点时间:

  1. LLM 的“工具调用”指令一定要极其明确
    第一次我让 LLM 自由发挥,它一会儿输出 JSON,一会儿输出纯文本,解析老报错。后来我把系统提示词写成“​只输出 JSON,不要解释​”,世界清净了。
  2. RAG 检索质量决定一切
    如果文档分块太粗,检索到的内容会偏离主题;如果太细,又会丢失上下文。我试了几次发现,每个文档块控制在 100~200 字是最优的。
  3. 不要把 Agent 想得太神
    它本质上还是一个“概率机器”,只是通过工程手段把犯错概率压低了。当工具调用链超过 3 层时,错误累积就很明显了。所以目前我只让 Agent 做最多两次工具调用,再多就分步骤人工介入。

但我依然很兴奋​——因为这套架构让我看到了“通用人工智能助理”的雏形。它不再是一个聊天窗口,而是一个能行动的实体。未来每家企业都会有自己的 Agent,它们之间甚至能互相通信、协作完成项目。

写在最后

如果你现在去翻各类技术论坛,会发现每个人都在争论“Agent 到底有没有用”。我的亲身实验告诉我:​有用,但别指望它马上取代人类​。

它更像一个刚入职的实习生——热情、学得快、能帮你干不少杂活,但偶尔也会犯低级错误。你需要给它清晰的指令、可靠的工具(Skill)、干净的知识库(RAG),以及一套统一的指挥系统(MCP)。

我今天分享的代码只有一百多行,但它已经能把“周末去长沙玩”这种模糊需求变成一份可执行的行程单。如果你换个场景——比如变成“帮我整理本月销售数据并生成周报”——只需要换掉 Skill 和 RAG 文档库,Agent 照样能干活。

这才是 AI 最迷人的地方:它不是一个产品,而是一套可以无限组合的积木。

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐