Browse Source

3.30学习笔记

huangyongxing/feature-20260327161252-学习笔记
huangyongxing 2 weeks ago
parent
commit
a4008af72a
  1. BIN
      黄永兴学习笔记/3.30黄永兴-软件功能总结.docx
  2. BIN
      黄永兴学习笔记/3.30黄永兴.docx
  3. 10
      黄永兴学习笔记/StudySpringAI/.idea/.gitignore
  4. 7
      黄永兴学习笔记/StudySpringAI/.idea/MarsCodeWorkspaceAppSettings.xml
  5. 20
      黄永兴学习笔记/StudySpringAI/.idea/compiler.xml
  6. 7
      黄永兴学习笔记/StudySpringAI/.idea/encodings.xml
  7. 35
      黄永兴学习笔记/StudySpringAI/.idea/jarRepositories.xml
  8. 15
      黄永兴学习笔记/StudySpringAI/.idea/misc.xml
  9. 8
      黄永兴学习笔记/StudySpringAI/.idea/modules.xml
  10. 6
      黄永兴学习笔记/StudySpringAI/.idea/vcs.xml
  11. 33
      黄永兴学习笔记/StudySpringAI/SpringAIEmbedding/.gitignore
  12. 3
      黄永兴学习笔记/StudySpringAI/SpringAIEmbedding/.mvn/wrapper/maven-wrapper.properties
  13. 100
      黄永兴学习笔记/StudySpringAI/SpringAIEmbedding/pom.xml
  14. 13
      黄永兴学习笔记/StudySpringAI/SpringAIEmbedding/src/main/java/com/example/springaiembedding/SpringAiEmbeddingApplication.java
  15. 54
      黄永兴学习笔记/StudySpringAI/SpringAIEmbedding/src/main/java/com/example/springaiembedding/controller/EmbeddingController.java
  16. 22
      黄永兴学习笔记/StudySpringAI/SpringAIEmbedding/src/main/java/com/example/springaiembedding/controller/RagController.java
  17. 87
      黄永兴学习笔记/StudySpringAI/SpringAIEmbedding/src/main/java/com/example/springaiembedding/service/RagService.java
  18. 93
      黄永兴学习笔记/StudySpringAI/SpringAIEmbedding/src/main/java/com/example/springaiembedding/service/TextSimilarityService.java
  19. 28
      黄永兴学习笔记/StudySpringAI/SpringAIEmbedding/src/main/java/com/example/springaiembedding/tool/DocumentLoader.java
  20. 21
      黄永兴学习笔记/StudySpringAI/SpringAIEmbedding/src/main/resources/application.properties
  21. 8
      黄永兴学习笔记/StudySpringAI/SpringAIEmbedding/src/main/resources/knowledge.txt
  22. 13
      黄永兴学习笔记/StudySpringAI/SpringAIEmbedding/src/test/java/com/example/springaiembedding/SpringAiEmbeddingApplicationTests.java
  23. 33
      黄永兴学习笔记/StudySpringAI/SpringAIQuickStart/.gitignore
  24. 3
      黄永兴学习笔记/StudySpringAI/SpringAIQuickStart/.mvn/wrapper/maven-wrapper.properties
  25. 104
      黄永兴学习笔记/StudySpringAI/SpringAIQuickStart/pom.xml
  26. 13
      黄永兴学习笔记/StudySpringAI/SpringAIQuickStart/src/main/java/com/example/springaiquickstart/SpringAiQuickStartApplication.java
  27. 127
      黄永兴学习笔记/StudySpringAI/SpringAIQuickStart/src/main/java/com/example/springaiquickstart/controller/ChatController.java
  28. 13
      黄永兴学习笔记/StudySpringAI/SpringAIQuickStart/src/main/resources/application.properties
  29. 224
      黄永兴学习笔记/StudySpringAI/SpringAIQuickStart/src/main/resources/static/index.html
  30. 13
      黄永兴学习笔记/StudySpringAI/SpringAIQuickStart/src/test/java/com/example/springaiquickstart/SpringAiQuickStartApplicationTests.java
  31. 8
      黄永兴学习笔记/StudySpringAI/StudySpringAI.iml

BIN
黄永兴学习笔记/3.30黄永兴-软件功能总结.docx

BIN
黄永兴学习笔记/3.30黄永兴.docx

10
黄永兴学习笔记/StudySpringAI/.idea/.gitignore

