Commit 74555209 authored by luojun's avatar luojun

Initial commit

parents
Pipeline #6407 canceled with stages
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="accountSettings">
<option name="activeRegion" value="us-east-1" />
<option name="recentlyUsedRegions">
<list>
<option value="us-east-1" />
</list>
</option>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="kedaxunfei" />
</profile>
</annotationProcessing>
</component>
<component name="JavacSettings">
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
<module name="kedaxunfei" options="-parameters" />
</option>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="justh5" />
<option name="name" value="Public Repositories" />
<option name="url" value="http://120.24.176.53:8081/repository/maven-public/" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="http://maven.aliyun.com/nexus/content/groups/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="http://120.24.176.53:8081/repository/maven-public/" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
</component>
</project>
\ No newline at end of file
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK" />
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>deep-ask</artifactId>
<name>deepseek问答模块</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<!-- spring boot web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- sse长连接 -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp-sse</artifactId>
<version>4.12.0</version>
</dependency>
<!--用于构造http请求-->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.3</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.6.2</version>
</dependency>
<!-- Spring boot websocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>1.3.70</version>
</dependency>
<!--用于输出日志包-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId >
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>voice-identify</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
<!--lombok插件-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Spring boot websocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!--用于处理json数据(包括jsonPath功能)-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.70</version>
</dependency>
<!--针对开发IO流功能的工具类库-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
</dependencies>
</project>
package admin;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
@EnableAsync
@SpringBootApplication(scanBasePackages = {"admin"})
public class WeixinRun {
public static void main(String[] args) {
SpringApplication.run(WeixinRun.class, args);
}
}
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package admin.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* @author ZhangHouYing
* @date 2019-08-24 15:44
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
package admin.listener;
import admin.model.deepseek.resp.stream.ChatStreamResponse;
import admin.model.maxdb.resp.MaxdbStreamResponse;
import admin.service.TextToSpeechService;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.sse.EventSource;
import okhttp3.sse.EventSourceListener;
import javax.annotation.Resource;
import javax.websocket.Session;
import java.net.SocketException;
import java.util.Objects;
/**
* @author lj
* @date 2025/2/24 9:26
*/
@Slf4j
public class DeepSeekAiListener extends EventSourceListener {
StringBuffer stringBuffer = new StringBuffer();
private Session session;
private static TextToSpeechService textToSpeechService;
@Resource
public static void setTextToSpeechService(TextToSpeechService textToSpeechService){
DeepSeekAiListener.textToSpeechService = textToSpeechService;
}
public DeepSeekAiListener(Session session) {
this.session = session;
}
@Override
public void onOpen(EventSource eventSource, Response response) {
super.onOpen(eventSource, response);
log.info("DeepSeek建立sse连接...onOpen");
}
@Override
public void onEvent(EventSource eventSource, String id, String type, String data) {
super.onEvent(eventSource, id, type, data);
Gson gson= new Gson();
try {
MaxdbStreamResponse completionResponse = gson.fromJson(data, MaxdbStreamResponse.class);
if (completionResponse.getIsEnd()) {
log.info("DeepSeek返回数据结束了...onEvent");
textToSpeechService.convertTextToSpeech(this.stringBuffer.toString());
return;
}
if (completionResponse.getContent()!=null){
System.out.print(completionResponse.getContent());
this.stringBuffer.append(completionResponse.getContent());
this.session.getBasicRemote().sendText(completionResponse.getContent());
}
}catch (Exception e){
System.out.println(e.getMessage());
}
// ChatStreamResponse completionResponse = mapper.readValue(data, MaxdbStreamResponse.class);
// if (completionResponse.getChoices()!=null && !completionResponse.getChoices().isEmpty()){
// System.out.print(completionResponse.getChoices().get(0).getDelta().getContent());
// this.stringBuffer.append(completionResponse.getChoices().get(0).getDelta().getContent());
// }
}
@Override
public void onClosed(EventSource eventSource) {
super.onClosed(eventSource);
log.info("DeepSeek关闭sse连接...onClosed");
}
@Override
@SneakyThrows
public void onFailure(EventSource eventSource, Throwable t, Response response) {
super.onFailure(eventSource, t, response);
if (Objects.isNull(response)) {
return;
}
if(t instanceof SocketException){
log.info("用户停止输出...onFailure");
}else {
ResponseBody body = response.body();
if (Objects.nonNull(body)) {
log.error("DeepSeek sse连接异常data:{},异常:{}", body.string(), t);
} else {
log.error("DeepSeek sse连接异常data:{},异常:{}", response, t);
}
}
response.close();
eventSource.cancel();
log.info("eventSource cancel....onFailure");
}
}
package admin.model.deepseek.req;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
/**
* @author lj
* @date 2025/2/23 13:27
*/
@Data
public class ChatMessage {
/**
* 消息的内容
*/
@SerializedName("content")
private String content;
/**
* 该消息的发起角色,其值为 system user assistant tool
*/
@SerializedName("role")
private String role;
/**
* 可以选填的参与者的名称,为模型提供信息以区分相同角色的参与者
*/
@SerializedName("name")
private String name;
}
package admin.model.deepseek.req;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import java.util.List;
/**
* @author lj
* @date 2025/2/23 10:59
*/
@Data
public class ChatReqMsg {
/**
* 对话的消息列表
*/
@SerializedName("messages")
private List<ChatMessage> messages;
/**
* 使用的模型的 ID。您可以使用 deepseek-chat。
*/
@SerializedName("model")
private String model;
/**
* 介于 -2.0 和 2.0 之间的数字。如果该值为正,那么新 token 会根据其在已有文本中的出现频率受到相应的惩罚,降低模型重复相同内容的可能性。
*/
@SerializedName("frequency_penalty")
private Double frequencyPenalty;
/**
* 介于 1 到 8192 间的整数,限制一次请求中模型生成 completion 的最大 token 数。输入 token 和输出 token 的总长度受模型的上下文长度的限制。
* 如未指定 max_tokens参数,默认使用 4096。
*/
@SerializedName("max_tokens")
private Integer maxTokens;
/**
* 介于 -2.0 和 2.0 之间的数字。如果该值为正,那么新 token 会根据其是否已在已有文本中出现受到相应的惩罚,从而增加模型谈论新主题的可能性。
*/
@SerializedName("presence_penalty")
private Double presencePenalty;
/**
* 一个 object,指定模型必须输出的格式。
*
* 设置为 { "type": "json_object" } 以启用 JSON 模式,该模式保证模型生成的消息是有效的 JSON。
*
* 注意: 使用 JSON 模式时,你还必须通过系统或用户消息指示模型生成 JSON。否则,模型可能会生成不断的空白字符,直到生成达到令牌限制,从而导致请求长时间运行并显得“卡住”。此外,如果 finish_reason="length",这表示生成超过了 max_tokens 或对话超过了最大上下文长度,消息内容可能会被部分截断。
*
* type
* string
* Possible values: [text, json_object]
*
* Default value: text
*
* Must be one of text or json_object.
*/
@SerializedName("response_format")
private ChatRespType responseFormat;
/**
* 如果设置为 True,将会以 SSE(server-sent events)的形式以流式发送消息增量。消息流以 data: [DONE] 结尾。
*/
@SerializedName("stream")
private Boolean stream;
/**
* 流式输出相关选项。只有在 stream 参数为 true 时,才可设置此参数。
*
* include_usage
* boolean
* 如果设置为 true,在流式消息最后的 data: [DONE] 之前将会传输一个额外的块。此块上的 usage 字段显示整个请求的 token 使用统计信息,而 choices 字段将始终是一个空数组。所有其他块也将包含一个 usage 字段,但其值为 null。
*/
@SerializedName("stream_options")
private ChatStreamOption streamOptions;
/**
* 采样温度,介于 0 和 2 之间。更高的值,如 0.8,会使输出更随机,而更低的值,如 0.2,会使其更加集中和确定。 我们通常建议可以更改这个值或者更改 top_p,但不建议同时对两者进行修改。
*/
@SerializedName("temperature")
private Double temperature;
/**
* 作为调节采样温度的替代方案,模型会考虑前 top_p 概率的 token 的结果。所以 0.1 就意味着只有包括在最高 10% 概率中的 token 会被考虑。 我们通常建议修改这个值或者更改 temperature,但不建议同时对两者进行修改。
*/
@SerializedName("top_p")
private Double topP;
/**
* 是否返回所输出 token 的对数概率。如果为 true,则在 message 的 content 中返回每个输出 token 的对数概率。
*/
@SerializedName("logprobs")
private Boolean logprobs;
/**
* 一个介于 0 到 20 之间的整数 N,指定每个输出位置返回输出概率 top N 的 token,且返回这些 token 的对数概率。指定此参数时,logprobs 必须为 true。
*/
@SerializedName("top_logprobs")
private Integer topLogprobs;
}
package admin.model.deepseek.req;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
/**
* @author lj
* @date 2025/2/23 13:31
*/
@Data
public class ChatRespType {
/**
* 一个 object,指定模型必须输出的格式。
*
* 设置为 { "type": "json_object" } 以启用 JSON 模式,该模式保证模型生成的消息是有效的 JSON。
*
* 注意: 使用 JSON 模式时,你还必须通过系统或用户消息指示模型生成 JSON。否则,模型可能会生成不断的空白字符,直到生成达到令牌限制,从而导致请求长时间运行并显得“卡住”。此外,如果 finish_reason="length",这表示生成超过了 max_tokens 或对话超过了最大上下文长度,消息内容可能会被部分截断。
*
* type
* string
* Possible values: [text, json_object]
*
* Default value: text
*
* Must be one of text or json_object.
*/
@SerializedName("type")
private String type;
}
package admin.model.deepseek.req;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
/**
* @author lj
* @date 2025/2/23 13:33
*/
@Data
public class ChatStreamOption {
/**
* 流式输出相关选项。只有在 stream 参数为 true 时,才可设置此参数。
*
* include_usage
* boolean
* 如果设置为 true,在流式消息最后的 data: [DONE] 之前将会传输一个额外的块。此块上的 usage 字段显示整个请求的 token 使用统计信息,而 choices 字段将始终是一个空数组。所有其他块也将包含一个 usage 字段,但其值为 null。
*/
@SerializedName("include_usage")
private Boolean includeUsage;
@SerializedName("continuous_usage_stats")
private Boolean continuousUsageStats;
// @SerializedName("additional_prop1")
// private String additionalProp1="{}";
}
package admin.model.deepseek.resp.error;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
/**
* @author lj
* @date 2025/2/23 14:51
*/
@Data
public class ChatErrorResponse {
@SerializedName("error")
private Error error;
}
package admin.model.deepseek.resp.error;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
/**
* @author lj
* @date 2025/2/23 14:51
*/
@Data
public class Error {
@SerializedName("code")
private String code; // 错误码(如 "invalid_api_key")
@SerializedName("message")
private String message;
@SerializedName("type")
private String type; // 错误类型(如 "auth_error")
}
package admin.model.deepseek.resp.starnd;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import java.util.List;
/**
* @author lj
* @date 2025/2/23 14:36
*/
@Data
public class ChatTextResponse {
@SerializedName("id")
private String id;
@SerializedName("object")
private String object;
@SerializedName("created")
private long created;
@SerializedName("model")
private String model;
@SerializedName("choices")
private List<CompletionChoice> choices;
@SerializedName("usage")
private Usage usage;
}
package admin.model.deepseek.resp.starnd;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
/**
* @author lj
* @date 2025/2/23 14:47
*/
@Data
public class CompletionChoice {
@SerializedName("index")
private int index;
@SerializedName("message")
private Message message;
@SerializedName("finish_reason")
private String finishReason;
}
package admin.model.deepseek.resp.starnd;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
/**
* @author lj
* @date 2025/2/23 14:47
*/
@Data
public class Message {
@SerializedName("role")
private String role;
@SerializedName("content")
private String content;
}
package admin.model.deepseek.resp.starnd;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
/**
* @author lj
* @date 2025/2/23 14:47
*/
@Data
public class Usage {
@SerializedName("prompt_tokens")
private int promptTokens;
@SerializedName("completion_tokens")
private int completionTokens;
@SerializedName("total_tokens")
private int totalTokens;
}
package admin.model.deepseek.resp.stream;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import java.util.List;
/**
* @author lj
* @date 2025/2/23 14:50
*/
@Data
public class ChatStreamResponse {
@SerializedName("id")
private String id;
@SerializedName("object")
private String object; // 固定为 "chat.completion.chunk"
@SerializedName("created")
private long created;
@SerializedName("model")
private String model;
@SerializedName("choices")
private List<StreamChoice> choices;
}
package admin.model.deepseek.resp.stream;
import admin.model.deepseek.resp.starnd.Message;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
/**
* @author lj
* @date 2025/2/23 14:50
*/
@Data
public class StreamChoice {
@SerializedName("index")
private Integer index;
@SerializedName("delta")
private Message delta; // 流式返回的增量内容
@SerializedName("logprobs")
private String logprobs; // 流式返回的增量内容
@SerializedName("finish_reason")
private String finishReason; // 流式返回的增量内容
}
package admin.model.maxdb;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author lj
* @date 2025/2/26 12:41
*/
@Data
@Component
@ConfigurationProperties(prefix = "maxdb.screen")
public class MaxdbScreenConfig {
private String applicationId;
private String talkUrl;
private String chatUrl;
private String apiKey;
}
package admin.model.maxdb;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author lj
* @date 2025/2/25 22:24
*/
@Data
@Component
@ConfigurationProperties(prefix = "maxdb.zhongke")
public class MaxdbZkhjConfig {
private String applicationId;
private String talkUrl;
private String chatUrl;
private String apiKey;
}
package admin.model.maxdb.req;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
/**
* @author lj
* @date 2025/2/24 14:16
*/
@Data
public class MaxdbReq {
@SerializedName("message")
private String message;
@SerializedName("re_chat")
private boolean reChat=false;
@SerializedName("stream")
private boolean stream=true;
}
package admin.model.maxdb.resp;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
/**
* @author lj
* @date 2025/2/24 14:28
*/
@Data
public class ChatChildResponse {
@SerializedName("runtime_node_id")
private String runtimeNodeId;
@SerializedName("chat_record_id")
private String chatRecordId;
@SerializedName("child_node")
private ChatChildResponse childNode;
}
package admin.model.maxdb.resp;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import java.util.List;
/**
* @author lj
* @date 2025/2/24 14:26
*/
@Data
public class MaxdbStreamResponse {
@SerializedName("chat_id")
private String chatId;
@SerializedName("chat_record_id")
private String chatRecordId;
private Boolean operate;
private String content;
@SerializedName("node_id")
private String nodeId;
@SerializedName("up_node_id_list")
private List<String> upNodeIdList;
@SerializedName("is_end")
private Boolean isEnd;
@SerializedName("usage")
private Usage usage;
@SerializedName("node_type")
private String nodeType;
@SerializedName("runtime_node_id")
private String runtimeNodeId;
@SerializedName("view_type")
private Object viewType;
@SerializedName("child_node")
private ChatChildResponse childNode;
@SerializedName("node_is_end")
private Boolean nodeIsEnd;
@SerializedName("real_node_id")
private String realNodeId;
@SerializedName("reasoning_content")
private String reasoningContent;
}
package admin.model.maxdb.resp;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
/**
* @author lj
* @date 2025/2/24 14:27
*/
@Data
public class Usage {
@SerializedName("completion_tokens")
private Integer completionTokens;
@SerializedName("prompt_tokens")
private Integer promptTokens;
@SerializedName("total_tokens")
private Integer totalTokens;
}
/*
* Copyright (c) 2016, FPX and/or its affiliates. All rights reserved.
* Use, Copy is subject to authorized license.
*/
package admin.resp;
import lombok.Data;
@Data
public class ApiResponse<T> {
protected String code;
protected String message;
protected T data;
private String traceId;
public ApiResponse() {
}
public static <T> ApiResponse<T> buildSuccess() {
ApiResponse<T> response = new ApiResponse();
response.code = ApiResponseCode.SUCCESS.getCode();
response.message = ApiResponseCode.SUCCESS.getMessage();
return response;
}
public static <T> ApiResponse<T> buildSuccess(T data) {
ApiResponse<T> response = new ApiResponse();
response.data = data;
response.code = ApiResponseCode.SUCCESS.getCode();
response.message = ApiResponseCode.SUCCESS.getMessage();
return response;
}
public static <T> ApiResponse<T> buildFailure(ApiResponseCode responseCode) {
ApiResponse<T> response = new ApiResponse();
response.code = responseCode.getCode();
response.message = responseCode.getMessage();
return response;
}
public static <T> ApiResponse<T> buildFailure(String errorCode, String errorMsg) {
ApiResponse<T> response = new ApiResponse();
response.code = errorCode;
response.message = errorMsg;
return response;
}
public static boolean isSuccess(ApiResponse<Object> apiResponse){
return apiResponse.code.equals("0");
}
public void setTraceId(String traceId) {
this.traceId = traceId;
}
public String getCode() {
return this.code;
}
public void setCode(String code) {
this.code = code;
}
public String getMessage() {
return this.message;
}
public ApiResponse<T> setMessage(String message) {
this.message = message;
return this;
}
public T getData() {
return this.data;
}
public void setData(T data) {
this.data = data;
}
public String toString() {
return "data.ApiResponse{traceId='" + this.traceId + '\'' + ", code='" + this.code + '\'' + ", message='" + this.message + '\'' + ", data=" + this.data + '}';
}
}
package admin.resp;
public enum ApiResponseCode {
SUCCESS("0", "成功"),
FAILURE("9000", "处理失败"),
WAIT_CHECK("1001", "已认证,待处理"),
WAIT_PAY("1002", "待充值"),
DATA_EMPTY("9995", "数据为空"),
DB_ERROR("9996", "数据库错误"),
PARAM_NULL("9997", "参数为空"),
PARAM_ERROR("9998", "参数错误"),
SYSTEM_ERROR("9999", "系统异常"),
USER_NOT_LOGIN("9","已在其他设备登录!"),
USER_NO_BIND_Mobile("11","未绑定手机号码!"),
WAIT_RESULT("99","等待结果,请查询交易流水信息"),
MAS_SUCCESS("1", "成功"),
MAS_MOBILES_NULL("102", "mobiles为空"),
MAS_MOBILES_EMPTY("103", "mobiles为空数组"),
MAS_MOBILES_CHECK("104", "mobiles含有非法号码"),
MAS_AUTHENTICATION_CHECK("105", "未进行身份认证或认证失败"),
MAS_SIGN_NULL("106", "sign为空"),
MAS_OTHER_ERROR("107", "其它错误"),
MAS_MOBILES_REPEAT("109","mobiles含有重复号码"),
MAS_MOBILES_MAX("11","mobiles中号码数量超限(>5000),应≤5000"),
MAS_THREAD_POOL_BUSY("112","线程池忙");
private String code;
private String message;
private ApiResponseCode(String code, String message) {
this.code = code;
this.message = message;
}
public String getCode() {
return this.code;
}
public String getMessage() {
return this.message;
}
public ApiResponseCode setMessage(String message) {
this.message = message;
return this;
}
public static String getMessage(String code) {
for (ApiResponseCode value : ApiResponseCode.values()) {
if (value.getCode().equals(code)) {
return value.getMessage();
}
}
return null;
}
}
package admin.rest;
import admin.resp.ApiResponse;
import admin.service.DeepSeekOpenApiService;
import admin.service.MaxkbOpenApiService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.websocket.Session;
/**
* @author lj
* @date 2025/2/23 13:35
*/
@RestController
@RequestMapping(value = "v1/openApi/")
@RequiredArgsConstructor
@Slf4j
public class OpenApiController {
private final DeepSeekOpenApiService deepSeekOpenApiService;
private final MaxkbOpenApiService maxkbOpenApiService;
@PostMapping(value = "completions")
public ApiResponse<Object> completions(@RequestParam String content){
deepSeekOpenApiService.chatCompletions(content);
return null;
}
@GetMapping("testOpen")
public ApiResponse<Object> open(@RequestParam String applicationId){
return maxkbOpenApiService.getMaxkbSessionId(applicationId);
}
@GetMapping("testcompletions")
public void testcompletions(@RequestParam String chatId,
@RequestParam String message){
maxkbOpenApiService.chatCompletions(message,chatId,null);
}
@GetMapping("aItalk")
public void testcompletions(@RequestParam String message){
maxkbOpenApiService.talk(message,null);
}
}
package admin.server;
import admin.config.SpeechToTextConfig;
import admin.service.MaxkbOpenApiService;
import lombok.extern.slf4j.Slf4j;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.ResponseBody;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author lj
* @date 2025/2/20 19:46
*/
@ServerEndpoint("/webSocket/voice/{memberId}")
@Component
@Slf4j
public class VoiceWebSocketServer {
private static AtomicInteger onlineNum = new AtomicInteger();
private static SpeechToTextConfig voiceConfig;
private static MaxkbOpenApiService maxkbOpenApiService;
@Resource
public void setVoiceConfig(SpeechToTextConfig speechToTextConfig){
voiceConfig = speechToTextConfig;
}
@Resource
public void setMaxkbOpenApiService(MaxkbOpenApiService maxkbOpenApiService){
VoiceWebSocketServer.maxkbOpenApiService = maxkbOpenApiService;
}
private static ConcurrentHashMap<String, Session> sessionPools = new ConcurrentHashMap<>();
//建立连接成功调用
@OnOpen
public void onOpen(Session session, @PathParam(value = "memberId") String memberId) {
log.info("{}已连接", memberId);
sessionPools.put(memberId, session);
}
//关闭连接时调用
@OnClose
public void onClose(@PathParam(value = "memberId") String memberId) {
sessionPools.remove(memberId);
log.info("关闭连接");
System.out.println(sessionPools);
}
//收到客户端信息
@OnMessage
public void onTextMessage(Session session,String message) throws IOException {
session.setMaxBinaryMessageBufferSize(50 * 1024 * 1024);
log.info("message:{}",message);
maxkbOpenApiService.talk(message,session);
}
@OnMessage
public void onBinaryMessage(Session session, ByteBuffer data) {
session.setMaxBinaryMessageBufferSize(50 * 1024 * 1024);
// 处理二进制音频数据块
log.info("data:{}",data);
handleAudioChunk(session, data);
}
//错误时调用
@OnError
public void onError(Session session, Throwable throwable) {
System.out.println("发生错误");
for (Map.Entry<String, Session> map : sessionPools.entrySet()) {
Session value = map.getValue();
if (value.equals(session)) {
sessionPools.remove(map.getKey());
}
}
throwable.printStackTrace();
}
//发送消息
public void sendMessage(Session session, String message) {
if (session != null) {
synchronized (session) {
try {
session.getBasicRemote().sendText(message);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
/**
* 处理音频数据
* @param session
* @param data
*/
private void handleAudioChunk(Session session, ByteBuffer data) {
//1.音频转文本
speechToText(data);
//2.向ai提问获取答案
//3.文本转语音
textToSpeech();
sendMessage(session, null);
}
private void textToSpeech() {
}
/**
* 语音转文本
* @param data 语音数据
*/
private void speechToText(ByteBuffer data) {
byte[] bytes = new byte[data.remaining()];
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try {
byteArrayOutputStream.write(bytes);
String authUrl = null;
authUrl = getAuthUrl(voiceConfig.getHostUrl(), voiceConfig.getApiKey(), voiceConfig.getApiSecret());
OkHttpClient client = new OkHttpClient.Builder().build();
String url = authUrl.toString().replace("http://", "ws://").replace("https://", "wss://");
Request request = new Request.Builder().url(url).build();
ResponseBody body = client.newCall(request).execute().body();
System.out.println(body.string());
// WebSocket webSocket = client.newWebSocket(request, new ResponseData());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public String getAuthUrl(String hostUrl, String apiKey, String apiSecret) throws Exception {
URL url = new URL(hostUrl);
SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
format.setTimeZone(TimeZone.getTimeZone("GMT"));
String date = format.format(new Date());
StringBuilder builder = new StringBuilder("host: ").append(url.getHost()).append("\n").//
append("date: ").append(date).append("\n").//
append("GET ").append(url.getPath()).append(" HTTP/1.1");
//System.out.println(builder);
Charset charset = Charset.forName("UTF-8");
Mac mac = Mac.getInstance("hmacsha256");
SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(charset), "hmacsha256");
mac.init(spec);
byte[] hexDigits = mac.doFinal(builder.toString().getBytes(charset));
String sha = Base64.getEncoder().encodeToString(hexDigits);
//System.out.println(sha);
String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha);
//System.out.println(authorization);
HttpUrl httpUrl = HttpUrl.parse("https://" + url.getHost() + url.getPath()).newBuilder().//
addQueryParameter("authorization", Base64.getEncoder().encodeToString(authorization.getBytes(charset))).//
addQueryParameter("date", date).//
addQueryParameter("host", url.getHost()).//
build();
return httpUrl.toString();
}
}
package admin.service;
/**
* @author lj
* @date 2025/2/23 13:41
*/
public interface DeepSeekOpenApiService {
void chatCompletions(String content);
}
package admin.service;
import admin.resp.ApiResponse;
import javax.websocket.Session;
/**
* @author lj
* @date 2025/2/24 11:11
*/
public interface MaxkbOpenApiService {
//获取应用id对应的会话id
ApiResponse<Object> getMaxkbSessionId(String apiKey);
/**
*
* @message message 问题
*/
void chatCompletions(String message,String chatId, Session session);
void talk(String message,Session seesion);
}
package admin.service.impl;
import admin.listener.DeepSeekAiListener;
import admin.model.deepseek.req.ChatMessage;
import admin.model.deepseek.req.ChatReqMsg;
import admin.model.deepseek.req.ChatStreamOption;
import admin.model.deepseek.resp.starnd.Message;
import admin.model.deepseek.resp.stream.ChatStreamResponse;
import admin.model.deepseek.resp.stream.StreamChoice;
import admin.service.DeepSeekOpenApiService;
import com.google.gson.Gson;
import lombok.RequiredArgsConstructor;
import okhttp3.*;
import okhttp3.sse.EventSources;
import okio.BufferedSource;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* @author lj
* @date 2025/2/23 13:42
*/
@Service
@RequiredArgsConstructor
public class DeepSeekOpenApiServiceImpl implements DeepSeekOpenApiService {
@Override
public void chatCompletions(String content) {
OkHttpClient client = new OkHttpClient().newBuilder().readTimeout(1, TimeUnit.MINUTES)
.build();
MediaType mediaType = MediaType.parse("application/json");
ChatReqMsg req = createChatReqMsg(content);
Gson gson = new Gson();
RequestBody body = RequestBody.create(mediaType, gson.toJson(req));
Request request = new Request.Builder()
.url("http://192.168.0.122:6006/v1/chat/completions")
.method("POST", body)
.addHeader("Content-Type", "application/json")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer zkhjdpQ8")
.build();
DeepSeekAiListener deepSeekAiListener = new DeepSeekAiListener(null);
// OkHttpClient okHttpClient = new OkHttpClient.Builder()
// .connectTimeout(1, TimeUnit.MINUTES)
// .readTimeout(1, TimeUnit.MINUTES)
// .build();
EventSources.createFactory(client).newEventSource(request,deepSeekAiListener);
// factory.newEventSource(request, eventSourceListener);
//
// client.newCall(request).enqueue(new Callback() {
// @Override
// public void onFailure(@NotNull Call call, @NotNull IOException e) {
//
// }
//
// @Override
// public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
// if (!response.isSuccessful()) {
// System.err.println("请求失败: " + response.code());
// return;
// }
//
// try (ResponseBody body = response.body()) {
// if (body != null) {
// processStream(body.source());
// }
// }
// }
// });
}
public static void processStream(BufferedSource source) throws IOException {
StringBuilder fullContent = new StringBuilder();
Gson gson = new Gson();
while (!source.exhausted()) {
String line = source.readUtf8Line();
if (line == null) break;
// 过滤心跳包和非数据行
if (line.startsWith("data: ")) {
String jsonData = line.substring(6).trim(); // 去掉 "data: "
if ("[DONE]".equals(jsonData)) {
System.out.println("\n[流式传输结束]");
break;
}
// 解析JSON块
ChatStreamResponse chunk = gson.fromJson(jsonData, ChatStreamResponse.class);
if (chunk != null && chunk.getChoices() != null) {
for (StreamChoice choice : chunk.getChoices()) {
Message deltaContent = choice.getDelta();
if (deltaContent != null && deltaContent.getContent()!=null) {
fullContent.append(deltaContent.getContent());
System.out.print(deltaContent.getContent()); // 实时输出
}
}
}
}
}
System.out.println("\n完整内容:\n" + fullContent);
}
private ChatReqMsg createChatReqMsg(String content) {
ChatReqMsg chatReqMsg = new ChatReqMsg();
ChatMessage chatMessage = new ChatMessage();
chatMessage.setContent(content);
chatMessage.setRole("user");
chatReqMsg.setMessages(new ArrayList<>(Collections.singleton(chatMessage)));
chatReqMsg.setModel("DeepSeek-R1-Distill-Qwen-32B-GGUF");
chatReqMsg.setStream(true);
ChatStreamOption chatStreamOption = new ChatStreamOption();
chatStreamOption.setIncludeUsage(true);
chatStreamOption.setContinuousUsageStats(false);
chatReqMsg.setStreamOptions(chatStreamOption);
// ChatRespType chatRespType = new ChatRespType();
// chatRespType.setType("text");
// chatReqMsg.setResponse_format(chatRespType);
return chatReqMsg;
}
}
package admin.service.impl;
import admin.model.maxdb.MaxdbScreenConfig;
import admin.model.maxdb.MaxdbZkhjConfig;
import admin.model.maxdb.req.MaxdbReq;
import admin.resp.ApiResponse;
import admin.service.MaxkbOpenApiService;
import admin.util.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.websocket.Session;
/**
* @author lj
* @date 2025/2/24 11:11
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class MaxkbOpenApiServiceImpl implements MaxkbOpenApiService {
private final MaxdbZkhjConfig maxdbConfig;
private final MaxdbScreenConfig maxdbScreenConfig;
@Override
public ApiResponse<Object> getMaxkbSessionId(String applicationId) {
String data = HttpUtil.get(String.format(maxdbScreenConfig.getChatUrl(),applicationId),maxdbScreenConfig.getApiKey());
return JSONObject.parseObject(data, ApiResponse.class);
}
@Override
public void chatCompletions( String message, String chatId, Session session) {
MaxdbReq maxdbReq = new MaxdbReq();
maxdbReq.setMessage(message);
HttpUtil.postCallBackStream(String.format(maxdbScreenConfig.getTalkUrl(),chatId), maxdbReq, maxdbScreenConfig.getApiKey(),session);
}
@Override
public void talk(String message,Session seesion) {
// if (message.contains("中科")){
//
// }else if (message.contains("大屏")){
//
// }else if (message.contains("分析")){
//
// }else{
// }
ApiResponse<Object> maxkbSessionId = getMaxkbSessionId(maxdbScreenConfig.getApplicationId());
chatCompletions(message,String.valueOf(maxkbSessionId.getData()),seesion);
}
}
package admin.util;
import admin.listener.DeepSeekAiListener;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.*;
import okhttp3.sse.EventSource;
import okhttp3.sse.EventSources;
import javax.websocket.Session;
import java.io.IOException;
/**
* @author lj
* @date 2025/2/24 13:18
*/
public class HttpUtil {
public static String get(String url,String apiKey){
OkHttpClient okHttpClient = new OkHttpClient().newBuilder().build();
Request request = new Request.Builder()
.url(url)
.method("GET",null)
.addHeader("Content-Type", "application/json")
.addHeader("Accept", "application/json")
.addHeader("Authorization", apiKey)
.build();
try {
Response execute = okHttpClient.newCall(request).execute();
return execute.body().string();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void postCallBackStream(String url, Object data, String apiKey, Session session){
OkHttpClient okHttpClient = new OkHttpClient().newBuilder().build();
// RequestBody body = RequestBody.create(MediaType.parse("application/json"), data);
Request request = null;
try {
request = new Request.Builder()
.url(url)
.addHeader("Content-Type", "application/json")
.addHeader("Accept", "application/json")
.addHeader("Authorization", apiKey)
.post(RequestBody.create(MediaType.parse("application/json"),
new ObjectMapper().writeValueAsString(data)))
.build();
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
EventSource.Factory factory = EventSources.createFactory(okHttpClient);
factory.newEventSource(request,new DeepSeekAiListener(session));
}
}
maxdb:
zhongke:
api-key: application-5479ccf9b59c66432e5529febe94719a
application-id: 1a0e5e60-f1bd-11ef-a7de-0242ac110002
chat-url: http://192.168.0.122:8080/api/application/%s/chat/open
talk-url: http://192.168.0.122:8080/api/application/chat_message/%s
screen:
api-key: application-6e8250fa092a566c7c0aea0e08c9b1a3
application-id: adc51c8c-f3f4-11ef-a70b-0242ac110002
chat-url: http://192.168.0.122:8080/api/application/%s/chat/open
talk-url: http://192.168.0.122:8080/api/application/chat_message/%s
server:
port: 8888
tomcat:
max-swallow-size: 104857600
\ No newline at end of file
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
maxdb:
zhongke:
api-key: application-5479ccf9b59c66432e5529febe94719a
application-id: 1a0e5e60-f1bd-11ef-a7de-0242ac110002
chat-url: http://192.168.0.122:8080/api/application/%s/chat/open
talk-url: http://192.168.0.122:8080/api/application/chat_message/%s
screen:
api-key: application-6e8250fa092a566c7c0aea0e08c9b1a3
application-id: adc51c8c-f3f4-11ef-a70b-0242ac110002
chat-url: http://192.168.0.122:8080/api/application/%s/chat/open
talk-url: http://192.168.0.122:8080/api/application/chat_message/%s
server:
port: 8888
tomcat:
max-swallow-size: 104857600
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment