基于 Spring Boot 3 + LangChain4j 快速构建企业级 AI 应用实战
摘要:本文将手把手教你如何在 Spring Boot 3 项目中集成 LangChain4j,实现智能对话、RAG 知识库检索、Function Calling 等核心能力,并给出完整的生产级代码和架构建议。
一、前言:为什么 Java 开发者需要关注 AI 集成?
2024-2025 年,大模型(LLM)已经从"玩具"变成了"生产工具"。但市面上 90% 的 AI 教程都是 Python 生态,这让广大 Java 开发者望而却步。
好消息是:LangChain4j 的出现彻底改变了这一局面。它是 LangChain 的 Java 版本,专为 JVM 生态设计,提供了:
- 统一的 LLM 接入抽象(OpenAI、通义千问、文心一言、Ollama 本地模型等)
- RAG(检索增强生成)完整链路
- Function Calling(工具调用)
- 内存管理与对话持久化
本文将基于 Spring Boot 3.2 + LangChain4j 0.35 版本,构建一个完整的 AI 客服系统。
二、环境准备
2.1 技术栈选型
| 组件 | 版本 | 说明 |
|---|---|---|
| JDK | 21 | 虚拟线程 + 模式匹配 |
| Spring Boot | 3.2.x | 最新稳定版 |
| LangChain4j | 0.35.0 | Java AI 框架 |
| Ollama | 0.3.x | 本地大模型运行 |
| Redis | 7.x | 向量存储 + 缓存 |
| PostgreSQL | 16 | 业务数据 + pgvector |
2.2 项目初始化
bash
# 使用 Spring Initializr 创建项目
curl https://start.spring.io/starter.zip \
-d dependencies=web,lombok,data-jpa,postgresql,redis \
-d javaVersion=21 \
-d bootVersion=3.2.5 \
-d baseDir=ai-service \
-o ai-service.zip
三、核心依赖配置
3.1 Maven 依赖
xml
<properties>
<langchain4j.version>0.35.0</langchain4j.version>
</properties>
<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- LangChain4j 核心 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- LangChain4j Spring Boot 集成 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-spring-boot-starter</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- OpenAI 适配器(也可替换为通义千问、文心等) -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- 本地模型 Ollama 适配器 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-ollama</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- 向量存储:Redis -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-redis</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- 文档解析 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-document-parser-apache-tika</artifactId>
<version>${langchain4j.version}</version>
</dependency>
</dependencies>
3.2 application.yml 配置
yaml
spring:
application:
name: ai-customer-service
datasource:
url: jdbc:postgresql://localhost:5432/ai_service
username: postgres
password: your_password
data:
redis:
host: localhost
port: 6379
# LangChain4j 配置
langchain4j:
open-ai:
chat-model:
api-key: ${OPENAI_API_KEY:sk-your-key}
model-name: gpt-4o
temperature: 0.7
timeout: PT60S
ollama:
chat-model:
base-url: http://localhost:11434
model-name: qwen2.5:14b
timeout: PT120S
# 自定义配置
ai:
knowledge-base:
enabled: true
chunk-size: 500
chunk-overlap: 50
四、核心架构设计
4.1 整体架构图
┌─────────────────────────────────────────────────────────────┐
│ Spring Boot Application │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ REST API │ │ AI Service │ │ Knowledge Base │ │
│ │ Controller │──│ Layer │──│ Service │ │
│ └──────────────┘ └──────────────┘ └──────────────────┘ │
│ │ │ │ │
│ └─────────────────┴────────────────────┘ │
│ │ │
│ ┌────────────┴────────────┐ │
│ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ LangChain4j │ │ Vector Store │ │
│ │ AI Services │ │ (Redis/PG) │ │
│ │ │ │ │ │
│ │ • ChatMemory │ │ • Embeddings │ │
│ │ • RAG Chain │ │ • Similarity │ │
│ │ • Tools │ │ Search │ │
│ └────────┬────────┘ └─────────────────┘ │
│ │ │
│ ┌────────┴────────┐ │
│ ▼ ▼ │
│ ┌─────────┐ ┌──────────┐ │
│ │ OpenAI │ │ Ollama │ (本地/云端模型切换) │
│ │ GPT-4o │ │ Qwen2.5 │ │
│ └─────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────┘
4.2 领域模型设计
java
package com.example.ai.entity;
import jakarta.persistence.*;
import lombok.Data;
import org.hibernate.annotations.CreationTimestamp;
import java.time.LocalDateTime;
@Data
@Entity
@Table(name = "chat_sessions")
public class ChatSession {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private String id;
@Column(name = "user_id", nullable = false)
private String userId;
@Column(name = "session_title")
private String sessionTitle;
@Column(name = "model_type")
@Enumerated(EnumType.STRING)
private ModelType modelType = ModelType.OPENAI;
@CreationTimestamp
@Column(name = "created_at")
private LocalDateTime createdAt;
public enum ModelType {
OPENAI, OLLAMA, QIANWEN
}
}
@Entity
@Table(name = "knowledge_docs")
@Data
public class KnowledgeDocument {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private String id;
@Column(name = "file_name", nullable = false)
private String fileName;
@Column(name = "content_type")
private String contentType;
@Column(name = "content_text", length = 10000)
private String contentText;
@Column(name = "embedding_status")
@Enumerated(EnumType.STRING)
private EmbeddingStatus status = EmbeddingStatus.PENDING;
@CreationTimestamp
private LocalDateTime uploadedAt;
public enum EmbeddingStatus {
PENDING, PROCESSING, COMPLETED, FAILED
}
}
五、核心功能实现
5.1 AI 服务配置类
java
package com.example.ai.config;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.ollama.OllamaChatModel;
import dev.langchain4j.rag.content.retriever.ContentRetriever;
import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
import dev.langchain4j.store.memory.chat.redis.RedisChatMemoryStore;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.time.Duration;
@Configuration
public class AiConfig {
@Value("${langchain4j.open-ai.chat-model.api-key}")
private String openAiApiKey;
@Value("${langchain4j.ollama.chat-model.base-url}")
private String ollamaBaseUrl;
@Bean
@Primary
public ChatLanguageModel openAiModel() {
return OpenAiChatModel.builder()
.apiKey(openAiApiKey)
.modelName("gpt-4o")
.temperature(0.7)
.timeout(Duration.ofSeconds(60))
.build();
}
@Bean
public ChatLanguageModel localModel() {
return OllamaChatModel.builder()
.baseUrl(ollamaBaseUrl)
.modelName("qwen2.5:14b")
.timeout(Duration.ofSeconds(120))
.build();
}
/**
* Redis 持久化对话记忆
*/
@Bean
public RedisChatMemoryStore chatMemoryStore(StringRedisTemplate redisTemplate) {
return new RedisChatMemoryStore(redisTemplate.getConnectionFactory());
}
/**
* 基于 Redis 的 RAG 内容检索器
*/
@Bean
public ContentRetriever contentRetriever(
EmbeddingStoreContentRetriever embeddingStoreContentRetriever) {
return embeddingStoreContentRetriever;
}
}
5.2 智能对话服务(带历史记忆)
java
package com.example.ai.service;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.rag.content.retriever.ContentRetriever;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
import dev.langchain4j.store.memory.chat.ChatMemoryStore;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Slf4j
@Service
@RequiredArgsConstructor
public class ChatService {
private final ChatLanguageModel chatModel;
private final ChatMemoryStore memoryStore;
private final ContentRetriever contentRetriever;
// 内存缓存会话级别的 AI Service 实例
private final Map<String, CustomerSupportAgent> agentCache = new ConcurrentHashMap<>();
/**
* 定义 AI 客服代理接口
*/
public interface CustomerSupportAgent {
@SystemMessage("""
你是一位专业的智能客服助手,名为"小智"。请遵循以下规则:
1. 使用中文回答用户问题,语气友好专业
2. 如果用户询问的是产品技术问题,优先使用知识库内容回答
3. 如果知识库中没有相关信息,坦诚告知并建议转人工客服
4. 对于敏感操作(如退款、修改订单),必须要求用户确认身份信息
5. 每次回复控制在 300 字以内,重点突出
当前时间:{{current_time}}
用户等级:{{user_level}}
""")
String chat(@UserMessage String userMessage,
@V("current_time") String currentTime,
@V("user_level") String userLevel);
}
/**
* 执行对话
*/
public ChatResponse chat(String sessionId, String userId, String message) {
// 获取或创建带记忆的 AI Agent
CustomerSupportAgent agent = agentCache.computeIfAbsent(sessionId, sid -> {
ChatMemory chatMemory = MessageWindowChatMemory.builder()
.id(sid)
.maxMessages(20) // 保留最近 20 轮对话
.chatMemoryStore(memoryStore)
.build();
return AiServices.builder(CustomerSupportAgent.class)
.chatLanguageModel(chatModel)
.chatMemory(chatMemory)
.contentRetriever(contentRetriever) // 接入 RAG
.build();
});
String currentTime = java.time.LocalDateTime.now()
.format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
// 调用 AI(自动处理记忆、RAG 检索)
String response = agent.chat(message, currentTime, "VIP");
log.info("Session[{}] User: {} | AI: {}", sessionId,
message.substring(0, Math.min(50, message.length())),
response.substring(0, Math.min(100, response.length())));
return new ChatResponse(response, sessionId, false);
}
/**
* 清除会话记忆
*/
public void clearSession(String sessionId) {
agentCache.remove(sessionId);
memoryStore.deleteMessages(sessionId);
}
public record ChatResponse(String content, String sessionId, boolean escalated) {}
}
5.3 RAG 知识库服务(文档上传与检索)
java
package com.example.ai.service;
import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.DocumentParser;
import dev.langchain4j.data.document.DocumentSplitter;
import dev.langchain4j.data.document.parser.apache.tika.ApacheTikaDocumentParser;
import dev.langchain4j.data.document.splitter.DocumentSplitters;
import dev.langchain4j.data.embedding.Embedding;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.EmbeddingStoreIngestor;
import com.example.ai.entity.KnowledgeDocument;
import com.example.ai.repository.KnowledgeDocRepository;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayInputStream;
import java.util.List;
@Slf4j
@Service
@RequiredArgsConstructor
public class KnowledgeBaseService {
private final EmbeddingStore<TextSegment> embeddingStore;
private final EmbeddingModel embeddingModel;
private final KnowledgeDocRepository docRepository;
/**
* 上传文档并构建向量索引
*/
@SneakyThrows
public String ingestDocument(MultipartFile file) {
String docId = java.util.UUID.randomUUID().toString();
// 1. 保存文档元数据
KnowledgeDocument doc = new KnowledgeDocument();
doc.setId(docId);
doc.setFileName(file.getOriginalFilename());
doc.setContentType(file.getContentType());
doc.setStatus(KnowledgeDocument.EmbeddingStatus.PROCESSING);
docRepository.save(doc);
// 2. 异步处理文档向量化(生产环境建议用消息队列)
new Thread(() -> processDocument(docId, file)).start();
return docId;
}
@SneakyThrows
private void processDocument(String docId, MultipartFile file) {
try {
// 解析文档(支持 PDF、Word、TXT、Markdown 等)
DocumentParser parser = new ApacheTikaDocumentParser();
Document document = parser.parse(new ByteArrayInputStream(file.getBytes()));
document.metadata().add("doc_id", docId);
document.metadata().add("file_name", file.getOriginalFilename());
// 文档分块策略:按 500 token 分块,重叠 50 token
DocumentSplitter splitter = DocumentSplitters.recursive(
500, // max chunk size
50, // overlap
new dev.langchain4j.model.openai.OpenAiTokenizer("gpt-4o")
);
// 构建 Ingestor 并执行向量化存储
EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder()
.documentSplitter(splitter)
.embeddingModel(embeddingModel)
.embeddingStore(embeddingStore)
.build();
ingestor.ingest(document);
// 更新状态
updateStatus(docId, KnowledgeDocument.EmbeddingStatus.COMPLETED);
log.info("文档 [{}] 向量化完成,共处理 {} 个片段",
file.getOriginalFilename(), document.text().length());
} catch (Exception e) {
log.error("文档向量化失败: {}", e.getMessage(), e);
updateStatus(docId, KnowledgeDocument.EmbeddingStatus.FAILED);
}
}
private void updateStatus(String docId, KnowledgeDocument.EmbeddingStatus status) {
docRepository.findById(docId).ifPresent(doc -> {
doc.setStatus(status);
docRepository.save(doc);
});
}
/**
* 相似度搜索(调试用)
*/
public List<String> searchSimilar(String query, int maxResults) {
Embedding queryEmbedding = embeddingModel.embed(query).content();
return embeddingStore.findRelevant(queryEmbedding, maxResults)
.stream()
.map(match -> match.embedded().text())
.toList();
}
}
5.4 Function Calling(工具调用)实战
java
package com.example.ai.tools;
import dev.langchain4j.agent.tool.Tool;
import dev.langchain4j.agent.tool.ToolMemoryId;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
/**
* AI 可调用的业务工具类
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class CustomerServiceTools {
private final OrderRepository orderRepository;
private final UserRepository userRepository;
/**
* 查询订单信息
* AI 在对话中识别到用户想查订单时,会自动调用此方法
*/
@Tool("查询用户的订单信息,支持按订单号或日期范围查询")
public List<OrderInfo> queryOrders(
@ToolMemoryId String sessionId, // 自动注入会话ID
@dev.langchain4j.agent.tool.P("用户ID") String userId,
@dev.langchain4j.agent.tool.P("订单号,可选") String orderNo,
@dev.langchain4j.agent.tool.P("开始日期,格式 yyyy-MM-dd") String startDate,
@dev.langchain4j.agent.tool.P("结束日期,格式 yyyy-MM-dd") String endDate) {
log.info("[Session {}] AI 调用 queryOrders: userId={}, orderNo={}",
sessionId, userId, orderNo);
// 实际业务查询逻辑
return orderRepository.findByUserIdAndConditions(
userId, orderNo,
startDate != null ? LocalDate.parse(startDate) : null,
endDate != null ? LocalDate.parse(endDate) : null
);
}
/**
* 申请退款
*/
@Tool("为用户申请订单退款,需要验证订单状态是否符合退款条件")
public RefundResult applyRefund(
@dev.langchain4j.agent.tool.P("订单号") String orderNo,
@dev.langchain4j.agent.tool.P("退款原因") String reason,
@dev.langchain4j.agent.tool.P("退款金额") BigDecimal amount) {
// 业务校验:订单是否存在、是否已发货、是否在退款期内等
Order order = orderRepository.findByOrderNo(orderNo)
.orElseThrow(() -> new RuntimeException("订单不存在"));
if (!order.canRefund()) {
return new RefundResult(false, "该订单不符合退款条件:" + order.getStatus().getDesc());
}
// 执行退款逻辑...
return new RefundResult(true, "退款申请已提交,预计 3-5 个工作日到账");
}
/**
* 查询物流信息
*/
@Tool("查询订单的物流跟踪信息")
public LogisticsInfo queryLogistics(
@dev.langchain4j.agent.tool.P("订单号") String orderNo) {
// 调用第三方物流接口...
return new LogisticsInfo("顺丰速运", "SF1234567890",
List.of(
new TrackNode("2024-05-01 10:30", "深圳市", "已揽收"),
new TrackNode("2024-05-01 18:00", "深圳市", "运输中"),
new TrackNode("2024-05-02 08:00", "北京市", "派送中")
));
}
// 数据记录定义
public record OrderInfo(String orderNo, LocalDate createDate,
String status, BigDecimal amount, List<String> items) {}
public record RefundResult(boolean success, String message) {}
public record LogisticsInfo(String carrier, String trackingNo, List<TrackNode> tracks) {}
public record TrackNode(String time, String location, String status) {}
}
5.5 在 AI Service 中注册工具
java
// 修改 ChatService 中的 Agent 构建逻辑
CustomerSupportAgent agent = AiServices.builder(CustomerSupportAgent.class)
.chatLanguageModel(chatModel)
.chatMemory(chatMemory)
.contentRetriever(contentRetriever)
.tools(customerServiceTools) // 注册工具!AI 会自动决策调用
.build();
六、REST API 层
java
package com.example.ai.controller;
import com.example.ai.service.ChatService;
import com.example.ai.service.KnowledgeBaseService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import reactor.core.publisher.Flux;
@RestController
@RequestMapping("/api/v1/ai")
@RequiredArgsConstructor
public class AiController {
private final ChatService chatService;
private final KnowledgeBaseService kbService;
/**
* 普通对话(同步)
*/
@PostMapping("/chat")
public ResponseEntity<ChatService.ChatResponse> chat(
@RequestBody ChatRequest request) {
String sessionId = request.sessionId() != null ?
request.sessionId() : java.util.UUID.randomUUID().toString();
var response = chatService.chat(sessionId, request.userId(), request.message());
return ResponseEntity.ok(response);
}
/**
* 流式对话(SSE)
*/
@PostMapping(value = "/chat/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> chatStream(@RequestBody ChatRequest request) {
// 使用 LangChain4j 的 StreamingChatLanguageModel 实现
// 代码略,原理相同,返回 Flux<String>
return Flux.empty();
}
/**
* 上传知识库文档
*/
@PostMapping("/knowledge/upload")
public ResponseEntity<String> uploadKnowledge(
@RequestParam("file") MultipartFile file) {
String docId = kbService.ingestDocument(file);
return ResponseEntity.accepted().body("文档处理中,ID: " + docId);
}
/**
* 查询知识库状态
*/
@GetMapping("/knowledge/{docId}/status")
public ResponseEntity<?> getDocStatus(@PathVariable String docId) {
// 返回处理状态
return ResponseEntity.ok().build();
}
/**
* 清除会话
*/
@DeleteMapping("/session/{sessionId}")
public ResponseEntity<Void> clearSession(@PathVariable String sessionId) {
chatService.clearSession(sessionId);
return ResponseEntity.noContent().build();
}
public record ChatRequest(String sessionId, String userId, String message) {}
}
七、生产环境优化建议
7.1 性能优化
| 优化点 | 方案 | 效果 |
|---|---|---|
| 首次加载慢 | Ollama 模型预加载 + Keep-Alive | 减少 5-10s 等待 |
| 向量检索慢 | Redis 分片 + HNSW 索引 | 毫秒级响应 |
| 高并发 | 虚拟线程(JDK 21)+ 连接池 | 支撑万级并发 |
| Token 消耗 | 对话摘要压缩(SummaryMemory) | 降低 60% Token |
7.2 安全与监控
java
/**
* AI 输入输出过滤器示例
*/
@Component
public class AiSafetyFilter {
private static final List<String> BLOCKED_KEYWORDS = List.of(
"密码", "身份证号", "银行卡", "验证码"
);
public String sanitizeInput(String input) {
// 1. 敏感信息脱敏
// 2. Prompt 注入检测
// 3. 输入长度限制
return input;
}
public boolean validateOutput(String output) {
// 1. 检查是否泄露系统 Prompt
// 2. 内容安全审核
return true;
}
}
7.3 多模型路由策略
java
@Service
public class ModelRouter {
public ChatLanguageModel route(AiTaskType taskType) {
return switch (taskType) {
case SIMPLE_QA -> localModel; // 简单问答用本地模型
case COMPLEX_REASONING -> openAiModel; // 复杂推理用 GPT-4o
case CODE_GENERATION -> codeModel; // 代码专用模型
case SUMMARIZATION -> localModel; // 摘要本地处理
};
}
}
八、完整项目结构
ai-customer-service/
├── src/main/java/com/example/ai/
│ ├── AiApplication.java
│ ├── config/
│ │ ├── AiConfig.java # AI 模型配置
│ │ ├── RedisConfig.java # Redis 向量存储配置
│ │ └── SecurityConfig.java # 安全配置
│ ├── controller/
│ │ └── AiController.java # REST API
│ ├── service/
│ │ ├── ChatService.java # 对话服务
│ │ ├── KnowledgeBaseService.java # RAG 服务
│ │ └── ModelRouter.java # 模型路由
│ ├── tools/
│ │ └── CustomerServiceTools.java # AI 工具
│ ├── entity/
│ │ ├── ChatSession.java
│ │ └── KnowledgeDocument.java
│ └── repository/
│ └── KnowledgeDocRepository.java
├── src/main/resources/
│ ├── application.yml
│ └── prompts/
│ └── system_prompt.txt # 可外部化的 Prompt
├── docker-compose.yml # 一键启动依赖
└── README.md
九、总结与展望
本文完整演示了如何在 Spring Boot 3 中集成 LangChain4j,实现了:
✅ 多模型支持 :OpenAI / Ollama 本地模型无缝切换
✅ 对话记忆 :Redis 持久化,支持长期上下文
✅ RAG 检索 :文档上传 → 分块 → 向量化 → 语义检索
✅ Function Calling :AI 自主调用业务工具
✅ 生产级设计:异步处理、安全过滤、模型路由
下一步可以探索:
- Multi-Agent 架构 :用 LangChain4j 的
AgentExecutor实现多智能体协作 - MCP 协议集成:接入 Model Context Protocol 生态
- A2A 协议:实现 Agent 之间的标准化通信
- 本地知识库:结合 DeepSeek + Ollama 实现完全离线部署
🔗 产品体验入口:https://www.ipdatacloud.com/
📖 API文档参考:https://www.ipdatacloud.com/doc/
🔗 产品体验入口:https://www.ipdatacloud.com/
📖 API文档参考:https://www.ipdatacloud.com/doc/## 参考资源
📌 GitHub 源码 :
https://github.com/yourname/ai-customer-service(示例链接)💬 讨论区:欢迎在评论区交流生产环境踩坑经验!