spring AI 的简单使用

1. 引入

Spring 官⽅推出的⾸个稳定版⼈⼯智能(AI)集成框架. 旨在帮助 Java/Spring 开发者更便捷地在企业级应⽤中集成 AI 能⼒ (如⼤语⾔模型、机器学习、向量数据库、图像⽣成等)。
它主要提供了以下功能:
• ⽀持主要的AI模型提供商, ⽐如 Anthropic、OpenAI、Microsoft、Amazon、Google 和 Ollama, 此外它⽀持的模型种类也⾮常多, ⽐如: 聊天模型, 嵌⼊模型, 图像模型, ⾳频模型, 内容审核等.
• 跨 AI 提供商的可移植 API ⽀持. ⽀持聊天 (Chat) , ⽂本到图像 (text-to-image) 和嵌⼊(Embedding) 模型的统⼀接⼝, 同时提供同步和流式 API 选项. ⽀持访问模型特定功能.
总之, Spring AI 为 ⾮AI专家的开发者也能快速调⽤⼤语⾔模型, 提供了构建 AI 应⽤的基础抽象层, 允许开发⼈员通过极少的代码修改即可轻松替换组件, 简化集成了AI功能的应⽤程序开发。
spring AI 官网 链接

2. 术语介绍

2.1 模型

模型是人工智能系统的核心组件,通过算法和大量数据训练而成,能够执行特定任务,如预测、分类或生成内容,⽐如ChatGPT、DeepSeek、通义千问等等. 每种模型能⼒不同, 适合的任务也不同。
我们给模型的叫 输入;模型返回给我们的叫 输出

Spring AI 的能让我们在 Java/Spring 应⽤中, 能更方便地:① 选择不同的 模型 ;
② 构造和发送 输⼊ (Prompt) ;③接收并处理 输出 (AI 的响应) 。

2.2 LLM

LLMLarge Language Model 大语言模型,也称⼤型语⾔模型。是⼈⼯智能模型中专⻔处理⽂本的⼀种类型, 属于语⾔模型的范畴。
特点是:规模庞⼤, 参数数量通常在数百亿到万亿级别。
以下是几个代表模型:
• GPT-5(OpenAI)
◦ ⽀持 128K⻓上下⽂(128K token的上下文长度大约可以支持128,000个汉字) , 在多轮复杂推理、创意写作中表现突出
• DeepSeek R1(深度求索)
◦ 开源, 专注于逻辑推理与数学求解, ⽀持128K⻓上下⽂和多语⾔ (20+语⾔) , 在科技领域表现突出
• Qwen2.5-72B-Instruct (阿⾥巴巴)
◦ 通义千问开源模型家族重要成员, 擅⻓代码⽣成结构化数据 (如JSON) 处理⻆⾊扮演对话等, 尤其适合企业级复杂任务, ⽀持包括中⽂英⽂法语等29种语⾔
• Gemini 2.5 Pro (Google)
◦ 多模态融合标杆 , ⽀持图像/代码/⽂本混合输⼊, 适合跨模态任务 (如图⽂⽣成、技术⽂档解析)

2.3 提示词

提示词是用户或系统提供给大语言模型 (LLM) 的指令或文本 ,用于引导模型生成特定输出。
用户提示词:我们使用 ai 工具时,发给 它 的文字,文件等就属于 用户提示词。
系统提示词:一般是开发者预设的,它 对 ai 进行了行为预设,划定边界等,像你使用 ai 时,它告诉你问题暂时不能回答之类的,就是受到了系统提示词的规范。

2.4 词元

词元(即 Token)是自然语言处理(NLP)中的基本单位,指文本分割后的最小语义单元。使文本被拆解为模型可理解的离散单元.。

词元具体形式取决于分词策略,可以是单词、子词(Subword)、字符或符号。例如,英文句子“I love NLP”可能被拆分为词元 [“I”, “love”, “NLP”],而中文句子“我喜欢NLP”可能被拆分为 [“我”, “喜欢”, “NLP”]。不同模型的分词策略不同, 同一个词在不同模型中可能被拆分成不同词元。

