Slide 1

Slide 1 text

Build LLM-Powered Applications with LangChain4j NISHIKAWA, Akihiro (@logico_jp) Cloud Solution Architect Microsoft Japan

Slide 2

Slide 2 text

Agenda  LangChain4jについて  基本的な使い方  Azure OpenAI Serviceとともに使う

Slide 3

Slide 3 text

LangChain4j https://docs.langchain4j.dev/

Slide 4

Slide 4 text

LangChain4j LangChain for Java  JavaアプリケーションからAI/LLMの機能を利用するためのライブラリ LangChain4j | LangChain4j  PythonベースのLangChainをJavaにポーティング  本家ではなく、コミュニティが主導して移植

Slide 5

Slide 5 text

特長  統一したAPI  様々なベンダーのLLMを透過的に使えるように(抽象度は2段階)  LLMを活用するアプリケーションで必要な機能を幅広く提供  プロンプトテンプレート、メモリ管理、出力解析...  エージェント、 RAG...  開発フレームワークやランタイムとの統合  もちろん、統合されていない開発フレームワークでも利用可能

Slide 6

Slide 6 text

低レベルAPI 高レベルAPI モジュール Chains AI Services Basics RAG Language Model Document Loader Prompt Template Document Splitter Output Parser Embedding Models Memory Embedding Store

Slide 7

Slide 7 text

多種多様なLLM、機能をサポート  Comparison Table of all supported Language Models | LangChain4j  langchain4j/langchain4j: Java version of LangChain (github.com)

Slide 8

Slide 8 text

開発フレームワークとの統合 Quarkus / Spring Boot Quarkus Quarkus LangChain4j quarkus-langchain4j-azure-openai extension quarkiverse/quarkus-langchain4j: Quarkus Langchain4j extension (github.com) Spring Boot LangChain4j Spring Boot Starter langchain4j/langchain4j-spring: LangChain4j integration with Spring (github.com) Azure OpenAI Service langchain4j-azure-open-ai-spring-boot-starter Azure AI Search langchain4j-azure-ai-search-spring-boot-starter

Slide 9

Slide 9 text

基本的な使い方

Slide 10

Slide 10 text

依存関係  2024/06/04現在の最新は0.31.0  必須の依存関係  共通部分: langchain4j  LLM固有部分: langchain4j-azure-open-ai  必要に応じて他の依存関係を取り込む  langchain4j-azure-ai-search  langchain4j-open-ai など

Slide 11

Slide 11 text

共通 依存関係 dev.langchain4j langchain4j 0.31.0 dev.langchain4j langchain4j-azure-open-ai 0.31.0 dev.langchain4j langchain4j-open-ai 0.31.0 LLM固有 必要に 応じて追加

Slide 12

Slide 12 text

プロンプトの設定 コードの流れ モデルの構築 後処理 (必要であれば) リクエスト発行 レスポンスの収集

Slide 13

Slide 13 text

①モデルの構築 JSONで出力するChatLanguageModelの例 ChatLanguageModel chatLanguageModel = AzureOpenAiChatModel.builder() .endpoint(AZURE_OPENAI_ENDPOINT) .apiKey(AZURE_OPENAI_APIKEY) .deploymentName(DEPLOYMENT_MODEL_NAME) .temperature(0.0) // Temperature .responseFormat( new ChatCompletionsJsonResponseFormat()) // ResponseFormat .logRequestsAndResponses(true) // ログ出力の有無 .build(); ChatLanguageModel, StreamingLanguageModel, EmbeddingModel, ImageModel, StreamingChatLanguageModel など

Slide 14

Slide 14 text

②プロンプトの設定 System Prompt 低レベルAPI 高レベルAPI SystemMessage.from( "あなたはフランスについて詳しい人です"); @SystemMessage( "あなたは天真爛漫なアシスタントです。") String chat(String userMessage); User Prompt 低レベルAPI 高レベルAPI UserMessage.from( "誰がモナリザの微笑を描きましたか?"); @SystemMessage( "あなたは{{characteristic}}なアシスタントです") String chat( @UserMessage String userMessage, @V("characteristic") String characteristic);

Slide 15

Slide 15 text

③リクエスト発行・レスポンスの収集 ChatとImageの例 // 生成結果を取得 (テキスト) Response response1 = chatLanguageModel.generate(systemMessage, userMessage1); var answer1 = response1.content().text(); // イメージを生成 Response image1 = imageModel.generate(userMessage2); // 出力されたイメージ格納先 (Blob storage) のURLを取得 var answer2 = image1.content().url().toString();

