互客鱼 返回主站

WordPress 和 WooCommerce

内容同步

一旦插件连接到您的工作区,您需要将 WordPress 内容推送到互客鱼, 以便智能体可以从中检索。插件以两种互补模式同步: 您从设置页面触发的手动批量同步,以及为您选择的帖子/产品类型 在每个 WP 钩子上触发的自动增量。

两种模式在 external_id 上都是幂等的 — 重新运行它们是免费的。

内容源

WP 实体互客鱼 Source 类型External ID 格式
帖子、页面、自定义帖子类型wordpresswp:{post_id}
WooCommerce 产品woocommerce_productswc:{product_id}
WC 优惠券嵌入在 woocommerce_products source config['coupons']

每个(智能体、站点主机)一对应一个 Source 行。两种类型共存于同一智能体上 — 帖子回答 FAQ 风格的问题,产品回答 "你有 X 吗" 风格的购物意图。 互客鱼在第一次同步时自动创建每个 Source。

批量同步(手动)

打开 Settings → hukeyu。配置插件后会出现两个按钮:

  • Sync posts now — 始终可见。分页遍历您启用的帖子类型的每个 publish 状态帖子,每批 HTTP 50 个。
  • Sync products now — 仅在 WooCommerce 活动时可见。分页遍历 simplevariablegroupedexternal 产品,每批 50 个。

点击任一按钮。状态行显示进度和最终计数: "Sync complete. (124 posts, 87 queued, 37 skipped)"。 Skipped 表示内容哈希与之前的同步匹配 — 无需重新嵌入,无 LLM 成本。

可恢复同步(大型站点)

共享主机通常强制执行 30 秒 PHP 执行上限。互客鱼的同步器尊重这一点: 每次传递强制执行 TIME_BUDGET_SECONDS = 20 挂钟保护。 当预算耗尽且还有更多页面要处理时,同步器:

  1. 将恢复标记持久化为 WP transient:帖子的 hukeyu_post_sync_resume,产品的 hukeyu_product_sync_resume。形状:{ "page": 7, "at": 1715472000 }
  2. 在同一钩子上调度 30 秒后的 WP-Cron 延续(hukeyu_run_full_sync_event / hukeyu_run_product_sync_event)。
  3. 立即返回,响应中包含 more: truenext_page: 7,以便管理员 UI 知道显示 "检测到大型站点,其余部分在后台继续。"

当存在恢复标记时重新运行 "Sync now" 会从上次传递停止的地方继续。 成功完成(没有更多页面)会清除恢复标记。

当块状同步正在进行时,每个 WP 管理员页面都会显示一个柔和通知: "hukeyu is finishing a large-site sync in the background (posts). The widget already works; new content shows up once this completes."

增量同步(自动)

在每个 save_postwp_trash_postbefore_delete_post 对于具有 publish 状态的 已选择加入的帖子类型,插件会向互客鱼触发单个增量调用:

端点触发器Body 形状
POST /api/v1/wp/posts/changed save_post / wp_trash_post / before_delete_post 在已选择加入的帖子类型上。 一个帖子负载 + action: "upsert""delete"
POST /api/v1/wp/products/changed woocommerce_new_productwoocommerce_update_productwoocommerce_delete_productwoocommerce_trash_product 一个产品负载 + action: "upsert""delete"

批量同步使用并行的 /posts/sync/products/sync 端点,每批最多 50 个实体。两个端点的身份验证方式完全相同 (bearer + HMAC)。

内容规范化

插件的 PostContentExtractor 在发送到互客鱼之前为每个帖子解析可见 HTML:

  1. 页面构建器检测 — 如果帖子由 Elementor、Beaver Builder、Oxygen 或 Bricks 拥有,则调用构建器的原生渲染器而不是 post_content。详见 页面构建器
  2. Postdata 准备 — 设置 $GLOBALS['post'] + 调用 setup_postdata(),以便第三方 the_content 过滤器(Yoast、Jetpack、Divi、嵌入)看到有效的 $post 全局变量。
  3. 块扩展do_blocks() 解析每个 Gutenberg 块。
  4. 过滤器链apply_filters('the_content', …) 运行每个主题/插件钩子(懒加载、图像替换、相关帖子等)。
  5. 短代码解析do_shortcode() 解析任何剩余的短代码。
  6. 过滤器覆盖 — 最终 HTML 通过您自己的 hukeyu_post_content_html 过滤器运行,这使您可以剥离导航 chrome、强制自定义模板或完全短路。见下面的“覆盖同步的 HTML”。
  7. 清理$GLOBALS['post']finally 块中恢复并调用 wp_reset_postdata(),因此抛出过滤器回调不会泄露循环状态。

内容哈希和不变跳过

每次同步(批量或增量)都发送一个 content_hash 字段。 互客鱼将其与现有 Document 的存储哈希进行比较;匹配时服务器立即返回, 无需重新分块或重新嵌入。针对稳定站点重新运行 "Sync now" 实际上是免费的 — 只有差异有成本。