前面的 模型的上下文 (如128K) 指的就是词元数量限制, 此外,如果充值使用 AI 的 API,就会知道收费通常按词元数计费。 词元数越多, 计算耗时和内存占用越⾼,因此在使用时, 应尽量避免冗余词(如请, 谢谢) ,这样不仅能省钱,还可以给 AI 减负。

3. Spring AI 快速入门

3.1 环境要求

JDK 要至少 JDK17 或以上版本。
Spring Boot 版本至少 3.2 以上。
IDEA 使用 专业版。

3.2 条件准备

3.2.1 deepseek api 申请

DeepSeek 网址
在这里插入图片描述
进入 API 开放平台,先进行充值(1 块钱一般就够用了)。
在这里插入图片描述

然后在 API keys 中进行 API 申请。
注意:这里要记住 API keys,因为它只在创建时显示,后面都不显示了。如果,手太快点了关闭,没有记住那就再申请一个。
此外,别人如果知道了你的 API key 也是可以使用的,所有要妥善报存。

3.2.2 阿里云百炼平台API-KEY 申请

阿里云百炼平台 API 申请,
按照网页说明进行申请,新人有 百万 token 的免费额度
在这里插入图片描述

3.3 基于 deepseek 的简单使用

Spring AI 为OpenAI及兼容的API服务(如DeepSeek)设计了Starter spring-ai-openaispring-boot-starter , 用于快速集成大语⾔模型能力到 Spring Boot 应用中.
核心价值包括:
• 简化配置:自动动封装 OpenAI API 的请求/响应等逻辑
• 统⼀接口:提供 ChatClient 等标准化接口, 支持无缝切换不同模型提供商
• Spring ⽣态集成:与 Spring Boot 的⾃动配置、依赖注⼊等特性深度整合

3.3.1 项目创建

Spring AI 中
在这里插入图片描述
在这里插入图片描述

3.3.2 配置文件设置

这里用的 .yml 进行配置,不是 .properties

spring:ai:openai:api-key: sk-your-key  #你申请的 api keybase-url: https://api.deepseek.comchat:options:model: deepseek-chat  #使用的 deepseek 模型temperature: 0.7  
#在AI模型的temperature参数中,值的大小直接影响生成文本的特性:
#较低值(如0.1-0.3):输出更加确定性和保守,倾向于选择最高概率的词汇,适合需要准确性和一致性的场景
#中等值(如0.4-0.7):在创造性和可靠性之间取得平衡,会产生适度变化的输出
#较高值(如0.8-1.0):输出更加随机和创造性,适合需要多样性和新颖性的场景
#您当前设置的0.7属于中等偏高,会使模型输出有一定创造性但不会过于随机

3.3.3 ChatModel 使用

package com.example.saidemo;import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/dp")
public class DPChat {@AutowiredOpenAiChatModel openAiChatModel;@RequestMapping("/chat")public String chat(String message){//call() 调用AIreturn openAiChatModel.call(message);}
}

前面说过,deepseek 的 API 是兼容的,这里使用 OpenAiChatModel
使用示例:
在这里插入图片描述

3.3.4 ChatClient 使用

ChatModel 属于底层接口,而 ChatClient 则是高阶接口,它基于 ChatModel 进行了再次封装。ChatClient 使用链式调用,可读性更强。

简单对话

@RestController
@RequestMapping("/dp")
public class DPChat {private final ChatClient chatClient;public DPChat(ChatClient.Builder chatClientBuilder) {this.chatClient = chatClientBuilder.build();}@RequestMapping("/chat2")public String chat2(String message){return chatClient.prompt().user(message).call().content();}
}

ChatClient 不支持使用用 @Autowired 进行直接注入,需要调用 ChatClient.Builder 下的 build() 才可以。
使用示例:
在这里插入图片描述
角色预设
为了方便后续使用,我们将 ChatClient 单独定义。

package com.example.saidemo;import org.springframework.ai.chat.client.ChatClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class ChatClientConfig {@Beanpublic ChatClient chatClient(ChatClient.Builder chatClientBuilder){return chatClientBuilder.build();}
}

这样后面就可以直接使用 @Autowired 进行注入。

回顾前文,我们知道系统提示词能够对模型进行预设,为它指定规范。所以,这里的角色预设就是设置 系统提示词
操作如下:

package com.example.saidemo;import org.springframework.ai.chat.client.ChatClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class ChatClientConfig {@Beanpublic ChatClient chatClient(ChatClient.Builder chatClientBuilder){return chatClientBuilder.defaultSystem("你叫小明,你是一个不专业的写信者").build();}
}

使用 defaultSystem() 进行设置。
使用示例:
在这里插入图片描述
结构化输出
就是当你输入提示词后, AI 根据你所规定的结构,进行回答。
首先,我们使用JDK16提供的新关键词 record 来定义⼀个实体类

