AI购物代理如何劝你不买:反向推荐Agent的设计与实现
2026/9/11 13:18:21 网站建设 项目流程

现在的大模型购物助手,几乎都活成同一个样子:你给它一个商品链接,它帮你拉参数、比价格、说优点,最后补一句"综合考虑,建议入手"。用久了你会发现,这类 agent 给人的帮助,其实非常有限。它把"帮你买东西"简化成了"帮你把东西加入购物车",而真正难的问题——这个东西你到底该不该买,它反而避开了。

所以当我在 Show HN 上看到 TickClip 这个项目时,第一反应是:终于有人把产品锚点放在"recommend not buying"上了。一个 AI shopping agent 不把"成交"当目标,而是主动劝用户别买。这不是营销噱头,它背后其实是一个完全不同的 agent 设计思路:目标函数从"平台转化率"变成了"用户长期效用"。

这篇文章我不打算只评价 TickClip 的理念有多好,而是想把它作为一个技术案例来拆解:一个能诚实说"不要买"的购物代理,需要哪些模块支撑?它的 prompt 和普通购物助手有什么本质区别?如果我们要自己做一个最小实现,代码应该怎么组织?文章最后会给出一个可以直接运行的参考实现,并把我认为这类 agent 最容易踩的坑和工程化建议一并说清楚。

1. 为什么"建议不买"的 AI 购物代理值得关注

先看一个现象:现在几乎所有购物类 agent,优化目标都是"让用户下单"。品牌方看 GMV,平台看转化率,推荐系统看点击率。整个链路里的每一个环节,都在往"成交"方向推用户。当我们把一个 LLM Agent 接到这个链路里时,它也会无意识地继承这种立场,因为它的 prompt、工具、评分标准,全都围绕"如何完成购买"来设计。

这带来一个结构性问题:agent 的立场天然偏向卖家,而它服务的却是买家。用户在冲动消费、买错型号、忽略替代品的时候,agent 通常会顺着用户的高预期,给出一个"看起来合理"的推荐。你问它这个耳机值不值得买,它会拼命找好评、参数亮点、品牌背书,然后把结论导向"值得买"。

TickClip 的价值恰恰在于反着做。从标题看,它的核心卖点不是"帮你买得更快",而是"帮你判断要不要买"。这个差异如果落到技术实现上,会产生一系列连锁变化:

  • 检索方向变了。普通购物 agent 检索的是"为什么这个商品好",TickClip 这类 agent 需要检索"为什么这个商品不该现在买"。
  • 信息权重变了。差评、历史价格、替代品、需求匹配度这些"劝退信号",在普通 agent 里是次要信息,在这种 agent 里是核心证据。
  • 输出形式变了。不再是一个"买它"的结论,而是一个 BUY / WAIT / DON'T_BUY 的三分决策,并且要求给出可验证的理由。

也就是说,这事真正值得技术人关注的点,不是"推荐不买"这个产品概念多新鲜,而是它代表了购物类 agent 里一种很少见的评估标准:这个 agent 不是以成交率衡量好坏,而是以用户是否做出了理性决策来衡量好坏。指标一变,整个系统设计都会跟着变。

2. TickClip 这类 AI 购物代理的核心概念与设计差异

2.1 什么是 AI shopping agent

AI shopping agent 可以理解为一个能自主完成购物任务的智能体。它通常具备以下能力:理解用户模糊的自然语言需求、调用搜索或商品 API 获取信息、做多商品对比、给出购买建议,有些还会自动完成下单流程。核心是把"逛、找、比、买"这个链路尽量自动化。

市面上多数实现是把 agent 当"高级搜索引擎"用:用户给需求,agent 搜出一堆商品,按评分和价格排序,推荐一个最高分。这个过程最大的问题是:推荐系统的评分依赖的是历史用户行为,它不会理解"你"这个具体的人到底需不需要。一个 4.8 分的商品对你可能毫无价值,因为你压根不需要这项功能。

2.2 "反向推荐"与传统购物助手的差异

TickClip 式的 agent,它的差异不在某个单一功能上,而在整条决策链路的立场上。我整理了一个对比表格:

维度传统购物 agentTickClip 这类反向推荐 agent
核心目标完成成交,提升转化率帮用户做出理性购买决策
检索方向找出商品优点、卖点、促销信息找出负面评价、价格风险、替代品、需求错配
信息权重好评与官方参数优先差评、长期评价、实际体验反馈优先
结论倾向偏向 BUY,给出"放心买"的话术允许 WAIT 和 DON'T_BUY,并且不为此道歉
成功指标下单率、GMV决策准确率、用户后悔率下降、退货率下降
输出设计商品卡片 + 推荐理由决策动作 + 置信度 + 证据链 + 下单前自查清单

可以看到,"推荐不买"不是简单地给商品打个低分,而是把 agent 的整个信息处理逻辑反转了。它要求模型主动去寻找"不买的理由",并且让这些理由足够具体、可验证,才能支撑一个反对结论。

2.3 为什么普通 LLM 做不到"反向推荐"

有人会说:那我在 prompt 里加一句"如果商品不好就告诉用户别买"不就行了?事实上没有那么简单。

原因在于,大型语言模型的训练语料里,购物推荐类内容绝大多数是"种草"内容,模型天然倾向于顺着用户表达输出积极结论。你只加一句"可以说不买",模型通常会给你一个很别扭的"如果……那么不建议,但总体来说还是可以尝试"的中庸答案。真正需要的是通过 prompt 结构和工具链,强迫模型先收集反向证据,再基于证据下判断,而不是直接让它生成一个"不买"的理由。这一点,我会在第 5 章的代码里演示。

3. 反向推荐 agent 的核心模块拆解

要做成一个 TickClip 思路的购物 agent,光靠一个 LLM 的 prompt 是不够的。从工程上看,至少有五个模块需要认真设计。

3.1 需求理解模块

这个模块负责把用户的模糊需求变成可判断的约束条件。比如"我想买个好一点的降噪耳机",它要进一步拆解为:预算区间是多少、主要使用场景(通勤/办公/运动)、是否在乎便携性、对降噪强度的要求有多高、是否接受二手、多久之内必须用上。

更重要的是,它还应该识别"伪需求"。比如用户说"最近心情不好想买个耳机",这类需求背后可能是情绪驱动而非功能驱动。反向推荐的 agent 在这种情况下应当给出 WAIT 而非 BUY,这是普通购物 agent 完全不会考虑的。

3.2 商品信息采集模块

这个模块负责获取候选商品的完整信息。至少包括:价格、历史价格曲线、评分、评论数量、差评摘要、官方参数、优惠活动。目前公开可用的电商 API 有限,很多项目会通过爬虫或第三方比价服务获取数据,这块也是合规风险最高的部分。建议优先使用平台官方开放接口,或者商用比价 API。

3.3 反向证据收集模块

这是整个系统最核心的模块。它要做的事情是:主动寻找不利于"立刻下单"的证据。具体包括:

  • 差评分析:从大量中差评里提取重复出现的问题,比如品控、售后、发热、噪音。
  • 价格风险:对比历史价格,判断当前是否处于高位。
  • 替代品挖掘:查找同品牌上一代、竞品同价位产品,判断是否有更好的选择。
  • 需求匹配度:对照用户需求约束,检查商品是否存在明显错配。
  • 长期成本:耗材、维护、生态绑定带来的后续支出。

这个模块在技术上可以用一次独立的 LLM 调用来完成,也可以做成一个多工具并行的检索流程。关键是它和推荐模块解耦:先收集反面证据,再让决策模块基于正反两面信息做判断,而不是让模型一次性生成又找优点又找缺点的混杂结果。

3.4 决策与输出模块

决策模块接收正反两面信息,输出一个结构化决策。我建议采用三分法:

  • BUY:现在买是理性的。
  • WAIT:需求真实存在,但可以等促销、换渠道、等下一代。
  • DON'T_BUY:不应该买,原因是需求不成立或商品质量不值得。

输出不能只是一个动作,还应该包含置信度、理由列表、下单前自查清单。这个自查清单很重要,它把一部分判断责任交还给用户,避免 agent 给出错误建议时用户完全没有复核机会。

3.5 记录与复盘模块