@ -0,0 +1,10 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 已忽略包含查询文件的默认文件夹
/queries/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/

7
黄永兴学习笔记/StudySpringAI/.idea/MarsCodeWorkspaceAppSettings.xml

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="com.codeverse.userSettings.MarscodeWorkspaceAppSettingsState">
<option name="chatAppRouterInfo" value="builder/69c9f63d3b54644cf72884fa" />
<option name="progress" value="1.0" />
</component>
</project>

20
黄永兴学习笔记/StudySpringAI/.idea/compiler.xml

@ -0,0 +1,20 @@
<?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="SpringAIEmbedding" />
<module name="SpringAIQuickStart" />
</profile>
</annotationProcessing>
</component>
<component name="JavacSettings">
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
<module name="SpringAIEmbedding" options="-parameters" />
<module name="SpringAIQuickStart" options="-parameters" />
</option>
</component>
</project>

7
黄永兴学习笔记/StudySpringAI/.idea/encodings.xml

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/SpringAIEmbedding/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/SpringAIQuickStart/src/main/java" charset="UTF-8" />
</component>
</project>

35
黄永兴学习笔记/StudySpringAI/.idea/jarRepositories.xml

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central-portal-snapshots" />
<option name="name" value="Central Portal Snapshots" />
<option name="url" value="https://central.sonatype.com/repository/maven-snapshots/" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://repo.maven.apache.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="spring-milestones" />
<option name="name" value="Spring Milestones" />
<option name="url" value="https://repo.spring.io/milestone" />
</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="spring-snapshots" />
<option name="name" value="Spring Snapshots" />
<option name="url" value="https://repo.spring.io/snapshot" />
</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>

15
黄永兴学习笔记/StudySpringAI/.idea/misc.xml

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/SpringAIQuickStart/pom.xml" />
<option value="$PROJECT_DIR$/SpringAIEmbedding/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

8
黄永兴学习笔记/StudySpringAI/.idea/modules.xml

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/StudySpringAI.iml" filepath="$PROJECT_DIR$/StudySpringAI.iml" />
</modules>
</component>
</project>

6
黄永兴学习笔记/StudySpringAI/.idea/vcs.xml

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

33
黄永兴学习笔记/StudySpringAI/SpringAIEmbedding/.gitignore

@ -0,0 +1,33 @@
HELP.md
target/
.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/

3
黄永兴学习笔记/StudySpringAI/SpringAIEmbedding/.mvn/wrapper/maven-wrapper.properties

@ -0,0 +1,3 @@
wrapperVersion=3.3.4
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.14/apache-maven-3.9.14-bin.zip

100
黄永兴学习笔记/StudySpringAI/SpringAIEmbedding/pom.xml

@ -0,0 +1,100 @@
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.13</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>SpringAIEmbedding</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SpringAIEmbedding</name>
<description>SpringAIEmbedding</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
<spring-ai.version>1.1.3</spring-ai.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.0.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring AI Zhipuai 模型依赖 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-zhipuai</artifactId>
</dependency>
<!-- Spring AI Chat 客户端依赖 中包括TokenTextSplitter、TextReader、Document 等工具类 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-client-chat</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
<!-- 声明仓库,用于获取 Spring AI 以及相关预发布版本 -->
<repositories>
<!-- Spring Milestones 仓库 -->
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<!-- Spring Snapshots 仓库 -->
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

13
黄永兴学习笔记/StudySpringAI/SpringAIEmbedding/src/main/java/com/example/springaiembedding/SpringAiEmbeddingApplication.java

@ -0,0 +1,13 @@
package com.example.springaiembedding;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringAiEmbeddingApplication {
public static void main(String[] args) {
SpringApplication.run(SpringAiEmbeddingApplication.class, args);
}
}

54
黄永兴学习笔记/StudySpringAI/SpringAIEmbedding/src/main/java/com/example/springaiembedding/controller/EmbeddingController.java

