news 2026/9/4 20:16:16

DeepSeek Agent开发实战:从Function Calling到前端集成排错

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
DeepSeek Agent开发实战:从Function Calling到前端集成排错

之前在接 DeepSeek 的 Agent 类需求时,很多同学会遇到一个很现实的问题:官方文档和开源仓库都看了,模型接口也能通,但一到“让模型自己决定调用哪个工具、把工具结果再喂回去”这一步就卡住了。尤其是想参考 deepseek-ai 相关的 awesome-deepseek-agent 这类资源清单时,面对一堆项目名、示例代码,反而不知道从哪条路径开始落地。这篇文章就把 DeepSeek Agent 从概念到可运行代码完整梳理一遍,包括环境准备、Function Calling 实战、一个可扩展的最小 Agent 骨架,以及前端集成阶段出现过的一个加载报错failed to load plugins client-modules: html did not preload @deepseek-ai/dsh的排查思路。

内容适合三类读者:

  • 想用 DeepSeek 做智能客服、Copilot、个人助理的开发者;
  • 已经在调 API,但想深入了解 Agent 工具调用和上下文管理的同学;
  • 遇到前端插件或客户端模块加载异常,需要快速定位问题的前端同学。

读完你可以掌握 DeepSeek Agent 的完整调用链路,并且拿到一套可以复制到本地跑通的 Python 示例工程。

1. 认识 DeepSeek Agent 与 awesome-deepseek-agent

1.1 DeepSeek 是怎么提供能力的

DeepSeek 对外提供大模型 AI 能力,常见的接入方式分为两类:

  • 官方 API 服务:使用 OpenAI 兼容的接口格式,通过api.deepseek.com调用deepseek-chat等模型;
  • 开源模型权重:在本地或私有化环境部署,适合对数据有强管控要求的团队。

一般做 Agent 原型验证时最推荐官方 API,因为它省去显卡、部署和运维成本,接口也是主流模型厂商通用的风格。模型名称方面,官方文档会根据版本发布情况调整,所以代码中不要写死依赖某个特定模型版本,最好把模型名收敛到一个配置项里。

这里有一个很容易混淆的点:DeepSeek 有普通对话模型,也有偏推理的模型。做 Agent 时,如果你的任务需要模型自主决定“调用哪个工具”,建议优先选择支持 Function Calling(函数调用)的对话模型。推理模型能想得很深,但工具调用能力和交互稳定性在不同版本上有差异,因此选型前要确认当前模型的官方能力矩阵。

1.2 awesome-deepseek-agent 是什么

在 GitHub 社区里,awesome-*系列仓库通常是指“围绕某个技术主题整理的高质量资源清单”。deepseek-ai 组织以及社区维护的 awesome-deepseek-agent 类仓库,目标就是把 DeepSeek Agent 相关的官方示例、第三方框架、工具插件、Prompt 案例、部署方案汇总到一处。

这类仓库的实际价值可以分为三层:

  1. 信息索引:你不用再到处搜索“DeepSeek Agent 项目”,清单里已经按类别整理好;
  2. 快速找案例:当你想看某个场景是否有人实现过,可以直接顺着仓库推荐的项目看源码;
  3. 了解生态:从仓库条目数量和维护活跃度,能判断 DeepSeek Agent 生态里哪些方向成熟、哪些方向还在早期。

需要注意的是,社区仓库的增长速度非常快,条目会不断变化。把它当成“地图”而不是“标准教材”更合理。真正搭建 Agent 时,核心还是要理解模型 API 的工作原理,以及工具调用、上下文、记忆、异常控制这些通用工程问题。下面就从最核心的原理开始拆解。

2. Agent 应用的基础架构与核心概念

2.1 对话模型和 Agent 的区别

普通对话模型是“一次性交互”:用户提问,模型回答。

Agent 则是在一次任务中,让模型具备“观察 - 决策 - 行动 - 再观察”的能力。最常用的实现模式是 ReAct(Reasoning + Acting)。流程可以理解为:

用户提出需求 ↓ 模型分析:当前需要什么信息或操作 ↓ 模型返回一个“工具调用指令”,而不是最终答案 ↓ 程序执行真实工具(查天气、查数据库、发请求等) ↓ 把工具结果作为新消息送回模型 ↓ 模型根据结果继续推理,或给出最终回答

这个过程可能会循环多次,直到模型认为信息足够、不再返回工具调用为止。

为了让模型能“决策”,我们需要给它提供三样东西:

  • 工具定义:用 JSON Schema 描述工具名称、用途、参数;
  • 当前对话上下文:包括历史消息、上一轮工具执行结果;
  • 清晰的系统提示词:规定模型在什么情况下必须调用工具。

2.2 Function Calling 在 Agent 中的位置

Function Calling(函数调用)是 Agent 的技术底座。过去我们要靠 Prompt 约束模型输出 JSON,再自己解析,效果不稳定。现在模型原生支持返回结构化工具调用参数,程序只需要判断tool_calls字段是否存在即可。

一段补全接口返回中,和工具调用相关的关键结构通常是:

message.tool_calls ├── id # 工具调用 ID,后续回传结果时必须带上 └── function ├── name # 要调用的工具名 └── arguments # JSON 字符串格式的参数

参数arguments是字符串而不是对象,这一点新人最容易踩坑。拿到后必须json.loads()解析,再传给本地函数。

2.3 Agent 的关键组件

抛开模型本身,一个工程上可用的 Agent 通常包含以下部分:

组件作用选型建议
模型接入层统一封装 API 调用、超时重试、密钥管理OpenAI SDK 或 requests 直连
工具注册表管理工具名、描述、执行函数推荐使用装饰器或字典映射
上下文管理器维护 messages 历史,控制 token 长度记录角色、做截断或摘要
执行控制层判断是否继续循环、设置最大步数防止模型无限工具调用
观测日志记录每次请求和工具调用JSON 日志、调用链路 ID

对个人开发者来说,不用第一版就做得很重。一个函数加一个循环,就能跑通最小 Agent;后续再逐步引入记忆、重试、并发和安全控制。

3. 实战前置准备:环境、密钥和项目结构

3.1 运行环境说明

本文代码以 Python 为例,依赖非常少。你不需要搭建本地大模型,只需要能访问 DeepSeek 官方 API。

  • Python 版本建议 3.9 及以上;
  • 操作系统不限,Windows / macOS / Linux 均可;
  • 需要提前申请 DeepSeek API Key,并保证账户有可用额度;
  • 示例中使用了 OpenAI Python SDK,因为 DeepSeek 官方提供的接口兼容 OpenAI 格式。

版本方面不需要纠结,示例重点演示的是接口思路,不同 SDK 版本之间参数差异很小。

3.2 安装依赖

先创建虚拟环境,避免污染全局 Python 环境。

python -m venv .venv source .venv/bin/activate # Windows 下使用 .venv\Scripts\activate

安装依赖:

pip install openai python-dotenv

说明:

  • openai负责发送请求和解析响应;
  • python-dotenv负责从本地.env文件读取密钥,避免把密钥写死在代码里。

3.3 密钥管理

在项目根目录创建.env文件:

DEEPSEEK_API_KEY=sk-你的密钥

再生成.gitignore,一定不要把.env提交到代码仓库:

.env .venv/ __pycache__/

密钥安全是红线。若密钥泄露,别人可以消耗你的额度,甚至调用危险操作。生产环境建议使用密钥管理平台或 K8s Secret,而不要依赖.env文件。

3.4 项目结构

后续示例代码建议按下述结构组织:

deepseek-agent-demo/ ├── .env ├── .gitignore ├── requirements.txt ├── deepseek_agent/ │ ├── __init__.py │ ├── client.py # 模型客户端封装 │ ├── tools.py # 工具定义与实现 │ └── agent.py # Agent 主循环 └── run_demo.py # 启动入口

