news 2026/4/18 11:53:29

DeepChat与Java SpringBoot集成指南:企业级对话系统开发

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
DeepChat与Java SpringBoot集成指南:企业级对话系统开发

DeepChat与Java SpringBoot集成指南:企业级对话系统开发

1. 为什么需要将DeepChat集成到SpringBoot项目中

很多开发者第一次接触DeepChat时,会被它简洁的桌面界面和多模型切换能力吸引。但当真正要落地到金融、医疗这类对数据安全和系统稳定性要求极高的行业时,单纯使用桌面客户端就显得力不从心了。

我曾经参与过一个银行智能客服系统的改造项目,客户明确提出了几个核心需求:所有对话数据必须留在内网、需要对接现有的OAuth2统一认证体系、不同业务部门要隔离会话数据、系统要能支撑每秒上百次的并发请求。这时候,把DeepChat作为后端服务引擎嵌入到已有的SpringBoot技术栈中,就成了最务实的选择。

DeepChat本身是一个功能完备的AI对话平台,但它提供的REST API和深度链接机制,让开发者可以把它当作一个"智能对话中间件"来使用。通过SpringBoot的灵活架构,我们既能保留DeepChat强大的多模型调度、上下文管理能力,又能无缝融入企业现有的安全体系、监控体系和运维流程。

这种集成方式不是简单地调用一个API,而是让DeepChat成为你整个应用生态中的一个智能组件——就像数据库连接池或消息队列那样自然,却又比它们更懂如何理解用户意图。

2. 环境准备与基础架构设计

2.1 技术选型与版本确认

在开始编码之前,先确认几个关键版本的兼容性。根据DeepChat官方文档和实际测试,推荐使用以下组合:

  • DeepChat服务端:v0.5.5及以上版本(支持完整的REST API和MCP协议)
  • SpringBoot:2.7.x或3.1.x(本文以3.1.12为例,兼顾新特性和企业稳定性需求)
  • Java:17或21(LTS版本,避免使用预览特性)
  • 构建工具:Maven 3.8.6+

特别注意,DeepChat的API设计遵循RESTful原则,但它的鉴权机制和会话管理有自己的一套逻辑,不能直接套用Spring Security的默认配置。我们需要做的是"适配"而非"覆盖"。

2.2 项目结构规划

一个健康的集成项目应该清晰分离关注点。我建议采用这样的包结构:

com.example.deepchat ├── config/ # DeepChat相关配置类 ├── client/ # REST客户端封装 ├── service/ # 业务逻辑层 ├── dto/ # 数据传输对象 ├── exception/ # 自定义异常 ├── controller/ # Web控制器 └── model/ # 领域模型

这种结构的好处是,当未来需要替换为其他AI引擎(比如本地部署的Ollama)时,只需要修改client/包下的实现,上层业务代码几乎不需要改动。

2.3 Maven依赖配置

pom.xml中添加必要的依赖:

<dependencies> <!-- Spring Boot Web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Spring Security --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <!-- HTTP客户端 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <!-- JSON处理 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <!-- Lombok简化代码 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies>

这里没有引入任何DeepChat官方SDK,因为我们采用原生HTTP调用方式,这样更可控,也避免了SDK版本升级带来的兼容性问题。

3. REST API对接实现

3.1 DeepChat服务端启动与配置

DeepChat服务端可以通过Docker快速启动,这是企业环境中最推荐的方式:

# 拉取镜像 docker pull ghcr.io/thinkinaixyz/deepchat:latest # 启动服务(生产环境建议使用compose文件) docker run -d \ --name deepchat-server \ -p 8080:3000 \ -v /path/to/config:/app/config \ -v /path/to/models:/app/models \ --restart=unless-stopped \ ghcr.io/thinkinaixyz/deepchat:latest

关键配置项需要在config.yaml中设置:

