Location>code7788 >text

Spring AI + ollama Local Build Chat AI

Popularity:45 ℃/2024-11-13 18:00:45

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)

gif

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)

db

summarize

The main implementation of the method, the actual project process needs to implement the interface to rewrite the method.