springAI结合ollama简单实现

Mr.var 2024-10-26 09:01:02 阅读 97

一、ollama安装下载

1、官方下载地址

https://ollama.com/

2、修改模型的安装地址

Ollama的模型会占用较大的磁盘空间,默认会在C盘用户文件夹下的.ollama/models文件夹中,可以配置环境变量OLLAMA_MODELS,设置为指定的路径:

在这里插入图片描述

3、模型参考

https://ollama.com/library

下载命令:

<code># 电脑性能好的可以装一个高版本的,例如4b、7b等

ollama run qwen:0.5b

# 查看已安装的模型

ollama list

二、springAI的使用

1、环境准备

jdk17、springboot3.0+

2、添加依赖

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

这里贴出完整pom:

<code><?xml version="1.0" encoding="UTF-8"?>code>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"code>

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">code>

<modelVersion>4.0.0</modelVersion>

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>3.3.2</version>

<relativePath/> <!-- lookup parent from repository -->

</parent>

<groupId>com.example</groupId>

<artifactId>ollamaTest</artifactId>

<version>0.0.1-SNAPSHOT</version>

<name>spring-ai-ollama</name>

<description>spring-ai-ollama</description>

<properties>

<java.version>17</java.version>

<!-- 快照版本-->

<spring-ai.version>1.0.0-SNAPSHOT</spring-ai.version>

</properties>

<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.ai</groupId>

<artifactId>spring-ai-ollama-spring-boot-starter</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-devtools</artifactId>

<scope>runtime</scope>

<optional>true</optional>

</dependency>

<dependency>

<groupId>org.projectlombok</groupId>

<artifactId>lombok</artifactId>

<optional>true</optional>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-test</artifactId>

<scope>test</scope>

</dependency>

</dependencies>

<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>

<build>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

<configuration>

<excludes>

<exclude>

<groupId>org.projectlombok</groupId>

<artifactId>lombok</artifactId>

</exclude>

</excludes>

</configuration>

</plugin>

</plugins>

</build>

<!-- 快照版本-->

<repositories>

<repository>

<id>spring-snapshot</id>

<name>Spring Snapshots</name>

<url>https://repo.spring.io/snapshot</url>

<releases>

<enabled>false</enabled>

</releases>

</repository>

</repositories>

</project>

3、编写一个公共的调用组件

/**

* 存入上下文信息,并调用接口进行聊天

*/

@Component

public class Completion {

@Resource

private OllamaChatModel aiClient;

/**

* 最大消息记录数

*/

private final static Integer MAX_SIZE = 10;

/**

* 消息记录

*/

private List<Message> messages = new ArrayList<>();

/**

* 初始化存入系统消息

*/

@PostConstruct

private void addSystemMessage() {

String message = "李白(701年2月28日—762年12月),字太白,号青莲居士,出生于蜀郡绵州昌隆县(今四川省绵阳市江油市青莲镇),一说出生于西域碎叶 ,祖籍陇西成纪(今甘肃省秦安县)。唐朝伟大的浪漫主义诗人,凉武昭王李暠九世孙 。" +

"为人爽朗大方,乐于交友,爱好饮酒作诗,名列“酒中八仙” 。曾经得到唐玄宗李隆基赏识,担任翰林供奉,赐金放还后,游历全国,先后迎娶宰相许圉师、宗楚客的孙女。唐肃宗李亨即位后,卷入永王之乱,流放夜郎,辗转到达当涂县令李阳冰家。上元二年,去世,时年六十二 。" +

"著有《李太白集》,代表作有《望庐山瀑布》《行路难》《蜀道难》《将进酒》《早发白帝城》《黄鹤楼送孟浩然之广陵》等。李白所作词赋,就其开创意义及艺术成就而言,享有极为崇高的地位,后世誉为“诗仙”,与诗圣杜甫并称“李杜”。";

Message systemMessage = new SystemMessage(message);

messages.add(systemMessage);

}

/**

* 存储用户发送的消息

*/

private void addUserMessage(String message) {

Message userMessage = new UserMessage(message);

messages.add(userMessage);

}

/**

* 存储AI回复的消息

*/

private void addAssistantMessage(String message) {

Message assistantMessage = new AssistantMessage(message);

messages.add(assistantMessage);

}

/**

* 聊天接口

*/

public String chat(String message) {

addUserMessage(message);

String result = aiClient.call(new Prompt(messages)).getResult().getOutput().getContent();

addAssistantMessage(result);

update();

return result;

}

/**

* 流式聊天接口

*/

public Flux<String> chatStream(String message) {

addUserMessage(message);

StringBuffer fullReply = new StringBuffer();

Flux<String> fluxResult = aiClient.stream(new Prompt(messages))

.flatMap(response -> {

String reply = response.getResult().getOutput().getContent();

//拼接回复内容

fullReply.append(reply);

return Flux.just(reply);

})

.doOnComplete(() -> {

//监听流式响应完成,完整回复存入消息记录

System.out.println(fullReply);

addAssistantMessage(String.valueOf(fullReply));

});

update();

return fluxResult;

}

/**

* 更新消息记录

*/

private void update() {

if (messages.size() > MAX_SIZE) {

messages = messages.subList(messages.size() - MAX_SIZE, messages.size());

}

}

}

