深入浅出 LangChain —— 第十一章:实战一 智能客服系统

LangChain实战项目:智能客服系统 智能客服系统摘要 本项目基于LangChain构建智能客服系统,具备多轮对话、知识库问答、情感分析等功能。系统采用模块化设计,包含核心组件如配置管理、数据模型、LLM服务和知识库服务。主要实现内容包括: 配置管理模块:集中处理API密钥、数据库连接等配置项 数据模型:定义客户信息和对话记录的数据结构 LLM服务:封装OpenAI接口,实现对话生成和记忆管理 知识库服务:集成向量数据库,支持知识检索和问答 系统架构清晰,各组件职责明确,便于扩展和维护,能为用户提供智能化的客户服务体验。 阅读详情

📖 本章学习目标

  • ✅ 设计完整的智能客服系统架构
  • ✅ 构建基于 RAG 的产品知识库
  • ✅ 实现多轮对话管理和上下文追踪
  • ✅ 集成订单查询、工单创建等业务系统
  • ✅ 实现智能转人工机制
  • ✅ 配置 LangSmith 监控和质量评估
  • ✅ 部署到生产环境并建立运维体系

一、项目概述

1、业务背景

某电商公司每天有数千条客服咨询,传统的人工客服面临以下挑战:

  • ❌ 响应速度慢(平均等待 5 分钟)
  • ❌ 人力成本高(需要 50+ 客服人员)
  • ❌ 服务质量不一致(不同客服水平差异大)
  • ❌ 无法 24/7 服务

解决方案: 构建智能客服 Agent,自动处理 80% 的常见问题。

2、系统目标

指标当前状态目标状态提升
自动解决率0%80%-
平均响应时间5 分钟3 秒⬇️ 99%
客户满意度75%85%⬆️ 10%
人力成本¥500K/月¥100K/月⬇️ 80%
服务时间9:00-21:0024/7⬆️ 100%

3、技术栈选型

外部系统

基础设施层

后端服务层

前端层

Web 聊天界面

移动端 App

Express API Server

LangChain Agent

PostgreSQL
用户数据

Pinecone
知识库

Redis
会话缓存

订单系统 API

工单系统 API

CRM 系统

核心技术:

  • 框架:LangChain.js v1.3.1 + LangGraph
  • 模型:OpenAI GPT-4o(主模型)、GPT-4o-mini(降级)
  • 向量数据库:Pinecone(生产)、Chroma(开发)
  • 关系数据库:PostgreSQL(用户数据、会话历史)
  • 缓存:Redis(会话状态、响应缓存)
  • 后端:Node.js + Express + TypeScript

二、系统架构设计

1、整体架构图

外部系统

订单系统 API

物流系统 API

工单系统 API

支付系统 API

业务工具集

订单查询工具

物流跟踪工具

工单创建工具

退款申请工具

转人工工具

用户

对话界面
Web/App

API Gateway
速率限制/认证

客服 Agent
核心大脑

对话记忆
MemorySaver + Redis

知识库检索
RAG Pipeline

业务工具集

LangSmith
监控与评估

外部系统

2、核心组件说明

组件职责技术选型
客服 Agent理解用户意图、调用工具、生成回复LangChain createAgent
知识库存储产品文档、FAQ、政策文件Pinecone + OpenAI Embeddings
对话记忆维护多轮对话上下文PostgreSQL + thread_id
业务工具对接订单、物流、工单等系统自定义 Tool 函数
监控系统追踪执行链路、评估质量LangSmith
API Gateway认证、限流、日志Express + 中间件

三、开发里程碑

我们将项目分解为 5 个里程碑,每个里程碑都有明确的目标和验收标准。

里程碑 1:基础框架搭建(2天)

目标: 搭建项目基础结构,实现最简单的问答功能。

步骤 1:初始化项目
# 创建项目目录
mkdir customer-service-agent && cd customer-service-agent

# 初始化 package.json
pnpm init

# 安装核心依赖
pnpm add langchain @langchain/openai @langchain/langgraph
pnpm add express cors dotenv zod
pnpm add -D typescript ts-node @types/node @types/express

# 初始化 TypeScript
npx tsc --init
步骤 2:配置环境变量

创建 .env 文件:

# OpenAI API Key
OPENAI_API_KEY=sk-your-api-key

# LangSmith 配置
LANGSMITH_API_KEY=lsv2-your-api-key
LANGSMITH_TRACING=true
LANGSMITH_PROJECT=customer-service-prod

# 数据库配置
DATABASE_URL=postgresql://user:password@localhost:5432/customer_service
REDIS_URL=redis://localhost:6379

# Pinecone 配置
PINECONE_API_KEY=your-pinecone-api-key
PINECONE_INDEX_NAME=customer-knowledge-base

# 服务器配置
PORT=3000
NODE_ENV=production
步骤 3:创建基础 Agent
// src/agent.ts
import "dotenv/config";
import { createAgent } from "langchain";
import { PostgresSaver } from "@langchain/langgraph-checkpoint-postgres";

// 创建持久化 checkpointer
const checkpointer = PostgresSaver.fromConnString(
  process.env.DATABASE_URL!
);

// 初始化数据库表
await checkpointer.setup();

// 创建基础客服 Agent
export const customerServiceAgent = createAgent({
  model: "openai:gpt-4o",
  tools: [],  // 暂时不添加工具
  checkpointer,
  
  systemPrompt: `你是专业的电商客服助手。

行为准则:
1. 用友好、专业的语气回答用户问题
2. 如果不知道答案,诚实告知,不要编造
3. 保持回答简洁,每次不超过 3 句话
4. 对于复杂问题,主动提出转接人工客服

当前时间:${new Date().toLocaleString("zh-CN")}`,
});
步骤 4:创建 API 服务器
// src/server.ts
import express from "express";
import cors from "cors";
import { customerServiceAgent } from "./agent";

const app = express();
app.use(cors());
app.use(express.json());

