在搜索业务中,仅靠关键词匹配(如使用Elasticsearch)召回的结果,往往无法最优地满足用户的真实意图,导致用户点击率和满意度不高。本文将向您展示如何利用PolarDB for AI的内置机器学习能力,通过分析用户历史行为数据(如点击、停留时长),训练一个排序模型,对初步召回的结果进行二次优化(精排),从而显著提升搜索结果的质量和用户点击率。
功能简介
搜索排序通常分为两个阶段:
召回(Recall):由Elasticsearch等搜索引擎,根据用户查询(Query)快速从海量文档中召回一个候选集(例如Top 400)。此阶段追求快和全,保证相关内容不被遗漏。
排序(Ranking):对召回的候选集进行精细化排序。此阶段利用机器学习模型,综合考虑相关性、热度、用户偏好等多种特征,预测每个档文档的点击概率,然后按预测分数由高到低排序,最终呈现给用户。此阶段追求准,以提升核心业务指标。
PolarDB for AI的核心价值在于极大简化了第二阶段。它将模型训练和预测能力内置于数据库中,您只需通过SQL接口即可完成传统模式下需要多个工程组件(如特征存储、模型训练平台、在线推理服务)才能实现的工作。
前提条件
增加AI节点,并设置AI节点的连接数据库账号:开启PolarDB for AI功能
说明若您在购买集群时已添加AI节点,则可以直接为AI节点设置连接数据库的账号。
AI节点的连接数据库账号需具有读写权限,以确保能够顺利读取和写入目标数据库。
使用集群地址连接PolarDB集群:登录PolarDB for AI
构建搜索精排模型
以下将通过四个步骤,详细介绍如何构建一个可用的搜索排序模型。
步骤一:准备训练数据与特征工程
模型训练的第一步是准备一份高质量的教材,即带有标签的训练数据。这份数据来源于您业务系统的真实用户行为日志。
数据源与日志要求
您需要收集并整合以下三类日志信息:
日志类型 | 说明 | 关键字段 |
曝光日志(Impression Log) | 记录了哪些文档在何时、何处被展示给了哪个用户。 | 查询词( |
点击日志(Click Log) | 记录了用户对曝光文档的交互行为。 | 曝光ID( |
文档元数据(Document Metadata) | 记录了文档本身的静态属性。 | 文档ID( 说明 请注意时间穿越问题,训练时使用的所有特征(如文档历史点击率CTR)都必须是基于样本产生时间点之前的数据计算得出的。 |
构造训练标签(Pointwise)
将问题简化为一个二分类任务,预测一个被曝光的文档是否会被有效点击。
正样本(isClick = 1):定义为有效点击。建议设置一个简单的过滤规则,例如:用户点击了该文档,并且停留时间超过5秒。
负样本(isClick = 0):定义为曝光但未点击的文档。对于点击后迅速离开的(如停留时间<3秒),也可视为弱负样本。
设计特征体系(Feature Engineering)
特征是模型的原材料,其质量直接决定模型效果。以下是搜索排序场景中常用的特征类别,您可以根据业务实际情况选择和构建:
特征类别 | 说明 | 示例特征 |
查询特征(Query Features) | 描述用户查询本身的基础属性。 | 查询长度( |
文档特征(Doc Features) | 描述文档的静态属性和先验质量。 | 文档类目( |
统计特征(Statistical Features) | 反映文档的热度,需使用平滑处理避免冷启动问题。 | 历史曝光数( |
匹配特征(Query-Doc Features) | 衡量查询与文档在文本和语义层面的匹配程度。 | 召回分数( |
个性化特征(Personalization) | (按需选用)引入用户维度,实现个性化排序。 | 用户对该类目的历史偏好( |
参考实例
将上述处理好的数据整合到PolarDB集群的一张表中,例如
train_data
。CREATE TABLE train_data ( id INT AUTO_INCREMENT PRIMARY KEY, -- 特征列 query_len INT, query_term_count INT, doc_category VARCHAR(50), doc_score FLOAT, doc_during_time INT, exp_count BIGINT, click_count BIGINT, click_rate FLOAT, es_score FLOAT, word_overlap FLOAT, emb_cos_score FLOAT, jaccard_score FLOAT, editdistance_score FLOAT, -- 标签列 isClick INT );
插入示例数据。
INSERT INTO train_data (query_len, query_term_count, doc_category, doc_score, doc_during_time, exp_count, click_count, click_rate, es_score, word_overlap, emb_cos_score, jaccard_score, editdistance_score, isClick) VALUES (10, 2, 'tech', 0.9, 15, 1000, 100, 0.1, 60.5, 0.8, 0.95, 0.7, 0.2, 1), (10, 2, 'news', 0.7, 300, 5000, 200, 0.04, 55.1, 0.6, 0.7, 0.5, 0.4, 0), (15, 3, 'tech', 0.95, 20, 500, 80, 0.16, 75.0, 0.9, 0.98, 0.8, 0.1, 1), (15, 3, 'sports', 0.8, 400, 10000, 150, 0.015, 40.3, 0.3, 0.4, 0.2, 0.8, 0);
步骤二:训练排序模型
准备好高质量的训练数据后,就可以开始训练模型了。PolarDB for AI将复杂的模型训练过程封装成一条简单的CREATE MODEL
语句。
模型选择
在开始编码前,需先选择一个适合的模型。对于搜索排序这类拥有丰富结构化特征(表格数据)的场景,梯度提升决策树算法(GBDT)通常是首选。
强大的拟合能力:能有效捕捉特征间的复杂非线性关系(例如,“只有当
doc_category
是‘科技’时,较高的word_overlap
才对点击率有强正向影响”)。对特征无需归一化:对数值大小不敏感,简化了数据预处理步骤。
容错性好:对异常值和缺失值有较好的容忍度。
易于解释:可以分析特征重要性,帮助理解哪些因素对用户点击行为影响最大。
PolarDB for AI内置的aliboost
算法就是基于GBDT实现的。因此,在下面的代码中,可通过model_class = 'aliboost'
和boosting_type = 'gbdt'
来指定使用它。
训练流程与代码实现
整个训练流程在数据库内部自动完成,PolarDB for AI会读取您指定的train_data
表,根据您设置的参数,聚合样本、生成标签,并应用aliboost
算法进行迭代学习,最终将训练好的模型元数据持久化存储。
/*polar4ai*/CREATE MODEL rerank_model WITH
(
model_class = 'aliboost',
x_cols = 'query_len,query_term_count,doc_category,doc_score,doc_during_time,exp_count,click_count,click_rate,es_score,word_overlap,emb_cos_score,jaccard_score,editdistance_score',
y_cols = 'isClick',
model_parameter = (
boosting_type = 'gbdt',
n_estimators = 20,
loss = 'binary'
)
)AS (SELECT * FROM train_data);
训练细节与参数调优
model_parameter
中的参数是模型效果的关键,理解它们有助于您进行精细化调优:
loss = 'binary'
:损失函数。它定义了模型的优化目标。binary
(即binary_logloss
) 是专门为二分类问题设计的,其目标是让模型输出的预测概率尽可能地接近真实标签(0或1)。在本次任务中,这是一个固定选项。n_estimators = 20
:决策树的数量。这是模型复杂度的核心参数。一个较大的值能让模型学习得更充分,但也可能导致过拟合(模型在训练集上表现很好,但在新数据上表现差)。您需要通过后续的评估来寻找最佳值。其他关键超参数:除了示例中的参数,
aliboost
还支持更多用于控制模型行为的参数,例如:max_depth
:每棵树的最大深度,控制单棵树的复杂度。learning_rate
:学习率,控制每棵树对最终结果的贡献权重。较小的学习率通常需要搭配更多的n_estimators
。min_data_in_leaf
:每个叶子节点最少的样本数,用于防止过拟合。
参考建议
数据划分:在生产环境中,严格按时间划分训练集和测试集(例如,用上周的数据训练,用昨天的数据测试)至关重要,这能最真实地模拟线上环境。
类别不平衡:搜索场景中,未点击的负样本数量远多于点击的正样本。如果类别比例失衡严重,可以考虑在构造
train_data
时对负样本进行降采样(down-sampling),以帮助模型更好地学习正样本的特征。
步骤三:评估模型效果
模型训练完成后,需要通过一份独立的测试集(test_data
)来进行客观地评估其性能。这份测试集是模型在训练过程中从未见过的数据,评估结果能真实反映模型在未来新数据上的表现。
评估指标:AUC与Precision@K
对于排序任务,通常关注以下离线评估指标:
AUC(Area Under the Curve):衡量模型整体的排序能力。它反映的是模型将正样本排在负样本前面的概率。AUC值在0.5到1之间,越接近1,说明模型区分会点击和不会点击的文档的能力越强。它是一个宏观的,与具体排序位置无关的诊断性指标。
Precision@K(前K个结果的准确率):更贴近业务场景的指标。它计算的是在模型排序得分最高的K个结果中,真正被用户点击的(正样本)占了多少比例。例如,
Precision@10
衡量了用户在搜索结果第一页所看到的内容的质量。
评估代码实现
使用EVALUATE
语句可以方便地计算这些指标。下面的例子演示了如何计算AUC:
/*polar4ai*/SELECT * FROM EVALUATE(
MODEL rerank_model,
SELECT * FROM test_data
) WITH (
x_cols = 'query_len,query_term_count,doc_category,doc_score,doc_during_time,exp_count,click_count,click_rate,es_score,word_overlap,emb_cos_score,jaccard_score,editdistance_score',
y_cols = 'isClick',
metrics = 'auc'
);
执行上述语句后,您会得到一个AUC值。一般来说,AUC达到0.75以上,模型就具有了不错的区分能力。达到0.85以上,则表示模型效果非常优秀。您可以将这个值与基线模型(如仅使用es_score
排序)的AUC进行对比,以量化新模型的提升。
参考建议
多维度评估:不要只看总体的AUC。将测试集按不同维度(如查询的头部/腰部/长尾、不同客户端、不同内容类目)进行切分,分别计算AUC,这能帮助您发现模型在哪些细分场景下表现不佳,从而进行针对性优化。
特征重要性分析:训练完成后,您还可以分析模型的特征重要性,了解哪些特征对预测贡献最大。这不仅能帮助您理解模型,还能指导未来的特征工程方向。
步骤四:上线与在线推理
当模型通过离线评估后,就进入了最关键的一步:将其集成到您的线上应用中,实时地为用户搜索请求提供排序服务。
在线服务流程
一个典型的在线排序服务流程如下,它需要您的应用后端与PolarDB集群紧密协作:
召回候选集(Recall):您的应用后端接收到用户查询后,首先请求召回引擎(如Elasticsearch),获取一个初步排序的候选文档列表(例如Top 400),并取回文档ID、ES分数等基础特征。
准备预测数据:针对这400个候选文档,应用后端需要实时地准备好模型所需的所有特征。
离线特征:如文档的历史点击率、质量分等,通常从高速缓存(如Redis)或特征库中批量拉取。
在线特征:如查询与每个文档的语义相似度,需要实时计算。为提高效率,文档的向量表示(Embedding)应提前算好并存储,在线只需计算一次查询的向量,然后与400个文档向量进行点积运算。
写入预测表:将整合好的特征数据批量写入PolarDB的一张预测专用表(例如
recall_table
)中。执行模型预测(Predict):应用后端执行
PREDICT
语句,调用之前训练好的rerank_model
为表中的每一行数据(每一个候选文档)打分。/*polar4ai*/SELECT * FROM PREDICT( MODEL rerank_model, SELECT * FROM recall_table ) WITH ( x_cols = 'querylen,query_term_count,doc_category,doc_score,doc_during_time,exp_count,click_count,click_rate,es_score,word_overlap,emb_cos_score,jaccard_score,editdistance_score' );
业务逻辑后处理:您的应用程序获取带有预测分的文档列表后,不要直接返回,通常还需要进行一系列业务规则处理:
多样性:避免首页出现过多相同类目或来自同一作者的内容。可以对连续出现的同类目/同作者内容进行降分惩罚。
新鲜度:对新发布的高质量内容进行适当提权。
业务规则:强制置顶或过滤某些特定内容。
返回结果并记录日志:将经过后处理的最终排序列表返回给前端展示给用户。同时,建议完整地记录此次请求的详细日志(包括查询、返回的文档列表、它们的顺序、模型得分等),这些日志同于持续训练模型。
参考建议
性能与延迟:在线服务的延迟是核心用户体验指标。您需要设定一个严格的端到端时延预算(例如,P95延迟<100ms)。这个预算反过来会限制您可以召回的候选集大小(K值)以及特征的复杂度。
缓存策略:缓存是降低延迟的利器。对高频查询的最终排序结果、热门文档的特征、查询的向量表示等都可以进行缓存。
高可用与安全:
灰度发布(A/B测试):新模型上线应采用A/B测试,切分一小部分流量给新模型,验证其线上真实效果。
熔断与降级:为防止模型服务或其依赖(如特征库)出现问题影响整体可用性,应设置熔断机制。当排序服务超时或失败时,能自动降级到旧的排序策略(例如,直接使用ES的召回排序结果),保证用户总能看到内容。
模型维护与迭代
机器学习模型不是一次性项目,而是一个需要持续维护和优化的生命周期过程。上线仅仅是开始。
在线评估:A/B测试
离线指标(如AUC)的提升不完全等同于线上业务指标的提升。A/B测试是检验模型真实价值的唯一标准。通过分流实验,您需要密切关注新旧排序策略在以下核心业务指标上的对比表现:
核心指标:点击率(CTR)、用户停留时长、会话满意度(如会话最后一次点击的占比)。
辅助指标:跳出率、转化率、用户反馈等。
护栏指标:服务延迟、系统负载等。
只有当新模型在核心指标上取得显著正向收益,且不损害护栏指标时,才能全量上线。
周期性重训
用户的兴趣和内容的热点是不断变化的,这会导致数据分布发生漂移(Data Drift),使旧模型的预测能力逐渐下降。因此,必须周期性地用最新的数据重新训练模型。
频率:根据业务变化速度,可以设定每周、每双周或每月进行一次模型重训。
自动化:建立自动化的模型训练与评估流水线(MLOps),定期触发重训、生成评估报告,并将达到上线标准的模型版本自动注册到模型库中。
离线分析与优化
在两次重训之间,您可以通过离线分析来寻找模型的优化方向:
分场景评估:深入分析模型在不同查询类型(头部热门查询 vs 长尾低频查询)、不同用户群体、不同内容类目下的表现,找到模型的短板。
特征去除实验:通过在训练时暂时移除某些特征,来观察模型性能的下降程度,以此判断哪些特征是真正有价值的。这能帮助您迭代和优化特征工程。
处理冷启动问题
对于新发布的内容或新注册的用户,由于缺乏历史行为数据,模型的统计类和个性化特征会缺失,导致预测不准。这即是冷启动问题。
内容冷启动:对于新文档,模型应更依赖其内容本身的特征(如内容质量分、文本语义特征)。同时,可以在业务逻辑层面给予新内容一定的探索曝光机会,让其快速积累早期用户行为数据。
用户冷启动:对于新用户,可以先使用不依赖个性化特征的通用排序模型,待其产生足够行为后再切换到个性化模型。