Skip to content

评论洞察 Agent

本页说明评论洞察 Agent 如何在只读委托下读取电商、App Store、G2 或评论后台,从授权可见和公开评论中提取用户反馈主题、聚类洞察并生成 positioning insight。读完本页,你能理解这个场景需要哪些模块、权限边界如何收窄,以及评论原文和聚类结果为什么应该归档到分析存储而不是 Memory。

适用场景

Marketing 和产品团队需要从用户评论中理解购买动机、异议、功能反馈和竞品对比。评论分散在多个平台、量大且持续新增,人工通读难以形成可复查的主题聚类;而没有来源支撑的"用户都在说"式结论,也无法作为 positioning 决策依据。

典型触发时机:

  • 新版本或新品发布后,需要在一周内汇总各平台评论的主题分布。
  • Positioning 复盘前,需要提取用户原话中的购买动机和异议证据。
  • 竞品评分波动,需要对比双方评论中的功能反馈差异。

工程挑战

  • 评论量大且噪声高:跨平台成千上万条评论里混着刷评、无关吐槽和重复内容,聚类很容易产出"看起来合理"但没有任何一条原文支撑的结论。
  • 洞察必须可回溯:"用户都在说太贵"这类结论如果没有评论原文 URL,既无法复核,也无法在 positioning 决策被质疑时自证——无来源的洞察等于没有洞察。
  • 主题体系要跨周期可比:分类规则一变,前后两期的主题分布就失去可比性;规则必须版本化管理,聚类结果必须连同规则版本一起归档,趋势判断才有依据。

模块组合

模块角色说明
GenAuth核心评论后台等授权页面的只读委托、撤销与审计链;后台账号的回复、举报和商家信息编辑能力不进入委托范围。
Web Agent核心受控会话登录评论后台或访问公开评论页,逐页抽取评分、原文摘录和来源链接;公开评论页可通过 WebSearch 定位补充来源。
GUMem不使用评论原文、聚类版本和趋势数据是分析资产,归档到你的分析存储;分类规则和竞品映射是版本化规则,放在规则库(policy store)按版本注入。都不属于 Memory。

评论洞察 Agent 场景架构

权限与委托边界

Agent 本身不持有任何固有权限。每次任务的实际权限是三个集合的交集:用户真实权限 ∩ 本次显式委托范围 ∩ 企业批准边界。落到这个场景:

  • 委托范围只覆盖"读取授权评论后台和指定产品的公开评论页",不包含回复评论、举报内容或修改商家信息。
  • 委托凭证短时效,单次挖掘任务建议分钟级有效期。
  • 用户或管理员可随时撤销授权;撤销后新的评论抽取请求立即失败。
  • 越权尝试(例如读取委托范围外的其他产品评论后台)会被拒绝并留痕——审计链覆盖全部尝试,不只是成功行为。

注意:SDK 示例申请的是产品级 scope(如 webagent.do_anything:read)。平台清单、产品范围和动作白名单这类细粒度边界由 GenAuth 的 Agent Profile 或策略层配置强制执行,不由任务 prompt 承担;本页示例未展示该配置。完整语义见 Delegate Token 与缩权

工作流程

评论洞察 Agent 工作流程

  1. 用户选择产品、平台和时间范围,并在 Qoni Console 确认本次交互式授权。

  2. GenAuth 为本次任务签发最小权限的只读委托凭证。

  3. 应用从规则库读取当前版本的分类规则、主题体系和竞品映射,注入任务描述。

  4. Web Agent 登录评论后台或打开公开评论页,逐页抽取评分、原文摘录和来源链接。

    检查点:评论平台出现登录墙、验证码或风控页时,Web Agent 应升级给人处理,而不是静默绕过。

  5. Agent 按主题聚类评论,标注购买动机、异议、功能反馈和竞品对比,每条洞察附代表性评论原文和来源链接。

  6. 应用侧校验输出契约:缺少评论原文 URL 的洞察直接丢弃;聚类结果连同规则版本归档到你的分析存储。

  7. Agent 输出主题聚类、代表性评论、messaging 建议和来源列表,附规则版本号与 audit id。

    检查点:每条情感或主题结论都应能回溯到具体评论来源链接;无原文支撑的结论不应进入交付物。

示例代码

下面的示例使用官方 Qoni SDK@qoniai/qoni)把这个场景接到你的服务端:交互式委托(含完整回调)→ 从规则库读取分类规则 → 一次 doAnything.run() 完成评论抽取与聚类 → 解析并校验洞察。

ts
import { Qoni, QoniScopes } from '@qoniai/qoni'

