掘金 人工智能 09月14日
LLM的进化:从书呆子到超级助理的蜕变
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文深入剖析了大语言模型(LLM)的核心本质——一个“下一个词元概率预测模型”,并揭示了其“涌现能力”如何赋予其推理、规划等高级智能。文章指出了LLM的局限性,如知识滞后、知识幻觉和行动无能,但同时也强调了其作为“天才”的一面。为克服这些局限,Prompt工程、RAG、Function Calling和MCP等关键技术应运而生,共同构建了AI Agent。文章详细介绍了Prompt的作用、RAG解决知识问题、Function Calling赋予行动能力,以及Agent架构的核心逻辑,并预告了下一篇的实战应用。

💡 LLM的核心本质是“下一个词元概率预测模型”,其强大的能力源于海量数据训练和“涌现能力”,使其展现出复杂的推理、逻辑分析和任务规划等高级智能。

⚠️ LLM存在“知识滞后”(知识截止日期)、“知识幻觉”(一本正经地胡说八道)和“行动无能”(无法与现实世界交互)三大局限性,使其在某些场景下表现如同“白痴”。

🚀 Prompt工程、RAG(检索增强生成)、Function Calling(函数调用)和MCP(模型上下文协议)等技术是克服LLM局限性、充分发挥其优势的关键。它们共同协作,构成了强大的AI Agent(智能代理)架构。

🛠️ RAG通过外部知识库为LLM提供最新、专有信息,解决知识滞后和幻觉问题;Function Calling赋予LLM调用外部工具的能力,使其能够执行具体操作并与现实世界互动;Agent架构则利用LLM的推理能力自主规划、分解任务并调用工具,实现更高级别的自主性。

🤝 MCP作为一种应用层协议,为AI应用集成外部工具提供了标准化、可互操作的通信规范,确保不同工具之间的顺畅协作,极大地简化了Agent的开发和管理。

引入:将你的LLM从“读死书的书呆子”武装成“超级助理”

从22年底ChatGPT的爆火,到今年年初国产大语言模型DeepSeekv3的频繁刷屏,我们看到了大语言模型(LLM)那令人惊叹的能力:写诗、编程、答疑仿佛无所不能,无所不知。其高度自然的人机交互界面,容易让我们感觉像是在与一位“全知全能”的对话者交流。然而,揭开这层表象,LLM的核心本质是一个基于海量数据训练的“下一个词元概率预测模型”

他的核心任务非常简单:就是根据上下文(即你的问题)从数十亿的参数中,计算出下一个最可能出现的词元是什么。如此不断反复最终生成一个长文本。

当然如果仅仅是一个简单的下一个词元的概率预测模型,LLM也不会像现在这样火热。关键在于,凭借其庞大的参数规模与训练数据量,LLM显现了“涌现能力”(Emergent Abilities)也就是我们的俗语书读百遍,其意自现——这意味着当模型规模超过某个临界点时,它会展现出诸如复杂推理、逻辑分析、任务规划等并未在训练中被明确指定的新能力。

因此,LLM的能力呈现出一种二元性:

正是为了克服LLM的固有局限,同时充分利用其强大的推理和规划能力,Prompt工程、检索增强生成(RAG)、函数调用(Function Calling)和模型上下文协议(MCP)等技术应运而生。它们共同协作,构成了当今火热无比的AI Agent(智能代理)。

如下图所示:

我们可以将AI Agent想象为一个高效的超级助理

接下来,我们将初步了解Prompt、RAG、Function Calling和MCP这四大关键技术,看看他们是如何工作的,在**下一篇文章中,**我将以一个实际的形同为例,带你看看它们如何协同工作,将一个简单的LLM武装成一个“数据超级助理”。

一、Prompt(提示词):一切交互的基石

定义

prompt(提示词)不是一种具体的技术,是我们和LLM沟通的控制语言。他的构成就是指令式的语言,这是整个Agent中的一个核心,我们所有功能的实现都是基于一个我们精心设计好的提示词。

核心作用

