智能客户服务支持智能体

超越传统客服机器人。智能体可以深度查询知识库、调用订单系统API、甚至根据客户情绪灵活处理退货、退款、升级投诉等复杂流程。

案例:

客户说:“我上周买的鞋子尺码不对,想换货但是找不到订单页面了。”

智能体行动: ① 通过用户身份验证;② 调用订单查询API找到该订单;③ 检查换货政策;④ 生成换货链接并指导用户下一步操作;⑤ 若流程中断,后续可主动发送邮件提醒。

1. 核心功能

  • 多轮对话与上下文理解:能理解并记忆对话上下文。
  • 工具调用(Tool Use):能调用外部API获取真实数据(如订单、用户信息)。
  • 知识库检索(RAG):能从企业知识库(如手册、FAQ)中检索精准信息。
  • 安全性与权限控制:验证用户身份,并基于身份控制数据访问范围
  • 人工接管(Human-in-the-loop):在无法处理或用户要求时,无缝转接人工客服

2. 技术栈选择(企业级)

  • LLM(大脑): OpenAI GPT-4 Turbo (性价比和性能平衡)

  • 开发框架: LangChain / LangGraph (用于构建复杂、有状态的智能体工作流)

  • 工具调用: LangChain Tools & Custom Functions

  • 知识库: Chroma (向量数据库,轻量且高效) + OpenAI Embeddings

  • 后端API: FastAPI (高性能、异步支持好,适合生产环境)

  • 身份认证: JWT Tokens

  • 数据持久化: SQL Database (PostgreSQL) for logging

  • 部署: Docker & Kubernetes (容器化便于扩展和管理)

架构设计
在这里插入图片描述
在这里插入图片描述

一、环境依赖

# 创建项目目录并初始化虚拟环境
mkdir customer-support-agent
cd customer-support-agent
python -m venv venv
source venv/bin/activate  # Linux/Mac
# venv\Scripts\activate  # Windows# 安装核心依赖
pip install openai langchain langgraph chromadb langchain-openai fastapi uvicorn python-jose[cryptography] passlib sqlalchemy psycopg2-binary pydantic

二、数据模型

models.py

  • UserIdentity - 用户身份标识,跟踪用户身份和会话信息
  • AgentState - 智能体状态管理,管理对话智能体的完整状态,这是LangGraph框架中的核心概念
  • ConversationType - 对话类型枚举,定义对话的意图分类,限制可能的对话类型,便于处理后续的统计分析和逻辑分支
  • ConversationLog - 对话日志存储:用于持久化存储对话记录到数据库
from pydantic import BaseModel, Field #Pydantic: 提供数据验证和设置管理的现代Python数据验证库
from typing import Optional, List, Dict, Any #typing: 用于类型注解,提高代码可读性和类型安全
from enum import Enum #enum: 用于定义枚举类型,限制可能的取值class UserIdentity(BaseModel):"""用户身份标识"""user_id: Optional[str] = None #user_id: 可选字段,用于已登录用户session_id: str #session_id: 必需字段,唯一标识一个对话会话is_authenticated: bool = False #is_authenticated: 标识用户是否通过身份验证class AgentState(BaseModel):"""LangGraph智能体的状态"""#一个列表,列表中的每个元素都是字典,使用Field类来定义字段的详细配置,...表示该字段是必需的,不能为空messages: List[Dict[str, Any]] = Field(..., description="对话消息历史")user_identity: UserIdentity = Field(..., description="用户身份信息")current_step: str = Field("greeting", description="当前对话步骤")#"greeting": 默认值,表示如果没有提供值,就使用这个默认值#default_factory=dict: 使用工厂函数,每次创建新实例时都会调用dict()创建一个新的空字典extracted_info: Dict[str, Any] = Field(default_factory=dict, description="从对话中提取的结构化信息")class ConversationType(Enum):QUERY_ORDER = "query_order"  # 订单查询RETURN_EXCHANGE = "return_exchange"  # 退换货GENERAL_QUESTION = "general_question" # 一般问题class ConversationLog(BaseModel):"""存入数据库的对话日志"""session_id: str  # 会话标识user_id: Optional[str] # 可选用户IDmessage: str # 用户消息内容agent_response: str # 智能体回复内容intent: Optional[str] # 识别出的意图timestamp: str # 时间戳success: bool  # 处理是否成功

