面筋鉴赏-aiagent
面筋学习(ai agent)!!🤣🤣
主流 agent 开发框架
基础能力
function call:强调怎么把调用意图表示出来。ai 如何用结构化的格式告诉外部程序,需要使用什么方法,以及参数信息
tool use:强调模型能不能使用外部能力完成任务,关心 ai 能不能在需要时使用外部工具
function call 是表达调用意图的一种方法,tool use 可以使用 function call 的方式调用工具,当然也可以使用其他的方法
低代码框架
coze、dify、langflow
代码框架
LangGraph
把 agent 的每一步建模为有向图中的节点,控制流由边显式定义。比如【思考 ➡️ 判断 ➡️ 行动 ➡️ 继续/结束】的循环,用图结构表述。每步执行后的状态完整保存,可以 checkpoint、回放、人工修改后继续
支持循环和条件分支、原生 human-in-the-loop(中断后,人可以进行修改然后继续执行),持久化 checkpoint 让调试和回放变得可行。

CrewAI
给每个 agent 定义 role、goal 和 background,用一个 manager agent 调度,agent 之间有一个共享的 crew 上下文记忆,能够记住之前的决策
内置短期记忆(对话上下文)、长期记忆(跨任务持久化)。任务级错误隔离能力:一个 agent 挂了不会让整个 crew 崩溃,manager可以重新分配或转人工

AutoGen
核心理念为一切皆对话。多个 agent (可以是LLM、工具执行器、人类)像群聊成员一样互相发消息协作。他支持事件驱动和异步执行,一个 agent 在等待 api 返回时候,其他 agent 可以继续工作,不会互相阻塞
内置反思循环:agent 执行出错了,自动分析错误原因、修改方案、重新尝试。在代码生成场景中非常有用(写代码 ➡️ 运行 ➡️ 报错 ➡️ 分析 ➡️ 修改 ➡️ 再运行)

OpenAI Agents SDK
一个 agent 只需要三个要素:instructions(告诉 agent 他是谁,他要做什么)、tools(调用的参数和 api)、handoff(可选,把上下文转交给另一个 agent)
代码量是所有框架中最少的,内置 guardrails(安全护栏),自动检测是否输入敏感内容、是否越界。

LlamaIndex
核心是从数据出发。流程为 加载文档 ➡️ 解析内容 ➡️ 构建索引 ➡️ 查询检索 ➡️ agent 决策,强调让 agent 理解和检索海量数据
rag 生态业界最全,从最简单的向量检索到 agentic rag(agent 自主决定何时检索以及检索内容),再到 graphrag(知识图谱增强检索)。支持多种索引结构:向量索引、树索引、关键词索引、知识图谱索引。agent 建立在索引之上,先查资料再进行决策

