news 2026/9/7 6:50:30

从模型到Agent:手写最小Agent Loop的完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从模型到Agent:手写最小Agent Loop的完整指南

先放个观点:模型不是 Agent。这句话我最近在好几个项目里反复体会到,尤其是当你试图让一个大语言模型“自己完成一件需要多步操作的事”时,模型本身的局限性会非常明显。模型能做的是根据输入生成输出,但 Agent 要做的是一件事从目标出发,通过感知环境、调用工具、观察结果、调整策略,最终把目标完成。这个循环就是 Agent Loop,也是我从零实现一个最小可用 Agent 时,最先搞清楚的东西。

这篇文章会从“模型和 Agent 到底差在哪”讲起,然后拆解一个最小 Agent Loop 的四个核心环节,再给出一套可以直接跑起来的 Python 代码框架,最后聊聊我在实操中踩过的坑和排查思路。不管你是想入门 Agent 开发,还是已经写过一些 Demo 但总觉得不“Agent”,这篇文章应该都能给你一些可落地的参考。内容不依赖任何重型框架,底层逻辑讲透之后,你去看 LangChain、AutoGPT、MetaGPT 之类的项目,也会更容易理解它们到底在做什么。

1. 模型和 Agent 之间差的不是一个概念,而是一个 Loop

1.1 模型是“脑子”,Agent 是“手脚加脑子”的循环

经常有人把“调一下大模型接口”叫成“做了一个 Agent”,但严格来说,这只是在调用一个模型。模型本质上是函数:输入文本,输出文本。你把一段 prompt 丢进去,它基于训练时学到的概率分布吐出一段回答,这个过程没有目标,没有环境,没有反馈,更没有连续行动。Agent 不一样,Agent 是围绕一个目标持续运行的系统,它有感知、有决策、有动作,还会根据动作的结果修正下一步动作。

怎么理解?打个比方,模型像一个很聪明但不会动手的顾问。你问他“北京今天适合出门吗”,他能根据训练数据里的常识给你一通分析。但如果你让他“帮我看看北京现在下雨没,然后再查一下未来三小时有没有雨,最后告诉我该不该带伞”,单次调用模型,他只能给你一个“建议”,而不是真正去查数据。Agent Loop 做的事情,就是给这个聪明顾问配上查询天气的“手”,让他自己去查、去比对、去得出结论,并且这个过程中他可以多次查询、多次思考,直到把事情办完。

所以我说模型不是 Agent,这句话真正的含义是:模型只是 Agent 内部那个负责“思考”的引擎,Agent 本身是一个包含思考、行动、观察、再思考的循环结构。这也是 Agent Loop 这个名字的来源,英文里的 loop 就是循环。

1.2 为什么光靠模型调用干不了“多步实事”

单次调用模型干不了多步实事,原因其实不复杂。第一,模型没有自主性,你问一句他答一句,你不继续问,他就不继续动。第二,模型没有工具,他不能真的去查数据库、调接口、操作文件,只能基于训练数据做推断。第三,模型没有反馈机制,他生成完一段文字就结束了,不会知道这个结果到底有没有用、地方对不对、下一步该不该调整。

举个例子,你想让模型“把当前目录下所有大于 10MB 的文件列出来,并按大小排序”。如果只是调用模型,他能给你一段 Python 代码,但不会替你执行,更不会帮你把执行结果拿回来继续处理。Agent Loop 就能解决这个问题:模型先生成一段代码,Agent 把代码放到终端里跑,然后把输出回传给模型,模型基于输出继续整理成你要的列表。这个“生成工具调用、执行工具、回填结果、继续推理”的循环,就是 Agent 的骨架。

我在最初做 Agent 的时候,最大的误区就是把 prompt 写得特别复杂,妄想让模型“一步到位”。后来我发现,真正让 Agent 变实用的不是把 prompt 写得天花乱坠,而是把 Loop 搭好,让模型在循环里自然地进行多步推理。接下来我就拆一下这个最小 Loop 到底由哪些部分组成。

2. 最小 Agent Loop 的四个核心环节

2.1 Loop 的本质:思考、行动、观察、再思考

