2025 年 Python AI 技术白皮书:AI Agent、Prompt、RAG、Function Calling、MCP 与 AI 开发框架
目录
-
[AI Agent(智能代理)](#AI Agent(智能代理) "#AI-Agent%E6%99%BA%E8%83%BD%E4%BB%A3%E7%90%86")
-
[RAG(Retrieval-Augmented Generation,检索增强生成)](#RAG(Retrieval-Augmented Generation,检索增强生成) "#RAG%E6%A3%80%E7%B4%A2%E5%A2%9E%E5%BC%BA%E7%94%9F%E6%88%90")
-
[Function Calling(函数调用)](#Function Calling(函数调用) "#Function-Calling%E5%87%BD%E6%95%B0%E8%B0%83%E7%94%A8")
-
[MCP(Multi-agent Collaboration Protocol,多智能体协作协议)](#MCP(Multi-agent Collaboration Protocol,多智能体协作协议) "#MCP%E5%A4%9A%E6%99%BA%E8%83%BD%E4%BD%93%E5%8D%8F%E4%BD%9C%E5%8D%8F%E8%AE%AE")
-
[Python AI 开发生态概览(2025)](#Python AI 开发生态概览(2025) "#Python-AI-%E5%BC%80%E5%8F%91%E7%94%9F%E6%80%81%E6%A6%82%E8%A7%882025")
引言
近年来,大型语言模型(LLM)驱动的人工智能技术突飞猛进,从早期的Prompt(提示词)设计到更复杂的 AI Agent(智能代理)和多智能体协作 ,各种新概念和技术框架不断涌现。Retrieval-Augmented Generation (RAG,检索增强生成) 技术通过引入外部检索信息提高了模型的准确性,**Function Calling(函数调用)机制让模型可以调用工具和函数,而MCP(多智能体协作协议)**正在探索不同智能体之间标准化通信的方法。这些概念紧密相关,共同定义了 2025 年 AI 应用开发的前沿方向。本白皮书旨在全面讲解上述各概念的原理和实践,并结合 Python 生态中的主流框架(如 OpenAI API、LangChain、LlamaIndex、Haystack、Transformers、FastAPI、Autogen 等),通过实际示例代码演示它们的用法和效果。报告内容结构如技术白皮书形式,包括清晰的章节划分、代码示例和详尽的解释说明,帮助读者系统地理解和应用这些 AI 技术。
2. AI Agent(智能代理)
2.1 定义和技术背景
AI Agent(人工智能智能代理) 通常指能够自主地感知环境、进行决策并执行动作的软件实体。换言之,AI 智能体是一种使用人工智能来实现目标、代表用户完成任务的系统,它具备一定的推理、规划和记忆能力,并具有自主性,能够自主学习、适应和做出决定。典型的 AI Agent 内部往往依托大型语言模型(LLM)作为"大脑"来理解指令和做推理,但相对于传统只会回答问题的聊天机器人,Agent 更强调自主性和行动力。例如,一个 AI Agent 可以在没有人类干预的情况下按照给定目标连续执行多步任务,如分析数据、调用工具接口、与外部环境交互等。
AI Agent 概念的兴起与近年大模型的"Agent化"趋势密切相关。一方面,像 GPT-4 这样的 LLM 展现出强大的推理和语言生成能力;另一方面,开发者希望这些模型不只是被动回答,而是能主动解决复杂问题。这催生了各种 Agent 框架和自治 Agent 项目,例如 AutoGPT、BabyAGI 等。这些系统赋予 LLM 一定的记忆和工具使用能力,使其可以拆解任务、规划步骤并逐步完成目标。AI Agent 通常还结合强化学习、人机反馈等技术,增强其自主决策的合理性。
总的来说,AI Agent 是 LLM 技术发展的必然产物,它将人工智能由"应答者"升级为"执行者"。随着技术演进,智能代理正逐步在工程、客服、数据分析等领域落地,为处理复杂、多步骤任务提供自动化方案。
2.2 工作机制与核心流程
AI Agent 的工作机制通常可以用感知-思考-行动的循环来描述。其核心流程包括以下几个阶段:
-
感知(Perception):Agent 从环境获取信息。这可能是读取用户提供的输入、通过传感器感知物理世界,或者调用 API 检索数据。对于基于LLM的代理,感知往往表现为读取对话上下文、获取工具返回的结果等。
-
决策与推理(Decision & Reasoning) :Agent 根据已感知的信息,利用其内部的推理引擎(通常是LLM)思考下一步行动。在这一阶段,Agent 可能会分解任务、制定子目标或规划行动序列。这类似于人类解决问题时的思考过程。许多 Agent 系统采用 ReAct (Reasoning and Acting) 框架,即让模型交替产生"思考"(Thought)和"行动"(Action)。模型先输出思考内容(这通常对用户不可见),再根据思考决定执行某个工具操作或给出最终答案。
-
执行动作(Action):Agent 将决策转化为实际操作。这一步可能是调用一个外部函数/API(例如数据库查询、计算工具),也可能是向用户展示结果。在 LLM Agent 中,常见的动作包括:调用搜索引擎查询信息、进行计算、调用其他服务(如天气API)等。执行动作往往通过事先定义的一组**工具(Tool)**来进行,Agent 会从可用工具列表中选择合适的工具并提供相应输入。
-
观察结果并反馈(Observation & Feedback):Agent 获取所执行动作的结果,并将其纳入下一轮感知。例如,LLM Agent 在调用工具后,会将工具返回结果附加到对话上下文,然后再次进入"决策与推理"阶段,继续处理新的信息。这样的循环会一直持续,直到Agent判定任务完成或达到预设的终止条件。
上述循环过程可重复多次,使得 Agent 能够在多步骤的任务中逐步推进。这种机制赋予了 Agent 动态调整策略的能力。例如,如果某一步结果不理想,Agent 可以在下一个循环中选择改用其他方法。很多 Agent 实现还引入了**记忆(Memory)**模块,记录中间过程或过往经验,避免Agent重复犯错并提高长期决策质量。
需要注意的是,AI Agent 的自主性来源于其决策过程主要由AI模型驱动,而非固定规则。因此,其行为具有一定不确定性和创造性。在工程实现中,通常会通过设定合理的系统提示(System Prompt)、约束条件和监控策略,来引导 Agent 的决策朝向正确、有益的方向。
2.3 与其他概念的关系
AI Agent 作为一个综合概念,与本报告讨论的其他技术概念均有密切关系:
-
Prompt(提示词):Prompt 是驱动 LLM 产生决策的直接触发因素。Agent 在每轮决策中都会构造用于喂给 LLM 的 prompt,其中包含当前环境信息、任务说明,以及(在多智能体场景下)其他 Agent 的对话内容等。精心设计的 prompt 对于Agent正确决策至关重要。例如,Agent 的系统提示通常明确它可以使用哪些工具、格式如何,这实际上是一种提示工程。在与用户交互时,Agent 也需要将用户请求转化为合适的LLM提示。
-
Retrieval-Augmented Generation (RAG):RAG 经常被作为 Agent 获取外部知识的一种工具或子模块。例如,一个问答类的 Agent 面对用户提问时,如果自身模型知识不足,可以调用RAG模块从数据库或向量索引中检索答案,再据此生成回复。因此,RAG可以视为Agent的"查询工具",Agent 通过决策知道何时需要检索额外信息以辅佐回答。这两者结合可以提高回答的准确性并减少幻觉。
-
Function Calling(函数调用):函数调用机制提供了一种安全、结构化的方式让LLM Agent执行动作。在OpenAI API中,开发者可以定义函数接口,让模型输出对应JSON格式来调用函数。Agent框架往往利用这一特性,将可用工具封装成函数描述,让LLM自主选择调用。例如,LangChain 等库已将工具使用与OpenAI的function calling集成,使Agent决策更稳定。简而言之,函数调用是Agent执行动作(特别是外部工具)的一种重要实现方式。
-
MCP(多智能体协作协议):当多个 AI Agent 同时工作时,就需要考虑它们之间如何通信与协作。MCP 提供了一个标准协议让不同Agent共享信息、协调行动。例如,一个复杂任务可能需要多个专长不同的Agent共同完成(类似多人团队)。这时就涉及消息格式、上下文共享等协作机制。可以说,MCP 是为多Agent环境设计的"规则",而每个具体Agent仍通过各自的Prompt、决策机制来行动。MCP 与 Agent 的关系类似网络协议与节点设备的关系------协议规范通信,智能体负责具体执行。
此外,围绕 AI Agent 的开发,还衍生出如人类反馈强化学习(RLHF)用于训练Agent更好地对齐人类期望、以及自主 Agent 的评估基准等概念。这些也都是为了提升Agent性能和可靠性,与上述核心概念相辅相成。
2.4 示例场景与代码
**示例场景:**假设我们希望构建一个智能问答Agent,它能回答用户的问题。如果问题涉及计算或互联网查询,它可以自主决定调用计算器或搜索工具。这体现了Agent的自主决策和工具使用能力。
下面用 Python 代码展示如何利用 LangChain 库创建一个简单的智能代理。该 Agent 将有两个工具:一个计算器和一个搜索函数。当用户问复杂问题时,Agent 会通过 ReAct 决策框架自动选择使用哪个工具来辅助回答。
python
# 安装所需库:!pip install langchain openai (已提前完成)
from langchain.agents import load_tools, initialize_agent
from langchain.agents import AgentType
from langchain.llms import OpenAI
# 设置OpenAI API密钥(假设已设置环境变量或替换为实际密钥)
import os
os.environ["OPENAI_API_KEY"] = "<YOUR_OPENAI_KEY>"
# 1. 准备大型语言模型(LLM)
llm = OpenAI(temperature=0) # 使用OpenAI的GPT-3.5/4接口
# 2. 加载工具:这里我们使用 LangChain 内置的计算器和搜索工具
tools = load_tools(["python_repl", "serpapi"])
# "python_repl" 工具用于执行Python代码(可当计算器),"serpapi" 用于搜索网络
# 3. 初始化Agent
agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)
# 4. 提供一个用户问题,Agent 将自主决定是否调用工具
query = "请问法国的人口是多少?它的平方又是多少?"
response = agent.run(query)
print(response)
代码说明:
- 我们使用
OpenAI()
来调用 OpenAI 的 ChatGPT 模型作为 Agent 的大脑。temperature=0
确保模型输出稳定可控。 - 通过
load_tools
函数加载两个工具:"Python REPL"(可执行 Python 表达式,充当计算器)和 "SerpAPI" 搜索工具(需要配置 SerpAPI API 密钥)。这些工具封装了特定功能,Agent 可以在决策中调用它们。 - 使用
initialize_agent
创建 Agent,指定AgentType.ZERO_SHOT_REACT_DESCRIPTION
意味着使用 LangChain 提供的 ReAct 型代理模板,让模型零样本地学会 ReAct 决策模式。 - 提出一个复杂问题:"法国的人口是多少?它的平方又是多少?"。这个问题涉及查找法国人口(知识)以及计算平方(算术)。Agent 将判断首先使用搜索工具获取法国人口,然后调用Python计算平方,最后综合给出答案。
agent.run(query)
会打印详细的决策过程(因verbose=True
),包括 Thought/Action/Observation 等步骤,最终返回答案。
**预期输出:**Agent 可能先通过搜索工具找到"法国人口约6700万",然后用计算器算出其平方(约4.49e14),最后回复类似:"法国人口约6700万,那么它的平方约为4.49×10^14。" 整个过程中无需人工干预,体现了Agent自主推理和行动的能力。
2.5 应用场景与优缺点
应用场景: AI Agent 作为一种通用的智能决策与执行单元,在各行业有广泛应用前景。例如:
- 自动化助手:个人助理(如日程管理、邮件回复)、客户服务机器人(自主解决客户问题)等。
- 数据分析与操作:让Agent充当数据分析师,自动从不同数据源收集信息、生成报表,或作为运维Agent自主执行脚本、监控系统状态。
- 内容创作:Agent可以帮助生成文案、绘制简单图片(调用绘图API)等,成为创意领域的辅助。
- 科研助理:在科研中自动检索文献、总结比较结果,甚至自主设计实验步骤。
- 复杂决策支持:例如在游戏AI中,多智能体协作控制NPC;在商业决策中,不同代理分析市场、财务等数据后协同提出方案。
优点:
- 自主性高:Agent 能自主分解任务和调用工具,减少人为干预,实现端到端自动化。
- 灵活适应:基于LLM的代理具有通用性,可以应用于未明确编程的新问题,通过提示引导就能解决多样任务。
- 可扩展性:通过增加工具或与其他Agent协作(MCP),可以扩展Agent能力边界,应对更复杂任务。
- 自然交互:Agent面对用户时,仍以自然语言交流,复杂内部决策对用户透明,从而提供友好体验。
缺点:
- 不可预测性:由于依赖LLM决策,Agent 有时可能产生意外行为或错误步骤,需要监控和约束。例如可能调用错误的工具或曲解指令。
- 错误传播:如果Agent在多步推理中早期做出错误决定,可能累积导致后续步骤都走偏,需要设计反馈机制让Agent自我纠正。
- 资源开销:完整的Agent一次任务可能调用多轮LLM接口和工具,成本和延迟都比单次问答高。尤其大型模型调用开销大,部署Agent需权衡性能。
- 实现复杂度:开发一个可靠的Agent系统需要精心设计提示、工具接口和协作协议,调试困难。此外确保安全(避免Agent误用有害工具)也是挑战。
总的来说,AI Agent 为自动化复杂任务带来了前所未有的灵活性,但仍需结合良好的工程实践(监控、限制、反馈学习)才能安全、高效地应用于实际场景。
3. Prompt(提示词)
3.1 定义和技术背景
**Prompt(提示词)**是指我们提供给大型语言模型的输入文本,用于引导模型产生期望输出的指令或问题。简单来说,Prompt 就像是对 AI 模型下达的一道指令,它可以是一个问题、一段描述、几句话的场景设定,甚至包含多轮对话的上下文。通过精心设计 Prompt,用户可以在不改变模型参数的情况下,让同一个模型执行不同任务或产生风格各异的回答。
提示词的重要性随着 GPT-3、GPT-4 等强大模型的问世而凸显。由于这些模型具备"少样本学习"能力,一个清晰、详细的 Prompt 能极大影响模型输出质量。这引出了**提示工程(Prompt Engineering)**这一概念:通过优化 Prompt 的措辞、结构和内容,最大程度发挥模型潜力。提示工程被视为一种新的技能和实践领域,甚至催生了专职的"Prompt Engineer"职位。
技术背景方面,Prompt 的有效性源于大模型的预训练原理。GPT 等模型在训练过程中学习了语言的模式和知识,推理时,它会尝试继续人类给出的提示文本。因此提示其实提供了"语境"和"示范",模型会在这种语境下作答。例如,通过在 Prompt 中加入示例问答(few-shot 提示),模型能按照示例模式回答新问题。
需要注意的是,Prompt 不仅用于文本生成任务。在图像生成(如Stable Diffusion)中,描述图像内容的文字也是 Prompt;在代码生成、对话等任务中,同样依赖 Prompt 来引导。所以 Prompt 是一切生成式AI交互的起点,它定义了模型该"扮演什么角色、执行什么任务"。
3.2 工作机制与核心流程
从模型交互流程看,Prompt 是进入模型的输入,LLM 根据 Prompt 生成相应的输出。构造和使用 Prompt 时,有一些重要机制与技巧:
-
指令与上下文:Prompt 通常包含明确的指令部分,告知模型需要什么。例如:"请翻译以下句子..."。此外,可以在 Prompt 中提供上下文信息或限定条件,让模型参考。例如提供背景知识段落,再提问相关问题。上下文窗口(Context Window)限制了Prompt长度,过长的Prompt可能被截断。
-
Few-shot 提示:在 Prompt 中给出一系列范例(输入->输出)来示范任务,模型会据此归纳模式再回答实际问题。这对于没有经过专门微调的模型特别有用。比如要求模型列举项目信息,可在Prompt内先举一两个例子。
-
角色设定 :通过在 Prompt 中假定模型的身份或风格(如:"你是某某专家..."),可以约束模型回答的语气和内容。这实际利用了模型的系统消息或在Prompt开头声明角色,让模型在该角色语境下回答,更具一致性。
-
明确要求输出格式:如果需要特定格式输出,可以在 Prompt 里直接说明。如要求列表、JSON格式、只给出数字等。尽管模型有时会偏离要求,但明确提示通常能增加准确率。在OpenAI的新功能中,引入了函数调用/格式控制等手段增强这方面,但在无特殊接口时,详细说明格式仍是主要方法。
-
迭代提示:有时初次Prompt结果不理想,可以基于输出再给模型新提示进行调整。这种逐步 refine 提示或多轮对话也是提示工程的一部分,即通过对话引导模型逼近期望答案。例如模型先给出思路,用户再提示"请更详细展开第二点"。
-
提示长度和信息量 :理想的 Prompt 需要在提供充分信息和简明易懂之间平衡。如果过于简短,模型可能无法明确你的需求;过长又可能淹没关键信息。通常要确保指令清晰 (明确要做什么)且具体(提供必要细节)。例如,与其问"Who won the election?"不如具体为"2023年巴拉圭大选由哪个政党获胜?"。
提示的工作机制可看作是模型的条件生成:用户提供条件(Prompt),模型依据条件在其知识和语言分布上采样生成响应。因此用户对 Prompt 的迭代优化,实际上是在试图找到能让模型以高概率给出正确答案的条件表达。这也是 Prompt Engineering 成为一门艺术的原因------它并非精确科学,而更像与模型对话、摸索模型"脾气"的过程。
3.3 与其他概念的关系
Prompt 作为与 LLM 交互的接口,几乎与本报告涉及的所有概念都有直接关系:
-
AI Agent:Prompt 是 Agent 决策过程中的关键。在 Agent 场景下,不仅用户给Agent下达的任务描述是一个Prompt,Agent在内部与LLM交互也依赖Prompt。例如Agent会动态生成Prompt来告诉LLM目前的观察结果和可选行动,让LLM输出下一步决策。可以说,Prompt是Agent大脑思考的语言。因此Prompt工程在Agent开发中尤为重要,需要设计模板涵盖工具使用格式、思维链格式等。
-
RAG(检索增强生成):在RAG流程中,Prompt起到了将检索到的信息融入模型输入的作用。具体做法是将用户问题和检索结果拼接形成一个长Prompt,再交给LLM生成答案。这被称为"提示融合"或"提示模板"。例如常见的提示模板是:"基于以下文档回答问题:<检索内容>。问题:<用户问题>。回答:..."。这个Prompt明确要求模型只根据提供文档内容回答,从而减少幻觉。所以RAG非常依赖精心设计Prompt来让模型引用检索信息。
-
Function Calling:OpenAI 的函数调用实质上是通过特殊的系统Prompt引导模型输出JSON结构。当开发者提供函数说明给模型时,底层也是把这些说明插入Prompt上下文中,如"可用函数列表及用法..."等。模型学习到这个模式后,会在满足条件时输出函数调用格式而非自然语言回答。因此,对模型而言,函数调用也是Prompt影响下的一种输出形式。开发者也可以通过提示直接要求模型输出JSON,即一种手工的函数调用模拟。总之,Prompt在函数调用机制中无处不在------从描述函数契约的提示,到引导模型选择调用。
-
MCP(多智能体协作协议):MCP定义了Agent间通信格式和内容,而这些通信本质上也是Prompt。例如Agent A 给Agent B发送一段消息,Agent B 会将此消息作为Prompt的一部分来生成回应。因此MCP消息可以视为在不同AI之间传递的Prompt。遵循统一协议格式有助于Prompt被正确解析利用。此外,MCP环境下,每个Agent通常有自己的角色和职责,这些也反映在各Agent的系统Prompt中(如"你是负责法律咨询的Agent")。因此,在多Agent协作中,需要为每个Agent设计适合其角色的Prompt,同时MCP保证这些Prompt/消息在Agent间传递顺畅。
总结来说,Prompt 是大型语言模型发挥作用的输入载体,其他概念都是在此基础上构建的更高层机制。无论是Agent调用工具,还是多Agent对话,这些复杂行为最终都要转换成文本交给LLM,所以都依赖于恰当的Prompt设计。可以说,Prompt是连接人类意图与AI行为的桥梁,在AI应用中居于核心地位。
3.4 示例场景与代码
**示例场景:**假设我们要用 OpenAI 的 GPT-3.5 模型搭建一个简单的对话问答接口。我们希望模型以特定风格回答,比如扮演一个幽默的助理。同时我们需要演示如何通过 Prompt 控制模型输出格式,例如让模型在回答后附上一个Emoji表情。
下面通过 Python 代码示范如何构造 Prompt 并调用 OpenAI API 得到回答。
python
# 安装openai库: pip install openai (假设已安装)
import openai
openai.api_key = "<YOUR_OPENAI_API_KEY>"
# 构造提示词 Prompt
system_prompt = "你是一个幽默风格的中文助手。回答问题时措辞风趣,但信息准确。"
user_question = "人工智能和机器学习有什么区别?请用一句话回答。"
# 使用 ChatCompletion 接口调用模型
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": system_prompt}, # 系统消息,设定助手角色和风格
{"role": "user", "content": user_question + " 请在回答末尾加上一个合适的表情符号。"}
],
temperature=0.7,
)
answer = response.choices[0].message["content"]
print(answer)
代码说明:
- 设置
system_prompt
明确模型的角色:"一个幽默风格的中文助手"。系统消息可以被视为一种特殊的 Prompt,用于规定模型整体语调和身份。 - 用户消息中,不仅包含实际问题"人工智能和机器学习有什么区别?",还进一步要求输出格式:"请用一句话回答,并在末尾加一个表情符号"。这部分也是提示词,指导模型如何组织答案。
- 调用
openai.ChatCompletion.create
时,将消息列表传入,其中包括系统角色和用户消息。我们选用gpt-3.5-turbo
模型,并设置了一定的 creativity (temperature=0.7
)。 - 模型返回的
answer
就是根据 Prompt 生成的回复文本。
**预期输出:**模型可能返回: "人工智能是广义的模拟人类智能的技术领域,而机器学习是其中让机器通过数据经验自动改进的一个子集😉" 可以看到,它按照要求给出了幽默但准确的一句话回答,并在句末加了一个眨眼笑的Emoji。这正是我们通过 Prompt 控制得到的效果。
通过这个示例可以体会到:调整 Prompt 中的措辞(比如要求"一句话回答"或加表情)会直接影响模型输出。如果去掉幽默风格和表情要求,模型将给出更正式的回答。因此,根据应用需求设计 Prompt,对实现所需功能非常关键。
3.5 应用场景与优缺点
**应用场景:**Prompt 广泛存在于各类基于LLM的应用中,下面举几个典型场景:
- 问答系统:用户问题直接作为Prompt喂给模型,模型返回答案。这是最直接的提示-应答场景。
- 创意内容生成:给模型提示"帮我写一首关于春天的诗"或提供一个故事开头,模型续写诗歌或故事。
- 代码生成与调试:描述想实现的功能,让模型生成代码;或贴出错误日志,请模型诊断问题。这些描述都是Prompt。
- 对话聊天机器人:每一轮对话用户输入都是新的Prompt的一部分,结合上下文历史形成完整Prompt发给模型。
- 教育和培训:利用Prompt引导模型扮演老师,出题测验学生;或扮演学生练习对话,这些都是通过设计不同提示实现角色扮演。
优点:
- 无需训练,灵活快速:通过更改Prompt就能切换任务或要求,无需训练模型权重。这使得同一模型可以零门槛地服务多种用途。
- 人性化控制:Prompt以人类自然语言编写,更直观易用。开发者或用户可以直接用语言调整AI行为,而不必懂模型内部细节。
- 可解释性:在一定程度上,Prompt提供了AI输出的依据,人们可以从提示中理解为什么模型会那样回答(虽然模型仍可能不按常理出牌,但提示是显性的影响因素)。
- 快速迭代:可以方便地试验不同提示措辞,观察模型响应变化,从而逐步改进。这种试错成本比改模型低得多。
缺点:
- 不稳定性:Prompt 对输出的影响有时不确定,稍微不同的措辞可能导致显著不同结果,需要大量试验经验。提示工程仍然带有一定"玄学"成分。
- 上下文窗口限制:Prompt长度受模型上下文窗口限制,过长的提示或大量的few-shot示例可能会超出上下文长度,使模型忽略部分内容。这在处理长文档时尤其麻烦,需要借助分段提问等策略。
- 模型误解或忽略提示:有时模型可能忽略指令的一部分,特别是在复杂提示下。例如要求输出JSON,但模型未完全遵守格式。这需要加强提示或借助函数调用等手段。
- 安全与偏见:不当的Prompt可能诱导模型输出有害内容(Prompt Injection攻击)或带出模型训练中固有的偏见。如果提示包含偏颇信息,模型往往不加判断地沿用。因此,Prompt设计也需考虑道德和安全准则,避免恶意利用。
总之,Prompt 是威力强大的"双刃剑",善用者能让AI如虎添翼,滥用或不当使用则可能出现问题。在实际应用中,通常需要结合Prompt工程技巧和必要的安全过滤,来获得稳定可靠的模型输出。
4. RAG(Retrieval-Augmented Generation,检索增强生成)
4.1 定义和技术背景
**RAG(Retrieval-Augmented Generation,检索增强生成)**是一种将信息检索与生成式AI相结合的技术方法,旨在提升大语言模型回答的准确性和时效性。简单来说,RAG在模型回答用户查询之前,先从一个外部知识库中检索出相关的信息,并把这些信息提供给模型用于作答。这样模型不仅依赖自身训练语料中的知识,还能"现查现用"最新或领域专门的信息,从而克服纯生成模型知识固化和幻觉的问题。
技术背景方面,GPT-3 等大型模型虽然掌握了海量知识,但存在两个限制:
- 知识截止:模型参数固化了训练时的知识,无法更新。如果问到训练后发生的事,模型会不知道或编造。
- 参数容量有限:即使训练语料包含某专业细节,模型不一定准确记忆调取。如果用户问到长尾专业问题,模型可能给出错误回答或幻觉。
RAG 正是为了解决上述问题提出。其核心思想是利用经典的**信息检索(IR)**技术为生成模型提供外部"记忆"。这一理念与开放域问答系统类似,但RAG将检索紧密融入生成流程。早期的开放域QA通常:查询 -> 找文档 -> 用阅读器模型抽取答案。而RAG更灵活,让生成模型直接把检索结果整合进回答中。
RAG的典型实现源自Facebook AI(Meta AI)在2020年的论文,将Dense Passage Retrieval (DPR)与生成模型结合,开创了这一思路。此后,RAG在对话机器人、知识问答等场景广泛应用。近来也有很多开源框架(如 Haystack、LangChain、LlamaIndex)支持方便地搭建RAG管道,使开发者不用训练模型就能实现基于自身数据的问答系统。
4.2 工作机制与核心流程
RAG 的工作流程可以分为两个主要阶段:检索(Retrieve) 和 生成(Generate),通常外加一个预处理/后处理步骤:
-
查询处理(Query Processing):用户提出问题后,将问题文本转换为可用于检索的查询格式。如果是语义向量检索,则需要将查询编码为向量;如果是传统关键词检索,则可能对查询分词、扩展等。多数现代实现使用预训练语言模型将查询编码成向量表示,以进行语义搜索。
-
检索(Retrieve) :在预先构建的知识库中,根据查询找到相关信息。知识库可以是非结构化文档集合、FAQ库,甚至是数据库。实现上,常用向量数据库 或搜索引擎。向量数据库例子包括 FAISS、Pinecone 等,它们存储了文档向量;搜索引擎如 Elasticsearch 则基于反向索引。检索阶段返回若干条最相关的文档或文本片段,以及它们的相关度分数。例如,对于"什么是量子计算?"的提问,检索模块可能返回一段定义量子计算的百科文本。
-
生成(Generation) :将检索得到的文本与原始问题合并,构造成 Prompt 输入给生成模型,让模型参考这些资料来生成答案。这一过程通常通过提示模板实现,比如:"根据以下资料回答问题:{文档片段}。问题:{用户问题}。"。由于模型能从提供的资料中找到关键事实,它回答时更有依据。模型输出即为最终答案文本。这一步实际上就是一个受控的Prompt→Completion过程。
-
后处理(Post-processing):可选地,对模型输出进行修饰或验证。例如可以增加一个模块检查答案是否引用了提供的文档内容,或者在答案后附上引用来源(实现"可查证性")。有些RAG系统还会对答案进行纠错,或者如果答案不完整,尝试新的检索-生成迭代。
通过上述机制,RAG将检索与生成无缝衔接。举个例子,假设用户问:"火星有大气层吗?"。纯LLM可能不确定,甚至瞎猜。而RAG流程是:先检索火星大气的资料(比如Wiki上写着"火星有稀薄的大气层,主要成分二氧化碳..."),然后模型在Prompt中看到这段资料,就会回答:"有,火星有一层稀薄的大气,主要由二氧化碳构成。"。这样既准确又有依据。
一个关键点是,RAG减轻了模型记忆负担 ,将知识存储外部化,从而降低幻觉发生率。模型不需要凭空回忆,只需基于提供的文档措辞回答。当然,如果检索失败或检索内容本身错误,模型仍可能出错,所以构建高质量知识库和有效检索至关重要。
4.3 与其他概念的关系
-
Prompt:RAG 可以被视作一种特殊的提示工程,即通过在 Prompt 中加入检索资料,来影响模型输出。这些资料其实就是扩充了模型的上下文。因此,RAG对Prompt设计很有讲究,需要选择哪些检索结果、如何拼接、加哪些引导语,以确保模型真正"读懂"资料并用其回答,而不是忽略资料。另外,如果要模型引用来源,可在Prompt里要求它按某格式输出引用。这些都属于Prompt技巧在RAG场景的应用。
-
AI Agent :在Agent体系中,RAG常作为一个工具供Agent调用。例如Agent在推理过程中识别出自己对某知识点不了解,就会采取一个"Action"调用检索工具,从而获取信息。LangChain等框架已将RAG封装成Retrieval工具,Agent可以通过类似function calling方式请求检索。因此,Agent和RAG经常结合使用:Agent负责驱动多步对话和决策,RAG负责在需要时提供实时知识。另一方面,有些RAG系统本身就是简化版的Agent(固定的两步:检索->回答),没有复杂决策,因此Agent可以看作RAG的广义扩展。
-
Function Calling :OpenAI的函数调用机制可以用于RAG。例如可定义一个
search()
函数,让模型在需要时输出search("查询词")
,由程序捕获后执行检索,再将结果通过函数信息传回模型。这其实是一种Agent化的实现。但即使不借助function calling,传统RAG也是通过硬提示实现函数调用的思想:模型根据Prompt内容决定是否需要利用资料。在更广泛场景中,RAG属于工具调用的一类,因此function calling可以看成支持RAG的一种手段。Haystack 等也支持将生成模型和检索组件组合,从而一部分功能由函数/模块完成,一部分由模型完成。 -
MCP(多智能体协作) :如果有多个Agent协作解决复杂任务,RAG可以作为知识源供所有Agent共享。例如一个法律顾问Agent和一个财务顾问Agent在讨论某商业问题时,二者都可以访问同一个公司内部知识库(通过各自的RAG组件)以获取事实数据,从而减少彼此空谈无依据的情况。MCP本身不规定Agent如何获取知识,但协作中共享的信息很可能来自RAG检索。此外,在多Agent对话中,如果一个Agent引用了某资料,MCP协议可以要求他提供来源,这又涉及RAG的输出格式。总体而言,RAG在协作环境中扮演"智能图书馆"的角色,为Agent团队提供知识支持。
4.4 示例场景与代码
**示例场景:**构建一个简易的知识库问答系统,让用户就给定文档提问,系统会检索相关段落并回答问题。我们将使用 FAISS 向量索引和 OpenAI 模型来实现这一RAG流程。知识库内容假定为几段维基百科文本。
python
# 安装所需库: pip install faiss-cpu langchain openai (假设已安装)
from langchain.text_splitter import CharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS
from langchain.chains import RetrievalQA
from langchain.llms import OpenAI
# 假设我们有一些文档文本
docs = [
"火星(Mars)是太阳系中第四颗行星。火星有稀薄的大气层,主要成分是二氧化碳。",
"金星(Venus)是太阳系中第二颗行星。金星有浓厚的大气层,主要成分是二氧化碳,也被称为晨星或昏星。",
# ... 其他文档
]
# 1. 将文档切分为段落并创建向量索引
text_splitter = CharacterTextSplitter(chunk_size=100, chunk_overlap=0)
docs_chunks = [chunk for doc in docs for chunk in text_splitter.split_text(doc)]
embeddings = OpenAIEmbeddings() # 使用OpenAI文本嵌入模型将文本编码为向量
vector_store = FAISS.from_texts(docs_chunks, embedding=embeddings)
# 2. 构建检索器和QA链
retriever = vector_store.as_retriever(search_kwargs={"k": 2})
qa_chain = RetrievalQA.from_chain_type(
llm=OpenAI(temperature=0),
chain_type="stuff", # 将检索结果直接拼接到prompt的简单链
retriever=retriever,
)
# 3. 用户提问并运行 QA 链
question = "火星的大气主要成分是什么?"
result = qa_chain.run(question)
print(result)
代码说明:
- 准备知识库 :这里我们手动定义了
docs
列表,每个元素是一段简短的百科描述(火星和金星作为示例)。在真实场景,可从文件或数据库加载文档。 - 创建向量索引 :使用 LangChain 的
CharacterTextSplitter
将长文档切分成较小块(chunk_size=100字符),以保证检索粒度。然后使用OpenAIEmbeddings
将文本块转为向量,并利用 FAISS 建立向量索引(FAISS.from_texts
)。这一步实现了将文本语义映射到向量空间,方便后续相似度检索。 - 构建 RetrievalQA 链 :通过
vector_store.as_retriever()
获取一个检索器对象,每次检索返回相关的2条文本块。然后用RetrievalQA.from_chain_type
创建一个问答链。参数说明:llm采用OpenAI模型(例如gpt-3.5),chain_type="stuff"表示将检索的文本直接附加在Prompt后(这是最简单的RAG融合方式,别的类型比如 map-reduce 适合长文档场景)。这样,每次用户问问题时,流程会先用retriever找出文本块,再把这些块和问题一起喂给LLM产生答案。 - 提问:"火星的大气主要成分是什么?"。根据知识库,火星段落提到"大气主要成分是二氧化碳"。我们的链会检索到火星相关文本,然后OpenAI模型应当据此给出答案。
- 打印结果。
预期输出:"火星的大气层主要由二氧化碳构成。"
可以看到,RAG流程保证了答案的准确性,因为模型在Prompt中看到了火星那段资料。如果我们改问"金星的大气成分?",系统会检索金星段落并回答"金星大气主要成分是二氧化碳"。如果问一个知识库里没有的,比如"木星有大气吗?",检索可能找不到相关内容,这时模型可能会回答"不知道"或猜测。这提示我们,如果知识库不涵盖问题,RAG系统应设计成回答"未找到答案",以避免模型乱答。
4.5 应用场景与优缺点
应用场景:
- 企业知识问答:将公司文档、手册、数据库接入RAG,实现内部问答系统。员工可查询政策、技术文档等,模型从更新的资料中作答,确保准确率和保密性。
- 聊天机器人:为对话机器人接入常识库或新闻库,让其回答实时事实类问题(如天气、股票等)而不再凭训练知识猜测。例如微软的Bing Chat就大量使用了网络检索(RAG)来回答最新信息。
- 客服和FAQ:把常见问答集或产品说明作为知识库,RAG机器人可以理解用户问题语义并检索匹配答案段落,再生成回复,达到智能客服效果。
- 医学/法律助理:这些领域知识更新快且专业术语多。将最新医学文献或法律条文作为知识源,RAG助手能够根据查询提供有依据的专业回答,提高可信度。
- 学术研究:科研人员可用RAG构建文献问答系统,提问时直接从大量论文中检索答案片段。这比传统检索返回整篇论文再人工翻阅效率高得多。
优点:
- 减少幻觉、提高准确性:模型回答基于检索内容,有据可依,大幅降低了胡编乱造的可能。特别在事实性问题上,RAG能提供可信来源支撑答案。
- 知识实时可更新:知识库更新即可影响回答,无需耗时耗资地重新训练模型。这对需要频繁更新信息的应用(新闻、行情等)非常关键。
- 参数需求低:相比直接训练一个包含所有知识的大模型,RAG只需一个通用LLM配合外部存储,减少了模型参数量和训练难度。许多场景下,一个中等大小模型+一个大知识库就能胜任任务。
- 答案可解释:通过提供原始文档来源,用户可以验证答案正确性。这对要求可追溯性的领域(医疗、法律)尤为重要,增加了AI输出的透明度和可信度。
缺点:
- 检索质量依赖知识库:如果知识库缺失相关信息或检索算法不佳,模型将"巧妇难为无米之炊"。它可能只能凭记忆硬答或者直接说不知道。因此需要投入构建全面、高质量的知识库,并调优检索算法(向量训练、索引参数等)。
- 上下文长度限制:检索来的文档太长时,无法全部塞进Prompt,只能取部分,这可能遗漏关键信息。长文档问答需要分段、多轮摘要等复杂流程,增加实现难度。
- 潜在信息泄露:如果知识库中有敏感信息,被检索出后模型会直接使用,可能泄露给不该看到的人。因此在企业应用中,要做好权限控制和安全审查,或对知识库做脱敏处理。
- 多轮对话一致性:在对话系统中,多轮提问的上下文关联会影响检索。例如用户后续提问省略主语,需要从对话历史推断才能检索正确内容。这种多轮情境给RAG增加了复杂度,需要更智能的检索策略。
总体而言,RAG将语言模型的生成能力与信息检索的精确匹配结合,取长补短,已成为实用AI系统的标配之一。尤其在追求正确性的应用场景下,RAG提供了一条无需训练却高效增强模型的方法。不过,要充分发挥其优势,仍需在知识库建设和系统工程上投入,并根据具体场景优化检索和提示策略。
5. Function Calling(函数调用)
5.1 定义和技术背景
**Function Calling(函数调用)**指的是让大语言模型以调用预定义函数的方式来输出结果的一种机制。在OpenAI API的语境下,函数调用功能允许开发者为模型提供一系列函数的接口说明,使模型可以选择输出一个JSON对象来调用某个函数,并填写所需的参数。这样,模型的回答不再仅仅是自然语言,而可以是结构化的函数调用指令,由外部程序执行后,再将执行结果反馈给模型继续处理。
这一技术最初由OpenAI在2023年中推出,目的是让模型的输出更可控和结构化。在此之前,开发者往往通过提示工程让模型以JSON格式回答,但模型容易格式错误或遗漏字段。函数调用从模型生成机制上支持JSON schema,确保输出严格符合所定义的函数参数格式。此外,这项功能也是 ChatGPT 插件系统的基础:当用户在ChatGPT中询问天气,模型其实是在内部以函数调用形式调用了一个天气查询插件。
技术背景方面,函数调用可被视作模型推理过程与传统编程流程的结合。大型语言模型长于自由文本生成,但短于执行精确计算或访问实时数据。而通过函数调用,我们可以把确定性处理 (如数学计算、数据库查询、调用API)交给程序函数来完成,让模型专注于不确定性处理(语言理解、生成)。模型通过识别何时需要函数,生成调用指令,然后由外部完成操作,相当于让AI "长出手脚"可以操作工具,同时保证这些操作按预期格式进行。
值得一提的是,函数调用并非OpenAI专有思想。早期一些Agent框架已让模型输出特殊标记来调用工具,只是没有严格模式。OpenAI将其标准化并集成到API,使得开发者无需自己实现解析器,就能方便地把模型和代码功能结合起来。这在2025年已经成为主流,大部分新型对话AI系统(Anthropic, Azure OpenAI等)都支持类似功能调用或工具使用接口。
5.2 工作机制与核心流程
函数调用的运作涉及模型和调用者(程序)之间的配合,核心流程如下:
-
函数描述提供 :开发者在调用 ChatCompletion API 时,通过参数提供函数定义列表给模型。每个函数定义包含函数名、描述和参数的JSON模式(schema)。例如定义一个
get_weather
函数,描述它获取天气,参数为城市名和温度单位。这些定义在对话的系统层面传递给模型,模型据此了解可以使用哪些函数及如何使用。 -
模型生成函数调用意图 :当模型根据用户消息推理时,如果判断需要调用某个函数(例如用户问天气),它会选择输出一个特殊消息,其role为"assistant",内容包含一个
function_call
字段,指明函数名和填充的参数。例如:json{"role": "assistant", "function_call": { "name": "get_weather", "arguments": "{\"location\": \"北京\", \"unit\": \"C\"}" }}
这实际上是模型的输出,被OpenAI API捕获后,作为返回结果的一部分交给开发者。注意模型并非真的执行了函数,它只是把调用所需的信息组织成JSON字符串。
-
调用方执行函数 :客户端(开发者的代码)收到模型输出后,检测到其中的
function_call
。此时就由客户端实际去调用对应的函数,将JSON参数解析成函数参数。例如调用get_weather(location="北京", unit="C")
。函数可以访问数据库或外部API拿到所需数据(如天气温度)。 -
函数结果反馈模型:函数执行后,将结果转成字符串形式,作为一个新的消息发给模型,role设为"function",name为函数名,content为函数返回结果(可以是JSON或文本)。这一步相当于告诉模型"你调用的函数返回了这些内容"。
-
模型利用结果继续对话:模型拿到函数返回值,会将其视作对话的一部分,结合用户最初请求,最终生成一个正常的回答消息。比如函数给出了天气数据,模型可能回复用户:"北京今天25摄氏度,晴间多云。"。这一回复过程模型知道函数调用已结束,不会再输出 function_call,而是产生活动用户可见的答案。
综上,函数调用实际形成了一个双轮对话:用户→模型(请求函数调用)→函数→模型(拿结果答复)。这一切对最终用户是透明的,他们只看到问题和最后的答案。
函数调用机制关键在于什么时候调用哪种函数由模型自行决定。这取决于我们如何设计系统Prompt,让模型明白哪些情况下用函数。例如系统提示可以列举函数功能:"如果用户问天气,就调用get_weather函数。" 模型通过学习和Few-shot可以掌握这种模式。OpenAI通过对模型进行微调,已经让GPT-4、GPT-3.5系列在看到函数定义时倾向于按需调用函数。
5.3 与其他概念的关系
-
AI Agent :函数调用可以看作Agent调用工具的一种实现方式。传统Agent框架里,模型输出像
Action: Search
的指令文本,然后由解析器执行。函数调用用更结构化的JSON让模型输出function_call
,本质一样:都是模型决定用某工具,然后执行并拿结果。很多Agent系统现在都整合了OpenAI函数调用,使LLM成为决策引擎而具体操作由代码完成。例如LangChain Agent已经支持函数调用作为其工具执行backend,使Agent决策稳定且易于扩展新工具。因此,函数调用是Agent体系中模型与工具交互的标准接口之一。 -
Prompt:函数调用的触发和参数选择,与Prompt的设计密不可分。开发者需要在系统Prompt中清晰告诉模型何种场景用何函数,以及参数格式要求。这其实是一种提示工程,只不过OpenAI训练降低了提示难度。但在自定义场景下,可能要加入few-shot示例让模型学会正确调用。另一方面,函数调用减少了很多复杂提示的需求(过去要引导模型输出JSON,现在不需要手工提示,只靠函数定义就行),所以在Prompt工程上简化了开发者工作。此外,函数调用返回结果传给模型也是以消息形式,这也可以看作Prompt的一部分,模型会将之与原用户询问一起考虑后再回答。
-
RAG :检索增强生成可以通过函数调用来实现。比如定义一个
search_docs
函数,当模型需要外部知识时就会调用它,然后函数检索资料返回给模型。相比于硬拼接资料进Prompt,函数调用方式让流程更明晰,有无资料也更可控(模型不会在没资料时硬编)。LangChain等框架已经提供了基于函数调用的RAG链路,将向量检索封装为函数。因此函数调用可以视为RAG的一种实现细节,用于规范模型获取信息的流程。 -
MCP(多智能体协作):在多Agent协议中,各Agent可能扮演不同功能模块,比如一个Agent专门算数,另一个负责语言回答。函数调用可以类比这种协作,只不过这里"函数"是非智能模块而不是Agent。MCP本身关注Agent通信协议,但如果把一个函数看作一个特殊Agent(只接受结构化输入,返回输出),那么函数调用过程就像Agent向这个"工具Agent"发消息,得到回复。因此,多Agent系统中可以混合使用函数调用,把一些定式任务交给函数型Agent,从而让真正的AI Agent专注高层协作。
5.4 示例场景与代码
**示例场景:**实现一个能够回答用户数学问题的对话机器人。对于简单问题模型直接回答,对于需要计算的问题则通过函数调用使用计算器函数。我们将定义一个简单的 calculator
函数,让模型学会在需要时调用它。
python
import openai
openai.api_key = "<YOUR_OPENAI_API_KEY>"
# 定义函数列表,包含一个计算器函数的描述
function_defs = [
{
"name": "calculator",
"description": "执行算术计算,返回计算结果。",
"parameters": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "需要计算的算术表达式,例如 '2+2' 或 'sqrt(16)'"
}
},
"required": ["expression"]
}
}
]
# 模拟实现 calculator 函数
import math
def calculator(expression):
try:
# 为安全,只允许有限的数学符号
allowed_chars = "0123456789+-*/().sqrt "
if any(ch not in allowed_chars for ch in expression):
return "错误:包含非法字符"
# 使用 eval 计算表达式值
result = eval(expression, {"__builtins__": None, "sqrt": math.sqrt})
return str(result)
except Exception as e:
return f"错误:无法计算 {e}"
# 用户提问
user_question = "半径为5的圆的面积是多少?"
# 调用ChatCompletion,让模型尝试函数调用
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo-0613", # 使用支持函数调用的模型
messages=[{"role": "user", "content": user_question}],
functions=function_defs,
function_call="auto" # 模型自动决定是否调用函数
)
msg = response.choices[0].message
if msg.get("function_call"):
# 模型请求调用函数
func_name = msg["function_call"]["name"]
args = msg["function_call"]["arguments"]
import json
func_args = json.loads(args)
# 执行函数
result = None
if func_name == "calculator":
result = calculator(func_args.get("expression", ""))
# 将函数结果发回模型继续
second_response = openai.ChatCompletion.create(
model="gpt-3.5-turbo-0613",
messages=[
{"role": "user", "content": user_question},
{"role": "assistant", "function_call": msg["function_call"]},
{"role": "function", "name": func_name, "content": result}
]
)
final_answer = second_response.choices[0].message["content"]
else:
# 模型未调用函数,直接给出最终答案
final_answer = msg["content"]
print("AI回答:", final_answer)
代码说明:
-
定义
function_defs
列表,其中一个函数calculator
,描述其功能是执行算术计算,参数是一个字符串表达的数学表达式。这样模型就知道有这样一个函数可用。 -
提供
calculator
函数的Python实现,用于实际执行模型请求的算术计算。这里用Python的eval
简单计算,但实际应用中应注意安全,只允许安全表达式。 -
用户问题是问圆面积:"半径为5的圆的面积是多少?"。模型若懂就知道需要计算 π*5^2。
-
调用
openai.ChatCompletion.create
:- 模型用
gpt-3.5-turbo-0613
(支持函数调用的版本)。 functions=function_defs
将函数定义传给模型。function_call="auto"
表示让模型自由决定是否以及如何调用函数。
- 模型用
-
检查模型回复:
- 如果
msg["function_call"]
存在,表示模型请求函数调用。例如可能返回calculator("3.14159*5*5")
之类。 - 解析出函数名和参数字符串,用
json.loads
将参数JSON解析为字典。 - 匹配函数名为 "calculator",调用我们实现的
calculator()
函数执行计算,得到结果字符串。 - 准备再次调用 ChatCompletion,将用户提问、模型的函数调用请求、函数返回结果按顺序作为消息发给模型。这相当于把函数结果告诉模型。
- 模型这次会根据函数结果给出最终回答,提取
final_answer
。 - 如果模型第一步没有调用函数(可能直接就回答了),我们直接取它的回答内容。
- 如果
-
打印 AI 最终回答。
预期输出: 模型应识别这是需要计算的问题,会调用calculator函数计算 3.14159*5*5
(或类似表达)。calculator返回结果 78.53975
(左右)。模型二次回复可能输出:"半径为5的圆的面积约为78.54。"
这个示例展示了函数调用的完整流程:模型先输出函数名和参数,经过程序执行后,再得到最终答案。整个对话对最终用户是无缝的,他们只看到AI的答案而不感知其中用了函数。然而通过日志可以看到AI内部调用了计算器,从而确保了计算准确。
5.5 应用场景与优缺点
应用场景:
- 工具型对话机器人:函数调用可以让聊天机器人连接各种工具插件,如日历查询、酒店预订、文件操作等。用户用自然语言下指令,机器人通过调用相应函数(插件API)完成任务。例如用户:"帮我创建明天的日程提醒",模型调用calendar函数添加事件并回复完成。
- 结构化数据生成:当需要模型返回JSON、表格等特定结构数据时,使用函数调用定义schema,模型输出会严格符合格式。这在需要把AI结果传给下游程序时很有用,如填写表单、多段回答分类等。
- 代码助理:像Github Copilot Chat那样,可以定义函数让模型运行代码片段测试或查文档。模型写出代码后,通过函数调用execute_code运行,看结果再调整。这大幅提高编程问答正确率。
- 多步骤任务:通过定义多个函数,模型可逐步调用,从而拆解复杂任务。例如先调用search查资料,再调用translate翻译结果,最后组织回答。这种多函数组合让模型具备流水线能力。
- 机器人流程自动化 (RPA):把常用的业务操作(点击按钮、读写文件等)封装成函数,语言模型根据用户指令选择调用,能执行跨系统的操作流程。例如语音助手打开应用、读邮件、发送消息等,都可以建成函数供模型使用。
优点:
- 增强模型能力:模型借助外部函数可以完成原本做不到的操作(比如精算、数据库提取、系统控制),扩展了AI应用边界。
- 输出确定性强:通过函数schema约束,模型输出格式更可靠,不会随意改变字段名或忘记必要信息。这让AI更容易融入现有软件系统,因为接口契约清晰。
- 减少对Prompt的依赖:开发者无需穷举各种提示来诱导模型用某工具,只要提供函数定义和基本指导,模型即可学会。这降低了提示工程难度,尤其当工具很多时,不用写长篇提示描述每个工具。
- 高效交互:函数调用使一次用户请求可分解成多步模型+函数的闭环,无需每步都等待用户输入,提升了交互效率和用户体验连贯性。
缺点:
- 实现复杂度:开发者需要实现和维护这些函数(或插件),并确保其安全性。例如我们Calculator示例就要防范恶意表达式。函数调用增加了系统组件,调试时既要看模型又要看函数执行,出错源头更多样。
- 模型决策不透明:模型何时决定调用函数以及用哪些参数,可能不易控制。有时模型可能错误调用无关函数或参数不恰当,这需要在提示或函数设计上不断调优和防错。尽管可通过few-shot训练模型调用倾向,但仍有不确定性。
- 依赖模型支持:目前只有一些新版本模型支持函数调用。开源模型很多还不具备这能力(除非通过复杂prompt模拟)。因此在不同模型间移植时,可能失去这一便利,需要用其他方案替代。
- 安全与权限:给予模型调用外部函数的能力,如不加限制,可能导致风险。例如模型可能尝试调用文件操作函数删除重要文件(若被恶意指引)。因此需要在函数实现侧严格校验和设置权限,防止模型误用或用户利用模型注入恶意调用。
总结来看,函数调用机制为人机自然交互注入了"编程接口",让AI与传统软件结合更紧密。它有效平衡了AI的智能与程序的精确。但就像给予AI工具使用权一样,我们也需要制定使用规则 和防护措施,以确保这些强大的能力被正确、安全地使用。
6. MCP(Multi-agent Collaboration Protocol,多智能体协作协议)
6.1 定义和技术背景
MCP(Multi-agent Collaboration Protocol)通常指为多智能体系统设计的一套通用通信与协作协议,其目标是在不同AI Agent之间共享上下文、工具和记忆,以协同完成复杂任务。值得注意的是,MCP 也常解读为 Model Context Protocol(模型上下文协议),本质上强调为多个Agent提供结构化的共享上下文。
简单来说,在一个多Agent环境中,MCP规定了Agent之间如何交流信息、传递任务以及调用共享资源。就像网络中的TCP/IP协议标准化了不同计算机通信一样,MCP旨在标准化不同AI Agent框架(LangChain、Autogen、其他自定义Agent)之间的协作接口。通过MCP,不同开发平台的Agent理论上可以无缝对接,形成"AI智能体互联网"。
技术背景:随着AI Agent应用的发展,业界出现了许多Agent框架,如 Microsoft 的 Autogen、LangChain Agents、OpenAI Functions 等。这些框架之间原本互不兼容,各自Agent无法一起工作。而复杂任务往往需要多个Agent各司其职(如一个擅长规划,一个擅长执行)。为此,业界开始探索Agent间互操作标准,如微软提出的 A2A (Agent-to-Agent) 协议 以及贡献于社区的 MCP 等。这些协议提供统一规范,让Agent可以跨平台协作。
MCP 通常包含内容:消息格式(Agent发送消息应包含哪些字段,如 sender, receiver, content, context 等)、对话管理(怎么启动协作,怎么轮询发言)、工具共享(如何让一个Agent使用另一个Agent提供的工具)以及共享记忆(是否有公共的知识库或记忆区供Agent访问)。Autogen 框架中,MCP被用来让多个 ConversableAgent 通过群聊形式解决任务。可以把MCP想象成一个多方对话的规程:谁先说,怎么引用别人的话,群聊的频道和权限等等。
2025年,MCP 相关标准仍在演进中,但已被视为构建大规模多Agent系统的关键一步。有了协议,开发者就能像微服务那样组合AI Agent,实现1+1>2的效果。而微软、OpenAI等也在推动此生态,比如微软的Semantic Kernel也加入了对A2A/MCP的支持,用于跨企业协作的AI代理。
6.2 工作机制与核心流程
MCP作为协议,并非具体软件,而是一套约定。所以其"工作机制"体现在多Agent协作的流程上,可以概括主要环节:
-
会话初始化:当需要多个Agent协作时,首先建立一个共享会话上下文。MCP规定如何初始化会话,可能包括生成一个会话ID,确定参与的Agent列表,以及分配各Agent的初始角色或任务目标。比如一个问题需要三个Agent讨论,MCP会建立一个group chat,将三者都拉入,并发送任务描述给所有Agent。
-
消息格式:MCP定义了Agent之间交换消息的统一格式。通常每条消息包含发送方Agent标识、接收方(可能群体广播)、消息类型(如普通对话、工具请求、结果反馈)和内容。其中"内容"可以是自然语言,也可以是结构化数据(比如函数调用结果、知识引用)。统一的格式保证不同开发的Agent也能解析彼此信息,不会因为风格不同而沟通障碍。
-
回合交流机制:规定Agent对话的流程控制,比如是否按顺序发言或异步。简单情况是轮流发言,复杂情况可能有一个"主持Agent"协调谁该在何时发言。MCP可能支持两种模式:
- 群聊模式:所有Agent公用一个对话频道,每个消息有前缀标注是谁说的,其他Agent都能读。这类似人类会议讨论。
- 点对点模式:Agent可以私信某Agent或调用某Agent服务,有点像微服务RPC。MCP需要支持寻址不同Agent。 某些实现如Autogen支持GroupController管理群聊流程,确保不会乱。MCP负责定义这些控制消息的格式和流程。
-
上下文共享 :MCP关键就在于提供共享记忆/上下文。这可能通过一个共享的黑板(blackboard)系统,所有消息都记录其中,Agent能随时访问既往对话内容(除非权限限制)。也可能规定一个中央内存Agent或知识库,所有Agent可查询。通过上下文共享,Agent可以建立共同知识,不会各说各的。另外,如果有共用工具,比如一个数据库接口,MCP也要定义如何调度这个资源防冲突,以及结果广播策略。
-
冲突解决和决策合并:多Agent协作常会有观点或计划冲突,MCP有时需要提供决策规则。例如若两个Agent结论不一致,是否由某优先级Agent决定?或引入投票Agent仲裁?这一般属于协议高层。目前许多实现简单采用某Agent为主导(如一个Manager agent,其它为Worker)。MCP可能描述这种主从关系和决策优先权,让协作更有序。
-
任务完成与终止:MCP也定义如何结束一个多Agent会话。当达成目标或超时等,协议触发终止信号,Agent停止交流。可能由主持Agent发送一条"END_OF_DIALOG"消息或设置某标志。之后会话上下文归档,资源释放。
通过以上机制,MCP保障多个Agent可以像团队一样协同。举例:有用户请求"规划一个欧洲两周旅游行程并预算"。一套MCP下,可能这样:
- 系统创建会话,包括一个任务描述。
- 三个Agent:行程规划Agent、预算计算Agent、景点推荐Agent被加入。
- 按MCP规定次序对话:行程Agent先提出一个初步路线,景点Agent补充景点细节,预算Agent计算每段费用。他们互相发送消息,引用公共知识(通过MCP共有的地图数据工具)。
- 最后整合出一份完整方案,由行程Agent发送给用户,MCP会话结束。
这种流程的顺利进行,离不开MCP对消息和角色的规范,使各Agent各尽其职又能听懂对方。
6.3 与其他概念的关系
-
AI Agent:MCP是为AI Agent服务的协议,没有Agent就无所谓MCP。可以说MCP是Agent的"语言"和"规矩"。单个Agent在自身框架内有一套工具和memory,而MCP把多个Agent组织起来,共享部分这些资源。Agent在MCP环境下需要遵守协议,比如用协议指定格式说话,不然别的Agent可能无法解析。MCP也赋予Agent新的能力:一个Agent可以请求另一个Agent的帮助,如让擅长代码的Agent检查它生成的代码。这相当于每个Agent获得了一个AI同事网络。所以Agent是MCP的主体,而MCP是Agent协作的规则,两个概念紧密相连,共同实现更强的多智能体系统。
-
Prompt:在多Agent协作中,每个Agent实际上依然通过Prompt与各自的LLM交互。然而,MCP会对Prompt内容做规范。例如,当Agent A 收到Agent B的消息时,这段消息会被纳入Agent A的Prompt上下文,可能前面加上"B说: ..."。协议规定了这种插入格式。如果Prompt不规范,不同Agent模型可能误解。MCP也可能包含一些全局的system prompt,设定合作目标和语气。比如在群聊开始时广播一条系统消息:"你们是一个团队,目标是一起完成X任务。" 这会影响后续所有Agent各自的Prompt理解。所以MCP与Prompt工程交织在一起,为了让多模型对话顺畅,需要特别设计prompt模板符合协议。
-
RAG :多Agent环境往往涉及大量信息,有时某个Agent的专长就是信息检索(RAG Agent)。MCP可以让这个Agent为其他Agent服务。例如规划Agent说"我需要法国景点资料",可以通过协议请求检索Agent获取。这样RAG能力在多Agent中共享,相当于一个工具。协议需要定义检索请求/响应的消息形式,比如一个Agent发消息
{"type": "QUERY", "content": "法国著名景点有哪些?"}
,检索Agent回复{"type": "RESULT", "content": "...景点列表..."}
。这其实就是函数调用思想的Agent化,通过MCP传递。但在实现上,如果Agent框架内有RAG工具,也可以每个Agent自己用。不过共享一个检索Agent可以避免重复搜索和节省资源。在任何情况下,MCP需要考虑知识共享的问题。如果一个Agent检索得到资料,协议可以让资料对其他Agent可见,避免每个Agent各自搜一遍,提高效率和一致性。 -
Function Calling :函数调用和MCP都涉及"调用某种能力"的机制。不同在于函数调用是在模型和代码之间,而MCP是在模型和模型之间。不过,可以将某些Agent视作专门执行函数的Agent。例如,有提议将工具API封装成Agent,这样LLM Agent通过MCP请求这个工具Agent完成操作,效果等同函数调用,只是通道不同。MCP强调Agent自治协作,所以尽量让每个Agent都用统一消息方式沟通,包括对工具Agent也是如此。而函数调用是特定模型厂商实现的。如果我们要跨不同公司的模型协同,就不能直接用OpenAI函数调用让一个模型调用另一个模型,但可以通过MCP消息来实现类似目标。因此MCP提供了一个通用层:无论内部用的是哪个模型、哪种函数调用,外部通信都走MCP封装的格式。概括来说,函数调用偏单Agent工具使用,MCP偏多Agent互操作,但两者并不冲突------MCP消息里也可以嵌入函数式请求或结果,只要各方约定好即可。
6.4 示例场景与代码
**示例场景:**使用 Microsoft Autogen 框架,通过 MCP 协议让两个 AI Agent 合作完成任务:比如一个Agent用来写 Python 代码,另一个Agent用来审查代码并优化。用户给出一个功能需求,写代码的Agent先生成代码,然后审查的Agent检查并提出改进,最后两者达成最终代码方案。
下面用 Autogen 的接口演示多Agent协作的流程,重点展示 MCP 群聊的部分。代码为概念性,可能需在真实环境调整参数。
python
# 安装 autogen: pip install autogen-agentchat autogen-ext[openai] (假设已装)
import asyncio
from autogen_agentchat import AssistantAgent, UserProxyAgent, Conversation
# 使用OpenAI GPT-4 模型作为Agent的LLM后端
from autogen_ext import OpenAIChatCompletionClient
llm_config = {"model": "gpt-4"} # GPT-4 模型
# 定义两个智能体:Coder 和 Reviewer
coder = AssistantAgent(name="Coder", llm_config=llm_config, system_message="你是资深Python开发工程师。负责根据需求编写代码。")
reviewer = AssistantAgent(name="Reviewer", llm_config=llm_config, system_message="你是代码审查员。负责检查代码并提出改进建议。")
# 定义一个用户代理来代表用户提出任务
user = UserProxyAgent(name="User")
# 初始化对话,会话中包含用户和两个助手Agent
conversation = Conversation(agent_list=[user, coder, reviewer])
# 用户发布任务
task = "请编写一个函数,输入一个整数列表,返回其中所有奇数的平方组成的新列表。"
conversation.post_user_message(task)
# 模拟对话进行,直到结束条件
async def run_conversation():
await conversation.run(max_steps=6) # 运行最多6轮交流
asyncio.run(run_conversation())
# 获取对话记录
for msg in conversation.history:
print(f"[{msg['sender']}]: {msg['content']}")
代码说明:
-
建立OpenAI GPT-4作为基础模型,每个Agent共享此LLM配置。
-
创建
AssistantAgent
实例:Coder
和Reviewer
。各自的system_message设置了明确的角色:"Python开发工程师"和"代码审查员"。这让他们在对话中扮演不同职能。 -
创建一个
UserProxyAgent
代表用户,以便将用户输入纳入 Autogen 的会话系统。 -
用
Conversation
将三个Agent组织在一起,相当于创建一个群聊会话。Autogen底层通过MCP协议管理对话,保证每个Agent都能接收对话消息并产出回复。 -
用户提出任务(通过UserProxyAgent):让Coder编写一个函数解决给定问题。
-
调用
conversation.run(max_steps=6)
异步运行对话,允许最多6步交互。在这个过程中,Autogen会自动协调两个AssistantAgent的交流:通常Coder会先响应用户任务给出代码片段,然后Reviewer收到Coder的消息(代码)进行审查,提出修改建议,Coder再根据建议改进代码...如此往复,直到达到某个收敛(比如Reviewer认可代码或达到步数上限)。 -
打印整个对话历史,观察多Agent协作过程。输出可能类似:
python[User]: 请编写一个函数... [Coder]: ```python def square_odds(nums): return [x*x for x in nums if x % 2 == 1] ``` 这里函数返回输入列表中奇数的平方结果。 [Reviewer]: 代码看起来正确且简洁。我建议给函数添加文档字符串说明输入输出,以提高可读性。 [Coder]: ```python def square_odds(nums): """ 接收一个整数列表,返回其中所有奇数的平方组成的新列表。 """ return [x*x for x in nums if x % 2 == 1] ``` 已添加文档字符串。 [Reviewer]: 好的,这样更完善了,代码通过审查。
可以看到,两Agent以MCP协议在内部沟通:Reviewer能读取Coder发的代码,并给出反馈;Coder能理解Reviewer的建议并修改代码。这种交互顺序和内容都是Autogen遵循MCP规则自动实现的,我们只需定义Agent角色和目标任务。
**注意:**实际运行需OpenAI API支持,输出也依赖模型。但这一示例清晰体现了MCP的价值:不同智能体(写代码 vs. 审代码)各自发挥所长,通过统一对话通道合作达成更优结果。如果没有MCP,可能我们需要串行地先调用一次模型写代码,再手动把代码塞给第二次模型审查。而采用协议驱动,整个过程AI自主完成,人只提供初始任务,极大提高了自动化和智能程度。
6.5 应用场景与优缺点
应用场景:
- 复杂任务分工:将一个复杂任务拆分给多个专长不同的Agent。例如在产品设计中,一个Agent擅长创意头脑风暴,另一个擅长逻辑分析,通过MCP讨论产生兼具创意和可行性的方案。
- 模拟多人讨论:在培训或决策支持中,用多Agent模拟不同专家的观点碰撞。比如医疗诊断AI,一个Agent支持某诊断,另一个持反对意见,他们辩论,有助于给出更全面结论。
- 大型项目协作:如软件开发AI团队,一个写代码,一个写测试,一个写文档,通过MCP协调,一起产出完整的软件交付物。
- 跨系统AI编排:在企业内部,不同部门可能各有AI模型处理本部门任务。通过MCP,可以让销售AI、生产AI、财务AI在某些场景下协作(比如制定季度计划时综合各部门信息)。
- 教学和问答:可以有一个学生Agent一个老师Agent,学生提问题老师回答,在此过程中引入另一个提问Agent促进更深入回答。这种MCP下多Agent互动可用于教学系统中模拟陪练。
优点:
- 发挥专长,协同增效:每个Agent可以专注自己擅长的子任务,通过MCP整合,结果往往比单一Agent完成整个任务更好。例如前述代码示例,写代码和审代码分别由最合适的Agent做,使错误减少、质量提高。
- 模块化灵活性:采用协议,可以方便地增减Agent或更换Agent实现,而不影响整体架构。就像插件一样,可插拔。例如想加入第三个性能优化Agent,只需其遵守MCP即可加入现有对话,系统扩展性强。
- 复用现有框架 :MCP作为通用协议,使得不同Agent框架输出可以互通。这保护了已有投资,可能接入外部伙伴的Agent服务,不必所有Agent都用同一家模型或库,实现互操作。
- 避免单点失败:多Agent协作一定程度上有冗余,如果一个Agent没想到的方法,另一个可能想到。例如脑暴Agent没主意时,分析Agent可以提供线索,增强系统健壮性,不完全依赖单个模型的完备性。
- 透明决策过程:相对于黑箱的大模型,多Agent对话过程更透明,中间推理过程以对话记录形式展现,便于调试和监控。同时也便于插入人类监督(人类可以看对话,必要时以一个Agent身份介入)。
缺点:
- 通信开销和延迟:Agent来回对话多轮才能完成任务,相比单Agent直接完成耗时更长,也消耗更多API调用次数。此外,多Agent需要保持大量上下文,可能更快达到上下文窗口限制,需要截断或摘要,增加复杂度。
- 协调难度:多个智能体的互动可能出现意料之外的复杂行为,比如死循环讨论、争执不下、不停地礼貌寒暄等。需要在协议上和提示上严格约束,以及引入终止条件、仲裁机制,否则可能"跑飞"。
- 实现复杂:尽管MCP定义协议,但实际搭建多Agent系统需要综合应用许多技术(对话管理、队列、并发处理)。调试难度也高于单Agent,因为出错时要分析是哪一步哪个Agent的问题。现有框架(如Autogen)在简化这些过程,但使用起来仍有一定门槛。
- 资源占用:每个Agent往往是一个大型模型实例,多个Agent就意味着成倍的内存和算力占用。同一台机器跑多个大模型可能不现实,通常需多机分布式,这又涉及网络通信和部署成本问题。
- 知识不一致:如果各Agent底层模型知识或版本不同,可能导致信息不一致,一个Agent要纠正另一个Agent的错误。这虽然有好处(互相检查),但也可能徒增交互而降低效率。如果都用同源模型,又可能思维模式太相似起不到互补作用。这需要在Agent多样性和一致性间权衡。
总而言之,MCP代表了AI从单体智能向群体智能演进的趋势,通过规范Agent之间的交流与协作,AI系统有望 tackling 更复杂的任务。不过,这一模式目前尚属前沿,虽然潜力巨大,但在工程和实践上还需要继续探索完善,以应对实际应用中的挑战。
7. Python AI 开发生态概览(2025)
7.1 主要技术框架简介
经过近几年的快速发展,Python 生态中已经涌现出一系列强大且主流的AI开发框架和工具库。它们各自侧重不同功能,常常可以配合使用,加速构建复杂的AI应用。以下简要介绍几种 2025 年主流的 Python AI 技术框架:
-
OpenAI API :OpenAI 提供的云端大型语言模型服务接口。开发者可以通过 Python 的
openai
库调用 GPT-3.5、GPT-4 等模型来完成文本生成、对话、函数调用等任务。OpenAI API 以其领先的模型能力成为许多应用的首选大脑。它支持函数调用功能,以及插件生态。其优势是模型性能强大、使用简单;但需联网并受制于调用费用和速率限制。 -
Hugging Face Transformers:Hugging Face 的 Transformers 库是开源模型的事实标准库。它提供数以万计的预训练模型(GPT系列、BERT系列、ViT系列等)供下载使用。通过统一的接口,开发者可以加载模型并执行推理、微调训练。Transformers 支持PyTorch和TensorFlow,覆盖文本、图像、音频多模态。配合 HuggingFace Hub,可以方便地分享和部署模型。对于需要自定义模型或离线私有部署的场景,这是必不可少的工具。
-
LangChain:一个针对 LLM 应用编排的高层框架。LangChain 提供了"链"和"代理"等抽象,将 Prompt 模板、LLM调用、工具使用、记忆等组织起来,方便构建复杂的对话和决策流程。LangChain集成了超过50种向量数据库和工具插件, 并支持使用OpenAI、Transformers等多种模型接口。开发者可以用LangChain快速搭建诸如对话问答、AGI代理等应用,而不用从零处理Prompt、上下文管理等细节。LangChain 自 2022 年问世以来增长迅速,成为LLM应用开发的主流选择之一。
-
LlamaIndex(GPT Index):LlamaIndex 是专注于将私有数据接入LLM的框架。它提供了一系列索引结构(列表索引、树索引、向量索引等)来组织文本数据,并在查询时智能地从索引中提取相关内容交给LLM。简单说,它是RAG的一站式解决方案,帮开发者把自有文档变成可被LLM高效查询的知识库。与LangChain更多侧重流程不同,LlamaIndex更关注数据-LLM接口。它也能与LangChain配合,作为其中的Retrieval组件使用。
-
Haystack:由 deepset 开发的开源框架,最初专注于搭建问答系统,现已扩展为通用 LLM 应用框架。Haystack的特色在于**管道(Pipeline)**概念,允许开发者将各组件(检索器、生成器、阅读器等)串联成端到端流程。它内置向量搜索、BM25检索、Reader(如RoBERTa模型找答案)等模块,也集成OpenAI等生成模型。Haystack强调"生产级"应用,提供REST API服务部署、反馈回路监控等功能。适合需要快速上线QA/chatbot系统的场景。
-
FastAPI:虽然不是AI专用框架,但FastAPI因其高性能、易用性,成为部署AI应用常用的Web框架。用FastAPI可以很容易地把模型推理包装成RESTful API服务,支持异步IO和自动文档。【FastAPI】的优势是速度媲美Node.js,语法简洁,与标准Python类型提示集成。这对于需要把AI能力提供给前端或第三方使用时非常有用。例如用LangChain构建逻辑后,用FastAPI封装成HTTP接口对接前端网页或APP。
-
Autogen:微软开源的多智能体协作框架,正是前述MCP协议的一个实现者。Autogen提供了ConversableAgent抽象,每个Agent可以绑定LLM和工具,然后通过事件驱动的聊天实现多Agent协同。它支持复杂的对话流程、组内通信、角色管理,并可扩展接入外部服务(OpenAI接口等)。对于想尝试AutoGPT类多智能体应用或复杂对话场景的开发者,Autogen提供了强大的基础设施。
除了上述主要框架,还有许多工具值得一提:如Pinecone (托管向量数据库,用于存储嵌入向量做语义检索)、Weaviate (另一向量库方案)、Gradio/Streamlit (快速搭建模型演示界面的库),Ray(用于分布式部署模型服务)等等。这些都构成了Python AI开发者的工具箱,在不同需求下组合使用。
7.2 框架协同工作机制
单个框架往往专注某一环节,但在实际应用中,我们常常需要将多个框架组装起来以构建完整系统。下面通过一个典型应用------企业文档问答系统------说明各框架如何协同:
场景:公司有大量内部文档,希望一个聊天机器人能回答员工提问,并给出处。
协同方案:
-
知识库构建(LlamaIndex/Haystack + Transformers):首先用 LlamaIndex 从文档建立索引。如果需要对文档文本生成嵌入,可以用 HuggingFace Transformers 加载一个embedding模型(比如 sentence-transformers)或使用 OpenAI Embedding API。LlamaIndex/Haystack会调用这些模型,将文本编码成向量并存储在一个向量数据库中(如 Pinecone 或 FAISS)。
-
查询接口(LangChain + OpenAI API):搭建一个 LangChain RetrievalQA Chain,将 OpenAI GPT-4 设为LLM,将前述构建的向量索引作为检索器。这条Chain工作时会:接收用户问题 -> 用向量检索找到相关文档段落 -> 将段落和问题组装成Prompt让GPT-4生成答案 -> 输出答案并附带引用。
-
对话管理(LangChain Agent + Tools):如果还需要机器人具备闲聊和工具使用能力,可进一步用LangChain的Agent。Agent背后仍用GPT-4,但配置一些Tools:其中RetrievalQA作为一个Tool,Calculator作为另一个Tool等等。这样,当用户提问涉及公司知识时,Agent会判断调用RetrievalQA工具;如果是数学就调用Calculator;普通闲聊则直接回答。
-
服务部署(FastAPI) :将上述Chain或Agent封装成一个FastAPI应用。例如定义一个
/ask
POST接口,接受{question: "..."},然后在函数中调用 LangChain Chain 来获得答案,最后通过API返回答案(JSON格式)。FastAPI负责处理HTTP请求和响应序列化。可以配合
uvicorn`服务器运行,使服务可并发响应多个请求。 -
前端与鉴权:FastAPI还可与OAuth等集成做鉴权,保证只有员工能访问。前端可以用React/Vue等实现,对接这个API,与聊天机器人交互。
-
监控优化(Haystack或自定义):Haystack Pipeline可插入一个 Feedback 环节,记录每次问答,员工可以评价答案是否有用。开发者收集这些反馈以改进系统,例如扩充知识库或优化Prompt。如果采用LangChain,可以自行添加日志和评分存储来实现类似功能。
在这个过程中,各框架分工明确又衔接紧密:
- Transformers/OpenAI 提供模型算力;
- LlamaIndex/Haystack 处理知识检索部分;
- LangChain 负责逻辑编排(决定用哪个模型/索引做哪步);
- FastAPI 则负责对外服务集成。
通过标准的Python接口(函数调用、类方法),我们可以让一个框架的对象作为另一个框架的输入。例如LangChain的RetrievalQA可以直接包装LlamaIndex生成的retriever。OpenAI API通过其Python库被LangChain透明调用。各工具间的数据接口主要是文本、向量、JSON等,兼容性很好。
这种模块化的好处在于灵活:如果日后想改用本地模型代替OpenAI,只需把LangChain中的LLM换成HuggingFaceHub或者 transformers.pipeline
,其他部分不用改。如果想换向量数据库,用Haystack支持的Milvus替代Pinecone,也比较独立。框架协同使开发既快又不锁定单一供应商。
7.3 示例场景与代码
**示例场景:**构建一个简化的问答Web服务。用户通过HTTP提交问题,服务器检索本地知识库并用OpenAI模型生成答案,然后将答案通过API返回。这将结合FastAPI、FAISS、OpenAI API几项。
假设知识库是一些TXT文件存储在 docs/
目录下,我们在启动时用 FAISS 创建向量索引。查询时用 OpenAI Embedding API + FAISS 找相关文档片段,再用 OpenAI ChatCompletion 生成答案。
python
from fastapi import FastAPI
from pydantic import BaseModel
import openai
import faiss
import numpy as np
app = FastAPI()
openai.api_key = "<YOUR_OPENAI_API_KEY>"
# 预处理:加载文档并建立向量索引
import os
docs = []
for fname in os.listdir("docs"):
text = open("docs/"+fname, encoding="utf-8").read()
docs.append(text)
# 使用OpenAI文本嵌入,将每个文档编码为向量
embeddings = openai.Embedding.create(input=docs, model="text-embedding-ada-002")["data"]
doc_vectors = [np.array(item["embedding"], dtype='float32') for item in embeddings]
index = faiss.IndexFlatL2(len(doc_vectors[0]))
index.add(np.stack(doc_vectors))
# 索引准备完毕
class Query(BaseModel):
question: str
@app.post("/ask")
def ask_question(query: Query):
question = query.question
# 1. 将问题编码为向量
q_emb = openai.Embedding.create(input=[question], model="text-embedding-ada-002")["data"][0]["embedding"]
q_vec = np.array(q_emb, dtype='float32').reshape(1, -1)
# 2. 在索引中搜索
D, I = index.search(q_vec, k=3) # 找最相关的3条文档
retrieved_texts = [docs[i] for i in I[0]]
# 3. 将检索结果放入Prompt调用OpenAI模型
context = "\n".join(retrieved_texts[:2]) # 取最相关的前2条拼接
prompt = f"根据以下文档回答问题:\n{context}\n\n问题:{question}\n回答:"
completion = openai.Completion.create(prompt=prompt, model="text-davinci-003", max_tokens=200)
answer = completion.choices[0].text.strip()
return {"answer": answer}
代码说明:
-
使用FastAPI定义应用和POST接口
/ask
。Query
数据模型用于解析请求JSON,它包含用户提出的问题字符串。 -
向量索引构建 (启动时执行):读取
docs/
目录下所有文本文件内容到docs
列表。调用 OpenAI 的text-embedding-ada-002
模型对每个文档生成嵌入向量(维度1536)。使用 FAISS (IndexFlatL2
) 建立内存索引,将所有文档向量添加进去。这样后续查询可以快速近似匹配。 -
查询处理:收到用户问题:
- 生成该问题的向量表示
q_vec
(再次用 OpenAI Embedding,相同模型以保证向量空间一致)。 - 在 FAISS 索引上
search
,返回距离最小的k=3条文档索引(I)和距离(D)。这里选择前3条相关文档。 - 提取这些文档文本,将最相关的前2条拼接作为
context
。(实际应用可以更智能选择片段,这里简单处理)。
- 生成该问题的向量表示
-
生成答案 :构造Prompt:"根据以下文档回答问题:<文档内容> 问题:<用户问题> 回答:",然后调用 OpenAI
text-davinci-003
(GPT-3)模型生成补全,让它依据提供的文档回答问题。限制输出最大200 tokens。 -
获取模型生成的文本作为
answer
,通过JSON返回给API请求方。
**测试示例:**假设 docs/
包含一篇关于Python的文章,用户问题:"Python 列表如何切片?"。系统会检索出文档中有关切片的段落,然后模型据此生成回答,如"Python 使用 list[start: end: step] 语法进行切片,例如..."。FastAPI 返回 {"answer": "Python 使用 list[start: end: step] 语法进行切片..."}。
该实现综合利用了OpenAI的模型服务(embedding与生成)、FAISS向量搜索和FastAPI网络服务。虽然未使用LangChain等更高级的封装,但却演示了各组件如何在Python中衔接------embedding得到numpy向量->FAISS查询索引->取文本->组装prompt->OpenAI生成答案->FastAPI返回。开发者可以基于此逐步替换或扩展组件:比如换成本地embedding模型(Transformers)、换成长文本支持更好的ChatGPT-4、或用LangChain简化Prompt和检索部分逻辑等。
7.4 应用场景与优缺点
应用场景:
- 企业内部知识助手:综合OpenAI API(语言理解强)和自有知识库(企业数据)搭建智能助手,整合LangChain、LlamaIndex 实现知识查询,FastAPI提供接口给聊天前端或Slack机器人。
- 电商客服机器人:利用Haystack管道,将用户问句经意图分类(Transformer模型)、商品FAQ检索(向量DB)、再用生成模型润色回答。最终通过FastAPI/Flask作为后端服务支撑网页客服。
- 自动化办公助手:借助LangChain Agents+函数调用,可以控制日历、邮件等,再通过FastAPI或GUI库提供界面给用户使用。例如一个日程助理,可以在用户询问时查日历(通过某API函数)并综合回复,这需要OpenAI函数调用和外部API集成。
- 内容生成系统:如文章生成、报告总结等。可用Transformers本地模型进行初稿生成,用OpenAI API或自己微调模型润色。最终结果通过Web界面(Streamlit/Gradio)展示并允许用户反馈。
- 多模态应用:Python还有如 torchvision、SpeechRecognition 等库,可以把图像、语音处理接入管道。例如先用OCR识别图片文字,再把结果交给生成模型摘要。这往往通过Python脚本串联不同库实现。
优点:
- 生态完善,集成度高:Python AI框架生态覆盖了从训练、推理到部署各环节,并能方便地互操作。开发者能利用丰富的库快速构建端到端应用,而不必所有组件从头开发。
- 开发效率高:高层框架(LangChain等)封装了许多模式,提供现成模块可用,极大减少样板代码。比如搭建一个问答只需几行LangChain配置即可完成之前数百行的功能。此外,有大量示例和文档可供参考,遇到问题社区支持友好。
- 灵活性强:模块化设计允许替换不同实现,避免被某一家绑定。例如可以先用OpenAI,后面迁移到开源模型,只需改一个组件。而且可以增减功能模块应对需求变化,如增加日志监控、加入新工具等。
- 性能可扩展:许多框架对性能优化有所考虑。FastAPI/UGVicorn足够支撑高并发API;向量数据库Pinecone等可扩展分布式部署;Transformer库支持GPU/TPU加速推理和多机训练。可以在原型验证后升级到生产配置。
- 主流社区维护:使用主流框架意味着持续的更新改进和社区贡献。例如LangChain每天在迭代新功能;HuggingFace有大量预训练模型和社区上传。站在这些巨人的肩膀上开发,可少走弯路。
缺点:
- 学习曲线:框架众多,各有概念。初学者可能需要一些时间熟悉例如LangChain的链式思维、Haystack的管道配置、FastAPI的异步用法等。踩坑在所难免,需要查文档和案例。
- 兼容性问题:有时不同库版本不兼容或发生冲突,比如Transformers的新版本改接口,会导致依赖它的LangChain老版本出错。因此需要注意版本锁定及测试。生态快速发展也意味着不稳定,API可能频繁变化。
- 性能开销:抽象层次多可能带来额外开销。例如LangChain在LLM调用外又套了一层,会稍增延迟(不过一般相对于模型时间可忽略)。有时为了方便用Python实现某些逻辑,牺牲了一些速度。如果对性能极致要求,可能需要自己用C++/Rust等重写关键部分。
- 调试复杂:高层框架有时封装过深,出问题时不易定位。例如LangChain报错往往是底层模型或请求问题,但error stack很长。开发者需要了解各层大致工作原理才能有效调试。善用日志和Tracing工具(LangChain有Chain monitor)来追踪流程很重要。
- 部署运维:把开发环境的AI应用部署到生产还涉及容器化、扩容、监控等运维问题。Python GIL可能限制多线程,需用多进程或协程。模型服务需要GPU支持、显存管理。这超出了框架本身,需要运维经验支撑。
总之,2025年的Python AI开发生态提供了前所未有的便利,开发者能以较少人力打造强大的AI系统。在具体项目中,应根据需求选用合适的组件组合,既避免重复造轮子,又保证可控性和效率。在掌握各框架的基础用法后,灵活调整搭配,将能最大程度发挥它们的威力,加速AI应用的落地。
8. 结论
本博客系统地阐述了当今 AI 应用开发中的几个关键概念和技术------从AI Agent 的自主决策执行,到Prompt 的指令设计艺术,再到结合检索的RAG 增强方法,支持工具使用的Function Calling 机制,以及规范多模型协作的MCP 协议,并进一步概览了 2025 年 Python 生态中相关的主流框架。通过对每个概念的定义、原理机制、关联关系的分析,以及结合实际场景的Python代码示例,我们可以清晰地看到这些技术如何各司其职又互相配合,共同构建出现代智能应用。
可以预见,未来的AI系统将越来越多地体现出Agent化 和模块化协作的特征:多个智能Agent彼此通信,调用工具、检索知识,协同为用户完成复杂任务。在这一进程中,Prompt工程和函数调用等技术将继续起到关键作用,帮助我们更自然高效地驾驭大型模型。而像LangChain、Autogen这样的一站式框架,也会不断发展,降低多Agent系统的开发门槛。
对于开发者而言,善用这些新兴技术和框架,能够大幅提升AI应用开发效率和效果。但也需要保持对底层原理的理解,才能在问题出现时迅速定位解决,或根据具体需求进行定制优化。本白皮书希望提供的全面讲解和示例,能帮助读者掌握这些概念的精髓,进而在实践中灵活运用,打造出功能强大、性能可靠的AI系统。
展望未来,随着基础模型能力的进一步提升和开源开放,AI Agent 将变得更聪明,Prompt 工程可能被更自动化的策略取代,RAG 的检索将更精准实时,函数调用将支持更丰富的操作,多Agent协议也有望标准化为行业规范。Python生态会继续繁荣,引领AI开发创新。我们正站在一个"智能协作"的新时代开端,人类与AI、AI与AI之间的合作将创造出前所未有的生产力。通过深入理解并掌握本报告讨论的技术,每一位开发者都可以积极参与并引领这场变革,在2025年及未来构建出更加智能、互联的应用。