{"repo": "ai-learning-planning-tracking-hitwh/backend", "files": {"src/main/resources/application.properties": {"dedf7a5ed2b797c8c16131837a1bd2810e5b3457": {"t": 1786068239.130884, "n": 798, "h": "d2012b7f7b8e3354", "c": "spring.application.name=backend\nspring.main.allow-circular-references=true\n\n# JWT\njwt.secret=${JWT_SECRET:}\njwt.expiration=604800000\n\n# Server Port\nserver.port=8080\n\n# MySQL\nspring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver\nspring.datasource.url=jdbc:mysql://localhost:3306/ai_learning_planning?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf-8&allowPublicKeyRetrieval=true\nspring.datasource.username=appuser\nspring.datasource.password=Zxcvbnm@1015\n\n# MyBatis\nmybatis.type-aliases-package=com.agent.backend.entity\nmybatis.configuration.map-underscore-to-camel-case=true\n\n# log\nlogging.level.com.agent.backend.mapper=debug\nlogging.level.root=info\n\n# DeepSeek API\ndeepseek.api-key=${DEEPSEEK_API_KEY:}\ndeepseek.base-url=https://api.deepseek.com\ndeepseek.model=deepseek-chat"}}, "src/main/java/com/agent/backend/service/LLMService.java": {"dedf7a5ed2b797c8c16131837a1bd2810e5b3457": {"t": 1786068379.22064, "n": 5283, "h": "8e501422f248118b", "c": "package com.agent.backend.service;\n\nimport com.fasterxml.jackson.databind.JsonNode;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.http.HttpEntity;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.MediaType;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.stereotype.Service;\nimport org.springframework.web.client.RestTemplate;\n\nimport javax.annotation.PostConstruct;\nimport java.util.*;\n\n@Service\npublic class LLMService {\n private static final Logger log = LoggerFactory.getLogger(LLMService.class);\n\n @Value(\"${deepseek.api-key:}\")\n private String apiKey;\n\n @Value(\"${deepseek.base-url:https://api.deepseek.com}\")\n private String baseUrl;\n\n @Value(\"${deepseek.model:deepseek-chat}\")\n private String model;\n\n private final ObjectMapper objectMapper = new ObjectMapper();\n private final RestTemplate restTemplate = new RestTemplate();\n\n /**\n * 调用 DeepSeek API(简单对话)\n */\n public String chat(String systemPrompt, String userPrompt) {\n try {\n List> messages = new ArrayList<>();\n\n Map systemMessage = new HashMap<>();\n systemMessage.put(\"role\", \"system\");\n systemMessage.put(\"content\", systemPrompt);\n messages.add(systemMessage);\n\n Map userMessage = new HashMap<>();\n userMessage.put(\"role\", \"user\");\n userMessage.put(\"content\", userPrompt);\n messages.add(userMessage);\n\n // 构建请求体\n Map requestBody = new HashMap<>();\n requestBody.put(\"model\", model);\n requestBody.put(\"messages\", messages);\n requestBody.put(\"temperature\", 0.7);\n requestBody.put(\"max_tokens\", 4096);\n\n String response = callAPI(requestBody);\n return extractContent(response);\n\n } catch (Exception e) {\n log.error(\"调用 DeepSeek API 失败\", e);\n throw new RuntimeException(\"AI服务暂时不可用:\" + e.getMessage());\n }\n }\n\n /**\n * 调用 DeepSeek API(支持自定义参数)\n */\n public String chat(String systemPrompt, String userPrompt, Double temperature, Integer maxTokens) {\n try {\n List> messages = new ArrayList<>();\n\n Map systemMessage = new HashMap<>();\n systemMessage.put(\"role\", \"system\");\n systemMessage.put(\"content\", systemPrompt);\n messages.add(systemMessage);\n\n Map userMessage = new HashMap<>();\n userMessage.put(\"role\", \"user\");\n userMessage.put(\"content\", userPrompt);\n messages.add(userMessage);\n\n Map requestBody = new HashMap<>();\n requestBody.put(\"model\", model);\n requestBody.put(\"messages\", messages);\n requestBody.put(\"temperature\", temperature != null ? temperature : 0.7);\n requestBody.put(\"max_tokens\", maxTokens != null ? maxTokens : 4096);\n\n String response = callAPI(requestBody);\n return extractContent(response);\n\n } catch (Exception e) {\n log.error(\"调用 DeepSeek API 失败\", e);\n throw new RuntimeException(\"AI服务暂时不可用:\" + e.getMessage());\n }\n }\n\n /**\n * 调用 DeepSeek API(支持多轮对话历史)\n */\n public String chatWithHistory(List> messages) {\n try {\n Map requestBody = new HashMap<>();\n requestBody.put(\"model\", model);\n requestBody.put(\"messages\", messages);\n requestBody.put(\"temperature\", 0.7);\n requestBody.put(\"max_tokens\", 4096);\n\n String response = callAPI(requestBody);\n return extractContent(response);\n\n } catch (Exception e) {\n log.error(\"调用 DeepSeek API 失败\", e);\n throw new RuntimeException(\"AI服务暂时不可用:\" + e.getMessage());\n }\n }\n\n private String callAPI(Map requestBody) {\n HttpHeaders headers = new HttpHeaders();\n headers.setContentType(MediaType.APPLICATION_JSON);\n if (apiKey != null && !apiKey.isEmpty()) {\n headers.setBearerAuth(apiKey);\n }\n\n HttpEntity> entity = new HttpEntity<>(requestBody, headers);\n String url = baseUrl + \"/v1/chat/completions\";\n\n log.debug(\"调用 DeepSeek API,model:{},url:{}\", model, url);\n\n ResponseEntity response = restTemplate.postForEntity(url, entity, String.class);\n return response.getBody();\n }\n\n private String extractContent(String responseJson) {\n try {\n JsonNode root = objectMapper.readTree(responseJson);\n JsonNode choices = root.path(\"choices\");\n if (choices.isArray() && choices.size() > 0) {\n return choices.get(0).path(\"message\").path(\"content\").asText();\n }\n log.warn(\"DeepSeek 响应格式异常:{}\", responseJson);\n return \"\";\n } catch (Exception e) {\n log.error(\"解析 DeepSeek 响应失败\", e);\n return \"\";\n }\n }\n}"}}}}