// 聊天接口
app.post("/api/chat", async (req, res) => {
  try {
    const { message, sessionId } = req.body;
    
    if (!message || !sessionId) {
      return res.status(400).json({ 
        error: "缺少必要参数:message 和 sessionId" 
      });
    }
    
    // 配置 thread_id
    const config = {
      configurable: {
        thread_id: `session-${sessionId}`,
      },
    };
    
    // 调用 Agent
    const result = await customerServiceAgent.invoke(
      {
        messages: [{ role: "user", content: message }],
      },
      config
    );
    
    // 返回回复
    const response = result.messages.at(-1)?.content;
    
    res.json({
      success: true,
      response,
      sessionId,
    });
  } catch (error) {
    console.error("聊天接口错误:", error);
    res.status(500).json({
      success: false,
      error: "服务器内部错误",
    });
  }
});

// 健康检查
app.get("/health", (req, res) => {
  res.json({ status: "ok", timestamp: new Date().toISOString() });
});

// 启动服务器
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`✅ 客服服务器运行在 http://localhost:${PORT}`);
});
步骤 5:测试基础功能
# 启动服务器
pnpm ts-node src/server.ts

# 测试 API(使用 curl 或 Postman)
curl -X POST http://localhost:3000/api/chat \
  -H "Content-Type: application/json" \
  -d '{
    "message": "你好",
    "sessionId": "test-001"
  }'

预期输出:

{
  "success": true,
  "response": "你好!我是客服助手,很高兴为您服务。请问有什么可以帮助您的吗?",
  "sessionId": "test-001"
}

✅ 验收标准:

  • 项目可以成功启动
  • API 接口正常响应
  • 对话历史正确保存(同一 sessionId 的多轮对话有上下文)
  • LangSmith 中可以查看追踪记录

里程碑 2:知识库构建(3天)

目标: 构建产品知识库,实现基于 RAG 的智能问答。

步骤 1:准备知识库文档

创建 knowledge-base/ 目录,存放各类文档:

knowledge-base/
├── products/           # 产品文档
│   ├── iphone-15.md
│   ├── macbook-pro.md
│   └── airpods.md
├── policies/           # 政策文件
│   ├── return-policy.md
│   ├── shipping-policy.md
│   └── warranty.md
├── faq/               # 常见问题
│   ├── account.md
│   ├── payment.md
│   └── delivery.md
└── troubleshooting/   # 故障排查
    ├── login-issues.md
    └── payment-failed.md

示例文档(return-policy.md):

# 退货政策

## 退货条件
1. 商品未使用,包装完好
2. 在购买后 7 天内申请
3. 非定制商品

## 退货流程
1. 登录账号,进入"我的订单"
2. 找到对应订单,点击"申请退货"
3. 填写退货原因,上传商品照片
4. 等待审核(1-2 个工作日)
5. 审核通过后,寄回商品
6. 收到商品后,3-5 个工作日内退款

## 注意事项
- 退货运费由用户承担(质量问题除外)
- 退款原路返回
- 优惠券不退
步骤 2:文档加载和切割
// src/knowledge-base/loader.ts
import { DirectoryLoader } from "langchain/document_loaders/fs/directory";
import { TextLoader } from "langchain/document_loaders/fs/text";
import { RecursiveCharacterTextSplitter } from "@langchain/textsplitters";
import { Document } from "@langchain/core/documents";

/**
 * 加载知识库文档
 */
export async function loadKnowledgeBase(): Promise<Document[]> {
  console.log("📚 开始加载知识库文档...");
  
  // 加载所有 Markdown 文件
  const loader = new DirectoryLoader(
    "./knowledge-base",
    {
      ".md": (path) => new TextLoader(path),
    }
  );
  
  const docs = await loader.load();
  console.log(`✅ 加载了 ${docs.length} 个文档`);
  
  return docs;
}

/**
 * 切割文档为 chunks
 */
export async function splitDocuments(
  docs: Document[]
): Promise<Document[]> {
  console.log("✂️ 开始切割文档...");
  
  const splitter = new RecursiveCharacterTextSplitter({
    chunkSize: 800,      // 每个 chunk 800 字符
    chunkOverlap: 150,   // 重叠 150 字符
    separators: [
      "\n\n",   // 段落
      "\n",     // 换行
      "。",      // 中文句号
      ",",      // 中文逗号
      " ",       // 空格
    ],
  });
  
  const chunks = await splitter.splitDocuments(docs);
  console.log(`✅ 切割为 ${chunks.length} 个 chunks`);
  
  return chunks;
}
步骤 3:生成 Embedding 并存储
// src/knowledge-base/indexer.ts
import { OpenAIEmbeddings } from "@langchain/openai";
import { PineconeStore } from "@langchain/pinecone";
import { Pinecone } from "@pinecone-database/pinecone";
import { loadKnowledgeBase, splitDocuments } from "./loader";

/**
 * 构建知识库索引
 */
export async function buildKnowledgeIndex() {
  console.log("🚀 开始构建知识库索引...");
  
  // 1. 加载文档
  const docs = await loadKnowledgeBase();
  
  // 2. 切割文档
  const chunks = await splitDocuments(docs);
  
  // 3. 初始化 Embedding 模型
  console.log("🔤 初始化 Embedding 模型...");
  const embeddings = new OpenAIEmbeddings({
    model: "text-embedding-3-small",
  });
  
  // 4. 连接 Pinecone
  console.log("🔗 连接 Pinecone...");
  const pinecone = new Pinecone({
    apiKey: process.env.PINECONE_API_KEY!,
  });
  
  const index = pinecone.Index(process.env.PINECONE_INDEX_NAME!);
  
  // 5. 批量写入向量数据库
  console.log("💾 写入向量数据库...");
  const vectorStore = await PineconeStore.fromDocuments(
    chunks,
    embeddings,
    {
      pineconeIndex: index,
      namespace: "customer-service",
    }
  );
  
  console.log(`✅ 知识库索引构建完成,共 ${chunks.length} 个向量`);
  
  return vectorStore;
}

// 执行索引构建
if (require.main === module) {
  buildKnowledgeIndex().catch(console.error);
}

运行索引构建:

pnpm ts-node src/knowledge-base/indexer.ts

输出:

🚀 开始构建知识库索引...
📚 开始加载知识库文档...
✅ 加载了 25 个文档
✂️ 开始切割文档...
✅ 切割为 180 个 chunks
🔤 初始化 Embedding 模型...
🔗 连接 Pinecone...
💾 写入向量数据库...
✅ 知识库索引构建完成,共 180 个向量
步骤 4:创建检索工具
// src/tools/knowledge-search.ts
import { tool } from "@langchain/core/tools";
import { PineconeStore } from "@langchain/pinecone";
import { OpenAIEmbeddings } from "@langchain/openai";
import { Pinecone } from "@pinecone-database/pinecone";
import { z } from "zod";

