Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/chenzhan20050128_newcourseselectionsystem.json
T

1 line
11 KiB
JSON

{"repo": "chenzhan20050128/newcourseselectionsystem", "files": {"backend/src/main/java/org/example/newcourseselectionsystem/infrastructure/client/DeepSeekApiClient.java": {"b6175585f769ca8b35938377daef75c78ef4805e": {"t": 1785746126.0163248, "n": 4894, "h": "bcf752b44c4b3616", "c": "package org.example.newcourseselectionsystem.infrastructure.client;\n\nimport com.fasterxml.jackson.databind.JsonNode;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport lombok.RequiredArgsConstructor;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.http.MediaType;\nimport org.springframework.stereotype.Component;\nimport org.springframework.core.io.buffer.DataBuffer;\nimport org.springframework.core.io.buffer.DataBufferUtils;\nimport org.springframework.web.reactive.function.client.WebClient;\nimport reactor.core.publisher.Flux;\n\nimport java.nio.charset.StandardCharsets;\nimport java.time.Duration;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * DeepSeek API 客户端\n */\n@Slf4j\n@Component\n@RequiredArgsConstructor\npublic class DeepSeekApiClient {\n\n private final WebClient.Builder webClientBuilder;\n private final ObjectMapper objectMapper;\n\n @Value(\"${deepseek.api.key:}\")\n private String apiKey;\n\n private static final String BASE_URL = \"https://api.deepseek.com/chat/completions\";\n\n /**\n * 调用 DeepSeek API 获取流式推荐结果\n *\n * @param messages 消息列表\n * @return AI 回复内容流\n */\n public Flux<String> chatStream(List<Message> messages) {\n try {\n Map<String, Object> requestBody = new HashMap<>();\n requestBody.put(\"model\", \"deepseek-chat\");\n requestBody.put(\"messages\", messages);\n requestBody.put(\"stream\", true);\n\n WebClient webClient = webClientBuilder\n .baseUrl(BASE_URL)\n .defaultHeader(\"Authorization\", \"Bearer \" + apiKey)\n .defaultHeader(\"Content-Type\", MediaType.APPLICATION_JSON_VALUE)\n .build();\n\n return webClient.post()\n .uri(BASE_URL)\n .bodyValue(requestBody)\n .retrieve()\n .bodyToFlux(DataBuffer.class)\n .timeout(Duration.ofMinutes(5))\n .map(dataBuffer -> {\n byte[] bytes = new byte[dataBuffer.readableByteCount()];\n dataBuffer.read(bytes);\n DataBufferUtils.release(dataBuffer);\n return new String(bytes, StandardCharsets.UTF_8);\n })\n .flatMap(this::parseSSELines)\n .filter(data -> data != null && !data.trim().isEmpty())\n .filter(data -> !data.equals(\"data: [DONE]\"))\n .map(this::parseStreamData)\n .filter(content -> content != null && !content.isEmpty())\n .doOnError(error -> log.error(\"调用 DeepSeek API 失败\", error))\n .onErrorResume(error -> {\n log.error(\"DeepSeek API 流式调用失败\", error);\n return Flux.just(\"错误: \" + error.getMessage());\n });\n } catch (Exception e) {\n log.error(\"调用 DeepSeek API 失败\", e);\n return Flux.just(\"错误: \" + e.getMessage());\n }\n }\n\n /**\n * 解析 SSE 格式的多行数据\n */\n private Flux<String> parseSSELines(String data) {\n String[] lines = data.split(\"\\n\");\n return Flux.fromArray(lines)\n .filter(line -> line.startsWith(\"data: \"));\n }\n\n /**\n * 解析流式数据\n */\n private String parseStreamData(String data) {\n try {\n // SSE 格式: \"data: {...}\"\n if (data.startsWith(\"data: \")) {\n String jsonStr = data.substring(6).trim();\n if (jsonStr.equals(\"[DONE]\")) {\n return null;\n }\n JsonNode jsonNode = objectMapper.readTree(jsonStr);\n JsonNode choices = jsonNode.get(\"choices\");\n if (choices != null && choices.isArray() && choices.size() > 0) {\n JsonNode choice = choices.get(0);\n JsonNode delta = choice.get(\"delta\");\n if (delta != null) {\n JsonNode content = delta.get(\"content\");\n if (content != null && content.isTextual()) {\n return content.asText();\n }\n }\n }\n }\n return null;\n } catch (Exception e) {\n log.warn(\"解析流式数据失败: {}\", data, e);\n return null;\n }\n }\n\n @Data\n @NoArgsConstructor\n @AllArgsConstructor\n public static class Message {\n private String role;\n private String content;\n }\n\n @Data\n public static class DeepSeekResponse {\n private List<Choice> choices;\n }\n\n @Data\n public static class Choice {\n private Message message;\n }\n}\n"}, "61cd2062747b5c8d36a7ab2dbbadb41444253505": {"t": 1785760034.2727714, "n": 4894, "h": "bcf752b44c4b3616", "c": "package org.example.newcourseselectionsystem.infrastructure.client;\n\nimport com.fasterxml.jackson.databind.JsonNode;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport lombok.RequiredArgsConstructor;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.http.MediaType;\nimport org.springframework.stereotype.Component;\nimport org.springframework.core.io.buffer.DataBuffer;\nimport org.springframework.core.io.buffer.DataBufferUtils;\nimport org.springframework.web.reactive.function.client.WebClient;\nimport reactor.core.publisher.Flux;\n\nimport java.nio.charset.StandardCharsets;\nimport java.time.Duration;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * DeepSeek API 客户端\n */\n@Slf4j\n@Component\n@RequiredArgsConstructor\npublic class DeepSeekApiClient {\n\n private final WebClient.Builder webClientBuilder;\n private final ObjectMapper objectMapper;\n\n @Value(\"${deepseek.api.key:}\")\n private String apiKey;\n\n private static final String BASE_URL = \"https://api.deepseek.com/chat/completions\";\n\n /**\n * 调用 DeepSeek API 获取流式推荐结果\n *\n * @param messages 消息列表\n * @return AI 回复内容流\n */\n public Flux<String> chatStream(List<Message> messages) {\n try {\n Map<String, Object> requestBody = new HashMap<>();\n requestBody.put(\"model\", \"deepseek-chat\");\n requestBody.put(\"messages\", messages);\n requestBody.put(\"stream\", true);\n\n WebClient webClient = webClientBuilder\n .baseUrl(BASE_URL)\n .defaultHeader(\"Authorization\", \"Bearer \" + apiKey)\n .defaultHeader(\"Content-Type\", MediaType.APPLICATION_JSON_VALUE)\n .build();\n\n return webClient.post()\n .uri(BASE_URL)\n .bodyValue(requestBody)\n .retrieve()\n .bodyToFlux(DataBuffer.class)\n .timeout(Duration.ofMinutes(5))\n .map(dataBuffer -> {\n byte[] bytes = new byte[dataBuffer.readableByteCount()];\n dataBuffer.read(bytes);\n DataBufferUtils.release(dataBuffer);\n return new String(bytes, StandardCharsets.UTF_8);\n })\n .flatMap(this::parseSSELines)\n .filter(data -> data != null && !data.trim().isEmpty())\n .filter(data -> !data.equals(\"data: [DONE]\"))\n .map(this::parseStreamData)\n .filter(content -> content != null && !content.isEmpty())\n .doOnError(error -> log.error(\"调用 DeepSeek API 失败\", error))\n .onErrorResume(error -> {\n log.error(\"DeepSeek API 流式调用失败\", error);\n return Flux.just(\"错误: \" + error.getMessage());\n });\n } catch (Exception e) {\n log.error(\"调用 DeepSeek API 失败\", e);\n return Flux.just(\"错误: \" + e.getMessage());\n }\n }\n\n /**\n * 解析 SSE 格式的多行数据\n */\n private Flux<String> parseSSELines(String data) {\n String[] lines = data.split(\"\\n\");\n return Flux.fromArray(lines)\n .filter(line -> line.startsWith(\"data: \"));\n }\n\n /**\n * 解析流式数据\n */\n private String parseStreamData(String data) {\n try {\n // SSE 格式: \"data: {...}\"\n if (data.startsWith(\"data: \")) {\n String jsonStr = data.substring(6).trim();\n if (jsonStr.equals(\"[DONE]\")) {\n return null;\n }\n JsonNode jsonNode = objectMapper.readTree(jsonStr);\n JsonNode choices = jsonNode.get(\"choices\");\n if (choices != null && choices.isArray() && choices.size() > 0) {\n JsonNode choice = choices.get(0);\n JsonNode delta = choice.get(\"delta\");\n if (delta != null) {\n JsonNode content = delta.get(\"content\");\n if (content != null && content.isTextual()) {\n return content.asText();\n }\n }\n }\n }\n return null;\n } catch (Exception e) {\n log.warn(\"解析流式数据失败: {}\", data, e);\n return null;\n }\n }\n\n @Data\n @NoArgsConstructor\n @AllArgsConstructor\n public static class Message {\n private String role;\n private String content;\n }\n\n @Data\n public static class DeepSeekResponse {\n private List<Choice> choices;\n }\n\n @Data\n public static class Choice {\n private Message message;\n }\n}\n"}}}}