您的位置:首页 > 娱乐 > 明星 > 辽宁工程建筑信息网_苏州专业高端网站建设企业_松松软文平台_肇庆疫情最新消息

辽宁工程建筑信息网_苏州专业高端网站建设企业_松松软文平台_肇庆疫情最新消息

2025/4/29 7:40:57 来源:https://blog.csdn.net/qq_66862911/article/details/147382520  浏览:    关键词:辽宁工程建筑信息网_苏州专业高端网站建设企业_松松软文平台_肇庆疫情最新消息
辽宁工程建筑信息网_苏州专业高端网站建设企业_松松软文平台_肇庆疫情最新消息

目录

1、Ollama 的下载配置 与 DeepSeek 的本地部署流程

1.1 下载安装 Ollama

1.2 搜索模型并进行本地部署

2、基于 SpringAI 调用 Ollama 模型

2.1 基于OpenAI 的接口规范(其他模型基本遵循)

2.2 在 IDEA 中进行创建 SpringAI 项目并调用 DS 模型

3、基于 SpringAI 实现会话记忆功能

4、基于 SpringAI 实现会话历史功能

需求一:需要进行展示历史会话的列表信息

需求二:点击会话列表,展示对应的历史会话记录信息


📜后端代码地址:

MySpringAI: 基于 SpringAI + 大模型 实现基本的对话功能(只提供后端)https://gitee.com/MIMIDeK/my-spring-ai.git

1、Ollama 的下载配置 与 DeepSeek 的本地部署流程

很多云平台都提供了一键部署大模型的功能,这里不再赘述(阿里云百炼平台、火山方舟-火山引擎等)


官网地址如下:

Ollamahttps://ollama.com/

1.1 下载安装 Ollama

首先,我们需要下载一个Ollama的客户端,在官网提供了各种不同版本的Ollama,大家可以根据自己的需要下载

注意:

Ollama默认安装目录是C盘的用户目录,如果不希望安装在C盘的话(其实C盘如果足够大放C盘也没事),就不能直接双击安装了,需要通过命令行安装

OllamaSetup.exe 所在目录打开cmd命令行,然后命令如下:

OllamaSetup.exe /DIR=你要安装的目录位置

安装完成后,需要进行环境变量的配置:

OLLAMA_MODELS=你想要保存模型的目录

1.2 搜索模型并进行本地部署

Ollama 是一个模型管理工具和平台,它提供了很多国内外常见的模型,我们可以在其官网上搜索自己需要的模型,这里我们部署的是 DeepSeek R1 模型(我选择的是 7b,根据需求进行选择):

其中,Ollama 的命令很像 Docker 的,选择好对应的模型后,在控制台中进行运行命令:

ollama run deepseek-r1:7b

首次下载的话会有些慢,耐性等待即可

以下是本地下载部署完成后,进行对话的场景,ctrl + d 进行退出与 DeepSeek 的对话:


2、基于 SpringAI 调用 Ollama 模型

2.1 基于OpenAI 的接口规范(其他模型基本遵循)

目前大多数大模型都遵循 OpenAI 的接口规范,是基于Http协议的接口;因此请求路径、参数、返回值信息都是类似的,可能会有一些小的差别,具体需要查看大模型的官方API文档

以下是基于 Python 的代码示范:

# Please install OpenAI SDK first: `pip3 install openai`from openai import OpenAI# 1.初始化OpenAI客户端,要指定两个参数:api_key、base_url
client = OpenAI(api_key="<DeepSeek API Key>", base_url="https://api.deepseek.com")# 2.发送http请求到大模型,参数比较多
response = client.chat.completions.create(model="deepseek-chat", # 2.1.选择要访问的模型messages=[ # 2.2.发送给大模型的消息{"role": "system", "content": "You are a helpful assistant"},{"role": "user", "content": "Hello"},],stream=False # 2.3.是否以流式返回结果
)print(response.choices[0].message.content)

接口说明

  • 请求方式):通常是POST,因为要传递JSON风格的参数
  • 请求路径):与平台有关
    • DeepSeek官方平台:https://api.deepseek.com
    • 阿里云百炼平台:https://dashscope.aliyuncs.com/compatible-mode/v1
    • 本地ollama部署的模型:http://localhost:11434
  • 安全校验):开放平台 都需要提供 API_KEY 来校验权限,本地 ollama 则不需要
  • 请求参数)(这里只列举常用的):
    • model:要访问的模型名称
    • messages:发送给大模型的消息,是一个数组
    • stream:true,代表响应结果流式返回;false,代表响应结果一次性返回,但需要等待
    • temperature:取值范围[0:2),代表大模型生成结果的随机性,越小随机性越低。DeepSeek-R1不支持
  • 这里请求参数中的 messages 是一个消息数组,其中包含两个属性):
    • role:消息对应的角色
    • content:消息内容

2.2 在 IDEA 中进行创建 SpringAI 项目并调用 DS 模型

以下是创建项目的基本依赖需求(基于SpringBoot3、JDK17):

.yaml 配置:

这里是基于 Ollama 的(默认端口是11434)

这里是基于 openAI 的,进行调用开放平台的 API,需要输入 API-KEY(后面就不具体写明了,这里主要是基于 Ollama 的调用演示)

Config 配置类:(固定写法)

@Configuration
public class CommonConfig {@Beanpublic ChatClient chatClient(OllamaChatModel model) {return ChatClient.builder(model).build();}
}

Controller 控制响应类:(这里是以流式的方式进行响应)

@RestController
@RequestMapping("/ai")
public class ChatController {@Resourceprivate ChatClient chatClient;// 由于以流式方式调用模型,展示的数据会出现乱码,需要进行规定编码格式@GetMapping(value = "/chat", produces = "text/html; charset=utf-8")public Flux<String> chat(String msg) {return chatClient.prompt().user(msg).stream().content();}
}

进行页面的调用(若非流式访问,则需要等待 DS 生成完毕,才会出现响应信息):

注意,进行接口的调用时,需要启动 ollama 中的模型

🔖也可以加上日志的控制台打印输出,方便调试

.yml 中的配置:

然后在 Config 配置类中添加这一行代码,即可开启日志的打印:


3、基于 SpringAI 实现会话记忆功能

大致步骤:

定义会话存储方式(默认基于Map集合) ➡️ 配置会话记忆(关联上下文) ➡️ 添加会话ID(保证每个会话独立)

这里使用默认方式,由源码可知是基于 Map 直接存入内存中的;当然也可以重写 ChatMemory,比如存入到 Redis 中做缓存之类的(根据业务需求)

然后将 "存储方式" 配置到 "会话的上下文" 中,以处理会话的内容

运行结果:

之前的msg提问信息是:现在有15个苹果,6个人应该怎么分才好

我现在直接问它x个人应该怎么分,很明显它会进行关联之前的会话,根据上下文,来进行作答

存在问题:

然而,以上会话的处理会比较混乱,不管是谁来进行提问,模型都会自动关联所有的会话上下文来进行回答,这显然是不符合需求的;这时就需要与前端进行交接,即传递对应的会话 ID 过来进行处理,以实现用户的每个独立会话内容互不干扰

由前端响应接口可知,不同的会话对应着不同的会话ID

这时需要在 Controller 接口中添加以下配置,来接收存储不同会话下的ID


4、基于 SpringAI 实现会话历史功能

存在问题:目前,只要页面一刷新,之前的会话列表和对话记录都会被清除,不会被保留展示

前言:以下的 type 参数可根据具体需求进行更换,chatId 建议作保留以记录唯一会话

需求一:需要进行展示历史会话的列表信息

以下是对应的 UI 页面,以及对应的接口地址(模拟):

以下是 自定义 的 方法接口 与 实现类,主要用于 保存 和 获取 会话信息