对于一个小 Demo 而言,这个结构已经足够清晰。不建议一开始就引入 LangChain 之类的重框架,先把原生调用流程跑通,再决定是否要引入上层抽象。

4. 第一个 DeepSeek Agent:基于 Function Calling 的工具调用实战

4.1 第一步:封装模型客户端

创建deepseek_agent/client.py,统一管理 API Key、基础地址和模型名:

# 文件路径:deepseek_agent/client.py import os from dotenv import load_dotenv from openai import OpenAI load_dotenv() client = OpenAI( api_key=os.getenv("DEEPSEEK_API_KEY"), base_url="https://api.deepseek.com", ) # 模型名以官方文档为准,通过变量统一管理,方便后续切换 MODEL_NAME = os.getenv("DEEPSEEK_MODEL", "deepseek-chat")

这里把base_url写成 DeepSeek 官方 API 地址。需要注意:当前网络环境必须能够正常访问该域名,如果公司内网有防火墙限制,需要提前在运维侧确认白名单。

4.2 第二步:定义一个工具

为了让示例简单又能说明问题,这里实现一个“根据城市查天气”的工具。真实项目中,这里通常会换成requests请求天气服务或查询内部接口。

# 文件路径:deepseek_agent/tools.py import json def get_weather(city: str) -> str: """模拟查询某个城市的天气情况。 参数 city 由模型解析并传入,真实项目中应替换为天气服务 API。 """ weather_map = { "北京": "晴,25~33℃", "上海": "多云,26~34℃", "深圳": "阵雨,25~30℃", "成都": "阴,22~29℃", } result = weather_map.get(city, "暂未收录该城市天气数据") return json.dumps({"city": city, "weather": result}, ensure_ascii=False)

注意两点:

  • 工具返回结果最好是字符串,因为它是作为content塞回给模型的;
  • 如果结果本身是结构化的,可以先用json.dumps序列化,既方便模型阅读,也方便日志记录。

4.3 第三步:定义工具 Schema

模型不知道 Python 函数内部怎么实现,它只能通过 JSON Schema 了解“这个工具是干什么的、需要什么参数”。

# 文件路径:deepseek_agent/tools.py TOOL_GET_WEATHER = { "type": "function", "function": { "name": "get_weather", "description": "查询指定城市当天的天气情况", "parameters": { "type": "object", "properties": { "city": { "type": "string", "description": "城市名,例如:北京", } }, "required": ["city"], }, }, } TOOLS = [TOOL_GET_WEATHER]

工具描述越明确,模型就越不会乱调用。例如参数里写清楚“城市名,例如:北京”,可以有效减少模型传省份而不是城市的概率。

4.4 第四步:编写 Agent 主循环

有了模型客户端和工具,接下来完成最核心的 Agent 循环逻辑。

# 文件路径:deepseek_agent/agent.py import json from deepseek_agent.client import MODEL_NAME, client from deepseek_agent.tools import TOOLS, get_weather def call_tool(name: str, arguments: str) -> str: """根据模型返回的工具调用信息,分发到真实函数。""" args = json.loads(arguments) if name == "get_weather": return get_weather(city=args.get("city", "")) # 如果没有匹配到工具,必须返回一个可读结果,而不是抛异常 return json.dumps({"error": f"unknown tool: {name}"}) def run_agent(user_input: str, max_steps: int = 5) -> str: """Agent 主循环:模型决策 -> 执行工具 -> 结果回填 -> 继续或结束。""" messages = [ {"role": "user", "content": user_input}, ] for step in range(1, max_steps + 1): print(f"[step {step}] request to model...") resp = client.chat.completions.create( model=MODEL_NAME, messages=messages, tools=TOOLS, tool_choice="auto", ) message = resp.choices[0].message messages.append(message) # 如果模型没有返回工具调用,说明已经可以生成最终答案 if not message.tool_calls: return message.content # 否则逐个执行工具,并把结果以 tool 角色追加到上下文 for tool_call in message.tool_calls: print(f"[step {step}] tool call: {tool_call.function.name} {tool_call.function.arguments}") tool_result = call_tool( name=tool_call.function.name, arguments=tool_call.function.arguments, ) messages.append( { "role": "tool", "tool_call_id": tool_call.id, "content": tool_result, } ) return "已达到最大执行步数,任务未完成,请简化问题后重试。"