画外题:

#创建实例
state = AgentState(messages=[{"role": "user", "content": "你好"}],user_identity=UserIdentity(...),  # 需要提供UserIdentity实例# current_step 使用默认值 "greeting"# extracted_info 使用默认空字典
)# 访问属性
print(state.current_step)  # 输出: "greeting"
print(state.extracted_info)  # 输出: {}

在这里插入图片描述

三、核心工具

tools.py

  • 订单查询工具→ AI调用query_order_tool
  • 退换货政策查询工具→ AI调用query_return_policy_tool
  • 复杂问题无法解决 → AI调用create_support_ticket_tool
import requests
from langchain.tools import tool #LangChain的工具装饰器,将函数转换为AI可调用的工具
from typing import Type
from pydantic import BaseModel, Field
import os# 1. 订单查询工具
class OrderQueryInput(BaseModel):order_id: str = Field(..., description="The order ID to query")#装饰器是一种高级功能,它允许在不修改原函数代码的情况下,为函数添加额外的功能。
#将一个普通的 Python 函数"包装"成一个可以被 AI 大语言模型(LLM)识别和调用的工具(Tool)
#(args_schema=OrderQueryInput):这是传递给 @tool 装饰器的参数,定义了工具输入参数的名称、类型、描述等,帮助 AI 模型理解如何正确地调用这个函数。
@tool(args_schema=OrderQueryInput)
def query_order_tool(order_id: str) -> str: # -> str::返回类型提示,表明这个函数执行完毕后会返回一个字符串(String)类型的结果"""查询用户订单信息。需要先验证用户身份。"""# 模拟调用内部订单系统API# 真实环境中,这里会是 requests.get(f"{ORDER_API_URL}/{order_id}", headers=...)print(f"🔍 [Tool Call] Querying order: {order_id}")# 模拟响应 创建字典 构建了一个订单对象的详细信息,包括产品、尺寸、日期、状态mock_order_data = {"order_id": order_id,"product": "Running Shoes (Model X)","size": "42","order_date": "2024-09-15","status": "Delivered","customer_id": "cust_12345"}return f"Order Details: {str(mock_order_data)}"# 2. 退换货政策查询工具 (RAG)
@tool # @tool 装饰器告诉AI框架:“这个函数是我(AI)可以用的一个工具”。
def query_return_policy_tool(product_category: str) -> str:"""根据产品类别查询退换货政策。如果用户未指定类别,则查询通用政策。"""# 在真实环境中,这里会从向量数据库检索print(f"🔍 [Tool Call] Querying return policy for: {product_category}")policies = {"general": "You can return most items within 30 days of delivery. Items must be unworn and in original packaging.","shoes": "Shoes can be exchanged for a different size within 45 days. Must have original box and no signs of wear.","electronics": "Electronics can be returned within 14 days. Must be factory reset and all accessories included."}policy = policies.get(product_category.lower(), policies["general"])return f"Our return policy for {product_category}: {policy}"# 3. 创建客服工单工具
class CreateTicketInput(BaseModel):issue_summary: str = Field(..., description="A summary of the customer's issue")priority: str = Field("medium", description="Priority of the ticket: low, medium, high")@tool(args_schema=CreateTicketInput)
def create_support_ticket_tool(issue_summary: str, priority: str = "medium") -> str:"""在第三方系统(如Zendesk、Jira)中创建支持工单。用于当智能体无法解决问题时。"""print(f"🔍 [Tool Call] Creating Support Ticket. Priority: {priority}. Issue: {issue_summary}")# 模拟创建工单的API调用ticket_id = "TICKET-0987"return f"Successfully created a support ticket for you. Your ticket ID is {ticket_id}. A human agent will contact you shortly."

