使用Spring Boot和LangChain构建Java中的AI ChatGPT仿制教程

22,629次阅读
没有评论

共计 5157 个字符,预计需要花费 13 分钟才能阅读完成。

学习使用 Java 中的 Spring Boot、LangChain 和 Hilla 构建 ChatGPT 克隆。涵盖同步聊天完成和高级流完成。

许多用于 AI 应用程序开发的库主要是用 Python 或 JavaScript 编写的。好消息是其中一些库也具有 Java API。在本教程中,我将向您展示如何使用 Spring Boot、LangChain 和 Hilla 构建 ChatGPT 克隆。

本教程将涵盖简单的同步聊天完成和更高级的流式完成,以获得更好的用户体验。

大神完成得开源源代码

您可以在我的 GitHub 存储库中找到该示例的源代码。

https://github.com/marcushellberg/spring-boot-react-langchain-chatgpt

要求

  • Java 17+

  • Node 18+

  • Hilla(https://hilla.dev/)

  • LangChain4j(https://github.com/langchain4j/langchain4j)

  • OPENAI_API_KEY环境变量中的 OpenAI API 密钥

创建 Spring Boot 和 React 项目,添加 LangChain

首先,使用 Hilla CLI 创建一个新的 Hilla 项目。这将创建一个带有 React 前端的 Spring Boot 项目。

npx @hilla/cli init ai-assistant

在 IDE 中打开生成的项目。然后,将 LangChain4j 依赖项添加到文件中pom.xml


    dev.langchain4j
    langchain4j
    0.22.0 

使用 LangChain 使用内存完成简单的 OpenAI 聊天

我们将通过简单的同步聊天完成来开始探索 LangChain4j。在本例中,我们希望调用 OpenAI 聊天完成 API 并获得单个响应。我们还希望跟踪聊天历史记录中最多 1,000 个标记。

com.example.application.service 包中,创建一个 ChatService.java 包含以下内容的类:

@BrowserCallable
@AnonymousAllowed
public class ChatService {@Value("${openai.api.key}")
    private String OPENAI_API_KEY;

    private Assistant assistant;

    interface Assistant {String chat(String message);
    }

    @PostConstruct
    public void init() {var memory = TokenWindowChatMemory.withMaxTokens(1000, new OpenAiTokenizer("gpt-3.5-turbo"));
        assistant = AiServices.builder(Assistant.class)
                .chatLanguageModel(OpenAiChatModel.withApiKey(OPENAI_API_KEY))
                .chatMemory(memory)
                .build();}

    public String chat(String message) {return assistant.chat(message);
    }
}
  • @BrowserCallable使该类可供前端使用。

  • @AnonymousAllowed允许匿名用户调用这些方法。

  • @Value从环境变量注入 OpenAI API 密钥OPENAI_API_KEY

  • Assistant是我们用来调用聊天 API 的接口。

  • init()使用 1,000 个令牌内存和模型初始化助手gpt-3.5-turbo

  • chat()是我们将从前端调用的方法。

Application.java通过在 IDE 中运行或使用默认 Maven 目标来启动应用程序:

MVN

这将为前端生成 TypeScript 类型和服务方法。

接下来,App.tsxfrontend 文 件夹中打开并使用以下内容更新它:

export default function App() {const [messages, setMessages] = useState([]);

    async function sendMessage(message: string) {setMessages((messages) => [
        ...messages,
        {
        text: message,
        userName: "You",
        },
    ]);

    const response = await ChatService.chat(message);
    setMessages((messages) => [
        ...messages,
        {
        text: response,
        userName: "Assistant",
        },
    ]);
    }

    return (
                  sendMessage(e.detail.value)} />     
    ); }

文章来源地址 https://www.toymoban.com/diary/java/380.html

  • 我们使用 Hilla UI 组件库中的 MessageList 和组件MessageInput

  • sendMessage()将消息添加到消息列表中,并调用类 chat() 上的方法ChatService。收到响应后,会将其添加到消息列表中。

您现在拥有一个正在运行的聊天应用程序,该应用程序使用 OpenAI 聊天 API 并跟踪聊天历史记录。它对于短消息非常有效,但对于长答案来说速度很慢。为了改善用户体验,我们可以使用流式完成来代替,在收到响应时显示响应。

显示用户和 AI 机器人之间两条消息的聊天界面

使用 LangChain 使用内存流式传输 OpenAI 聊天完成情况

让我们更新该类 ChatService 以使用流式完成:

@BrowserCallable
@AnonymousAllowed
public class ChatService {@Value("${openai.api.key}")
    private String OPENAI_API_KEY;
    private Assistant assistant;

    interface Assistant {TokenStream chat(String message);
    }

    @PostConstruct
    public void init() {var memory = TokenWindowChatMemory.withMaxTokens(1000, new OpenAiTokenizer("gpt-3.5-turbo"));

        assistant = AiServices.builder(Assistant.class)
                .streamingChatLanguageModel(OpenAiStreamingChatModel.withApiKey(OPENAI_API_KEY))
                .chatMemory(memory)
                .build();}

    public Flux chatStream(String message) {Sinks.Many sink = Sinks.many().unicast().onBackpressureBuffer();

        assistant.chat(message)
                .onNext(sink::tryEmitNext)
                .onComplete(sink::tryEmitComplete)
                .onError(sink::tryEmitError)
                .start();

        return sink.asFlux();}
}

代码与以前基本相同,但有一些重要的区别:

  • Assistant现在返回 a TokenStream而不是 a String

  • init()使用 streamingChatLanguageModel() 而不是  chatLanguageModel().

  • chatStream()返回 一个 Flux而不是 一个 String

更新 App.tsx 以下内容:

export default function App() {const [messages, setMessages] = useState([]);

    function addMessage(message: MessageListItem) {setMessages((messages) => [...messages, message]);
    }

    function appendToLastMessage(chunk: string) {setMessages((messages) => {const lastMessage = messages[messages.length - 1];
        lastMessage.text += chunk;
        return [...messages.slice(0, -1), lastMessage];
    });
    }

    async function sendMessage(message: string) {
    addMessage({
        text: message,
        userName: "You",
    });

    let first = true;
    ChatService.chatStream(message).onNext((chunk) => {if (first && chunk) {
        addMessage({
            text: chunk,
            userName: "Assistant",
        });
        first = false;
        } else {appendToLastMessage(chunk);
        }
    });
    }

    return (
                  sendMessage(e.detail.value)} />     
    ); }

模板与以前相同,但我们处理响应的方式不同。我们不再等待收到响应,而是开始监听响应块。当收到第一个块时,我们将其添加为新消息。当收到后续块时,我们将它们附加到最后一条消息中。

重新运行应用程序,您应该看到响应按收到时的样子显示。

结论

正如您所看到的,LangChain 可以轻松地在 Java 和 Spring Boot 中构建由 LLM 驱动的 AI 应用程序。

完成基本设置后,您可以按照本文前面链接的 LangChain4j GitHub 页面上的示例,通过链接操作、添加外部工具等来扩展功能。在 Hilla 文档中了解有关 Hilla 的更多信息。

Hilla 文档:https://hilla.dev/docs/react

到此这篇关于使用 Spring Boot 和 LangChain 构建 Java 中的 AI ChatGPT 仿制教程的文章就介绍到这了, 更多相关内容可以在右上角搜索或继续浏览下面的相关文章,希望大家以后多多支持 TOY 模板网!

原文地址:https://www.toymoban.com/diary/java/380.html

如若转载,请注明出处:如若内容造成侵权 / 违法违规 / 事实不符,请联系站长进行投诉反馈,一经查实,立即删除!

    正文完
     0
    Yojack
    版权声明:本篇文章由 Yojack 于1970-01-01发表,共计5157字。
    转载说明:
    1 本网站名称:优杰开发笔记
    2 本站永久网址:https://yojack.cn
    3 本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行删除处理。
    4 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
    5 本站所有内容均可转载及分享, 但请注明出处
    6 我们始终尊重原创作者的版权,所有文章在发布时,均尽可能注明出处与作者。
    7 站长邮箱:laylwenl@gmail.com
    评论(没有评论)