这段代码是整个示例的核心,有几处需要重点理解:

  1. messages.append(message):模型返回的 message 对象中包含了tool_calls信息,必须原样保留在上下文里,模型才能知道“自己上一步做了什么决定”;
  2. role: "tool"的消息必须携带tool_call_id,用来和模型之前的工具调用 ID 对应;
  3. max_steps是安全阀。没有它,模型可能在复杂任务中陷入无限工具调用,既消耗 token,也让用户等待时间无限拉长;
  4. 未知工具不要直接抛异常,因为异常会导致整个对话中断。更优雅的做法是返回可读的错误结果,让模型自己决定下一步。

4.5 第五步:运行验证

创建入口文件:

# 文件路径:run_demo.py from deepseek_agent.agent import run_agent if __name__ == "__main__": answer = run_agent("北京今天天气怎么样?适不适合穿短袖出门?") print("最终回答:", answer)

运行:

python run_demo.py

预期观察行为如下:

  • 控制台先输出模型请求日志;
  • 然后输出一次工具调用,例如tool call: get_weather {"city": "北京"}
  • 程序调用本地get_weather函数拿到模拟结果;
  • 模型再次收到上下文后,生成最终回答,例如“北京今天晴,25~33℃,适合穿短袖出门,但要注意防晒”。

第一次跑通这个流程,意味着你已经理解 Agent 最核心的机制。后面所有更复杂的能力,都是在这个循环上叠加记忆、更多工具、更多控制策略。

5. 进一步封装:带上下文记忆和任务循环的 Agent 骨架

5.1 把 Agent 封装成可复用类

实际项目里不会只处理单条消息,而是要把多轮对话、工具状态、上下文裁剪都收拢到一起。下面给出一个精简版 Agent 骨架,你可以在此基础上扩展。

# 文件路径:deepseek_agent/agent.py(扩展版) from typing import Callable, Optional TOOL_MAP: dict[str, Callable] = { "get_weather": get_weather, } def _default_tool_caller(name: str, arguments: str) -> str: if name not in TOOL_MAP: return "未知工具,请换一个方式完成任务。" func = TOOL_MAP[name] return func(**json.loads(arguments)) class SimpleAgent: def __init__( self, system_prompt: str, tools: Optional[list[dict]] = None, tool_caller: Optional[Callable] = None, max_steps: int = 5, ): self.system_prompt = system_prompt self.tools = tools or [] self.tool_caller = tool_caller or _default_tool_caller self.max_steps = max_steps self.history: list[dict] = [] def _build_messages(self) -> list[dict]: return [{"role": "system", "content": self.system_prompt}, *self.history] def chat(self, user_input: str) -> str: self.history.append({"role": "user", "content": user_input}) for _ in range(self.max_steps): resp = client.chat.completions.create( model=MODEL_NAME, messages=self._build_messages(), tools=self.tools, tool_choice="auto", ) message = resp.choices[0].message self.history.append(message) if not message.tool_calls: return message.content for tool_call in message.tool_calls: result = self.tool_caller( name=tool_call.function.name, arguments=tool_call.function.arguments, ) self.history.append( { "role": "tool", "tool_call_id": tool_call.id, "content": result, } ) return "已达到最大执行步数,请调整问题后重试。"

使用方式:

agent = SimpleAgent( system_prompt="你是智能助手,需要查天气时请使用 get_weather 工具。", tools=TOOLS, ) print(agent.chat("上海呢?")) print(agent.chat("那北京呢?"))

通过把history保存为实例属性,实现了同一个 Agent 实例内多轮对话的上下文传递。

5.2 上下文长度与记忆裁剪

模型上下文窗口是有限的。随着 conversation 越来越长,有两个问题会越来越明显:

  • token 消耗持续上涨,成本线性增加;
  • 超出上下文窗口时,API 会报错,或者早期内容被静默截断。

常用的处理策略有三种:

策略做法适用场景
固定窗口裁剪只保留最近 N 条消息简单客服场景
摘要压缩把早期对话用模型总结成摘要长时间多轮对话
关键信息抽取从历史中抽取用户偏好、任务状态个性化助手

建议第一版先实现固定窗口裁剪。例如只保留最近 20 条消息,超过时丢弃最早的非系统消息:

MAX_HISTORY = 20 def trim_history(history: list[dict]) -> list[dict]: system_msgs = [m for m in history if m["role"] == "system"] other_msgs = [m for m in history if m["role"] != "system"] if len(other_msgs) > MAX_HISTORY: other_msgs = other_msgs[-MAX_HISTORY:] return system_msgs + other_msgs

这个方法简单但不完美,因为如果裁掉的消息里包含未被消费的tool结果,模型可能会产生混乱。裁剪时最好从对话边界整体切分,避免把 user、assistant、tool 一组消息拆散。

5.3 工具注册机制

真实项目中工具数量可能很多,把所有工具写进TOOLS列表和TOOL_MAP会很混乱。推荐将工具依赖关系设计为“工具名称作为唯一键”,并提供批量注册能力。

def register_tools(name: str, description: str, parameters: dict, handler: Callable) -> dict: schema = { "type": "function", "function": { "name": name, "description": description, "parameters": parameters, }, } TOOL_MAP[name] = handler return schema

这样每新增一个工具,只需要写一个处理函数加一行注册代码,Agent 主循环不需要改动。后续如果要接 LangChain、Dify 或其他框架,这种“注册表”设计也能平滑迁移。

6. 前端集成中的高频报错:failed to load plugins client-modules

6.1 报错现象

在部分 Web 端的 DeepSeek 工具链或社区前端项目中,构建运行时会出现类似下面的报错:

failed to load plugins client-modules: html did not preload @deepseek-ai/dsh

这个报错会让页面里的 Agent 面板、工具配置区域或聊天组件完全无法渲染。只看报错文本,容易误以为是大模型接口问题,实际上它属于前端工程化问题,和模型调用没有直接关系。

6.2 报错含义拆解

把报错拆成两部分:

  • failed to load plugins client-modules:插件加载器在加载“客户端模块”时失败;
  • html did not preload @deepseek-ai/dsh:HTML 页面没有预加载名为@deepseek-ai/dsh的模块。

浏览器在解析模块化 JavaScript 时,期望该模块以<link rel="modulepreload">或类似方式被提前预加载。如果页面 HTML 中没有对应预加载声明,或者声明的资源路径与实际打包产物不一致,运行时就会抛出这个错误。

产生该问题的常见原因有:

  1. 前端项目引用了@deepseek-ai/dsh相关的依赖包,但依赖没有安装成功;
  2. 依赖安装成功,但构建产物没有包含该模块,资源 404;
  3. 构建工具配置了 CDN 路径或base路径,导致 HTML 中的预加载地址和实际部署路径不匹配;
  4. 本地构建缓存过期,旧 HTML 引用了已不存在的 chunk;
  5. 插件加载器期望应用在入口 HTML 中显式声明modulepreload,但当前模板没有配置。

6.3 排查步骤

遇到这个报错不要直接改代码,按下面顺序排查效率更高。

第 1 步:确认依赖是否真实存在。

npm ls @deepseek-ai/dsh