@ -0,0 +1,54 @@
package com.example.springaiembedding.controller;
import com.example.springaiembedding.service.TextSimilarityService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.beans.factory.annotation.Autowired;
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;
import java.util.Arrays;
import java.util.Map;
@RestController
@RequestMapping("/ai")
public class EmbeddingController {
@Autowired
private EmbeddingModel embeddingModel;
//对用户传入的文本进行向量化处理测试embedding模型
@RequestMapping("/embedding")
public Map<String,Object> embedding(
@RequestParam(value = "message",defaultValue = "给我讲个笑话") String message
){
// 对用户传入的文本进行向量化处理
float[] embedding = embeddingModel.embed(message);
return Map.of("message",message,
"vector",embedding);
}
@Resource
private TextSimilarityService textSimilarityService;
/**
* 查找相似文本接口
* @param message 查询文本
* @return 相似文本+相似度
*/
@GetMapping("/similarity")
public Map<String, Double> findSimilarText(@RequestParam String message) {
// 查询Top3相似文本
return textSimilarityService.findSimilarTexts(message, 3);
}
}

22
黄永兴学习笔记/StudySpringAI/SpringAIEmbedding/src/main/java/com/example/springaiembedding/controller/RagController.java

@ -0,0 +1,22 @@
package com.example.springaiembedding.controller;
import com.example.springaiembedding.service.RagService;
import jakarta.annotation.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;
@RestController
@RequestMapping("/ai/rag")
public class RagController {
@Resource
private RagService ragService;
// 问答接口
@GetMapping("/query")
public String query(@RequestParam String question) {
return ragService.generateAnswer(question);
}
}

87
黄永兴学习笔记/StudySpringAI/SpringAIEmbedding/src/main/java/com/example/springaiembedding/service/RagService.java

@ -0,0 +1,87 @@
package com.example.springaiembedding.service;
import com.example.springaiembedding.tool.DocumentLoader;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.embedding.EmbeddingResponse;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class RagService {
@Resource
private EmbeddingModel embeddingModel;
@Resource
private ChatModel chatModel;
// 内存存储知识库片段 对应向量
private Map<String, float[]> knowledgeVectors = new HashMap<>();
// 项目启动时自动加载并向量化知识库
@PostConstruct
public void initKnowledgeBase() throws IOException {
// 1. 加载并拆分文档
List<String> chunks = DocumentLoader.loadAndSplit("knowledge.txt");
// 2. 批量向量化一次请求生成所有片段向量
EmbeddingResponse embeddingResponse = embeddingModel.embedForResponse(chunks);
// 3. 存储片段与向量的映射
for (int i = 0; i < chunks.size(); i++) {
knowledgeVectors.put(chunks.get(i), embeddingResponse.getResults().get(i).getOutput());
}
}
// 检索与用户问题最相似的 Top N 片段
private List<String> retrieveSimilarChunks(String query, int topN) {
// 1. 用户问题向量化
float[] queryVector = embeddingModel.embed(query);
// 2. 计算与所有知识库片段的相似度
Map<String, Double> similarityMap = new HashMap<>();
//Entry是什么Map.Entry<String, float[]> entry 是一个 Map.Entry 对象用于遍历 Map 中的键值对
for (Map.Entry<String, float[]> entry : knowledgeVectors.entrySet()) {
similarityMap.put(entry.getKey(), CosineSimilarityCalculator.calculate(queryVector, entry.getValue()));
}
// 3. 按相似度降序排序 Top N
return similarityMap.entrySet().stream()
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
.limit(topN)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
}
// 生成最终回答
public String generateAnswer(String query) {
// 1. 检索相似片段 Top 2
List<String> similarChunks = retrieveSimilarChunks(query, 2);
// 2. 拼接 Prompt约束模型基于知识库回答
StringBuilder prompt = new StringBuilder();
prompt.append("请基于以下知识库内容回答用户问题,禁止编造信息:\n");
for (String chunk : similarChunks) {
prompt.append("- ").append(chunk).append("\n");
}
prompt.append("\n用户问题:").append(query);
// 3. 调用 Chat 模型生成回答
ChatClient chatClient = ChatClient.builder(chatModel).build();
return chatClient.prompt().user(prompt.toString()).call().content();
}
public class CosineSimilarityCalculator {
// 计算两个 float[] 向量的余弦相似度
public static double calculate(float[] vectorA, float[] vectorB) {
double dotProduct = 0.0;
double normA = 0.0;
double normB = 0.0;
for (int i = 0; i < vectorA.length; i++) {
dotProduct += vectorA[i] * vectorB[i];
normA += Math.pow(vectorA[i], 2);
normB += Math.pow(vectorB[i], 2);
}
return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
}
}
}

93
黄永兴学习笔记/StudySpringAI/SpringAIEmbedding/src/main/java/com/example/springaiembedding/service/TextSimilarityService.java