提示词的核心作用就玩一场cosplay。我们要精确的告诉模型“你是谁(角色)”、“你要做什么(任务)”、“依照什么样的规则(约束)”、“参考什么信息(上下文,非必须)”,以及示例(非必须)。

LLM模型接受的训练数据是多种多样的,所以在回答时他的答案边界就会很模糊,Prompt的作用就是给模型画个圈,让他的答案限制在这个圈内。

演示

接下来让我们做一个简单的演示,我们让模型来写一个关于狗的故事。

>(模型一) 写一个300字左右的关于狗的故事:>(模型二) 你是一位小说家,你现在要用欧亨利的风格写一个300字左右的关于狗的故事。

我们用腾讯元宝中的DeepSeek,开启深度思考,会有如下的结果:

可以看出,两篇故事还是有很大的区别的。后一篇明显可以看出欧亨利的意料之外情理之中的结尾。

如何写好一个提示词

那么我们应该如何写好一个提示词呢?

    C - 清晰具体 (Clear & Specific): 避免使用模糊、笼统的词语。L - 提供背景 (Lay out Context): 给出足够的上下文信息,帮助 AI 理解任务的背景和目的。E - 明确目标 (Explicit Goal): 清晰地说明你想要 AI 完成什么任务,以及最终成果的用途。A - 指定格式 (Assign a Format): 规定输出的格式、风格、语气和长度。

在实践中,我们可以用上面的基本原则加我们下面的基本公式来生成你的提示词:

角色 + 任务 + 背景 + 要求 + 格式/范例

小Tips:

二、两大核心外挂:为LLM赋予“新知识”和“真行动”

RAG———解决知识滞后和幻觉

定义

RAG(Retrieval-Augmented Generation,检索增强生成):是一种将信息检索和LLM结合的技术框架,让LLM在回答问题前,先从外部知识库(内部数据库、PDF)获取相关信息然后将查询到的信息注入到Prompt中,利用LLM的总结能力来回答问题。

如图所示,RAG的调用流程共包含5个步骤

    用户提问检索器将用户的问题转化成向量知识库根据查询算法,从向量数据库中搜索出最相关的几个知识片段将这些知识片段填入到提前编辑好的提示词中LLM根据提示词以及相关的知识片段利用自己的推理能力生成对用户提问的回答

Demo演示

环境准备

    先安装必要的库:
pip install openai scikit-learn python-dotenv

    在项目文件夹中创建一个.env的文件,填入你的LLM API

    这里使用硅基流动的API,有免费的模型可以使用:Qwen/Qwen3-8B这是我的邀请链接大家需要的话可以点一点,硅基流动现在学生注册免费送50元额度: cloud.siliconflow.cn/i/elkOMWfK

    API_KEY的生成方式为:登陆硅基流动,在左边点击API密钥,点击新建密钥,粘贴到SILICONFLOW_API_KEY中就可以。

# SiliconFlow 的 API 地址export SILICONFLOW_BASE_URL="https://api.siliconflow.cn/v1"# 您在 SiliconFlow 平台获取的 API Keyexport SILICONFLOW_API_KEY="sk-..."
    简单的RAG代码
