Spring AI + ollama Local Build Chat AI
For those of you who don't know how to build ollama, check out the previous post.Spring AI for Beginners。
The project can be viewedgitee
preliminary
Adding Dependencies
Create a SpringBoot project and add the main relevant dependencies (spring-boot-starter-web, spring-ai-ollama-spring-boot-starter)
Spring AI supports Spring Boot 3. and 3.
Spring Boot 3.2.11 requires at least Java 17 and is compatible with versions up to and including Java 23
<dependency>
<groupId></groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
<version>1.0.0-M3</version>
</dependency>
configuration file
The parameters can be added in the OllamaChatProperties, yml configuration file, or you can specify the model and other parameters in the project, see OllamaChatProperties for details.
# properties, model qwen2.5:14b depending on the model you download
= qwen2.5:14b
#yml
spring.
ai.
ollama.
chat.
model: qwen2.5:14b
Chat Realization
The main use of the interface is to save dialog information.
I. Using Java to Cache Dialog Messages
Supported Functions: Chat Conversation, Switch Conversation, Delete Conversation
controller
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import .*;
import ;
/*
*@title Controller
*@description Conversations using memory
*@author yb
*@version 1.0
*@create 2024/11/12 14:39
*/
@Controller
public class ChatController {
//injection model,Models in the configuration file,Or you can specify the model in the method
@Resource
private OllamaChatModel model;
//chats client
private ChatClient chatClient;
// Simulating database storage sessions and messages
private final ChatMemory chatMemory = new InMemoryChatMemory();
//home page (of a website)
@GetMapping("/index")
public String index(){
return "index";
}
//开始chats,Generate unique sessionId
@GetMapping("/start")
public String start(Model model){
//新建chats模型
// OllamaOptions options = ();
// ("qwen2.5:14b");
// OllamaChatModel chatModel = new OllamaChatModel(new OllamaApi(), options);
//Create Random Session ID
String sessionId = ().toString();
("sessionId", sessionId);
//创建chatsclient
chatClient = ().defaultAdvisors(new MessageChatMemoryAdvisor(chatMemory, sessionId, 10)).build();
return "chatPage";
}
//chats
@PostMapping("/chat")
@ResponseBody
public String chat(@RequestBody ChatParam param){
//Direct return
return (()).call().content();
}
//删除chats
@DeleteMapping("/clear/{id}")
@ResponseBody
public void clear(@PathVariable("id") String sessionId){
(sessionId);
}
}
rendering (visual representation of how things will turn out)
II. Use of databases to store dialogue information
Supported Functions: Chat Dialog, Switch Dialog, Delete Dialog, Withdraw Message
entity class
import ;
import ;
@Data
public class ChatEntity {
private String id;
/** conversationsid */
private String sessionId;
/** conversations内容 */
private String content;
/** AI、man */
private String type;
/** Creation time */
private Date time;
/** Delete or not,Y-be */
private String beDeleted;
/** AIconversations时,获取man对话ID */
private String userChatId;
}
configuration
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
/*
*@title DBMemory
*@description realization ChatMemory,pour into spring,facilitate the adoption of service methodologies
*@author yb
*@version 1.0
*@create 2024/11/12 16:15
*/
@Configuration
public class DBMemory implements ChatMemory {
@Resource
private IChatService chatService;
@Override
public void add(String conversationId, List<Message> messages) {
for (Message message : messages) {
(conversationId, (), ().getValue());
}
}
@Override
public List<Message> get(String conversationId, int lastN) {
List<ChatEntity> list = (conversationId, lastN);
if(list != null && !()) {
return ().map(l -> {
Message message = null;
if (().equals(())) {
message = new AssistantMessage(());
} else if (().equals(())) {
message = new UserMessage(());
}
return message;
}).collect(Collectors.<Message>toList());
}else {
return new ArrayList<>();
}
}
@Override
public void clear(String conversationId) {
(conversationId);
}
}
Services implementation class
import ;
import ;
import ;
import ;
import .*;
/*
*@title ChatServiceImpl
*@description Save user session service implementation class
*@author yb
*@version 1.0
*@create 2024/11/12 15:50
*/
@Service
public class ChatServiceImpl implements IChatService {
Map<String, List<ChatEntity>> map = new HashMap<>();
@Override
public void saveMessage(String sessionId, String content, String type) {
ChatEntity entity = new ChatEntity();
(().toString());
(content);
(sessionId);
(type);
(new Date());
//Change to Constant
("N");
if(().equals(type)){
(getLastN(sessionId, 1).get(0).getId());
}
//todo Save database
//Simulation saved to database
List<ChatEntity> list = (sessionId, new ArrayList<>());
(entity);
(sessionId, list);
}
@Override
public List<ChatEntity> getLastN(String sessionId, Integer lastN) {
//todo Getting it from the database
//模拟Getting it from the database
List<ChatEntity> list = (sessionId);
return list != null ? ().skip((0, () - lastN)).toList() : ();
}
@Override
public void clear(String sessionId) {
//todo Database update beDeleted field
(sessionId, new ArrayList<>());
}
@Override
public void deleteById(String id) {
//todo The database directs this id digital beDeleted adapt (a story to another medium) Y
for (<String, List<ChatEntity>> next : ()) {
List<ChatEntity> list = ();
(chat -> (()) || (()));
}
}
}
controller
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import .*;
import ;
import ;
/*
*@title ChatController2
*@description Using the database((computing) cache)hold a dialog
*@author yb
*@version 1.0
*@create 2024/11/12 16:12
*/
@Controller
public class ChatController2 {
//injection model,Models in the configuration file,Or you can specify the model in the method
@Resource
private OllamaChatModel model;
//chats client
private ChatClient chatClient;
//操作chats信息service
@Resource
private IChatService chatService;
//Session Storage Methods
@Resource
private DBMemory dbMemory;
//开始chats,Generate unique sessionId
@GetMapping("/start2")
public String start(Model model){
//新建chats模型
// OllamaOptions options = ();
// ("qwen2.5:14b");
// OllamaChatModel chatModel = new OllamaChatModel(new OllamaApi(), options);
//Create Random Session ID
String sessionId = ().toString();
("sessionId", sessionId);
//创建chats client
chatClient = ().defaultAdvisors(new MessageChatMemoryAdvisor(dbMemory, sessionId, 10)).build();
return "chatPage2";
}
//Switching Sessions,You need to pass in the sessionId
@GetMapping("/exchange2/{id}")
public String exchange(@PathVariable("id")String sessionId){
//切换chats client
chatClient = ().defaultAdvisors(new MessageChatMemoryAdvisor(dbMemory, sessionId, 10)).build();
return "chatPage2";
}
//chats
@PostMapping("/chat2")
@ResponseBody
public List<ChatEntity> chat(@RequestBody ChatParam param){
//todo judgements AI Whether to return to the session,从而judgements用户是否可以输入
(()).call().content();
//Get the latest two items returned,One user question(User Get User SendID),article AI Return results
return ((), 2);
}
//Withdrawal of messages
@DeleteMapping("/revoke2/{id}")
@ResponseBody
public void revoke(@PathVariable("id") String id){
(id);
}
//Empty message
@DeleteMapping("/del2/{id}")
@ResponseBody
public void clear(@PathVariable("id") String sessionId){
(sessionId);
}
}
rendering (visual representation of how things will turn out)
summarize
The main implementation of the method, the actual project process needs to implement the interface to rewrite the method.