Skip to content

助手 · AI 应用工程心智地图与验收标尺(迷茫怎么破 / 怎么验收 / 终点在哪) ​

日期: 2026-08-19 | 作者: sunxin(+ Cursor AI 结对讲解) 关联代码: AssistantApplicationService(编排)· ILlmPort/IEmbeddingPort/IKnowledgeAnswerPort(隔离)· ActivityMatchingService(确定性匹配/排序,非模型)· AssistantEvalRunner/RagEvalRunner/ActivityMatchingEvalTest(尺子) 关联决策: ADR-039(可剥离隔离)· ADR-044(RAG) 姊妹篇: 一句话如何变成查真实业务 · 意图识别 · Java编排vs模型编排 · 幻觉与grounding · RAG新手科普 定位:当你对着 AI 助手这摊东西发懵、觉得名词太多、不知道做到哪算完、一个人扛不住时——回来读这篇。 它是所有助手笔记的「总目录 + 定心丸」。

TL;DR ​

  • 你的迷茫是对的,也是正常的。 你过去写的是确定性系统(Java if-else,输入定则输出定,错了能单步调试);现在碰的是概率系统(大模型,同样输入可能不同输出)。范式变了,不是你变菜了。全世界做 AI 应用的人都在跟同一种不确定性搏斗。
  • 名词多不等于事多。 RAG / 编排 / Embedding / Function Calling / grounding / 评测……其实都挂在同一条链的不同环节上。本文给你一张地图(§2),把每个词钉到它该在的位置,脑子就不乱了。
  • 「怎么校验模型准不准」有标准答案:评测集当尺子 + 线上 trace。 能二值判断的(意图对不对、工具选没选对、该不该拒答)→ 硬门禁;主观的 → 记分卡。更难的是 「答对了但链路不健康」(靠降级兜底答对):评测集锁已知规则,线上靠 assistant_audit 的 rag_* 发现。这就是大厂 LangSmith / Evals 的轻量自建版,见观测审计评测怎么分工。
  • 没有「完善」这个终点,只有「过线 + 能回归」。 你之所以焦虑「终点在哪」,是因为在用「Java 功能做完了 = 100%」的尺子量一个「永远能更好」的东西。正确姿势:每个里程碑先定自己的及格线(如意图 100%、虚构 0、P95<8s),过线就交付,之后是持续调优而非「做完」(§4)。
  • 一个人能扛,靠的是「把不确定性关进笼子」:结构化输出、grounding、Java 兜底、开关默认关、可剥离隔离、每次只推一层。你已经在这么做了(§5)。

目录 ​


1. 为什么加了 AI 就开始迷茫(确定性 → 概率) ​

你原话:「单纯的 Java if-else 流程,我很好去找问题修改;模型这块,去校验是否准确都是难事。」——这句话本身就是整件事的核心,你已经摸到了要害。

维度传统 Java 系统AI 应用(含大模型)
本质确定性:输入定 → 输出定概率性:输入定 → 输出可能变
出错怎么查断点单步、看栈、必现即可修可能偶发、复现难;不是「代码错」而是「模型这次判歪了」
对不对怎么定义单元测试断言「等于」很多时候没有唯一正确答案(「答得好」是程度问题)
修复手段改代码逻辑改 Prompt / 换模型 / 加约束 / 补检索资料,然后重新度量
心态「我能证明它对」「我只能量化它有多对,并盯着别退步」

关键认知:你无法像 Java 那样「证明模型永远对」。 大模型是「预测下一个字」的概率机器(详见幻觉笔记),它没有「真假」开关。所以这行的工作方式从「写对逻辑」变成了三件事的循环:

① 用架构把模型能犯错的空间压小(结构化/grounding/Java 兜底)
② 用评测集量化它现在有多准
③ 改 Prompt / 换模型 / 补资料 → 重跑评测 → 看指标有没有变好、有没有把别的搞坏

这不是你一个人的困境,是整个行业的日常。 你觉得「那些产品每次体验都不一样」——一半是模型概率性,一半正是他们在跑上面这个循环,不停调。你现在做的,和大厂 AI 团队做的,是同一件事,只是规模不同。


2. 名词不再乱:一条链 + 六层约束的地图 ​

