LLM之Agent(六十一)|拆解 Coding Agent 的 harness:从零构建你的第一个 AI 编程助手
1. 为什么你的 Coding Agent 总在第三步崩掉harness 层缺失的典型症状很多人第一次写 AI 编程助手代码大概长这样一个 while 循环把用户输入丢给模型模型返回 tool_call 就执行执行完把结果塞回 messages再循环。跑 demo 没问题一旦让它改一个真实仓库里的文件问题就来了——它会在第三步或第四步开始重复读同一个文件、忘记前面已经改过什么、把cd之后的路径当成永久生效、甚至在等你确认的时候把整个上下文烧光。这些症状看起来像模型不够聪明实际上几乎全部出在 harness 层。所谓 harness中文可以理解成挽具或编排脚夫它是包在模型外面那一圈基础设施状态机、上下文管理、权限门、执行隔离、事件流。模型权重和核心 API 行为是固定的你能工程化的部分几乎全在 harness 里。我拆过 Claude Code、OpenCode、Pi 这类主流 coding agent 的实现得出一个反直觉的结论真正让 agent 可用的不是那个 ReAct 循环而是循环外面的东西。一个 bare agent loop 大概 20 行就能写完但一个能跑真实项目的 harness 需要处理 phase machine、steering queue、permission gate、sandbox、context compaction、memory 注入、可观测性这一整套。这篇文章面向想理解 Agent 如何调度工具与上下文的开发者。我会带你把 harness 拆成可复制的配置片段最后用一个端到端请求验证整条链路真的通了。你不需要先读完所有源码跟着配置走一遍黑箱就透明了。先明确边界。Agent 层负责想模型评估状态、选择 action 或 tool call、接收 observation、迭代。Harness 层负责活它驱动 turn 的执行、管理输入队列、拦截危险操作、隔离命令执行、压缩上下文、把事件流分发给界面。Interface 层负责看TUI 或 headless 远程执行。三层分离之后你换模型、换界面、换沙箱harness 逻辑都不用重写。下面这张对照表帮你快速定位自己卡在哪一层症状大概率出问题的层典型原因重复读同一文件Harness / Context没有 compaction历史里全是旧 tool 结果改完文件又改回去Harness / Memory没有把已改事实写回上下文命令执行后路径丢失Harness / Sandboxfresh-exec 模式下 cd 不持久但代码假设它持久危险命令直接执行Harness / Permission没有 permission gate 或 gate 规则写反等待确认时卡死Harness / Queue单队列阻塞没有 steering 与 follow-up 分流长任务中途断掉无法恢复Harness / Runtime没有 durable checkpoint看清这张表你就知道接下来该配什么。2. TaoToken 前置给 harness 一个稳定的模型入口harness 要跑起来第一件事是让模型调用这条链路稳定。我试过把模型入口写死在代码里结果每次换模型都要改源码、重跑测试非常痛苦。正确做法是把 Base URL、Key、Model ID 三件套抽成配置harness 只读配置不关心供应商。TaoToken 在这里的角色是提供统一的模型调用入口。官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 端点是 https://taotoken.net/api 。注意 API 地址不带 UTM 参数配置里写干净的 endpoint 就行。你需要准备三样东西缺一不可Base URLhttps://taotoken.net/api这是所有请求的前缀harness 里的 model client 指向它。API Key在控制台创建形如sk-开头的一串。这个 Key 只放在环境变量或本地配置文件里绝对不要提交到 git。我见过有人把 Key 写进settings.py然后推到公开仓库十分钟内就被扫走了。Model ID具体调用哪个模型。harness 的配置里要显式声明不要依赖默认值否则换环境时行为会漂移。获取 Key 的入口在控制台的 API Keys 页面地址是 https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 。创建之后复制一次页面刷新就看不到了先存到本地.env。如果你只是想先验证模型能不能通不想写代码可以用模型对话页面直接发一条消息地址是 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。这一步能帮你排除是 Key 错了还是 harness 写错了的干扰。对于长期跑编码任务或 Agent 工作流的场景Coding Plan 更合适入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。它的计费方式对高频 tool call 更友好因为 coding agent 一个 turn 可能触发十几次模型请求按次计费会很难受。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里面有各语言的调用示例。我建议你先照着文档跑通一个最小请求再把它塞进 harness。这里有个容易踩的坑harness 里的 model client 通常需要兼容 OpenAI 风格的/chat/completions或 Anthropic 风格的/messages。TaoToken 的 API 端点支持标准协议你在配置里把 base_url 指对剩下的交给 SDK。不要自己手写 HTTP 拼接容易在 header 和 body 格式上出错。环境变量建议这样组织harness 启动时统一读取# .env 本地文件不要提交 TAOTOKEN_BASE_URLhttps://taotoken.net/api TAOTOKEN_API_KEYsk-你的key TAOTOKEN_MODEL_ID你的模型ID然后在代码里用os.environ或pydantic-settings读取。这样你的 harness 代码里不会出现任何硬编码的 Key换环境只改.env。3. 可复制配置把 harness 三件套写进 settings这一节给你可以直接抄的配置片段。harness 的配置分三块模型入口、权限门、沙箱。我按文件路径组织你照着建目录就行。先建项目结构my-agent/ config/ settings.toml permissions.json src/ harness/ runner.py queue.py gate.py agent/ loop.py模型入口配置写在config/settings.toml。TOML 比 JSON 更适合写配置因为支持注释# config/settings.toml [llm] base_url https://taotoken.net/api api_key_env TAOTOKEN_API_KEY # 从环境变量读不写明文 model_id 你的模型ID timeout_s 120 max_retries 3 [harness] # 上下文窗口预算compaction 阈值基于它计算 context_window_tokens 200000 # 保留最近多少 token 不压缩 keep_recent_tokens 40000 # 触发 microcompaction 的预留比例 microcompaction_reserve_fraction 0.15 # 触发完整 compaction 的预留比例 compaction_reserve_fraction 0.20 [sandbox] # none | docker | modal mode docker image python:3.12-slim exec_timeout_s 60权限门配置写在config/permissions.json。规则顺序很重要先走 deny再走 allow最后落到 mode 默认行为{ mode: default, rules: [ { match: { tool: bash, command_regex: rm\\s-rf\\s/ }, decision: deny, reason: 禁止删除根目录 }, { match: { tool: bash, command_regex: git\\spush }, decision: ask, reason: 推送需要人工确认 }, { match: { tool: read }, decision: allow }, { match: { tool: glob }, decision: allow }, { match: { tool: grep }, decision: allow }, { match: { tool: write }, decision: ask }, { match: { tool: edit }, decision: ask } ] }注意mode字段。default模式下只读工具自动放行写文件和 bash 需要确认edit模式下文件编辑自动放行bash 仍然要问bypass模式全部放行只用于 headless 自动化绝不能在有真实凭证的环境里开。harness 读取配置的代码长这样用 pydantic 做校验字段缺失直接报错而不是静默用默认值# src/harness/config.py from pathlib import Path import json import tomllib from pydantic import BaseModel, Field class LLMConfig(BaseModel): base_url: str api_key_env: str model_id: str timeout_s: int 120 max_retries: int 3 class HarnessConfig(BaseModel): context_window_tokens: int 200_000 keep_recent_tokens: int 40_000 microcompaction_reserve_fraction: float 0.15 compaction_reserve_fraction: float 0.20 class SandboxConfig(BaseModel): mode: str none image: str python:3.12-slim exec_timeout_s: int 60 class Settings(BaseModel): llm: LLMConfig harness: HarnessConfig sandbox: SandboxConfig def load_settings(root: Path) - Settings: with open(root / config / settings.toml, rb) as f: raw tomllib.load(f) return Settings(**raw) def load_permissions(root: Path) - dict: with open(root / config / permissions.json, r, encodingutf-8) as f: return json.load(f)如果你用的是 Claude Code 或 Cline 这类现成工具配置位置不一样但三件套逻辑相同。Claude Code 的 settings 里要写ANTHROPIC_BASE_URL、ANTHROPIC_API_KEY、ANTHROPIC_MODELCline 的 MCP 配置里要写baseUrl、apiKey、model。不管哪个工具Base URL、Key、Model ID 三个字段一个都不能少少一个就会在第一次请求时报 401 或 model not found。CC Switch 这类多配置切换工具也遵循同样结构。它的配置文件里每个 profile 就是一组三件套切换 profile 等于换模型入口。如果你同时用多个模型做对比这个结构能省很多事。配置写完先别急着跑 agent。用一段最小代码验证模型入口通不通# scripts/check_llm.py import os from openai import OpenAI from pathlib import Path from src.harness.config import load_settings settings load_settings(Path(.)) client OpenAI( base_urlsettings.llm.base_url, api_keyos.environ[settings.llm.api_key_env], ) resp client.chat.completions.create( modelsettings.llm.model_id, messages[{role: user, content: 只回复两个字通了}], timeoutsettings.llm.timeout_s, ) print(resp.choices[0].message.content)跑python scripts/check_llm.py输出通了就说明模型入口没问题。这一步能帮你把模型问题和 harness 问题彻底分开。4. 端到端验证一次请求看清执行链路配置就绪后跑一次完整的 turn观察事件流。harness 的价值在于把黑箱变成可观测的事件序列。我设计一个最小验证场景让 agent 读一个文件、改一个文件、跑一条命令全程打印事件。先写事件定义。事件是 frozen 且 hashable 的这样 TUI 和远程可观测性可以共用同一个真实来源# src/harness/events.py from dataclasses import dataclass from typing import Union dataclass(frozenTrue) class TurnStarted: turn_id: str dataclass(frozenTrue) class AssistantTextDelta: text: str dataclass(frozenTrue) class ToolCallStarted: tool: str args: dict dataclass(frozenTrue) class ToolResult: tool: str ok: bool preview: str dataclass(frozenTrue) class PermissionRequested: tool: str reason: str dataclass(frozenTrue) class ContextCompacted: before_tokens: int after_tokens: int dataclass(frozenTrue) class TurnFinished: turn_id: str stop_reason: str Event Union[ TurnStarted, AssistantTextDelta, ToolCallStarted, ToolResult, PermissionRequested, ContextCompacted, TurnFinished, ]然后是 runner 的 phase machine。单飞single-flight是关键一个 turn 可能包含多个 legiter → deferred pause → resume → follow-upphase 在第一个 await 之前同步设置保证状态查询不会看到中间态# src/harness/runner.py import enum from dataclasses import dataclass, field class Phase(enum.Enum): IDLE idle DISPATCHING dispatching # 第一个 await 之前的同步窗口 RUNNING running class Boundary(enum.Enum): MODEL_REQUEST model_request # 下一次模型调用前 drain steering WOULD_STOP would_stop # drain follow-up空则回 idle dataclass class Runner: phase: Phase Phase.IDLE _abort_flag: bool False def dispatch(self): # 同步设置避免竞态 self.phase Phase.DISPATCHING self._abort_flag False def mark_running(self): self.phase Phase.RUNNING def request_abort(self): # 协作式 abort设置 flagturn 在下一个 boundary 停止 self._abort_flag True def should_abort(self) - bool: return self._abort_flag双队列交互模型是防止 mid-turn 破坏的核心。用户按 Enter 的消息进 steering 队列在下一个 model-request 边界注入按 AltEnter 的消息进 follow-up 队列只在 WOULD_STOP 边界处理# src/harness/queue.py import asyncio from dataclasses import dataclass, field def _drain(q: asyncio.Queue) - list[str]: out [] while not q.empty(): out.append(q.get_nowait()) return out dataclass class InteractionQueues: steering: asyncio.Queue field(default_factoryasyncio.Queue) follow_up: asyncio.Queue field(default_factoryasyncio.Queue) def drain_steering(self) - list[str]: return _drain(self.steering) def drain_follow_up(self) - list[str]: return _drain(self.follow_up)现在写主循环把事件打出来。这是验证 harness 是否工作的核心# src/harness/main.py import asyncio import os from pathlib import Path from openai import AsyncOpenAI from src.harness.config import load_settings, load_permissions from src.harness.runner import Runner, Phase, Boundary from src.harness.queue import InteractionQueues from src.harness.events import ( TurnStarted, AssistantTextDelta, ToolCallStarted, ToolResult, TurnFinished, ) async def run_turn(prompt: str, settings, queues, runner): client AsyncOpenAI( base_urlsettings.llm.base_url, api_keyos.environ[settings.llm.api_key_env], ) runner.dispatch() yield TurnStarted(turn_idt1) messages [{role: user, content: prompt}] tools [ {type: function, function: { name: read, description: 读文件, parameters: {type: object, properties: { path: {type: string}}, required: [path]}}}, {type: function, function: { name: bash, description: 执行命令, parameters: {type: object, properties: { command: {type: string}}, required: [command]}}}, ] for leg in range(8): # MODEL_REQUEST 边界注入 steering for msg in queues.drain_steering(): messages.append({role: user, content: msg}) runner.mark_running() resp await client.chat.completions.create( modelsettings.llm.model_id, messagesmessages, toolstools, timeoutsettings.llm.timeout_s, ) choice resp.choices[0].message if choice.content: yield AssistantTextDelta(textchoice.content) if not choice.tool_calls: # WOULD_STOP 边界处理 follow-up follow queues.drain_follow_up() if follow: for msg in follow: messages.append({role: user, content: msg}) continue yield TurnFinished(turn_idt1, stop_reasoncompleted) runner.phase Phase.IDLE return messages.append(choice) for call in choice.tool_calls: yield ToolCallStarted(toolcall.function.name, args{}) # 这里接真实工具执行示例用占位 result f[{call.function.name} 执行完成] yield ToolResult(toolcall.function.name, okTrue, previewresult[:80]) messages.append({ role: tool, tool_call_id: call.id, content: result, }) yield TurnFinished(turn_idt1, stop_reasonmax_legs) async def main(): settings load_settings(Path(.)) queues InteractionQueues() runner Runner() async for ev in run_turn(读一下 README.md 然后告诉我项目是做什么的, settings, queues, runner): print(f[{type(ev).__name__}] {ev}) if __name__ __main__: asyncio.run(main())跑起来你会看到类似这样的输出[TurnStarted] TurnStarted(turn_idt1) [ToolCallStarted] ToolCallStarted(toolread, args{}) [ToolResult] ToolResult(toolread, okTrue, preview[read 执行完成]) [AssistantTextDelta] AssistantTextDelta(text这个项目是一个...) [TurnFinished] TurnFinished(turn_idt1, stop_reasoncompleted)这条事件序列就是 harness 的心电图。你能清楚看到turn 开始、工具被调用、结果返回、模型生成文本、turn 结束。如果中间某一步缺失问题就定位到了具体环节。验证成功的标志有三个事件按顺序出现、stop_reason是completed而不是max_legs、工具结果被正确回填到 messages。三个都满足说明你的 harness 主链路通了。5. 本篇常见错排查401、local proxy failed、reading choices、OAuth配置和验证过程中报错几乎都集中在这几类。我按真实报错信息给你对照排查。401 Unauthorized / invalid api key最常见。原因通常是 Key 没读到、Key 写错、或者 base_url 和 Key 不匹配。先确认环境变量真的加载了python -c import os; print(os.environ.get(TAOTOKEN_API_KEY, NOT SET)[:8])如果输出NOT SET说明.env没被加载。Python 不会自动读.env你需要python-dotenv或手动 export。如果输出了前 8 位但请求还是 401检查 base_url 是否写成了带路径的形式比如https://taotoken.net/api/v1有些 SDK 会自己拼/v1重复拼接就会 404 或 401。正确写法是只写到https://taotoken.net/api。local proxy failed / connection refused这个报错说明请求根本没发出去卡在本地网络层。检查三件事base_url 是否拼错、本机是否有残留的代理环境变量、DNS 是否能解析。用 curl 直接测curl -sS -o /dev/null -w %{http_code}\n https://taotoken.net/api返回 200 或 401 都说明网络通返回 000 说明连接失败。如果本机有HTTP_PROXY之类的环境变量先 unset 再试。注意不要在代码里硬编码任何代理地址harness 应该直连配置的 base_url。reading choices of undefined / KeyError: choices这个报错几乎都是响应结构不符合预期。可能原因模型 ID 写错导致返回了错误对象、SDK 版本和 API 协议不匹配、或者请求体格式不对。先打印完整响应resp await client.chat.completions.create(...) print(resp.model_dump_json(indent2))如果返回体里是{error: {...}}而不是{choices: [...]}那就是请求本身被拒了去看 error 字段的具体信息。常见的是 model not found说明 Model ID 和账号可用模型不匹配去控制台确认一下。OAuth / authentication failed / token expired如果你用的是 Claude Code 这类带 OAuth 流程的工具报错可能来自它的登录态而不是你的 API Key。这类工具通常有两套认证一套是工具自身的账号登录一套是模型 API 的 Key。两者不能混。检查工具的配置文件里模型入口是否指向了正确的 base_url 和 Key。Claude Code 的配置在~/.claude/settings.jsonCline 的在 VS Code 设置里Codex 的在~/.codex/auth.json。以 Codex 的auth.json为例三件套要写全{ base_url: https://taotoken.net/api, api_key: sk-你的key, model: 你的模型ID }少任何一个字段工具都会回退到默认认证流程然后报 OAuth 相关错误。Cline 的 MCP 配置同理baseUrl、apiKey、model三个字段缺一不可。CC Switch 切换 profile 时如果某个 profile 只填了两个字段切过去就会认证失败。上下文超限 / context length exceeded这个不是认证问题是 harness 的 compaction 没生效。检查context_window_tokens是否和实际模型窗口一致keep_recent_tokens是否设得太大。如果keep_recent_tokens接近context_window_tokenscompaction 永远触发不了因为保留区就占满了。经验值是保留区占窗口的 20% 到 30%触发阈值设在 80% 左右给模型响应和后续 tool output 留 headroom。工具执行卡死 / 等待确认无响应这是队列设计问题。如果你只有一个队列等待用户确认时会阻塞整个循环。正确做法是 permission gate 返回 ASK 时tool 抛出 ApprovalRequired循环暂停并返回 deferred 状态通过独立的 decision channel 等待用户输入。用户输入 y/n/a 后 resolve future循环恢复。这样等待期间不占用计算资源也不会死锁。排查完这几类你的 harness 基本就稳了。每次遇到新报错先看它属于哪一层认证层、网络层、协议层、还是 harness 逻辑层。分层之后排查范围立刻缩小。6. 把 harness 用起来从验证到长期编码主链路通了之后你可以按需扩展。harness 的每个组件都是可插拔的不用一次全上。先加 memory 注入。在项目根目录放AGENTS.mdharness 启动时读取并注入到 system prompt。这样 agent 每次都知道项目约定不用你重复交代# src/harness/memory.py from pathlib import Path def assemble_memory(cwd: Path) - str: blocks [] for path in discover_memory_files(cwd): content path.read_text(encodingutf-8, errorsignore) if path.name MEMORY.md: content \n.join(content.splitlines()[:200]) blocks.append(f# From {path}\n{content}) return \n\n.join(blocks) def discover_memory_files(cwd: Path): # 从 cwd 向上遍历到文件系统根收集 AGENTS.md 和 MEMORY.md current cwd.resolve() found [] while True: for name in (AGENTS.md, MEMORY.md): candidate current / name if candidate.exists(): found.append(candidate) if current.parent current: break current current.parent return list(reversed(found))再加 context compaction。两级级联microcompaction 不调模型只把旧的 tool 输出体替换成占位符完整 compaction 调一次便宜的模型把老历史总结成固定骨架。触发阈值基于 token 预算# src/harness/compaction.py import enum class CompactOutcome(enum.Enum): COMPACTED compacted NOTHING_TO_COMPACT nothing_to_compact SUMMARIZER_FAILED summarizer_failed def split_tail(messages, *, keep_recent_tokens: int) - int: 从尾部累积 tokensnap 到 compaction boundary 保证 tool-call/result 对不被拆开。 total 0 for i in range(len(messages) - 1, -1, -1): total estimate_tokens(messages[i]) if total keep_recent_tokens: return snap_to_boundary(messages, i) return 0 def microcompact(messages, *, keep_recent_tokens: int): 无 LLM 层把旧 tool 输出体清空。 boundary split_tail(messages, keep_recent_tokenskeep_recent_tokens) for msg in messages[:boundary]: if msg.get(role) tool: msg[content] [已压缩] return messages沙箱层按需开启。本地开发用mode none跑真实命令时切docker。fresh-exec 模式下每条命令作为全新进程运行cd和export不会跨调用持久化。这个设计看起来反直觉但它让本地和远程行为字节级一致避免本地能跑远程不能跑的问题# src/harness/sandbox.py class SandboxExecutor: Fresh-execcd/export 不持久。 def __init__(self, backend, workspace): self._backend backend self._workspace workspace self._created False async def run(self, command: str, *, timeout_s: float): if not self._created: await self._backend.create(self._workspace) self._created True return await self._backend.exec(bash, -lc, command, timeout_stimeout_s)如果你要跑长期任务或 Agent 工作流建议用 Coding Plan入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。高频 tool call 场景下稳定的计费和额度比单次便宜更重要因为 harness 一个 turn 可能触发十几次模型请求。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里面有各语言和各工具的完整配置示例。API Keys 管理在 https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 建议给不同项目建不同的 Key方便按项目排查和吊销。最后说一个我踩过的坑不要一上来就把所有组件都打开。先跑通模型入口再加事件流再加权限门最后加沙箱和 compaction。每加一层就跑一次端到端验证确认事件序列没变。这样出问题时你永远知道是哪一层引入的。harness 的复杂度是必要的但引入复杂度必须可控。

