Forráskód Böngészése

feature:000.000.009:AI模型换为使用DeepSeek的模型
原AI服务使用讯飞的星火大模型,现在使用DeepSeek的V3模型;
并调整prompt,指定输出生成内容的格式为json字符串;

YangYi 7 hónapja
szülő
commit
66727599c8

+ 80 - 0
serve/src/main/java/space/anyi/BI/entity/deepseek/DeepSeekChoice.java

@@ -0,0 +1,80 @@
+package space.anyi.BI.entity.deepseek;
+
+import java.io.Serializable;
+
+/**
+ * @ProjectName: serve
+ * @ClassName Choice
+ * @date 2025/2/6 13:27
+ * @Description 
+ * @Version 1.0
+ * @Author: 杨逸
+ */
+public class DeepSeekChoice implements Serializable {
+    /**
+     * 模型生成的 completion 消息。
+     */
+    private DeepSeekHttpRequestMessage message;
+    /**
+     * 该 completion 在模型生成的 completion 的选择列表中的索引。
+     */
+    private Integer index;
+    /**
+     * 模型停止生成 token 的原因。
+     *
+     * stop:模型自然停止生成,或遇到 stop 序列中列出的字符串。
+     *
+     * length :输出长度达到了模型上下文长度限制,或达到了 max_tokens 的限制。
+     *
+     * content_filter:输出内容因触发过滤策略而被过滤。
+     *
+     * insufficient_system_resource:系统推理资源不足,生成被打断。
+     */
+    private String finish_reason;
+    /**
+     * 该 choice 的对数概率信息。
+     */
+    private DeepSeekLogprobs logprobs;
+
+    public DeepSeekHttpRequestMessage getMessage() {
+        return message;
+    }
+
+    public void setMessage(DeepSeekHttpRequestMessage message) {
+        this.message = message;
+    }
+
+    public Integer getIndex() {
+        return index;
+    }
+
+    public void setIndex(Integer index) {
+        this.index = index;
+    }
+
+    public String getFinish_reason() {
+        return finish_reason;
+    }
+
+    public void setFinish_reason(String finish_reason) {
+        this.finish_reason = finish_reason;
+    }
+
+    public DeepSeekLogprobs getLogprobs() {
+        return logprobs;
+    }
+
+    public void setLogprobs(DeepSeekLogprobs logprobs) {
+        this.logprobs = logprobs;
+    }
+
+    @Override
+    public String toString() {
+        return "DeepSeekChoice{" +
+                "message=" + message +
+                ", index=" + index +
+                ", finish_reason='" + finish_reason + '\'' +
+                ", logprobs=" + logprobs +
+                '}';
+    }
+}

+ 46 - 0
serve/src/main/java/space/anyi/BI/entity/deepseek/DeepSeekFunction.java

@@ -0,0 +1,46 @@
+package space.anyi.BI.entity.deepseek;
+
+import java.io.Serializable;
+
+/**
+ * @ProjectName: serve
+ * @ClassName DeepSeekFunction
+ * @date 2025/2/7 12:56
+ * @Description DeepSeek的函数对象
+ * @Version 1.0
+ * @Author: 杨逸
+ */
+public class DeepSeekFunction implements Serializable {
+    /**
+     * 模型调用的 function 名。
+     */
+    private String name;
+    /**
+     * 要调用的 function 的参数,由模型生成,格式为 JSON。请注意,模型并不总是生成有效的 JSON,并且可能会臆造出你函数模式中未定义的参数。在调用函数之前,请在代码中验证这些参数。
+     */
+    private String arguments;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getArguments() {
+        return arguments;
+    }
+
+    public void setArguments(String arguments) {
+        this.arguments = arguments;
+    }
+
+    @Override
+    public String toString() {
+        return "DeepSeekFunction{" +
+                "name='" + name + '\'' +
+                ", arguments='" + arguments + '\'' +
+                '}';
+    }
+}

+ 103 - 0
serve/src/main/java/space/anyi/BI/entity/deepseek/DeepSeekHttpRequestData.java