一个最小可用的 Agent Loop,抽象出来就四个环节:思考(Think)、行动(Act)、观察(Observe)、再思考(Repeat)。模型在循环里不是只生成一次,而是生成多次,每次生成的内容会被 Agent 解析,如果发现模型想调用某个工具,Agent 就执行这个工具,把结果作为新的上下文喂给模型,模型再继续生成。直到某次生成里模型不再调用工具,而是给出了最终答案,循环才结束。

这跟人类的做事方式很像。你打算出去玩,第一步是看天,第二步是决定要不要带伞,第三步是出门前再看一眼窗外,确认没有变天,第四步再决定最终带不带。Agent 也一样,每一步“看”到的信息都会影响下一步“想”的方向。这种循环结构最大的优点,是让整个系统的行为变得可以拆解,你可以随时介入、随时调试,而不是靠一个大 prompt 相信模型能一次搞定。

我再强调一遍,这四步缺一不可。没有“思考”,模型输出就没有方向;没有“行动”,模型只能纸上谈兵;没有“观察”,模型不知道自己刚才做的有没有用;没有“再思考”,整个流程就断了,没法逼近最终目标。

2.2 工具调用的格式设计:让模型“会用人手”

要让模型在循环里调用工具,首先得让模型“知道”有哪些工具可用,以及怎么调用。目前主流做法是在请求里带上工具定义,让模型生成一个结构化的“想要调用某个函数”的指令,而不是让模型自己在文本里写“我想调用查天气函数”。

以 OpenAI 的 function calling 格式为例,工具定义是一个 JSON Schema,里面包含工具的名称、描述、参数和参数类型。模型看到这些定义之后,如果觉得某个工具对当前任务有帮助,就会在返回内容里带一个tool_calls字段,里面写明要调用哪个函数、参数是什么。Agent 拿到这个字段之后,自己去执行对应的函数,再把结果以tool消息的形式返回给模型。

这个设计很好理解:模型不是真的能执行工具,而是“提出一个调用工具的请求”,真正执行的还是你的代码。所以工具格式设计得好不好,直接影响模型能不能准确调用。我的经验是,工具描述一定要写清楚“什么时候用”和“怎么用”,比如“当用户询问天气时,调用此工具,参数 city 是城市中文名”,模型理解起来会容易很多。如果描述太模糊,模型很容易在不需要调用工具的时候乱调用,或者在需要调用的时候漏调用。

2.3 停止条件与轮数限制:没有出口的循环是灾难点

Any循环都要考虑出口。Agent Loop 也不例外。如果模型迟迟不给最终答案,或者反复调用同一个工具,你的程序就会一直跑下去,既消耗 token 又浪费时间。所以最小实现里必须设置两样东西:最大轮数和停止条件。

最大轮数就是 Agent 最多进行多少轮“思考和行动”,比如设成 5 或者 10。一旦超过这个数还没出最终答案,就强制终止,返回一个超时错误。停止条件则是“模型不再请求调用工具,而是输出最终答案”,这是最自然的循环出口。

实操中我还会额外加一个“重复检测”:如果模型连续两三次生成完全一样的工具调用,大概率是陷入死循环了,这时候直接中断比继续跑下去更有意义。这种启发式规则不难实现,我就见过很多人在日志里看到一大堆重复的 tool_call,其实这就是代码里少了重复检测导致的。

2.4 为什么最小实现不需要框架

现在市面上有大量 Agent 框架,LangChain、AutoGPT、MetaGPT、Microsoft Agent Framework 之类,功能看着很全。但我在从零实现最小 Agent Loop 的过程中,最大的体会是:理解本质之前,不要急着套框架。框架帮你封装了太多细节,表面上你写两行代码就能跑起来一个 Agent,但遇到问题的时候你根本不知道问题出在哪儿,是在模型那边,工具那边,还是编排逻辑那边。

自己实现一个最小 Loop 并不难,代码量可能就一百行左右。你自己写一遍循环,就会很清楚每一步发生了什么:模型在什么时候决定调用工具、工具结果怎么回填、上下文怎么组织、什么时候该停止。这些理解会帮助你看框架源码时一眼就知道它们在做什么,排查问题也有方向。

所以这篇文章接下来我直接给你一个可以运行的最小实现,不需要装任何框架,只需要有一个支持工具调用的模型接口就行。

3. 从零实现:一个可直接运行的最小 Agent

3.1 技术选型:Python 加一个兼容工具调用的模型

