目录
大模型应用开发
模型部署
模型部署方案对比
云部署
优点:
- 前期成本低
- 部署维护简单
- 弹性扩展
- 全球访问
缺点:
- 数据隐私性不高
- 网络依赖性强
- 长期成本高
本地部署优点:
- 数据安全
- 不依赖外部部署
- 长期成本低
- 高度定制
缺点:
- 初始成本高
- 维护复杂
- 部署周期长
开放API优点:
- 前期成本极低
- 无需部署
- 无需维护
- 全球访问
缺点:
- 数据隐私性不高
- 网络依赖性强
- 定制限制
小型企业开发以及个人学习应用开发可以使用开放API,如果要长期使用的话,用云部署或本地部署较好。
模型部署-云部署
云平台 | 公司 | 地址 |
---|---|---|
阿里百炼 | 阿里巴巴 | https://bailian.console.aliyun.com |
腾讯TI平台 | 腾讯 | https://cloud.tencent.com/product/ti |
千帆平台 | 百度 | https://console.bce.baidu.com/gianfan/overview |
SiliconCloud | 硅基流动 | https://siliconflow.cn/zh-cn/siliconcloud |
火山方舟-火山引擎 | 字节跳动 | https://www.volcengine.com/product/ark |
模型部署-本地部署
本地部署最简单的一种方案就是使用ollama,官网地址:https://ollama.com
打开ollama的官网可以选择系统下载

左上角Models里面会有各个AI大模型

点击你要选择的大模型,下面会有许多版本让你选择,后面的1.5b,7b指的是它的算力,数值越大对电脑配置要求越高,数值最大的就是我们说的满血版,其余都是阉割版,右上角是对应使用的命令,打开命令提示符并输入指令它就会自动为你下载。

调用大模型
下面是DeepSeek官方给出的一段API示例代码:

AI应用开发技术架构

SpringAI
对话机器人-快速入门
1.引入依赖(可以在创建项目时在加入依赖时AI下边勾选对应依赖)
<properties>
<java.version>17</java.version>
<spring-ai.version>1.0.3</spring-ai.version>
</properties>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-ollama</artifactId>
</dependency>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
2.配置大模型
spring:
application:
name: demo
ai:
ollama:
base-url: http://localhost:11434
chat:
model: deepseek-r1:8b
3.配置客户端
package com.example.config;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.ollama.OllamaChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CommonConfiguration {
@Bean
public ChatClient chatClient(OllamaChatModel model) {
return ChatClient
.builder(model)
.build();
}
}
都配置好以后就能书写请求然后启动项目发送请求了
@RequiredArgsConstructor
@RestController
@RequestMapping("/ai")
public class ChatController {
private final ChatClient chatClient;
@RequestMapping("/chat1")
// 阻塞式返回(全部输出完才返回)
public String chat(String prompt) {
return chatClient.prompt()
.user(prompt)
.call()
.content();
}
// 流式返回(输出过程中返回)
//这里要在返回值加上 produces = "text/html;charset=utf-8",否则会乱码
@RequestMapping(value = "/chat2", produces = "text/html;charset=utf-8")
public Flux<String> stream(String prompt) {
return chatClient.prompt()
.user(prompt)
.stream()
.content();
}
}
对话机器人-会话日志
SpringAI利用AOP原理提供了AI会话时的拦截、增强等功能,也就是Advisor。

SpringAI在提示词发送到AI大模型之前(②Before advising)和大模型结果产生后但是发送到用户之前(⑤After advising)进行了环绕增强,我们可以在②位置处记录提示词(作为记忆功能),在⑤处记录输出的内容(记录返回日志)。
SpringAI为我们提供了Advisor的实现,可以直接使用不需要我们自己去写。
配置日志选项并且设置日志级别为DEBUG
@Configuration
public class CommonConfiguration {
@Bean
public ChatClient chatClient(OllamaChatModel model) { //创建ChatClient工厂实例
return ChatClient
.builder(model)
.defaultSystem("你是皮卡丘,请以皮卡丘的视角回答")
.defaultAdvisors(new SimpleLoggerAdvisor()) //配置日志Advisor
.build(); //创建ChatClient实例
}
}
#配置日志级别为debug
logging:
level:
org.springframework.ai.chat.client: DEBUG
com.example.demo: DEBUG
对话机器人-会话记忆
大模型是不具备记忆能力的,要想让大模型记住之前聊天的内容,唯一的办法就是把之前聊天的内容与新的提示词一起发给大模型。

一、定义会话存储方式
要定义会话存储方式,可以去实现ChatMemory接口,然后重写对应方法去实现。
SpringAI也提供了一个默认的实现InMemoryChatMemory(最新1.0.3版本已经换成MessageWindowChatMemory了),但这个是存储在内存中的,服务器重启记忆就没了。