const qoni = new Qoni({
  accessKey: process.env.QONI_ACCESS_KEY!,
  secretKey: process.env.QONI_SECRET_KEY!,
})

// 1. 交互式委托:涉及评论后台登录,让用户在 Qoni Console 确认授权
export async function startReviewMining(userId: string, taskId: string) {
  const { data: authorization } = await qoni.delegateToken({
    mode: 'interactive',
    agent: 'review-mining',
    scopes: [QoniScopes.DO_ANYTHING_READ, QoniScopes.DO_ANYTHING_MANAGE],
    redirectUri: 'https://app.example.com/qoni/callback',
    state: taskId,
    user: { id: userId },
    expiresIn: 900, // 单次挖掘任务给分钟级有效期
  })
  redirectUserTo(authorization.authorizationUrl)
}

// GET /qoni/callback —— 用户同意后在服务端兑换 grant,继续执行任务
export async function handleQoniCallback(request: Request) {
  const query = new URL(request.url).searchParams
  const { data: grant } = await qoni.completeDelegateToken({
    grantId: query.get('grantId')!,
    code: query.get('code')!,
    state: query.get('state')!,
  })
  return runMiningTask(grant, await loadMiningTask(query.get('state')!))
}

async function runMiningTask(
  grant: { token: string; auditId: string; grantedScopes: string[] },
  task: { product: string; platforms: string[]; timeRange: string },
) {
  // 2. 任务前:从你的规则库读取当前版本的分类规则与主题体系(不是 Memory)
  const policy = await loadReviewTaxonomyPolicy() // 例如 { version: '2026-08', themes: [...], competitorMap: ... }

  // 3. 一次调用完成挖掘:登录后台、逐页抽取、按主题聚类
  const run = await qoni.doAnything.run({
    token: grant.token,
    prompt: `
      Mine customer reviews for ${task.product} on ${task.platforms.join(', ')}
      within ${task.timeRange}. Extract ratings, verbatim excerpts and source
      links, then cluster them into the themes defined in the taxonomy below —
      motivations, objections, feature feedback, competitor comparisons.
      Return insights as a JSON array of
      { theme, insight, quote, reviewUrl } objects.
      Never reply, report or edit merchant info; exclude reviewer personal data.

      Review taxonomy (version ${policy.version}):
      ${JSON.stringify(policy)}
    `,
    capture: { screenshots: true },
  })

  const result = await run.wait({
    // 登录墙 / 验证码 / 风控页:升级给人处理
    onInteraction: (interaction) => notifyUserActionRequired(interaction),
  })

  // 4. 应用侧校验输出契约:缺评论原文 URL 的洞察直接丢弃
  const insights = parseInsights(result.output).filter((i) => i.reviewUrl)

  // 聚类结果连同规则版本归档到你的分析存储(不是 Memory)
  await archiveInsights(insights, policy.version)

  return {
    insights,
    artifacts: result.artifacts,
    policyVersion: policy.version,
    audit: { auditId: grant.auditId, permissionBoundary: grant.grantedScopes },
  }
}

输出结构由任务描述约定:这里约定返回 { theme, insight, quote, reviewUrl } 数组,应用侧 parseInsights 负责解析与校验,任何缺少 reviewUrl 的条目被直接丢弃。SDK 顶层只返回通用的 RunResultrunIdstatusoutputartifacts 等)。

数据与记忆边界

这个场景涉及四类数据,都不需要进入 GUMem:

  • 版本化规则:分类规则、主题体系、竞品映射——放在规则库(policy store)里按版本管理,每期聚类引用规则版本号。
  • 业务状态:评论原文摘录、聚类结果、趋势数据——按规则版本归档到你的分析存储,供跨期对比与复查。
  • 审计记录:grantIdauditId 构成的委托与行为链——由 GenAuth 维护。
  • 用户 Memory(可选):这个场景默认不召回也不写回;评论内容属于评论作者的公开表达,不应作为任何人的 Memory 沉淀。

失败处理

情况推荐处理
评论后台登录态失效任务挂起,通知用户重新登录,从断点继续。
评论页结构变化导致抽取失败按失败处理并回放会话记录,不输出无证据的洞察。
委托范围外的产品后台请求直接拒绝并记录,事后可在审计链中查到未遂访问。
洞察条目缺少评论原文 URL应用侧校验直接丢弃该条目,并在报告中标注丢弃数量。

生产注意点

不要输出用户隐私信息。公开引用评论时应保留平台规则和最小必要摘录。Agent 只处理公开可见或授权可见的评论内容,评论作者的个人数据仅限洞察分析用途,不用于建联或画像;对公开评论页的抽取频率应设置上限,遵守平台服务条款。

下一步