@@ -0,0 +1,103 @@
+package space.anyi.BI.entity.deepseek;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* @ProjectName: serve
+* @ClassName HttpRequestData
+* @date 2025/2/6 13:04
+* @Description 调用DeepSeek模型的请求参数对象
+* @Version 1.0
+* @Author: 杨逸
+*/
+public class DeepSeekHttpRequestData {
+    /**
+     * deekseek V3模型
+     */
+    public static final String DEEPSEEK_CHAT = "deepseek-chat";
+    /**
+     * deekseek R1模型
+     */
+    public static final String DEEPSEEK_REASONER = "deepseek-reasoner";
+    private List<DeepSeekHttpRequestMessage> messages = new ArrayList<>();
+    private String model = DEEPSEEK_CHAT;
+    private Integer frequency_penalty = 0;
+    private Integer max_tokens = 1024*8;
+    private Integer presence_penalty = 0;
+    private DeepSeekHttpResponseFormat response_format = DeepSeekHttpResponseFormat.json();
+    private Boolean stream = false;
+
+    public void addMessage(DeepSeekHttpRequestMessage message) {
+        messages.add(message);
+    }
+    public List<DeepSeekHttpRequestMessage> getMessages() {
+        return messages;
+    }
+
+    public void setMessages(List<DeepSeekHttpRequestMessage> messages) {
+        this.messages = messages;
+    }
+
+    public String getModel() {
+        return model;
+    }
+
+    public void setModel(String model) {
+        this.model = model;
+    }
+
+    public Integer getFrequency_penalty() {
+        return frequency_penalty;
+    }
+
+    public void setFrequency_penalty(Integer frequency_penalty) {
+        this.frequency_penalty = frequency_penalty;
+    }
+
+    public Integer getMax_tokens() {
+        return max_tokens;
+    }
+
+    public void setMax_tokens(Integer max_tokens) {
+        this.max_tokens = max_tokens;
+    }
+
+    public Integer getPresence_penalty() {
+        return presence_penalty;
+    }
+
+    public void setPresence_penalty(Integer presence_penalty) {
+        this.presence_penalty = presence_penalty;
+    }
+
+    public DeepSeekHttpResponseFormat getResponse_format() {
+        return response_format;
+    }
+
+    public void setResponse_format(DeepSeekHttpResponseFormat response_format) {
+        this.response_format = response_format;
+    }
+
+    public Boolean getStream() {
+        return stream;
+    }
+
+    public void setStream(Boolean stream) {
+        this.stream = stream;
+    }
+
+    @Override
+    public String toString() {
+        return "HttpRequestData{" +
+                "messages=" + messages +
+                ", model='" + model + '\'' +
+                ", frequency_penalty=" + frequency_penalty +
+                ", max_tokens=" + max_tokens +
+                ", presence_penalty=" + presence_penalty +
+                ", response_format=" + response_format +
+                ", stream=" + stream +
+                '}';
+    }
+}

+ 130 - 0
serve/src/main/java/space/anyi/BI/entity/deepseek/DeepSeekHttpRequestMessage.java

