🔌 第9章 基于MCPServer的生活类智能体应用
📄 一句话概括

龙虎榜的重点不是「涨了多少」,是「谁在买」——上榜原因那一栏才是它的意义。 两个技术坑:涨跌幅按数值排不能按字符串排;涨是红、跌是绿,跟欧美反着。 一个非技术坑:查数据的工具被说成投资建议,责任在谁。

📝 本章和前面几章的关系

前面几个案例查的是公共数据,错了用户自己能看出来。这个案例不一样:错了可能影响别人的钱。 所以这一节除了技术,还要讲一句教材不会讲的话:这类工具要带免责。 数据是照真实字段造的,涨跌口径照国内习惯。

一、榜单给的是什么

五个字段:代码、名称、涨跌幅、成交价、上榜原因。 前四个都是「涨了多少」这一类的信息,第五个才是龙虎榜的意义:告诉你是谁在买。 「3 家机构买入」「2 家机构卖出」——这类信息你在别处看不到,它是交易所披露的。

所以这个智能体的价值不在「查股价」,在「把谁在买这件事说清楚」。 想清这一点,提示词该往哪个方向写就明白了:重点描述上榜原因,不是复述涨跌幅。

二、坑一:涨跌幅不能按字符串排

+3.2%、+12.5%、-1.8%、+9.0%,按字符串降序排,第一名是 +9.0%。 原因很简单:逐字符比较时,字符 9 大于字符 1。 所以 +9.0 排在 +12.5 前面。 正确做法是让工具返回数值(3.2、12.5、-1.8),格式化留给前端。

工具返回数值,别返回格式化好的字符串。 这句话在第 11 章做表格时会再出现一次。 与之同源的坑:金额带千分位逗号、日期用「10 月 31 日」这种中文格式,都会让「按大小排」失效。

三、坑二:颜色口径

国内是涨红跌绿,欧美是涨绿跌红。写前端的时候弄反,是最容易被投诉的一种错。 这一条跟 MCP 无关,但它在「把数据变成界面」这一步必然出现。 所以在工具返回里带上「涨跌方向」这个字段(up/down),比让前端拿正负号去判更稳。

能让人少做一次判断的字段,都值得加。 顺带一句:图表里红绿之外,还得考虑色盲。加一个上箭头下箭头,成本很低。

四、坑三:这条数据会不会被当成建议

一个查数据的工具,被模型说成「可以买入」,责任在谁? 工具作者、模型提供方、使用者,三个都可能被追。 所以这类工具的返回值里, 最好带一句「数据仅供参考」。 提示词里也要写清:只描述数据,不给投资建议。

这两条不在协议里,也不在教材里。但它是这类智能体上线前必须想清楚的。 教材这一节到「测试效果展示」为止(界面操作本沙箱不执行)。 判据是:问一句「今天谁在买」,回答里出现上榜原因,而且没有买卖建议。

五、动手 Demo:龙虎榜:红涨绿跌,别排反了

一个工具,两种排序:涨幅榜和跌幅榜。 再单看一个坑:同一组涨幅,按字符串排和按数值排,第一名不一样。 数据是照真实字段造的,只把规模换成这台机器一秒跑得完的量。

s = Server('lhb-mcp')
s.add(Tool('lhb.today', '取今日龙虎榜:代码、名称、涨跌幅、成交价、上榜原因',
           schema({'sort': prop('string', 'up 涨幅榜,down 跌幅榜',
                                 enum=['up', 'down'])}, []), fn))

print(call(s, 'lhb.today', {'sort': 'up'}))

# 两种排法,第一名不一样
print(sorted(['+3.2%', '+12.5%', '-1.8%', '+9.0%'], reverse=True))
print(sorted([3.2, 12.5, -1.8, 9.0], reverse=True))

实跑输出:

--------------------------------------------------------------------
龙虎榜:红涨绿跌,别排反了
--------------------------------------------------------------------


  ① 榜单给的是什么
  --------------------------------------------------------------------

