LangChain4j之HelloWorld

什么是LangChain4j

它是Java版本的LangChain,随着大模型的不断发展,如何在程序中更好的利用大模型的能力来提高编程效率是一种趋势,LangChain是这么自己介绍自己的:

LangChain gives developers a framework to construct LLM‑powered apps easily.

意思是:LangChain提供了一个开发框架,使得开发者可以很容易的用来构建具有LLM能力的应用程序。

LLM就是Large Language Model,也就是常说的大语言模型,简称大模型。

个人认为:大模型时代,如何将大模型能力和传统应用相结合,使得传统应用更加智能,是人工智能时代的趋势。以前一个应用要获得智能,需要企业自己投入资源训练模型,而现在只需要接入大模型即可,这种便利性将使得大模型会应用得更为广泛,而如何将大模型能力和Java编程语言相结合,这就是LangChain4j所做的。

注意,大模型的能力远远不止聊天的能力,而LangChain4j就在帮助我们更好的利用大模型的能力,从而帮我们打造出更加智能的应用。

初识LangChain4j

接下来,让我们与LangChain4j初识一下,新建一个Maven工程,然后添加以下依赖:

<?xml version="1.0" encoding="UTF-8"?>
<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>
    
    <groupId>com.timi</groupId>
    <artifactId>langchain4j-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <langchain4j.version>0.27.1</langchain4j.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j</artifactId>
            <version>${langchain4j.version}</version>
        </dependency>
        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-open-ai</artifactId>
            <version>${langchain4j.version}</version>
        </dependency>

        <dependency>
            <groupId>org.tinylog</groupId>
            <artifactId>tinylog-impl</artifactId>
            <version>2.6.2</version>
        </dependency>
        <dependency>
            <groupId>org.tinylog</groupId>
            <artifactId>slf4j-tinylog</artifactId>
            <version>2.6.2</version>
        </dependency>
    </dependencies>

</project>

引入了langchain4j的核心依赖、langchain4j集成OpenAi各个模型的依赖、轻量级实现了slf4j接口的tinylog日志依赖。

和OpenAi的第一次对话

package com.timi;

import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;

public class _01_HelloWorld {

    public static void main(String[] args) {

        ChatLanguageModel model = OpenAiChatModel.withApiKey("demo");

        String answer = model.generate("你好,你是谁?");

        System.out.println(answer);

    }
}

运行代码结果为:

你好,我是一个人工智能助手。我可以回答你的问题和提供帮助。有什么可以帮到你的吗?

这样,我们使用LangChain4j第一次成功的和OpenAi的GPT模型进行了对话,正常来说,调用OpenAi的API接口需要在OpenAi的官网去申请ApiKey才能调用成功,而我这里传入的ApiKey为"demo"却也能调通,这是因为:

public OpenAiChatModel(String baseUrl, String apiKey, String organizationId, String modelName, Double temperature, Double topP, List<String> stop, Integer maxTokens, Double presencePenalty, Double frequencyPenalty, Map<String, Integer> logitBias, String responseFormat, Integer seed, String user, Duration timeout, Integer maxRetries, Proxy proxy, Boolean logRequests, Boolean logResponses, Tokenizer tokenizer) {
	
	baseUrl = (String)Utils.getOrDefault(baseUrl, "https://api.openai.com/v1");
	if ("demo".equals(apiKey)) {
		baseUrl = "http://langchain4j.dev/demo/openai/v1";
	}

	//其他代码
}

在底层在构造OpenAiChatModel时,会判断传入的ApiKey是否等于"demo",如果等于会将OpenAi的原始API地址"https://api.openai.com/v1"改为"http://langchain4j.dev/demo/openai/v1",这个地址是langchain4j专门为我们准备的一个体验地址,实际上这个地址相当于是"https://api.openai.com/v1"的代理,我们请求代理时,代理会去调用真正的OpenAi接口,只不过代理会将自己的ApiKey传过去,从而拿到结果返回给我们。

所以,真正开发时,需要大家设置自己的apiKey或baseUrl,可以这么设置:

ChatLanguageModel model = OpenAiChatModel.builder()
	.baseUrl("http://langchain4j.dev/demo/openai/v1")
	.apiKey("demo")
	.build();

多轮对话

前面的例子中,我们通过ChatLanguageModel的generate()方法向大模型提出问题:

String answer = model.generate("你好,你是谁?");

那如果我继续向大模型说:

model.generate("请重复")

那么大模型还记得它之前的回答吗?我们先看看效果,代码如下:

package com.timi;

import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;

public class _01_HelloWorld {

    public static void main(String[] args) {

        ChatLanguageModel model = OpenAiChatModel.builder()
                .baseUrl("http://langchain4j.dev/demo/openai/v1")
                .apiKey("demo")
                .build();

        System.out.println(model.generate("你好,你是谁?"));
        System.out.println("----");
        System.out.println(model.generate("请重复"));

    }
}

运行结果如下:

你好,我是一个聊天机器人,可以回答你的问题和进行对话。有什么可以帮助你的吗?
----
请重复

大模型重复了我第二次跟它说的,而不是重复它的第一次回答,这是因为,目前的代码中,每次调用generate()都是一次新的会话,我再举一个例子:

package com.timi;

import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;

public class _01_HelloWorld {

    public static void main(String[] args) {

        ChatLanguageModel model = OpenAiChatModel.builder()
                .baseUrl("http://langchain4j.dev/demo/openai/v1")
                .apiKey("demo")
                .build();

        System.out.println(model.generate("你好,我是Timi"));
        System.out.println("----");
        System.out.println(model.generate("我叫什么"));

    }
}

运行结果为:

你好Timi,有什么可以帮助你的吗?
----
抱歉,我不知道您的名字。您可以告诉我您的名字吗?我可以记住它并以后称呼您。

一样的情况,因为第二次调用generate()方法是一次单独的会话,那么如何做到使得两次或多次generate()在同一个会话中呢?在LangChain4j中有一个ChatMemory组件,它就是专门用来实现会话功能的,但是它需要结合LangChain4j中的AiService来使用,我们后面再介绍,现在我们先使用笨办法来解决多轮对话的问题。

在ChatLanguageModel中有多个generate()重载方法:

default String generate(String userMessage) {
	return generate(UserMessage.from(userMessage)).content().text();
}

default Response<AiMessage> generate(ChatMessage... messages) {
    return generate(asList(messages));
}

Response<AiMessage> generate(List<ChatMessage> messages);

我们前面使用的就是第一个generate()方法,而第二个和第三个generate()方法都是接收一个ChatMessage集合,并且返回一个AiMessage,那么ChatMessage和AiMessage分别都表示什么意思呢?

ChatMessage是一个接口,表示聊天消息,它有以下四种实现:

  1. UserMessage:表示用户发送给大模型的消息
  2. AiMessage:表示大模型响应给用户的消息
  3. SystemMessage:也是用户发送给大模型的消息,和UserMessage不同在于,SystemMessage一般是应用程序帮用户设置的,举个例子,假如有一个作家应用,那么“请你扮演一名作家,请帮我写一篇关于春天的作文”,其中“请你扮演一名作家”就是SystemMessage,“请帮我写一篇关于春天的作文”就是UserMessage
  4. ToolExecutionResultMessage:也是用户发送给大模型的,表示工具的执行结果,关于LangChain4j的工具机制,会在后续介绍,目前可以忽略

我们先重点关注UserMessage和AiMessage,它们就相当于请求和响应,所以如果我们想要实现多轮对话,可以这么实现:

package com.timi;

import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.output.Response;

public class _01_HelloWorld {

    public static void main(String[] args) {

        ChatLanguageModel model = OpenAiChatModel.builder()
                .baseUrl("http://langchain4j.dev/demo/openai/v1")
                .apiKey("demo")
                .build();


        UserMessage userMessage1 = UserMessage.userMessage("你好,我是Timi");
        Response<AiMessage> response1 = model.generate(userMessage1);
        AiMessage aiMessage1 = response1.content(); // 大模型的第一次响应
        System.out.println(aiMessage1.text());
        System.out.println("----");

        // 下面一行代码是重点
        Response<AiMessage> response2 = model.generate(userMessage1, aiMessage1, UserMessage.userMessage("我叫什么"));
        AiMessage aiMessage2 = response2.content(); // 大模型的第二次响应
        System.out.println(aiMessage2.text());

    }
}