    record Recipe(String dish, List<String> ingredients) {}

通过 entity() ⽅法将模型输出转为自定义实体,(模型会自动匹配并填充)。

package com.example.saidemo;import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController
@RequestMapping("/dp")
public class DPChat {@AutowiredChatClient chatClient;record Recipe(String dish, List<String> ingredients) {}@RequestMapping("/chat3")public String chat1(String message){Recipe recipe = chatClient.prompt().user(String.format("请根据用户的描述,生成一个菜谱。用户的描述是:%s", message)).call().entity(Recipe.class);return recipe.toString();}
}    

使用示例:
在这里插入图片描述
流式输出
运行之前的代码,你会发现和常用的 AI 工具不同,它是直接将完整结果发送过来,这就导致用户等待时间过长。想要和使用的 AI 工具的输出效果相同,就要采用流式输出,逐步生成内容而非一次性返回完整结果。

package com.example.saidemo;import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;import java.util.List;@RestController
@RequestMapping("/dp")
public class DPChat {@AutowiredChatClient chatClient;@RequestMapping("/chat4")public Flux<String> chat1(String message){return chatClient.prompt().user(String.format("请根据用户的描述,生成一个菜谱。用户的描述是:%s", message)).stream().content();}
}

直接运行,你会发现输出结果为乱码:
在这里插入图片描述
这是因为没有对输出结果的类型进行设置,对 @RequestMapping("/chat4") 进行如下修改,就能够正确输出了。

    @RequestMapping(value = "/chat4" ,produces = "text/html;charset=utf-8")

运行结果:
在这里插入图片描述
(流式效果不好展示,这里只展示最终效果,感兴趣的可以自己试一试)

打印日志
Spring AI 借助Advisors 来实现日志打印的功能.。

Advisors 是基于 AOP思想实现的, 在具体实现上进行了领域适配. 其设计核心借鉴了Spring AOP 的拦截机制, 各个Advisor以链式结构运⾏,序列中的每个Advisor都有机会对传入的请求和传出的响应进行处理。 这种链式处理机制确保了每个Advisor可以在请求和响应流中添加自己的逻辑, 从而实现更灵活和可定制的功能。如下图:
在这里插入图片描述
主要应用场景:
• 敏感词过滤
• 建⽴聊天历史
• 对话上下⽂管理

可以直接在Config 中添加,那么后续使用 ChatClient 都会有。

package com.example.saidemo;import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class ChatClientConfig {@Beanpublic ChatClient chatClient(ChatClient.Builder chatClientBuilder){return chatClientBuilder.defaultSystem("你叫小明,你是一个不专业的写信者").defaultAdvisors(new SimpleLoggerAdvisor()).build();}
}

同样,也可以在单个接口中添加,仅对这一个起作用:

@RestController
@RequestMapping("/dp")
public class DPChat {@AutowiredChatClient chatClient;@RequestMapping(value = "/chat4" ,produces = "text/html;charset=utf-8")public Flux<String> chat1(String message){return chatClient.prompt().user(String.format("请根据用户的描述,生成一个菜谱。用户的描述是:%s", message)).advisors(new SimpleLoggerAdvisor()).stream().content();}
}

3.3.5 ChatModel 拓展

Ctrl + 左键进入之前代码中的 call() 方法,会发现它调用了 参数类型为 Promptcall() 方法。

接下来使用 Prompt 来使用 call() 方法。
简单使用

