Upgrade to Pro — share decks privately, control downloads, hide ads and more …

LangChain for Java - Java on Azure Day 2024

LangChain for Java - Java on Azure Day 2024

Overview to leverage LangChain for Java (LangChain4j) to create AI-powered applications (in Japanese).
This presentation contains only basic information about LangChain4j.

Akihiro Nishikawa

June 05, 2024
Tweet

More Decks by Akihiro Nishikawa

Other Decks in Technology

Transcript

  1. LangChain4j LangChain for Java  JavaアプリケーションからAI/LLMの機能を利用するためのライブラリ LangChain4j | LangChain4j 

    PythonベースのLangChainをJavaにポーティング  本家ではなく、コミュニティが主導して移植
  2. 低レベルAPI 高レベルAPI モジュール Chains AI Services Basics RAG Language Model

    Document Loader Prompt Template Document Splitter Output Parser Embedding Models Memory Embedding Store
  3. 多種多様なLLM、機能をサポート  Comparison Table of all supported Language Models |

    LangChain4j  langchain4j/langchain4j: Java version of LangChain (github.com)
  4. 開発フレームワークとの統合 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
  5. 依存関係  2024/06/04現在の最新は0.31.0  必須の依存関係  共通部分: langchain4j  LLM固有部分:

    langchain4j-azure-open-ai  必要に応じて他の依存関係を取り込む  langchain4j-azure-ai-search  langchain4j-open-ai など
  6. 共通 依存関係 <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j</artifactId> <version>0.31.0</version> </dependency> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-azure-open-ai</artifactId>

    <version>0.31.0</version> </dependency> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-open-ai</artifactId> <version>0.31.0</version> </dependency> LLM固有 必要に 応じて追加
  7. ①モデルの構築 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 など
  8. ②プロンプトの設定 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);
  9. ③リクエスト発行・レスポンスの収集 ChatとImageの例 // 生成結果を取得 (テキスト) Response<AiMessage> response1 = chatLanguageModel.generate(systemMessage, userMessage1);

    var answer1 = response1.content().text(); // イメージを生成 Response<Image> image1 = imageModel.generate(userMessage2); // 出力されたイメージ格納先 (Blob storage) のURLを取得 var answer2 = image1.content().url().toString();
  10. ③リクエスト発行・レスポンスの収集 Streamモード時は、StreamingChatLanguageModelを利用 streamingChatLanguageModel.generate( systemMessage, userMessage, new StreamingResponseHandler<AiMessage>() { @Override public

    void onNext(String s) {...} @Override public void onComplete(Response<AiMessage> response) { // LLMによる生成結果 System.out.println(response.content().text()); } @Override public void onError(Throwable throwable) {...} }); ...
  11. ③リクエスト発行・レスポンスの収集 a) 過去のやりとりを可変長引数やListで都度generateメソッドに渡す var systemMessage = SystemMessage.from("あなたはフランスについて詳しい人です。"); var userMessage1 =

    UserMessage.from("誰がモナリザの微笑を描きましたか?"); Response<AiMessage> aiMessage1 = chatLanguageModel.generate(systemMessage, userMessage1); var userMessage2 = UserMessage.from("どこでその絵を鑑賞できますか?"); Response<AiMessage> aiMessage2 = chatLanguageModel .generate(systemMessage, userMessage1, aiMessage1, userMessage2);
  12. ③リクエスト発行・レスポンスの収集 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()));
  13. シンプルなChat 京都出身の親友という体で会話 interface Kyoto { @SystemMessage(""" あなたは私の京都出身の親友です。 京都人らしく、心温かくも少々いけずな返答をしてください。 """) String

    chat(String message); } var question = "こんにちは。どこかにお出かけですか?"; Kyoto friend = AiServices.create(Kyoto.class, chatLanguageModel); var answer = friend.chat(question);
  14. イメージからデータを抽出する Response FormatはJSON var systemMessage = SystemMessage.from( "画像のアイテムを読み取り、JSON形式で出力してください。"); var userMessage

    = UserMessage.from(ImageContent.from(URL)); Response<AiMessage> response = chatLanguageModel .generate(systemMessage, userMessage); var answer = response.content().text(); // Jacksonを利用してJSONオブジェクトに変換 ObjectMapper objectMapper = new ObjectMapper(); JsonNode json = objectMapper.readTree(answer); ...
  15. イメージから撮影場所を推定する ResponseFormatはテキスト (default) var systemMessage = SystemMessage.from(""" 画像から撮影場所を見つけ出し、 日本語で回答してください。 """);

    var userMessage = UserMessage.from( ImageContent.from(URL)); Response<AiMessage> response = chatLanguageModel.generate( systemMessage, userMessage);
  16. イメージの生成 Chatの場合とほぼ同じ ImageModel imageModel = AzureOpenAiImageModel.builder() .endpoint(AZURE_OPENAI_ENDPOINT) .apiKey(AZURE_OPENAI_APIKEY) .deploymentName(DEPLOYMENT_MODEL_NAME) .maxRetries(5)

    .build(); var question = "夏の終わりの夕暮れ時に、海辺をドライブする様子をアメリカンポップアート風に描いてください。"; Response<Image> image1 = imageModel.generate(question); var url = image1.content().url().toString();
  17. 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; } }
  18. 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の為替レートを教えてください。");
  19. 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("...");
  20. 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
  21. 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)
  22. 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
  23. RAGでの考慮事項  プロトタイピング時  In-process embeddingモデルとIn-process embeddingストアを使って手軽に確認  期待した精度が出ないときは 

    ユースケースや文書コーパスにあわせて、分割、Embeddingパラメータを最適化  ドキュメント分割前にドキュメントを整備しておく  分割したドキュメント(セグメント)にコンテキストを付加する  Advanced RAG  良好な結果が得られるが、レイテンシが大きい
  24. 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<TextSegment> embeddingStore = AzureAiSearchEmbeddingStore.builder() .endpoint(AZURE_AISEARCH_ENDPOINT) .apiKey(AZURE_AISEARCH_KEY) .dimensions(1536) .build();
  25. Embedding & Query ドキュメントの取り込み・解析 // HTMLからテキストを抽出し、分割してEmbeddingを生成し、Embedding Storeに格納 EmbeddingStore<TextSegment> 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<TextSegment> segments = splitter.split(document); List<Embedding> embeddings = embeddingModel.embedAll(segments).content(); embeddingStore.addAll(embeddings, segments);
  26. Embedding & Query RAG (プロンプトとクエリ) interface Assistant { @SystemMessage(“”“ あなたはJava言語のエキスパートです。

    Instructions: - Java SE 22言語仕様に基づき回答ください。 - 回答は日本語でお願いします。 - わからない場合は、"わからない" と答えてください。 - 参考文献のURLを提示してください。 """) Result<String> 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();
  27. 認証・認可・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();
  28. 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
  29. 複数のインスタンスに負荷分散して、TPMを稼いでいる場合 ロードバランサー Application Gateway Front Door (API Management) (L7のみ利用可) エンドポイント

    /openai で終わること (API Managementと同じ) モデルデプロイ名 利用するAzure OpenAI Service全インスタンスで名称を統一 API認証 Microsoft Entra ID認証
  30. 絶賛開発進行中  0.31で GPT-4o が追加  今後、Tokenizer (jtokkit) がアップデートされる予定 

    GPT-4o でアップデートされたTokenizerに追随  Feature requestsなどはIssuesをチェック  Issues · langchain4j/langchain4j (github.com)
  31. リソース  ドキュメント  LangChain4j | LangChain4j  Overview (LangChain4j

    :: Aggregator 0.31.0-SNAPSHOT API)  リポジトリ  langchain4j/langchain4j: Java version of LangChain (github.com)