@@ -0,0 +1,130 @@
+package space.anyi.BI.entity.deepseek;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @ProjectName: serve
+ * @ClassName HttpRequestMessage
+ * @date 2025/2/6 13:24
+ * @Description DeepSeek的信息对象
+ * @Version 1.0
+ * @Author: 杨逸
+ */
+public class DeepSeekHttpRequestMessage implements Serializable {
+
+    /**
+     * 系统命令
+     * @see String
+     */
+    public static final String SYSTEM_ROLE = "system";
+    /**
+     * 用户
+     * @see String
+     */
+    public static final String USER_ROLE = "user";
+    /**
+     * AI模型
+     * @see String
+     */
+    public static final String ASSISTANT_ROLE = "assistant";
+    /**
+     * function call执行结果
+     * @see String
+     */
+    public static final String TOOL_ROLE = "tool";
+    /**
+     * 生成这条消息的角色。
+     */
+    private String role = USER_ROLE;
+    /**
+     * 该 completion 的内容。
+     */
+    private String content = "";
+    /**
+     * 仅适用于 deepseek-reasoner 模型。内容为 assistant 消息中在最终答案之前的推理内容。
+     */
+    private String reasoning_content = "";
+    /**
+     * 模型生成的 tool 调用,例如 function 调用。
+     */
+    private List<DeepSeekTool> tool_calls;
+
+
+    public DeepSeekHttpRequestMessage(String role, String content) {
+        this.role = role;
+        this.content = content;
+    }
+
+    public DeepSeekHttpRequestMessage(String content) {
+        this.content = content;
+    }
+
+    public DeepSeekHttpRequestMessage() {
+    }
+
+    /**
+     * 获取预设的prompt信息
+     * @return {@code HttpRequestMessage }
+     * @description:
+     * @author: 杨逸
+     * @data:2024/12/04 20:52:46
+     * @since 1.0.0
+     */
+    public static DeepSeekHttpRequestMessage getPromptMessage() {
+        String prompt = "你是一位专业的数据分析师和前端工程师,擅长对数据进行分析并得出明确的结论。你精通使用Echarts进行数据可视化,并能结合可视化的数据图表进行合理的分析。\n" +
+                "**要求:**\n" +
+                "1. 直接输出两个部分:完整的Echarts图表的配置代码和数据分析结论,代码不能是伪代码,代码是可以直接使用的代码,生成内容不包含其他提示内容。\n" +
+                "2. 我将提供原始数据和分析目标,你需要根据这些信息生成Echarts图表的配置对象标准JSON代码(标准的JSON字符串的属性是使用英文双引号包裹的)。\n" +
+                "3. 输出格式为一个JSON格式的对象,包含两个属性(Echarts的option配置对象的标准格式JSON代码和基于原始数据和图表分析得出的结论):\n" +
+                "\t{\n" +
+                "\t\"option\":\"Echarts的option配置对象的标准格式JSON代码\",\n" +
+                "\t\"conclusion\":\"基于原始数据和图表分析得出的结论\"\n" +
+                "\t}\n" +
+                "4. 请严格按照指定的输出格式提供所需内容。";
+        DeepSeekHttpRequestMessage message = new DeepSeekHttpRequestMessage(DeepSeekHttpRequestMessage.SYSTEM_ROLE,prompt);
+        return message;
+    }
+
+    public String getRole() {
+        return role;
+    }
+
+    public void setRole(String role) {
+        this.role = role;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+
+    public String getReasoning_content() {
+        return reasoning_content;
+    }
+
+    public void setReasoning_content(String reasoning_content) {
+        this.reasoning_content = reasoning_content;
+    }
+
+    public List<DeepSeekTool> getTool_calls() {
+        return tool_calls;
+    }
+
+    public void setTool_calls(List<DeepSeekTool> tool_calls) {
+        this.tool_calls = tool_calls;
+    }
+
+    @Override
+    public String toString() {
+        return "HttpRequestMessage{" +
+                "role='" + role + '\'' +
+                ", content='" + content + '\'' +
+                ", reasoning_content='" + reasoning_content + '\'' +
+                ", tool_calls=" + tool_calls +
+                '}';
+    }
+}

+ 91 - 0
serve/src/main/java/space/anyi/BI/entity/deepseek/DeepSeekHttpResponseData.java

@@ -0,0 +1,91 @@
+package space.anyi.BI.entity.deepseek;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @ProjectName: serve
+ * @ClassName HttpResponseData
+ * @date 2025/2/6 13:31
+ * @Description DeepSeek响应数据的对象
+ * @Version 1.0
+ * @Author: 杨逸
+ */
+public class DeepSeekHttpResponseData implements Serializable {
+    private String id;
+    private List<DeepSeekChoice> choices;
+    private Long created;
+    private String model;
+    private String system_fingerprint;
+    private String object;
+    private DeepSeekUsage usage;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public List<DeepSeekChoice> getChoices() {
+        return choices;
+    }
+
+    public void setChoices(List<DeepSeekChoice> choices) {
+        this.choices = choices;
+    }
+
+    public Long getCreated() {
+        return created;
+    }
+
+    public void setCreated(Long created) {
+        this.created = created;
+    }
+
+    public String getModel() {
+        return model;
+    }
+
+    public void setModel(String model) {
+        this.model = model;
+    }
+
+    public String getObject() {
+        return object;
+    }
+
+    public void setObject(String object) {
+        this.object = object;
+    }
+
+    public DeepSeekUsage getUsage() {
+        return usage;
+    }
+
+    public void setUsage(DeepSeekUsage usage) {
+        this.usage = usage;
+    }
+
+    public String getSystem_fingerprint() {
+        return system_fingerprint;
+    }
+
+    public void setSystem_fingerprint(String system_fingerprint) {
+        this.system_fingerprint = system_fingerprint;
+    }
+
+    @Override
+    public String toString() {
+        return "DeepSeekHttpResponseData{" +
+                "id='" + id + '\'' +
+                ", choices=" + choices +
+                ", created=" + created +
+                ", model='" + model + '\'' +
+                ", system_fingerprint='" + system_fingerprint + '\'' +
+                ", object='" + object + '\'' +
+                ", usage=" + usage +
+                '}';
+    }
+}

+ 41 - 0
serve/src/main/java/space/anyi/BI/entity/deepseek/DeepSeekHttpResponseFormat.java

@@ -0,0 +1,41 @@
+package space.anyi.BI.entity.deepseek;
+
+import java.io.Serializable;
+
+/**
+ * @ProjectName: serve
+ * @ClassName HttpResponseFormat
+ * @date 2025/2/6 13:26
+ * @Description 用于指定返回数据格式的对象
+ * @Version 1.0
+ * @Author: 杨逸
+ */
+public class DeepSeekHttpResponseFormat implements Serializable {
+    private String type;
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public static DeepSeekHttpResponseFormat json(){
+        DeepSeekHttpResponseFormat format = new DeepSeekHttpResponseFormat();
+        format.type = "json_object";
+        return format;
+    }
+    public static DeepSeekHttpResponseFormat text(){
+        DeepSeekHttpResponseFormat format = new DeepSeekHttpResponseFormat();
+        format.type = "text";
+        return format;
+    }
+
+    @Override
+    public String toString() {
+        return "HttpResponseFormat{" +
+                "type='" + type + '\'' +
+                '}';
+    }
+}

+ 73 - 0
serve/src/main/java/space/anyi/BI/entity/deepseek/DeepSeekLogprob.java

@@ -0,0 +1,73 @@
+package space.anyi.BI.entity.deepseek;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @ProjectName: serve
+ * @ClassName DeepSeekLogprob
+ * @date 2025/2/7 13:01
+ * @Description
+ * @Version 1.0
+ * @Author: 杨逸
+ */
+public class DeepSeekLogprob implements Serializable {
+    /**
+     * 输出的 token。
+     */
+    private String token;
+    /**
+     * 该 token 的对数概率。-9999.0 代表该 token 的输出概率极小,不在 top 20 最可能输出的 token 中。
+     */
+    private Double logprob;
+    /**
+     * 一个包含该 token UTF-8 字节表示的整数列表。一般在一个 UTF-8 字符被拆分成多个 token 来表示时有用。如果 token 没有对应的字节表示,则该值为 null。
+     */
+    private List<Integer> bytes;
+    /**
+     * 一个包含在该输出位置上,输出概率 top N 的 token 的列表,以及它们的对数概率。在罕见情况下,返回的 token 数量可能少于请求参数中指定的 top_logprobs 值。
+     */
+    private List<DeepSeekTopLogprob> top_logprobs;
+
+    public String getToken() {
+        return token;
+    }
+
+    public void setToken(String token) {
+        this.token = token;
+    }
+
+    public Double getLogprob() {
+        return logprob;
+    }
+
+    public void setLogprob(Double logprob) {
+        this.logprob = logprob;
+    }
+
+    public List<Integer> getBytes() {
+        return bytes;
+    }
+
+    public void setBytes(List<Integer> bytes) {
+        this.bytes = bytes;
+    }
+
+    public List<DeepSeekTopLogprob> getTop_logprobs() {
+        return top_logprobs;
+    }
+
+    public void setTop_logprobs(List<DeepSeekTopLogprob> top_logprobs) {
+        this.top_logprobs = top_logprobs;
+    }
+
+    @Override
+    public String toString() {
+        return "DeepSeekLogprob{" +
+                "token='" + token + '\'' +
+                ", logprob=" + logprob +
+                ", bytes=" + bytes +
+                ", top_logprobs=" + top_logprobs +
+                '}';
+    }
+}

+ 34 - 0
serve/src/main/java/space/anyi/BI/entity/deepseek/DeepSeekLogprobs.java

@@ -0,0 +1,34 @@
+package space.anyi.BI.entity.deepseek;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @ProjectName: serve
+ * @ClassName DeepSeekLogprobs
+ * @date 2025/2/7 12:59
+ * @Description DeepSeek的logprobs对象
+ * @Version 1.0
+ * @Author: 杨逸
+ */
+public class DeepSeekLogprobs implements Serializable {
+    /**
+     * 一个包含输出 token 对数概率信息的列表。
+     */
+    private List<DeepSeekLogprob> content;
+
+    public List<DeepSeekLogprob> getContent() {
+        return content;
+    }
+
+    public void setContent(List<DeepSeekLogprob> content) {
+        this.content = content;
+    }
+
+    @Override
+    public String toString() {
+        return "DeepSeekDeepSeekLogprobs{" +
+                "content=" + content +
+                '}';
+    }
+}

+ 30 - 0
serve/src/main/java/space/anyi/BI/entity/deepseek/DeepSeekPromptTokensDetails.java

@@ -0,0 +1,30 @@
+package space.anyi.BI.entity.deepseek;
+
+import java.io.Serializable;
+
+/**
+ * @ProjectName: serve
+ * @ClassName PromptTokensDetails
+ * @date 2025/2/6 14:48
+ * @Description
+ * @Version 1.0
+ * @Author: 杨逸
+ */
+public class DeepSeekPromptTokensDetails implements Serializable {
+    private Integer cached_tokens;
+
+    public Integer getCached_tokens() {
+        return cached_tokens;
+    }
+
+    public void setCached_tokens(Integer cached_tokens) {
+        this.cached_tokens = cached_tokens;
+    }
+
+    @Override
+    public String toString() {
+        return "PromptTokensDetails{" +
+                "cached_tokens=" + cached_tokens +
+                '}';
+    }
+}

+ 59 - 0
serve/src/main/java/space/anyi/BI/entity/deepseek/DeepSeekTool.java

@@ -0,0 +1,59 @@
+package space.anyi.BI.entity.deepseek;
+
+import java.io.Serializable;
+
+/**
+ * @ProjectName: serve
+ * @ClassName DeepSeekTool
+ * @date 2025/2/7 12:54
+ * @Description DeepSeek的工具对象
+ * @Version 1.0
+ * @Author: 杨逸
+ */
+public class DeepSeekTool implements Serializable {
+    /**
+     * tool 调用的 ID。
+     */
+    private String id;
+    /**
+     * tool 的类型。目前仅支持 function。
+     */
+    private String type;
+    /**
+     * 模型调用的 function。
+     */
+    private DeepSeekFunction function;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public DeepSeekFunction getFunction() {
+        return function;
+    }
+
+    public void setFunction(DeepSeekFunction function) {
+        this.function = function;
+    }
+
+    @Override
+    public String toString() {
+        return "DeepSeekTool{" +
+                "id='" + id + '\'' +
+                ", type='" + type + '\'' +
+                ", function=" + function +
+                '}';
+    }
+}

+ 60 - 0
serve/src/main/java/space/anyi/BI/entity/deepseek/DeepSeekTopLogprob.java

@@ -0,0 +1,60 @@
+package space.anyi.BI.entity.deepseek;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @ProjectName: serve
+ * @ClassName DeepSeekTopLogprob
+ * @date 2025/2/7 13:04
+ * @Description
+ * @Version 1.0
+ * @Author: 杨逸
+ */
+public class DeepSeekTopLogprob implements Serializable {
+    /**
+     * 输出的 token。
+     */
+    private String token;
+    /**
+     * 该 token 的对数概率。-9999.0 代表该 token 的输出概率极小,不在 top 20 最可能输出的 token 中。
+     */
+    private Double logprob;
+    /**
+     * 一个包含该 token UTF-8 字节表示的整数列表。一般在一个 UTF-8 字符被拆分成多个 token 来表示时有用。如果 token 没有对应的字节表示,则该值为 null。
+     */
+    private List<Integer> bytes;
+
+    public String getToken() {
+        return token;
+    }
+
+    public void setToken(String token) {
+        this.token = token;
+    }
+
+    public Double getLogprob() {
+        return logprob;
+    }
+
+    public void setLogprob(Double logprob) {
+        this.logprob = logprob;
+    }
+
+    public List<Integer> getBytes() {
+        return bytes;
+    }
+
+    public void setBytes(List<Integer> bytes) {
+        this.bytes = bytes;
+    }
+
+    @Override
+    public String toString() {
+        return "DeepSeekTopLogprob{" +
+                "token='" + token + '\'' +
+                ", logprob=" + logprob +
+                ", bytes=" + bytes +
+                '}';
+    }
+}

+ 80 - 0
serve/src/main/java/space/anyi/BI/entity/deepseek/DeepSeekUsage.java

@@ -0,0 +1,80 @@
+package space.anyi.BI.entity.deepseek;
+
+import java.io.Serializable;
+
+/**
+ * @ProjectName: serve
+ * @ClassName Usage
+ * @date 2025/2/6 13:30
+ * @Description DeepSeek token使用的表示对象
+ * @Version 1.0
+ * @Author: 杨逸
+ */
+public class DeepSeekUsage implements Serializable {
+    private Integer total_tokens;
+    private Integer prompt_tokens;
+    private Integer completion_tokens;
+    private DeepSeekPromptTokensDetails prompt_tokens_details;
+    private Integer prompt_cache_hit_tokens;
+    private Integer prompt_cache_miss_tokens;
+
+    public Integer getTotal_tokens() {
+        return total_tokens;
+    }
+
+    public void setTotal_tokens(Integer total_tokens) {
+        this.total_tokens = total_tokens;
+    }
+
+    public Integer getPrompt_tokens() {
+        return prompt_tokens;
+    }
+
+    public void setPrompt_tokens(Integer prompt_tokens) {
+        this.prompt_tokens = prompt_tokens;
+    }
+
+    public Integer getCompletion_tokens() {
+        return completion_tokens;
+    }
+
+    public void setCompletion_tokens(Integer completion_tokens) {
+        this.completion_tokens = completion_tokens;
+    }
+
+    public DeepSeekPromptTokensDetails getPrompt_tokens_details() {
+        return prompt_tokens_details;
+    }
+
+    public void setPrompt_tokens_details(DeepSeekPromptTokensDetails prompt_tokens_details) {
+        this.prompt_tokens_details = prompt_tokens_details;
+    }
+
+    public Integer getPrompt_cache_hit_tokens() {
+        return prompt_cache_hit_tokens;
+    }
+
+    public void setPrompt_cache_hit_tokens(Integer prompt_cache_hit_tokens) {
+        this.prompt_cache_hit_tokens = prompt_cache_hit_tokens;
+    }
+
+    public Integer getPrompt_cache_miss_tokens() {
+        return prompt_cache_miss_tokens;
+    }
+
+    public void setPrompt_cache_miss_tokens(Integer prompt_cache_miss_tokens) {
+        this.prompt_cache_miss_tokens = prompt_cache_miss_tokens;
+    }
+
+    @Override
+    public String toString() {
+        return "Usage{" +
+                "total_tokens=" + total_tokens +
+                ", prompt_tokens=" + prompt_tokens +
+                ", completion_tokens=" + completion_tokens +
+                ", prompt_tokens_details=" + prompt_tokens_details +
+                ", prompt_cache_hit_tokens=" + prompt_cache_hit_tokens +
+                ", prompt_cache_miss_tokens=" + prompt_cache_miss_tokens +
+                '}';
+    }
+}

+ 43 - 29
serve/src/main/java/space/anyi/BI/service/impl/ChartServiceImpl.java

@@ -4,6 +4,8 @@ import cn.hutool.core.util.IdUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.util.StringUtils;
@@ -12,21 +14,19 @@ import space.anyi.BI.entity.Chart;
 import space.anyi.BI.entity.dto.ChartDTO;
 import space.anyi.BI.entity.vo.ChartVO;
 import space.anyi.BI.entity.vo.PageVO;
-import space.anyi.BI.entity.xinghuo.HttpRequestData;
-import space.anyi.BI.entity.xinghuo.HttpResponseData;
+import space.anyi.BI.entity.deepseek.DeepSeekHttpRequestData;
+import space.anyi.BI.entity.deepseek.DeepSeekHttpResponseData;
 import space.anyi.BI.exception.SystemException;
 import space.anyi.BI.service.ChartService;
 import space.anyi.BI.mapper.ChartMapper;
 import org.springframework.stereotype.Service;
-import space.anyi.BI.util.AiUtil;
-import space.anyi.BI.util.BeanCopyUtil;
-import space.anyi.BI.util.ExcelUtils;
-import space.anyi.BI.util.SecurityUtils;
+import space.anyi.BI.util.*;
 
 import javax.annotation.Resource;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.RejectedExecutionException;
 import java.util.concurrent.ThreadPoolExecutor;
 
@@ -41,6 +41,8 @@ public class ChartServiceImpl extends ServiceImpl<ChartMapper, Chart>
     private final static Logger log = LoggerFactory.getLogger(ChartServiceImpl.class);
     @Resource
     private ThreadPoolExecutor threadPoolExecutor;
+    @Resource
+    private ObjectMapper objectMapper;
 
     /**
      * 异步使用AI生成图表
@@ -90,24 +92,31 @@ public class ChartServiceImpl extends ServiceImpl<ChartMapper, Chart>
                 message.append(chartDTO.getAnalysisTarget());
                 message.append("\n.使用").append(chartDTO.getChartType()).append("进行可视化分析.\n");
                 //配置prompt向AI发送请求
-                HttpRequestData requestData = AiUtil.createDefaultRequestData(message.toString());
-                HttpResponseData responseData = AiUtil.doChat(requestData);
-                //解析AI返回的数据
-                String content = responseData.getChoices().get(0).getMessage().getContent();
-                log.info("AI返回的数据为:{}", content);
-                int index = content.indexOf("```");
-                int endIndex = content.lastIndexOf("```");
-                if (index == -1 || endIndex == -1){
+                DeepSeekHttpRequestData requestData = DeepSeekAIUtil.createDefaultRequestData(message.toString());
+
+                //AI生成的指定内容
+                Map contentMap = null;
+                try {
+                    DeepSeekHttpResponseData responseData = DeepSeekAIUtil.doChat(requestData);
+                    //解析AI返回的数据
+                    String content = responseData.getChoices().get(0).getMessage().getContent();
+                    log.info("AI返回的数据为:{}", content);
+                    contentMap = objectMapper.readValue(content, Map.class);
+                } catch (JsonProcessingException e) {
                     chart.setState("失败");
                     chart.setExecuteMessage("AI生成图表失败");
                     updateById(chart);
                     throw new SystemException(500, "AI生成图表失败");
+                }catch (SystemException e){
+                    chart.setState("失败");
+                    chart.setExecuteMessage("AI生成图表失败");
+                    updateById(chart);
+                    throw e;
                 }
                 //数据可视化,Echarts的option代码
-                chart.setGeneratedChartData(content.substring(index+7, endIndex).trim());
-                index = endIndex;
+                chart.setGeneratedChartData(contentMap.get("option").toString());
                 //分析结论
-                chart.setAnalysisConclusion(content.substring(index+3).trim());
+                chart.setAnalysisConclusion(contentMap.get("conclusion").toString());
                 //保存到数据库
                 chart.setState("成功");
                 chart.setExecuteMessage("AI生成图表成功");
@@ -177,25 +186,30 @@ public class ChartServiceImpl extends ServiceImpl<ChartMapper, Chart>
         chart.setExecuteMessage("AI正在生成图表");
         updateById(chart);
         //配置prompt向AI发送请求
-        HttpRequestData requestData = AiUtil.createDefaultRequestData(message.toString());
-        HttpResponseData responseData = AiUtil.doChat(requestData);
-        //解析AI返回的数据
-        //ChartVO chartVO = BeanCopyUtil.copyBean(chartDTO, ChartVO.class);
-        String content = responseData.getChoices().get(0).getMessage().getContent();
-        log.info("AI返回的数据为:{}", content);
-        int index = content.indexOf("```");
-        int endIndex = content.lastIndexOf("```");
-        if (index == -1 || endIndex == -1){
+        DeepSeekHttpRequestData requestData = DeepSeekAIUtil.createDefaultRequestData(message.toString());
+        //AI生成的指定内容
+        Map contentMap = null;
+        try {
+            DeepSeekHttpResponseData responseData = DeepSeekAIUtil.doChat(requestData);
+            //解析AI返回的数据
+            String content = responseData.getChoices().get(0).getMessage().getContent();
+            log.info("AI返回的数据为:{}", content);
+            contentMap = objectMapper.readValue(content, Map.class);
+        } catch (JsonProcessingException e) {
             chart.setState("失败");
             chart.setExecuteMessage("AI生成图表失败");
             updateById(chart);
             throw new SystemException(500, "AI生成图表失败");
+        }catch (SystemException e){
+            chart.setState("失败");
+            chart.setExecuteMessage("AI生成图表失败");
+            updateById(chart);
+            throw e;
         }
         //数据可视化,Echarts的option代码
-        chart.setGeneratedChartData(content.substring(index+7, endIndex).trim());
-        index = endIndex;
+        chart.setGeneratedChartData(contentMap.get("option").toString());
         //分析结论
-        chart.setAnalysisConclusion(content.substring(index+3).trim());
+        chart.setAnalysisConclusion(contentMap.get("conclusion").toString());
 
         //更新数据库
         chart.setState("成功");

+ 63 - 0
serve/src/main/java/space/anyi/BI/util/DeepSeekAIUtil.java

@@ -0,0 +1,63 @@
+package space.anyi.BI.util;
+
+import cn.hutool.http.HttpResponse;
+import cn.hutool.http.HttpUtil;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import space.anyi.BI.entity.ResponseResult;
+import space.anyi.BI.entity.deepseek.DeepSeekHttpRequestData;
+import space.anyi.BI.entity.deepseek.DeepSeekHttpRequestMessage;
+import space.anyi.BI.entity.deepseek.DeepSeekHttpResponseData;
+import space.anyi.BI.exception.SystemException;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @ProjectName: serve
+ * @ClassName DeepSeekAIUtil
+ * @date 2025/2/6 13:41
+ * @Description 调用DeepSeek模型的工具类
+ * @Version 1.0
+ * @Author: 杨逸
+ */
+public class DeepSeekAIUtil {
+    private static final String url = "https://api.deepseek.com/chat/completions";
+    public static ObjectMapper objectMapper = new ObjectMapper();
+    public static DeepSeekHttpResponseData doChat(DeepSeekHttpRequestData requestData){
+        String json = null;
+        try {
+            json = objectMapper.writeValueAsString(requestData);
+        } catch (JsonProcessingException e) {
+            e.printStackTrace();
+        }
+        HttpResponse httpResponse = HttpUtil.createPost(url)
+                .header("Content-Type", "application/json")
+                .header("Authorization", "Bearer sk-9260e6b06ae94516878e1e6fff403e65")
+                .body(json)
+                .execute();
+        String body = httpResponse.body();
+        int index = body.indexOf('i');
+        DeepSeekHttpResponseData httpResponseData = null;
+        if (index == 2){
+            //调用成功
+            try {
+                httpResponseData = objectMapper.readValue(body, DeepSeekHttpResponseData.class);
+            } catch (JsonProcessingException e) {
+                e.printStackTrace();
+            }
+        }else{
+            System.err.println(body);
+            throw new SystemException(ResponseResult.AppHttpCodeEnum.SYSTEM_ERROR);
+        }
+        return httpResponseData;
+    }
+    public static DeepSeekHttpRequestData createDefaultRequestData(String message){
+        DeepSeekHttpRequestData httpRequestData = new DeepSeekHttpRequestData();
+        List<DeepSeekHttpRequestMessage> messages = new ArrayList<>();
+        messages.add(DeepSeekHttpRequestMessage.getPromptMessage());
+        messages.add(new DeepSeekHttpRequestMessage(DeepSeekHttpRequestMessage.USER_ROLE, message));
+        httpRequestData.setMessages(messages);
+        return httpRequestData;
+    }
+}