哈希是规范化连接的 SHA-256:

sha256( title + "\n" + content_html + "\n" + excerpt + "\n" + taxonomy_term_names )

在哈希之前,空格通过 preg_replace('/\s+/u', ' ', …) 折叠为单个空格,因此琐碎的重排不会触发重新索引。

每个帖子索引的内容

  • 帖子标题(纯文本、实体解码、标签剥离)
  • 摘要 — 如果设置了显式帖子摘要,否则为剥离内容的前 40 个单词
  • 分类术语名称 — 帖子类型注册的每个分类中的每个术语(类别、标签、自定义分类)
  • 主体 HTML — 如上所述完全扩展,服务器剥离标签成块
  • 永久链接、帖子类型、修改时间戳、检测到的语言(来自 WP 语言环境)

每个 WooCommerce 产品索引的内容

  • 名称、SKU、永久链接、主图像 URL(中等大小)
  • 简短描述 + 长描述(Gutenberg 块扩展、短代码解析、应用 the_content 过滤器)
  • 价格、regular_price、sale_price、货币、on_sale 标志、stock_status
  • 类别名称(通过 product_cat 分类)
  • 属性名称 + 值对展平为 "color: blue, red" 字符串,以便嵌入捕获两者
  • SHA-256 content_hash + ISO 8601 modified_at

优惠券同步

优惠券随产品同步一起进行。在每次成功的产品同步完成后 (恢复到完成,而不是中途),插件的 CouponSyncer 运行快照:

  1. 通过 get_posts() 枚举最多 50 个 shop_coupon 自定义帖子类型的发布状态条目 — 这适用于自 WC 2.0 中优惠券发货以来的每个 WooCommerce 版本。(之前插件使用 wc_get_coupons(),这不是每个版本的公共 WC API。)
  2. 通过 new WC_Coupon($id)(稳定的 WC 类)水化每个匹配项。
  3. 过滤掉已过期的优惠券(get_date_expires() < now)或已超过其使用限制的优惠券。
  4. 将结果 POST 到 POST /api/v1/wp/coupons/sync。互客鱼将它们持久化在 source 的 config['coupons'] 数组上。

对于每个优惠券,插件发送:code(大写)、 label(人性化:"10% off"、"5 off your order" 等)、 discountexpires_at。 详见 WooCommerce 深度链接 了解 LLM 如何使用这些。

自动切换到电商垂直领域

在针对 site_typegeneric 的智能体的第一次成功产品 upsert 时, 互客鱼自动将智能体切换到 site_type = "ecommerce"。 这启用了 EcommercePreset 系统提示词片段和 <product/> 内联块发射规则,以便 LLM can recommend products as rich cards instead of plain text.

The switch fires only when site_type is generic。已经在 saasdocumentation 或显式 ecommerce 的智能体永远不会被覆盖。

删除语义

before_delete_post / woocommerce_delete_product 触发单个 delete 增量。互客鱼拆除 Document、其块以及与之关联的向量点。 删除互客鱼从未见过的实体是静默无操作 (HTTP 200,带有 deleted: false),因此重复清理是安全的。

覆盖同步的 HTML

应用您自己的过滤器来修改插件发送到互客鱼的 HTML — 剥离站点标题、强制 Elementor 模板、编辑某一部分等。

add_filter('hukeyu_post_content_html', function ($html, $post, $builder) {
    // $builder 是检测到的页面构建器 slug,或者对于普通 Gutenberg 帖子为 null。
    // 例如 'elementor'、'divi'、'bricks'。
    if ($post->post_type === 'product') {
        return $html;
    }

    // 剥离我们的主题通过 the_content 注入的任何剩余导航 chrome。
    // 互客鱼已经进行自己的标签剥离,但在这里做可以减少块开销。
    $html = preg_replace('#<nav[^>]*>.*?</nav>#is', '', $html);

    return $html;
}, 10, 3);

过滤器在哈希和 POST 之前接收完全渲染的 HTML。 返回 '' 实际上禁用该帖子的同步 (互客鱼将看到空内容并拒绝嵌入任何内容)。

程序化同步(从 PHP)

您可以从自己的代码触发同步 — 对迁移或测试很有用:

// 帖子
$result = (new \hukeyu\Sync\PostSyncer)->runFullSync();
// $result['ok'], $result['posts'], $result['more'], $result['next_page']

// 产品(需要 WooCommerce)
$result = (new \hukeyu\Sync\ProductSyncer)->runFullSync();

// 优惠券
$result = (new \hukeyu\Sync\CouponSyncer)->run();

这些都不会抛出异常 — 它们返回带有 ok 键、 errors 数组的结果数组,以及(对于块状同步器) 用于恢复跟踪的 more + next_page 字段。