别再被 AI 黑话“收智商税”了:讲透 Agent / RAG / MCP / Skill 的通用工程解法

别再被 AI 黑话“收智商税”了:讲透 Agent / RAG / MCP / Skill 的通用工程解法

刷到“Skill、MCP、RAG、Agent”这些词时,第一反应大概率是:我是不是又落后了?

换个研发负责人的视角看:绝大多数新名词,都在做同一件事——把“模型只会生成字”的能力,包装成“能完成任务的系统”。名字可以很潮,但工程本质永远逃不出:

  • 数据(Context)
  • 检索(Search)
  • 工具(Tool)
  • 编排(Workflow)
  • 约束(Schema)

下面用一套“通杀新概念”的方法,把这些词拆到你能复用、能落地。

摘要(先看结论)

  • RAG、Agent、MCP、Skill 本质都在补 LLM 的短板:缺知识、缺实时、缺手脚。
  • 选型只问三件事:补什么短板?确定性来自哪里?风险与成本在哪里?
  • 不要把名词当“黑科技”。把它们当成可拆分、可替换的系统零件,你就不会被词牵着走。

0)一句话定义(方便记忆)

术语一句话你真正要做的工程事
RAG先检索,再把命中的材料喂给模型做好召回/排序/切片/去重/防注入与评估闭环
Agent带工具的循环控制器:计划→调用→观察→再计划设计循环、停止条件、失败回退与可观测性
Function Calling(工具调用)与结构化输出LLM 世界的“接口契约”用 schema 把输入输出钉死,避免解析失败与字段乱填
MCP工具生态对接的标准化插头把“接工具”变成可复用连接层,同时补齐权限与审计
Skill可复用的提示词/流程片段(有时带工具)做版本化、评估、依赖声明与适用范围说明

0.1)放到 Trae 里:这些词分别对应什么?

如果你平时主要用 Trae 来读代码、改代码、跑命令,可以把上面这些概念直接“落到 Trae 的日常动作”里理解:

概念在 Trae 里你看到的样子最小可复现案例(示意)
Context / Memory你发给模型的 messages + 你补充的规则/状态/资料把「问题 + 相关文件片段 + 当前改动目标」拼到一次请求里
RAG先找材料,再回答先在仓库里搜(代码/文档),把命中的片段喂给模型再生成结论
Function Calling(工具调用)模型不直接“写答案”,而是先触发一次可执行动作先让模型去搜代码/读文件/跑测试(工具),再基于结果输出最终答案
Agent多轮循环:计划→执行→观察→再计划修一个线上 bug:先定位→改动→跑测试→失败再定位→直到通过
MCP把外部系统“接进来”给模型用拉飞书文档/设计稿/组件库文档作为上下文或工具输出
Skill一套可复用的“工作流提示词 + 约束 + 自检清单”做一个“仓库问答带引用”的 Skill,让新人按固定格式提问与验收

1)先把地基钉死:大模型到底会什么、不会什么?

大语言模型(LLM/LM)的核心能力可以粗暴理解为:在给定上下文里生成下一段最可能的文本。这很强,但也天然有三大短板:

  1. 不知道你公司的私有信息(除非你把信息塞进上下文)
  2. 不知道今天刚发生的事(训练数据是历史的)
  3. 没有手脚(不会自己去查系统、发消息、改表格)

所以你看到的很多能力,本质都是围绕这三条补短板:

  • Prompt / Context / Memory:怎么把更多信息塞进上下文
  • Function Calling / 工具调用:怎么让模型可靠地“动手”
Trae 实战:把“三短板”翻译成三个具体动作

把“短板”翻译成 Trae 里你每天会做的动作,会更直观:

  • 缺私有知识(不知道你公司/你仓库)→ 先把材料找出来再问:在仓库里搜到关键文件与片段(相当于 RAG 的 retrieve),再让模型基于这些片段解释或改代码。
  • 缺实时(不知道今天发生了什么)→ 让模型先拿到新信息再回答:例如先抓取公告/最新文档/线上日志摘要(来自你的系统/网页/平台),再回填给模型。
  • 缺手脚(不会动手)→ 把“动手”变成工具:跑测试、执行脚本、生成补丁、读写文件,都要让模型通过“可执行动作”完成,而不是只靠嘴说。

1.1)记忆:短期记忆是“上下文管理”,长期记忆才是“可持久化的库”

很多人说“给大模型加记忆”,容易误会成“模型自己会记住”。工程上更准确的说法是:LLM 每次调用只看你当次发给它的上下文,所谓“记忆”通常由你的应用侧负责存储与回填。

可以把记忆拆成两类:

  • 短期记忆(Short-term):存在于上下文窗口内,本质是“把最近对话/状态/工具结果拼回去”。特点是即时、便宜、但会被 token 预算挤掉。
  • 长期记忆(Long-term):存在于上下文窗口之外,本质是“把历史沉淀到外部存储,再按需检索回填”。特点是可持久、可治理、但必须做检索、去噪与权限隔离。

两类记忆最容易踩坑的点:短期记忆不是“存”,而是“选哪些发给模型”;长期记忆不是“全存”,而是“存什么、怎么取、怎么删”。

1.1.1 短期记忆怎么做:对话历史 + 状态压缩 + token 预算

短期记忆通常由这几块组成:

  • 对话历史(messages):你在服务端保存历史消息,每次请求挑一部分塞回去。
  • 运行时状态(state):当前任务进度、已选选项、已完成步骤、用户当前页等(不要让模型“回忆”,要让它“看到”)。
  • 工具结果(tool results):检索命中片段、数据库查询结果、接口返回等。
  • 压缩摘要(summary):当历史太长时,用摘要把关键事实与决策压缩成更短的片段。

一个最小的“短期记忆拼装器”长这样:

messages(last N) + state(snapshot) + tool_results(recent) + summary(if needed) -> assemble_context(token_budget) 
1.1.2 长期记忆怎么做:存储、检索、回填三件事

长期记忆不是“把所有聊天记录都存起来”,而是把可复用的东西沉淀成可治理资产。常见的长期记忆形态:

  • 用户画像/偏好(Profile):语言偏好、输出格式、常用项目、权限范围(结构化字段优先)。
  • 事实记忆(Facts):确认过的事实(例如“项目代号、接口地址、约定字段”),必须可追溯来源。
  • 经验记忆(Episodic):历史交互的关键片段(例如“上次排查过的错误、最终结论是什么”),适合用向量检索按相似度召回。

存储选型上,通常是“结构化 + 向量”混合:

  • 结构化记忆:SQL/NoSQL/KV(便于更新、删除、按用户隔离、做审计)。
  • 语义记忆:向量库(embedding)+ 元数据(用户/租户/权限标签/时间戳/来源)。

回填到模型时,永远走“检索后注入”,不要走“全量塞回”:

user_query -> retrieve_memories(user_scope, topK) -> dedupe + sanitize -> inject_into_context 
1.1.3 记忆怎么“传给模型”:本质就是上下文注入

无论短期还是长期,最终都要走到同一件事:把你选中的记忆片段拼到 prompt 里发给模型。可以用一个更直观的拼装示意:

system(规则/角色) + tools(schemas) + user(question) + retrieved_docs(RAG) + retrieved_memories(long-term) + session_state(short-term) -> LLM 
Trae 实战:一次多轮排障时,短期/长期记忆分别放什么?(Android)

场景:Android 新同学在 Trae 里排查一个“Gradle 单测只在 CI 失败、本地 Android Studio 跑是绿的”的问题。你希望模型每一轮都能稳定“接着上一步继续”,而不是反复问同样的问题。

短期记忆(本轮与近期必须看到的东西)建议长这样:

{"task":"Fix CI-only Android unit test failure","context":{"build":"gradlew testDebugUnitTest","ci_os":"Linux runner","local_os":"macOS","jdk":"17","timezone":"CI=UTC, local=Asia/Shanghai"},"hypotheses":["时区/Locale 不一致导致日期格式化/解析差异","Robolectric/Android SDK 版本差异导致行为不同","协程/线程调度导致偶发竞态(本地复现概率低)","测试依赖文件路径/编码(Windows 路径、大小写、换行符)在 CI 不同"],"confirmed_facts":["失败用例:com.example.app.LoginViewModelTest#whenTokenExpired_shouldLogout","只在 CI 的 Linux runner 失败,本地 macOS 通过","失败栈里出现了 Date/Time 或 Locale 相关的关键调用"],"next_action":"定位失败用例中对时间/Locale/线程调度的依赖点,并固定可控输入(Clock/Locale/Dispatcher)"}

把它拼到“本轮请求的上下文”里,模型就会把它当成当前状态继续推进;它不是“记住”,而是“看见”。

长期记忆(跨天/跨人可复用的结论)建议只沉淀“可复用且可追溯”的东西,例如把下面内容写入团队知识库/故障库:

  • 结论:某类 Android 单测在 CI 默认时区/Locale 为 UTC/en-US,需固定时区/Locale 或注入 Clock
  • 证据:链接到具体失败日志与对应代码行
  • 修复模板:给出统一的测试基建写法(例如注入 Clock、固定 Locale、对协程使用可控 Dispatcher

下次再遇到类似问题,你在 Trae 里提问时做的事情其实是“先检索历史故障库(长期记忆召回)→ 再把命中的结论片段回填到上下文”,然后模型才能复用经验,而不是从头猜。

1.1.4 记忆的工程边界:不要把“风险”一起存进去
  • 权限隔离:长期记忆必须按用户/租户隔离,检索时强制带 scope 过滤。
  • 防注入:记忆片段也可能携带恶意指令,回填前同样需要 sanitize。
  • 可删除/可审计:涉隐私与合规场景必须支持删除(TTL/硬删)与访问审计。
  • 防“幻觉写入”:模型生成的“新事实”不要直接进长期记忆,必须要么可验证(工具查证),要么人工/规则确认后再写入。

2)RAG:别神化,它就是“先检索再喂给模型”