# rag_complete.pyimport osimport asynciofrom openai import AsyncOpenAIfrom sklearn.feature_extraction.text import TfidfVectorizerfrom sklearn.metrics.pairwise import cosine_similarityfrom dotenv import load_dotenv# --- 1. 设置环境 ---load_dotenv() # 加载 .env 文件中的环境变量# 从环境变量中获取配置BASE_URL = os.getenv("SILICONFLOW_BASE_URL")API_KEY = os.getenv("SILICONFLOW_API_KEY")if not API_KEY or not BASE_URL:    print("错误: 请确保 SILICONFLOW_BASE_URL 和 SILICONFLOW_API_KEY 环境变量已设置。")    exit()# 初始化一个指向指定端点的异步 OpenAI 客户端llm_client = AsyncOpenAI(    base_url=BASE_URL,    api_key=API_KEY)# --- 2. 构建简易知识库 ---knowledge_base = [    "Starlight-15 是 Starlight Inc. 公司于 2024 年发布的旗舰智能手机,配备了超感光摄像头和 A18 Pro 芯片。",    "Galaxy Fold 6 是三星公司推出的最新折叠屏手机,主打大屏体验和多任务处理能力。",    "Starlight Inc. 公司的售后服务政策是自购买之日起一年内免费维修非人为损坏。",    "A18 Pro 芯片采用了 3 纳米工艺,集成了 200 亿个晶体管,性能比上一代提升了 20%。",    "Starlight-15 的电池容量为 5000mAh,支持 80W 快充,30分钟可充满 100%。"]vectorizer = TfidfVectorizer()knowledge_base_vectors = vectorizer.fit_transform(knowledge_base)# --- 3. 实现检索器 ---def retrieve_context(query, top_k=2):    """根据用户问题,从知识库中检索最相关的 K 个文本片段。"""    query_vector = vectorizer.transform([query])    similarities = cosine_similarity(query_vector, knowledge_base_vectors).flatten()    top_k_indices = similarities.argsort()[-top_k:]    return [knowledge_base[i] for i in reversed(top_k_indices)]# --- 4. RAG 核心流程 ---async def simple_rag_query(query):    """执行完整的 RAG 流程"""    print(f"用户问题: {query}")    retrieved_context = retrieve_context(query)    print(f"检索到的上下文:\n- {'\n- '.join(retrieved_context)}")        augmented_prompt = (        "你是一个问答机器人。请根据以下提供的上下文信息来回答用户的问题。\n"        "如果上下文信息不足以回答问题,请说'根据我所掌握的信息,无法回答该问题'。\n\n"        "--- 上下文 ---\n"        f"{'\n'.join(retrieved_context)}\n"        "--- 问题 ---\n"        f"{query}\n"        "--- 回答 ---\n"    )        print("\n增强后的 Prompt (发送给 LLM 的内容):")    print("-----------------------------------------")    print(augmented_prompt)    print("-----------------------------------------")    try:        response = await llm_client.chat.completions.create(            model="Qwen/Qwen3-8B",            messages=[{"role": "user", "content": augmented_prompt}]        )        final_answer = response.choices[0].message.content        print(f"\nLLM 生成的最终答案:\n{final_answer}")    except Exception as e:        print(f"\n调用 LLM 时发生错误: {e}")async def main():    await simple_rag_query("Starlight-15 用的什么芯片?充电快吗?")    print("\n" + "="*50 + "\n")    await simple_rag_query("三星的折叠屏手机怎么样?")if __name__ == "__main__":    asyncio.run(main())

解决的问题

存在的问题

Function Calling———给模型提供行动能力

定义

Function Calling (函数调用) 让LLM能够调用外部的API或代码机制。这是模型与现实世界互动的“双手”。LLM 负责“决定调用哪个函数”,而外部程序负责“真正执行”。

    系统开始前开发人员需要将要使用的函数的文档编写送入Prompt组合器中。我们需要提前编写好Prompt,在里面需要告诉模型我们有哪些函数,他以什么样的形式向我们传递参数。用户提问后,模型通过查看函数文档以及推理思考决定调用哪个函数,传递什么参数。函数服务器接受到模型的回复后,按照约定解析函数参数,发起函数调用。完成调用后将数据按照约定格式返回给模型。模型收到返回值后再次进行推理思考形成自然语言回答用户的问题。

Demo演示