@ -0,0 +1,93 @@
package com.example.springaiembedding.service;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.embedding.EmbeddingResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class TextSimilarityService {
@Autowired
private EmbeddingModel embeddingModel;
// 模拟本地文本库可替换为数据库/向量库
private final List<String> TEXT_LIBRARY = Arrays.asList(
"我爱Java编程",
"SpringBoot是最流行的后端框架",
"人工智能改变世界",
"大模型应用开发",
"我喜欢学习编程",
"向量数据库用于存储Embedding",
"SpringAI简化大模型开发"
);
/**
* 查找最相似的文本
* @param queryText 查询文本
* @param topN 返回前N条结果
* @return 相似文本+相似度
*/
public Map<String, Double> findSimilarTexts(String queryText, int topN) {
// 1. 将查询文本转为向量
//float[] queryVector = embeddingModel.embed(queryText);
EmbeddingResponse queryEmbedding = embeddingModel.embedForResponse(List.of(queryText));
float[] queryVector = queryEmbedding.getResults().get(0).getOutput();
// 2. 将文本库所有文本转为向量
// 2. 将文本库所有文本转为向量
Map<String, float[]> textVectorMap = new HashMap<>();
for (String text : TEXT_LIBRARY) {
float[] textVector = embeddingModel.embed(text);
//put是将文本和向量存储到Map中
textVectorMap.put(text, textVector);
}
// 3. 计算相似度并排序
Map<String, Double> similarityMap = new HashMap<>();
for (Map.Entry<String, float[]> entry : textVectorMap.entrySet()) {
double similarity = CosineSimilarityCalculator.calculate(queryVector, entry.getValue());
similarityMap.put(entry.getKey(), similarity);
}
// 4. 按相似度降序排序取TopN
return similarityMap.entrySet().stream()
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
.limit(topN)
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(oldValue, newValue) -> oldValue,
LinkedHashMap::new
));
}
/**
* 余弦相似度工具类计算文本向量相似度
*/
public class CosineSimilarityCalculator {
/**
* 计算两个向量的余弦相似度
* @param vectorA 向量A
* @param vectorB 向量B
* @return 相似度 0~1值越大越相似
*/
public static double calculate(float[] vectorA, float[] vectorB) {
double dotProduct = 0.0;
double normA = 0.0;
double normB = 0.0;
for (int i = 0; i < vectorA.length; i++) {
dotProduct += vectorA[i] * vectorB[i];
normA += Math.pow(vectorA[i], 2);
normB += Math.pow(vectorB[i], 2);
}
return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
}
}
}

28
黄永兴学习笔记/StudySpringAI/SpringAIEmbedding/src/main/java/com/example/springaiembedding/tool/DocumentLoader.java

@ -0,0 +1,28 @@
package com.example.springaiembedding.tool;
import org.springframework.core.io.ClassPathResource;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
// 文档加载工具类
public class DocumentLoader {
// 加载并拆分知识库文档
public static List<String> loadAndSplit(String resourcePath) throws IOException {
ClassPathResource resource = new ClassPathResource(resourcePath); // 从类路径加载资源
BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream())); // 按行读取
String content = reader.lines().collect(Collectors.joining("\n")); // 读取文件内容将所有行连接起来一个字符串
// "---" 拆分片段过滤空内容
List<String> chunks = new ArrayList<>();
for (String chunk : content.split("---")) {
String trimmed = chunk.trim();
if (!trimmed.isEmpty()) chunks.add(trimmed);
}
return chunks;
}
}

21
黄永兴学习笔记/StudySpringAI/SpringAIEmbedding/src/main/resources/application.properties

@ -0,0 +1,21 @@
spring.application.name=SpringAIEmbedding
server.port=8080
## ????AI ????
# Embedding ??
spring.ai.zhipuai.api-key=c721340a438942d0942148b48a22e50e.5VCKagzmQdyHpwyc
spring.ai.zhipuai.base-url=https://open.bigmodel.cn/api/paas
# Embedding ??
spring.ai.zhipuai.embedding-model=embedding-2
# Chat ??
spring.ai.zhipuai.chat.options.model=GLM-4.7-Flash
# ??????
logging.pattern.console=%-5level %logger - %msg%n

8
黄永兴学习笔记/StudySpringAI/SpringAIEmbedding/src/main/resources/knowledge.txt

