当前位置: 首页 > news >正文

LangChain4j(2):整合SpringBoot

1 新建Springboot项目

1.1 引入依赖

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.4.3</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>
  <groupId>org.example</groupId>
  <artifactId>langchain4jSpringbootpro</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>langchain4jSpringbootpro</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <langchain4j.version>1.0.0-beta1</langchain4j.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>dev.langchain4j</groupId>
      <artifactId>langchain4j-community-dashscope-spring-boot-starter</artifactId>
    </dependency>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>dev.langchain4j</groupId>
        <artifactId>langchain4j-community-bom</artifactId>
        <version>${langchain4j.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

</project>

2 配置项

查看加载的依赖中的langchain4j-community-dashscope-spring-boot-starter的Autoconfig文件。

可以看到使用时需要的配置条件,需要配置apikey。

在源文件中可以查看配置模型:

新建配置application.properties

server.port=8080

langchain4j.community.dashscope.chat-model.api-key = 你的apikey
langchain4j.community.dashscope.chat-model.model-name = qwen-plus

2.3 代码实现

package org.example.controller;

import dev.langchain4j.community.model.dashscope.QwenChatModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/ai")
public class AiController {

    @Autowired
    QwenChatModel qwenChatModel;

    @RequestMapping("/chat")
    public String test(@RequestParam(defaultValue = "你是谁") String message){
        String chat = qwenChatModel.chat(message);
        return chat;
    }


}

2.4 访问结果

启动后,访问链接http://localhost:8080/ai/chat。

2 接入DeepSeek

接入DeepSeek只需要修改配置文件即可,如下:

langchain4j.community.dashscope.chat-model.api-key = 你的key
langchain4j.community.dashscope.chat-model.model-name = deepseek-r1

启动后,访问链接http://localhost:8080/ai/chat。

3 接入Ollama

安装Ollama,下载想要的大模型。

引用依赖:

    <dependency>
      <groupId>dev.langchain4j</groupId>
      <artifactId>langchain4j-ollama-spring-boot-starter</artifactId>
      <version>${langchain4j.version}</version>
    </dependency>

加入配置文件:

langchain4j.ollama.chat-model.base-url = http://localhost:11434
langchain4j.ollama.chat-model.model-name = deepseek-r1:1.5b

代码如下:

package org.example.controller;

import dev.langchain4j.community.model.dashscope.QwenChatModel;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.ollama.OllamaChatModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/ai")
public class AiController {

    @Autowired
    ChatLanguageModel chatLanguageModel;


    @RequestMapping("/ollamachat")
    public String ollamachatfuc(@RequestParam(defaultValue = "你是谁") String message){
        String ollamachat = chatLanguageModel.chat(message);
        return ollamachat;
    }

}

结果如下:

4 流式输出

之前的依赖不变,但是因为langchain4j不是spring家族,所以我们在wen应用中需要引入webflux。

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

通过Flux进行流式响应

    @RequestMapping(value = "/streamchat",produces = "text/stream;charset=UTF-8")
    public Flux<String> streamchatfuc(@RequestParam(defaultValue="你是谁") String message){

        Flux<String> flux = Flux.create(fluxSink -> {

            streamingChatModel.chat(message, new StreamingChatResponseHandler() {
                @Override
                public void onPartialResponse(String partialResponse) {
                    fluxSink.next(partialResponse);
                }

                @Override
                public void onCompleteResponse(ChatResponse completeResponse) {
                    fluxSink.complete();
                }

                @Override
                public void onError(Throwable error) {
                    fluxSink.error(error);
                }
            });


        });
        return flux;
    }

加入配置文件:

langchain4j.community.dashscope.streaming-chat-model.api-key = sk-4d1748fba8994a2e94cb0fbaf3d34f23
langchain4j.community.dashscope.chat-model.model-name = deepseek-r1

启动后访问链接:http://localhost:8080/ai/streamchat,会发现答复是按照流式输出的。

5 记忆对话

5.1 ChatMemory

大模型并不会把我们每次的对话存在服务端,所以他记不住我们说的话,如下代码:

    @Test
    public void test_bad(){
        ChatLanguageModel model = OpenAiChatModel
                .builder()
                .apiKey("demo")
                .modelName("gpt-4o-mini")
                .build();
        System.out.println(model.chat("你好,我是徐庶老师"));
        System.out.println("----");
        System.out.println(model.chat("我叫什么"));
    }

运行结果如下:

所以每次对话都需要将之前的对话记录,都发给大模型,这样才能知道我们之前说了什么:

    @Test
    public void test03(){
        ChatLanguageModel model = OpenAiChatModel
                .builder()
                .apiKey("demo")
                .modelName("gpt-4o-mini")
                .build();

        UserMessage userMessage1 = UserMessage.userMessage("你好,我是徐庶");
        ChatResponse response1 = model.chat(userMessage1);
        AiMessage aiMessage1 = response1.aiMessage();//大模型的第一次响应
        System.out.println(aiMessage1.text());
        System.out.println("----");
        // 下面一行代码是重点
        ChatResponse response2 = model.chat(userMessage1,aiMessage1, UserMessage.userMessage("我叫什么?"));
        AiMessage aiMessage2 = response2.aiMessage();
        // 大模型的第二次响应
        System.out.println(aiMessage2.text());
        System.out.println(model.chat("你好,我是徐庶老师"));
        System.out.println("----");
        System.out.println(model.chat("我叫什么"));
    }

返回结果如下:

但是如果要我们每次把之前的记录自己去维护,未免太麻烦,所以提供了ChatMemory但是他这个ChatMemory没有SpringAi好用、易用、十分麻烦!所以说谁在跟我说Langchain4i比SpringAi好我跟谁急!

package org.example.config;

import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.chat.StreamingChatLanguageModel;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.service.TokenStream;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class Aiconfig {
    public interface Assistant{
        String chat(String message);
        // 流式响应
        TokenStream stream(String message);
    }

    @Bean
    public Assistant assistant(ChatLanguageModel qwenchatModel, StreamingChatLanguageModel qwenstreamingchatModel) {
        //设置最大记录对话数
        ChatMemory chatMemory = MessageWindowChatMemory.withMaxMessages(10);

        Assistant assistant = AiServices
                .builder(Assistant.class)
                .chatLanguageModel(qwenchatModel)
                .streamingChatLanguageModel(qwenstreamingchatModel)
                .chatMemory(chatMemory)
                .build();
        return assistant;
    }
}

原理:

  1. 通过AiService创建的代理对象(Aiservices.builder(XushuChatModel.class))调用chat方法(XushuChatModel.chat)
  2. 代理对象会去ChatMemory中获取之前的对话记录(获取记忆)
  3. 将获取到的对话记录合并到当前对话中(此时大模型根据之前的聊天记录肯定就拥有了“记忆”)
  4. 将当前的对话内容存入ChatMemory(保存记忆)

代码如下:

package org.example.controller;

import dev.langchain4j.service.TokenStream;
import jakarta.servlet.http.HttpServletResponse;
import org.example.config.Aiconfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import java.time.LocalDate;

@RestController
@RequestMapping("/ai_other")
public class OtherAiController {
    @Autowired
    Aiconfig.Assistant assistant;
    //告诉模型我叫诸葛懿
    @RequestMapping(value = "/memory_chat")
    public String memorychat(@RequestParam(defaultValue = "我叫诸葛懿") String message) {
        return assistant.chat(message);
    }
    //流式响应
    @RequestMapping(value = "/memory_stream_chat",produces ="text/stream;charset=UTF-8")
    public Flux<String> memoryStreamChat(@RequestParam(defaultValue="我是谁") String message, HttpServletResponse response) {
        TokenStream stream = assistant.stream(message);

        return Flux.create(sink -> {
            stream.onPartialResponse(s -> sink.next(s))
                    .onCompleteResponse(c -> sink.complete())
                    .onError(sink::error)
                    .start();

        });
    }
}

先访问http://localhost:8080/ai_other/memory_chat告诉模型你的名字,后访问http://localhost:8080/ai_other/memory_stream_chat看结果,结果如下:

5.2 记忆分离

现在我们再来想另一种情况:如果不同的用户或者不同的对话肯定不能用同一个记忆,要不然对话肯定会混淆此时就需要进行区分:

可以通过memoryld进行区分

5.3 持久对话

6 Funcion-call

相关文章:

  • MCP服务:五分钟实现微服务治理革命,无缝整合Nacos/Zookeeper/OpenResty
  • 【QT5 网络编程示例】TCP 通信
  • Spring Boot启动流程
  • 力扣每日一题:2712——使所有字符相等的最小成本
  • 车载以太网网络测试-26【SOME/IP-通信方式-2】
  • 【力扣hot100题】(026)合并两个有序链表
  • [RoarCTF 2019]Easy Java1
  • 排序算法可视化工具——基于React的交互式应用
  • openEuler 24.03 (LTS) 安装 docker 记录
  • Go语言从零构建SQL数据库引擎(3)
  • rustdesk 客户端使用
  • 算法篇-------------双指针法
  • Matplotlib绘制常用图像
  • 各种网址整理-vue,前端,linux,ai前端开发,各种开发能用到的网址和一些有用的博客
  • javaweb自用笔记:文件上传案例、登录(统一拦截)案例
  • SpringCould微服务架构之Docker(9)
  • 便捷解析下载热门短视频、图片的安卓免费软件
  • 代码随想录C++算法训练,二叉树(day16)
  • vcpkg安装及使用教程,以安装matio库解析mat文件为例
  • 部署Dify接入微信验证反代根目录创建一个文件通过微信小程序验证
  • 扁平化网站设计方案/全网整合营销推广系统
  • 每天做任务得钱的网站/找seo外包公司需要注意什么
  • 手机端自适应网站布局/自己有域名怎么建网站
  • wordpress的配置文件/seo推广服务哪家好
  • 宿迁宿豫网站建设/seo关键词seo排名公司
  • 网站测试毕设代做/百度网址大全电脑版