如果命令报错或显示missing,说明依赖没有安装成功。重新安装:

npm install

如果项目使用 pnpm 或 yarn,先清掉 lock 文件的损坏状态,再重新安装:

pnpm install # 或者 yarn install

第 2 步:在源码中检索引用位置。

grep -r "@deepseek-ai/dsh" src --include="*.js" --include="*.jsx" --include="*.ts" --include="*.tsx" --include="*.vue" --include="*.html"

确认是哪个文件在运行时 import 了这个模块。有时问题不在自己写的代码,而是某个插件依赖链中间接引入了它。

第 3 步:检查构建产物中是否真的存在对应文件。

# 以 Vite 为例,构建后产物一般在 dist 目录 find dist -name "*dsh*" -o -name "*@deepseek-ai*"

如果文件不存在,可能是构建配置将它排除了,或依赖版本不一致。如果文件存在,则继续检查路径匹配。

第 4 步:清理缓存并重新构建。

rm -rf node_modules/.vite dist .nuxt .output npm install npm run build

这一步能解决大量“改完代码但页面还走旧资源”的偶发问题。

第 5 步:检查部署后的资源路径。

如果项目设置了独立部署子路径,比如https://example.com/agent/,那么 HTML 里的预加载地址必须带上/agent/前缀。以 Vite 为例:

// vite.config.ts export default defineConfig({ base: process.env.NODE_ENV === "production" ? "/agent/" : "/", build: { modulePreload: { polyfill: true, }, }, });

第 6 步:手动预加载兜底。

如果插件加载器要求 HTML 中显式预加载,你可以在入口 HTML 中补上手动声明。注意实际资源名要以构建输出为准:

<link rel="modulepreload" href="/assets/@deepseek-ai_dsh.js" />

这里的文件名是示例写法。真实项目中建议先查看dist目录里实际生成的文件名,避免写错。

6.4 这类问题的通用解决思路

前端模块加载类报错,本质上可以归结为三类:

  • 模块不存在:依赖没装、装错版本、被 tree-shaking 移除;
  • 路径不匹配:base、CDN 地址、部署子路径不一致;
  • 时序不一致:HTML 先解析,模块后到达,预加载缺失导致插件系统判定失败。

排查时记住一个原则:不要先怀疑模型代码,先确认“浏览器到底有没有正确拿到这个 JS 文件”。打开开发者工具 Network 面板,看对应请求是不是 404、有没有被缓存、响应头 Content-Type 是否正确,比反复改业务代码有效得多。

7. 常见问题与排查清单

问题现象常见原因解决思路
API 返回 401 错误API Key 错误、环境变量没有加载检查.env是否存在,打印os.getenv确认值
请求超时或连接失败网络策略不允许访问api.deepseek.com先 curl 测试域名连通性,再在运维侧放行白名单
模型返回的内容里没有 tool_calls工具描述不规范、模型不支持函数调用精简描述,检查参数必填项,确认模型支持 Function Calling
arguments解析报错模型返回的不是合法 JSON先打印原始字符串,必要时做 JSON 清洗修复
工具执行了但模型不基于结果回答tool 消息没有附带tool_call_id确认每条 tool 消息都回传对应 ID
Agent 无限循环缺少最大步数限制设置max_steps,超过次数返回兜底文案
多轮对话上下文割裂历史消息被随意裁剪裁剪时整组保留 user/assistant/tool 消息
前端报did not preload依赖缺失、路径不匹配、缓存过期按章节 6.3 的六个步骤排查
页面加载但 Agent 面板空白前端运行时 JS 报错被吞掉打开控制台查看完整堆栈,不要只看插件提示

8. 工程化最佳实践与建议

8.1 Prompt 与工具描述

Agent 的质量上限,往往由工具描述决定。

同一个工具,描述写“查询天气”和写“查询指定城市当天的天气情况,参数城市名使用中文常用名,如北京、上海”,后者的调用准确率会明显更高。建议工具描述遵循如下模板:

该工具用于(功能用途)。当用户提问涉及(触发场景)时调用。 参数说明:xxx 表示(含义),取值示例:xxx。

另外不要给模型提供它用不到的工具。工具列表越长,模型做选择时的错误率越高,还会增加每次请求的 token 消耗。按需装配工具是 Agent 工程里最容易被忽视的优化点。

8.2 安全边界

Agent 一旦连上真实工具,就不仅仅是“文本生成”了。如果模型可以触发 SQL 查询、Shell 命令或发送请求,必须做好以下安全措施:

  • 工具白名单:只开放明确允许执行的操作;
  • 参数校验:模型传入的参数必须二次校验,不能直接拼进 SQL 或 Shell;
  • 权限最小化:服务账号只授予必要权限,禁止使用 root / DBA 账号;
  • 危险操作确认:删除、更新、转账、发布类操作必须增加人工确认环节;
  • 敏感操作审计:记录谁在什么时间调用了什么工具,参数是什么。

特别提醒:不要在 Agent 中实现“帮我删除数据库所有记录”这样的无人确认工具,即使只是测试。生产环境任何变更操作都要走审批和备份流程。

8.3 日志与可观测性

Agent 排错最大的难点在于“模型为什么做了这个决定”。好的日志应该记录:

  • 请求 ID 和调用链 ID;
  • 每次请求的 messages 摘要;
  • 工具调用名称、参数、返回结果;
  • token 消耗和执行耗时;
  • 是否命中了异常分支。

推荐使用 JSON 结构日志,方便后续接入日志平台。示例:

import logging logger = logging.getLogger("agent") logger.info( "tool_call", extra={ "name": tool_call.function.name, "arguments": tool_call.function.arguments, "trace_id": trace_id, }, )

8.4 稳定性设计

模型接口天然存在延迟和不确定性,Agent 工程必须预设以下异常:

  • 单次请求超时:设置合理超时时间,并增加重试策略;
  • 模型返回格式异常:捕获解析异常并转成可读报错;
  • API 限流:遇到限流错误时退避重试;
  • 工具执行失败:让模型知道失败原因,而不是直接中断。

重试时需要注意:如果请求已经发给模型并成功执行,但客户端超时了,不能无脑重试。最好为请求增加幂等标识,或者接受“偶尔丢失一次响应”的代价,换取整体稳定。

8.5 从 Demo 到生产

本文的代码可以直接跑通原型,但离生产还有距离。建议按以下优先级改造:

  1. 配置中心化:密钥、模型名、超时参数从环境变量读取;
  2. 依赖版本锁定:维护 requirements.txt 或 poetry.lock;
  3. 增加单元测试:工具分发、JSON 解析、上下文裁剪都是纯函数,可以单测;
  4. 接入监控:统计调用成功率、平均耗时、token 成本;
  5. 采用更成熟的 Agent 框架:当需求复杂度超过手写循环能维护的边界时,再引入 LangChain / LlamaIndex / Dify 等方案。

社区里关于 DeepSeek Agent 的第三方框架很多,但不要盲目追逐新框架。你自己能写明白原生循环之后,再去看框架源码,会发现一切都清晰很多。

9. 总结与后续学习建议

到现在为止,你已经完成了 DeepSeek Agent 从零到一的闭环:

  • 理解了 Agent 与普通对话模型的区别;
  • 知道 Function Calling 在 Agent 循环中的作用;
  • 用不到 100 行 Python 代码实现了“模型决策 - 本地工具执行 - 结果回填”的完整流程;
  • 了解了上下文记忆裁剪和工具注册机制;
  • 掌握了一个前端模块加载报错failed to load plugins client-modules: html did not preload @deepseek-ai/dsh的系统排查方法。

