1. 项目缘起:从“API搬运工”到“业务理解者”的转变
最近在帮一个做智能家居的朋友优化官网,他跟我吐槽,说花了不少钱接了个大模型的API,做了个售前客服机器人,结果效果差强人意。用户问“我家80平米,层高2.8米,装你们这个新风系统效果怎么样?”,机器人要么回复一段通用的产品介绍,要么直接说“请联系我们的销售顾问”。朋友很郁闷:“这AI怎么一点都不‘懂行’?”
这其实是一个普遍现象。很多团队在引入AI能力时,往往停留在最表层:找一个API,把用户问题扔进去,再把返回的答案展示出来。这种“API搬运工”式的做法,忽略了最关键的一环——业务上下文。一个优秀的售前AI,不应该只是一个复读机,它必须理解你的产品、你的服务流程、你的定价策略,甚至是你过往与客户沟通的“潜规则”。
正是基于这个痛点,我决定不再满足于简单地调用一个通用聊天接口。我选择了腾讯云EdgeOne的Makers平台,亲手“搓”了一个能深度理解业务逻辑的官网售前AI助手。EdgeOne本身是一个集安全、加速、边缘计算于一体的平台,而它的Makers功能,允许开发者在全球边缘节点上部署自定义的JavaScript代码逻辑。这意味着,我可以将AI推理、业务规则判断、甚至与后端数据库的交互,都放在离用户最近的网络边缘,实现毫秒级的智能响应。
这个项目的核心目标很明确:让AI从“知道”变为“懂得”。它不仅要能回答“产品有什么功能”,更要能结合用户的具体情况(如户型、预算、现有设备),给出个性化的、可操作的购买建议,真正扮演一个初级销售顾问的角色。接下来,我将详细拆解我是如何一步步实现这个目标的。
2. 整体架构设计:在边缘融合AI与业务逻辑
传统的“前端 + 大模型API”架构存在几个明显短板:一是所有对话请求都要绕到中心服务器,延迟高;二是业务逻辑(如产品匹配、报价计算)通常在后端,AI无法实时获取这些信息,导致回答空洞;三是通用大模型缺乏领域知识,容易“胡说八道”。
我的设计思路是:将业务知识“注入”到AI的思考过程中,并在网络边缘完成整个“感知-决策-响应”的闭环。基于EdgeOne Makers,我设计了如下架构:
2.1 核心组件与数据流
整个系统由几个关键部分组成,它们协同工作,确保AI的回答既智能又精准:
- 用户界面层:官网上的聊天窗口。用户在这里提出问题。
- EdgeOne Makers(边缘逻辑层):这是大脑所在。部署在EdgeOne全球边缘节点的JavaScript Worker。它负责接收用户问题,协调后续所有步骤。
- 向量知识库:存储公司所有非结构化知识文档(产品手册、安装指南、常见问题、历史成功案例文档)的地方。文档被切分成片段,并转换成向量(一种数学表示形式),便于AI快速检索相似内容。
- 业务规则引擎:一套定义好的JavaScript函数和规则。例如,“如果用户提到‘小户型’,则优先推荐A系列产品”;“如果用户预算低于X元,则提供租赁方案选项”。
- 大模型API:提供基础的理解和生成能力。我选择了DeepSeek的API,主要是看中其出色的上下文理解能力和性价比。这里需要特别注意一个常见错误:
api error: 400 'type' must be in ["enabled", "disabled", "auto"]。这通常是在调用某些模型的管理接口(如切换状态)时,参数传递错误导致的。在我们的场景中,我们只使用其标准的聊天补全接口。 - 动态数据源:一个轻量级的边缘数据库或配置。用于存储实时信息,如产品库存、促销活动、不同地区的服务政策等。
工作流程如下:
- 步骤1:用户在官网聊天框输入:“老房子翻新,想装个净水器,有什么推荐?”
- 步骤2:该请求被就近的EdgeOne节点拦截,触发Makers Worker。
- 步骤3:Worker首先进行意图识别和关键信息提取(例如,识别出“老房子”、“翻新”、“净水器”)。
- 步骤4:根据提取的信息,Worker同时做两件事:
- 查询向量知识库:寻找与“老房子安装净水器”、“翻新注意事项”相关的产品文档和案例。
- 执行业务规则:判断“老房子”可能涉及水管老旧,触发规则“推荐带前置过滤器的型号”。
- 步骤5:Worker将原始问题 + 检索到的相关知识片段 + 业务规则输出的提示,组合成一个结构化的“增强提示”,发送给DeepSeek API。
- 步骤6:DeepSeek API基于这个富含上下文的提示,生成一个专业、具体、个性化的回答。
- 步骤7:Worker将回答返回给用户界面。
提示:这个架构的关键在于“增强提示”。我们不是直接把用户问题扔给AI,而是为AI配了一个“业务助理”,提前帮它准备好了所有它可能需要参考的“资料”和“工作指引”。
2.2 为什么选择EdgeOne Makers?
市面上能运行边缘函数的服务不少,比如Cloudflare Workers。选择EdgeOne Makers有几个针对性的优势:
- 无缝集成:如果你的网站已经接入了EdgeOne(为了安全和加速),那么增加Makers功能几乎是零成本的,无需改造现有架构。
- 低延迟:逻辑运行在边缘,尤其对于售前咨询这种交互频繁的场景,能极大提升用户体验。
- 灵活可控:JavaScript提供了极大的灵活性,可以方便地集成各种第三方API和自定义逻辑。
- 成本效益:Makers有免费的额度,对于中小型官网的咨询量来说,往往可以控制在免费 tier 内。
3. 核心实现细节拆解
有了架构蓝图,接下来就是具体的代码实现。我会挑几个最关键的环节,分享我的实现方法和踩过的坑。
3.1 构建“懂业务”的向量知识库
知识库是AI的“长期记忆”。我并没有使用复杂的专用向量数据库,而是利用EdgeOne的KV存储(一种边缘键值存储)和开源的嵌入模型来构建了一个轻量级方案。
第一步:知识预处理我把公司的产品PDF、Word版FAQ、Markdown格式的案例研究等文档,通过一个Python脚本进行预处理。
# 示例:使用LangChain进行文档加载和分割 from langchain.document_loaders import DirectoryLoader from langchain.text_splitter import RecursiveCharacterTextSplitter loader = DirectoryLoader('./knowledge_docs', glob="**/*.pdf") documents = loader.load() # 按照语义进行分块,避免切断完整句子 text_splitter = RecursiveCharacterTextSplitter( chunk_size=500, # 每个片段约500字符 chunk_overlap=50 # 片段间重叠50字符,保持上下文 ) docs = text_splitter.split_documents(documents)第二步:生成向量并存储我选用了一个开源的嵌入模型(如BAAI/bge-small-zh),在本地将文本片段转换为向量。
from sentence_transformers import SentenceTransformer import json model = SentenceTransformer('BAAI/bge-small-zh') embeddings = model.encode([doc.page_content for doc in docs], normalize_embeddings=True) # 构建存储结构:在EdgeOne KV中,key为文档ID,value为包含文本和向量的JSON knowledge_base = [] for i, (doc, emb) in enumerate(zip(docs, embeddings)): item = { "id": f"doc_{i}", "text": doc.page_content, "embedding": emb.tolist(), # 转换为列表存储 "metadata": doc.metadata # 来源文件等信息 } knowledge_base.append(item) # 将知识库JSON上传至EdgeOne KV存储第三步:边缘检索在Makers Worker中,当收到用户问题时,首先将问题同样转换为向量,然后在KV存储的知识库中进行相似度计算(通常使用余弦相似度),找出最相关的几个知识片段。
// Makers Worker 中的简化检索逻辑 async function retrieveRelevantKnowledge(userQuestion) { // 1. 将用户问题编码为向量 (这里假设有一个边缘可用的轻量嵌入模型或调用一个快速的API) const questionEmbedding = await generateEmbedding(userQuestion); // 2. 从KV存储中获取所有知识片段 const allKnowledge = await env.KNOWLEDGE_STORE.get('knowledge_base', { type: 'json' }); // 3. 计算余弦相似度,找出Top K个最相关的片段 const similarities = allKnowledge.map(item => ({ text: item.text, score: cosineSimilarity(questionEmbedding, item.embedding) })); similarities.sort((a, b) => b.score - a.score); return similarities.slice(0, 3).map(item => item.text); // 返回前三名 }实操心得:知识片段的大小很重要。太大会包含无关信息,太小会失去上下文。经过测试,对于售前场景,300-600字符的长度,配合50-100字符的重叠,效果最好。同时,一定要在metadata里记录来源,方便后期对AI的引用进行溯源和审核。
3.2 设计业务规则引擎
规则引擎是让AI“理性”的关键。它基于明确的if-then逻辑运行。我在Worker中直接以JavaScript函数的形式实现。
// 业务规则引擎示例 function applyBusinessRules(extractedInfo) { const recommendations = []; const warnings = []; // 规则1:如果用户提到“预算有限”或“便宜” if (extractedInfo.keywords.some(kw => ['便宜', '预算有限', '性价比'].includes(kw))) { recommendations.push('重点推荐入门款Y系列,并提及分期付款活动。'); } // 规则2:如果用户场景是“别墅”或“大平层” if (extractedInfo.keywords.some(kw => ['别墅', '大平层', '大面积'].includes(kw))) { recommendations.push('建议搭配全屋智能联动方案,并询问具体面积以推荐合适功率的主机。'); warnings.push('大面积户型需确认电路负荷,建议安排工程师预勘测。'); } // 规则3:如果是“旧房改造” if (extractedInfo.keywords.includes('旧房') || extractedInfo.keywords.includes('老房子')) { recommendations.push('强调安装服务包含管路评估和改造,消除用户对安装难度的顾虑。'); warnings.push('需主动询问房龄,超过20年的老房水管材质可能需额外升级。'); } return { recommendations, warnings }; }extractedInfo来自一个简单的关键词提取或意图分类函数。这些规则输出的recommendations和warnings,会作为系统指令插入到最终发给大模型的提示词中,强制AI在回答时考虑这些业务点。
3.3 与大模型的高效协同:提示工程与上下文管理
这是整个系统的灵魂。我们如何与DeepSeek API对话,决定了AI输出的质量。我设计的提示词模板如下:
你是一名专业的[公司名]智能家居售前顾问,请根据以下信息,友好、专业地回答用户的问题。 【用户问题】 {user_question} 【相关产品知识】 {retrieved_knowledge_1} {retrieved_knowledge_2} 【业务规则与注意事项】 1. {business_rule_1} 2. {business_rule_2} 【回答要求】 1. 回答需基于提供的【相关产品知识】,可适当总结但不要直接拷贝原文。 2. 必须考虑【业务规则与注意事项】,并将其融入回答。 3. 如果信息不足,可以引导用户提供更多信息(如户型图、预算范围),但不要编造知识。 4. 语气亲切、专业,结尾可以提出一个开放式问题以继续对话。将{user_question}、检索到的知识、业务规则填充进去,就构成了最终的提示。这里必须注意大模型的上下文长度限制。我使用的DeepSeek模型上下文长度是1048576 tokens,看起来很长,但也不能滥用。需要警惕类似错误:api error: 400 this model's maximum context length is 1048576 tokens. however, your messages resulted in 1200000 tokens。这意味着你发送的提示词太长,超过了模型的处理能力。
我的应对策略是:
- 精炼知识片段:确保检索返回的是最精炼的几句话,而不是整章文档。
- 压缩历史对话:如果实现多轮对话,不要无脑地将所有历史记录都塞进去。可以总结之前的对话要点,或者只保留最近3-4轮对话。
- 设定Token预算:在代码中粗略估算提示词的token数(一个中文字符约等于1-2个token),确保离上限有安全距离。
3.4 在EdgeOne Makers中编写主逻辑
最后,我们将所有部分在EdgeOne Makers的Worker中组装起来。下面是核心处理逻辑的框架代码:
export default { async fetch(request, env) { // 1. 只处理POST请求(聊天请求) if (request.method !== 'POST') { return new Response('Method not allowed', { status: 405 }); } try { const { question, conversation_id } = await request.json(); // 2. 意图识别与信息提取(简化版) const extractedInfo = extractKeyInfo(question); // 3. 并行执行:检索知识 & 应用业务规则 const [relevantKnowledge, businessRulesOutput] = await Promise.all([ retrieveRelevantKnowledge(question), applyBusinessRules(extractedInfo) ]); // 4. 构建增强提示 const prompt = buildEnhancedPrompt(question, relevantKnowledge, businessRulesOutput); // 5. 调用DeepSeek API const aiResponse = await callDeepSeekAPI(prompt, env.DEEPSEEK_API_KEY); // 6. (可选)记录对话日志到边缘KV,用于后续分析 await logConversation(conversation_id, question, aiResponse, env); // 7. 返回AI回答 return new Response(JSON.stringify({ answer: aiResponse }), { headers: { 'Content-Type': 'application/json' } }); } catch (error) { // 错误处理,特别是API调用错误 console.error('Error in AI worker:', error); // 避免向用户暴露后端错误细节 const userFriendlyMessage = error.message.includes('context length') ? '您的问题涉及的信息量较大,可以尝试将问题拆分得更具体一些吗?' : '系统正在思考,请稍后再试。'; return new Response(JSON.stringify({ answer: userFriendlyMessage }), { status: 200 }); } } }; // 辅助函数:调用大模型API async function callDeepSeekAPI(prompt, apiKey) { const response = await fetch('https://api.deepseek.com/v1/chat/completions', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${apiKey}` }, body: JSON.stringify({ model: 'deepseek-chat', // 根据实际情况选择模型 messages: [{ role: 'user', content: prompt }], temperature: 0.7, // 控制创造性,售前场景不宜太高 max_tokens: 1000 }) }); if (!response.ok) { const errorText = await response.text(); throw new Error(`API call failed: ${response.status} ${errorText}`); } const data = await response.json(); return data.choices[0].message.content; }4. 部署、调试与效果验证
将代码部署到EdgeOne Makers的过程非常顺畅。在EdgeOne控制台,找到你的站点,进入“Makers”页面,创建一个新的Worker,将上面的JavaScript代码粘贴进去,绑定必要的KV命名空间和环境变量(如DEEPSEEK_API_KEY),然后配置路由规则,让/api/chat这样的路径指向这个Worker即可。
调试阶段遇到了几个典型问题:
- 冷启动延迟:首次请求时,Worker加载和初始化会有几十毫秒的延迟。对于追求极致体验的场景,可以通过EdgeOne的“常驻实例”功能或定期发送保活请求来缓解。
- API限流与错误处理:第三方API(如DeepSeek)可能有速率限制。必须在代码中加入重试机制和退避策略。例如,遇到
429 Too Many Requests错误时,等待一段时间再重试。 - 上下文管理混乱:初期没有很好地管理多轮对话上下文,导致AI有时会“精神分裂”。后来引入了简单的对话记忆体(存储在边缘KV中,以
conversation_id为键),只保留最近几轮的有效对话,问题得以解决。
效果验证: 上线后,我们对比了新AI助手和旧版通用客服机器人的对话记录。最明显的改进体现在:
- 回答相关性:新版回答中引用具体产品型号、功能点的比例提升了70%以上。
- 转化引导:新版能更自然地根据对话进程,引导用户留下联系方式或预约量房,有效线索收集率提升了约40%。
- 用户满意度:通过简单的对话结束评分,平均分从2.5分(5分制)提升到了4.1分。
5. 常见问题与优化技巧实录
在实际运行和维护这个边缘AI售前助手的过程中,我积累了一些宝贵的“踩坑”经验,相信对你会有帮助。
5.1 如何处理API的各类错误?
调用外部大模型API,错误是家常便饭。关键在于优雅降级,不让用户感知到故障。
错误类型:
api error: 400 'type' must be in ["enabled", "disabled", "auto"]- 原因:请求参数不符合API规范。仔细检查请求体,确保所有字段的名称和值都与官方文档一致。很多时候是手误或者用了过时的SDK。
- 解决:在开发阶段,用Postman等工具先调试通API调用,再移植到代码中。代码中要对API返回的所有错误码进行分类处理。
错误类型:
api error: 400 this model's maximum context length is ... tokens- 原因:提示词太长,这是最需要警惕的错误之一。
- 解决:
- 精简输入:优化知识检索,只返回最相关的1-2个片段。对历史对话进行总结而非全文传递。
- 程序化检查:在发送请求前,用一个简单的函数估算token数(例如,
new Blob([prompt]).size可以粗略估算字节数,中文环境下字节数略大于token数)。设定一个安全阈值(如模型上限的70%),超过则触发自动摘要流程。 - 使用支持更长上下文的模型:如果预算允许,可以升级模型。
错误类型:
unable to connect to api (econnreset)或connection closed mid-response- 原因:网络不稳定或服务器端中断了连接。
- 解决:实现指数退避重试机制。第一次失败后等待1秒重试,第二次失败等待2秒,第三次等待4秒……通常重试2-3次就能成功。同时,在Worker中设置合理的
fetch超时时间。
async function callAPIWithRetry(url, options, maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { try { const response = await fetch(url, options); if (response.ok) return response; // 如果是4xx错误(客户端错误),通常重试无意义 if (response.status >= 400 && response.status < 500) { throw new Error(`Client error: ${response.status}`); } // 如果是5xx错误或网络错误,则重试 throw new Error(`Request failed with status: ${response.status}`); } catch (error) { if (i === maxRetries - 1) throw error; // 最后一次重试失败,抛出错误 // 等待一段时间后重试 const delay = Math.pow(2, i) * 1000; // 指数退避 await new Promise(resolve => setTimeout(resolve, delay)); } } }5.2 如何让AI的回答更稳定、更可控?
通用大模型存在“幻觉”问题,可能编造不存在的产品功能。我们的“知识增强”和“规则约束”就是为了解决这个问题。
- 技巧一:使用系统指令强约束:在提示词开头,用严厉的语气明确AI的角色和限制。例如:“你必须且只能根据提供的【相关产品知识】来回答问题,如果知识库中没有相关信息,请明确告知用户‘该信息暂未收录’,切勿自行编造。”
- 技巧二:设置较低的
temperature参数:这个参数控制输出的随机性。对于售前这种需要准确性的场景,建议设置在0.1到0.7之间。值越低,回答越保守、可预测;值越高,回答越有创造性但也更可能出错。 - 技巧三:后处理校验:对于关键信息,如产品价格、型号,可以在AI生成回答后,用正则表达式或规则匹配进行二次校验,确保没有出现知识库外的内容。
5.3 如何持续优化知识库和规则?
AI助手不是一劳永逸的,需要持续运营。
- 收集bad cases:建立一个渠道,让客服或销售可以标记AI回答不准确或不满意的对话。
- 分析日志:定期查看EdgeOne Worker的日志和对话记录,寻找高频问题或知识盲区。
- 迭代更新:每周根据分析结果,更新一次向量知识库(补充新文档),并优化业务规则引擎。这是一个“数据飞轮”,用得越多,它就越聪明。
5.4 关于成本与性能的权衡
- 向量检索成本:如果知识库很大,在边缘进行向量相似度计算可能开销较大。一个折中方案是,在中心服务器预处理好知识库,并将“问题-最相关文档ID”的映射关系以缓存的形式下发到边缘KV。边缘Worker只需做一次快速的KV查询即可。
- 大模型API成本:这是主要成本。优化方向是:1) 优化提示词,减少不必要的tokens;2) 对于非常常见的问题(如“你们公司地址在哪?”),可以直接在边缘KV中设置问答对,完全绕过API调用,既能降低成本,又能实现毫秒级响应。
- 冷启动优化:EdgeOne Worker冷启动时间在百毫秒级。对于对延迟极度敏感的场景,可以考虑用少量请求保持Worker活跃,或者使用提供更优冷启动特性的边缘计算方案。
通过这个项目,我深刻体会到,将AI能力转化为实际业务价值,关键不在于用了多炫酷的模型,而在于如何将AI与你的业务数据、流程和规则深度结合。EdgeOne Makers提供了一个非常轻巧而强大的“粘合剂”,让我们能在离用户最近的地方,快速构建出这种“懂业务”的智能体。它不再是一个黑盒,而是一个你可以完全掌控、持续优化的业务伙伴。