二、配置会话记忆Advisor

三、添加会话id

上面advisors里的AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY 在最新的1.0.3中已经修改为ChatMemory.CONVERSATION_ID
最后综合代码如下:
@Configuration
public class CommonConfiguration {
@Bean
public ChatMemory chatMemory() {
// 创建Memory实例
return MessageWindowChatMemory.builder().build();
}
@Bean
public ChatClient chatClient(OllamaChatModel model, ChatMemory chatMemory) { //创建ChatClient工厂实例
return ChatClient
.builder(model)
.defaultSystem("你是皮卡丘,请以皮卡丘的视角回答")
.defaultAdvisors(
new SimpleLoggerAdvisor(),
// 配置MemoryAdvisor
MessageChatMemoryAdvisor.builder(chatMemory).build()
) //配置日志Advisor
.build(); //创建ChatClient实例
}
}
// 流式返回(输出过程中返回)
//这里要在返回值加上 produces = "text/html;charset=utf-8",否则会乱码
@RequestMapping(value = "/chat2", produces = "text/html;charset=utf-8")
//再传入一个chatId
public Flux<String> stream(String prompt, String chatId) {
return chatClient.prompt()
.user(prompt)
//这里的key值是一个固定的参数,不能随便修改
.advisors(a -> a.param(CONVERSATION_ID, chatId) )
.stream()
.content();
}
}
对话机器人-会话历史记录功能

第一个请求是要查询到对应AI会话业务下的所有会话ID,即上图中左侧列表中的两个就是该请求的返回值。 第二个请求是要根据会话类型和会话id返回用户和AI的对话记录。
我们先要写记录会话ID接口,然后再写查询会话id记录,最后根据会话id查询出具体的会话内容。
先写出记录会话记录和查询会话id记录的方法
public interface ChatHistoryRepository {
// 保存会话记录
void save(String type, String chatId);
// 获取会话ID记录
List<String> get(String type);
}
public class InMemoryChatHistoryRepository implements ChatHistoryRepository{
private final Map<String, List<String>> chatHistory = new HashMap<>();
// 保存会话记录
@Override
public void save(String type, String chatId) {
//先判断该类型会话是否已经存在会话id列表,如果不存在则创建一个空列表
if (!chatHistory.containsKey(type)){
chatHistory.put(type, List.of());
}
//从缓存中获取该类型会话的会话id列表
List<String> chatHistoryList = chatHistory.get(type);
//如果该类型列表中已经存在该会话id,则直接返回
if (chatHistoryList.contains(chatId)){
return;
}
//否则将新的会话id添加到该类型列表中
chatHistoryList.add(chatId);
}
// 根据会话类型获取会话ID记录
@Override
public List<String> get(String type) {
List<String> chatHistoryList = chatHistory.get(type);
//如果该类型列表不存在,则返回一个空列表
return chatHistoryList != null ? chatHistoryList : List.of();
}
}
在对话的时候对会话记录进行保存

我们创建实例时用的是spring ai提供的方法,我们对话的具体内容也由它进行存储记录,要查询到会话内容就要看它内部是如何查询的。

Ctrl+左键进去我们可以看到下面的方法,它需要会话id返回Message类型的集合。
进入到Message里面,我们需要看它返回的是否是我们需要的格式,Message是一个接口,里面有一个方法 getMessageType() 并且其继承了Content。

进入到 getMessageType() 方法里,其返回的是对话的角色(类型),我们只需要其中的 user(用户提问)和 assistant(ai回答)。

进入到Content中,里面的getText()方法就是获取对话具体内容的方法。

看完了spring ai提供的方法和返回格式,我们能知道其提供的格式不是我们想要的,因此我们就需要写一个VO类来编写我们需要的返回格式。
@Data
@NoArgsConstructor
public class MessageVO {
private String role;
private String content;
// 构造函数
public MessageVO(Message message) {
//我们从message中获取role和content
switch (message.getMessageType()){
//保留下来我们需要的角色
case USER -> this.role = "user";
case ASSISTANT -> this.role = "assistant";
default -> this.role = "";
}
this.content = message.getText();
}
}
最后我们把获取会话记录的方法写出来就完成了。
@GetMapping("/{type}/{chatId}")
public List<MessageVO> getChatHistory(@PathVariable("type") String type, @PathVariable("chatId") String chatId) {
//获取会话记录
List<Message> messages = chatMemory.get(chatId);
if (messages == null){
return List.of();
}
return messages.stream().map(MessageVO::new).toList();
}