相关新闻

短视频app搭建:用MediaStore获取手机图库最新视频缩略图(含TaoToken配置)

短视频app搭建:用MediaStore获取手机图库最新视频缩略图(含TaoToken配置)

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

2026/10/2 16:25:17 阅读更多 →
新手接入 Claude API,最容易忽略的五个配置项:TaoToken 统一 Key 通道实践

新手接入 Claude API,最容易忽略的五个配置项: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/2 16:25:17 阅读更多 →
2026-10-01-v2-职业发展-数字孪生从业者职业路径指南

2026-10-01-v2-职业发展-数字孪生从业者职业路径指南

数字孪生从业者职业路径全解析:从入门到专家的成长指南 前言 数字孪生行业的高速发展,创造了大量的就业机会,很多人想要进入这个行业,但对数字孪生行业的职业路径、岗位要求、发展前景都不太了解。本文将全面解析数字孪生行业的职…

2026/10/2 16:24:16 阅读更多 →

最新新闻

汽车测试数据采集全链路解析:从传感器到HIL/PIL的工程实践

汽车测试数据采集全链路解析:从传感器到HIL/PIL的工程实践

汽车测试这个领域,外行看着就是"把车开上试验台跑一圈",但真正做过整车或零部件验证的人都知道,从传感器信号采集到数据入库,中间隔着一堆协议转换、时钟同步、量纲对齐的脏活累活。Axiometrix Solutions 这套一站式方案…