RAG(Retrieval-Augmented Generation)说白了就是:模型自己“不一定知道”,那就先去资料库找证据,再把证据连同问题一起喂给模型,让它基于材料回答。

RAG 的工程关键不在名词,而在三件事:

  • 检索质量:召回是否全、排序是否准(向量检索/混合检索/重排)
  • 上下文拼装:片段怎么截、怎么去重、怎么防注入
  • 评估闭环:命中率、引用覆盖率、事实一致性(否则就是“看起来更像对了”)

一个可落地的最小流水线长这样:

query -> retrieve(topK) -> rerank -> chunk + dedupe + sanitize -> assemble_context(token_budget) -> model_answer(with_citations) 

这里的几个词分别代表:

  • retrieve(topK):召回。用 query 去知识库/索引里“捞”出候选片段,topK 表示先取前 K 个候选(K 越大召回越全,但噪声与成本也更高)。
  • rerank:重排。对召回的候选再做一轮更精细的相关性排序(通常更慢但更准),把真正最相关的片段提到最前面,供后续拼装上下文使用。
  • chunk:把命中的长文档切成“可用片段”。通常按段落/标题/滑窗切分,并控制片段长度,避免一段太长塞爆上下文或一段太短丢语义。
  • dedupe:去重。把高度相似/重复的片段合并或丢弃,避免浪费 token、降低模型被重复信息“带偏”的概率。
  • sanitize:净化/消毒。对片段做安全与质量处理,比如去掉无关噪声、过滤潜在 prompt injection(例如“忽略以上指令”)、做最小必要的转义与白名单化。
  • assemble_context(token_budget):在 token 预算内拼上下文。要做取舍与排序:保留最高相关片段、补齐必要元信息(来源/时间/权限),并防止引用超长导致后续步骤被截断。
  • model_answer(with_citations):让模型回答,并要求带引用。引用至少要能定位到“来自哪份材料的哪段”,否则评估闭环做不起来。
Trae 实战:把“仓库”当知识库做一次最小 RAG(Android 视角,带引用)

场景:Android 新同学问“登录态为什么会丢?token 是在哪写入/读取的?失败会怎么处理?”

在 Trae 里按这个固定套路走就行:

  1. 先搜(retrieve):搜 token、interceptor、auth、DataStore/SharedPreferences、refresh
  2. 再读(chunk):只读和问题相关的几个关键文件片段(不要把整个目录都塞给模型)
  3. 再去重/净化(dedupe + sanitize):去掉重复片段,过滤无关噪声与潜在注入内容
  4. 最后回答并引用(with_citations):每个关键结论都能回放到“某个文件的某段”

示意输出(路径/行号为示意,重点是格式与验收方式):

{"answer":"登录态通常丢在两类问题:token 持久化没写成功/被覆盖,或网络层刷新失败但上层没做降级处理。先从 token 的写入点、读取点、以及 401/refresh 流程三处排查。","citations":[{"path":"app/src/main/java/com/example/auth/TokenStore.kt (示意)","lines":"1-120"},{"path":"app/src/main/java/com/example/network/AuthInterceptor.kt (示意)","lines":"1-160"},{"path":"app/src/main/java/com/example/network/RefreshTokenUseCase.kt (示意)","lines":"1-200"}]}

这里的“引用”不是装饰:你拿着引用范围回到代码里核对,就能判断结论是不是“代码里真的这么实现的”,也能快速定位该改哪。

3)Agent:别把它当“机器人”,它更像“带工具的循环控制器”

很多人理解 Agent 以为是“有自主意识的机器人”。工程上更准确的说法是:

Agent = 模型 + 工具(Tools) + 循环(Loop) + 停止条件(Stop Condition)

这也是选型时最常用的一句话:

  • 确定性优先 → Workflow(可控、可测、可回滚)
  • 探索性/开放问题 → Agent(更灵活,但要更强的治理)

一个最小 Agent 循环可以抽象为:

Goal -> Plan -> Act (tool call) -> Observe (tool result) -> Update memory/context -> Stop? else loop 

落地时真正容易翻车的不是“会不会循环”,而是:

  • 停止条件:什么时候算完成?什么时候必须停?
  • 失败策略:工具超时/权限不足/返回异常怎么办?
  • 可观测性:每一步到底干了什么?成本与耗时在哪?
Trae 实战:用“循环控制器”修一个 bug(并且能停得住)

场景:新同学在 Trae 里接到一个需求:“某个页面偶发崩溃,堆栈提示空指针,修完需要跑完测试再交付。”

把它按 Agent 循环落地,通常长这样(示意日志):

Goal: Fix NPE crash in FooViewModel 1) Plan: - 定位 NPE 触发路径 - 找到谁在传 null/谁没做校验 - 修复 + 补回归用例 2) Act (tool call): - 搜索崩溃堆栈里的符号/函数名 3) Observe (tool result): - 命中 3 处调用点,其中 1 处来自异步回调 4) Update memory/context: - 记录已确认事实:null 来自网络字段缺失 - 更新下一步动作:给解析层加默认值/给 ViewModel 加 guard 5) Act: - 修改代码并补测试 - 运行测试 6) Stop condition: - 单测通过 + 关键路径有回归覆盖 + 变更范围可解释 - 否则回到第 1) 继续循环 

