AI应用开发指南

1. 引入

1.1. 将你的 LLM 从"读死书的书呆子"武装成"超级助理"

从 22 年底 ChatGPT 的爆火,到今年年初国产大语言模型 DeepSeek V3 的频繁刷屏,我们看到了**大语言模型(LLM)**那令人惊叹的能力:写诗、编程、答疑仿佛无所不能,无所不知。其高度自然的人机交互界面,容易让我们感觉像是在与一位"全知全能"的对话者交流。

然而,揭开这层表象,LLM 的核心本质是一个基于海量数据训练的"下一个词元概率预测模型"。受惠于庞大的参数规模与训练数据量,LLM 显现了**“涌现能力”(Emergent Abilities)**,也就是我们的俗语书读百遍,其意自现——这意味着当模型规模超过某个临界点时,它会展现出诸如复杂推理、逻辑分析、任务规划等并未在训练中被明确指定的新能力。

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

1.2. 它是"白痴":从概率模型上讲,它有三个局限

  • 知识滞后:他的知识永远停留在训练截止日,他无法获得在那以后的信息。
  • 幻觉问题:他的核心任务非常简单:就是根据上下文(即你的问题)从数十亿的参数中,计算出下一个最可能出现的词元是什么。如此不断反复最终生成一个长文本。由于本质是概率模型,他总能选到概率很高的词,也即一本正经地胡说八道。
  • 行动无能:他无法和现实世界产生交互。

1.3. 但另一方面,它是"天才":"涌现"让他拥有了卓越的推理与分解能力

  • 任务分解:能够理解复杂问题并将其分解为可处理的子任务。
  • 任务规划:可以规划多步骤任务的执行路径。

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

图片

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

  • LLM 是助理的"大脑",负责核心的思考、推理与决策
  • Prompt 是清晰的"指令",明确告知助理需要完成的任务和目标
  • RAG 是助理的"动态知识库",使其能够访问和利用最新、专有的信息,减少幻觉
  • Function Calling 是助理的"手脚",允许它调用各种函数和工具来执行具体操作
  • MCP 则是连接大脑与手脚的"神经系统",为工具调用提供标准化、可互操作的协议,确保协作流畅

接下来,我们将初步了解 Prompt、RAG、Function Calling 和 MCP 这四大关键技术,看看他们是如何工作的,在 Function Calling,我将以一个我参加比赛的实际系统为例,带你看看它们如何协同工作,将一个简单的 LLM 武装成一个"数据超级助理"。

图片

2. Prompt(提示词)

2.1. 一切交互的基石

2.2. 定义

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

2.3. 核心作用

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

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

2.4. 演示

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

2.4.1. 模型一

写一个 300 字左右的关于狗的故事;

2.4.2. 模型二

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

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

2.4.3. 模型一 vs 模型二

图片

图片

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

2.5. 如何写好一个提示词

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

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

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

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

2.6. 💡 小 Tips

在面对复杂的任务时,可以尝试把它拆分成多个小步骤,一步一步引导 AI 完成。

巧用思维链,在处理涉及推理和逻辑的问题的时候让 AI 一步步思考,或者展示他的思考过程,这样会使得最终的输出更加严谨、准确。

不要想着一蹴而就,一个好的提示词是需要不断迭代更新的,先从简单的开始,然后给他添加正面和负面的例子,再把例子抽象成新的指令,一步一步完善你的提示词。

3. 两大核心外挂:为 LLM 赋予"新知识"和"真行动"

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

4.1. 定义

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

图片

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

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

4.3. Demo 演示

4.4. 环境准备

4.4.1. 先安装必要的库

pip install openai scikit-learn python-dotenv

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

这里使用硅基流动的 API,有免费的模型可以使用:Qwen/Qwen3-8B。

这是我的邀请链接,大家需要的话可以点一点,硅基流动现在学生注册免费送 50 元额度:https://cloud.siliconflow.cn/i/elkOMWfK

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

# SiliconFlow 的 API 地址
export SILICONFLOW_BASE_URL="https://api.siliconflow.cn/v1"
# 您在 SiliconFlow 平台获取的 API Key
export SILICONFLOW_API_KEY="sk-..."

