在搜索框里输入“示例队甲主场本赛季平均控球率是多少”,传统搜索引擎会交给你十个蓝色链接:一个是球队主页,一个是三年前的赛后报道,一个是某个论坛的讨论帖,还有两个是数据网站的入口。你需要逐个点开,找到对应的表格,再自己判断哪一列是“主场”、哪一行是“本赛季”。这条路走得通,但它默认了一件事:答案已经写在某个网页上。而体育数据的很多问题,答案根本没有写在任何网页上,它只存在于“对若干场比赛的记录做一次筛选和聚合”之后。半岛体育AI要解决的,正是这类问题:让搜索在该给链接的时候给链接,在该计算的时候直接计算。
先做分诊:哪些问题该给链接,哪些该直接算
“直接给答案”并不是对链接的取代。把体育搜索的问题分一下类,会发现两类需求的性质完全不同,处理方式也应该不同。
| 用户问题(示例) | 答案的形态 | 更合适的处理 |
|---|---|---|
| 某项规则最近一次修订了什么 | 一段有出处的文字 | 检索文档,给摘要加原文链接 |
| 某支示例队的历史沿革 | 叙述性资料 | 检索资料页,给链接 |
| 球员A最近10场平均出场时间 | 一个由记录算出的数字 | 查结构化数据库,直接计算 |
| 示例队乙客场失球最多的月份 | 分组聚合后的排序 | SQL 聚合,返回小表格 |
| 某教练执教期间转会走的球员有哪些 | 多跳关系的一组实体 | 图查询,返回名单加时间区间 |
| 某场比赛的战术是否偏保守 | 带主观判断的分析 | 先给数据,再明确标注为解读,配相关报道链接 |
这张表背后的判断标准很朴素:答案是“被找到的”,还是“被算出来的”。规则条文、赛事公告、人物介绍属于前者,它们是别人写好的文字,搜索的价值在于找得准、排得对、给出处。最近10场平均值、分组排名、多跳名单属于后者,它们是对记录的运算结果,任何网页都可能过时或口径不同,用户真正需要的是“按我这个条件现算的结果”。
一个十个链接解决不了的问题
看一个具体的场景,下面所有数字都是示例数据。用户输入:“前锋林某(虚构示例)最近8场在客场的射门转化率”。
如果只走链接式搜索,能拿到的大概是球员的资料页、几篇赛后综述和一个季度汇总表。汇总表里有“射门转化率”,但那是整个赛季、主客场合并的数字。用户要的三个条件——最近8场、客场、射门转化率——没有一个网页恰好按这个组合做过统计。用户只能打开比赛列表,自己数场次、自己挑客场、自己拿进球数除以射门数。绝大多数人在第二步就放弃了。
如果走直接计算,系统需要做的事情其实很确定:识别“林某”对应哪个球员编号;把“最近8场”翻译成“按日期倒序、只取该球员有出场记录的比赛、限8场”;把“客场”翻译成主客场字段的过滤;把“射门转化率”翻译成进球数之和除以射门数之和。注意最后一步,是先各自求和再相除,而不是把每场的比率取平均,这两者在样本场次射门数差别很大时结果会明显不同。这类口径问题,链接式搜索完全没有介入的空间,直接计算却必须显式地做出选择。
直接答案的三个前提
想把“给出答案”这件事做得让人放心,至少要满足三个前提,缺一个都不应该直接给数字。
前提一:问题能被落到结构化数据上
系统首先要判断这个问题有没有对应的表和字段。“林某射门转化率”落在球员比赛技术统计表上,字段齐全;但“林某那场比赛跑位是不是很聪明”就落不到任何字段。前者可以计算,后者只能给相关报道和录像资料的链接,并如实说明“没有可直接计算的数据”。
前提二:条件能被明确地解析
“最近8场”“客场”“射门转化率”三个条件都必须被解析成可执行的过滤和聚合。只要有一个词含糊,比如用户写的是“最近状态”,系统就应该先反问或者明示自己采用的口径,而不是悄悄挑一个。关于这一点,半岛体育在拆解复杂体育搜索的那篇文章里有更细的说明。
前提三:结果能被回溯
直接给数字的风险在于用户没法验证。所以答案旁边要能看到:用了哪8场、数据更新到哪一天、转化率是怎么算的。没有这些信息的数字,比十个链接更容易误导人,因为链接至少让用户自己面对原始来源。这也是半岛体育给答案增加“证据链”的原因,详细设计可以看答案溯源这一篇。
用一段查询看“直接计算”到底做了什么
同样是上面那个问题,落到示例表上,查询大致是下面的样子。表名和字段都是为了说明而设计的示例。
SELECT COUNT(*) AS games,
SUM(goals) AS goals,
SUM(shots) AS shots,
ROUND(SUM(goals) * 1.0 / NULLIF(SUM(shots), 0), 3) AS conversion
FROM (
SELECT g.game_date, s.goals, s.shots
FROM player_game_stats s
JOIN games g ON g.game_id = s.game_id
WHERE s.player_id = 'P_0421'
AND s.side = 'away'
AND s.minutes > 0
ORDER BY g.game_date DESC
LIMIT 8
) recent;
这里有几个值得指出的小细节。minutes > 0 排除了没有出场的比赛,否则“最近8场”会把坐板凳的场次也算进去;NULLIF 防止射门数为零时出现除零错误;先在子查询里取够8场,再在外层求和。至于“客场”是先过滤再取8场,还是先取最近8场再看其中客场有几场,是两种完全不同的问法,前者是“最近8个客场”,后者是“最近8场里的客场”。这个歧义系统必须识别出来。用户的原话“最近8场在客场的”更接近后一种,但也可能是前一种,这时候系统的正确做法是把采用的理解写在答案里。
混合型问题:先给答案,再给链接
现实中的问题经常是混合的。比如:“林某最近是不是在客场更容易进球?为什么教练换了打法?”前半句可以计算,后半句是解释,需要文字类资料支撑。
比较合理的呈现顺序是三段。第一段是可以计算出来的事实:最近若干场里客场与主场的进球、射门、上场时间对比,用一张小表格。第二段是明确的边界声明:“换打法”这件事没有对应的结构化字段,下面只是相关报道,不是系统计算的结论。第三段才是链接列表,并且每条链接用一句话说明它为什么相关,而不是只列标题。
这种“计算部分”和“检索部分”并排、但标注分开的做法,比让大模型把两者揉成一段流畅的文字要可靠得多。流畅的文字会让读者误以为“为什么换打法”也是计算出来的。半岛体育AI的设计思路里,一直坚持把“数据发现”与“文字解读”在版面上分开。
直接答案可能错在哪里
既然强调直接给答案,就必须诚实地说,它比链接更容易“错得很自信”。几种典型的失败方式:
- 实体认错。用户输入的名字对应多个球员,系统选错了一个,后面的计算再精确也是白费。所以名字有歧义时应该先让用户确认,具体思路见实体识别那一篇。
- 时间窗口偏了。数据库的最新记录停在几天前,用户以为“最近8场”包含昨天的比赛,实际并不包含。答案里必须写数据截止日期。
- 口径差异。“射门”是否包含被封堵的,“进球”是否包含点球,不同数据来源定义不同。答案要说明采用的是哪一套定义。
- 样本太小。8场里客场只有2场,射门转化率的数字看上去很具体,参考价值却很有限。系统应该在样本量很小时给出提示,而不是把小数点后三位摆出来。
- 问题本身不可计算。用户问的是主观判断,系统却硬凑了一个指标来回答。这类问题宁可退回到链接。
这些风险没有一条是靠“换一个更大的模型”就能自动消失的,它们要靠数据结构、解析规则和展示方式共同约束。任何声称能够完全避免这些错误的说法都不可信,半岛体育在产品设计里能做的是让错误更容易被发现,而不是假装错误不存在。
搜索框真正该做的,是判断用户想要哪一种东西
回到最初那个问题:体育搜索为什么不该只返回十个蓝色链接?因为链接只是答案的一种形态,而且恰好是最不适合数字型问题的一种。但反过来,把所有问题都改成“直接给答案”同样危险,规则解读、历史资料、战术评论这类内容,链接加摘要仍然是最诚实的形态。
好的体育搜索,第一步不是搜,而是分辨这个问题的答案是被找到的还是被算出来的。分辨对了,链接和计算各归其位;分辨错了,要么让用户自己去数场次,要么让系统对着一个根本没有数据支撑的问题信口开河。这个分辨能力,比任何一次检索的排序技巧都更重要,也是半岛体育AI搜索方向持续投入的部分。