“能停得住”的关键不在模型聪明,而在你把停止条件写清楚:验收标准是什么、必须满足哪些客观信号(测试通过/引用齐全/风险可控)。没有停止条件,Agent 很容易变成“越修越多、越跑越远”。

4)Function Calling(工具调用)与结构化输出:它们不是“黑科技”,是“契约”

模型要调用工具,最大的问题不是“能不能调用”,而是“输出能不能被机器稳定解析”。

一句话:这是“前后端接口协议”在 LLM 世界的再发明。它解决的是工程确定性——不然你会天天在解析失败、字段缺失、枚举乱填里痛苦。

下面是一个最小示例(schema 约束工具入参),核心点是:让模型只能在你允许的结构里填值。

{"name":"search_docs","description":"Search internal docs and return relevant snippets","parameters":{"type":"object","properties":{"query":{"type":"string"},"top_k":{"type":"integer","minimum":1,"maximum":20}},"required":["query"]}}

如果你完全看不懂,上面这个 JSON 可以先按“工具说明书”来理解:它不是让你直接调用工具的参数,而是让模型知道“有哪些工具可以用、每个工具要填哪些字段、字段有什么约束”。

逐项解释:

  • name:工具名。模型在决定要用工具时,会产出“我要调用 name=search_docs”这样的结构化意图。
  • description:工具用途说明。给模型做选择依据:什么时候该用它。
  • parameters:工具入参的 JSON Schema(核心)。
    • type: object:表示入参整体是一个对象(类似函数的参数对象)。
    • properties:这个对象里允许出现哪些字段。
      • query:字符串。你要搜什么。
      • top_k:整数,且限定范围 1–20。你允许模型最多取多少条候选,避免模型乱填一个特别大的数导致成本爆炸。
    • required:必填字段列表。这里要求必须提供 query,top_k 不填也可以(你的程序可以给默认值)。

它和 Function Calling 的关系可以一句话讲清:

  • Function Calling 是“模型怎么把调用意图变成机器可执行的结构化数据”的机制。
  • 上面这个 JSON(schema)就是 Function Calling 需要的“契约”:你把工具的名字与入参约束定义好,模型就按这个契约产出可解析的调用参数。

一个典型链路长这样:

你把 tools(=schemas) 交给模型 -> 模型产出:call search_docs({query: "...", top_k: 5}) -> 你的程序校验参数是否符合 schema -> 你的程序真实执行搜索 -> 把搜索结果回传给模型继续生成最终答案 
Trae 实战:把“工具调用”当成强类型接口(先校验再执行)

在 Trae 的体验里,你会频繁看到“模型先触发一个工具动作(搜代码/读文件/跑命令)→ 再基于结果回答”。这件事之所以稳定,是因为它不是“让模型随便输出一段文字再让你猜”,而是:

  • 输入:用 schema 约束字段(防止字段缺失、枚举乱填、topK 过大导致成本爆炸)
  • 过程:宿主程序做校验与执行(模型不直接碰你的数据库/命令行)
  • 输出:用输出 schema 或固定格式要求“答案 + 引用/证据”,便于验收与回放

最小落地写法(伪代码)可以理解为:

typeSearchDocsArgs={ query:string; top_k?:number};functionvalidateSearchDocsArgs(args:any):asserts args is SearchDocsArgs {if(!args ||typeof args.query !=="string"|| args.query.length ===0){thrownewError("invalid args: query is required");}if(args.top_k !==undefined&&(typeof args.top_k !=="number"|| args.top_k <1|| args.top_k >20)){thrownewError("invalid args: top_k must be 1..20");}}asyncfunctionhandleToolCall(name:string, rawArgs:unknown){if(name !=="search_docs")thrownewError("unknown tool");const args = rawArgs asany;validateSearchDocsArgs(args);returnawaitrealSearch(args.query, args.top_k ??5);}

新人理解到这里,就能把“Function Calling”当成一次“后端接口调用”:模型负责产出结构化请求,你的程序负责校验与执行,最后再把结果回传给模型生成最终答案。

你问“这玩意是谁传给 LLM 的,还是 LLM 自带的?”——答案是两部分:

  • schema 不是 LLM 自带的知识,也不是模型训练时“天然就知道你有哪些工具”。它是你(应用开发者)在调用模型 API 时,通过 tools/functions 之类的参数显式传给模型的。
  • Function Calling 是模型/接口提供的能力:模型能在你提供的 tools 列表里做选择,并按 schema 生成结构化的调用参数;但“工具清单与约束”永远来自你的应用侧配置。

换句话说:

  • LLM 自带:生成文本、在候选工具里做选择、按 schema 填字段(尽量)。
  • 你要提供:有哪些工具、每个工具的入参/约束、工具实际怎么执行(真实 HTTP/DB/脚本调用)、鉴权与审计。

如果你还要求输出也必须严格符合结构(例如必须给出引用段落与置信信息),那就是把“结构化输出”进一步拉满:

{"type":"object","properties":{"answer":{"type":"string"},"citations":{"type":"array","items":{"type":"object","properties":{"doc_id":{"type":"string"},"start":{"type":"integer"},"end":{"type":"integer"}},"required":["doc_id","start","end"]}}},"required":["answer","citations"]}

这段 schema 描述的不是“工具入参”,而是“你希望模型最终返回的答案长什么样”(输出契约):

  • type: object:输出整体是一个对象。
  • properties:允许的输出字段。
    • answer:字符串,模型给出的最终答案正文。
    • citations:数组,每一项代表一条引用(证据)。
      • items.type: object:每条引用是一个对象。
      • doc_id:字符串,用来标识证据来自哪份文档/哪条数据源(例如 URL、文档主键、文件路径、知识库条目 ID)。
      • start/end:整数,用来定位证据在原文中的范围(可以是字符偏移、chunk 序号、段落号等;关键是你要选一种“可回放”的口径并坚持)。
      • required:每条引用至少要带 doc_id/start/end,避免模型只给“泛泛而谈的引用”。
  • required: [“answer”,“citations”]:要求必须同时返回答案与引用,否则就视为不合格输出。

结合一个端到端例子(把“输入/输出”说清楚):

目标:用户问“Android 发版前必须跑哪些检查/Gradle task?给出处。” 输入(应用 -> LLM)包含三块: 1) 用户问题(messages) 2) 工具契约:search_docs 的入参 schema(tools/functions) 3) 输出契约:要求最终必须返回 {answer, citations}(输出 schema / response schema) 

第一步:模型决定先调用工具(Function Calling 的产物,结构化调用参数)

{"tool_name":"search_docs","arguments":{"query":"Android 发版 SOP 提测 检查 gradle task lint test","top_k":5}}

第二步:你的程序执行工具,把结果回传给模型(tool result)

{"tool_name":"search_docs","result":[{"doc_id":"android-release-sop-2026","text":"提测前必跑:./gradlew testDebugUnitTest 与 ./gradlew lint...(略)","start":1200,"end":1268}]}

第三步:模型输出最终答案(必须满足上面的输出 schema)

{"answer":"发版/提测前需要跑的检查是:./gradlew testDebugUnitTest 与 ./gradlew lint...(根据 SOP 条款整理)","citations":[{"doc_id":"android-release-sop-2026","start":1200,"end":1268}]}

把它和上一段“工具入参 schema”对照起来,你会发现:

  • 工具入参 schema:约束的是“模型调用工具时怎么填参数”(call 的 arguments)。
  • 输出 schema:约束的是“模型给用户最终回答的结构”(final answer JSON)。

5)MCP:它解决的是“工具生态对接的标准化”,不是取代 Function Calling

MCP(Model Context Protocol)是一个开放协议,用来把 LLM 应用与外部数据源/工具用统一方式连接起来。

你可以把它理解成:“Agent/IDE/Chat 应用(客户端)”对接“工具/数据(服务器)”的标准插头。有了插头,生态就能扩张得更快。

这里最容易混淆的是:

  • Function Calling:模型 ↔ 你的程序之间的“工具调用格式/契约”
  • MCP:你的程序 ↔ 外部工具服务之间的“连接与交互规范”

很多系统会两者同时用:模型用 Function Calling 产出结构化调用参数,你的程序再通过 MCP 去连各种工具服务。

同样重要的一句提醒:工具一旦“连通”,风险也会被放大。研发负责人的视角必须补齐:权限边界、最小授权、审计与沙箱,否则“能干活”会变成“能闯祸”。

Trae 实战:用 MCP 拉飞书 SOP 文档,做“带出处”的问答

场景:团队把“Android 发版/提测 SOP”放在飞书文档里,新同学想问“提测前必须跑哪些检查、失败怎么处理”,并且要求每个结论都能给出处。

在 Trae 里可以把它拆成一条很清晰的链路:

用户问题 -> MCP:拉取飞书文档内容(拿到原文) -> RAG:把文档切片 + 检索命中段落 -> 输出:答案 + 引用(文档ID/段落范围) 

示意(把“拉文档”这一步当成 MCP 工具调用):

{"tool_name":"mcp_mcp-component-doc_get-feishu-content","arguments":{"documentLink":"https://your-feishu-doc-link"}}

把它展开成“端到端三步”,新人更容易理解“谁在调用谁、数据怎么流”:

Step 1) 模型触发 MCP 工具:拉飞书文档(拿原文) Step 2) 宿主执行工具:返回文档内容片段(可能很长,后续要切片/检索) Step 3) 模型输出最终答案:结论 + 引用(指向文档的段落/范围) 

示意(第 2 步的 tool result,形状因平台而异,这里只强调“你拿到了原文”):

{"tool_name":"mcp_mcp-component-doc_get-feishu-content","result":{"title":"Android 发版 SOP","content_markdown":"## 提测前检查\n...\n## 灰度与回滚\n..."}}