一个负责任的购物 agent 应该记住自己给过的建议。用户三个月前听你的买了某产品,后来发现不好用,这个反馈如果无法回流,agent 就永远学不会。工程上可以用一个简单的历史记录表,记录每次建议和后续用户反馈,定期重算"建议准确率"。这也是构建评测集的第一步。

4. 环境准备与前置条件

下面开始搭建一个最小可运行的参考实现。这个 demo 借鉴 TickClip 的产品思路,但代码是我为演示写的,并非 TickClip 官方实现。它只解决一个核心问题:让读者看到"反向证据收集 + 决策输出"这个链路在代码里长什么样。

4.1 运行环境

  • 操作系统:Windows / macOS / Linux 均可
  • Python 版本:3.9 及以上
  • 依赖:openai(仅当使用真实模型时需要)
  • GPU:不需要,LLM 调用走 API 或本地 mock

4.2 安装步骤

建议先创建虚拟环境:

mkdir tickclip_demo && cd tickclip_demo python3 -m venv venv source venv/bin/activate # 如果使用真实模型,需要安装 openai SDK pip install openai

如果只想先跑通演示流程,不需要安装任何第三方依赖,因为默认的 mock 模式只用 Python 标准库。

4.3 目录结构

tickclip_demo/ ├── agent.py # 购物决策 agent 核心逻辑 ├── prompts.py # prompt 模板 ├── mock_llm.py # 无网络 mock 实现 └── run_demo.py # 演示入口

5. 完整示例:一个 TickClip 思路的购物代理参考实现

5.1 Prompt 设计

先说结论:反向推荐的关键在 prompt 结构,不在模型多聪明。如果让模型一次性输出"该不该买",它很容易打太极。正确做法是拆成两次调用:第一次只收集反面证据,第二次基于证据做决策。

""" 文件路径: tickclip_demo/prompts.py 这里把"找不买的理由"拆成了两个独立步骤: 1. 反向证据收集:让模型主动搜索不利于购买的信号。 2. 决策判断:结合正反两面证据输出最终结论。 """ EVIDENCE_SYSTEM_PROMPT = """ 你是一个购物决策分析助手,你的目标不是说服用户购买,而是帮助用户避免冲动消费和错误购买。 请基于给定的用户需求与候选商品信息,完成两项任务: 1. 找出所有"不应该立刻购买"的证据,包括:价格风险、质量问题、需求匹配度不足、替代品优势等。 2. 指出当前信息中缺少哪些关键信息,例如售后政策、真实评测、长期使用反馈。 要求: - 输出必须是 JSON 对象,字段为 negative_evidence 和 missing_info。 - negative_evidence 是字符串数组,每一项都必须有依据。 - 不要编造商品页面中不存在的评价;如果信息不足,请写入 missing_info。 """ DECISION_SYSTEM_PROMPT = """ 你是一个克制、理性、以用户长期利益为目标的购物决策助手。 你会拿到:用户需求、候选商品信息、反向证据。 请从用户角度判断,对当前这个商品给出一个动作: - BUY:可以购买 - WAIT:暂时不要买,等待更好的时机、渠道或价格 - DON'T_BUY:不建议购买 输出必须是 JSON 对象,字段: - action: 以上三个字符串之一 - confidence: 0 到 1 之间的浮点数 - reasons: 字符串数组,说明判断理由 - checks: 字符串数组,列出用户下单前应该自己再确认的事项 注意: - 当反向证据充分时,不要为了避免冲突而转向 BUY。 - 优先给出可执行的建议,不要只说"看情况"。 """

这里有个容易被忽略的设计点:第二次决策的输入里,不但要有商品信息,还必须把第一次收集到的negative_evidence原样传进去。如果省掉这一步,模型会退回"种草模式",因为它的直觉是在帮用户完成购买。

5.2 无网络 mock 实现

为了让没有 API key 的读者也能立刻跑通流程,我写了一个 mock 类。它根据system_prompt判断当前阶段,返回一个符合预期格式的 JSON。注意,mock 里的证据和理由都是固定写死的,目的只是演示链路,不代表真实模型输出。