下一步想继续深入,建议按这个顺序推进:

  1. 先给 Agent 增加 3 个不同类型工具,例如查天气、查询数据库、发送 HTTP 请求,体会工具分发机制;
  2. 研究模型返回的usage字段,学会计算单次任务 token 成本;
  3. 尝试实现一个简单的 RAG,让 Agent 能访问私有文档;
  4. 把日志、超时重试、安全校验补上,观察系统在生产数据下的表现;
  5. 再回来重新翻看 awesome 类资源仓库,这时候你已经能评判哪些项目设计得好、哪些只是表面包装了。

大模型 Agent 的工程化还在快速演进,新工具和新框架层出不穷,但“模型负责决策、程序负责执行、上下文负责记忆”这条主线短期不会变。把本文的最小闭环跑通,你就拿到了所有复杂 Agent 系统的基础积木。如果这篇文章对你有帮助,可以收藏备用;实际落地过程中遇到新的报错,也欢迎在评论区把错误信息贴出来,大家一起排查。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/4 20:15:17

定时器原理与工作模式全解析:从51到STM32的实战指南

我做了十年嵌入式开发&#xff0c;从51单片机一路折腾到Cortex-M系列&#xff0c;踩过最多的坑基本都集中在定时器上。很多人觉得定时器不就是“数数”嘛&#xff0c;但真正做项目时才发现&#xff0c;同一个TIM外设&#xff0c;有人用来输出电机PWM&#xff0c;有人用来捕获编…

作者头像 李华
网站建设 2026/9/4 20:11:07

Python办公自动化实战:Excel、Word、PDF全流程处理与工具链解析

简介&#xff1a;本资源是一套面向零基础学习者与职场办公人员的Python办公自动化实战指南&#xff0c;聚焦Excel、Word、PDF、PPT及CSV等高频办公场景的自动化处理&#xff0c;解决重复性文档操作效率低、跨格式数据整合难等实际问题。压缩包共含多个核心模块&#xff1a;PDF处…

作者头像 李华
网站建设 2026/9/4 20:10:58

C、C++、Python先学哪个?编程语言学习顺序与底层原理路线指南

这个问题的标准答案不是一句“先学 C&#xff0c;再学 C&#xff0c;最后学 Python”就完了。我见过太多人照这条路线走&#xff0c;结果在 C 的指针上卡了两个星期直接放弃&#xff1b;也见过先学 Python 的人写出了能跑的脚本&#xff0c;却说不清为什么程序内存占用越来越高…

作者头像 李华
网站建设 2026/9/4 20:10:20

SpringBoot+Neo4j医疗知识图谱问答系统实战:从架构到部署

简介&#xff1a;这是一套面向计算机、人工智能及相关专业本科生的高分毕业设计项目源码&#xff0c;基于SpringBoot与Neo4j构建医疗领域知识图谱问答系统&#xff0c;解决医学实体识别、关系抽取与自然语言问句匹配等典型KG应用问题&#xff0c;适用于课程设计、毕设参考及知识…

作者头像 李华
网站建设 2026/9/4 20:02:22

AI二创短片生产管线拆解:角色一致、批量生成与合规边界

《SCP-午夜和弦》第二集这类作品&#xff0c;真正值得拆的不是“弗莱迪被收容”这个结果&#xff0c;而是过程中如何解决角色一致性、批量镜头生成、素材目录管理和二创合规边界。这次我们把项目当成一条小规模AI内容生产管线来看&#xff1a;从视觉设定怎么固化&#xff0c;到…

作者头像 李华
网站建设 2026/9/4 20:01:25

Simulink微电网动态运行仿真:光储并网暂态建模与IEEE 1547合规验证

简介&#xff1a;本资源是一套面向电力系统仿真初学者与新能源方向研究生的光储微电网动态建模实践材料&#xff0c;聚焦光伏-储能协同并网及微电网运行模式切换的核心问题。压缩包共含多个关键文件&#xff1a;Simulink模型文件&#xff08;.slx&#xff09;用于构建含光伏阵列…

作者头像 李华