代码执行结果为:

你好,Timi。有什么可以帮助你的吗?
----
您的名字是Timi。有什么其他问题我可以帮忙解答吗?

其中重点代码为:

Response<AiMessage> response2 = model.generate(userMessage1, aiMessage1, UserMessage.userMessage("我叫什么"));

同样是问"我叫什么",但是这里我把第一次的问题和答案,也就是我和大模型的历史对话传给了大模型,只有这样,大模型才能结合历史对话知道"我叫什么"。事实上,我们在使用ChatGPT时也是一样的原理,因为ChatGPT需要结合历史对话才更能理解你最新一句话的真正意思。

打字机流式响应

在前面的例子中,当我们通过ChatLanguageModel的generate()方法向大模型提问时,ChatLanguageModel一次性给了整段响应结果,而不是一个字一个字打字机式的回答,不过我们可以使用OpenAiStreamingChatModel来实现打字机效果,代码如下:

package com.timi;

import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.StreamingResponseHandler;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.chat.StreamingChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.openai.OpenAiStreamingChatModel;

import java.util.concurrent.TimeUnit;

public class _01_HelloWorld {

    public static void main(String[] args) {

        StreamingChatLanguageModel model = OpenAiStreamingChatModel.builder()
                .baseUrl("http://langchain4j.dev/demo/openai/v1")
                .apiKey("demo")
                .build();


        model.generate("你好,你是谁?", new StreamingResponseHandler<AiMessage>() {
            @Override
            public void onNext(String token) {

                System.out.println(token);

                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

            }

            @Override
            public void onError(Throwable error) {
                System.out.println(error);
            }
        });

    }
}

这样就能实现打字机效果了。

整合SpringBoot

先引入SpringBoot:

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

<dependency>
	<groupId>dev.langchain4j</groupId>
	<artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
	<version>0.27.1</version>
</dependency>

然后定义SpringBoot启动类:

package com.timi;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Main {

	public static void main(String[] args) {
		SpringApplication.run(Main.class, args);
	}
}

然后定义HelloController:

package com.timi;

import dev.langchain4j.model.chat.ChatLanguageModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @Autowired
    private ChatLanguageModel chatLanguageModel;

    @GetMapping("/hello")
    public String hello(){
        return chatLanguageModel.generate("你好啊");
    }
}

配置api-key:

langchain4j.open-ai.chat-model.api-key=demo

启动SpringBoot并访问:image.png

ModerationModel

package com.timi;

import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.moderation.Moderation;
import dev.langchain4j.model.moderation.ModerationModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.openai.OpenAiModerationModel;
import dev.langchain4j.model.output.Response;

public class _01_HelloWorld {

    public static void main(String[] args) {
        ModerationModel moderationModel = OpenAiModerationModel.withApiKey("demo");
        Response<Moderation> response = moderationModel.moderate("我要谢谢你");
        System.out.println(response.content().flaggedText());

    }
}

ModerationModel能够校验输入中是否存在敏感内容。

ImageModel

package com.timi;

import dev.langchain4j.data.image.Image;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.image.ImageModel;
import dev.langchain4j.model.moderation.Moderation;
import dev.langchain4j.model.moderation.ModerationModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.openai.OpenAiImageModel;
import dev.langchain4j.model.openai.OpenAiModerationModel;
import dev.langchain4j.model.output.Response;

public class _01_HelloWorld {

    public static void main(String[] args) {
        ImageModel imageModel = OpenAiImageModel.builder()
                .baseUrl("http://localhost:3000/v1")
                .apiKey("sk-peszVtFXoLnWK45bB15370Df6f344cAa9a088eF50f9c7302")
                .build();
        Response<Image> response = imageModel.generate("一辆车");
        System.out.println(response.content().url());

    }
}