Slide 16

Slide 16 text

③リクエスト発行・レスポンスの収集 Streamモード時は、StreamingChatLanguageModelを利用 streamingChatLanguageModel.generate( systemMessage, userMessage, new StreamingResponseHandler() { @Override public void onNext(String s) {...} @Override public void onComplete(Response response) { // LLMによる生成結果 System.out.println(response.content().text()); } @Override public void onError(Throwable throwable) {...} }); ...

Slide 17

Slide 17 text

③リクエスト発行・レスポンスの収集 a) 過去のやりとりを可変長引数やListで都度generateメソッドに渡す var systemMessage = SystemMessage.from("あなたはフランスについて詳しい人です。"); var userMessage1 = UserMessage.from("誰がモナリザの微笑を描きましたか?"); Response aiMessage1 = chatLanguageModel.generate(systemMessage, userMessage1); var userMessage2 = UserMessage.from("どこでその絵を鑑賞できますか?"); Response aiMessage2 = chatLanguageModel .generate(systemMessage, userMessage1, aiMessage1, userMessage2);

Slide 18

Slide 18 text

③リクエスト発行・レスポンスの収集 b) 過去のやりとりをConversationChainにアタッチしたChatMemoryに保持 var systemMessage = SystemMessage.from("あなたはフランスについて詳しい人です。"); var chatMemory = MessageWindowChatMemory.withMaxMessages(20); chatMemory.add(systemMessage); var chain = ConversationalChain.builder() .chatLanguageModel(chatLanguageModel).chatMemory(chatMemory).build(); var answer1 = chain.execute("誰がモナリザの微笑を描きましたか?"); var answer2 = chain.execute("どこでその絵を鑑賞できますか?"); // 履歴はList形式で格納されている chatMemory.messages().forEach(f-> System.out.printf( "type[%s] text[%s]¥n", f.type().name(), f.text()));

Slide 19

Slide 19 text

Demo シンプルなChat プロンプトとしてイメージを使う イメージの生成 AI Servicesの利用 Function calling RAG

Slide 20

Slide 20 text

シンプルなChat 京都出身の親友という体で会話 interface Kyoto { @SystemMessage(""" あなたは私の京都出身の親友です。 京都人らしく、心温かくも少々いけずな返答をしてください。 """) String chat(String message); } var question = "こんにちは。どこかにお出かけですか?"; Kyoto friend = AiServices.create(Kyoto.class, chatLanguageModel); var answer = friend.chat(question);

Slide 21

Slide 21 text

イメージからデータを抽出する Response FormatはJSON var systemMessage = SystemMessage.from( "画像のアイテムを読み取り、JSON形式で出力してください。"); var userMessage = UserMessage.from(ImageContent.from(URL)); Response response = chatLanguageModel .generate(systemMessage, userMessage); var answer = response.content().text(); // Jacksonを利用してJSONオブジェクトに変換 ObjectMapper objectMapper = new ObjectMapper(); JsonNode json = objectMapper.readTree(answer); ...

Slide 22

Slide 22 text

No content

Slide 23

Slide 23 text

イメージから撮影場所を推定する ResponseFormatはテキスト (default) var systemMessage = SystemMessage.from(""" 画像から撮影場所を見つけ出し、 日本語で回答してください。 """); var userMessage = UserMessage.from( ImageContent.from(URL)); Response response = chatLanguageModel.generate( systemMessage, userMessage);

Slide 24

Slide 24 text

イメージの生成  DALL-E 2/3  ImageModel#generate(question);  0.31時点の制限  ImageModel#edit

Slide 25

Slide 25 text

イメージの生成 Chatの場合とほぼ同じ ImageModel imageModel = AzureOpenAiImageModel.builder() .endpoint(AZURE_OPENAI_ENDPOINT) .apiKey(AZURE_OPENAI_APIKEY) .deploymentName(DEPLOYMENT_MODEL_NAME) .maxRetries(5) .build(); var question = "夏の終わりの夕暮れ時に、海辺をドライブする様子をアメリカンポップアート風に描いてください。"; Response image1 = imageModel.generate(question); var url = image1.content().url().toString();

Slide 26

Slide 26 text

Tools (Function calling)  利用可能なツール (Function)  ウェブ検索、外部APIの呼び出し、特定のコードの実行など @Tool(name="ツール名(無指定時はメソッド名)", value="LLMにツールの目的と利用を理解させるための文章")

Slide 27

Slide 27 text

Tools (Function calling) Toolとして利用可能なメソッドを定義 class RateCalculator { @Tool("基準通貨に基づいた為替レートを取得します。") String calculator(String a, String b) { String result = null; String url = "https://..."; try (Client client = ClientBuilder.newClient()) { result = client.target(url) .request(MediaType.APPLICATION_JSON_TYPE) .get(String.class); } catch (Exception e) { throw new RuntimeException(e); } return result; } }

Slide 28

Slide 28 text

Tools (Function calling) AiServicesから利用できるようにInterfaceを定義 interface Assistant { String rate(String userMessage); } Assistant assistant = AiServices.builder(Assistant.class) .chatLanguageModel(chatLanguageModel) .tools(new RateCalculator()) .chatMemory(MessageWindowChatMemory.withMaxMessages(10)) .build(); var ans = assistant.rate("USDを基準にしたJPYの為替レートを教えてください。");

Slide 29

Slide 29 text

AI Servicesの利用  テキストから情報を抽出し、POJOに格納する  UserMessageの可変部分をLLMに渡す

Slide 30

Slide 30 text

AI Servicesの利用 文章中の情報をもとに、POJOを返す interface PersonExtractor { @UserMessage("次の文章から人の情報を抽出してください。: {{it}}") Person extractPersonFrom(@V("it") String text); } // ResponseFormat形式はJSON PersonExtractor personExtractor = AiServices.create(PersonExtractor.class, chatLanguageModel); return personExtractor.extractPersonFrom("...");

Slide 31

Slide 31 text

Embedding Embedding Model テキストをベクトルデータに変換 AzureOpenAiEmbeddingModel Embedding Store ベクトルデータの保存先 Azure AI Search Azure CosmosDB Mongo vCore Azure CosmosDB (NoSQL) その他PostgreSQL、Redis、Cassandraなど Embedding Models | LangChain4j Comparison table of all supported Embedding Stores | LangChain4j

Slide 32

Slide 32 text

RAG (Retrieval-Augmented Generation)  Easy RAG  LangChain4jがよしなにやってくれる  カスタマイズしたRAGに比べると、精度は落ちる  RAG APIを使ってカスタマイズ (Naïve RAG)  Advanced RAG  Deconstructing RAG (langchain.dev)  [2312.10997] Retrieval-Augmented Generation for Large Language Models: A Survey (arxiv.org)

Slide 33

Slide 33 text

User message + Contents Advanced RAG Foundation for advanced RAG by langchain4j · Pull Request #538 · langchain4j/langchain4j (github.com) 2 Vector store RDB or Graph DB 3 4 ContentRetriever-A ContentRetriever-B 1 QueryTransformer ContentInjector QueryRouter 5 ContentAggregator 6 Query User message

Slide 34

Slide 34 text

RAGでの考慮事項  プロトタイピング時  In-process embeddingモデルとIn-process embeddingストアを使って手軽に確認  期待した精度が出ないときは  ユースケースや文書コーパスにあわせて、分割、Embeddingパラメータを最適化  ドキュメント分割前にドキュメントを整備しておく  分割したドキュメント(セグメント)にコンテキストを付加する  Advanced RAG  良好な結果が得られるが、レイテンシが大きい

Slide 35

Slide 35 text

Demo: Java SE 22の言語仕様において、 whenはContextual Keywordなのか?

Slide 36

Slide 36 text

Java SE 22において、whenはContextual Keyword Chapter 3. Lexical Structure (oracle.com)

Slide 37

Slide 37 text

Embedding & Query ModelとStoreのクライアント EmbeddingModel embeddingModel = AzureOpenAiEmbeddingModel.builder() .endpoint(AZURE_OPENAI_ENDPOINT) .apiKey(AZURE_OPENAI_APIKEY) .deploymentName(DEPLOYMENT_MODEL_NAME) .tokenizer(new OpenAiTokenizer( OpenAiEmbeddingModelName.TEXT_EMBEDDING_3_SMALL)) .build(); EmbeddingStore embeddingStore = AzureAiSearchEmbeddingStore.builder() .endpoint(AZURE_AISEARCH_ENDPOINT) .apiKey(AZURE_AISEARCH_KEY) .dimensions(1536) .build();

Slide 38

Slide 38 text

Embedding & Query ドキュメントの取り込み・解析 // HTMLからテキストを抽出し、分割してEmbeddingを生成し、Embedding Storeに格納 EmbeddingStore embeddingStore; EmbeddingModel embeddingModel; String url = "https://...."; DocumentParser documentParser = new TextDocumentParser(); HtmlTextExtractor htmlTextExtractor = new HtmlTextExtractor(); Document document = htmlTextExtractor.transform( UrlDocumentLoader.load(url, documentParser)); DocumentSplitter splitter = DocumentSplitters.recursive(600,30); List segments = splitter.split(document); List embeddings = embeddingModel.embedAll(segments).content(); embeddingStore.addAll(embeddings, segments);

Slide 39

Slide 39 text

Embedding & Query RAG (プロンプトとクエリ) interface Assistant { @SystemMessage(“”“ あなたはJava言語のエキスパートです。 Instructions: - Java SE 22言語仕様に基づき回答ください。 - 回答は日本語でお願いします。 - わからない場合は、"わからない" と答えてください。 - 参考文献のURLを提示してください。 """) Result answer(String query); } Assistant createAssistant() { ContentRetriever contentRetriever = EmbeddingStoreContentRetriever .builder() .embeddingModel(embeddingModel) .embeddingStore(embeddingStore) .maxResults(3).minScore(0.6).build(); ChatMemory chatMemory = MessageWindowChatMemory .withMaxMessages(10); return AiServices .builder(Assistant.class) .chatLanguageModel(chatLanguageModel) .contentRetriever(contentRetriever) .chatMemory(chatMemory).build(); } // プロンプトの受け渡しと回答の取得 String query="..."; Assistant assistant = createAssistant(); return assistant.answer(query).content();

Slide 40

Slide 40 text

Q: JDK 22でwhenはContextual Keywordに含まれていますか? 左: GPT-4o / 右: GPT-4o + RAG

Slide 41

Slide 41 text

Azure OpenAI Serviceとともに使う

Slide 42

Slide 42 text

認証・認可・RBAC  API Key でも TokenCredential でも利用可能 DefaultAzureCredential Class | Microsoft Learn  // API Keyを利用する場合 AzureOpenAiChatModel.builder() .endpoint(AZURE_OPENAI_ENDPOINT) .apiKey(AZURE_OPENAI_APIKEY) .deploymentName(DEPLOYMENT_MODEL_NAME) .temperature(1.0) .build(); // TokenCredentialを利用する場合 // この例ではPlatformのSystem assigned // managed identityを利用する前提 AzureOpenAiChatModel.builder() .endpoint(AZURE_OPENAI_ENDPOINT) .tokenCredential( new DefaultAzureCredentialBuilder() .build()) .deploymentName(DEPLOYMENT_MODEL_NAME) .temperature(1.0) .build();

Slide 43

Slide 43 text

Azure API Managementが Azure OpenAI Serviceの前段にある場合  LangChain4jが期待しているものに合わせる  基本的にLangChainが期待しているものと同じ  API認証  APIリクエスト: Frontend (Inbound section) でリクエストを認証 (validate-jwtポリシー)  バックエンド: API ManagementのManaged Identityで認証(Authorizationヘッダーを上書き) LangChain4j API Management エンドポイント /openai で終わる 任意 API Key api-key 任意 デフォルトはocp-apim-subscription-key

Slide 44

Slide 44 text

複数のインスタンスに負荷分散して、TPMを稼いでいる場合 ロードバランサー Application Gateway Front Door (API Management) (L7のみ利用可) エンドポイント /openai で終わること (API Managementと同じ) モデルデプロイ名 利用するAzure OpenAI Service全インスタンスで名称を統一 API認証 Microsoft Entra ID認証

Slide 45

Slide 45 text

まとめ

Slide 46

Slide 46 text

絶賛開発進行中  0.31で GPT-4o が追加  今後、Tokenizer (jtokkit) がアップデートされる予定  GPT-4o でアップデートされたTokenizerに追随  Feature requestsなどはIssuesをチェック  Issues · langchain4j/langchain4j (github.com)

Slide 47

Slide 47 text

まとめ  様々な機能、LLMをサポート  使い慣れた開発フレームワークとの統合  未実装の部分がまだまだあるので、ぜひContributionしてください!

Slide 48

Slide 48 text

Resources

Slide 49

Slide 49 text

リソース  ドキュメント  LangChain4j | LangChain4j  Overview (LangChain4j :: Aggregator 0.31.0-SNAPSHOT API)  リポジトリ  langchain4j/langchain4j: Java version of LangChain (github.com)

Slide 50

Slide 50 text

Thank you! NISHIKAWA, Akihiro @Logico_jp