使用 Java、LangChain4j、OpenAI 和 Ollama 的生成式 AI

在本文中,我们将探讨以下内容:

  • 生成式人工智能简介?

  • 如何使用 Java 与 Open AI API 交互?

  • 如何使用LangChain4j与OpenAI交互?

  • 如何使用 Ollama 在本地运行 LLM 模型?

  • 使用 LangChain4j 和 Testcontainers 与 Ollama 合作。

LangChain4j 教程系列

您可以查看本系列中的其他文章:

生成式 AI 简介

除非你生活在岩石下,否则你可能听说过生成式人工智能。 这是一个引人入胜的人工智能领域,用于生成新内容,例如图像、文本、音频等。 几年前,构建聊天机器人是一件大事,但现在我们正在谈论生成类似人类的聊天机器人 文本、图像和音频,使用简单的 API 调用。

一般来说,人工智能涉及复杂的学科,如机器学习深度学习自然语言处理 (NLP) 等。 构建 AI 应用程序需要对这些主题有很好的理解,而且要上手并不容易。 得益于人工智能的最新进展,我们可以构建人工智能驱动的应用程序,而无需深入了解这些复杂的主题。 人工智能领域的专家构建了可以生成类似人类的文本的大型语言模型 (LLM),这些模型可作为 API 使用。

大型语言模型 (LLM) 是指一种旨在理解和 大规模生成类人语言。这些模型在海量数据集上进行训练,包括 语言使用的各种示例,使他们能够学习语言的模式、上下文和语义。

生成式 AI 具有多种用例,包括:

  • 内容生成:创建文本、图像、视频和音乐。

  • 语言翻译:改进机器翻译模型。

  • 聊天机器人:开发用于客户支持的对话代理。

  • 代码生成:为软件开发编写代码。

  • 文本分析:分析和总结大量文本。

有一些流行的 LLM 可作为 API,例如 OpenAI 的 GPT-3/4Google 的 VertexMicrosoft 的 Azure AI 等。

使用 Java 的 OpenAI 入门

在本节中,我们将探讨如何使用 Java 与 OpenAI API 进行交互。

示例代码存储库

可以在 GitHub 存储库中找到本文的示例代码

首先,我们需要在 OpenAI 中创建一个帐户并获取 API 密钥。

  • 转到 OpenAI 平台并创建一个帐户。

  • 在仪表板中,单击左侧导航菜单中的 API 密钥,然后创建新的 API 密钥。

如果您要创建一个新帐户,您将获得一些免费积分来使用 OpenAI API。 否则,您需要购买积分才能使用 OpenAI API。

获得 API 密钥后,您可以使用它与 OpenAI API 进行交互。 您可以在此处找到 Open AI API 参考文档

首先,让我们看看如何使用其聊天 API 端点向 OpenAI 提问。

curl https://api.openai.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "model": "gpt-3.5-turbo",
    "messages": [
      {
        "role": "user",
        "content": "List all the movies directed by Quentin Tarantino"
      }
    ]
  }'

您可能会收到如下响应:

{
  "id": "chatcmpl-8tvrQyjw3s28IREvkFl6kIhTxIUGZ",
  "object": "chat.completion",
  "created": 1708341148,
  "model": "gpt-3.5-turbo-0125",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "1. Reservoir Dogs (1992)\n2. Pulp Fiction (1994)\n3. Jackie Brown (1997)\n4. Kill Bill: Vol. 1 (2003)\n5. Kill Bill: Vol. 2 (2004)\n6. Death Proof (2007)\n7. Inglourious Basterds (2009)\n8. Django Unchained (2012)\n9. The Hateful Eight (2015)\n10. Once Upon a Time in Hollywood (2019)"
      },
      "logprobs": null,
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 16,
    "completion_tokens": 105,
    "total_tokens": 121
  },
  "system_fingerprint": "fp_69829325d0"
}

如您所见,这是一个简单的 API 调用来获取来自 OpenAI 的响应。

现在,让我们看看如何使用 Java 内置的 HttpClient 与 OpenAI 进行交互。

我们将使用 Jackson JSON 库来序列化/反序列化请求和响应。

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.16.1</version>
</dependency>

首先,我们将创建 Java 记录类来表示请求和响应 JSON 有效负载。

record Message(String role, String content) {}

record ChatRequest( String model, List<Message> messages, double temperature) {}

@JsonIgnoreProperties(ignoreUnknown = true)
record ChatUsage(
        @JsonProperty("prompt_tokens")
        int promptTokens,
        @JsonProperty("completion_tokens")
        int completionTokens,
        @JsonProperty("total_tokens")
        int totalTokens
) {}