// 初始化向量存储
const pinecone = new Pinecone({
  apiKey: process.env.PINECONE_API_KEY!,
});

const embeddings = new OpenAIEmbeddings();
const index = pinecone.Index(process.env.PINECONE_INDEX_NAME!);

const vectorStore = new PineconeStore(embeddings, {
  pineconeIndex: index,
  namespace: "customer-service",
});

// 创建检索器
const retriever = vectorStore.asRetriever({
  k: 3,  // 返回最相关的 3 个文档
});

/**
 * 知识库搜索工具
 */
export const searchKnowledgeBase = tool(
  async ({ query }) => {
    console.log(`[Knowledge Search] 搜索: "${query}"`);
    
    // 执行检索
    const docs = await retriever.invoke(query);
    
    if (docs.length === 0) {
      return "未在知识库中找到相关信息。";
    }
    
    // 格式化结果
    const formattedDocs = docs.map((doc, index) => {
      const source = doc.metadata.source || "未知来源";
      return `【文档 ${index + 1}】来源:${source}\n${doc.pageContent}\n`;
    }).join("\n---\n");
    
    return formattedDocs;
  },
  {
    name: "search_knowledge_base",
    description: "搜索产品知识库,包括产品信息、退货政策、物流政策、常见问题等。当用户询问产品相关、政策相关或常见问题时调用此工具。",
    schema: z.object({
      query: z.string().describe("搜索关键词或问题描述"),
    }),
  }
);
步骤 5:集成到 Agent
// src/agent.ts
import { createAgent } from "langchain";
import { PostgresSaver } from "@langchain/langgraph-checkpoint-postgres";
import { searchKnowledgeBase } from "./tools/knowledge-search";

const checkpointer = PostgresSaver.fromConnString(
  process.env.DATABASE_URL!
);

export const customerServiceAgent = createAgent({
  model: "openai:gpt-4o",
  tools: [searchKnowledgeBase],  // 添加知识库搜索工具
  checkpointer,
  
  systemPrompt: `你是专业的电商客服助手。

可用工具:
- search_knowledge_base:搜索产品知识库

工作流程:
1. 首先理解用户问题
2. 如果问题涉及产品、政策、FAQ,调用 search_knowledge_base 搜索相关知识
3. 基于搜索结果回答问题
4. 如果知识库中没有相关信息,如实告知用户

行为准则:
1. 用友好、专业的语气回答
2. 引用知识库内容时,标注来源
3. 保持回答简洁(不超过 3 句话)
4. 不确定时,主动提出转接人工`,
});
步骤 6:测试知识库功能
# 测试知识库检索
curl -X POST http://localhost:3000/api/chat \
  -H "Content-Type: application/json" \
  -d '{
    "message": "退货政策是什么?",
    "sessionId": "test-002"
  }'

预期输出:

{
  "success": true,
  "response": "根据我们的退货政策:\n\n1. 退货条件:商品未使用且包装完好,在购买后7天内申请\n2. 退货流程:登录账号 → 我的订单 → 申请退货 → 等待审核 → 寄回商品 → 退款\n\n更多信息请参考:policies/return-policy.md",
  "sessionId": "test-002"
}

✅ 验收标准:

  • 知识库索引成功构建
  • 检索工具能返回相关文档
  • Agent 能基于知识库准确回答问题
  • 回答中标注了信息来源

里程碑 3:业务工具集成(4天)

目标: 集成订单查询、物流跟踪、工单创建等业务系统。

步骤 1:订单查询工具
// src/tools/order-query.ts
import { tool } from "@langchain/core/tools";
import axios from "axios";
import { z } from "zod";

/**
 * 查询订单状态
 */
export const queryOrderStatus = tool(
  async ({ orderId, userId }) => {
    console.log(`[Order Query] 查询订单: ${orderId}, 用户: ${userId}`);
    
    try {
      // 调用订单系统 API
      const response = await axios.get(
        `${process.env.ORDER_API_URL}/orders/${orderId}`,
        {
          headers: {
            "Authorization": `Bearer ${process.env.ORDER_API_KEY}`,
            "X-User-ID": userId,
          },
        }
      );
      
      const order = response.data;
      
      // 格式化订单信息
      const statusMap = {
        pending: "待付款",
        paid: "已付款",
        shipped: "已发货",
        delivered: "已送达",
        cancelled: "已取消",
      };
      
      return `订单信息:
- 订单号:${order.id}
- 商品:${order.items.map((item: any) => item.name).join(", ")}
- 金额:¥${order.total}
- 状态:${statusMap[order.status as keyof typeof statusMap]}
- 下单时间:${new Date(order.createdAt).toLocaleString("zh-CN")}`;
    } catch (error) {
      console.error("[Order Query] 查询失败:", error);
      return `抱歉,无法查询订单 ${orderId} 的信息。请确认订单号是否正确,或联系人工客服。`;
    }
  },
  {
    name: "query_order_status",
    description: "查询订单状态和详细信息。需要提供订单号和用户ID。当用户询问订单状态、订单详情时调用此工具。",
    schema: z.object({
      orderId: z.string().describe("订单号,例如:ORD-20250101-001"),
      userId: z.string().describe("用户ID,从会话上下文中获取"),
    }),
  }
);
步骤 2:物流跟踪工具
// src/tools/tracking.ts
import { tool } from "@langchain/core/tools";
import axios from "axios";
import { z } from "zod";

/**
 * 跟踪物流信息
 */
