您的位置:首页 > 文旅 > 美景 > 南京商城网站建设_如何制作个人网页页_厦门网站关键词推广_市场调研报告怎么写

南京商城网站建设_如何制作个人网页页_厦门网站关键词推广_市场调研报告怎么写

2025/4/4 4:03:12 来源:https://blog.csdn.net/FBB360JAVA/article/details/145881074  浏览:    关键词:南京商城网站建设_如何制作个人网页页_厦门网站关键词推广_市场调研报告怎么写
南京商城网站建设_如何制作个人网页页_厦门网站关键词推广_市场调研报告怎么写

文章目录

  • 前言
  • 正文
    • 一、项目环境
    • 二、项目代码
      • 2.1 pom.xml
      • 2.2 DeepSeekController.java
      • 2.3 启动类
      • 2.4 logback-spring.xml
      • 2.5 application.yaml
      • 2.6 index.html
    • 三、页面调试
      • 3.1 参数提示
      • 3.2 开始请求
      • 3.3 手动断开

前言

作为一个Java程序员,了解前沿科技技术,也算是份内的事了。
DeepSeek 大模型,从开源到现在,一直在🔥。各个公司也基本都部署了自己的所谓满血版DeepSeek。

虽然官方是免费使用的,但是它太忙了。因此,很多能直接使用的,不太忙的DeepSeek应运而生。

我今天使用的就是“硅基流动版”DeepSeek!

本文的主旨是,使用SpringBoot接入DeepSeek,并提供一个调试页面,用来请求,和展示结果。

硅基流动DeepSeek页面:
https://m.siliconflow.cn/playground/chat
硅基流动推理模型接口文档:
https://docs.siliconflow.cn/cn/userguide/capabilities/reasoning

正文

一、项目环境

  • Java版本:Java1.8
  • SpringBoot版本:2.7.7
  • deepseek-spring-boot-starter:1.1.0

项目结构如下:
在这里插入图片描述

二、项目代码

2.1 pom.xml

<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"><modelVersion>4.0.0</modelVersion><groupId>org.pine.ai</groupId><artifactId>pine-ai</artifactId><version>1.0-SNAPSHOT</version><packaging>jar</packaging><name>pine-ai-demo</name><url>http://maven.apache.org</url><properties><java.version>1.8</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-boot.version>2.7.7</spring-boot.version></properties><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.34</version><scope>provided</scope><optional>true</optional></dependency><dependency><groupId>io.github.pig-mesh.ai</groupId><artifactId>deepseek-spring-boot-starter</artifactId><version>1.1.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.7.7</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.11</version></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>1.8</source><target>1.8</target><encoding>UTF-8</encoding></configuration></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>2.7.7</version><configuration><mainClass>org.pine.ai.BootDemoApplication</mainClass><skip>true</skip></configuration><executions><execution><id>repackage</id><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins></build>
</project>

2.2 DeepSeekController.java