生产环境改进建议

def query_order_tool(order_id:str) -> str:try:response = requests.get(r"{os.getenv('ORDER_API_URL')}/{order_id}",headers = {"Authorization": f"Bearer {os.getenv('API_TOKEN')}"},timeout = 10)return f"Order Details:{response.json()}"except requests.RequestException as e:return f"Sorry, I couldn't retrieve your order details. Error: {str(e)}"

四、构建智能体工作流

        +-------------+|   agent     |  # 决策节点+-------------+|v (条件路由)+---------+---------+|         |         |v         v         v
+-------+   END   +-------------+
| tools |         | human_agent |
+-------+         +-------------+|                   |+--------+          |v          v+-------------+|    agent    |  # 循环回到agent+-------------+

agent.py

  • 智能体决策节点,接收当前对话状态,调用LLM会自动决定是否需要调用工具,返回AI消息到状态中
  • 路由函数 - 核心决策逻辑
from langgraph.graph import StateGraph, END
from langgraph.prebuilt import ToolNode
from langchain_core.messages import HumanMessage, AIMessage, ToolMessage
from langchain_openai import ChatOpenAI
from models import AgentState
from tools import query_order_tool, query_return_policy_tool, create_support_ticket_tool
from typing import Literal, Dict, Any# 初始化LLM
llm = ChatOpenAI(model="gpt-4-turbo", temperature=0) #模型选择: gpt-4-turbo 提供强大的推理能力 温度设置: temperature=0 确保确定性输出,适合客服场景
# 绑定工具 工具绑定: bind_tools() 让LLM知道可用的工具及其功能
llm_with_tools = llm.bind_tools([query_order_tool, query_return_policy_tool, create_support_ticket_tool])# 定义工具节点 ToolNode 专门处理工具调用的执行
tool_node = ToolNode(tools=[query_order_tool, query_return_policy_tool, create_support_ticket_tool])def agent_step(state: AgentState):#接收当前对话状态"""智能体决策节点"""print(f"🤖 [Agent Step] Current Step: {state['current_step']}")messages = state["messages"]response = llm_with_tools.invoke(messages) #调用LLM生成响应,LLM会自动决定是否需要调用工具return {"messages": [response]}# 返回AI消息到状态中def route_to_tools(state: AgentState) -> Literal["tools", "end", "human_agent"]:"""路由函数,决定下一步是调用工具、结束还是转人工"""ai_msg = state["messages"][-1]#检查工具调用: 如果AI消息包含tool_calls,转到"tools"节点if not hasattr(ai_msg, 'tool_calls') or len(ai_msg.tool_calls) == 0:# 如果没有工具调用,检查是否需要结束或转人工if "thank you" in state["messages"][-2].content.lower():#结束条件: 用户说"thank you"时结束对话return "end"if "human" in state["messages"][-2].content.lower():return "human_agent"return "end"return "tools"def call_human_agent(state: AgentState):"""调用创建工单工具并结束对话"""issue_summary = f"Customer requested human agent. Conversation history: {state['messages']}"tool_input = {"issue_summary": issue_summary, "priority": "medium"}result = create_support_ticket_tool.invoke(tool_input)#返回友好的转接消息return {"messages": [AIMessage(content=f"I've escalated your issue to our human team. {result}")]}# 构建图
workflow = StateGraph(AgentState)
workflow.add_node("agent", agent_step)
workflow.add_node("tools", tool_node)
workflow.add_node("human_agent", call_human_agent)workflow.set_entry_point("agent")
workflow.add_conditional_edges("agent",route_to_tools,{"tools": "tools","end": END,"human_agent": "human_agent"}
)
workflow.add_edge("tools", "agent")
workflow.add_edge("human_agent", END)# 编译图
app = workflow.compile()

实际对话示例:

用户: "我想查询订单12345"
AI: (决定调用query_order_tool) → 工具节点 → 返回结果
用户: "谢谢你的帮助"
AI: (检测到感谢) → 结束对话用户: "我要找人工客服"  
AI: (检测到"human") → 转人工节点 → 创建工单 → 结束

五、创建FastAPI后端与安全中间件

from fastapi import FastAPI, HTTPException, Depends, Header
from fastapi.middleware.cors import CORSMiddleware
from models import UserIdentity, AgentState, ConversationLog
from agent import app as agent_app
from typing import Annotated, Optional
import uuid
import datetime
import json# 初始化FastAPI应用
app = FastAPI(title="Customer Support Agent API")# 中间件:CORS(允许前端访问)
app.add_middleware(CORSMiddleware,allow_origins=["*"],  # 生产环境应指定具体域名allow_credentials=True,allow_methods=["*"],allow_headers=["*"],
)# 模拟用户身份验证(生产环境应使用JWT)
async def verify_token(authorization: Annotated[Optional[str], Header()] = None) -> UserIdentity:session_id = str(uuid.uuid4())if authorization and authorization.startswith("Bearer "):token = authorization[7:]# 这里应验证JWT token并提取user_id# 为简单起见,我们模拟一个已验证用户user_identity = UserIdentity(user_id="cust_12345", session_id=session_id, is_authenticated=True)else:# 未认证用户只有session_iduser_identity = UserIdentity(session_id=session_id, is_authenticated=False)return user_identity# API路由
@app.post("/chat")
async def chat_endpoint(message: str,user_identity: UserIdentity = Depends(verify_token)
):"""主聊天端点"""try:# 1. 初始化或获取对话状态(这里应使用Redis等持久化状态,为简单起见我们每次新建)initial_state = AgentState(messages=[HumanMessage(content=message)],user_identity=user_identity,current_step="greeting")# 2. 执行智能体图final_state = agent_app.invoke(initial_state)# 3. 获取最终响应agent_response = final_state["messages"][-1].content# 4. 记录日志(应异步写入数据库)log_entry = ConversationLog(session_id=user_identity.session_id,user_id=user_identity.user_id,message=message,agent_response=agent_response,intent=final_state.get("current_step"),timestamp=datetime.datetime.utcnow().isoformat(),success=True)print(f"📝 Logging conversation: {log_entry.json()}")# 5. 返回响应return {"response": agent_response,"session_id": user_identity.session_id,"user_id": user_identity.user_id}except Exception as e:print(f"❌ Error in chat endpoint: {e}")raise HTTPException(status_code=500, detail=str(e))@app.get("/health")
async def health_check():return {"status": "OK"}if __name__ == "__main__":import uvicornuvicorn.run(app, host="0.0.0.0", port=8000)

六、测试智能体

import asyncio
from models import AgentState, UserIdentity
from agent import app# 模拟一个测试用户
test_user = UserIdentity(user_id="cust_12345", session_id="test_session_001", is_authenticated=True)def test_conversation():# 模拟用户消息:询问订单状态test_messages = ["Hi, I want to check the status of my order ORD-67890"]state = AgentState(messages=[], user_identity=test_user, current_step="start")for msg in test_messages:state["messages"].append(HumanMessage(content=msg))print(f"User: {msg}")# 调用智能体state = app.invoke(state)agent_msg = state["messages"][-1]print(f"Agent: {agent_msg.content}")if hasattr(agent_msg, 'tool_calls') and agent_msg.tool_calls:print(f"Agent called tools: {agent_msg.tool_calls}")print("---")if __name__ == "__main__":test_conversation()

七、使用Docker容器化部署

FROM python:3.11-slimWORKDIR /appCOPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txtCOPY . .EXPOSE 8000CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]

docker-compose.yml

version: '3.8'
services:support-agent:build: .ports:- "8000:8000"environment:- OPENAI_API_KEY=${OPENAI_API_KEY}# 生产环境应添加以下依赖# depends_on:#   - postgres#   - redis# postgres:#   image: postgres:13#   environment:#     POSTGRES_DB: agent_db#     POSTGRES_USER: agent#     POSTGRES_PASSWORD: password# redis:#   image: redis:7-alpine

