ai对话修复
continuous-integration/drone Build is passing Details

master
chenyuepan 2 weeks ago
parent accbc9e869
commit 1c61edb659

@ -125,6 +125,16 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
<!-- 二维码 --> <!-- 二维码 -->
<dependency> <dependency>
@ -176,6 +186,7 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId> <artifactId>spring-boot-starter-websocket</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId> <artifactId>spring-boot-starter-webflux</artifactId>

@ -21,6 +21,7 @@ public class InterceptorConfig implements WebMvcConfigurer {
.excludePathPatterns("/user/test") .excludePathPatterns("/user/test")
.excludePathPatterns("/user/admin") .excludePathPatterns("/user/admin")
.excludePathPatterns("/user/reset") .excludePathPatterns("/user/reset")
.excludePathPatterns("/chat/**")
.excludePathPatterns("/reservation/excel") .excludePathPatterns("/reservation/excel")
.excludePathPatterns("/reservation/payment") .excludePathPatterns("/reservation/payment")
.excludePathPatterns("/swagger-ui/index.html") .excludePathPatterns("/swagger-ui/index.html")

@ -0,0 +1,39 @@
package com.example.venue_reservation_service.controller;
import com.example.venue_reservation_service.entity.ChatRequest;
import com.example.venue_reservation_service.service.ChatService;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@RestController
@RequestMapping("/chat")
@CrossOrigin
public class ChatController {
@Resource
private ChatService chatService;
@PostMapping(value = "/ask", produces = MediaType.TEXT_PLAIN_VALUE)
public void chat(@RequestBody ChatRequest request, HttpServletRequest httpRequest, HttpServletResponse response) throws IOException {
// 设置流式响应头
response.setContentType("text/event-stream");
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
response.setHeader("Cache-Control", "no-cache");
// 获取输出流
ServletOutputStream outputStream = response.getOutputStream();
// 处理流式响应
chatService.streamChatResponse(request, outputStream, httpRequest);
}
}

@ -1,5 +1,6 @@
package com.example.venue_reservation_service.controller; package com.example.venue_reservation_service.controller;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.example.venue_reservation_service.domain.Device; import com.example.venue_reservation_service.domain.Device;
import com.example.venue_reservation_service.mapper.DeviceMapper; import com.example.venue_reservation_service.mapper.DeviceMapper;
import com.example.venue_reservation_service.service.DeviceService; import com.example.venue_reservation_service.service.DeviceService;
@ -39,17 +40,10 @@ public class DeviceController {
} }
// //
// 定时任务 - 每秒生成一条数据 // 定时任务 - 每秒生成一条数据
// @Scheduled(fixedRate = 1000) // @Scheduled(fixedRate = 3000)
// public void generateAndSendDeviceData() { // public void generateAndSendDeviceData() {
// // 生成并保存新数据 // // 生成并保存新数据
// Device newDevice = deviceService.generateDeviceData(); // Device newDevice = deviceService.getOne(Wrappers.<Device>query().orderByDesc("id").last("LIMIT 1"));
// deviceService.save(newDevice);
//
// // 检查并清理旧数据
// long count = deviceService.count();
// if (count > 100) {
// deviceMapper.deleteOldestRecords(50);
// }
// //
// // 推送新数据到前端 // // 推送新数据到前端
// messagingTemplate.convertAndSend("/topic/devices", newDevice); // messagingTemplate.convertAndSend("/topic/devices", newDevice);

