从零构建智能客服系统:基于LangChain.js的全栈技术实践

一、系统架构设计

1.1 技术栈选型

本系统采用前后端分离架构:

  • 前端:Vue3 + TypeScript + Pinia状态管理
  • 后端:Express + Node.js(LangChain.js运行环境)
  • 存储层:文件系统(文档存储) + 内存数据库(向量索引)
  • 核心框架:LangChain.js v0.2+(支持链式调用与智能代理)

1.2 模块划分

  1. src/
  2. ├── client/ # 前端应用
  3. ├── components/ # 对话界面组件
  4. └── stores/ # 状态管理
  5. └── server/ # 后端服务
  6. ├── config/ # 环境配置
  7. ├── controllers/ # 路由处理
  8. ├── models/ # 数据模型
  9. ├── services/ # 核心服务
  10. ├── agents/ # 智能代理实现
  11. └── chains/ # 链式处理流程
  12. └── utils/ # 工具函数

二、核心功能实现

2.1 文档处理模块

2.1.1 文档加载器实现

  1. // services/loaders/DocumentLoader.ts
  2. import { DirectoryLoader, TextLoader } from 'langchain/document_loaders';
  3. export class CustomDocumentLoader {
  4. static async loadFromDirectory(path: string) {
  5. const loader = new DirectoryLoader(path, {
  6. '.txt': (path) => new TextLoader(path),
  7. // 可扩展支持.pdf/.docx等格式
  8. });
  9. return await loader.load();
  10. }
  11. }

2.1.2 文本分块策略

采用递归分块算法处理长文档:

  1. function recursiveChunk(text: string, maxSize = 1000, minSize = 200) {
  2. if (text.length <= maxSize) return [text];
  3. const mid = Math.floor(text.length / 2);
  4. const left = recursiveChunk(text.slice(0, mid), maxSize, minSize);
  5. const right = recursiveChunk(text.slice(mid), maxSize, minSize);
  6. return [...left, ...right].filter(chunk => chunk.length >= minSize);
  7. }

2.2 向量存储与检索

2.2.1 内存向量存储实现

  1. // services/storage/VectorStore.ts
  2. import { InMemoryDocumentStore } from 'langchain/document_loaders/fs';
  3. import { Embeddings } from 'langchain/embeddings';
  4. export class CustomVectorStore {
  5. private store: InMemoryDocumentStore;
  6. constructor(private embeddings: Embeddings) {
  7. this.store = new InMemoryDocumentStore();
  8. }
  9. async addDocuments(docs: Document[]) {
  10. const vectors = await this.embeddings.embedDocuments(
  11. docs.map(doc => doc.pageContent)
  12. );
  13. // 实现向量存储逻辑...
  14. }
  15. }

2.2.2 语义搜索优化

采用混合检索策略提升精度:

  1. async similaritySearch(query: string, k = 3) {
  2. const queryEmbedding = await this.embeddings.embedQuery(query);
  3. // 基础向量检索
  4. let results = this.store.similaritySearchVectorWithScore(queryEmbedding, k);
  5. // 可选:添加关键词过滤
  6. if (shouldUseKeywordFilter(query)) {
  7. const keywordMatches = this.keywordSearch(query);
  8. results = results.filter(([doc]) =>
  9. keywordMatches.includes(doc.metadata.source)
  10. );
  11. }
  12. return results;
  13. }

2.3 会话记忆管理

2.3.1 上下文窗口控制

  1. // services/memory/BufferMemory.ts
  2. import { BufferMemory } from 'langchain/memory';
  3. export class ConversationMemory extends BufferMemory {
  4. constructor(private maxTokens = 2048) {
  5. super({
  6. memoryKey: 'chat_history',
  7. inputKey: 'input',
  8. outputKey: 'output'
  9. });
  10. }
  11. async getContext() {
  12. let history = await super.loadMemoryVariables({});
  13. // 实现基于token数的截断逻辑
  14. return this.truncateHistory(history.chat_history);
  15. }
  16. }

2.3.2 对话状态持久化

  1. // 前端状态管理示例
  2. export const useConversationStore = defineStore('conversation', {
  3. state: () => ({
  4. history: [] as ConversationEntry[],
  5. currentSession: null as string | null
  6. }),
  7. actions: {
  8. async saveSession() {
  9. if (this.currentSession) {
  10. await api.saveConversation({
  11. id: this.currentSession,
  12. messages: this.history
  13. });
  14. }
  15. }
  16. }
  17. });

2.4 智能代理集成

2.4.1 代理工具链配置

  1. // services/agents/ToolAgent.ts
  2. import { initializeAgentExecutorWithOptions } from 'langchain/agents';
  3. import { Calculator, WebSearch } from 'langchain/tools';
  4. export async function createToolAgent(llm) {
  5. const tools = [
  6. new Calculator(),
  7. new WebSearch({
  8. apiKey: process.env.SEARCH_API_KEY,
  9. // 可配置搜索参数
  10. })
  11. ];
  12. return await initializeAgentExecutorWithOptions(tools, llm, {
  13. agentType: 'zero-shot-react-description',
  14. verbose: true
  15. });
  16. }

2.4.2 代理路由策略

  1. // 路由控制器示例
  2. router.post('/agent', async (req, res) => {
  3. const { query, context } = req.body;
  4. try {
  5. // 根据查询类型选择代理
  6. const agent = isFactQuestion(query)
  7. ? factAgent
  8. : calculationAgent;
  9. const result = await agent.call({
  10. input: query,
  11. chat_history: context
  12. });
  13. res.json({ success: true, result });
  14. } catch (error) {
  15. res.status(500).json({ error: error.message });
  16. }
  17. });

三、系统优化策略

3.1 性能优化方案

  1. 向量检索加速

    • 使用FAISS等近似最近邻库替代纯内存实现
    • 实现异步索引更新机制
  2. 缓存策略

    1. // 查询结果缓存示例
    2. const cache = new LRUCache({ max: 1000 });
    3. async function cachedQuery(query: string) {
    4. const cacheKey = hash(query);
    5. if (cache.has(cacheKey)) {
    6. return cache.get(cacheKey);
    7. }
    8. const result = await performQuery(query);
    9. cache.set(cacheKey, result);
    10. return result;
    11. }

3.2 可靠性增强措施

  1. 错误处理机制

    • 实现重试逻辑(网络请求/模型调用)
    • 降级策略(当LLM不可用时返回缓存结果)
  2. 监控体系

    1. // 简单监控实现
    2. class QueryMonitor {
    3. private metrics = {
    4. success: 0,
    5. failure: 0,
    6. latency: [] as number[]
    7. };
    8. record(success: boolean, duration: number) {
    9. this.metrics[success ? 'success' : 'failure']++;
    10. this.metrics.latency.push(duration);
    11. }
    12. getStats() {
    13. return {
    14. successRate: this.metrics.success /
    15. (this.metrics.success + this.metrics.failure),
    16. avgLatency: this.metrics.latency.reduce((a, b) => a + b, 0) /
    17. this.metrics.latency.length
    18. };
    19. }
    20. }

四、部署与扩展建议

4.1 容器化部署方案

  1. # Dockerfile示例
  2. FROM node:18-alpine
  3. WORKDIR /app
  4. COPY package*.json ./
  5. RUN npm install --production
  6. COPY . .
  7. EXPOSE 3000
  8. CMD ["node", "dist/server/index.js"]

4.2 水平扩展架构

  1. 无状态服务设计

    • 将向量存储迁移至Redis等外部服务
    • 实现会话标识的跨实例共享
  2. 负载均衡配置

    1. upstream langchain_servers {
    2. server server1:3000;
    3. server server2:3000;
    4. server server3:3000;
    5. }
    6. server {
    7. location / {
    8. proxy_pass http://langchain_servers;
    9. }
    10. }

五、总结与展望

本方案完整实现了从文档处理到智能对话的全流程,核心创新点包括:

  1. 混合检索机制提升语义理解精度
  2. 动态代理路由适应不同查询场景
  3. 多层级缓存策略优化系统性能

未来可扩展方向:

  • 接入多模态处理能力(图片/音频理解)
  • 实现主动学习机制持续优化检索效果
  • 添加用户反馈循环改进对话质量

通过本实践,开发者可以掌握LangChain.js框架的核心应用模式,为构建更复杂的智能应用奠定基础。完整代码实现已开源至某托管仓库,包含详细注释与测试用例。