2026/10/2 16:52:24 阅读更多 →
自制无刷电调全攻略:原理、方案与VESC实战

自制无刷电调全攻略:原理、方案与VESC实战

1. 为什么我自己动手做电调,而不是直接买现成的先交代一下背景。我玩FPV穿越机也有几年了,中间折腾过不少动力系统的东西:换电机、调PID、改机架,但电调这块一直用的都是成品——一开始是BLHeli_S的小四合一,后来升级到…

2026/10/2 16:52:24 阅读更多 →
在Trae中接入SenseNova的DeepSeek V4 Flash API:前端开发每5小时500次调用配置指南

在Trae中接入SenseNova的DeepSeek V4 Flash API:前端开发每5小时500次调用配置指南

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

2026/10/2 16:52:24 阅读更多 →
工业缺陷检测中小样本训练与漏检控制实战指南

工业缺陷检测中小样本训练与漏检控制实战指南

1. 为什么工业缺陷检测的“漏检”比“误检”更致命?在产线现场盯了三年AOI设备,我见过太多次因为一个微小划痕没被识别出来,导致整批次PCB板返工——不是因为算法不准,而是因为那个划痕恰好出现在训练集里从未出现过的角度、光照和…

2026/10/2 16:52:24 阅读更多 →
Krita游戏开发实战:从零构建2D美术资产管线与自动化脚本