@ -1,66 +0,0 @@
package com.example.venue_reservation_service.controller;
import com.example.venue_reservation_service.domain.VeMessage;
import com.example.venue_reservation_service.domain.VeSession;
import com.example.venue_reservation_service.service.VeMessageService;
import com.example.venue_reservation_service.service.VeSessionService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jakarta.annotation.Resource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/session")
@Api("ai会话管理模块")
@CrossOrigin
public class SessionController {
@Resource
private VeSessionService sessionService;
@Resource
private VeMessageService messageService;
@ApiOperation("创建新会话")
@PostMapping("/create")
public ResponseEntity<VeSession> createSession(@RequestBody VeSession session) {
VeSession savedSession = sessionService.saveSession(session);
return ResponseEntity.status(HttpStatus.CREATED).body(savedSession);
}
@ApiOperation("获取用户会话历史")
@GetMapping("/list")
public ResponseEntity<List<VeSession>> getUserSessions(@RequestParam(name = "userId") Integer userId) {
List<VeSession> sessions = sessionService.getSessionsByUserId(userId);
return ResponseEntity.ok(sessions);
}
@ApiOperation("获取会话详情")
@GetMapping("/{sessionId}")
public ResponseEntity<VeSession> getSession(@PathVariable("sessionId") Integer sessionId) {
VeSession session = sessionService.getById(sessionId);
if (session != null) {
return ResponseEntity.ok(session);
} else {
return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
}
}
@ApiOperation("获取指定会话的所有消息")
@GetMapping("/message/{sessionId}")
public ResponseEntity<List<VeMessage>> getSessionMessages(@PathVariable("sessionId") Integer sessionId) {
List<VeMessage> messages = messageService.getMessagesBySessionId(sessionId);
return ResponseEntity.ok(messages);
}
@ApiOperation("创建新消息")
@PostMapping("/message/create")
public ResponseEntity<VeMessage> createMessage(@RequestBody VeMessage message) {
VeMessage savedMessage = messageService.saveMessage(message);
return ResponseEntity.status(HttpStatus.CREATED).body(savedMessage);
}
}

