Skip to main content

概述

Chat服务是LangChat Pro的核心功能模块,负责处理用户的聊天对话请求,支持流式响应、知识库检索、工具调用等高级功能。

架构层次

┌──────────────────────────────────────────────────────┐
│           LcChatController (REST API)              │
└────────────────┬─────────────────────────────────┘


┌──────────────────────────────────────────────────────┐
│               ChatService                          │
│              业务逻辑层                             │
│  - 参数验证                                        │
│  - 业务处理                                        │
│  - 消息保存                                        │
└────────────────┬─────────────────────────────────┘


┌──────────────────────────────────────────────────────┐
│              LcChatService                         │
│              核心服务层                             │
│  - 上下文构建                                      │
│  - 模型获取                                        │
│  - AI Service组装                                  │
│  - 流式调用                                        │
└────────────────┬─────────────────────────────────┘


┌──────────────────────────────────────────────────────┐
│           LangChain4j Agent                        │
│              AI推理引擎                             │
└──────────────────────────────────────────────────────┘

核心组件

1. LcChatController

路径: langchat-core/src/main/java/cn/langchat/core/controller/LcChatController.java 职责: REST API控制器,处理HTTP聊天请求 核心方法:
// 流式聊天
@PostMapping("/chat/chat")
public void chat(@RequestBody LcChatReq req, HttpServletResponse response) throws IOException

// 独立流式聊天
@PostMapping("/chat/standalone")
public void standalone(@RequestBody LcChatReq req, HttpServletResponse response) throws IOException
功能特性:
  • REST API接口
  • 流式响应支持
  • 权限验证
  • 参数校验

2. ChatService

接口路径: langchat-aigc/langchat-aigc-api/src/main/java/cn/langchat/aigc/api/service/ChatService.java 实现路径: langchat-aigc/langchat-aigc-api/src/main/java/cn/langchat/aigc/api/service/impl/ChatServiceImpl.java 职责: 聊天业务逻辑处理 核心方法:
// 聊天(流式)
TokenStream chat(ChatReq req)

// 聊天(异步处理)
void asyncChat(ChatReq req, StreamEventPublisher publisher)

// 聊天建议获取
String getChatSuggestion(ChatSuggestionReq req)

// 简单文本对话
String simpleChatForText(SimpleChatContext context)
主要职责:
  1. 参数验证和转换
  2. 调用LcChatService执行AI推理
  3. 处理流式响应
  4. 保存聊天记录
  5. 敏感词过滤
  6. 消息推送

3. LcChatService

接口路径: langchat-core/src/main/java/cn/langchat/core/service/LcChatService.java 实现路径: langchat-core/src/main/java/cn/langchat/core/service/impl/LcChatServiceImpl.java 职责: 核心聊天服务,负责AI Service构建和调用 核心方法:
// 流式聊天(支持知识库、RAG)
TokenStream streamingChat(LcChatReq req)

// 独立流式聊天(不关联知识库)
TokenStream standaloneStreamingChat(LcChatReq req)

// 简单文本对话
String simpleChatForText(SimpleChatContext context)

// 获取ChatModel
ChatModel getChatModel(BaseChatContext context)

// 获取StreamingChatModel
StreamingChatModel getStreamingChatModel(BaseChatContext context)
实现流程:

streamingChat 流程

@Override
public TokenStream streamingChat(LcChatReq req) {
    // 1. 生成chatId
    String chatId = StrUtil.isNotBlank(req.getChatId()) 
        ? req.getChatId() 
        : LcIdUtil.getUUID();
    
    // 2. 构建ChatContext
    var chatContext = contextBuilder.build(req);
    chatContext.setChatId(chatId);
    chatContext.setAppId(req.getAppId());
    chatContext.setConversationId(req.getConversationId());
    
    // 3. 设置ThreadLocal上下文
    ChatContextHolder.set(chatContext);
    
    // 4. 获取StreamingChatModel(带listener)
    StreamingChatModel streamingModel = 
        modelFactory.getStreamingModel(chatContext, chatId);
    
    // 5. 构建Agent
    var agent = aiServiceBuilder.build(streamingModel, req, conversationId);
    
    // 6. 构建消息
    var message = buildChatMessages(req);
    
    // 7. 调用Agent
    var tokenStream = agent.stream(conversationId, message);
    
    return tokenStream;
}