package org.pine.ai.controller;import io.github.pigmesh.ai.deepseek.core.DeepSeekClient;
import io.github.pigmesh.ai.deepseek.core.chat.ChatCompletionRequest;
import io.github.pigmesh.ai.deepseek.core.chat.ChatCompletionResponse;
import io.github.pigmesh.ai.deepseek.core.chat.ResponseFormatType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import reactor.core.publisher.Flux;import javax.annotation.Resource;
import java.util.List;@Controller
@Slf4j
@RequestMapping("/deepseek")
public class DeepSeekController {@Resourceprivate DeepSeekClient deepSeekClient;@GetMapping(value = "/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)public Flux<ChatCompletionResponse> chat(@RequestParam("prompt") String prompt,@RequestParam(value = "model", defaultValue = "deepseek-ai/DeepSeek-R1") String model,@RequestParam(value = "temperature", defaultValue = "0.7") Double temperature,@RequestParam(value = "frequencyPenalty", defaultValue = "0.5") Double frequencyPenalty,@RequestParam(value = "user", defaultValue = "user") String user,@RequestParam(value = "topP", defaultValue = "0.7") Double topP,@RequestParam(value = "maxCompletionTokens", defaultValue = "1024") Integer maxCompletionTokens) {log.info("prompt: {}", prompt);log.info("model: {}, temperature: {}, frequencyPenalty: {}, user: {}, topP: {}, maxCompletionTokens: {}", model, temperature, frequencyPenalty, user, topP, maxCompletionTokens);if (!StringUtils.hasText(prompt)) {throw new IllegalArgumentException("prompt is empty");}ChatCompletionRequest request = ChatCompletionRequest.builder()// 添加用户输入的提示词(prompt),即模型生成文本的起点。告诉模型基于什么内容生成文本。.addUserMessage(prompt)// 指定使用的模型名称。不同模型可能有不同的能力和训练数据,选择合适的模型会影响生成结果。.model(model)// 是否以流式(streaming)方式返回结果。.stream(true)// 控制生成文本的随机性。0.0:生成结果非常确定,倾向于选择概率最高的词。1.0:生成结果更具随机性和创造性。.temperature(temperature)// 控制生成文本中重复内容的惩罚程度。0.0:不惩罚重复内容。1.0 或更高:减少重复内容,增加多样性。.frequencyPenalty(frequencyPenalty)// 标识请求的用户。用于跟踪和日志记录,通常用于区分不同用户的请求。.user(user)// 控制生成文本时选择词的范围。0.7:从概率最高的 70% 的词中选择。1.0:不限制选择范围。.topP(topP)// 控制模型生成的文本的最大长度。这对于防止生成过长的文本或确保响应在预期的范围内非常有用。.maxCompletionTokens(maxCompletionTokens)// 响应结果的格式。.responseFormat(ResponseFormatType.TEXT).build();return deepSeekClient.chatFluxCompletion(request);}
}

2.3 启动类

package org.pine.ai;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.CrossOrigin;@SpringBootApplication
@CrossOrigin(origins = "*",allowedHeaders = "*",exposedHeaders = {"Cache-Control", "Connection"}  // 暴露必要头
)
public class BootDemoApplication {public static void main(String[] args) {SpringApplication.run(BootDemoApplication.class, args);}}

2.4 logback-spring.xml

<?xml version="1.0" encoding="UTF-8" ?>
<configuration debug="false"><!-- 配置控制台输出 --><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><!-- 格式化输出: %d表示日期, %thread表示线程名, %-5level: 级别从左显示5个字符宽度 %msg:日志消息, %n是换行符 --><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS}[%thread] %-5level %logger{50} - %msg%n</pattern></encoder></appender><!-- 日志输出级别 --><root level="INFO"><appender-ref ref="STDOUT"/></root>
</configuration>

2.5 application.yaml

deepseek:# 硅基流动的urlbase-url: https://api.siliconflow.cn/v1# 秘钥(自己注册硅基的账号,并申请即可)api-key: sk-ezcxadqecocxixxxxxxx
spring:main:allow-bean-definition-overriding: trueserver:tomcat:keep-alive-timeout: 30000  # 30秒空闲超时max-connections: 100       # 最大连接数uri-encoding: UTF-8servlet:encoding:charset: UTF-8force: trueenabled: truecompression:enabled: false  # 禁用压缩(否则流式数据可能被缓冲)