public interface ChatHistoryService {/*** 保存会话记录(这里的 type 可根据需求进行更改,chatId 建议保留以作为会话的唯一ID)*/void save(String type, String chatId);/*** 获取会话列表(这里的 type 可根据需求进行更改)*/List<String> getChatIds(String type);
}
@Service
public class ChatHistoryServiceImpl implements ChatHistoryService {// 使用 map 集合进行存储private final Map<String, List<String>> chatHistoryMap = new HashMap<>();/*** 保存会话记录(这里的 type 可根据需求进行更改,chatId 建议保留以作为会话的唯一ID)*/@Overridepublic void save(String type, String chatId) {// 1.判断当前是否存在对应的 type 类型,若不存在则新增if (! chatHistoryMap.containsKey(type)) {chatHistoryMap.put(type, new ArrayList<>());}// 2.判断当前的 type 对应的 会话集合ID 是否含有当前的会话IDList<String> chatIds = chatHistoryMap.get(type);if (chatIds.contains(chatId)) {return;}chatIds.add(chatId);}/*** 获取会话列表信息(这里的 type 可根据需求进行更改)*/@Overridepublic List<String> getChatIds(String type) {List<String> chatIds = chatHistoryMap.get(type);return chatIds == null ? new ArrayList<>() : chatIds;}
}

每次用户在进行模型对话的时候,都需要将会话ID做保存(这里的 key 根据自己的业务需求来定,比如使用 用户ID 来进行拼接等,这里先写死)

然后获取当前对应 key 的会话 ID 集合,进行会话列表信息展示

@RestController
@RequestMapping("/ai/history")
public class ChatHistoryController {@Resourceprivate ChatHistoryService chatHistoryService;/*** 获取历史会话列表信息(这里的 type 可根据需求进行更改)*/@RequestMapping("/{type}")public List<String> getChatIds(@PathVariable("type") String type) {return chatHistoryService.getChatIds(type);}
}

需求二:点击会话列表,展示对应的历史会话记录信息

像以下UI所示,随便点击其中一个会话列表,对应的历史会话记录依然存在,并进行全部展示

接口地址(模拟):

会话的存储是在 ChatMemory 类中进行的,所以需要跟进源码进行查看

主要还是这个 get 方法,来进行获取对应会话的对话记录

然后 返回值 Message 类型,内部有继承以及实现的类

其中的 Content 代表着对话记录的内容,MessageType 代表着当前对话记录的类型

以上结论:由于需要满足当前接口的返回值,所以需要创建一个 DTO 来进行满足

@Data
@NoArgsConstructor
public class MessageDTO implements Serializable {/*** 角色类型*/private String role;/*** 对应的内容信息*/private String content;public MessageDTO(Message message) {// 判断当前会话的类型switch (message.getMessageType()) {case USER:this.role = "user";break;case ASSISTANT:this.role = "assistant";break;case SYSTEM:this.role = "system";break;case TOOL:this.role = "tool";break;default:this.role = "";break;}this.content = message.getText();}@Serialprivate static final long serialVersionUID = 1L;
}

接下来实现 “查询对话记录” 接口,与前端交互,即可实现展现历史对话记录

    /*** 查询会话记录详情(这里的 type 可根据需求进行更改,chatId 建议保留以作为会话的唯一ID)*/@GetMapping("/{type}/{chatId}")public List<MessageDTO> getChatHistory(@PathVariable("type") String type, @PathVariable("chatId") String chatId) {// 这里的展示记录条数最大值规定,直接使用的 int 型最大值,具体自己根据需求规定List<Message> messages = chatMemory.get(chatId, Integer.MAX_VALUE);if (messages == null) {return List.of();}// 进行封装返回类型return messages.stream().map(new Function<Message, MessageDTO>() {@Overridepublic MessageDTO apply(Message message) {return new MessageDTO(message);}}).toList();}

版权声明:

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

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