请求处理流程

完整聊天流程

┌─────────────┐
│   Client    │
└──────┬──────┘
       │ HTTP / REST API
       │ LcChatReq

┌─────────────────────┐
│ LcChatController   │
│  (接收请求)         │
└──────┬──────────────┘

       │ 转发请求

┌─────────────────────┐
│   ChatService      │
│  (业务逻辑)        │
│  - 参数验证        │
│  - 权限检查        │
│  - 敏感词过滤      │
└──────┬──────────────┘

       │ LcChatReq

┌─────────────────────┐
│  LcChatService     │
│  (核心服务)        │
└──────┬──────────────┘

       ├────────────────────────────────┐
       │                              │
       ▼                              ▼
┌──────────────┐           ┌───────────────┐
│ContextBuilder│           │ModelFactory   │
│(构建上下文)  │           │(获取模型)      │
└──────┬───────┘           └──────┬────────┘
       │                           │
       └───────────┬───────────────┘

         ┌──────────────────┐
         │AiServiceBuilder  │
         │(组装AI Service) │
         └────────┬────────┘


         ┌──────────────────┐
         │ LangChain4j     │
         │   Agent         │
         └────────┬────────┘


         ┌──────────────────┐
         │ TokenStream     │
         │ (流式响应)      │
         └────────┬────────┘

                  │ onPartialThinking
                  │ onComplete
                  │ onError

         ┌──────────────────┐
         │ Client          │
         │ (接收响应)       │
         └─────────────────┘

核心依赖组件

1. ChatContextBuilder

路径: langchat-core/src/main/java/cn/langchat/core/builder/ChatContextBuilder.java 职责: 从请求构建ChatContext 代码:
@Component
public class ChatContextBuilder {
    
    public BaseChatContext build(LcChatReq req) {
        var context = SimpleChatContext.of(req.getModelConfig());
        context.setModelId(req.getModelId());
        context.setUserId(req.getUserId());
        context.setFormat(req.getFormat());
        return context;
    }
}

2. ChatModelFactory

路径: langchat-core/src/main/java/cn/langchat/core/factory/ChatModelFactory.java 职责: 动态创建ChatModel实例 核心方法:
// 获取StreamingChatModel(带chatId绑定listener)
public StreamingChatModel getStreamingModel(
    BaseChatContext context, 
    String chatId
)

// 获取ChatModel(带chatId绑定listener)
public ChatModel getChatModel(
    BaseChatContext context, 
    String chatId
)
支持的模型供应商:
  • OpenAI
  • Ollama
  • Qwen (通义千问)
  • Qianfan (百度千帆)
  • Zhipu (智谱AI)
详细设计: 参见 03-模型工厂架构.md

3. AiServiceBuilder

路径: langchat-core/src/main/java/cn/langchat/core/builder/AiServiceBuilder.java 职责: 构建完整的AI Service 核心方法:
public LangChatAgent build(
    StreamingChatModel model, 
    LcChatReq req, 
    String conversationId
)
构建组件:
  1. ChatMemory - 聊天记忆
  2. SystemMessage - 系统提示
  3. Tools - 动态工具(插件、MCP等)
  4. RetrievalAugmentor - RAG组件
详细设计: 参见 04-AiService构建器架构.md

流式响应处理

TokenStream 回调

tokenStream
    .onPartialThinking(thinking -> {
        // 接收思维过程
        log.debug("Thinking: {}", thinking);
    })
    .onPartialResponse(response -> {
        // 接收部分响应
        log.debug("Response: {}", response);
    })
    .onComplete(answer -> {
        // 接收完整回答
        log.info("Complete: {}", answer);
    })
    .onError(error -> {
        // 错误处理
        log.error("Error", error);
    });

ChatListener 事件监听

路径: langchat-core/src/main/java/cn/langchat/core/observability/ChatListener.java 监听的事件:
  • onRequest - 请求开始
  • onResponse - 接收响应
  • onTokenStreamGenerated - 生成Token流
  • onError - 错误发生
  • onComplete - 请求完成
