从“数据结构入门”到“开发原神”,这个标题看起来像一句玩笑,但如果你当真去拆解,会发现它其实是很多开发者走过的真实路线:先把数组、链表、栈、队列、哈希表、树、图这些基础数据结构学明白,然后才有能力去设计一个复杂的 AI 应用,甚至是做一个“AI 原神助手”这样的智能体项目。
本文将围绕“数据结构入门后,如何转向 AI 应用开发 / Agent 开发”这条主线展开,用一个轻量 Python Agent 骨架和一套可视化平台搭建思路,帮你把数据结构知识落地到真实项目里。适合已经学过数据结构、正在找练手方向的新手,也适合想从传统 CRUD 开发转向 AI 应用开发的后端工程师。
1. 从“数据结构入门”到“开发原神”:先搞懂两者关系
1.1 为什么“数据结构入门”是关键分水岭
很多人在学习编程时,前几个月都在写 if-else、for 循环、函数调用,这些内容属于语法层面。真正让一个开发者开始区分“会写代码”和“会做设计”的,往往是数据结构。
举个例子:
- 同样是一批待处理任务,用普通列表逐个处理,任务一多就会出现顺序错乱、重复处理、无法回退的问题。
- 如果用栈来管理“撤销”操作,用队列来管理“待执行任务”,用哈希表来管理“已缓存结果”,整个程序会清晰很多。
数据结构入门,意味着你开始具备一种能力:把现实问题抽象成数据组织方式,再选择合适的数据结构去解决它。这种能力在 AI 应用开发里,比背 API 重要得多。
1.2 “开发原神”在本文语境是什么意思
先说清楚:本文不是要教你复刻米哈游的《原神》客户端,也不是要带你做 3D 游戏引擎。
“开发原神”在网络语境里是一种夸张说法,意思是“我已经有能力开发一款复杂、有趣、可迭代的产品了”。所以本文把它落地成一个更现实的目标:用数据结构 + 大模型能力,开发一个“AI 原神助手”智能体。
这个智能体可以做到:
- 回答《原神》角色、武器、圣遗物等知识类问题。
- 根据玩家需求推荐配队方案、养成路径。
- 调用外部搜索工具,获取最新活动信息。
- 在多轮对话中记住用户偏好。
虽然它不是一个开放世界游戏,但它的开发流程里会用到数组、字典、队列、树图、JSON 解析等大量数据结构知识,是一个很好的“数据结构 → AI 开发”衔接案例。
1.3 数据结构与 AI 应用开发的关系
很多同学会问:现在开发 AI 应用不是直接调大模型 API 就行了吗?还需要学数据结构吗?
答案是:需要。
大模型 API 只是“大脑”,但一个完整的 AI 应用还需要:
- 上下文管理:对话历史怎么存、怎么截断、怎么压缩,这是队列和缓冲区的经典应用。
- 工具调用:Agent 决定调用哪个工具、按什么顺序调用,这是图或状态机的调度问题。
- 知识库检索:把文档切片、建索引、做相似度搜索,背后是向量化和树形索引思想。
- 结果缓存:相同问题直接返回缓存结果,这是哈希表最常见的工程场景。
- 流式输出:大模型逐字返回内容时,如何按完整句子或完整 JSON 边界切分,这是缓冲区的应用。
所以说,数据结构不是“考试完就扔”的知识,它会在每一次 AI 应用开发中反复出现。下面我们把核心数据结构换一个视角重新梳理一遍。
2. 数据结构核心回顾:换一个“开发视角”重新理解
2.1 数组 / List:连续存储与随机访问
数组是最基础的数据结构。它在内存中是一段连续空间,可以通过下标在 O(1) 时间内访问任意元素。
在开发中,我们几乎天天都在用数组,但可能没有意识到它的特性:
# 用 List 保存待展示的攻略列表 guides = [ {"title": "新手开荒指南", "author": "九月的风"}, {"title": "角色培养优先级", "author": "提瓦特小助手"}, ] # 随机访问:直接按下标取得某一篇 first_guide = guides[0]数组适合“按位置读”的场景,比如排行榜、列表页、批量数据展示。但如果频繁在中间插入、删除元素,数组的代价就比较高,因为需要移动大量元素。这时候就要考虑链表。
在 AI 应用里,列表通常用于:
- 保存候选工具列表。
- 保存知识库检索结果。
- 保存每次大模型调用的消息列表。
2.2 栈与队列:函数调用栈与任务调度
栈是“后进先出”结构,队列是“先进先出”结构。
开发中最常见的栈是函数调用栈。你在 Python 里调用函数 A,A 里调用函数 B,B 里再调用 C,程序就是靠栈来保存每一层调用现场。一旦递归过深,抛出 RecursionError,本质就是栈溢出了。
队列在工程里更常用,比如:
- 任务队列:把多个待处理任务按顺序排好,逐个执行。
- 消息队列:生产者和消费者解耦。
- 对话历史缓冲:只保留最近 N 轮对话,超出部分自动丢弃。
在 Agent 开发中,一个很典型的队列应用就是“任务计划”。Agent 收到用户复杂指令后,会拆分成多个子任务,按顺序放入队列,然后依次执行:
from collections import deque tasks = deque() tasks.append("查询角色信息") tasks.append("查询武器推荐") tasks.append("生成最终配队建议") while tasks: task = tasks.popleft() print(f"正在执行:{task}")如果某个子任务执行失败,需要重试,还可以用栈记录“回退点”,相当于给任务加一个撤销机制。
2.3 哈希表 / 字典:KV 结构构建“工作记忆”
哈希表(在 Python 中叫 dict)以键值对形式存储数据,理想情况下查找、插入、删除都是 O(1)。
它是 AI 应用里最重要的数据结构之一。可以这样理解:Agent 的“记忆”本质上就是一个大字典。
memory = { "user_name": "紫苏九月", "favorite_character": "芙宁娜", "adventure_level": 58, "chat_history": [] }用字典来管理记忆,好处是:
- 按 key 快速读写,不需要遍历。
- 结构清晰,容易序列化成 JSON 传给大模型。
- 天然适合做缓存。
Agent 开发中,几乎所有的工具调用入参、模型返回结果、知识库记录,最终都会转成字典或 JSON 来处理。
2.4 树与图:从数据组织到流程编排
树结构常见于文件系统、组织架构、DOM 节点、知识库分类。图结构则更适合表达复杂关系,比如社交网络、任务依赖关系。
AI Agent 开发中,树与图主要用在两个地方:
第一,Agent 的工作流编排。
一个复杂的 Agent 可能包含多个节点,比如“意图识别 → 知识库检索 → 大模型生成 → 工具调用 → 结果汇总”。这些节点之间可能有条件分支、循环、并行,如果画成图,每个节点是一个顶点,连线是边。
第二,知识库的层级结构。
比如把《原神》角色资料按“角色 → 天赋 → 命之座 → 武器推荐”组织成树状结构,检索时先定位到角色,再往下层查找具体内容,比平铺查询效率更高。
所以,学完树和图之后,再看 Agent 工作流、再看 RAG 知识检索,你会觉得很多概念非常熟悉。
3. Agent 开发中的数据流:数据结构藏在每一次请求里
3.1 一次大模型调用的“数据链路”
一次大模型调用,表面上只是发一个 HTTP 请求,实际上数据经过了多道结构变换:
- 用户输入 → 作为字符串进入上下文。
- 系统提示词 + 历史消息 + 用户消息 → 组装成一个消息数组。
- 消息数组 → 序列化为 JSON 请求体。
- 大模型返回 → 解析 JSON 响应。
- 把新消息追加回历史记录 → 用队列或列表保存。
每一步都涉及数据结构。如果你不清楚消息该用什么结构存放,很快会写出“字符串拼接一切”的代码,后续维护成本非常高。
3.2 JSON:接口世界的树形数据
JSON 本质上就是树形结构。一个嵌套 JSON 里,有对象节点、数组节点、叶子值,解析 JSON 的过程就是一个树的遍历过程。
看一个典型的大模型响应:
{ "id": "chatcmpl-123", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "根据你的冒险等级,建议优先培养芙宁娜。" } } ], "usage": { "prompt_tokens": 35, "completion_tokens": 18 } }在 Python 里解析时,最常用的是通过字典的 key 逐层取数据:
import json data = json.loads(response_text) message = data["choices"][0]["message"]["content"] print(message)这就是“多维数组/字典的访问练习”。如果对树形遍历不熟悉,遇到三层以上的嵌套 JSON 就很容易写错 key。
3.3 上下文管理:用队列和缓冲区控制 Token 成本
大模型按 Token 计费,上下文越长,单次调用成本越高,响应也越慢。所以不能无限地往消息列表里追加历史对话,必须做截断。
最常见的方式是用一个“滑动窗口”,只保留最近 N 轮对话。Python 的deque(maxlen=N)可以天然实现这个效果:
from collections import deque history = deque(maxlen=3) history.append({"role": "user", "content": "原神怎么快速升级?"}) history.append({"role": "assistant", "content": "优先做主线任务。"}) history.append({"role": "user", "content": "具体怎么做?"}) history.append({"role": "assistant", "content": "传送到任务点,按指引完成。"}) # 只保留最近 3 条,最早的记录被自动丢弃 print(list(history))[{'role': 'user', 'content': '具体怎么做?'}, {'role': 'assistant', 'content': '传送到任务点,按指引完成。'}, {'role': 'user', 'content': '我还要更详细的步骤。'}]注意最后一条是我加的,用来演示容量满了之后旧消息被自动丢弃的效果。实际项目中,除了截断,还有“摘要压缩”策略:把很早之前的对话用大模型生成一段摘要,把摘要当作一条系统消息放进上下文,从而在保留关键信息的同时控制 Token。
3.4 工具调用与状态机:图式编排实现多步骤任务
现代大模型支持 Function Calling,也就是模型在回答前先决定“要不要调用某个工具、传什么参数”。Agent 会根据模型返回的工具调用信息,执行对应函数,再把结果传回模型,继续生成最终回答。
一次真实的工具调用流程如下:
- 用户提问:“帮我查一下水神芙宁娜的培养材料。”
- 大模型分析后返回:
tool_calls里的函数名是query_material,参数是{"character": "芙宁娜"}。 - Agent 执行本地函数,取得材料列表。
- 把工具结果作为一条 role=tool 的消息传回大模型。
- 大模型根据结果生成最终答案。
这段流程里,Agent 需要维护“当前处于哪个步骤”,这就是状态机思维。如果涉及多个工具的串联调用,比如先查角色、再查武器、最后生成报告,就需要用队列或图来编排顺序。
4. 实战一:用 Python 实现一个轻量 Agent 核心骨架
理论说了这么多,下面我们直接写一个可运行的 Python 项目。它不调用真实大模型接口,但完整演示了 Agent 开发中常见的数据结构用法。
4.1 需求拆解
我们要实现一个简化版 Agent,具备以下能力:
- 维护多轮对话上下文,最多保留最近 5 条。
- 用字典保存用户偏好和记忆。
- 支持注册工具,用字典做工具路由。
- 用队列保存待执行任务,依次执行。
- 最终输出一个“模拟回答”。
4.2 建模:每个数据结构对应什么职责
| 数据结构 | 对应职责 |
|---|---|
| deque | 对话历史滑动窗口 |
| dict | 用户记忆 / 工具注册表 |
| deque | 待执行任务队列 |
| str | 最终拼接提示词 |
| list | 工具返回结果列表 |
4.3 核心代码实现
创建文件agent_core.py:
# 文件路径:agent_core.py from collections import deque, defaultdict class Tool: def __init__(self, name, handler, desc=""): self.name = name self.handler = handler # 一个可调用对象 self.desc = desc class AgentCore: def __init__(self, max_history=5): # 对话历史:deque 按顺序保存,超过 maxlen 自动丢弃最老记录 self.history = deque(maxlen=max_history) # 记忆:用 defaultdict 存集合,避免重复插入 self.memory = defaultdict(set) # 工具注册表:以工具名为 key,工具对象为 value self.tools = {} # 任务队列:按顺序执行子任务 self.task_queue = deque() # ---------- 基础能力 ---------- def register_tool(self, tool): self.tools[tool.name] = tool def user_say(self, content): self.history.append({"role": "user", "content": content}) def assistant_say(self, content): self.history.append({"role": "assistant", "content": content}) def remember(self, key, value): self.memory[key].add(value) # ---------- 任务规划 ---------- def plan(self, steps): for step in steps: self.task_queue.append(step) def run(self): if not self.task_queue: print("[Agent] 当前没有待执行任务。") return while self.task_queue: task = self.task_queue.popleft() print(f"[执行] {task}") tool = self.tools.get(task) if tool: result = tool.handler(self) print(f"[工具返回] {result}") else: print(f"[提示] 没有找到工具:{task}") # ---------- 记忆与上下文 ---------- def build_prompt(self): lines = [] for msg in self.history: lines.append(f"{msg['role']}: {msg['content']}") return "\n".join(lines) def show_memory(self): for key, values in self.memory.items(): print(f"{key}: {list(values)}") # ---------- 一个示例工具 ---------- def query_character_handler(agent): # 这里可以写真实的 API 调用或知识库检索 return "芙宁娜——水元素角色,高人气辅助/输出。" def query_material_handler(agent): return "芙宁娜培养材料:涤净青金碎屑、湖光铃兰等。" if __name__ == "__main__": Agent = AgentCore(max_history=5) # 注册工具 Agent.register_tool(Tool("查询角色", query_character_handler)) Agent.register_tool(Tool("查询材料", query_material_handler)) # 用户表达需求 Agent.user_say("帮我查一下芙宁娜的培养材料。") # 记录用户偏好 Agent.remember("favorite_character", "芙宁娜") # 规划任务:按顺序执行 Agent.plan(["查询角色", "查询材料"]) # 执行 Agent.run() # 展示提示词 print("\n===== 当前上下文 =====") print(Agent.build_prompt()) print("\n===== 当前记忆 =====") Agent.show_memory()4.4 运行与验证
在命令行执行:
python agent_core.py预期输出类似:
[执行] 查询角色 [工具返回] 芙宁娜——水元素角色,高人气辅助/输出。 [执行] 查询材料 [工具返回] 芙宁娜培养材料:涤净青金碎屑、湖光铃兰等。 ===== 当前上下文 ===== user: 帮我查一下芙宁娜的培养材料。 ===== 当前记忆 ===== favorite_character: ['芙宁娜']注意:上面代码示例只演示数据结构组织思路,没有实际调用大模型 API。真正接入大模型时,只需要把build_prompt()的结果传给模型接口,再把模型返回追加到Agent.history中即可。
4.5 为什么说这是“入门到开发”的第一步
上面这段代码用到的知识点,全部是数据结构与算法里的基础内容:
deque用来做上下文滑动窗口。dict用来做工具路由和记忆存储。set用来做去重。list用来组织返回结果。- “任务规划→入队→执行”是一种队列调度思想。
如果你能看懂这段代码,并且知道为什么要选deque而不是普通list,说明你已经具备把数据结构知识迁移到实际开发的意识了。
5. 实战二:借助可视化平台搭建“AI 原神助手”智能体
如果你不希望从零写代码,也可以借助目前主流的 AI Agent 可视化平台快速搭建一个“AI 原神助手”。这类平台通常支持无代码或低代码配置,适合先跑通完整产品流程,再回去理解底层数据结构。
5.1 平台选型思路
目前常见的平台类型包括:
- 通用 Agent 平台:如 Dify、Coze 等,支持知识库、工作流、插件,适合快速搭建问答助手。
- 云厂商大模型平台:很多云厂商提供 Agent 开发服务,内置大模型接口、知识库、函数调用能力。
- 开源框架:如 LangChain、LlamaIndex,适合有一定编程基础、需要深度定制的团队。
选择哪种平台取决于你的需求。如果只是想快速验证“AI 原神助手”的交互效果,可视化平台足够;如果要对接私域数据、自定义复杂逻辑,建议使用开源框架或直接写代码。
需要注意的是:不同平台的功能名称和版本迭代速度不同,本文只讲通用设计思路,具体界面以你使用的平台为准。
5.2 设计 Agent 结构
无论是哪种平台,一个 AI Agent 通常都包含以下几块配置:
| 模块 | 作用 | 数据结构对应 |
|---|---|---|
| 系统提示词 | 定义 Agent 身份和行为边界 | 字符串模板 |
| 知识库 | 存放角色攻略、材料数据 | 文档列表、向量索引 |
| 工具 | 提供搜索、计算等外部能力 | 函数注册表 |
| 对话记忆 | 保存多轮会话 | 队列/列表 |
| 工作流 | 编排多步骤任务 | 图/状态机 |
“AI 原神助手”可以这样设计:
- 用户提问。
- 先判断问题类型:知识问答、配队推荐、活动查询。
- 如果是知识问答,走知识库检索。
- 如果是活动查询,调用工具搜索最新信息。
- 如果是配队推荐,结合用户已有角色记忆生成方案。
- 生成最终回答。
5.3 知识库与提示词配置思路
系统提示词模板参考:
你是一个原神助手,擅长回答《原神》游戏相关问题。 你的回答要简洁、准确、实用。 当用户询问角色培养、材料收集、配队方案时, 请优先参考知识库内容。 如果知识库没有相关内容,可以结合通用知识回答, 但需要说明“该信息可能不是最新版本”。知识库结构参考:
- 整理一份角色表,字段包括:角色名、元素、星级、定位、天赋、命之座、推荐武器、推荐圣遗物。
- 整理一份材料表,字段包括:材料名称、获取方式、来源怪物、采集地区。
- 将文档按角色或主题切块,导入知识库。
知识库本质上是把文档拆成很多小块,每个小块做向量化,查询时用相似度检索出最相关的几个块。这个过程可以看成“数组切片 + 树形索引 + 排序取 TopK”。
5.4 测试与发布
搭建完成后,建议按以下清单测试:
- 单轮知识问答是否准确。
- 多轮对话是否记得用户偏好。
- 查询最新活动时是否能触发工具调用。
- 遇到知识库覆盖不到的问题,是否会兜底回答。
- 长对话后响应是否变慢、费用是否明显上涨。
发布时要注意:对话历史、用户隐私、调用频率、成本监控都需要重点关注。先把体验做好,再考虑功能扩展,比如接入每日签到、角色养成进度记录、配队模拟器等。
6. 常见问题与排查思路
在从数据结构学习转向 AI 应用开发时,新手经常会遇到以下几个问题。下面用表格整理常见错误和排查思路。
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| 对话历史越来越长,调用费用飙升 | 使用了无限增长的 list,没有截断 | 改用deque(maxlen=N)或做摘要压缩 |
| Agent 执行任务顺序错乱 | 任务管理没有使用队列或栈,直接乱序调用 | 明确任务调度规则,统一入队/出队 |
| 大模型返回的 JSON 解析失败 | 返回内容被截断,或没有完整拿到响应体 | 先拼完整缓冲区,再json.loads,并处理异常 |
| 多轮对话忘记用户偏好 | 记忆只存在当前会话,没有持久化 | 用字典/数据库保存用户画像,在每次请求时注入 |
| 知识库检索效果差 | 文档切块过大/过小,检索结果不相关 | 调整切块大小,增加标题与摘要字段,做召回测试 |
| 流式输出出现乱码/断句 | 中文字节被截断,按固定长度切分导致半个字符 | 使用缓冲区,按完整字符边界或句子边界输出 |
| 工具调用参数错误 | 工具入参不符合大模型生成的参数结构 | 定义严格的 JSON Schema,并在工具层做参数校验 |
| Prompt 越来越长但模型表现下降 | 塞入太多无关信息,上下文被污染 | 精简系统提示词,把历史摘要放在前部,相关性高的放后部 |
下面重点说明两个高频坑。
第一个坑:队列长度设置不合理。
deque(maxlen=N)不是越大越好。如果 N=50,意味着每次请求都要携带 50 轮对话,Token 消耗大、响应慢、费用高。如果 N=3,又可能丢失关键信息,导致 Agent “失忆”。根据实际业务调节,一般问答类助手建议 5~10 轮,需要深度推理的辅助工具可以适当增加,但最好配合摘要压缩机制。
第二个坑:直接把大模型输出当纯文本处理。
很多模型支持流式输出、工具调用、JSON 结构化输出。如果你只把它当普通文本,遇到tool_calls字段时很容易漏处理。正确的做法是先统一转成字典,再判断是否有tool_calls,再决定走工具调用分支还是直接返回用户。
7. 从“学完数据结构”到“稳定做 AI 应用”的工程建议
学了数据结构,不代表能写出稳定可维护的 AI 应用。下面这些工程建议,是我在实际项目中总结出来的经验。
7.1 数据组织优先于写代码
写代码之前,先想清楚数据怎么组织。
- 对话消息用什么结构?建议统一用
{"role": "user" / "assistant" / "tool", "content": "..."}。 - 用户记忆用什么结构?建议按业务维度拆分 key,比如
favorite_character、last_query。 - 工具返回值用什么结构?建议统一包一层
{"status": "ok", "data": {...}}。
数据结构设计清楚了,代码写起来很顺。如果一开始就用字符串拼接对话记录,后面做截断、做摘要、做工具调用会非常痛苦。
7.2 异常处理与容错
AI 应用的不可控因素比传统后端多:
- 模型可能超时。
- 模型可能返回格式不对。
- 工具可能执行失败。
- 知识库检索可能没有结果。
所以在关键路径上都要有异常处理。比如调用大模型时,捕获超时异常,做一次重试;解析返回 JSON 时,捕获JSONDecodeError,必要时把原始内容写入日志。
7.3 日志与可观测
每一轮 Agent 运行都应该记录:
- 请求 ID。
- 用户输入。
- 模型返回的中间结果。
- 调用了哪些工具、传了什么参数、返回了什么。
- 最终输出。
- Token 消耗和耗时。
有了这些日志,遇到问题才能快速定位。传统开发强调“可观测性”,AI 应用更是如此,因为你很难复现一次随机对话。
7.4 成本与性能
控制成本是 AI 应用上线后的头号问题。几个实用手段:
- 用
deque限制上下文长度。 - 对重复问题做缓存,用 key 为“用户ID + 问题摘要”的字典。
- 对不需要大模型推理的固定回答,用规则直接返回。
- 流式输出可以改善用户体验,但要注意前端缓冲区处理。
- 批量处理任务时,要注意 API 的并发限制。
7.5 安全与合规
在开发和部署 AI 应用时,务必遵守平台规则和当地法律法规:
- 不要在提示词中引导模型输出违法违规内容。
- 用户隐私数据要脱敏存储,不要明文日志。
- 大模型 API Key 要放在服务端环境变量里,不要暴露在前端。
- 工具调用要限制权限,避免 Agent 执行危险操作。
- 生产环境变更前先在小范围灰度,做好备份和回滚方案。
这些原则不仅适用于“AI 原神助手”,也适用于所有 AI 应用开发项目。
8. 总结
“数据结构入门了,是时候开发原神了”这句话虽然是一句玩笑,但它背后的逻辑是成立的:数据结构决定了你对数据组织和流程编排的理解深度,而 AI 应用开发又把这种理解变成了真实产品能力。
这篇文章从数据结构核心概念讲起,重点分析了数组、栈、队列、哈希表、树图在 Agent 开发中的具体应用,然后给出了一个可运行的 Python Agent 骨架,并介绍了可视化平台搭建“AI 原神助手”的设计思路。你还可以继续深入学习。
如果你刚学完数据结构,建议动手做三件事:
- 把上面的
agent_core.py自己敲一遍,尝试加入“撤销上一步操作”的栈逻辑。 - 找一个可视化平台,搭一个自己的“AI 原神助手”。
- 把你熟悉的排序算法、树的遍历思想,迁移到“知识库检索结果排序”和“工作流节点执行”中。
数据结构是一门越用越熟练的基础课。当你开始用队列管对话、用字典管记忆、用图编排 Agent 工作流的时候,你会真正理解:它不是在考试卷上,而是在每一行代码里。