@ -0,0 +1,8 @@
---
Spring AI 是一个用于简化大模型应用开发的框架,支持智谱AI、OpenAI 等多种大模型厂商。
---
智谱AI Embedding 模型可将文本转换为向量,用于语义检索、相似匹配等场景。
---
RAG(检索增强生成)通过检索本地知识库内容,辅助大模型生成更准确的回答,避免幻觉。
---
Spring AI 提供 EmbeddingModel 和 ChatModel 接口,让开发者快速接入大模型能力。

13
黄永兴学习笔记/StudySpringAI/SpringAIEmbedding/src/test/java/com/example/springaiembedding/SpringAiEmbeddingApplicationTests.java

@ -0,0 +1,13 @@
package com.example.springaiembedding;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class SpringAiEmbeddingApplicationTests {
@Test
void contextLoads() {
}
}

33
黄永兴学习笔记/StudySpringAI/SpringAIQuickStart/.gitignore

@ -0,0 +1,33 @@
HELP.md
target/
.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/

3
黄永兴学习笔记/StudySpringAI/SpringAIQuickStart/.mvn/wrapper/maven-wrapper.properties

@ -0,0 +1,3 @@
wrapperVersion=3.3.4
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.14/apache-maven-3.9.14-bin.zip

104
黄永兴学习笔记/StudySpringAI/SpringAIQuickStart/pom.xml

@ -0,0 +1,104 @@
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.13</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>SpringAIQuickStart</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SpringAIQuickStart</name>
<description>SpringAIQuickStart</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.0.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring AI Deepseek 模型依赖 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-deepseek</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!-- 声明仓库,用于获取 Spring AI 以及相关预发布版本 -->
<repositories>
<!-- Spring Milestones 仓库 -->
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<!-- Spring Snapshots 仓库 -->
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

13
黄永兴学习笔记/StudySpringAI/SpringAIQuickStart/src/main/java/com/example/springaiquickstart/SpringAiQuickStartApplication.java

@ -0,0 +1,13 @@
package com.example.springaiquickstart;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringAiQuickStartApplication {
public static void main(String[] args) {
SpringApplication.run(SpringAiQuickStartApplication.class, args);
}
}

127
黄永兴学习笔记/StudySpringAI/SpringAIQuickStart/src/main/java/com/example/springaiquickstart/controller/ChatController.java

@ -0,0 +1,127 @@
package com.example.springaiquickstart.controller;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.model.Generation;
import org.springframework.ai.chat.prompt.ChatOptions;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.deepseek.DeepSeekChatModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpRequest;
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;
import reactor.core.publisher.Flux;
import java.util.Arrays;
import java.util.List;
@RestController
@RequestMapping("/ai")
public class ChatController {
@Autowired
private DeepSeekChatModel chatModel;
// 与模型直接对话返回字符串响应
@GetMapping("/generate")
public String generate(@RequestParam(value = "message",defaultValue = "你好,你是谁?") String message) {
System.out.println("message: " + message);
// 与模型直接对话调用chatModel的call方法生成响应
String response = chatModel.call(message);
System.out.println("response: " + response);
return response;
}
// 与模型对话流式返回内容
@GetMapping("/generateStream1")
public Flux<ChatResponse> generateStream1(@RequestParam(value = "message",defaultValue = "你好,你是谁?") String message) {
System.out.println("message: " + message);
// 与模型对话流式返回内容
Prompt prompt = new Prompt(message);
Flux<ChatResponse> stream = chatModel.stream(prompt);
System.out.println("stream: " + stream);
return stream;
}
// 与模型对话流式返回内容转换为字符串流
// 解决中文乱码问题
// 用lambda表达式简化
@GetMapping("/generateStream2")
public Flux<String> generateStream2(
@RequestParam(value = "message",defaultValue = "你好,你是谁?") String message,
HttpServletResponse response
) {
//设置字符编码为UTF-8,解决中文乱码问题
response.setCharacterEncoding("UTF-8");
System.out.println("message: " + message);
// 与模型对话流式返回内容
Prompt prompt = new Prompt(message);
Flux<ChatResponse> stream = chatModel.stream(prompt);
// 转换为字符串流用lambda表达式简化
Flux<String> result = stream.map(ChatResponse ->
ChatResponse.getResult().getOutput().getText()
);
// 转换为字符串流用方法引用简化
// Flux<String> result = stream.map(ChatResponse::getResult)
// .map(Generation::getOutput)
// .map(AssistantMessage::getText);
System.out.println("result: " + result);
return result;
}
//运行时设置模型参数
@GetMapping("/runtimeOptions")
public Flux<String> runtimeOptions(
@RequestParam(value = "message",defaultValue = "你好,你是谁?") String message,
@RequestParam(value = "temperature",required = false) Double temp,
HttpServletResponse response
) {
//设置字符编码为UTF-8,解决中文乱码问题
response.setCharacterEncoding("UTF-8");
// 构建系统提示
SystemMessage systemMessage = new SystemMessage("你是一个资深Java开发工程师,回答要简洁专业");
// 构建用户消息
UserMessage userMessage = new UserMessage(message);
// 构建历史消息多轮对话时加入
List<Message> messages = Arrays.asList(systemMessage, userMessage);
// 封装成 Prompt还可以设置模型参数
Prompt prompt = new Prompt(messages,
ChatOptions.builder()
.temperature(temp)
.maxTokens(1000)
.build()
);
// 流式调用
Flux<ChatResponse> stream = chatModel.stream(prompt);
// 转换为字符串流用lambda表达式简化
Flux<String> result = stream.map(ChatResponse ->
ChatResponse.getResult().getOutput().getText()
);
System.out.println("result: " + result);
return result;
}
}