""" 文件路径: tickclip_demo/mock_llm.py 默认的 LLM 实现:不依赖外网,也可以跑通演示流程。 """ import json def call_llm_mock(system_prompt: str, user_prompt: str) -> str: if "反向证据收集" in system_prompt: return json.dumps( { "negative_evidence": [ "该商品在近 3 个月出现过多次价格下调,当前价格处于相对高位", "差评区提到品控不稳定,存在一定比例一星反馈", "存在同品牌上一代型号,功能差异很小而价格低 30%", "用户需求是降噪耳机,但该商品主打音质,降噪表现一般", ], "missing_info": [ "官方保修时长与退换政策", "用户对佩戴舒适度的长期反馈", ], }, ensure_ascii=False, ) if "决策判断" in system_prompt: return json.dumps( { "action": "DON'T_BUY", "confidence": 0.85, "reasons": [ "价格处于历史高位,且上一代产品可以满足核心需求", "降噪能力与用户核心需求不匹配", "短期内容易出现同价位新款或降价", ], "checks": [ "确认是否真的需要降噪耳机,还是只是情绪化购物", "对比上一代型号的实际售价与保修政策", "等待一次大促或渠道促销再决策", ], }, ensure_ascii=False, ) return "{}"

5.3 Agent 核心逻辑

Agent 类的核心方法是analyze(),它完成了完整的两阶段调用。先收集反面证据,再基于证据做决策。为了展示真实场景的接入方式,我也写了一个_call_real()方法,用 OpenAI 兼容接口调用真实模型。

""" 文件路径: tickclip_demo/agent.py """ import json import os from typing import List, TypedDict from prompts import EVIDENCE_SYSTEM_PROMPT, DECISION_SYSTEM_PROMPT from mock_llm import call_llm_mock class Product(TypedDict): id: str title: str price: float rating: float review_count: int bad_review_snippets: List[str] alternatives: List[str] class Decision(TypedDict): action: str confidence: float reasons: List[str] checks: List[str] class TickClipLikeAgent: def __init__(self, use_mock: bool = True, model: str = "gpt-4o-mini"): self.use_mock = use_mock self.model = model def analyze(self, user_need: str, product: Product) -> Decision: # 第一步:收集反向证据 evidence = self._collect_negative_evidence(user_need, product) # 第二步:生成决策 user_prompt = self._build_decision_prompt(user_need, product, evidence) raw = self._call(DECISION_SYSTEM_PROMPT, user_prompt) return json.loads(raw) def _collect_negative_evidence(self, user_need: str, product: Product) -> dict: product_text = json.dumps(product, ensure_ascii=False, indent=2) user_prompt = f"用户需求:{user_need}\n\n候选商品信息:\n{product_text}" raw = self._call(EVIDENCE_SYSTEM_PROMPT, user_prompt) return json.loads(raw) def _build_decision_prompt( self, user_need: str, product: Product, evidence: dict ) -> str: return ( f"用户需求:{user_need}\n\n" f"候选商品信息:\n{json.dumps(product, ensure_ascii=False, indent=2)}\n\n" f"反向证据(必须认真对待):\n{json.dumps(evidence, ensure_ascii=False, indent=2)}" ) def _call(self, system_prompt: str, user_prompt: str) -> str: if self.use_mock: return call_llm_mock(system_prompt, user_prompt) return self._call_real(system_prompt, user_prompt) def _call_real(self, system_prompt: str, user_prompt: str) -> str: from openai import OpenAI client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY")) resp = client.chat.completions.create( model=self.model, messages=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt}, ], temperature=0.2, ) return resp.choices[0].message.content

这里值得注意的设计是_build_decision_prompt()这个方法。它把商品信息和反向证据放进同一个 user prompt 里,但没有把"正面的商品优点"单独包装成一段很长的说服性文本。这样可以避免模型被商品厂商的描述带偏。如果你在真实项目里接入商品详情页的 HTML,也应该先抽取出关键字段再传给模型,而不是把整页内容都塞进去。

5.4 运行入口