export const trackShipment = tool(
  async ({ trackingNumber }) => {
    console.log(`[Tracking] 跟踪物流: ${trackingNumber}`);
    
    try {
      const response = await axios.get(
        `${process.env.LOGISTICS_API_URL}/tracking/${trackingNumber}`,
        {
          headers: {
            "Authorization": `Bearer ${process.env.LOGISTICS_API_KEY}`,
          },
        }
      );
      
      const tracking = response.data;
      
      // 格式化物流信息
      const events = tracking.events
        .map((event: any) => {
          return `- ${new Date(event.timestamp).toLocaleString("zh-CN")}:${event.description} (${event.location})`;
        })
        .join("\n");
      
      return `物流跟踪信息(运单号:${trackingNumber}):\n\n${events}\n\n预计送达:${tracking.estimatedDelivery}`;
    } catch (error) {
      console.error("[Tracking] 跟踪失败:", error);
      return `抱歉,无法查询运单号 ${trackingNumber} 的物流信息。请稍后重试或联系人工客服。`;
    }
  },
  {
    name: "track_shipment",
    description: "跟踪包裹物流信息。需要提供运单号。当用户询问物流状态、包裹位置时调用此工具。",
    schema: z.object({
      trackingNumber: z.string().describe("运单号,例如:SF1234567890"),
    }),
  }
);
步骤 3:工单创建工具
// src/tools/ticket-create.ts
import { tool } from "@langchain/core/tools";
import axios from "axios";
import { z } from "zod";

/**
 * 创建客服工单
 */
export const createSupportTicket = tool(
  async ({ userId, category, subject, description }) => {
    console.log(`[Ticket] 创建工单: ${subject}`);
    
    try {
      const response = await axios.post(
        `${process.env.TICKET_API_URL}/tickets`,
        {
          userId,
          category,
          subject,
          description,
          priority: "normal",
          status: "open",
        },
        {
          headers: {
            "Authorization": `Bearer ${process.env.TICKET_API_KEY}`,
          },
        }
      );
      
      const ticket = response.data;
      
      return `工单已创建成功!
- 工单号:${ticket.id}
- 主题:${ticket.subject}
- 类别:${ticket.category}
- 预计响应时间:24小时内

我们的客服专员会尽快处理您的问题。您可以通过工单号查询处理进度。`;
    } catch (error) {
      console.error("[Ticket] 创建失败:", error);
      return `抱歉,创建工单失败。请直接联系人工客服:400-123-4567。`;
    }
  },
  {
    name: "create_support_ticket",
    description: "创建客服工单,用于处理复杂问题或投诉。需要提供用户ID、问题类别、主题和详细描述。当问题无法立即解决或需要人工介入时调用此工具。",
    schema: z.object({
      userId: z.string().describe("用户ID"),
      category: z.enum(["technical", "billing", "product", "complaint"]).describe("问题类别"),
      subject: z.string().describe("工单主题,简短描述问题"),
      description: z.string().describe("问题详细描述"),
    }),
  }
);
步骤 4:转人工工具
// src/tools/transfer-human.ts
import { tool } from "@langchain/core/tools";
import { interrupt } from "@langchain/langgraph";
import { z } from "zod";

/**
 * 转接人工客服
 */
export const transferToHuman = tool(
  async ({ reason, userId }) => {
    console.log(`[Transfer] 转人工: ${reason}`);
    
    // 记录转人工原因
    await logTransferRequest(userId, reason);
    
    // 发起中断,等待人工接入
    const humanAgentId = await interrupt({
      question: `用户请求转人工客服。\n原因:${reason}\n\n是否现在转接?`,
      type: "confirm",
    });
    
    if (humanAgentId) {
      return `已为您转接人工客服(工号:${humanAgentId})。请稍候,客服专员即将与您对话。`;
    } else {
      return `抱歉,当前人工客服繁忙。您可以:\n1. 留下联系方式,我们会回电\n2. 创建工单,24小时内回复\n3. 稍后再试`;
    }
  },
  {
    name: "transfer_to_human",
    description: "转接人工客服。当用户明确要求转人工、问题过于复杂、或用户情绪激动时调用此工具。",
    schema: z.object({
      reason: z.string().describe("转人工的原因"),
      userId: z.string().describe("用户ID"),
    }),
  }
);

// 辅助函数:记录转人工请求
async function logTransferRequest(userId: string, reason: string) {
  // 保存到数据库或发送到监控系统
  console.log(`[Transfer Log] 用户 ${userId} 请求转人工,原因:${reason}`);
}
步骤 5:集成所有工具到 Agent
// src/agent.ts
import { createAgent } from "langchain";
import { PostgresSaver } from "@langchain/langgraph-checkpoint-postgres";
import { searchKnowledgeBase } from "./tools/knowledge-search";
import { queryOrderStatus } from "./tools/order-query";
import { trackShipment } from "./tools/tracking";
import { createSupportTicket } from "./tools/ticket-create";
import { transferToHuman } from "./tools/transfer-human";

const checkpointer = PostgresSaver.fromConnString(
  process.env.DATABASE_URL!
);

export const customerServiceAgent = createAgent({
  model: "openai:gpt-4o",
  tools: [
    searchKnowledgeBase,    // 知识库搜索
    queryOrderStatus,       // 订单查询
    trackShipment,          // 物流跟踪
    createSupportTicket,    // 工单创建
    transferToHuman,        // 转人工
  ],
  checkpointer,
  
  systemPrompt: `你是专业的电商客服助手,拥有以下能力:

可用工具:
1. search_knowledge_base - 搜索产品知识库
2. query_order_status - 查询订单状态(需要订单号和用户ID)
3. track_shipment - 跟踪物流信息(需要运单号)
4. create_support_ticket - 创建客服工单
5. transfer_to_human - 转接人工客服

工作流程:
1. 理解用户问题和意图
2. 如果是常见问题,先搜索知识库
3. 如果涉及订单/物流,调用相应工具查询
4. 如果问题复杂或无法解决,创建工单或转人工
5. 基于工具返回的信息,用友好专业的语气回答

行为准则:
- 始终礼貌、耐心、专业
- 回答简洁明了(不超过 3-4 句话)
- 不确定时,如实告知并寻求帮助
- 对于投诉或紧急问题,优先转人工`,
});
步骤 6:测试业务工具
# 测试订单查询
curl -X POST http://localhost:3000/api/chat \
  -H "Content-Type: application/json" \
  -d '{
    "message": "帮我查一下订单 ORD-20250101-001 的状态",
    "sessionId": "user-123-session-001",
    "userId": "user-123"
  }'

✅ 验收标准:

  • 订单查询工具能正确调用 API 并返回结果
  • 物流跟踪工具能显示物流历程
  • 工单创建工具能成功创建工单
  • 转人工工具能正确触发中断
  • Agent 能根据场景选择合适的工具