4.4.3. 简单的 RAG 代码

图片

4.5. 解决的问题

4.6. LLM 的知识时效性

我们通过外挂的知识库可以补充模型训练好以后的数据或者不可公开的隐私数据。

4.7. 信息的可追溯性

模型回答依靠的信息是我们搜索后提供的,我们可以通过提示词让模型显示出来源。

4.8. 私有数据的利用

无法公开的私有数据可以通过本地部署 LLM+RAG 来构建知识问答系统。

4.9. 存在的问题

4.10. 数据切片的策略

我们存入向量库的数据是要经过分割的,我们不能把一份文档整个送入,而文档是有上下文依赖的,粗暴的分割会把原本完整意思的话切分开导致意思改变;用标点符号分割又会导致长短不一,处理困难。

4.11. 数据的预处理

文档是有很强的上下文信息的,这些信息需要经过预处理后才能正常的使用。

在一篇写小明的文章中,对小明的称呼除了小明还有"他"这个代词,在预处理的时候我们需要把他替换成小明。否则在后续的使用中我们问这篇文章一共提到过几次小明,模型只能回答出称呼名字的次数。

4.12. 检索的质量

RAG 系统的回答质量取决于其检索到的文档的质量,而检索的策略和参数又非常多,如何调出一份适合整个系统的方剂是一个很难的问题。

4.13. LLM 上下文长度的限制

LLM 的上下文长度有限制,我们要尽可能简短的为模型提供信息,但当搜索匹配到大量信息时,如何压缩保证不超过 LLM 的上下文长度限制。

4.14. 如何平衡已有知识和检索到的知识权重

当检索到的知识和模型训练知识冲突时,我们需要决定让模型选择相信哪种,要注意我们的文档不是一定正确的。

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

5.1. 定义

Function Calling(函数调用):让 LLM 能够调用外部的 API 或代码的机制,是模型与现实世界互动的"双手"。例如:

图片

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

5.2. Demo 演示

图片

5.3. 解决的问题

  • 可以执行现实世界的动作
  • 获取实时的数据
  • 完成精确的计算

5.4. 存在的问题

5.5. 依赖模型的基础能力

当模型的能力较低时,很难从一堆函数中选择出正确的函数并给出这个函数正确的参数格式。

5.6. 复杂函数调用的挑战

对于需要分解成多步骤的函数调用,模型很可能陷入思维倦怠,即处理到中间步骤突然停止了。

5.7. 安全性和可靠性

对于如删除邮件、修改信息等操作不能随意交给模型进行处理,很容易误删或者误修改。

5.8. 开发与调试的复杂度

对于长调用链路需要追踪每一个节点的参数以及思维链。

6. Agent(智能体)

6.1. 拥有"自主意识"的规划者

6.2. 定义

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

6.3. 核心逻辑(ReAct 范式)

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

  • 遇到问题先动脑想想(Thought)
  • 想好了动手去做(Action)
  • 做完了观察结果如何(Observation)
  • 根据观察的结果决定下一步怎么想,怎么做

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

图片

6.4. Demo

图片

6.5. 存在的问题

  • 过长的思维链可能会陷入死循环或偏离目标
  • 交互式调用 LLM 成本很高并且也会导致延迟高
  • 排查问题困难
  • 上下文容易超限

7. 一个协议:MCP 为 Agent 提供标准的通信

7.1. 定义

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

7.2. 出现原因

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

图片

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

核心分工:LLM 负责"决定调用哪个函数",而外部程序负责"真正执行"。

  • 主机(Host):主要负责用户与大模型的直接交互,同时又负责协调外部资源进行调度。
  • 服务端(Server):主要负责对接外部数据或服务,并通过标准的数据格式将相应的内容发送给 MCP 客户端。
  • 客户端(Client):直接寄生在 MCP 主机中,由主机创建并进行调度,客户端和服务端连接,并进行数据传输。

7.4. TIPS

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

7.5. Demo

7.6. 环境准备

pip install mcp

7.7. 服务端代码

图片

7.8. 客户端代码

图片

8. 总结与预告

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

但是纸上得来终觉浅,只有在实战中我们才能切身体会到上面提到的问题,才能想出如何优雅处理这些工具问题的方案。