首页 > 人工智能 > 人工智能 > 向量数据库在 UGC 社区个性化推荐的落地指南
UGC 社区典型特点:内容量大、更新快、长尾重。推荐系统要同时兼顾“ 眼下的即时兴趣 ” 和 “ 用户的稳定偏好 ” ,并在一次请求内完成多路候选召回与融合,保证毫秒级延迟。 本文给出一套 双向量用户兴趣 + 一次 SQL 多路召回 的实践方案,数据库层使用 OceanBase 原生向量 能力,结构化与向量同库,避免“两库同步/一致性坑”。
VECTOR
列 + HNSW/
IVF
向量索引在同一库里,天然支持
事务一致性
(更新浏览计数与短期向量可放在一个事务里)。内容表(帖子/短视频等)
CREATE
TABLE
posts (
post_id
BIGINT
PRIMARY
KEY,
author_id
BIGINT
,
title
VARCHAR
(
255
),
content TEXT,
created_at DATETIME,
status TINYINT
DEFAULT
1
,
-- 1上线
pop_7d
FLOAT
DEFAULT
0
,
-- 近7日人气
content_vector VECTOR(
768
),
-- 原生向量
VECTOR KEY idx_vec (content_vector)
WITH
(DISTANCE
=
COSINE, TYPE
=
HNSW, M
=
16
, EF_CONSTRUCTION
=
200
, EF_SEARCH
=
64
)
);
用户表(双向量:短期 + 长期)
CREATE
TABLE
users (
user_id
BIGINT
PRIMARY
KEY,
short_term_vector VECTOR(
768
),
-- 即时兴趣(秒级更新)
long_term_vector VECTOR(
768
),
-- 稳定偏好(天级/小时级更新)
region
VARCHAR
(
32
),
updated_at DATETIME
);
行为表(去重/特征)
CREATE
TABLE
user_actions (
user_id
BIGINT
,
post_id
BIGINT
,
action ENUM(
'view'
,
'like'
,
'collect'
,
'comment'
,
'share'
),
ts DATETIME,
PRIMARY
KEY(user_id, post_id, action, ts)
);
同一事务中更新浏览计数与短期向量,避免“计数+画像不同步”:
BEGIN
;
UPDATE
posts
SET
view_count
=
view_count
+
1
WHERE
post_id
=
?;
UPDATE
users
SET
short_term_vector
=
?
WHERE
user_id
=
?;
COMMIT
;
短期向量的在线融合
def
update_short_term_vector
(
user_id, post_vec, action
):
w = {
'view'
:
0.1
,
'like'
:
0.3
,
'collect'
:
0.5
}.get(action,
0.1
)
new_vec =
0.85
* current_short_vec(user_id) +
0.15
* w * post_vec
sql(
"UPDATE users SET short_term_vector=? WHERE user_id=?"
, [new_vec, user_id])
直观点: 短期追新,长期守稳 ;两者同时存在才不会“越推越窄”或“越推越慢”。
目标: 一次请求 同时召回“短期兴趣近邻”“长期兴趣近邻”,并叠加 新鲜度 与 人气 ,再统一排序。
关键点: 强过滤先行 (上架、时间窗、地域/类目等),不做过滤等着 P95 爆炸。
-- 取出用户双向量
WITH
user_vectors
AS
(
SELECT
short_term_vector
AS
svec, long_term_vector
AS
lvec
FROM
users
WHERE
user_id
=
:uid
),
-- 路1:短期兴趣召回(响应快,抓当前关注)
short_pool
AS
(
SELECT
p.post_id, p.title,
COSINE_SIMILARITY(p.content_vector, uv.svec)
AS
sim,
p.created_at, p.pop_7d,
'short'
AS
src
FROM
posts p, user_vectors uv
WHERE
p.status
=
1
AND
p.created_at
>
DATE_SUB(NOW(),
INTERVAL
7
DAY
)
-- 新鲜度强过滤
AND
NOT
EXISTS
(
SELECT
1
FROM
user_actions ua
WHERE
ua.user_id
=
:uid
AND
ua.post_id
=
p.post_id)
-- 去已看
ORDER
BY
p.content_vector
<
-
>
uv.svec
LIMIT
200
),
-- 路2:长期兴趣召回(稳定偏好)
long_pool
AS
(
SELECT
p.post_id, p.title,
COSINE_SIMILARITY(p.content_vector, uv.lvec)
AS
sim,
p.created_at, p.pop_7d,
'long'
AS
src
FROM
posts p, user_vectors uv
WHERE
p.status
=
1
AND
p.created_at
>
DATE_SUB(NOW(),
INTERVAL
30
DAY
)
ORDER
BY
p.content_vector
<
-
>
uv.lvec
LIMIT
200
),
-- 融合 + 评分(语义相似 + 新鲜度 + 人气)
merged
AS
(
SELECT
post_id, title, src,
(
CASE
src
WHEN
'short'
THEN
0.7
ELSE
0.3
END
)
*
sim
-- 双向量权重(PPT思路)
+
0.1
*
LOG
(
1
+
pop_7d)
+
0.2
*
EXP
(
-
TIMESTAMPDIFF(
HOUR
, created_at, NOW())
/
72.0
)
AS
score
FROM
short_pool
UNION
ALL
SELECT
post_id, title, src,
(
CASE
src
WHEN
'short'
THEN
0.7
ELSE
0.3
END
)
*
sim
+
0.1
*
LOG
(
1
+
pop_7d)
+
0.2
*
EXP
(
-
TIMESTAMPDIFF(
HOUR
, created_at, NOW())
/
72.0
)
AS
score
FROM
long_pool
)
SELECT
post_id, title,
MAX
(score)
AS
final_score
FROM
merged
GROUP
BY
post_id, title
ORDER
BY
final_score
DESC
LIMIT
50
;
要点
1.COSINE_SIMILARITY
直接用
相似度(0~1)
,不要 distance 再 1-distance,阈值语义清晰。
2.新鲜度、人气做 轻权重加成 ,防止纯语义把“陈年老贴”顶上来。
3.已看过过滤必须在 DB 层完成,避免服务端侧再次 Join 带来不一致。
sim_short、sim_long、pop_7d、age
等作为特征;预算充足再上 DNN。status、时间窗、地域/类目
一定要在 KNN 之前过滤,减少参与向量搜索的数据量。M/EF_SEARCH
做 A/B 压测(召回@K vs P95);内容超大时热冷分层(热:HNSW;冷:IVF-PQ)。posts / users / user_actions
(如上)。long_term_vector
;实时流更新
short_term_vector
。sim_top*、来源池(短/长)、延迟、去重率、曝光→点击漏斗
;0.7/0.3
、新鲜度衰减系数。
UGC 社区的推荐不需要花哨堆栈,核心就三件事:
一是双向量建模 同时覆盖即时兴趣与稳定偏好;
二是用 OceanBase 原生向量 把“结构化 + 向量 + 事务”放在同一库里;
三是通过 一次 SQL 多路召回 把短期池、长期池、时间与人气统一融合,端到端稳定提速。
根据本文结构化表、SQL 与更新策略上线,即可做出一个 快、稳、可迭代 的 UGC 个性化推荐系统。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70047136/viewspace-3094188/ ,如需转载,请注明出处,否则将追究法律责任。