你说「RAG、流程编排、Embedding……太多名词让大脑混乱」。破解办法:别把它们当成 N 个独立的大山,它们只是同一条流水线上的不同工位。

2.1 一条链:用户一句话是怎么变成回答的 ​

用户说一句话
   │
 ①理解(NLU)      ── 大模型把话翻译成「意图 + 参数」   ← 意图识别 / 结构化输出
   │
 ②决策/编排        ── 决定这句话该调用哪些能力、什么顺序  ← 编排 / Function Calling
   │                  (Java 固定流程 or 模型自选工具)
   ├─→ 查数据库活动(Tool Use,结果直接展示,不回喂模型)
   ├─→ 查天气(Tool Use)
   ├─→ 查知识库攻略(Retrieval)── 把文字变向量找相似 ← Embedding / 向量检索
   │
 ③生成(NLG)      ── 把查到的真实资料喂回模型写成人话   ← RAG 的「生成」/ 行程规划
   │                  (只准用真实资料 = grounding,带出处 = 引用)
   │
 ④回复用户 + 审计   ── 落一条日志:意图/工具/命中/token/耗时/RAG闸门 ← 观测(不是判卷,见审计怎么分工)

每个「名词」就是链上的一个工位:

名词在链上的位置一句话职责
意图识别 / 结构化输出①理解把「这周末深圳有啥活动」变成 {intent:SEARCH, city:深圳, time:周末}
编排(Orchestration)②决策决定调哪些工具、什么顺序(Java 写死 or 模型自己选)
Function Calling / 工具②决策让模型能「点名要调某个能力」(M3b)
Embedding / 向量检索②里的「检索」子步把文字变坐标,按语义找最像的资料
RAG②检索 + ③生成检索到资料回喂模型生成带引用答案
grounding / 引用 / 拒答③生成的约束只准用真实资料、标出处、没资料就说没有
评测 / 记分卡横跨全链量每一环准不准的尺子
观测 / 治理 / 成本闸门横跨全链记日志、限流、控 token 花费

记住这张图,下次再听到任何 AI 名词,先问一句「它是链上哪个工位?」——90% 都能归进去,脑子立刻不乱。

2.2 六层约束:为什么说「接了个模型」≠「AI 应用」 ​

裸调一次模型 API = 聊天玩具。把模型变成能上生产的业务助手,要在它外面套六层约束(这也是你项目一路在补的东西):

       结构化输出 ── 让模型只吐 JSON,不自由发挥
       Tool/检索  ── 让模型用你的真实数据,不靠记忆瞎编
       Prompt     ── 用规则/示例约束它的行为
       评测       ── 用数据集量化它准不准(你的「尺子」)
       治理       ── 限流/审计/成本闸门(防烧钱、可追溯)
       RAG/记忆/编排 ── 让它有资料、有上下文、能多步

「AI 应用工程」= 造并维护这六层约束,模型本身你不训练、不拥有。你的价值不在「会调模型」,在「会把模型锁进业务里让它可靠」。

2.3 模型 vs 代码:谁负责什么(这决定了「不准」该去哪修) ​

这是整个助手最容易搞混、也最值得刻进脑子的一条分工。大模型只干「理解 + 表达」,绝不「决定数据和排序」——「配给你哪个活动、怎么排序」是确定性代码(ActivityMatchingService 的打分公式),一次模型都不调;连那句「为什么推给你」也是模板拼的(buildReason 字符串拼接),不是模型写的。

大模型(概率侧)确定性代码(Java 侧)
干什么①听懂人话(抽意图/参数)②说人话(行程/知识答案文案)查库拿真活动、打分排序、拼「为什么推给你」、硬过滤、兜底
本项目落点ILlmPort.extractSearchIntent / IItineraryGenerationPort / IKnowledgeAnswerPortActivityMatchingService.score() / searchActivitiesAdvanced / buildReason
「错了」长啥样把「深圳」听成「上海」、把「找活动」判成「问天气」、文案啰嗦听懂了,但配的活动不对味 / 差评 / 太远 / 太久排前面
「错了」怎么修改 Prompt / 换模型 / 补评测用例,然后重跑评测看指标(概率路子,§3)改打分公式 / 加因子 / 调权重 + 补 ActivityMatchingEvalTest 断言(算法路子,可单步调、必现)