里程碑 4:对话优化与质量控制(3天)

目标: 优化对话体验,建立质量评估体系。

步骤 1:实现主动引导
// src/agent.ts - 更新 systemPrompt
systemPrompt: `你是专业的电商客服助手。

[之前的配置...]

主动引导策略:
1. 用户询问产品时,主动推荐相关产品
2. 用户遇到问题时,提供多种解决方案
3. 对话结束时,询问是否还有其他帮助
4. 检测到用户不满时,及时安抚并转人工

示例对话:
用户:"我想买手机"
助手:"我们有 iPhone 15、Samsung Galaxy S24 等多款手机。您更看重哪些方面?(拍照、性能、价格)"

用户:"我的订单还没到"
助手:"我来帮您查询物流状态。请提供订单号或运单号。"
(查询后)
"您的包裹正在运输中,预计明天送达。如有其他问题,随时告诉我。"`
步骤 2:情感检测和处理
// src/middleware/sentiment-analysis.ts
import { createMiddleware } from "langchain";

/**
 * 简单的情感分析
 */
function detectSentiment(text: string): "positive" | "neutral" | "negative" {
  const negativeWords = ["生气", "投诉", "差评", "失望", "愤怒", "垃圾", "骗子"];
  const positiveWords = ["谢谢", "满意", "好评", "感谢", "棒", "好"];
  
  const hasNegative = negativeWords.some(word => text.includes(word));
  const hasPositive = positiveWords.some(word => text.includes(word));
  
  if (hasNegative) return "negative";
  if (hasPositive) return "positive";
  return "neutral";
}

/**
 * 情感分析中间件
 */
export const sentimentAnalysisMiddleware = createMiddleware({
  name: "SentimentAnalysis",
  
  beforeModel: async (request) => {
    const userMessage = request.messages.findLast(m => m.role === "user");
    
    if (userMessage && typeof userMessage.content === "string") {
      const sentiment = detectSentiment(userMessage.content);
      
      // 添加元数据
      request.metadata = {
        ...request.metadata,
        userSentiment: sentiment,
      };
      
      // 如果检测到负面情绪,添加特殊指令
      if (sentiment === "negative") {
        request.messages.push({
          role: "system",
          content: "⚠️ 用户情绪负面,请特别注意:\n1. 保持冷静和专业\n2. 表达理解和歉意\n3. 提供明确的解决方案\n4. 必要时主动转人工",
        });
      }
    }
    
    return request;
  },
});
步骤 3:配置 LangSmith 评估
// src/evaluation/setup.ts
import { Client } from "langsmith";
import { evaluate } from "langsmith/evaluation";
import { customerServiceAgent } from "../agent";

const client = new Client();

// 定义评估数据集
async function createEvaluationDataset() {
  const dataset = await client.createDataset("customer-service-eval");
  
  const testCases = [
    {
      inputs: { question: "退货政策是什么?" },
      expected_keywords: ["7天", "未使用", "包装完好"],
    },
    {
      inputs: { question: "如何查询订单?" },
      expected_keywords: ["订单号", "我的订单", "个人中心"],
    },
    {
      inputs: { question: "物流多久能到?" },
      expected_keywords: ["运单号", "物流", "配送时间"],
    },
    // ...更多测试用例
  ];
  
  for (const testCase of testCases) {
    await client.createExample({
      inputs: testCase.inputs,
      outputs: { keywords: testCase.expected_keywords },
    });
  }
  
  console.log(`✅ 创建了 ${testCases.length} 个评估用例`);
  return dataset;
}

// 运行评估
async function runEvaluation() {
  const results = await evaluate(
    async (inputs) => {
      const result = await customerServiceAgent.invoke({
        messages: [{ role: "user", content: inputs.question }],
      });
      return { answer: result.messages.at(-1)?.content };
    },
    {
      data: "customer-service-eval",
      evaluators: [
        // 关键词匹配评估器
        async ({ outputs, referenceOutputs }) => {
          const answer = outputs.answer.toLowerCase();
          const keywords = referenceOutputs?.keywords || [];
          
          const matchedKeywords = keywords.filter((keyword: string) =>
            answer.includes(keyword.toLowerCase())
          );
          
          const score = matchedKeywords.length / keywords.length;
          
          return {
            key: "keyword_match",
            score,
            comment: `匹配了 ${matchedKeywords.length}/${keywords.length} 个关键词`,
          };
        },
      ],
    }
  );
  
  // 输出评估报告
  const avgScore = results.reduce((sum, r) => sum + r.score, 0) / results.length;
  console.log(`\n📊 评估报告:`);
  console.log(`平均得分:${avgScore.toFixed(2)}`);
  console.log(`测试用例数:${results.length}`);
  
  return results;
}

// 执行
if (require.main === module) {
  createEvaluationDataset()
    .then(() => runEvaluation())
    .catch(console.error);
}

✅ 验收标准:

  • 主动引导策略生效,对话更流畅
  • 情感检测能识别负面情绪并调整回复策略
  • LangSmith 评估报告生成,平均得分 > 0.8
  • 可以在 LangSmith 中查看详细的评估结果

里程碑 5:部署和监控(2天)

目标: 部署到生产环境,建立完整的监控体系。

步骤 1:Docker 化部署

创建 Dockerfile:

# 使用 Node.js 18 LTS
FROM node:18-alpine

# 设置工作目录
WORKDIR /app

# 复制 package.json
COPY package.json pnpm-lock.yaml ./

# 安装 pnpm
RUN npm install -g pnpm

# 安装依赖
RUN pnpm install --prod

# 复制源代码
COPY . .

# 编译 TypeScript
RUN pnpm build

# 暴露端口
EXPOSE 3000

# 启动服务器
CMD ["node", "dist/server.js"]

创建 docker-compose.yml:

version: '3.8'

services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - OPENAI_API_KEY=${OPENAI_API_KEY}
      - DATABASE_URL=postgresql://postgres:password@db:5432/customer_service
      - REDIS_URL=redis://redis:6379
      - PINECONE_API_KEY=${PINECONE_API_KEY}
    depends_on:
      - db
      - redis
    restart: unless-stopped

  db:
    image: postgres:15-alpine
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=customer_service
    volumes:
      - postgres_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data

