---
title: "home-mixer 编排层"
description: "home-mixer 服务进程：五个 gRPC 服务、六条流水线、QueryBuilder、候选源总表与热门帖子源"
---

> Documentation Index
> Fetch the complete documentation index at: https://x-algorithm.vergego.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# home-mixer 编排层

## 这一页回答什么

`home-mixer` 是 For You 信息流的服务进程。本页回答五个问题：它怎样启动；它暴露哪些 gRPC 服务；它怎样把 [流水线框架](https://x-algorithm.vergego.ai/concepts/candidate-pipeline-framework/) 组装成多条流水线；请求怎样变成 `ScoredPostsQuery`；候选来自哪些源。候选源总表与热门帖子源（`PopularPostsSource`）也在本页。

## 核心结论

1. **一个进程，五个 gRPC 服务**：`ScoredPostsService`、`ForYouFeedService`、`RankedFollowingFeedService`、`FollowingFeedService`、`PhoenixScoresService`（`home-mixer/server.rs:944-1001`）。旧版只有前两个。
2. **For You 使用两层嵌套流水线**：外层 `ForYouCandidatePipeline`（混排层，README 称 Blending Pipeline）把内层 `PhoenixCandidatePipeline`（帖子层，README 称 Post Pipeline）当作候选源 `ScoredPostsSource` 调用（`home-mixer/sources/scored_posts_source.rs:13-31`）。
3. **内层流水线有 9 个候选源**，按装配顺序：Thunder、热门帖子、TweetMixer、SimClusters、Phoenix 召回、Phoenix 话题召回、Phoenix MoE 召回、SID 召回、缓存帖子（`home-mixer/candidate_pipeline/phoenix_candidate_pipeline.rs:380-390`）。开源默认值下 TweetMixer、MoE、SID 三个源关闭。
4. **热门帖子源是一份全站共享列表**。离线任务从高粉丝活跃作者的近期原创帖里按浏览量挑出 500 条。请求时，源直接读取内存快照，不做个性化（`home-mixer/util/popular_posts.rs:36-86`）。
5. **`QueryBuilder` 是所有入口的统一适配器**：它校验 `viewer_id`、并发拉取用户数据、评估 feature switches、构造 `ScoredPostsQuery`（`home-mixer/server.rs:79-184`）。

## 服务启动

入口是 `home-mixer/main.rs`。同一个二进制文件按命令行参数进入三种模式之一：

| 模式 | 触发参数 | 做什么 |
|------|----------|--------|
| 热门作者任务 | `--popular-authors-job` / `--popular-authors-job-once` | 从 BigQuery 读作者表，选出热门作者并写入存储（`main.rs:135-161`） |
| 热门帖子任务 | `--popular-posts-job` / `--popular-posts-job-once` | 按热门作者拉帖、取浏览量、选出热门帖子并写入存储（`main.rs:165-182`） |
| gRPC 服务 | 默认 | 用 `XServiceBuilder` 启动服务（`main.rs:221-239`） |

服务模式的 CLI 默认值（`main.rs:16-28`）：`grpc_port` 8080、`metrics_port` 9090、`shard_coordinate` -1（不分片）、`shard_total_size` 500、`datacenter` “atla”。旧页面写的 50051 端口已失效。服务启动时还调用 `quality_factor::init(70.0, 30.0)`（`main.rs:187`）。Thunder 与 Phoenix 召回的结果数上限都由 `quality_factor::apply` 调整。

`HomeMixerServer::build()`（`server.rs:815-942`）是装配中心。它先并发创建 VF 客户端与安全标签客户端；再并发创建 Gizmoduck 客户端、复活时间客户端、`PhoenixCandidatePipeline::prod()`、`PhoenixScoresPipeline::prod()`；然后构造 `ScoredPostsServer`；最后并发构造 `ForYouCandidatePipeline`、`RankedFollowingCandidatePipeline`、`FollowingCandidatePipeline`。

## 五个 gRPC 服务

| 服务 | 方法 | 跑哪条流水线 | 源码 |
|------|------|--------------|------|
| `ScoredPostsService` | `get_scored_posts`、`get_debug_scored_posts` | `PhoenixCandidatePipeline` | `server.rs:257-328` |
| `ForYouFeedService` | `get_for_you_feed`、`get_for_you_feed_urt`、`get_debug_for_you_feed`、`get_debug_for_you_feed_urt` | `ForYouCandidatePipeline` | `server.rs:331-523` |
| `RankedFollowingFeedService` | `get_ranked_following_feed_urt`、`get_debug_ranked_following_feed` | `RankedFollowingCandidatePipeline` | `server.rs:526-628` |
| `FollowingFeedService` | `get_following_feed_urt`、`get_debug_following_feed` | `FollowingCandidatePipeline` | `server.rs:631-728` |
| `PhoenixScoresService` | `get_phoenix_scores`、`get_debug_phoenix_scores` | `PhoenixScoresPipeline` | `server.rs:731-809` |

两个 Following 服务在构造查询后强制设置 `in_network_only = true`（`server.rs:559`、`server.rs:662`）。所有服务都启用 gzip 与 zstd 双向压缩，消息上限 `MAX_GRPC_MESSAGE_SIZE` 为 128 MiB（`params/config.rs:16`）。

`get_for_you_feed_urt` 先运行 `get_for_you_feed`，再用 `urt::make_urt_timeline` 把 `FeedItem` 列表转成 X 客户端使用的 URT Thrift，并做二进制序列化（`for_you_server.rs:52-92`）。

## 六条流水线

| 流水线 | 候选类型 | 用途 | 结果规模（开源默认值） |
|--------|----------|------|----------|
| `PhoenixCandidatePipeline` | `PostCandidate` | 帖子层：召回、水合、过滤、打分、选择 | `RESULT_SIZE` = 35（`params/config.rs:18`） |
| `ForYouCandidatePipeline` | `FeedItem` | For You 混排层 | `FOR_YOU_MAX_RESULT_SIZE` = 35 + 5 + 8 = 48（`params/config.rs:19-22`） |
| `RankedFollowingCandidatePipeline` | `FeedItem` | 排序版“关注”页：复用 `ScoredPostsSource` 并加广告 | 38（`params/config.rs:23`） |
| `FollowingCandidatePipeline` | `FeedItem` | 时间序“关注”页 | 112（`params/config.rs:24-27`） |
| `ReverseChronPostsPipeline` | `PostCandidate` | 时间序关注页的帖子层，源是 `FollowingNightOwlSource` | 101（`params/config.rs:26`） |
| `PhoenixScoresPipeline` | `PostCandidate` | 对调用方给定的帖子 ID 打 Phoenix 分，源是 `SeedCandidatesSource` | 35（`phoenix_scores_pipeline.rs:452-454`） |

六条流水线都实现同一个 [CandidatePipeline trait](https://x-algorithm.vergego.ai/entities/candidate-pipeline/)。下文只展开 For You 使用的两条。

### 外层 ForYouCandidatePipeline

`CandidatePipeline<ScoredPostsQuery, FeedItem>`（`for_you_candidate_pipeline.rs:62-69`）。`FeedItem` 是 oneof 类型，取值为：帖子、广告、Who to Follow 模块、Prompt、PushToHome、Frame、FeedSurvey、视频轮播。

| 阶段 | 组件 | 源码 |
|------|------|------|
| Query 水合 | `ServedHistoryQueryHydrator`、`PastRequestTimestampsQueryHydrator` | `for_you_candidate_pipeline.rs:210-217` |
| 候选源 | `ScoredPostsSource`、`AdsSource`、`WhoToFollowSource`、`PromptsSource`、`PushToHomeSource`、`JetfuelFrameSource`、`FeedSurveySource` | `:219-234` |
| 过滤 | `PushToHomeDedupFilter` | `:236-237` |
| 选择 | `BlenderSelector` | `:239` |
| 选后过滤 | `AdAdjacentServedFilter` | `:262-263` |
| Side effect | 13 个：广告注入日志、漏斗追踪、广告历史缓存、seen ids 发 Kafka、served candidates 发 Kafka、客户端事件、served 事件、视频轮播候选日志、响应统计、更新请求时间戳、更新与截断 served history、served slate 缓存 | `:241-260` |

候选水合、打分、选后水合三个阶段返回空切片（`for_you_candidate_pipeline.rs:336-354`）。旧版外层没有过滤器，新版有两个。`PushToHomeDedupFilter` 在 `push_to_home_post_id` 存在时删掉与它重复的帖子（`filters/push_to_home_dedup_filter.rs:8-26`）。`AdAdjacentServedFilter` 检查广告与已服务帖子的相邻关系，开源默认关闭（`params/param.rs:1021-1026`）。

外层 Query 水合在候选源之前运行。`ScoredPostsSource` 克隆外层已水合的查询，再交给内层（`scored_posts_source.rs:15-19`）。因此内层能读到外层写入的 `served_ids` 与模块疲劳标记。`ServedHistoryQueryHydrator` 按疲劳时长计算 `who_to_follow_eligible`、`feed_survey_eligible`、`video_carousel_eligible`（`query_hydrators/served_history_query_hydrator.rs:38-57`）。

### 内层 PhoenixCandidatePipeline

`CandidatePipeline<ScoredPostsQuery, PostCandidate>`（`phoenix_candidate_pipeline.rs:224-234`）。全部组件在 `build_with_clients()` 里装配（`:237-556`）：

| 阶段 | 数量 | 组件 | 源码 |
|------|------|------|------|
| Query 水合 | 21 | 打分序列、沉浸式打分序列、召回序列、屏蔽 / 静音 / 关注 / 订阅用户、缓存帖子、互关、人口属性、关注的 Grok 话题、关注的 starter pack、已装应用、视频轮播 CTR 模型、近期搜索词、显式与隐式互动信号、曝光 Bloom 过滤器、IP、视频轮播已看、推断性别 | `:285-348` |
| 候选源 | 9 | 见下节候选源总表 | `:354-390` |
| 候选水合 | 15 | `InNetworkCandidateHydrator`、`BidirectionalFollowHydrator`、`CoreDataCandidateHydrator`、`PhoenixReplyAncestorsHydrator`、`QuoteHydrator`、`MediaInfoHydrator`、`SubscriptionHydrator`、`GizmoduckCandidateHydrator`、`BlockedByHydrator`、`FilteredTopicsHydrator`、`LanguageCodeHydrator`、`EngagementCountsHydrator`、`PostEngagersHydrator`、`SemanticIdHydrator`、`NewUserSoftNsfwLabelHydrator` | `:392-423` |
| 预打分过滤 | 21 | 见 [过滤流水线](https://x-algorithm.vergego.ai/concepts/filtering-pipeline/) | `:429-453` |
| 打分 | 5 | `PhoenixScorer`、`ImmersiveVideoScorer`、`VMRanker`、`PageDecodeRerankScorer`、`PageRlExplorationScorer`，见 [打分与排序](https://x-algorithm.vergego.ai/concepts/scoring-and-ranking/) | `:475-481` |
| 选择 | 1 | `TopKScoreSelector` | `:483` |
| 选后水合 | 10 | `VFCandidateHydrator`、`AdsBrandSafetyVfHydrator`、`TweetTypeMetricsHydrator`、`FollowingRepliedUsersHydrator`、`MutualFollowJaccardHydrator`、`TopicFeedbackContextHydrator`、`AiTrendFeedbackContextHydrator`、`VideoMediaHydrator`、`VideoEmbeddingHydrator`、`AncestorVideoHydrator` | `:485-509` |
| 选后过滤 | 5 | `VFFilter`、`AncillaryVFFilter`、`AncestorVideoFilter`、`DedupConversationFilter`、`VideoCarouselFilter` | `:511-517` |
| Side effect | 11 | Phoenix 实验、reranking Kafka、召回候选 Kafka、Redis 候选缓存、打分统计、响应多样性统计、意外发现统计、作者曝光指标、互关统计、调试、Phoenix 请求缓存 | `:519-543` |

装配函数构造了 `ImpressedPostsQueryHydrator`，但没有把它放进 Query 水合列表（`:350-352`）。因此在开源装配下，`impressed_post_ids` 保持为空。

`ScoredPostsServer::run_pipeline()`（`scored_posts_server.rs:43-101`）对 `TEST_USER_IDS`（123、234，`params/config.rs:13`）直接返回空结果。对其余请求，它调用 `execute_traced`，把选中候选转成 `ScoredPost`，并附带视频轮播模块。只有 `is_under_the_hood_request` 为真时，流水线追踪才附到响应里（`scored_posts_server.rs:96-98`）。追踪的用途见 [Under the Hood 透明度工具](https://x-algorithm.vergego.ai/concepts/under-the-hood/)。

## QueryBuilder：请求入口适配器

每个 gRPC 入口都先调用 `QueryBuilder::build()`（`server.rs:79-184`）：

1. `viewer_id == 0` 时返回 `invalid_argument`（`:88-90`）。
2. 并发拉取 Gizmoduck 用户数据与账号复活时间，各自 200ms 超时（`VIEWER_ROLES_TIMEOUT_MS`，`:49`）。超时或出错时分别退回 `ViewerData::default()` 与 `None`（`:206-235`）。
3. 推导 `in_network_only = proto.in_network_only || allow_for_you_recommendations == Some(false)`（`:100-101`）。用户关闭“为你推荐”时，For You 只走站内。
4. 用 `FsRecipientInputs`（用户 ID、国家、语言、客户端版本、角色、是否有手机号、复活时间、产品类型等）匹配 feature switches，并应用请求带来的覆盖值（`:103-123`、`:186-204`）。feature switches 是 X 的实验开关系统：系统按用户画像命中一组配置值，各组件从 `Params` 读取这些值。
5. 判定是否影子流量（`:129`），构造 `ScoredPostsQuery`，写入 `request_type` 与 Under the Hood 标记（`:130-167`）。Under the Hood 标记还要求 `EnableUnderTheHood` 为真，开源默认值为 false（`params/param.rs:695-700`）。

## 候选源总表

框架用 `join_all` 并发执行内层 9 个源（见 [candidate-pipeline 框架](https://x-algorithm.vergego.ai/concepts/candidate-pipeline-framework/)）。下表按装配顺序列出（`phoenix_candidate_pipeline.rs:380-390`）。

| 源 | 内容 | `enable()` 条件 | 开源默认值 | `served_type` |
|----|------|-----------------|------------|---------------|
| `ThunderSource` | 关注账号的近期帖子 | `!has_cached_posts`（`thunder_source.rs:23-25`） | 上限 `ThunderMaxResults` 1200（`param.rs:23-28`） | `ForYouInNetwork`；站内限定请求为 `RankedFollowing`（`thunder_source.rs:97-101`） |
| `PopularPostsSource` | 全站共享热门帖子列表 | 无缓存、非站内限定、`EnablePopularPostsSource`（`popular_posts_source.rs:27-31`） | 开启，上限 500（`param.rs:1119-1130`） | `ForYouPopularPosts` |
| `TweetMixerSource` | TweetMixer 服务召回 | `EnableTweetMixerSource`、非站内限定、无缓存（`tweet_mixer_source.rs:25-29`） | **关闭**（`param.rs:41-46`） | `ForYouTweetMixer` |
| `SimclustersSource` | 从用户互动过的帖子出发，按社区簇找相似帖 | `EnableSimclustersSource`、非站内限定、无缓存、有互动信号（`simclusters_source.rs:215-220`） | 开启（`param.rs:48-53`） | `ForYouSimclusters` |
| `PhoenixSource` | Phoenix 双塔召回 | `EnablePhoenixSource`、非话题请求或批量话题请求、非站内限定、无缓存（`phoenix_source.rs:103-108`） | 开启，上限 1000，冷启动上限 200（`param.rs:4-21`） | `ForYouPhoenixRetrieval` / `...Cold` / `...ZeroFav`（`phoenix_source.rs:165-170`） |
| `PhoenixTopicsSource` | 单话题请求的 Phoenix 召回 | 话题请求且非批量、非站内限定、无缓存（`phoenix_topics_source.rs:27-32`） | 随请求 | `ForYouPhoenixRetrieval` |
| `PhoenixMOESource` | Phoenix MoE 集群召回 | `EnablePhoenixMOESource`、SID 源关闭、非站内限定、无缓存、kill switch 未开（`phoenix_moe_source.rs:25-35`） | **关闭**（`param.rs:181-186`） | `ForYouPhoenixRetrievalMoe` |
| `SidSource` | 以互动过的帖子为种子，按语义 ID 前缀召回 | `EnableSidSource`、非话题请求、非站内限定、无缓存、有互动信号（`sid_source.rs:58-64`） | **关闭**（`param.rs:759-764`） | `ForYouPhoenixRetrievalMoe`（`sid_source.rs:94`） |
| `CachedPostsSource` | 上次请求缓存的候选 | `has_cached_posts`（`cached_posts_source.rs:10-12`） | 缓存开启（`param.rs:689-694`） | 沿用缓存值 |

以下规则容易误读：

- **站内限定请求只保留 Thunder**。`in_network_only` 为真时，除 Thunder 外的所有源都关闭。Thunder 的条件只检查缓存。
- **命中缓存时只保留缓存源**。`CachedPostsQueryHydrator` 从 Redis 读回不少于 500 条候选时，设置 `has_cached_posts`（`query_hydrators/cached_posts_query_hydrator.rs:11`、`:69`），其余 8 个源全部关闭。`RedisPostCandidateCacheSideEffect` 写入缓存，每次最多 `MaxPostsToCache` 750 条（`param.rs:701-706`）。
- **SimClusters 和 SID 需要互动信号**。两者都调用 `has_post_signals()`，要求显式或隐式互动信号非空（`simclusters_source.rs:277-285`）。SimClusters 只用 90 天内的种子帖（`simclusters_source.rs:36`）。细节见 [SimClusters](https://x-algorithm.vergego.ai/concepts/simclusters/)。
- **Phoenix 召回可按新用户路由集群**。`PhoenixRetrievalNewUserHistoryThreshold` 大于 0 且召回序列长度低于阈值时，该源改用新用户集群（`phoenix_source.rs:32-68`）。开源默认阈值为 0，即不启用（`param.rs:260-265`）。召回模型见 [Phoenix 召回](https://x-algorithm.vergego.ai/concepts/phoenix-retrieval/)。
- **两个文件没有编进源码树**。`sources/popular_topics_source.rs` 与 `filters/popular_topics_author_dedup_filter.rs` 存在，但不在对应的 `mod.rs` 里（`sources/mod.rs:1-19`、`filters/mod.rs:1-33`），因此不参与编译。

Thunder 的存储与查询见 [Thunder 站内帖子内存库](https://x-algorithm.vergego.ai/concepts/thunder-in-network-store/)。

外层 `ForYouCandidatePipeline` 的非帖子源：

| 源 | 条件 | 产出 |
|----|------|------|
| `AdsSource` | `EnableAdsSource`（默认开启，`param.rs:929-934`）且非预览请求（`ads_source.rs:19-21`） | 广告候选 |
| `WhoToFollowSource` | `EnableWhoToFollowModule` 且未处于 30 小时疲劳期（`who_to_follow_source.rs:24-26`、`param.rs:1139-1150`） | Who to Follow 模块 |
| `PromptsSource` | `EnablePrompts`（默认开启，`param.rs:1152`） | Prompt |
| `PushToHomeSource` | 请求带 `push_to_home_post_id`（`push_to_home_source.rs:19-21`） | 推送落地帖 |
| `JetfuelFrameSource` | 至少一个 Frame 符合条件（`jetfuel_frame_source.rs:27-29`）；总开关 `EnableJetfuelFrames` 默认关闭（`param.rs:1167-1172`） | 体育话题等 Frame 模块 |
| `FeedSurveySource` | `EnableFeedSurvey`（默认关闭，`param.rs:1204-1209`）且未处于 1440 分钟疲劳期 | 信息流问卷，位置 12（`params/config.rs:32`） |

## 热门帖子源

README 把 `popular_posts_source` 列为与 Thunder、Phoenix 召回、SimClusters 并列的候选来源。它由两个离线任务和一个在请求时读取的缓存组成。

```mermaid
flowchart LR
    BQ[(BigQuery 作者表)] --> PAJ["popular_authors_job<br/>按粉丝数取前 0.005% 活跃作者"]
    PAJ --> AS[(热门作者存储)]
    AS --> PPJ["popular_posts_job<br/>经 Thunder 拉原创帖并取浏览量"]
    PPJ --> SEL["select_popular_posts<br/>每作者 5 条,总量 500"]
    SEL --> PS[(热门帖子存储)]
    PS --> CACHE["PopularPostsCache<br/>每 60 秒后台刷新"]
    CACHE --> SRC[PopularPostsSource]
    SRC --> PIPE[内层流水线候选池]
```

1. **选作者**：`select_top_posting_authors` 计算 7 天活跃发帖人数 × `TOP_POSTING_AUTHORS_FRACTION`（0.00005）并向上取整，再从按粉丝数降序的列表头部截取这么多作者（`util/popular_authors.rs:11`、`:25-43`）。任务默认每 3600 秒运行一次（`main.rs:33-34`）。
2. **拉帖子**：`popular_posts_job` 每批 20 个作者调用 Thunder，每作者最多 50 条，排除回复与转发（`popular_posts_job.rs:22-24`、`:83-85`），只保留原创帖（`:67-69`），再批量取浏览量。任务默认每 300 秒运行一次（`main.rs:52-53`）。
3. **打分与挑选**：`quality = views × (1 − e^(−λ·24)) / (1 − e^(−λ·max(age, 0.5)))`，λ = ln2 / 半衰期（`util/popular_posts.rs:48-53`）。这个公式把浏览量折算成“24 小时窗口内的预期浏览量”，使新帖不吃亏。挑选只考虑 24 小时内的帖子，每作者最多 5 条，总量 500，半衰期 8 小时（`util/popular_posts.rs:36-46`、`:61-86`）。以上都是开源默认值。
4. **请求时读取**：`PopularPostsCache` 持有内存快照，距上次加载满 60 秒时在后台刷新（`util/popular_posts.rs:7`、`:207-239`）。`PopularPostsSource` 取前 `PopularPostsMaxResults` 条，去掉 `seen_ids` 里的帖子，标为 `ForYouPopularPosts`（`popular_posts_source.rs:33-64`）。

热门帖子对所有用户相同，不经过任何个性化召回。它们进入候选池后，和其他候选一起经过过滤与 Phoenix 打分。

## 数据模型

### ScoredPostsQuery

查询对象贯穿整条流水线（`models/query.rs:46-149`），约有一百个字段。主要分组如下：

- **身份与上下文**：`user_id`、`client_app_id`、`country_code`、`language_code`、`request_type`、`request_context`、`cursor`、设备与 IP 字段。
- **去重输入**：`seen_ids`、`served_ids`、`bloom_filter_entries`、`impressed_post_ids`、`seen_carousel_video_ids`。
- **模型输入**：`scoring_sequence`、`retrieval_sequence` 及其列式与沉浸式变体、显式与隐式互动信号、`history_topics`。
- **用户特征**：`user_features`（屏蔽、静音、关注、订阅、静音词）、人口属性、推断性别、关注话题与 starter pack 位图、已装应用、近期搜索词。
- **请求形态**：`in_network_only`、`is_bottom_request`、`topic_ids`、`excluded_topic_ids`、`exclude_videos`、`push_to_home_post_id`、`seed_candidate_post_ids`。
- **跨组件共享的结果槽**：`ad_drops`、`video_carousel`、`served_post_score_infos` 等 `Arc<OnceLock<…>>` 字段。选择器与过滤器通过这些字段把旁路结果交给后续阶段。

`RequestType` 有五种：`ForYou`、`RankedFollowing`、`Following`、`ScoredPosts`、`PhoenixScores`（`query.rs:30-37`）。`is_bulk_topic_request()` 判定话题数大于 6（`query.rs:275-277`）。

### PostCandidate

该类型是内层候选（`models/candidate.rs:14`）。源阶段只填 `tweet_id`、`author_id`、`served_type`、`retrieval_sources`。水合器补全正文、媒体、计数、安全标签与可见性结果。打分器写入 `weighted_score` 与 `score`。`retrieval_sources` 记录候选来自哪些源。去重过滤器删除重复候选时，把来源合并到保留的那一条（`filters/drop_duplicates_filter.rs:19-28`）。

## 设计决策

| 决策 | 理由 |
|------|------|
| 外层混排、内层排序两条流水线 | 帖子排序与多类型内容组装分开演化；内层可单独作为 `ScoredPostsService` 复用 |
| 外层 Query 水合先于内层执行 | served history 只拉一次，内外两层共用同一份去重与疲劳信息 |
| 同一进程承载 For You、Following、Phoenix 打分 | 共享客户端与 QueryBuilder，各产品只换流水线组装 |
| 用户数据 200ms 超时并退回默认值 | Gizmoduck 慢调用不拖垮整次请求 |
| 热门帖子离线挑选，请求时只读快照 | 挑选需要扫描热门作者的全部近期帖，放在请求路径上代价过高 |
| 命中缓存时关闭全部召回源 | 翻页请求复用上次召回结果，省掉召回调用 |

## FAQ

**Q：内层流水线能单独调用吗？**
A：可以。`ScoredPostsService` 直接暴露 `PhoenixCandidatePipeline`，返回 `ScoredPost` 列表与可选的视频轮播，不含广告与模块（`server.rs:257-328`）。

**Q：热门帖子源会不会让大号的帖子绕过过滤？**
A：不会。它只把候选放进候选池。这些候选之后照常经过 21 个预打分过滤器、Phoenix 打分、选后可见性过滤（`phoenix_candidate_pipeline.rs:429-517`）。

## 源码锚点

- `home-mixer/main.rs:129-239` —— 三种运行模式与服务启动
- `home-mixer/server.rs:79-235` —— `QueryBuilder`
- `home-mixer/server.rs:815-1001` —— `HomeMixerServer::build()` 与 `register()`
- `home-mixer/candidate_pipeline/for_you_candidate_pipeline.rs:189-273` —— 外层装配
- `home-mixer/candidate_pipeline/phoenix_candidate_pipeline.rs:237-556` —— 内层装配
- `home-mixer/scored_posts_server.rs:43-101` —— `run_pipeline()`
- `home-mixer/util/popular_posts.rs:36-239` —— 热门帖子挑选与缓存
- `home-mixer/popular_posts_job.rs:134-179` —— 热门帖子任务单次运行
- `home-mixer/params/config.rs:13-42` —— 结果规模与位置常量

## 相关页面

- [系统架构总览](https://x-algorithm.vergego.ai/concepts/system-architecture/) —— 请求路径与标签路径总览
- [端到端数据流](https://x-algorithm.vergego.ai/concepts/end-to-end-dataflow/) —— 一条帖子从发布到被推荐
- [candidate-pipeline 框架](https://x-algorithm.vergego.ai/concepts/candidate-pipeline-framework/) —— 流水线 trait 与执行模型
- [CandidatePipeline trait](https://x-algorithm.vergego.ai/entities/candidate-pipeline/) —— 执行器方法逐个说明
- [过滤流水线](https://x-algorithm.vergego.ai/concepts/filtering-pipeline/) —— 21 个预打分过滤器与 5 个选后过滤器
- [打分与排序](https://x-algorithm.vergego.ai/concepts/scoring-and-ranking/) —— 内层打分器
- [候选选择与成型](https://x-algorithm.vergego.ai/concepts/candidate-selection/) —— 选择器与选后成型
- [广告混排](https://x-algorithm.vergego.ai/concepts/ads-blending/) —— `BlenderSelector` 的广告混排
- [SimClusters](https://x-algorithm.vergego.ai/concepts/simclusters/) —— `SimclustersSource` 背后的社区簇
- [Thunder 站内帖子内存库](https://x-algorithm.vergego.ai/concepts/thunder-in-network-store/) —— `ThunderSource` 背后的站内库
- [Phoenix 召回](https://x-algorithm.vergego.ai/concepts/phoenix-retrieval/) —— `PhoenixSource` 背后的召回模型
- [算法用了你的哪些数据](https://x-algorithm.vergego.ai/guide/your-data/) —— `ScoredPostsQuery` 字段的用户侧来源

Source: https://x-algorithm.vergego.ai/concepts/home-mixer-orchestration/index.mdx