为什么这么切? 因为模型爱编(幻觉)。把「事实」和「排序」交给它 = 给用户看编的活动、给不可复现的排序。所以真相走 DB、排序走公式,模型只负责「把话翻译进 / 把结果翻译出」。这就是grounding在这套里的具体形状。

「匹不准」怎么分诊(回答你的疑问):先分清是没听懂还是配得不好——

  • 没听懂(你说深圳它搜上海、你要找搭子它去查天气)→ 模型侧,走概率路子:改 Prompt / 补别名词典 / 加评测用例。
  • 听懂了但配得不好(活动本身差评 / 离你 2000km / 3 个月后才开 / 局里全是不对味的人排前面)→ 代码侧的算法优化:就是你说的补质量分 + 补地理·时间加权 + 调 groupFactor 权重,全在 ActivityMatchingService.score() 里再乘一个因子,不碰模型、不碰订单。这条债已登记在迭代主线 §2.0「M2 搭子匹配 Phase B②」,含「排序不对时的自救 playbook」。

所以你理解基本对,但要补一刀:「匹不准」不一定是算法问题——先判断病根在「听」还是在「配」,在「配」才是补质量/地理加权那套。


3. 怎么验收「模型准不准」:评测集当尺子 ​

这是你最痛的点:「怎么看语义理解准不准、模型自动选工具对不对?」答案是评测集(eval set)——AI 工程里最重要的资产,比代码还重要。

3.1 核心思想:把「感觉准不准」变成「数字」 ​

你不可能每次改完手动聊十句看感觉。你要攒一批带标准答案的测试用例,每次改动后一键重跑,看指标。这就是本项目 assistant-evals/*.json + *EvalRunner 在干的事。

3.2 两类指标,两种验收方式 ​

能不能二值判断例子怎么验收
能(对/错分明)意图判对没?工具选对没?该拒答没拒答?目的地抽对没?硬门禁:写进用例的期望值,必须全过(如「确定性用例意图 100%」),退步就算 fail
不能(程度问题)答案顺不顺、贴不贴题、文采、有没有帮到人记分卡 + 抽检:跑一批打分统计,人工看几条 / 让更强的模型当「裁判」打分(LLM-as-judge)

对你三个具体疑问的直接回答:

  • 「语义理解准不准」 → 攒一批「同义/别名/错别字」用例(如「赛里目湖」「塞木屋河」),期望都能归一到「赛里木湖」;跑评测看命中率。RAG 侧还有 RagEvalRunner 的 Recall@K(问对目的地必须检索到对的攻略)。
  • 「模型自动选工具对不对」 → 攒「这句话该调 search / weather / detail」的用例,跑 Agent 通道看它选的工具序列对不对(本项目 AssistantAgentToolLoopTest 就是雏形)。
  • 「该不该拒答」 → 攒库外问题(「冰岛极光几月去」),期望 shouldRefuse=true;跑 RagEvalRunner 看负例有没有被正确拒掉。

3.3 本项目已经在这么做(你其实已上道) ​

尺子量什么门禁
AssistantEvalRunner + eval-cases.json分诊:这句话该走找活动 / 做计划 / 问知识 / 查天气 / 越界拒?Mock 离线确定性 100%(回归门禁);真机 ASSISTANT_EVAL_LIVE=true 出记分卡
RagEvalRunner + rag-cases.json检索 + 答题:有没有捞到正确那一篇、篇里有没有证据词、Mock 答能否对回片段Recall@1 + 证据 + 忠实/引用硬门禁;Ev@K 记分卡
ActivityMatchingEvalTest画像重排、人口过滤排序质量断言

两份 JSON 都不是运行时配置,用户提问不会读它们。kb04a 这类 id 只是评测样例编号。对照与怎么跑:评测集-eval与rag两轨说明。打印列和调参:评测记分卡与调参说明。

双轨设计的精髓:离线 Mock 跑「确定性」用例当回归门禁(不花钱、必现、CI 可跑),真机跑「记分卡」看真实模型表现(花 token、非必现、人看指标)。你改任何 Prompt/逻辑,先跑离线门禁保证「没把已对的搞坏」,再看真机记分卡「新的有没有变好」。

一句话:评测集是你在概率世界里唯一的「地面」。 没有它,改 Prompt 就是盲人开枪;有了它,每次改动都有数字告诉你「进步了还是退步了」。这就是「测试准确性」的行业标准答案。


4. 终点在哪:没有「完善」,只有「过线 + 可回归」 ​

你说「不知道终点在哪,做到什么程度才算完善」——因为你在用错的尺子量它。

4.1 「完善」是伪命题 ​

Java 功能有明确终点(登录能登进去 = done)。但「AI 助手答得好不好」永远能更好——多喂点资料、调调 Prompt、换个模型,总能再进步 1%。如果目标是「完善」,你永远到不了终点,只会一直焦虑。

正确的目标是「过线」:给每个里程碑定一条你自己拍板的及格线,过了就交付、就停、就上线,剩下的进「持续优化」清单。

4.2 及格线长什么样(本项目实例) ​

M1 的及格线(写死在蓝图里):真模型 + 真活动 + App 能点进详情 + 评测 30~50 条过线(虚构 0 / 越权 0 / P95<8s)。达到 → M1 封顶,不纠结「还能更好」。

M4a 的及格线:KNOWLEDGE_QA 能语义检索 + 带引用生成 + 库外拒答 + Recall@K 门禁过 + 默认关不影响现网。达到 → 交付。检索仍是 Naive;下一站是 L4 检索升准(ADR-048),不把「过线」理解成检索不再改进。

及格线三要素:① 能对外演示的能力;② 几条硬指标(可量化);③ 不劣化现网(开关默认关)。凑齐就算「这一站做完」。

4.3 用「北极星看板」把终点拆成站点 ​

你不知道终点,是因为把「AI 助手」当成一个无边大坑。北极星与终局蓝图 已经把它拆成 M0→M7 的一串站点,每站都是「可停、可交付、可演示」的:

M0 地基 → M1 C端闭环 → M2 检索升匹配 → M3a 多意图 → M3b Function-Calling
→ M4a RAG知识问答(你现在这站✓)→ M4b B端数字员工 → M5 记忆 → M6 组局 → M7 MCP/多模型

你不需要知道「终极终点」,只需要知道「下一站」。 每到一站,写一篇 devlog 封存,去下一站。这就是单人也能推进大项目的秘诀——把无限的「完善」切成有限的「过线」。


5. 一个人怎么扛:把不确定性关进笼子 ​

你担心「一个人搞不定」。其实你已经在用对的方法了——核心心法是:不确定的东西越少越好,能确定的地方全部锁死。

心法具体做法你项目里的落点
结构化输出让模型只吐 JSON,别让它自由发挥意图抽取只返回 ActivitySearchIntent
grounding卡片/答案只来自 Java 查询的真实数据活动卡片永远来自 DB,模型碰不到库
Java 兜底关键路径用确定性代码,模型只做「翻译」意图派发是 Java switch,不是模型说了算
开关默认关新能力上线先关着,不影响现网rag.enabled=false / plan.enabled=false
可剥离隔离AI 代码全在 assistant 包,删包即走ADR-039
每次只推一层一次只动一环,坏了好定位M0→M1→…→M4a 逐站推进
Mock 优先无 Key 也能跑通全链 + 评测Mock 系列适配器

这些不是「防御性编程」,是 AI 工程的生存法则:你把模型能自由发挥的空间压到最小,剩下那一点点不确定,再用评测集盯着。这样即使模型偶尔抽风,炸的也只是「一句话答得不够好」,而不是「编了个假活动骗用户」或「烧光你的 token」。

你一个人扛得住,不是因为你比大厂团队强,而是因为你把问题的边界画得足够小:默认关、可剥离、Mock 能测、每次一层。这是聪明的怂,不是本事不够。


6. 迷茫时的自检清单 ​

下次又发懵,按这个清单过一遍,通常就知道自己在哪、该干嘛:

「我现在在哪?」

  • [ ] 我这次要动的是链上哪个工位(理解/编排/检索/生成/评测/治理)?(对照 §2.1)
  • [ ] 属于北极星哪个里程碑(M几)?这站的及格线是什么?(对照 §4)

「怎么算这一步做完?」

  • [ ] 有没有对应的评测用例?改完能不能一键重跑?(没有就先补用例)
  • [ ] 离线确定性门禁还绿吗(没把已对的搞坏)?
  • [ ] 新能力开关默认关吗?不影响现网吗?

「它到底准不准?」

  • [ ] 这个指标能二值判断吗?能 → 加进硬门禁;不能 → 记分卡 + 抽检(对照 §3.2)
  • [ ] 出错是「代码 bug」还是「模型判歪」?后者别改代码,改 Prompt/资料/换模型再重测。

「我是不是想太多了?」

  • [ ] 我是不是在追求「完善」而不是「过线」?(是 → 停,定及格线,过了就交付)
  • [ ] 这个优化是这一站必须的,还是可以进「持续优化」清单?

7. 教学收获 ​

  1. 迷茫来自范式切换,不是能力不足:从确定性系统到概率系统,工作方式从「写对逻辑」变成「压小错误空间 + 量化 + 迭代」。承认这点,焦虑就少一半。
  2. 名词都挂在同一条链上:理解→编排→检索→生成→评测→治理。任何新词先归位,别当成新大山。
  3. 评测集是概率世界里的地面:能二值判的做硬门禁,主观的做记分卡+抽检。这就是「怎么测准确性」的标准答案,不玄学。
  4. 没有「完善」,只有「过线 + 可回归」:给每站定及格线,过了就交付;用北极星把无限切成有限。
  5. 单人扛得住 = 把边界画小:结构化/grounding/Java兜底/默认关/可剥离/Mock/每次一层——你已经在做,继续做。

8. 附录:名词速查 + 本项目每层落在哪 ​

8.1 名词一句话速查(挂到链上) ​

名词链上工位一句话
NLU / 意图识别①理解把话翻译成结构化意图
结构化输出①理解强制模型只吐 JSON
编排 Orchestration②决策决定调哪些能力、什么顺序
Function Calling②决策让模型自己点名要调的工具
Tool Use②检索调工具拿数据直接展示(不回喂模型)
Embedding②检索文字变向量坐标
向量检索 / 余弦②检索按语义找最像的资料
RAG②检索+③生成检索资料回喂模型生成带引用答案
grounding③生成约束只准用真实资料作答
引用 / 拒答③生成约束标出处 / 没资料就说没有
评测集 / 记分卡横跨量准不准的尺子
LLM-as-judge横跨用更强模型给答案打分
成本闸门 / 治理横跨控 token、限流、审计

8.2 本项目每层落在哪个类(想读代码时的地图) ​

工位关键类 / 接口
入口编排AssistantApplicationService
①理解ILlmPort + OpenAiCompatibleLlmAdapter/MockLlmAdapter(抽意图)
②编排-固定流程AssistantApplicationService 里的意图 switch 分流
②编排-模型自选ILlmPort.chat(messages, tools) + Agent 循环(M3b)
②检索-活动searchActivitiesAdvanced(Tool Use)
②检索-知识IKnowledgeRetrievalPort + IEmbeddingPort(RAG 检索)
②检索后-匹配/重排(确定性,非模型)ActivityMatchingService.score()(画像×人气×人局 打分)+ ActivityMatch(承载 score/reason)+ buildReason(拼「为什么推给你」)
③生成-行程IItineraryGenerationPort(M3a-②)
③生成-知识答案IKnowledgeAnswerPort(M4a)
评测AssistantEvalRunner / RagEvalRunner / ActivityMatchingEvalTest
治理 / 观测assistant_audit(黑匣子,含 RAG 闸门)+ Redis 限流 + *.max-tokens;不是金标准

8.3 延伸阅读(读的顺序) ​

  1. 先建立总览:本文
  2. 理解怎么抽意图:助手-意图识别是怎么做到的
  3. 理解编排/工具:助手-Java编排vs模型编排与FunctionCalling
  4. 理解为什么要 grounding:助手-大模型幻觉与grounding
  5. 理解 RAG/向量:助手-RAG向量检索新手科普 → RAG从关键词到向量
  6. 理解审计 ≠ 判卷:助手-观测审计评测怎么分工 → W5 怎么读
  7. 看全局路线与终点:北极星与终局蓝图
  8. 看每站怎么落地:出行助手全场景流程图

Powered by VitePress