实现语言我选了 Python,原因不用多说,生态最简单,处理 JSON、HTTP 都很方便。模型方面,你只需要一个支持工具调用的模型接口,现在很多模型都兼容 OpenAI 的 tools 参数格式,比如本地 Ollama 的某些模型、Qwen、DeepSeek 等。为了演示方便,我建议你直接用 OpenAI 兼容的接口,代码里只需要用requests或者openai的 Python SDK 即可。

如果你没有 API Key,也可以用本地部署的方案,比如 Ollama 里跑一个 qwen2.5 或者 llama3.1 之类的模型,本地接口开到http://localhost:11434/v1,然后代码里把base_url指过去就行。本地模型的好处是数据不出门、免费,缺点是推理速度慢,但跑通最小 Loop 完全够用。这里我不限定具体厂商,你用自己手头能调通的模型就行。

3.2 定义工具:先用计算器和“假天气接口”练手

定义一个工具,本质上就是写一个普通的 Python 函数,然后给这个函数配一份 JSON Schema 说明。为了方便演示,我定义两个工具:一个是calculator,用来算加减乘除;另一个是get_weather,我故意不接真实天气 API,而是返回一个固定结果,这样你跑起来不需要申请任何第三方 API。

为什么要用假天气?因为最小 Demo 的重点是“循环怎么跑”,不是“工具怎么实现”。等你理解了 Loop 结构,再把假工具换成真实 API、数据库查询、文件操作都很容易。工具函数本身和 Agent 循环是解耦的。

工具定义示例:

def calculator(expression: str) -> str: # 生产环境不要用 eval,这里仅作演示 return str(eval(expression)) def get_weather(city: str) -> str: return f"{city} 现在小雨,未来三小时有小到中雨,温度 18-20 度"

对应工具 Schema:

tools = [ { "type": "function", "function": { "name": "calculator", "description": "计算数学表达式的值,比如 '1 + 2 * 3'", "parameters": { "type": "object", "properties": { "expression": {"type": "string"} }, "required": ["expression"] } } }, { "type": "function", "function": { "name": "get_weather", "description": "查询指定城市的实时天气和未来三小时预报", "parameters": { "type": "object", "properties": { "city": {"type": "string"} }, "required": ["city"] } } } ]

这里有个细节:参数名和函数参数名要保持一致。calculator里参数叫expression,Schema 里 properties 也要叫expression。如果对不上,模型生成的参数传到函数里就会TypeError

3.3 核心循环代码:一百行以内跑通 Agent Loop

下面是我自己常写的最小循环版本,你可以直接抄走跑。核心逻辑就一个for循环,循环里做三件事:调用模型、检查是否有工具调用、如果有就执行工具并回传结果,如果没有就输出最终答案结束。

import json import requests def chat_once(api_url, api_key, messages, tools): payload = { "model": "你的模型名", "messages": messages, "tools": tools, "tool_choice": "auto" } headers = {"Authorization": f"Bearer {api_key}"} resp = requests.post(api_url, json=payload, headers=headers) resp.raise_for_status() return resp.json()["choices"][0]["message"] def run_agent(task, api_url, api_key, tools, tool_map, max_steps=5): messages = [{"role": "user", "content": task}] for step in range(max_steps): print(f"\n===== Step {step + 1} =====") msg = chat_once(api_url, api_key, messages, tools) messages.append(msg) if msg.get("tool_calls"): for call in msg["tool_calls"]: fn = call["function"] name = fn["name"] args = json.loads(fn["arguments"] or "{}") print(f"调用工具: {name}, 参数: {args}") result = tool_map[name](**args) messages.append({ "role": "tool", "tool_call_id": call["id"], "content": result }) else: print("最终答案:", msg["content"]) return msg["content"] raise RuntimeError("超过最大轮数,未得到最终答案") if __name__ == "__main__": api_url = "http://localhost:11434/v1/chat/completions" api_key = "YOUR_API_KEY" tool_map = {"calculator": calculator, "get_weather": get_weather} result = run_agent( task="帮我计算 (12 + 34) * 5 的结果,然后查一下北京的天气,并告诉我出门要不要带伞。", api_url=api_url, api_key=api_key, tools=tools, tool_map=tool_map, max_steps=5 ) print("\nAgent 最终返回:", result)

这段代码就是最小 Agent Loop 的骨架,你把它跑起来之后,会看到日志里模型先生成一次,决定调用计算器工具,工具返回结果,模型再生成一次,决定调用天气工具,天气返回结果,最后模型综合结果给出最终答案。整个过程非常直观。

几个需要注意的细节:第一,messages是不断累积的,模型每次生成前都能看到前面所有的历史,所以工具结果会被自动当作上下文的一部分。第二,tool_call_id必须精确回填,这是把“工具调用请求”和“工具调用结果”配对的关键字段,如果漏掉这个字段,很多模型会报错。第三,最大轮数不要设太大,5 到 10 足够大多数简单任务,设太大反而会在死循环时浪费更多时间。

3.4 跑起来看日志,理解每一步的状态

代码写完之后,我强烈建议你先跑一个简单任务,把日志完整看一遍。你会发现模型第一次生成的tool_calls内容是什么、工具返回之后模型的态度发生了什么变化,这些“现场感”是看文档得不到的。

我实际跑过一个天气任务,日志大概是这样的:第一次模型调用get_weather,参数是{"city": "北京"},工具返回“北京小雨”,然后模型下一步没有继续调用工具,而是直接输出“北京现在下雨,出门建议带伞”。整个循环就两步:一步行动,一步收尾。非常符合直觉。

如果你跑出来的结果和预期不一致,比如模型一轮就输出最终答案,没有调用工具,那也不用慌,多半是工具描述不清晰,或者tool_choice设成了auto之后模型觉得不必调用。你可以把tool_choice强制设为{"type": "function", "function": {"name": "get_weather"}}来逼它必须先查天气,这在调试的时候很好用。

3.5 从手工循环到循环内的“异常安全”

真实场景中,工具调用不一定总是成功。比如网络超时、参数传错、模型生成的 JSON 格式不合法。所以最小实现里,我还会在工具调用外面套一层 try-except。如果工具抛异常,我会把错误信息当作工具结果回传给模型,让模型自己决定是换个参数重试还是告诉用户工具出错了。这比让 Agent 直接崩溃要好得多。

举个例子,如果用户问“计算 10 除以 0”,calculator里的eval会抛ZeroDivisionError,如果我把异常信息回传给模型,模型可能会说“这个表达式无法计算,因为除数为零”,而不是整个程序崩掉。这个设计叫“错误即观察”,在 Agent Loop 里非常实用。很多时候模型比你想的聪明,你给它一个错误信息,它能自己修正调用方式。

4. 实际运行时常见的坑和排查方法

4.1 模型就是不调用工具,光给你一段话

这是我见过最多的问题。现象是:任务明明需要查天气,模型却直接输出“北京今天可能有雨,建议带伞”,完全不经过工具。排查思路有三个方向。

第一,检查工具定义里的描述是否清晰。如果get_weather的描述写的是“一个函数”,模型很可能不知道什么时候该用它。改成“当用户查询某个城市的天气或需要基于天气做决策时,必须调用此工具”,效果会立刻不一样。第二,检查模型本身是否支持工具调用。有些模型 API 虽然兼容 OpenAI 格式,但工具调用能力很弱,可能直接忽略 tools 参数。你可以先手动构造一个简单请求,看看返回里有没有tool_calls字段。第三,检查tool_choice。如果你设了"tool_choice": "none",模型永远不会调工具,这个参数默认是"auto",但有些 SDK 的默认行为不同,显式设置比较稳妥。

我自己的经验是,前两个原因占了 80%。很多新手一上来就怪模型笨,其实就是工具描述没写好。

4.2 循环卡死或无限转圈,最后报 execution terminated

如果你看到日志里模型不断生成tool_calls,但始终没有最终答案,这就是死循环。最常见的原因是工具执行结果没有改变模型所处的状态,比如某个工具不管传什么参数都返回同一句话,模型反复尝试也没法推进任务。

解决办法有几个。一是设置最大轮数,这是底线,保证程序不会无限跑。二是加重复检测,比如相邻两轮生成完全相同的tool_calls,直接中断并提示“检测到重复调用”。三是给工具结果多回传一些信息,比如错误原因、可用参数范围,让模型能更有针对性地修正。

另外提到“Agent execution terminated due to error”这类报错,常见的是上下文超长或者 API 返回 400。我遇到最多的是tool_call_id配对错误,或者工具参数是非法 JSON。你可以在把工具结果回填前打印一下相关内容,基本一眼就能找到问题。

4.3 上下文越来越长,后面效果越来越差

Agent Loop 每转一轮,messages 里就会多一条 assistant 消息和一条 tool 消息。如果任务复杂,十几轮下来上下文会非常长,既花钱又可能让模型“迷失在上下文中”。尤其是当你一次回传了大量工具结果,模型再看后面的任务提示时,注意力容易被带偏。

我的做法是给工具结果做截断和摘要。比如某个工具返回 5 万字符,我不会全部塞进上下文,而是先截断前面几百字符,或者用一个小模型做个摘要,再把摘要回填。还有一个思路是只保留最近 N 轮的消息,更早的历史可以折叠成一句“在此之前你已经完成了哪些步骤”,让模型记得主干但不用看每一条细节。

不过要注意,截断得保守一点,别把关键信息截没了。我一般在 debug 阶段先不截断,跑通之后再逐步加截断逻辑,避免引入新的问题。

4.4 工具参数格式对不上,函数执行报错

模型生成的arguments是 JSON 字符串,如果你用json.loads解析失败,多半是模型生成了不合法 JSON,比如多了一个逗号、用了单引号。这种问题在那个场景下很少见,但模型越弱越容易出现。你可以加一层容错:尝试json.loads,如果失败就用正则匹配里面的纯字符串形式,再不行就直接把原始字符串作为参数传给一个只接受单个字符串的工具。

另一个常踩的坑是参数名不一致。比如你在 Schema 里写的是city,函数定义里却写的是city_name,模型按 Schema 生成{"city": "北京"},调用函数时就会报unexpected keyword argument 'city'。最简单的办法是让函数参数名和 Schema 里的属性名保持一致,别搞映射,除非你有特殊需求。

4.5 安全边界:别让 Agent 随便执行一切工具

最后提一个很多人忽略的问题,Agent 能调用工具意味着它有“行动能力”,如果工具里包含执行 Shell 命令、删除文件这种危险操作,一定要做权限限制。从零实现的时候,你可以先只让 Agent 调用只读工具,比如查询天气、计算数学、读文件,不要开放任意代码执行、数据库写入。

如果确实需要写操作,我建议加一个确认机制:Agent 生成工具调用之后,不直接执行,而是先打印给用户看,等用户输入 y 再真正执行。这个“人工审批”环节在自动化测试里尤其有用,可以避免模型因为 prompt 注入或者理解偏差,做出不可逆的操作。这也是为什么我把工具调用和真正执行分开设计,表面上看多了几行代码,但安全性和可控制性高很多。

5. 从最小 Loop 到真正可用的 Agent:记忆、技能与框架

5.1 记忆:给 Loop 加上持久化状态

最小 Loop 里的消息列表就是记忆,但它只是“当前任务内的短期记忆”。任务一结束,消息列表清空,什么都没留下。真实场景里,Agent 需要长期记忆,比如记住用户偏好、记住上次任务结果、跨会话复用经验。实现长期记忆的办法一般是用向量数据库存历史记录,或者用结构化数据库存关键信息,然后在每次任务开始前,把相关的历史记忆检索出来拼进系统 prompt。

我建议先不要急着上向量数据库,你可以先做一个简单的文件版记忆:每次任务结束后,把关键信息存到一个 JSON 文件里,下次任务开始时读取相关字段。这种方式足够让你理解“记忆”到底是怎么参与到 Agent Loop 里的。等你有经验了,再换向量库也不迟。

5.2 技能(Skill)和工具(Tool)的区别

现在 Agent 社区里“Skill”这个词很流行。很多人问 skill 和 tool 到底有什么区别。我的理解是,Tool 是原子操作,比如“查天气”“计算表达式”“读文件”;Skill 则是把多个 Tool 和提示词编排成一个“可复用的能力”,比如“做一个市场调研”是一个 Skill,它会内部调用搜索工具、读取网页工具、汇总工具,甚至还会调用多个模型轮次。

从最小 Loop 的角度看,Skill 其实就相当于一个“复合工具”。你可以把 Skill 也定义成一个函数,对外暴露统一的输入输出,内部再去调用更小的工具。这样设计最大的好处是复用,你不需要每次写任务都从零设计一堆工具调用流程,而是把常见套路封装成 Skill。这也是为什么很多 Agent 框架都开始引入 Skills 的概念。

5.3 框架到底在帮你解决什么

当你理解了最小 Agent Loop 之后,再去看现成的 Agent 框架会很轻松。框架解决的是工程化问题:多工具调度、错误重试、并发执行、记忆插槽、可视化观测、插件体系、权限管理。这些不是核心原理,而是规模化和稳定性的配套设施。你完全可以在自己的最小实现上一点点加,但也确实没必要重复造轮子,如果项目已经复杂到一定程度。

不过我的建议是,至少在动手做第一个 Agent 项目时,自己把最小 Loop 手写一遍。这个“慢”会给你带来扎实的理解。以后再切换框架、选型技术方案,你心里会有底得多。

5.4 Agent Loop 的调试与可观测性

最后一个我想强调的点是日志。Agent Loop 本身就是多步骤交互,你如果不打日志,出了问题根本没法查。我在实现里会在每个 Step 开头打印当前步骤数,每次工具调用都打印工具名和参数,每次工具返回都打印结果片段,每次最终输出都完整打印。这不是为了炫技,而是为了让整个循环过程“可审讯”。

有条件的可以把每一步的消息都存下来,后面复盘的时候看看模型是在哪一步开始“跑偏”的。很多 Agent 项目真正难的不是写代码,而是调试。你要是能把日志做好,后面排查问题会快很多。这也是我踩了很多坑以后最想分享的经验之一:先把日志写好,再谈优化。

如果日志打印的是英文,你可能会看到类似tool_call_idrole: assistantfinish_reason: tool_calls这种字段。别怕,这就是最小 Loop 里最基本的几个元素。你只要把每一步的数据流动看清楚,Agent 就不再是玄学。

我个人在实际操作中的体会是,手写一个最小 Agent Loop 最大的价值,不是做出一个多厉害的 Demo,而是让你建立对“模型输出驱动行动”这个机制的手感。工具调用的格式、上下文回填的顺序、停止条件的判定,这些细节在文档里看一百遍,都不如自己跑一遍印象深。

最后再分享一个小技巧:调试 Agent 循环时,不要一上来就塞很多工具,先从一个工具、一个任务开始跑通。跑通之后再加第二个工具,再跑一个需要两个工具配合的任务。这样你很容易定位问题到底出在模型的工具选择上,还是出在工具本身的执行上。等这个最小循环已经变得非常顺手,你再去研究记忆、技能、多 Agent 协作,会发现那些东西都是在这个核心 Loop 上长出来的。

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

Atlas1337技术项目实测:从环境准备到生产部署的完整指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 6:46:29

Pixy2源码包实战:从固件编译到颜色识别全解析

简介:面向Arduino开发者的Pixy2机器视觉完整项目包,围绕“物体识别与跟踪”场景提供从底层固件到应用示例的全套参考资料。压缩包内含490个文件,以C/C源码(h、cpp、c)、Arduino工程文件(ino、project、uvpr…

作者头像 李华
网站建设 2026/9/7 6:45:03

解压到稳定对接:中控Java二次开发实战指南

简介:针对中控考勤机二次开发的Java示例项目,面向需要对接考勤硬件、实现自动化考勤数据采集与人员管理的后端开发人员。压缩包大小约37.77MB,内含源码与配套文档,文件总数与具体类型暂未标注,但内容覆盖从通信对接、数…

作者头像 李华
网站建设 2026/9/7 6:44:48

多人聊天系统架构实战:WebSocket、Redis与消息可靠性设计

简介:这是一套基于JSP与Servlet技术构建的多人聊天系统Java Web项目源码,面向正在学习Java Web开发的学生和初中级开发者,用来理解多用户实时通信、会话保持与页面动态交互的实现方式。压缩包共11个文件,以6个class字节码、2个jav…

作者头像 李华
网站建设 2026/9/7 6:44:09

基于LSTM的通信信号调制识别实战:RML2016.10a数据集与Pytorch实现

简介:面向通信信号调制识别任务,这套基于RML2016-10a数据集的LSTM实现方案,采用PyTorch框架,适合期望掌握循环神经网络在无线信号处理中应用的开发者与研究人员。压缩包共14个文件,涵盖Python训练与数据处理脚本、pyc编…

作者头像 李华