LangChain4j を導入して、LLM の Java アプリケーションへの統合を簡素化します。
LangChain4j (LangChain for Java) は、プレーン Java で RAG アプリケーションを構築するための強力なツールセットです。
LangChain4j フレームワークは、次の目標を掲げて 2023 年に作成されました。
LangChain4j の目標は、LLM を Java アプリケーションに簡単に統合することです。
LangChain4j は次の標準的な方法を提供します:
与えられたコンテンツ(例えばテキスト)から埋め込み(ベクトル)を作成する
埋め込みを埋め込みストアに保存する
埋め込みストア内の類似ベクトルを検索する
LLMと議論する
チャットメモリを使用して、LLMとの議論の文脈を記憶する
このリストは網羅的なものではなく、LangChain4j コミュニティは常に新しい機能を実装しています。
この投稿では、フレームワークの最初の主要部分について説明します。
プロジェクトにLangChain4j OpenAIを追加する
すべての Java プロジェクトと同様に、これは依存関係の問題にすぎません。ここでは Maven を使用しますが、他の依存関係マネージャーでも同じことを実現できます。
ここで構築するプロジェクトの最初のステップとして、OpenAI を使用するので、 langchain4j-open-aiアーティファクトを追加するだけです。
<properties>
<langchain4j.version>0.34.0</langchain4j.version>
</properties>
<dependencies>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>${langchain4j.version}</version>
</dependency>
</dependencies>残りのコードでは、 OpenAIにアカウントを登録することで取得できる独自の API キー、またはデモ目的でのみ LangChain4j プロジェクトによって提供される API キーを使用します。
static String getOpenAiApiKey() {
String apiKey = System.getenv(API_KEY_ENV_NAME);
if (apiKey == null || apiKey.isEmpty()) {
Logger.warn("Please provide your own key instead using [{}] env variable", API_KEY_ENV_NAME);
return "demo";
}
return apiKey;
}これで ChatLanguageModel のインスタンスを作成できます。
ChatLanguageModel model = OpenAiChatModel.withApiKey(getOpenAiApiKey());そして最後に、簡単な質問をして答えを得ることができます。
String answer = model.generate("Who is Thomas Pesquet?");
Logger.info("Answer is: {}", answer);与えられた答えは次のようになります:
Thomas Pesquet is a French aerospace engineer, pilot, and European Space Agency astronaut.
He was selected as a member of the European Astronaut Corps in 2009 and has since completed
two space missions to the International Space Station, including serving as a flight engineer
for Expedition 50/51 in 2016-2017. Pesquet is known for his contributions to scientific
research and outreach activities during his time in space.このコードを実行する場合は、 Step1AiChatTest.javaクラスを確認してください。
langchain4jでより多くのコンテキストを提供する
langchain4jアーティファクトを追加しましょう:
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>${langchain4j.version}</version>
</dependency>これは、アシスタントを構築するために、より高度な LLM 統合を構築するのに役立つツールセットを提供します。ここでは、先ほど定義したChatLanguageModelを自動的に呼び出すchatメソッドを提供するAssistantインターフェイスを作成します。
interface Assistant {
String chat(String userMessage);
}LangChain4j AiServicesクラスにインスタンスを構築するよう依頼するだけです。
Assistant assistant = AiServices.create(Assistant.class, model);次に、 chat(String)メソッドを呼び出します。
String answer = assistant.chat("Who is Thomas Pesquet?");
Logger.info("Answer is: {}", answer);これは以前と同じ動作になります。では、なぜコードを変更したのでしょうか?まず第一に、よりエレガントですが、それ以上に、シンプルな注釈を使用して LLM にいくつかの指示を与えることができるようになりました。
interface Assistant {
@SystemMessage("Please answer in a funny way.")
String chat(String userMessage);
}これにより、次のようになります:
Ah, Thomas Pesquet is actually a super secret spy disguised as an astronaut!
He's out there in space fighting aliens and saving the world one spacewalk at a time.
Or maybe he's just a really cool French astronaut who has been to the International
Space Station. But my spy theory is much more exciting, don't you think?このコードを実行する場合は、 Step2AssistantTest.javaクラスを確認してください。
別のLLMへの切り替え:langchain4j-ollama
素晴らしいOllamaプロジェクトを利用できます。LLM を自分のマシン上でローカルに実行するのに役立ちます。
langchain4j-ollamaアーティファクトを追加しましょう:
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-ollama</artifactId>
<version>${langchain4j.version}</version>
</dependency>テストを使用してサンプル コードを実行しているので、プロジェクトにTestcontainers を追加しましょう。
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>ollama</artifactId>
<version>1.20.1</version>
<scope>test</scope>
</dependency>Docker コンテナを起動/停止できるようになりました。
static String MODEL_NAME = "mistral";
static String DOCKER_IMAGE_NAME = "langchain4j/ollama-" + MODEL_NAME + ":latest";
static OllamaContainer ollama = new OllamaContainer(
DockerImageName.parse(DOCKER_IMAGE_NAME).asCompatibleSubstituteFor("ollama/ollama"));
@BeforeAll
public static void setup() {
ollama.start();
}
@AfterAll
public static void teardown() {
ollama.stop();
}先ほど使用したOpenAiChatModelではなく、 modelオブジェクトをOllamaChatModelに変更するだけです。
OllamaChatModel model = OllamaChatModel.builder()
.baseUrl(ollama.getEndpoint())
.modelName(MODEL_NAME)
.build();モデルを含むイメージを取得するのに多少時間がかかる場合がありますが、しばらくすると答えが得られることに注意してください。
Oh, Thomas Pesquet, the man who single-handedly keeps the French space program running
while sipping on his crisp rosé and munching on a baguette! He's our beloved astronaut
with an irresistible accent that makes us all want to learn French just so we can
understand him better. When he's not floating in space, he's probably practicing his
best "je ne sais quoi" face for the next family photo. Vive le Thomas Pesquet!
🚀🌍🇫🇷 #FrenchSpaceHeroメモリがあればさらに良くなる
複数の質問をした場合、デフォルトではシステムは以前の質問と回答を記憶しません。最初の質問の後に「彼はいつ生まれたのですか?」と尋ねると、私たちのアプリケーションは次のように答えます:
Oh, you're asking about this legendary figure from history, huh? Well, let me tell
you a hilarious tale! He was actually born on Leap Year's Day, but only every 400
years! So, do the math... if we count backwards from 2020 (which is also a leap year),
then he was born in... *drumroll please* ...1600! Isn't that a hoot? But remember
folks, this is just a joke, and historical records may vary.それはナンセンスだ。代わりに、チャットメモリを使用する必要があります。
ChatMemory chatMemory = MessageWindowChatMemory.withMaxMessages(10);
Assistant assistant = AiServices.builder(Assistant.class)
.chatLanguageModel(model)
.chatMemory(chatMemory)
.build();同じ質問を実行すると、意味のある答えが得られます。
Oh, Thomas Pesquet, the man who was probably born before sliced bread but after dinosaurs!
You know, around the time when people started putting wheels on suitcases and calling it
a revolution. So, roughly speaking, he came into this world somewhere in the late 70s or
early 80s, give or take a year or two - just enough time for him to grow up, become an
astronaut, and make us all laugh with his space-aged antics! Isn't that a hoot?
*laughs maniacally*まとめ
次の投稿では、Elasticsearch を埋め込みストアとして使用して、プライベート データセットに質問する方法を説明します。これにより、アプリケーション検索を次のレベルに引き上げる方法が得られます。

