AI编码代理的机密安全上下文边界:本地过滤与零信任实践
1. 为什么AI编码代理的上下文边界是个要命的问题先抛一个我亲身踩过的坑。去年我给自己搭了一套本地AI编码助手用来处理一些内部项目的代码补全和重构建议。刚开始跑得挺爽直到有一次我让它帮我改一个配置文件它顺手把旁边一个包含数据库连接串的文件内容也读进去当上下文了。虽然那次只是本地日志没造成实际泄露但那一瞬间我后背是发凉的——AI编码代理的上下文边界本质上就是它的“视野范围”而这个范围如果不受控它看到的东西可能远超你的预期。这就是“AI编码代理需要一个机密安全的上下文边界”这个命题的核心。说白了AI编码代理在帮你写代码、改bug、做重构的时候它需要读取项目文件、理解代码结构、参考历史对话甚至调用外部工具。这些操作都会把信息喂进模型的上下文窗口。问题在于哪些信息可以进上下文哪些绝对不能进由谁来决定怎么强制执行。如果没有一个明确的、可验证的边界机制你的API密钥、内部业务逻辑、客户数据、未公开的算法实现都可能在不经意间被塞进模型的上下文里然后被发送到某个你无法控制的推理端点上。这个内容适合谁看三类人一是正在或计划把AI编码代理引入团队工作流的开发者二是对代码安全、数据隐私有硬性要求的项目负责人三是自己折腾本地AI编码工具、想搞清楚“怎么让AI帮忙又不让它乱看”的独立开发者。我不打算讲空泛的安全理念而是从实际搭建和使用的角度把上下文边界的构建拆成可操作的步骤和判断逻辑。2. 上下文边界到底在防什么威胁模型拆解2.1 三种典型的上下文泄露路径在动手做边界之前得先搞清楚敌人从哪来。根据我自己的实践和跟同行交流的经验AI编码代理的上下文泄露主要有三条路径。第一条是隐式文件读取。你让代理“帮我优化一下这个函数的性能”它为了理解函数可能会自动读取同目录下的其他文件包括配置文件、环境变量文件、测试数据。很多代理框架默认会把当前工作目录下的相关文件都纳入检索范围这个“相关”的判定逻辑往往很粗糙就是简单的文件名匹配或目录遍历。第二条是对话历史累积。多轮对话中你之前粘贴过的代码片段、报错日志、甚至聊天记录里提到的内部系统地址都会留在上下文窗口里。随着对话轮次增加这些历史信息会持续占用上下文并且在后续的每一次推理请求中都被重新发送。你以为只问了一个小问题实际上整个对话历史都在被传输。第三条是工具调用返回。AI编码代理通常会挂载一些工具比如执行shell命令、查询数据库、调用内部API。这些工具的返回结果会直接进入上下文。如果工具没有做输出过滤一条env命令的返回就可能把一堆敏感环境变量暴露出来。2.2 零信任思路在上下文管理中的落地“零信任”这个词在安全圈已经不新鲜了但把它用到AI编码代理的上下文管理上思路是一样的不默认信任任何文件、任何工具输出、任何历史消息所有进入上下文的内容都必须经过显式检查和过滤。具体来说零信任在上下文边界上的体现是三个原则。第一默认拒绝代理启动时上下文是空的没有任何文件被预加载。第二最小权限每次任务只授予完成该任务所必需的文件读取权限任务结束权限回收。第三持续验证即使某个文件被允许读取在内容进入上下文之前还要做一次敏感信息扫描。我见过不少团队的做法是“先让代理跑起来安全问题后面再说”结果后面要补的窟窿比一开始就设计边界要大得多。上下文边界这个东西越早做越省事。2.3 本地过滤为什么是关键一环热搜词里有个“本地过滤”这个词很准。上下文边界的第一道防线必须在本地的、离数据最近的地方。原因很简单如果过滤逻辑放在远端服务上那数据在到达远端之前就已经离开了你的控制范围过滤与否已经不重要了泄露已经发生。本地过滤的核心任务是在文件内容、工具输出、历史消息被组装进模型请求之前在本地完成扫描和脱敏。这包括正则匹配常见的密钥格式、识别高熵字符串、检查文件路径是否在允许列表内、对工具输出做结构化截断。这些操作全部在本地进程内完成不依赖任何外部服务。3. 搭建上下文边界的具体方案与核心组件3.1 文件访问控制层白名单加路径规范化文件访问控制是上下文边界的第一道闸门。我的做法是维护一个显式的文件白名单而不是黑名单。黑名单的问题在于你永远不知道下一个敏感文件叫什么名字而白名单的逻辑是“只有我明确说可以读的才能读”。白名单的粒度可以到文件级也可以到目录级。对于AI编码代理来说我建议至少做到目录级白名单再配合文件扩展名过滤。比如只允许读取src/目录下的.py和.md文件禁止读取.env、.pem、.key、credentials等敏感文件。路径规范化是容易被忽略的一步。代理在解析文件路径时必须先把路径转成绝对路径再做规范化处理消除../这样的相对路径跳转。否则一个../../etc/passwd这样的路径就可能绕过白名单。在Python里可以用os.path.realpath()配合os.path.commonpath()来判断目标路径是否在白名单目录之下。import os ALLOWED_DIRS [os.path.realpath(/project/src), os.path.realpath(/project/docs)] SENSITIVE_EXTENSIONS {.env, .pem, .key, .p12, .pfx} def is_path_allowed(filepath): real os.path.realpath(filepath) if any(real.endswith(ext) for ext in SENSITIVE_EXTENSIONS): return False for allowed in ALLOWED_DIRS: if os.path.commonpath([real, allowed]) allowed: return True return False这段代码的逻辑是先检查扩展名黑名单再检查路径是否在白名单目录内。注意commonpath的使用它能正确处理路径前缀匹配的问题避免/project/src_backup被误判为在/project/src之下。3.2 内容扫描与脱敏正则加熵值双保险文件被允许读取之后内容还不能直接进上下文得再过一道内容扫描。这一步的目标是识别并处理敏感信息比如API密钥、数据库密码、私钥片段、内部IP地址等。我的做法是两层扫描。第一层是正则匹配针对已知的敏感信息格式。比如常见的API密钥前缀、JWT格式的字符串、PEM私钥的头部标记。第二层是熵值检测针对那些没有固定格式但看起来像随机字符串的内容。高熵字符串往往是密钥或令牌即使它不符合任何已知的正则模式。import re import math from collections import Counter PATTERNS [ (rsk-[A-Za-z0-9]{20,}, [REDACTED_API_KEY]), (r-----BEGIN [A-Z ] PRIVATE KEY-----, [REDACTED_PRIVATE_KEY]), (r(?i)(password|passwd|pwd)\s*[:]\s*\S, [REDACTED_CREDENTIAL]), ] def shannon_entropy(s): if not s: return 0 counts Counter(s) length len(s) return -sum((c/length) * math.log2(c/length) for c in counts.values()) def scan_and_redact(text): for pattern, replacement in PATTERNS: text re.sub(pattern, replacement, text) # 高熵字符串检测 tokens re.findall(r[A-Za-z0-9/_-]{32,}, text) for token in tokens: if shannon_entropy(token) 4.5: text text.replace(token, [REDACTED_HIGH_ENTROPY]) return text熵值阈值4.5是我在实际使用中调整出来的经验值。太低会误伤正常的哈希值或base64编码的图片数据太高会漏掉一些短密钥。你可以根据自己的项目特点微调但建议不要低于4.0。注意脱敏后的内容会改变原始代码的语义如果代理需要基于脱敏后的内容做代码修改修改结果可能不可用。所以脱敏策略要区分场景只读分析场景可以激进脱敏代码修改场景需要更精细的处理比如只替换值而保留变量名。3.3 对话历史管理滑动窗口加敏感信息回溯清理对话历史是上下文边界里最容易被忽视的部分。很多人只关注文件读取的控制却忘了之前对话里可能已经混入了敏感信息。我的做法是给对话历史设置一个滑动窗口只保留最近N轮对话。N的取值取决于任务的复杂度一般编码任务5到10轮足够。超出窗口的历史消息直接丢弃不参与后续的上下文组装。但光有滑动窗口还不够因为敏感信息可能在窗口内。所以还需要一个回溯清理机制每次组装上下文之前对窗口内的所有历史消息做一次内容扫描把之前可能漏掉的敏感信息替换掉。这个扫描逻辑和文件内容扫描共用同一套规则。另外对于工具调用的返回结果我建议不要原样存入对话历史而是存一个摘要版本。比如执行了一个测试命令返回了200行日志存进历史的应该是“测试通过耗时3.2秒”这样的摘要而不是完整的日志文本。这样既保留了任务状态又减少了敏感信息暴露面。3.4 工具调用的输出过滤与权限隔离AI编码代理挂载的工具是上下文泄露的高风险入口。一个执行shell命令的工具如果不做输出过滤cat /etc/hosts、env、ps aux这些命令的返回都可能包含敏感信息。我的处理方式是在工具层面做三层控制。第一层是命令白名单只允许执行预定义的安全命令比如pytest、python -m black、git diff。第二层是输出长度截断任何工具返回超过一定字符数比如2000字符就截断只保留头部和尾部。第三层是输出内容扫描和文件内容扫描用同一套脱敏规则。权限隔离方面工具执行应该在一个受限的环境中运行比如独立的容器或沙箱限制文件系统访问范围和网络访问。这样即使工具被诱导执行了危险操作影响范围也可控。4. 实操落地从零搭建一个带上下文边界的编码代理4.1 整体架构与数据流我搭建的这套方案整体数据流是这样的用户输入任务 - 任务解析器确定需要读取的文件列表 - 文件访问控制层校验路径 - 读取文件内容 - 内容扫描脱敏 - 组装上下文系统提示 脱敏后的文件内容 滑动窗口内的历史消息 工具定义- 发送给模型 - 模型返回工具调用请求 - 工具执行层校验命令 - 执行并过滤输出 - 输出扫描脱敏 - 结果进入下一轮上下文。这个流程里文件访问控制层和内容扫描层是必须在本地的工具执行层也建议本地化或至少在内网环境中。模型推理端点可以根据实际情况选择但发送过去的内容已经经过了本地过滤。4.2 关键参数配置与调优记录在实际搭建过程中有几个参数我反复调整过这里把调优记录分享出来。滑动窗口大小初始设为20轮发现上下文经常超长而且很多早期对话已经无关了。后来降到8轮配合任务摘要机制效果更好。对于长任务我会在每5轮后生成一个任务状态摘要替代之前的详细对话。熵值阈值从5.0降到4.5再降到4.2。4.2的时候开始出现误报一些正常的base64编码字符串被误判。最终定在4.5配合一个白名单机制把已知的安全高熵字符串比如项目里固定的测试哈希排除掉。输出截断长度工具输出截断从5000字符降到2000字符。2000字符大约能覆盖大部分测试输出的关键部分再长的输出通常包含大量重复信息截断后对任务完成度影响不大。文件大小限制单个文件超过100KB就不直接读入上下文而是先做摘要或只读取相关函数片段。这个限制是为了防止一个大文件把上下文窗口占满导致其他重要信息被挤出去。4.3 一个完整的请求处理示例假设用户输入“帮我看看src/utils/parser.py里的parse_config函数有没有bug。”处理流程如下。首先任务解析器识别出目标文件是src/utils/parser.py目标函数是parse_config。文件访问控制层检查该路径是否在白名单内假设src/在白名单中扩展名.py也允许通过。然后读取文件内容但只提取parse_config函数及其直接依赖的导入语句而不是整个文件。提取出的代码片段经过内容扫描没有发现敏感信息。接着组装上下文系统提示说明任务、代码片段、最近8轮对话历史经过回溯清理、可用工具列表。模型返回一个分析结果指出函数中有一个边界条件未处理。整个过程中没有读取任何其他文件没有执行任何工具上下文边界完整。如果模型要求执行测试来验证工具执行层会校验命令是否在白名单内执行后对输出做截断和扫描再返回给模型。4.4 本地过滤的性能考量本地过滤会增加每次请求的处理时间。在我的测试环境里一个中等规模的项目约200个文件文件访问控制加内容扫描的额外耗时在50到150毫秒之间取决于文件大小和扫描规则的复杂度。这个开销对于交互式编码辅助来说是可以接受的因为模型推理本身通常需要几秒。如果觉得扫描太慢可以做两级缓存对已经扫描过的文件内容做缓存文件未修改时直接复用扫描结果。缓存键可以用文件路径加修改时间。这样在同一个会话中反复读取同一文件时扫描只发生一次。5. 常见问题与排查技巧实录5.1 代理“看不到”需要的文件怎么办这是最常见的抱怨。你明明把文件放在项目里了代理却说找不到。排查顺序是这样的先确认文件路径是否在白名单目录内再看扩展名是否被敏感扩展名规则误伤然后检查文件大小是否超过了限制。如果都正常看看任务解析器是否正确识别了文件路径有时候用户输入的文件名和实际路径有出入解析器匹配失败。我的经验是给代理加一个“请求访问”的机制当代理判断需要读取一个不在白名单内的文件时它不直接读取而是生成一个访问请求由用户确认后再临时加入白名单。这样既保证了安全又不会因为白名单太严导致代理没法工作。5.2 脱敏过度导致代码无法使用内容扫描太激进的时候会把正常的变量名、字符串常量也替换掉导致代理看到的代码是残缺的。解决办法是区分“值脱敏”和“结构保留”。对于代码文件只替换那些明确匹配敏感模式的内容高熵检测的阈值调高一些并且对代码中的字符串字面量做白名单处理——如果一个高熵字符串出现在赋值语句的右侧且变量名包含test、mock、example等关键词就跳过脱敏。另一个技巧是保留脱敏前的映射关系在本地维护一个替换表。当代理基于脱敏后的代码生成修改建议时在应用修改之前把替换表反向映射回去。这样代理看到的是脱敏内容但最终修改的是原始代码。5.3 工具输出被截断后丢失关键错误信息工具输出截断到2000字符有时候错误信息恰好在被截断的部分。我的处理方式是智能截断优先保留包含Error、Exception、FAILED、Traceback等关键词的行以及这些行前后的若干行上下文。对于测试输出保留最后的汇总行和第一个失败用例的详细信息。这样即使总长度受限关键信息也不会丢。5.4 对话历史中的敏感信息清理不彻底回溯清理只能处理文本形式的敏感信息如果敏感信息被编码或变形了正则和熵值检测可能漏掉。一个补充措施是限制对话历史中允许出现的消息类型用户消息只保留文本不保留粘贴的代码块中的完整内容只保留代码块的语言标识和行数摘要助手消息只保留最终回复不保留中间的推理过程。这样从源头上减少了敏感信息进入历史的可能性。5.5 常见问题速查表问题现象可能原因排查步骤解决方式代理找不到文件路径不在白名单检查白名单配置和文件实际路径添加目录到白名单或使用请求访问机制代码被过度脱敏熵值阈值过低查看脱敏日志确认被替换的内容调高熵值阈值添加白名单排除规则工具输出关键信息丢失截断策略太粗暴检查截断后的输出内容改用智能截断优先保留错误行上下文超长滑动窗口太大或文件太大查看上下文token计数缩小窗口对大文件做摘要或片段提取代理行为异常脱敏导致语义变化对比脱敏前后代码调整脱敏策略保留代码结构6. 边界之外的思考安全与效率的平衡点做上下文边界这件事最容易走极端。要么管得太死代理什么都看不到跟没有一样要么放得太开安全形同虚设。我自己的体会是边界的位置应该由数据的敏感程度和任务的必要程度共同决定。对于公开的、开源的代码库边界可以宽松一些主要防的是意外泄露而非恶意攻击。对于内部业务代码边界要收紧文件白名单要精确到具体模块工具调用要严格限制。对于涉及用户数据、支付逻辑、认证授权的代码我建议根本不要让AI编码代理直接读取而是通过接口抽象的方式让代理只看到接口定义和mock实现。另一个体会是上下文边界不是一次配置就完事的。项目在变代码在变敏感信息的形态也在变。我每个月会review一次白名单和扫描规则看看有没有新增的敏感文件类型需要排除有没有新的工具输出格式需要处理。这个维护成本不高但能避免很多事后补救的麻烦。最后分享一个实用技巧在代理的系统提示里明确告诉它边界的存在和规则。比如“你只能读取白名单目录下的文件如果任务需要读取其他文件请生成访问请求而不是直接读取”。模型在知道规则的情况下会更好地配合边界机制减少无效的尝试和报错。这个技巧是我在实际使用中发现的效果比单纯在代码层面做限制要好得多因为模型会主动适应规则而不是反复撞墙。