    @RequestMapping("/chatByPrompt")public String chatByPrompt (String msg) {Prompt prompt = new Prompt(msg);ChatResponse response = chatModel.call(prompt);return response.getResult().getOutput().getText();}

角色预设

    @RequestMapping("/role")public String role(String msg) {SystemMessage systemMessage = new SystemMessage("你叫dp,是对话ai机器人");UserMessage userMessage = new UserMessage(msg);Prompt prompt = new Prompt(userMessage,systemMessage);ChatResponse response = chatModel.call(prompt);return response.getResult().getOutput().getText();}

流式响应

    @RequestMapping(value = "/stream" ,produces = "text/html;charset=utf-8"  )public Flux<String> stream (String msg) {Prompt prompt = new Prompt(msg);Flux<ChatResponse> response = chatModel.stream(prompt);return response.map(x->x.getResult().getOutput().getText());}

.map(x->x.getResult().getOutput() .getText()) 方法,用于操作流中元素。
基于代码可知,chatModel.stream(prompt); 的返回类型为 Flux<ChatResponse>。你可以理解为 response (流) 是一辆列车,是由很多节组成的连续一长串,这每一节都是 类型为 ChatResponse 的元素。

map 方法则是操作每一节,并返回生成新的 流,且不改变原流。这里 x 就代指 response 中的元素(也可以使用其他字母来代指),x 经过 getResult().getOutput().getText() 就变成了 String 类型,所以新的流就是 Flux<String> 类型。

3.3.6 Client & Model 对比

维度ChatModelChatClient
交互⽅式⼿动构建Prompt, 解析响应链式API, ⾃动封装请求与响应
结构化输出⼿动解析⽂本⽀持 .entity(Class) ⾃动映射POJO
扩展能⼒依赖外部组件内置Advisor机制, 提供更⾼级的功能, 如提供上下⽂记忆, RAG等功能
适合场景适合需要精细控制模型参数的场景, ⽐如模型实验, 参数调优等定制需求适合快速构建AI服务, 如带记忆的客服系统

3.4 流式编程 - 资料了解

HTTP 协议本身设计为无状态的 请求-响应模式,严格来说, 是无法做到服务器主动推送消息到客户端, 但通过Server-Sent Events (服务器发送事件, 简称SSE)技术可实现流式传输,允许服务器主动向浏览器推送数据流。
服务器会告诉客户端,接下来要发送的是流消息(streaming), 这时客户端不会关闭连接,会⼀直等待服务器发送过来新的数据流。
SSE(Server-Sent Events)是⼀种基于 HTTP 的轻量级实时通信协议,浏览器通过内置的
EventSource API接收并处理这些实时事件。
特点:
基于 HTTP 协议
复⽤标准了 HTTP/HTTPS 协议,⽆需额外端⼝或协议,兼容性好且易于部署 。
单向通信机制
SSE 仅支持服务器向客户端的单向数据推送,客户端通过普通 HTTP 请求建⽴连接后,服务器可持续发送数据流,但客户端无法通过同⼀连接向服务器发送数据。
自动重连机制
⽀持断线重连,连接中断时,浏览器会⾃动尝试重新连接(⽀持 retry 字段指定重连间隔)
自定义消息类型
客户端发起请求后,服务器保持连接开放, 响应头设置 Content-Type: text/event-stream,标识为事件流格式, 持续推送事件流。

数据格式
每⼀次发送的消息,由若干个message组成, 每个message之间由 \n\n 分隔, 每个message内部由若干行组成, 每⼀行都是如下格式:

[field]: value\n

前端代码:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>SSE</title>
</head>
<body><div id="sse"></div>
</body>
<script>let eventSource = new EventSource('/sse/data')eventSource.onmessage = function (event) {document.getElementById('sse').innerHTML = event.data;}// eventSource.addEventListener('foo', (event) => {//     document.getElementById('sse').innerHTML = event.data;// })// eventSource.addEventListener('end', (event) => {//     eventSource.close()// })
</script>
</html>

EventSource('/sse/data') 中填写的是后端接口。
后端代码:

package com.example.saidemo;import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;import java.awt.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.time.Duration;
import java.util.Date;@Slf4j
@RequestMapping("/sse")
@RestController
public class SseController {@RequestMapping("/data")public void data(HttpServletResponse response) throws IOException, InterruptedException {log.info("返回响应:  data");response.setContentType("text/event-stream;charset=utf-8");PrintWriter writer = response.getWriter();for (int i = 0; i < 10; i++) {String s = "data: " + new Date() + "\n\n";writer.write(s);writer.flush();Thread.sleep(1000L);}}@RequestMapping("/retry")public void retry(HttpServletResponse response) throws IOException, InterruptedException {log.info("返回响应:  retry");response.setContentType("text/event-stream;charset=utf-8");PrintWriter writer = response.getWriter();String s = "retry: 2000\n";s += "data: " + new Date() + "\n\n";writer.write(s);writer.flush();}@RequestMapping("/event")public void event(HttpServletResponse response) throws IOException, InterruptedException {log.info("返回响应:  event");response.setContentType("text/event-stream;charset=utf-8");PrintWriter writer = response.getWriter();for (int i = 0; i < 10; i++) {String s = "event: foo\n";  //自定义事件,对应前端注释掉的代码s += "data: " + new Date() + "\n\n";writer.write(s);writer.flush();Thread.sleep(1000L);}}@RequestMapping("/end")public void end(HttpServletResponse response) throws IOException, InterruptedException {log.info("返回响应:  event");response.setContentType("text/event-stream;charset=utf-8");PrintWriter writer = response.getWriter();for (int i = 0; i < 10; i++) {String s = "event: foo\n";	//自定义事件,对应前端注释掉的代码s += "data: " + new Date() + "\n\n";writer.write(s);writer.flush();Thread.sleep(1000L);}writer.write("event: end\ndata: EOF\n\n");}@RequestMapping(value = "/stream",produces = MediaType.TEXT_EVENT_STREAM_VALUE)public Flux<String> stream() {return Flux.interval(Duration.ofSeconds(1)) //发送间隔.map(s->new Date().toString());  }
}

自动重连的体现:
在这里插入图片描述
运行后,访问前端页面,发现数字一直在改变。但实际后端 /sse/data 接口中只定义发送 10 次。这是因为当该接口的完整逻辑执行完后,进行了自动重连。

3.5 基于 Spring AI Alibaba 的简单使用

3.5.1 项目创建

项目创建时,添加的依赖:
在这里插入图片描述

3.5.2 配置文件设置

pom 文件的配置:

<dependencyManagement><dependencies><dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-bom</artifactId><version>1.0.0.2</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement><dependencies><dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-starter-dashscope</artifactId></dependency>
</dependencies>

.yml 文件配置:

spring:ai:dashscope:api-key: #你在百炼平台申请的 API KEYchat:options:model: qwen-vl-max-latest #模型名称multi-model: true #是否启⽤多模型

3.5.3 ChatModel 使用

由于使用类似,不同的是 这里使用 ChatModel 类,不再使用 OpenAiChatModel
所以,不再细说,只进行代码展示和必要说明。

package com.example.salidemo;import org.springframework.ai.chat.model.ChatModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/ali")
public class AliController {@Autowiredprivate ChatModel chatModel;@RequestMapping("/chat")public String chat(String message){return chatModel.call(message);}
}

使用示例:
在这里插入图片描述

3.5.4 ChatClient 使用

直接使用

package com.example.salidemo;import org.springframework.ai.chat.client.ChatClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;import java.util.List;@RestController
@RequestMapping("/chat")
public class ChatController {private ChatClient chatClient;public ChatController(ChatClient.Builder chatClientBuilder) {this.chatClient = chatClientBuilder.build();}@RequestMapping("/chat")public String chat(String message){return chatClient.prompt().user(message).call().content();}
}    

角色预设
这里同样将 ChatClient 单独迁出,并使用 @Bean 注解进行注入。

单独类:

package com.example.salidemo;import org.springframework.ai.chat.client.ChatClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class ChatConfiguration {@Beanpublic ChatClient chatClient(ChatClient.Builder chatClientBuilder){return chatClientBuilder.defaultSystem("你是一个专业的演员,在每次回复前加上{word}").build();}
}

这里的 {word} 就相当于占位符,在实际使用时可进行替换,否则 原样输出。像这样:
在这里插入图片描述