server: port: 3000 host: 0.0.0.0 cors: allowedOrigins: ["*"] # 生产环境请限制为具体域名 allowCredentials: true auth: enabled: true jwtSecret: "your-super-secret-key-change-in-production" tokenExpiry: "24h" models: default: "deepseek-chat" available: - name: "deepseek-chat" provider: "deepseek" apiKey: "${DEEPSEEK_API_KEY}" - name: "gpt-4o" provider: "openai" apiKey: "${OPENAI_API_KEY}"

启动后,你可以通过http://localhost:8080/api/v1/health验证服务状态。

3.2 SpringBoot客户端封装

创建一个类型安全的REST客户端,避免到处写字符串URL和JSON解析:

@Configuration public class DeepChatClientConfig { @Value("${deepchat.api.url:http://localhost:8080}") private String apiUrl; @Bean public WebClient deepChatWebClient() { return WebClient.builder() .baseUrl(apiUrl) .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(10 * 1024 * 1024)) .build(); } }

然后创建核心的对话服务接口:

@Service @Slf4j public class DeepChatService { private final WebClient webClient; private final ObjectMapper objectMapper; public DeepChatService(WebClient webClient, ObjectMapper objectMapper) { this.webClient = webClient; this.objectMapper = objectMapper; } /** * 创建新的对话会话 * @param userId 用户唯一标识 * @param model 模型名称,如 "deepseek-chat" * @return 会话ID */ public Mono<String> createSession(String userId, String model) { return webClient.post() .uri("/api/v1/sessions") .bodyValue(Map.of( "userId", userId, "model", model, "metadata", Map.of("source", "springboot-integration") )) .retrieve() .bodyToMono(Map.class) .map(response -> (String) response.get("sessionId")) .doOnError(error -> log.error("创建会话失败: {}", error.getMessage())); } /** * 发送消息并获取响应 * @param sessionId 会话ID * @param message 用户消息 * @return 响应内容 */ public Mono<String> sendMessage(String sessionId, String message) { return webClient.post() .uri("/api/v1/sessions/{sessionId}/messages", sessionId) .bodyValue(Map.of("content", message)) .retrieve() .bodyToMono(Map.class) .map(response -> (String) response.get("content")) .doOnError(error -> log.error("发送消息失败 [{}]: {}", sessionId, error.getMessage())); } }

这个封装的关键在于:它把DeepChat的API细节完全隐藏起来,上层业务代码只需要关心"创建会话"和"发送消息"这两个业务概念。

3.3 多模型动态路由

企业级应用往往需要根据不同场景选择不同模型。比如金融客服需要严谨准确,适合DeepSeek;营销文案需要创意丰富,适合GPT-4o。我们可以设计一个简单的策略模式:

@Component public class ModelRouter { // 从配置中心或数据库读取路由规则 private final Map<String, String> routingRules = Map.of( "finance.*", "deepseek-chat", "marketing.*", "gpt-4o", "support.*", "qwen2-72b" ); public String getTargetModel(String context) { return routingRules.entrySet().stream() .filter(entry -> context.matches(entry.getKey())) .map(Map.Entry::getValue) .findFirst() .orElse("deepseek-chat"); } } // 在服务中使用 public Mono<String> smartSendMessage(String userId, String context, String message) { String model = modelRouter.getTargetModel(context); return deepChatService.createSession(userId, model) .flatMap(sessionId -> deepChatService.sendMessage(sessionId, message)); }

这种方式让模型选择变得可配置、可扩展,不需要修改代码就能调整业务规则。

4. OAuth2鉴权体系集成

4.1 理解DeepChat的鉴权模型

DeepChat本身支持JWT鉴权,但企业通常已有成熟的OAuth2体系。我们的目标不是让DeepChat去对接企业的OAuth2,而是让SpringBoot应用作为OAuth2客户端,代表用户向DeepChat发起受信请求。

DeepChat的鉴权流程是:

  1. 用户登录SpringBoot应用(通过企业SSO)
  2. SpringBoot应用获取用户的访问令牌(Access Token)
  3. SpringBoot应用在调用DeepChat API时,将此令牌作为Bearer Token传递
  4. DeepChat验证令牌有效性,并提取用户信息用于会话隔离

4.2 Spring Security配置

@Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(authz -> authz .requestMatchers("/api/public/**").permitAll() .requestMatchers("/api/chat/**").authenticated() .anyRequest().authenticated() ) .oauth2Login(oauth2 -> oauth2 .authorizationEndpoint(authorization -> authorization .baseUri("/oauth2/authorize")) .redirectionEndpoint(redirection -> redirection .baseUri("/login/oauth2/code/*")) .userInfoEndpoint(userInfo -> userInfo .userService(customOAuth2UserService())) ) .sessionManagement(session -> session .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)); return http.build(); } @Bean public OAuth2UserService<OAuth2UserRequest, OAuth2User> customOAuth2UserService() { DefaultOAuth2UserService delegate = new DefaultOAuth2UserService(); return userRequest -> { OAuth2User oAuth2User = delegate.loadUser(userRequest); // 从企业OAuth2提供者获取用户信息 String userId = extractUserId(oAuth2User); String userName = extractUserName(oAuth2User); // 创建自定义用户详情 return new CustomOAuth2User(oAuth2User.getAttributes(), userId, userName); }; } }

4.3 令牌透传与会话绑定

关键是要在每次调用DeepChat API时,把用户的OAuth2令牌安全地传递过去:

@Service public class SecureDeepChatService { private final WebClient webClient; private final ReactiveOAuth2AuthorizedClientService authorizedClientService; public SecureDeepChatService(WebClient webClient, ReactiveOAuth2AuthorizedClientService authorizedClientService) { this.webClient = webClient; this.authorizedClientService = authorizedClientService; } public Mono<String> secureSendMessage(ServerWebExchange exchange, String sessionId, String message) { // 从当前请求中提取OAuth2令牌 return exchange.getPrincipal() .cast(OAuth2AuthenticationToken.class) .flatMap(token -> authorizedClientService.loadAuthorizedClient( token.getAuthorizedClientRegistrationId(), token.getName())) .map(client -> client.getAccessToken().getTokenValue()) .flatMap(accessToken -> webClient.post() .uri("/api/v1/sessions/{sessionId}/messages", sessionId) .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) .bodyValue(Map.of("content", message)) .retrieve() .bodyToMono(Map.class) .map(response -> (String) response.get("content"))); } }

这样,DeepChat就能通过令牌识别出真实的用户身份,为后续的多租户会话管理打下基础。

5. 多租户会话管理实现

5.1 企业级会话隔离需求分析

在金融、医疗等行业,会话隔离不是可选项,而是强制要求:

  • 不同客户的对话数据必须物理隔离
  • 同一客户的不同业务线(如信用卡、贷款)需要逻辑隔离
  • 会话数据需要满足GDPR等合规要求,支持按需删除

DeepChat原生支持会话ID,但默认是全局唯一的。我们需要在此基础上增加租户维度。

5.2 租户标识注入策略

最优雅的方式是在HTTP头中注入租户信息,让DeepChat服务端自动识别:

@Component public class TenantWebClientCustomizer implements WebClientCustomizer { @Override public void customize(WebClient.Builder builder) { builder.filter((request, next) -> { ServerWebExchange exchange = (ServerWebExchange) request.attribute("exchange").get(); // 从请求头或JWT中提取租户ID String tenantId = extractTenantId(exchange); ClientRequest filteredRequest = ClientRequest.from(request) .header("X-Tenant-ID", tenantId) .header("X-Request-ID", generateRequestId()) .build(); return next.exchange(filteredRequest); }); } private String extractTenantId(ServerWebExchange exchange) { // 优先从请求头获取 String headerTenant = exchange.getRequest().getHeaders() .getFirst("X-Tenant-ID"); if (StringUtils.hasText(headerTenant)) { return headerTenant; } // 其次从JWT claims中提取 return Optional.ofNullable(exchange.getPrincipal()) .filter(p -> p instanceof OAuth2AuthenticationToken) .map(p -> (OAuth2AuthenticationToken) p) .map(token -> token.getPrincipal().getAttributes()) .map(attrs -> (String) attrs.get("tenant_id")) .orElse("default"); } }

5.3 会话生命周期管理

创建一个会话管理器,负责会话的创建、续期和清理:

@Component public class SessionManager { private final RedisTemplate<String, Object> redisTemplate; private final DeepChatService deepChatService; public SessionManager(RedisTemplate<String, Object> redisTemplate, DeepChatService deepChatService) { this.redisTemplate = redisTemplate; this.deepChatService = deepChatService; } /** * 创建租户会话 */ public Mono<String> createTenantSession(String tenantId, String userId, String model) { String sessionId = UUID.randomUUID().toString(); String sessionKey = "session:" + tenantId + ":" + sessionId; return deepChatService.createSession(userId, model) .flatMap(deepChatSessionId -> { // 存储会话映射关系 Map<String, Object> sessionData = Map.of( "deepChatSessionId", deepChatSessionId, "createdAt", System.currentTimeMillis(), "lastActive", System.currentTimeMillis(), "userId", userId, "tenantId", tenantId, "model", model ); redisTemplate.opsForHash().putAll(sessionKey, sessionData); redisTemplate.expire(sessionKey, Duration.ofHours(24)); return Mono.just(sessionId); }); } /** * 获取会话详情(带租户隔离) */ public Mono<Map<Object, Object>> getSession(String tenantId, String sessionId) { String sessionKey = "session:" + tenantId + ":" + sessionId; return Mono.fromCallable(() -> redisTemplate.opsForHash().entries(sessionKey)) .onErrorResume(e -> { log.warn("会话不存在或已过期: {}-{}", tenantId, sessionId); return Mono.empty(); }); } /** * 清理会话(GDPR合规) */ public Mono<Void> deleteSession(String tenantId, String sessionId) { String sessionKey = "session:" + tenantId + ":" + sessionId; return Mono.fromRunnable(() -> { redisTemplate.delete(sessionKey); // 同时通知DeepChat服务端清理对应会话 deepChatService.deleteSession(sessionId).block(); }); } }

Redis在这里扮演了"会话目录"的角色,而DeepChat服务端只负责"会话执行",职责分离得很清楚。

6. 性能优化与生产实践

6.1 连接池与超时配置

DeepChat API调用的性能瓶颈往往不在AI模型本身,而在网络IO。需要精细配置WebClient:

@Bean public WebClient deepChatWebClient() { ConnectionProvider provider = ConnectionProvider.builder("deepchat-pool") .maxConnections(500) // 最大连接数 .pendingAcquireMaxCount(-1) // 无限制等待 .pendingAcquireTimeout(Duration.ofSeconds(30)) .maxIdleTime(Duration.ofMinutes(5)) .maxLifeTime(Duration.ofMinutes(10)) .build(); HttpClient httpClient = HttpClient.create(provider) .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000) .responseTimeout(Duration.ofSeconds(60)) .doOnConnected(conn -> conn .addHandlerLast(new ReadTimeoutHandler(30)) .addHandlerLast(new WriteTimeoutHandler(30))); return WebClient.builder() .clientConnector(new ReactorClientHttpConnector(httpClient)) .build(); }

这些参数需要根据实际压测结果调整,但基本原则是:连接池大小应该略大于预期并发量,超时时间要给AI推理留足空间。

6.2 响应流式处理

对于长文本生成场景,用户不希望等到整个响应完成才看到内容。DeepChat支持SSE(Server-Sent Events),我们可以利用Spring WebFlux的流式能力:

@GetMapping(value = "/api/chat/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux<ServerSentEvent<String>> streamResponse( @RequestParam String sessionId, @RequestParam String message) { return webClient.post() .uri("/api/v1/sessions/{sessionId}/messages/stream", sessionId) .bodyValue(Map.of("content", message)) .retrieve() .bodyToFlux(String.class) .map(content -> ServerSentEvent.<String>builder() .data(content) .build()) .onErrorResume(error -> { log.error("流式响应错误", error); return Flux.just(ServerSentEvent.<String>builder() .event("error") .data("处理失败: " + error.getMessage()) .build()); }); }

前端JavaScript可以这样消费:

const eventSource = new EventSource('/api/chat/stream?sessionId=xxx&message=hello'); eventSource.onmessage = (event) => { document.getElementById('response').innerHTML += event.data; };

6.3 监控与可观测性

在生产环境中,必须为AI调用添加完善的监控:

@Component public class DeepChatMetrics { private final MeterRegistry meterRegistry; public DeepChatMetrics(MeterRegistry meterRegistry) { this.meterRegistry = meterRegistry; } public Timer.Sample startTimer(String operation) { return Timer.start(meterRegistry); } public void recordSuccess(Timer.Sample sample, String operation, String model) { sample.stop(Timer.builder("deepchat.api.call") .tag("operation", operation) .tag("model", model) .tag("status", "success") .register(meterRegistry)); } public void recordFailure(Timer.Sample sample, String operation, String error) { sample.stop(Timer.builder("deepchat.api.call") .tag("operation", operation) .tag("error", error) .tag("status", "failure") .register(meterRegistry)); } } // 在服务中使用 public Mono<String> monitoredSendMessage(String sessionId, String message) { Timer.Sample sample = deepChatMetrics.startTimer("send-message"); return deepChatService.sendMessage(sessionId, message) .doOnSuccess(response -> deepChatMetrics.recordSuccess(sample, "send-message", "deepseek-chat")) .doOnError(error -> deepChatMetrics.recordFailure(sample, "send-message", error.getClass().getSimpleName())); }

配合Prometheus和Grafana,你可以实时看到每个模型的P95延迟、错误率、QPS等关键指标。

7. 实际应用场景演示

7.1 金融行业智能投顾对话

让我们看一个具体的业务场景:银行APP中的智能投顾功能。用户问"我想为孩子教育储备资金,有什么建议?",系统需要:

  1. 识别用户风险偏好(从用户画像中获取)
  2. 调用合适的模型生成专业建议
  3. 在回复中嵌入合规免责声明
@RestController @RequestMapping("/api/investment") public class InvestmentAdvisorController { @PostMapping("/advice") public Mono<ResponseEntity<Map<String, Object>>> getInvestmentAdvice( @RequestBody InvestmentRequest request, @AuthenticationPrincipal CustomOAuth2User user) { return Mono.just(user) .flatMap(u -> userService.getUserProfile(u.getUserId())) .flatMap(profile -> { // 根据用户风险等级选择模型 String model = profile.getRiskLevel().equals("conservative") ? "deepseek-finance" : "gpt-4o-finance"; String prompt = buildInvestmentPrompt(request, profile); return deepChatService.sendMessage( request.getSessionId(), prompt) .map(response -> { Map<String, Object> result = new HashMap<>(); result.put("advice", response); result.put("disclaimer", "本建议仅供参考,不构成投资建议..."); result.put("timestamp", Instant.now()); return ResponseEntity.ok(result); }); }); } private String buildInvestmentPrompt(InvestmentRequest request, UserProfile profile) { return String.format( "你是一位资深金融顾问,正在为一位%s岁的%s投资者提供建议。" + "用户的目标是为孩子教育储备资金,期望年化收益率%s%%," + "可接受的最大回撤为%s%%。请给出3个具体的投资方案," + "每个方案包含产品类型、预期收益、风险等级和持有期限。", profile.getAge(), profile.getRiskLevel(), request.getExpectedReturn(), request.getMaxDrawdown() ); } }

这个例子展示了如何将DeepChat的能力与业务逻辑深度结合,而不是简单地做一个"AI代理"。

7.2 医疗健康问答系统

另一个典型场景是医疗健康领域的问答系统。这里的关键挑战是准确性保障和合规性:

@Service public class MedicalQaService { private final List<String> medicalKeywords = Arrays.asList( "症状", "疾病", "药物", "检查", "治疗", "诊断" ); public Mono<String> getMedicalAnswer(String question) { // 先进行关键词过滤 if (medicalKeywords.stream() .anyMatch(keyword -> question.contains(keyword))) { // 添加医疗领域约束 String constrainedQuestion = String.format( "你是一名持证医师,请基于最新临床指南回答以下问题:" + "【%s】\n\n" + "回答要求:\n" + "1. 只提供医学事实,不给出个人意见\n" + "2. 如果问题超出你的知识范围,请明确说明\n" + "3. 所有建议必须标注参考来源(如:《内科学》第9版)", question ); return deepChatService.sendMessage("medical-session", constrainedQuestion) .map(this::addMedicalDisclaimer); } return deepChatService.sendMessage("general-session", question); } private String addMedicalDisclaimer(String response) { return response + "\n\n 重要提示:本回答仅供参考,不能替代专业医疗建议。" + "如有健康问题,请及时咨询执业医师。"; } }

这种"领域约束+免责声明"的模式,既发挥了AI的效率优势,又守住了医疗行业的合规底线。

8. 常见问题与解决方案

在实际集成过程中,我们遇到了一些典型问题,分享出来供大家参考:

问题1:会话上下文丢失现象:用户连续提问时,DeepChat似乎"忘记"了之前的对话。 原因:SpringBoot每次请求都是无状态的,而DeepChat的会话ID需要在客户端维护。 解决方案:在前端使用HTTP-only Cookie存储会话ID,后端在每次请求时读取并透传。

问题2:模型切换延迟高现象:从DeepSeek切换到GPT-4o需要10秒以上。 原因:DeepChat首次加载模型需要下载权重文件。 解决方案:在服务启动时预热常用模型,通过API调用/api/v1/models/{model}/warmup

问题3:中文分词效果不佳现象:处理中文长文本时,生成内容出现断句错误。 原因:DeepChat默认使用英文分词器。 解决方案:在请求体中添加{"tokenizer": "jieba"}参数,或在配置中指定中文分词器。

问题4:大文件上传失败现象:用户上传PDF文件进行分析时,返回413错误。 原因:Nginx或SpringBoot默认请求体大小限制为1MB。 解决方案:在application.yml中增加:

spring: servlet: context-path: /api web: resources: static-locations: classpath:/static/ servlet: max-http-header-size: 65536 webflux: max-http-header-size: 65536

问题5:OAuth2令牌过期导致调用失败现象:用户长时间未操作后,再次提问时报401错误。 解决方案:实现令牌自动刷新机制,在WebClient Filter中捕获401响应,自动调用refresh_token接口获取新令牌。

这些问题的解决过程,实际上就是把DeepChat从一个"玩具"变成"生产级组件"的必经之路。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 2:24:26

MusePublic进阶调参指南:CFG Scale与Steps协同优化策略

MusePublic进阶调参指南&#xff1a;CFG Scale与Steps协同优化策略 1. 为什么需要重新理解CFG Scale与Steps的关系 很多人把CFG Scale&#xff08;分类器自由引导尺度&#xff09;和Steps&#xff08;推理步数&#xff09;当成两个独立调节的滑块——调高CFG让画面更贴合文字…

作者头像 李华
网站建设 2026/4/18 2:26:40

RetinaFace在C语言项目中的集成:跨语言调用实战

RetinaFace在C语言项目中的集成&#xff1a;跨语言调用实战 1. 为什么要在C项目里用RetinaFace 你可能已经用Python跑过RetinaFace&#xff0c;效果确实不错——能框出人脸&#xff0c;还能标出眼睛、鼻子、嘴巴这五个关键点。但当项目要上嵌入式设备、做系统级服务&#xff…

作者头像 李华
网站建设 2026/4/18 2:26:02

ChatGLM-6B法律领域实践:合同条款解释助手开发记录

ChatGLM-6B法律领域实践&#xff1a;合同条款解释助手开发记录 1. 为什么选ChatGLM-6B做法律助手&#xff1f; 你有没有遇到过这样的场景&#xff1a;手头一份几十页的采购合同&#xff0c;密密麻麻全是“不可抗力”“违约责任”“管辖法院”这类术语&#xff0c;逐条查法条太…

作者头像 李华