# function_calling_complete.pyimport osimport asyncioimport jsonfrom openai import AsyncOpenAIfrom dotenv import load_dotenv# --- 1. 设置环境 ---load_dotenv()BASE_URL = os.getenv("SILICONFLOW_BASE_URL")API_KEY = os.getenv("SILICONFLOW_API_KEY")if not API_KEY or not BASE_URL:    print("错误: 请确保 SILICONFLOW_BASE_URL 和 SILICONFLOW_API_KEY 环境变量已设置。")    exit()llm_client = AsyncOpenAI(base_url=BASE_URL, api_key=API_KEY)# --- 2. 定义我们的 Python 函数 (工具) ---def get_current_weather(location: str, unit: str = "celsius"):    """获取指定地点的当前天气信息。"""    print(f"--- 正在执行函数: get_current_weather(location='{location}', unit='{unit}') ---")    if "nanjing" in location.lower() or "南京" in location.lower():        return json.dumps({"location": "南京", "temperature": "15", "unit": unit, "forecast": "晴天"})    else:        return json.dumps({"location": location, "temperature": "未知"})def send_email(to: str, subject: str, body: str):    """向指定收件人发送邮件。"""    print(f"--- 正在执行函数: send_email(to='{to}', subject='{subject}', body='...') ---")    return json.dumps({"status": "成功", "message": f"邮件已成功发送至 {to}。"})available_functions = {    "get_current_weather": get_current_weather,    "send_email": send_email,}# --- 3. Function Calling 核心流程 ---async def run_conversation(user_query):    """执行完整的函数调用流程"""    print(f"用户问题: {user_query}")    messages = [{"role": "user", "content": user_query}]        tools = [        {            "type": "function",            "function": {                "name": "get_current_weather",                "description": "获取一个指定地点的当前天气情况",                "parameters": {                    "type": "object",                    "properties": {                        "location": {"type": "string", "description": "城市名称, 例如:南京"},                        "unit": {"type": "string", "enum": ["celsius", "fahrenheit"], "description": "温度单位"},                    }, "required": ["location"],                },            },        },        {            "type": "function",            "function": {                "name": "send_email",                "description": "向指定收件人发送一封邮件",                "parameters": {                    "type": "object",                    "properties": {                        "to": {"type": "string", "description": "收件人的邮箱地址"},                        "subject": {"type": "string", "description": "邮件的主题"},                        "body": {"type": "string", "description": "邮件的正文内容"},                    }, "required": ["to", "subject", "body"],                },            }        }    ]    try:        response = await llm_client.chat.completions.create(            model="Qwen/Qwen3-8B",            messages=messages,            tools=tools,            tool_choice="auto",        )        response_message = response.choices[0].message                if response_message.tool_calls:            print("LLM 决定调用一个工具。")            messages.append(response_message)                        for tool_call in response_message.tool_calls:                function_name = tool_call.function.name                function_to_call = available_functions[function_name]                function_args = json.loads(tool_call.function.arguments)                                print(f"   - 函数名: {function_name}, 参数: {function_args}")                function_response = function_to_call(**function_args)                                messages.append({                    "tool_call_id": tool_call.id,                    "role": "tool",                    "name": function_name,                    "content": function_response,                })            second_response = await llm_client.chat.completions.create(                model="Qwen/Qwen3-8B", messages=messages            )            final_answer = second_response.choices[0].message.content        else:            print("LLM 决定不调用工具,直接回答。")            final_answer = response_message.content        print(f"\nLLM 生成的最终答案:\n{final_answer}")    except Exception as e:        print(f"\n与 LLM 交互时发生错误: {e}")async def main():    await run_conversation("南京现在天气怎么样?")    print("\n" + "="*50 + "\n")    await run_conversation("你好吗?")if __name__ == "__main__":    asyncio.run(main())

解决的问题

存在的问题

三、Agent(智能体):拥有“自主意识”的规划者

定义

如果RAG和Function Calling是“工具”,那么Agent就是那个总指挥。Agent不是一个单一的技术,而是一套架构的范式,其核心就是利用LLM强大的推理能力来自主规划、分解任务并决定调用哪个工具。

核心逻辑(ReAct范式)

ReAct范式模拟了人类解决问题的方式:

也即形成一个如下图的循环。

Demo

