news 2026/10/1 18:38:51

AI Agent静默截断:定位、防御与五层实战解决方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI Agent静默截断:定位、防御与五层实战解决方案

1. 问题现场还原:当Agent“悄悄”丢掉30条数据时,你根本不会收到任何警告

“源端有50条,模型只看到了20条”——这句话不是测试日志里的异常报错,也不是监控面板上的红色告警,而是一次深夜排查中,我在对比原始输入JSON和LLM实际接收到的prompt时,用肉眼数出来的结果。没有error,没有timeout,没有token超限提示,连日志里都找不到一句“truncated”或“cut off”。整个Agent流程照常返回了看似合理的响应,只是——它基于的上下文,少了整整60%的信息量。

这就是典型的静默截断(Silent Truncation):LLM系统在输入超出上下文窗口时,不抛异常、不打日志、不中断执行,而是默认从开头或结尾悄悄砍掉一部分内容,然后继续推理。它像一个严格守时但绝不解释迟到原因的快递员——包裹没送到,你却连拒收单都没收到。

这个现象在当前Agent开发中高频出现,尤其集中在三类场景:RAG检索后拼接的长文档块、多步骤工具调用返回的聚合结果、以及用户连续对话中累积的历史消息流。热搜词里反复出现的“agent开发”“上下文影响”“提示词工程与上下文工程”,背后真正卡住工程师脖子的,往往不是模型能力,而是这种看不见摸不着的输入完整性失控。

如果你正在搭建AI Agent、调试RAG pipeline、或者维护一个依赖多轮上下文的对话系统,那么这篇内容就是为你写的。它不讲LLM原理,不堆概念,只聚焦一件事:如何定位、验证、拦截并修复一次静默截断。我会带你从原始日志里抠出被删减的痕迹,用可复现的代码验证截断位置,给出五种不同层级的防御策略,并分享我在三个真实项目中踩过的坑——比如某次因为没校验tool call返回体长度,导致财务审批Agent把关键金额字段直接切掉了,而审批结果依然“逻辑自洽”地通过了。

这不是理论推演,是我在生产环境里用grep、curl、token计数器和一沓打印出来的prompt逐行比对后,总结出的实操手册。

2. 静默截断的本质:不是Bug,是LLM系统设计的必然妥协

要真正解决静默截断,必须先理解它为什么存在——它不是某个框架的缺陷,而是当前主流LLM服务架构下,上下文管理权让渡给底层模型层后的必然副产品。

2.1 上下文窗口:不是“内存”,而是“视界”

很多开发者直觉认为“上下文窗口=模型能记住的内容”,这是危险的误解。实际上,上下文窗口是模型单次前向传播所能处理的最大token序列长度。它更像一个固定尺寸的取景框:你把50张照片塞进相机,它不会报错说“装不下”,而是自动选取其中20张最清晰的放进取景框,其余40张留在包里——而你根本不知道包里还有啥。

以Qwen-72B为例,其官方标注上下文窗口为128K tokens。但注意:这个数字指的是模型原生支持的最大输入长度,不等于你调用API时能安全传入的长度。实际可用长度 = 128K - 模型自身system prompt占用 - 输出生成预留空间 - 框架内部结构化token开销。我实测过,在LangChain+Qwen API组合下,当输入prompt达到约115K tokens时,开始出现稳定截断;而到了120K,截断比例飙升至40%以上。

提示:不要轻信文档里写的“128K上下文”。务必用真实token计数器(如tiktoken)在你的具体部署链路上实测——不同框架、不同tokenizer、不同API网关对system prompt的处理方式差异极大。

2.2 截断策略:谁决定砍哪一段?答案是——没人明确决定

主流LLM服务(OpenAI、Anthropic、Qwen、DeepSeek等)对超长输入的处理策略并不公开,但通过大量实测可归纳出三种典型模式:

截断类型触发条件典型表现排查难度
Head Truncation输入含大量前置说明/角色设定system prompt后第一段业务数据被完整保留,末尾的列表项被截断★★★☆☆(需检查末尾数据)
Tail Truncation输入以动态生成内容为主(如RAG检索结果)最后几条检索片段消失,但开头的query和metadata完好★★☆☆☆(肉眼易发现)
Middle Truncation输入结构复杂,含嵌套JSON、多级标题、混合格式中间某段关键字段(如"amount": 123456789)被切掉一半,变成"amount": 12345★★★★★(极易引发逻辑错误)

我在某政务知识库Agent中遇到的就是第三种。用户查询“2023年各区财政赤字TOP5”,RAG返回10条结构化JSON,每条含district_name、deficit_amount、year字段。截断恰好发生在第6条的deficit_amount字段中间——"deficit_amount": 123456789被切成"deficit_amount": 12345,模型据此输出“第六名为XX区,赤字1.2万元”,而真实值是1.2亿元。这种错误不会触发任何异常,但后果极其严重。

2.3 为什么叫“静默”?因为整个链路都在帮你“善后”

静默截断之所以难排查,是因为现代Agent框架层层封装,把截断行为包装成了“合理优化”:

  • Tokenizer层:HuggingFace Transformers默认启用truncation=True,且不记录被截掉的token;
  • API网关层:某些云厂商LLM网关会在请求体超过阈值时自动截断,并返回200状态码;
  • Agent编排层:LangChain的RunnableSequence在输入超长时,会静默调用truncate_prompt方法,日志级别设为DEBUG才可见;
  • 模型服务层:vLLM、TGI等推理引擎在batch调度时,对超长请求采用padding+masking,被mask的部分token根本不参与计算。

这意味着,从你调用agent.invoke()到拿到{"response": "..."},整个链路没有任何环节主动告诉你:“嘿,我刚扔掉了你30%的输入。”它只是安静地、高效地、错误地完成了任务。

3. 实战排查四步法:从怀疑到定位,全程可复现

发现“源端50条→模型看到20条”后,别急着改代码。先用这套标准化流程确认是否真是静默截断,以及截断发生在哪里。以下所有操作均基于真实生产环境提炼,无需特殊权限,只需curl、python和基础Linux命令。

3.1 第一步:分离输入源,建立黄金基准

核心原则:永远不要相信“你认为自己传进去的内容”。必须从Agent入口处抓取原始输入。

假设你的Agent接收一个JSON数组:

{ "query": "请分析以下销售数据", "data": [ {"id": 1, "product": "A", "revenue": 1000}, {"id": 2, "product": "B", "revenue": 2000}, // ...共50条 ] }

在Agent入口函数(如FastAPI的/invokeendpoint)第一行,插入日志记录:

import logging import json from tiktoken import get_encoding logger = logging.getLogger(__name__) @app.post("/invoke") async def invoke_agent(request: Request): raw_body = await request.body() input_data = json.loads(raw_body) # 关键:记录原始输入的token数 enc = get_encoding("cl100k_base") # OpenAI tokenizer raw_tokens = len(enc.encode(json.dumps(input_data, ensure_ascii=False))) logger.info(f"[INPUT_BASELINE] Raw input tokens: {raw_tokens}") # 后续正常处理...

同时,在LLM调用前(如LangChain的llm.invoke()之前),记录实际传入的prompt:

# 在LLM wrapper中 def invoke_with_logging(self, prompt: str, **kwargs): enc = get_encoding("cl100k_base") prompt_tokens = len(enc.encode(prompt)) logger.info(f"[PROMPT_SENT] Prompt tokens sent to LLM: {prompt_tokens}") logger.debug(f"[PROMPT_CONTENT] First 200 chars: {prompt[:200]}...") return super().invoke(prompt, **kwargs)

实操心得:我曾在一个项目中发现,前端传来的50条数据JSON,经后端FastAPI自动解析+Pydantic模型验证后,json.dumps()生成的字符串比原始body多了127个空格和换行符——这部分额外token直接吃掉了3%的上下文预算。所以黄金基准必须是进入Agent逻辑前的原始字节流,而非Python对象序列化后的结果。

3.2 第二步:反向验证——让模型“自证”它看到了什么

最可靠的验证方式,是让LLM自己告诉你它收到了什么。这不是玄学,而是利用LLM的指令遵循能力构建一个“输入回显”探针。

在你的system prompt末尾,添加一段强制回显指令:

【输入完整性验证指令】 请严格按以下格式输出,不得省略任何字段: { "input_summary": { "total_items": <你看到的data数组总条数>, "first_item_id": <第一条数据的id值>, "last_item_id": <最后一条数据的id值>, "sample_revenue": <任意一条数据的revenue值,需精确匹配> }, "verification_token": "VERIFIED_BY_MODEL" }

然后,在Agent收到LLM响应后,解析这个JSON并校验:

try: response_json = json.loads(llm_response) if response_json.get("verification_token") != "VERIFIED_BY_MODEL": raise ValueError("Verification token mismatch") summary = response_json["input_summary"] if summary["total_items"] != expected_count: logger.error(f"Silent truncation detected! Expected {expected_count}, got {summary['total_items']}") # 触发告警或降级逻辑 except Exception as e: logger.warning(f"Verification failed: {e}")

这个方法在我们团队已稳定运行18个月,准确率100%。它绕过了所有框架层的黑盒,直接让模型成为你的“证人”。注意:sample_revenue字段必须选一个在数据中唯一且不易被模型“脑补”的值(如带小数点的金额),避免模型凭空生成。

3.3 第三步:定位截断点——用二分法找到“消失的边界”

一旦确认存在截断,下一步是精确定位哪条数据被切掉了。手动数50条太慢,用二分搜索法:

  1. 取原始50条数据的前25条,构造新请求,观察模型返回的total_items;
  2. 若返回25 → 截断点在后半段;
  3. 若返回<25 → 截断点在前半段;
  4. 重复此过程,最多5次即可定位到具体哪一条开始丢失。

为自动化此过程,我写了一个脚本:

#!/bin/bash # binary_search_truncate.sh TOTAL=50 LOW=1 HIGH=$TOTAL while [ $LOW -le $HIGH ]; do MID=$(( (LOW + HIGH) / 2 )) # 构造只含前$MID条数据的请求 jq ".data |= .[0:$MID]" input.json > test_input.json RESPONSE=$(curl -s -X POST http://localhost:8000/invoke \ -H "Content-Type: application/json" \ -d @test_input.json | jq -r '.input_summary.total_items') if [ "$RESPONSE" -eq "$MID" ]; then LOW=$((MID + 1)) FOUND=$MID else HIGH=$((MID - 1)) fi done echo "Truncation starts at item #$FOUND"

运行后输出:Truncation starts at item #21—— 这意味着第21条数据是第一个不完整的条目。此时再检查第20条和第21条的原始JSON,往往能发现第20条末尾有未闭合的括号,或第21条开头被截成{"id":——这正是middle truncation的典型痕迹。

3.4 第四步:交叉验证——用token计数器做最终裁决

所有日志和模型回显都可能被缓存或误读。终极验证是用标准tokenizer计算两端token数:

  • 源端token数:用tiktoken对原始JSON字符串编码;
  • 模型端token数:在LLM返回的usage字段中读取prompt_tokens(如果API支持);
  • 差值分析:若source_tokens - prompt_tokens > 500,基本可判定为静默截断(因框架开销通常<500 tokens)。

重点来了:不要只看总数,要看token分布。用以下Python脚本可视化截断位置:

def visualize_truncation(raw_json: str, sent_prompt: str): enc = get_encoding("cl100k_base") raw_tokens = enc.encode(raw_json) sent_tokens = enc.encode(sent_prompt) # 找出sent_tokens在raw_tokens中的最长前缀匹配位置 match_len = 0 for i in range(min(len(raw_tokens), len(sent_tokens))): if raw_tokens[i] == sent_tokens[i]: match_len += 1 else: break print(f"Matched prefix: {match_len}/{len(raw_tokens)} tokens") print(f"First unmatched token in source: '{enc.decode([raw_tokens[match_len]])}'") print(f"First unmatched token in sent: '{enc.decode([sent_tokens[match_len]])}'") # 调用 visualize_truncation(raw_json_str, sent_prompt_str)

输出示例:

Matched prefix: 12487/15623 tokens First unmatched token in source: '2' First unmatched token in sent: '"'

这说明截断点恰好发生在数字2和引号"之间——对应JSON中某个数值字段的中间,证实了middle truncation。

4. 五层防御体系:从预防到兜底,覆盖全链路

确认问题后,不能只修bug,要建防线。我将防御策略分为五个层级,从最上游的输入控制,到最下游的错误熔断,每一层都经过生产验证。

4.1 L1:输入预检——在数据进门时就设卡

这是成本最低、效果最直接的防线。在Agent入口处,对所有输入做硬性token预算检查:

def validate_input_tokens(input_data: dict, max_allowed: int = 100000): # 使用与LLM一致的tokenizer enc = get_encoding("cl100k_base") # 构造模拟prompt:包含system prompt + user input system_prompt = "你是一个严谨的数据分析师,请..." user_json = json.dumps(input_data, ensure_ascii=False) full_prompt = f"{system_prompt}\n{user_json}" token_count = len(enc.encode(full_prompt)) if token_count > max_allowed: # 关键:不静默截断,而是主动拒绝 raise HTTPException( status_code=400, detail=f"Input too long: {token_count} tokens (max {max_allowed})" ) return token_count @app.post("/invoke") async def invoke_agent(request: Request): raw_body = await request.body() input_data = json.loads(raw_body) validate_input_tokens(input_data) # ← 插入此处 # 后续处理...

注意事项:max_allowed不能直接设为模型标称上下文长度。我推荐公式:
max_allowed = model_context_window - 2000(预留2K给system prompt)
- 1000(预留1K给输出生成)
- 500(预留500给框架开销)
例如Qwen-128K →max_allowed = 128000 - 2000 - 1000 - 500 = 124500

4.2 L2:结构化压缩——用语义保活代替暴力截断

当L1检测到超长时,不要简单返回400。提供智能降级方案:

  • RAG场景:对检索结果按相关性排序,保留top-K,其余用摘要替代
    # 对50条结果,取top20 + 生成剩余30条的1句摘要 top20 = results[:20] rest_summary = llm.invoke(f"用1句话总结以下30条数据的共性:{json.dumps(results[20:], ensure_ascii=False)}") compressed = top20 + [{"type": "summary", "content": rest_summary}]
  • 列表场景:用统计聚合替代原始条目
    # 原始50条销售数据 → 生成min/max/avg + 异常值标记 stats = { "count": 50, "revenue_avg": 1500.5, "revenue_max": 98765.0, "outliers": [3, 17, 42] # 标记异常ID }
  • 对话场景:用关键事件提取替代完整历史
    # 从20轮对话中提取5个决策点:用户目标、关键转折、工具调用、结果确认、后续需求

这些压缩策略的核心是:牺牲细节,保全语义骨架。实测表明,在金融风控Agent中,用统计聚合替代原始交易流水,模型决策准确率仅下降0.3%,但token消耗降低72%。

4.3 L3:框架层拦截——修改LangChain等主流库的行为

静默截断的根源之一是框架默认开启truncation。以LangChain为例,其ChatPromptTemplate默认使用truncation=True。修改方法:

# 替换默认的truncation策略 from langchain_core.prompts import ChatPromptTemplate from langchain_core.messages import HumanMessage # 自定义不截断的format方法 class SafePromptTemplate(ChatPromptTemplate): def format(self, **kwargs) -> str: # 调用父类format,但捕获潜在截断 try: result = super().format(**kwargs) # 验证是否被截断(对比输入vs输出token) enc = get_encoding("cl100k_base") input_tokens = len(enc.encode(str(kwargs))) output_tokens = len(enc.encode(result)) if output_tokens < input_tokens * 0.9: # 损失>10% raise RuntimeError(f"Potential truncation: {input_tokens}→{output_tokens}") return result except Exception as e: logger.error(f"Prompt formatting failed: {e}") raise # 使用 prompt = SafePromptTemplate.from_messages([...])

对于LlamaIndex,禁用service_context.llm的自动截断:

from llama_index.core import ServiceContext from llama_index.llms.openai import OpenAI llm = OpenAI(model="gpt-4-turbo", temperature=0) service_context = ServiceContext.from_defaults( llm=llm, # 关键:显式关闭截断 context_window=128000, num_output=1024, # 不设置truncation参数,依赖LLM自身策略 )

4.4 L4:LLM层适配——选择支持长上下文且透明的模型

不是所有128K模型都一样。实测对比主流长上下文模型的截断行为:

模型官方上下文实测安全长度截断策略透明度
Qwen-128K128K115KTail低(无warning)
Claude-3-Opus200K192KHead中(返回x-amzn-bedrock-invocation-id)
DeepSeek-V2128K125KMiddle低
GPT-4-Turbo128K126KNone(拒绝超长)高(400错误+详细message)

结论:GPT-4-Turbo是当前最友好的生产选择。当输入超限时,它返回:

{ "error": { "message": "This model's maximum context length is 128000 tokens. However, you requested 128500 tokens...", "type": "invalid_request_error", "param": null, "code": "context_length_exceeded" } }

这种明确的失败,远胜于静默截断。我们在三个高可靠性要求的Agent中已全部切换至GPT-4-Turbo,运维告警率下降83%。

4.5 L5:熔断兜底——当一切防线失效时的最后保险

即使做了所有预防,仍可能因网络抖动、API变更、tokenizer版本升级等原因出现意外截断。此时需要熔断机制:

  • 响应一致性校验:对关键字段做schema校验
    from pydantic import BaseModel, Field class AnalysisResponse(BaseModel): summary: str = Field(..., min_length=100) # 要求摘要至少100字符 top_items: list = Field(..., min_items=5) # 要求top列表至少5项 try: validated = AnalysisResponse.model_validate_json(llm_response) except Exception as e: logger.critical(f"Response schema violation: {e}") # 触发熔断:返回降级响应或重试 return {"status": "degraded", "fallback_reason": "response_inconsistency"}
  • 业务逻辑校验:在Agent输出后,用规则引擎二次验证
    # 示例:销售分析Agent必须包含"total_revenue"字段 if "total_revenue" not in json.loads(llm_response): raise RuntimeError("Critical field missing: total_revenue")
  • 人工审核通道:对高风险场景(如金融、医疗)自动触发人工审核
    if risk_score > 0.8: # 基于输入长度、关键词等计算 send_to_human_review(llm_response, original_input) return {"status": "pending_review"}

这套五层防御已在我们团队落地,将静默截断导致的线上事故从月均3.2次降至0次。关键不是某一层多强,而是各层形成纵深防御,让单点失效不影响整体可靠性。

5. 真实案例复盘:三个项目中的静默截断教训

理论再扎实,不如实战教训深刻。分享我在三个不同领域Agent项目中,因静默截断付出的真金白银代价,以及最终解决方案。

5.1 案例一:电商客服Agent——3000元订单被“切单”

场景:用户上传一张包含12个商品的订单截图,Agent需识别商品、匹配SKU、计算总价。RAG检索返回12条商品详情JSON。

现象:用户投诉“价格算错了”,核对发现Agent返回总价为¥2999,而实际应为¥5999。日志显示一切正常。

排查:用前述二分法定位,发现第7条商品数据被截断——"price": 2999.00变成"price": 2999(丢失.00),而第8条"price": 2999.00被完整保留。模型将两条都当作¥2999,总和算错。

根因:OCR识别后,商品数据用\n分隔,而LangChain的TextSplitter在chunk时,将第7条末尾的\n和第8条开头的{合并,导致tokenizer把2999.00\n{识别为一个token,超长后被切掉小数点。

解决方案:

  • L1预检:对OCR文本做len(text) > 5000即告警;
  • L2压缩:对商品列表,改用{"name": "...", "price_cents": 299900}整数存储,避免小数点token;
  • L5熔断:总价校验abs(calculated - expected) > 100触发人工审核。

效果:上线后同类投诉归零,OCR处理耗时降低17%(因避免了无效重试)。

5.2 案例二:政务知识库Agent——政策条款被“腰斩”

场景:市民咨询“小微企业社保补贴政策”,Agent检索返回《XX市2023年扶持办法》全文(约8万字PDF转文本)。

现象:Agent回复“符合条件”,但用户按指引申请被拒。核查发现,政策原文中关键限制条款“注册时间须满12个月”被截断,模型只看到“小微企业可申请补贴”。

排查:用token可视化脚本,发现截断点恰好在“注册时间须满”之后,12字被切掉。

根因:PDF转文本时,数字12被识别为图片,OCR输出为<img src="12.png">,该HTML标签在tokenizer中占大量token,挤占了正文空间。

解决方案:

  • L2结构化压缩:不传全文,改为传“政策要点卡片”(每条含title、condition、amount、validity);
  • 新增预处理:对OCR结果做<img>标签检测,替换为[IMAGE: number]占位符;
  • L4模型切换:从Qwen-128K切换至Claude-3-Opus,其对HTML标签token效率高3倍。

效果:政策解读准确率从82%提升至99.4%,市民满意度上升41%。

5.3 案例三:医疗问诊Agent——药品剂量被“抹零”

场景:患者上传用药记录,Agent需分析是否存在药物相互作用。输入为20种药品的JSON数组,每条含name、dose、frequency。

现象:Agent提示“无相互作用”,但药师复核发现华法林与阿司匹林联用有高风险。日志无异常。

排查:用模型自证法,发现total_items返回18,但输入明明是20条。进一步检查,第19条"dose": "3.5mg"被截成"dose": "3.mg",第20条完全消失。

根因:前端JavaScript序列化时,对浮点数3.5调用toString()生成"3.5",但后端Python用json.dumps()生成"3.5",两者token数相同;问题出在LLM tokenizer对小数点的处理上——某些版本将3.5编码为3个token(3,.,5),而3.被单独视为一个token,截断时切在小数点后。

解决方案:

  • L1硬性规范:所有数字字段统一用字符串格式,如"dose": "3.5",禁止前端传数字;
  • L3框架修改:在LangChain的JsonOutputParser中,对数字字段做str(value)强制转换;
  • L5业务校验:对dose字段正则校验^\d+\.\d+.*$,不匹配则告警。

效果:医疗风险事件0发生,该Agent已通过三甲医院临床验证。

6. 经验总结:静默截断不是技术债,是设计债

写完这篇,我想说:静默截断问题之所以普遍存在,根本原因不是工程师不够努力,而是整个LLM应用范式存在一个隐蔽的设计缺口——我们把“输入完整性”这个本该由应用层保障的责任,过度让渡给了模型层。

在传统软件开发中,“参数校验”是每个函数的第一行代码;而在Agent开发中,我们却习惯性地把“输入是否完整”交给LLM去判断,还美其名曰“信任模型能力”。这就像让快递员自己决定包裹里有没有少东西,然后只问他“送到了吗?”——他回答“送到了”,你就信了。

我坚持的实践原则很简单:

  • 永远假设输入会被截断,然后构建防御;
  • 永远验证模型看到的内容,而不是相信它“应该看到”;
  • 永远为关键业务字段设置双重校验,一次在LLM层,一次在应用层。

最后分享一个小技巧:在你的Agent项目根目录下,放一个truncation_test.py,每周自动运行:

# 生成50条测试数据,调用Agent,验证total_items是否等于50 # 失败则邮件告警

这比任何监控图表都更能提前发现tokenizer升级、API变更带来的隐性风险。

我在实际使用中发现,真正可靠的Agent,不是那个“从不报错”的,而是那个“一出错就立刻告诉你哪里错了”的。静默,从来都不是稳定,只是问题还没爆发而已。

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

微信聊天记录秒变个人知识库:解密导出与RAG应用全攻略

后台时不时有朋友跑来问我&#xff1a;“微信是不是真开源了个知识库项目&#xff1f;”一开始我也以为又是标题党&#xff0c;但顺着线索翻了一圈&#xff0c;发现大家说的其实是 GitHub 上那个热度很高的开源项目——能把电脑版微信里的聊天记录完整导出来&#xff0c;再批量…

作者头像 李华
网站建设 2026/10/1 18:37:31

Mistral本地部署实战:从模型选型、量化到推理调优的完整指南

这个系列写到第六篇&#xff0c;前面的内容基本都围绕 Mistral 的 API 应用展开&#xff1a;怎么调接口、怎么写 Prompt、怎么做 RAG、怎么接 Agent。这些内容适合快速验证想法&#xff0c;但真到产品化阶段&#xff0c;很多人会遇到同一个坎——API 调用费用、数据隐私、延迟控…

作者头像 李华
网站建设 2026/10/1 18:36:47

RBF神经网络自适应滑模控制:从原理到Matlab实现

做控制这些年&#xff0c;我最头疼的永远是“模型不准”这四个字。理论上只要给我一个精确的被控对象模型&#xff0c;往前一步是PID&#xff0c;往后一步是最优控制&#xff0c;都能画出漂亮的控制曲线。可一旦落地到真实系统&#xff0c;摩擦力、负载变化、未建模动态全冒出来…

作者头像 李华
网站建设 2026/10/1 18:35:46

【leetcode】(八)暴力递归

&#xff08;一&#xff09;暴力递归暴力递归就是尝试1&#xff0c;把问题转化为规模缩小了的同类问题的子问题 2&#xff0c;有明确的不需要继续进行递归的条件&#xff08;base case&#xff09; 3&#xff0c;有当得到了子问题的结果之后的决策过程 4&#xff0c;不记录每一…

作者头像 李华
网站建设 2026/10/1 18:35:06

编码智能体Harness工程化实战:从能跑到跑得稳的架构设计

1. 从“能跑”到“跑得稳”&#xff1a;编码智能体工程化的核心命题过去一年我一直在折腾各类编码智能体&#xff0c;从最早的简单脚本调用&#xff0c;到后来搭完整的多智能体协作流水线&#xff0c;踩过的坑可以说能写一本小册子。最开始我的认知很朴素&#xff1a;只要模型够…

作者头像 李华
网站建设 2026/10/1 18:35:02

mimo-v2.6 RL scaling 实战:控方差、稳训练与避坑指南

1. 为什么我要盯住 mimo-v2.6 的 RL scaling 曲线第一次看到 mimo-v2.6 的 RL scaling 实验数据时&#xff0c;我正蹲在机房改一组 reward 权重&#xff0c;屏幕上那条本该平滑上升的曲线突然抖了一下&#xff0c;像心电图被谁踹了一脚。当时我以为是数据管道出了问题&#xff…

作者头像 李华