@JsonIgnoreProperties(ignoreUnknown = true)
record ChatResponseChoice(
        int index,
        Message message,
        @JsonProperty("finish_reason")
        String finishReason
) {}

@JsonIgnoreProperties(ignoreUnknown = true)
record ChatResponse(
        String id, String object, long created,
        String model, ChatUsage usage,
        List<ChatResponseChoice> choices
) {}

我们创建了 Java 记录来表示请求和响应,仅包括我们感兴趣的字段。

接下来,让我们使用 Java 的 HttpClient 与 OpenAI 进行交互。

package com.sivalabs.openai.demo;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.List;

public class ChatDemo {
    public static final String OPENAI_API_KEY = System.getenv("OPENAI_API_KEY");
    public static final String CHAT_URL = "https://api.openai.com/v1/chat/completions";
    public final static String MODEL = "gpt-3.5-turbo";
    public final static double TEMPERATURE = 0.7;

    static HttpClient client = HttpClient.newHttpClient();
    static ObjectMapper mapper = new ObjectMapper();

    public static void main(String[] args) throws Exception {
        ChatRequest chatRequest = new ChatRequest(
                MODEL, List.of(new Message("user", "List all the movies directed by Quentin Tarantino")),
                TEMPERATURE);
        String requestPayload = mapper.writeValueAsString(chatRequest);
        
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(CHAT_URL))
                .header("Authorization", "Bearer %s".formatted(OPENAI_API_KEY))
                .header("Content-Type", "application/json")
                .header("Accept", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(requestPayload))
                .build();
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        
        String body = response.body();
        ChatResponse chatResponse = mapper.readValue(body, ChatResponse.class);
        System.out.println(chatResponse.choices().getFirst().message().content());
    }
}

我们创建了一个 ChatRequest 实例,并使用 Jackson 将其序列化为 JSON 字符串。 然后,我们创建了一个 HttpRequest 实例,并使用 Java 的 HttpClient 发送它。 最后,我们使用 Jackson 将响应 JSON 反序列化为 ChatResponse

这里需要注意的几件重要事情:

  • 我们从环境变量 OPENAI_API_KEY 获取 OpenAI API 密钥。

  • 我们使用的是 gp-3.5-turbo 模型,您可以在此处查看 OpenAI 中的所有可用模型。

  • 我们使用的温度为 0.7,它控制响应的随机性。 温度越低,响应越确定,温度越高,随机响应越多。

这里需要注意的重要一点是响应中的使用字段,它使你了解请求和响应使用了多少令牌。

{
  "..":"..",
  "usage": {
    "prompt_tokens": 16,
    "completion_tokens": 105,
    "total_tokens": 121
  }
}

您的 Open AI API 使用量是根据使用的令牌数量计量的。 您可以在什么是令牌以及如何计算令牌?中了解有关令牌的更多信息。

我们已经了解了如何使用 Java 的 HttpClient 与 OpenAI 进行交互。 但是,这是低级的,使用起来不是很方便。 在下一节中,我们将看到如何使用 LangChain4j 与 OpenAI 进行交互。

使用 LangChain4j 与 OpenAI 交互

LangChain4j 是流行的 Python LangChain 库的 Java 端口,用于与 LLM 交互。 LangChain4j 提供了一个高级 API 来与 LLM 进行交互, 包括 OpenAI、Vertex AI、OllamaHuggingFace 等。

创建一个 Java 项目,并将以下依赖项添加到pom.xml

<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j</artifactId>
    <version>0.27.1</version>
</dependency>
<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-open-ai</artifactId>
    <version>0.27.1</version>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.5.0</version>
</dependency>

我们添加了 langchain4j 核心库和 langchain4j-open-ai,它们提供了与 Open AI 的集成。

现在,让我们看看如何使用 LangChain4j 与 OpenAI 进行交互。

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

public class LangChain4jOpenAIDemo {
    
    public static void main(String[] args) {
        String openAiKey = System.getenv("OPENAI_API_KEY");
        ChatLanguageModel model = OpenAiChatModel.withApiKey(openAiKey);
        String answer = model.generate("List all the movies directed by Quentin Tarantino");
        System.out.println(answer);
    }
}

正如你所看到的,使用 LangChain4j 提供了高级抽象,并提供了一个简单的 API 来与 OpenAI 交互。

提示

您还可以使用特殊的 LangChain4j Open AI API 密钥“demo”来测试 OpenAI API,而无需使用您自己的 API 密钥。

我们刚刚看到了 LangChain4j 与 OpenAI 交互的基本用法。 在以后的文章中,我们将探讨 LangChain4j 的更多高级功能,例如使用 PromptTemplates、AiServices、RAG 等。

Open AI 是一项付费服务,您将根据使用的代币数量付费。 在学习和试验时,您可能希望在不产生成本的情况下在本地运行 LLM 模型。 幸运的是,有一些开源项目提供了可以在本地运行的 LLM 模型。 在下一节中,我们将看到如何使用 Ollama 在本地运行 LLM 模型。

使用 Ollama 在本地运行 LLM 模型

Ollama 是一个开源项目,它提供可以在本地运行的 LLM 模型。 从这里下载并安装 Ollama。 安装后,您可以启动 Ollama 并运行任何可用的模型。 我们将运行 llama2 模型。

ollama run llama2

当您第一次运行它时,它将下载模型并启动服务器。 服务器启动后,您可以通过访问应显示 Ollama 正在运行http://localhost:11434 来检查状态。

现在,让我们看看如何使用 LangChain4j 与 Ollama 进行交互。

让我们将 langchain4j-ollama 依赖项添加到我们的 .pom.xml

<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-ollama</artifactId>
    <version>0.27.1</version>
</dependency>

现在,让我们使用 LangChain4j Ollama API 与 Ollama LLM 进行交互。

import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.ollama.OllamaChatModel;

public class OllamaChatDemo {

    public static void main(String[] args) {
        ChatLanguageModel model = OllamaChatModel.builder()
                .baseUrl("http://localhost:11434")
                .modelName("llama2")
                .build();
        String answer = model.generate("List all the movies directed by Quentin Tarantino");
        System.out.println(answer);
    }
}

你可以看到,使用 LangChain4j,我们可以像使用 OpenAI 一样与 Ollama LLM 进行交互。

您可以使用 Testcontainers 在 Docker 容器中运行 Ollama,而不是手动安装 Ollama。 在下一节中,我们将看到如何使用 LangChain4j 和 Testcontainers 在 Docker 容器中运行 Ollama。

使用 LangChain4j 和 Testcontainers 与 Ollama 合作

Testcontainers 是一个 Java 库,可以提供任何 Docker 容器的轻量级一次性实例。 LangChain4j 提供了各种具有不同 LLM 模型的 Ollama Docker 镜像

首先,让我们将 Testcontainers 依赖项添加到我们的 .pom.xml

<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>testcontainers</artifactId>
    <version>1.19.4</version>
    <scope>test</scope>
</dependency>

让我们看看如何将 LangChain4j 与 Testcontainers 一起使用,以便在 Docker 容器中运行 Ollama。

public class LangChain4jTestcontainersDemo {
    static String MODEL_NAME = "llama2";
  
    public static void main(String[] args) {
      GenericContainer<?> ollama = new GenericContainer<>("langchain4j/ollama-" + MODEL_NAME + ":latest")
              .withExposedPorts(11434);
      ollama.start();
      
      String baseUrl = String.format("http://%s:%d", ollama.getHost(), ollama.getFirstMappedPort());
      ChatLanguageModel model = OllamaChatModel.builder()
              .baseUrl(baseUrl)
              .modelName(MODEL_NAME)
              .build();
      String answer = model.generate("List all the movies directed by Quentin Tarantino");
      System.out.println(answer);

      ollama.stop();
    }
}

Testcontainers 将启动 Ollama Docker 容器,并在主机上的随机可用端口上公开容器端口 11434。 我们可以分别使用 和 获取主机和端口。ollama.getHost()ollama.getFirstMappedPort()

如果您正在构建 Spring Boot、Quarkus 或 Micronaut 应用程序, 您可以在 Docker 容器中运行 Ollama 进行集成测试并在本地运行应用程序 使用它们与 Testcontainers 的开箱即用集成。

结论

我们已经探讨了生成式 AI 的基础知识,以及如何使用 Java 和 LangChain4j 与 OpenAI 进行交互。 在以后的文章中,我们将探讨 LangChain4j 的更多高级功能,例如使用 PromptTemplates、AiServices、RAG 等。


使用 Java、LangChain4j、OpenAI 和 Ollama 的生成式 AI
http://47.123.5.226:8090//archives/shi-yong-java-langchain4j-openai-he-ollama-de-sheng-cheng-shi-ai-ru-men
作者
pony
发布于
2024年06月25日
许可协议