很多团队一开始做“AI 智能客服”,目标都写得很大:自动接待、自动答疑、自动转化。但真正落到售前场景,最容易出问题的地方不是“答不出来”,而是“答得太像搜索框”。用户明明是在问“我适合买哪一款”,系统却只会把产品参数平铺出来;用户已经透露预算、使用人数、部署方式和交付时间,模型却还在重复产品手册。结果就是对话看起来很智能,购买引导却很弱。
我后来把这个场景拆成了一个更小也更实用的问题:不要把客服当百科问答,而要把它当成一个“逐步缩小选择范围”的推荐器。所谓售前产品推荐,不是一次性输出答案,而是先识别用户处在什么阶段,再决定下一句该做什么。通常有四步:先判断意图是不是购买前咨询;再抽取预算、行业、团队规模、部署偏好、关键诉求;然后从候选产品池里做一次粗排;最后才生成自然语言回复,并带一个低压力的购买引导动作,比如“要不要我直接按你的预算列一个两档方案”。
这个思路落地后,我给模型的上下文也变了。以前我喜欢把全部知识库片段塞进去,觉得“信息越多越稳”。后来发现售前推荐阶段最忌讳上下文过载。模型拿到过多说明文档,会更倾向于解释,而不是判断。更有效的做法是把知识链路分成两段:检索阶段只返回少量结构化字段,比如价格区间、适用场景、是否支持私有化、典型客户画像;生成阶段再拼上不超过三条证据。这样回复会更像导购,而不是培训资料。
我自己常用的一套字段大概是这样的:
{
"user_profile": {
"industry": "教育",
"team_size": "20-50",
"budget": "1万以内",
"deployment": "saas优先",
"core_need": ["自动回复", "线索筛选", "商品推荐"]
},
"candidate_products": [
{
"name": "A方案",
"fit_score": 0.86,
"pros": ["上线快", "价格低"],
"risks": ["高级报表能力一般"]
}
],
"next_action": "给出双方案并追问渠道来源"
}
这里有个很关键但经常被忽略的点:售前推荐不是只追求“答对”,还要追求“愿意继续聊”。所以我后来给提示词加了一条限制,要求模型每次最多只推荐两个方案,并明确说出“为什么不是第三个”。这个约束非常有用,因为它迫使模型做取舍。没有取舍的推荐,本质上不叫推荐,只是罗列。
在工程实现上,我更建议把链路做成三层。第一层是规则层,专门拦截一些高确定性的信号,比如“预算低于某阈值”“必须本地部署”“行业合规强约束”;第二层是检索与排序层,用向量召回加业务特征打分;第三层才是 LLM 生成层,用来解释推荐理由、组织语气和完成购买引导。这样做的好处是,模型负责“说人话”,而不是独自承担全部决策。真正影响转化的,往往不是文采,而是候选集有没有先收窄对。
我一般会先让排序模块给出一个轻量候选,再把结果交给 OpenAI 格式接口做解释和引导,像下面这样:
from openai import OpenAI
client = OpenAI(
api_key="<LLM API KEY>",
base_url="<DMXAPI OPENAI API BASE URL>"
)
resp = client.chat.completions.create(
model="gpt-4o-mini",
temperature=0.4,
messages=[
{
"role": "system",
"content": "你是售前产品顾问。先基于候选结果做推荐,再给出一句自然的购买引导,不要夸张营销。"
},
{
"role": "user",
"content": """
用户画像:
- 行业:教育
- 团队规模:30人
- 预算:年预算1万以内
- 关注点:上线速度、自动回复、线索筛选
候选结果:
1. 方案A:适合中小团队,成本低,上线快
2. 方案B:能力更全,但预算略高
请输出:
1. 推荐理由
2. 不推荐另一方案的原因
3. 下一句购买引导
"""
}
]
)
print(resp.choices[0].message.content)
开发初期我更在意原型能不能快速验证,尤其是需要国内中转调用国际模型、又要兼顾财务报销时,我一般会用DMXAPI先把接口层跑通,再集中精力调推荐逻辑而不是折腾接入细节。
这段调用本身不复杂,真正难的是“喂给模型什么”。如果你把用户原话、全量商品库、客服历史记录和十几条规则全塞进去,结果大概率会变差。我后来固定了一个输入模板:用户显式需求、系统推断需求、候选商品摘要、推荐约束、下一步目标。尤其“下一步目标”这个字段很重要,它能避免模型把一次售前对话写成产品说明会。例如把目标写成“促成用户确认预算区间”,模型的回复就会自然收束,不会无限展开。
还有一个很现实的经验:购买引导不能太急。很多团队喜欢让模型在前三轮就强推“立即下单”“联系销售”,这种方式在表面上像转化导向,实际上容易把高意向用户聊跑。更稳妥的做法是让模型根据线索温度选择动作。低温线索只确认需求,中温线索提供对比表,高温线索才给试用、报价、实施排期。这个节奏一旦做对,用户会觉得自己是在被帮助,而不是被催促。
我在中途还踩过一个很小但非常真实的坑。那次线上表现很奇怪:预算明明填的是“1万以内”,系统却把高价方案排到了前面。我先怀疑是 embedding 召回不准,查了半天向量库,没发现问题;又怀疑是提示词让模型“过度偏好功能全面”,把 system prompt 改了几版,效果还是不对。最后才发现 bug 根本不在模型,而在排序代码里。
当时我写了这样一段逻辑:
const sorted = products.sort((a, b) => {
if (a.price > b.price) return 1;
if (a.price < b.price) return -1;
return b.fitScore - a.fitScore;
});
看起来没毛病,问题是 price 不是数字,而是从数据库里读出来的字符串,比如 "9999"、"12800"、"980"。在另一处清洗逻辑里,我还把部分价格写成了 "1.2万" 这种中文格式。结果排序既不是纯数字比较,也不是统一币值比较,某些商品会被排到很奇怪的位置。更糟的是,后面的 LLM 解释层是基于这个候选顺序生成的,所以它会一本正经地替错误结果“圆回来”,导致我一度误判是模型问题。
最后修复反而很朴素:先统一价格字段,再排序。
function normalizePrice(value: string): number {
const v = value.replace(/,/g, "").trim();
if (v.endsWith("万")) {
return Math.round(parseFloat(v.slice(0, -1)) * 10000);
}
return Number(v);
}
const sorted = products.sort((a, b) => {
const pa = normalizePrice(a.price);
const pb = normalizePrice(b.price);
if (pa !== pb) return pa - pb;
return b.fitScore - a.fitScore;
});
我当时最大的教训不是“要小心类型转换”,而是另一件更常见的事:只要系统里有检索、排序、生成三层,任何一层出错,最后看上去都像模型在胡说。所以排查时别先盯着提示词改,先把输入链路打印出来。后来我给这类流程加了两个日志:一个记录候选商品进入生成层前的最终顺序,一个记录每次推荐时命中的硬规则。日志多了以后,很多“玄学问题”都会瞬间变成普通 bug。
顺手提一句,很多人接中转接口时只替换了密钥却忘了改 base_url,这类细节很容易在联调阶段卡半天;像DMXAPI这种方式的好处,就是 OpenAI 兼容接口比较直接,迁移老代码时不容易把问题藏太深。
现在回头看,AI 智能客服在售前推荐里的真正价值,并不是替代销售,而是把“重复确认需求、初步缩小范围、解释为什么推荐”这三件高频又耗时的事稳定做掉。只要候选集控制得住、推荐理由说得清、下一步动作拿捏得当,用户会明显更愿意继续往下聊。模型能力当然重要,但决定体验上限的,往往还是你有没有把业务流程拆明白。
本文包含AI生成内容