volumes:
  postgres_data:
  redis_data:

部署命令:

# 构建并启动
docker-compose up -d

# 查看日志
docker-compose logs -f app

# 停止服务
docker-compose down
步骤 2:配置 PM2 进程管理

创建 ecosystem.config.js:

module.exports = {
  apps: [
    {
      name: "customer-service-agent",
      script: "dist/server.js",
      instances: "max",  // 使用所有 CPU 核心
      exec_mode: "cluster",
      max_memory_restart: "1G",
      env: {
        NODE_ENV: "production",
        PORT: 3000,
      },
      error_file: "logs/error.log",
      out_file: "logs/out.log",
      merge_logs: true,
      log_date_format: "YYYY-MM-DD HH:mm:ss",
    },
  ],
};

PM2 命令:

# 启动应用
pm2 start ecosystem.config.js

# 查看状态
pm2 status

# 查看日志
pm2 logs

# 重启应用
pm2 restart customer-service-agent

# 设置开机自启
pm2 startup
pm2 save
步骤 3:配置监控告警
// src/monitoring/alerts.ts
import { Client } from "langsmith";

const client = new Client();

/**
 * 检查关键指标并发送告警
 */
export async function checkAndAlert() {
  // 1. 检查错误率
  const errorRate = await getErrorRate(lastMinutes: 5);
  if (errorRate > 0.1) {
    await sendAlert({
      severity: "critical",
      message: `⚠️ 错误率过高:${(errorRate * 100).toFixed(2)}%`,
    });
  }
  
  // 2. 检查响应时间
  const p95Latency = await getLatencyPercentile(95, lastMinutes: 5);
  if (p95Latency > 5000) {
    await sendAlert({
      severity: "warning",
      message: `⚠️ P95 延迟过高:${p95Latency}ms`,
    });
  }
  
  // 3. 检查成本
  const dailyCost = await getDailyCost();
  const budget = parseFloat(process.env.DAILY_BUDGET || "100");
  if (dailyCost > budget * 0.8) {
    await sendAlert({
      severity: "warning",
      message: `💰 今日成本已达到预算的 80%:$${dailyCost.toFixed(2)}`,
    });
  }
}

/**
 * 发送告警通知
 */
async function sendAlert({
  severity,
  message,
}: {
  severity: "critical" | "warning";
  message: string;
}) {
  console.error(`[Alert] [${severity.toUpperCase()}] ${message}`);
  
  // 发送到 Slack
  if (process.env.SLACK_WEBHOOK_URL) {
    await fetch(process.env.SLACK_WEBHOOK_URL, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        text: `[${severity.toUpperCase()}] ${message}`,
        channel: "#alerts",
      }),
    });
  }
  
  // 严重告警发送到 PagerDuty
  if (severity === "critical" && process.env.PAGERDUTY_INTEGRATION_KEY) {
    await triggerPagerDuty(message);
  }
}

// 每分钟检查一次
setInterval(checkAndAlert, 60000);

✅ 验收标准:

  • Docker 容器成功启动并运行
  • PM2 进程管理正常工作
  • 监控告警系统能及时发现异常
  • LangSmith 中可以查看所有追踪记录
  • 系统可以承受至少 100 并发用户

四、项目总结

📊 最终成果(假设)

指标数值
自动解决率82%
平均响应时间2.8 秒
客户满意度87%
人力成本节省78%
服务时间24/7

🎯 关键技术点

  1. RAG 知识库:基于 Pinecone 的向量检索,准确率 90%+
  2. 多工具集成:订单、物流、工单等业务系统无缝对接
  3. 对话管理:基于 thread_id 的多轮对话上下文追踪
  4. 质量监控:LangSmith 全链路追踪和自动化评估
  5. 生产部署:Docker + PM2 + 监控告警体系

💡 经验教训(假设)

成功经验:

  • ✅ 分阶段开发,每个里程碑都有明确目标
  • ✅ 早期接入 LangSmith,便于调试和优化
  • ✅ 充分的错误处理和降级策略
  • ✅ 完善的监控告警,及时发现问题

踩坑记录:

  • ❌ 初期未设置 Token 预算,导致成本失控
  • ❌ 忘记配置速率限制,遭遇恶意刷接口
  • ❌ 知识库文档质量参差不齐,影响检索效果
  • ❌ 未做充分的压力测试,上线后出现性能瓶颈

📚 延伸阅读


下一章:《第十二章 —— 实战二:代码助手 Agent》

LangChain框架入门16:智能客服系统RAG应用实战 本文介绍了一个基于RAG(检索增强生成)的智能电商客服系统实现方案。系统通过商品信息文档加载、文本分割、嵌入模型转换和向量存储四个步骤完成RAG准备阶段,后续将结合大语言模型实现商品咨询的智能回复功能。系统架构支持历史记忆持久化、LCEL链式构建和RAG检索,能够根据商品知识库准确回答用户问题。文中详细展示了商品信息文档格式和RAG准备阶段的Python实现代码,包括文本分割器配置、嵌入模型选择及Weaviate向量数据库的使用方法。 阅读详情

相关推荐

【好书推荐】《 LangChain实战派:大语言模型+LangChain+向量数据库》

各位友友,如果你正在寻找一本能够带你深入大语言模型应用开发的实战指南,《LangChain实战派——大语言模型+LangChain+向量数据库》绝对值得你拥有。京东电子工业出版社自营店 书籍链接:https://item.jd.com/14871256.html全面的技术覆盖:本书不仅详细介绍了LangChain的各个模块,还涵盖了向量数据库和大语言模型的基础知识,让你在掌握核心技能的同时,也能对相关技术有全面的了解。

努力才是唯一的入场券。 3万+

别再怕了!用LangChain搭建智能客服系统,代码详解+收藏指南

本文详解使用LangChain构建智能客服系统的六大核心组件:模型包装器处理输入输出,数据连接器实现知识库检索,记忆模块维持对话上下文,链组件协调工作流程,代理处理复杂任务,回调监控系统性能。通过这些模块化组件的组合,开发者可像搭积木一样构建适合业务场景的AI客服应用,即使是小白也能轻松上手。

bugyinyin的博客 584

深入浅出LangChain AI Agent智能体开发教程(一)—认识LangChain&LangGraph

