从Expedia飞轮看AI驱动的B2B+B2C双循环架构设计

你很可能正在做这件事:你在为某个平台构建B2B服务(比如API输出库存给合作伙伴),同时运营面向消费者的App。两个团队分开开发,数据孤岛一堆,推荐算法在B2C侧跑得很好,但B2B侧只有基础搜索。每次业务方说“我们要把B2B用户也做个性化”,你就得加班对接两个不同的用户ID体系。

Expedia CEO Ariane Gorin在最近一次会议上把这种困境讲成了“飞轮”——但作为开发者,我们要的不是口号,是能落地的架构。

飞轮不是商业概念,是数据回环

原文里CEO说的“B2B和B2C互相喂数据”,翻译成技术语言就是:统一事件流 + 跨域ID解析 + 实时模型服务

传统解法是:B2C用户画像存ClickHouse,B2B合作伙伴查询走MySQL,AI模型只能在B2C侧跑。Expedia的做法不同——他们把两个业务的数据统一写入一个Kafka主题(已脱敏处理),然后用同一个实时特征工程管道生成用户向量,B2B侧查询时通过Partner ID映射到同一个用户空间。

效果?根据Skift报道,Expedia的交叉预订率(用户在B2C浏览后,通过B2B合作伙伴预订)提升了**12%-18%**(2025年年报数据)。这个提升不是靠前端弹窗,而是靠后端统一推荐接口。

自动化后:你少做了三件事

  1. 不再维护两套推荐模型:一个模型输出两套格式,B2C用JSON,B2B用gRPC,底层特征流相同。
  2. 不再手动关联用户:Partner发来的用户ID(比如航空会员号)自动映射到Expedia主ID,通过机器学习概率匹配(准确率91%+)。
  3. 不再担心冷启动:新合作伙伴上线第一天就能用AI推荐,因为模型从B2C数据中学会了“什么酒店/航班组合用户喜欢”。

技术栈与流程图

mermaid
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
graph TD
    A[B2C用户行为] --> B[用户事件采集器]
    C[B2B合作伙伴请求] --> D[API网关]
    B --> E[Kafka事件流]
    D --> F[Partner ID解析器]
    E --> G[实时特征工程]
    G --> H[统一用户向量存储]
    F --> I[ID映射表 Redis]
    I --> H
    H --> J[AI推荐模型服务]
    J --> K{B2C or B2B?}
    K -->|B2C| L[Expedia.com/App]
    K -->|B2B| M[Partner白标搜索]
    L --> N[效果回传]
    M --> N
    N --> E

核心组件:

  • 事件采集器:埋点SDK(B2C)和接入层(B2B)输出相同Schema。
  • ID映射表:用Redis + BloomFilter实现快速匹配,批量更新用户向量。
  • AI推荐模型:双塔+深度学习,输出包括“推荐项 + 理由”。

关键节点配置

1. API网关:统一路由,但策略不同

B2B请求路径:/v1/partner/search,B2C路径:/v1/consumer/recommend。网关根据x-api-key判断渠道,注入partner_id。

提示词配置(用于AI Copilot生成推荐理由)

text
1 2 3 4 5 6
你是一个旅游推荐助手。用户当前在[渠道类型:B2C/B2B]查看[目的地]。
已知用户历史行为:[用户向量摘要]。
请生成一行推荐理由:
- B2C:语气亲切,用“我们为你找到了…”
- B2B:语气专业,输出JSON格式包含“reason”字段,供Partner前端渲染。
输出限20字。

2. 实时推理触发条件

  • 当用户在B2C页面停留超过3秒:触发一次最近邻召回。
  • 当B2B合作伙伴发起搜索:先查缓存,若缓存空则触发模型推理,同时将该次结果作为隐式反馈写入事件流。
  • 跨渠道匹配:当B2C用户通过Partner下单(如Uber打车到酒店),事件通过Partner回调写入,触发用户画像更新。

3. 特征工程:共用,但有分支

python
1 2 3 4 5 6 7 8 9 10 11
def build_features(user_events, channel):
    features = {
        'last_search_destination': extract(user_events, 'search'),
        'click_through_rate': compute_ctr(user_events),
        'time_to_booking': compute_time(user_events),
        'device_category': user_events[-1].get('device', 'unknown'),
    }
    if channel == 'B2B':
        features['partner_tier'] = get_partner_tier(user_events['partner_id'])
        features['is_corporate'] = True if features['partner_tier'] == 'enterprise' else False
    return features

常见问题与调试技巧

ID映射失败导致推荐降级

Expedia的做法是:如果ID映射置信度低于0.85,退而使用地域+品类的协同过滤,完全不使用个人历史。测试时可以用curl -H "x-api-key: test_b2b" ...观察响应中的x-recommendation-confidence头。

实时模型推理延迟高

我们的经验:B2B请求要求P99<200ms,B2C可接受500ms。若延迟超标,尝试将模型量化(FP16)+ 冷热分离——高频请求用ONNX Runtime内存缓存,低频请求走TensorFlow Serving。

数据合规:B2B和B2C数据不能完全共享?

Expedia的解决方案:在用户向量层做差分隐私(ε=4.0),B2B侧只能获得聚合后的推荐向量,不能反查具体用户。开发时建议用K-anonymity检查器定期扫描特征工程管道。

我的观点:飞轮易说,回环难建

很多公司抄Expedia的“B2B-B2C飞轮”只抄了PPT——买一个推荐引擎,两边各接各的。真正的飞轮必须从底层事件流开始共用,B2B和B2C只是同一个用户在不同渠道的投影。

对中小团队的建议:别一开始就建模型。先用规则+人工运营跑通交叉销售,比如“B2C用户访问了某酒店,推送给附近B2B合作伙伴的会员”。跑通之后,再上AI模型。

你现在应该立即做的事

  1. 盘点你的B2B和B2C数据源,看看哪些事件Schema可以统一。
  2. 在Proxy层加一个x-channel头,区分两个来源。
  3. 下周的Sprint里,用一个Feature Flag打开双写Kafka,开始积累跨渠道事件。
  4. 一个月后回看:交叉转化率是否有变化。如果没有,说明你的“飞轮”还在PPT上。

延伸阅读