拿到文档内容后,再做检索与引用输出(和前面的 RAG/输出 schema 完全同一套方法),新人就能理解:MCP 不神秘,它只是把“外部内容/工具”接进来,让你有材料可喂、有动作可做。

Trae 实战:用 MCP 把设计稿变成代码(把“资料”换成“设计源”)

场景:产品给了 Figma 链接,希望快速生成一版可落地的 UI 骨架。

在 Trae 里你可以把它理解为:MCP 负责把设计稿数据拉进来,然后你再让模型做“解释/改造/对齐规范”的工作。

{"tool_name":"mcp_mcp-component-doc_get-figma-to-code","arguments":{"figma_url":"https://www.figma.com/file/xxxxxx"}}

风险提醒(新人容易忽略但线上必须有):

  • 文档/设计稿属于数据源:要做权限隔离与审计,不要让“能拉到的都能问到”
  • 生成代码属于可执行产物:要有 review、lint、测试与回滚路径

6)Skill:多数产品里它就是“可复用提示词/流程片段”,别被神化

“Skill”在不同产品里定义不一,但落到工程实现,经常就是两类东西:

  1. Prompt 模板的资产化:把一段高质量提示词 + 输入槽位 + 约束,做成可复用组件
  2. 轻量流程编排:把“先做 A 再做 B”的步骤固化(有时只是把步骤写进提示词)

所以你听到“Skill 很强”,不要先激动,先问:

  • 它是纯提示词?还是带工具?
  • 有 schema 约束吗?
  • 有评估与版本管理吗?

没有这些,Skill 很容易变成“看起来很强、线上很飘”的玄学资产。

Trae 里的 Skill 更接近“一个可被发现与加载的文件夹”,核心文件通常是 SKILL.md(Markdown + YAML frontmatter 元信息),并配套 references/scripts/assets/ 等资源:

.trae/skills/doc-search-answer/ SKILL.md references/ # 可选:示例输入、知识片段、对齐材料 scripts/ # 可选:用于复现/校验的脚本(如果你的环境支持执行) assets/ # 可选:图片/示意图等 

一个“更像 Trae”的 SKILL.md(示例)可以这样写(重点是:触发条件 + 输入要求 + 输出格式 + 自检清单):

--- name: "doc-search-answer" description: "对文档库检索并生成带引用的回答;适合 FAQ/制度/规范类问题。" --- # Doc Search Answer ## 使用时机(触发条件) - 用户问的是“有明确证据来源”的问题:制度、规范、接口文档、SOP、历史决策 - 你需要输出可追溯引用,而不是只给看起来合理的回答 ## 输入要求(尽量明确) - 用户问题:一句话 + 关键约束(时间范围/团队/版本/区域) - 可选:需要优先检索的数据源范围(例如:仅 policies/ 或仅 engineering/) ## 工具依赖(概念层) - search_docs(query, top_k): 检索候选片段 ## 输出格式(严格) ```json { "answer": "...", "citations": [ { "doc_id": "...", "start": 0, "end": 0 } ] } ``` ## 工作流(推荐) 1) 先检索:用问题里的关键词做 search 2) 再筛选:去重、过滤注入片段,保留最相关证据 3) 再回答:先给结论,再用引用对齐关键句 ## 自检清单 - [ ] 是否每个关键结论都有对应 citation? - [ ] 引用是否能定位到原文范围(doc_id + start/end)? - [ ] 是否避免把引用当成“装饰”(引用必须真的支持结论)? 
Trae 实战:再给一个更“工程向”的 Skill 模板(修 bug/改代码)

如果你的目标不是“回答问题”,而是“改代码并交付”,Skill 的输出就不该只有答案,还要包含可验收的产物(补丁/测试结果/回滚方式)。一个偏工程的模板可以这样写:

--- name: "repo-bugfix-workflow" description: "在仓库内定位问题、最小改动修复、跑测试验证,并输出可回放证据。" --- # Repo Bugfix Workflow ## 使用时机(触发条件) - 用户给了错误现象/堆栈/日志,目标是“修复并验证” ## 输入要求 - 错误信息:堆栈/日志关键行 - 验收标准:要通过哪些测试/是否允许改动行为 ## 输出格式(固定) 1) Root Cause(根因一句话) 2) Fix(改动点列表:文件 + 行号范围) 3) Verification(验证命令 + 关键输出摘要) 4) Risk & Rollback(风险点 + 回滚方式) ## 自检清单 - [ ] 是否提供了能复现/回放的证据(文件引用或日志片段)? - [ ] 是否跑过项目约定的测试/检查? - [ ] 改动是否满足“最小范围”,避免顺手重构? 

7)给你一套“通杀新概念”的三问法(拿去就能用)

下次再出现一个新黑话(比如 XX Copilot、YY Agent、ZZ Skill),你只问三件事:

  1. 它在补大模型哪块短板?
    • 缺知识 → RAG/搜索
    • 缺记忆 → Memory/总结压缩
    • 缺手脚 → Tools/MCP/插件
  2. 它的确定性来自哪里?
    • schema/结构化输出?
    • workflow 编排?
    • 还是“相信模型会乖”?
  3. 它的风险与成本在哪里?
    • 权限/数据泄露/注入
    • token 成本与延迟
    • 线上可观测与回滚

能把这三问答清楚,你就不会被名词牵着走。

Trae 实战:用“三问法”选对打法(新人不容易走偏)

场景:新同学说“我想搞个 Agent,把问题都自动解决”。这时候用三问法能快速把需求落到工程选型:

  • 它在补什么短板?
    • 只是“读懂仓库/解释代码” → 缺知识:优先做 RAG(先搜再读再答),不需要 Agent 循环
    • 需要“改代码并验证” → 缺手脚:需要工具调用(跑测试/改文件),是否需要 Agent 取决于任务是否开放探索
  • 它的确定性来自哪里?
    • 有明确验收(测试必须通过/输出必须带引用)→ 用 schema + 固定输出格式 + workflow 步骤约束
    • 没有明确验收(“帮我优化一下体验”)→ 才更像 Agent 的探索型任务,但必须加停止条件与预算上限
  • 它的风险与成本在哪里?
    • 读权限/写权限边界是否清晰?是否会把敏感内容回显?
    • 会不会跑错命令/改错文件?是否能回滚?
    • token 与延迟是否可接受?是否需要缓存与摘要?

8)一张图讲清全家桶(研发视角)

用户问题 ↓ (可选) RAG/搜索:取资料 ↓ 上下文拼装(Context/Memory) ↓ LLM 推理(生成/决策) ↓ (可选) 工具调用:Function Calling(工具调用) ↓ (可选) 连接工具生态:MCP / 插件 ↓ 执行结果 → 回写上下文 → 继续循环(Agent)或结束(Workflow) 

8.1)Trae 版“全家桶”一眼看懂(把概念映射到实际动作)

你在 Trae 输入需求 ↓ (可选)加载 Skill:选择一套固定工作流/输出格式 ↓ (可选)RAG:在仓库/文档里搜索 + 读取关键片段 ↓ 上下文拼装:把规则 + 资料片段 + 当前状态拼进一次请求 ↓ 模型决策:生成方案 / 选择下一步动作 ↓ (可选)工具调用:读文件 / 跑命令 / 生成补丁 ↓ (可选)MCP:对接飞书/设计稿/组件库等外部数据源 ↓ 验证与交付:测试通过 + 引用可回放 + 风险可控 

9)趋势判断:未来一定是“降门槛”,而不是“叠名词”

趋势不是“你要记住更多名词”,而是:

  • 更多能力被打包成默认能力(不用你配一堆参数)
  • 更强的治理与安全成为标配(权限、审计、沙箱、评估)
  • Workflow 与 Agent 会长期共存:核心链路要稳,边缘探索要灵活

10)落地检查清单(快速自查)

这一段只做一件事:在你准备“真的把它用到研发流程里”之前,用 1 分钟把方向校准好,避免把系统做成“能演示但不好用、能生成但不能上线”。

  • 我到底要解决什么问题?
    • 知识类(看不懂代码/制度/文档)→ 先做 RAG(先搜再读再答)
    • 执行类(改代码/跑测试/发版)→ 需要工具调用 + 验证闭环
  • 我交付的“证据”是什么?
    • 知识类:答案 + 可回放引用(文件/段落/行号范围)
    • 执行类:补丁 + 验证结果(测试/检查输出摘要)
  • 我怎么保证它不会乱来?
    • 结构:schema / 固定输出格式
    • 流程:workflow 步骤 + 停止条件(什么时候必须停)
    • 权限:最小授权 + 审计 + 沙箱(能读什么、能写什么、能跑什么)
  • 我怎么上线后兜底?
    • 评估:命中率/引用覆盖/事实一致/成本与延迟(至少有一组回归问题)
    • 回滚:禁用工具、只读模式、回滚提交

10.1)放到 Trae 里怎么验收(新人交付不翻车)

把一次 Trae 里的交付,验收成“像正常研发交付一样”:

  • 读得懂:结论是否能回放到证据?
    • 必须有引用:文件路径/段落/行号范围(不接受“我觉得是这样”)
  • 改得对:改动是否最小且可解释?
    • 清楚说明:改了哪几个文件、为什么改、影响面是什么(Android 侧尤其要写清楚是否影响主线程/启动/序列化)
  • 跑得过:是否真的验证过?
    • 至少提供:执行了哪些命令(例如 ./gradlew test / ./gradlew lint),以及关键输出摘要(通过/失败点)
  • 不越权:是否守住数据与权限边界?
    • 不回显敏感信息、不把内部链接/凭证贴进答案;需要访问外部系统时必须走授权工具链
  • 能回退:是否有明确回滚方式?
    • 出问题如何快速降级到只读/禁用工具,或回滚到某次提交

结尾:别怕黑话,你要盯的是“系统补短板的方式”

你不需要追着每个新名词跑。记住开头那五个零件(Context/Search/Tool/Workflow/Schema),再用三问法校准:它补什么短板?确定性来自哪里?代价和风险在哪里?

