这一页回答什么
Phoenix 召回在“全站候选帖”里查找最近邻。本页回答三个问题:这份候选帖名单从哪里来,多久更新一次,哪些帖子有资格进入。答案在 2026-08 新开源的两个目录里:
phoenix-rankall-strato/:用 Strato(X 内部的数据列/流处理 DSL)写的事件层。它监听发帖与点赞事件,查询帖子元数据和可见性过滤结论,决定帖子进入哪些索引,并把“索引事件”写入 Kafka。phoenix-rankall/:Rust 服务xai-recsys-rankall。它消费这些 Kafka 事件,按“索引名 × 时间窗”维护内存表,并定期写成 parquet 快照文件。
本页不讲召回模型。召回模型见 Phoenix 召回:双塔检索架构。
核心结论
- 事件驱动索引更新,不做批量全量构建。 索引有两个入口:发帖事件(
postCreationEventForwarder.strato)和点赞事件(favoriteEventForwarder.strato)。两个入口都汇入同一个 Strato 列phoenixRankAllCandidateProcessor。 - 点赞事件按 2 的幂次限流。 系统第一次处理一条帖子时立即触发。之后,只有点赞数越过下一个 2 的幂次阈值,才再次触发。阈值存在 memcache 中,TTL 为 50 小时(
phoenix-rankall-strato/columns/tweetUpdateThresholdsCache.strato:19)。 - 帖子进入索引前,系统先查可见性过滤。
shouldDropPostByVF以safetyLevel = TimelineHomeRecommendations调用可见性过滤服务(phoenix-rankall-strato/lib/eventProcessing.strato:260-279)。结论为 drop 的帖子和标为 NSFW/成人的帖子不进入主索引。唯一例外是 NSFW 长视频,它进入nsfw_video专用索引。 - 有两条路径绕过可见性过滤: 系统在 VF 检查之前写入
search_unfiltered索引;EvergreenVideo/EvergreenNsfwVideo两种事件源完全不查 VF(phoenixRankAllCandidateProcessor.strato:459-475)。 - 索引的单位是“索引名 + 时间窗”。 例如
1fav_1day、video_4to14day。系统按帖子 ID(snowflake,内含发帖时间)裁剪时间窗,不按事件时间裁剪。 - 产物是本地 parquet 快照加符号链接。 系统每 180 秒(开源默认值)重写一次快照,保留 3 个版本(
phoenix-rankall/src/config/mod.rs:55-59)。 - 下游消费方位于
phoenix/xrex/: 召回语料加载器按文件名读取1fav_1day.parquet等窗口(phoenix/xrex/data/retrieval_dataset.py:290-325);排序/召回推理进程读取1fav_topic_*_1day.parquet,做 topic 位图过滤(phoenix/xrex/inference/model_runner.py:99-107)。源码未包含 parquet 从 rankall 输出目录搬到PHOENIX_INDEX_BASE的过程。
整体数据流
flowchart TB
PC["发帖事件<br/>content_understanding_realtime_unified_posts_v3"] --> PCP[postCreationEventProcessor]
FV["时间线事件<br/>timeline_events_prototype"] --> FEP[favoriteEventProcessor]
FEP -- "跨过 2 的幂次阈值" --> FK["Kafka: phoenix_rankall_fav_event"]
FK --> CP[phoenixRankAllCandidateProcessor]
PCP --> CP
CP -- "查元数据、互动数、注解" --> META["Tweetypie、UecAggTotal、帖子注解"]
CP -- "safetyLevel=TimelineHomeRecommendations" --> VF[可见性过滤 shouldDropTweet]
CP --> K1["Kafka: phoenix_rank_all_indexing_event"]
CP --> K2["Kafka: phoenix_rank_all_indexing_event_backup"]
CP --> K3["Kafka: phoenix_rankall_metadata_event"]
CP --> MH["Manhattan: filtered_topics_by_experiment"]
K1 --> MAIN["rankall --pipeline main"]
K1 --> SID["rankall --pipeline sid"]
K2 --> TOPIC["rankall --pipeline topic"]
K3 --> MD["rankall --pipeline metadata"]
K3 --> TAIL["rankall --pipeline sid-tail"]
MAIN --> PQ["parquet 快照<br/>window_epoch.parquet + 符号链接"]
SID --> PQ
TOPIC --> PQ
MD --> PQ
TAIL --> PQ
PQ -. "搬运方式源码未包含" .-> XREX["phoenix/xrex<br/>召回语料 + topic 位图"]
事件层:phoenix-rankall-strato
两个入口
| 入口 | 源 Kafka topic | 转发目标 | 锚点 |
|---|---|---|---|
| 发帖 | content_understanding_realtime_unified_posts_v3 |
postCreationEventProcessor → 构造 {postId, eventSource = PostCreation},调用候选处理器 |
phoenix-rankall-strato/stream_forwarders/postCreationEventForwarder.strato:5、columns/phoenix_rank_all/postCreationEventProcessor.strato:7-15 |
| 点赞 | timeline_events_prototype |
favoriteEventProcessor → 达到阈值才写入 phoenix_rankall_fav_event → 再转发给候选处理器 |
stream_forwarders/favoriteEventForwarder.strato:5、stream_forwarders/favoritePhoenixIndexingEventForwarder.strato:5,15 |
两个上游转发器都设置了 delay = 2.minutes 和 slo = { maxLag = 120.minutes }(favoriteEventForwarder.strato:17-18、postCreationEventForwarder.strato:19-20)。因此,帖子最早在事件发生约 2 分钟后才进入索引流程。
候选处理器为 EvergreenVideo、EvergreenNsfwVideo 两种事件源设了分支(phoenixRankAllCandidateProcessor.strato:459-468)。但开源代码里没有产生这两种事件的转发器。源码未包含它们的来源。
点赞限流:2 的幂次阈值
favoriteEventProcessor 只处理 Favorite 事件。它对取消点赞等其他事件只计数,然后忽略(phoenix-rankall-strato/columns/favoriteEventProcessor.strato:96-157)。它从事件中读取帖子当前的点赞数,再查询 tweetUpdateThresholdsCache:
- 缓存中没有这条帖子:帖子年龄小于 49 小时且点赞数小于 2^30 时触发(
lib/eventProcessing.strato:62-70)。 - 缓存中有这条帖子:必须同时满足以下五个条件才触发(
lib/eventProcessing.strato:42-60)。- 点赞数 ≥ 缓存中的
nextTriggerThreshold。 - 距离上次触发 ≥ 1 分钟。
- 距离第一次触发 ≤ 48 小时。
- 帖子年龄 < 49 小时。
- 点赞数 <
1073741824。
- 点赞数 ≥ 缓存中的
触发后,系统把下一个阈值设为 nextPowerOfTwo(count),即 2^(floor(log2(count)) + 1)(favoriteEventProcessor.strato:14-21)。例如,当前有 5 个赞时,下一个阈值是 8。
| 常量(开源默认值) | 值 | 锚点 |
|---|---|---|
maxTimeSinceFirstUpdate |
48 小时 | lib/eventProcessing.strato:28 |
minTimeSinceLatestUpdate |
1 分钟 | lib/eventProcessing.strato:30 |
maxTweetAge |
49 小时 | lib/eventProcessing.strato:32 |
maxEngagements |
1073741824 | lib/eventProcessing.strato:34 |
| 阈值缓存 TTL | 50 小时 | columns/tweetUpdateThresholdsCache.strato:19 |
效果:在 48 小时内,系统对一条帖子最多重新评估约 log2(点赞数) 次,而不是每个赞评估一次。每次重新评估都会重新查询 VF 和互动数。
候选处理器:决定帖子进入哪个索引
phoenixRankAllCandidateProcessor 收到 {postId, eventSource} 后,先补齐以下数据(phoenixRankAllCandidateProcessor.strato:437-456):
getPostMetadataLightweight:帖子本体(Tweetypie)。getUnifiedPostAnnotations:内容理解注解(topic 实体、NSFW 标记、标签)。getEngagementCount:从unified-counter/service/UecAggTotal读取 9 类计数(转发、回复、点赞、引用、收藏、曝光、不感兴趣、举报、拉黑),dataVersion = Safe(lib/eventProcessing.strato:281-302)。getAuthorFollowers:作者粉丝数。
缺少帖子元数据或作者 ID 的事件被直接丢弃(:532-537)。
然后,处理器按下图的顺序分流(phoenixRankAllCandidateProcessor.strato:469-530):
flowchart TB
S{eventSource} -- "EvergreenVideo / EvergreenNsfwVideo" --> EV["有沉浸式视频即进<br/>evergreen_video / evergreen_nsfw_video<br/>不查 VF"]
S -- "Fav / PostCreation" --> SU{"Fav 且非社区帖、非转发?"}
SU -- 是 --> SUI["点赞数 ≥ 1 即进 search_unfiltered<br/>此时尚未查 VF"]
SU --> D["shouldDropPost = VF drop 或 isNsfw"]
SUI --> D
D --> C1{社区帖?}
C1 -- 是 --> X1[跳过]
C1 -- 否 --> C2{回复?}
C2 -- "是,且 Fav、非自回复、未被 drop" --> R["1fav_reply<br/>32fav_reply(≥32 赞)<br/>metadata"]
C2 -- 否 --> C3{转发?}
C3 -- 是 --> X2[跳过]
C3 -- 否 --> C4{shouldDropPost?}
C4 -- "是,且 NSFW + 沉浸式视频 + Fav" --> NV["nsfw_video + metadata + mm_emb_metadata"]
C4 -- "是,其余" --> X3[跳过]
C4 -- 否 --> C5{eventSource}
C5 -- Fav --> F["1fav、1fav 备份、1fav_topic 系列、32fav(≥32 赞)<br/>有沉浸式视频时加 video、1fav_video、imagine<br/>metadata + mm_emb_metadata"]
C5 -- PostCreation --> P["post_creation<br/>有沉浸式视频时加 video<br/>metadata"]
各判定的定义如下:
- 可见性过滤:
shouldDropPostByVF先读取开关enable_vf_rust_should_drop_tweet。开关为真时,它调用visibility/xai/shouldDropTweet;否则调用visibility/service/shouldDropTweetV2。两条路径都使用safetyLevel = TimelineHomeRecommendations,不带观看者(forUserId = None)。Rust 路径在调用失败时默认不 drop(lib/eventProcessing.strato:260-279)。Rust 版可见性过滤在visibility-filtering/rules/safety_level.rs:123-124定义这个安全级别。规则细节见 可见性过滤。 - NSFW:只检查注解里的
isNsfw(lib/eventProcessing.strato:332-340)。同一文件另有一个同时检查isAdult的isAdultPost(:322-330)。但候选处理器里名为isAdultPost的变量实际调用的是isNsfwPost(phoenixRankAllCandidateProcessor.strato:478)。 - 沉浸式视频:
hasImmersiveVideo只要求帖子含有TweetVideo或AmplifyVideo类媒体(lib/eventProcessing.strato:393-401)。hasValidImmersiveVideo更严格:所有媒体都必须属于这两类,且时长 > 10 秒(:23-24、:403-418)。video、1fav_video、nsfw_video三个索引的构建函数在内部再用后者检查。 - imagine:媒体元数据带有
grokPostId,即该视频由 Grok Imagine 生成(lib/eventProcessing.strato:385-391)。
buildAdsIndex(写入 ads 索引)有定义,但没有调用点(phoenixRankAllCandidateProcessor.strato:16-24)。rankall 侧的 Ads 管线也标记为未实现(phoenix-rankall/src/config/mod.rs:157-162)。
Topic 索引与 filteredTopicsByExperiment
点赞路径上的 build1FavTopicIndex 为同一条帖子计算 6 套 topic 实体列表,对应 6 个实验选项(phoenixRankAllCandidateProcessor.strato:213-261、lib/eventProcessing.strato:600-617):
| 选项 | 索引名 | topic 来源 |
|---|---|---|
| 0 | 1fav_topic |
帖子注解里的全部 topic 实体 |
| 1 | 1fav_topic_option_1 |
只保留作者在人工整理名单 V0 中所属类别的 topic |
| 2 | 1fav_topic_option_2 |
规则同上,名单为 V1 |
| 3 | 1fav_topic_option_3 |
作者最近 15 条原创/引用帖中占比 ≥ 0.90 的类别 |
| 4 | 1fav_topic_option_4 |
规则同上,占比 ≥ 0.75 |
| 5 | 1fav_topic_option_5 |
规则同上,占比 ≥ 0.50 |
阈值与样本数见 lib/eventProcessing.strato:475-479(开源默认值)。人工整理名单 curatedAuthorLists 通过 import <hydra/curatedAuthorLists> 引入,源码未包含名单内容。
另有两条硬编码的“紧急 topic”。第一条:带 xAI News 实体且带 Iran 标签的帖子,追加实体 2000000000000000001(usIranWarTopicEntityId)。第二条:带 Business & Finance 实体,且带利率、美联储、股票等 11 个标签之一的帖子,追加实体 2000000000000000002(phoenixRankAllCandidateProcessor.strato:168-241)。Rust 侧的 topic 名称表里没有这两个 ID(phoenix-rankall/src/processor/topic_names.rs:4)。
处理器把 6 套列表整体写入 Manhattan 数据集 filtered_topics_by_experiment。存储 TTL 为 2 天;读缓存命中时保留 1 小时,未命中时保留 5 分钟(columns/mh/filteredTopicsByExperiment.strato:5-25)。只有候选处理器有写权限(:27-30)。处理器再把非空列表作为索引事件写入备份 topic phoenix_rank_all_indexing_event_backup(phoenixRankAllCandidateProcessor.strato:146-153)。
输出的三个 Kafka topic
| topic | 载荷 | 写入者 | 锚点 |
|---|---|---|---|
phoenix_rank_all_indexing_event |
PhoenixRankAllObject{postId, authorId, indexName} |
绝大多数索引 | columns/kafka/indexingEventKafkaTopic.strato:10 |
phoenix_rank_all_indexing_event_backup |
同上;topic 索引额外带 topicEntityIds |
1fav 备份、1fav_topic* |
columns/kafka/indexingEventKafkaBackupTopic.strato:10 |
phoenix_rankall_metadata_event |
PhoenixRankAllCandidateFlat:是否有图/视频、粉丝数、9 类互动数、视频时长、是否回复;或多模态嵌入 v3 / v5_1 / v6_dev |
buildMetadataDump、buildMMEmbMetadataDump |
columns/kafka/metadataEventKafkaTopic.strato:12、phoenixRankAllCandidateProcessor.strato:356-417 |
索引服务:phoenix-rankall
一个二进制,六种管线
xai-recsys-rankall 用 --pipeline 参数选择管线。每种管线由 Kafka 消费者、一种 RecordProcessor 和一种快照存储组成(phoenix-rankall/src/main.rs:76-254)。
| 管线 | 默认 topic | 处理器 | 时间窗(开源默认值) |
|---|---|---|---|
main |
phoenix_rank_all_indexing_event |
MainProcessor:反序列化,丢弃 ID 为 0 或索引名为空的记录 |
19 个,见下表 |
sid |
同上 | SidProcessor:只保留配置窗口里的索引名,批量查询语义 ID |
18 个 |
topic |
phoenix_rank_all_indexing_event_backup |
TopicProcessor:另做黑名单过滤 |
7 个,均为 24 小时 |
metadata |
phoenix_rankall_metadata_event |
MetadataProcessor |
metadata 1/2/3 天 |
sid-tail |
同上 | SidTailProcessor:只保留粉丝数 < 1000 的作者,再查询语义 ID |
tail 1 天 |
analysis |
home_mixer_phoenix_scored_candidates |
AnalysisProcessor:解析 home-mixer 写出的打分记录,读取前缀为 phoenix.HomeExperiment1Lap7. 的分数 |
不分窗,按日期目录写分析 dump |
topic 与窗口的定义在 phoenix-rankall/src/config/mod.rs:147-228。sid-tail 的粉丝阈值 tail_max_author_followers = 1000 和点赞下限 tail_min_fav_count = 0 见 config/mod.rs:104-107。analysis 的分数前缀见 config/mod.rs:64-68。该管线跳过 suggest_type 为 rankedfollowing 的记录(phoenix-rankall/src/processor/analysis_processor.rs:26-30)。
main 管线的 19 个窗口如下(config/mod.rs:170-190):
| 索引名 | 时间窗 |
|---|---|
post_creation |
1 天 |
1fav |
1 天、2 天 |
1fav_video |
2 天、2–4 天、4–14 天、4–30 天 |
32fav、1fav_reply、32fav_reply |
各 1 天 |
video |
2、4、7、14、30 天 |
nsfw_video |
2 天、7 天 |
evergreen_video、evergreen_nsfw_video |
各 1825 天(5 年) |
sid 管线另有 video_6h、video_6hto2day、imagine_4day、nsfw_video_14day 等窗口(config/mod.rs:205-224)。窗口文件名规则为 {索引名}_{天数}day;有下限时写成 {索引名}_{下限}to{上限}day(config/mod.rs:270-293)。
黑名单
topic 管线启动时从输出目录读取 blacklisted_post_ids.txt 与 blacklisted_author_ids.txt。文件每行一个 ID,以 # 开头的行是注释(phoenix-rankall/src/processor/blacklist.rs:13-63)。TopicProcessor 丢弃命中黑名单的帖子或作者(src/processor/topic_processor.rs:56-65)。只有 topic 管线加载黑名单(src/main.rs:101)。源码未包含名单内容与维护方式。
语义 ID 补全
sid 与 sid-tail 管线通过 gRPC SidLookupService.LookupSids 批量查询每条帖子的语义 ID 码(phoenix-rankall/proto/sid_lookup.proto:5-19)。语义 ID 是帖子多模态嵌入的残差量化码,默认 6 层(config/mod.rs:101-102)。语义 ID 在模型侧的含义见 哈希嵌入。
- 新鲜度门槛:管线不为年龄 < 180 秒的帖子发请求(
config/mod.rs:83-84、src/sid/client.rs:75-86)。原因是语义 ID 要等多模态嵌入计算完成。 - 回填循环:管线每 30 秒扫描一次存储里“1 小时内、语义 ID 仍缺失”的帖子。每批 5000 条,每轮最多 800000 条(
config/mod.rs:89-99、src/sid/backfill.rs:70-80)。 - 缺失占位:写 parquet 时,语义 ID 长度不等于层数的行写成 6 个
-1(src/store/base.rs:721-775)。
快照存储
BaseSnapshotStore 按窗口名维护 post_id → 值 的内存表(phoenix-rankall/src/store/base.rs):
- 写入:新记录先进入 pending 区,窗口路由器决定它进入哪些窗口。
main与sid按索引名精确匹配;metadata进入全部窗口;topic使用写死的映射表(src/store/base.rs:1195-1238)。同一帖子重复到达时,存储合并记录。互动计数逐项取最大值,防止后到的 0 覆盖先到的计数(src/processor/record.rs:65-80)。 - 裁剪:存储每
dump_interval_secs = 180秒(config/mod.rs:55-56)删除帖子 ID 小于now - retention的记录(src/store/base.rs:354-360)。帖子 ID 是 snowflake,高位是发帖时间(src/store/snowflake.rs:1-9)。因此,窗口按发帖时间计算,不按点赞时间计算。带下限的窗口还会去掉过新的帖子,并另写一份放宽 6 小时的prefloor_文件(src/store/base.rs:110、:340-342)。 - 落盘:存储先写
{窗口}.parquet.tmp,再改名为{窗口}_{epoch秒}.parquet,然后原子替换符号链接{窗口}.parquet,保留最近 3 个版本(src/store/writer.rs:9-49、config/mod.rs:58-59)。压缩格式为 Snappy。 - 重启恢复:服务启动时读回最新版本文件,重建内存表(
src/store/base.rs:130-242)。Kafka 消费者默认回拨 12 小时(config/mod.rs:43-44)。 - 提交位点:默认只在一次落盘完成后才提交 Kafka 位点(
commit_after_dump = true,config/mod.rs:71-72、src/pipeline/mod.rs:98-101)。服务崩溃时,最多重放一个周期的事件。
parquet 列:main 管线只有 post_id、author_id;sid 增加 post_sid;topic 增加 topic_entity_ids 与 topic_names;metadata 增加媒体标记、粉丝数和 9 类计数(src/store/base.rs:684-960)。
存储没有删除单条记录的路径。帖子只会因窗口过期而离开索引。如果一条已入索引的帖子之后被 VF 判为 drop,它不会再收到新的索引事件,但已写入的记录会保留到窗口过期。这一点是按代码推断:开源代码中未见主动撤回逻辑。
src/hydrate/ 模块实现了带优先级队列的帖子特征补全(Live / Refresh / Backfill,src/hydrate/scheduler.rs:23-28),但 main.rs 没有实例化它。源码未包含它在线上是否启用。
谁在读这些 parquet
| 消费方 | 读取的文件 | 用途 | 锚点 |
|---|---|---|---|
召回语料加载 RetrievalDataset |
post_sid_v8_256x6_snapshots/ 下的 1fav_1day、video_2day、video_4day、video_4to14day、nsfw_video_2day、imagine_4day;post_sid_v5_256x6_tail_snapshots/tail_1day |
每个枚举值对应召回语料里的一个子集(dataset_type);HOME 再拆成 HOME_COLD / HOME_HOT 两片 |
phoenix/xrex/data/retrieval_dataset.py:62-68、:290-325 |
| 训练侧语料暂存进程 | 同上,按文件名里的 10 位 epoch 识别版本 | 子进程轮询新版本;训练器保存 checkpoint 时,把候选塔嵌入烘进 post_embeddings |
phoenix/xrex/train/retrieval_corpus_stager.py:20、phoenix/xrex/train/trainer_recsys.py:3935-3958 |
| 推理进程 topic 过滤 | post_creation_snapshots_topic/1fav_topic*_1day.parquet |
读取 topic_entity_ids 并转成位图,按 topic_filter_mode 选 6 个选项之一来过滤召回候选 |
phoenix/xrex/inference/model_runner.py:99-107、:4760-4800、:5154-5169 |
消费方读取的文件名与 rankall 的窗口名一致(1fav_1day、video_4to14day 等)。版本号格式 _(\d{10})\.parquet$ 也与 atomic_write_parquet 的命名一致。由此可以确认 rankall 生产召回语料。仍有两点未确认:
- rankall 写入本地
output_dir,消费方读取PHOENIX_INDEX_BASE(线上还有 O2 / GCS 两个下载源,retrieval_dataset.py:255-280)。源码未包含两者之间的同步作业。 RetrievalDataset引用了32fav_video_14to30day.parquet(retrieval_dataset.py:325),但开源的 rankall 窗口配置里没有对应窗口,Strato 侧也没有32fav_video索引名。
召回服务如何用这份语料打分,见 Phoenix 召回:双塔检索架构。训练时怎样把语料嵌入写进 checkpoint,见 Phoenix 训练。
设计决策
| 决策 | 理由 |
|---|---|
| 点赞按 2 的幂次触发 | 热帖每秒可能收到大量点赞。按 log2 触发把重新评估次数从 O(点赞数) 降到 O(log 点赞数),同时保证 1、2、4、8……等关键门槛都会被检查到。 |
入索引前查 VF,安全级别用 TimelineHomeRecommendations |
召回候选是“推荐给陌生人”的帖子。不带观看者的推荐级判定可以提前一次算完,避免每个请求都对百万级语料做过滤。 |
search_unfiltered、evergreen 不查 VF |
这些索引用途不同(命名暗示用于搜索与长青视频),由使用方做过滤。源码未包含具体用途。 |
| 窗口按发帖时间裁剪 | 召回需要“最近发布、已有互动的帖子”。直接比较 snowflake ID 即可,不需要另存时间戳。 |
| 版本文件 + 符号链接原子替换 | 读取方(训练暂存进程、推理进程)在任何时刻都读到完整文件,不会读到写了一半的 parquet。 |
| 落盘后才提交 Kafka 位点 | 内存表丢失时,服务可以从上次落盘点重放。代价是最多重复处理一个 180 秒周期。 |
| topic 列表同时写 Manhattan 和 Kafka | Manhattan 供在线按帖子查询;Kafka → parquet 供推理进程整批构建位图。 |
源码锚点
phoenix-rankall-strato/stream_forwarders/postCreationEventForwarder.strato:3-23—— 发帖事件入口phoenix-rankall-strato/stream_forwarders/favoriteEventForwarder.strato:3-21—— 点赞事件入口phoenix-rankall-strato/columns/favoriteEventProcessor.strato:14-160—— 2 的幂次限流phoenix-rankall-strato/lib/eventProcessing.strato:28-70—— 限流常量与触发条件phoenix-rankall-strato/lib/eventProcessing.strato:260-279——shouldDropPostByVFphoenix-rankall-strato/columns/phoenix_rank_all/phoenixRankAllCandidateProcessor.strato:419-539—— 索引分流主逻辑phoenix-rankall-strato/columns/phoenix_rank_all/phoenixRankAllCandidateProcessor.strato:213-261—— 6 套 topic 实验选项phoenix-rankall-strato/columns/mh/filteredTopicsByExperiment.strato:5-30—— topic 列表存储phoenix-rankall-strato/columns/tweetUpdateThresholdsCache.strato:13-25—— 阈值缓存phoenix-rankall/src/config/mod.rs:9-228—— CLI 默认值、管线 topic、时间窗phoenix-rankall/src/main.rs:76-254—— 管线装配phoenix-rankall/src/processor/blacklist.rs:13-34—— 黑名单phoenix-rankall/src/sid/client.rs:64-100—— 语义 ID 查询与新鲜度门槛phoenix-rankall/src/store/base.rs:322-420—— 裁剪与落盘phoenix-rankall/src/store/writer.rs:9-49—— 原子写 parquetphoenix/xrex/data/retrieval_dataset.py:290-325—— 召回语料子集定义phoenix/xrex/inference/model_runner.py:99-107—— topic parquet 路径
相关页面
- Phoenix 召回:双塔检索架构 —— 读取这些索引的召回模型
- Phoenix 训练 —— 训练时如何把语料烘进 checkpoint
- 可见性过滤 ——
shouldDropTweet背后的规则 - 哈希嵌入 —— 语义 ID 在模型里的用法
- 多模态帖子嵌入器 —— 语义 ID 与
mm_emb_metadata的上游 - home-mixer 编排层 —— 召回在 home-mixer 候选源中的位置
- 系统架构总览