拓冰建站拓冰建站
首页 / 资讯中心 / 正文

大模型Agent开发实战:从零实现RAG与工具调用全流程

最近几天AI 圈子里有个消息讨论度很高一位从头部大模型团队走出来的联创新公司成立仅 3 个月就完成了估值 135 亿的融资融资规模 15 亿方向直指大模型应用与 Agent 赛道。很多人在讨论估值和融资节奏但从技术视角看更值得关注的是一家大模型创业公司靠什么在很短时间内搭起技术壁垒抛开商业叙事落地到开发层面无非是围绕大模型的应用架构、检索增强、工具调用、Agent 编排和工程化能力。这篇文章不聊估值也不做商业点评。我将从技术角度出发拆解大模型 Agent 应用开发的核心链路并带大家从零实现一个可运行的“RAG 工具调用”Agent 小项目。无论你是刚接触大模型应用开发的新手还是想快速搭建原型验证想法的后端工程师这篇文章都能给你一套完整、可复制的实操方案。代码全部基于 Python逻辑尽量简化方便你跟着一步步跑通。1. 背景与核心概念1.1 大模型创业公司为什么都在押注 Agent过去一年大模型赛道逐渐从“拼底座模型参数”转向“拼应用落地”。公开信息显示新一批明星创业公司大多聚焦在 Agent、AI 编程、企业级知识库、多模态应用等方向。为什么会这样一方面底层模型的训练成本极高且已经形成明确的头部效应新公司直接卷基座模型并不划算。另一方面模型能力再强如果不能与业务数据、业务系统打通就只是“聊天机器人”很难产生实际的工程价值。Agent智能体恰恰是解决“模型与业务衔接”的关键范式。它将大模型的推理能力、工具调用能力、记忆能力和外部数据源组合起来让模型不只是回答问题而是能够自主完成一个相对复杂的任务。这正是大模型应用创业公司快速起盘的重要原因。1.2 Agent 是什么从工程角度看Agent 至少包含以下四个核心模块模块作用典型实现大模型推理与决策核心OpenAI GPT、DeepSeek、Qwen 等工具调用让模型访问外部能力函数调用 Function Calling、Tool Use记忆保存上下文和历史交互短期对话记忆、长期向量记忆外部数据为模型提供私有知识向量数据库 RAG 检索一个最简单的 Agent 工作流程可以概括为用户输入任务。大模型分析任务决定是否需要调用工具。如果调用工具则生成结构化调用参数。程序执行工具并返回结果。大模型结合工具结果生成最终回复。1.3 RAG 为什么重要RAGRetrieval-Augmented Generation检索增强生成是目前大模型落地中最常用的技术方案。它的核心思想是先检索外部知识库中与用户问题相关的文本片段再把这些片段作为上下文喂给大模型由大模型生成答案。这么做有三个明显好处解决模型“不知道”的问题私有知识、实时数据、非公开文档都可以通过检索注入。降低幻觉概率模型生成的答案有据可依。避免频繁微调知识更新时只需要更新向量库不用重新训练模型。在 Agent 应用中RAG 通常作为“知识工具”存在Agent 判断用户问题涉及私有知识时会调用检索工具获取相关内容再继续推理。2. 环境准备与版本说明2.1 运行环境本文示例以 Python 3.10 为基础操作系统不限Windows、macOS、Linux 均可。建议使用虚拟环境隔离项目依赖。2.2 依赖安装项目核心依赖如下openai python-dotenv numpy你可以在项目目录下创建一个requirements.txt文件内容如下openai1.30.0 python-dotenv1.0.0 numpy1.24.0然后在终端执行安装命令pip install -r requirements.txt如果你还没有 Python 环境建议先安装 Anaconda 或直接使用系统 Python再创建虚拟环境python -m venv venv source venv/bin/activate # Windows 下使用 venv\Scripts\activate版本需要根据你的项目实际情况调整本文示例以常见环境为例重点演示配置思路。2.3 大模型 API 配置本文代码使用 OpenAI SDK 兼容接口方式调用大模型。目前很多模型服务商都提供 OpenAI 兼容 API你只需要设置base_url即可切换不同模型供应商。在项目根目录创建.env文件OPENAI_API_KEY你的_API_KEY OPENAI_API_BASEhttps://api.openai.com/v1 OPENAI_MODELgpt-4o-mini EMBEDDING_MODELtext-embedding-3-small请将OPENAI_API_KEY替换为你自己的密钥。不要将.env文件提交到 Git 仓库。如果你使用的是国内模型服务商把OPENAI_API_BASE改成对应的接口地址并确认模型名称即可。3. Agent 核心原理拆解3.1 Function Calling 函数调用Function Calling 是 Agent 的“手”。没有它大模型只能“动嘴”不能“动手”。函数调用的流程是这样的开发者预先定义工具列表每个工具包含名称、描述、参数结构。大模型根据用户输入判断是否调用工具并生成符合参数结构的 JSON。程序解析 JSON执行对应函数。将函数结果追加到对话中再让大模型生成最终答案。用 OpenAI SDK 时工具定义为tools [ { type: function, function: { name: get_weather, description: 查询指定城市的实时天气信息, parameters: { type: object, properties: { city: { type: string, description: 城市名称例如北京 } }, required: [city] } } } ]这里的核心是description写得越清楚模型判断“是否调用”和“参数怎么填”就越准确。3.2 记忆上下文管理Agent 需要记忆才能完成多轮任务。目前的常见做法是将系统提示词、历史对话、工具结果组装成 messages 列表。控制上下文长度避免 token 超限。对长期记忆使用向量库存储按相关度召回。在最小实现中我们用一个 Python 列表保存 messages 即可。在生产环境中建议接入 Redis 或专门的记忆服务并设计清理策略。3.3 检索向量相似度RAG 中使用的向量检索核心是“文本相似度计算”。常见流程将文档切分成块。用 Embedding 模型将块转为向量。将用户查询转为向量。计算查询向量与文档向量的余弦相似度。返回相似度最高的 Top K 文本块。余弦相似度公式为cosine_similarity (A · B) / (||A|| × ||B||)在代码中你可以用 NumPy 轻松实现import numpy as np def cosine_similarity(vec_a, vec_b): a np.array(vec_a) b np.array(vec_b) return float(a.dot(b) / (np.linalg.norm(a) * np.linalg.norm(b)))3.4 完整决策闭环结合上面的模块一个完整的 Agent 决策闭环就是用户输入 → 模型判断意图 → 需要检索调用 knowledge_retrieval 工具 → 需要查天气调用 get_weather 工具 → 都不需要直接回答 → 携带工具结果再次请求模型 → 输出最终答案接下来我们就把这个闭环完整实现一遍。4. 完整实战案例4.1 创建项目结构先创建以下目录和文件agent_demo/ ├── .env ├── requirements.txt ├── config.py ├── llm_client.py ├── rag_engine.py ├── tools.py ├── agent.py └── main.py4.2 编写配置模块 config.py我们先创建一个配置模块读取.env文件中的配置# 文件路径agent_demo/config.py import os from dotenv import load_dotenv load_dotenv() OPENAI_API_KEY os.getenv(OPENAI_API_KEY, ) OPENAI_API_BASE os.getenv(OPENAI_API_BASE, https://api.openai.com/v1) OPENAI_MODEL os.getenv(OPENAI_MODEL, gpt-4o-mini) EMBEDDING_MODEL os.getenv(EMBEDDING_MODEL, text-embedding-3-small)这里使用python-dotenv加载环境变量代码更干净也便于在不同环境中切换配置。4.3 编写 LLM 客户端 llm_client.py接下来封装大模型调用和 Embedding 调用# 文件路径agent_demo/llm_client.py from openai import OpenAI from config import EMBEDDING_MODEL, OPENAI_API_BASE, OPENAI_API_KEY, OPENAI_MODEL def get_llm_client(): return OpenAI(api_keyOPENAI_API_KEY, base_urlOPENAI_API_BASE) def chat(messages, toolsNone): 调用大模型对话接口 client get_llm_client() if tools: response client.chat.completions.create( modelOPENAI_MODEL, messagesmessages, toolstools, tool_choiceauto, ) else: response client.chat.completions.create( modelOPENAI_MODEL, messagesmessages, ) return response def embed_texts(texts): 批量向量化文本 client get_llm_client() data client.embeddings.create(modelEMBEDDING_MODEL, inputtexts).data return [item.embedding for item in data]如果你的模型服务商不支持 Embedding 接口可以本地使用开源 Embedding 模型或换成其他向量化方案本文示例思路不变。4.4 编写 RAG 检索引擎 rag_engine.py这里我们实现一个极简版 RAG文档库直接用 Python 列表存储向量用 NumPy 计算相似度。这样不依赖重型向量数据库便于初学者理解原理。# 文件路径agent_demo/rag_engine.py import numpy as np from llm_client import embed_texts class SimpleRAGEngine: 极简 RAG 检索引擎用于演示检索增强生成流程 def __init__(self): self.documents [] self._vectors [] def add_documents(self, texts): 添加文档并计算向量 self.documents.extend(texts) vectors embed_texts(texts) self._vectors.extend(vectors) def search(self, query, top_k3): 检索与查询最相关的文档片段 if not self.documents: return [] query_vector embed_texts([query])[0] scores self._compute_scores(query_vector) top_index np.argsort(scores)[::-1][:top_k] results [] for idx in top_index: results.append( { content: self.documents[idx], score: float(scores[idx]), } ) return results def _compute_scores(self, query_vector): scores [] for vec in self._vectors: score self._cosine_similarity(query_vector, vec) scores.append(score) return np.array(scores) staticmethod def _cosine_similarity(vec_a, vec_b): a np.array(vec_a) b np.array(vec_b) return a.dot(b) / (np.linalg.norm(a) * np.linalg.norm(b))为了让检索结果更真实我在main.py中会预置几段知识文档你也可以替换成自己的业务文档。4.5 编写工具函数 tools.py定义 Agent 可以调用的工具。这里提供两个示例get_weather模拟天气查询不接真实 API方便本地运行。search_knowledge调用 RAG 引擎查询内部知识库。# 文件路径agent_demo/tools.py from rag_engine import SimpleRAGEngine # 模拟天气数据 _WEATHER_MOCK { 北京: {weather: 晴, temperature: 25}, 上海: {weather: 多云, temperature: 28}, 广州: {weather: 小雨, temperature: 30}, } def get_weather(city: str) - str: 查询指定城市天气 if city in _WEATHER_MOCK: info _WEATHER_MOCK[city] return f{city}天气{info[weather]}气温 {info[temperature]}℃ return f抱歉暂时没有 {city} 的天气数据。 def register_rag_tool(rag_engine: SimpleRAGEngine): 注册知识检索工具 def search_knowledge(query: str) - str: results rag_engine.search(query, top_k2) if not results: return 知识库中没有找到相关内容。 return \n.join([item[content] for item in results]) return search_knowledge4.6 编写 Agent 主逻辑 agent.py现在把工具、模型、消息组装在一起实现 Agent 的执行循环。# 文件路径agent_demo/agent.py import json from llm_client import chat SYSTEM_PROMPT 你是一个智能助手你可以通过工具获取信息。 请根据用户的问题判断是否需要调用工具。 如果工具返回结果请基于工具结果回答。 不要编造工具没有返回的信息。 def run_agent(user_input, tool_registry): 运行 Agent 主流程 messages [ {role: system, content: SYSTEM_PROMPT}, {role: user, content: user_input}, ] tools [] for name, func in tool_registry.items(): tools.append(build_tool_schema(name, func)) response chat(messages, toolstools) message response.choices[0].message # 如果模型没有要求调用工具直接返回内容 if not message.tool_calls: return message.content # 处理工具调用 messages.append(message) for tool_call in message.tool_calls: function_name tool_call.function.name arguments json.loads(tool_call.function.arguments) print(f[Agent 调用工具] {function_name}参数{arguments}) if function_name in tool_registry: func tool_registry[function_name] result func(**arguments) else: result f未知工具{function_name} messages.append( { role: tool, tool_call_id: tool_call.id, content: str(result), } ) # 将工具结果交给模型生成最终回答 final_response chat(messages) return final_response.choices[0].message.content def build_tool_schema(name, func): 根据函数签名生成工具 Schema简化演示 return { type: function, function: { name: name, description: func.__doc__ or f调用 {name} 工具, parameters: { type: object, properties: { query: { type: string, description: 查询内容 } }, required: [query] } } }注意为了让代码在多数环境通用这里的build_tool_schema做了一个简化处理所有工具参数统一用query字符串。实际项目中你应根据每个函数定义独立的参数结构。4.7 编写入口 main.py最后写一个入口文件把 RAG 文档、工具注册、Agent 运行串起来。# 文件路径agent_demo/main.py from agent import run_agent from rag_engine import SimpleRAGEngine from tools import get_weather, register_rag_tool # 1. 初始化知识库 DOCUMENTS [ RAG 是检索增强生成的缩写结合了检索系统与大模型生成能力。, LangChain 是一个用于构建大模型应用的开源框架支持 Agent、工具调用等功能。, Function Calling 允许大模型输出结构化工具调用参数是实现 Agent 的重要机制。, 向量数据库用于存储文本向量常见产品包括 Milvus、Weaviate、Qdrant、Chroma。, 提示词工程通过优化输入提示词提升模型输出质量是成本最低的优化方式。, ] print(正在初始化知识库...) rag_engine SimpleRAGEngine() rag_engine.add_documents(DOCUMENTS) print(知识库初始化完成。\n) # 2. 注册工具 search_knowledge register_rag_tool(rag_engine) tool_registry { get_weather: get_weather, search_knowledge: search_knowledge, } # 3. 交互循环 print(Agent 已启动输入问题开始对话输入 exit 退出。) while True: user_input input(\n你) if user_input.lower() in (exit, quit): break try: answer run_agent(user_input, tool_registry) print(f\nAgent{answer}) except Exception as e: print(f\n[错误] {e})4.8 运行与验证在项目目录下执行python main.py预期运行过程大致如下正在初始化知识库... 知识库初始化完成。 Agent 已启动输入问题开始对话输入 exit 退出。 你北京今天天气怎么样 [Agent 调用工具] get_weather参数{query: 北京} Agent北京今天天气是晴气温 25℃。当你输入“什么是 RAG”这类问题时Agent 会调用search_knowledge工具返回文档片段你什么是 RAG [Agent 调用工具] search_knowledge参数{query: 什么是RAG} AgentRAG 是检索增强生成的缩写结合了检索系统与大模型生成能力。到这里一个带工具调用和知识检索的 Agent 就完整跑通了。5. 常见问题与排查思路5.1 启动时 API Key 报错问题现象openai.AuthenticationError: Error code: 401常见原因.env文件没有正确加载。API Key 填错或已失效。环境变量名与代码不一致。解决思路检查项目根目录是否存在.env文件。在config.py中打印OPENAI_API_KEY确认加载成功。确认 Key 是否有效是否已开通对应模型权限。5.2 模型没有按预期调用工具问题现象模型直接回答而不生成tool_calls或总是调用错误工具。常见原因工具描述不够清晰模型无法判断在什么情况下使用。系统提示词没有说明“优先使用工具”。模型本身对复杂工具选择能力较弱。解决思路优化工具的description明确触发条件。在系统提示词中加入“如果问题涉及 XX请使用 XX 工具”的引导。使用支持 Function Calling 的较新模型。5.3 工具参数解析失败问题现象json.JSONDecodeError: Expecting value: line 1 column 1常见原因模型返回的工具参数不是合法 JSON。使用tool_choiceauto时某些模型可能返回空arguments。自定义工具 Schema 与函数签名不匹配。解决思路捕获 JSON 解析异常并重试或要求模型重新生成。在build_tool_schema中按实际函数参数生成 Schema避免全部使用query字段。对参数做默认值兜底try: arguments json.loads(tool_call.function.arguments or {}) except json.JSONDecodeError: arguments {}5.4 RAG 检索结果不相关问题现象检索到的文档片段与用户问题关系不大模型只能瞎猜。常见原因文档切分不合理块过大或过小。Query 表达不清检索不到有效信息。Embedding 模型与领域不匹配。解决思路调整文档切分策略保持每个块语义完整。检索前对用户问题做改写或关键词抽取。换用领域相关度更高的 Embedding 模型。查看相似度分数太低时让模型直接回答“知识库中没有相关内容”避免硬编答案。6. 最佳实践与工程建议6.1 配置管理不要把 API Key、数据库地址等敏感配置写死在代码里。建议使用环境变量或配置中心并按环境拆分.env.development .env.test .env.production在 CI/CD 部署时通过密钥管理服务注入环境变量。6.2 工具设计Agent 的能力边界由工具决定工具设计要注意以下几点每个工具只做一件事不要创建大而全的“万能工具”。工具描述必须包含触发条件、参数含义、返回结果格式。对工具调用做权限控制尤其是涉及数据库、支付、删除等高风险操作时必须走审批或确认流程。所有工具调用应记录日志便于追踪 Agent 的决策链路。6.3 上下文安全不要盲目拼接全部历史对话。给 messages 设置最大长度超出后按策略裁剪保留系统提示词。保留最近 N 轮对话。对超出长度的重要信息做摘要后压缩。这样可以有效控制 token 成本也能减少模型注意力分散的问题。6.4 可观测性与日志Agent 应用的排错难度远高于普通接口因为“模型为什么这么做”很难直接解释。建议在关键节点记录结构化日志{ user_input: 北京天气, tool_calls: [ { name: get_weather, arguments: {\city\:\北京\} } ], tool_result: 北京天气晴气温 25℃, final_answer: 北京今天天气是晴气温 25℃。, latency_ms: 1234, token_usage: { prompt: 800, completion: 120 } }生产环境建议接入 Jaeger、SkyWalking 或云厂商的链路追踪服务把 Agent 调用链完整记录起来。6.5 成本控制Agent 的 token 消耗通常高于普通对话场景因为同一轮可能需要多次请求模型。控制成本的常用手段使用缓存减少重复请求。对简单问题直接命中规则或知识库不走 Agent 循环。设置模型返回的最大 token 上限。在高频场景选用价格更低的模型。7. 总结与下一步学习方向本文从一个 AI 创业动向切入梳理了大模型 Agent 应用的核心技术模块模型调用、函数调用、RAG 检索、上下文组装。然后从零实现了一个“RAG 工具调用”的最小 Agent 项目跑通了用户提问、模型决策、工具执行、结果汇总的完整闭环。代码量不大但覆盖了 Agent 开发最常见的几个关键点。下一步你可以在这套代码基础上做三件事换一个真实的业务知识库把本地文档切块、向量化替换掉示例文档看看 RAG 对回答质量的提升。引入真正的向量数据库用 Milvus、Qdrant 或 Chroma 替代 NumPy 相似度计算支持更大规模的数据检索。增加多轮记忆把历史对话存入 Redis让 Agent 支持更自然的连续对话。在实际项目中优先级最高的不是模型本身而是工具职责、数据质量和可观测性。Agent 的每一次工具调用都对应真实业务行为务必做好权限校验、日志留存和异常兜底。纸上得来终觉浅建议你动手把上面的代码跑一遍再逐步加入自己的业务逻辑。只有真正踩过工具参数解析失败、检索结果不相关、上下文被截断这些坑才算开始懂 Agent 工程化。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门