    @RequestMapping("/word")public String word(String message,String word){return chatClient.prompt().user(message).system(sp->sp.param("word",word)).call().content();}

system(sp->sp.param("word",word)) 替换操作。sp 是Lambda表达式的参数名称,可以自由命名,但必须与后续调用保持一致。
如果有多个参数,使用方法如下:

//链式调用param方法:
.system(sp -> sp.param("word1", word1).param("word2", word2).param("word3", word3))//使用Map传递多个参数:
Map<String, Object> params = new HashMap<>();
params.put("word1", word1);
params.put("word2", word2);
.system(sp -> sp.params(params))//使用对象封装参数(推荐):
record WordParams(String word1, String word2) {}
.system(sp -> sp.entity(new WordParams(word1, word2)))

之前的 基于 deepseek 的ChatClient 同样适用。

结构化输出

    record ActorFilms(String actor, List<String> films){}@RequestMapping("/entify")public String entify(String actor){return chatClient.prompt().user(String.format("帮我生成%S参演的作品",actor)).call().entity(ActorFilms.class).toString();}

流式输出

    @RequestMapping(value = "/stream",produces = "text/html;charset=utf-8")public Flux<String> stream(String message){return this.chatClient.prompt().user(message).stream().content();}

3.5.5 多模态的使用。

多模态性指模型同时理解和处理文本、图像、音频及其他数据格式等多源信息的能力。
这里展示 处理图片的能力。

@RestController
@RequestMapping("/multi")
public class MultiController {private final ChatClient chatClient;public MultiController(ChatClient.Builder chatClientBuilder) {this.chatClient = chatClientBuilder.build();}@RequestMapping("/image")public String image(String prompt) throws URISyntaxException, MalformedURLException {String url = "https://tse4-mm.cn.bing.net/th/id/OIP-C.TCq0ItOzbTzC11dudmqMrgHaLJ?w=195&h=294&c=7&r=0&o=5&dpr=1.5&pid=1.7";//网上随便找的网图List<Media> mediaList = List.of(new Media(MimeTypeUtils.IMAGE_JPEG, new URI(url).toURL().toURI()));//用户提示词UserMessage userMessage = UserMessage.builder().text(prompt).media(mediaList).build();//调用模型String response = chatClient.prompt(new Prompt(userMessage)).call().content();return response;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/95805.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/95805.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

图像去雾:从暗通道先验到可学习融合——一份可跑的 PyTorch 教程

一、为什么“去雾”依然是好课题&#xff1f; 真实需求大&#xff1a;手机拍照、自动驾驶、遥感、监控都要在恶劣天气下成像。 数据集相对干净&#xff1a;与通用目标检测相比&#xff0c;去雾只有“有雾/无雾”一对图像&#xff0c;标注成本低。 传统与深度并存&#xff1a;…

Ubuntu 22.04.1上安装MySQL 8.0及设置root密码

安装MySQL 8.0 在 Ubuntu 22.04.1 系统需要遵循几个明确的步骤&#xff0c;并在安装过程中配置root密码&#xff0c;以下是详细的过程和相关的注意事项。步骤 1: 更新系统 使用终端更新系统软件包列表以确保所有的包是最新的。sudo apt update sudo apt upgrade步骤 2: 安装MyS…

用 content-visibility 即刻提速:那个被你忽略的 CSS 性能杠杆

我有一支技术全面、经验丰富的小型团队&#xff0c;专注高效交付中等规模外包项目&#xff0c;有需要外包项目的可以联系我&#x1f50d; 引言长页面、信息密集、滚动迟滞&#xff1f;**content-visibility** 这项相对较新的 CSS 属性&#xff0c;允许浏览器跳过视口外元素的渲…

字符串(2)

4.字符串的常见函数代码#include <stdio.h> #include <string.h> int main() {char* str1 "abc";char str2[100] "abc";char str3[5] { q,w,e,r ,\0 };printf("---------------------strlen&#xff08;长度&#xff09;-------------…

案例分享|企微智能会话风控系统:为尚丰盈铝业筑牢沟通安全防线

企微智能会话安全风险分析系统是一款基于企业微信原生集成的高性能处理平台&#xff0c;其核心在于通过智能监测和AI风险识别技术&#xff0c;对员工与内外部客户的聊天内容进行多模态分析&#xff08;涵盖文本、图片、语音、视频、文件等多种形式&#xff09;&#xff0c;利用…

Paimon——官网阅读:配置

配置(Maintenance) 系统表 表特定系统表 表特定系统表包含关于每个表的元数据和信息&#xff0c;例如创建的快照以及正在使用的选项。用户可以通过批量查询来访问系统表。 目前&#xff0c;Flink、Spark、Trino 和 StarRocks 支持查询系统表。 在某些情况下&#xff0c;表…

阿里云对象存储OSS的使用

文章目录注册阿里OSS注册并登录阿里云账号开通对象存储OSS创建Bucket修改权限创建AccessKey全局存储到你的计算机(可以跳过)查看官方文档(可以跳过)SSM使用引入依赖在spring-mvc.xml中加入配置创建上传工具类AliOssUtil响应工具类ResultJSON编写controller编写前端代码使用Elme…

香港云主机常见使用问题汇总

本文主要为初次或正在接触香港云主机的用户介绍&#xff0c;对于香港云服务器的一些问题进行解答&#xff0c;帮助用户更好的了解香港云主机&#xff0c;熟悉香港云主机。1.香港云主机是否需要备案?香港云主机无需进行像内地服务器那样的 ICP 备案&#xff0c;可直接部署使用。…

JAVA同城打车小程序APP打车顺风车滴滴车跑腿源码微信小程序打车源码

JAVA同城打车系统源码&#xff1a;多端融合的智能出行生态解决方案一、市场需求与行业背景在共享经济蓬勃发展和数字化转型加速的背景下&#xff0c;中国同城出行市场正迎来快速增长期。2025年中国同城出行市场规模预计突破8000亿元&#xff0c;年复合增长率超过25%。基于Sprin…

AI入坑: Trae 通过http调用.net 开发的 mcp server

1. 为什么要写这个 为什么要写这个内容&#xff0c;前几天开始加入到ai大军&#xff0c;通过一周的学习&#xff0c;看了国外网站、看了b站教程、看了抖音教程&#xff0c;居然发现都是开发在本地的mcp server。本地mcp没问题&#xff0c;个人使用都ok&#xff0c;或者通过npx下…

记录Pycharm所使用虚拟环境与终端无法对应

在anaconda安装时&#xff0c;本文中的安装位置在D盘&#xff0c; D:\soware\anaconda 理论环境位置 D:\soware\anaconda\envs 经检查PATH配置均未发现错误&#xff0c;其次问题并不在于Pycharm的设置中解译器与终端的设置经过多次查找未发现可用解决方案 在anaconda建立虚拟环…

国产数据库之YashanDB:新花怒放

YashanDB&#xff08;崖山数据库&#xff09;是由深圳计算科学研究院自主研发的一款新型关系数据库管理系统。 YashanDB 在经典数据库理论基础上&#xff0c;融入了原创的有界计算、近似计算、并行可扩展和跨模融合计算理论&#xff0c;可以满足金融、政企、能源等关键行业对高…

Java基础 9.5

1.异常处理基本介绍异常处理就是当异常发生的时候 对异常处理的方式异常处理方式try-catch-finally程序员在代码中捕获发生的异常 自行处理throws将发生的异常抛出 交给调用者&#xff08;方法&#xff09;处理 最顶级的处理者是JVM示意图2.try-catch方式处理异常说明Java提供t…

B.50.10.06-NoSQL数据库与电商应用

NoSQL数据库核心原理与电商应用实战核心思想: NoSQL (Not Only SQL) 数据库是为了解决传统关系型数据库在超大规模数据、高并发和灵活数据模型方面的不足而设计的。它们通过牺牲部分一致性&#xff08;通常是最终一致性&#xff09;和事务的严格性&#xff0c;来换取极高的性能…

把开发环境丢云上,我的电脑风扇再也没转过!

Hello&#xff0c;兄弟们&#xff0c;我来啦作为一个天天搬砖的程序员&#xff0c;每天最让我心态爆炸的是啥&#xff1f;不是产品又改需求&#xff0c;也不是 Bug 藏得深&#xff0c;而是TMD——配&#xff01;环&#xff01;境&#xff01;新项目 git clone 下来&#xff0c;…

驱动ft232h通信

FT232H是一个单通道USB 2.0高速&#xff08;480Mb/s&#xff09;转换为UART/FIFO IC&#xff0c;具有多种工业标准串行或并行接口配置能力。 1.实验板卡 FPGA型号&#xff1a; FT232H型号&#xff1a; FT232H SINGLE CHANNEL HI-SPEED USB TO MULTIPURPOSE UART/FIFO IC Da…

隔空盗刷、AI钓鱼、代理劫持…金融黑产竟进化至此?

【导读】中国工商银行发布的《2024网络金融黑产研究报告》&#xff0c;以深度洞察拆解黑产攻击“新变种”、勾勒防护新路径&#xff0c;自发布以来&#xff0c;成为金融安全行业的重要参考坐标。本文会提炼出报告中黑产攻击的五大技术演变与体系化防护思路&#xff0c;再结合金…

服务器为啥离不开传感器?一文看懂数据中心“隐形守护者”的关键角色

在现代数据中心或企业机房中&#xff0c;服务器不仅仅是“跑程序”的机器&#xff0c;它们还是一整套复杂系统的一部分。为了保证这些服务器稳定、高效、安全地运行&#xff0c;传感器成了不可或缺的角色。那么&#xff0c;服务器为啥要有传感器&#xff1f;这些传感器到底是干…

React JSX 语法讲解

&#x1f680; React JSX 语法讲解 1. 课程概述 本课程旨在系统讲解 JSX&#xff08;JavaScript XML&#xff09; 的核心概念与实战应用。JSX 是 React 的核心语法扩展&#xff0c;它允许我们在 JavaScript 中编写类似 HTML 的结构&#xff0c;使得构建用户界面变得直观和高效。…

软件安装教程(四):在 Windows 上安装与配置 MATLAB(超详细)

文章目录前言1. 安装前准备&#xff08;必看&#xff09;2. 下载 MATLAB&#xff08;推荐在线安装&#xff09;3. 在 Windows 上安装&#xff08;详细步骤&#xff09;4. 激活 MATLAB&#xff08;在线与离线&#xff09;5. 首次启动与界面入门6. 推荐的基本配置&#xff08;让环…