# agent_complete.pyimport osimport asyncioimport jsonimport refrom openai import AsyncOpenAIfrom dotenv import load_dotenv# --- 1. 设置环境 ---load_dotenv()BASE_URL = os.getenv("SILICONFLOW_BASE_URL")API_KEY = os.getenv("SILICONFLOW_API_KEY")if not API_KEY or not BASE_URL:    print("错误: 请确保 SILICONFLOW_BASE_URL 和 SILICONFLOW_API_KEY 环境变量已设置。")    exit()llm_client = AsyncOpenAI(base_url=BASE_URL, api_key=API_KEY)# --- 2. 定义 Agent 可以使用的工具 ---def get_current_weather(location: str):    """获取指定地点的当前天气信息。"""    print(f"--- 正在执行工具: get_current_weather(location='{location}') ---")    if "nanjing" in location.lower() or "南京" in location.lower():        return "南京当前温度为15摄氏度,天气晴朗。"    else:        return f"抱歉,我没有 {location} 的天气信息。"def search_web(query: str):    """在网上搜索信息。"""    print(f"--- 正在执行工具: search_web(query='{query}') ---")    if "室内活动" in query:        return "南京热门的室内活动包括参观博物院、去新街口购物。"    elif "户外活动" in query:        return "南京晴天时热门的户外活动包括游览中山陵、逛玄武湖公园。"    else:        return f"关于 '{query}' 的搜索结果在此模拟中不可用。"available_tools = {    "get_current_weather": get_current_weather,    "search_web": search_web,}# --- 3. 定义 Agent 的核心 Prompt ---AGENT_SYSTEM_PROMPT = """你是一个作为自主智能体运行的得力助手。你的目标是通过将用户的请求分解成一系列步骤来解决它。在每一步,你都必须遵循以下格式:Thought: [你的推理和下一步行动的计划。分析上一步的观察结果并决定接下来做什么。]Action: [一个 JSON 对象,代表你想要使用的工具。它必须是可用工具之一,或者是用于最终回答的工具。]可用工具:- `get_current_weather`:   - 描述: 获取指定地点的当前天气。  - 参数: `{ "location": "string" }`- `search_web`:   - 描述: 在网上搜索信息。  - 参数: `{ "query": "string" }`当你拥有足够信息来回答用户的问题时,你必须使用 `final_answer` 工具。- `final_answer`:  - 描述: 向用户提供最终的答案。  - 参数: `{ "answer": "string" }`单步示例:Thought: 我需要找出南京的天气。我将使用 get_current_weather 工具。Action: { "tool_name": "get_current_weather", "arguments": { "location": "南京" } }"""# --- 4. Agent 的主循环 ---async def run_agent(user_query, max_steps=5):    """执行 Agent 的思考-行动循环"""    print(f"Agent 任务开始: {user_query}\n")    messages = [        {"role": "system", "content": AGENT_SYSTEM_PROMPT},        {"role": "user", "content": f"请解决以下请求: {user_query}"}    ]        for step in range(max_steps):        print(f"--- 步骤 {step + 1} ---")        try:            response = await llm_client.chat.completions.create(                model="Qwen/Qwen3-8B",                messages=messages,                temperature=0,            )            response_text = response.choices[0].message.content            print(response_text)                        thought_match = re.search(r"Thought: (.*?)\nAction: ", response_text, re.DOTALL)            action_match = re.search(r"Action: (\{.*\}|\{.*?\s*.*?\})", response_text, re.DOTALL)            if not thought_match or not action_match:                print("解析失败: 无法找到 Thought 或 Action。")                return                            action_json_str = action_match.group(1).strip()            action = json.loads(action_json_str)                        tool_name = action.get("tool_name")            tool_args = action.get("arguments")                        if tool_name == "final_answer":                print(f"\nAgent 任务完成!")                print(f"最终答案: {tool_args.get('answer')}")                return                        if tool_name in available_tools:                function_to_call = available_tools[tool_name]                observation = function_to_call(**tool_args)                print(f"   - 观察结果: {observation}")                messages.append({"role": "user", "content": f"Observation: {observation}"})            else:                print(f"未知工具: {tool_name}")                messages.append({"role": "user", "content": f"Observation: Error - Unknown tool '{tool_name}'."})        except Exception as e:            print(f"在步骤 {step + 1} 中发生错误: {e}")            return        print("\nAgent 达到最大步骤限制,任务终止。")async def main():    complex_task = "查询一下南京的天气,然后根据天气情况,帮我推荐一些适合的活动。"    await run_agent(complex_task)if __name__ == "__main__":    asyncio.run(main())

存在的问题

四、一个协议:MCP为Agent提供标准的通信

定义

MCP(Model Context Protocol,模型上下文协议)约定了AI应用如何规范地集成外部工具,实现为大模型补充上下文的目的,其本质是一个应用层协议。

出现原因

Function Calling 为我们提供了调用能力,但没有一个统一规范的标准,会导致不同人开发出来的Function 有不同的传输标准,此时如果去做接入,就会有大量无意义的工作产生。同时,MCP还为我们提供了生成标准化函数Prompt的工作,我们只需要把函数文档注释写好,其就可以生成供大模型使用的提示词。

MCP中主要有三个角色,主机、服务端、客户端

Tips:MCP时客户端与服务端的协议,实际上并不涉及LLM的交互。主要解决的问题是自动进行函数文档的注入,管理各个客户端的状态,以及客户端和服务端的交互形式。

Demo

环境准备

pip install mcp

服务端代码

# demo_server.pyfrom mcp.server.fastmcp import FastMcp# 创建 MCP 服务器实例,命名为 "DemoServer"mcp = FastMCP("DemoServer")@mcp.tool()def add(a: int, b: int) -> int:    """Add two numbers."""    return a + b@mcp.tool()def greet(name: str) -> str:    """Return greeting."""    return f"Hello, {name}!"if __name__ == "__main__":    # 使用 stdio 传输模式,方便本地调试    mcp.run(transport='stdio')

客户端代码

# demo_client.pyimport asyncioimport sysfrom mcp import ClientSession, StdioServerParametersfrom mcp.client.stdio import stdio_clientasync def main():    # 1. 配置服务器启动参数:使用当前 Python 解释器运行 server 脚本    server_params = StdioServerParameters(        command=sys.executable,        args=["demo_server.py"]    )    # 2. 建立与服务器的会话    async with stdio_client(server_params) as (read, write):        async with ClientSession(read, write) as session:            # 初始化连接,进行 MCP 握手            await session.initialize()            # 3. 列出服务器提供的所有可用工具            tools = await session.list_tools()            print("Available tools:", [t.name for t in tools.tools])            # 4. 调用 'add' 工具            add_result = await session.call_tool("add", arguments={"a": 3, "b": 4})            # 工具调用通常返回一个内容列表,我们提取文本内容            add_output = ''.join(content.text for content in add_result.content if hasattr(content, 'text'))            print("add(3, 4) =>", add_output)            # 5. 调用 'greet' 工具            greet_result = await session.call_tool("greet", arguments={"name": "MCP"})            greet_output = ''.join(content.text for content in greet_result.content if hasattr(content, 'text'))            print("greet('MCP') =>", greet_output)if __name__ == "__main__":    asyncio.run(main())

总结与预告

本篇文章我们从一个虽然有缺陷但推理能力超强的基本LLM出发,用Prompt与之沟通,用RAG作为他的外置大脑,用Function Calling为其赋予行动能力,并通过 Agent 架构使用 LLM 最强的推理能力来指挥这一切。我们还探讨了 MCP 协议如何为这套复杂的系统提供标准的通信规范。构建出了一个强大的工作流。

但是纸上得来终觉浅,只有在实战中我们才能切身体会到上面提到的问题,才能想出如何优雅处理这些工具问题的方案。在下篇《AI应用开发实战:从零构建一个企业私有数据管家的Agent》中,我们将撸起袖子,把今天的这些理论付诸到实践中去。敬请期待!让我们一起变得更强!


文章首发gzh【破茧plan】,欢迎关注。

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

LLM AI Agent Prompt Engineering RAG Function Calling MCP 大语言模型 智能代理 提示词工程 检索增强生成 函数调用 模型上下文协议
相关文章