13
黄永兴学习笔记/StudySpringAI/SpringAIQuickStart/src/main/resources/application.properties

@ -0,0 +1,13 @@
spring.application.name=SpringAIQuickStart
server.port=8080
#?? Deepseek ???????url?????????
spring.ai.deepseek.base-url=https://api.deepseek.com
spring.ai.deepseek.api-key=sk-ccbfe09f433148129cd98df6150653e8
spring.ai.deepseek.chat.options.model=deepseek-chat
#??0-2???0????????2???????
spring.ai.deepseek.chat.options.temperature=0.8

224
黄永兴学习笔记/StudySpringAI/SpringAIQuickStart/src/main/resources/static/index.html

@ -0,0 +1,224 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Spring AI 聊天助手</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#3b82f6',
secondary: '#64748b',
neutral: '#f8fafc',
dark: '#1e293b'
},
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif']
}
}
}
}
</script>
<style type="text/tailwindcss">
@layer utilities {
.content-auto {
content-visibility: auto;
}
.chat-message {
@apply p-4 rounded-lg mb-4 max-w-[80%];
}
.user-message {
@apply bg-primary text-white self-end;
}
.ai-message {
@apply bg-neutral border border-gray-200 text-dark self-start;
}
}
</style>
</head>
<body class="bg-gray-50 min-h-screen flex flex-col">
<!-- 顶部导航栏 -->
<header class="bg-white shadow-sm">
<div class="container mx-auto px-4 py-4 flex justify-between items-center">
<div class="flex items-center space-x-2">
<i class="fa fa-robot text-primary text-2xl"></i>
<h1 class="text-xl font-bold text-dark">Spring AI 聊天助手</h1>
</div>
<div class="text-sm text-secondary">
<span id="status" class="flex items-center">
<span class="w-2 h-2 bg-green-500 rounded-full mr-2"></span>
在线
</span>
</div>
</div>
</header>
<!-- 主内容区 -->
<main class="flex-1 container mx-auto px-4 py-8 max-w-4xl">
<!-- 聊天区域 -->
<div class="bg-white rounded-xl shadow-md overflow-hidden">
<!-- 聊天头部 -->
<div class="bg-primary text-white p-4">
<h2 class="text-lg font-semibold">AI 助手</h2>
<p class="text-sm opacity-80">基于 DeepSeek 模型</p>
</div>
<!-- 聊天消息区 -->
<div id="chat-messages" class="p-4 h-[500px] overflow-y-auto flex flex-col space-y-4">
<!-- 欢迎消息 -->
<div class="chat-message ai-message">
<div class="flex items-start">
<div class="w-8 h-8 rounded-full bg-primary text-white flex items-center justify-center mr-3 flex-shrink-0">
<i class="fa fa-robot"></i>
</div>
<div>
<p class="font-semibold mb-1">AI 助手</p>
<p>你好!我是基于 DeepSeek 模型的 AI 助手,有什么可以帮助你的吗?</p>
</div>
</div>
</div>
</div>
<!-- 输入区域 -->
<div class="p-4 border-t">
<form id="chat-form" class="flex space-x-2">
<input
type="text"
id="message-input"
placeholder="输入消息..."
class="flex-1 border border-gray-300 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent"
>
<button
type="submit"
id="send-button"
class="bg-primary text-white rounded-lg px-6 py-2 hover:bg-primary/90 transition-colors flex items-center space-x-2"
>
<span>发送</span>
<i class="fa fa-paper-plane"></i>
</button>
</form>
</div>
</div>
<!-- 功能说明 -->
<div class="mt-8 bg-white rounded-xl shadow-md p-6">
<h3 class="text-lg font-semibold mb-4">功能说明</h3>
<ul class="space-y-2 text-secondary">
<li class="flex items-center">
<i class="fa fa-check-circle text-green-500 mr-2"></i>
支持自然语言对话
</li>
<li class="flex items-center">
<i class="fa fa-check-circle text-green-500 mr-2"></i>
基于 DeepSeek 大语言模型
</li>
<li class="flex items-center">
<i class="fa fa-check-circle text-green-500 mr-2"></i>
实时响应生成
</li>
<li class="flex items-center">
<i class="fa fa-check-circle text-green-500 mr-2"></i>
简洁美观的用户界面
</li>
</ul>
</div>
</main>
<!-- 页脚 -->
<footer class="bg-white shadow-sm mt-8">
<div class="container mx-auto px-4 py-4 text-center text-secondary text-sm">
<p>© 2026 Spring AI 聊天助手 | 基于 DeepSeek 模型</p>
</div>
</footer>
<script>
document.addEventListener('DOMContentLoaded', function() {
const chatForm = document.getElementById('chat-form');
const messageInput = document.getElementById('message-input');
const chatMessages = document.getElementById('chat-messages');
const sendButton = document.getElementById('send-button');
const status = document.getElementById('status');
// 发送消息
chatForm.addEventListener('submit', function(e) {
e.preventDefault();
const message = messageInput.value.trim();
if (message) {
// 添加用户消息到聊天区
addMessage('user', message);
messageInput.value = '';
// 禁用发送按钮
sendButton.disabled = true;
sendButton.classList.add('opacity-50');
status.innerHTML = '<span class="w-2 h-2 bg-yellow-500 rounded-full mr-2"></span>处理中...';
// 调用后端 API
fetch(`/ai/generate?message=${encodeURIComponent(message)}`)
.then(response => response.text())
.then(data => {
// 添加 AI 响应到聊天区
addMessage('ai', data);
})
.catch(error => {
console.error('Error:', error);
addMessage('ai', '抱歉,处理请求时出错,请稍后再试。');
})
.finally(() => {
// 恢复发送按钮状态
sendButton.disabled = false;
sendButton.classList.remove('opacity-50');
status.innerHTML = '<span class="w-2 h-2 bg-green-500 rounded-full mr-2"></span>在线';
});
}
});
// 添加消息到聊天区
function addMessage(type, content) {
const messageDiv = document.createElement('div');
messageDiv.className = `chat-message ${type === 'user' ? 'user-message' : 'ai-message'} self-${type === 'user' ? 'end' : 'start'}`;
if (type === 'user') {
messageDiv.innerHTML = `
<div class="flex items-start justify-end">
<div>
<p class="font-semibold mb-1 text-right"></p>
<p>${content}</p>
</div>
<div class="w-8 h-8 rounded-full bg-gray-300 text-dark flex items-center justify-center ml-3 flex-shrink-0">
<i class="fa fa-user"></i>
</div>
</div>
`;
} else {
messageDiv.innerHTML = `
<div class="flex items-start">
<div class="w-8 h-8 rounded-full bg-primary text-white flex items-center justify-center mr-3 flex-shrink-0">
<i class="fa fa-robot"></i>
</div>
<div>
<p class="font-semibold mb-1">AI 助手</p>
<p>${content}</p>
</div>
</div>
`;
}
chatMessages.appendChild(messageDiv);
chatMessages.scrollTop = chatMessages.scrollHeight;
}
// 回车键发送消息
messageInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
chatForm.dispatchEvent(new Event('submit'));
}
});
});
</script>
</body>
</html>

13
黄永兴学习笔记/StudySpringAI/SpringAIQuickStart/src/test/java/com/example/springaiquickstart/SpringAiQuickStartApplicationTests.java

@ -0,0 +1,13 @@
package com.example.springaiquickstart;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class SpringAiQuickStartApplicationTests {
@Test
void contextLoads() {
}
}

8
黄永兴学习笔记/StudySpringAI/StudySpringAI.iml

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="GENERAL_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
Loading…
Cancel
Save