本篇分享从LangChain&LangGraph的核心概念、核心特性、与其它框架的对比以及热门项目四个方面带大家详细了解了LangChain和LangGraph框架特性,为后期系列分享奠定理论基础。

weixin_42782643的博客 1459

实战分享LangChain WebUI 部署智能客服:从零搭建到生产环境优化

本文介绍了基于LangChain和WebUI构建智能客服系统的完整实践方案。文章首先分析了智能客服的商业价值和技术选型要点,指出LangChain+WebUI组合在开发效率、可扩展性和可控性方面的优势。随后详细阐述了从零搭建的步骤,包括环境准备、知识库构建、核心流程设计等关键环节,并重点讲解了生产环境下的性能优化、安全合规和评估体系。最后提出了90天落地路径建议,强调智能客服系统需要融合知识工程、应用编排和持续迭代机制,才能实现从"能回答"到"答得准、答得稳"的升级。

2301_81527952的博客 773

《AI大模型实战指南》扩展篇:LlamaIndex与LangChain的智能客服系统构建

本文详细介绍了如何利用LlamaIndex与LangChain构建企业级智能客服系统。通过将LlamaIndex的专业文档检索能力与LangChain的复杂工作流编排能力无缝集成,开发者可以快速搭建一个既能精准查询内部知识库,又能进行流畅多轮对话的AI助手。文章提供了从环境准备、核心概念到命令行原型、Web界面及本地私有化部署的完整实战指南。

weixin_29207149的博客 506

基于LangChain与RAG技术构建企业级智能客服系统实战指南

大语言模型(LLM)在通用对话中表现出色,但其知识受限于训练数据,难以处理私有、实时或特定领域信息,这导致了“幻觉”问题。检索增强生成(RAG)技术通过引入外部知识库,让模型在生成答案前先检索相关信息,有效提升了回答的准确性和可信度,成为解决领域知识问答的关键。在工程实践中,LangChain框架通过将文档加载、文本分割、向量检索、提示工程等环节模块化,大幅降低了构建RAG应用的复杂度。结合智能体(Agent)技术,系统不仅能回答知识性问题,还能调用工具执行查询、创建工单等具体操作。本文以构建企业智能客服系

weixin_30376083的博客 425

深入浅出 LangChain — 导读

本系列文章导读,介绍写作背景、目标读者、内容结构与阅读建议,帮助读者在正式开始前建立清晰的学习预期,少走弯路。

FrontAI的博客 861

实习日记:用LangChain和Spring AI实现Agent框架的智能客服系统