功能:
  • Token统计和计费
  • 消息记录保存
  • 监控和日志

消息处理

消息构建

public String buildChatMessages(LcChatReq req) {
    var message = "";
    
    // 1. 优先单独的message字段
    if (StrUtil.isNotBlank(req.getMessage())) {
        message = req.getMessage();
    }
    
    // 2. 处理messages列表
    if (StrUtil.isNotBlank(req.getMessage()) 
        && CollUtil.isNotEmpty(req.getMessages())) {
        LcChatMessage userMessage = 
            ChatMessageConverter.getLatestUserMessage(req.getMessages());
        message = userMessage != null ? userMessage.getContent() : "";
    }
    
    // 3. 验证消息是否为空
    if (StrUtil.isBlank(message)) {
        throw new IllegalArgumentException("消息为空");
    }
    
    return message;
}

消息类型转换

ChatMessageConverter:
  • 将前端消息格式转换为LangChain4j消息格式
  • 支持UserMessage, SystemMessage, AssistantMessage等

ChatMemory 管理

LcChatMemory

路径: langchat-core/src/main/java/cn/langchat/core/service/LcChatMemory.java 职责: 基于Redis的ChatMemory实现 功能:
  • 存储历史消息
  • 消息窗口管理
  • 自动过期清理
配置:
return MessageWindowChatMemory.builder()
    .id(conversationId)
    .chatMemoryStore(new LcChatMemory(redisTemplate))
    .maxMessages(maxMessages)
    .build();

异常处理

常见异常类型

  1. IllegalArgumentException - 参数错误
    • 模型ID为空
    • 消息为空
    • chatId为空
  2. BusinessException - 业务错误
    • 模型不存在
    • 权限不足
    • 配额超限
  3. ServiceException - 服务错误
    • AI服务调用失败
    • 网络超时
    • 模型返回错误

异常处理流程

Exception

LcChatService catch

记录日志

ChatListener.onError

Client接收错误

清理ThreadLocal

性能优化

1. 模型实例缓存

ChatModelFactory 使用Caffeine缓存模型实例:
private Cache<String, ChatModel> chatModelCache;
private Cache<String, StreamingChatModel> streamingChatModelCache;
缓存策略:
  • 基于模型配置生成缓存键
  • 懒加载机制
  • 每次请求创建独立的listener

2. ChatMemory 优化

  • 使用Redis存储,支持分布式
  • 消息窗口限制,避免内存溢出
  • 自动过期机制

3. 异步处理

  • 流式响应,降低延迟
  • 非阻塞IO
  • 异步保存消息记录

配置说明

ChatMemory配置

langchat:
  memory:
    max-message: 20  # 历史消息数量
    ttl: 86400      # 过期时间(秒)

模型配置

langchat:
  model:
    timeout: 5  # 超时时间(分钟)

扩展点

1. 自定义ChatListener

继承或实现ChatListener,添加自定义事件处理:
@Component
public class CustomChatListener extends ChatListener {
    
    @Override
    public void onRequest(ChatModelRequestContext context) {
        // 自定义处理
    }
}

2. 自定义ChatMemory

实现ChatMemoryStore接口:
public class CustomChatMemoryStore implements ChatMemoryStore {
    // 自定义实现
}

3. 添加新的聊天模式

在LcChatService中添加新方法:
public TokenStream customChatMode(LcChatReq req) {
    // 自定义逻辑
}

最佳实践

1. 使用正确的聊天方法

  • streamingChat - 需要知识库、RAG的场景
  • standaloneStreamingChat - 独立聊天,不关联知识库
  • simpleChatForText - 获取纯文本,用于结构化数据提取

2. 合理设置ChatMemory

  • 根据应用场景调整maxMessages
  • 过大可能影响性能和成本
  • 过小可能导致上下文丢失

3. 流式响应处理

  • 必须处理所有回调
  • 正确处理错误
  • 及时释放资源

4. 安全考虑

  • 验证所有输入参数
  • 实施敏感词过滤
  • 控制访问频率

参考文档