Krita游戏开发实战:从零构建2D美术资产管线与自动化脚本

1. 为什么游戏开发者会盯上Krita这款绘画工具第一次听说有人用Krita做游戏开发,很多人的反应是:那不是画插画的吗?跟游戏引擎有什么关系?我当初也是这个反应。但真正上手做过两个小项目之后,我发现Krita在独立游戏开发…

2026/10/2 16:52:24 阅读更多 →
【Bug已解决】codex MCP server connection fails / Tool not found — CodeX CLI MCP 连接失败解决方案:把 MCP endpoint 改

【Bug已解决】codex MCP server connection fails / Tool not found — CodeX CLI MCP 连接失败解决方案:把 MCP endpoint 改

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

2026/10/2 16:51:24 阅读更多 →

日新闻

从零搭建AI工程化:模型之外的完整闭环

从零搭建AI工程化:模型之外的完整闭环

先搞清楚一件事:从零开始做 AI 工程化,难的从来不是调模型、写提示词,而是把一套原型 Demo 变成长得像是“正经系统”的东西。你手里可能已经有了能跑通的代码,也可能刚读完一些概念,但真到了要把它变成可维护、可观测…

2026/10/2 0:00:20 阅读更多 →
大模型训练显存估计与混合精度训练实战指南

大模型训练显存估计与混合精度训练实战指南

1. 大模型训练显存估计与混合精度训练详解显存不够用,几乎是每个做大模型训练的人都会撞上的第一堵墙。你可能也经历过:模型代码写完了,数据管道跑通了,满心欢喜地按下训练启动脚本,结果几秒钟后终端弹出一行红字——C…

2026/10/2 0:00:20 阅读更多 →
小样本学习数据集选型指南:27个真正可用的高质量数据集

小样本学习数据集选型指南:27个真正可用的高质量数据集

1. 小样本学习的“弹药库”:为什么你总在找数据集,却总找不到真正能用的? 小样本、数据集——这两个词最近半年在我处理的200多个AI项目咨询里,出现频率排进前三。不是模型调不好,不是代码写不对,而是卡在…

2026/10/2 0:00:20 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/10/1 19:40:48 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/10/1 19:41:40 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/10/1 20:05: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/2 10:36:31 阅读更多 →
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/2 5:26:06 阅读更多 →
黑夜航拍船只数据集训练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/2 6:09:11 阅读更多 →