ImageModel可以根据提示词来生成图片,默认提供的“demo”key不能用来生成图片,需要大家自己购买apiKey,可以先不买,先学习后面内容。

本节总结

本节我们介绍了LangChain4j的基本使用,以及多轮对话、流式响应的实现,其中我们提到了LangChain4j中的工具机制、AiService机制、ChatMemory机制,接下来我们先学习一下AiService机制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/749391.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Redis一】Redis配置与优化

目录 一.关系型数据库与非关系型数据库 1.关系型数据库 2.非关系型数据库 3.二者区别 4.非关系型数据库产生背景 5.NoSQL与SQL数据记录对比 关系型数据库 非关系型数据库 二.Redis相关概述 1.简介 2.五大数据类型 3.优缺点 3.1.优点 3.2.缺点 4.使用场景 5.采用…

阿里巴巴向国际用户开放人工智能模型平台ModelScope(魔搭社区)

阿里巴巴对 Hugging Face 和 Amazon Bedrock 的回应包含 5,000 多个中国专业模型&#xff0c;以及 1,500 个工具包和数据集 阿里云已将其人工智能模型存储库ModelScope&#xff08;魔搭社区&#xff09;的访问权限扩展至全球英语用户&#xff0c;意在吸引更多国际企业和开发者…

床旁交互,全视通打造以患者为中心的智慧病房

随着我国医疗建设的发展&#xff0c;医疗服务体系的不断建立健全&#xff0c;新形势下人们的医疗需求发生变化&#xff0c;医疗服务理念正逐步从传统的“以疾病为中心”向“以患者为中心”转变。 基于医院临床实际应用场景&#xff0c;在兼具实用性的前提下&#xff0c;建设了床…

yolov5驾驶员不规范行为检测

1 项目介绍 1.1 摘要 随着汽车工业的迅速发展和交通拥堵的加剧&#xff0c;驾驶员在行车过程中的不规范行为成为了导致交通事故频发的重要因素之一。为了减少交通事故的发生&#xff0c;保障道路安全&#xff0c;提高驾驶员的行车安全意识&#xff0c;本研究致力于实现驾驶员…

德国威步的技术演进之路(上):从软件保护到用户体验提升

德国威步自1989年成立以来一直专注于数字安全技术的研究和发展&#xff0c;在软件保护和数字授权领域树立了行业标杆&#xff0c;并在云端许可管理和物联网安全技术方面不断创新。德国威步的成就彰显了其对安全、创新和可持续发展的坚定追求。 德国威步将“完美保护、完美授权…

webpack+webpack server入门

​ 1.webpack介绍 webpack是一个模块加载器兼打包工具。它是以 commonJS 的形式来书写脚本的&#xff0c;但对 AMD/CMD 的支持也很全面&#xff0c;方便旧项目进行代码迁移。支持对react热插拔。 2.安装&#xff08;使用淘宝镜像&#xff09; 全局安装 cnpm install webpa…

Redis-数据类型-Set(不允许重复)

文章目录 1、查看redis是否启动2、通过客户端连接redis3、切换到2数据库4、给key指定的set集合中存入数据&#xff0c;set会自动去重5、返回可以指定的set集合中所有的元素6、返回集合中元素的数量(set cardinality)7、检查当前指定member是否是集合中的元素8、从集合中删除元素…

数学类-课程资料推荐-中科大教师首页

http://staff.ustc.edu.cn/~rui/cn/rui-course.html 数学分析讲义&#xff08;第一册&#xff09; (ustc.edu.cn)

BIO、NIO编程深入理解与直接内存、零拷贝

网路编程基本常识 一. Socket 什么是Socket Socket是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。它提供了应用层进程利用网络协议交换数据的机制&#xff0c;是应用程序与网络协议栈进行交互的接口。 说白了&#xff0c;Socket就是把TCP/IP协议族进行封装…

数通云网架构师涨薪班毕业都有哪些工作企业和岗位?

数通云网架构师涨薪班课程学完后&#xff0c;学员具备全行业全场景交付数通项目的能力&#xff0c;胜任企业网&#xff0c;广域网&#xff0c;数据中心网络等各种网络项目的交付能力&#xff0c;技术能力一项能够匹配年薪达30w-40w以上网络工程师岗位。 与誉天进行人才培养&…

Wordpress图像编辑插件-palleon v3.8.1中文版语言包

Palleon是一个强大的WordPress图像编辑器&#xff0c;可以与您的WordPress网站无缝集成&#xff0c;让您快速高效地工作。它拥有为你的WordPress网站创建令人惊叹的图像所需的一切。 Palleon让您完全控制图像&#xff0c;允许您逐个像素进行更改。您可以轻松地裁剪、调整图像大…

Android jetpack Room的简单使用

文章目录 项目添加ksp插件添加 room 引用开始使用room1. 创建bean2. 创建 dao类3. 创建database类 数据库升级复制数据库到指定路径参考文献 项目添加ksp插件 注意&#xff0c;因为ksp插件 是跟项目中使用的kotlin的版本要保持一致的&#xff0c;否则会报错的 首先我们去 https…

高德.js2.0绘制多条折线(轨迹)及清除所有折线

2.0版本的地图,需要绘制多条折线的时候,就需要循环生成,因此也需要循环清除 for (let j 0; j < combinedArray.length; j) {const item combinedArray[j];this.polyline new AMap.Polyline({map: this.map,path: item,showDir: true,strokeColor: "#28F", //线…

免费Logo在线生成:必试的6款工具

logo对企业来说非常重要。一个好的logo免费设计在线生成器往往会给企业带来无形的利润。因此&#xff0c;许多企业非常重视自己公司的logo。作为一名设计师&#xff0c;如果能找到一个好的logo免费设计在线生成器&#xff0c;势必会给实际的logo设计带来事半功倍的效果。本文精…

软件测试面试题:Web View如何测试?

Web View介绍 Web View&#xff08;网页视图&#xff09;是一种用于在应用程序中显示网页内容的组件或控件。提供了一种将网页内容嵌入到应用程序中的方式&#xff0c;使用户能够在应用程序中浏览和交互网页。 Web View通常用于开发移动应用程序&#xff0c;特别是混合应用程…

Docker构建多平台镜像

docker的多架构镜像构建 目前很多服务器都是基于arm架构的&#xff0c;而现在大多数的docker镜像都是基于x86架构的。一种情况就是同样的代码编译成业务包做成镜像需要部署在不同架构的服务器上&#xff0c;这个时候我们就可以使用docker的多平台构建了。 以下操作是在centos7.…

Github 2024-06-21 开源项目日报 Top10

根据Github Trendings的统计,今日(2024-06-21统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量TypeScript项目3Python项目3Java项目2非开发语言项目2JavaScript项目1Rust项目1Dart项目1HTML项目1Vue项目1C++项目1TensorFlow: 机器学习的开源…

软件自动化测试有哪些流程?可替代手工测试吗?

随着科技的不断发展&#xff0c;软件在我们生活中的地位越来越重要。然而&#xff0c;在软件开发过程中&#xff0c;必然会出现各种各样的问题和bug&#xff0c;为了提高软件的质量和稳定性&#xff0c;保证用户的使用体验&#xff0c;软件自动化测试应运而生。 那么&#xff…

什么是 Azure OpenAI?

目录 一、说明 二、什么是 Azure OpenAI 2.1 网络结构 2.2 、为什么使用 Azure OpenAI 2.3 如何使用 Azure OpenAI 三、从哪里开始 Azure OpenAI 之旅 3.1 关于 Azure OpenAI&#xff0c;我还需要了解什么 3.2 RBAC 权限和角色 3.3 演示 1&#xff1a;在公共数据上应用…

OpenAI封锁中国?国产大模型开启价格战?收好这份LLM选购指南,带你搞定极致性价比 | ShowMeAI

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; 1. Cloud LLM capability, cost, performance | 一份开发者最实用的大模型「性价比」计算手册 这是 Harlan Lewis 整理的大语言模型 (LLM) 对比清单…