回答完这三个问题,Skill/MCP/RAG/Agent 就会从“玄学名词”变成“可控组件”:能被验收、能回滚、能迭代。

Read more

无人机和地面站能够达到的多远的通信距离?无人机需要飞多高?附在线计算网页

无人机和地面站能够达到的多远的通信距离?无人机需要飞多高?附在线计算网页

无人机和地面站能够达到的多远的通信距离?无人机需要飞多高?附在线计算网页 在无人机组网通信中,如何估算无人机与地面站之间的稳定通信距离是一个常见的问题。本文将从地球曲率和菲涅尔区两个方面,详细探讨如何计算无人机与地面站的通信距离,并提供一个在线计算网页以方便读者进行实际计算。 经常有朋友会问到这个问题, * 无人机组网通信中,如果已经知道了无人机的飞行高度、地面站天线的高度,那么无人机和地面站稳定通信距离是多少km? * 无人机组网通信中,如果已经知道了地面站天线高度、期望的稳定通信距离,无人机需要飞多高才能满足期望的通信距离? 解答这个问题,需要从以下两个方面来考虑: 1. 无线通信距离受到地球曲率的影响 2. 无线通信距离受到空间传输通道的影响。 注意:本文不讨论由于发射端EIRP不够,链路余量不足引起的通信距离不足的问题,所有的计算和分析都是假设发射端EIRP足够,链线余量足够,仅仅考虑地球曲率和空间传输通道的影响。 地球曲率(无线信号传输的视距模型):解决能否看见的问题 无人机与地面电台之间的最远通讯距离受地球曲率限制,通常采用考虑大气折射的无线电视距

AI不是前端/UI的“终结者”,而是提升的“加速器”

AI不是前端/UI的“终结者”,而是提升的“加速器”

最近团队里的讨论越来越频繁:“XX用AI生成可视化大屏原型,半天就交了初稿”“Figma的AI插件直接把线框图转成高保真,切图都省了”“领导说以后简单的管理系统界面,让AI先出一版再改”。随之而来的是藏不住的焦虑:连最吃经验的视觉排版、组件适配都能被AI搞定,我们这些前端/UI从业者是不是迟早要被替代? 这种焦虑并非空穴来风,但恰恰走进了一个认知误区——把AI当成了抢饭碗的“终结者”,却忽略了它作为效率工具的核心价值。对于我们做网站建设、数字孪生、工控界面这些业务的前端/UI人来说,AI从来不是要取代我们,而是帮我们跳出重复劳动、承接更多项目、拿到更高提成的“推进器”。搞懂这一点,才能在技术迭代中站稳脚跟,而不是被焦虑牵着走。 一、先厘清:前端/UI领域的AI,到底是什么? 先别忙着恐慌,我们先给行业里的AI工具定个性——它不是能独立完成项目的“超级程序员”,而是精准匹配前端/UI工作场景的“高级辅助工匠”。具体来说,就是基于大量行业数据训练,能快速完成重复性、模板化工作的工具集合,核心作用是“减少基础工作量”,而非“替代核心决策”。 我们可以按工作场景把这些AI工具分

快速搭建人脸融合应用,UNet+WebUI组合真香推荐

快速搭建人脸融合应用,UNet+WebUI组合真香推荐 1. 引言:为什么选择UNet + WebUI构建人脸融合系统? 在当前AI生成内容(AIGC)快速发展的背景下,人脸融合技术已成为图像处理、娱乐社交、数字人构建等场景中的关键能力。它不仅要求高保真的面部特征迁移,还需兼顾实时性与易用性。 本文介绍的镜像 unet image Face Fusion人脸融合人脸合成 二次开发构建by科哥,基于阿里达摩院 ModelScope 模型,结合 UNet 架构与 Gradio WebUI,提供了一套开箱即用的人脸融合解决方案。其最大优势在于: * ✅ 无需编码即可使用:通过可视化界面完成全部操作 * ✅ 支持本地部署、隐私安全:所有数据处理均在本地完成,不上传服务器 * ✅ 参数可调性强:融合比例、模式、色彩调节一应俱全 * ✅ 易于二次开发:结构清晰,便于扩展为API服务或集成进其他系统 这种“UNet做核心,WebUI做交互”的技术组合,正成为轻量化AI应用落地的标准范式。 2.

Spring Web MVC 入门秘籍:从概念到实践的快速通道(上)

Spring Web MVC 入门秘籍:从概念到实践的快速通道(上)

个人主页:♡喜欢做梦 欢迎  👍点赞  ➕关注  ❤️收藏  💬评论 目录 一、什么是Spring Web MVC? 1.定义 2.关于MVC 2.1什么是MVC? 二、学习Sring MVC 1.项目准备 2.@RestController注解的介绍 3.@RequestMapping注解 1.@RequestMapping只用在类上(相当于“只给文件夹起名,不给文件起名”) 2.@RequestMapping只用在方法上(相当于“只给文件起名,不给文件夹起名”) 3.@RequestMapping用在类和方法上(相当于给文件夹和文件都取名) 三、Postman 1.什么是Postman? 2.关于API 3.传参介绍 1.普通传参: