C++从零实现MCP协议:智能体工具调用的核心工程实践
做智能体对接工具这事我以前一直觉得“协议不过是定个格式而已”直到自己亲手用C把MCP协议从零实现了一遍才意识到真正的复杂度全在边界条件和工程取舍上。这篇文章就是我对整个实现过程的复盘也是我们智能体通讯项目里这个子项目的核心设计笔记。如果你正准备给自己的AI应用接入工具调用体系或者想把MCP的基础能力嵌进C运行时这篇文章应该能帮你少走不少弯路。1. MCP协议到底在解决什么问题从AI应用与外部工具对接的痛点说起1.1 没有标准协议时工具集成是怎么乱成一团的先从一个具体场景说起。假设你的智能体需要同时调用日历服务、数据库查询接口和一个图像处理工具在没有统一协议的情况下你面对的是三套完全不同的HTTP接口A服务要用POST /api/v1/create_eventB服务要拼query string再带自定义鉴权头C服务干脆走gRPC。每个接口的入参格式、错误码语义、超时处理全都不一样。这时候你会发现真正的成本不在于调通某一个接口而在于“集成逻辑”本身写满了各种定制分支。函数里全是if (provider calendar)这种发散结构每接入一个新工具都要重新写一遍参数转换和错误映射。MCP协议要解决的就是把这个“接入成本”收敛成一套标准的交互范式——统一的传输层约定、统一的参数描述方式、统一的调用返回结构。当然一开始我也在想就直接用OpenAPI文档让它生成客户端不就行了但实际做下来发现OpenAPI描述的是“服务端视角的接口”而MCP描述的是“能力提供者与消费方之间的对话规则”它同时管住了工具清单、调用执行的格式还包括后续要说的生命周期和会话协商。两种定位还是明显不一样的。1.2 MCP的四个核心角色以及它们在智能体项目里各自代表的形态我先把MCP协议里的角色关系和团队里的部署形态做个简单的对照。协议文档里通常把参与方分成Host、Client、Server三层头顶上还要站一个Agent智能体本体。刚开始接触时很容易把Client和Host混在一起但写代码时你会发现这俩必须分开设计。角色职责在我们项目里的落地形态Agent发起任务的智能体本体是使用工具的主体主程序里的任务编排层HostAgent运行所在的容器/进程管理Client与Server的连接生命周期C主进程负责启动和销毁会话Client在Host内部运行负责与Server做协议层面的请求/响应交换每个Server连接对应一个Client实例Server提供工具、资源、提示词的进程/服务真正干活的一方本地子进程或远端HTTP服务进程这里值得多说一句在MCP协议的标准握手流程里两端都会声明自己的能力Host侧的Client要告诉Server“我能接收什么类型的通知”Server要告诉Client“我能提供什么类型的工具”。最开始我图省事让Client直接内嵌在主进程里结果发现只要涉及到跨进程通信角色边界就会变得很模糊。后来还是老老实实按协议拆开每个Server连接独立一个Client对象这样后面做会话数统计、工具粒度鉴权都方便了许多。1.3 为什么要在C层面重新实现一遍协议看到这里你可能会有疑问市面上已经有那么多MCP的SDK了Python有、TypeScript也有为什么我们还要在C里重新造一遍轮子其实这个决定是项目背景逼出来的。我们那个智能体通讯项目核心运行时本来就是一套C基础服务不想为了一个配套协议组件再拉一套跨语言运行时进来。更重要的是协议基础设施一旦引入脚本语言层排查问题时你就要在两条技术栈之间来回跳性能开销和运维复杂度都会明显上升。用C直接实现协议还有一个额外的好处整个状态流转都是可控的。你可以自己在initialize阶段注入额外版本标识可以在每个JSON-RPC消息通过的时候打印调用链甚至能在工具调度时做统一的超时中断而不需要依赖上层框架是否支持这些钩子。对于做基础通讯组件的团队来说这种“可控性”带来的价值可能比节省那几行代码要多得多。2. 协议骨架设计JSON-RPC 2.0消息模型与生命周期状态机的落地细节2.1 先把消息模型用C的类型表达出来MCP的底层消息格式是JSON-RPC 2.0。刚开始写C代码时我发现最麻烦的反而不是JSON解析而是怎么在这门强类型语言里优雅地表达“消息id要么是数字、要么是字符串”这种松散约束。直接用int64_t接收字符串类型的id就会直接解析失败用std::string统一接收返回响应时又要重新序列化。我最后的选择是定义一个JsonRpcMessage结构体用std::variantint64_t, std::string来保存id并在解析阶段做一层归一化。这样做的好处是后续所有协议处理方法都可以用同一套访客模式去处理id而不需要在每处都写分支判断。下面是这个结构体的核心接口struct JsonRpcMessage { enum class Kind { Request, Response, Notification, ErrorResponse }; Kind kind; std::variantint64_t, std::string id; std::string method; nlohmann::json params; nlohmann::json result; int error_code 0; std::string error_message; [[nodiscard]] std::string to_json() const; static std::optionalJsonRpcMessage from_json(const nlohmann::json raw); };解析函数里的逻辑不复杂但对细节要求很高——判断有没有id字段、有没有method字段、有没有error字段三者组合决定了消息类型。这里比较容易踩坑的是MCP协议里“通知notification”是没有id的如果你错误地把所有没有method的响应都当成通知解析后面做异步请求关联时一定会乱套。2.2 initialize握手版本协商和capabilities声明协议的生命周期管理是整个实现的重头戏。MCP规定双方连接建立后第一步必须发initialize请求这个请求里带着客户端支持的协议版本号、客户端名称和自己声明的能力集合。服务端收到后要校验自己的版本和客户端是否兼容然后返回服务端支持的版本号、服务端能力集合和服务端自身信息。这里有一个容易被忽略的机制服务端并不是一定要返回和客户端一样的版本号。如果服务端只支持更新版本它会返回自己这边的最新版本而客户端需要判断这个版本能否接受不行的话就要主动断开连接。因此在我的C实现里版本协商不是简单的字符串比较而是维护了一套“支持区间”的逻辑。void McpServer::handle_initialize(const JsonRpcMessage req) { const auto client_version req.params.at(protocolVersion).getstd::string(); const auto client_caps req.params.at(capabilities); if (!is_version_supported(client_version)) { // 服务端返回自己支持的最新版本由客户端决定是否继续 } else { JsonRpcMessage resp; resp.kind JsonRpcMessage::Kind::Response; resp.id req.id; resp.result { {protocolVersion, kCurrentProtocolVersion}, {capabilities, { {tools, {{listChanged, true}}}, {resources, {{subscribe, false}, {listChanged, true}}}, {prompts, {{listChanged, false}}} }}, {serverInfo, {{name, mcp-cpp-core}, {version, 0.1.0}}} }; write_message(resp); } }除了版本协商这个阶段还会把instructions字段带出来。这个字段可以用来告诉客户端一些使用偏好比如“灰度环境禁用什么类型工具”。我们在实际项目里就是用这个字段下发功能开关的比单独拉一个配置中心要轻量得多。2.3 状态机设计协议状态与非法调用拦截初始化握手之后真正难写的是状态机。MCP的连接生命周期大致分为四个状态未初始化、初始化中、已就绪、已关闭。所有业务方法比如tools/list都必须在“已就绪”状态下才能被调用。我在最初实现时直接把状态做成一个枚举然后在消息分发入口统一做拦截避免每个方法都自己检查状态。状态触发条件允许的消息NotInitialized新连接建立initialize请求Initializing收到initialize请求处理完成前无Readyinitialize响应已返回initialized通知、所有业务方法Shutdown收到关闭通知或传输层断开无拦截逻辑我建议放在消息分发的最外层而不是每个handler里。这样代码可以很清晰地分成两层外层只管“这个状态能不能收这个消息”内层只管“这个业务该干点什么”。后来联调时发现很多客户端会自动发一个notifications/initialized通知有些则不会。协议说这个通知是可选的但如果你在状态机里强制要求“没收到notification就不能处理业务请求”某些早期客户端会直接把连接卡死。我的处理是收到initialize响应后就把状态置为Readynotifications/initialized只当一次空通知处理不再影响状态转移。3. 传输层实现stdio模式、流式HTTP模式与进程内通道的取舍3.1 stdio模式最容易踩坑但也是本地部署最稳的选择MCP最常见的本地传输模式是stdio——Server作为一个子进程被Host拉起父子进程通过标准输入输出交换JSON-RPC消息。这种方式的好处是免去了端口管理、权限校验和防火墙配置只要进程还在连接就是活的。但是stdio模式有一个绝对需要注意的大坑标准输出是不能乱写的。协议规定的消息边界是换行符也就是每条JSON消息独占一行。所有业务日志、调试信息一旦打印到stdout就会混进协议帧里轻则让客户端解析器报错重则直接导致消息错乱。我们项目里所有日志输出都统一接到了stderr或者干脆写进文件。void StdioTransport::run() { std::string line; while (std::getline(std::cin, line)) { if (line.empty()) continue; auto msg JsonRpcMessage::from_json(nlohmann::json::parse(line)); if (!msg) continue; on_message(*msg); } } void StdioTransport::send(const JsonRpcMessage msg) { std::cout msg.to_json() std::endl; }你可能会想这样每行一个JSON消息大了会不会有问题实际用下来工具调用的请求和响应普遍在几KB到几十KB之间单行完全够用。如果未来要传base64图片之类的超大数据我建议直接换HTTP模式走流式传输而不是硬撑stdio的每行上限。3.2 Streamable HTTP模式跨进程、跨机器的传输方式当Server和Host不在同一台机器上时stdio模式就失效了这时候要用Streamable HTTP。这个模式其实包含两条通道客户端通过POST /messages发送JSON-RPC请求服务端通过GET /sse建立一条SSE事件流用于把响应和服务器主动推送的通知推给客户端。C实现这套传输我直接用了Boost.Beast搭HTTP服务端。核心点在于服务端处理POST /messages时先把请求放到一个pending队列里处理完之后根据请求头里的Accept字段决定响应方式——如果是application/json就直接返回结果如果是text/event-stream就把结果通过SSE通道推出去。这个模式里有一个我自己栽过跟头的点SSE通道是单向的客户端用来收消息但服务端如果同时收到多个并发请求SSE推给客户端的顺序和请求到达的顺序会不一致。客户端必须是靠消息里的id来关联响应而不是靠“先来后到”。所以HTTP模式下JSON-RPC的id字段就是你匹配请求响应的唯一凭证我在实现里把这个约定写进了开发规范。3.3 进程内通道把Server直接编译进主进程的备选方案有些小工具模块其实没必要单独拉起进程MCP也不要求Server必须是一个独立进程。我在项目里做了一个轻量的进程内传输实现底层就是函数调用不经过任何IPC。这样做的好处是调用开销几乎为零适合那种本身就对性能要求极高、且不需要隔离的小工具集。但要注意进程内集成会让状态机和异常隔离失效——Server崩溃的话主进程也跟着遭殃。所以我在传输抽象层做了明确区分可嵌入通道只用于可信的低风险工具常规外部工具全部走stdio子进程模式。传输层接口我定义为class McpTransport { public: virtual void send(const JsonRpcMessage msg) 0; virtual void set_message_handler(std::functionvoid(const JsonRpcMessage)) 0; virtual void close() 0; };上层业务代码完全依赖这个抽象接口下面接stdio也好、接HTTP也好、接进程内回调也好对业务来说没有感知。这一步抽象可以说是整份代码里收益最高的设计后续加Apache模块、加ZeroMQ通道都只是实现细节。4. 工具注册与调用链从JSON Schema描述到函数分发的完整实现4.1 tools/list给Client一份机器可读的能力清单在MCP协议里一个Server到底能提供哪些能力是通过tools/list方法对外呈现的。每个工具由三件套组成名称、描述、入参的JSON Schema。这套描述就像饭店的菜单客户端通过它来决定“点什么菜”。所以描述文本要尽量写清楚使用场景因为大模型会直接拿它做调用决策。struct ToolDefinition { std::string name; std::string description; nlohmann::json input_schema; }; class ToolRegistry { public: void add(const ToolDefinition def, std::functionnlohmann::json(const nlohmann::json) handler); std::vectorToolDefinition list() const; std::optionalnlohmann::json call(const std::string name, const nlohmann::json params); private: std::unordered_mapstd::string, Entry entries_; };JSON Schema的严谨度直接影响模型能不能正确调用。我的经验是入参描述里每个字段都要写description枚举值要尽可能列全必填项要用required数组声明清楚。如果某个字段是可选的别忘记给default否则模型经常会在可选参数上猜值一猜就容易出错。4.2 tools/call参数校验、动态分发与结果封装当客户端准备好了要执行某个工具它就会发tools/call请求参数里带上工具名和实际入参。服务端的处理链路分成四步查注册表、校验参数、执行handler、封装返回。查注册表的时候我加了一层防护如果请求的工具名不存在返回的JSON-RPC错误码是-32602无效参数还是方法错误-32601其实都有争议。我最终选择了在result里返回isError: true的调用结果而不是直接抛JSON-RPC错误。这样客户端能明确知道“工具存在但调用失败”而不是“协议层不认识这个请求”。参数校验我直接用JSON Schema的库来做但要注意MCP里的inputSchema是个嵌入的参数对象不能拿整个请求去校验需要先把params里的arguments字段抽出来再验证。返回结果要求是一个JSON对象通常结构是content数组每个元素带type字段text、image、resource。纯文本工具就返回type: text需要多模态输出时就放多个元素。4.3 一个可手写的最小工具注册器如果你不想引入太重的依赖这里给你一个可以跑起来的最小工具注册器实现。核心就两个函数注册和执行。void register_echo(ToolRegistry registry) { registry.add( { echo, 回显用户输入的文本通常用于连通性测试。, { {type, object}, {properties, {{text, {{type, string}, {description, 要回显的文本}}}}}, {required, {text}} } }, [](const nlohmann::json params) - nlohmann::json { return {{content, {{{type, text}, {text, params.at(text)}}}}}; } ); }这种设计看着简单但扩展性极佳。你在handler外头套一层超时控制就能直接给所有工具统一加超时限制再套一层权限检查就能实现调用白名单。工具函数本身保持极简只做业务逻辑协议相关的繁琐细节全部收敛到调度框架里。5. 联调中的真实排错记录三个坑把我折磨到半夜5.1 坑一日志污染stdout客户端一直报解析错误我们第一个MCP Server写好后拿标准客户端做联调。客户端启动后立刻报了一堆Failed to parse JSON我一度以为是消息格式没拼对愣是查了大半天。后来偶然把Server的日志输出关掉奇迹般正常了——问题就出在某个第三方库内部调用了std::cout打印调试信息两条JSON消息里混进了一行普通文本。解决的办法有三个层面第一程序入口处把std::cout的缓冲重定向到文件第二所有日志框架强制绑到stderr不允许任何自定义输出走stdout第三在传输层的send函数里加一个格式断言发送前检查输出串能否被正常解析失败就直接退出进程。经历过这次事故之后我接的每一个新传输通道第一件事就是确认“日志系统不会污染协议通道”。5.2 坑二protocolVersion不一致一握手就被断开另一个发生频率极高的问题是版本号不匹配。某天客户端跑起来Server端收到了initialize请求返回了响应结果客户端直接报了“unsupported protocol version”就断开了。查了日志才发现客户端用的协议版本比较新服务端代码里版本区间判断写得太窄对这版没有放行。这里要特别强调MCP版本协商的设计意图服务端返回的是“我支持的最接近版本”由客户端决定“这个版本我认不认”。所以服务端的判断逻辑不能写成“不是这个版本就报错”而是要返回一个合理的候选版本。我最后实现版本兼容的时候是拿一个受支持版本列表按优先级降序匹配客户端发来的版本在高优先级列表里则直接返回它否则返回列表里的最新版。5.3 坑三并发调用时响应串号工具A的返回被当成了工具B的项目后期我开了多线程处理工具调用为了让耗时长的工具不阻塞其他请求。结果客户端开始出现诡异现象明明只调用了两个工具收到的返回内容却对不上号。排查下来发现两个工具的处理线程几乎同时完成响应写回时都写的同一个变量后写的覆盖了先写的导致两个响应的内容一样。问题本质上是我没有严格按照“一次请求一个id响应必须带同一个id”的协议约束。解决方式不复杂给每个请求构造独立的上下文字段id和结果绑定保存响应发送前再校验id和非请求时的关联。同时在传输层的发送函数加一把互斥锁确保多条响应不会交错写入。MCP协议虽然没有明确要求传输层必须串行但实践中绝对不要依赖操作系统的写原子性。踩坑场景现象根因修复方案日志污染stdout客户端解析JSON失败第三方库把日志写进了stdout日志强制走stderr输出前校验版本号不匹配握手后立即断开服务端版本支持区间过窄返回候选版本交由客户端决策响应串号工具返回内容对不上多线程响应未绑定请求id上下文绑定id发送加锁6. 扩展与收尾在现有协议引擎上继续长出来的能力6.1 后续可扩展的协议能力资源订阅、采样回调与提示词模板协议引擎稳定之后我们开始往里面加扩展能力。第一个是resources/list与resources/read用来暴露结构化数据资源比如数据库里的配置表、文档片段让智能体可以直接读取而不是通过工具调用来间接拉取。和工具相比资源更偏“数据面”适合蓝图配置类场景。第二个是logging/setLevel与通知消息。这套机制让客户端可以动态调整服务端的日志级别然后服务端通过notifications/message把日志推给客户端。联调阶段非常有帮助再也不用让运维跑到机器上翻日志文件了。第三个是采样回调sampling。这个能力方向相反——由Server反向请求Client调用大模型适用于服务端需要智能路由或者动态决策的场景。实现上和普通方法不同先从协议引擎里单独提一个接口走异步回调避免协议帧阻塞。6.2 从“能跑通”到“能上线”我建议你提前做对位测试最后分享一个让项目少返工的建议从一开始就准备一个“标准客户端”的测试环境。协议这种东西自己写自己测容易形成“回音壁效应”两边都按同一个误解实现照样能跑通但一和官方工具链对接立刻露馅。我们项目里专门写了一套一致性测试用例把所有方法按协议文档逐条验证。不用追求100%覆盖但至少每个方法要有一正一反两个用例正常路径一次非法参数一次。有了这套用例往后每次改动协议引擎都会自动跑一遍避免改一行代码把老功能改坏的尴尬。代码写到最后我的真实体会是MCP协议本身的难点不在于框架有多复杂而在“约束”本身——约束消息格式、约束状态流转、约束传输边界。把这三条边界守住C实现协议就是一件踏实的事。如果你也在做类似的通讯基础件建议先把状态机和传输抽象这两块吃透再谈功能扩展。这两块是地基地基稳了上面加多少工具都不怕。

相关新闻

TypeScript工程化脚手架:Zod+tRPC+模块联邦三重校验

TypeScript工程化脚手架:Zod+tRPC+模块联邦三重校验

简介:这是一份基于TypeScript构建的React前端项目实战资源,面向中初级前端开发者,适用于学习现代Web应用开发流程、工程化配置与CI/CD基础实践。项目已预置完整脚手架,支持热更新开发(npm start)、交互式测…

2026/10/17 22:09:10 阅读更多 →
智慧医院大数据平台建设方案:从顶层设计到落地避坑

智慧医院大数据平台建设方案:从顶层设计到落地避坑

简介:这份PPT资料面向医院信息化管理者、医疗大数据从业者及智慧医院项目规划人员,系统梳理了智慧医院大数据综合分析应用从建设到运营的整体解决方案。内容围绕医院管理面临的医药分家、资产闲置、效率低下、数据孤岛等现实难题展开,涵盖大数…

2026/10/17 22:09:10 阅读更多 →
过孔设计实用指南:信号完整性、载流能力与散热优化全解析

过孔设计实用指南:信号完整性、载流能力与散热优化全解析

过孔是 PCB 设计里最容易被“默认存在”的元素。很多工程师的印象里,过孔无非是“打个洞、连通两层铜箔”,放上去能用就行。在低速、低密度的板卡上,这种理解确实够用。但当信号速率跑到 USB 3.x、PCIe、DDR3/DDR4,或者板子上有大…

2026/10/17 22:08:10 阅读更多 →

最新新闻

Agent安全审计实战:security-audit-skill技能包设计与findings.json解析

Agent安全审计实战:security-audit-skill技能包设计与findings.json解析

1. 从零拆解 security-audit-skill:一个让 Agent 真正会做安全审计的技能包第一次看到security-audit-skill这个标题,我脑子里蹦出来的不是“又一个安全扫描脚本”,而是一个更具体的问题:怎么让一个通用 Agent 在拿到一份代码仓库…

2026/10/17 23:02:58 阅读更多 →
学习率warm up与cosine decay原理及工程实践

学习率warm up与cosine decay原理及工程实践

1. 这不是调参玄学,而是模型收敛的底层节拍器“学习率设置-warm up与cosine learning rate”——光看标题,你可能觉得这是又一个深度学习调参黑箱里的术语组合。但实际在某实验室做图像分类模型优化时,我亲眼见过一组参数把ResNet-50在ImageN…

2026/10/17 23:02:58 阅读更多 →
AI日报 - 2026年03月13日:用 TaoToken 统一 Key 跑通多工具模型调用

AI日报 - 2026年03月13日:用 TaoToken 统一 Key 跑通多工具模型调用

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

2026/10/17 23:01:56 阅读更多 →
ETL设计核心:清洗与转换的业务可信重构方法论

ETL设计核心:清洗与转换的业务可信重构方法论

简介:本资源是一份面向数据工程师、BI开发人员及ETL初学者的系统性实践指南,聚焦BI项目核心环节——ETL全流程设计与落地难点。内容深度解析数据抽取(含多源适配策略:同构/异构数据库链接、文件导入与增量更新)、数据清…

2026/10/17 23:01:56 阅读更多 →
STM32F407与AD9854扫频信号源:HAL库FSMC驱动实践

STM32F407与AD9854扫频信号源:HAL库FSMC驱动实践

简介:面向2023年电赛训练的STM32F407HAL库工程,实现AD9854 DDS模块的正弦波输出与扫频,适合电赛备赛、嵌入式竞赛学习,也适用于对信号源频率平坦度有要求的开发场景。与之前利用DAC/DMA或FPGA ROM生成正弦波不同,该工程…

2026/10/17 23:01:56 阅读更多 →
从div到h1:HTML标签语义化与常用标签详解

从div到h1:HTML标签语义化与常用标签详解

前阵子带一位刚入行的实习生&#xff0c;让他把设计稿切成静态页面。他交上来的代码打开一看&#xff0c;满屏都是<div>&#xff0c;连标题都用<div class"title">加CSS调字号。我问他为什么不直接写<h1>&#xff0c;他犹豫了一下说&#xff1a;“…

2026/10/17 23:01:56 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介&#xff1a;《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南&#xff0c;重点围绕V3与R1两款模型的能力差异与适用场景展开&#xff0c;帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件&#xff0c;压缩包大小约311KB&#xff0c;篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介&#xff1a;这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档&#xff0c;共收录两百余条可直接套用的润色指令&#xff0c;涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度&#xff0c;并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介&#xff1a;本资源是一份基于OpenCV的本科课程设计完整报告&#xff0c;面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生&#xff0c;解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介&#xff1a;基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码&#xff0c;面向计算机相关专业课程设计与期末大作业学生&#xff0c;以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程&#xff0c;…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程&#xff1a;键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化&#xff0c;十个新手有八个栽在"往输入框里填东西"这件事上&#xff1a;要么填不进去&#xff0c;要么填了一半&#xff0c;要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程&#xff1a;阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀&#xff1a;什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面&#xff0c;跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/16 14:23:36 阅读更多 →