拓冰建站拓冰建站
首页 / 资讯中心 / 正文

硅基客服系统从1000通到1.5万通的架构演进与实践

1. 从“能对话”到“能上岗”AI 客服差在哪里过去两年几乎每个做客服系统的团队都做过同一个实验把大模型接上语音识别和语音合成搭出一个能“和人聊天”的机器人。Demo 演示时效果惊艳能听懂客户意图能流畅回复甚至能开个玩笑。可一旦把这套东西放到真实业务里问题立刻暴露出来客服话术答非所问、用户说到一半被静音打断、通话高峰时服务直接超时、知识库内容检索不到、该转人工的时候机器人却一直纠缠不放。这也是很多企业面对“AI 客服”的第一反应模型能力确实强了但离真正“上岗”还差得远。标题里“从 1000 通到 1.5 万通”是一个非常值得拆解的样本。它背后不只是模型从弱变强更是一整套工程系统从“能跑”到“能扛”的过程。日通话量从 1000 通涨到 1.5 万通意味着并发从个位数涨到几十路甚至上百路意味着大模型推理不再是孤立调用而是要跟呼叫中心、知识库、业务系统、人工坐席协作意味着任何一个环节的延迟和失败都会被放大 15 倍。所以这篇文章想表达一个明确判断让 AI 客服真正上岗的关键不在模型选得多强而在于你能否把模型放进一套可靠、可扩展、可排查的工程系统里。文章会从概念、架构、代码、压测、排错和工程实践几个角度展开帮助你弄清楚一个硅基客服系统到底是怎么在千万级通话量下保持稳定的。2. 什么是「硅基客服」概念、边界与适用范围2.1 从碳基到硅基客服角色的一次替换“硅基客服”是相对“碳基客服”即人类坐席而言的说法。硅基客服的核心不是简单的语音机器人而是由大语言模型驱动的、具备感知、理解、决策和执行能力的客服智能体。完整的链路是这样的用户打电话进来语音经过 ASR自动语音识别转成文字大模型结合对话历史和企业知识库理解用户意图再通过调用业务系统完成查询、办理、登记等操作最后把回复交给 TTS语音合成播报给用户。整个过程里机器人的角色从“按键菜单”变成“能听、能想、能办”的数字员工。这个转变的关键在于决策方式的升级。传统 IVR 的本质是有限状态机用户按照固定路径按键选择系统根据预设流程跳转。而硅基客服的本质是 Agent它把用户意图映射到工具调用上路径是动态的同一个问题可以有多种解决方式遇到模糊表达也能主动追问澄清。2.2 它和传统客服系统有什么本质区别对比维度传统 IVR / 按键客服硅基客服交互方式按键菜单、固定话术自然语言对话、多轮交互意图识别基于节点跳转基于大模型语义理解知识维护人工录入菜单和规则企业知识库 RAG 检索生成任务执行受限于固定流程通过工具调用对接业务系统复杂问题处理无法处理直接转人工可拆解任务部分自动化处理部署与扩展单点容量规划分布式服务按并发扩容这里要强调一个容易误解的地方硅基客服不是要把所有人工坐席替换掉而是把高频、标准化、低价值的咨询和操作交给机器人让人工坐席集中处理高情绪、高风险、高复杂度的问题。这也是为什么“转人工”能力做得好的系统业务方接受度反而更高。2.3 适用场景与不合适场景从行业实践看硅基客服最适合的场景有三类高频标准化咨询比如账单查询、余额提醒、预约通知、订单状态。规则明确的操作类业务比如改密、挂失、退订、登记这些操作可以通过工具调用完成。大量外呼任务比如还款提醒、回访、满意度调查这类任务话术相对固定适合机器人批量拨打。不适合的场景也很明显涉及复杂情感安抚、需要临场应变、涉及高额资金操作或合规要求极高的情况机器人的定位只能是“辅助”而不能脱离人工闭环。3. 支撑万级通话量的系统架构设计3.1 从单路对话到话务平台很多团队在做智能客服 Demo 时实现的是一个简单的“单轮对话服务”请求进来调用大模型返回结果就结束。真实客服系统完全不是这样它首先要解决“话务从哪来、怎么分配、怎么保证不丢”的问题。一套完整的硅基客服系统至少包含四层接入层负责电话线路接入、SIP 信令管理、语音流收发。会话层管理每一通电话的会话状态包括 ASR 识别结果、对话历史、用户身份、当前意图、上下文变量。智能层大模型 Agent负责意图识别、对话策略、RAG 检索、工具调用。业务层对接 CRM、订单系统、账务系统等完成实际业务操作。标题中的“从 1000 通到 1.5 万通”对应的正是接入层和会话层从单机到集群的变化。单机处理 1000 通日活电话可能只需要几路并发但当目标变成 1.5 万通且集中在某几个高峰时段瞬间并发可能达到上百路这时候任何一个共享组件都可能成为瓶颈。3.2 会话状态管理比模型更重要的是状态整体架构里最容易被忽略的是会话状态管理。大模型本身不维护状态每一轮请求都是无状态的但客服对话天然是有状态的。用户上一轮说“我要还款”下一轮说“帮我查下卡号”模型必须知道“卡号”是查哪张卡的。实践中建议把会话状态从大模型服务中剥离出来放在独立的存储里一般用 Redis 或内存态数据库。会话状态包括会话 ID、用户身份。当前对话轮次和摘要。已经确认的槽位信息比如卡号、身份证号、业务类型。当前所处流程节点。最近一次工具调用结果。这样设计的价值在于大模型服务可以随时扩容缩容某一台实例挂掉了其他实例可以从会话状态中恢复对话而不是让用户重新说一遍。3.3 并发控制与容量规划对话量从 1000 通上升到 1.5 万通系统要过的第一关就是并发。假设每通电话平均通话时长 3 分钟大模型回复一次需要 1.5 秒每通电话大概发生 10 次模型调用。日话务 1.5 万通全天模型调用就是 15 万次如果集中在 8 小时业务时间内平均每秒约 5.2 次高峰时可能是平均值的 5 到 10 倍也就是每秒 30 到 50 次并发推理。这个量级对单卡本地部署的模型是有压力的。因此架构上必须做到模型服务多副本部署前面加负载均衡。对模型调用做超时控制和熔断避免单个慢请求拖垮整体。外呼任务使用消息队列削峰填谷控制同时处于通话中的线路数。高频知识检索结果缓存减少重复计算。3.4 外呼场景的特殊设计如果要支撑 1.5 万通外呼任务还有一个独特问题外呼和呼入不一样系统要主动发起呼叫而且不能一次性把所有号码全部并发拨出否则线路会拥堵接通率也会下降。常见做法是预测式外呼加并发控制。系统维护一个“当前活跃呼叫数”的计数每当一个呼叫结束就从任务队列里取出新的号码继续拨打。同时通过配置最大并发线路数、呼叫超时时间、振铃没接判定、空号失效处理等参数保证外呼平滑推进。4. 环境准备与前置条件为了把前面的思路落到代码层面接下来我会用一个最小可运行的项目来演示。这个项目的目标是跑通三个核心环节智能客服 Agent 的文本对话、外呼任务调度、工具调用与转人工兜底。4.1 技术栈选择本文的示例使用以下技术栈Python 3.10 以上FastAPI提供 HTTP 接口Redis用于会话状态缓存和任务队列Chroma 或 Milvus lite作为向量数据库存储企业知识库OpenAI 兼容的 LLM API或本地部署的 vLLM 服务一个语音网关比如 Asterisk / FreeSWITCH / 云通信平台用于对接电话线路需要说明的是这里不会绑定具体云厂商或具体语音设备。版本号请以实际项目为准本文重点演示通用思路。4.2 依赖安装mkdir silicon-agent cd silicon-agent python3 -m venv venv source venv/bin/activate pip install fastapi uvicorn redis chromadb openai pydantic python-dotenv4.3 环境变量配置# 文件路径.env LLM_API_KEYyour-llm-api-key LLM_BASE_URLhttps://your-llm-service.example.com/v1 LLM_MODELyour-model-name REDIS_URLredis://localhost:6379/0 COLLECTION_NAMEenterprise_kb注意不要把 API Key 硬编码到代码里也不要把生产环境变量提交到 Git 仓库。4.4 知识库初始化硅基客服要回答业务问题必须有自己的知识库。这里用 Chroma 作为向量数据库把一批业务文档切块后写入。# 文件路径init_kb.py import os from dotenv import load_dotenv from chromadb import PersistentClient from chromadb.utils import embedding_functions load_dotenv() client PersistentClient(path./chroma_data) collection client.get_or_create_collection( nameos.getenv(COLLECTION_NAME, enterprise_kb), embedding_functionembedding_functions.DefaultEmbeddingFunction(), ) documents [ 用户可以在每月账单日之后查询当期账单金额和还款截止日。, 如遇银行卡丢失用户可以申请临时挂失挂失有效期 5 天。, 提前还款支持线上办理操作路径为我的-贷款-提前还款。, 联系人工客服的方式是拨打 95XXX 后按 0 转入人工坐席。, ] collection.upsert( ids[fdoc_{i} for i in range(len(documents))], documentsdocuments, ) print(f初始化完成共写入 {len(documents)} 条知识。)这个步骤非常关键。很多团队在 Demo 阶段用模型内置知识回答问题看起来能对话但一到真实业务就完全不可用原因就是模型没有接入企业私有知识。知识库的写入和更新应该形成固定流程而不是每次手工改代码。5. 智能客服 Agent 的完整示例代码实现5.1 核心 Agent 服务RAG 动态工具调用下面这段代码实现了一个最小可用的客服 Agent。它接收用户的文本输入结合会话历史先从知识库检索相关内容再把检索结果和对话历史一起交给大模型生成回复。# 文件路径agent.py import os import json from dotenv import load_dotenv from chromadb import PersistentClient from chromadb.utils import embedding_functions from openai import OpenAI load_dotenv() client OpenAI( api_keyos.getenv(LLM_API_KEY), base_urlos.getenv(LLM_BASE_URL), ) vectordb PersistentClient(path./chroma_data) collection vectordb.get_collection( nameos.getenv(COLLECTION_NAME, enterprise_kb), embedding_functionembedding_functions.DefaultEmbeddingFunction(), ) SYSTEM_PROMPT 你是一个金融机构的智能客服助手。 请基于提供的知识库内容回答用户问题。 如果知识库中没有相关信息明确告诉用户你不知道并建议转人工坐席。 回答要简洁、口语化适合电话语音播报。 def retrieve(query: str, top_k: int 3) - list[str]: result collection.query(query_texts[query], n_resultstop_k) return result[documents][0] def run_agent(session_id: str, user_input: str, history: list[dict]) - str: knowledge retrieve(user_input) messages [{role: system, content: SYSTEM_PROMPT}] for item in history[-6:]: messages.append(item) messages.append({ role: user, content: f用户问题{user_input}\n\n知识库内容\n \n.join(knowledge), }) resp client.chat.completions.create( modelos.getenv(LLM_MODEL), messagesmessages, temperature0.3, max_tokens300, ) return resp.choices[0].message.content这段代码的关键点有三个知识检索在模型调用之前完成把检索结果注入到上下文中避免模型凭空编造。会话历史截取最近 6 条既保留上下文又控制 token 消耗。temperature 设置较低客服场景追求准确和稳定不需要太多创造性。5.2 FastAPI 接口会话状态与会话恢复有了核心 Agent 逻辑之后还需要一个 HTTP 接口把它暴露出来。接口同时负责从 Redis 读取和写入会话状态。# 文件路径main.py import uuid from fastapi import FastAPI, HTTPException from pydantic import BaseModel import redis import json import agent app FastAPI(titleSilicon Agent Service) redis_client redis.Redis.from_url(redis://localhost:6379/0) class ChatRequest(BaseModel): session_id: str | None None user_input: str class ChatResponse(BaseModel): session_id: str reply: str def load_history(session_id: str) - list[dict]: raw redis_client.get(fsession:{session_id}) if raw: return json.loads(raw) return [] def save_message(session_id: str, role: str, content: str, history: list[dict]): history.append({role: role, content: content}) # 只保留最近 20 条避免状态无限膨胀 trimmed history[-20:] redis_client.setex(fsession:{session_id}, 1800, json.dumps(trimmed, ensure_asciiFalse)) app.post(/chat, response_modelChatResponse) def chat(req: ChatRequest): session_id req.session_id or uuid.uuid4().hex history load_history(session_id) save_message(session_id, user, req.user_input, history) reply agent.run_agent(session_id, req.user_input, history) save_message(session_id, assistant, reply, history) return ChatResponse(session_idsession_id, replyreply)这里真正容易踩坑的地方是会话历史一致性。如果不从 Redis 重新加载直接把内存里的 history 传下去一旦服务多副本部署用户的上下文就会在不同实例之间丢失。把状态外置到 Redis是支撑多实例扩展的前提。5.3 外呼任务调度器从 1000 通到 1.5 万通的关键外呼场景和呼入场景不同系统需要主动从任务池里拉取号码并控制同时呼叫的数量。下面用 Redis List 实现一个简版任务调度器。# 文件路径dispatcher.py import time import uuid import redis r redis.Redis.from_url(redis://localhost:6379/0) TASK_QUEUE outbound:tasks ACTIVE_KEY outbound:active_counter MAX_CONCURRENT 10 def push_tasks(phone_numbers: list[str]): for phone in phone_numbers: task_id uuid.uuid4().hex r.lpush(TASK_QUEUE, f{task_id}:{phone}) print(f已推送 {len(phone_numbers)} 个外呼任务) def start_dispatcher(): while True: active int(r.get(ACTIVE_KEY) or 0) if active MAX_CONCURRENT: time.sleep(1) continue raw r.rpop(TASK_QUEUE) if not raw: time.sleep(2) continue r.incr(ACTIVE_KEY) task_id, phone raw.split(:) print(f发起呼叫 task{task_id} phone{phone}) try: # 这里应该调用语音网关发起呼叫 # 呼叫结束后必须调用 finish_call 释放并发名额 time.sleep(3) finally: finish_call(task_id) def finish_call(task_id: str): r.decr(ACTIVE_KEY) print(f呼叫结束 task{task_id}) if __name__ __main__: push_tasks([f1380000{i:04d} for i in range(50)]) start_dispatcher()这个调度器的核心设计是通过 Redis 计数控制活跃呼叫数任务从队列里取出后先增加计数呼叫结束再释放。这样无论并发是多少系统都能稳定在 MAX_CONCURRENT 以内避免线路被瞬间打爆。真实项目里还需要把 task_id 与呼叫结果关联起来记录接通、未接通、振铃超时、空号等状态并把结果回写到业务数据库。5.4 转人工与工具调用兜底最后是转人工逻辑。AI 客服不可能处理所有问题系统必须在模型判断需要人工介入时自动转接到人工坐席队列。# 文件路径handoff.py import redis r redis.Redis.from_url(redis://localhost:6379/0) HANDOFF_KEYWORDS [人工, 投诉, 转人工, 负责人] HANDOFF_MAX_ROUNDS 3 def need_handoff(text: str) - bool: return any(kw in text for kw in HANDOFF_KEYWORDS) def should_handoff(session_id: str, reply: str, history_len: int) - bool: if need_handoff(reply): return True if history_len HANDOFF_MAX_ROUNDS * 2: # 同一问题连续多轮仍未解决转人工 rounds r.incr(fhandoff:count:{session_id}) r.expire(fhandoff:count:{session_id}, 300) if rounds HANDOFF_MAX_ROUNDS: return True return False这段代码体现的是一个工程原则转人工不是模型的一个可选项而是系统的安全网。无论模型如何升级都必须保留“我不行就转人工”的能力否则用户问题永远得不到解决体验会比传统客服更差。6. 运行结果与效果验证6.1 启动服务python init_kb.py uvicorn main:app --host 0.0.0.0 --port 8000注意在启动 FastAPI 服务之前先执行 init_kb.py 初始化向量库。如果没有执行这一步运行后检索接口会报错。6.2 接口测试curl -X POST http://127.0.0.1:8000/chat \ -H Content-Type: application/json \ -d {user_input: 我的卡丢了怎么办}预期返回类似{ session_id: a1b2c3d4e5f6, reply: 请您不要担心您可以办理临时挂失挂失有效期是5天之后如果需要补办新卡可以联系网点办理。 }判断成功的关键有两个第一回复内容与知识库内容一致第二再次发送同一 session_id 的请求时模型能够理解上下文。如果连续问“那怎么联系人工”模型应该能根据历史判断用户要的是人工电话而不是把上一轮挂失知识又重复一遍。6.3 简单的并发验证可以用命令行工具快速测试并发请求是否出错不一定需要专业压测平台for i in $(seq 1 20); do curl -s -o /dev/null -w %{http_code}\n \ -X POST http://127.0.0.1:8000/chat \ -H Content-Type: application/json \ -d {user_input: 账单怎么查询} done wait如果全部返回 200说明基本链路是通的。但要注意这只是功能层面的验证不是容量层面的验证。真实支撑 1.5 万通日话务还需要更完整的压测。6.4 语音客服场景的验证方式如果是语音客服验证链路会更复杂。完整链路是用户拨打电话。语音网关接入发送实时音频流。ASR 将音频转为文字。Agent 服务返回回复文字。TTS 将回复合成语音。网关把语音播放给用户。建议先分模块测试先用录音文件测试 ASR 识别效果再离线测试 TTS 播报音色和语速最后才联调网关。如果联调失败优先检查 RTP 音频流是否打通、ASR 返回的文字是不是被静音检测截断。6.5 关键运营指标上线后真正需要盯着看的不是单次回答质量而是以下五类指标指标说明健康参考转人工率每百通电话中需要人工介入的比例越高说明自助解决能力越弱成功办理率机器人独立完成业务操作的比例比单次回答准确性更重要ASR 识别准确率用户关键信息识别的准确程度涉及金额、卡号时需要重点审计平均通话时长用户与机器人交互的时长过短可能没解决问题过长可能绕圈P95 响应延迟95% 请求的模型响应时间语音场景通常要求在 2 秒内这里特别想强调“成功办理率”这个指标。很多团队上线 AI 客服时只关注模型答得对不对却忽略了一个本质问题用户是不是真的把事情办成了。答得好但办不了用户一样不会满意。7. 常见问题与排查思路问题现象可能原因排查方式解决方案模型回答包含知识库以外的内容RAG 检索结果未注入或注入内容不完整打印请求上下文查看检索命中的文档检查知识库切块粒度增大 top_k并强化 system prompt 约束用户说“转人工”但系统不响应转人工判断逻辑未覆盖关键词或模型拦截了意图查看对话日志确认 ASR 文字是否识别准确在语音场景中将“转人工”等关键词同时挂到 ASR 热词表并发升高后接口超时大模型推理成为瓶颈没有做超时和熔断压测时观察模型推理耗时和队列堆积模型服务多副本部署增加超时控制引入降级话术会话上下文偶尔丢失Redis 会话过期时间过短或连接异常检查 Redis 连接和 key 的 TTL延长会话 TTL在 Redis 故障时兜底返回“请您稍后再说一遍”外呼任务重复拨打任务消费成功后计数未及时释放或没有记录任务状态查看任务队列是否有重复消息引入去重表用 task_id 做唯一约束消费前先检查状态语音识别把数字听错ASR 对专业名词、数字、生僻字识别不稳回放录音对比 ASR 文本在 ASR 中配置热词表关键词强制命中关键数字二次确认回答太啰嗦不像客服语气模型 temperature 过高提示词缺少口语化约束检查生成结果的长度和风格降低 temperature在提示词中引导短句播报加字数上限知识库更新后模型仍答旧内容向量库写入不生效或缓存未失效查看向量库中的文档时间戳和缓存逻辑更新后重建或增量写入向量库清理检索缓存排查思路上有一条经验值得分享所有智能客服问题第一件事永远是看“模型拿到的是什么输入”而不是直接调模型参数。因为大量错误发生在输入侧比如 ASR 识别错了、知识库检索不中、历史记录拼接错误。把输入日志打出来问题往往立刻清楚。8. 从 1000 通到 1.5 万通的最佳实践与工程建议8.1 先跑通 1000 通再追求 1.5 万通很多团队一上来就规划 1.5 万通的目标结果系统上线第一周就崩溃。更合理的路径是分阶段灰度第 1 阶段只覆盖查询类业务比如账单查询、网点查询日话务目标 1000 通。第 2 阶段增加操作类业务比如挂失、预约、退订需要打通业务系统权限。第 3 阶段接入外呼任务比如还款提醒、回访并建立完整的任务状态机。第 4 阶段在数据积累的基础上优化话术和流程逐步把转人工率降下来。这种递进方式的好处是每一阶段的故障范围是可控的。如果第一步查询类都没做好就不要急着开操作类权限。8.2 知识库管理要有流程不能靠开发人员手工改硅基客服的准确度上限很大程度上由知识库质量决定。知识库管理建议做到三点文档切块策略要统一每块控制在 200 到 500 字之间太长了检索噪声大太短了语义不完整。知识文档必须带版本和生效时间业务规则变化时旧知识要能追溯。线上知识库和测试知识库分离新知识先在小流量灰度观察回复质量后再全量放开。8.3 关键操作必须二次确认AI 客服执行挂失、退订、改密等操作时务必要在关键动作前加二次确认。比如用户说“我要挂失”机器人应该先播报“请问您确认要挂失尾号为 1234 的银行卡吗”等用户确认后再执行。这既能防止 ASR 误听也能防止模型错误理解用户意图。涉及高风险操作时宁可多问一句也不要擅自执行。8.4 日志、追踪与人工抽检闭环智能客服系统比传统客服系统更需要完善的日志体系。每一通电话都应该记录完整的 JSONL 日志包含会话 ID、通话 ID、时间戳。ASR 识别文本、模型回复文本。检索到的知识文档 ID。是否调用了工具、调用结果。是否转人工、转人工原因。这不仅是排查问题的基础更重要的是可以做人工抽检闭环。运营团队每天抽检一定比例的通话录音发现回答错误立刻标记并反馈到知识库或提示词中。没有这个闭环系统质量只会在上线后缓慢下降。8.5 成本控制不是所有请求都要走最大模型大模型推理成本是智能客服系统的核心成本之一。实践中通常把请求分级高频固定咨询比如“人工电话多少”可以直接配置静态话术不走模型。标准问答走 RAG 中等规模模型。复杂多轮任务走大模型 工具调用。也就是说模型服务可以配置多种规格根据意图置信度和任务复杂度路由到不同模型而不是盲目追求“所有请求都用最强模型”。外呼场景尤其要注意这点话术相对固定的外呼完全可以用小模型加静态话术模板完成只有用户主动询问超出模板的问题才升级到大模型。8.6 合规与安全基线硅基客服涉及录音、个人信息、金融业务操作等多个敏感领域工程上必须提前考虑合规边界用户在接入机器人后应立即收到“本次通话可能被录音”的告知这是行业基本要求。涉及卡号、身份证号、密码等敏感信息的采集系统日志要脱敏不允许明文落库。所有业务操作类工具接口必须做权限隔离。客服 Agent 的权限应控制在最小范围不能因为模型获得了某个业务接口的调用权限就能执行超出客服角色的操作。系统应支持“一键暂停”能力当话术或知识库出现严重问题时能在运营后台立即把流量切回人工。9. 总结与后续学习方向回到标题本身“从 1000 通到 1.5 万通”不是一句简单的业绩汇报它代表了一整套智能客服系统的工程成熟度。在这条路上模型能力只是起点真正的护城河在于知识库能否高效维护会话状态能否在多实例间保持一致并发扩展是否平滑故障是否能被快速定位以及人工介入是否足够顺畅。如果你正在规划自己的智能客服系统建议按这样的顺序动手先搭一个 FastAPI 文本 Agent跑通 RAG 检索加模型回复的最小链路。增加 Redis 会话状态让多轮对话在接口层可用。接一个外呼任务队列验证并发控制逻辑。最后再接语音网关处理 ASR 和 TTS。这一步之前先用文本方式把业务逻辑验证完整否则排错时会同时面对语音问题、网络问题和模型问题非常痛苦。从更长远看硅基客服的下一步演进方向包括更强的多模态能力比如识别用户情绪和意图更复杂的工作流编排比如跨多个业务系统的联合办理以及更完善的自学习闭环让系统从每一次人工介入中归纳失败原因并持续优化。但无论技术怎么演进有一条原则始终不会变AI 客服的目标不是让用户觉得“机器很聪明”而是让用户感觉“问题真的被解决了”。理解了这一点你就能在技术选型和系统设计上做出更务实的判断。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门