@ -1,5 +1,6 @@
package com.example.venue_reservation_service.controller; package com.example.venue_reservation_service.controller;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.example.venue_reservation_service.domain.Type; import com.example.venue_reservation_service.domain.Type;
import com.example.venue_reservation_service.dto.PageDTO; import com.example.venue_reservation_service.dto.PageDTO;
import com.example.venue_reservation_service.service.TypeService; import com.example.venue_reservation_service.service.TypeService;
@ -8,9 +9,12 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.util.Optional;
@RestController @RestController
@RequestMapping("/type") @RequestMapping("/type")
@CrossOrigin @CrossOrigin
@ -20,10 +24,17 @@ public class TypeController {
@Resource @Resource
private TypeService typeService; private TypeService typeService;
@Value("${access.url}")
private String imgPrefix;
@ApiOperation("查询某个场馆信息") @ApiOperation("查询某个场馆信息")
@GetMapping("/select/{id}") @GetMapping("/select/{id}")
public Result select(@PathVariable("id") Integer id){ public Result select(@PathVariable("id") Integer id){
return Result.ok(typeService.getById(id)).message("查询成功"); Type type = typeService.getById(id);
if(Optional.ofNullable(type).isPresent() && StringUtils.isNotBlank(type.getImgUrl())){
type.setImgUrl(imgPrefix + type.getImgUrl());
}
return Result.ok(type).message("查询成功");
} }
@ApiOperation("查看所有场馆信息") @ApiOperation("查看所有场馆信息")

@ -38,7 +38,7 @@ public class VeMessage implements Serializable {
/** /**
* *
*/ */
private Object sender; private String sender;
/** /**
* *

@ -8,7 +8,9 @@ import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data; import lombok.Data;

@ -0,0 +1,11 @@
package com.example.venue_reservation_service.entity;
import lombok.Data;
@Data
public class ChatRequest {
private String content;
private String sessionToken;
}

@ -0,0 +1,14 @@
package com.example.venue_reservation_service.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class ChatResponse {
private String content;
private String sessionToken;
}

@ -2,6 +2,9 @@ package com.example.venue_reservation_service.mapper;
import com.example.venue_reservation_service.domain.VeMessage; import com.example.venue_reservation_service.domain.VeMessage;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.*;
import java.util.List;
/** /**
* @author 31586 * @author 31586
@ -9,7 +12,10 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
* @createDate 2025-06-17 15:36:33 * @createDate 2025-06-17 15:36:33
* @Entity generator.domain.VeMessage * @Entity generator.domain.VeMessage
*/ */
@Mapper
public interface VeMessageMapper extends BaseMapper<VeMessage> { public interface VeMessageMapper extends BaseMapper<VeMessage> {
@Select("SELECT * FROM venue_message WHERE session_id = #{sessionId} ORDER BY created_at ASC")
List<VeMessage> selectMessagesBySessionId(@Param("sessionId") Integer sessionId);
} }

@ -2,11 +2,9 @@ package com.example.venue_reservation_service.mapper;
import com.example.venue_reservation_service.domain.VeSession; import com.example.venue_reservation_service.domain.VeSession;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.*;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.time.LocalDateTime;
import java.util.List; import java.util.List;
/** /**
@ -15,8 +13,12 @@ import java.util.List;
* @createDate 2025-06-17 15:36:33 * @createDate 2025-06-17 15:36:33
* @Entity generator.domain.VeSession * @Entity generator.domain.VeSession
*/ */
@Mapper
public interface VeSessionMapper extends BaseMapper<VeSession> { public interface VeSessionMapper extends BaseMapper<VeSession> {
@Select("SELECT * FROM venue_session WHERE session_token = #{sessionToken}")
VeSession selectBySessionToken(@Param("sessionToken") String sessionToken);
} }

@ -0,0 +1,10 @@
package com.example.venue_reservation_service.service;
import com.example.venue_reservation_service.entity.ChatRequest;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
// ChatService.java
public interface ChatService {
void streamChatResponse(ChatRequest request, ServletOutputStream outputStream, HttpServletRequest httpRequest);
}

@ -12,7 +12,6 @@ import java.util.List;
*/ */
public interface VeMessageService extends IService<VeMessage> { public interface VeMessageService extends IService<VeMessage> {
VeMessage saveMessage(VeMessage message); List<VeMessage> getBySessionId(Integer sessionId);
List<VeMessage> getMessagesBySessionId(Integer sessionId);
} }

@ -3,8 +3,6 @@ package com.example.venue_reservation_service.service;
import com.example.venue_reservation_service.domain.VeSession; import com.example.venue_reservation_service.domain.VeSession;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/** /**
* @author 31586 * @author 31586
* @description venue_sessionService * @description venue_sessionService
@ -12,7 +10,7 @@ import java.util.List;
*/ */
public interface VeSessionService extends IService<VeSession> { public interface VeSessionService extends IService<VeSession> {
VeSession saveSession(VeSession session); VeSession createSession(Integer userId, String userIp);
VeSession getByToken(String token);
List<VeSession> getSessionsByUserId(Integer userId);
} }

@ -0,0 +1,169 @@
package com.example.venue_reservation_service.service.impl;
import com.example.venue_reservation_service.domain.VeMessage;
import com.example.venue_reservation_service.domain.VeSession;
import com.example.venue_reservation_service.entity.ChatRequest;
import com.example.venue_reservation_service.mapper.VeMessageMapper;
import com.example.venue_reservation_service.mapper.VeSessionMapper;
import com.example.venue_reservation_service.service.ChatService;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class ChatServiceImpl implements ChatService {
@Resource
private VeSessionMapper sessionMapper;
@Resource
private VeMessageMapper messageMapper;
@Value("${internai.api-url}")
private String apiUrl;
@Value("${internai.api-key}")
private String apiKey;
@Override
@Transactional
public void streamChatResponse(ChatRequest request, ServletOutputStream outputStream, HttpServletRequest httpRequest) {
// 获取或创建会话
VeSession session = getOrCreateSession(request.getSessionToken(), httpRequest);
String sessionToken = session.getSessionToken();
// 保存用户消息
saveMessage(request.getContent(), "user", session.getId());
// 构建完整对话历史
List<Map<String, String>> messages = buildMessages(session.getId());
// 调用第三方API
streamApiResponse(messages, outputStream, sessionToken, session.getId());
// 更新会话结束时间
updateSessionEndTime(session);
}
private VeSession getOrCreateSession(String sessionToken, HttpServletRequest request) {
if (sessionToken != null && !sessionToken.isEmpty()) {
VeSession session = sessionMapper.selectBySessionToken(sessionToken);
if (session != null) {
return session;
}
}
// 创建新会话
VeSession newSession = new VeSession();
newSession.setUserIp(request.getRemoteAddr());
newSession.setStartTime(LocalDateTime.now());
newSession.setSessionToken(UUID.randomUUID().toString());
newSession.setTitle("New Chat");
newSession.setUserId(1);
sessionMapper.insert(newSession);
return newSession;
}
private void saveMessage(String content, String sender, Integer sessionId) {
VeMessage message = new VeMessage();
message.setSessionId(sessionId);
message.setContent(content);
message.setSender(sender);
message.setCreatedAt(LocalDateTime.now());
messageMapper.insert(message);
}
private List<Map<String, String>> buildMessages(Integer sessionId) {
List<VeMessage> history = messageMapper.selectMessagesBySessionId(sessionId);
return history.stream().map(msg -> {
Map<String, String> messageMap = new HashMap<>();
messageMap.put("role", msg.getSender().equals("user") ? "user" : "assistant");
messageMap.put("content", msg.getContent());
return messageMap;
}).collect(Collectors.toList());
}
private void streamApiResponse(List<Map<String, String>> messages,
ServletOutputStream outputStream,
String sessionToken,
Integer sessionId) {
StringBuilder assistantResponse = new StringBuilder();
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
HttpPost httpPost = new HttpPost(apiUrl);
httpPost.setHeader("Authorization", "Bearer " + apiKey);
httpPost.setHeader("Content-Type", "application/json");
// 构建请求体
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("model", "internlm3-latest");
requestBody.put("messages", messages);
requestBody.put("temperature", 0.8);
requestBody.put("top_p", 0.9);
requestBody.put("stream", true);
httpPost.setEntity(new StringEntity(new ObjectMapper().writeValueAsString(requestBody)));
try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
InputStream contentStream = response.getEntity().getContent();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(contentStream))) {
String line;
while ((line = reader.readLine()) != null) {
if (line.startsWith("data: ")) {
String json = line.substring(6).trim();
if (json.equals("[DONE]")) break;
JsonNode data = new ObjectMapper().readTree(json);
JsonNode choices = data.path("choices");
if (!choices.isEmpty()) {
String chunk = choices.get(0).path("delta").path("content").asText();
if (!chunk.isEmpty()) {
assistantResponse.append(chunk);
outputStream.write(chunk.getBytes(StandardCharsets.UTF_8));
outputStream.flush();
}
}
}
}
}
}
// 保存助手回复
if (!assistantResponse.isEmpty()) {
saveMessage(assistantResponse.toString(), "assistant", sessionId);
}
} catch (Exception e) {
throw new RuntimeException("API call failed", e);
}
}
private void updateSessionEndTime(VeSession session) {
session.setEndTime(LocalDateTime.now());
sessionMapper.updateById(session);
}
}

