大模型专栏--Spring Ai Alibaba介绍和功能演示
Spring AI Alibaba 介绍和功能演示
背景
Spring AI Alibaba 开源项目基于 Spring AI 构建,是阿里云通义系列模型及服务在 Java AI 应用开发领域的最佳实践,提供高层次的 AI API 抽象与云原生基础设施集成方案,帮助开发者快速构建 AI 应用。
Spring AI Alibaba 生态图如下:
演示
在此节中,将演示如何使用 Spring AI Alibaba 提供的接口功能完成和 LLMs 的交互。
框架搭建
pom.xml
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>3.3.4</version></dependency><!-- 最新版本 Spring AI Alibaba --><dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-starter</artifactId><version>1.0.0-M3.1</version></dependency></dependencies><!-- 添加仓库配置,否则报错,如果添加之后仍然报错,刷新 mvn 或者清楚 IDEA 缓存 --><repositories><repository><id>spring-milestones</id><name>Spring Milestones</name><url>https://repo.spring.io/milestone</url><snapshots><enabled>false</enabled></snapshots></repository></repositories><!-- 解决报错: Name for argument of type [java.lang.String] not specified, and parameter name information not available via reflection. Ensure that the compiler uses the '-parameters' flag --><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.11.0</version><configuration><parameters>true</parameters></configuration></plugin></plugins></build></project>
application.yml
spring:ai:dashscope:api-key: ${AI_DASHSCOPE_API_KEY}
启动类
@SpringBootApplication
public class AIApplication {public static void main(String[] args) {SpringApplication.run(AIApplication.class, args);}}
到此为止,我们已经搭建好了一个基本的 AI 应用雏形,现在开始和大模型交互 🎉🎉
只演示朴素请求,流式 API 不演示!
Chat 功能
AIChatController.java
@RestController
@RequestMapping("/ai")
public class AIChatController {// 使用高级 Client API,也可以使用低级 ChatModel APIprivate final ChatClient chatClient;public AIChatController(ChatClient.Builder builder) {this.chatClient = builder.build();}@GetMapping("/chat/{prompt}")public String chatWithChatMemory(@PathVariable String prompt) {return chatClient.prompt().user(prompt).call().chatResponse().getResult().getOutput().getContent();}}
如果一切顺利,请求 http://localhost:8080/ai/chat/你好
接口,将得到以下输出:
你好!有什么我可以帮助你的吗?
从代码中可以看到,使用 Spring AI Alibaba 之后,和模型交互变得非常简单容易。
但是大模型是无状态的,怎么能让他变得有记忆?Spring AI 提供了 ChatMemory 的接口,只需要调用接口即可(源码将在后续文章中分析)
@RestController
@RequestMapping("/ai")
public class AIChatController {private final ChatClient chatClient;public AIChatController(ChatModel chatModel) {this.chatClient = ChatClient.builder(chatModel).defaultAdvisors(new MessageChatMemoryAdvisor(new InMemoryChatMemory())).build();}@GetMapping("/chat/{chatId}/{prompt}")public String chatWithChatMemory(@PathVariable String chatId,@PathVariable String prompt) {return chatClient.prompt().user(prompt).advisors(a -> a.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId).param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 100)).call().chatResponse().getResult().getOutput().getContent();}}
我们像这样请求接口:
# 1
input: http://localhost:8080/ai/chat/10001/你好,我是牧生
output:你好,牧生!很高兴认识你。你可以叫我Qwen,我是阿里云推出的一种超大规模语言模型。我有强大的语言生成和理解能力,可以进行自然流畅的对话,还能写故事、写公文、写邮件、写剧本等等,也能表达观点,玩游戏等。有什么我可以帮助你的吗?# 2
input:http://localhost:8080/ai/chat/10001/我是谁
output:你刚才提到你的名字是牧生。如果你有任何问题或需要进一步的帮助,随时告诉我,我很乐意为你服务!# 当切换 chatId 时
input:http://localhost:8080/ai/chat/10000/我叫什么名字
output:您还没有告诉我您的名字呢。如果您愿意,可以告诉我您希望被称为什么,或者您想如何介绍自己。
能看到借助 Spring AI 的 ChatMemory 接口,已经使大模型变得聪明了起来。 😀
PS:Spring AI Alibaba 的 Chat Memory 功能已经在规划中了!
Image 功能
本节我们将展示如何使用 Spring AI Alibaba 提供的 Image API 完成和大模型的图像交互功能,包含文生图,多模态等功能。
AIImageController.java
@RestController
@RequestMapping("/ai")
public class AIImageController {private final ImageModel imageModel;public AIImageController(ImageModel imageModel) {this.imageModel = imageModel;}@GetMapping("/image/{input}")public void image(@PathVariable("input") String input, HttpServletResponse response) {String imageUrl = imageModel.call(new ImagePrompt(input)).getResult().getOutput().getUrl();try {URL url = URI.create(imageUrl).toURL();InputStream in = url.openStream();response.setHeader("Content-Type", MediaType.IMAGE_PNG_VALUE);response.getOutputStream().write(in.readAllBytes());response.getOutputStream().flush();} catch (IOException e) {response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);}}}
请求接口 http://localhost:8080/ai/image/给我一张AI图片
,将会得到以下输出:
多模态
MultiModelController.java
多模态还支持视频解析和 流式 API。
@RestController
@RequestMapping("/ai")
public class AIImageController {private final ImageModel imageModel;// 加入 chatClientprivate final ChatClient client;public AIImageController(ImageModel imageModel, ChatClient.Builder builder) {this.imageModel = imageModel;this.client = builder.build();}@GetMapping("/image/{input}")public void image(@PathVariable("input") String input, HttpServletResponse response) {ImageOptions options = ImageOptionsBuilder.builder().withModel("wanx-v1").build();String imageUrl = imageModel.call(new ImagePrompt(input, options)).getResult().getOutput().getUrl();try {URL url = URI.create(imageUrl).toURL();InputStream in = url.openStream();response.setHeader("Content-Type", MediaType.IMAGE_PNG_VALUE);response.getOutputStream().write(in.readAllBytes());response.getOutputStream().flush();} catch (IOException e) {response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);}}@GetMapping("/image")public String image(@RequestParam(value = "prompt", required = false, defaultValue = "图片里是什么")String prompt) throws Exception {// 图片资源 同时支持读取本地文件作为输入List<Media> mediaList = List.of(new Media(MimeTypeUtils.IMAGE_PNG,new URI("https://dashscope.oss-cn-beijing.aliyuncs.com/images/dog_and_girl.jpeg").toURL()));UserMessage message = new UserMessage(prompt, mediaList);message.getMetadata().put(DashScopeChatModel.MESSAGE_FORMAT, MessageFormat.IMAGE);ChatResponse response = client.prompt(new Prompt(message,DashScopeChatOptions.builder().withModel("qwen-vl-max-latest").withMultiModel(true).build())).call().chatResponse();return response.getResult().getOutput().getContent();}}
请求 http://localhost:8080/ai/image
接口,将得到以下输出:
这张图片展示了一位女士和一只狗在海滩上互动的温馨场景。女士坐在沙滩上,面带微笑,与狗握手。狗戴着项圈,显得非常温顺和友好。背景是广阔的海洋和天空,阳光洒在沙滩上,营造出一种温暖和谐的氛围。
Audio 功能
本节我们将展示如何使用 Spring AI Alibaba 提供的 Audio API 完成和大模型的音频交互功能,包含文生语音,语音转文字等功能。
截止文章发布期间,Spring AI Alibaba 的语音转录接口还没有发版,有关 stt 和 tts 的更多使用,参考官方 example。
https://github.com/alibaba/spring-ai-alibaba/tree/main/spring-ai-alibaba-examples/audio-example/src/main/java/com/alibaba/cloud/ai/example/audio
AIAudioController.java
@RestController
@RequestMapping("/ai")
public class AIAudioController implements ApplicationRunner {private final SpeechSynthesisModel speechSynthesisModel;private static final String TEXT = "白日依山尽,黄河入海流。";private static final String FILE_PATH = "src/main/resources/gen/tts/";private AIAudioController(SpeechSynthesisModel speechSynthesisModel) {this.speechSynthesisModel = speechSynthesisModel;}@GetMapping("/tts")public void tts() throws IOException {SpeechSynthesisResponse response = speechSynthesisModel.call(new SpeechSynthesisPrompt(TEXT));File file = new File(FILE_PATH + "output.mp3");try (FileOutputStream fos = new FileOutputStream(file)) {ByteBuffer byteBuffer = response.getResult().getOutput().getAudio();fos.write(byteBuffer.array());}catch (IOException e) {throw new IOException(e.getMessage());}}@Overridepublic void run(ApplicationArguments args) {File file = new File(FILE_PATH);if (!file.exists()) {file.mkdirs();}}@PreDestroypublic void destroy() throws IOException {FileUtils.deleteDirectory(new File(FILE_PATH));}}
请求接口,将得到一个语音文件的输出。
函数调用
函数调用是为了弥补大模型的训练数据落后的问题,用外部的 API 来补充 LLMs 的知识,给用户最合理的回答。
天气函数注册 MockWeatherService.java
public class MockWeatherService implements Function<MockWeatherService.Request, Response> {@Overridepublic Response apply(Request request) {if (request.city().contains("杭州")) {return new Response(String.format("%s%s晴转多云, 气温32摄氏度。", request.date(), request.city()));}else if (request.city().contains("上海")) {return new Response(String.format("%s%s多云转阴, 气温31摄氏度。", request.date(), request.city()));}else {return new Response(String.format("暂时无法查询%s的天气状况。", request.city()));}}@JsonInclude(JsonInclude.Include.NON_NULL)@JsonClassDescription("根据日期和城市查询天气")public record Request(@JsonProperty(required = true, value = "city") @JsonPropertyDescription("城市, 比如杭州") String city,@JsonProperty(required = true, value = "date") @JsonPropertyDescription("日期, 比如2024-08-22") String date) {}}
紧接着,我们在 AIChatController 中加入函数调用的代码:
@RestController
@RequestMapping("/ai")
public class AIChatController {private final ChatClient chatClient;public AIChatController(ChatModel chatModel) {this.chatClient = ChatClient.builder(chatModel).defaultAdvisors(new MessageChatMemoryAdvisor(new InMemoryChatMemory())).build();}@GetMapping("/chat/{chatId}/{prompt}")public String chatWithChatMemory(@PathVariable String chatId,@PathVariable String prompt) {return chatClient.prompt().user(prompt).advisors(a -> a.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId).param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 100)).call().chatResponse().getResult().getOutput().getContent();}// 函数调用@GetMapping("/weather-service/{city}")public String weatherService(@PathVariable String city) {return chatClient.prompt().function("getWeather", "根据城市查询天气", new MockWeatherService()).user(city).call().content();}}
请求 http://localhost:8080/ai/weather-service/杭州2024年11月29日天气怎么样
接口,将得到如下响应:
2024年11月29日,杭州的天气预报为晴转多云,气温为32摄氏度。请根据天气情况做好相应的准备。如果您有其他问题,欢迎随时询问!
RAG
本节中我们将使用 ES 作为 RAG 的实现,演示 Spring AI Alibaba RAG 的实现。
在 resource 目录下准备一个 system-qa.st
Context information is below.
---------------------
{question_answer_context}
---------------------
Given the context and provided history information and not prior knowledge,
reply to the user comment. If the answer is not in the context, inform
the user that you can't answer the question.
之后准备一个 df 文件,点击这里下载:https://github.com/alibaba/spring-ai-alibaba/blob/main/spring-ai-alibaba-examples/rag-example/src/main/resources/data/spring_ai_alibaba_quickstart.pdf
使用 docker compose up -d
启动一个 es:
准备配置文件:
config/es.yaml
cluster.name: docker-es
node.name: es-node-1
network.host: 0.0.0.0
network.publish_host: 0.0.0.0
http.port: 9200
http.cors.enabled: true
http.cors.allow-origin: "*"
bootstrap.memory_lock: true# 关闭认证授权 es 8.x 默认开启
# 如果不关闭,spring boot 连接会 connection closed
xpack.security.enabled: false
docker-compose.yaml
version: '3.3'services:elasticsearch:image: docker.elastic.co/elasticsearch/elasticsearch:8.16.1container_name: elasticsearchprivileged: trueenvironment:- "cluster.name=elasticsearch"- "discovery.type=single-node"- "ES_JAVA_OPTS=-Xms512m -Xmx1096m"- bootstrap.memory_lock=truevolumes:- ./config/es.yaml:/usr/share/elasticsearch/config/elasticsearch.ymlports:- "9200:9200"- "9300:9300"deploy:resources:limits:cpus: "2"memory: 1000Mreservations:memory: 200M
application.yml 中加入 rag 相关配置:
server:port: 9097spring:ai:dashscope:api-key: ${AI_DASHSCOPE_API_KEY}vectorstore:elasticsearch:index-name: spring-ai-alibaba-indexsimilarity: cosinedimensions: 1536initialize-schema: true
pom.xml 中加入如下配置:
<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-pdf-document-reader</artifactId><version>1.0.0-M3</version>
</dependency><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-elasticsearch-store-spring-boot-starter</artifactId><version>1.0.0-M3</version>
</dependency>
AIRagController.java
package indi.yuluo.controller;import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.mapping.DenseVectorProperty;
import co.elastic.clients.elasticsearch._types.mapping.KeywordProperty;
import co.elastic.clients.elasticsearch._types.mapping.ObjectProperty;
import co.elastic.clients.elasticsearch._types.mapping.Property;
import co.elastic.clients.elasticsearch._types.mapping.TextProperty;
import co.elastic.clients.elasticsearch._types.mapping.TypeMapping;
import co.elastic.clients.elasticsearch.indices.CreateIndexResponse;
import co.elastic.clients.elasticsearch.indices.IndexSettings;
import com.alibaba.cloud.ai.advisor.RetrievalRerankAdvisor;
import com.alibaba.cloud.ai.model.RerankModel;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Flux;import org.springframework.ai.autoconfigure.vectorstore.elasticsearch.ElasticsearchVectorStoreProperties;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.document.Document;
import org.springframework.ai.document.DocumentReader;
import org.springframework.ai.reader.pdf.PagePdfDocumentReader;
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.ai.vectorstore.filter.FilterExpressionBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.io.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;/*** @author yuluo* @author <a href="mailto:yuluo08290126@gmail.com">yuluo</a>*/@RestController
@RequestMapping("/ai")
public class AIRagController implements ApplicationRunner {private static final Logger logger = LoggerFactory.getLogger(AIRagController.class);@Value("classpath:/data/spring_ai_alibaba_quickstart.pdf")private Resource PdfResource;@Value("classpath:/prompts/system-qa.st")private Resource systemResource;private static final String textField = "content";private static final String vectorField = "embedding";private final ChatModel chatModel;private final VectorStore vectorStore;private final RerankModel rerankModel;private final ElasticsearchClient elasticsearchClient;private final ElasticsearchVectorStoreProperties options;public AIRagController(ChatModel chatModel,VectorStore vectorStore,RerankModel rerankModel,ElasticsearchClient elasticsearchClient,ElasticsearchVectorStoreProperties options) {this.chatModel = chatModel;this.vectorStore = vectorStore;this.rerankModel = rerankModel;this.elasticsearchClient = elasticsearchClient;this.options = options;}@GetMapping("/rag")public Flux<String> generate(@RequestParam(value = "message", defaultValue = "how to get start with spring ai alibaba?")String message,HttpServletResponse response) throws IOException {// 不设置返回值会乱码response.setCharacterEncoding(StandardCharsets.UTF_8.name());return this.retrieve(message).map(x -> x.getResult().getOutput().getContent());}private Flux<ChatResponse> retrieve(String message) throws IOException {// Enable hybrid search, both embedding and full text searchSearchRequest searchRequest = SearchRequest.defaults().withFilterExpression(new FilterExpressionBuilder().eq(textField, message).build());// Step3 - Retrieve and llm generateString promptTemplate = systemResource.getContentAsString(StandardCharsets.UTF_8);;ChatClient chatClient = ChatClient.builder(chatModel).defaultAdvisors(new RetrievalRerankAdvisor(vectorStore,rerankModel,searchRequest,promptTemplate,0.1)).build();return chatClient.prompt().user(message).stream().chatResponse();}@Overridepublic void run(ApplicationArguments args) throws Exception {// 1. parse documentDocumentReader reader = new PagePdfDocumentReader(PdfResource);List<Document> documents = reader.get();logger.info("{} documents loaded", documents.size());// 2. split trunksList<Document> splitDocuments = new TokenTextSplitter().apply(documents);logger.info("{} documents split", splitDocuments.size());// 3. create embedding and store to vector storelogger.info("create embedding and save to vector store");createIndexIfNotExists();vectorStore.add(splitDocuments);}private void createIndexIfNotExists() {try {String indexName = options.getIndexName();Integer dimsLength = options.getDimensions();if (Objects.isNull(indexName) || indexName.isEmpty()) {throw new IllegalArgumentException("Elastic search index name must be provided");}boolean exists = elasticsearchClient.indices().exists(idx -> idx.index(indexName)).value();if (exists) {logger.debug("Index {} already exists. Skipping creation.", indexName);return;}String similarityAlgo = options.getSimilarity().name();IndexSettings indexSettings = IndexSettings.of(settings -> settings.numberOfShards(String.valueOf(1)).numberOfReplicas(String.valueOf(1)));Map<String, Property> properties = new HashMap<>();properties.put(vectorField, Property.of(property -> property.denseVector(DenseVectorProperty.of(dense -> dense.index(true).dims(dimsLength).similarity(similarityAlgo)))));properties.put(textField, Property.of(property -> property.text(TextProperty.of(t -> t))));Map<String, Property> metadata = new HashMap<>();metadata.put("ref_doc_id", Property.of(property -> property.keyword(KeywordProperty.of(k -> k))));properties.put("metadata",Property.of(property -> property.object(ObjectProperty.of(op -> op.properties(metadata)))));CreateIndexResponse indexResponse = elasticsearchClient.indices().create(createIndexBuilder -> createIndexBuilder.index(indexName).settings(indexSettings).mappings(TypeMapping.of(mappings -> mappings.properties(properties))));if (!indexResponse.acknowledged()) {throw new RuntimeException("failed to create index");}logger.info("create elasticsearch index {} successfully", indexName);}catch (IOException e) {logger.error("failed to create index", e);throw new RuntimeException(e);}}}
之后,请求 http://localhost:8080/ai/rag
接口,将得到如下响应:
根据提供的上下文信息,以下是开始使用 Spring AI Alibaba 的步骤: ### 概述 Spring AI Alibaba 实现了与阿里云通义模型的完整适配。下面将介绍如何使用 Spring AI Alibaba 开发一个基于通义模型服务的智能聊天应用。 ### 快速体验示例 #### 注意事项 - **JDK 版本**:因为 Spring AI Alibaba 基于 Spring Boot 3.x 开发,所以本地 JDK 版本要求为 17 及以上。 #### 步骤 1. **下载项目** - 运行以下命令下载源码,并进入 `helloworld` 示例目录: ```sh git clone --depth=1 https://github.com/alibaba/spring-ai-alibaba.git cd spring-ai-alibaba/spring-ai-alibaba-examples/helloworld-example ```2. **运行项目** - 首先,需要获取一个合法的 API-KEY 并设置 `AI_DASHSCOPE_API_KEY` 环境变量。你可以跳转到 [阿里云百炼平台](https://sca.aliyun.com/) 了解如何获取 API-KEY。 ```sh export AI_DASHSCOPE_API_KEY=${REPLACE-WITH-VALID-API-KEY} ```- 启动示例应用: ```sh ./mvnw compile exec:java -Dexec.mainClass="com.alibaba.cloud.ai.example.helloworld.HelloWorldExample" ```3. **访问应用** - 打开浏览器,访问 `http://localhost:8080/ai/chat?input=给我讲一个笑话吧`,向通义模型提问并得到回答。 希望这些步骤能帮助你快速上手 Spring AI Alibaba!如果有任何问题,可以随时提问。
总结
Spring AI Alibaba 基于 Spring AI 开发,并在上层提供更多高级的抽象 API。帮助开发者构建 Java LLMs 应用。
相关文章:
大模型专栏--Spring Ai Alibaba介绍和功能演示
Spring AI Alibaba 介绍和功能演示 背景 Spring AI Alibaba 开源项目基于 Spring AI 构建,是阿里云通义系列模型及服务在 Java AI 应用开发领域的最佳实践,提供高层次的 AI API 抽象与云原生基础设施集成方案,帮助开发者快速构建 AI 应用。…...
【GPT】为什么人需要睡觉?
睡觉对人类来说是至关重要的生理和心理需求。以下是一些为什么人需要睡觉的主要原因,以及睡眠对身体和大脑的影响: 1. 恢复与修复 身体修复:在睡眠期间,身体进行细胞修复和再生。例如,生长激素在深度睡眠中分泌&#…...
【Linux】磁盘 | 文件系统 | inode
🪐🪐🪐欢迎来到程序员餐厅💫💫💫 主厨:邪王真眼 主厨的主页:Chef‘s blog 所属专栏:青果大战linux 总有光环在陨落,总有新星在闪烁 模电好难啊ÿ…...
A051-基于Spring Boot的网络海鲜市场系统的设计与实现
🙊作者简介:在校研究生,拥有计算机专业的研究生开发团队,分享技术代码帮助学生学习,独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取,记得注明来意哦~🌹 赠送计算机毕业设计600…...
谷歌浏览器Chrome打开百度很慢,其他网页正常的解决办法,试了很多,找到了适合的
最近不知怎么的,Chrome突然间打开百度很慢,甚至打不开。不光我一个人遇到这问题,我同事也遇到这个问题。开发中难免遇到问题,需要百度,现在是百度不了。 作为一名开发人员,习惯了使用Chrome进行开发&#…...
《企业级低代码开发平台技术要求》核心要点解析
一、引言 在数字化转型的浪潮中,企业级低代码开发平台成为推动企业创新与发展的关键力量。深圳市标准化协会发布的《企业级低代码开发平台技术要求》(T/SZAS 77—2024)为该领域提供了重要的规范与指引。深入剖析其核心要点,对于理…...
AI一键生成3D动画:腾讯最新方案,为小程序带来革命性变化
随着3D技术的快速发展,将静态的3D模型转化为能够生动展现各种动作的角色已经成为许多创作者和开发者梦寐以求的能力。然而,在过去,这一过程往往需要大量的手动工作和技术积累。现在,腾讯推出了一项创新的技术——AI一键生成3D动画,它不仅极大地简化了流程,还显著提高了效…...
AD软件如何快速切换三维视图,由2D切换至3D,以及如何恢复
在Altium Designer软件中,切换三维视图以及恢复二维视图的操作相对简单。以下是具体的步骤: 切换三维视图 在PCB设计界面中,2D切换3D,快捷键按住数字键盘中的“3”即可切换; 快捷键ctrlf(或者vb快捷键也…...
【赵渝强老师】PostgreSQL的数据库
PostgreSQL的逻辑存储结构主要是指数据库中的各种数据库对象,包括:数据库集群、数据库、表、索引、视图等等。所有数据库对象都有各自的对象标识符oid(object identifiers),它是一个无符号的四字节整数,相关对象的oid都…...
opencv 区域提取三种算法
opencv 区域提取三种算法 1.轮廓查找 findContours()函数,得到轮廓的点集集合 cv::vector<cv::vector<Point>> contours;threshold(roiMat,binImg,m_pPara.m_nMinGray,m_pPara.m_nMaxGray,THRESH_BINARY);//膨胀处理Mat dilaElement getStructuringE…...
C++初阶(十六)--STL--list的模拟实现
目录 结点类的实现 迭代器类的模拟实现 迭代器类的模板参数说明 构造函数 *运算符重载 ->运算符的重载 运算符的重载 --运算符重载 !运算符重载 运算符重载 list类的模拟实现 成员变量 默认成员函数 构造函数 拷贝构造函数 赋值运算符重载 迭代器相关函数 …...
树莓集团:以人工智能为核心,打造数字化生态运营新典范
在当今数字化浪潮席卷全球的背景下,各行各业都在积极探索数字化转型的路径。作为数字产业的领军者,树莓集团凭借其深厚的技术积累和创新理念,在人工智能、大数据、云计算等前沿技术领域不断突破,成功打造了一个以人工智能为核心的…...
基于深度学习的卷积神经网络十二生肖图像识别系统(PyQt5界面+数据集+训练代码)
本研究提出了一种基于深度学习的十二生肖图像识别系统,旨在利用卷积神经网络(CNN)进行图像分类,特别是十二生肖图像的自动识别。系统的核心采用了两种经典的深度学习模型:ResNet50和VGG16,进行图像的特征提…...
Torchtune在AMD GPU上的使用指南:利用多GPU能力进行LLM微调与扩展
Torchtune on AMD GPUs How-To Guide: Fine-tuning and Scaling LLMs with Multi-GPU Power — ROCm Blogs 这篇博客提供了一份详细的使用Torchtune在AMD GPU上微调和扩展大型语言模型(LLM)的指南。Torchtune 是一个PyTorch库,旨在让您轻松地…...
ESLint
代码规范 一套写代码的约定规则;比如赋值符号左右是否需要空格,一句话结束是否要加;.... 代码规范错误 如果你的代码不符合standard的要求,ESLint(脚手架里配的东西)会告诉你哪个文件第几行错了 解决代码…...
小程序-基于java+SpringBoot+Vue的微信小程序养老院系统设计与实现
项目运行 1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。 2.IDE环境:IDEA,Eclipse,Myeclipse都可以。推荐IDEA; 3.tomcat环境:Tomcat 7.x,8.x,9.x版本均可 4.硬件环境:…...
如何具体实现商品详情的提取?
在电商领域,获取商品详情信息对于市场分析、价格比较、商品推荐等应用场景至关重要。本文将详细介绍如何使用Java编写爬虫程序,以合法合规的方式获取淘宝商品的详情信息,并提供详细的代码示例。 1. 环境准备 在开始编写爬虫之前,…...
antd table 自定义表头过滤表格内容
注意:该功能只能过滤可一次性返回全部数据的表格,通过接口分页查询的请自主按照需求改动哈~ 实现步骤: 1.在要过滤的列表表头增加过滤图标,点击图标显示浮窗 2.浮窗内显示整列可选选项,通过勾选单选或者全选、搜索框来…...
高效处理 iOS 应用中的大规模礼物数据:以直播项目为例(1-礼物池)
引言 在现代iOS应用开发中,处理大规模数据是一个常见的挑战。尤其实在直播项目中,礼物面板作为展示用户互动的重要部分,通常需要实时显示海量的礼物数据。这些数据不仅涉及到不同的区域、主播的动态差异,还需要保证高效的加载与渲…...
Maven - 优雅的管理多模块应用的统一版本号
文章目录 概述一、使用 versions-maven-plugin 插件1. 在主 pom.xml 中定义插件2. 修改版本号3. 回退修改4. 提交修改 二、使用占位符统一管理版本号1. 在主 pom.xml 中定义占位符2. 使用 flatten-maven-plugin 插件自动替换占位符3. 修改版本号4. 为什么这种方式更方便&#x…...
C++设计模式(观察者模式)
一、介绍 1.动机 在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系”,即一个对象的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵…...
【unity】WebSocket 与 EventSource 的区别
WebSocket 也是一种很好的选择,尤其是在需要进行 双向实时通信(例如聊天应用、实时数据流等)时。与 EventSource 不同,WebSocket 允许客户端和服务器之间建立一个持久的、全双工的通信通道。两者的区别和适用场景如下:…...
从ETL到DataOps:WhaleStudio替代Informatica,实现信创化升级
作者 | 白鲸开源 姜维 在数据集成和调度的领域,Informatica曾经是公认的权威工具。其强大的ETL功能、多年积累的市场经验,使其成为众多企业数据处理的核心工具。 然而,随着新一代大数据平台的迅速崛起,以及信创化改造的要求愈发严…...
第四十二篇 EfficientNet:重新思考卷积神经网络的模型缩放
文章目录 摘要1、简介2、相关工作3、复合模型缩放3.1、 问题公式化3.2、扩展维度3.3、复合比例 4、EfficientNet架构5、实验5.1、扩展MobileNets和ResNets5.2、EfficientNet的ImageNet结果5.3、EfficientNet的迁移学习结果 6、讨论7、结论 摘要 卷积神经网络(ConvNets)通常在固…...
[OpenHarmony5.0][Docker][环境]OpenHarmony5.0 Docker编译环境镜像下载以及使用方式
T. 已测试目录 主机类型主机版本Docker镜像版本结果WSL2Ubuntu22.04Ubuntu20.04PASSWSL2Ubuntu22.04Ubuntu18.04PASS R. 软硬件要求: 编译硬件需求:做多系统测试,磁盘500GB起步(固态)(机械会卡死),内存3…...
Web Worker 和 WebSocket的区别
Web Worker(消息传递机制) 定义:是为了在浏览器中提供多线程支持,允许 JavaScript 在后台线程运行,而不阻塞主线程。它非常适合执行耗时的计算任务或处理大量数据,避免主线程(通常是 UI 线程&a…...
vmware Ubuntu2004运行STAR-Searcher
github链接 安装ros noetic gazebo11 略 gazebo更新方法 sudo sh -c echo "deb http://packages.osrfoundation.org/gazebo/ubuntu-stable lsb_release -cs main" > /etc/apt/sources.list.d/gazebo-stable.list wget https://packages.osrfoundation.org/gaz…...
04_JavaScript引入到文件
JavaScript引入到文件 嵌入到HTML文件中 <body> <script> var age 20 </script></body> 引入本地独立JS文件 <body> <script type"text/javascript" src"./itbaizhan.js"> </script></body> 引入网络来…...
计算机网络的功能
目录 信息交换 资源共享 分布式处理 可靠性增强 集中管理 信息交换 计算机网络最基本的功能之一是允许不同设备之间的数据通信。这包括电子邮件的发送和接收、即时消息的传递、文件传输等。通过网络,用户可以轻松地与全球各地的其他人进行沟通和协作。 信息交…...
38 基于单片机的宠物喂食(ESP8266、红外、电机)
目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于STC89C52单片机,采用L298N驱动连接P2.3和P2.4口进行电机驱动, 然后串口连接P3.0和P3.1模拟ESP8266, 红外传感器连接ADC0832数模转换器连接单片机的P1.0~P1.…...
Git仓库迁移到远程仓库(源码、分支、提交)
单个迁移仓库 一、迁移仓库 1.准备工作 > 手动在电脑创建一个临时文件夹,CMD进入该目录 > 远程仓库上创建一个同名的空仓库 2.CMD命令:拉取旧Git仓库(包含提交、分支、源码) $ git clone --bare http://git.domain.cn/…...
Go语言压缩文件处理
目录 Go 语言压缩文件处理1. 压缩文件:Zip函数2. 解压文件:UnZip 函数3. 小结 Go 语言压缩文件处理 在现代的应用开发中,处理压缩文件(如 .zip 格式)是常见的需求。Go 语言提供了内置的 archive/zip 包来处理 .zip 文…...
Libevent库-http通信不同请求方式的处理
做项目的时候用到了http通信,同事用libevent库写的,特此记录后端从前端拿到消息后的处理方式 void CHTTPTest::request(const std::any & data) {// data 是从前端拿到的数据void *obj std::any_cast<void *>(data); // std::any是C17新标准…...
Vue3 v-if与v-show的区别
v-if 与 v-show 我们都可以在开发中用于条件渲染,在面试时也是个常考的题目 实现原理 v-if:是真正的条件渲染,当v-if true时,元素会被创建、渲染,并插入到dom树中,这个过程会耗费系统的资源,当…...
同时在github和gitee配置密钥
同时在github和gitee配置密钥 1. 生成不同的 SSH 密钥 为每个平台生成单独的 SSH 密钥。 # 为 GitHub 生成密钥(默认文件路径为 ~/.ssh/github_id_rsa) ssh-keygen -t rsa -b 4096 -C "your_github_emailexample.com" -f ~/.ssh/github_id_…...
Scala—数组(不可变数组Array、可变数组ArrayBuffer)用法详解
Scala集合概述-链接 大家可以点击上方链接,先对Scala的集合有一个整体的概念🤣🤣🤣 在 Scala 中,数组是一种特殊的集合类型,可以是可变的也可以是不可变的。 1. 不可变数组 在 Scala 中,不可变…...
Failed to find SV in PRN block of SINEX file (Name svnav.dat)
gamit 精密星历生成失败 gamit svnav.dat没更新 下载svnav.dat.allgnss 重命名成 svnav.dat ,替换到tables,即可。...
H.265流媒体播放器EasyPlayer.js无插件H5播放器关于移动端(H5)切换网络的时候,播放器会触发什么事件
EasyPlayer.js无插件H5播放器作为一款功能全面的H5流媒体播放器,凭借其多种协议支持、多种解码方式、丰富的渲染元素和强大的应用功能,以及出色的跨平台兼容性,为用户提供了高度定制化的选项和优化的播放体验。无论是视频直播还是点播&#x…...
Ubuntu上使用自带python创建虚拟环境
虚拟环境让项目之间的依赖关系更加清晰,也可以避免全局安装的包的版本冲突问题。 1.查看python Ubuntu上一般都是自带python的,查看python版本及指向(使用的话python要换成python3): ls -l /usr/bin | grep python 2.安装python虚拟环境工…...
对智能电视直播App的恶意监控
首先我们要指出中国广电总局推出的一个政策性文件是恶意监控的始作俑者,这个广电总局的政策性文件禁止智能电视和电视盒子安装直播软件。应该说这个政策性文件是为了保护特殊利益集团,阻挠技术进步和发展的。 有那么一些电视机和电视盒子的厂商和电信运…...
网络原理(一):应用层自定义协议的信息组织格式 HTTP 前置知识
目录 1. 应用层 2. 自定义协议 2.1 根据需求 > 明确传输信息 2.2 约定好信息组织的格式 2.2.1 行文本 2.2.2 xml 2.2.3 json 2.2.4 protobuf 3. HTTP 协议 3.1 特点 4. 抓包工具 1. 应用层 在前面的博客中, 我们了解了 TCP/IP 五层协议模型: 应用层传输层网络层…...
微软企业邮箱:安全可靠的企业级邮件服务!
微软企业邮箱的设置步骤?如何注册使用烽火域名邮箱? 微软企业邮箱作为一款专为企业设计的邮件服务,不仅提供了高效便捷的通信工具,更在安全性、可靠性和功能性方面树立了行业标杆。烽火将深入探讨微软企业邮箱的多重优势。 微软…...
matlab导出3D彩色模型(surface类转stl,并对白模上色)
在matlab中绘制3维图形时,需要将3维图形导出到PPT中展示。但是直接导出图片效果欠佳,无法全方位展示。 最近学习了如何将matlab中的图形导出为stl模型,然后再采用简单的方法对模型上色。 中间尝试过matlab导出stl、ply、3dm等多种格式&…...
【JavaScript】async /await异步详解2 promise举例
在 JavaScript 中,async 和 await 是处理异步操作的强大工具。结合 try...catch 语句,你可以优雅地处理异步操作中的错误。 基本用法 定义异步函数:使用 async 关键字。等待 Promise 解析:使用 await 关键字。错误处理ÿ…...
Android 设备使用 Wireshark 工具进行网络抓包
背景 电脑和手机连接同一网络,想使用wireshark抓包工具抓取Android手机网络日志,有以下两种连接方法: Wi-Fi 网络抓包。USB 网络共享抓包。需要USB 数据线将手机连接到电脑,并在开发者模式中启用 USB 网络共享。 查看设备连接信…...
封装类与封装函数
目录结构 src/ ├── utils/ │ ├── test.js │ ├── Calculator.js ├── views/ │ ├── Home.vue ├── App.vue 共同点:模块导出与模块引入 封装函数 场景 简单、轻量级和性能敏感的场景,适合快速开发和维护。 优 可维护性&…...
【java】接口幂等性的实现
文章目录 1. 引言介绍幂等性的概念为什么需要在Java接口中实现幂等性 2. 使用幂等表实现幂等性什么是幂等表如何设计幂等表示例:Java代码实现使用幂等表使用幂等表实现幂等性 3. 利用Nginx Lua 和 Redis实现幂等性Nginx和Lua的作用简介介绍Redis的SETNX命令架构设计…...
Leetcode 1.两数之和
题目意在对数组的快速查找 思路:哈希表 先创建一个哈希表,然后对数组进行遍历,iter代表用目标值依次减去遍历数组中的元素后得出的值,如果这个值在map中存在,则返回其索引和当前数组元素中的索引;若不存…...
GitLab指定用户分配合并权限
进入项目 -》 Project Settings Repository -》展开 Protected branches -》 添加要保护的分支,设置角色 管理用户角色权限 查看到不同用户的角色,一般设置Developer只有Merger Request权限,Maintainer还有Merge审批权限 GitLab 中的权限…...
实战优化公司线上系统JVM:从基础到高级
引言 Java虚拟机(JVM)是Java语言的核心组件,它使得Java程序能够实现“一次编写,到处运行”的跨平台特性。在现代应用程序中,JVM的性能和稳定性直接影响到系统的整体表现。本文将深入探讨JVM的基础知识、基本特点、定义…...