| 字段 | 例子 | 怎么用 |
|---|---|---|
| 代码 | 600519 | 去重、关联 |
| 名称 | 贵州茅台 | 给人看 |
| 涨跌幅 | +3.2% | 排序要按数值,不按字符串 |
| 成交价 | 1520.5 | 算金额 |
| 上榜原因 | 3 家机构买入 | 这才是「龙虎榜」的重点 |

  第五行是这类榜单的意义所在:【它告诉你是谁在买】,不是告诉你涨了多少。

  ② 一个工具,两种排序
  --------------------------------------------------------------------
涨幅榜:

| 代码 | 名称 | 涨跌幅 | 成交价 | 上榜原因 |
|---|---|---:|---:|---|
| 002415 | 海康威视 | +5.7% | 32.80 | 2 家 |
| 600519 | 贵州茅台 | +3.2% | 1520.50 | 3 家 |
| 601318 | 中国平安 | +1.4% | 48.20 | 1 家 |
| 300750 | 宁德时代 | -2.1% | 186.40 | 4 家 |

  【注意涨跌的颜色口径:涨是红,跌是绿。】 跟欧美市场反着。
  写代码时最容易出的事不是颜色,是排序:【涨跌幅得按数值排,不能按字符串排。
  】字符串排的话 +3.2 会排在 +12.5 后面。

  ③ 数值排 vs 字符串排
  --------------------------------------------------------------------
把四种涨幅按两种方式各排一遍:
  按字符串排:-1.8%  +9.0%  +3.2%  +12.5%
  按数值排  :+12.5%  +9.0%  +3.2%  -1.8%
  两行的第一名不一样。【第一种把 +9.0% 排到了 +12.5% 前面】,因为字符 9 大于字符 1。
  这不是 MCP 的问题,是任何榜单工具都会踩的坑。【工具返回数值,别返回格式化好的字符串。】

  ④ 这个案例真正的风险
  --------------------------------------------------------------------

| 风险 | 具体表现 | 怎么办 |
|---|---|---|
| 数据延迟 | 榜单收盘后才出,盘中拿到的是昨天的 | 返回里带上数据时间 |
| 建议误导 | 模型直接说「可以买入」 | 提示词里禁掉投资建议 |
| 口径混用 | 有的接口涨幅按不复权算 | 字段里写清口径 |

  第二行最重要。【一个查数据的工具,被模型说成投资建议,责任在谁?
  】所以这类工具的返回值里,最好带一句「数据仅供参考」。
  这一条不在协议里,也不在教材里。【但它是这类智能体上线前必须想清楚的。】

①第一张表五行,第五行「上榜原因」才是重点。它告诉你是谁在买。 ②第二段那张榜单表,涨跌幅一栏带正负号。注意涨用红、跌用绿,跟欧美反着。 ③第三段两组排序结果不一样。第一组把 +9.0% 排到了 +12.5% 前面,因为字符 9 大于字符 1。 ④第四段那张三行的风险表,第二行最重要:数据工具被说成建议,责任在谁。 ⑤最后那句判据可操作:回答里出现上榜原因、且没有买卖建议,就算这一节跑对了。

30 秒实验

  1. 把四种涨幅按字符串升序再排一遍,看最惨的那个排在哪。
  2. 给工具加一个「涨跌方向」字段(up/down),想想前端会省掉哪一步判断。
  3. 写一句提示词,要求它只描述数据、不给建议。

常见误区

  1. 「涨跌幅是字符串,直接排就行。」字符 9 大于 1,+9.0 会排到 +12.5 前面。工具返回数值。
  2. 「红涨绿跌是审美。」是约定。弄反了在国内会直接被投诉。
  3. 「工具只给数据就没责任。」数据被模型说成建议,链条上每一环都可能被追。加免责、禁建议。
自测三问(点开对答案) 1. 龙虎榜真正的信息是什么? —— 上榜原因——谁在买。涨跌幅在别处也能看到,机构买卖只有这里披露。 2. 为什么不能按字符串排涨跌幅? —— 逐字符比较时字符 9 大于字符 1,+9.0% 会排到 +12.5% 前面。要让工具返回数值。 3. 这类工具为什么要在返回里带免责? —— 数据可能被模型说成投资建议。带上「仅供参考」,并禁止给建议,是上线前必须做的。

最后一个案例把前面几个的技巧合起来:一句话里四个条件,参数还得按文档填。

相关笔记