""" 文件路径: tickclip_demo/run_demo.py """ import json from agent import TickClipLikeAgent def main(): user_need = "我每天通勤两小时,想买一款降噪耳机,预算 1500 到 2500 元" product: Product = { "id": "P001", "title": "某品牌旗舰款头戴式降噪耳机 HX-2000", "price": 2399, "rating": 4.6, "review_count": 12800, "bad_review_snippets": [ "用了一个月出现右耳电流声", "降噪开满之后有轻微底噪", "戴久了夹头", ], "alternatives": [ "上一代 HX-1000,价格 1699,降噪能力接近", "竞品 QC-Ultra,价格 1899,佩戴更舒适", ], } agent = TickClipLikeAgent(use_mock=True, model="gpt-4o-mini") decision = agent.analyze(user_need, product) print("=" * 60) print("TickClip 思路的购物决策结果") print("=" * 60) print(json.dumps(decision, ensure_ascii=False, indent=2)) if __name__ == "__main__": main()

run_demo.py里,我把用户需求和商品信息都写死成了演示数据。真实项目中,用户需求应该由对话模块产生,商品信息应该来自比价 API 或商品数据库。这里的重点是让你看清调用关系。

6. 运行结果与效果验证

运行演示:

cd tickclip_demo # 有虚拟环境时先激活 source venv/bin/activate python run_demo.py

预期输出如下:

{ "action": "DON'T_BUY", "confidence": 0.85, "reasons": [ "价格处于历史高位,且上一代产品可以满足核心需求", "降噪能力与用户核心需求不匹配", "短期内容易出现同价位新款或降价" ], "checks": [ "确认是否真的需要降噪耳机,还是只是情绪化购物", "对比上一代型号的实际售价与保修政策", "等待一次大促或渠道促销再决策" ] }

怎么判断这个结果是否有效?我建议从三个角度观察:

  1. 输出格式是否合法action是否在三个枚举值内,confidence是否为 0 到 1 的浮点数,reasonschecks是否都是字符串数组。
  2. 证据是否支撑结论。如果 action 是 DON'T_BUY,给定的 reasons 是否引用到了具体信息,比如价格、差评、替代品。如果理由全是"感觉一般""不太推荐"这种空话,说明 prompt 结构需要加强。
  3. 是否提供了可执行的下一步。好的反向推荐不应该只说"No",它还要告诉用户怎么做,是等促销、换型号还是彻底放弃。

运行失败时,第一步要看的是json.loads()是否报错。真实模型经常输出非 JSON 内容,比如代码块标记、前后多出的文字,这在第 7 章会详细说。Mock 模式基本不会失败,如果 mock 都报错,先检查 Python 版本和文件目录结构。

7. 常见问题与排查思路

问题现象可能原因排查方式解决方案
json.loads()报错,LLM 返回的内容无法解析模型输出了多余文字或代码块标记打印原始raw内容,观察前后缀在 prompt 中要求只输出 JSON;增加输出清理函数,去除 ```json 和前后空白
真实模型几乎永远不会给出 DON'T_BUY模型的推荐立场仍然偏向"成交"检查是否把negative_evidence真正传入了决策 prompt将反向证据作为决策 prompt 的强制输入;降低 temperature;必要时用 few-shot 示例展示 DON'T_BUY 样本
结论过于保守,全部输出 WAIT模型为了安全倾向不表态查看每个 WAIT 的理由是否具体;评估评测集里 WAIT 占比在 prompt 中说明"当证据充分时应给出明确 BUY 或 DON'T_BUY";增加置信度阈值判断
mock 模式正常,切到真实模型后效果差很多mock 的固定输出掩盖了 prompt 缺陷单独测试证据收集阶段的输出质量先跑 10 个真实商品样本,人工检查negative_evidence的覆盖率,再调决策 prompt
商品信息过多,API 成本高商品详情页全文被直接塞入 prompt检查传入内容是否包含无关字段只保留商品标题、价格、评分、差评摘要、替代品等结构化字段;做截断或向量检索
无法判断模型给出的理由是否真实模型幻觉,编造"降价 30%"这类事实将理由中的事实性陈述与商品数据做字符串匹配或人工抽检要求模型引用输入中的具体字段;对没把握的信息允许写入missing_info

这里我想重点强调最后一个问题:幻觉。购物决策 agent 一旦编造理由,危害比普通聊天助手大得多。用户可能因为一个虚构的"历史低价"放弃购买,也可能因为一个虚构的差评错过好商品。工程上最有效的缓解手段是:让模型只基于输入信息做判断,并明确允许它说"信息不足"。不要在 prompt 里要求模型"自行判断市场行情"。如果你想让模型参考历史价格,就把历史价格数据喂给它,而不是让它凭记忆编。

8. 工程化的最佳实践与建议

8.1 建立自己的评测集

购物决策是个开放问题,别指望靠感觉调优。建议你从第一天开始就积累评测集。每个评测样本包含:用户需求描述、候选商品结构化信息、标准答案(BUY/WAIT/DON'T_BUY)以及理由里的关键事实点。最少先做 30 条,覆盖三类动作、不同商品类目和不同价格区间。后续所有 prompt 改动都跑一遍评测,看三类动作的准确率变化,而不是只看几个手工案例。

8.2 对真实 LLM 输出做防御式解析

真实模型的输出不可控,所以解析层一定要做加固。建议你封装一个safe_parse_json()函数:

  • 去除输出中的 ```json 代码块标记。
  • 找到第一个{和最后一个}截取 JSON 子串。
  • 解析失败时自动把异常信息和原始输出返回,方便排查。
  • action字段做枚举校验,不符合时降级为WAIT,并记录日志。