@ -88,7 +88,6 @@ public class InformationServiceImpl extends ServiceImpl<InformationMapper, Infor
Page<Type> page = new Page<>(dto.getCurrent(), dto.getSize()); Page<Type> page = new Page<>(dto.getCurrent(), dto.getSize());
page = typeService.page(page, null); page = typeService.page(page, null);
List<Type> types = new ArrayList<>(); List<Type> types = new ArrayList<>();
for (Type record : page.getRecords()) { for (Type record : page.getRecords()) {
// 获取场馆中的场地信息 // 获取场馆中的场地信息
QueryWrapper<Information> wrapper = new QueryWrapper<>(); QueryWrapper<Information> wrapper = new QueryWrapper<>();
@ -98,6 +97,9 @@ public class InformationServiceImpl extends ServiceImpl<InformationMapper, Infor
.stream() .stream()
.map(obj -> (String) obj).toList(); .map(obj -> (String) obj).toList();
record.setVenues(locations); record.setVenues(locations);
if(StringUtils.isNotBlank(record.getImgUrl())){
record.setImgUrl(imgPrefix + record.getImgUrl());
}
types.add(record); types.add(record);
} }
return Result.ok(types).message("查询成功"); return Result.ok(types).message("查询成功");

@ -1,6 +1,5 @@
package com.example.venue_reservation_service.service.impl; package com.example.venue_reservation_service.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.venue_reservation_service.domain.VeMessage; import com.example.venue_reservation_service.domain.VeMessage;
import com.example.venue_reservation_service.service.VeMessageService; import com.example.venue_reservation_service.service.VeMessageService;
@ -8,7 +7,6 @@ import com.example.venue_reservation_service.mapper.VeMessageMapper;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List; import java.util.List;
/** /**
@ -20,22 +18,23 @@ import java.util.List;
public class VeMessageServiceImpl extends ServiceImpl<VeMessageMapper, VeMessage> public class VeMessageServiceImpl extends ServiceImpl<VeMessageMapper, VeMessage>
implements VeMessageService{ implements VeMessageService{
@Resource @Resource
private VeMessageMapper messageMapper; private VeMessageMapper messageMapper;
@Override @Override
public VeMessage saveMessage(VeMessage message) { public boolean save(VeMessage message) {
message.setCreatedAt(LocalDateTime.now()); if (message.getId() == null) {
messageMapper.insert(message); messageMapper.insert(message);
return message; } else {
messageMapper.updateById(message);
}
return false;
} }
@Override @Override
public List<VeMessage> getMessagesBySessionId(Integer sessionId) { public List<VeMessage> getBySessionId(Integer sessionId) {
QueryWrapper<VeMessage> queryWrapper = new QueryWrapper<>(); return messageMapper.selectMessagesBySessionId(sessionId);
queryWrapper.eq("session_id", sessionId)
.orderByAsc("created_at");
return messageMapper.selectList(queryWrapper);
} }
} }

@ -1,8 +1,5 @@
package com.example.venue_reservation_service.service.impl; package com.example.venue_reservation_service.service.impl;
import cn.hutool.core.lang.UUID;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.venue_reservation_service.service.VeSessionService; import com.example.venue_reservation_service.service.VeSessionService;
import com.example.venue_reservation_service.domain.VeSession; import com.example.venue_reservation_service.domain.VeSession;
@ -10,9 +7,12 @@ import com.example.venue_reservation_service.mapper.VeSessionMapper;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List; import java.util.List;
import java.util.UUID;
/** /**
* @author 31586 * @author 31586
@ -26,20 +26,21 @@ public class VeSessionServiceImpl extends ServiceImpl<VeSessionMapper, VeSession
@Resource @Resource
private VeSessionMapper sessionMapper; private VeSessionMapper sessionMapper;
public VeSession saveSession(VeSession session) { @Override
public VeSession createSession(Integer userId, String userIp) {
VeSession session = new VeSession();
session.setUserId(userId);
session.setUserIp(userIp);
session.setStartTime(LocalDateTime.now()); session.setStartTime(LocalDateTime.now());
if (StringUtils.isEmpty(session.getSessionToken())) { session.setSessionToken(UUID.randomUUID().toString());
session.setSessionToken("sess_" + UUID.randomUUID()); session.setTitle("New Chat");
}
sessionMapper.insert(session); sessionMapper.insert(session);
return session; return session;
} }
public List<VeSession> getSessionsByUserId(Integer userId) { @Override
QueryWrapper<VeSession> queryWrapper = new QueryWrapper<>(); public VeSession getByToken(String token) {
queryWrapper.eq("user_id", userId) return sessionMapper.selectBySessionToken(token);
.orderByDesc("start_time");
return sessionMapper.selectList(queryWrapper);
} }
} }

@ -0,0 +1,104 @@
package com.example.venue_reservation_service.utils;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Scanner;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;
public class AIChatClient {
private static final String API_URL = "https://chat.intern-ai.org.cn/api/v1/chat/completions";
private static final String BEARER_TOKEN = "eyJ0eXBlIjoiSldUIiwiYWxnIjoiSFM1MTIifQ.eyJqdGkiOiI4NjMwNjcyNyIsInJvbCI6IlJPTEVfUkVHSVNURVIiLCJpc3MiOiJPcGVuWExhYiIsImlhdCI6MTc1MTUzOTEzNCwiY2xpZW50SWQiOiJlYm1ydm9kNnlvMG5semFlazF5cCIsInBob25lIjoiMTc4NzAzNDI2ODUiLCJvcGVuSWQiOm51bGwsInV1aWQiOiIzNDg5ZTJkOC04ZGI4LTQyNDUtOTFiZC03YmRkN2Y3MTI0ZDEiLCJlbWFpbCI6IiIsImV4cCI6MTc2NzA5MTEzNH0.-Bfg41q0v4RDjN6mgfLmga1isL02KF5DdoA1LoiNmUQg8I19FjEMz2w9dOJsql3-MavE6UB5QlECQiDvk4t6XQ"; // 替换为你的实际Token
private static final ObjectMapper objectMapper = new ObjectMapper();
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 初始化对话历史
String conversationHistory = buildInitialHistory();
while (true) {
System.out.print("\n请输入你的问题 (输入 'exit' 退出): ");
String userInput = scanner.nextLine();
if ("exit".equalsIgnoreCase(userInput)) {
break;
}
// 更新对话历史
conversationHistory = updateHistory(conversationHistory, userInput);
try {
// 发送请求并获取响应
String response = sendChatRequest(conversationHistory);
// 更新对话历史添加AI回复
conversationHistory = conversationHistory +
",{\"role\":\"assistant\",\"content\":\"" + escapeJson(response) + "\"}";
System.out.println("\nAI回复: " + response);
} catch (Exception e) {
System.err.println("请求失败: " + e.getMessage());
}
}
scanner.close();
}
private static String sendChatRequest(String history) throws Exception {
// 构建完整的请求体
String requestBody = String.format(
"{\"model\":\"internlm3-latest\",\"messages\":[%s],\"temperature\":0.8,\"top_p\":0.9,\"stream\":true}",
history
);
// 创建HTTP请求
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(API_URL))
.header("Authorization", "Bearer " + BEARER_TOKEN)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(requestBody))
.build();
// 发送请求并处理流式响应
StringBuilder fullResponse = new StringBuilder();
client.send(request, HttpResponse.BodyHandlers.ofLines()).body()
.filter(line -> line.startsWith("data:") && !line.contains("[DONE]"))
.forEach(line -> {
try {
String json = line.substring(5).trim();
if (!json.isEmpty()) {
JsonNode node = objectMapper.readTree(json);
String content = node.path("choices").get(0).path("delta").path("content").asText();
if (content != null && !content.isEmpty()) {
System.out.print(content); // 实时输出
fullResponse.append(content);
}
}
} catch (Exception e) {
System.err.println("\n解析错误: " + e.getMessage());
}
});
return fullResponse.toString();
}
private static String buildInitialHistory() {
return "{\"role\":\"user\",\"content\":\"你知道刘慈欣吗?\"}," +
"{\"role\":\"assistant\",\"content\":\"为一个人工智能助手,我知道刘慈欣。他是一位著名的中国科幻小说家和工程师,曾经获得过多项奖项,包括雨果奖、星云奖等。\"}";
}
private static String updateHistory(String history, String newQuestion) {
return history + ",{\"role\":\"user\",\"content\":\"" + escapeJson(newQuestion) + "\"}";
}
private static String escapeJson(String input) {
return input.replace("\\", "\\\\")
.replace("\"", "\\\"")
.replace("\n", "\\n")
.replace("\r", "\\r")
.replace("\t", "\\t");
}
}

@ -65,7 +65,7 @@ spring:
boot: boot:
admin: admin:
client: client:
url: http://119.29.191.232:10020/monitor # 服务端地址 url: http://119.29.191.232:10025/monitor # 服务端地址
username: admin # 服务端用户名 username: admin # 服务端用户名
password: admin123! # 服务端密码 password: admin123! # 服务端密码
mail: mail:
@ -136,3 +136,7 @@ access:
logging: logging:
level: level:
root: info root: info
# AI API 配置
internai:
api-url: https://chat.intern-ai.org.cn/api/v1/chat/completions
api-key: eyJ0eXBlIjoiSldUIiwiYWxnIjoiSFM1MTIifQ.eyJqdGkiOiI4NjMwNjcyNyIsInJvbCI6IlJPTEVfUkVHSVNURVIiLCJpc3MiOiJPcGVuWExhYiIsImlhdCI6MTc1MTUzOTEzNCwiY2xpZW50SWQiOiJlYm1ydm9kNnlvMG5semFlazF5cCIsInBob25lIjoiMTc4NzAzNDI2ODUiLCJvcGVuSWQiOm51bGwsInV1aWQiOiIzNDg5ZTJkOC04ZGI4LTQyNDUtOTFiZC03YmRkN2Y3MTI0ZDEiLCJlbWFpbCI6IiIsImV4cCI6MTc2NzA5MTEzNH0.-Bfg41q0v4RDjN6mgfLmga1isL02KF5DdoA1LoiNmUQg8I19FjEMz2w9dOJsql3-MavE6UB5QlECQiDvk4t6XQ
Loading…
Cancel
Save