如何运行

设置环境变量:

export OPENAI_API_KEY='your-openai-api-key'

启动服务

uvicorn main:app --reload

测试API

curl -X 'POST' \'http://localhost:8000/chat' \-H 'Authorization: Bearer fake_jwt_token_for_testing' \-H 'Content-Type: application/json' \-d '{"message": "I need to return my shoes, what is your policy?"}'

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/96320.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/96320.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【MySQL|第四篇】DQL语句(二)——数据查询语言

4、排序分页:(1)排序:查询数据的时候进行排序,就是根据某个字段的值,按照升序或者降序的情况将记录显示出来语法: select col_name,... from tb_name order by col_name [asc|desc]注意事项&…

百度文心X1.1发布!实测深度思考能力!

文章目录背景模型实测效果事实性指令跟随智能体模型技术解读基准测试文心飞桨携手共进总结背景 9月9日,WAVE SUMMIT深度学习开发者大会上,百度首席技术官、深度学习技术及应用国家工程研究中心主任王海峰正式发布了文心大模型X1.1深度思考模型&#xff…

基于Java+SpringBoot的B站评论系统架构设计与实践深度解析

基于JavaSpringBoot的B站评论系统架构设计与实践深度解析 前言 作为国内领先的视频分享平台,B站的评论系统承载着海量用户的实时互动需求。本文将从架构师角度,基于JavaSpringBoot技术栈,深度解析评论系统的技术实现方案、核心难点及扩展性设…

赋能数字孪生:Paraverse平行云实时云渲染平台LarkXR,提供强大的API与SDK用于二次开发和深度集成

在数字孪生渗透千行百业的今天,构建一个高保真、实时交互、可大规模访问的虚拟孪生世界已成为核心需求。然而,对于开发者而言,从零开始构建实时云渲染、海量模型加载、数据双向互通、多端适配、网页嵌套,平台定制化等底层技术难关…

基于Nginx实现反向代理、负载均衡与动静分离完整部署指南

基于Nginx实现反向代理、负载均衡与动静分离完整部署指南 文章目录基于Nginx实现反向代理、负载均衡与动静分离完整部署指南一、架构规划与环境准备1.1 架构设计思路1.2 服务器规划1.3 环境依赖二、部署Nginx负载均衡器2.1 安装Nginx依赖包2.2 创建Nginx专用用户2.3 编译安装Ng…

HTML5国庆网站源码

一. 网站概述 本国庆主题网站以弘扬爱国主义精神为核心,通过丰富多元的交互功能与视觉设计,打造沉浸式国庆体验空间。网站采用单页面架构,通过平滑滚动实现各模块的无缝衔接,涵盖首页、知识科普、互动体验等十大功能板块&#xf…

MySQL收集processlist记录的shell工具mysql_collect_processlist

文章目录安装指南日志文件内容日志分析参考1.简单检索2.统计不同状态的语句的数量3.按照时间统计注意事项仓库这是一个纯脚本工具,用于从MySQL的information_schema.processlist视图中定期收集数据并保存到本地日志文件。支持MYSQL5.7-9.4版本。 template copy fro…

工业RFID现场网关模块:实现多协议互通,128台读写设备互连!

随着工业4.0进程加速,企业对生产系统集成度的需求不断增长。在工厂中常需整合不同品牌PLC、驱动器、机械臂、读写器等设备系统,这其中就会涉及到如Profinet、EtherNet/IP、EtherCAT、Modbus TCP、CC-LINK IE等不同通讯协议连接。虽可将部分设备直接与PLC…

黑马点评高级篇第7节课 输入INFO replication 显示0个从节点,但是在7002节点又显示它已经是7001节点的从节点了

问题描述在黑马点评高级篇第七节课的这个位置​​​​​​,当我输入INFO replication 的时候下面本应该显示为connected_slaves: 2,但是我的显示的是0。然后当我切换到7002端口的节点时,又显示7002就是7001的从节点解决我看弹幕上说在7002和7…