2.6 index.html

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>调用演示</title><style>body {padding: 20px;font-family: Arial, sans-serif;}#output {height: 400px;width: 900px;border: 2px solid #c7c1c1;padding: 10px;overflow-y: auto;margin: 20px 0;white-space: pre-wrap;box-shadow: 0 4px 6px rgba(13, 118, 231, 0.25);}button {padding: 10px 20px;background: #007bff;color: white;border: none;border-radius: 4px;cursor: pointer;}.danger-button {background-color: #ec1b1b;}.form-group {margin: 20px 0;max-width: 900px;}label[for="promptInput"] {display: block;margin-bottom: 12px;font-size: 1.1em;color: #2c3e50;font-weight: 600;letter-spacing: 0.5px;}label[for="paramInput"] {display: block;margin-bottom: 12px;font-size: 1.1em;color: #2c3e50;font-weight: 600;letter-spacing: 0.5px;}#promptInput, #paramInput {/* 尺寸调整 */width: 100%;padding: 14px 20px;/* 样式美化 */border: 2px solid #007bff;border-radius: 8px;font-size: 1.1rem;background-color: #f8f9fa;transition: all 0.3s ease-in-out;box-shadow: 0 2px 4px rgba(0,0,0,0.05);color: #44878c;font-style: italic;}#promptInput, #paramInput:focus {outline: none;border-color: #0056b3;box-shadow: 0 4px 6px rgba(0,123,255,0.25);background-color: white;}/* 暗色模式适配 */@media (prefers-color-scheme: dark) {#promptInput, #paramInput {background-color: #2d3436;border-color: #4a90e2;color: #ecf0f1;}#promptInput, #paramInput:focus {background-color: #34495e;}}/* 输入提示动画 */@keyframes pulse-shadow {0% { box-shadow: 0 0 0 0 rgba(0,123,255,0.4) }100% { box-shadow: 0 0 0 10px rgba(0,123,255,0) }}.input-highlight {animation: pulse-shadow 1.5s infinite;}</style>
</head>
<body><div class="form-group"><label for="promptInput">URL + Prompt 提示词:</label><input type="text"id="promptInput"value="http://localhost:8080/deepseek/chat?prompt="class="styled-input">
</div><div class="form-group"><label for="paramInput">参数串:</label><input type="text"id="paramInput"value="model=deepseek-ai/DeepSeek-R1&temperature=0.7&frequencyPenalty=0.5&user=user&topP=0.7&maxCompletionTokens=1024"class="styled-input">
</div><button onclick="start()">开始请求</button>
<button onclick="disconnectAiServer()" class="danger-button">断开连接</button>
<button onclick="tips()">参数提示</button>
<div id="output"></div><script>let eventSource;function connectAiServer(url) {eventSource = new EventSource(url);}function disconnectAiServer() {if (eventSource) {eventSource.close()}}function start() {const output = document.getElementById('output')const promptInput = document.getElementById('promptInput')const paramInput = document.getElementById('paramInput')output.textContent = '' // 清空内容try {// 创建 EventSource 连接connectAiServer(promptInput.value + "&" + paramInput.value)// 监听默认事件(无事件名的消息)eventSource.onmessage = (event) => {const value = event.data;const data = JSON.parse(value);if (data.choices[0].delta.reasoning_content === '') {output.textContent += '开始思考:\n\t'}if (data.choices[0].delta.content === '\n\n') {output.textContent += '思考结束!!\n\n\n\n'output.textContent += '以下是正式回答:\n\n'}if(data.choices[0].delta.content === "" && data.choices[0].finish_reason === "stop") {output.textContent += '\r\n\r\n回答结束!!'disconnectAiServer()}// 拼接思考内容if (data.choices[0].delta.reasoning_content) {output.textContent += data.choices[0].delta.reasoning_content}// 拼接回答内容if (data.choices[0].delta.content) {output.textContent += data.choices[0].delta.content;}// 自动滚动到底部output.scrollTop = output.scrollHeight};} catch (error) {console.error('请求失败:', error)output.textContent = '请求失败: ' + error.messagedisconnectAiServer()}}/* 回车触发请求 */document.querySelector('#promptInput').addEventListener('keypress', (e) => {if(e.key === 'Enter') {start()}})function tips() {const output = document.getElementById('output')output.textContent = `参数说明:prompt:添加用户输入的提示词(prompt),即模型生成文本的起点。告诉模型基于什么内容生成文本。默认为:空\nmodel:不同模型可能有不同的能力和训练数据,选择合适的模型会影响生成结果。默认为:deepseek-ai/DeepSeek-R1\ntemperature:控制生成文本的随机性。0.0:生成结果非常确定,倾向于选择概率最高的词。1.0:生成结果更具随机性和创造性。默认为:0.7\nfrequencyPenalty:控制生成文本中重复内容的惩罚程度。0.0:不惩罚重复内容。1.0 或更高:减少重复内容,增加多样性。默认为:0.5\nuser:标识请求的用户。用于跟踪和日志记录,通常用于区分不同用户的请求。默认为:user\ntopP:控制生成文本时选择词的范围。0.7:从概率最高的 70% 的词中选择。1.0:不限制选择范围。默认为:0.7\nmaxCompletionTokens:控制模型生成的文本的最大长度。这对于防止生成过长的文本或确保响应在预期的范围内非常有用。默认为:1024\n`}</script>
</body>
</html>

三、页面调试

启动项目后,访问:http://localhost:8080/

3.1 参数提示

点击参数提示
在这里插入图片描述

3.2 开始请求

在【URL + Prompt参数提示】的输入框中,追加你要问的问题。然后点击【开始请求】或直接【回车】。
在这里插入图片描述

3.3 手动断开

点击【断开连接】。将会停止回答。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com