从自然语言到正确数据:认知澄清
2026-08-13。回答:步骤是什么、为何禁止 Text-to-SQL、要不要 MCP、要不要训练模型、评测话术干什么、为什么感觉很难。
0. 先纠正最常见的三处偏差
你原来的图景大致是:
系统先提供 MCP
→ 把自然语言翻译成 LLM 能听懂的话
→ LLM 把拿到的数据整理成报告更接近事实的图景是:
用户原话直接进 LLM(LLM 自己就是「理解自然语言」的那一层)
→ LLM 只输出结构化意图 / 选哪个工具 / 填什么参数
→ Java Tool 按白名单去查库、算指标(数据真相在这里)
→ 把「已经算好的表」再交给 LLM 写人话 / 做报告三处偏差:
| 你的理解 | 更准确的说法 |
|---|---|
| 先要有 MCP,AI 才能知道怎么取数 | MCP 只是工具的一种对外协议。对内更常见的是 Function Calling / Tool,本质就是调你已经写好的 Java 方法 |
| 先有一层 NLU,把人话翻译给 LLM | 没有单独的翻译层。LLM 读的就是用户原话;你要约束的是它的输出格式(JSON Intent),不是再发明一种「LLM 语言」 |
| 数据交给 LLM 去整理、分析、出数 | LLM 不负责出数。转化率、退款率必须 Java/SQL 算完,LLM 只解释和润色。否则它会编数字 |
医院挂号 / 营养餐如果看起来像「自己训练了一个模型」,多数其实是:固定流程 + 业务工具 + 提示词(偶尔再加领域微调)。你现在做数据分析助手,不需要训练模型。
1. 一次请求到底走几步
以 B 端这句话为例:
帮我分析五一活动的订单转化情况,重点看退款率异常的产品,最后生成一份运营报告。
步骤 1:接入与鉴权(你的系统,不是 LLM)
用户已登录 Admin。请求带上 userId、角色。后面每个 Tool 都带着这个身份,不能换成超级管理员。
步骤 2:LLM 做「理解」,只输出结构,不碰库
把用户原话 + System Prompt(角色、只允许的意图、JSON Schema、禁止编造)发给模型。期望得到类似:
{
"intent": "CAMPAIGN_EFFECT_ANALYSIS",
"campaignHint": "五一活动",
"period": { "preset": "MAY_DAY_2026" },
"focus": ["CONVERSION", "REFUND_RATE_ANOMALY"],
"deliverable": "OPS_REPORT_MARKDOWN"
}这一步没有访问数据库。模型不知道五一对应哪些 activityId,也不知道退款率是多少。
评测话术(C001、C009…)测的主要就是这一层:意图对不对、槽位抽得对不对、该拒的有没有拒。
步骤 3:Java 补全与校验(确定性代码)
- 「五一活动」可能对应 1 个或 N 个活动 → 不够就追问,或按运营配置的活动集合解析
- 时间窗写成具体日期
- 当前用户有没有权限看这些活动的订单
- 意图若是「取消活动并退款」→ 直接拒绝,不进后续 Tool
步骤 4:按固定工作流调 Tool(仍然是你的代码)
不是让模型即兴写 SQL,而是走已经写死的步骤:
get_campaign
→ query_campaign_orders
→ query_refund_statistics
→ calculate_campaign_metrics // 转化率、退款率在这里算每个 Tool ≈ 一个受约束的 ApplicationService 方法:入参 Schema、权限、超时、审计。
数据正确性的保证在这一层,不在 LLM。 工具返回什么,库里就是什么。LLM 看不到连接串,也拼不出 SELECT * FROM users。
步骤 5:异常用规则标,不用模型「感觉」
例如:退款率 > 20% 或同比 +50% → 标 SEVERE。阈值写在代码或配置里。
步骤 6:LLM 第二次出场——只看表,写报告
把 已经算好的 JSON/表格 塞进 Prompt:
以下数据由系统计算,禁止改数字、禁止补充表中没有的活动。
[metrics table]
请用中文写运营报告:结论、异常产品、可能原因(仅基于表内字段)、建议。模型可以写「A 活动退款率 28%,高于阈值」,不能把 28% 改成 12%,也不能发明一个不存在的产品。
步骤 7:人确认后保存
报告预览 → 运营点确认 → 落库。这是企业助手能上线的关键,不是可选装饰。
2. 为什么反复说「不要 Text-to-SQL」
Text-to-SQL = 让模型根据人话直接生成 SELECT ... 打生产库。
问题:
- SQL 很容易错:JOIN 漏了、时间区切错、把「转化率」写成订单数/UV 的错误分母
- 不安全:提示注入可以诱导出
DROP/ 扫全表 / 读手机号(你评测里的 C012) - 口径漂移:今天一种 SQL,明天另一种,报表对不上
- 权限难做:模型生成的 SQL 很难按「这个运营只能看自己负责的活动」过滤
正确替代:
人话 → Intent JSON → 白名单 Tool → 你写好的查询/聚合模型选的是 query_campaign_orders(campaignId, start, end) 这种函数,不是任意 SQL。
这和你平时写 Controller 调 ApplicationService 是同一件事,只是触发方式从「点按钮」变成「说话」。
C 端同理:不是「帮我写一段查活动的 SQL」,而是填 ActivitySearchCriteria 再调已经存在的 searchActivitiesAdvanced。
3. MCP 是什么、要不要「全部 MCP」
Tool / Function Calling(你真正要用的)
模型 API 支持:你声明一批函数(名字、描述、参数 JSON Schema),模型返回「我要调哪个、参数是什么」,你的服务器执行后再把结果喂回模型。
对接 TourMate:
AssistantApplicationService
→ ILlmPort(Spring AI)
→ SearchActivitiesTool / GetCampaignTool
→ 现有 IActivityQueryApplicationService 等这就是嵌入当前系统的默认方式。不是 MCP。
MCP(可选外壳)
MCP 是一套开放协议:让 Claude Desktop、Cursor 等客户端,用统一方式发现和调用你的工具。
Tool Use = 业务能力(查活动、查订单)
MCP = 把这些能力暴露给「别的 AI 客户端」的插头类比:你已经有 REST API;OpenAPI 是说明书;MCP 有点像「给 Agent 用的说明书 + 调用约定」。
| 阶段 | 用什么 |
|---|---|
| C 端 / B 端助手嵌在 TourMate 里 | 主站内 Function Calling + Java Tool |
| 想让 Cursor / Claude 也能查旅搭订单 | 再包一层 tour-mate-mcp-server |
| 一上来全部 MCP | 不建议:多一层鉴权、部署、排障,对内聊天框没有收益 |
「计划去新疆的出游」不是「做一个 MCP 就完了」。MCP 最多暴露 search_activities、get_weather 这类工具;真正难的是:槽位是否抽对、无结果怎么问、卡片是否真实、用户会不会点进去。工具只是零件。
4. 医院挂号 / 营养餐:多半不是「从零训练了一个大模型」
你看到的产品,常见组合是:
| 能力 | 通常怎么做 |
|---|---|
| 听懂「7 天营养餐」「嗓子痛」 | Prompt + 结构化输出;有的会做小规模微调(分类/抽槽) |
| 列出真实餐品 / 可挂医生 | Tool 查库存/号源,和是否微调无关 |
| 合计金额、支付、按日派单 | 原订单系统,模型不碰钱 |
| 独立服务器上的 Qwen / DeepSeek | 多数是 部署开源权重做推理(自托管),不等于「用你们业务数据训练出一个新模型」 |
三种容易混的词:
| 说法 | 含义 | 你现需要吗 |
|---|---|---|
| 调用模型 | HTTP 调 Qwen/DeepSeek/OpenAI | ✅ 要 |
| 自托管开源模型 | GPU 上跑 vLLM 等,数据不出机房 | 可选,后期成本/合规再考虑 |
| 训练 / 微调 | 改模型权重(SFT、LoRA) | ❌ 第一期不要 |
判断是否微调:Prompt → 结构化输出 → RAG → Tool → 工作流,都解决不了再评估。
数据分析、活动检索都属于「知识在库里、口径在代码里」——微调帮不上忙,还引入数据集和评测地狱。
5. 怎么保证 LLM 拿到的是正确数据?
不靠「相信模型」,靠 管道设计:
- 模型拿不到库。 它只能调用你声明过的 Tool。
- Tool 返回的就是查询结果。 正确性 = 你现有
searchActivitiesAdvanced/ 订单聚合对不对(跟有没有 AI 无关)。 - 第二次调用时只喂表,并写死「禁止改数字、禁止补行」。
- 报告里带出处。 「转化率 12.3%(订单 32 / 曝光 260,来源 query_campaign_orders)」——人可以点开对账。
- 对账抽检。 同一活动用助手出的数 vs Admin 报表页,必须一致。不一致就是 Tool/口径 bug,不是「模型不够聪明」。
C 端更硬:活动卡片的 activityId/title/price 必须来自 Tool 返回值 原样拷贝,禁止模型重写标题或编一个 id。
6. 怎么保证每次结果差不多一致?评测话术是不是在测这个?
LLM 默认 非确定性(温度、措辞都会变)。企业做法是分层:
| 层 | 要稳定的东西 | 怎么保证 |
|---|---|---|
| 意图 / 槽位 | 「五一 + 转化 + 退款异常 + 要报告」 | 结构化输出 + 低温度 + 评测话术 |
| 工具选择 | 调了该调的 Tool、没调禁止的 | 评测:是否 call tool、参数对不对 |
| 数字 | 转化率、退款率 | 代码计算,与 LLM 无关;同一输入同一输出 |
| 报告文案 | 可以略有出入 | 不要求逐字相同;要求不改数、不编活动、结构完整 |
| 拒答 / 安全 | C009 写游记、C012 要手机号 | 评测集必须覆盖 |
所以:
- 评测话术 = AI 应用的测试集(测理解、抽槽、拒答、是否乱调工具)
- 它不测「报告是否每个字一样」,也 不测「数据库算得对不对」(那是单测/对账)
- 数字一致性靠 Java;理解一致性靠评测 + 固定 Schema;文案允许轻微波动
同一句话跑 10 次:Intent JSON 应几乎一样;报告用词可以不同,但表中的 28% 必须还是 28%。
7. 为什么感觉很难?难的不是 MCP
难的是 约束一个会胡说的模型,去驱动一个已经正确的业务系统:
- 边界:什么能查、什么必须拒、什么要人点确认
- 槽位:用户说半句时追问,而不是猜错时间去查
- 口径:转化率分母是曝光还是报名,必须唯一
- 评测:50 句话里越权 0、虚构 0
- 体验:慢、贵、用户以为万能
容易的部分你已经有了:活动搜索、订单、退款、权限、DDD Port。
助手只是新开一扇「用说话触发这些 Port」的门。
C 端 MVP 甚至更窄:
人话 → Intent → ActivitySearchCriteria → searchActivitiesAdvanced → 卡片 + deep link这里连「第二次让 LLM 写长报告」都可以极短(一句话复述条件即可)。
B 端「五一分析」才需要工作流 + 二次生成;仍然 不是 先上 MCP、也 不是 先训练模型。
8. 嵌进当前系统:推荐对接图(不是全部 MCP)
App / Admin 对话 UI
→ POST /api/assistant/chat (Trigger)
→ AssistantApplicationService
├─ ILlmPort.structured(用户原话) → Intent
├─ 校验权限、补默认时间
├─ ToolDispatcher
│ search_activities → IActivityQueryApplicationService
│ get_campaign / query_orders / query_refunds → 现有查询
│ calculate_metrics → 纯 Java
└─ (可选)ILlmPort.report(指标表) → Markdown
→ 卡片 / 报告预览- 第一期:零 MCP、零微调、零 Text-to-SQL
- 模型:先云端 API(通义/DeepSeek 等);自托管是运维选项
- MCP:仅当需要被 Cursor 等外部 Agent 复用同一批 Tool 时再做
9. 一句话对照表
| 问题 | 答案 |
|---|---|
| 自然语言怎么变成数据? | LLM 抽 Intent → Java Tool 查数/算数 → (可选)LLM 写人话 |
| 要 MCP 吗? | 对内不要;Tool Calling 就够 |
| 要训练模型吗? | 不要;要的是正确 Tool + 评测 |
| 数据对不对? | 看 Tool 是否复用现网查询;报告禁止改数 |
| 结果稳不稳? | 数字靠代码;理解靠评测话术;文案允许略变 |
| 出游计划是不是就是 MCP? | 不是。MCP 只是插头;计划能力是流程 + 工具 + 产品边界 |