相关新闻

KBQA数据集选型实战指南:匹配业务场景的5大主流数据集解析

KBQA数据集选型实战指南:匹配业务场景的5大主流数据集解析

/* 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 4:03:12 阅读更多 →
超远距离USB蓝牙Dongle实战:原理、选购与避坑指南

超远距离USB蓝牙Dongle实战:原理、选购与避坑指南

做智能家居这几年,我最大的感受是:无线设备越多,家里越像是个电磁信号迷宫。蓝牙门锁、蓝牙温湿度计、蓝牙人体传感器这一票设备,手机直连的时候经常走到客厅就掉线,信号明明还在,App 却显示“设备离线”。…

2026/10/16 4:03:12 阅读更多 →
PostgreSQL数据库开发中的赋值机制:从SQL到PL/pgSQL的完整指南

PostgreSQL数据库开发中的赋值机制:从SQL到PL/pgSQL的完整指南

1. 从一条UPDATE语句开始理解“赋值”在PG开发里的分量做 PostgreSQL 开发这几年,我越来越觉得“赋值”才是整个数据库应用里最容易被低估的一个动作。很多人觉得赋值不就是“给变量塞个值”吗?SELECT 查出来,写个变量,再插回去&a…

2026/10/16 4:03:12 阅读更多 →

最新新闻

Python控制硬件:Arduino与树莓派实战对比与协同架构

Python控制硬件:Arduino与树莓派实战对比与协同架构

聊到用Python控制硬件,大部分教程会把Arduino和树莓派放在同一个标题下讲,好像这俩就是同一个东西的两种形态。等我把两种方案都跑进真实项目里,才发现开发体验完全不一样:Arduino这条路,核心是和串口协议斗智斗勇&…

2026/10/16 4:48:25 阅读更多 →
eSIM开户安全基石:二要素认证的技术拆解与工程实践

eSIM开户安全基石:二要素认证的技术拆解与工程实践

eSIM这个概念聊了很多年,真正大规模落地也就是近几年的事。我最早接触eSIM开户相关的项目,是在给某运营商做线上开户支撑系统的时候。那时候团队讨论最多的还是Profile怎么下发、兼容性怎么处理,等到线上开户量真正涨起来,大家才猛…

2026/10/16 4:48:25 阅读更多 →
eSIM开户的二要素认证:原理、落地与避坑指南

eSIM开户的二要素认证:原理、落地与避坑指南

eSIM开户已经不是什么新鲜事,但很多人不知道,真正决定开户能不能顺利完成的,不是手机型号,也不是网络条件,而是二要素认证。我在处理线上开户反馈时,经常遇到用户卡在“身份核验”这一步,要么证…

2026/10/16 4:48:25 阅读更多 →
KV Cache 显存优化实战:长上下文推理性能瓶颈与调优策略

KV Cache 显存优化实战:长上下文推理性能瓶颈与调优策略

1. 从一次对话卡顿说起:KV Cache 到底在解决什么问题如果你用过任何基于 Transformer 架构的对话模型,大概率遇到过这样一种体验:刚开始聊的时候,回复速度飞快,字是一个一个往外蹦的;聊到几十轮之后&#x…

2026/10/16 4:48:25 阅读更多 →
JavaScript数组reduce实战:核心原理、业务场景与边界问题

JavaScript数组reduce实战:核心原理、业务场景与边界问题

提起数组的reduce方法,大多数前端开发者的状态是:面试前背过“累加器”“归并”这些概念,真到项目里却很少主动用。我观察过不少团队的代码评审,reduce常常被两派人争论:一派觉得它晦涩难懂,看到就想改成fo…

2026/10/16 4:48:25 阅读更多 →
光储充换电站分时电价双层优化模型及Matlab实现

光储充换电站分时电价双层优化模型及Matlab实现

光储充换电站和分时电价互动这两件事,放在一起研究的论文和代码我见过不少,但真正能把“用户充电负荷”这个变量建模得当、又能在Matlab里跑通寻优的,确实不算多。这个标题对应的方向,简单说就是:站在运营商的视角&…

2026/10/16 4:47:24 阅读更多 →

日新闻

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

/* 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 0:00:05 阅读更多 →
信号与系统频域分析作业解题指南

信号与系统频域分析作业解题指南

1. 作业背景与核心要求解析信号与系统作为电子信息类专业的核心基础课,其作业设计往往直接关联课程的核心知识框架。2026年春季第六次作业的布置,通常对应着课程进展到频域分析的关键阶段。根据常规教学进度推测,本次作业可能涉及以下核心内容…

2026/10/16 0:00:05 阅读更多 →
Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

1. 从一个"四不像"的练手项目说起如果你已经看完了Django的官方教程前几章,跟着敲完了投票应用,大概会有一种"我好像会了,又好像什么都不会"的割裂感。教程里每个知识点都是拆开的——这一章讲模型,下一章讲视…

2026/10/16 0:00:05 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 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/15 0:14:36 阅读更多 →
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/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练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/15 9:49:14 阅读更多 →