4、调用接口

@RestController

@RequestMapping("/ollama")

public class OllamaController {

@Resource

private OllamaChatModel ollamaChatModel;

/**

* 简单调用

*/

@PostMapping(value = "/ai/ask")

public Object ask(String msg) {

String called = ollamaChatModel.call(msg);

System.out.println(called);

return called;

}

/***

* 流式方式

*/

@PostMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)

public Flux<String> stream(String msg) {

return ollamaChatModel.stream(msg).flatMapSequential(Flux::just);

}

private final Completion completion;

public OllamaController(Completion completion) {

this.completion = completion;

}

/**

* 分析上下文聊天

*/

@PostMapping("/chat")

public String chat(String message) {

return completion.chat(message);

}

/**

* 流式上下文

*/

@PostMapping(value = "/chatStream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)

public Flux<String> chatStream(@RequestBody String message) {

return completion.chatStream(message);

}

}

5、测试调用

在这里插入图片描述

6、前端使用fetch处理流式数据

<code><!DOCTYPE html>

<html>

<head>

<meta name="viewport" content="width=device-width, initial-scale=1.0">code>

<title>Test Page</title>

</head>

<body>

<input type="text" id="inputData">code>

<button onclick="sendRequest()">发送</button>code>

<div id="output"></div>code>

<script>

const s = document.getElementById('output'); //获取元素ID

function sendRequest(msg) { -- -->

const inputData = document.getElementById('inputData').value;

s.innerText += (inputData + "\n");

// 发送 POST 请求

fetch('http://localhost:8088/ollama/chatStream', {

method: "POST",

body: JSON.stringify({

"message": inputData

}),

timeout: 0,

dataType: "text/event-stream",

headers: {

"Content-Type": "application/json"

},

}).then(response => {

// 检查响应是否成功

if (!response.ok) {

throw new Error('Network response was not ok');

}

// 返回一个可读流

return response.body;

}).then(body => {

const reader = body.getReader();

// 读取数据流

function read() {

return reader.read().then(({

done,

value

}) => {

// 检查是否读取完毕

if (done) {

console.log('已传输完毕');

s.innerText += "\n";

return;

}

// 处理每个数据块

// console.log('收到的数据:', value);

let data = new TextDecoder().decode(value);

//处理data:字样,格式化流数据

s.innerText += data.replace(/data:/g, "").replace(/\n/g, "");;

// 继续读取下一个数据块

read();

});

}

// 开始读取数据流

read();

}).catch(error => {

console.error('Fetch error:', error);

});

}

</script>

</body>

</html>

在这里插入图片描述



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。