Agent框架让大语言模型具备工具调用能力规划器(Planner):解析用户意图,生成执行计划工具集(Tools):API/函数等可执行单元执行引擎(Executor):协调工具调用和结果整合graph LRA[用户提问] --> B(规划器)B --> C{需要工具?C -->|是| D[工具调用]C -->|否| E[直接回答]D --> F[执行引擎]F --> G[结果整合]G --> H[最终响应]

m0_59004289的博客 677

LangChain学习一:模型-实战

聊天模型:这些模型通常由语言模型支持,但它们的API更加结构化。具体来说,这些模型将聊天消息列表作为输入,并返回聊天消息。这里的content就相当于大模型机器回答,干啥用呢,为了以后的多轮对话做准备。LLMs:这些模型将文本字符串作为输入,并返回文本字符串作为输出。还可有以下情况,就是上面说的模仿大模型说话,我们先看一下原生的。文本嵌入模型:这些模型将文本作为输入,并返回一个浮点数列表。看到没,这时候,我们的大模型就可以作为一个助手帮你了。LangChain 支持的各种模型类型和模型集成。

huiguo_的博客 2416

电路板功能测试系统-FCT for PCBA

电路板功能测试系统用于电路板组件(PCBA)的功能测试(FCT),满足自动化大批量生产的要求。  ● 用户根据自己需要定义测试步骤,灵活方便  ● 适合工业自动化大批量生产应用  ● 系统测试精度高,稳定可靠   一、电路板功能测试系统概述 电路板测试过程通常由多个步骤组成,每单个步骤中需要对多个物理量(电压、电流、电阻、频率、波形等)进行测试。在每个步骤测试时

6813

华为MA5626 ONU开局配置实战:从零到业务就绪的完整命令手册

本文详细介绍了华为MA5626 ONU设备的开局配置全流程,包括物理连接、命令行初始化、业务VLAN划分、PoE功能配置及故障排查。通过实战命令手册,帮助网络工程师快速完成从设备上电到业务就绪的完整配置,特别适合FTTB场景部署。

weixin_26934905的博客 561

LlamaIndex与LangChain深度整合指南:原理、代码与实战

LlamaIndex与LangChain深度整合指南:原理、代码与实战

嗨,欢迎来到我的 优快云 博客小天地!一名深耕多年的技术发烧友。在这里,我将把日常工作中积累的宝贵经验,从复杂架构设计的精妙之处,到代码优化的实战技巧,毫无保留地分享给大家。 1156

告别手动处理:用 Bruker NSMatlabUtilities 工具箱批量分析 AFM 力曲线数据的实战案例

本文介绍了如何使用 Bruker NSMatlabUtilities 工具箱实现 AFM 力曲线数据的批量分析,解决传统手动处理耗时且易出错的问题。通过实战案例展示工具箱的核心功能,包括数据读取、力曲线分析和可视化,帮助科研人员提升数据处理效率和准确性。

weixin_28362173的博客 214

构建下一代智能客服系统:LangChain驱动的5大架构革新指南

在数字化转型浪潮中,**智能客服系统**正成为企业与客户沟通的关键桥梁。随着AI技术的成熟,构建能够深度理解用户意图、提供个性化服务的智能客服平台已成为企业提升客户体验的核心需求。本文将深入探讨如何基于LangChain框架构建完整的**智能客服解决方案**,从技术选型到架构设计,从对话管理到智能决策,为您呈现一条清晰的技术实践路径。 ## 📊 系统架构设计:模块化与可扩展性 ### 核心架

gitblog_01026的博客 1036

STM32开发者必看:如何在正点原子探索者开发板上快速移植CANopenNode协议栈

本文为STM32开发者提供了在正点原子探索者开发板上快速移植CANopenNode协议栈的实战指南。文章详细介绍了从环境准备、硬件抽象层适配到协议栈初始化与测试的全过程,并分享了PDO配置与性能优化等关键技巧,帮助开发者高效实现CANopen标准化通信。

weixin_29173777的博客 462

AI视频生成提示词工程:结构化公式与实战案例详解

在实际使用 AI 生成视频或图像时,最常遇到的困惑是:为什么我的提示词(Prompt)生成的画面总是不理想?是模型能力不足,还是我的描述有问题?答案往往是后者。提示词工程(Prompt Engineering)并非简单的“翻译”需求,而是一门需要结构化思维和精准描述的技能。它决定了 AI 能否准确理解你的意图,并生成符合预期的视觉内容。 本文将通过两个核心案例,深入拆解提示词的构建逻辑。第一个案例聚焦于“文生视频”,我们将学习如何将一个简单的想法,如“小猫在雪地里玩雪球”,通过结构化公式扩展为一段富有细节和

weixin_30800987的博客 563

深入浅出 LangChain

LangChain 就是那个让我们能将这些语言模型乐高积木组合成有趣应用的工具箱。LangChian 不是一个实物,而是一个开源的基于 LLM 的上层应用开发框架,LangChain 提供了一系列的工具和接口,让开发者可以轻松地构建和部署基于 LLM 的应用。LangChain 围绕将不同组件 “链接” 在一起的核心概念构建,简化了与 GPT-3.5、GPT-4 等 LLM 合作的过程,使得我们可以轻松创建定制的高级用例。LangChain 已经成为大模型应用开发的最主流框架(之一)。

岁月斑驳7的博客 1302

SAP 系统间 SSO 的真正价值,从 SM59 到可信 RFC 的安全设计

SAP S/4HANA系统间Single Sign-On(SSO)的核心价值在于集中管理通信身份与信任关系,而非仅减少密码输入。传统固定账号密码方式在系统规模扩大后会面临密码管理、审计追踪等挑战。通过SM59配置可信RFC目标系统,结合SSL证书或SAP Trusted System等强认证机制,能有效降低安全凭据暴露风险。SSO配置需配合授权对象、角色管理等建立清晰的信任边界,实现系统间安全通信的同时保持可审计性。这种方案特别适用于Fiori前端与S/4HANA后端等场景,通过可信RFC传递用户身份,避免

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1063

DeerFlow智能客服系统实战:基于LangChain的对话引擎集成

本文介绍了如何在星图GPU平台上一键自动化部署DeerFlow智能客服镜像,快速构建基于LangChain的对话引擎。该镜像能自动处理电商场景中的用户咨询,实现多轮对话与精准问答,大幅提升客服响应效率与准确率。

weixin_35755823的博客 417

【AI】获取各类AI大模型api-key的快速教程(OpenAI、Gemini、Claude、DeepSeek)

【AI】获取各类AI大模型api-key的快速教程(OpenAI、Gemini、Claude、DeepSeek)

funfan的博客 3003

基于STM32、HAL库的MCP4651-503E/ST数字电位器驱动程序设计

@param channel: 通道 (0: A通道, 1: B通道)* @param channel: 通道 (0: A通道, 1: B通道)// SPI1 SCK/MISO/MOSI引脚配置。* @param hmcp: MCP4651句柄。* @param hmcp: MCP4651句柄。* @param hmcp: MCP4651句柄。* @param hmcp: MCP4651句柄。* @param hmcp: MCP4651句柄。* @param hspi: SPI句柄。

corlin6688的博客 137

LangChain 1.0实战:打造企业级智能客服系统

它的在线编辑器可以直接运行和调试代码,还能一键部署测试环境,省去了本地配置各种依赖的麻烦。最近在做一个企业智能客服系统的项目,正好用上了刚发布的LangChain 1.0,整个过程比想象中顺利很多。具体实现时,先把企业知识库的JSON文件转换成向量存储,这样就能做语义相似度匹配了。当用户提问时,系统会先做意图识别,然后在知识库中搜索最相关的答案。前端用React构建交互界面,后端选择了FastAPI作为API服务框架,主要考虑到它的异步特性和简洁的代码风格。遇到的最大挑战是如何提高回答的准确性。

CyanWave34的博客 483

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

2024全新Langchain大模型AI应用与多智能体实战开发

Langchain是一个用于开发由LLM驱动的应用程序的框架,可以视为LLM领域的Spring,以及开源版的ChatGPT插件系统。它提供了多种组件,帮助开发者轻松构建大语言模型应用,包括Models、Prompts、Indexes、Memory、Chains和Agents等。Langchain本身不提供LLM,但提供通用的接口访问LLM,方便开发者更换或自定义底层的LLM。

2401_84204413的博客 1348

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

LangChain4j实战:构建智能客服系统的5个关键步骤

用Spring Initializr快速生成项目骨架时,除了常规的Web依赖,特别注意添加了H2数据库和LangChain4j的starter。最惊喜的是支持H2数据库的持久化存储,对话记录不会因为重启丢失。整个开发过程让我感受到LangChain4j的强大之处——用熟悉的Java技术栈就能实现复杂的AI应用。遇到的一个典型问题是长对话时的性能下降,后来通过异步写入和定期清理旧对话解决了。的一键部署能力,从开发到上线只需要几个小时,对快速验证想法特别有帮助。多轮对话的关键是维护上下文。

CrystalwaveStag的博客 424

深入浅出 LangChain 与智能 Agent:构建下一代 AI 助手

LangChain 为大型语言模型提供了一种全新的搭建和集成方式,正如乐高积木提供了无尽的创造可能。通过这个强大的框架,我们可以将复杂的技术任务简化,让创意和创新更加易于实现。在第一篇的内容中,我们穿越了 LangChain 的世界,体验了如同搭建乐高积木般构建语言模型应用的乐趣。从 LangChain 的核心概念到其在现实世界中人脸问题的智能排查应用,我们见证了这一框架如何助力智能体的创新与成长。在第二篇的内容中,我们讨论了智能体的发展,目前主要呈现两大方向。

2401_85116933的博客 1221
上一篇: 深入浅出 LangChain —— 第十章:上下文工程与安全护栏
下一篇: 深入浅出 LangChain —— 第十三章:实战三 - 企业知识库问答
FrontAI
博客等级 码龄1年 61粉丝 61原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值