Gorse Learning
参考的资料:
入门
什么是推荐系统
三个要素:
- 记录行为
- 理解兴趣
- 预测可能喜欢
启动与使用
直接使用 docker 启动(参阅官方文档)。
基于 Web 的,直接访问 localhost:8088 可以浏览。
使用 curl 进行插入数据、创建物品、插入反馈、获取推荐等。
核心工作原理的概述
四个核心概念:
- 用户
- 基础信息:ID、标签等(如年龄、性别)
- 行为历史:浏览、点击、购买...
- 物品
- 基础信息:ID、标签
- 统计数据:热度、评分
- 反馈
- 用户+物品+类型+时间
- 推荐
- 根据历史行为预测用户可能喜欢的物品
流程图:
- 用户产生行为
- 系统记录反馈
- 模型定期执行分析、训练
- 生成推荐
- 用户看到推荐
- 循环迭代,回到 1
Gorse 的推荐策略:多源融合。
- 协同过滤:找到相似用户,推荐他们喜欢的物品
- 物品相似:推荐和用户历史物品相似的其他物品
- 热门推荐:推荐最热门的物品
- 最新推荐:字面意思
所谓融合策略:推荐结果 = 30% 协同过滤 + 30% 物品相似 + 20% 热门推荐 + 20% 最新推荐
Gorse 的架构设计
三层架构:
flowchart TD
A["用户 / 应用<br/>Web · App · 小程序"]
B["Server 节点<br/>RESTful API + 实时推荐"]
C["Master 节点<br/>模型训练 + 任务调度 + Dashboard"]
D["Worker 节点(多个)<br/>离线计算 + 批量推荐"]
E["存储层<br/>MySQL + Redis<br/>用户数据 + 物品数据 + 推荐缓存"]
A -->|HTTP / HTTPS| B
B -->|gRPC| C
C -->|gRPC| D
D --> E
关于 gRPC
RPC = Remote Procedure Call,远程过程调用。核心思想就是「像调用本地函数一样调用另一台机器上的函数」。
gRPC = Google 开源的一套 RPC 框架。
Protobuf = gRPC 通常使用的数据描述和序列化格式。你会写一个 .proto 文件定义「有哪些函数、参数是什么、返回值是什么」。
比如 Gorse 架构里:
Server ──gRPC──> Master
Master ──gRPC──> Worker假设 Master 提供一个函数:
GetModel(name string) ModelServer 想调用它。但问题是:Master 和 Server 是两个独立进程,甚至可能运行在不同机器上,Server 显然不能直接:
model := master.GetModel("ranking")gRPC 做的事情,就是让这种远程调用看起来很像普通函数调用:
model, err := client.GetModel(ctx, request)实际上背后发生的是:
Server
│
│ 调用 GetModel(...)
↓
gRPC Client
│
│ 序列化成 Protobuf
│ 通过 HTTP/2 发送
↓
网络
↓
Master 上的 gRPC Server
│
│ 反序列化
↓
真正执行 GetModel(...)Master 节点
可以理解为 Gorse 架构的大脑。
- 模型训练
- AutoML: Automated Machine Learning(自动机器学习)
- 任务调度,触发 Worker
- Dashboard:监控、数据管理
Worker 节点
理解为 Gorse 架构的手脚。
- 批量推荐:为每个用户生成推荐列表
- 相似度计算:计算物品之间的相似,计算用户之间的相似度
- 水平扩展:启动多个 Worker,负载均衡
Server 节点
理解为「嘴巴」。
- 提供 RESTful API
- 实时推荐
- 在线更新
综合
flowchart LR
A["用户行为"] --> B["Server"]
B --> C["DataStore<br/>MySQL"]
C --> D["Master<br/>定期加载数据"]
D --> E["训练模型"]
E --> F["Worker<br/>计算推荐"]
F --> G["CacheStore<br/>Redis"]
G --> H["Server"]
H --> I["返回用户"]
%% 局部调整布局
subgraph Train[" "]
direction TB
D --> E
end
subgraph Recommend[" "]
direction TB
F --> G
end
理解 Gorse 的管道(pipeline)

- 数据源输入输入层之后,传入检索层
- 检索层由多个推荐器构成,为用户生成候选物品
- 排序层合并来自不同推荐器的所有输出,删除用户已经看过的物品(已读物品),并根据用户与剩余物品互动的可能性对其进行评分
默认的管道是只推荐最新物品。
管道中的缓存
以下中间结果被缓存并定期更新:
- 用户到用户推荐器的用户邻居。
- 简单来说,用户 A 的相似用户是 B C D,那么这个结果会被缓存
- 物品到物品推荐器的物品邻居。
- 和上面同理,相似物品缓存
- 非个性化推荐器的结果。
- 和具体用户没有太大关系的内容,比如说最新榜、热门榜
- 每个用户的排序器输出
- 就是最后排序器输出的结果
Gorse 工作原理
管道以分布式方式执行。Gorse 中有三种类型的节点:主节点、工作节点和服务器节点。也就是上面说的 Master Worker Server,不再赘述。
深入 Gorse 推荐系统:数据结构与存储层设计剖析
深入 Gorse 推荐系统:数据结构与存储层设计剖析 - 技术漫游 - 博客园
我感觉也是这个作者的 AI 文章自己洗了一遍...总之大概看看吧。
字符串->索引的映射
显然我们会有大量的 JSON(也可以是 Go 里面的 map[string][]),里面都是字符串作为 key。
字符串作为 key,效率很低(主要是哈希比较带来的开销是 $O(len(string))$