pcb线路板打样厂家有哪些?

在电子制造产业升级浪潮中,PCB打样环节的效率与品质直接影响产品迭代速度。本文聚焦国内五家具备核心技术竞争力的PCB打样厂商,深度解析其差异化优势,为硬件开发者提供精准选型参考。猎板PCB作为国家高新技术企业,猎板PCB在高频高…

【python实用小脚本-211】[硬件互联] 桌面壁纸×Python梦幻联动|用10行代码实现“开机盲盒”自动化改造实录(建议收藏)

1. 场景故事 “作为HR,我曾每天手动换壁纸提神,直到某天忙到忘记,结果被同事截图当‘黑历史’…” → 转折点:用Python调用Windows API写了个“随机壁纸机”,开机自启,每次登录都是新风景,现在截…

集成学习 —— 梯度提升树GBDT、XGBoost

目录 一、梯度提升树 1、残差提升树 Boosting Decision Tree 2、梯度提升树 Gradient Boosting Decision Tree 二、构建案例 1、 初始化弱学习器(CART树): 2、 构建第1个弱学习器 3、 构建第2个弱学习器 4、 构建第3个弱学习器 5、 构建最终弱学习器 6、 构…

【船类】监控录像下船舶类别检测识别数据集:近7k图像,6类,yolo标注

监控录像下船舶类别检测识别数据集概述 数据集包含 6900监控录像下船舶类别图像,6个标注类别: 散货船、集装箱船、渔船、杂货船、矿砂船、客船 标注格式:yolo txt(格式可转,可直接训练) 标注工具&#…

用户故事设计范式(As a... I want to... So that...)

我们来详细解析一下用户故事(User Story),包括其结构、为什么重要、如何编写好的用户故事以及一个完整的示例。1. 用户故事的基本结构:三段式模板最经典和通用的用户故事模板就是您提到的三段式:As a [角色]:目的&…

【OpenGL】LearnOpenGL学习笔记20 - 实例化 Instancing

上接:https://blog.csdn.net/weixin_44506615/article/details/151156446?spm1001.2014.3001.5501 完整代码:https://gitee.com/Duo1J/learn-open-gl | https://github.com/Duo1J/LearnOpenGL 实例化 Instancing 以往当我们在场景中要大量绘制相同模型…

MySQL主从不一致?DBA急救手册:14种高频坑点+3分钟定位+无损修复!

MySQL「主从不一致」最常见的成因、快速定位思路以及可落地的修复手段 一、为什么会不一致?14 类高频场景类别典型表现/触发条件快速自检命令/日志1. 从库被写入业务或 DBA 直连从库 UPDATE/INSERTSHOW VARIABLES LIKE read_only 应为 ON2. 复制过滤规则主从 binlog…

AI 网站源码:探秘 SUNO,革新音乐创作的 AI 先锋

在当今数字化浪潮中,人工智能(AI)正深刻地重塑各个领域,音乐创作也不例外。SUNO 作为一款引领潮流的音乐生成工具,宛如一颗璀璨新星,在音乐创作的天空中熠熠生辉,为音乐爱好者和创作者们带来了前…

Linux:malloc背后的实现细节

目录前言一、先搞懂基础:程序的内存布局(关键前提!)二、malloc的核心实现步骤(4层架构拆解)第1层:用户调用 → 标准库处理(glibc的malloc.c)第2层:堆内存池管…

什么是X11转发?

X11 转发(X11 forwarding,ssh -X)是一种 SSH 协议功能,它允许用户在远程服务器上运行图形化应用程序,并通过本地的显示设备和输入输出设备与这些程序进行交互。它被开发者广泛使用,用于在大规模、异构的服务…

Android Kotlin 动态注册 Broadcast 的完整封装方案

在 Kotlin 中封装动态注册的 Broadcast 可以让你更优雅地管理广播的注册和注销,避免内存泄漏。下面是一个完整的封装方案: 基础封装类 import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import …