Semantic Kernel
把 LLM 能力嵌入到传统软件工程中。不是只关注多个 agent 如何聊天,而是把模型调用、函数调用、插件、工作流、记忆和企业系统集成组织成一个可编排的 kernel。
腾讯 ai 应用开发 一面
项目中把skill直接塞到 system propmt中,如果 skill 太多,占用上下文窗口太大的话,应该如何处理?
不能把所有的 skill 常驻塞进 system propmt,这样会带来三个问题:上下文窗口被占满、候选技能噪声太大、模型在选择 skill 时更容易混淆。更合理的方式是把 skill 做成外部注册表,system prompt 里只保留最小规则和调用协议,真正的 skill 描述按需动态注入
常见的做法是先做一层 skill routing。可以用规则、分类模型或者向量检索先筛选出 topk skill,再把这几个 skill 的descption、参数和 few-shot 示例放进 prompt。如果 skill 本身很长,还要把 skill 信息拆成摘要版本和完整版本,先注入摘要,模型确定要调用后再加载详细说明,减少 token。
如果两个 skill 实际内容不一样,但是 description 很相似,导致 agent 每次加载错 skill,怎么解决
描述很相似的时候,单靠自然语言匹配很容易误找回。解决思路是给 skill 增加更强的判别信息,而不是继续堆描述
可以把 skill 从纯文本的 description 升级为结构化的定义,包括适用的场景、禁用的场景、输入参数、返回格式、前置条件、失败条件和调用示例。然后做两阶段的选择,先召回 topk,再让模型根据参数约束和样例做 rerank。第三步是加入负样本示例,明确告诉模型什么问题不应该调用这个 skill,之后在执行前做 schema 校验(检查输入参数的格式是否正确)和 rule check(检查语义是否正确),即使模型选错,也不能误调
如果两个 skill 语义上十分接近,可以考虑合并
agent 设计中你觉得最重要的是什么?
最重要的是上下文工程。agent 最终不是单轮回复,而是一个持续决策系统。模型能够看到什么信息,这些信息的顺序和优先级是什么,哪些内容是规则,哪些内容是证据,哪些内容只是历史状态,都会直接影响到 agent 的稳定性,在 prompt 中给到正确的信息是最重要的
context prompt 有哪些需要注意的点
首先要做角色隔离,system、developer、user、tool input、memory 的优先级和边界要清楚,不能把外部文本和系统规则混在一起。其次是信息裁剪,只保留和当前任务相关的内容,避免把所有历史对话、所有检索结果和所有工具说明一股脑灌进去
然后是格式控制,结构化上下文通常比自然语言更稳定,所以尽量用 json 格式表示,任务状态单独字段化、长历史做摘要而不是堆原文
如果是长任务,还需要做上下文压缩和过期淘汰,不然越到后面越容易发生状态漂移和旧信息污染新决策
如何设计 agent 的长期记忆写回策略、衰减策略和冲突消解
长期记忆不能等价于把所有历史都存起来。真正可用的长期记忆必须回答三个问题:什么值得写回、什么时候应该忘、冲突信息怎么处理
写回策略上,通常只保存高价值稳定信息,比如用户偏好、身份属性、长期任务目标、反复出现的业务现实。写回时最好做结构化抽取,比如说“用户更喜欢用 python”写成 profile 字段,而不是原文整段存储。
衰减策略上,记忆需要有时效性和权重,短期热点信息可以高权重,但随着时间衰减;长期稳定偏好可以低频刷新但不轻易删除。
冲突消解上,一般要结合时间戳、来源可信度和置信度,新的高可信度事实覆盖旧事实,低可信内容作为候选
如何做并行 tool calling,既提升吞吐又保证一致性和可回放
并行 tool calling 的核心是要解决 tool 之间的依赖关系、状态一致性、结果合并和失败回滚。只有互不依赖的工具才能并行,比如天气查询和汇率查询可以一起发;如果后一个工具依赖前一个工具的结果,就必须串行
一致性上,一般不会让多个工具直接对共享状态进行修改,而是工具执行结果先写到临时观察区,再统一合并的方式
主流的 agent 设计
ReAct,边推理边行动,模型通过思考、调用工具、观察结果、继续思考完成任务。
Plan-and-Execute,先做规划,再按照步骤执行,适合长任务
Router,先做任务分类,再路由给不同的子 agent 或工具链。
Workflow + agent,固定流程里嵌局部的自主决策
supervisor,由主 agent 拆解任务并分派给多个子 agent
blackboard,多个 agent 通过共享状态协作
mcp、a2a、function calling 三者的本质区别是,工程里应该怎么选
function calling 是模型和宿主应用之间的一种单机式的工具调用协议,模型输出结构化的调用意图,宿主进程负责执行函数并把结果返回,重点在“模型怎么调用本地或受控工具”
mcp 更像标准化的上下文和工具保录协议,把资源、工具、提示模板等能力统一封装出来,解决的是“外部能力如何以标准方式被模型客户端发现和调用”
a2a 更偏 agent 和 agent 之间的协议,实现多个智能体之间如何交换任务、状态、结果
工程上,如果是单应用内工具调用,用 function calling 足够,如果要让多个模型共享一套工具和资源能力, 适用 mcp,如果还是多个 agent 分工协作,更适合 a2a
rag 接到 agent 中,一般怎么设计
rag 进入 agent 后,不应该只是固定的先查再答,而是应该作为一个决策节点。模型需要先判断这个问题是否真的需要外部知识,再决定 query rewrite、query decomposition、召回、rerank 和生成的顺序
比较常见的做法是把 rag 包装成一个工具,agent 自主决定何时调用
检索结果不要原封不动扔给模型,需要做去重、切片、排序(与 rag 中的 rerank 不同,如何组织材料,组织成 prompt)和来源标注(给 chunk 保留出处信息)
在 prompt 需要约束模型根据检索到的信息回答,没有证据就说不确定,降低幻觉
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15典型的 rag 流程:
用户问题
↓
判断是否需要 RAG
↓
query rewrite / query decomposition
↓
召回 retrieve
↓
rerank 重排序
↓
结果处理:去重、切片、排序、来源标注
↓
生成答案query rewrite
把信息改写成更适合检索的 query
query decomposition
如果一个问题很复杂,需要拆成多个子问题分别查询
retrieve / rerank
先查找一批最相关的 chunk,作为一个候选集,然后进行重新排序,确定相关性
tool calling 一般怎么做,和普通函数调用有什么区别
本质是模型决定调用意图,宿主系统决定能否执行。
普通函数调用是硬编码的,谁调用哪个函数,传什么参数由开发者控制,tool calling 是模型根据任务上下文自主输出工具名称和参数,要加一层校验和调度
工程上一般有四层:工具注册层、参数 schema 层、执行器层、审计日志层。模型只能输出候选调用,服务端要负责白名单校验、参数校验、超时控制、幂等控制和错误包装
agent 的 memory 一般怎么做
memory 通常分为短期记忆和长期记忆。长期记忆又可以分为情景记忆和语义记忆
短期记忆用于保留最近几轮对话和当前任务状态,保证会话连贯
长期记忆用于保存稳定事实,比如用户偏好、长期目标
在工程中一般不会把对话原文塞进上下文,而是保留最近 N 轮原文,再把更久远的内容压缩成 summary,同时抽取关键字段单独存储。按需召回
prompt injection 在 agent 场景中如何防范
prompt injection 是指把恶意指令混进用户输入或外部文档中,诱导模型忽略既定规则。agent 场景中更危险,不仅会生成错误文本,还可能误调工具、越权执行
需要分层防范。1️⃣角色和优先级隔离,外部知识不能覆盖系统规则。2️⃣把检索文档视为证据,不能视为命令。3️⃣所有工具调用都要白名单和参数校验,高风险操作需要显式确认。4️⃣输出和调用链路必须是可追踪的,可以排查问题。5️⃣可以做输入清洗和风险分类,对明显越权或诱导内容做拦截
如何评估一个 agent 系统的效果
评估不能只看回答像不像人,而是要看任务完成的情况。
1️⃣回答质量,比如说准确性、完整性、是否是基于证据的。2️⃣工具质量,选用的工具是否正确,参数是否正确,调用是否成功。3️⃣任务质量,一次对话能否完成目标,是否需要额外追问,是否需要人工接管。4️⃣系统质量,耗时、成本。
如果线上发现 agent 经常选错工具,如何排查
先看 tool description 和 schema 设计,边界是否模糊,参数能否区分场景
然后看 skill routing 层,是否一次性喂了过多的候选工具,造成竞争
再看 prompt 和 few-shot 是不是给了错误的引导
回放 trace,检查模型选工具前看到的上下文,历史记忆是否污染,输入是否有歧义
长任务场景中,怎么避免 agent 无限推理或者死循环
靠状态机和终止条件
实际系统中必须限制最大推理步数、最大工具调用次数、最大 token 开销和最大执行时长。
同时要定义清楚怎么样是完成、怎样是失败、什么情况需要让用户补充信息。
还可以添加重复动作检测,如果连续多步都在调用同一个工具、得到相似结果或者没有带来新证据,就应该强制终止并返回阶段性的结果。
字节 AI Infra 剪映面经(实习)
https://zhuanlan.zhihu.com/p/1977830568436729070
KV Cache 是什么
LLM 生成每个 token 时都要做 Attention。Attention 需要三个矩阵:Query、Key、Value,当前 token 前面的 t - 1 个 K 和 V 在上一步就已经计算完毕了。KV Cache的思路是将前面的 t 个 token存储起来。
缓存命中率
API 厂商在服务端做的优化。每次请求的 prompt 中都有重复的内容,这些内容在多次请求中是会重复的。厂商把这些前缀的信息存在服务器上,后续请求如果需要前缀匹配,直接从缓存中读取,不需要计算。
缓存命中的 token 按照低价计算,缓存未命中的按照标准价格,缓存命中率 = 命中 token 数量 / 总输入 token 数。
使用 api 做 agent 开发时,可以通过把 system prompt 写稳定的方法提高缓存命中率。
DPO 和 PPO 的区别
PPO 的思想是,有一个奖励模型 RM,利用强化学习让策略最大化奖励,同时通过 KL (散度,让模型在变得符合奖励模型偏好的同时,不要离原本的 SFT 模型太远)控制不偏离 SFT 模型太远。训练负责,需要 value function 和 critic 部分
DPO 的思想是不再训练奖励模型,而是直接基于偏好数据更新策略,把 chosen 应该比 rejected 概率大的偏好直接写进损失函数,训练链路更短,相比 PPO 更稳定
淘天 AI Agent 三轮面经
什么是 AI Agent?与传统 LLM API 调用有什么本质区别?
AI Agent 是一种以 LLM 为核心的自主任务执行系统,根据 prompt 生成文本,还能围绕目标进行任务分解、规划、工具调用、结果观察和多轮迭代。传统 LLM API 调用通常是一次性的输入输出,流程是硬编码的,而 Agent 更强调动态决策、状态维护和持续行动能力
什么是 Agent loop
AI Agent 反复进行思考、行动、观察、更新的循环机制
如何让 Agent 自动拆分任务
通常通过 planning 模块实现,模型根据用户目标生成一组有输入、输出和完整标准的子任务,Agent Loop 按顺序执行这些子任务。每一步执行后,系统观察结果、评估是否完成,并在必要时重新规划。
米哈游 agnet 应用算法实习一面
Agent 架构 & 系统设计类问题
Agent 和 workflow 的区别是什么?在什么场景下选择哪种?
agent 和 worflow 的区别主要在于自主性和流程确定性
workflow 是固定流程,开发者预先定义好每一步做什么,模型只是在某些节点完成指定任务,所以更稳定、可控,适合流程明确的场景,比如固定的 RAG、数据清晰、审批流
agent 是在给定目标、工具和约束的情况下,由模型自己判断下一步动作,比如是否检索、是否调用工具、是否拆分任务、是否继续执行。更适合开放式、路径不确定、需要动态规划的任务,例如复杂调研、代码修复、多工具任务执行等
企业级 agent 架构应该如何设计?安全与隔离应该怎么做?权限、审计、日志怎么做?
企业级 agent 一般会分为这几层:入口层负责接收请求和做风险判断;决策层负责规划任务和选择工具;工具层通过 API 或者 MCP server 访问业务系统;权限层负责教研用户和 agent 是否有权限执行这个操作;安全层负责沙箱、脱敏、租户隔离和工具白名单;审计层记录完整的请求、计划、工具调用、返回结果、异常和人工确认过程
安全上遵循最小权限原则。agent 不应该直接拥有数据库、邮件、代码仓库或生产系统的访问权限,应该通过受控工具进行访问,每个工具只开放必要能力。对于高风险操作,比如删除数据、修改配置,需要添加审批流或者人工操作
权限上可以结合 **RBAC 和 ABAC**。agent 只能在用户本身已有权限范围内执行,不饿那个绕过用户权限。审计上要记录每次调用的用户、时间、输入、工具、参数、输出、权限判断和最终结果,同时对敏感信息做脱敏和访问控制
RBAC(Role-Based Access Control):按照角色授权,比如普通员工、管理员、财务人员拥有不同工具权限。
ABAC(Attribute-Based Access Control):根据用户、资源、时间、任务类型、数据敏感级别等属性动态判断是否能够执行
Agent reasoning 指的是 agent 在完成任务时的动态决策过程,根据目标、上下文、历史状态和可用工具,判断下一步应该做什么
常见的 agent reasoning 方式
ReAct:Reason + Act 一边推理,一边调用工具,再根据工具结果继续推理。
Plan-and-Execute:先制定整体计划,再一步步执行。
Reflection: 执行后反思结果是否足够好,如果不好就修改或重试。
Tree-of-Thought / Search: 同时探索多条可能路径,再选择较优路径。
Multi-agent reasoning: 把任务拆给多个角色 agent,例如 researcher、coder、reviewer、manager。
MCP(Model Context Protocol)是什么?有哪些分类?MCP server 如何开发?Transport 层有哪些(SSE / Streamable HTTP / 其他)?为什么 MCP 这么重要?
MCP 是一种面向大模型应用的工具和上下文接入协议,统一了 agent 接入外部工具和上下文资源的方式
MCP 的核心架构由 Host、Client 和 Server 组成。Host 是运行大模型应用的宿主环境,比如 Claude Desktop、IDE 或 agent 平台,负责用户交互、模型调用和整体任务流程。Client 是 Host 内部负责链接 MCP Server 的组件,它负责发现 Server 能力、发送请求并接收结果。Server 是外部能力的提供方,会按照 MCP 协议暴露工具、资源和提示词模板
MCP Server 主要提供三个能力:tools、resources 和 prompts。Tools 是可调用的工具函数,例如查数据库、读文件、创建 issue;resources 是可读取的上下文资源,例如文档、日志、数据库记录;prompts 是预定义的提示词模板,用于封装常见任务
开发 MCP Server 的本质,是把一个外部系统封装成符合 MCP 协议的服务。开发者需要定义工具列表、输入输出 schema、资源读取方式、API 调用逻辑,以及权限控制、错误处理和安全边界
MCP 的 Transport 层负责 client 和 Server 之间的通信,常见方式包括 stdio、SSE 和 Steramable HTTP。stdio 适合本地工具,SSE 和 Streamable HTTP 更适合远程服务,其中 Streamable HTTP 更适合生产部署和标准 HTTP 基础设施集成
Claude code / CodeX / Manus 这类 agent 产品的理解与评价(架构逻辑 / 与传统 chat agent 的差别,工程能力如何实现)?
这类产品和传统 chat agent 的区别在于,chat agent 主要通过对话给出答案,而这类 agent 会围绕用户目标进行多步执行,包括理解任务、读取上下文、制定计划、调用工具、修改文件、运行命令、检查结果和继续迭代
从架构上看,通常由 LLM reasoning、上下文管理、工具调用、执行环境、验证机制、权限控制和日志审计组成。模型负责判断下一步做什么,工具系统负责访问文件、终端、浏览器或外部 API
以 cc 为例,它可以进入代码仓库,理解项目结构、定位文件、修改代码,运行测试,并根据报错修复。Manus 这类通用 agent 更强调任务执行,比如调研、网页操作、文档生成和流程自动化
agent research 方法论,deep research 要配备哪些工具?基础设施如何搭建?安全和基建的挑战是什么?
Agent research / deep research 不是简单让模型搜索网页,而是一套围绕研究目标进行规划、检索、阅读、证据抽取、交叉验证和报告生成的 agentic workflow。
方法论上,它通常包括:先理解用户研究目标和范围,再把大问题拆成多个子问题;然后进行多源检索,包括网页、论文、内部文档、数据库、GitHub 等;接着对资料进行阅读、切片、摘要和证据抽取;再对关键事实做来源评估和交叉验证;最后生成带引用、可追溯的研究报告。
工具上,deep research agent 需要配备搜索工具、浏览器、PDF / 文档解析、OCR、表格抽取、向量检索、reranker、代码执行、数据分析、引用管理和报告生成工具。如果是企业场景,还需要接入内部知识库、数据库、邮件、GitHub
基础设施上,可以分为入口层、规划层、检索层、文档处理层、证据管理层、推理综合层、验证层、输出层和审计监控层。核心不是一次性生成答案,而是维护一个可追踪的 research state,记录 agent 搜了什么、看了什么、采纳了哪些证据、为什么得出这个结论。
安全和基建挑战主要包括:信息来源不可靠、引用幻觉、上下文过长、资料过期、prompt injection、内部数据越权、工具滥用、成本过高和评估困难。解决方式包括权限控制、工具沙箱、外部内容隔离、敏感信息脱敏、人工确认、日志审计、引用校验、关键事实交叉验证和缓存机制。
所以 deep research agent 的关键能力不是“会搜索”,而是“能把搜索、阅读、验证、综合和引用变成一个可控、可审计、可复现的研究流程”。
多轮对话中的长短期记忆怎么做?Short-term memory 怎么实现?Long-term memory 怎么实现?Task memory 是什么?
多轮对话中的记忆可以分为短期记忆、长期记忆和任务记忆。
短期记忆是当前会话内的上下文,通常直接放在 prompt context 中,用来维持当前几轮对话的连续性。如果上下文过长,可以通过 sliding window 或 rolling summary 压缩,只保留当前任务相关的信息。
长期记忆是跨会话保存的信息,比如用户偏好、长期项目背景、常用写作风格、历史决策等。它通常会被结构化存储到数据库或向量库中,并在新对话中根据当前问题检索相关内容再注入上下文。长期记忆需要做去重、压缩、更新、过期处理和权限控制。
Task memory 是某个具体任务执行过程中的状态记忆。它记录 agent 已经做过哪些步骤、调用过哪些工具、得到过哪些中间结果、当前计划是什么、还有哪些待解决问题。它主要用于保证长任务执行的连续性,避免 agent 重复工作、忘记进度或丢失中间状态。
上下文机制的完整实现流程是什么?写入策略、读取策略、rerank 如何做?如何保证状态稳定?
上下文机制的完整实现不是把所有历史对话都塞进 prompt,而是一个动态的 context management 流程,包括写入、存储、读取、rerank、prompt 组装和状态更新。
写入策略上,需要判断哪些信息值得保存。通常会保存用户长期偏好、项目背景、用户确认过的事实、当前任务状态、工具调用结果、重要决策和待办事项。写入时要结构化,并区分事实、假设和计划,避免把模型猜测直接写成长期记忆。
读取策略上,每次模型调用前,系统会根据当前任务从不同记忆源召回相关信息,包括最近对话、长期记忆、任务记忆、文件内容和工具结果。不同任务读取的内容不同,比如代码任务更关注报错、文件和修改记录;研究任务更关注来源、证据和待验证结论。
Rerank 的作用是在召回到的候选上下文中选择最值得放进 prompt 的内容。因为上下文窗口有限,不能把所有信息都放进去,所以需要按相关性、新鲜度、可信度、用户确认程度、任务阶段匹配度和重要性重新排序。它解决的是“动态上下文太多时选什么”的问题,而 prompt caching 解决的是“稳定内容如何复用”的问题,两者不是一回事。
Prompt 组装时,一般会把稳定不变的 system prompt、工具说明、输出 schema、项目固定背景放在前面,有利于缓存命中;把当前用户请求、最近对话、检索出的动态上下文放在后面。这样既能保证稳定性,也能让模型看到最新信息。
为了保证状态稳定,需要维护结构化 task_state,而不是只依赖自然语言聊天记录。系统应当定期生成 checkpoint,使用 schema 约束模型输出,区分事实、假设和计划,让工具结果和用户确认信息优先于模型猜测,并在新旧状态冲突时进行冲突检测或人工确认。
所以完整的上下文机制可以概括为:写入时筛选和结构化,读取时按任务召回,rerank 时选择最相关证据,组装时区分稳定内容和动态内容,更新时通过 schema、checkpoint 和冲突检测保证状态不漂移。
超 token 怎么处理?Rolling summary、State extraction、RAG / Retrieval 三段式组合策略
超 token 后不能简单截断历史,而要做上下文压缩和分层管理。常见方法是 Rolling summary、State extraction 和 RAG / Retrieval 组合。
Rolling summary 用来压缩长对话历史,把早期多轮对话总结成持续更新的摘要,保留背景和关键决策。
State extraction 用来抽取结构化任务状态,例如当前目标、已完成步骤、待解决问题、关键变量、工具调用结果和下一步计划。它比普通摘要更稳定,可以防止 agent 在长任务中状态漂移。
RAG / Retrieval 则用于处理大量外部资料或历史记忆。系统不把所有文档、历史对话和知识都塞进 prompt,而是存到外部索引或向量库里,在当前问题需要时检索最相关片段,再放入上下文。
所以这三者的关系是:Rolling summary 压缩历史(压缩历史对话和背景),State extraction 稳定任务状态(维护当前任务的结构化状态),Retrieval 动态补充相关资料。它们共同解决超 token、上下文遗忘和状态漂移的问题。
Prefix caching / KV cache 原理,为什么存储的是 K / V,为什么 Q 不缓存,不再算前缀具体指什么,Attention 复杂度如何下降?
KV cache 是 Transformer 自回归生成中的一种缓存机制。模型在 attention 层会映射成 Q、K、V,其中 Q 表示当前 token 的查询,K 表示历史 token 可被匹配的索引特征,V 表示历史 token 携带的信息内容。
在生成新 token 时,当前 token 只需要用自己的 Q 去和所有历史 token 的 K 做匹配,然后根据 attention 权重读取历史 token 的 V。因此,历史 token 的 K 和 V 在后续生成中会反复被用到,而且它们不会变化,所以可以缓存下来,避免每一步都重新计算。
Q 通常不缓存,是因为历史 token 的 Q 对后续生成没有用。每一步生成时只需要当前新 token 的 Q,历史 token 已经不再作为查询者参与新的计算。换句话说,cache 的不是“方便读取的结构化信息”,而是 attention 中会被后续 token 反复访问的 K/V 中间结果。
所谓“不再算前缀”,指的是对已经处理过的 prompt、历史对话和已生成 token,不再重复计算它们在每一层中的 K/V 表示。模型只需要计算新 token 的 Q/K/V,并把新 token 的 K/V 追加到 cache 中。
从复杂度上看,第一次读取 prompt 的 prefill 阶段仍然需要处理完整上下文,attention 复杂度大约是 O(n²)。但在逐 token 生成的 decode 阶段,有 KV cache 后,每一步只需要让当前 token 的 Q 和历史 K/V 做 attention,单步复杂度大约从重新处理完整序列的 O(n²) 降到 O(n)。因此 KV cache 主要优化的是生成阶段的重复计算,而不是消除长上下文本身的注意力成本。
Prefix caching 可以看作 KV cache 在多请求场景下的复用。如果多个请求共享相同的 system prompt、工具说明或固定前缀,系统可以缓存这段前缀的 K/V。后续请求只要前缀完全匹配,就可以直接复用这部分 cache,减少 prefill 成本,提高吞吐和响应速度。
如何保证代码能够运行?
对于提交的代码,或者说生成的代码,无法保证它一定是能正确运行的,但可以通过标准化有运行环境、自动测试和沙箱机制,保证它在可控范围内被真实执行
系统通常会先根据语言选择固定版本的运行时镜像,然后为每次任务创建独立沙箱,把代码和输入写入临时工作目录,在沙箱中调用编辑器或解释器执行。执行过程中收集标准输出、错误输出、退出码、运行时间和内存占用,最后通过测试用例判断结果是否正确
沙箱的核心作用是隔离不可信代码,可以使用docker容器,也可以使用虚拟机或微虚拟机(vm),容器主要通过Linux namespace隔离进程、网络、用户和文件系统,通过Cgroups限制cpu、内存和进程数量,再配合seccomp、linux capabiities、只读文件系统和非root用户降低权限
资源限制需要覆盖多个维度,包括运行超时、cpu配额、内存上限、进程数、磁盘空间、文件描述符、输出大小和网络访问。超时后不能只杀父进程,而应终止整个进程组或直接销毁容器,避免子进程残留
普通 Docker 容器启动快、开销低,适合大多数在线判题和代码运行场景,但它与宿主机共享内核,安全要求很高时可以使用 VM、Firecracker、gVisor 或 Kata Containers 提升隔离强度。无论采用哪种方式,任务结束后都要销毁执行环境,避免文件、状态和进程在不同用户任务之间泄漏。
如何验证ai生成的代码是可以运行的
在 LLM 辅助编程环境中,不能把模型输出的代码当成正确代码,而应该把模型看作一个需要接受工具验证的代码生成器。
我会先采用 Spec-Driven Development 的思路,把自然语言需求转化成明确的接口、输入输出、异常行为、边界条件和验收标准,然后把需求拆分成小范围的 change 和 task,避免模型一次修改过多内容。
在实现阶段可以结合 TDD,先根据验收标准编写测试,并确认新测试在修改前确实失败,再让模型实现最小代码变更。生成代码后,需要实际在隔离环境中执行编译、静态检查、类型检查、单元测试、接口契约测试和集成测试,不能只由模型阅读代码后自我判断。
对 API 还要验证函数签名、参数类型、返回结构、状态码和 Schema 是否与定义一致;对性能则通过 benchmark 和资源监控验证,而不是只依赖模型分析时间复杂度。
最后还要检查 Git diff、执行完整回归测试,并限制模型不能删除测试、降低检查规则或者修改无关模块。对于高风险变更,测试通过后仍需要人工 review。
整体上,它是一个“规格化需求—小步生成—沙箱执行—测试反馈—自动修复—回归审核”的闭环。