这类防御代码看起来不起眼,但在生产环境里能避免大量线上故障。

8.3 数据源与合规边界

构建这类 agent,最大的工程风险不在模型,而在商品数据。直接爬取电商平台页面可能违反平台条款,也存在封号风险。更稳妥的做法是使用平台官方开放 API,或接入有授权的比价服务。即便拿到数据,也要注意:

  • 价格历史数据要标注统计口径,比如"近 90 天自营渠道价格区间"。
  • 用户购物数据属于敏感信息,不要长期保存超过必要的范围。
  • agent 如果具备自动下单能力,务必设置最低人工确认门槛,比如金额超过 500 元必须用户二次确认。

8.4 输出可解释性优先

TickClip 这类产品想要建立用户信任,可解释性比准确性更早暴露问题。我给用户的每个决策都包含reasonschecks,这不是为了好看,而是为了让用户可以反驳 agent。如果用户发现理由中有任何一条与事实不符,他要么撤销决策,要么对 agent 失去信任。所以在 prompt 里尽量减少"宏大判断",比如"市场趋势下滑""竞品全面碾压"这种没有数据支撑的表述,而要多输出"该商品近 3 个月的公开降价记录显示""用户需求与商品主打功能不匹配"这种可验证的内容。

8.5 用缓存降低 API 成本

购物数据相对稳定,同一个商品短时间内不会频繁变化。可以对同一商品 ID 的决策结果做缓存,比如 12 小时有效。只有当价格、评分等重要字段发生变化时,才重新调用模型。搜索结果的缓存也要考虑,避免用户每次问同一个问题都产生多次 LLM 调用。

9. 总结与后续实践方向

TickClip 这个项目的出现,给 AI 购物 agent 提供了一个稀缺的视角:购物助手不一定只能帮用户"买",它还可以帮用户"不买"。从技术实现上看,这件事并不复杂,核心就是两段式 prompt 结构加一个"反向证据优先"的决策逻辑,但它背后代表的产品立场,会直接影响 agent 的目标函数、数据采集方式和评测体系。

如果你打算自己动手做一个类似的东西,我建议按下面的顺序推进:

  • 先跑通本文的参考实现,把 mock 换成真实模型,观察输出差异。
  • 然后找一个你熟悉的商品类目,手动构造 10 条评测数据,单独测证据收集阶段的质量。
  • 接着把商品数据从写死字典改为接一个真实的比价 API,处理字段缺失和价格波动。
  • 最后再考虑加缓存、历史记录和用户反馈回流。

对于 TickClip 这类产品,它最终能走多远,取决于一个问题:当用户真的因为 agent 的劝阻而省下一笔钱时,这个 agent 如何证明自己的价值。这比任何推荐算法都更难量化,但也正是这个方向最值得做的原因。建议收藏这篇文章,后面搭建自己的购物决策 agent 时可以直接复用其中的 prompt 和代码结构。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询