第一轮面试官(技术负责人)
- RAG 召回效果排查与调优设计。
- LangGraph 的理解:谈谈你对 LangGraph 中 Human-in-the-Loop 的理解,以及如何支持重启和多端并发?
- SSE 流式乱序:在流式对话中,如何防止消息乱序?
- React Native 经验:是否有 React Native 相关项目落地?
- React 性能优化:复杂商城页面中,父组件筛选条件切换导致大量无关子组件重渲染,如何排查和解决?
- Next.js 实践:是否有真实的 Next.js 服务端渲染项目经验?
- Monorepo 工程化:谈谈你的见解,以及常见的目录结构(如 apps 、packages 等)分别放什么?
- AI 代码质量/幻觉控制:在 AI 辅助编程中,如何做工程化建设( Harness )来保证代码可靠且不上下文漂移?
- 上下文漂移的强制约束:如果老项目有自己的规范,如何强制或软约束 AI 遵循当前项目规范,而非全局通用规则?
- AI 编程工具钩子:对 Cursor 或 Cline 的生命周期钩子( Hooks )了解多少?
第二轮面试官(同事/交叉面)
- 多工具规范复用:多套 AI 工具( Cursor/Cloud 等)如何共用同一套编码规范( Skill/MDC )?
- 组件库自动提取 Skill:你提到的组件库自动提取上传 Skill ,具体流程是怎样的?
- 文档投喂方式:拉取文档喂给大模型,是通过 MCP 还是 Skill 直接读文件?
- Agent 对接 MCP/Skill:Agent 中如何配置和对接 MCP 与 Skill 功能?
- MCP 传输模式:你们支持 MCP 的 SSE ( HTTP )模式还是 STDIO (本地进程)模式?为什么?
- Agent 拓展 Skill 槽位:如果现在要给 Agent 增加 Skill 配置能力,你觉得应该怎么设计拓展槽?
- MCP 配置界面:你们的系统是否有供用户自定义配置 MCP 的可视化界面?
- 大数据量处理:如果 MCP 一次返回 1 万条数据,Agent 侧如何处理和截断?
- 多 Agent 通信:是否涉及 Sub-agent 或多 Agent 之间的通信(图编排)场景?
- Copilot Kit 选型:为什么选 Copilot Kit 来做 Human-in-the-Loop ?它解决了哪些特定痛点?
- 当前开发工作流:你提到用 Superpower + OpenSpec ,具体配合流程是怎样的?
- Spec 文件管理:AI 生成的 Spec (规格说明)文档是和仓库一起管理吗?如果生成结果不满意,文件是删掉还是保留?
AI解答-kimi2.7
1. RAG 召回效果排查与调优设计
排查召回效果应建立“检索漏斗 + 人工标注”的闭环:
- 指标体系:Top-K 召回率、MRR、NDCG,结合人工标注判断“相关片段”是否被召回。
- Badcase 归类:将失败样本分为 query 理解偏差、chunk 切分过碎/过长、embedding 语义漂移、文档本身缺失、排序靠后等类型。
- Query 侧优化:
- 查询重写(Query Rewriting):补全指代、扩展同义词、纠错。
- 查询分解(Decomposition):复杂多条件问题拆成子查询。
- HyDE:用 LLM 生成假设答案再检索。
- 索引侧优化:
- 分块策略:按语义/段落/固定长度 + overlap,尝试 256/512/1024 对比实验。
- 文本清洗:去页眉页脚、表格还原、OCR 后处理。
- Metadata:给 chunk 打标签(章节、版本、产品、时间),检索时先过滤。
- 召回策略:向量 + 关键词(BM25/TF-IDF)混合召回,多路召回后做 Rerank(交叉编码器 ColBERT/BGE-Rerank)。
- 反馈闭环:线上收集用户点赞/点踩,定期回流到训练或 Rerank 微调。
2. LangGraph 中 Human-in-the-Loop 的理解,以及如何支持重启和多端并发?
LangGraph 的 HITL 核心依赖 Checkpoint(检查点)+ Interrupt(中断):
- 中断节点:在需要人工确认的步骤调用
interrupt(),工作流挂起并把当前状态持久化到 checkpoint store(如 Redis/Postgres/SQLite)。 - 恢复执行:用户确认后调用
graph.invoke(None, config),LangGraph 从 checkpoint 恢复状态继续下游节点。 - 重启:因为状态已持久化,只要
thread_id/checkpoint_id不变,即使服务重启也能从断点继续。 - 多端并发:每条对话/流程使用独立的
thread_id作为隔离键;并发请求分别走不同 thread,互不影响。若需多端同步同一会话,后端以 thread_id 为 key 读写 checkpoint,前端轮询或 SSE 拉取最新状态。
3. SSE 流式乱序:在流式对话中,如何防止消息乱序?
SSE 本身按建立连接顺序推送,乱序通常出现在“多轮并发请求”或“前端异步处理”场景:
- 消息 ID / sequence:后端为每个 chunk 生成单调递增
seq或message_id,前端用优先队列暂存,按 seq 排序后再渲染。 - 请求串行化:同一对话会话内,一次只处理一个 LLM 请求,后续请求入队或取消前一条。
- Promise 链 / 锁:前端用异步锁(如
p-queue)保证上一条流式响应结束后再发下一条。 - 时间戳兜底:服务端在 chunk 里带
created_at,前端做最终排序校准。 - 取消竞态:新请求发出时 abort 旧请求的 EventSource,避免旧流数据混入新消息。
4. React Native 经验:是否有 React Native 相关项目落地?
若有实际项目,可从以下角度描述:
- 项目背景:如电商 App、企业办公 App、小程序容器等,说明负责模块(首页、支付、IM、地图)。
- 技术栈:React Native + Expo / 原生混合开发,使用 React Navigation、Redux/Zustand、Reanimated、MMKV。
- 性能优化:Hermes 引擎、Bundle 拆分、原生模块桥接、图片缓存与懒加载、启动耗时治理。
- 落地难点:iOS/Android 双端差异、键盘适配、原生能力集成、热更新(CodePush/OTA)。
- 成果:如一套代码双端覆盖 90% 业务、迭代周期缩短、崩溃率降低。
若暂无真实落地,可说明“有一定调研/ demo 经验”,并强调对跨端原理(JS Bridge、Fabric/TurboModules 新架构)的理解。
5. React 性能优化:复杂商城页面中,父组件筛选条件切换导致大量无关子组件重渲染,如何排查和解决?
排查:
- React DevTools Profiler 查看渲染火焰图,定位高频渲染组件。
- 检查 state 提升是否过度,导致无关子树随父组件刷新。
解决:
- 组件拆分:把筛选条件、商品列表、侧边栏等拆成独立子树,减少影响范围。
- 记忆化:
React.memo包装展示型子组件。useMemo缓存计算结果,useCallback缓存事件处理函数并稳定子组件 props。
- Context 拆分:避免一个 Context 承载所有状态;按关注点拆成多个 Provider,或使用状态管理库(Zustand、Jotai、Redux Toolkit)。
- Selector 模式:子组件只订阅自己关心的最小状态片段。
- 虚拟滚动:商品列表用
react-window/react-virtualized只渲染视口内节点。 - 防抖节流:筛选条件输入用 debounce,减少请求与渲染频次。
6. Next.js 实践:是否有真实的 Next.js 服务端渲染项目经验?
可从以下维度回答:
- 渲染策略:SSR(getServerSideProps / Server Components)、SSG(getStaticProps + ISR 增量再生成)、Client Components 边界划分。
- 数据获取:Server Component 直接 fetch(带缓存控制),Client Component 用 SWR/React Query。
- 性能优化:Image/Script 组件、路由分割、Streaming SSR、
loading.js、Partial Prerendering(PPR)。 - 部署运维:Vercel / Docker 自托管、Edge Runtime、Middleware 鉴权、日志与监控。
- 项目经验:如内容站点、电商平台、B 端后台,重点说明如何解决首屏、SEO、 hydration 错误等问题。
7. Monorepo 工程化:谈谈你的见解,以及常见的目录结构(如 apps 、packages 等)分别放什么?
见解:Monorepo 适合多应用、多包共享代码的场景,优势是统一依赖、原子提交、共享工具链;劣势是构建体积大、权限管理复杂,需要任务调度与缓存(Turborepo / Nx / Rush)。
目录结构示例:
1 | my-org/ |
apps:面向用户的可运行产物,有独立部署单元。packages:被 apps 依赖的复用模块,通常不直接部署。- 工具配置也作为 package 共享,保证全仓库一致性。
8. AI 代码质量/幻觉控制:在 AI 辅助编程中,如何做工程化建设(Harness)来保证代码可靠且不上下文漂移?
Harness 思路:把 AI 生成结果纳入 CI/CD 与人工 Review 双重校验:
- Spec 先行:让 AI 先写需求/设计文档(Spec),人审通过后再生成代码。
- 受限上下文:通过 RAG 只召回当前项目相关文档、接口、组件示例,避免全局泛泛规则。
- 自动化验证:
- 单元测试 / 集成测试必须跑通。
- TypeScript 类型检查、ESLint、Prettier 零报错。
- 安全扫描(SAST)、依赖审计。
- 黄金用例集(Golden Dataset):对高频任务准备标准输入输出,AI 改动后跑回归。
- Diff Review:要求 AI 只输出变更 diff,人工聚焦 review;大改动拆分为多个小 PR。
- 可观测性:记录 AI 生成的代码、Prompt、上下文版本,便于回溯幻觉根因。
- 人在回路:关键模块(支付、权限、核心算法)必须人工最终确认。
9. 上下文漂移的强制约束:如果老项目有自己的规范,如何强制或软约束 AI 遵循当前项目规范,而非全局通用规则?
强制约束:
- 项目根目录放置
CLAUDE.md/.cursorrules/copilot-instructions.md,写明:技术栈、目录约定、命名规范、禁用 API、必须使用的工具函数。 - Prompt 里强制要求 AI “只能参考项目内已有代码风格,不得引入全局假设”。
- CI 中加入 lint、format、架构规则检查(如 dependency-cruiser、custom ESLint rules),不合规即阻断合并。
软约束:
- 提供“项目范例库”:把优质代码片段、典型组件、错误处理模式写入 Skill / MDC 文件,随 Prompt 注入。
- 在 AI 工具中配置 “rules for AI”,让其在生成前检索项目规范。
- 定期做 Code Review 反馈,把共性问题沉淀为新的规则文件,形成迭代。
10. AI 编程工具钩子:对 Cursor 或 Cline 的生命周期钩子(Hooks)了解多少?
- Cursor:主要通过
.cursorrules文件和 Settings 中的 Rules for AI 注入系统/项目级指令。Cursor 的“钩子”更多是隐式的:模型在生成代码前会读取.cursorrules,生成后可通过Apply应用到文件。Cursor 也支持 MCP Servers 扩展工具能力。 - Cline:支持更明确的系统提示、自定义指令、MCP Tool 调用;可在
cline_mcp_settings.json中配置 MCP,Cline 在规划阶段调用工具,执行阶段写文件/运行命令。 - 生命周期大致阶段:Plan(读取规则/上下文)→ 生成代码/调用工具 → Apply/Diff → 运行验证命令 → 反馈修正。钩子能力目前主要依赖工具本身的 Rules、MCP、slash commands 实现,尚未像传统框架那样开放完整的 pre/post 代码钩子。
11. 多工具规范复用:多套 AI 工具(Cursor/Cloud 等)如何共用同一套编码规范(Skill/MDC)?
- 规范即代码:把编码规范写成 Markdown / MDC 文件,存放到独立 Git 仓库或 Monorepo 的
packages/ai-rules/里。 - 统一格式:使用各工具都认识的格式——Markdown 文本 + 前置元数据(如 MDC 的
--- description, globs ---)。 - 分发方式:
- Git submodule / symlink 链接到各工具的配置目录(
.cursorrules、Claude 项目根目录、Cline custom instructions)。 - 通过内部 npm/private registry 发布规范包,安装后复制到对应位置。
- 云侧 Agent 启动时从统一 URL/Git 拉取最新规范。
- Git submodule / symlink 链接到各工具的配置目录(
- 版本管理:规范仓库打 tag,各 AI 工具引用固定版本,避免规则漂移;关键变更走 PR Review。
- 抽象层:如果工具差异大,可维护一份“规范源文件”+ 各工具的“适配器模板”,通过脚本生成最终配置。
12. 组件库自动提取 Skill:你提到的组件库自动提取上传 Skill ,具体流程是怎样的?
- 源码解析:用 AST(Babel / TypeScript Compiler API / @babel/parser)遍历组件文件,提取:组件名、Props 类型、默认值、事件、Slots(Vue)/ children 结构。
- 文档抽取:解析 JSDoc / TSDoc、Storybook stories、README 示例代码。
- 生成描述:将 Props 表格、使用示例、最佳实践格式化为 Markdown 或 MDC。
- 向量化(可选):把组件描述和示例 embedding 后存入向量库,供 Agent 检索。
- 打包 Skill:按目标 AI 工具格式输出为
.mdc/.md文件,包含globs匹配规则(如src/components/Button/**/*)。 - 上传/同步:
- 提交到规范仓库。
- 通过 API 推送到 Cursor Cloud / Claude Projects / 内部 Agent 的 Skill Registry。
- CI 中组件库发版后自动触发同步。
13. 文档投喂方式:拉取文档喂给大模型,是通过 MCP 还是 Skill 直接读文件?
两种方式的取舍:
- Skill / 直接读文件:
- 优点:实现简单、延迟低、一次加载完整上下文。
- 缺点:文档更新后需手动同步;超大文档容易超 token;权限控制弱。
- 适合:规范文件、项目 README、固定组件示例等体量较小的知识。
- MCP 读取文档(RAG/检索):
- 优点:动态检索、可按需召回、支持大规模文档库、更新实时。
- 缺点:需要构建检索服务、召回质量依赖 embedding 与分块。
- 适合:大型产品文档、知识库、频繁更新的 API 文档。
建议混合:静态规范用 Skill 直接注入;动态/海量文档用 MCP + RAG 检索,Agent 根据问题自动选择调用。
14. Agent 中如何配置和对接 MCP 与 Skill 功能?
- MCP 对接:
- 在 Agent 配置文件中声明 MCP Servers(
mcpServers),包含名称、传输方式(stdio/sse)、命令/URL、环境变量、权限范围。 - Agent 初始化时建立连接,拉取可用 tools 列表。
- 执行阶段,LLM 根据用户意图决定调用哪个 MCP tool,Agent 负责序列化参数、调用、解析结果、继续推理。
- 在 Agent 配置文件中声明 MCP Servers(
- Skill 对接:
- Skill 通常以 Markdown / MDC 文件形式存在,Agent 启动时加载到 system prompt 或上下文中。
- 根据用户当前任务匹配 Skill(按 globs 或语义相似度),把对应规则注入 prompt。
- 统一配置层:
- 设计一个 Agent Profile / Preset,里面列出启用的 MCP Servers、Skills、模型参数、输出格式要求。
- 运行时可切换 Profile,实现“不同场景用不同工具集”。
15. MCP 传输模式:你们支持 MCP 的 SSE(HTTP)模式还是 STDIO(本地进程)模式?为什么?
STDIO 模式:Agent 与本地子进程通过标准输入输出通信。
- 优点:部署简单、延迟低、适合本地工具/CLI;天然隔离进程。
- 缺点:只能跑在同一台机器,跨网络受限;需要管理进程生命周期。
- 适用:本地开发环境、敏感数据不出本机、快速集成脚本。
SSE(HTTP)模式:通过 HTTP SSE 流远程连接 MCP Server。
- 优点:可跨网络、可部署为服务、支持多客户端并发、便于扩缩容。
- 缺点:需要网络与鉴权、延迟略高于 STDIO、运维复杂。
- 适用:SaaS 平台、多租户、Serverless、需要集中管理工具的服务端 Agent。
选型建议:本地优先或数据敏感用 STDIO;需要多端共享、远程服务化用 SSE。也可以同时支持,由配置决定。
16. Agent 拓展 Skill 槽位:如果现在要给 Agent 增加 Skill 配置能力,你觉得应该怎么设计拓展槽?
- Skill Manifest 格式:每个 Skill 一个
skill.json或 MDC 文件头,声明:name、version、description、globs(生效文件范围)、triggers(触发关键词)、priority。
- 注册/发现机制:
- 本地文件系统扫描指定目录(如
.skills/)。 - 远程 Skill Store 通过 API 拉取。
- 允许用户/管理员在 Agent 配置里启用/禁用某个 Skill。
- 本地文件系统扫描指定目录(如
- 加载策略:
- 静态加载:启动时全部读入内存。
- 动态加载:根据当前任务和文件路径,按 globs/triggers 匹配后注入上下文。
- 槽位接口:定义
SkillLoader接口,支持load()、unload()、match(context),方便后续接入不同来源的 Skill。 - 版本与依赖:Skill 可声明依赖其他 Skill 或 MCP Server,Agent 初始化时校验并自动安装/提示。
- 可视化配置:在设置页提供 Skill 市场/列表,支持开关、优先级拖拽、自定义规则覆盖。
17. MCP 配置界面:你们的系统是否有供用户自定义配置 MCP 的可视化界面?
若有,可描述:
- 表单配置:Server 名称、传输方式(STDIO/SSE)、启动命令/URL、环境变量、超时、权限范围。
- 校验与测试:保存前连通性测试,返回可用 tools 列表。
- 权限模型:普通用户只能使用系统预置 MCP,高级用户/管理员可新增私有 MCP。
- 版本管理:配置以 JSON/YAML 存到用户目录或数据库,支持导入导出。
若无,可说明当前通过配置文件/代码硬编码,并给出建设方向:先提供 JSON 配置化,再逐步做 UI 封装,降低非技术用户门槛。
18. 大数据量处理:如果 MCP 一次返回 1 万条数据,Agent 侧如何处理和截断?
- 源头控制:优先让 MCP Server 支持分页(offset/limit/cursor)和过滤条件,避免一次性返回全量。
- 流式处理:若必须全量,使用流式传输,Agent 边读边处理,不全部驻留内存。
- 截断策略:
- 按 Token 截断:只保留前 N token(如 8K/16K/32K)。
- 按条数截断:取 Top-K,并在提示中说明“结果已截断,共 N 条”。
- 按相关性截断:若有排序分数,保留分数阈值以上数据。
- 聚合摘要:对列表做分组统计、生成摘要,而非把每条原始记录喂给 LLM。
- 二次检索:让 LLM 生成更精确的过滤条件,再次调用 MCP 缩小范围。
- 用户确认:截断前提示用户数据量过大,询问是否继续或细化条件。
19. 多 Agent 通信:是否涉及 Sub-agent 或多 Agent 之间的通信(图编排)场景?
可结合项目经验说明:
- Sub-agent 模式:主 Agent 把任务拆给子 Agent,子 Agent 完成专项任务(如代码生成、测试生成、文档生成)后返回结果,主 Agent 汇总。
- 图编排(LangGraph / CrewAI / AutoGen):用有向图定义 Agent 节点与边,节点负责不同角色(规划、执行、验证、审批),边决定流转条件。
- 通信方式:
- 共享状态(Shared State):各 Agent 读写同一份状态对象。
- 消息总线:Pub/Sub 或队列,Agent 订阅自己关心的事件。
- 直接调用:父 Agent 显式调用子 Agent 的接口。
- 适用场景:复杂工作流(如自动修复 Bug:分析 → 改代码 → 跑测试 → Code Review → 合并),需要多个角色协作与审批。
20. Copilot Kit 选型:为什么选 Copilot Kit 来做 Human-in-the-Loop?它解决了哪些特定痛点?
Copilot Kit 的优势:
- 现成 UI 组件:提供 Chat UI、Suggestion、Textarea Autocomplete 等 React 组件,减少自研前端成本。
- HITL 原生支持:内置
useCopilotAction/renderAndWaitForResponse等 API,可轻松在 AI 工作流中插入人工确认节点。 - 与 LangChain/LangGraph 集成:可直接对接 LangGraph 的 checkpoint 与 interrupt,后端状态管理无需重复开发。
- 前后端状态同步:Copilot Runtime 负责协调 LLM、前端 UI、后端 Agent 之间的状态,降低多端一致性难度。
- 解决的痛点:
- 自己搭建 HITL 需要写大量 UI + 状态持久化代码。
- LLM 流式输出与前端的绑定繁琐。
- 人工审批与自动流程的衔接复杂。
21. 当前开发工作流:你提到用 Superpower + OpenSpec ,具体配合流程是怎样的?
Superpower + OpenSpec 工作流 是一种“规格驱动、AI 辅助实现”的流程:
- 需求输入:把产品需求、接口定义、设计稿喂给 AI。
- 生成 Spec(OpenSpec):AI 输出结构化的规格文档,包括:功能范围、接口契约、数据模型、错误码、验收标准、任务拆分。
- 人工 Review Spec:确认无歧义后锁定 Spec,作为后续实现的“合同”。
- AI 按 Spec 生成代码:基于 Spec 和项目规范(Skill/MDC)生成实现、测试、文档。
- 自动化验证:跑测试、类型检查、Lint,确保符合 Spec。
- 迭代更新:若需求变更,先改 Spec,再同步代码;保证 Spec 与实现一致。
价值:降低 AI 自由发挥导致的幻觉,让“想清楚”先于“写代码”,便于团队协作与验收。
22. Spec 文件管理:AI 生成的 Spec(规格说明)文档是和仓库一起管理吗?如果生成结果不满意,文件是删掉还是保留?
管理方式:
- 与仓库一起管理:Spec 文件(Markdown / YAML / JSON)应纳入版本控制,放在
docs/specs/或specs/目录,与代码同仓库,方便 PR 时一起 Review。 - 命名规范:按日期或功能命名,如
spec-2026-07-21-user-auth.md或features/user-auth/spec.md。
不满意时的处理:
- 不要直接删除:保留不满意版本,便于回溯 AI 为什么走偏、对比迭代过程。
- 分支/草稿机制:
- 用
spec/draft/放初稿,评审通过后移到spec/final/。 - 或在 Git 分支上迭代,满意后再合并。
- 用
- 归档策略:定期把废弃 Spec 移到
spec/archive/,避免干扰主目录,但仍可审计。 - 反馈沉淀:把生成失败的原因总结成 Prompt 改进点或规则,减少下次再犯。
AI解答-Hy3
1. RAG 召回效果排查与调优设计
排查路径(先量化再动手)
- 建立标注评估集(query + 期望命中 doc id),用 Hit Rate@k、MRR、NDCG 量化”召回率”与”排序质量”,而不是凭感觉调。
- 分层定位:先区分是”没召回出来”(召回阶段问题)还是”召回了但排后面/被截断”(排序/截断问题)。
- 召回阶段检查:embedding 模型是否适配领域(通用 bge-large 在垂直语料上可能不够)、chunk 切分是否把答案切断、metadata 过滤是否把正确文档误杀。
- 排序阶段检查:是否缺 rerank、top_k 是否过小、score threshold 是否误杀。
调优手段(按性价比排序)
- 切分策略实验:固定大小 vs 语义切分(按标题/段落),调整 chunk_size 与 overlap,避免跨段切断语义。
- 混合检索(Hybrid):向量召回 + BM25 关键词召回做 reciprocal rank fusion,弥补向量对专名/编号不敏感。
- Query 侧增强:query rewrite / 多查询扩展(multi-query)、HyDE(用假设答案去检索)、问题分类路由到不同索引。
- 召回后重排:接入 bge-reranker / Cohere rerank,先召回 top-20 再 rerank 取 top-5,精度显著提升。
- Metadata 过滤与路由:用结构化字段(时间、来源、权限)先做硬过滤,缩小召回空间。
- 闭环评估:用 Ragas / 自建 eval 跑回归,每次改动都有指标对比,防止”越调越差”。
2. LangGraph 的 Human-in-the-Loop、重启与多端并发
HITL 的本质
LangGraph 的 HITL 建立在 checkpoint(检查点)机制上。图在节点之间可设 interrupt_before / interrupt_after(或 Node.interrupt()),执行到断点时把当前状态写入 checkpointer 并暂停,等待人工输入(approve / edit / 提供字段)后通过 graph.ainvoke(input, config) 带着同一 thread_id 恢复。
重启(resume / replay)
- 状态全部持久化到 checkpointer(MemorySaver 仅内存,Sqlite/Postgres 可跨进程)。
- 通过
thread_id唯一定位对话;checkpoint_ns+checkpoint_id可精确到某次快照,支持从任意历史 checkpoint replay 或 fork(复制状态开新分支)。 - 进程崩溃后只要 checkpointer 在外部存储,重启服务即可用同一 thread_id 续跑,不会丢失进度。
多端并发
- 会话隔离靠
thread_id:每个用户/会话一个 thread_id,checkpointer 后端需支持并发写入(Postgres + 行锁 / 分布式锁),避免两个端同时写同一会话。 - 无状态服务化:把 graph 执行做成无状态 worker,checkpoint 放 PG/Redis,前端通过 thread_id 拉取状态;状态变更用 WebSocket / SSE 广播给所有在线端,实现”一端操作、多端同步”。
- 水平扩展:worker 可多实例,因为状态不在内存里,天然支持多端、多实例。
3. SSE 流式乱序的防止
SSE 底层是单条 TCP 长连接,HTTP/2 下同一流内帧是严格有序的,所以”纯文本 token 流”本身不会乱序。乱序几乎都来自应用层并发写或多路聚合:
- 单一模型 token 流:server 只用一个 writer 顺序
write(delta),client 顺序append,天然有序,无需序号。 - 多工具/多 Agent 并行结果回传:这是乱序主因。解决:
- 消息级 buffer:每条消息带
message_id,并行流各自写入对应 buffer,互不覆盖; - 序列号:每个 chunk 带
index,client 收到先入队,按 seq 重排补齐后再上屏; - 占位符回填:先下发带 id 的占位块(如”正在调用搜索…”),工具结果回来后按 id 填充,避免顺序依赖;
- 服务端串行化:对非顺序不敏感的输出用单写队列(asyncio.Queue)汇总,保证写出顺序。
- 消息级 buffer:每条消息带
- 多模态分块(文字 + 图片 URL):同样用 message_id + 类型标记,client 按结构组装而非按到达顺序。
核心原则:顺序由”消息 id + 序列号”在客户端重组,服务端避免多个生产者直接抢同一连接。
4. React Native 落地经验
(按真实项目情况填写;以下为落地时涉及的关键点,可据实裁剪)
真实 RN 项目的几个硬骨头我都处理过:
- 新架构(Fabric + JSI + TurboModules):老架构靠 Bridge 异步序列化,UI 卡顿;迁移到新架构后,JS 通过 JSI 直接调 Native,同步通信,长列表和动画明显变顺。
- 原生模块与三方 SDK 集成:支付、推送、埋点、蓝牙等需写 Native Module,跨 iOS/Android 双端对齐接口;用 TurboModules 做类型安全的原生桥。
- 性能:FlatList/FlashList 虚拟化长列表、图片懒加载与缓存、避免 JS→Native 频繁跨桥;用 Hermes 引擎降内存、提启动速度。
- 热更新:CodePush / Expo EAS Update 做 OTA,紧急修复不发版。
- 工程化:Monorepo 下 RN app 与共享 business logic(packages)共用,统一 lint/type/test;CI 用 Fastlane 出包。
- 状态管理用 Redux Toolkit / Zustand,按 feature 切片避免大 store 重渲染。
(若实际无 RN 项目,可如实说明并切换到”我对 RN 架构的理解是…”,避免编造。)
5. React 性能优化:父组件筛选条件切换导致大量无关子组件重渲染
排查
- React DevTools → Profiler 录制,看哪些组件”不必要地” re-render(高亮提交)。
- 接入
why-did-you-render打印每次重渲染的原因(props 引用变了?context 变了?)。 - 常见误判:以为
React.memo包了就安全,结果父组件传了内联函数/新对象导致 memo 失效。
解决(按根因)
- 状态下沉 / 切片:把筛选条件 state 从顶层父组件下移到真正消费它的子组件,或用多个独立 Context(ThemeContext / FilterContext),避免一个 context 变全部订阅者重渲染。
- 原子化状态:用 Jotai / Zustand,每个筛选维度是一个 atom/store,只有订阅该 atom 的组件才更新,与”无关子组件”彻底解耦。
- 稳定引用:
useCallback包回调、useMemo包对象/数组,配合React.memo才有意义。 - 选择器模式:
useSelector(state => state.x, shallowEqual),只取自己需要的片段,相等则不重渲染。 - 并发特性:非紧急的筛选结果用
useTransition/useDeferredValue,让输入流畅、列表更新不阻塞交互。 - 虚拟化:结果列表用
react-window/react-virtuoso,只渲染可视区。 - key 策略:列表用稳定业务 id 作 key,避免重建 DOM。
6. Next.js 服务端渲染真实项目经验
做过生产级 Next.js 项目,关键实践:
- 渲染策略选择:营销/SEO 页用 SSG/ISR(定时再生成),个性化页用 SSR/CSR 混合;App Router 下用 RSC 减少 client bundle。
- App Router + RSC:server component 直接读 DB / 调内部服务,不把敏感配置打到前端;client component 只包交互部分。
- 数据获取与流式:RSC 内
async/await取数 +<Suspense>流式渲染,骨架屏优先出水,提升首屏感知。 - 缓存与性能:合理用
fetch的revalidate、Route Segment Config(revalidate/dynamic);用 next/font、图片优化、边缘函数降延迟。 - SEO/元信息:
generateMetadata动态 title/OG,sitemap/robots。 - 部署:Vercel 与自托管(Docker + standalone 输出)都跑过;CI 做 build/lint/typecheck 门禁。
- 可观测:集成 Sentry/日志,监控 RSC 报错与慢接口。
7. Monorepo 工程化与目录结构
工具选型:pnpm workspace(快、省磁盘、严格依赖隔离)+ Turborepo / Nx(任务编排 + 远程缓存)。
典型结构
1 | apps/ # 可独立部署的应用 |
收益与坑:依赖提升(hoist)冲突(用 pnpm 的 strict + onlyBuiltDependencies 解决);Turborepo 按 DAG 并行 build、缓存命中跳过重复;CI 按 affected 只测改动包;共享 config 一处改全局生效,但需防止”误伤”其他包。
8. AI 代码质量 / 幻觉控制的工程化(Harness)
Harness = 把”让 AI 写出可靠代码”变成可复用的脚手架与门禁,而非靠 prompt 祈祷:
- 契约先行:先有 spec / 接口类型 / 测试样例,AI 按契约实现,而不是自由发挥。
- 强类型 + 严格 lint/format:生成的代码必须过
tsc --noEmit、ESLint、Prettier,编译不过不让合并。 - 引用可达性校验:静态分析确保 AI 调用的函数/类型/导入在仓库内真实存在,禁止编造 API(如不存在的 NPM 包、错的方法名)。
- 自动验证闭环:生成后自动跑
test + lint + typecheck + build,全绿才提交;失败把报错回喂给 AI 自修(有限次数)。 - 结构化输出 + schema 校验:需要 JSON/字段时强制 schema 校验(zod),防止格式漂移。
- 检索约束:只允许引用仓库内已有符号 / 文档,RAG 给”真依据”,减少凭空生成。
- 人工 gate + 审计:关键改动需人 review;每次 AI 改动留 trace(哪个 prompt、哪个工具、改了什么),可审计可回滚。
- 回归 eval:对已知易错点建 eval 用例,每次模型/规则升级跑回归,防退化。
9. 上下文漂移的强制约束(老项目规范)
软约束(提示层)
- 项目根放
AGENTS.md/CLAUDE.md/.cursorrules/.clinerules,写明命名、目录、import 顺序、禁用写法;AI 启动时注入。 - 把规范拆成多条可检索的规则(如
.cursor/rules/*.mdc),按需命中注入,避免一次性塞爆上下文。
强制(执行层,关键是把”规范”变成”可执行规则”)
- 规范编译成 ESLint / Biome 规则(命名、目录约束、禁止
any、import 顺序),AI 生成后自动 lint,违反即报错不可合并。 tsc严格模式 +pre-commithook(Husky + lint-staged)拦在提交前。- CI 门禁:类型检查、测试、规范扫描全部过才允许 merge。
- 优先级:项目级规则覆盖全局规则——在 prompt/配置里明确”项目规则优先于通用默认”,MCP 提供”查询本项目规范”工具,让 AI 主动对齐当前仓库而非套用全局偏好。
- 把历史代码风格做成可学习样本(few-shot),AI 模仿既有文件而非引入新风格。
10. AI 编程工具生命周期 Hooks(Cursor / Cline)
两类工具都有 hook 机制,在工具调用生命周期的节点插入自定义脚本:
- 常见钩子点:
PreToolUse(工具执行前,可拦截/拒绝)、PostToolUse(执行后)、UserPromptSubmit(用户提交前,可改写/附加上下文)、Notification、Stop(一轮结束)、SubagentStop。 - 典型用途:
PreToolUse拦危险命令(如rm -rf、推送到主分支)、限制只改白名单目录;PostToolUse自动lint/format/ 跑单测,把结果回注;UserPromptSubmit自动附加项目规范、注入相关文件上下文;Stop自动生成改动摘要 / 写 commit message / 触发审计日志。
- 配置:Cursor 在
settings.json的hooks字段按event+matcher(匹配工具名/命令)注册 shell 命令;Cline 有类似 hooks 配置。 - 价值:把”可靠编码”从”AI 自觉”变成”系统强制”,是 Harness 的关键一环。
11. 多工具共用同一套编码规范(Skill / MDC)
核心思想:规范只写一份”真源”(canonical),各工具按需生成自己的消费格式。
- 真源放在仓库根的
AGENTS.md+ 一份结构化规范(Markdown / YAML),涵盖命名、目录、lint、禁用项。 - 用一个生成脚本(CI 或 pre-commit)把真源转成各工具格式:
- Cursor:
.cursorrules或.cursor/rules/*.mdc - Cline / WindSurf:
.clinerules/.windsurfrules - GitHub Copilot:
.github/copilot-instructions.md - Claude Code:
CLAUDE.md
- Cursor:
- 这样改一处、全工具同步,杜绝”Cursor 一套、Cline 一套”的漂移。
- Skill 也可作为跨工具载体:把可复用流程(如”加一个新 API”)写成 Skill,各工具都能加载。
12. 组件库自动提取 Skill 的流程
目标:让 AI 自动知道”项目里有哪些组件、怎么用”,而不是靠人写文档。
- 扫描解析:CI 里用 AST(TS compiler API / ts-morph)扫
packages/ui,提取每个组件的导出名、props(含类型与默认值)、文件路径、是否 deprecated。 - 抽取示例:从组件目录的
*.stories.tsx/examples// 单元测试里提取真实用法片段。 - 生成结构化描述:产出组件清单(名称、用途、何时用、import 路径、props 表、示例代码)。
- 生成 Skill 文件:拼成
SKILL.md(触发条件 + 组件索引 + 用法约束)+ 可选references/放完整 API 表。 - 发布/上传:推到 Skill 仓库或内部市场,带版本号。
- 增量更新:组件库 PR 触发重新提取,diff 出新增/变更组件,更新 Skill 版本,旧版本保留可回溯。
- 难点:props 类型抽取的准确性、示例质量过滤、与组件库版本对齐(避免 AI 用了已下线的组件)。
13. 文档投喂:MCP 还是 Skill 直接读文件
取决于文档规模与访问模式:
- Skill 直接读文件:适合静态、小体量、每次都需要的规范/约定(如 AGENTS.md、编码规范)。直接
@注入或 Skill 内Read本地文件,零额外服务、延迟低。缺点是占上下文、不适合频繁变动的大库。 - MCP + 检索:适合大体量、需检索、多人共享、动态更新的知识库(产品文档、API 手册、内部 wiki)。MCP server 对外暴露
search_docs/fetch_doc工具,AI 按需检索再读片段,避免一次性灌爆上下文,也便于权限控制与服务端更新。 - 实践:规范类用 Skill/规则文件常驻;知识库类用 MCP 检索;两者可并存——规范保证”怎么写”,MCP 提供”写什么内容的事实依据”。
14. Agent 对接 MCP 与 Skill
- MCP 对接:在 Agent 配置里声明
mcpServers(STDIO 模式给command/args/env,SSE 模式给url/headers)。启动时 Agent 拉起/连接 server,调用list_tools发现能力,把工具描述注入系统提示;运行时 planner 决定调用,框架负责参数 schema 校验与结果回传。 - Skill 对接:Skill 作为”提示层能力”注册到 agent 的 skill registry。每个 Skill 有触发条件(关键词/意图)与
SKILL.md(指令 + 可选脚本/引用)。命中意图时,框架把 SKILL.md 内容注入上下文,引导 agent 按既定流程做事;重逻辑可配脚本由 agent 调用。 - 架构分层:
- Tool 层:统一封装 native tools + MCP tools,对 planner 透明;
- Skill 层:prompt 模板 / 流程编排,约束”怎么做”;
- Planner/Orchestrator:根据任务选择 tool 与 skill,编排执行。
- 关键是把 MCP 的”能力”和 Skill 的”方法论”都变成 planner 可寻址的资源,且各自带权限/描述元数据。
15. MCP 传输模式:SSE(HTTP)vs STDIO
- STDIO(本地子进程):
- 优点:零网络、零部署、进程级隔离、启动即用;最适本地私有工具(读本地文件、本地 DB、CLI 包装)。
- 缺点:每 client 一个进程、状态难共享、无内置认证、难横向扩展、崩溃即失联;多用户场景重复拉起。
- SSE / Streamable HTTP(远程服务):
- 优点:server 常驻、多 client 共享同一服务与状态、可加认证/限流/审计、可水平扩展、适合团队/云端共享能力。
- 缺点:需部署与运维、有网络延迟。
- 我们的选型:两种都支持。本地个人工具走 STDIO(简单安全);团队共享、需要统一权限与状态的后端能力走 SSE/HTTP。判断标准就是”是否需要多用户共享与集中治理”。
16. Agent 拓展 Skill 槽位的设计
把 Skill 当成可插拔扩展点(extension slot),而非写死在代码里:
- 声明式 manifest:每个 Skill 提供
skill.json(name、description、triggers、permissions、所需 tools、依赖、版本、入口脚本)。Agent 启动时扫描目录 / 远程 registry 自动注册。 - 配置接口:
- 文件配置(YAML/JSON)列出启用的 skill 及参数;
- 可视化 UI 添加/启停/调参(见 Q17);
- 支持远程 registry 拉取,按需安装。
- 隔离与限额:每个 skill 在沙箱(受限 FS / 网络 / 工具白名单)内运行,设超时与资源上限,防止一个坏 skill 拖垮 agent。
- 生命周期:install → enable → update → disable,版本化管理,回滚无忧。
- 动态加载:不常用 skill 延迟加载(命中触发才读 SKILL.md),省上下文。
- 这样”加一个 Skill”对用户是填一份配置 / 点一下按钮,对开发者是丢一个符合 manifest 的目录。
17. MCP 配置可视化界面
有。我们提供用户侧 MCP 管理界面,能力包括:
- 列出已连接的所有 MCP server 及健康状态、已暴露 tools 数;
- 新增:表单填写模式(STDIO:command/args/env;SSE:URL/headers),含连接测试;
- 编辑 / 删除 / 启停;
- 工具浏览:展开看每个 tool 的名称、描述、参数 schema;
- 信任机制:新增 server 默认需用户显式”信任”才激活(防止恶意 server 执行命令);
- 配置持久化到用户配置(如
mcp.json),与 agent 共享。
这样非技术同学也能自助接 MCP,不必手改 JSON。
18. MCP 返回大数据量(1 万条)的处理与截断
核心:不让原始巨量数据直接进 LLM 上下文。
- 服务端先收敛(优先):MCP tool 应支持
filter / paginate / aggregate / limit参数,让 server 先算完再返少量结果,而不是 dump 1 万条。 - 客户端截断 + 透明提示:若 server 只能返全量,client 截断到合理上限(如 top 50 / 按相关性排序后取前 N),并明确告诉模型”数据已截断,共 1 万条,仅展示前 N 条,需要更多请二次查询”。
- 聚合代替明细:把 1 万条先做统计(count by 维度、sum、top-K),只把聚合结果给模型决策。
- 按需二次查询:先返 id + 摘要列表,模型决定关注哪些,再用
get_detail(ids)拉详情,避免一次性全量。 - 代码执行兜底:超大数据交给 agent 的 code interpreter / 临时脚本处理,模型只看结论。
- 缓存:tool result 缓存,重复查询不重复拉取。
19. 多 Agent 通信 / 图编排
有涉及。典型模式:
- Supervisor / 图编排:用 LangGraph 把任务拆成节点,节点可由不同 sub-agent 执行;supervisor 负责派发与汇总,节点间通过共享 state(graph state)或消息传递通信。
- Handoff(交接):一个 agent 完成局部后把上下文与结论交给下一个专职 agent(如”调研 agent → 写作 agent → 审查 agent”),通过显式 message / task 传递,避免上下文无限膨胀。
- Blackboard / 共享黑板:多 agent 读写同一份中间状态,适合并行调研后合并。
- 场景:复杂研究(并行多路检索再汇总)、代码生成 + 自动审查、多角色辩论(如投资分析里的多视角 agent)。
- 关键工程点:agent 间上下文隔离(各管各的窗口)、显式交接协议(传什么、格式)、结果可追溯(谁产出了什么)、失败重试与熔断。
20. 为什么选 Copilot Kit 做 Human-in-the-Loop
CopilotKit 把”人类确认/介入”从后端 chore 变成前端一等公民:
- 原生 HITL 组件:
CopilotAction/CopilotTask可直接在 React 里渲染”确认/编辑表单”,用户在前端点一下就完成 approve,不需自己写 WebSocket + 前端状态同步 + 后端 checkpoint 恢复那一套。 - 解决的具体痛点:
- UI 与 agent 解耦但可交互——前端能插入决策点,agent 暂停等人工;
- 类型安全:action 的入参/出参有 TS 类型,前端表单自动生成;
- 流式集成:与 LLM streaming 天然配合,边生成边可介入;
- 比”裸接 LangGraph checkpoint + 自建前端状态机”省掉大量胶水代码,尤其在前端确认、表单填充、人类反馈回写这些场景。
- 一句话:LangGraph 负责”流程可暂停/可恢复”(后端状态机),CopilotKit 负责”暂停点对人类友好呈现”(前端交互),二者互补。
21. Superpower + OpenSpec 的开发工作流
- Superpower:作为”能力/规则系统”,定义编码规范、可用技能、工作流约定,确保 AI 行为有边界、有标准。
- OpenSpec:管理规格(spec)即变更契约,典型命令
init / proposal / apply / archive:- 需求 → proposal:新功能先写 proposal(目标、影响面、接口、测试),进 PR 评审,先对齐再写码;
- 评审通过 → apply:基于已定 spec 让 AI 实现,AI 严格按 spec 而非自由发挥,避免漂移;
- 实现 → 验证:自动跑 lint/type/test,spec 里的验收点逐条核对;
- 完成 → archive:spec 归档为决策记录,可追溯”为什么这么改”。
- 配合流程:Superpower 定”怎么写”(规范/技能),OpenSpec 定”写什么、改到哪、验收标准”(契约),AI 在两者约束下产出可审计、可回滚的代码。spec 驱动让多轮迭代不跑偏。
22. Spec 文件管理:与仓库同管?不满意删还是留?
- 与仓库同管理:spec 作为代码变更的契约,放进仓库(如
openspec/目录)版本化,随 PR 评审、可 diff、可 blame,保证”代码与意图”一致、可追溯。 - 不满意怎么处理:
- 不硬删:采用
archive(标记完成/废弃)而非物理删除,保留决策轨迹——今天觉得烂的 spec,三个月后可能是”当初为什么没这么做”的关键证据。 - 覆盖而非销毁:新方案写新 proposal,旧 spec 标
superseded-by: <new>,关系清晰。 - 实验隔离:拿不准时在 feature 分支 / 草稿目录试写,定型再合主干;合入后若推翻,用新 proposal 反转,留下完整因果链。
- 清理原则:真正无用的临时草稿可删,但”已评审过的正式 spec”一律归档保留,因为它是团队的决策资产。
- 不硬删:采用